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.xp / comwinds.cpp next >
Encoding:
C/C++ Source or Header  |  1996-04-11  |  109.7 KB  |  2,805 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. //  File Name 
  4. //      COMWINDS.CPP
  5. //
  6. //  Description
  7. //      This file implement the RPC code to talk to the WINDS Sample Server
  8. //      Messaging Host.
  9. //      Here we also implement common code used by providers in the service
  10. //      that talking to WINDS and that share similiar configuration UI.
  11. //
  12. //  Author
  13. //      Irving De la Cruz
  14. //
  15. //  Revision: 1.7
  16. //
  17. // Written for Microsoft Windows Developer Support
  18. // Copyright (c) 1995-1996 Microsoft Corporation. All rights reserved.
  19. //
  20. #include "COMWINDS.H"
  21.  
  22. // Remark this line to turn verbose tracing OFF
  23. #define DO_INFO_TRACES
  24. #ifdef DO_INFO_TRACES
  25. #define InfoTrace(a)   TraceInfoMessage(a)
  26. #else
  27. #define InfoTrace(a)   
  28. #endif // DO_INFO_TRACES
  29.  
  30. typedef struct tagSELECTED_MAILBOX_INFO
  31. {
  32.     HANDLE  hPipe;
  33.     HRESULT hLastError;
  34.     LPTSTR  szMailBoxName;
  35.     LPTSTR  szDisplayName;
  36.     LPTSTR  szPassword;
  37.     DWORD * pdwMailboxID;
  38. } SELECTED_MAILBOX_INFO;
  39.  
  40. HINSTANCE ghUIControl = NULL;
  41. typedef BOOL (WINAPI CTL3DFUNCTION) (HINSTANCE hInstance);
  42. typedef CTL3DFUNCTION *LPCTL3DFUNCTION;
  43. typedef BOOL (WINAPI CTL3DSUBCLASS) (HWND hDlg, DWORD dwFlags);
  44. typedef CTL3DSUBCLASS *LPCTL3DSUBCLASS;
  45.  
  46. LPCTL3DFUNCTION pfn3DRegister = NULL, pfn3DUnregister = NULL, pfn3DAutoSubclass = NULL;
  47. LPCTL3DSUBCLASS pfnDlgSubclassEx = NULL;
  48.  
  49. LPFREEBUFFER pfnMAPIFreeBuffer;
  50.  
  51. extern "C"
  52. {
  53.     void STDAPICALLTYPE BrowseMailboxes
  54.                     (CUIMAPIProp *              pObj,
  55.                      HWND                       hOwnerWnd,
  56.                      HINSTANCE                  hInstance);
  57.     void STDAPICALLTYPE ConfigChangePassword
  58.                     (CUIMAPIProp *              pObj,
  59.                      HWND                       hOwnerWnd,
  60.                      HINSTANCE                  hInstance);
  61.     HRESULT WINAPI ShowServerAccounts
  62.                     (HWND                       hOwnerWnd,
  63.                      HINSTANCE                  hInstance,
  64.                      LPTSTR                     szServerName,
  65.                      LPTSTR                     szMailboxName,
  66.                      LPTSTR                     szFullName,
  67.                      LPTSTR                     szPassword,
  68.                      DWORD *                    pdwMailboxID);
  69.     BOOL CALLBACK PasswordDlgProc
  70.                     (HWND                       hDlg,
  71.                      UINT                       message,
  72.                      WPARAM                     wParam, 
  73.                      LPARAM                     lParam);
  74.     BOOL CALLBACK EnterMBPasswordDlgProc
  75.                     (HWND                       hDlg,
  76.                      UINT                       message,
  77.                      WPARAM                     wParam, 
  78.                      LPARAM                     lParam);
  79.     BOOL CALLBACK SelectMailBoxDlgProc
  80.                     (HWND                       hDlg,
  81.                      UINT                       message,
  82.                      WPARAM                     wParam, 
  83.                      LPARAM                     lParam);
  84.     void WINAPI TogglePage
  85.                     (HWND                       hDlg,
  86.                      UINT                       iPage,
  87.                      BOOL                       fState);                    
  88.     HRESULT WINAPI LogonServerMailbox
  89.                     (LPTSTR                     szServerName,
  90.                      LPTSTR                     szMailboxName,
  91.                      LPTSTR                     szDisplayName,
  92.                      LPTSTR                     szPassword,
  93.                      DWORD *                    pdwMailboxID);
  94. };
  95.  
  96. HRESULT WINAPI LogonServerMailboxAndSetNotif
  97.                     (LPTSTR                     szServerName,
  98.                      LPTSTR                     szMailboxName,
  99.                      LPTSTR                     szDisplayName,
  100.                      LPTSTR                     szPassword,
  101.                      DWORD *                    pdwMailboxID,
  102.                      DWORD                      dwNotifMask,
  103.                      DWORD &                    dwConnectID);
  104.  
  105. // Static data for the transport provider configuration property sheets
  106. TCHAR szFilter[] = TEXT("*"); // "*" to allow any character
  107. TCHAR szTimeFilter[] = TEXT("[0-9:]");
  108. TCHAR szPhoneFilter[] = TEXT("[0-9-]");
  109. TCHAR szBlank[] = TEXT("");
  110.  
  111. extern TCHAR gszProviderName[];
  112.  
  113. // Control description structures
  114. DTBLLABEL       DtLabel      = { sizeof(DTBLLABEL),       fMapiUnicode};
  115. DTBLGROUPBOX    DtGroupBox   = { sizeof(DTBLGROUPBOX),    fMapiUnicode};
  116. DTBLPAGE        DtPage       = { sizeof(DTBLPAGE),        fMapiUnicode};
  117. DTBLEDIT        DtServer     = { sizeof(DTBLEDIT),        fMapiUnicode, MAX_STRING_SIZE, PR_SMP_REMOTE_SERVER};
  118. DTBLEDIT        DtUserName   = { sizeof(DTBLEDIT),        fMapiUnicode, MAX_STRING_SIZE, PR_SMP_USER_NAME};
  119. DTBLEDIT        DtMBAlias    = { sizeof(DTBLEDIT),        fMapiUnicode, MAX_ALIAS_SIZE,  PR_SMP_MAILBOX_NAME};
  120. DTBLBUTTON      DtBrowseMB   = { sizeof(DTBLBUTTON),      fMapiUnicode, PR_SMP_BROWSE_MB};
  121. DTBLBUTTON      DtChangePW   = { sizeof(DTBLBUTTON),      fMapiUnicode, PR_SMP_CHANGE_PASSWORD};
  122. DTBLRADIOBUTTON DtLANConnect = { sizeof(DTBLRADIOBUTTON), fMapiUnicode, 2, PR_SMP_CONNECTION_TYPE, LAN_CONNECT };
  123. DTBLRADIOBUTTON DtREMConnect = { sizeof(DTBLRADIOBUTTON), fMapiUnicode, 2, PR_SMP_CONNECTION_TYPE, OFFLINE_CONNECT };
  124.  
  125. // Keys for field the we are going to update dynamically and we
  126. // want MAPI's property pages to pick the changes on thes
  127. #define ALIAS_KEY_VALUE     "UI_CONTROL_ALIAS"
  128. #define ALIAS_KEY           ((LPBYTE)ALIAS_KEY_VALUE)
  129. #define CB_ALIAS_KEY        sizeof(ALIAS_KEY_VALUE)
  130.  
  131. #define NAME_KEY_VALUE      "UI_CONTROL_NAME"
  132. #define NAME_KEY            ((LPBYTE)NAME_KEY_VALUE)
  133. #define CB_NAME_KEY         sizeof(NAME_KEY_VALUE)
  134.  
  135. // Description table for the controls
  136. DTCTL UserConfigPage[] =
  137. {
  138.     { DTCT_PAGE,        0,           NULL,      0,            NULL,     0,                   &DtPage       },
  139.     { DTCT_EDIT,        DT_REQUIRED, NULL,      0,            szFilter, IDC_SERVERNAME,      &DtServer     },
  140.     { DTCT_EDIT,        DT_REQUIRED, ALIAS_KEY, CB_ALIAS_KEY, szFilter, IDC_MAILBOXNAME,     &DtMBAlias    },
  141.     { DTCT_BUTTON,      0,           NULL,      0,            NULL,     IDC_BROWSE_MB,       &DtBrowseMB   },
  142.     { DTCT_EDIT,        DT_REQUIRED, NAME_KEY,  CB_NAME_KEY,  szFilter, IDC_USER_NAME,       &DtUserName   },
  143.     { DTCT_BUTTON,      0,           NULL,      0,            NULL,     IDC_CHANGE_PASSWORD, &DtChangePW   },
  144.     { DTCT_RADIOBUTTON, DT_SET_IMMEDIATE,NULL,  0,            NULL,     IDC_CONNECT_ONLINE,  &DtLANConnect },
  145.     { DTCT_RADIOBUTTON, DT_SET_IMMEDIATE,NULL,  0,            NULL,     IDC_CONNECT_OFFLINE, &DtREMConnect },
  146.     { DTCT_LABEL,       0,           NULL,      0,            NULL,     IDC_STATIC1,         &DtLabel      },
  147.     { DTCT_LABEL,       0,           NULL,      0,            NULL,     IDC_STATIC2,         &DtLabel      },
  148.     { DTCT_GROUPBOX,    0,           NULL,      0,            NULL,     IDC_STATIC3,         &DtGroupBox   },
  149.     { DTCT_GROUPBOX,    0,           NULL,      0,            NULL,     IDC_STATIC4,         &DtGroupBox   },
  150.     { DTCT_GROUPBOX,    0,           NULL,      0,            NULL,     IDC_STATIC5,         &DtGroupBox   }
  151. };
  152.  
  153. // Global data used in the WizardDlgProc function
  154. LPMAPIPROP pPropObj = NULL;
  155. BOOL fInitalizeControls, fDownloadMBList;
  156.  
  157. extern "C"
  158. {
  159.     HINSTANCE            ghInstance = NULL;
  160.     WIZARDENTRY          WizardEntry;    
  161.     SERVICEWIZARDDLGPROC WizardDlgProc;   
  162. };
  163.  
  164. ///////////////////////////////////////////////////////////////////////////////
  165. //    IsWINDSServerAvailable()
  166. //
  167. //    Parameters
  168. //      szServer        Pointer to a string with the name of the remote
  169. //                      server to verify
  170. //
  171. //    Purpose
  172. //      This functions makes remote procedure call to a server to make sure
  173. //      the remote machine is available.
  174. //      The remote server must be running the WINDS sample server messaging
  175. //      host because that is the server procedure that will answer the
  176. //      RPC call.
  177. //
  178. //    Return Value
  179. //      TRUE if the server was found, FALSE otherwise.
  180. //
  181. BOOL WINAPI IsWINDSServerAvailable (LPTSTR szServer)
  182. {
  183.     // We the user didn't supply a server, then fail.
  184.     if (!szServer)
  185.     {
  186.         TraceMessage ("IsWINDSServerAvailable: No server name?");
  187.         return FALSE;
  188.     }
  189.     HCURSOR hCursor = SetCursor (LoadCursor (NULL, IDC_WAIT));
  190.     // Before we make an RPC call, we must initialize the RPC runtime
  191.     // binding handle with the server
  192.     HRESULT hResult = BindToServer (szServer);
  193.     if (!hResult)
  194.     {
  195.         RpcTryExcept
  196.         {
  197.             // Call the server.
  198.             hResult = RemoteIsServerRunning();
  199.         }
  200.         RpcExcept(1)
  201.         {
  202.             // If we got here is because there was an error while call was made
  203.             // or when it was about to be made.
  204.             hResult = RpcExceptionCode();
  205.             if (RPC_S_SERVER_UNAVAILABLE == hResult)
  206.             {
  207.                 hResult = HRESULT_FROM_WIN32(ERROR_HOST_UNREACHABLE);
  208.             }
  209.             else
  210.             {
  211.                 hResult = MAKE_HRESULT(1, FACILITY_RPC, hResult);
  212.             }
  213.         }
  214.         RpcEndExcept
  215.         TraceResult ("IsWINDServerAvailable", hResult);
  216.     }
  217.     SetCursor (hCursor);
  218.     return (S_OK == hResult ? TRUE : FALSE);
  219. }
  220.  
  221. ///////////////////////////////////////////////////////////////////////////////
  222. //    ShowServerAccounts()
  223. //
  224. //    Parameters
  225. //      hOwnerWnd       Handle to a parent window. If NULL we don't display a
  226. //                      list of available mailboxes in the server.
  227. //      hInstance       Handle to the instance of the DLL where the dialog
  228. //                      resource is located
  229. //      szServerName    Name of the server we are going to make an RPC call to
  230. //      szMailboxName   Where we return the name of the mailbox selected.
  231. //      szFullName      Where we return the name of the owner of the
  232. //                      mailbox seleted.
  233. //      szPassword      Where we return the password of the mailbox seleted
  234. //      pdwMailboxID    Where we return the ID of the mailbox seleted
  235. //
  236. //    Purpose
  237. //      This function displays a list of available mailboxes in the server.
  238. //
  239. //    Return Value
  240. //      An HRESULT
  241. //
  242. HRESULT WINAPI ShowServerAccounts (HWND        hOwnerWnd,
  243.                                    HINSTANCE   hInstance,
  244.                                    LPTSTR      szServerName,
  245.                                    LPTSTR      szMailboxName,
  246.                                    LPTSTR      szFullName,
  247.                                    LPTSTR      szPassword,
  248.                                    DWORD *     pdwMailboxID)
  249. {
  250.     ASSERT (hOwnerWnd);
  251.     ASSERT (hInstance);
  252.     ASSERT (szServerName);
  253.     ASSERT (szMailboxName);
  254.     ASSERT (szFullName);
  255.     ASSERT (szPassword);
  256.     ASSERT (pdwMailboxID);
  257.     HRESULT hResult = BindToServer (szServerName);
  258.     if (hResult)
  259.     {
  260.         return hResult;
  261.     }
  262.     long lPipeNumber;
  263.     HANDLE hPipe;
  264.     TCHAR szPipeName[64];
  265.     SELECTED_MAILBOX_INFO info = { 0 };
  266.     RpcTryExcept
  267.     {
  268.         hResult = RemoteGetAllAccounts (&lPipeNumber);
  269.         if (S_OK == hResult)
  270.         {
  271.             wsprintf (szPipeName, PIPE_NAME_FORMAT, szServerName, lPipeNumber);
  272.             hPipe = CreateFile (szPipeName,
  273.                                 GENERIC_READ,
  274.                                 0,
  275.                                 NULL,
  276.                                 OPEN_EXISTING,
  277.                                 0,
  278.                                 NULL);
  279.             if (INVALID_HANDLE_VALUE == hPipe)
  280.             {
  281.                 hResult = HRESULT_FROM_WIN32(GetLastError());
  282.                 TraceResult ("ShowServerAccounts: Failed to open pipe to server", hResult);
  283.             }
  284.             else
  285.             {
  286.                 info.hPipe = hPipe;
  287.                 info.hLastError = E_FAIL;
  288.                 info.szDisplayName = szFullName;
  289.                 info.szMailBoxName = szMailboxName;
  290.                 info.szPassword = szPassword;
  291.                 info.pdwMailboxID = pdwMailboxID;
  292.                 hResult = DialogBoxParam (hInstance,
  293.                                           MAKEINTRESOURCE(IDD_SELECTMB),
  294.                                           hOwnerWnd,
  295.                                           SelectMailBoxDlgProc,
  296.                                           (LPARAM)&info);
  297.                 if (-1 == hResult)
  298.                 {
  299.                     hResult = info.hLastError;
  300.                 }
  301.                 else
  302.                 {
  303.                     if (FALSE == hResult)
  304.                     {
  305.                         hResult = MAPI_E_USER_CANCEL;
  306.                     }
  307.                     else
  308.                     {
  309.                         hResult = S_OK;
  310.                     }
  311.                 }
  312.                 CloseHandle (hPipe);
  313.             }
  314.         }
  315.     }
  316.     RpcExcept(1)
  317.     {
  318.         // If we got here is because there was an error while call was made
  319.         // or when it was about to be made.
  320.         hResult = RpcExceptionCode();
  321.         if (RPC_S_SERVER_UNAVAILABLE == hResult)
  322.         {
  323.             hResult = HRESULT_FROM_WIN32(ERROR_HOST_UNREACHABLE);
  324.         }
  325.         else
  326.         {
  327.             hResult = MAKE_HRESULT(1, FACILITY_RPC, hResult);
  328.         }
  329.     }
  330.     RpcEndExcept
  331.     TraceResult ("ShowServerAccounts", hResult);
  332.     return hResult;
  333. }
  334.  
  335. ///////////////////////////////////////////////////////////////////////////////
  336. //    LogonServerMailbox()
  337. //
  338. //    Parameters
  339. //      szServerName        Name of the server where are connecting to.
  340. //      szMailboxName       Name of the mailbox we are attempting to access
  341. //      szDisplayName       Name of the owner of the mailbox
  342. //      szPassword          Password to access the mailbox
  343. //      pdwMailboxID        Where we return the ID of the mailbox as stored
  344. //                          on the server
  345. //
  346. //    Purpose
  347. //      This function makes a connection to the remote server and makes sure
  348. //      we can access it with the given password. Upon success, the remote
  349. //      call returns us the full name of the owner of the mailbox and the
  350. //      ID of the recipient.
  351. //      
  352. //    Return Value
  353. //      An HRESULT
  354. //
  355. HRESULT WINAPI LogonServerMailbox (LPTSTR   szServerName,
  356.                                    LPTSTR   szMailboxName,
  357.                                    LPTSTR   szDisplayName,
  358.                                    LPTSTR   szPassword,
  359.                                    DWORD *  pdwMailboxID)
  360. {
  361.     ASSERT (szServerName);
  362.     ASSERT (szMailboxName);
  363.     ASSERT (szDisplayName);
  364.     ASSERT (szPassword);
  365.     ASSERT (pdwMailboxID);
  366.     HRESULT hResult = BindToServer (szServerName);
  367.     if (hResult)
  368.     {
  369.         return hResult;
  370.     }
  371.     RpcTryExcept
  372.     {
  373.         hResult = RemoteLogonMailBox ((WINDS_RPC_STRING)szMailboxName,
  374.                                       (WINDS_RPC_STRING)szPassword,
  375.                                       (WINDS_RPC_STRING)szDisplayName,
  376.                                       pdwMailboxID);
  377.     }
  378.     RpcExcept(1)
  379.     {
  380.         // If we got here is because there was an error while call was made
  381.         // or when it was about to be made.
  382.         hResult = RpcExceptionCode();
  383.         if (RPC_S_SERVER_UNAVAILABLE == hResult)
  384.         {
  385.             hResult = HRESULT_FROM_WIN32(ERROR_HOST_UNREACHABLE);
  386.         }
  387.         else
  388.         {
  389.             hResult = MAKE_HRESULT(1, FACILITY_RPC, hResult);
  390.         }
  391.     }
  392.     RpcEndExcept
  393.     TraceResult ("LogonServerMailbox", hResult);
  394.     return hResult;
  395. }
  396.  
  397. ///////////////////////////////////////////////////////////////////////////////
  398. //    LogonServerMailboxAndSetNotif()
  399. //
  400. //    Parameters
  401. //      szServerName       Name of the server where are connecting to.
  402. //      szMailboxName      Name of the mailbox we are attempting to access
  403. //      szDisplayName      Name of the owner of the mailbox
  404. //      szPassword         Password to access the mailbox
  405. //      pdwMailboxID        Where we return the ID of the mailbox as stored
  406. //                          on the server
  407. //      dwNotifMask         Mask of events the loggin service is intersted in.
  408. //      dwConnectID         Where we return the connection number the server
  409. //                          assigned to us.
  410. //
  411. //    Purpose
  412. //      In addition to what LogonServerMailbox() does, this function also
  413. //      instructs the remote server to set up a notification link with us
  414. //      to advise us of changes in the server's data or the server state.
  415. //
  416. //    Return Value
  417. //      An HRESULT
  418. //
  419. HRESULT WINAPI LogonServerMailboxAndSetNotif (LPTSTR    szServerName,
  420.                                               LPTSTR    szMailboxName,
  421.                                               LPTSTR    szDisplayName,
  422.                                               LPTSTR    szPassword,
  423.                                               DWORD *   pdwMailboxID,
  424.                                               DWORD     dwNotifMask,
  425.                                               DWORD &   dwConnectID)
  426. {
  427.     ASSERT (szServerName);
  428.     ASSERT (szMailboxName);
  429.     ASSERT (szDisplayName);
  430.     ASSERT (szPassword);
  431.     ASSERT (pdwMailboxID);
  432.  
  433.     // Get the computer name of us (the client) so that the server can
  434.     // create the mailslot name appropiately.
  435.     TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  436.     HRESULT hResult;
  437.     DWORD dwNameSize = MAX_COMPUTERNAME_LENGTH + 1;
  438.     if (!GetComputerName (szComputerName, &dwNameSize))
  439.     {
  440.         hResult = HRESULT_FROM_WIN32(GetLastError());
  441.         TraceResult ("LogonServerMailboxAndSetNotif: Failed to get the computer name", hResult);
  442.     }
  443.     else
  444.     {
  445.         hResult = BindToServer (szServerName);
  446.     }
  447.     if (hResult)
  448.     {
  449.         return hResult;
  450.     }
  451.     RpcTryExcept
  452.     {
  453.         hResult = RemoteLogonMailBoxAndSetNotif ((WINDS_RPC_STRING)szMailboxName,
  454.                                                  (WINDS_RPC_STRING)szPassword,
  455.                                                  (WINDS_RPC_STRING)szDisplayName,
  456.                                                  pdwMailboxID,
  457.                                                  (WINDS_RPC_STRING)szComputerName,
  458.                                                  dwNotifMask,
  459.                                                  &dwConnectID);
  460.     }
  461.     RpcExcept(1)
  462.     {
  463.         // If we got here is because there was an error while call was made
  464.         // or when it was about to be made.
  465.         hResult = RpcExceptionCode();
  466.         if (RPC_S_SERVER_UNAVAILABLE == hResult)
  467.         {
  468.             hResult = HRESULT_FROM_WIN32(ERROR_HOST_UNREACHABLE);
  469.         }
  470.         else
  471.         {
  472.             hResult = MAKE_HRESULT(1, FACILITY_RPC, hResult);
  473.         }
  474.     }
  475.     RpcEndExcept
  476.     TraceResult ("LogonServerMailboxAndSetNotif", hResult);
  477.     return hResult;
  478. }
  479.  
  480. ///////////////////////////////////////////////////////////////////////////////
  481. //    TerminateServerNotifications()
  482. //
  483. //    Parameters
  484. //      szServerName           Name of the server we want to terminate
  485. //                              connections with.
  486. //      dwConnectionID          Connection ID assigned to us in that server
  487. //
  488. //    Purpose
  489. //      Tell the server that this provider is shutting down an it show remove
  490. //      it from the list of advise clients.
  491. //
  492. //    Return Value
  493. //      An HRESULT
  494. //
  495. HRESULT WINAPI TerminateServerNotifications (LPTSTR     szServerName,
  496.                                              DWORD      dwConnectionID)
  497. {
  498.     // If the connection is zero, there is nothing to do here.
  499.     if (0 == dwConnectionID)
  500.     {
  501.         return S_OK;
  502.     }
  503.     TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  504.     HRESULT hResult;
  505.     DWORD dwNameSize = MAX_COMPUTERNAME_LENGTH + 1;
  506.     if (!GetComputerName (szComputerName, &dwNameSize))
  507.     {
  508.         hResult = HRESULT_FROM_WIN32(GetLastError());
  509.         TraceResult ("TerminateServerNotifications: Failed to get the computer name", hResult);
  510.     }
  511.     else
  512.     {
  513.         hResult = BindToServer (szServerName);
  514.     }
  515.     if (hResult)
  516.     {
  517.         return hResult;
  518.     }
  519.     RpcTryExcept
  520.     {
  521.         hResult = RemoteTerminateNotif ((WINDS_RPC_STRING)szComputerName, dwConnectionID);
  522.     }
  523.     RpcExcept(1)
  524.     {
  525.         // If we got here is because there was an error while call was made
  526.         // or when it was about to be made.
  527.         hResult = RpcExceptionCode();
  528.         if (RPC_S_SERVER_UNAVAILABLE == hResult)
  529.         {
  530.             hResult = HRESULT_FROM_WIN32(ERROR_HOST_UNREACHABLE);
  531.         }
  532.         else
  533.         {
  534.             hResult = MAKE_HRESULT(1, FACILITY_RPC, hResult);
  535.         }
  536.     }
  537.     RpcEndExcept
  538.     TraceResult ("TerminateServerNotifications", hResult);
  539.     return hResult;
  540. }
  541.  
  542. ///////////////////////////////////////////////////////////////////////////////
  543. //    ResetServerNotifications()
  544. //
  545. //    Parameters
  546. //      szServerName        Name of the remote server
  547. //      szMailboxName       Name of the owner mailbox where the notifations
  548. //                          are set
  549. //      dwNotifMask         Mask of events the service is interested in.
  550. //      pdwConnectionID     Where the server returns the new connection number
  551. //
  552. //    Purpose
  553. //      This function is called in response to a notification sent by the
  554. //      server to advise clients that they need to reset the notification
  555. //      because the old connection is no longer valid.
  556. //      The server send this notification periodically to make sure the advise
  557. //      client he sending notifications to are still around.
  558. //
  559. //    Return Value
  560. //      An HRESULT
  561. //
  562. HRESULT WINAPI ResetServerNotifications (LPTSTR     szServerName,
  563.                                          LPTSTR     szMailboxName,
  564.                                          DWORD      dwNotifMask,
  565.                                          DWORD *    pdwConnectionID)
  566. {
  567.     // The connections with the server is dead anyways so 0 the connection ID even we fail.
  568.     *pdwConnectionID = 0;
  569.     TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  570.     HRESULT hResult;
  571.     DWORD dwNameSize = MAX_COMPUTERNAME_LENGTH + 1;
  572.     if (!GetComputerName (szComputerName, &dwNameSize))
  573.     {
  574.         hResult = HRESULT_FROM_WIN32(GetLastError());
  575.         TraceResult ("ResetServerNotifications: Failed to get the computer name", hResult);
  576.     }
  577.     else
  578.     {
  579.         hResult = BindToServer (szServerName);
  580.     }
  581.     if (hResult)
  582.     {
  583.         return hResult;
  584.     }
  585.     RpcTryExcept
  586.     {
  587.         hResult = RemoteValidateNotif ((WINDS_RPC_STRING)szComputerName,
  588.                                        (WINDS_RPC_STRING)szMailboxName,
  589.                                        dwNotifMask,
  590.                                        pdwConnectionID);
  591.     }
  592.     RpcExcept(1)
  593.     {
  594.         // If we got here is because there was an error while call was made
  595.         // or when it was about to be made.
  596.         hResult = RpcExceptionCode();
  597.         if (RPC_S_SERVER_UNAVAILABLE == hResult)
  598.         {
  599.             hResult = HRESULT_FROM_WIN32(ERROR_HOST_UNREACHABLE);
  600.         }
  601.         else
  602.         {
  603.             hResult = MAKE_HRESULT(1, FACILITY_RPC, hResult);
  604.         }
  605.     }
  606.     RpcEndExcept
  607.     TraceResult ("ResetServerNotifications", hResult);
  608.     return hResult;
  609. }
  610.  
  611. ///////////////////////////////////////////////////////////////////////////////
  612. //    GetHeadersFromServer()
  613. //
  614. //    Parameters
  615. //      szServerName   Name of the server we are going to make an RPC call to
  616. //      szMailbox      Mailbox for which we are going to retrieve the
  617. //                      headers for.
  618. //      szHeaderFile   The name of the local file where we will copy the
  619. //                      message headers found in the remote mailbox
  620. //
  621. //    Purpose
  622. //      This function makes an RPC call to the remote server host to retrieve
  623. //      the message header information of a particular mailbox. The headers
  624. //      found are save to a local file and then used to fill the contents
  625. //      table of the remote folder object we return to a client remote
  626. //      viewer application.
  627. //
  628. //    Return Value
  629. //      An HRESULT
  630. //
  631. HRESULT WINAPI GetHeadersFromServer (LPTSTR szServerName,
  632.                                      LPTSTR szMailbox,
  633.                                      LPTSTR szHeaderFile)
  634. {
  635.     HANDLE hFile, hPipe;
  636.     DWORD dwBytesWrite, dwBytesRead;
  637.     BYTE abBuffer[IO_BUFFERSIZE];
  638.     long lPipeNumber;
  639.     HRESULT hResult = BindToServer (szServerName);
  640.     if (hResult)
  641.     {
  642.         return hResult;
  643.     }
  644.     HCURSOR hCursor = SetCursor (LoadCursor (NULL, IDC_WAIT));
  645.     RpcTryExcept
  646.     {
  647.         hResult = RemoteOpenHeaderDownloadPipe ((WINDS_RPC_STRING)szMailbox, &lPipeNumber);
  648.         if (S_OK == hResult)
  649.         {
  650.             wsprintf ((LPTSTR)abBuffer, PIPE_NAME_FORMAT,szServerName, lPipeNumber);
  651.             hPipe = CreateFile ((LPTSTR)abBuffer,
  652.                                 GENERIC_READ,
  653.                                 0,
  654.                                 NULL,
  655.                                 OPEN_EXISTING,
  656.                                 0,
  657.                                 NULL);
  658.             if (INVALID_HANDLE_VALUE == hPipe)
  659.             {
  660.                 hResult = HRESULT_FROM_WIN32(GetLastError());
  661.                 TraceResult ("GetHeadersFromServer: Failed to open pipe to server", hResult);
  662.             }
  663.             else
  664.             {
  665.                 hFile = CreateFile (szHeaderFile,
  666.                                     GENERIC_WRITE,
  667.                                     0,
  668.                                     NULL,
  669.                                     CREATE_ALWAYS,
  670.                                     FILE_FLAG_SEQUENTIAL_SCAN,
  671.                                     NULL);
  672.                 if (INVALID_HANDLE_VALUE == hFile)
  673.                 {
  674.                     hResult = HRESULT_FROM_WIN32(GetLastError());
  675.                     TraceResult ("GetHeadersFromServer: Failed to open local headers file", hResult);
  676.                 }
  677.                 else
  678.                 {
  679.                     do
  680.                     {
  681.                         // Read the pipe handle.
  682.                         if (!ReadFile (hPipe, abBuffer, IO_BUFFERSIZE, &dwBytesRead, NULL))
  683.                         {
  684.                             hResult = HRESULT_FROM_WIN32(GetLastError());
  685.                             if (HRESULT_FROM_WIN32(ERROR_BROKEN_PIPE)   != hResult &&   // For Windows NT
  686.                                 HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) != hResult)     // For Windows 95
  687.                             {
  688.                                 // There was an error and we can't continue
  689.                                 TraceResult ("GetHeadersFromServer: Failed to read from the pipe", hResult);
  690.                             }
  691.                             else
  692.                             {
  693.                                 // If the pipe was broken, it means the server finished writing
  694.                                 // to the it, so we are finished reading from it.
  695.                                 hResult = S_OK;
  696.                             }
  697.                         }
  698.                         if (dwBytesRead)
  699.                         {
  700.                             if (!WriteFile (hFile, abBuffer, dwBytesRead, &dwBytesWrite, NULL))
  701.                             {
  702.                                 hResult = HRESULT_FROM_WIN32(GetLastError());
  703.                                 TraceResult ("GetHeadersFromServer: Failed to write to local header file", hResult);
  704.                             }
  705.                         }
  706.                     } while (dwBytesRead && !hResult);
  707.                     CloseHandle (hFile);
  708.                 }
  709.                 CloseHandle (hPipe);
  710.             }
  711.         }
  712.     }
  713.     RpcExcept(1)
  714.     {
  715.         // If we got here is because there was an error while call was made
  716.         // or when it was about to be made.
  717.         hResult = RpcExceptionCode();
  718.         if (RPC_S_SERVER_UNAVAILABLE == hResult)
  719.         {
  720.             hResult = HRESULT_FROM_WIN32(ERROR_HOST_UNREACHABLE);
  721.         }
  722.         else
  723.         {
  724.             hResult = MAKE_HRESULT(1, FACILITY_RPC, hResult);
  725.         }
  726.     }
  727.     RpcEndExcept
  728.     // Terminate connections with the remote server
  729.     BindToServer (NULL);
  730.     SetCursor (hCursor);
  731.     TraceResult ("GetHeadersFromServer", hResult);
  732.     return hResult;
  733. }
  734.  
  735. ///////////////////////////////////////////////////////////////////////////////
  736. //    OpenServerUploadPipe()
  737. //
  738. //    Parameters
  739. //      hMsgFile            Handle to the local TNEF file with the message to
  740. //                          upload
  741. //      szServerName       String with the name of the remote server
  742. //      szRecipMailbox     String with the name of the mailbox where the
  743. //                          message will be uploaded.
  744. //
  745. //    Purpose
  746. //      This function uploads a file to a server. The file must have been
  747. //      opened by the caller and a handle to it must have been passed in
  748. //      hMsgFile. The function will bind to the server (the name is is
  749. //      szServerName).
  750. //      This functions makes a remote procedure call to a server to request
  751. //      the a pipe to upload the data through.
  752. //      The remote server must be running the WINDS sample server messaging
  753. //      host because that is the server procedure that will answer the
  754. //      RPC call.
  755. //
  756. //    Return Value
  757. //      An HRESULT
  758. //
  759. HRESULT WINAPI OpenServerUploadPipe (LPTSTR     szServerName,
  760.                                      LPTSTR     szSenderMailbox,
  761.                                      HANDLE     hMsgFile,
  762.                                      LPTSTR     szConnectionInfo,
  763.                                      BOOL *     pfErrorInTheServer)
  764. {
  765.     *pfErrorInTheServer = FALSE;
  766.     HANDLE hPipe;
  767.     char szPipeName[64];
  768.     DWORD dwBytesWrite, dwBytesRead;
  769.     BYTE abBuffer[IO_BUFFERSIZE];
  770.     long lPipeNumber, hResult = BindToServer (szServerName);
  771.     if (hResult)
  772.     {
  773.         return hResult;
  774.     }
  775.     RpcTryExcept
  776.     {
  777.         hResult = RemoteOpenMsgUploadPipe ((WINDS_RPC_STRING)szSenderMailbox,
  778.                                            &lPipeNumber,
  779.                                            (WINDS_RPC_STRING)szConnectionInfo);
  780.         if (!hResult)
  781.         {
  782.             wsprintf (szPipeName, PIPE_NAME_FORMAT, szServerName, lPipeNumber);
  783.             hPipe = CreateFile (szPipeName,
  784.                                 GENERIC_WRITE,
  785.                                 0,
  786.                                 NULL,
  787.                                 OPEN_EXISTING,
  788.                                 0,
  789.                                 NULL);
  790.             if (INVALID_HANDLE_VALUE == hPipe)
  791.             {
  792.                 hResult = HRESULT_FROM_WIN32(GetLastError());
  793.                 TraceResult ("OpenServerUploadPipe: Failed to open pipe to server", hResult);
  794.             }
  795.             else
  796.             {
  797.                 do
  798.                 {
  799.                     if (!ReadFile (hMsgFile, abBuffer, IO_BUFFERSIZE, &dwBytesRead, NULL))
  800.                     {
  801.                         hResult = HRESULT_FROM_WIN32(GetLastError());
  802.                         TraceResult ("OpenServerUploadPipe: Failed to read local msg file", hResult);
  803.                     }
  804.                     if (dwBytesRead)
  805.                     {
  806.                         if (!WriteFile (hPipe, abBuffer, dwBytesRead, &dwBytesWrite, NULL))
  807.                         {
  808.                             hResult = HRESULT_FROM_WIN32(GetLastError());
  809.                             TraceResult ("OpenServerUploadPipe: Failed to write to the pipe", hResult);
  810.                         }
  811.                     }
  812.                 } while (dwBytesRead && !hResult);
  813.                 CloseHandle (hPipe);
  814.             }
  815.         }
  816.         else
  817.         {
  818.             if (hResult)
  819.             {
  820.                 *pfErrorInTheServer = TRUE;
  821.             }
  822.         }
  823.     }
  824.     RpcExcept(1)
  825.     {
  826.         // If we got here is because there was an error while call was made
  827.         // or when it was about to be made.
  828.         hResult = RpcExceptionCode();
  829.         if (RPC_S_SERVER_UNAVAILABLE == hResult)
  830.         {
  831.             *pfErrorInTheServer = TRUE;
  832.             hResult = HRESULT_FROM_WIN32(ERROR_HOST_UNREACHABLE);
  833.         }
  834.         else
  835.         {
  836.             hResult = MAKE_HRESULT(1, FACILITY_RPC, hResult);
  837.         }
  838.     }
  839.     RpcEndExcept
  840.     TraceResult ("OpenServerUploadPipe", hResult);
  841.     return hResult;
  842. }
  843.  
  844. ///////////////////////////////////////////////////////////////////////////////
  845. //    SendMsgToAccount()
  846. //
  847. //    Parameters
  848. //
  849. //    Purpose
  850. //
  851. //    Return Value
  852. //      An HRESULT
  853. //
  854. HRESULT WINAPI SendMsgToAccount (LPTSTR    szServerName,
  855.                                  LPTSTR    szRecipMailbox,
  856.                                  LPTSTR    szHeader,
  857.                                  LPTSTR    szConnectionInfo,
  858.                                  BOOL *    pfErrorInTheServer)
  859. {
  860.     *pfErrorInTheServer = FALSE;
  861.     long hResult = BindToServer (szServerName);
  862.     if (hResult)
  863.     {
  864.         return hResult;
  865.     }
  866.     RpcTryExcept
  867.     {
  868.         hResult = RemoteSendMsgToAccount ((WINDS_RPC_STRING)szRecipMailbox,
  869.                                           (WINDS_RPC_STRING)szHeader,
  870.                                           (WINDS_RPC_STRING)szConnectionInfo);
  871.         if (hResult)
  872.         {
  873.             *pfErrorInTheServer = TRUE;
  874.         }
  875.     }
  876.     RpcExcept(1)
  877.     {
  878.         // If we got here is because there was an error while call was made
  879.         // or when it was about to be made.
  880.         hResult = RpcExceptionCode();
  881.         if (RPC_S_SERVER_UNAVAILABLE == hResult)
  882.         {
  883.             *pfErrorInTheServer = TRUE;
  884.             hResult = HRESULT_FROM_WIN32(ERROR_HOST_UNREACHABLE);
  885.         }
  886.         else
  887.         {
  888.             hResult = MAKE_HRESULT(1, FACILITY_RPC, hResult);
  889.         }
  890.     }
  891.     RpcEndExcept
  892.     TraceResult ("SendMsgToAccount", hResult);
  893.     return hResult;
  894. }
  895.  
  896. ///////////////////////////////////////////////////////////////////////////////
  897. //    FinishUploadConnection()
  898. //
  899. //    Parameters
  900. //
  901. //    Purpose
  902. //
  903. //    Return Value
  904. //      An HRESULT
  905. //
  906. HRESULT WINAPI FinishUploadConnection (LPTSTR   szServerName,
  907.                                        LPTSTR   szConnectionInfo)
  908. {
  909.     long hResult = BindToServer (szServerName);
  910.     if (hResult)
  911.     {
  912.         return hResult;
  913.     }
  914.     RpcTryExcept
  915.     {
  916.         hResult = RemoteFinishUpload ((WINDS_RPC_STRING)szConnectionInfo);
  917.     }
  918.     RpcExcept(1)
  919.     {
  920.         // If we got here is because there was an error while call was made
  921.         // or when it was about to be made.
  922.         hResult = RpcExceptionCode();
  923.         if (RPC_S_SERVER_UNAVAILABLE == hResult)
  924.         {
  925.             hResult = HRESULT_FROM_WIN32(ERROR_HOST_UNREACHABLE);
  926.         }
  927.         else
  928.         {
  929.             hResult = MAKE_HRESULT(1, FACILITY_RPC, hResult);
  930.         }
  931.     }
  932.     RpcEndExcept
  933.     TraceResult ("FinishUploadConnection", hResult);
  934.     return hResult;
  935. }
  936.  
  937. ///////////////////////////////////////////////////////////////////////////////
  938. //    OpenRemoteServerDownLoadPipe()
  939. //
  940. //    Parameters                        
  941. //      szServer   Name of the server we are downloading the message from
  942. //      szMBox     Name of the mailbox we are downloading from.
  943. //      phPipe      Pointer where I return the handle to the opened named
  944. //                  pipe to the server machine.
  945. //
  946. //    Purpose
  947. //      Makes an RPC to the remote server which sets up a pipe
  948. //      over which the download occurs. The RPC returns to the
  949. //      client (us) the pipe's ID that the server creates. We
  950. //      then connect to the pipe.
  951. //
  952. //    Return Value
  953. //      An HRESULT
  954. //
  955. HRESULT WINAPI OpenRemoteServerDownLoadPipe (LPTSTR     szServer,
  956.                                              LPTSTR     szMBox,
  957.                                              HANDLE *   phPipe)
  958. {
  959.     ASSERT (szServer);
  960.     ASSERT (szMBox);
  961.     HRESULT hResult = BindToServer (szServer);
  962.     if (hResult)
  963.     {
  964.         return hResult;
  965.     }
  966.     RpcTryExcept
  967.     {
  968.         ULONG ulPipeNum;
  969.         hResult = RemoteOpenMsgDownloadPipe ((WINDS_RPC_STRING)szMBox, &ulPipeNum);
  970.         if (!hResult)
  971.         {
  972.             TCHAR szPipeName[_MAX_PATH];
  973.             HANDLE hPipe;
  974.             // Construct the download pipe name
  975.             wsprintf (szPipeName, PIPE_NAME_FORMAT, szServer, ulPipeNum);
  976.             // Create our endpoint and connect    
  977.             hPipe = CreateFile (szPipeName, 
  978.                                 GENERIC_READ | GENERIC_WRITE,
  979.                                 0,
  980.                                 NULL,
  981.                                 OPEN_EXISTING,
  982.                                 0,
  983.                                 NULL);
  984.             if (INVALID_HANDLE_VALUE == hPipe)
  985.             {
  986.                 hResult = HRESULT_FROM_WIN32(GetLastError());
  987.             }
  988.             else
  989.             {
  990.                 *phPipe = hPipe;
  991.             }
  992.         }
  993.     }
  994.     RpcExcept(1)
  995.     {        
  996.         // If we got here is because there was an error while call was made
  997.         // or when it was about to be made.
  998.         hResult = RpcExceptionCode();
  999.         if (RPC_S_SERVER_UNAVAILABLE == hResult)
  1000.         {
  1001.             hResult = HRESULT_FROM_WIN32(ERROR_HOST_UNREACHABLE);
  1002.         }
  1003.         else
  1004.         {
  1005.             hResult = MAKE_HRESULT(1, FACILITY_RPC, hResult);
  1006.         }
  1007.     }
  1008.     RpcEndExcept
  1009.     // Terminate connections with the remote server
  1010.     BindToServer (NULL);
  1011.     TraceResult ("OpenRemoteServerDownLoadPipe", hResult);
  1012.     return hResult;
  1013. }
  1014.  
  1015. ///////////////////////////////////////////////////////////////////////////////
  1016. //    SelectMailBoxDlgProc()
  1017. //
  1018. //    Parameters
  1019. //      { Refer to Win32 API documentation on dialog procedures }
  1020. //
  1021. //    Purpose
  1022. //      Displays a dialog with all available mailboxes in the remote machine
  1023. //      
  1024. //    Return Value
  1025. //      TRUE if message was handled, FALSE if we don't handle the message
  1026. //      
  1027. BOOL CALLBACK SelectMailBoxDlgProc (HWND    hDlg,
  1028.                                     UINT    message,
  1029.                                     WPARAM  wParam, 
  1030.                                     LPARAM  lParam)
  1031. {
  1032.     static SELECTED_MAILBOX_INFO * pInfo;
  1033.     switch (message)
  1034.     {   
  1035.         case WM_INITDIALOG :
  1036.             {
  1037.                 HWND hCtl = GetDlgItem (hDlg, IDC_LIST);
  1038.                 int nTabStops[3];
  1039.                 nTabStops[0] = 75;
  1040.                 nTabStops[1] = 1000; // Off the screen
  1041.                 nTabStops[2] = 1015; // Off the screen
  1042.                 ListBox_SetTabStops (hCtl, sizeof(nTabStops)/sizeof(int), nTabStops);
  1043.                 pInfo = (SELECTED_MAILBOX_INFO *)lParam;
  1044.                 TCHAR szFormated[256];
  1045.                 AB_ENTRY_INFO abEntry = { 0 };
  1046.                 DWORD dwLastError = 0, dwBytesRead = 0;
  1047.                 do
  1048.                 {
  1049.                     // Read the pipe handle.
  1050.                     if (!ReadFile (pInfo->hPipe, &abEntry, sizeof(AB_ENTRY_INFO), &dwBytesRead, NULL))
  1051.                     {
  1052.                         dwLastError = HRESULT_FROM_WIN32(GetLastError());
  1053.                         if (HRESULT_FROM_WIN32(ERROR_BROKEN_PIPE)   != dwLastError &&   // For Windows NT
  1054.                             HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) != dwLastError)     // For Windows 95
  1055.                         {
  1056.                             // There was an error and we can't continue
  1057.                             TraceResult ("SelectMailBoxDlgProc: Failed to read from the pipe", dwLastError);
  1058.                         }
  1059.                         else
  1060.                         {
  1061.                             // If the pipe was broken, it means the server finished writing
  1062.                             // to the it, so we are finished reading from it.
  1063.                             dwLastError = 0;
  1064.                         }
  1065.                     }
  1066.                     else
  1067.                     {
  1068.                         wsprintf (szFormated,
  1069.                                   TEXT("%s\t%s\t%s\t%d"),
  1070.                                   abEntry.Info.MB.szMailboxName,
  1071.                                   abEntry.Info.MB.szFullName,
  1072.                                   abEntry.Info.MB.szPassword,
  1073.                                   abEntry.Info.MB.dwObjID);
  1074.                         ListBox_AddString (hCtl, szFormated);
  1075.                     }
  1076.                 } while (dwBytesRead && !dwLastError);
  1077.                 if (!dwLastError)
  1078.                 {
  1079.                     if (pfnDlgSubclassEx)
  1080.                     {
  1081.                         pfnDlgSubclassEx (hDlg, CTL3D_ALL);
  1082.                     }
  1083.                     return TRUE;
  1084.                 }
  1085.                 pInfo->hLastError = dwLastError;
  1086.                 EndDialog (hDlg, -1);
  1087.             }
  1088.             return TRUE;
  1089.  
  1090.         case WM_COMMAND :
  1091.             switch (LOWORD(wParam))
  1092.             {
  1093.                 case IDC_LIST :
  1094.                     if (LBN_DBLCLK != HIWORD(wParam))
  1095.                     {
  1096.                         break;
  1097.                     }
  1098.                 case IDOK :
  1099.                     {
  1100.                         TCHAR szBuffer[256];
  1101.                         LPTSTR pStr;
  1102.                         HWND hCtl = GetDlgItem (hDlg, IDC_LIST);
  1103.                         int i = ListBox_GetCurSel (hCtl);
  1104.                         if (i != LB_ERR)
  1105.                         {
  1106.                             ListBox_GetText (hCtl, i, szBuffer);
  1107.                             pStr = strtok (szBuffer, "\t");
  1108.                             lstrcpy (pInfo->szMailBoxName, pStr);
  1109.                             pStr = strtok (NULL, "\t");
  1110.                             lstrcpy (pInfo->szDisplayName, pStr);
  1111.                             pStr = strtok (NULL, "\t");
  1112.                             lstrcpy (pInfo->szPassword, pStr);
  1113.                             pStr = strtok (NULL, "\t");
  1114.                             *(pInfo->pdwMailboxID) = (DWORD)atol (pStr);
  1115.                         }
  1116.                         else
  1117.                         {
  1118.                             PrivateMessageBox (IDS_MSG_SELECT_MB_NAME, hDlg);
  1119.                             return FALSE;
  1120.                         }
  1121.                     }
  1122.                 case IDCANCEL :
  1123.                     EndDialog (hDlg, (LOWORD(wParam) == IDCANCEL ? FALSE : TRUE));
  1124.                     return TRUE;
  1125.             }
  1126.             break;
  1127.     }
  1128.     return FALSE;
  1129. }
  1130.  
  1131. ///////////////////////////////////////////////////////////////////////////////
  1132. //    ChangeMBServerPassword()
  1133. //
  1134. //    Parameters
  1135. //      szServerName        Name of the server machine we are connecting to
  1136. //      szMailboxName       Name of the mailbox where the password will
  1137. //                          be changed.
  1138. //      szOldPassword       Old password of the mailbox
  1139. //      szNewPassword       New password for the mailbox
  1140. //
  1141. //    Purpose
  1142. //      Changes the access password in the specified mailbox in
  1143. //      the specified server.
  1144. //
  1145. //    Return Value
  1146. //      An HRESULT
  1147. //
  1148. HRESULT WINAPI ChangeMBServerPassword (LPTSTR   szServerName,
  1149.                                        LPTSTR   szMailboxName,
  1150.                                        LPTSTR   szOldPassword,
  1151.                                        LPTSTR   szNewPassword)
  1152. {
  1153.     if (BindToServer (szServerName))
  1154.     {
  1155.         return FALSE;
  1156.     }
  1157.     HRESULT hResult;
  1158.     RpcTryExcept
  1159.     {
  1160.         hResult = RemoteChangePassword ((WINDS_RPC_STRING)szMailboxName,
  1161.                                         (WINDS_RPC_STRING)szOldPassword,
  1162.                                         (WINDS_RPC_STRING)szNewPassword);
  1163.     }
  1164.     RpcExcept(1)
  1165.     {
  1166.         // If we got here is because there was an error while call was made
  1167.         // or when it was about to be made.
  1168.         hResult = RpcExceptionCode();
  1169.         if (RPC_S_SERVER_UNAVAILABLE == hResult)
  1170.         {
  1171.             hResult = HRESULT_FROM_WIN32(ERROR_HOST_UNREACHABLE);
  1172.         }
  1173.         else
  1174.         {
  1175.             hResult = MAKE_HRESULT(1, FACILITY_RPC, hResult);
  1176.         }
  1177.     }
  1178.     RpcEndExcept
  1179.     BindToServer (NULL);
  1180.     TraceResult ("ChangeMBServerPassword", hResult);
  1181.     return hResult;
  1182. }
  1183.  
  1184. ///////////////////////////////////////////////////////////////////////////////
  1185. //    PrivateMessageBox()
  1186. //
  1187. //    Parameters
  1188. //      ids             String ID of a string in the resource string table
  1189. //      hOwnerWnd       Window who will own the Message Box
  1190. //      uFlags          Flags (options) for the message box
  1191. //      
  1192. //    Purpose
  1193. //      This function display a message box with a string loaded from the
  1194. //      string table of this app. The ID of the string is passed in the ids
  1195. //      parameter. The dialog box is modal with respect to the window
  1196. //      identified in hOwnerWnd. The options to display the dialog box are
  1197. //      passed in uFlags
  1198. //      
  1199. //    Return Value
  1200. //      ID of the button pressed in the message box dialog box
  1201. //      
  1202. int WINAPI PrivateMessageBox (UINT          ids,
  1203.                               HWND          hOwnerWnd,
  1204.                               UINT          uFlags,
  1205.                               HINSTANCE     hInst)
  1206. {
  1207.     int nResponse = -1; // Default response
  1208.     // Get the string from the string table. The size of the buffer is the
  1209.     // maximum number of character allowed in the character buffer, without
  1210.     // the accounting for the NULL terminator
  1211.     if (NULL == hInst)
  1212.     {
  1213.         hInst = ghInstance;
  1214.     }
  1215.     ASSERT (hInst);
  1216.     TCHAR szBuffer[256];
  1217.     if (LoadString (hInst, ids, szBuffer, 255))
  1218.     {
  1219.         if (!(MB_ICONSTOP & uFlags))
  1220.         {
  1221.             uFlags |= MB_ICONINFORMATION;
  1222.         }
  1223.         // Show the message box and get the ID of the button pressed
  1224.         nResponse = MessageBox (hOwnerWnd,
  1225.                                 szBuffer,
  1226.                                 gszProviderName,
  1227.                                 uFlags |
  1228.                                 MB_SETFOREGROUND |
  1229.                                 MB_SYSTEMMODAL);
  1230.     }
  1231.     return nResponse;
  1232. }
  1233.  
  1234. ///////////////////////////////////////////////////////////////////////////////
  1235. //    IsValidServerName()
  1236. //
  1237. //    Parameters
  1238. //      szServerName       Pointer to a string with the UNC name of a
  1239. //                          network or local server
  1240. //    Purpose
  1241. //      Check the string for a server name and determines if the name is a
  1242. //      valid UNC name for a network server
  1243. //
  1244. //    Return Value
  1245. //      TRUE if the server name is valid, FALSE otherwise.
  1246. //      
  1247. BOOL WINAPI IsValidServerName (LPTSTR szServerName)
  1248. {
  1249.     // Server name need to be at least "\\x"
  1250.     if (lstrlen(szServerName) < 3)
  1251.     {
  1252.         return FALSE;
  1253.     }
  1254.     // The first two character in the string must be "\". This is standard
  1255.     // UNC (Universal Naming Convention) for server names
  1256.     if (szServerName[0] != '\\' || szServerName[1] != '\\')
  1257.     {
  1258.         return FALSE;
  1259.     }
  1260.     return TRUE;
  1261. }
  1262.  
  1263. ///////////////////////////////////////////////////////////////////////////////
  1264. //    BindToServer()
  1265. //
  1266. //    Parameters
  1267. //      [IN]    szServer   Name of the remote server to which we will bind
  1268. //                          for RPC calls. If this pointer is NULL, we
  1269. //                          unbind from that server.
  1270. //
  1271. //    Purpose
  1272. //      This function makes the necessary calls to the RPC runtime library
  1273. //      to bind to the remote server so that we can start RPC function calls.
  1274. //
  1275. //    Return Value
  1276. //      An HRESULT
  1277. //
  1278. HRESULT WINAPI BindToServer (LPTSTR szServer)
  1279. {
  1280.     static unsigned char * szStringBinding = NULL;
  1281.     static char szLastServer[32] = { 0 };
  1282.  
  1283.     // If a server name was given, we compare to the current server that we are
  1284.     // already bounded to. If we are connected return the call.
  1285.     if (szServer)
  1286.     {
  1287.         if (0 == lstrcmpi (szLastServer, szServer))
  1288.         {
  1289.             if (szStringBinding)
  1290.             {
  1291.                 return 0;
  1292.             }
  1293.         }
  1294.         else
  1295.         {
  1296.             // Save the name of the server in the static buffer
  1297.             lstrcpy (szLastServer, szServer);
  1298.         }
  1299.     }
  1300.  
  1301.     RPC_STATUS status = 0;
  1302.     if (szStringBinding) // Unbind only if bound
  1303.     {
  1304.         status = RpcStringFree (&szStringBinding);
  1305.         TraceRPCError  ("BindToServer: RpcStringFree failed", status);
  1306.         if (!status)
  1307.         {
  1308.             szStringBinding = NULL;
  1309.             status = RpcBindingFree (&hWINDSREM);  // hWINDSREM is defined in WINDS.H and WINDS.ACF
  1310.             TraceRPCError  ("BindToServer: RpcBindingFree failed", status);
  1311.         }
  1312.     }
  1313.     // If this is NULL, then we don't need to bind to anything.
  1314.     if (!szServer)
  1315.     {
  1316.         szLastServer[0] = 0;
  1317.         return 0;
  1318.     }
  1319.     if (!status)
  1320.     {
  1321.         status = RpcStringBindingCompose (NULL,
  1322.                                           (WINDS_RPC_STRING)WINDS_RPC_PROTOCOL,
  1323.                                           (WINDS_RPC_STRING)szServer,
  1324.                                           (WINDS_RPC_STRING)WINDS_PROVIDERS_RPC_ENDPOINT,
  1325.                                           NULL,
  1326.                                           &szStringBinding);
  1327.         TraceRPCError  ("BindToServer: RpcStringBindingCompose failed", status);
  1328.         if (!status)
  1329.         {
  1330.             status = RpcBindingFromStringBinding (szStringBinding, &hWINDSREM); // hWINDSREM is defined in WINDS.H and WINDS.ACF
  1331.             TraceRPCError ("BindToServer: RpcBindingFromStringBinding failed", status);
  1332.         }
  1333.     }
  1334.     if (status)
  1335.     {
  1336.         szLastServer[0] = 0;
  1337.         status = MAKE_HRESULT(1, FACILITY_RPC, status);;
  1338.     }
  1339.     return status;
  1340. }
  1341.  
  1342. ///////////////////////////////////////////////////////////////////////////////
  1343. //    TerminateRemoteConnections()
  1344. //
  1345. //    Parameters
  1346. //      None.
  1347. //
  1348. //    Purpose
  1349. //      Termintes the binding links in the RPC runtime library to the remote
  1350. //      server after a sequence of RPC calls.
  1351. //
  1352. //    Return Value
  1353. //      None
  1354. //
  1355. void WINAPI TerminateRemoteConnections()
  1356. {
  1357.     BindToServer (NULL);
  1358. }
  1359.  
  1360. ///////////////////////////////////////////////////////////////////////////////
  1361. //    midl_user_allcate()
  1362. //
  1363. //    Parameters
  1364. //      len     Size (in bytes) of the memory block to allocate for the
  1365. //              RPC object
  1366. //
  1367. //    Purpose
  1368. //      Allocates memory as needed by the RPC runtime library.
  1369. //      The stubs or runtime libraries may need to allocate memory.
  1370. //      By convention, they call a user-specified function named
  1371. //      midl_user_allocate.
  1372. //
  1373. //    Return Value
  1374. //      Pointer to a block of memory of len byte in size
  1375. //
  1376. void __RPC_FAR * __RPC_API midl_user_allocate (size_t len)
  1377. {
  1378.     LPVOID pVoid = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, (DWORD)len);
  1379.     if (NULL == pVoid)
  1380.     {
  1381.         TraceMessage ("midl_user_allocate: Failed to allocated RPC memory block");
  1382.     }
  1383.     return pVoid;
  1384. }
  1385.  
  1386. ///////////////////////////////////////////////////////////////////////////////
  1387. //    midl_user_free()
  1388. //
  1389. //    Parameters
  1390. //      ptr     Pointer to memory block to release
  1391. //
  1392. //    Purpose
  1393. //      Free memory as needed by the RPC runtime library.
  1394. //      The stubs or runtime libraries may need to free memory.
  1395. //      By convention, they call a user-specified function named
  1396. //      midl_user_free.
  1397. //
  1398. //    Return Value
  1399. //      None
  1400. //
  1401. void __RPC_API midl_user_free (void __RPC_FAR * ptr)
  1402. {
  1403.     HeapFree (GetProcessHeap(), 0, ptr);
  1404. }
  1405.  
  1406. ///////////////////////////////////////////////////////////////////////////////
  1407. //    CUIMAPIProp::CUIMAPIProp()
  1408. //
  1409. //    Parameters
  1410. //      hInstance           Instance of the DLL where this provider is
  1411. //      pfnAllocateBuffer   MAPI allocation function
  1412. //      pfnAllocateMore     MAPI allocation function
  1413. //      pfnFreeBuffer       MAPI allocation function
  1414. //      fReadOnly           Weather or not the UI is in read-only mode
  1415. //
  1416. //    Purpose
  1417. //      Constructor of the class.
  1418. //
  1419. //    Return Value
  1420. //      None.
  1421. //
  1422. CUIMAPIProp::CUIMAPIProp (HINSTANCE             hInstance,
  1423.                           LPALLOCATEBUFFER      pfnAllocateBuffer,
  1424.                           LPALLOCATEMORE        pfnAllocateMore,
  1425.                           LPFREEBUFFER          pfnFreeBuffer,
  1426.                           BOOL                  fReadOnly)
  1427. {
  1428.     // Save in global pointer
  1429.     pfnMAPIFreeBuffer = pfnFreeBuffer;
  1430.  
  1431.     // Use MAPI's IMAPIProp in-memory implementation to do the actual
  1432.     // work of store the properties. If we fail to create this, we throw
  1433.     // and exception, to new creator of this object must have the
  1434.     // construction of this object protected within a try-catch block.
  1435.     HRESULT hResult = CreateIProp ((LPIID)&IID_IMAPIPropData,
  1436.                                    pfnAllocateBuffer,
  1437.                                    pfnAllocateMore,
  1438.                                    pfnFreeBuffer,
  1439.                                    NULL,
  1440.                                    &m_pImpObj);
  1441.     if (hResult)
  1442.     {   
  1443.         TraceResult ("CUIMAPIProp: CreateIProp failed to create IPropData object", hResult);
  1444.         throw CException (hResult);
  1445.     }
  1446.     m_hInstance = hInstance;
  1447.     m_fReadOnly = fReadOnly;
  1448.     m_cRef = 1;
  1449.     m_ulCustomPropTag = 0;
  1450.     m_pfnCallBack = NULL;
  1451.     m_pTableData = NULL;
  1452.     InitializeCriticalSection (&m_csObj);
  1453. }
  1454.  
  1455. ///////////////////////////////////////////////////////////////////////////////
  1456. //    CUIMAPIProp::OpenProperty()
  1457. //
  1458. //    Parameters
  1459. //      { Refer to the MAPI documentation for parameter description }
  1460. //
  1461. //    Purpose
  1462. //      Open the property for the BUTTON control on the display table. We
  1463. //      only allow the IID_IMAPIControl interface specified in this method.
  1464. //      If we have the property specified, create a new IMAPIControl
  1465. //      interface and return it to the caller.
  1466. //
  1467. //    Return Value
  1468. //      An HRESULT
  1469. //
  1470. STDMETHODIMP CUIMAPIProp::OpenProperty (ULONG       ulPropTag,
  1471.                                         LPCIID      piid,
  1472.                                         ULONG       ulInterfaceOptions,
  1473.                                         ULONG       ulFlags,
  1474.                                         LPUNKNOWN * ppUnk)
  1475. {
  1476.     Validate_IMAPIProp_OpenProperty (this,
  1477.                                      ulPropTag, 
  1478.                                      piid,
  1479.                                      ulInterfaceOptions,
  1480.                                      ulFlags,
  1481.                                      ppUnk);
  1482.     if (IID_IMAPIControl != *piid)
  1483.     {
  1484.         return E_NOINTERFACE;
  1485.     }
  1486.     LPBUTTONCALLBACK pfnCallBack = NULL;
  1487.     switch (ulPropTag)
  1488.     {
  1489.         case PR_SMP_BROWSE_MB :
  1490.             pfnCallBack = BrowseMailboxes;
  1491.             break;
  1492.         case PR_SMP_CHANGE_PASSWORD :
  1493.             pfnCallBack = ConfigChangePassword;
  1494.             break;
  1495.         default :
  1496.             // We allow client of CUIMAPIProp to set one custom property
  1497.             // that is not know internally and a custom callback.
  1498.             if (m_ulCustomPropTag == ulPropTag)
  1499.             {
  1500.                 pfnCallBack = m_pfnCallBack;
  1501.             }
  1502.     }
  1503.     if (NULL == pfnCallBack)
  1504.     {
  1505.         return MAPI_E_NOT_FOUND;
  1506.     }
  1507.     CMAPIControl * pControl = new CMAPIControl (this, pfnCallBack, m_fReadOnly);
  1508.     if (!pControl)
  1509.     {
  1510.         return E_OUTOFMEMORY;
  1511.     }
  1512.     *ppUnk = (LPUNKNOWN)pControl;
  1513.     return S_OK;
  1514. }
  1515.  
  1516. ///////////////////////////////////////////////////////////////////////////////
  1517. //    EnterMBPasswordDlgProc()
  1518. //
  1519. //    Parameters
  1520. //      { Refer to Win32 API documentation on dialog procedures }
  1521. //
  1522. //    Purpose
  1523. //      Display a dialog where the user enters the password for a mailbox
  1524. //      on the server.
  1525. //      
  1526. //    Return Value
  1527. //      TRUE if message was handled, FALSE if we don't handle the message
  1528. //      
  1529. BOOL CALLBACK EnterMBPasswordDlgProc (HWND    hDlg,
  1530.                                       UINT    message,
  1531.                                       WPARAM  wParam, 
  1532.                                       LPARAM  lParam)
  1533. {
  1534.     static LPTSTR szStoredPassword;
  1535.     static LPTSTR szReturningBuffer;
  1536.     switch (message)
  1537.     {   
  1538.         case WM_INITDIALOG :
  1539.             {
  1540.                 // On this message only, the lParam is an argument passed by the
  1541.                 // caller who instantiated this dialog.
  1542.                 LPSPropValue pProps = (LPSPropValue)lParam;
  1543.                 SetWindowText (GetDlgItem (hDlg, IDC_MAILBOXNAME), pProps[0].Value.LPSZ);
  1544.                 SetWindowText (GetDlgItem (hDlg, IDC_USER_NAME), pProps[1].Value.LPSZ);
  1545.                 szStoredPassword = pProps[2].Value.LPSZ;
  1546.                 szReturningBuffer = pProps[3].Value.LPSZ;
  1547.                 Edit_LimitText (GetDlgItem (hDlg, IDC_PASSWORD), MAX_PASSWORD_SIZE);
  1548.                 // If this value is false, we should disable the BROWSE button to prevent
  1549.                 // users from changing the mailbox.
  1550.                 if (FALSE == pProps[4].Value.b)
  1551.                 {
  1552.                     EnableWindow (GetDlgItem (hDlg, IDC_BROWSE_MB), FALSE);
  1553.                 }
  1554.                 if (pfnDlgSubclassEx)
  1555.                 {
  1556.                     pfnDlgSubclassEx (hDlg, CTL3D_ALL);
  1557.                 }
  1558.             }
  1559.             return TRUE;
  1560.         case WM_COMMAND :
  1561.             switch (LOWORD(wParam))
  1562.             {
  1563.                 case IDC_BROWSE_MB :
  1564.                     EndDialog (hDlg, IDC_BROWSE_MB);
  1565.                     break;
  1566.                 case IDOK :
  1567.                     // Get the password and do a CASE-SENSITIVE comparison of the stored and entered psswords.
  1568.                     GetWindowText (GetDlgItem (hDlg, IDC_PASSWORD), szReturningBuffer, MAX_PASSWORD_SIZE);
  1569.                     if (szStoredPassword && (0 != lstrcmp (szReturningBuffer, szStoredPassword)))
  1570.                     {
  1571.                         MessageBeep (MB_ICONEXCLAMATION);
  1572.                         PrivateMessageBox (IDS_MSG_INVALID_MB_PASSWORD, hDlg);
  1573.                         SetFocus (GetDlgItem (hDlg, IDC_PASSWORD));
  1574.                         return TRUE;
  1575.                     }
  1576.                     // else fall through
  1577.                 case IDCANCEL :
  1578.                     EndDialog (hDlg, (LOWORD(wParam) == IDCANCEL ? FALSE : TRUE));
  1579.                     return TRUE;
  1580.             }
  1581.     }
  1582.     return FALSE;
  1583. }
  1584.  
  1585. ///////////////////////////////////////////////////////////////////////////////
  1586. //    PasswordDlgProc()
  1587. //
  1588. //    Parameters
  1589. //      { Refer to Win32 API documentation on dialog procedures }
  1590. //
  1591. //    Purpose
  1592. //      Display a dialog where the user enters a new password for the mailbox.
  1593. //      
  1594. //    Return Value
  1595. //      TRUE if message was handled, FALSE if we don't handle the message
  1596. //      
  1597. BOOL CALLBACK PasswordDlgProc (HWND    hDlg,
  1598.                                UINT    message,
  1599.                                WPARAM  wParam, 
  1600.                                LPARAM  lParam)
  1601. {
  1602.     static LPTSTR * pszPasswords;
  1603.     switch (message)
  1604.     {   
  1605.         case WM_INITDIALOG :
  1606.             // On this message only, the lParam is an argument passed by the
  1607.             // caller who instantiated this dialog.
  1608.             pszPasswords = (LPTSTR *)lParam;
  1609.             // Limit the fields the user can type in.
  1610.             Edit_LimitText  (GetDlgItem (hDlg, IDC_PASSWORD), MAX_PASSWORD_SIZE);
  1611.             Edit_LimitText  (GetDlgItem (hDlg, IDC_PASSWORD_CONFIRM), MAX_PASSWORD_SIZE);
  1612.             Edit_LimitText  (GetDlgItem (hDlg, IDC_OLD_PASSWORD), MAX_PASSWORD_SIZE);
  1613.             if (pfnDlgSubclassEx)
  1614.             {
  1615.                 pfnDlgSubclassEx (hDlg, CTL3D_ALL);
  1616.             }
  1617.             return TRUE;
  1618.         case WM_COMMAND :
  1619.             switch (LOWORD(wParam))
  1620.             {
  1621.                 case IDOK :
  1622.                     {
  1623.                         // Get and verify the OLD password
  1624.                         TCHAR szConfirm[MAX_PASSWORD_SIZE+1],  szOldPassword[MAX_PASSWORD_SIZE+1];
  1625.                         if (!GetWindowText (GetDlgItem (hDlg, IDC_OLD_PASSWORD), szOldPassword, MAX_PASSWORD_SIZE+1))
  1626.                         {
  1627.                             MessageBeep (MB_ICONEXCLAMATION);
  1628.                             PrivateMessageBox (IDS_MSG_NEED_OLD_PASSWORD, hDlg);
  1629.                             SetFocus (GetDlgItem (hDlg, IDC_OLD_PASSWORD));
  1630.                             return TRUE;
  1631.                         }
  1632.                         if (lstrcmp (szOldPassword, pszPasswords[1]))
  1633.                         {
  1634.                             MessageBeep (MB_ICONEXCLAMATION);
  1635.                             PrivateMessageBox (IDS_MSG_OLD_PASSWORD_NO_MATCH, hDlg);
  1636.                             SetWindowText (GetDlgItem (hDlg, IDC_OLD_PASSWORD), szBlank);
  1637.                             SetFocus (GetDlgItem (hDlg, IDC_OLD_PASSWORD));
  1638.                             return TRUE;
  1639.                         }
  1640.                         // Get the NEW password
  1641.                         if (!GetWindowText (GetDlgItem (hDlg, IDC_PASSWORD), pszPasswords[0], MAX_PASSWORD_SIZE+1))
  1642.                         {
  1643.                             MessageBeep (MB_ICONEXCLAMATION);
  1644.                             PrivateMessageBox (IDS_MSG_NEED_PASSWORD, hDlg);
  1645.                             SetFocus (GetDlgItem (hDlg, IDC_PASSWORD));
  1646.                             return TRUE;
  1647.                         }
  1648.                         // Get the NEW password (CONFIRM)
  1649.                         if (!GetWindowText (GetDlgItem (hDlg, IDC_PASSWORD_CONFIRM), szConfirm, MAX_PASSWORD_SIZE+1))
  1650.                         {
  1651.                             MessageBeep (MB_ICONEXCLAMATION);
  1652.                             PrivateMessageBox (IDS_MSG_NEED_PASSWORD_CONFIRM, hDlg);
  1653.                             SetFocus (GetDlgItem (hDlg, IDC_PASSWORD_CONFIRM));
  1654.                             return TRUE;
  1655.                         }
  1656.                         // Compare (case-sensitive) the instances of the new password typed in
  1657.                         if (lstrcmp (szConfirm, pszPasswords[0]))
  1658.                         {
  1659.                             MessageBeep (MB_ICONEXCLAMATION);
  1660.                             PrivateMessageBox (IDS_MSG_NEW_PASSWORD_NO_MATCH, hDlg);
  1661.                             SetWindowText (GetDlgItem (hDlg, IDC_PASSWORD), szBlank);
  1662.                             SetWindowText (GetDlgItem (hDlg, IDC_PASSWORD_CONFIRM), szBlank);
  1663.                             SetFocus (GetDlgItem (hDlg, IDC_PASSWORD));
  1664.                             return TRUE;
  1665.                         }
  1666.                     }
  1667.                 case IDCANCEL :
  1668.                     EndDialog (hDlg, (IDOK == LOWORD(wParam) ? TRUE : FALSE));
  1669.                     return TRUE;
  1670.             }
  1671.     }
  1672.     return FALSE;
  1673. }
  1674.  
  1675. ///////////////////////////////////////////////////////////////////////////////
  1676. //    BrowseMailboxes()
  1677. //
  1678. //    Parameters
  1679. //      pObj            Pointer to our IMAPIProp implementation (CUIMAPIProp)
  1680. //                      passed in to the DoConfidPropSheet() function
  1681. //      hOwnerWnd       The owner of any window we display
  1682. //      hInstance       The instance of this DLL
  1683. //
  1684. //    Purpose
  1685. //      This function get called by our implementation of
  1686. //      IMAPIControl::Active() by a user hitting a "Browse"
  1687. //      on the provider configuration property sheet.
  1688. //      Display a dialog box with all the mailboxes in the remote system
  1689. //
  1690. //    Return Value
  1691. //      None
  1692. //
  1693. void STDAPICALLTYPE BrowseMailboxes (CUIMAPIProp *  pObj,
  1694.                                      HWND           hOwnerWnd,
  1695.                                      HINSTANCE      hInstance)
  1696. {
  1697.     TCHAR szDisplayName[MAX_STRING_SIZE+1], szMailboxName[MAX_ALIAS_SIZE+1];
  1698.     TCHAR szStoredPassword[MAX_PASSWORD_SIZE+1], szEnterPassword[MAX_PASSWORD_SIZE+1];
  1699.     LPSPropValue pProp = NULL;
  1700.     DWORD dwMailboxID;
  1701.     SPropTagArray sptServer;
  1702.     sptServer.cValues = 1;
  1703.     sptServer.aulPropTag[0] = PR_SMP_REMOTE_SERVER;
  1704.     ULONG cValues;
  1705.     // Get the server name the user may have typed in the edit field
  1706.     HRESULT hResult = pObj->GetProps (&sptServer, fMapiUnicode, &cValues, &pProp);
  1707.     if (FAILED(hResult) || MAPI_W_ERRORS_RETURNED == hResult)
  1708.     {
  1709.         pfnMAPIFreeBuffer (pProp);
  1710.         PrivateMessageBox (IDS_MSG_NEED_SERVER_NAME, hOwnerWnd);
  1711.         return;
  1712.     }
  1713.     ASSERT (pProp->ulPropTag == PR_SMP_REMOTE_SERVER);
  1714.     TCHAR szServer[MAX_STRING_SIZE+1];
  1715.     lstrcpy (szServer, pProp->Value.LPSZ);
  1716.     pfnMAPIFreeBuffer (pProp);
  1717.     // Validate the server
  1718.     if (!IsValidServerName (szServer))
  1719.     {
  1720.         MessageBeep (MB_ICONEXCLAMATION);
  1721.         PrivateMessageBox (IDS_MSG_INVALID_SERVER_NAME, hOwnerWnd);
  1722.         return;
  1723.     }
  1724.     if (!IsWINDSServerAvailable (szServer))
  1725.     {
  1726.         PrivateMessageBox (IDS_MSG_SERVER_NOT_FOUND, hOwnerWnd);
  1727.         return;
  1728.     }
  1729.     // Show the list of mailboxes in the server. If the user hit OK, process the selected entry.
  1730. Restart:
  1731.     if (S_OK == ShowServerAccounts  (hOwnerWnd,
  1732.                                      hInstance,
  1733.                                      szServer,
  1734.                                      szMailboxName,
  1735.                                      szDisplayName,
  1736.                                      szStoredPassword,
  1737.                                      &dwMailboxID))
  1738.     {
  1739.         // Set the selected mailbox properties in the property object
  1740.         SPropValue spvProps[5] = { 0 };
  1741.         spvProps[0].ulPropTag = PR_SMP_MAILBOX_NAME;
  1742.         spvProps[0].Value.LPSZ = szMailboxName;
  1743.         spvProps[1].ulPropTag = PR_SMP_USER_NAME;
  1744.         spvProps[1].Value.LPSZ = szDisplayName;
  1745.         spvProps[2].ulPropTag = PR_SMP_MAILBOX_PASSWORD;
  1746.         spvProps[2].Value.LPSZ = szStoredPassword;
  1747.         spvProps[3].ulPropTag = PR_SMP_MAILBOX_PASSWORD;
  1748.         spvProps[3].Value.LPSZ = szEnterPassword;
  1749.         spvProps[4].Value.b = TRUE; // Activate the "BROWSE" button on the dialog below
  1750.         // Before continuing, the user must verify it's access to the mailbox by typing the correct password
  1751.         int nAnswer = DialogBoxParam (hInstance,  
  1752.                                       MAKEINTRESOURCE(IDD_ENTER_PASSWORD),
  1753.                                       hOwnerWnd,
  1754.                                       EnterMBPasswordDlgProc,
  1755.                                       (LPARAM)spvProps);
  1756.         if (IDC_BROWSE_MB == nAnswer)
  1757.         {
  1758.             goto Restart;
  1759.         }
  1760.         if (TRUE == nAnswer)
  1761.         {
  1762.             // Access is verified, continue
  1763.             spvProps[3].ulPropTag = PR_SMP_MAILBOX_ID;
  1764.             spvProps[3].Value.l = dwMailboxID;
  1765.             pObj->SetProps (4, spvProps, NULL);
  1766.             // Now we must tell the property sheet handler to re-read the data for
  1767.             // this field from the IMAPIProp object any of the DTCTL members with a key, for a notification on them.
  1768.             for (ULONG iRow=0; ; iRow++)
  1769.             {
  1770.                 LPSRow pRow;
  1771.                 LPSPropValue pControlID;
  1772.                 hResult = pObj->m_pTableData->HrEnumRow (iRow, &pRow);
  1773.                 if (hResult || !pRow)
  1774.                 {
  1775.                     TraceResult ("BrowseMailboxes: Traversing the display table", hResult);
  1776.                     return;
  1777.                 }
  1778.                 pControlID = PpropFindProp (pRow->lpProps, pRow->cValues, PR_CONTROL_ID);
  1779.                 if (pControlID->Value.bin.cb)
  1780.                 {
  1781.                     pObj->m_pTableData->HrNotify (0, 1, pControlID);
  1782.                 }
  1783.                 pfnMAPIFreeBuffer (pRow);
  1784.             }
  1785.         }
  1786.     }
  1787. }
  1788.  
  1789. ///////////////////////////////////////////////////////////////////////////////
  1790. //    ConfigChangePassword()
  1791. //
  1792. //    Parameters
  1793. //      pObj            Pointer to our IMAPIProp implementation (CUIMAPIProp)
  1794. //                      passed in to the DoConfidPropSheet() function
  1795. //      hOwnerWnd       The owner of any window we display
  1796. //      hInstance       The instance of this DLL
  1797. //
  1798. //    Purpose
  1799. //      This function get called by our implementation of
  1800. //      IMAPIControl::Active() by a user hitting a "Change Mailbox Password"
  1801. //      on the provider configuration property sheet.
  1802. //      Display a dialog box where the user can change the password of the
  1803. //      mailbox.
  1804. //
  1805. //    Return Value
  1806. //      None
  1807. //
  1808. void STDAPICALLTYPE ConfigChangePassword (CUIMAPIProp * pObj, HWND hOwnerWnd, HINSTANCE hInstance)
  1809. {
  1810.     const static SizedSPropTagArray(3, sptServerAndPass) =
  1811.     {
  1812.         3,
  1813.         {
  1814.             PR_SMP_REMOTE_SERVER,
  1815.             PR_SMP_MAILBOX_NAME,
  1816.             PR_SMP_MAILBOX_PASSWORD
  1817.         }
  1818.     };
  1819.     TCHAR szOldPassword[MAX_PASSWORD_SIZE+1], szNewPassword[MAX_PASSWORD_SIZE+1];
  1820.     TCHAR szServer[MAX_STRING_SIZE+1], szMBName[MAX_STRING_SIZE+1];
  1821.     LPTSTR aszPasswords[2] = { 0 };
  1822.     ULONG cValues;
  1823.     LPSPropValue pProp = NULL;
  1824.     SPropValue spvNewPassword = { 0 };
  1825.     // Get the server and mailbox information for the property object
  1826.     HRESULT hResult = pObj->GetProps ((LPSPropTagArray)&sptServerAndPass, fMapiUnicode, &cValues, &pProp);
  1827.     if (FAILED(hResult) || MAPI_W_ERRORS_RETURNED == hResult)
  1828.     {
  1829.         pfnMAPIFreeBuffer (pProp);
  1830.         PrivateMessageBox (IDS_MSG_NEED_SERVER_NAME, hOwnerWnd);
  1831.         return;
  1832.     }
  1833.     ASSERTMSG (pProp[0].ulPropTag == PR_SMP_REMOTE_SERVER, "Where is PR_SMP_REMOTE_SERVER?!?!");
  1834.     ASSERTMSG (pProp[1].ulPropTag == PR_SMP_MAILBOX_NAME, "Where is PR_SMP_MAILBOX_NAME?!?!");
  1835.     ASSERTMSG (pProp[2].ulPropTag == PR_SMP_MAILBOX_PASSWORD, "Where is PR_SMP_MAILBOX_PASSWORD?!?!");
  1836.     lstrcpy (szServer, pProp[0].Value.LPSZ);
  1837.     lstrcpy (szMBName, pProp[1].Value.LPSZ);
  1838.     lstrcpy (szOldPassword, pProp[2].Value.LPSZ);
  1839.     pfnMAPIFreeBuffer (pProp);
  1840.     // Validate the server name and availability
  1841.     if (!IsValidServerName (szServer))
  1842.     {
  1843.         MessageBeep (MB_ICONEXCLAMATION);
  1844.         PrivateMessageBox (IDS_MSG_INVALID_SERVER_NAME, hOwnerWnd);
  1845.         return;
  1846.     }
  1847.     if (!IsWINDSServerAvailable (szServer))
  1848.     {
  1849.         PrivateMessageBox (IDS_MSG_SERVER_NOT_FOUND, hOwnerWnd);
  1850.         return;
  1851.     }
  1852.     aszPasswords[0] = szNewPassword;
  1853.     aszPasswords[1] = szOldPassword;
  1854.  
  1855.     // Show the dialog where the user can change the information
  1856.     if (TRUE == DialogBoxParam (hInstance,
  1857.                                 MAKEINTRESOURCE(IDD_NEW_PASSWORD),
  1858.                                 hOwnerWnd,
  1859.                                 PasswordDlgProc,
  1860.                                 (LPARAM)&aszPasswords))
  1861.     {
  1862.         // If the user is ok call the server
  1863.         if (S_OK == ChangeMBServerPassword (szServer, szMBName, szOldPassword, szNewPassword))
  1864.         {
  1865.             // If the change was successfull, save the new password in the property object.
  1866.             spvNewPassword.ulPropTag = PR_SMP_MAILBOX_PASSWORD;
  1867.             spvNewPassword.Value.LPSZ = szNewPassword;
  1868.             pObj->SetProps (1, &spvNewPassword, NULL);
  1869.         }
  1870.     }
  1871. }
  1872.  
  1873. ///////////////////////////////////////////////////////////////////////////////
  1874. //    PingRemoteServer()
  1875. //
  1876. //    Parameters
  1877. //      hOwnerWnd       Handle to a windows that owns any UI done by
  1878. //                      this provider
  1879. //      pProps          An array of SPropValue structures with the logon
  1880. //                      properties of the service. The first 5 properties
  1881. //                      must be the standard properties for a WINDS service
  1882. //                      and they must be in the standard order (see COMWINDS.H)
  1883. //
  1884. //    Purpose
  1885. //      Make a quick connection to the server verifying a mailbox access
  1886. //      with the current password and name.
  1887. //
  1888. //    Return Value
  1889. //      TRUE if the connection was successful, or the user does not care that
  1890. //      the server is offline.
  1891. //      FALSE if the user wants to change the configuration properties again.
  1892. //
  1893. BOOL WINAPI PingRemoteServer (HWND hOwnerWnd, LPSPropValue pProps)
  1894. {
  1895.     BOOL fPingedOK = TRUE;
  1896.     DWORD dwMsgIDS = 0, dwMailboxID;
  1897.     TCHAR szServerUserFullName[MAX_STRING_SIZE+1];
  1898.     HRESULT hLogonError;
  1899.     CharUpper (pProps[SERVER_NAME].Value.LPSZ);
  1900.     // Try to connect to the server and see if it is around
  1901.     if (IsWINDSServerAvailable (pProps[SERVER_NAME].Value.LPSZ))
  1902.     {
  1903.         hLogonError = LogonServerMailbox (pProps[SERVER_NAME].Value.LPSZ,
  1904.                                           pProps[MAILBOX_NAME].Value.LPSZ,
  1905.                                           szServerUserFullName,
  1906.                                           pProps[PASSWORD].Value.LPSZ,
  1907.                                           &dwMailboxID);
  1908.         if (hLogonError)
  1909.         {
  1910.             switch (hLogonError)
  1911.             {
  1912.                 case HRESULT_FROM_WIN32 (ERROR_NO_SUCH_USER) :
  1913.                     dwMsgIDS = IDS_MSG_CONFIG_INVALID_USER;
  1914.                     break;
  1915.                 case HRESULT_FROM_WIN32 (ERROR_BAD_USERNAME) :
  1916.                     dwMsgIDS = IDS_MSG_CONFIG_INVALID_USER_NAME;
  1917.                     break;
  1918.                 case HRESULT_FROM_WIN32 (ERROR_INVALID_PASSWORD) :
  1919.                     dwMsgIDS = IDS_MSG_INVALID_MB_PASSWORD;
  1920.                     break;
  1921.                 default :
  1922.                     dwMsgIDS = IDS_MSG_CONFIG_NO_CONNECT;
  1923.                     break;
  1924.             }
  1925.             PrivateMessageBox (dwMsgIDS, hOwnerWnd);
  1926.             fPingedOK = FALSE;
  1927.         }
  1928.     }
  1929.     else
  1930.     {
  1931.         if (IDNO == PrivateMessageBox (IDS_MSG_NO_SERVER_GO_OFFLINE, hOwnerWnd, MB_YESNO | MB_ICONSTOP))
  1932.         {
  1933.             // The user wants to re-enter the name of the remote server
  1934.             fPingedOK = FALSE;
  1935.         }
  1936.     }
  1937.     return fPingedOK;
  1938. }
  1939.  
  1940. ///////////////////////////////////////////////////////////////////////////////
  1941. //    DoServerLogon()
  1942. //
  1943. //    Parameters
  1944. //      pMBInfo             Pointer to the mailbox info structure where this
  1945. //                          function returns the mailbox information of the
  1946. //                          user logging in.
  1947. //      pProps              An array of SPropValue structures with the logon
  1948. //                          properties of the service. The first 5 properties
  1949. //                          must be the standard properties for a WINDS
  1950. //                          service and they must be in the standard order
  1951. //                          (see COMWINDS.H)
  1952. //      pProfileObj         Profile object to which this function write
  1953. //                          changes, if any are required based on the latest
  1954. //                          information comming down from the server or
  1955. //                          entered by the user in the configuration dialog.
  1956. //      fUIAllowed          Weather or not the function is allowed to display
  1957. //                          any UI of information or request input from
  1958. //                          the user.
  1959. //      hOwnerWnd           Handle to the window that owns any UI displayed.
  1960. //      fSetNotification    Weather or not to set notifications with the
  1961. //                          remote server
  1962. //      dwNotifMask         Mask of events this provider is intersted in
  1963. //                          receiving.
  1964. //      pdwConnectID        Where I return the connection ID returned by
  1965. //                          the server
  1966. //      fOffLineOK          Flag that indicates that the caller does not
  1967. //                          want to be bother with a "server offline"
  1968. //                          notification/UI and that we should return success
  1969. //                          even if the server could not be reached.
  1970. //
  1971. //    Purpose
  1972. //      This function does a complete logon to the server with the
  1973. //      information passed in the pProps arguments. The function makes a
  1974. //      remote call to the server to request access to a mailbox. If
  1975. //      access is not granted we display messages and if needed, display the
  1976. //      appropiate dialog boxes for reconfiguration or change of password.
  1977. //      If the server was off-line, but the user does not mind, we return
  1978. //      MAPI_W_NO_SERVICE.
  1979. //      If the server is off-line, but no UI is allowed we return
  1980. //      MAPI_E_NETWORK_ERROR.
  1981. //
  1982. //    Return Value
  1983. //      An HRESULT
  1984. //
  1985. HRESULT WINAPI DoServerLogon (PMAILBOX_INFO pMBInfo,
  1986.                               LPSPropValue  pProps,
  1987.                               LPPROFSECT    pProfileObj,
  1988.                               BOOL          fUIAllowed,
  1989.                               HWND          hOwnerWnd,
  1990.                               BOOL          fSetNotification,
  1991.                               DWORD         dwNotifMask,
  1992.                               DWORD *       pdwConnectID,
  1993.                               BOOL          fOffLineOK)
  1994. {
  1995.     ASSERT (PR_SMP_REMOTE_SERVER == pProps[SERVER_NAME].ulPropTag);
  1996.     ASSERT (PR_SMP_MAILBOX_NAME == pProps[MAILBOX_NAME].ulPropTag);
  1997.     ASSERT (PR_SMP_MAILBOX_ID == pProps[MAILBOX_ID].ulPropTag);
  1998.     ASSERT (PR_SMP_USER_NAME == pProps[USER_NAME].ulPropTag);
  1999.     ASSERT (PR_SMP_MAILBOX_PASSWORD == pProps[PASSWORD].ulPropTag);
  2000.     
  2001.     pMBInfo->dwObjID = pProps[MAILBOX_ID].Value.l;
  2002.     lstrcpy (pMBInfo->szMailboxName, pProps[MAILBOX_NAME].Value.LPSZ);
  2003.     lstrcpy (pMBInfo->szFullName, pProps[USER_NAME].Value.LPSZ);
  2004.     lstrcpy (pMBInfo->szPassword, pProps[PASSWORD].Value.LPSZ);
  2005.     
  2006.     SPropValue spvProps[5] = { 0 };
  2007.     DWORD dwMsgIDS = 0, dwStyle = MB_YESNO | MB_ICONSTOP, dwMailboxID;
  2008.     HRESULT hLogonError;
  2009.     long nResponse;
  2010.  
  2011.     // Try to connect to the server and see if it is around
  2012.     if (IsWINDSServerAvailable (pProps[SERVER_NAME].Value.LPSZ))
  2013.     {
  2014. RestartMailboxLogon:
  2015.         if (fSetNotification)
  2016.         {
  2017.             hLogonError = LogonServerMailboxAndSetNotif (pProps[SERVER_NAME].Value.LPSZ,
  2018.                                                          pMBInfo->szMailboxName,
  2019.                                                          pMBInfo->szFullName,
  2020.                                                          pMBInfo->szPassword,
  2021.                                                          &dwMailboxID,
  2022.                                                          dwNotifMask,
  2023.                                                          *pdwConnectID);
  2024.         }
  2025.         else
  2026.         {
  2027.             hLogonError = LogonServerMailbox (pProps[SERVER_NAME].Value.LPSZ,
  2028.                                               pMBInfo->szMailboxName,
  2029.                                               pMBInfo->szFullName,
  2030.                                               pMBInfo->szPassword,
  2031.                                               &dwMailboxID);
  2032.         }
  2033.         if (hLogonError)
  2034.         {
  2035.             if (fUIAllowed)
  2036.             {
  2037.                 switch (hLogonError)
  2038.                 {
  2039.                     case HRESULT_FROM_WIN32 (ERROR_NO_SUCH_USER) :
  2040.                         dwMsgIDS = IDS_MSG_LOGON_INVALID_USER;
  2041.                         break;
  2042.                     case HRESULT_FROM_WIN32 (ERROR_BAD_USERNAME) :
  2043.                         dwMsgIDS = IDS_MSG_LOGON_INVALID_USER_NAME;
  2044.                         break;
  2045.                     case HRESULT_FROM_WIN32 (ERROR_INVALID_PASSWORD) :
  2046.                         dwMsgIDS = IDS_MSG_INVALID_MB_PASSWORD;
  2047.                         dwStyle = MB_OK | MB_ICONSTOP;
  2048.                         break;
  2049.                     default :
  2050.                         dwMsgIDS = IDS_MSG_LOGON_NO_CONNECT;
  2051.                         break;
  2052.                 }
  2053.                 if (dwMsgIDS)
  2054.                 {
  2055.                     PrivInitialize3DCtl (ghInstance);
  2056.                     nResponse = PrivateMessageBox (dwMsgIDS, hOwnerWnd, dwStyle);
  2057.                     if (IDYES == nResponse && hLogonError != HRESULT_FROM_WIN32 (ERROR_INVALID_PASSWORD))
  2058.                     {
  2059.                         return S_FALSE;
  2060.                     }
  2061.                     if (hLogonError == HRESULT_FROM_WIN32 (ERROR_INVALID_PASSWORD))
  2062.                     {
  2063.                         spvProps[0].ulPropTag = PR_SMP_MAILBOX_NAME;
  2064.                         spvProps[0].Value.LPSZ = pMBInfo->szMailboxName;
  2065.                         spvProps[1].ulPropTag = PR_SMP_USER_NAME;
  2066.                         spvProps[1].Value.LPSZ = pMBInfo->szFullName;
  2067.                         spvProps[2].ulPropTag = PR_SMP_MAILBOX_PASSWORD;
  2068.                         spvProps[2].Value.LPSZ = NULL;
  2069.                         spvProps[3].ulPropTag = PR_SMP_MAILBOX_PASSWORD;
  2070.                         spvProps[3].Value.LPSZ = pMBInfo->szPassword;
  2071.                         spvProps[4].Value.b = FALSE; // De-activate the "BROWSE" button on the dialog below
  2072.                         ASSERT (NULL != ghInstance);
  2073.                         nResponse = DialogBoxParam (ghInstance,  
  2074.                                                     MAKEINTRESOURCE(IDD_ENTER_PASSWORD),
  2075.                                                     hOwnerWnd,
  2076.                                                     EnterMBPasswordDlgProc,
  2077.                                                     (LPARAM)spvProps);
  2078.                         if (FALSE == nResponse)
  2079.                         {
  2080.                             return MAPI_E_EXTENDED_ERROR;
  2081.                         }
  2082.                         else
  2083.                         {
  2084.                             goto RestartMailboxLogon;
  2085.                         }
  2086.                     }
  2087.                 }
  2088.             }
  2089.             else
  2090.             {
  2091.                 return hLogonError;
  2092.             }
  2093.         }
  2094.         else
  2095.         {
  2096.             ULONG ulProps = 0;
  2097.             // If any of this properties that came from the server is different to
  2098.             // what we have stored on the profile, then set them back for the next session.
  2099.             if (lstrcmp (pProps[USER_NAME].Value.LPSZ, pMBInfo->szFullName))
  2100.             {
  2101.                 spvProps[ulProps].ulPropTag = PR_SMP_USER_NAME;
  2102.                 spvProps[ulProps++].Value.LPSZ = pMBInfo->szFullName;
  2103.             }
  2104.             if (lstrcmp (pProps[PASSWORD].Value.LPSZ, pMBInfo->szPassword))
  2105.             {
  2106.                 spvProps[ulProps].ulPropTag = PR_SMP_MAILBOX_PASSWORD;
  2107.                 spvProps[ulProps++].Value.LPSZ = pMBInfo->szPassword;
  2108.             }
  2109.             if (dwMailboxID != pProps[MAILBOX_ID].Value.ul)
  2110.             {
  2111.                 spvProps[ulProps].ulPropTag = PR_SMP_MAILBOX_ID;
  2112.                 spvProps[ulProps++].Value.l = dwMailboxID;
  2113.             }
  2114.             if (ulProps)
  2115.             {
  2116.                 HRESULT hResult = pProfileObj->SetProps (ulProps, spvProps, NULL);
  2117.                 TraceResult ("DoServerLogon: Could not set last-minute props", hResult);
  2118.             }
  2119.         }
  2120.     }
  2121.     else
  2122.     {
  2123.         // If the caller says that is OK to be offline, then return.
  2124.         if (fOffLineOK)
  2125.         {
  2126.             return S_OK;
  2127.         }
  2128.         if (fUIAllowed)
  2129.         {
  2130.             PrivInitialize3DCtl (ghInstance);
  2131.             if (IDYES == PrivateMessageBox (IDS_MSG_NO_SERVER_ONLINE, hOwnerWnd, MB_YESNO))
  2132.             {
  2133.                 // The user wants to re-enter the name of the remote server
  2134.                 return MAPI_W_NO_SERVICE;
  2135.             }
  2136.         }
  2137.         else
  2138.         {
  2139.             return MAPI_E_NETWORK_ERROR;
  2140.         }
  2141.     }
  2142.     return S_OK;
  2143. }
  2144.  
  2145. ///////////////////////////////////////////////////////////////////////////////
  2146. //    WizardEntry()
  2147. //
  2148. //    Parameters
  2149. //      { Refer to MAPI Documentation on this method }
  2150. //
  2151. //    Purpose
  2152. //      Returns the name of the resource where the controls for the wizard
  2153. //      pages are defined and outlined. The Wizard gives us a pointer to an
  2154. //      IMAPIProp object. We will release this object after we are finished
  2155. //      in the dialog procedure of our configuration pages.
  2156. //
  2157. //    Return Value
  2158. //      S_OK always.
  2159. //
  2160. ULONG STDAPICALLTYPE WizardEntry (HINSTANCE     hProviderDLLInstance,
  2161.                                   LPTSTR *      ppcsResourceName,
  2162.                                   DLGPROC *     ppDlgProc,
  2163.                                   LPMAPIPROP    pMapiProp,
  2164.                                   LPVOID        pSupObj)
  2165. {   
  2166.     InfoTrace ("WizardEntry function called");
  2167.     // Quick sanity check on the input parameters
  2168.     ASSERT (ppcsResourceName);
  2169.     ASSERT (pMapiProp);
  2170.     ASSERT (ppDlgProc);
  2171.     ASSERT (hProviderDLLInstance);
  2172.     // The resource name needs to be an actual text string not
  2173.     // something generated with the MAKEINTRESOURCE() macro
  2174.     const static TCHAR szTemplate[] = TEXT("WIZARD_PAGES");
  2175.     *ppcsResourceName = (LPTSTR)szTemplate;
  2176.     *ppDlgProc = (DLGPROC)WizardDlgProc;
  2177.     pPropObj = pMapiProp;
  2178.     pPropObj->AddRef();
  2179.     ghInstance = hProviderDLLInstance;
  2180.  
  2181.     fInitalizeControls = fDownloadMBList = TRUE;
  2182.     return S_OK;
  2183. }
  2184.  
  2185. ///////////////////////////////////////////////////////////////////////////////
  2186. //    WizardDlgProc()
  2187. //
  2188. //    Parameters
  2189. //      { Refer to MAPI and Win32 SDK Documentation on this method }
  2190. //
  2191. //    Purpose
  2192. //      This is the function that the profile wizard will call while
  2193. //      interacting with our configuration pages.
  2194. //
  2195. //    Return Value
  2196. //      TRUE if we handle a message, FALSE if we don't or there was an error
  2197. //      in the data
  2198. //
  2199. BOOL STDAPICALLTYPE WizardDlgProc (HWND           hDlg,
  2200.                                    UINT           message,
  2201.                                    WPARAM         wParam,
  2202.                                    LPARAM         lParam)
  2203. {
  2204.     static SPropValue spvWizardProps[WIZARD_PROPERTIES] = { 0 };
  2205.     static TCHAR szDisplayName[MAX_STRING_SIZE+1];
  2206.     static TCHAR szServerName[MAX_STRING_SIZE+1];
  2207.     static TCHAR szMailboxName[MAX_ALIAS_SIZE+1];
  2208.     static TCHAR szStoredPassword[MAX_PASSWORD_SIZE+1];
  2209.     static TCHAR szEnterPassword[MAX_PASSWORD_SIZE+1];
  2210.     static DWORD dwMailboxID;
  2211.     static UINT iPageNum;
  2212.     switch (message)
  2213.     {
  2214.         case WM_INITDIALOG:
  2215.             // If the control have not been initialized do so
  2216.             if (fInitalizeControls)
  2217.             {
  2218.                 // Send output to a console window BUT NOT to the COM1
  2219.                 InitTraces (TRACES_CONSOLE | TRACES_NO_COM_OUTPUT);
  2220.                 dwMailboxID = 0;
  2221.                 // Set the flag to avoid re-initialization
  2222.                 fInitalizeControls = FALSE;
  2223.                 // Limit the maximum number of character users can enter for the mailbox PASSWORD
  2224.                 Edit_LimitText  (GetDlgItem (hDlg, IDC_PASSWORD), MAX_PASSWORD_SIZE);
  2225.                 PrivInitialize3DCtl (ghInstance);
  2226.                 iPageNum = 0;
  2227.             }
  2228.             return TRUE;
  2229.  
  2230.         case WIZ_QUERYNUMPAGES :
  2231.             // Return the number of pages the our provider needs to display
  2232.             return (BOOL)2;
  2233.  
  2234.         case WM_CLOSE :
  2235.             pPropObj->Release();
  2236.             pPropObj = NULL;
  2237.             PrivUninitialize3DCtl (ghInstance);
  2238.             // Close down the log file/com port/console window/etc.
  2239.             UnInitTraces();
  2240.             return TRUE;
  2241.  
  2242.         case WM_COMMAND :
  2243.             switch (LOWORD(wParam))
  2244.             {
  2245.                 case IDC_BROWSE_MB :
  2246.                     if (S_OK == ShowServerAccounts  (hDlg,
  2247.                                                      ghInstance,
  2248.                                                      szServerName,
  2249.                                                      szMailboxName,
  2250.                                                      szDisplayName,
  2251.                                                      szStoredPassword,
  2252.                                                      &dwMailboxID))
  2253.                     {
  2254.                         SetWindowText (GetDlgItem (hDlg, IDC_MAILBOXNAME), szMailboxName);
  2255.                         SetWindowText (GetDlgItem (hDlg, IDC_USER_NAME), szDisplayName);
  2256.                     }
  2257.                     return TRUE;
  2258.  
  2259.                 case WIZ_NEXT:
  2260.                     switch (iPageNum)
  2261.                     {
  2262.                         // We are about to leave a page in each of the 
  2263.                         // following cases. Here we should get the data from
  2264.                         // the controls in that page, validate it if necessary
  2265.                         // and copy the validated data into the property array
  2266.                         case 0:
  2267.                             break;
  2268.  
  2269.                         case 1:
  2270.                             if (!GetWindowText (GetDlgItem (hDlg, IDC_SERVERNAME),
  2271.                                                 szServerName,
  2272.                                                 sizeof(szServerName)))
  2273.                             {
  2274.                                 MessageBeep (MB_ICONEXCLAMATION);
  2275.                                 PrivateMessageBox (IDS_MSG_NEED_SERVER_NAME, hDlg);
  2276.                                 return FALSE;
  2277.                             }
  2278.                             if (!IsValidServerName (szServerName))
  2279.                             {
  2280.                                 MessageBeep (MB_ICONEXCLAMATION);
  2281.                                 PrivateMessageBox (IDS_MSG_INVALID_SERVER_NAME, hDlg);
  2282.                                 return FALSE;
  2283.                             }
  2284.                             if (!IsWINDSServerAvailable (szServerName))
  2285.                             {
  2286.                                 PrivateMessageBox (IDS_MSG_SERVER_NOT_FOUND, hDlg);
  2287.                                 return FALSE;
  2288.                             }
  2289.                             if (fDownloadMBList)
  2290.                             {
  2291.                                 if (S_OK == ShowServerAccounts  (hDlg,
  2292.                                                                  ghInstance,
  2293.                                                                  szServerName,
  2294.                                                                  szMailboxName,
  2295.                                                                  szDisplayName,
  2296.                                                                  szStoredPassword,
  2297.                                                                  &dwMailboxID))
  2298.                                 {
  2299.                                     SetWindowText (GetDlgItem (hDlg, IDC_MAILBOXNAME), szMailboxName);
  2300.                                     SetWindowText (GetDlgItem (hDlg, IDC_USER_NAME), szDisplayName);
  2301.                                     fDownloadMBList = FALSE;
  2302.                                 }
  2303.                                 else
  2304.                                 {
  2305.                                     return FALSE;
  2306.                                 }
  2307.                             }
  2308.                             break;
  2309.  
  2310.                         case 2:
  2311.                             if (!GetWindowTextLength (GetDlgItem (hDlg, IDC_PASSWORD)))
  2312.                             {
  2313.                                 MessageBeep (MB_ICONEXCLAMATION);
  2314.                                 PrivateMessageBox (IDS_MSG_SELECT_MB_NAME, hDlg);
  2315.                                 SetFocus (GetDlgItem (hDlg, IDC_BROWSE_MB));
  2316.                                 return FALSE;
  2317.                             }
  2318.                             if (!GetWindowText (GetDlgItem (hDlg, IDC_PASSWORD), szEnterPassword, sizeof(szEnterPassword)))
  2319.                             {
  2320.                                 MessageBeep (MB_ICONEXCLAMATION);
  2321.                                 PrivateMessageBox (IDS_MSG_NEED_PASSWORD, hDlg);
  2322.                                 SetFocus (GetDlgItem (hDlg, IDC_PASSWORD));
  2323.                                 return FALSE;
  2324.                             }
  2325.                             if (lstrcmp (szEnterPassword, szStoredPassword))
  2326.                             {
  2327.                                 MessageBeep (MB_ICONEXCLAMATION);
  2328.                                 PrivateMessageBox (IDS_MSG_INVALID_MB_PASSWORD, hDlg);
  2329.                                 SetFocus (GetDlgItem (hDlg, IDC_PASSWORD));
  2330.                                 return FALSE;
  2331.                             }
  2332.                             spvWizardProps[SERVER_NAME].ulPropTag  = PR_SMP_REMOTE_SERVER;
  2333.                             spvWizardProps[SERVER_NAME].Value.LPSZ = szServerName;
  2334.                             spvWizardProps[MAILBOX_NAME].ulPropTag  = PR_SMP_MAILBOX_NAME;
  2335.                             spvWizardProps[MAILBOX_NAME].Value.LPSZ = szMailboxName;
  2336.                             spvWizardProps[MAILBOX_ID].ulPropTag  = PR_SMP_MAILBOX_ID;
  2337.                             spvWizardProps[MAILBOX_ID].Value.l = dwMailboxID;
  2338.                             spvWizardProps[USER_NAME].ulPropTag  = PR_SMP_USER_NAME;
  2339.                             spvWizardProps[USER_NAME].Value.LPSZ = szDisplayName;
  2340.                             spvWizardProps[PASSWORD].ulPropTag  = PR_SMP_MAILBOX_PASSWORD;
  2341.                             spvWizardProps[PASSWORD].Value.LPSZ = szStoredPassword;
  2342.                             // Since this is the last page in our configuration
  2343.                             // we must save the obtained data into the
  2344.                             // IMAPIProp object that the wizard gave us. In
  2345.                             // turn this data will be saved in the profile
  2346.                             // section of this provider
  2347.                             ASSERT (pPropObj);
  2348.                             if (pPropObj)
  2349.                             {
  2350.                                 HRESULT hResult = pPropObj->SetProps (WIZARD_PROPERTIES, spvWizardProps, NULL);
  2351.                                 if (hResult)
  2352.                                 {
  2353.                                     // Something went wrong
  2354.                                     TraceResult ("WizardDlgPrc: Failed to set props", hResult);
  2355.                                     return FALSE;
  2356.                                 }
  2357.                             }
  2358.                             break;
  2359.  
  2360.                         default:
  2361.                             // We should not get here. No pages after three
  2362.                             ASSERT (FALSE);
  2363.                             break;
  2364.                     }
  2365.                     // Disable the page we were in and enable the next one
  2366.                     // before it is display by the wizard
  2367.                     TogglePage (hDlg, iPageNum, FALSE);
  2368.                     TogglePage (hDlg, ++iPageNum, TRUE);
  2369.                     return TRUE;
  2370.  
  2371.                 case WIZ_PREV:
  2372.                     // Disable the page we were in and enable the next one
  2373.                     // before it is display by the wizard
  2374.                     TogglePage (hDlg, iPageNum, FALSE);
  2375.                     TogglePage (hDlg, --iPageNum, TRUE);
  2376.                     return TRUE;
  2377.             }
  2378.             break;
  2379.     }
  2380.     return FALSE;
  2381. }
  2382.  
  2383. ///////////////////////////////////////////////////////////////////////////////
  2384. //    TogglePage()
  2385. //
  2386. //    Parameters
  2387. //      hDlg        Handle to the dialogs where the controls are located
  2388. //      iPage       Number of the page we are going to toggle
  2389. //      fState      State of the controls: TRUE shows them, FALSE hides them
  2390. //
  2391. //    Purpose
  2392. //      This function will hide or show the controls for the page number
  2393. //      specified in the iPage parameter.
  2394. //
  2395. //    Return Value
  2396. //      None
  2397. //
  2398. void WINAPI TogglePage (HWND hDlg, UINT iPage, BOOL fState)
  2399. {
  2400.     // What page is it?
  2401.     HWND hEditCtl = NULL;
  2402.     switch (iPage)
  2403.     {
  2404.         // Toggle the controls that should be displayed for a particular page
  2405.         case 1 :
  2406.             EnableWindow (GetDlgItem (hDlg, IDC_STATIC1), fState);
  2407.             ShowWindow   (GetDlgItem (hDlg, IDC_STATIC1), fState ? SW_SHOW : SW_HIDE);
  2408.             EnableWindow (GetDlgItem (hDlg, IDC_INFO1), fState);
  2409.             ShowWindow   (GetDlgItem (hDlg, IDC_INFO1), fState ? SW_SHOW : SW_HIDE);
  2410.             hEditCtl = GetDlgItem (hDlg, IDC_SERVERNAME);
  2411.             break;
  2412.  
  2413.         case 2 :
  2414.             EnableWindow (GetDlgItem (hDlg, IDC_STATIC2), fState);
  2415.             ShowWindow   (GetDlgItem (hDlg, IDC_STATIC2), fState ? SW_SHOW : SW_HIDE);
  2416.             EnableWindow (GetDlgItem (hDlg, IDC_STATIC3), fState);
  2417.             ShowWindow   (GetDlgItem (hDlg, IDC_STATIC3), fState ? SW_SHOW : SW_HIDE);
  2418.             EnableWindow (GetDlgItem (hDlg, IDC_STATIC4), fState);
  2419.             ShowWindow   (GetDlgItem (hDlg, IDC_STATIC4), fState ? SW_SHOW : SW_HIDE);
  2420.             EnableWindow (GetDlgItem (hDlg, IDC_INFO2), fState);
  2421.             ShowWindow   (GetDlgItem (hDlg, IDC_INFO2), fState ? SW_SHOW : SW_HIDE);
  2422.             EnableWindow (GetDlgItem (hDlg, IDC_MAILBOXNAME), fState);
  2423.             ShowWindow   (GetDlgItem (hDlg, IDC_MAILBOXNAME), fState ? SW_SHOW : SW_HIDE);
  2424.             EnableWindow (GetDlgItem (hDlg, IDC_USER_NAME), fState);
  2425.             ShowWindow   (GetDlgItem (hDlg, IDC_USER_NAME), fState ? SW_SHOW : SW_HIDE);
  2426.             EnableWindow (GetDlgItem (hDlg, IDC_BROWSE_MB), fState);
  2427.             ShowWindow   (GetDlgItem (hDlg, IDC_BROWSE_MB), fState ? SW_SHOW : SW_HIDE);
  2428.             hEditCtl = GetDlgItem (hDlg, IDC_PASSWORD); // We want the button to have the focus by default
  2429.             break;
  2430.     }
  2431.     if (hEditCtl)
  2432.     {
  2433.         EnableWindow (hEditCtl, fState);
  2434.         ShowWindow   (hEditCtl, fState ? SW_SHOW : SW_HIDE);
  2435.         if (fState)
  2436.         {
  2437.             SetFocus (hEditCtl);
  2438.         }
  2439.     }
  2440. }
  2441.  
  2442. ///////////////////////////////////////////////////////////////////////////////
  2443. //    MergeConfigProps()
  2444. //
  2445. //    Parameters
  2446. //      ulCfgProps      Number of properties for configuration
  2447. //      pCfgProps       Array of properties to configure the provider
  2448. //      pLogonProps     Array of properties found in the profile section of
  2449. //                      this service provider
  2450. //
  2451. //    Purpose
  2452. //      This function merges a property array that the user (or configuration
  2453. //      application) passed into ServiceEntry with the property array of
  2454. //      the provider, stored in the profile. This merged array is what
  2455. //      either gets passed into the configuration dialog (if UI is allowed)
  2456. //      and gets written out to the profile section for the service provider.
  2457. //
  2458. //    Return Value
  2459. //      An HRESULT
  2460. //
  2461. HRESULT WINAPI MergeConfigProps (ULONG                  ulCfgProps,
  2462.                                  LPSPropValue           pCfgProps,
  2463.                                  LPSPropValue           pLogonProps)
  2464. {
  2465.     while (ulCfgProps--)
  2466.     {
  2467.         // For the particular property found, set the proptag (in case
  2468.         // the one in the profile was not valid), and the value. The
  2469.         // value will be the value passed in the configuration prop array.
  2470.         switch (pCfgProps[ulCfgProps].ulPropTag)
  2471.         {
  2472.             case PR_SMP_REMOTE_SERVER :
  2473.                 if (FALSE == IsValidServerName (pCfgProps[ulCfgProps].Value.LPSZ))
  2474.                 {
  2475.                     return E_INVALIDARG;
  2476.                 }
  2477.                 pLogonProps[SERVER_NAME] = pCfgProps[ulCfgProps];
  2478.                 break;
  2479.             case PR_SMP_USER_NAME :
  2480.                 pLogonProps[USER_NAME] = pCfgProps[ulCfgProps];
  2481.                 break;
  2482.             case PR_SMP_MAILBOX_NAME :
  2483.                 pLogonProps[MAILBOX_NAME] = pCfgProps[ulCfgProps];
  2484.                 break;
  2485.             case PR_SMP_MAILBOX_ID :
  2486.                 pLogonProps[MAILBOX_ID] = pCfgProps[ulCfgProps];
  2487.                 break;
  2488.             case PR_SMP_MAILBOX_PASSWORD :
  2489.                 pLogonProps[PASSWORD] = pCfgProps[ulCfgProps];
  2490.                 break;
  2491.         }
  2492.     }
  2493.     return S_OK;
  2494. }
  2495.  
  2496. ///////////////////////////////////////////////////////////////////////////////
  2497. //    OpenServiceProfileSection()
  2498. //
  2499. //    Parameters
  2500. //      pSupObj         Pointer to the provider support object
  2501. //      ppProfSectObj   Where we return a pointer to the service profile
  2502. //                      section of the provider
  2503. //      pfnFreeBuffer   MAPI memory allocation function
  2504. //
  2505. //    Purpose
  2506. //      This function opens the profile section of this service, where the
  2507. //      properties of a WINDS provider (AB, MS, or XP) are stored.
  2508. //
  2509. //    Return Value
  2510. //      An HRESULT
  2511. //
  2512. HRESULT WINAPI OpenServiceProfileSection (LPMAPISUP    pSupObj,
  2513.                                           LPPROFSECT * ppProfSectObj,
  2514.                                           LPFREEBUFFER pfnFreeBuffer)
  2515. {
  2516.     SPropTagArray sptService = { 1, { PR_SERVICE_UID } };
  2517.     LPPROFSECT pProvProfSectObj;
  2518.     ULONG cValues;
  2519.     LPSPropValue pProp;
  2520.     // Get the PROVIDER profile section
  2521.     HRESULT hResult = pSupObj->OpenProfileSection (NULL,
  2522.                                                    MAPI_MODIFY,
  2523.                                                    &pProvProfSectObj);
  2524.     if (!hResult)
  2525.     {
  2526.         // Get the UID of the profile section of the service where this provider is installed
  2527.         hResult = pProvProfSectObj->GetProps (&sptService, fMapiUnicode, &cValues, &pProp);
  2528.         if (SUCCEEDED(hResult))
  2529.         {
  2530.             if (S_OK == hResult)
  2531.             {
  2532.                 // Now, with the obtained UID, open the profile section of the service
  2533.                 ASSERTMSG (PR_SERVICE_UID == pProp->ulPropTag, "Where is PR_SERVICE_UID");
  2534.                 hResult = pSupObj->OpenProfileSection ((LPMAPIUID)pProp->Value.bin.lpb,
  2535.                                                        MAPI_MODIFY,
  2536.                                                        ppProfSectObj);
  2537.             }
  2538.             else
  2539.             {
  2540.                 hResult = E_FAIL;
  2541.             }
  2542.             pfnFreeBuffer (pProp);
  2543.         }
  2544.         pProvProfSectObj->Release();
  2545.     }
  2546.     TraceResult ("OpenServiceProfileSection", hResult);
  2547.     return hResult;
  2548. }
  2549.  
  2550. ///////////////////////////////////////////////////////////////////////////////
  2551. //    PrivInitialize3DCtl()
  2552. //
  2553. //    Parameters
  2554. //      hInstance   Handle to the instance the control 3d library will
  2555. //                  subclass
  2556. //
  2557. //    Purpose
  2558. //      This function dynamically binds to the CTL3D library for UI apperance
  2559. //      on Windows NT. On Windows 95 the library may or may not be on the
  2560. //      system. We do this to have a single binary file that works on
  2561. //      Windows NT and Windows 95 and ensure that the WINDS service DLL loads
  2562. //      correctly in both platforms.
  2563. //      The CTL3D provider a less disparate user interface between the two OS's
  2564. //
  2565. //    Return Value
  2566. //      None
  2567. //
  2568. void WINAPI PrivInitialize3DCtl (HINSTANCE hInstance)
  2569. {
  2570.     if (NULL == ghUIControl)
  2571.     {
  2572.         ghUIControl = LoadLibrary (TEXT("CTL3D32.DLL"));
  2573.         if (ghUIControl)
  2574.         {
  2575.             pfn3DRegister = (LPCTL3DFUNCTION)GetProcAddress (ghUIControl, TEXT("Ctl3dRegister"));
  2576.             pfn3DUnregister = (LPCTL3DFUNCTION)GetProcAddress (ghUIControl, TEXT("Ctl3dUnregister"));
  2577.             pfn3DAutoSubclass = (LPCTL3DFUNCTION)GetProcAddress (ghUIControl, TEXT("Ctl3dAutoSubclass"));
  2578.             pfnDlgSubclassEx = (LPCTL3DSUBCLASS)GetProcAddress (ghUIControl, TEXT("Ctl3dSubclassDlgEx"));
  2579.             
  2580.             if (pfn3DRegister &&
  2581.                 pfn3DUnregister &&
  2582.                 pfn3DAutoSubclass &&
  2583.                 pfnDlgSubclassEx)
  2584.             {
  2585.                 pfn3DRegister (hInstance);
  2586.                 pfn3DAutoSubclass (hInstance);
  2587.             }
  2588.             else
  2589.             {
  2590.                 PrivUninitialize3DCtl (hInstance);
  2591.             }
  2592.         }
  2593.     }
  2594. }
  2595.  
  2596. ///////////////////////////////////////////////////////////////////////////////
  2597. //    PrivUninitialize3DCtl()
  2598. //
  2599. //    Parameters
  2600. //      hInstance   Handle to the instance the control 3d library will
  2601. //                  de-attach from.
  2602. //
  2603. //    Purpose
  2604. //      Unregister the 3D UI control stuff and unload the library of the
  2605. //      3D controls.
  2606. //
  2607. //    Return Value
  2608. //      None
  2609. //
  2610. void WINAPI PrivUninitialize3DCtl (HINSTANCE hInstance)
  2611. {
  2612.     if (ghUIControl)
  2613.     {
  2614.         if (pfn3DUnregister)
  2615.         {
  2616.             pfn3DUnregister (hInstance);
  2617.         }
  2618.         FreeLibrary (ghUIControl);
  2619.         ghUIControl = NULL;
  2620.         pfn3DRegister = NULL;
  2621.         pfn3DUnregister = NULL;
  2622.         pfn3DAutoSubclass = NULL;
  2623.         pfnDlgSubclassEx = NULL;
  2624.     }
  2625. }
  2626.  
  2627. ///////////////////////////////////////////////////////////////////////////////
  2628. //    CheckForPendingMessages()
  2629. //
  2630. //    Parameters
  2631. //      szServerName        Name of the server we are going to connect
  2632. //      szMailboxName       Name of the mailbox we are going to check
  2633. //      pulMsgWaiting       Number of messages waiting for download
  2634. //
  2635. //    Purpose
  2636. //      This function queries the remote server for how many messages are
  2637. //      waiting in the specified mailbox.
  2638. //      If there are not messages waiting, the function return S_FALSE.
  2639. //
  2640. //    Return Value
  2641. //      An HRESULT
  2642. //
  2643. HRESULT WINAPI CheckForPendingMessages (LPTSTR  szServerName,
  2644.                                         LPTSTR  szMailboxName,
  2645.                                         ULONG * pulMsgWaiting)
  2646. {
  2647.     HRESULT hResult = BindToServer (szServerName);
  2648.     if (hResult)
  2649.     {
  2650.         return hResult;
  2651.     }
  2652.     RpcTryExcept
  2653.     {
  2654.         hResult = RemoteCheckNewMail ((WINDS_RPC_STRING)szMailboxName, pulMsgWaiting);
  2655.     }
  2656.     RpcExcept(1)
  2657.     {
  2658.         // If we got here is because there was an error while call was made
  2659.         // or when it was about to be made.
  2660.         hResult = RpcExceptionCode();
  2661.         if (RPC_S_SERVER_UNAVAILABLE == hResult)
  2662.         {
  2663.             hResult = HRESULT_FROM_WIN32(ERROR_HOST_UNREACHABLE);
  2664.         }
  2665.         else
  2666.         {
  2667.             hResult = MAKE_HRESULT(1, FACILITY_RPC, hResult);
  2668.         }
  2669.     }
  2670.     RpcEndExcept
  2671.     #ifdef _DEBUG
  2672.     if (hResult && S_FALSE != hResult)
  2673.     {
  2674.         TraceResult ("CheckForPendingMessages", hResult);
  2675.     }
  2676.     #endif // _DEBUG
  2677.     return hResult;
  2678. }
  2679.  
  2680. ///////////////////////////////////////////////////////////////////////////////
  2681. //    GetNextMailboxMsg()
  2682. //
  2683. //    Parameters
  2684. //      szServerName        Name of the server we are going to connect
  2685. //      szMailboxName       Name of the mailbox we are going to get the
  2686. //                          messages from
  2687. //      szLocalMsgFile      Name of the local file where the message
  2688. //                          should be placed.
  2689. //
  2690. //    Purpose
  2691. //      This function connect to the server an request the next message to
  2692. //      be downloaded for the mailbox specified in call. If there are no
  2693. //      more messages to download, we return S_FALSE.
  2694. //
  2695. //    Return Value
  2696. //      An HRESULT
  2697. //
  2698. HRESULT WINAPI GetNextMailboxMsg (LPTSTR szServerName,
  2699.                                   LPTSTR szMailboxName,
  2700.                                   LPTSTR szLocalMsgFile)
  2701. {
  2702.     HRESULT hResult = BindToServer (szServerName);
  2703.     if (hResult)
  2704.     {
  2705.         return hResult;
  2706.     }
  2707.     long lPipeNumber;
  2708.     HANDLE hPipe, hFile;
  2709.     TCHAR szPipeName[64];
  2710.     BYTE abBuffer[IO_BUFFERSIZE];
  2711.     DWORD dwBytesRead, dwBytesWritten;
  2712.     RpcTryExcept
  2713.     {
  2714.         hResult = RemoteOpenOneMsgDownloadPipe ((WINDS_RPC_STRING)szMailboxName, &lPipeNumber);
  2715.         if (!hResult)
  2716.         {
  2717.             wsprintf (szPipeName, PIPE_NAME_FORMAT, szServerName, lPipeNumber);
  2718.             hPipe = CreateFile (szPipeName,
  2719.                                 GENERIC_READ,
  2720.                                 0,
  2721.                                 NULL,
  2722.                                 OPEN_EXISTING,
  2723.                                 0,
  2724.                                 NULL);
  2725.             if (INVALID_HANDLE_VALUE == hPipe)
  2726.             {
  2727.                 hResult = HRESULT_FROM_WIN32(GetLastError());
  2728.                 TraceResult ("GetHeadersFromServer: Failed to open pipe to server", hResult);
  2729.             }
  2730.             else
  2731.             {
  2732.                 hFile = CreateFile (szLocalMsgFile,
  2733.                                     GENERIC_WRITE,
  2734.                                     0,
  2735.                                     NULL,
  2736.                                     CREATE_ALWAYS,
  2737.                                     FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
  2738.                                     NULL);
  2739.                 if (INVALID_HANDLE_VALUE == hFile)
  2740.                 {
  2741.                     hResult = HRESULT_FROM_WIN32(GetLastError());
  2742.                     TraceResult ("GetNextMailboxMsg: Failed to open local headers file", hResult);
  2743.                 }
  2744.                 else
  2745.                 {
  2746.                     do
  2747.                     {
  2748.                         // Read the pipe handle.
  2749.                         if (!ReadFile (hPipe, abBuffer, IO_BUFFERSIZE, &dwBytesRead, NULL))
  2750.                         {
  2751.                             hResult = HRESULT_FROM_WIN32(GetLastError());
  2752.                             if (HRESULT_FROM_WIN32(ERROR_BROKEN_PIPE)   != hResult &&   // For Windows NT
  2753.                                 HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) != hResult)     // For Windows 95
  2754.                             {
  2755.                                 // There was an error and we can't continue
  2756.                                 TraceResult ("GetNextMailboxMsg: Failed to read from the pipe", hResult);
  2757.                             }
  2758.                             else
  2759.                             {
  2760.                                 // If the pipe was broken, it means the server finished writing
  2761.                                 // to the it, so we are finished reading from it.
  2762.                                 hResult = S_OK;
  2763.                             }
  2764.                         }
  2765.                         if (dwBytesRead)
  2766.                         {
  2767.                             if (!WriteFile (hFile, abBuffer, dwBytesRead, &dwBytesWritten, NULL))
  2768.                             {
  2769.                                 hResult = HRESULT_FROM_WIN32(GetLastError());
  2770.                                 TraceResult ("GetNextMailboxMsg: Failed to write to local header file", hResult);
  2771.                             }
  2772.                         }
  2773.                     } while (dwBytesRead && !hResult);
  2774.                     CloseHandle (hFile);
  2775.                 }
  2776.                 CloseHandle (hPipe);
  2777.             }
  2778.         }
  2779.     }
  2780.     RpcExcept(1)
  2781.     {
  2782.         // If we got here is because there was an error while call was made
  2783.         // or when it was about to be made.
  2784.         hResult = RpcExceptionCode();
  2785.         if (RPC_S_SERVER_UNAVAILABLE == hResult)
  2786.         {
  2787.             hResult = HRESULT_FROM_WIN32(ERROR_HOST_UNREACHABLE);
  2788.         }
  2789.         else
  2790.         {
  2791.             hResult = MAKE_HRESULT(1, FACILITY_RPC, hResult);
  2792.         }
  2793.     }
  2794.     RpcEndExcept
  2795.     #ifdef _DEBUG
  2796.     if (hResult && S_FALSE != hResult)
  2797.     {
  2798.         TraceResult ("GetNextMailboxMsg", hResult);
  2799.     }
  2800.     #endif // _DEBUG
  2801.     return hResult;
  2802. }
  2803.  
  2804. // End of file for COMWINDS.CPP
  2805.