///////////////////////////////////////////////////////////////////////////////
//
//  File Name 
//      RABRPC.CPP
//
//  Description
//      This file implements all the remote functions available to client
//      WINDS address book providers. 
//      
//  Author
//      Irving De la Cruz
//
//  Revision: 1.7
//
// Written for Microsoft Windows Developer Support
// Copyright (c) 1995-1996 Microsoft Corporation. All rights reserved.
//
#include "_WINDS.H"
#include <RPC.H>
#include "WINDS.H"      // Header file generated by the MIDL compiler
#include "WDSADM.H"     // Header file generated by the MIDL compiler

///////////////////////////////////////////////////////////////////////////////
//    RemoteChangePasswordA()
//
//    Parameters
//
//    Purpose
//
//    Return Value
//
long RemoteChangePasswordA (unsigned char *  szMailbox,
                            unsigned char *  szOldPassword,
                            unsigned char *  szNewPassword)
{
    long lResult = GetServiceState();
    if (lResult)
    {
        return lResult;
    }
    MAILBOX_INFO MBInfo = { 0 };
    if (S_OK != GlobalObjectMap.FindObjFromName (SERVER_USER_MAILBOX, (LPSTR)szMailbox, &MBInfo.dwObjID))
    {
        TraceMessage ("RemoteChangePasswordA: Invalid mailbox");
        return HRESULT_FROM_WIN32(ERROR_NO_SUCH_USER);
    }
    lstrcpy (MBInfo.szMailboxName, (LPSTR)szMailbox);
    
    HANDLE hWaitEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
    if (!hWaitEvent)
    {
        lResult = HRESULT_FROM_WIN32(GetLastError());
        TraceResult ("RemoteChangePasswordA: Failed to create I/O event", lResult);
        return lResult;
    }
    EnterCriticalSection (&g_csIOInfo);
    SetEvent (g_IOInfo.hResumeEvent);
    g_IOInfo.Action           = IO_GET_MAILBOX_PROPERTIES;
    g_IOInfo.hActionCompleted = hWaitEvent;
    g_IOInfo.phLastError      = &lResult;
    g_IOInfo.pMBInfo          = &MBInfo;
    LeaveCriticalSection (&g_csIOInfo);
    WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);
    if (S_OK == lResult)
    {
        if (0 == lstrcmp (MBInfo.szPassword, (LPSTR)szOldPassword))
        {
            lstrcpy (MBInfo.szPassword, (LPSTR)szNewPassword);
            EnterCriticalSection (&g_csIOInfo);
            SetEvent (g_IOInfo.hResumeEvent);
            g_IOInfo.Action           = IO_SET_MAILBOX_PROPERTIES;
            g_IOInfo.hActionCompleted = hWaitEvent;
            g_IOInfo.phLastError      = &lResult;
            g_IOInfo.pMBInfo          = &MBInfo;
            LeaveCriticalSection (&g_csIOInfo);
            WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);
        }
        else
        {
            lResult = HRESULT_FROM_WIN32(ERROR_WRONG_PASSWORD);
        }
    }
    CloseHandle (hWaitEvent);
    TraceResult ("RemoteChangePasswordA", lResult);
    return lResult;
}

