home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / dbmsg / mapi / remote.srv / rxprpc.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-11  |  50.6 KB  |  1,447 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. //  File Name 
  4. //      RXPRPC.CPP
  5. //
  6. //  Description
  7. //      This file implements all the remote functions available to client
  8. //      WINDS message transport providers.
  9. //      
  10. //  Authors
  11. //      Irving De la Cruz
  12. //      Les Thaler
  13. //
  14. //  Revision: 1.7
  15. //
  16. // Written for Microsoft Windows Developer Support
  17. // Copyright (c) 1995-1996 Microsoft Corporation. All rights reserved.
  18. //
  19. #include "_WINDS.H"
  20. #include <RPC.H>
  21. #include "WINDS.H"     // Header file generated by the MIDL compiler
  22. #include "WDSADM.H"    // Header file generated by the MIDL compiler
  23.  
  24. typedef struct tagTHREAD_PROC_INFO
  25. {
  26.     HANDLE          hPipe;
  27.     HANDLE          hTmpFile;
  28.     TCHAR           szTmpFile[MAX_PATH];
  29.     TCHAR           szMailbox[MAX_ALIAS_SIZE+1];
  30. } THREAD_PROC_INFO, *PTHREAD_PROC_INFO;
  31.  
  32. typedef struct tagDL_DELIVERY_PROC_INFO
  33. {
  34.     TCHAR               szTmpFile[MAX_PATH];
  35.     TCHAR               szHeader[1024];
  36.     DIST_LIST_INFO      DLInfo;
  37.     DWORD               dwAliasDelivered;
  38.     LPTSTR *            ppszAliasList;
  39.     HANDLE              hWaitEvent;
  40.     HANDLE              hFile;
  41.     BOOL                fDeleteInfoStruct;
  42. } DL_DELIVERY_PROC_INFO, *PDL_DELIVERY_PROC_INFO;
  43.  
  44. extern "C"
  45. {
  46.     HRESULT WINAPI MsgUploadPipeThread
  47.                         (PTHREAD_PROC_INFO          pInfo);
  48.     HRESULT WINAPI MsgDownloadThread
  49.                         (PTHREAD_PROC_INFO          pInfo);
  50.     HRESULT WINAPI OneMsgDownloadPipeThread
  51.                         (PTHREAD_PROC_INFO          pInfo);
  52.     HRESULT WINAPI HeaderDLPipeThread
  53.                         (PTHREAD_PROC_INFO          pInfo);
  54.     DWORD WINAPI DistListDeliveryThread
  55.                         (PDL_DELIVERY_PROC_INFO     pDLInfo);
  56.     BOOL WINAPI DeleteMessage
  57.                         (HANDLE                     hResumeEvt,
  58.                          LPTSTR                     szMBox,
  59.                          LPBYTE                     pEID);
  60.     HANDLE WINAPI OpenMessage
  61.                         (HANDLE                     hResumeEvt,
  62.                          LPTSTR                     pszMailBox,
  63.                          LPBYTE                     pEID,
  64.                          ULONG                      ulCmd,
  65.                          ULONG *                    pulMsgLen);
  66.     HRESULT WINAPI ObjectDelivered
  67.                         (PDL_DELIVERY_PROC_INFO     pInfo,
  68.                          LPTSTR                     szObject);
  69. }
  70.  
  71. ///////////////////////////////////////////////////////////////////////////////
  72. //    RemoteOpenMsgUploadPipeA()
  73. //
  74. //    Parameters
  75. //
  76. //    Purpose
  77. //
  78. //    Return Value
  79. //
  80. long RemoteOpenMsgUploadPipeA (unsigned char *   szSenderMailbox,
  81.                                long *            pPipeNumber,
  82.                                unsigned char *   szCookie)
  83. {
  84.     LPTSTR pStrTok;
  85.     TCHAR szBuffer[_MAX_PATH];
  86.     long lResult = GetServiceState();
  87.     if (lResult)
  88.     {
  89.         return lResult;
  90.     }
  91.     DWORD dwMailboxID;
  92.     if (S_OK != GlobalObjectMap.FindObjFromName (SERVER_USER_MAILBOX, (LPSTR)szSenderMailbox, &dwMailboxID))
  93.     {
  94.         TraceMessage ("RemoteOpenUploadPipeA: The originator no longer has an account in this server");
  95.         return HRESULT_FROM_WIN32(ERROR_NO_SUCH_USER);
  96.     }
  97.  
  98.     PTHREAD_PROC_INFO pInfo = (PTHREAD_PROC_INFO)HeapAlloc (ghHeap,
  99.                                                             HEAP_ZERO_MEMORY,
  100.                                                             sizeof(THREAD_PROC_INFO));
  101.     if (NULL == pInfo)
  102.     {
  103.         TraceMessage ("RemoteOpenMsgUploadPipeA: Failed to allocate info structure");
  104.         return E_OUTOFMEMORY;
  105.     }
  106.     
  107.     lResult = GetLocalTempFileName (szBuffer);
  108.     if (lResult)
  109.     {
  110.         goto TerminateAndCleanup;
  111.     }
  112.     lstrcpy (pInfo->szTmpFile, szBuffer);
  113.     pInfo->hTmpFile = CreateFile (szBuffer,
  114.                                   GENERIC_WRITE,
  115.                                   FILE_SHARE_READ,
  116.                                   NULL,
  117.                                   CREATE_ALWAYS,
  118.                                   FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
  119.                                   NULL);
  120.     if (INVALID_HANDLE_VALUE == pInfo->hTmpFile)
  121.     {
  122.         lResult = HRESULT_FROM_WIN32(GetLastError());
  123.         TraceResult ("RemoteOpenMsgUploadPipeA: Failed to create the temp file", lResult);
  124.         goto TerminateAndCleanup;
  125.     }
  126.  
  127.     pStrTok = &szBuffer[lstrlen(szBuffer)];
  128.     while ('\\' != *pStrTok)
  129.     {
  130.         pStrTok--;
  131.     }
  132.     pStrTok++;
  133.     lstrcpy ((LPSTR)szCookie, pStrTok);
  134.     
  135.     *pPipeNumber = GetNextPipeID();
  136.  
  137.     SECURITY_ATTRIBUTES sa;
  138.     SECURITY_DESCRIPTOR sd;
  139.  
  140.     // Initialize the new security descriptor.
  141.     InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
  142.  
  143.     // Add a NULL descriptor ACL to the security descriptor.
  144.     SetSecurityDescriptorDacl (&sd, TRUE, (PACL)NULL, FALSE);
  145.  
  146.     sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  147.     sa.lpSecurityDescriptor = &sd;
  148.     sa.bInheritHandle = TRUE;
  149.  
  150.     // Create a pipe where we will expect the transport to send the data
  151.     wsprintf (szBuffer, SERVER_PIPE_NAME_FORMAT, *pPipeNumber);
  152.     pInfo->hPipe = CreateNamedPipe (szBuffer,
  153.                                     PIPE_ACCESS_INBOUND,
  154.                                     PIPE_WAIT | PIPE_READMODE_BYTE | PIPE_TYPE_BYTE,
  155.                                     1,
  156.                                     IO_BUFFERSIZE,
  157.                                     IO_BUFFERSIZE,
  158.                                     0,
  159.                                     &sa);
  160.     if (INVALID_HANDLE_VALUE == pInfo->hPipe || ERROR_INVALID_PARAMETER == (DWORD)pInfo->hPipe)
  161.     {
  162.         lResult = HRESULT_FROM_WIN32(GetLastError());
  163.         TraceResult ("RemoteOpenMsgUploadPipeA: Failed to create pipe", lResult);
  164.     }
  165.     else
  166.     {
  167.         DWORD dwThreadID;
  168.         HANDLE hThread = CreateThread (NULL,
  169.                                        0,
  170.                                        (LPTHREAD_START_ROUTINE)MsgUploadPipeThread,
  171.                                        (LPVOID)pInfo,
  172.                                        0,
  173.                                        &dwThreadID);
  174.         if (hThread)
  175.         {
  176.             TraceDebugger ("RemoteOpenMsgUploadPipeA: Message Upload thread spawned. ID: %X", dwThreadID);
  177.             CloseHandle (hThread);
  178.             pInfo = NULL; // The thread will free this memory
  179.         }
  180.         else
  181.         {
  182.             lResult = HRESULT_FROM_WIN32(GetLastError());
  183.             TraceResult ("RemoteOpenMsgUploadPipeA: Failed to create pipe thread", lResult);
  184.         }
  185.     }
  186. TerminateAndCleanup :
  187.     if (pInfo)
  188.     {
  189.         if (pInfo->hTmpFile && (ERROR_INVALID_HANDLE != (DWORD)pInfo->hTmpFile))
  190.         {
  191.             CloseHandle (pInfo->hTmpFile);
  192.         }
  193.         if (pInfo->hPipe)
  194.         {
  195.             CloseHandle (pInfo->hPipe);
  196.         }
  197.         HeapFree (ghHeap, 0, pInfo);
  198.     }
  199.     if (lResult)
  200.     {
  201.         if (FACILITY_NULL == HRESULT_FACILITY(lResult))
  202.         {
  203.             lResult = HRESULT_FROM_WIN32 (lResult);
  204.         }
  205.     }
  206.     return lResult;
  207. }
  208.  
  209. ///////////////////////////////////////////////////////////////////////////////
  210. //    RemoteSendMsgToAccountA()
  211. //
  212. //    Parameters
  213. //
  214. //    Purpose
  215. //
  216. //    Return Value
  217. //
  218. long RemoteSendMsgToAccountA (unsigned char * szRecipAccount,
  219.                               unsigned char * szHeaderInfo,
  220.                               unsigned char * szCookie)
  221. {
  222.     long lResult = GetServiceState();
  223.     if (lResult)
  224.     {
  225.         return lResult;
  226.     }
  227.     DWORD dwMailboxID;
  228.     WINDS_AB_OBJTYPE Type;
  229.     if (S_OK != GlobalObjectMap.FindObjAndTypeFromName ((LPSTR)szRecipAccount, &Type, &dwMailboxID))
  230.     {
  231.         TraceMessage ("RemoteSendMsgToAccountA: Rejecting message for an non-existing recipient");
  232.         return HRESULT_FROM_WIN32(ERROR_INVALID_ACCOUNT_NAME);
  233.     }
  234.     
  235.     TCHAR szTmpPath[_MAX_PATH];
  236.     if (!GetTempPath (_MAX_PATH, szTmpPath))
  237.     {
  238.         lResult = HRESULT_FROM_WIN32(GetLastError());
  239.         TraceResult ("RemoteSendMsgToAccountA: Failed to get temp path", lResult);
  240.         return HRESULT_FROM_WIN32 (lResult);
  241.     }
  242.  
  243.     lstrcat (szTmpPath, (LPSTR)szCookie);
  244.     PTHREAD_PROC_INFO pInfo = NULL;
  245.     PDL_DELIVERY_PROC_INFO pDLInfo = NULL;
  246.     HANDLE hFile = NULL, hWaitEvent;
  247. RetryOpenFile:
  248.     hFile = CreateFile (szTmpPath,
  249.                         GENERIC_READ,
  250.                         FILE_SHARE_READ,
  251.                         NULL,
  252.                         OPEN_ALWAYS,
  253.                         FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
  254.                         NULL);
  255.     if (INVALID_HANDLE_VALUE == hFile)
  256.     {
  257.         lResult = HRESULT_FROM_WIN32(GetLastError());
  258.         if (HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION) == lResult)
  259.         {
  260.             lResult = S_OK;
  261.             TraceMessage ("RemoteSendMsgToAccountA: Sharing Violation, waiting before retry");
  262.             SleepEx (200, FALSE);
  263.             goto RetryOpenFile;
  264.         }
  265.         TraceResult ("RemoteSendMsgToAccountA: Failed to open the temp file", lResult);
  266.         return lResult;
  267.     }
  268.     hWaitEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
  269.     if (!hWaitEvent)
  270.     {
  271.         lResult = HRESULT_FROM_WIN32(GetLastError());
  272.         TraceResult ("RemoteSendMsgToAccountA: Failed to create event for I/O thread", lResult);
  273.         goto ErrorExit;
  274.     }
  275.     if (SERVER_USER_MAILBOX == Type)
  276.     {
  277.         EnterCriticalSection (&g_csIOInfo);
  278.         SetEvent (g_IOInfo.hResumeEvent);
  279.         lstrcpy (g_IOInfo.szObject, (LPSTR)szRecipAccount);
  280.         lstrcpy (g_IOInfo.szHeader, (LPSTR)szHeaderInfo);
  281.         g_IOInfo.Action           = IO_COPY_MSG_FROM_FILE;
  282.         g_IOInfo.hActionCompleted = hWaitEvent;
  283.         g_IOInfo.hTmpFile         = hFile;
  284.         g_IOInfo.fCloseHandle     = TRUE;
  285.         hFile = NULL;
  286.         g_IOInfo.phLastError      = &lResult;
  287.         LeaveCriticalSection (&g_csIOInfo);
  288.         WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);
  289.     }
  290.     else
  291.     {
  292.         if (SERVER_DISTRIBUTION_LIST == Type)
  293.         {
  294.             pDLInfo = (PDL_DELIVERY_PROC_INFO)HeapAlloc (ghHeap,
  295.                                                          HEAP_ZERO_MEMORY,
  296.                                                          sizeof(DL_DELIVERY_PROC_INFO));
  297.             if (NULL == pDLInfo)
  298.             {
  299.                 TraceMessage ("RemoteSendMsgToAccountA: Failed to allocate info structure");
  300.                 lResult = E_OUTOFMEMORY;
  301.                 goto ErrorExit;
  302.             }
  303.             pDLInfo->fDeleteInfoStruct = TRUE;
  304.             lstrcpy (pDLInfo->DLInfo.szDLAlias, (LPSTR)szRecipAccount);
  305.             lstrcpy (pDLInfo->szHeader, (LPSTR)szHeaderInfo);
  306.             GetLocalTempFileName (pDLInfo->szTmpFile);
  307.             if (FALSE == CopyFile (szTmpPath, pDLInfo->szTmpFile, FALSE))
  308.             {
  309.                 lResult = HRESULT_FROM_WIN32(GetLastError());
  310.                 TraceResult ("RemoteSendMsgToAccountA: Failed to create duplicate tmp file for DL delivery", lResult);
  311.                 goto ErrorExit;
  312.             }
  313.  
  314.             EnterCriticalSection (&g_csIOInfo);
  315.             SetEvent (g_IOInfo.hResumeEvent);
  316.             g_IOInfo.Action           = IO_GET_DL_PROPERTIES;
  317.             g_IOInfo.hActionCompleted = hWaitEvent;
  318.             g_IOInfo.phLastError      = &lResult;
  319.             g_IOInfo.pDLInfo          = &(pDLInfo->DLInfo);
  320.             LeaveCriticalSection (&g_csIOInfo);
  321.             WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);
  322.             if (lResult)
  323.             {
  324.                 goto ErrorExit;
  325.             }
  326.             DWORD dwThreadID;
  327.             HANDLE hThread = CreateThread (NULL,
  328.                                            0,
  329.                                            (LPTHREAD_START_ROUTINE)DistListDeliveryThread,
  330.                                            (LPVOID)pDLInfo,
  331.                                            CREATE_SUSPENDED,
  332.                                            &dwThreadID);
  333.             if (hThread)
  334.             {
  335.                 TraceDebugger ("RemoteSendMsgToAccountA: Server DL delivery thread spawned. ID: %X", dwThreadID);
  336.                 SetThreadPriority (hThread, THREAD_PRIORITY_BELOW_NORMAL);
  337.  
  338.                 ResumeThread (hThread);
  339.                 CloseHandle (hThread);
  340.                 pDLInfo = NULL; // The thread will free this memory
  341.             }
  342.             else
  343.             {
  344.                 lResult = HRESULT_FROM_WIN32(GetLastError());
  345.                 TraceResult ("RemoteSendMsgToAccountA: Failed to create Server DL delivery thread", lResult);
  346.             }
  347.         }
  348.         else
  349.         {
  350.             TraceMessage ("RemoteSendMsgToAccountA: This type has not been implemented yet");
  351.             lResult = HRESULT_FROM_WIN32(ERROR_INVALID_ACCOUNT_NAME);
  352.         }
  353.     }
  354. ErrorExit:
  355.     if (lResult)
  356.     {
  357.         if (pDLInfo)
  358.         {
  359.             DeleteFile (pDLInfo->szTmpFile);
  360.             HeapFree (ghHeap, 0, pDLInfo);
  361.         }
  362.         if (pInfo)
  363.         {
  364.             DeleteFile (pInfo->szTmpFile);
  365.             HeapFree (ghHeap, 0, pInfo);
  366.         }
  367.     }
  368.     if (hFile)
  369.     {
  370.         CloseHandle (hFile);
  371.     }
  372.     if (hWaitEvent)
  373.     {
  374.         CloseHandle (hWaitEvent);
  375.     }
  376.     return lResult;
  377. }
  378.  
  379. ///////////////////////////////////////////////////////////////////////////////
  380. //    RemoteFinishUpload()
  381. //
  382. //    Parameters
  383. //
  384. //    Purpose
  385. //
  386. //    Return Value
  387. //
  388. long RemoteFinishUpload (unsigned char * szCookie)
  389. {
  390.     long lResult = GetServiceState();
  391.     if (lResult)
  392.     {
  393.         return lResult;
  394.     }
  395.     TCHAR szTmpPath[_MAX_PATH];
  396.     if (!GetTempPath (_MAX_PATH, szTmpPath))
  397.     {
  398.         lResult = HRESULT_FROM_WIN32(GetLastError());
  399.         TraceResult ("RemoteFinishUpload: Failed to get temp path", lResult);
  400.         lResult = lResult;
  401.     }
  402.     else
  403.     {
  404.         lstrcat (szTmpPath, (LPSTR)szCookie);
  405.         DeleteFile (szTmpPath);
  406.     }
  407.     return lResult;
  408. }
  409.  
  410. ///////////////////////////////////////////////////////////////////////////////
  411. //    RemoteOpenHeaderDownloadPipeA()
  412. //
  413. //    Parameters
  414. //
  415. //    Purpose
  416. //
  417. //    Return Value
  418. //
  419. long RemoteOpenHeaderDownloadPipeA (unsigned char * szMailbox, long * pPipeNumber)
  420. {
  421.     long lResult = GetServiceState();
  422.     if (lResult)
  423.     {
  424.         return lResult;
  425.     }
  426.     DWORD dwMailboxID;
  427.     if (S_OK != GlobalObjectMap.FindObjFromName (SERVER_USER_MAILBOX, (LPSTR)szMailbox, &dwMailboxID))
  428.     {
  429.         TraceMessage ("RemoteOpenHeaderDownloadPipeA: Invalid user mailbox");
  430.         return HRESULT_FROM_WIN32(ERROR_NO_SUCH_USER);
  431.     }
  432.     
  433.     *pPipeNumber = GetNextPipeID();
  434.  
  435.     TCHAR szBuffer[_MAX_PATH];
  436.     lResult = GetLocalTempFileName (szBuffer);
  437.     if (lResult)
  438.     {
  439.         return lResult;
  440.     }
  441.     HANDLE hFile = CreateFile (szBuffer,
  442.                                GENERIC_READ | GENERIC_WRITE,
  443.                                FILE_SHARE_READ,
  444.                                NULL,
  445.                                OPEN_ALWAYS,
  446.                                FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
  447.                                NULL);
  448.     if (INVALID_HANDLE_VALUE == hFile)
  449.     {
  450.         lResult = HRESULT_FROM_WIN32(GetLastError());
  451.         TraceResult ("RemoteOpenHeaderDownloadPipeA: Failed to temp file", lResult);
  452.         return lResult;
  453.     }
  454.  
  455.     SECURITY_ATTRIBUTES sa;
  456.     SECURITY_DESCRIPTOR sd;
  457.  
  458.     // Initialize the new security descriptor.
  459.     InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
  460.  
  461.     // Add a NULL descriptor ACL to the security descriptor.
  462.     SetSecurityDescriptorDacl (&sd, TRUE, (PACL)NULL, FALSE);
  463.  
  464.     sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  465.     sa.lpSecurityDescriptor = &sd;
  466.     sa.bInheritHandle = TRUE;
  467.     
  468.     wsprintf (szBuffer, SERVER_PIPE_NAME_FORMAT, *pPipeNumber);
  469.     HANDLE hPipe = CreateNamedPipe (szBuffer,
  470.                                     PIPE_ACCESS_OUTBOUND,
  471.                                     PIPE_WAIT | PIPE_READMODE_BYTE | PIPE_TYPE_BYTE,
  472.                                     1,
  473.                                     IO_BUFFERSIZE,
  474.                                     IO_BUFFERSIZE,
  475.                                     0,
  476.                                     &sa);
  477.     if (INVALID_HANDLE_VALUE == hPipe || ERROR_INVALID_PARAMETER == (DWORD)hPipe)
  478.     {
  479.         lResult = HRESULT_FROM_WIN32(GetLastError());
  480.         TraceResult ("RemoteOpenHeaderDownloadPipeA: Failed to create pipe", lResult);
  481.     }
  482.     else
  483.     {
  484.         PTHREAD_PROC_INFO pInfo = (PTHREAD_PROC_INFO)HeapAlloc (ghHeap,
  485.                                                                 HEAP_ZERO_MEMORY,
  486.                                                                 sizeof(THREAD_PROC_INFO));
  487.         if (pInfo)
  488.         {
  489.             lstrcpy (pInfo->szMailbox, (LPSTR)szMailbox);
  490.             pInfo->hPipe = hPipe;
  491.             pInfo->hTmpFile = hFile;
  492.             DWORD dwThreadID;
  493.             HANDLE hThread = CreateThread (NULL,
  494.                                            0,
  495.                                            (LPTHREAD_START_ROUTINE)HeaderDLPipeThread,
  496.                                            (LPVOID)pInfo,
  497.                                            0,
  498.                                            &dwThreadID);
  499.             if (hThread)
  500.             {
  501.                 TraceDebugger ("RemoteOpenHeaderDownloadPipeA: Header download thread spawned. ID: %X", dwThreadID);
  502.                 CloseHandle (hThread);
  503.             }
  504.             else
  505.             {
  506.                 lResult = HRESULT_FROM_WIN32(GetLastError());
  507.                 TraceResult ("RemoteOpenHeaderDownloadPipeA: Failed to create pipe thread", lResult);
  508.             }
  509.         }
  510.         else
  511.         {
  512.             TraceMessage ("RemoteOpenHeaderDownloadPipeA: Failed to allocate info structure");
  513.             lResult = E_OUTOFMEMORY;
  514.         }
  515.     }
  516.     if (lResult)
  517.     {
  518.         CloseHandle (hPipe);
  519.         CloseHandle (hFile);
  520.     }
  521.     return lResult;
  522. }
  523.  
  524. ///////////////////////////////////////////////////////////////////////////////
  525. //    RemoteOpenMsgDownloadPipeA()
  526. //
  527. //    Parameters
  528. //
  529. //    Purpose
  530. //
  531. //    Return Value
  532. //
  533. long RemoteOpenMsgDownloadPipeA (unsigned char *     szMailbox,
  534.                                  unsigned long *     pPipeNumber)
  535. {
  536.     long lResult = GetServiceState();
  537.     if (lResult)
  538.     {
  539.         return lResult;
  540.     }
  541.     DWORD dwMailboxID;
  542.     if (S_OK != GlobalObjectMap.FindObjFromName (SERVER_USER_MAILBOX, (LPSTR)szMailbox, &dwMailboxID))
  543.     {
  544.         TraceMessage ("RemoteOpenMsgDownloadPipeA: Invalid user mailbox");
  545.         return HRESULT_FROM_WIN32(ERROR_NO_SUCH_USER);
  546.     }
  547.     
  548.     PTHREAD_PROC_INFO pInfo = (PTHREAD_PROC_INFO)HeapAlloc (ghHeap,
  549.                                                             HEAP_ZERO_MEMORY,
  550.                                                             sizeof(THREAD_PROC_INFO));
  551.     if (!pInfo)
  552.     {
  553.         TraceMessage ("RemoteOpenMsgDownloadPipeA: Failed to allocate info structure");
  554.         return E_OUTOFMEMORY;
  555.     }
  556.     lstrcpy (pInfo->szMailbox, (LPSTR)szMailbox);
  557.  
  558.     *pPipeNumber = GetNextPipeID();
  559.     
  560.     SECURITY_ATTRIBUTES sa;
  561.     SECURITY_DESCRIPTOR sd;
  562.  
  563.     // Initialize the new security descriptor.
  564.     InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
  565.  
  566.     // Add a NULL descriptor ACL to the security descriptor.
  567.     SetSecurityDescriptorDacl (&sd, TRUE, (PACL)NULL, FALSE);
  568.  
  569.     sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  570.     sa.lpSecurityDescriptor = &sd;
  571.     sa.bInheritHandle = TRUE;
  572.  
  573.     TCHAR szPipeName[64];
  574.     wsprintf (szPipeName, SERVER_PIPE_NAME_FORMAT, *pPipeNumber);
  575.     pInfo->hPipe = CreateNamedPipe (szPipeName,
  576.                                     PIPE_ACCESS_DUPLEX,
  577.                                     PIPE_WAIT | PIPE_READMODE_BYTE | PIPE_TYPE_BYTE,
  578.                                     1,
  579.                                     IO_BUFFERSIZE,
  580.                                     IO_BUFFERSIZE,
  581.                                     0,
  582.                                     &sa);
  583.     if (INVALID_HANDLE_VALUE == pInfo->hPipe || ERROR_INVALID_PARAMETER == (DWORD)pInfo->hPipe)
  584.     {
  585.         lResult = HRESULT_FROM_WIN32(GetLastError());
  586.         TraceResult ("RemoteOpenMsgDownloadPipeA: Failed to create pipe", lResult);
  587.     }
  588.     else
  589.     {
  590.         DWORD dwThreadID;
  591.         HANDLE hThread = CreateThread (NULL,
  592.                                        0,
  593.                                        (LPTHREAD_START_ROUTINE)MsgDownloadThread,
  594.                                        (LPVOID)pInfo,
  595.                                        0,
  596.                                        &dwThreadID);
  597.         if (hThread)
  598.         {
  599.             TraceDebugger ("RemoteOpenMsgDownloadPipeA: Header download thread spawned. ID: %X", dwThreadID);
  600.             CloseHandle (hThread);
  601.         }
  602.         else
  603.         {
  604.             lResult = HRESULT_FROM_WIN32(GetLastError());
  605.             TraceResult ("RemoteOpenMsgDownloadPipeA: Failed create doanload thread", lResult);
  606.         }
  607.     }
  608.  
  609.     if (lResult)
  610.     {
  611.         if (FACILITY_NULL == HRESULT_FACILITY(lResult))
  612.         {
  613.             lResult = HRESULT_FROM_WIN32 (lResult);
  614.         }
  615.         HeapFree (ghHeap, 0, pInfo);
  616.     }
  617.     return lResult;
  618. }
  619.  
  620. ///////////////////////////////////////////////////////////////////////////////
  621. //    MsgUploadPipeThread()
  622. //
  623. //    Parameters
  624. //
  625. //    Purpose
  626. //
  627. //    Return Value
  628. //
  629. HRESULT WINAPI MsgUploadPipeThread (PTHREAD_PROC_INFO pInfo)
  630. {
  631.     BYTE abBuffer[IO_BUFFERSIZE];
  632.     DWORD dwBytesWrite, dwBytesRead = 0;
  633.     
  634.     ConnectNamedPipe (pInfo->hPipe, NULL);
  635.     HRESULT hResult = S_OK;
  636.     do
  637.     {
  638.         // Wait until the client writes to the pipe
  639.         if (!ReadFile (pInfo->hPipe, abBuffer, IO_BUFFERSIZE, &dwBytesRead, NULL))
  640.         {
  641.             // There was an error and we can't continue
  642.             hResult = HRESULT_FROM_WIN32(GetLastError());
  643.             if (hResult != HRESULT_FROM_WIN32(ERROR_BROKEN_PIPE))
  644.             {
  645.                 TraceResult ("MsgUploadPipeThread: Failed to read from the msg upload pipe", hResult);
  646.             }
  647.             else
  648.             {
  649.                 hResult = 0;
  650.             }
  651.         }
  652.         if (dwBytesRead && !hResult)
  653.         {
  654.             if (!WriteFile (pInfo->hTmpFile, abBuffer, dwBytesRead, &dwBytesWrite, NULL))
  655.             {
  656.                 hResult = HRESULT_FROM_WIN32(GetLastError());
  657.                 TraceResult ("MsgUploadPipeThread: Failed to write to the local tmp file", hResult);
  658.             }
  659.         }
  660.     } while (dwBytesRead && !hResult);
  661.  
  662.     TraceResult ("MsgUploadPipeThread", hResult);
  663.     CloseHandle (pInfo->hTmpFile);
  664.     CloseHandle (pInfo->hPipe);
  665.     if (hResult)
  666.     {
  667.         DeleteFile (pInfo->szTmpFile);
  668.     }
  669.     HeapFree (ghHeap, 0, pInfo);
  670.     return hResult;
  671. }
  672.  
  673. ///////////////////////////////////////////////////////////////////////////////
  674. //    HeaderDLPipeThread()
  675. //
  676. //    Parameters
  677. //
  678. //    Purpose
  679. //
  680. //    Return Value
  681. //
  682. HRESULT WINAPI HeaderDLPipeThread (PTHREAD_PROC_INFO pInfo)
  683. {
  684.     BYTE abBuffer[IO_BUFFERSIZE];
  685.     DWORD dwBytesRead, dwBytesWrite;
  686.     HRESULT hResult;
  687.     HANDLE hWaitEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
  688.     if (!hWaitEvent)
  689.     {
  690.         hResult = HRESULT_FROM_WIN32(GetLastError());
  691.         TraceResult ("HeaderDLPipeThread: Failed to create event for I/O thread", hResult);
  692.         goto Error;
  693.     }
  694.  
  695.     EnterCriticalSection (&g_csIOInfo);
  696.     SetEvent (g_IOInfo.hResumeEvent);
  697.     lstrcpy (g_IOInfo.szObject, pInfo->szMailbox);
  698.     g_IOInfo.Action           = IO_COPY_HEADERS_TO_FILE;
  699.     g_IOInfo.hTmpFile         = pInfo->hTmpFile;
  700.     g_IOInfo.hActionCompleted = hWaitEvent;
  701.     g_IOInfo.phLastError      = &hResult;
  702.     LeaveCriticalSection (&g_csIOInfo);
  703.  
  704.     WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);
  705.     CloseHandle (hWaitEvent);
  706.     if (hResult)
  707.     {
  708.         goto Error;
  709.     }
  710.  
  711.     // Wait until the client connects to the pipe
  712.     ConnectNamedPipe (pInfo->hPipe, NULL);
  713.     
  714.     do
  715.     {
  716.         if (!ReadFile (pInfo->hTmpFile, abBuffer, IO_BUFFERSIZE, &dwBytesRead, NULL))
  717.         {
  718.             hResult = HRESULT_FROM_WIN32(GetLastError());
  719.             TraceResult ("HeaderDLPipeThread: Failed to read the tmp file", hResult);
  720.         }
  721.         if (dwBytesRead && !hResult)
  722.         {
  723.             if (!WriteFile (pInfo->hPipe, abBuffer, dwBytesRead, &dwBytesWrite, NULL))
  724.             {
  725.                 hResult = HRESULT_FROM_WIN32(GetLastError());
  726.                 TraceResult ("HeaderDLPipeThread: Failed to write to the pipe", hResult);
  727.             }
  728.         }
  729.     } while (dwBytesRead && !hResult);
  730.  
  731. Error:
  732.     CloseHandle (pInfo->hTmpFile);
  733.     CloseHandle (pInfo->hPipe);
  734.     HeapFree (ghHeap, 0, pInfo);
  735.     return hResult;
  736. }
  737.  
  738. ////////////////////////////////////////////////////////////////////////////
  739. //    MsgDownloadThread()
  740. //
  741. //    Parameters
  742. //          pInfo       pointer to a THREAD_PROC_INFO containing the handle to
  743. //                      the open pipe for data transmission to the remote XP
  744. //
  745. //    Purpose
  746. //          This is the worker thread that is spawned when a request to
  747. //          messages arrives from the remote XP via RemoteOpenMsgDownloadPipe.
  748. //          Once the pipe has been opened the remote XP sends command messages
  749. //          on the pipe to request data from the server. These command messages
  750. //          are of 3 types: MSG_MOVE, MSG_DOWNLOAD, and MSG_DELETE. The command
  751. //          messages have a msg ID that tells the requested operation. When this
  752. //          thread is started, it creates an event object for synchronization
  753. //          with the storage thread that accesses the message database then
  754. //          immediately blocks waiting for the XP to connect to the pipe. We 
  755. //          unblock and start reading command requests. Each mail message we 
  756. //          process goes through the following cycle:
  757. //          
  758. //              1. read the command message, this contains the operation
  759. //                 requested by the XP and the mail message's entry ID
  760. //              
  761. //              2. if the command is to HANG UP, quit, otherwise:
  762. //
  763. //                 look up the entry ID of the mail message in the storage.
  764. //                 if unsuccessful, send a NAK message back to the XP
  765. //          
  766. //                 if the request is to DELETE, delete the message and if
  767. //                 successful send an ACK message back to the XP, otherwise
  768. //                 send a NAK message back, then start on the next request
  769. //
  770. //                 if the request is to MOVE or DOWNLOAD, get the mail message's
  771. //                 size, stuff it in an ACK message and write it to the XP.then
  772. //                 stream the mail message over the pipe
  773. //
  774. //              3. read the next command
  775. //  
  776. //          We treat write errors to the pipe as fatal and disconnect.
  777. //
  778. //    Return Value
  779. //          
  780. HRESULT WINAPI MsgDownloadThread(PTHREAD_PROC_INFO pInfo)
  781. {
  782.     MSG_HDR     MsgHdr;
  783.     HANDLE      hTmpFile;
  784.     DWORD       dwBytesRead, dwBytesWritten;
  785.     HRESULT hResult = S_OK;
  786.     HANDLE      hResumeEvt  = CreateEvent(NULL, FALSE, FALSE, NULL);
  787.  
  788.     if (!hResumeEvt)
  789.     {
  790.         hResult = HRESULT_FROM_WIN32(GetLastError());
  791.         TraceResult ("MsgDownloadThread: Failed to create event", hResult);
  792.         goto Quit;
  793.     }
  794.  
  795.     // block until XP connects to us
  796.     ConnectNamedPipe (pInfo->hPipe, NULL);
  797.  
  798.     while (TRUE)
  799.     {
  800.         if (!ReadFile(pInfo -> hPipe, &MsgHdr, sizeof(MSG_HDR), &dwBytesRead, NULL))
  801.             break; // Out of the WHILE() loop
  802.  
  803.         ASSERT (dwBytesRead == sizeof(MSG_HDR));
  804.  
  805.         switch (MsgHdr.ulMID)
  806.         {
  807.             case MSG_MOVE:  // Fall through
  808.             case MSG_DOWNLOAD:
  809.  
  810.                 // tell IO thread to open msg's container, write it
  811.                 // to a temp file and return us its size and handle
  812.  
  813.                 hTmpFile = OpenMessage(hResumeEvt, 
  814.                                        pInfo->szMailbox,
  815.                                        MsgHdr.Info.EID,
  816.                                        MsgHdr.ulMID,
  817.                                        &MsgHdr.Info.
  818.                                        ulMsgLen);
  819.                 if (!hTmpFile)
  820.                 {   
  821.                     MsgHdr.ulMID = OP_FAILED;           // send a NAK back to XP
  822.                     MsgHdr.Info.ulMsgLen = 0;
  823.                     if (!WriteFile(pInfo->hPipe, &MsgHdr, sizeof(MSG_HDR), &dwBytesWritten, NULL))
  824.                     {
  825.                         goto Quit;
  826.                     }
  827.                 }
  828.                 else
  829.                 {   
  830.                     MsgHdr.ulMID = OP_STARTED;         // send an ACK to XP
  831.                     // Bail on any write errors, the connection is down                    
  832.                     if (!WriteFile(pInfo->hPipe, &MsgHdr, sizeof(MSG_HDR), &dwBytesWritten, NULL))
  833.                     {
  834.                         goto Quit;
  835.                     }
  836.                     
  837.                     // set seek pointer to beginning of temp file
  838.                     if ((DWORD)-1 == SetFilePointer(hTmpFile, 0, NULL, FILE_BEGIN))
  839.                         break;
  840.  
  841.                     if (NO_ERROR != FileCopy(pInfo -> hPipe, hTmpFile, MsgHdr.Info.ulMsgLen))
  842.                         goto Quit;
  843.  
  844.                 }                    
  845.                 break;                
  846.                                     
  847.             case MSG_DELETE:
  848.                 // tell storage thread to delete msg's substorage
  849.                 MsgHdr.ulMID = (DeleteMessage (hResumeEvt, pInfo->szMailbox, MsgHdr.Info.EID) ? OP_COMPLETE : OP_FAILED);
  850.                 MsgHdr.Info.ulMsgLen = 0;
  851.                 
  852.                 // send ACK/NAK to XP
  853.                 if (!WriteFile (pInfo->hPipe, &MsgHdr, sizeof(MSG_HDR), &dwBytesWritten, NULL))
  854.                 {
  855.                     goto Quit;
  856.                 }
  857.                 break;
  858.                         
  859.             case GOODBYE:            // HANG UP
  860.                 goto Quit;        
  861.             
  862.             default :
  863.                 // don't attempt to resynchronize
  864.                 goto Quit;             
  865.         }      
  866.     }
  867.  
  868. Quit:
  869.     CloseHandle (pInfo->hPipe);
  870.     CloseHandle (hResumeEvt);
  871.     HeapFree (ghHeap, 0, pInfo);
  872.     return hResult;
  873. }
  874.  
  875. ////////////////////////////////////////////////////////////////////////////
  876. //    DeleteMessage()
  877. //
  878. //    Parameters
  879. //          hResumeEvt          handle to event object for signaling completion
  880. //                              of storage operation
  881. //          szMailBox           Name of mailbox for the mail msg we're handling
  882. //          pEID                entry ID of msg we're handling
  883. //    Purpose
  884. //          Sends a DELETE request to the storage thread.The request, along 
  885. //          with the message's EID, and the mailbox name where the message 
  886. //          resides are passed to the storage thread in g_IOInfo. We then block
  887. //          on an event from the storage thread signaling completetion of the
  888. //          requested operations. The storage finds the mail message and
  889. //          deletes it.                    
  890. //
  891. //    Return Value
  892. //          TRUE on success,FALSE otherwise
  893. //
  894. BOOL WINAPI DeleteMessage(HANDLE hResumeEvt, LPTSTR pszMailBox, LPBYTE pEID)
  895. {
  896.     HRESULT hResult = S_OK;
  897.     // In Windows NT 3.5 OLE storages can only be accessed by a single thread, so use
  898.     // this global data struct to pass data to the storage thread
  899.     EnterCriticalSection (&g_csIOInfo);
  900.     SetEvent(g_IOInfo.hResumeEvent);
  901.     g_IOInfo.Action           = IO_DELETE_MSG_IN_MAILBOX;
  902.     g_IOInfo.hActionCompleted = hResumeEvt;        
  903.     g_IOInfo.phLastError      = &hResult;
  904.     g_IOInfo.dwObjID          = (DWORD)atol((LPCSTR) &pEID[4]);
  905.     lstrcpy (g_IOInfo.szObject, pszMailBox);
  906.     LeaveCriticalSection (&g_csIOInfo);
  907.  
  908.     // Block until the storage thread finishes
  909.     WaitForSingleObject(hResumeEvt, GENERAL_TIME_OUT);
  910.     return (S_OK == hResult ? TRUE : FALSE);
  911. }
  912.  
  913. ////////////////////////////////////////////////////////////////////////////
  914. //    OpenMessage()
  915. //
  916. //    Parameters
  917. //          hResumeEvt          handle to event object for signaling completion
  918. //                              of storage operation
  919. //          pszMailBox          name of mailbox for the mail msg we're handling
  920. //          pEID                entry ID of msg we're handling
  921. //          ulCmd               operation to perform on the message
  922. //          pulMsgLen           to pass back the size of the data stream
  923. //    Purpose
  924. //          Create a temporary file to hold the mail message, then send
  925. //          a request for the operation passed in ulCmd to the storage
  926. //          thread.The request, along with the message's EID, the mailbox
  927. //          name where the message resides, and the handle to the tempfile
  928. //          are passed to the storage thread in g_IOInfo. We then block on
  929. //          an event from the storage thread signaling completetion of the
  930. //          requested operations. The storage finds the mail message and
  931. //          copies it into the tempfile passing back the size in pulMsgLen.                    
  932. //
  933. //    Return Value
  934. //          Handle of temp file on success, NULL otherwise
  935. //
  936. HANDLE WINAPI OpenMessage(HANDLE   hResumeEvt,
  937.                           LPTSTR   pszMailBox,
  938.                           LPBYTE   pEID,
  939.                           ULONG    ulCmd,
  940.                           ULONG *  pulMsgLen)
  941. {
  942.     HANDLE      hTempFile = NULL;                    
  943.     HRESULT     hResult;
  944.     TCHAR       szTempFile[MAX_PATH];
  945.     ACTION      Action;
  946.     // creates a unique tempfile name  
  947.     if (GetLocalTempFileName (szTempFile))
  948.     {
  949.         return NULL;
  950.     }
  951.  
  952.     switch (ulCmd)
  953.     {
  954.         case MSG_DOWNLOAD :
  955.             Action = IO_COPY_MSG_TO_FILE;
  956.             break;
  957.  
  958.         case MSG_MOVE :
  959.             Action = IO_MOVE_MSG_TO_FILE;
  960.             break;
  961.  
  962.         default : 
  963.             TraceMessage ("OpenMessage: Invalid command received");
  964.             ASSERT (FALSE);
  965.             return NULL;
  966.     }
  967.  
  968.     // create tempfile to hold message
  969.     if (! (hTempFile = CreateFile(szTempFile,
  970.                                   GENERIC_READ | GENERIC_WRITE,
  971.                                   FILE_SHARE_READ,
  972.                                   NULL,
  973.                                   CREATE_ALWAYS,
  974.                                   FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
  975.                                   NULL)))
  976.         return NULL;
  977.  
  978.     // OLE storages can only be accessed by a single thread, so use
  979.     // this global data struct to pass data to the storage thread
  980.  
  981.     EnterCriticalSection (&g_csIOInfo);
  982.     SetEvent (g_IOInfo.hResumeEvent);
  983.     g_IOInfo.Action           = Action;        // requested operation
  984.     g_IOInfo.hActionCompleted = hResumeEvt;    // signal us on this event    
  985.     g_IOInfo.phLastError      = &hResult;
  986.     g_IOInfo.dwObjID          = (DWORD) atol((const char *) &pEID[4]);
  987.     g_IOInfo.hTmpFile         = hTempFile;     // storage thread writes msg here
  988.     g_IOInfo.pdwData          = pulMsgLen;     // storage thread writes length here
  989.     lstrcpy (g_IOInfo.szObject, pszMailBox);
  990.     LeaveCriticalSection (&g_csIOInfo);
  991.  
  992.     // block until storage thread finishes
  993.     WaitForSingleObject(hResumeEvt, GENERAL_TIME_OUT);
  994.     return (hResult ? NULL : hTempFile);
  995. }
  996.  
  997. ////////////////////////////////////////////////////////////////////////////
  998. //    DistListDeliveryThread()
  999. //
  1000. //    Parameters
  1001. //
  1002. //    Purpose
  1003. //      This function is RECURSIVE
  1004. //
  1005. //    Return Value
  1006. //          
  1007. DWORD WINAPI DistListDeliveryThread (PDL_DELIVERY_PROC_INFO pDLInfo)
  1008. {
  1009.     DLM_LIST_A * pNode, *pSubNode;
  1010.     DL_DELIVERY_PROC_INFO SubDLInfo = { 0 };
  1011.     DWORD j, dwResult = S_OK;
  1012.     HRESULT hResult;
  1013.     HANDLE hWaitEvent, hFile;
  1014.     ObjectDelivered (pDLInfo, pDLInfo->DLInfo.szDLAlias);
  1015.     if (NULL == pDLInfo->hFile)
  1016.     {
  1017.         hFile = CreateFile (pDLInfo->szTmpFile,
  1018.                             GENERIC_READ,
  1019.                             0,
  1020.                             NULL,
  1021.                             OPEN_ALWAYS,
  1022.                             FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
  1023.                             NULL);
  1024.         if (INVALID_HANDLE_VALUE == hFile)
  1025.         {
  1026.             dwResult = HRESULT_FROM_WIN32(GetLastError());
  1027.             TraceResult ("DistListDeliveryThread: Failed to open the temp file", dwResult);
  1028.             goto ErrorExit;
  1029.         }
  1030.         pDLInfo->hFile = hFile;
  1031.     }
  1032.     else
  1033.     {
  1034.         hFile = pDLInfo->hFile;
  1035.     }
  1036.     if (NULL == pDLInfo->hWaitEvent)
  1037.     {
  1038.         hWaitEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
  1039.         if (!hWaitEvent)
  1040.         {
  1041.             TraceResult ("DistListDeliveryThread: Failed to create event for I/O thread", HRESULT_FROM_WIN32(GetLastError()));
  1042.         }
  1043.         pDLInfo->hWaitEvent = hWaitEvent;
  1044.     }
  1045.     else
  1046.     {
  1047.         hWaitEvent = pDLInfo->hWaitEvent;
  1048.     }
  1049.     // Process the USER mailboxes first
  1050.     pNode = (DLM_LIST_A *)pDLInfo->DLInfo.pMembers;
  1051.     while (pNode)
  1052.     {
  1053.         if (SERVER_USER_MAILBOX != (WINDS_AB_OBJTYPE)pNode->Info.dwMemberType)
  1054.         {
  1055.             continue;
  1056.         }
  1057.         SetFilePointer (hFile, 0, NULL, FILE_BEGIN);
  1058.         EnterCriticalSection (&g_csIOInfo);
  1059.         SetEvent (g_IOInfo.hResumeEvent);
  1060.         lstrcpy (g_IOInfo.szObject, (LPSTR)pNode->Info.szMemberAlias);
  1061.         lstrcpy (g_IOInfo.szHeader, pDLInfo->szHeader);
  1062.         g_IOInfo.Action           = IO_COPY_MSG_FROM_FILE;
  1063.         g_IOInfo.hActionCompleted = hWaitEvent;
  1064.         g_IOInfo.hTmpFile         = hFile;
  1065.         g_IOInfo.fCloseHandle     = FALSE;
  1066.         g_IOInfo.phLastError      = &hResult;
  1067.         LeaveCriticalSection (&g_csIOInfo);
  1068.         WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);
  1069.  
  1070.         // The message was successfully delivered to the recipient, so add it to the "DELIVERED" list
  1071.         if (S_OK == hResult)
  1072.         {
  1073.             ObjectDelivered (pDLInfo, (LPSTR)pNode->Info.szMemberAlias);
  1074.         }
  1075.         pNode = pNode->pNext;
  1076.     }
  1077.     lstrcpy (SubDLInfo.szHeader, pDLInfo->szHeader);
  1078.     SubDLInfo.hFile = hFile;
  1079.     SubDLInfo.hWaitEvent = hWaitEvent;
  1080.  
  1081.     // Process the Distribution lists second
  1082.     pNode = (DLM_LIST_A *)pDLInfo->DLInfo.pMembers;
  1083.     while (pNode)
  1084.     {
  1085.         if (SERVER_DISTRIBUTION_LIST != (WINDS_AB_OBJTYPE)pNode->Info.dwMemberType)
  1086.         {
  1087.             continue;
  1088.         }
  1089.         for (j=0; j<pDLInfo->dwAliasDelivered; j++)
  1090.         {
  1091.             // If the message has already been delivered to this sub DL, skip it
  1092.             if (0 == lstrcmp ((LPSTR)pNode->Info.szMemberAlias, pDLInfo->ppszAliasList[j]))
  1093.             {
  1094.                 continue;
  1095.             }
  1096.         }
  1097.  
  1098.         lstrcpy (SubDLInfo.DLInfo.szDLAlias, (LPSTR)pNode->Info.szMemberAlias);
  1099.         SubDLInfo.fDeleteInfoStruct = FALSE;
  1100.         SubDLInfo.DLInfo.pMembers = NULL;
  1101.         SubDLInfo.dwAliasDelivered = pDLInfo->dwAliasDelivered;
  1102.         SubDLInfo.ppszAliasList = pDLInfo->ppszAliasList;
  1103.  
  1104.         EnterCriticalSection (&g_csIOInfo);
  1105.         SetEvent (g_IOInfo.hResumeEvent);
  1106.         g_IOInfo.Action           = IO_GET_DL_PROPERTIES;
  1107.         g_IOInfo.hActionCompleted = hWaitEvent;
  1108.         g_IOInfo.phLastError      = &hResult;
  1109.         g_IOInfo.pDLInfo          = &(SubDLInfo.DLInfo);
  1110.         LeaveCriticalSection (&g_csIOInfo);
  1111.         WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);
  1112.         if (hResult)
  1113.         {
  1114.             TraceResult ("DistListDeliveryThread: Could not get DL properties", hResult);
  1115.             continue;
  1116.         }
  1117.  
  1118.         pSubNode = (DLM_LIST_A *)SubDLInfo.DLInfo.pMembers;
  1119.         while (pSubNode)
  1120.         {
  1121.             for (j=0; j<pDLInfo->dwAliasDelivered; j++)
  1122.             {
  1123.                 // If the message has already been delivered to a member of the Sub DL
  1124.                 // mark the entry in the sub DL so that it won't deliver to that recipient.
  1125.                 if (0 == lstrcmp ((LPSTR)pSubNode->Info.szMemberAlias, pDLInfo->ppszAliasList[j]))
  1126.                 {
  1127.                     pSubNode->Info.dwMemberType = (DWORD)UNDEFINED_OBJECT_TYPE;
  1128.                 }
  1129.             }
  1130.             pSubNode = pSubNode->pNext;
  1131.         }
  1132.         // Deliver to the members of the sub-distribution list        
  1133.         hResult = DistListDeliveryThread (&SubDLInfo);
  1134.         // Remember how many recipients were handled in this sub DL
  1135.         pDLInfo->dwAliasDelivered = SubDLInfo.dwAliasDelivered;
  1136.         pDLInfo->ppszAliasList = SubDLInfo.ppszAliasList;
  1137.         if (SubDLInfo.DLInfo.pMembers)
  1138.         {
  1139.             HeapFree (ghHeap, 0, SubDLInfo.DLInfo.pMembers);
  1140.         }
  1141.         pNode = pNode->pNext;
  1142.     }
  1143.  
  1144. ErrorExit:
  1145.     if (pDLInfo->fDeleteInfoStruct)
  1146.     {
  1147.         CloseHandle (pDLInfo->hWaitEvent);
  1148.         CloseHandle (pDLInfo->hFile);
  1149.         DeleteFile (pDLInfo->szTmpFile);
  1150.         if (pDLInfo->DLInfo.pMembers)
  1151.         {
  1152.             HeapFree (ghHeap, 0, pDLInfo->DLInfo.pMembers);
  1153.         }
  1154.         if (pDLInfo->ppszAliasList)
  1155.         {
  1156.             for (j=0; j<pDLInfo->dwAliasDelivered; j++)
  1157.             {
  1158.                 HeapFree (ghHeap, 0, pDLInfo->ppszAliasList[j]);
  1159.             }
  1160.             HeapFree (ghHeap, 0, pDLInfo->ppszAliasList);
  1161.         }
  1162.         HeapFree (ghHeap, 0, pDLInfo);
  1163.     }
  1164.     return dwResult;
  1165. }
  1166.  
  1167. ////////////////////////////////////////////////////////////////////////////
  1168. //    ObjectDelivered()
  1169. //
  1170. //    Parameters
  1171. //
  1172. //    Purpose
  1173. //
  1174. //    Return Value
  1175. //          
  1176. HRESULT WINAPI ObjectDelivered (PDL_DELIVERY_PROC_INFO pDLInfo, LPTSTR szObject)
  1177. {
  1178.     DWORD dwIndex = pDLInfo->dwAliasDelivered;
  1179.     if (NULL == pDLInfo->ppszAliasList)
  1180.     {
  1181.         ASSERT (0 == pDLInfo->dwAliasDelivered);
  1182.         pDLInfo->ppszAliasList = (LPTSTR *)HeapAlloc (ghHeap, 0, sizeof(LPTSTR));
  1183.         if (NULL == pDLInfo->ppszAliasList)
  1184.         {
  1185.             TraceMessage ("ObjectDelivered: Failed to allocate Delivered Alias List");
  1186.             return E_OUTOFMEMORY;
  1187.         }
  1188.     }
  1189.     else
  1190.     {
  1191.         pDLInfo->ppszAliasList = (LPTSTR *)HeapReAlloc (ghHeap,
  1192.                                                         0,
  1193.                                                         pDLInfo->ppszAliasList,
  1194.                                                         sizeof(LPTSTR) * (pDLInfo->dwAliasDelivered + 1));
  1195.         if (NULL == pDLInfo->ppszAliasList[dwIndex])
  1196.         {
  1197.             TraceMessage ("ObjectDelivered: Failed to re-allocate Delivered Alias List");
  1198.             return E_OUTOFMEMORY;
  1199.         }
  1200.     }
  1201.     
  1202.     pDLInfo->ppszAliasList[dwIndex] = (LPTSTR)HeapAlloc (ghHeap, 0, (sizeof (TCHAR)*(lstrlen(szObject)+1)));
  1203.     if (NULL == pDLInfo->ppszAliasList[dwIndex])
  1204.     {
  1205.         TraceMessage ("ObjectDelivered: Failed to allocate object alias string");
  1206.         return E_OUTOFMEMORY;
  1207.     }
  1208.     lstrcpy (pDLInfo->ppszAliasList[dwIndex], szObject);
  1209.     pDLInfo->dwAliasDelivered++;
  1210.     return S_OK;
  1211. }
  1212.  
  1213. ///////////////////////////////////////////////////////////////////////////////
  1214. //    RemoteCheckNewMailA()
  1215. //
  1216. //    Parameters
  1217. //
  1218. //    Purpose
  1219. //
  1220. //    Return Value
  1221. //
  1222. long RemoteCheckNewMailA (unsigned char * szMailbox, unsigned long * pulPending)
  1223. {
  1224.     long lResult = GetServiceState();
  1225.     if (lResult)
  1226.     {
  1227.         return lResult;
  1228.     }
  1229.     HANDLE hWaitEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
  1230.     if (!hWaitEvent)
  1231.     {
  1232.         lResult = HRESULT_FROM_WIN32(GetLastError());
  1233.         TraceResult ("RemoteCheckNewMailA: Failed to create event for I/O thread", lResult);
  1234.         return lResult;
  1235.     }
  1236.     *pulPending = 0;
  1237.     EnterCriticalSection (&g_csIOInfo);
  1238.     SetEvent (g_IOInfo.hResumeEvent);
  1239.     lstrcpy (g_IOInfo.szObject, (LPSTR)szMailbox);
  1240.     g_IOInfo.Action           = IO_CHECK_PENDING_MESSAGES;
  1241.     g_IOInfo.hActionCompleted = hWaitEvent;
  1242.     g_IOInfo.phLastError      = &lResult;
  1243.     g_IOInfo.pdwData          = pulPending;
  1244.     LeaveCriticalSection (&g_csIOInfo);
  1245.     WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);
  1246.     CloseHandle (hWaitEvent);
  1247.     return lResult;
  1248. }
  1249.  
  1250. ///////////////////////////////////////////////////////////////////////////////
  1251. //    RemoteOpenOneMsgDownloadPipeA()
  1252. //
  1253. //    Parameters
  1254. //
  1255. //    Purpose
  1256. //
  1257. //    Return Value
  1258. //
  1259. long RemoteOpenOneMsgDownloadPipeA (unsigned char *    szMailbox,
  1260.                                     long *             pPipeNumber)
  1261. {
  1262.     long lResult = GetServiceState();
  1263.     if (lResult)
  1264.     {
  1265.         return lResult;
  1266.     }
  1267.     TCHAR szTmpFile[_MAX_PATH], szPipeName[64];
  1268.     lResult = GetLocalTempFileName (szTmpFile);
  1269.     if (lResult)
  1270.     {
  1271.         return lResult;
  1272.     }
  1273.  
  1274.     PTHREAD_PROC_INFO pInfo = (PTHREAD_PROC_INFO)HeapAlloc (ghHeap,
  1275.                                                             HEAP_ZERO_MEMORY,
  1276.                                                             sizeof(THREAD_PROC_INFO));
  1277.     if (NULL == pInfo)
  1278.     {
  1279.         TraceMessage ("RemoteOpenOneMsgDownloadPipeA: Failed to allocate info structure");
  1280.         return E_OUTOFMEMORY;
  1281.     }
  1282.     DWORD dwThreadID, dwMsgID;
  1283.     HANDLE hThread, hWaitEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
  1284.     if (!hWaitEvent)
  1285.     {
  1286.         lResult = HRESULT_FROM_WIN32(GetLastError());
  1287.         TraceResult ("RemoteOpenOneMsgDownloadPipeA: Failed to create event for I/O thread", lResult);
  1288.         goto ErrorExit;
  1289.     }
  1290.     
  1291.     pInfo->hTmpFile = CreateFile (szTmpFile,
  1292.                                   GENERIC_WRITE | GENERIC_READ,
  1293.                                   0,
  1294.                                   NULL,
  1295.                                   CREATE_ALWAYS,
  1296.                                   FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_DELETE_ON_CLOSE,
  1297.                                   NULL);
  1298.     if (INVALID_HANDLE_VALUE == pInfo->hTmpFile)
  1299.     {
  1300.         lResult = HRESULT_FROM_WIN32(GetLastError());
  1301.         TraceResult ("RemoteOpenOneMsgDownloadPipeA: Failed to create the temp file", lResult);
  1302.         goto ErrorExit;
  1303.     }
  1304.     
  1305.     *pPipeNumber = GetNextPipeID();
  1306.     
  1307.     SECURITY_ATTRIBUTES sa;
  1308.     SECURITY_DESCRIPTOR sd;
  1309.  
  1310.     // Initialize the new security descriptor.
  1311.     InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
  1312.  
  1313.     // Add a NULL descriptor ACL to the security descriptor.
  1314.     SetSecurityDescriptorDacl (&sd, TRUE, (PACL)NULL, FALSE);
  1315.  
  1316.     sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  1317.     sa.lpSecurityDescriptor = &sd;
  1318.     sa.bInheritHandle = TRUE;
  1319.  
  1320.     wsprintf (szPipeName, SERVER_PIPE_NAME_FORMAT, *pPipeNumber);
  1321.     pInfo->hPipe = CreateNamedPipe (szPipeName,
  1322.                                     PIPE_ACCESS_OUTBOUND,
  1323.                                     PIPE_WAIT | PIPE_READMODE_BYTE | PIPE_TYPE_BYTE,
  1324.                                     1,
  1325.                                     IO_BUFFERSIZE,
  1326.                                     IO_BUFFERSIZE,
  1327.                                     0,
  1328.                                     &sa);
  1329.     if (INVALID_HANDLE_VALUE == pInfo->hPipe || ERROR_INVALID_PARAMETER == (DWORD)pInfo->hPipe)
  1330.     {
  1331.         lResult = HRESULT_FROM_WIN32(GetLastError());
  1332.         TraceResult ("RemoteOpenMsgDownloadPipeA: Failed to create pipe", lResult);
  1333.         goto ErrorExit;
  1334.     }
  1335.  
  1336.     EnterCriticalSection (&g_csIOInfo);
  1337.     SetEvent (g_IOInfo.hResumeEvent);
  1338.     lstrcpy (g_IOInfo.szObject, (LPSTR)szMailbox);
  1339.     g_IOInfo.Action           = IO_MOVE_NEXT_MSG_TO_FILE;
  1340.     g_IOInfo.hActionCompleted = hWaitEvent;
  1341.     g_IOInfo.hTmpFile         = pInfo->hTmpFile;
  1342.     g_IOInfo.pdwData          = &dwMsgID;
  1343.     g_IOInfo.phLastError      = &lResult;
  1344.     LeaveCriticalSection (&g_csIOInfo);
  1345.     WaitForSingleObject (hWaitEvent, GENERAL_TIME_OUT);
  1346.     if (lResult)
  1347.     {
  1348.         goto ErrorExit;
  1349.     }
  1350.  
  1351.     hThread = CreateThread (NULL,
  1352.                             0,
  1353.                             (LPTHREAD_START_ROUTINE)OneMsgDownloadPipeThread,
  1354.                             (LPVOID)pInfo,
  1355.                             0,
  1356.                             &dwThreadID);
  1357.     if (hThread)
  1358.     {
  1359.         TraceDebugger ("RemoteOpenOneMsgDownloadPipeA: Message Download thread spawned. ID: %X", dwThreadID);
  1360.         CloseHandle (hThread);
  1361.         pInfo = NULL; // The thread will free this memory
  1362.         EnterCriticalSection (&g_csIOInfo);
  1363.         SetEvent (g_IOInfo.hResumeEvent);
  1364.         lstrcpy (g_IOInfo.szObject, (LPSTR)szMailbox);
  1365.         g_IOInfo.Action           = IO_DELETE_MSG_IN_MAILBOX;
  1366.         g_IOInfo.hActionCompleted = NULL;
  1367.         g_IOInfo.dwObjID          = dwMsgID;
  1368.         g_IOInfo.phLastError      = NULL;
  1369.         LeaveCriticalSection (&g_csIOInfo);
  1370.     }
  1371.     else
  1372.     {
  1373.         lResult = HRESULT_FROM_WIN32(GetLastError());
  1374.         TraceResult ("RemoteOpenOneMsgDownloadPipeA: Failed to create pipe thread", lResult);
  1375.     }
  1376.     
  1377. ErrorExit:
  1378.     if (pInfo)
  1379.     {
  1380.         if (pInfo->hTmpFile)
  1381.         {
  1382.             CloseHandle (pInfo->hTmpFile);
  1383.         }
  1384.         if (pInfo->hPipe)
  1385.         {
  1386.             CloseHandle (pInfo->hPipe);
  1387.         }
  1388.         HeapFree (ghHeap, 0, pInfo);
  1389.     }
  1390.     if (hWaitEvent)
  1391.     {
  1392.         CloseHandle (hWaitEvent);
  1393.     }
  1394.     #ifdef _DEBUG
  1395.     if (lResult && S_FALSE != lResult)
  1396.     {
  1397.         TraceResult ("RemoteOpenOneMsgDownloadPipeA", lResult);
  1398.     }
  1399.     #endif // _DEBUG
  1400.     return lResult;
  1401. }
  1402.  
  1403. ///////////////////////////////////////////////////////////////////////////////
  1404. //    OneMsgDownloadPipeThread()
  1405. //
  1406. //    Parameters
  1407. //
  1408. //    Purpose
  1409. //
  1410. //    Return Value
  1411. //
  1412. HRESULT WINAPI OneMsgDownloadPipeThread (PTHREAD_PROC_INFO pInfo)
  1413. {
  1414.     DWORD dwBytesRead, dwBytesWritten;
  1415.     BYTE abBuffer[IO_BUFFERSIZE];
  1416.     HRESULT hResult = S_OK;
  1417.  
  1418.     SetFilePointer (pInfo->hTmpFile, 0, NULL, FILE_BEGIN);
  1419.  
  1420.     ConnectNamedPipe (pInfo->hPipe, NULL);
  1421.     
  1422.     do
  1423.     {
  1424.         if (!ReadFile (pInfo->hTmpFile, abBuffer, IO_BUFFERSIZE, &dwBytesRead, NULL))
  1425.         {
  1426.             hResult = HRESULT_FROM_WIN32(GetLastError());
  1427.             TraceResult ("OneMsgDownloadPipeThread: Failed to read the tmp file", hResult);
  1428.         }
  1429.         if (dwBytesRead && !hResult)
  1430.         {
  1431.             if (!WriteFile (pInfo->hPipe, abBuffer, dwBytesRead, &dwBytesWritten, NULL))
  1432.             {
  1433.                 hResult = HRESULT_FROM_WIN32(GetLastError());
  1434.                 TraceResult ("OneMsgDownloadPipeThread: Failed to write to the pipe", hResult);
  1435.             }
  1436.         }
  1437.     } while (dwBytesRead && !hResult);
  1438.  
  1439.     TraceResult ("OneMsgDownloadPipeThread", hResult);
  1440.     CloseHandle (pInfo->hPipe);
  1441.     CloseHandle (pInfo->hTmpFile);
  1442.     HeapFree (ghHeap, 0, pInfo);
  1443.     return hResult;
  1444. }
  1445.  
  1446. // End of file for RXPRPC.CPP
  1447.