///////////////////////////////////////////////////////////////////////////////
//    RemoteGetRecipientPropsA()
//
//    Parameters
//
//    Purpose
//
//    Return Value
//
long RemoteGetRecipientPropsA (unsigned long    dwObjID,
                               unsigned long *  pdwObjType,
                               unsigned char *  szMailboxName,
                               unsigned char *  szFullName,
                               unsigned char *  szJobTitle,
                               unsigned char *  szOffice,
                               unsigned char *  szPhone,
                               unsigned char *  szAltPhone,
                               unsigned char *  szFax,
                               unsigned char *  szComments,
                               unsigned char *  szCompany,
                               unsigned char *  szDepartment,
                               unsigned char *  szManagerName,
                               unsigned char *  szManagerAlias,
                               unsigned long *  pdwManagerID)
{
    long lResult = GetServiceState();
    if (lResult)
    {
        return lResult;
    }
    MAILBOX_INFO_A MBInfo = { 0 };
    MBInfo.dwObjID = dwObjID;
    lResult = GetObjectProp (dwObjID, pdwObjType, &MBInfo);
    if (S_OK == lResult)
    {
        lstrcpy ((LPSTR)szMailboxName,  MBInfo.szMailboxName);
        lstrcpy ((LPSTR)szFullName,     MBInfo.szFullName);
        lstrcpy ((LPSTR)szJobTitle,     MBInfo.szJobTitle);
        lstrcpy ((LPSTR)szOffice,       MBInfo.szOffice);
        lstrcpy ((LPSTR)szPhone,        MBInfo.szPhone);
        lstrcpy ((LPSTR)szFax,          MBInfo.szFax);
        lstrcpy ((LPSTR)szComments,     MBInfo.szComments);
        lstrcpy ((LPSTR)szAltPhone,     MBInfo.szAltPhone);
        lstrcpy ((LPSTR)szCompany,      MBInfo.szCompany);
        lstrcpy ((LPSTR)szDepartment,   MBInfo.szDepartment);
        lstrcpy ((LPSTR)szManagerName,  MBInfo.szManagerName);
        lstrcpy ((LPSTR)szManagerAlias, MBInfo.szManagerAlias);
        *pdwManagerID = MBInfo.dwManagerID;
    }
    return lResult;
}

///////////////////////////////////////////////////////////////////////////////
//    GetObjectProp()
//
//    Parameters
//
//    Purpose
//
//    Return Value
//
HRESULT WINAPI GetObjectProp (DWORD             dwObjID,
                              DWORD *           pdwObjType,
                              MAILBOX_INFO *    pMailboxInfo)
{
    if (dwObjID == 0)
    {
        TraceMessage ("GetObjectProp: Invoked with Object ID = 0, cannot accept");
        return HRESULT_FROM_WIN32 (ERROR_NO_SUCH_USER);
    }

    MAILBOX_INFO MBInfo = { 0 };
    WINDS_AB_OBJTYPE Type = UNDEFINED_OBJECT_TYPE;
    // If an object with the given ID is not found or if the
    // found object is not the expected, the fail the client request
    if ((S_OK != GlobalObjectMap.FindObjFromID (dwObjID, MBInfo.szMailboxName, &Type)) ||
        (!(SERVER_USER_MAILBOX == Type || GATEWAY_RECIPIENT == Type)))
    {
        return HRESULT_FROM_WIN32 (ERROR_NO_SUCH_USER);
    }
    ASSERT (SERVER_USER_MAILBOX == Type || GATEWAY_RECIPIENT == Type);
    *pdwObjType = (unsigned long)Type;
    HRESULT hResult;

    HANDLE hWaitEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
    if (!hWaitEvent)
    {
        hResult = HRESULT_FROM_WIN32(GetLastError());
        TraceResult ("GetMailboxProp: Failed to create I/O event", hResult);
        return hResult;
    }
    EnterCriticalSection (&g_csIOInfo);
    SetEvent (g_IOInfo.hResumeEvent);
    if (SERVER_USER_MAILBOX == Type)
    {
        g_IOInfo.Action = IO_GET_MAILBOX_PROPERTIES;
    }
    else
    {
        ASSERT (FALSE); // We haven't implemented gateway yet
        g_IOInfo.Action = IO_GET_MAILBOX_PROPERTIES;
    }
    g_IOInfo.hActionCompleted = hWaitEvent;
    g_IOInfo.phLastError      = &hResult;
    g_IOInfo.pMBInfo          = &MBInfo;
    LeaveCriticalSection (&g_csIOInfo);
    WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);
    CloseHandle (hWaitEvent);
    if (!hResult)
    {
        if (SERVER_USER_MAILBOX == Type)
        {
            *pMailboxInfo = MBInfo;
        }
        else
        {
            ASSERT (FALSE);
            hResult = E_FAIL;
        }
    }
    return hResult;
}

///////////////////////////////////////////////////////////////////////////////
//    RemoteGetDistListPropsA()
//
//    Parameters
//
//    Purpose
//
//    Return Value
//
long RemoteGetDistListPropsA (unsigned long     dwObjID,
                              unsigned char *   szDLAlias,
                              unsigned char *   szDLFullName,
                              unsigned long *   pdwContentCount,
                              unsigned char *   szOwnerAlias,
                              unsigned char *   szOwnerName,
                              unsigned char *   szComments)
{
    long lResult = GetServiceState();
    if (lResult)
    {
        return lResult;
    }
    DIST_LIST_INFO DLInfo = { 0 };
    WINDS_AB_OBJTYPE Type = UNDEFINED_OBJECT_TYPE;
    if ((S_OK != GlobalObjectMap.FindObjFromID (dwObjID, DLInfo.szDLAlias, &Type)) ||
        (SERVER_DISTRIBUTION_LIST != Type))
    {
        return HRESULT_FROM_WIN32 (ERROR_NO_SUCH_GROUP);
    }

    HANDLE hWaitEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
    if (!hWaitEvent)
    {
        lResult = HRESULT_FROM_WIN32(GetLastError());
        TraceResult ("RemoteGetDistListPropsA: Failed to create I/O event", lResult);
        return HRESULT_FROM_WIN32(lResult);
    }
    EnterCriticalSection (&g_csIOInfo);
    SetEvent (g_IOInfo.hResumeEvent);
    g_IOInfo.Action           = IO_GET_DL_PROPERTIES;
    g_IOInfo.hActionCompleted = hWaitEvent;
    g_IOInfo.phLastError      = &lResult;
    g_IOInfo.pDLInfo          = &DLInfo;
    LeaveCriticalSection (&g_csIOInfo);
    WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);
    CloseHandle (hWaitEvent);
    if (!lResult)
    {
        lstrcpy ((LPSTR)szDLAlias, DLInfo.szDLAlias);
        lstrcpy ((LPSTR)szDLFullName, DLInfo.szDLFullName);
        lstrcpy ((LPSTR)szOwnerAlias, DLInfo.szOwnerAlias);
        lstrcpy ((LPSTR)szOwnerName, DLInfo.szOwnerName);
        lstrcpy ((LPSTR)szComments, DLInfo.szComments);
        *pdwContentCount = DLInfo.dwMemberCount;
    }
    return lResult;
}

///////////////////////////////////////////////////////////////////////////////
//    RemoteGetContainerProps()
//
//    Parameters
//
//    Purpose
//
//    Return Value
//
long RemoteGetContainerProps (unsigned long     dwContainerID,
                              unsigned long *   pdwContentCount)
{
    long lResult = GetServiceState();
    if (lResult)
    {
        return lResult;
    }
    switch (dwContainerID)
    {
        case ROOT_CONTAINER_ID :
        case GATEWAY_CONTAINERS_ID :
        case GAL_CONTAINER_ID :
            *pdwContentCount = 0;
            if (GAL_CONTAINER_ID == dwContainerID)
            {
                *pdwContentCount = 0;
            }
            return S_OK;
        case FAX_CONTAINER_ID :
        case SMTP_CONTAINER_ID :
        case EXCHANGE_CONTAINER_ID :
            break;
        
        default :
            TraceMessage ("RemoteGetContainerProps: Invalid container ID passed in");
            return HRESULT_FROM_WIN32(ERROR_NO_SUCH_GROUP);
    }
    HANDLE hWaitEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
    if (!hWaitEvent)
    {
        lResult = HRESULT_FROM_WIN32(GetLastError());
        TraceResult ("RemoteGetContainerProps: Failed to create I/O event", lResult);
        return lResult;
    }
    EnterCriticalSection (&g_csIOInfo);
    SetEvent (g_IOInfo.hResumeEvent);
    g_IOInfo.Action           = IO_GET_GW_CONTAINER_COUNT;
    g_IOInfo.hActionCompleted = hWaitEvent;
    g_IOInfo.phLastError      = &lResult;
    g_IOInfo.pdwData          = pdwContentCount;
    LeaveCriticalSection (&g_csIOInfo);
    WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);
    CloseHandle (hWaitEvent);
    return lResult;
}

///////////////////////////////////////////////////////////////////////////////
//    RemoteGetContainerRecipients()
//
//    Parameters
//
//    Purpose
//
//    Return Value
//
long RemoteGetContainerRecipients (unsigned long    dwFlags,
                                   unsigned long    dwContainerID,
                                   long *           pPipeNumber)
{
    long lResult = GetServiceState();
    if (lResult)
    {
        return lResult;
    }
    
    *pPipeNumber = GetNextPipeID();

    SECURITY_ATTRIBUTES sa;
    SECURITY_DESCRIPTOR sd;

    // Initialize the new security descriptor.
    InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);

    // Add a NULL descriptor ACL to the security descriptor.
    SetSecurityDescriptorDacl (&sd, TRUE, (PACL)NULL, FALSE);

    sa.nLength = sizeof(sa);
    sa.lpSecurityDescriptor = &sd;
    sa.bInheritHandle = TRUE;

    // Create a pipe where we will expect the transport to send the data
    TCHAR szPipeName[64];
    wsprintf (szPipeName, SERVER_PIPE_NAME_FORMAT, *pPipeNumber);
    HANDLE hPipe;
    hPipe = CreateNamedPipe (szPipeName,
                             PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED,
                             PIPE_WAIT | PIPE_READMODE_BYTE | PIPE_TYPE_BYTE,
                             1,
                             IO_BUFFERSIZE,
                             IO_BUFFERSIZE,
                             0,
                             &sa);
    if (INVALID_HANDLE_VALUE == hPipe || ERROR_INVALID_PARAMETER == (DWORD)hPipe)
    {
        lResult = HRESULT_FROM_WIN32(GetLastError());
        TraceResult ("RemoteGetContainerRecipients: Failed to create pipe", lResult);
        goto ErrorExit;
    }

    EnterCriticalSection (&g_csIOInfo);
    SetEvent (g_IOInfo.hResumeEvent);
    g_IOInfo.Action           = IO_GET_CONTAINER_RECIPIENTS;
    g_IOInfo.hActionCompleted = NULL;
    g_IOInfo.phLastError      = NULL;
    g_IOInfo.dwObjID          = dwContainerID;
    g_IOInfo.hTmpFile         = hPipe;
    LeaveCriticalSection (&g_csIOInfo);

ErrorExit:
    return lResult;
}

///////////////////////////////////////////////////////////////////////////////
//    RemoteIsServerRunning()
//
//    Parameters
//
//    Purpose
//
//    Return Value
//
long RemoteIsServerRunning()
{
    return GetServiceState();
}

///////////////////////////////////////////////////////////////////////////////
//    RemoteGetAllAccounts()
//
//    Parameters
//
//    Purpose
//
//    Return Value
//
long RemoteGetAllAccounts (long * pPipeNumber)
{
    return RemoteAdmGetServerMailboxes (pPipeNumber);
}

///////////////////////////////////////////////////////////////////////////////
//    RemoteLogonMailBoxA()
//
//    Parameters
//
//    Purpose
//
//    Return Value
//
long RemoteLogonMailBoxA (unsigned char *    szMailbox,
                          unsigned char *    szPassword,
                          unsigned char *    szFullName,
                          unsigned long *    pdwMailboxID)
{
    long lResult = GetServiceState();
    if (lResult)
    {
        return lResult;
    }
    if (S_OK != GlobalObjectMap.FindObjFromName (SERVER_USER_MAILBOX, (LPSTR)szMailbox, pdwMailboxID))
    {
        return HRESULT_FROM_WIN32(ERROR_NO_SUCH_USER);
    }

    DWORD dwObjType;
    MAILBOX_INFO_A MBInfo = { 0 };
    lResult = GetObjectProp (*pdwMailboxID, &dwObjType, &MBInfo);
    if (lstrcmp (MBInfo.szPassword, (LPSTR)szPassword))
    {
        return HRESULT_FROM_WIN32(ERROR_INVALID_PASSWORD);
    }
    lstrcpy ((LPSTR)szMailbox, MBInfo.szMailboxName);
    lstrcpy ((LPSTR)szFullName, MBInfo.szFullName);
    return S_OK;
}

// The UNICODE version of these function, has not been implemented yet.
long RemoteChangePasswordW (wchar_t *       szMailbox,
                            wchar_t *       szOldPassword,
                            wchar_t *       szNewPassword)
{ return HRESULT_FROM_WIN32(E_NOTIMPL); }
long RemoteLogonMailBoxW (wchar_t *          szMailbox,
                          wchar_t *          szPassword,
                          wchar_t *          szFullName,
                          unsigned long *    pdwMailboxID)
{ return HRESULT_FROM_WIN32(E_NOTIMPL); }
long RemoteLogonMailBoxAndSetNotifW (wchar_t *          szMailbox,
                                     wchar_t *          szPassword,
                                     wchar_t *          szFullName,
                                     unsigned long *    pdwMailboxID,
                                     wchar_t *          szComputerName,
                                     unsigned long      ulNotifMask,
                                     unsigned long *    pulConnectionID)
{ return HRESULT_FROM_WIN32(E_NOTIMPL); }
long RemoteTerminateNotifW (wchar_t *       szComputerName,
                            unsigned long   ulConnectionID)
{ return HRESULT_FROM_WIN32(E_NOTIMPL); }
long RemoteValidateNotifW (wchar_t *        szComputerName,
                           wchar_t *        szMailboxName,
                           unsigned long    ulNotifMask,
                           unsigned long *  pulConnectionID)
{ return HRESULT_FROM_WIN32(E_NOTIMPL); }
long RemoteOpenMsgUploadPipeW (wchar_t *        szSenderMailbox,
                               long *           pPipeNumber,
                               unsigned char *  szCookie)
{ return HRESULT_FROM_WIN32(E_NOTIMPL); }
long RemoteSendMsgToAccountW (wchar_t * szRecipAccount,
                              wchar_t * szHeaderInfo,
                              wchar_t * szCookie)
{ return HRESULT_FROM_WIN32(E_NOTIMPL); }
long RemoteOpenMsgDownloadPipeW (wchar_t *          szMailbox,
                                 unsigned long *    pPipeNumber)
{ return HRESULT_FROM_WIN32(E_NOTIMPL); }
long RemoteOpenHeaderDownloadPipeW (wchar_t *   szMailbox,
                                    long *      pPipeNumber)
{ return HRESULT_FROM_WIN32(E_NOTIMPL); }
long RemoteCheckNewMailW (wchar_t *         szMailbox,
                          unsigned long *   pulPending)
{ return HRESULT_FROM_WIN32(E_NOTIMPL); }
long RemoteOpenOneMsgDownloadPipeW (wchar_t *   szMailbox,
                                    long *      pPipeNumber)
{ return HRESULT_FROM_WIN32(E_NOTIMPL); }
long RemoteGetRecipientPropsW (unsigned long    dwObjID,
                               unsigned long *  pdwObjType,
                               wchar_t *        szMailboxName,
                               wchar_t *        szFullName,
                               wchar_t *        szJobTitle,
                               wchar_t *        szOffice,
                               wchar_t *        szPhone,
                               wchar_t *        szAltPhone,
                               wchar_t *        szFax,
                               wchar_t *        szComments,
                               wchar_t *        szCompany,
                               wchar_t *        szDepartment,
                               wchar_t *        szManagerName,
                               wchar_t *        szManagerAlias,
                               unsigned long *  pdwManagerID)
{ return HRESULT_FROM_WIN32(E_NOTIMPL); }
long RemoteGetDistListPropsW (unsigned long     dwObjID,
                              wchar_t *         szDLAlias,
                              wchar_t *         szDLFullName,
                              unsigned long *   pdwContentCount,
                              wchar_t *         szOwnerAlias,
                              wchar_t *         szOwnerName,
                              wchar_t *         szComments)
{ return HRESULT_FROM_WIN32(E_NOTIMPL); }

// End of file for RABRPC.CPP
