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 / simple.cli / client.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-11  |  63.4 KB  |  2,525 lines

  1. /*
  2.  -  C L I E N T . C
  3.  -
  4.  *  Purpose:
  5.  *      Sample mail client for the MAPI 1.0 PDK.
  6.  *              Exclusively uses the Simple MAPI interface.
  7.  *
  8.  *  Copyright 1993-1995 Microsoft Corporation. All Rights Reserved.
  9.  */
  10.  
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include <windows.h>
  14. #include <commdlg.h>
  15. #include <mapiwin.h>
  16. #include <mapidbg.h>
  17. #include "client.h"
  18. #include "bitmap.h"
  19. #include "pvalloc.h"
  20.  
  21. HANDLE hInst;
  22. HINSTANCE hlibMAPI = 0;
  23.  
  24. LPMAPILOGON lpfnMAPILogon = NULL;
  25. LPMAPILOGOFF lpfnMAPILogoff = NULL;
  26. LPMAPISENDMAIL lpfnMAPISendMail = NULL;
  27. LPMAPISENDDOCUMENTS lpfnMAPISendDocuments = NULL;
  28. LPMAPIFINDNEXT lpfnMAPIFindNext = NULL;
  29. LPMAPIREADMAIL lpfnMAPIReadMail = NULL;
  30. LPMAPISAVEMAIL lpfnMAPISaveMail = NULL;
  31. LPMAPIDELETEMAIL lpfnMAPIDeleteMail = NULL;
  32. LPMAPIFREEBUFFER lpfnMAPIFreeBuffer = NULL;
  33. LPMAPIADDRESS lpfnMAPIAddress = NULL;
  34. LPMAPIDETAILS lpfnMAPIDetails = NULL;
  35. LPMAPIRESOLVENAME lpfnMAPIResolveName = NULL;
  36.  
  37. /* Static Data */
  38.  
  39. static BOOL fDialogIsActive = FALSE;
  40. static DWORD cUsers = 0;
  41. static ULONG flSendMsgFlags = 0;
  42. static LHANDLE lhSession = 0L;
  43. static HBITMAP hReadBmp = 0;
  44. static HBITMAP hReadABmp = 0;
  45. static HBITMAP hUnReadBmp = 0;
  46. static HBITMAP hUnReadABmp = 0;
  47. static HCURSOR hWaitCur;
  48. static LPMSGID lpReadMsgNode;
  49. static lpMapiMessage lpmsg = NULL;
  50.  
  51. #ifdef _WIN32
  52. #define szMAPIDLL       "MAPI32.DLL"
  53. #else
  54. #define szMAPIDLL       "MAPI.DLL"
  55. #endif
  56.  
  57. int WINAPI
  58. WinMain (HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpszCmd, int nCmdShow)
  59. {
  60.     MSG msg;
  61.  
  62.     if (!hPrevInst)
  63.     if (!InitApplication (hInstance))
  64.         return (FALSE);
  65.  
  66.     if (!InitInstance (hInstance, nCmdShow))
  67.     return (FALSE);
  68.  
  69.     while (GetMessage (&msg, 0, 0, 0))
  70.     {
  71.     TranslateMessage (&msg);
  72.     DispatchMessage (&msg);
  73.     }
  74.  
  75.     DeinitApplication ();
  76.  
  77.     return (msg.wParam);
  78. }
  79.  
  80. /*
  81.  -  InitApplication
  82.  -
  83.  *  Purpose:
  84.  *      Initialize the application.
  85.  *
  86.  *  Parameters:
  87.  *      hInstance   - Instance handle
  88.  *
  89.  *  Returns:
  90.  *      True/False
  91.  *
  92.  */
  93.  
  94. BOOL
  95. InitApplication (HANDLE hInstance)
  96. {
  97.     WNDCLASS wc;
  98.  
  99.     wc.style = 0;
  100.     wc.lpfnWndProc = MainWndProc;
  101.     wc.cbClsExtra = 0;
  102.     wc.cbWndExtra = 0;
  103.     wc.hInstance = hInstance;
  104.     wc.hIcon = LoadIcon (hInstance, "NoMail");
  105.     wc.hCursor = LoadCursor (0, IDC_ARROW);
  106.     wc.hbrBackground = GetStockObject (WHITE_BRUSH);
  107.     wc.lpszMenuName = "MailMenu";
  108.     wc.lpszClassName = "Client";
  109.  
  110.     return (RegisterClass (&wc));
  111. }
  112.  
  113. /*
  114.  -  InitInstance
  115.  -
  116.  *  Purpose:
  117.  *      Initialize this instance.
  118.  *
  119.  *  Parameters:
  120.  *      hInstance   - Instance handle
  121.  *      nCmdShow    - Do we show the window?
  122.  *
  123.  *  Returns:
  124.  *      True/False
  125.  *
  126.  */
  127.  
  128. BOOL
  129. InitInstance (HANDLE hInstance, int nCmdShow)
  130. {
  131.     HWND hWnd;
  132.     BOOL fInit;
  133.     ULONG ulResult;
  134.  
  135.     hInst = hInstance;
  136.  
  137.     hWnd = CreateWindow ("Client", "MAPI Sample Mail Client",
  138.         WS_OVERLAPPEDWINDOW, 5, 5, 300, 75, 0, 0, hInst, NULL);
  139.  
  140.     if (!hWnd)
  141.     return (FALSE);
  142.  
  143.     ShowWindow (hWnd, nCmdShow);
  144.     UpdateWindow (hWnd);
  145.  
  146.     hWaitCur = LoadCursor(0, IDC_WAIT);
  147.  
  148.     if (fInit = InitSimpleMAPI ())
  149.     {
  150.     
  151.         /* MAPILogon might yield control to Windows. So to prevent the user
  152.         from clicking "logon" while we are in the process of loggin on we
  153.         have to disable it*/
  154.         SecureMenu(hWnd, TRUE);
  155.         
  156.         if ((ulResult = MAPILogon ((ULONG) hWnd, NULL, NULL,
  157.             MAPI_LOGON_UI | MAPI_NEW_SESSION,
  158.             0, &lhSession)) == SUCCESS_SUCCESS)
  159.         {
  160.             ToggleMenuState (hWnd, TRUE);
  161.         }
  162.         else
  163.         {
  164.             SecureMenu(hWnd, FALSE);
  165.             lhSession = 0;
  166.             MakeMessageBox (hWnd, ulResult, IDS_LOGONFAIL, MBS_ERROR);
  167.         }
  168.     }
  169.  
  170.     return (fInit);
  171. }
  172.  
  173. /*
  174.  -  InitSimpleMAPI
  175.  -
  176.  *  Purpose:
  177.  *      Loads the DLL containing the simple MAPI functions and sets
  178.  *      up a pointer to each. Wrappers for the  function pointers
  179.  *      are declared in SMAPI.H.
  180.  *
  181.  *  Returns:
  182.  *      TRUE if sucessful, else FALSE
  183.  *
  184.  *  Side effects:
  185.  *      Loads a DLL and sets up function pointers
  186.  */
  187. BOOL
  188. InitSimpleMAPI (void)
  189. {
  190.     UINT fuError;
  191.  
  192.     /*
  193.      *Check if MAPI is installed on the system
  194.      */
  195.     if(!fSMAPIInstalled())
  196.         return FALSE;
  197.  
  198.     fuError = SetErrorMode(SEM_NOOPENFILEERRORBOX);
  199.     hlibMAPI = LoadLibrary(szMAPIDLL);
  200.     SetErrorMode(fuError);
  201.  
  202. #ifdef _WIN32
  203.     if (!hlibMAPI)
  204. #else
  205.     if (hlibMAPI < 32)
  206. #endif
  207.     return (FALSE);
  208.  
  209.     if (!(lpfnMAPILogon = (LPMAPILOGON) GetProcAddress (hlibMAPI, "MAPILogon")))
  210.     return (FALSE);
  211.     if (!(lpfnMAPILogoff = (LPMAPILOGOFF) GetProcAddress (hlibMAPI, "MAPILogoff")))
  212.     return (FALSE);
  213.     if (!(lpfnMAPISendMail = (LPMAPISENDMAIL) GetProcAddress (hlibMAPI, "MAPISendMail")))
  214.     return (FALSE);
  215.     if (!(lpfnMAPISendDocuments = (LPMAPISENDDOCUMENTS) GetProcAddress (hlibMAPI, "MAPISendDocuments")))
  216.     return (FALSE);
  217.     if (!(lpfnMAPIFindNext = (LPMAPIFINDNEXT) GetProcAddress (hlibMAPI, "MAPIFindNext")))
  218.     return (FALSE);
  219.     if (!(lpfnMAPIReadMail = (LPMAPIREADMAIL) GetProcAddress (hlibMAPI, "MAPIReadMail")))
  220.     return (FALSE);
  221.     if (!(lpfnMAPISaveMail = (LPMAPISAVEMAIL) GetProcAddress (hlibMAPI, "MAPISaveMail")))
  222.     return (FALSE);
  223.     if (!(lpfnMAPIDeleteMail = (LPMAPIDELETEMAIL) GetProcAddress (hlibMAPI, "MAPIDeleteMail")))
  224.     return (FALSE);
  225.     if (!(lpfnMAPIFreeBuffer = (LPMAPIFREEBUFFER) GetProcAddress (hlibMAPI, "MAPIFreeBuffer")))
  226.     return (FALSE);
  227.     if (!(lpfnMAPIAddress = (LPMAPIADDRESS) GetProcAddress (hlibMAPI, "MAPIAddress")))
  228.     return (FALSE);
  229.     if (!(lpfnMAPIDetails = (LPMAPIDETAILS) GetProcAddress (hlibMAPI, "MAPIDetails")))
  230.     return (FALSE);
  231.     if (!(lpfnMAPIResolveName = (LPMAPIRESOLVENAME) GetProcAddress (hlibMAPI, "MAPIResolveName")))
  232.     return (FALSE);
  233.  
  234.     return (TRUE);
  235. }
  236.  
  237. /*
  238.  -  fSMAPIInstalled
  239.  -
  240.  *  Purpose:
  241.  *      Checks the appropriate win.ini/registry value to see if Simple MAPI is
  242.  *      installed in the system. 
  243.  *  
  244.  *  Returns:
  245.  *      TRUE if Simple MAPI is installed, else FALSE
  246.  *
  247.  */
  248. BOOL
  249. fSMAPIInstalled(void)
  250. {
  251. #ifdef _WIN32
  252.     /* on win32, if it's NT 3.51 or lower the value to check is 
  253.         win.ini \ [Mail] \ MAPI, otherwise it's a registry value
  254.         HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Messaging Subsystem\MAPI
  255.     */
  256.     
  257.     OSVERSIONINFO osvinfo;
  258.     LONG lr;
  259.     HKEY hkWMS;
  260.     
  261.     #define MAPIVSize 8
  262.     char szMAPIValue[MAPIVSize];
  263.     DWORD dwType;
  264.     DWORD cbMAPIValue = MAPIVSize;
  265.  
  266.     osvinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  267.  
  268.     if(!GetVersionEx(&osvinfo))
  269.         return FALSE;
  270.  
  271.     if( osvinfo.dwMajorVersion > 3 ||
  272.         (osvinfo.dwMajorVersion == 3 && osvinfo.dwMinorVersion > 51))
  273.     { //check the registry value
  274.         lr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  275.                         "SOFTWARE\\Microsoft\\Windows Messaging Subsystem",
  276.                          0, KEY_READ, &hkWMS);
  277.         if(ERROR_SUCCESS == lr)
  278.         {
  279.             lr = RegQueryValueEx(hkWMS, "MAPI", 0, &dwType, szMAPIValue, &cbMAPIValue);
  280.             RegCloseKey(hkWMS);
  281.             if(ERROR_SUCCESS == lr)
  282.             {
  283.                 Assert(dwType == REG_SZ);
  284.                 if(lstrcmp(szMAPIValue, "1") == 0)
  285.                     return TRUE;
  286.             }
  287.         }
  288.         
  289.         return FALSE;
  290.     }
  291.  
  292.     /* fall through*/
  293. #endif /*_WIN32*/
  294.     
  295.     /*check the win.ini value*/
  296.     return GetProfileInt("Mail", "MAPI", 0);
  297.     
  298. }
  299.  
  300.  
  301. void
  302. DeinitApplication ()
  303. {
  304.     DeinitSimpleMAPI ();
  305. }
  306.  
  307. void
  308. DeinitSimpleMAPI ()
  309. {
  310.     if (hlibMAPI)
  311.     {
  312.     FreeLibrary (hlibMAPI);
  313.     hlibMAPI = 0;
  314.     }
  315. }
  316.  
  317. /*
  318.  -  MainWndProc
  319.  -
  320.  *  Purpose:
  321.  *      Main Window Procedure for test program.
  322.  *
  323.  *  Parameters:
  324.  *      hWnd
  325.  *      message
  326.  *      wParam
  327.  *      lParam
  328.  *
  329.  *  Returns:
  330.  *
  331.  *
  332.  */
  333.  
  334. LONG FAR PASCAL
  335. MainWndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  336. {
  337.     ULONG ulResult;
  338.  
  339.     switch (msg)
  340.     {
  341.     case WM_COMMAND:
  342.     switch (LOWORD (wParam))
  343.     {
  344.     case IDM_LOGON:
  345.         if (!lhSession)
  346.         {
  347.         /* MAPILogon might yield control to Windows. So to prevent the user
  348.         from clicking "logon" while we are in the process of loggin on we
  349.         have to disable it*/
  350.         SecureMenu(hWnd, TRUE);
  351.  
  352.         if ((ulResult = MAPILogon ((ULONG) hWnd, NULL, NULL,
  353.                 MAPI_LOGON_UI | MAPI_NEW_SESSION,
  354.                 0, &lhSession)) == SUCCESS_SUCCESS)
  355.         {
  356.             ToggleMenuState (hWnd, TRUE);
  357.         }
  358.         else
  359.         {
  360.             SecureMenu(hWnd, FALSE);
  361.             lhSession = 0;
  362.             MakeMessageBox (hWnd, ulResult, IDS_LOGONFAIL, MBS_ERROR);
  363.         }
  364.         }
  365.         break;
  366.  
  367.     case IDM_LOGOFF:
  368.         if (lhSession)
  369.         {
  370.         MAPILogoff (lhSession, (ULONG) hWnd, 0, 0);
  371.         ToggleMenuState (hWnd, FALSE);
  372.         lhSession = 0;
  373.         }
  374.         break;
  375.  
  376.     case IDM_COMPOSE:
  377.             fDialogIsActive = TRUE; 
  378.         DialogBox (hInst, "ComposeNote", hWnd, ComposeDlgProc);
  379.             fDialogIsActive = FALSE;        
  380.         break;
  381.  
  382.     case IDM_READ:
  383.             fDialogIsActive = TRUE; 
  384.         DialogBox (hInst, "InBox", hWnd, InBoxDlgProc);
  385.             fDialogIsActive = FALSE;        
  386.         break;
  387.  
  388.     case IDM_SEND:
  389.         if(lhSession)
  390.             {
  391.                 MapiMessage msgSend;
  392.  
  393.                 memset(&msgSend, 0, sizeof(MapiMessage));
  394.                 fDialogIsActive = TRUE; 
  395.                 MAPISendMail(lhSession, (ULONG)hWnd, &msgSend, MAPI_DIALOG, 0L);
  396.                 fDialogIsActive = FALSE;        
  397.             }
  398.         break;
  399.  
  400.     case IDM_ADDRBOOK:
  401.         if (lhSession)
  402.         {
  403.                 fDialogIsActive = TRUE; 
  404.         if ((ulResult = MAPIAddress (lhSession, (ULONG) hWnd,
  405.                 NULL, 0, NULL, 0, NULL, 0, 0, NULL, NULL)))
  406.         {
  407.             if (ulResult != MAPI_E_USER_ABORT)
  408.             MakeMessageBox (hWnd, ulResult, IDS_ADDRBOOKFAIL, MBS_ERROR);
  409.         }
  410.                 fDialogIsActive = FALSE;        
  411.         }
  412.         break;
  413.  
  414.     case IDM_DETAILS:
  415.         if (lhSession)
  416.             {
  417.                 fDialogIsActive = TRUE; 
  418.         DialogBox(hInst, "Details", hWnd, DetailsDlgProc);
  419.                 fDialogIsActive = FALSE;        
  420.             }
  421.         break;
  422.  
  423.     case IDM_ABOUT:
  424.             fDialogIsActive = TRUE; 
  425.         DialogBox (hInst, "AboutBox", hWnd, AboutDlgProc);
  426.             fDialogIsActive = FALSE;        
  427.         break;
  428.  
  429.     case IDM_EXIT:
  430.         if (lhSession)
  431.         MAPILogoff (lhSession, (ULONG) hWnd, 0, 0);
  432.  
  433.         PostQuitMessage (0);
  434.         break;
  435.  
  436.     default:
  437.         return (DefWindowProc (hWnd, msg, wParam, lParam));
  438.     }
  439.     break;
  440.  
  441.     case WM_QUERYENDSESSION:
  442.     {       
  443.  
  444.         /*
  445.          *      If we have a modal dialog open (all our dialogs are modal, so
  446.          *      just see if we have a dialog open), veto the shutdown.
  447.          */
  448.  
  449.         if (fDialogIsActive)
  450.         {
  451.             LPCSTR szTitle = "MAPI Sample Mail Client"; 
  452.             char szText[256]; 
  453.  
  454.         LoadString (hInst, IDS_DIALOGACTIVE, szText, 255);
  455.  
  456.         #ifdef WIN16
  457.             MessageBox((HWND)NULL, szText, szTitle, MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL);
  458.         #else
  459.             MessageBoxA(NULL, szText, szTitle, MB_OK | MB_ICONSTOP | MB_TASKMODAL | MB_SETFOREGROUND);
  460.         #endif
  461.         return FALSE;
  462.         }
  463.  
  464.         else
  465.         {
  466.         return TRUE;
  467.         }
  468.     }
  469.  
  470.     case WM_ENDSESSION:
  471.  
  472.         if (wParam)
  473.         {
  474.         DestroyWindow (hWnd);
  475.         }
  476.  
  477.     break;
  478.  
  479.     case WM_CLOSE:
  480.     case WM_DESTROY:
  481.     if (lhSession)
  482.         MAPILogoff (lhSession, (ULONG) hWnd, 0, 0);
  483.  
  484.     PostQuitMessage (0);
  485.     break;
  486.  
  487.     default:
  488.     return (DefWindowProc (hWnd, msg, wParam, lParam));
  489.     }
  490.     return FALSE;
  491. }
  492.  
  493. /*
  494.  -  AboutDlgProc
  495.  -
  496.  *  Purpose:
  497.  *      About box dialog procedure
  498.  *
  499.  *  Parameters:
  500.  *      hDlg
  501.  *      message
  502.  *      wParam
  503.  *      lParam
  504.  *
  505.  *  Returns:
  506.  *      True/False
  507.  *
  508.  */
  509.  
  510. BOOL FAR PASCAL
  511. AboutDlgProc (HWND hDlg, UINT msg, UINT wParam, LONG lParam)
  512. {
  513.  
  514. #include <pdkver.h>
  515.  
  516.     char    rgchVersion[80];
  517.  
  518.     switch (msg)
  519.     {
  520.     case WM_INITDIALOG:
  521.         wsprintf(rgchVersion, "Version %d.%d.%d (%s)", rmj, rmm, rup,
  522.             szVerName && *szVerName ? szVerName : "BUDDY");
  523.         SetDlgItemText(hDlg, IDC_VERSION, rgchVersion);
  524.     return TRUE;
  525.  
  526.     case WM_COMMAND:
  527.     if (wParam == IDOK || wParam == IDCANCEL)
  528.     {
  529.         EndDialog (hDlg, TRUE);
  530.         return TRUE;
  531.     }
  532.     break;
  533.     }
  534.     return FALSE;
  535. }
  536.  
  537. /*
  538.  -  OptionsDlgProc
  539.  -
  540.  *  Purpose:
  541.  *      Message Options dialog procedure
  542.  *
  543.  *  Parameters:
  544.  *      hDlg
  545.  *      message
  546.  *      wParam
  547.  *      lParam
  548.  *
  549.  *  Returns:
  550.  *      True/False
  551.  *
  552.  */
  553.  
  554. BOOL FAR PASCAL
  555. OptionsDlgProc (HWND hDlg, UINT msg, UINT wParam, LONG lParam)
  556. {
  557.     switch (msg)
  558.     {
  559.     case WM_INITDIALOG:
  560.     CheckDlgButton (hDlg, IDC_RETURN,
  561.         !!(flSendMsgFlags & MAPI_RECEIPT_REQUESTED));
  562.     return TRUE;
  563.  
  564.     case WM_COMMAND:
  565.     switch (LOWORD (wParam))
  566.     {
  567.     case IDOK:
  568.         if (IsDlgButtonChecked (hDlg, IDC_RETURN))
  569.         flSendMsgFlags |= MAPI_RECEIPT_REQUESTED;
  570.         else
  571.         flSendMsgFlags &= ~MAPI_RECEIPT_REQUESTED;
  572.  
  573.     case IDCANCEL:
  574.         EndDialog (hDlg, TRUE);
  575.         return TRUE;
  576.     }
  577.     break;
  578.     }
  579.     return FALSE;
  580. }
  581.  
  582. /*
  583.  -  DetailsDlgProc
  584.  -
  585.  *  Purpose:
  586.  *      User Details dialog procedure
  587.  *
  588.  *  Parameters:
  589.  *      hDlg
  590.  *      message
  591.  *      wParam
  592.  *      lParam
  593.  *
  594.  *  Returns:
  595.  *      True/False
  596.  *
  597.  */
  598.  
  599. BOOL FAR PASCAL
  600. DetailsDlgProc (HWND hDlg, UINT msg, UINT wParam, LONG lParam)
  601. {
  602.     LPSTR lpszType = NULL;
  603.     LPSTR lpszAddr = NULL;
  604.     LPSTR lpszName;
  605.     ULONG cRecips;
  606.     ULONG ulResult;
  607.     lpMapiRecipDesc lpRecip = NULL;
  608.  
  609.     switch (msg)
  610.     {
  611.     case WM_INITDIALOG:
  612.     while(!lpRecip)
  613.     {
  614.         if ((ulResult = MAPIAddress (lhSession, (ULONG) hDlg,
  615.             "Select One User", 1, "User:", 0, NULL, 0, 0,
  616.             &cRecips, &lpRecip)))
  617.         {
  618.         if (ulResult != MAPI_E_USER_ABORT)
  619.             MakeMessageBox (hDlg, ulResult, IDS_ADDRBOOKFAIL, MBS_ERROR);
  620.  
  621.         EndDialog (hDlg, TRUE);
  622.         return TRUE;
  623.         }
  624.  
  625.         if (cRecips == 0)
  626.         {
  627.         EndDialog (hDlg, TRUE);
  628.         return TRUE;
  629.         }
  630.  
  631.         if (cRecips > 1)
  632.         {
  633.         cRecips = 0;
  634.         MAPIFreeBuffer (lpRecip);
  635.         lpRecip = NULL;
  636.         MakeMessageBox (hDlg, 0, IDS_DETAILS_TOO_MANY, MBS_OOPS);
  637.         }
  638.     }
  639.     lpszName = lpRecip->lpszName;
  640.     if(lpRecip->lpszAddress)
  641.     {
  642.         lpszType = strtok(lpRecip->lpszAddress, ":");
  643.         lpszAddr = strtok(NULL, "\n");
  644.     }
  645.  
  646.     SetDlgItemText(hDlg, IDC_NAME, lpszName);
  647.     SetDlgItemText(hDlg, IDC_TYPE, (lpszType ? lpszType : "MSPEER"));
  648.     SetDlgItemText(hDlg, IDC_ADDR, (lpszAddr ? lpszAddr : ""));
  649.  
  650.     MAPIFreeBuffer (lpRecip);
  651.     return TRUE;
  652.  
  653.     case WM_COMMAND:
  654.     if(LOWORD(wParam) == IDC_CLOSE || LOWORD(wParam) ==IDCANCEL)
  655.     {
  656.         EndDialog (hDlg, TRUE);
  657.         return TRUE;
  658.     }
  659.     break;
  660.     }
  661.     return FALSE;
  662. }
  663.  
  664. /*
  665.  -  ComposeDlgProc
  666.  -
  667.  *  Purpose:
  668.  *      Dialog procedure for the ComposeNote dialog.
  669.  *
  670.  *  Parameters:
  671.  *      hDlg
  672.  *      message
  673.  *      wParam
  674.  *      lParam
  675.  *
  676.  *  Returns:
  677.  *      True/False
  678.  *
  679.  */
  680.  
  681. BOOL FAR PASCAL
  682. ComposeDlgProc (HWND hDlg, UINT msg, UINT wParam, LONG lParam)
  683. {
  684.     char szUnResNames[TO_EDIT_MAX];
  685.     char szDisplayNames[TO_EDIT_MAX];
  686.    /* char szAttach[FILE_ATTACH_MAX];*/
  687.     BOOL fUnResTo, fUnResCc;
  688.     LONG cb, cLines;
  689.     ULONG ulResult;
  690.     HCURSOR hOldCur;
  691.     static LPSTR lpszSubject;
  692.     static LPSTR lpszNoteText;
  693.     static ULONG cRecips;
  694.     static ULONG cNewRecips;
  695.     static ULONG cAttach;
  696.     static lpMapiRecipDesc lpRecips;
  697.     static lpMapiRecipDesc lpNewRecips;
  698.     static lpMapiFileDesc lpAttach;
  699.     ULONG idx;
  700.  
  701.     switch (msg)
  702.     {
  703.     case WM_INITDIALOG:
  704.     if (lpmsg)
  705.     {
  706.         /* ComposeNote is being called to either forward or reply */
  707.         /* to a message in the Inbox.  So, we'll initialize the   */
  708.         /* ComposeNote form with data from the global MapiMessage */
  709.  
  710.         lpszSubject = lpmsg->lpszSubject;
  711.         lpszNoteText = lpmsg->lpszNoteText;
  712.         cRecips = lpmsg->nRecipCount;
  713.         cAttach = lpmsg->nFileCount;
  714.         lpRecips = lpmsg->lpRecips;
  715.         lpAttach = lpmsg->lpFiles;
  716.  
  717.         if (cRecips)
  718.         {
  719.         MakeDisplayNameStr (szDisplayNames, MAPI_TO,
  720.             cRecips, lpRecips);
  721.         if (*szDisplayNames)
  722.             SetDlgItemText (hDlg, IDC_TO, szDisplayNames);
  723.  
  724.         MakeDisplayNameStr (szDisplayNames, MAPI_CC,
  725.             cRecips, lpRecips);
  726.         if (*szDisplayNames)
  727.             SetDlgItemText (hDlg, IDC_CC, szDisplayNames);
  728.         }
  729.         SetDlgItemText (hDlg, IDC_SUBJECT, lpmsg->lpszSubject);
  730.         SetDlgItemText (hDlg, IDC_NOTE, lpmsg->lpszNoteText);
  731.         if (!cAttach)
  732.         {
  733.             EnableWindow (GetDlgItem (hDlg, IDC_CATTACHMENT), FALSE);
  734.         EnableWindow (GetDlgItem (hDlg, IDT_CATTACHMENT), FALSE);
  735.         }
  736.         else
  737.         {
  738.             for(idx = 0; idx < cAttach; idx++)
  739.             if (lpAttach[idx].lpszFileName)
  740.                 SendDlgItemMessage(hDlg, IDC_CATTACHMENT, LB_ADDSTRING, 0,
  741.                 (LPARAM)lpAttach[idx].lpszFileName);
  742.  
  743.            /*SendDlgItemMessage(hDlg, IDC_CATTACHMENT, LB_SETCURSEL, 0, 0L);*/
  744.         }
  745.  
  746.         SendDlgItemMessage (hDlg, IDC_TO, EM_SETMODIFY, FALSE, 0);
  747.         SendDlgItemMessage (hDlg, IDC_CC, EM_SETMODIFY, FALSE, 0);
  748.         SendDlgItemMessage (hDlg, IDC_SUBJECT, EM_SETMODIFY, FALSE, 0);
  749.         SendDlgItemMessage (hDlg, IDC_NOTE, EM_SETMODIFY, FALSE, 0);
  750.         if(cRecips)
  751.         SetFocus (GetDlgItem (hDlg, IDC_NOTE));
  752.         else
  753.         SetFocus (GetDlgItem (hDlg, IDC_TO));
  754.     }
  755.     else
  756.     {
  757.         lpmsg = (lpMapiMessage)PvAlloc(sizeof(MapiMessage));
  758.  
  759.         if (!lpmsg)
  760.         goto cleanup;
  761.  
  762.             memset (lpmsg, 0, sizeof (MapiMessage));
  763.  
  764.         lpszSubject = NULL;
  765.         lpszNoteText = NULL;
  766.         cRecips = 0;
  767.         cAttach = 0;
  768.         lpRecips = NULL;
  769.         lpNewRecips = NULL;
  770.         lpAttach = NULL;
  771.  
  772.         lpmsg->flFlags = flSendMsgFlags;
  773.         SetFocus (GetDlgItem (hDlg, IDC_TO));
  774.     }
  775.     return FALSE;
  776.  
  777.     case WM_COMMAND:
  778.     switch (LOWORD (wParam))
  779.     {
  780.     case IDC_ATTACH:
  781.         if (GetNextFile (hDlg, (ULONG) -1, &cAttach, &lpAttach) == SUCCESS_SUCCESS)
  782.         {
  783.                 /* if the first attachment */
  784.                 if (cAttach == 1)
  785.                 {
  786.                     EnableWindow (GetDlgItem (hDlg, IDC_CATTACHMENT), TRUE);
  787.             EnableWindow (GetDlgItem (hDlg, IDT_CATTACHMENT), TRUE);
  788.                 }
  789.  
  790.                 if (lpAttach[cAttach - 1].lpszFileName)
  791.             SendDlgItemMessage(hDlg, IDC_CATTACHMENT, LB_ADDSTRING, 0,
  792.             (LPARAM)lpAttach[cAttach -1].lpszFileName);
  793.  
  794.              /* Now, send a little render message to the NoteText edit */
  795.  
  796.         /*wsprintf (szAttach, "<<File: %s>>",
  797.             lpAttach[cAttach - 1].lpszFileName);
  798.  
  799.         SendDlgItemMessage (hDlg, IDC_NOTE, EM_REPLACESEL, 0,
  800.             (LPARAM) ((LPSTR) szAttach));*/
  801.         }
  802.         break;
  803.  
  804.     case IDC_ADDRBOOK:
  805.             SendMessage(hDlg, WM_COMMAND, MAKELONG(IDC_RESOLVE,0), 0);
  806.         ulResult = MAPIAddress (lhSession, (ULONG) hDlg, NULL,
  807.         2, NULL, cRecips, lpRecips, 0, 0,
  808.         &cNewRecips, &lpNewRecips);
  809.         if (ulResult)
  810.         {
  811.         if (ulResult != MAPI_E_USER_ABORT)
  812.             MakeMessageBox (hDlg, ulResult, IDS_ADDRBOOKFAIL, MBS_ERROR);
  813.         }
  814.         else
  815.         {
  816.         if (cNewRecips)
  817.         {
  818.             PvFree(lpRecips);
  819.             lpRecips = (lpMapiRecipDesc)PvAlloc(cNewRecips*sizeof(MapiRecipDesc));
  820.             cRecips = cNewRecips;
  821.  
  822.                     while(cNewRecips--)
  823.                         CopyRecipient(lpRecips, &lpRecips[cNewRecips],
  824.                                 &lpNewRecips[cNewRecips]);
  825.  
  826.             MAPIFreeBuffer(lpNewRecips);
  827.             lpNewRecips = NULL;
  828.             cNewRecips = 0;
  829.  
  830.             MakeDisplayNameStr (szDisplayNames, MAPI_TO,
  831.             cRecips, lpRecips);
  832.             if (*szDisplayNames)
  833.             SetDlgItemText (hDlg, IDC_TO, szDisplayNames);
  834.  
  835.             MakeDisplayNameStr (szDisplayNames, MAPI_CC,
  836.             cRecips, lpRecips);
  837.             if (*szDisplayNames)
  838.             SetDlgItemText (hDlg, IDC_CC, szDisplayNames);
  839.  
  840.             SendDlgItemMessage (hDlg, IDC_TO, EM_SETMODIFY, FALSE, 0);
  841.             SendDlgItemMessage (hDlg, IDC_CC, EM_SETMODIFY, FALSE, 0);
  842.         }
  843.         }
  844.         break;
  845.  
  846.     case IDC_OPTIONS:
  847.         DialogBox (hInst, "Options", hDlg, OptionsDlgProc);
  848.         break;
  849.  
  850.     case IDC_SEND:
  851.     case IDC_RESOLVE:
  852.         fUnResTo = FALSE;
  853.         fUnResCc = FALSE;
  854.  
  855.         hOldCur = SetCursor(hWaitCur);
  856.  
  857.         
  858.         /* Get the names from the To: field and resolve them first */
  859.  
  860.         /*if (SendDlgItemMessage (hDlg, IDC_TO, EM_GETMODIFY, 0, 0) && */
  861.          if (cb = SendDlgItemMessage (hDlg, IDC_TO, WM_GETTEXT,
  862.             (WPARAM)sizeof(szUnResNames), (LPARAM)szUnResNames))
  863.         {
  864.         if (!ResolveFriendlyNames (hDlg, szUnResNames, MAPI_TO,
  865.             &cRecips, &lpRecips))
  866.         {
  867.             MakeDisplayNameStr (szDisplayNames, MAPI_TO,
  868.             cRecips, lpRecips);
  869.             if (*szDisplayNames)
  870.             {
  871.             if (*szUnResNames)
  872.             {
  873.                 lstrcat (szDisplayNames, "; ");
  874.                 lstrcat (szDisplayNames, szUnResNames);
  875.                 fUnResTo = TRUE;
  876.             }
  877.  
  878.             SetDlgItemText (hDlg, IDC_TO, szDisplayNames);
  879.             }
  880.             else
  881.             {
  882.             if (*szUnResNames)
  883.             {
  884.                 SetDlgItemText (hDlg, IDC_TO, szUnResNames);
  885.                 fUnResTo = TRUE;
  886.             }
  887.             }
  888.         }
  889.         /*SendDlgItemMessage (hDlg, IDC_TO, EM_SETMODIFY, FALSE, 0);*/
  890.         }
  891.  
  892.         /* Now, get the names from the Cc: field and resolve them */
  893.  
  894.         /*if (SendDlgItemMessage (hDlg, IDC_CC, EM_GETMODIFY, 0, 0) &&*/
  895.         if (cb = SendDlgItemMessage (hDlg, IDC_CC, WM_GETTEXT,
  896.             (WPARAM)sizeof(szUnResNames), (LPARAM)szUnResNames))
  897.         {
  898.         if (!ResolveFriendlyNames (hDlg, szUnResNames, MAPI_CC,
  899.             &cRecips, &lpRecips))
  900.         {
  901.             MakeDisplayNameStr (szDisplayNames, MAPI_CC,
  902.             cRecips, lpRecips);
  903.             if (*szDisplayNames)
  904.             {
  905.             if (*szUnResNames)
  906.             {
  907.                 lstrcat (szDisplayNames, "; ");
  908.                 lstrcat (szDisplayNames, szUnResNames);
  909.                 fUnResCc = TRUE;
  910.             }
  911.  
  912.             SetDlgItemText (hDlg, IDC_CC, szDisplayNames);
  913.             }
  914.             else
  915.             {
  916.             if (*szUnResNames)
  917.             {
  918.                 SetDlgItemText (hDlg, IDC_CC, szUnResNames);
  919.                 fUnResCc = TRUE;
  920.             }
  921.             }
  922.         }
  923.         /*SendDlgItemMessage (hDlg, IDC_CC, EM_SETMODIFY, FALSE, 0);*/
  924.         }
  925.  
  926.         /* If we were just Resolving Names then we can leave now */
  927.  
  928.         if (LOWORD (wParam) == IDC_RESOLVE)
  929.         {
  930.         SetCursor(hOldCur);
  931.         break;
  932.         }
  933.  
  934.         if (cRecips == 0 || fUnResTo || fUnResCc)
  935.         {
  936.         if (!cRecips)
  937.             MakeMessageBox (hDlg, 0, IDS_NORECIPS, MBS_OOPS);
  938.  
  939.         if (fUnResTo)
  940.             SetFocus (GetDlgItem (hDlg, IDC_TO));
  941.         else if (fUnResCc)
  942.             SetFocus (GetDlgItem (hDlg, IDC_CC));
  943.         else
  944.             SetFocus (GetDlgItem (hDlg, IDC_TO));
  945.  
  946.         SetCursor(hOldCur);
  947.         break;
  948.         }
  949.  
  950.         /* Everything is OK so far, lets get the Subject */
  951.         /* and the NoteText and try to send the message. */
  952.  
  953.         /* Get Subject from Edit */
  954.  
  955.         if (SendDlgItemMessage (hDlg, IDC_SUBJECT, EM_GETMODIFY, 0, 0))
  956.         {
  957.         cb = SendDlgItemMessage (hDlg, IDC_SUBJECT, EM_LINELENGTH, 0, 0L);
  958.  
  959.         PvFree(lpszSubject);
  960.         lpszSubject = (LPTSTR)PvAlloc(cb + 1);
  961.  
  962.         if (!lpszSubject)
  963.             goto cleanup;
  964.  
  965.         GetDlgItemText (hDlg, IDC_SUBJECT, lpszSubject, (int)cb+1);
  966.         }
  967.  
  968.         /* Get the NoteText from Edit */
  969.  
  970.         if (SendDlgItemMessage (hDlg, IDC_NOTE, EM_GETMODIFY, 0, 0))
  971.         {
  972.         cLines = SendDlgItemMessage (hDlg, IDC_NOTE,
  973.             EM_GETLINECOUNT, 0, 0L);
  974.  
  975.         if (cLines)
  976.         {
  977.             /* Get the total number of bytes in the multi-line */
  978.  
  979.             cb = SendDlgItemMessage (hDlg, IDC_NOTE, EM_LINEINDEX,
  980.             (UINT)cLines - 1, 0L);
  981.             cb += SendDlgItemMessage (hDlg, IDC_NOTE, EM_LINELENGTH,
  982.             (UINT)cb, 0L);
  983.  
  984.             /* The next line is to account for CR-LF pairs per line. */
  985.  
  986.             cb += cLines * 2;
  987.  
  988.                     PvFree(lpszNoteText);
  989.             lpszNoteText = (LPTSTR)PvAlloc(cb + 1);
  990.  
  991.             if (!lpszNoteText)
  992.             goto cleanup;
  993.  
  994.             /* Get the Note Text from the edit */
  995.  
  996.             GetDlgItemText (hDlg, IDC_NOTE, lpszNoteText, (int)cb);
  997.         }
  998.         else
  999.         {
  1000.             /* Make an empty string for NoteText */
  1001.  
  1002.             lpszNoteText = (LPTSTR)PvAlloc(1);
  1003.             if (!lpszNoteText)
  1004.             goto cleanup;
  1005.             *lpszNoteText = '\0';
  1006.         }
  1007.         }
  1008.  
  1009.         lpmsg->lpszSubject = lpszSubject;
  1010.         lpmsg->lpszNoteText = lpszNoteText;
  1011.         lpmsg->nRecipCount = cRecips;
  1012.         lpmsg->lpRecips = lpRecips;
  1013.         lpmsg->nFileCount = cAttach;
  1014.         lpmsg->lpFiles = lpAttach;
  1015.         lpmsg->flFlags = flSendMsgFlags;
  1016.  
  1017.         ulResult = MAPISendMail (lhSession, (ULONG) hDlg, lpmsg, 0, 0);
  1018.  
  1019.         LogSendMail(ulResult);
  1020.  
  1021.         if (ulResult)
  1022.         {
  1023.         MakeMessageBox (hDlg, ulResult, IDS_SENDERROR, MBS_ERROR);
  1024.         SetCursor(hOldCur);
  1025.         break;
  1026.         }
  1027. cleanup:
  1028.         SetCursor(hOldCur);
  1029.  
  1030.     case IDCANCEL:
  1031.         PvFree(lpmsg->lpszMessageType);
  1032.         PvFree(lpmsg->lpszConversationID);
  1033.         PvFree(lpmsg);
  1034.         PvFree(lpRecips);
  1035.         PvFree(lpAttach);
  1036.         PvFree(lpszSubject);
  1037.         PvFree(lpszNoteText);
  1038.         lpmsg = NULL;
  1039.  
  1040.         EndDialog (hDlg, TRUE);
  1041.         return TRUE;
  1042.         break;
  1043.  
  1044.     default:
  1045.         break;
  1046.     }
  1047.     break;
  1048.     }
  1049.     return FALSE;
  1050. }
  1051.  
  1052. /*
  1053.  -  InBoxDlgProc
  1054.  -
  1055.  *  Purpose:
  1056.  *      Dialog procedure for the InBox dialog.
  1057.  *
  1058.  *  Parameters:
  1059.  *      hDlg
  1060.  *      message
  1061.  *      wParam
  1062.  *      lParam
  1063.  *
  1064.  *  Returns:
  1065.  *      True/False
  1066.  *
  1067.  */
  1068.  
  1069. BOOL FAR PASCAL
  1070. InBoxDlgProc (HWND hDlg, UINT msg, UINT wParam, LONG lParam)
  1071. {
  1072.     char szMsgID[512];
  1073.     char szSeedMsgID[512];
  1074.     LPMSGID lpMsgNode;
  1075.     static LPMSGID lpMsgIdList = NULL;
  1076.     lpMapiMessage lpMessage;
  1077.     ULONG ulResult;
  1078.     DWORD nIndex;
  1079.     RECT Rect;
  1080.     HCURSOR hOldCur;
  1081.  
  1082.     switch (msg)
  1083.     {
  1084.     case WM_INITDIALOG:
  1085.     hOldCur = SetCursor(hWaitCur);
  1086.  
  1087.         InitBmps(hDlg, IDC_MSG);
  1088.  
  1089.     /* Populate List Box with all messages in InBox. */
  1090.     /* This is a painfully slow process for now.     */
  1091.  
  1092.     ulResult = MAPIFindNext (lhSession, (ULONG) hDlg, NULL, NULL,
  1093.         MAPI_GUARANTEE_FIFO | MAPI_LONG_MSGID, 0, szMsgID);
  1094.  
  1095.     while (ulResult == SUCCESS_SUCCESS)
  1096.     {
  1097.         ulResult = MAPIReadMail (lhSession, (ULONG) hDlg, szMsgID,
  1098.         MAPI_PEEK | MAPI_ENVELOPE_ONLY,
  1099.         0, &lpMessage);
  1100.  
  1101.         if (!ulResult)
  1102.         {
  1103.         lpMsgNode = MakeMsgNode (lpMessage, szMsgID);
  1104.  
  1105.         if (lpMsgNode)
  1106.         {
  1107.             InsertMsgNode (lpMsgNode, &lpMsgIdList);
  1108.  
  1109.             SendDlgItemMessage (hDlg, IDC_MSG, LB_ADDSTRING,
  1110.             0, (LONG) lpMsgNode);
  1111.         }
  1112.         MAPIFreeBuffer (lpMessage);
  1113.         }
  1114.  
  1115.         lstrcpy (szSeedMsgID, szMsgID);
  1116.         ulResult = MAPIFindNext (lhSession, (ULONG) hDlg, NULL, szSeedMsgID,
  1117.         MAPI_GUARANTEE_FIFO | MAPI_LONG_MSGID, 0, szMsgID);
  1118.     }
  1119.  
  1120.     SetCursor(hOldCur);
  1121.     SetFocus (GetDlgItem (hDlg, IDC_MSG));
  1122.     return TRUE;
  1123.     break;
  1124.  
  1125.     case WM_SETFOCUS:
  1126.     SetFocus (GetDlgItem (hDlg, IDC_MSG));
  1127.     break;
  1128.  
  1129.     case WM_MEASUREITEM:
  1130.     /* Sets the height of the owner-drawn List-Box */
  1131.         MeasureItem(hDlg, (MEASUREITEMSTRUCT *)lParam);
  1132.     break;
  1133.  
  1134.     case WM_DRAWITEM:
  1135.     DrawItem((DRAWITEMSTRUCT *)lParam);
  1136.     break;
  1137.  
  1138.     case WM_DELETEITEM:
  1139.     /* This message is handled by the IDC_DELETE message */
  1140.     return TRUE;
  1141.     break;
  1142.  
  1143.     case WM_COMMAND:
  1144.     switch (LOWORD (wParam))
  1145.     {
  1146.     case IDC_NEW:
  1147.         hOldCur = SetCursor(hWaitCur);
  1148.  
  1149.         ulResult = MAPIFindNext (lhSession, (ULONG) hDlg, NULL, NULL,
  1150.         MAPI_UNREAD_ONLY | MAPI_LONG_MSGID, 0, szMsgID);
  1151.  
  1152.         while (ulResult == SUCCESS_SUCCESS)
  1153.         {
  1154.         if (!FindNode (lpMsgIdList, szMsgID))
  1155.         {
  1156.             ulResult = MAPIReadMail (lhSession, (ULONG) hDlg, szMsgID,
  1157.             MAPI_PEEK | MAPI_ENVELOPE_ONLY, 0, &lpMessage);
  1158.  
  1159.             if (!ulResult)
  1160.             {
  1161.             lpMsgNode = MakeMsgNode (lpMessage, szMsgID);
  1162.             InsertMsgNode (lpMsgNode, &lpMsgIdList);
  1163.  
  1164.             SendDlgItemMessage (hDlg, IDC_MSG, LB_ADDSTRING,
  1165.                 0, (LONG) lpMsgNode);
  1166.  
  1167.             MAPIFreeBuffer (lpMessage);
  1168.             }
  1169.         }
  1170.  
  1171.         lstrcpy (szSeedMsgID, szMsgID);
  1172.         ulResult = MAPIFindNext (lhSession, (ULONG) hDlg, NULL, szSeedMsgID,
  1173.             MAPI_UNREAD_ONLY | MAPI_LONG_MSGID, 0, szMsgID);
  1174.         }
  1175.         SetCursor(hOldCur);
  1176.         break;
  1177.  
  1178.     case IDC_MSG:
  1179.         if(HIWORD(wParam) != LBN_DBLCLK)
  1180.         break;
  1181.  
  1182.     case IDC_READ:
  1183.         nIndex = SendDlgItemMessage (hDlg, IDC_MSG, LB_GETCURSEL, 0, 0);
  1184.  
  1185.         if (nIndex == LB_ERR)
  1186.         break;
  1187.  
  1188.         lpReadMsgNode = (LPMSGID) SendDlgItemMessage (hDlg, IDC_MSG,
  1189.         LB_GETITEMDATA, (UINT)nIndex, 0L);
  1190.  
  1191.         if (lpReadMsgNode)
  1192.         DialogBox (hInst, "ReadNote", hDlg, ReadMailDlgProc);
  1193.  
  1194.         /* Update the Messages List-Box with new icon */
  1195.  
  1196.         SendDlgItemMessage (hDlg, IDC_MSG, LB_GETITEMRECT, (UINT)nIndex, (LPARAM) &Rect);
  1197.         InvalidateRect(GetDlgItem(hDlg, IDC_MSG), &Rect, FALSE);
  1198.         break;
  1199.  
  1200.     case IDC_DELETE:
  1201.         nIndex = SendDlgItemMessage (hDlg, IDC_MSG, LB_GETCURSEL, 0, 0);
  1202.  
  1203.         if (nIndex == LB_ERR)
  1204.         break;
  1205.  
  1206.         lpMsgNode = (LPMSGID) SendDlgItemMessage (hDlg, IDC_MSG,
  1207.         LB_GETITEMDATA, (UINT)nIndex, 0);
  1208.  
  1209.         if (lpMsgNode)
  1210.         {
  1211.         MAPIDeleteMail (lhSession, (ULONG) hDlg, lpMsgNode->lpszMsgID, 0, 0);
  1212.         DeleteMsgNode (lpMsgNode, &lpMsgIdList);
  1213.         }
  1214.  
  1215.         SendDlgItemMessage (hDlg, IDC_MSG, LB_DELETESTRING, (UINT)nIndex, 0);
  1216.         break;
  1217.  
  1218.     case IDC_CLOSE:
  1219.     case IDCANCEL:
  1220.         FreeMsgList (lpMsgIdList);
  1221.         lpMsgIdList = NULL;
  1222.  
  1223.             DeInitBmps();
  1224.  
  1225.         EndDialog (hDlg, TRUE);
  1226.         return TRUE;
  1227.         break;
  1228.  
  1229.     default:
  1230.         break;
  1231.     }
  1232.     break;
  1233.     }
  1234.  
  1235.     return FALSE;
  1236. }
  1237.  
  1238. /*
  1239.  -  ReadMailDlgProc
  1240.  -
  1241.  *  Purpose:
  1242.  *      Dialog procedure for the ReadMail dilaog.
  1243.  *
  1244.  *  Parameters:
  1245.  *      hDlg
  1246.  *      message
  1247.  *      wParam
  1248.  *      lParam
  1249.  *
  1250.  *  Returns:
  1251.  *      True/False
  1252.  *
  1253.  */
  1254.  
  1255. BOOL FAR PASCAL
  1256. ReadMailDlgProc (HWND hDlg, UINT msg, UINT wParam, LONG lParam)
  1257. {
  1258.     ULONG ulResult;
  1259.     char szTo[TO_EDIT_MAX];
  1260.     char szCc[TO_EDIT_MAX];
  1261.     char szChangeMsg[512];
  1262.     ULONG idx;
  1263.     static lpMapiMessage lpReadMsg;
  1264.  
  1265.     switch (msg)
  1266.     {
  1267.     case WM_INITDIALOG:
  1268.     if (ulResult = MAPIReadMail (lhSession, (LONG) hDlg, lpReadMsgNode->lpszMsgID,
  1269.         0, 0, &lpReadMsg))
  1270.     {
  1271.         MakeMessageBox(hDlg, ulResult, IDS_READFAIL, MBS_ERROR);
  1272.         EndDialog (hDlg, TRUE);
  1273.         return TRUE;
  1274.     }
  1275.  
  1276.     lpReadMsgNode->fUnRead = FALSE;
  1277.  
  1278.     szTo[0] = '\0';
  1279.     szCc[0] = '\0';
  1280.  
  1281.     for (idx = 0; idx < lpReadMsg->nRecipCount; idx++)
  1282.     {
  1283.         if (lpReadMsg->lpRecips[idx].ulRecipClass == MAPI_TO)
  1284.         {
  1285.         lstrcat (szTo, lpReadMsg->lpRecips[idx].lpszName);
  1286.         lstrcat (szTo, "; ");
  1287.         }
  1288.         else if (lpReadMsg->lpRecips[idx].ulRecipClass == MAPI_CC)
  1289.         {
  1290.         lstrcat (szCc, lpReadMsg->lpRecips[idx].lpszName);
  1291.         lstrcat (szCc, "; ");
  1292.         }
  1293.         else
  1294.         {
  1295.         /* Must be Bcc, lets ignore it! */
  1296.         }
  1297.     }
  1298.  
  1299.     if(*szTo)
  1300.         szTo[lstrlen (szTo) - 2] = '\0';
  1301.     if(*szCc)
  1302.         szCc[lstrlen (szCc) - 2] = '\0';
  1303.  
  1304.     SetDlgItemText (hDlg, IDC_RFROM,
  1305.         (lpReadMsg->lpOriginator && lpReadMsg->lpOriginator->lpszName ?
  1306.                 lpReadMsg->lpOriginator->lpszName : ""));
  1307.     SetDlgItemText (hDlg, IDC_RDATE,
  1308.         (lpReadMsg->lpszDateReceived ? lpReadMsg->lpszDateReceived : ""));
  1309.     SetDlgItemText (hDlg, IDC_RTO, szTo);
  1310.     SetDlgItemText (hDlg, IDC_RCC, szCc);
  1311.     SetDlgItemText (hDlg, IDC_RSUBJECT,
  1312.         (lpReadMsg->lpszSubject ? lpReadMsg->lpszSubject : ""));
  1313.     SetDlgItemText (hDlg, IDC_READNOTE,
  1314.         (lpReadMsg->lpszNoteText ? lpReadMsg->lpszNoteText : ""));
  1315.  
  1316.     if (!lpReadMsg->nFileCount)
  1317.     {
  1318.         EnableWindow (GetDlgItem (hDlg, IDC_SAVEATTACH), FALSE);
  1319.         EnableWindow (GetDlgItem (hDlg, IDC_ATTACHMENT), FALSE);
  1320.         EnableWindow (GetDlgItem (hDlg, IDT_ATTACHMENT), FALSE);
  1321.     }
  1322.     else
  1323.     {
  1324.         for(idx = 0; idx < lpReadMsg->nFileCount; idx++)
  1325.         if (lpReadMsg->lpFiles[idx].lpszFileName)
  1326.             SendDlgItemMessage(hDlg, IDC_ATTACHMENT, LB_ADDSTRING, 0,
  1327.             (LPARAM)lpReadMsg->lpFiles[idx].lpszFileName);
  1328.  
  1329.         SendDlgItemMessage(hDlg, IDC_ATTACHMENT, LB_SETCURSEL, 0, 0L);
  1330.     }
  1331.  
  1332.     SetFocus (GetDlgItem (hDlg, IDC_READNOTE));
  1333.     return FALSE;
  1334.  
  1335.     case WM_COMMAND:
  1336.     switch (LOWORD (wParam))
  1337.     {
  1338.     case IDC_SAVECHANGES:
  1339.         if (SendDlgItemMessage (hDlg, IDC_READNOTE, EM_GETMODIFY, 0, 0))
  1340.         ulResult = SaveMsgChanges (hDlg, lpReadMsg, lpReadMsgNode->lpszMsgID);
  1341.         SendDlgItemMessage (hDlg, IDC_READNOTE, EM_SETMODIFY, 0, 0);
  1342.         break;
  1343.  
  1344.     case IDC_ATTACHMENT:
  1345.         if(HIWORD(wParam) != LBN_DBLCLK)
  1346.         break;
  1347.  
  1348.     case IDC_SAVEATTACH:
  1349.         idx = SendDlgItemMessage(hDlg, IDC_ATTACHMENT, LB_GETCURSEL, 0, 0L);
  1350.  
  1351.         if(idx != LB_ERR)
  1352.         {
  1353.         SaveFileAttachments(hDlg, &lpReadMsg->lpFiles[idx]);
  1354.         SetFocus(GetDlgItem (hDlg, IDC_ATTACHMENT));
  1355.         return FALSE;
  1356.  
  1357.         }
  1358.         break;
  1359.  
  1360.     case IDC_REPLY:
  1361.     case IDC_REPLYALL:
  1362.     case IDC_FORWARD:
  1363.         MakeNewMessage (lpReadMsg, LOWORD (wParam));
  1364.         DialogBox (hInst, "ComposeNote", hDlg, ComposeDlgProc);
  1365.         break;
  1366.  
  1367.     case IDCANCEL:
  1368.         if (SendDlgItemMessage (hDlg, IDC_READNOTE, EM_GETMODIFY, 0, 0))
  1369.         {
  1370.         wsprintf (szChangeMsg, "Save changes to: '%s' in Inbox?",
  1371.             (lpReadMsg->lpszSubject ? lpReadMsg->lpszSubject : ""));
  1372.  
  1373.         if (MessageBox (hDlg, szChangeMsg, "Mail", MB_YESNO) == IDYES)
  1374.         {
  1375.             ulResult = SaveMsgChanges (hDlg, lpReadMsg, lpReadMsgNode->lpszMsgID);
  1376.         }
  1377.         }
  1378.  
  1379.         /* If there were file attachments, then delete the temps */
  1380.  
  1381.         for(idx = 0; idx < lpReadMsg->nFileCount; idx++)
  1382.         if (lpReadMsg->lpFiles[idx].lpszPathName)
  1383.             DeleteFile(lpReadMsg->lpFiles[idx].lpszPathName);
  1384.  
  1385.         MAPIFreeBuffer (lpReadMsg);
  1386.         lpReadMsg = NULL;
  1387.         EndDialog (hDlg, TRUE);
  1388.         return TRUE;
  1389.     }
  1390.     break;
  1391.     }
  1392.     return FALSE;
  1393. }
  1394.  
  1395. /*
  1396.  -  MakeMessageBox
  1397.  -
  1398.  *  Purpose:
  1399.  *      Gets resource string and displays an error message box.
  1400.  *
  1401.  *  Parameters:
  1402.  *      hWnd            - Handle to parent window
  1403.  *      idString        - Resource ID of message in StringTable
  1404.  *
  1405.  *  Returns:
  1406.  *      Void
  1407.  *
  1408.  */
  1409.  
  1410. void
  1411. MakeMessageBox (HWND hWnd, ULONG ulResult, UINT idString, UINT fStyle)
  1412. {
  1413.     char szMessage[256];
  1414.     char szMapiReturn[64];
  1415.  
  1416.     LoadString (hInst, idString, szMessage, 255);
  1417.  
  1418.     if (ulResult)
  1419.     {
  1420.     LoadString (hInst, (UINT)ulResult, szMapiReturn, 64);
  1421.     lstrcat (szMessage, "\nReturn Code: ");
  1422.     lstrcat (szMessage, szMapiReturn);
  1423.     }
  1424.  
  1425.     MessageBox (hWnd, szMessage, "Problem", fStyle);
  1426. }
  1427.  
  1428. /*
  1429.  -  ResolveFriendlyNames
  1430.  -
  1431.  *  Purpose:
  1432.  *      Helper function to convert a string of ';' delimited friendly
  1433.  *      names into an array of MapiRecipDescs.
  1434.  *
  1435.  *  Side Effects:                                             
  1436.  *      The display string passed in is modified to contain the
  1437.  *      friendly names of the mail users as found in the sample
  1438.  *      address book.
  1439.  *
  1440.  *  Note:
  1441.  *      Duplicate names in the address book will result in undefined
  1442.  *      behavior.
  1443.  *
  1444.  *  Parameters:
  1445.  *      hWnd                - Handle to parent window
  1446.  *      lpszDisplayNames    - string of ';' delimited user names
  1447.  *      ulRecipClass        - either MAPI_TO, MAPI_CC, or MAPI_BCC
  1448.  *      lpcRecips           - Address of recipient count to be returned
  1449.  *      lppRecips           - Address of recipient array to be returned
  1450.  *
  1451.  *  Return:
  1452.  *      ulResult
  1453.  */
  1454.  
  1455. ULONG
  1456. ResolveFriendlyNames (HWND hWnd, LPSTR lpszDisplayNames, ULONG ulRecipClass,
  1457.     ULONG * lpcRecips, lpMapiRecipDesc * lppRecips)
  1458. {
  1459.     char szResolve[TO_EDIT_MAX];
  1460.     LPSTR lpszNameToken;
  1461.     ULONG cRecips = 0;
  1462.     ULONG cFails = 0;
  1463.     ULONG ulResult;
  1464.     lpMapiRecipDesc lpRecip;
  1465.     lpMapiRecipDesc lpRecipList;
  1466.  
  1467.     *szResolve = '\0';
  1468.     lpszNameToken = strtok (lpszDisplayNames, ";\n");
  1469.  
  1470.     while (lpszNameToken)
  1471.     {
  1472.     /* Strip leading blanks from name */
  1473.  
  1474.     while (*lpszNameToken == ' ')
  1475.         lpszNameToken++;
  1476.  
  1477.     /* Check if name has already been resolved */
  1478.  
  1479.     if (!FNameInList (lpszNameToken, *lpcRecips, *lppRecips))
  1480.     {
  1481.         lstrcat (szResolve, lpszNameToken);
  1482.         lstrcat (szResolve, "; ");
  1483.         cRecips++;
  1484.     }
  1485.  
  1486.     /* Get Next Token */
  1487.  
  1488.     lpszNameToken = strtok (NULL, ";\n");
  1489.     }
  1490.  
  1491.     *lpszDisplayNames = '\0';
  1492.  
  1493.     if (!szResolve[0])
  1494.     {
  1495.     ulResult = SUCCESS_SUCCESS;
  1496.     goto err;
  1497.     }
  1498.  
  1499.     szResolve[lstrlen (szResolve) - 2] = '\0';
  1500.  
  1501.     lpRecipList = (lpMapiRecipDesc)PvAlloc((cRecips + *lpcRecips) * sizeof (MapiRecipDesc));
  1502.  
  1503.     if (!lpRecipList)
  1504.     {
  1505.     ulResult = MAPI_E_INSUFFICIENT_MEMORY;
  1506.     goto err;
  1507.     }
  1508.     memset (lpRecipList, 0, (size_t)(cRecips+*lpcRecips)*sizeof(MapiRecipDesc));
  1509.  
  1510.     cRecips = 0;
  1511.  
  1512.     while (cRecips < *lpcRecips)
  1513.     {
  1514.     ulResult = CopyRecipient (lpRecipList, &lpRecipList[cRecips],
  1515.         *lppRecips + cRecips);
  1516.  
  1517.     if (ulResult)
  1518.     {
  1519.         PvFree(lpRecipList);
  1520.         goto err;
  1521.     }
  1522.  
  1523.     cRecips++;
  1524.     }
  1525.  
  1526.     PvFree(*lppRecips);
  1527.  
  1528.     lpszNameToken = strtok (szResolve, ";\n");
  1529.  
  1530.     while (lpszNameToken)
  1531.     {
  1532.     /* Strip leading blanks (again) */
  1533.  
  1534.     while (*lpszNameToken == ' ')
  1535.         lpszNameToken++;
  1536.  
  1537.     ulResult = MAPIResolveName (lhSession, (ULONG) hWnd, lpszNameToken,
  1538.         MAPI_DIALOG, 0, &lpRecip);
  1539.  
  1540.     if (ulResult == SUCCESS_SUCCESS)
  1541.     {
  1542.         lpRecip->ulRecipClass = ulRecipClass;
  1543.         ulResult = CopyRecipient (lpRecipList, &lpRecipList[cRecips], lpRecip);
  1544.  
  1545.         MAPIFreeBuffer (lpRecip);
  1546.  
  1547.         if (ulResult)
  1548.         goto cleanup;
  1549.  
  1550.         cRecips++;
  1551.     }
  1552.     else
  1553.     {
  1554.         lstrcat (lpszDisplayNames, lpszNameToken);
  1555.         lstrcat (lpszDisplayNames, "; ");
  1556.         cFails++;
  1557.     }
  1558.     lpszNameToken = strtok (NULL, ";\n");
  1559.     }
  1560.  
  1561.     /* if cFails > 0 then we have partial success */
  1562.  
  1563.     ulResult = SUCCESS_SUCCESS;
  1564.  
  1565.     if (cFails)
  1566.     MakeMessageBox (hWnd, 0, IDS_UNRESOLVEDNAMES, MBS_INFO);
  1567.  
  1568. cleanup:
  1569.     *lpcRecips = cRecips;
  1570.     *lppRecips = lpRecipList;
  1571. err:
  1572.     if (*lpszDisplayNames)
  1573.     lpszDisplayNames[lstrlen (lpszDisplayNames) - 2] = '\0';
  1574.  
  1575.     return ulResult;
  1576. }
  1577.  
  1578. /*
  1579.  -  CopyRecipient
  1580.  -
  1581.  *  Purpose:
  1582.  *      Called in support of ResolveFriendlyNames() to build an array
  1583.  *      of chained MapiRecipDescs.
  1584.  *
  1585.  *  Parameters:
  1586.  *      lpParent        - Parent memory that allocations get chained to
  1587.  *      lpDest          - Destination Recipient
  1588.  *      lpSrc           - Source Recipient
  1589.  *
  1590.  *  Return:
  1591.  *      ulResult
  1592.  */
  1593.  
  1594. ULONG
  1595. CopyRecipient (lpMapiRecipDesc lpParent,
  1596.     lpMapiRecipDesc lpDest,
  1597.     lpMapiRecipDesc lpSrc)
  1598. {
  1599.     lpDest->ulReserved = lpSrc->ulReserved;
  1600.     lpDest->ulRecipClass = lpSrc->ulRecipClass;
  1601.     lpDest->ulEIDSize = lpSrc->ulEIDSize;
  1602.  
  1603.     if (lpSrc->lpszName)
  1604.     {
  1605.     lpDest->lpszName = (LPTSTR)PvAllocMore(lstrlen(lpSrc->lpszName) + 1,
  1606.             (LPVOID)lpParent);
  1607.  
  1608.     if (!lpDest->lpszName)
  1609.         return MAPI_E_INSUFFICIENT_MEMORY;
  1610.  
  1611.     lstrcpy (lpDest->lpszName, lpSrc->lpszName);
  1612.     }
  1613.     else
  1614.     lpDest->lpszName = NULL;
  1615.  
  1616.     if (lpSrc->lpszAddress)
  1617.     {
  1618.     lpDest->lpszAddress = (LPTSTR)PvAllocMore(lstrlen (lpSrc->lpszAddress) + 1,
  1619.             (LPVOID)lpParent);
  1620.  
  1621.     if (!lpDest->lpszAddress)
  1622.         return MAPI_E_INSUFFICIENT_MEMORY;
  1623.  
  1624.     lstrcpy (lpDest->lpszAddress, lpSrc->lpszAddress);
  1625.     }
  1626.     else
  1627.     lpDest->lpszAddress = NULL;
  1628.  
  1629.     if (lpSrc->lpEntryID)
  1630.     {
  1631.     lpDest->lpEntryID = (LPBYTE)PvAllocMore(lpSrc->ulEIDSize,
  1632.             (LPVOID)lpParent);
  1633.  
  1634.     if (!lpDest->lpEntryID)
  1635.         return MAPI_E_INSUFFICIENT_MEMORY;
  1636.  
  1637.         if (lpSrc->ulEIDSize)
  1638.             memcpy (lpDest->lpEntryID, lpSrc->lpEntryID, (size_t)lpSrc->ulEIDSize);
  1639.     }
  1640.     else
  1641.     lpDest->lpEntryID = NULL;
  1642.  
  1643.     return SUCCESS_SUCCESS;
  1644.  
  1645. }
  1646.  
  1647. /*
  1648.  -  GetNextFile
  1649.  -
  1650.  *  Purpose:
  1651.  *      Called when user clicks 'Attach' button in Compose Note form.
  1652.  *      We will build a chained memory chunk for mmore than one file
  1653.  *      attachment so the memory can be freed with a single call to
  1654.  *      PvFree.
  1655.  *
  1656.  *  Parameters:
  1657.  *      hWnd            - Window handle of Compose Note dialog
  1658.  *      nPos            - Render position of attachment in Notetext.
  1659.  *      lpcAttach       - Pointer to the count of attachments.
  1660.  *      lppAttach       - Pointer to the MapiFileDesc array.
  1661.  *
  1662.  *  Return:
  1663.  *      ulResult.
  1664.  */
  1665.  
  1666. ULONG
  1667. GetNextFile (HWND hWnd, ULONG nPos, ULONG * lpcAttach,
  1668.     lpMapiFileDesc * lppAttach)
  1669. {
  1670.     lpMapiFileDesc lpAttach;
  1671.     lpMapiFileDesc lpAttachT;
  1672.     OPENFILENAME ofn;
  1673.     char szFileName[256] = "";
  1674.     char szFilter[256];
  1675.     static char szFileTitle[16];
  1676.     static char szDirName[256] = "";
  1677.     LPSTR lpszEndPath;
  1678.     ULONG idx;
  1679.     ULONG ulResult = SUCCESS_SUCCESS;
  1680.  
  1681.     if (!szDirName[0])
  1682.     GetSystemDirectory ((LPSTR) szDirName, 255);
  1683.     else
  1684.     lstrcpy (szFileName, szFileTitle);
  1685.  
  1686.     LoadString(hInst, IDS_FILTER, szFilter, sizeof(szFilter));
  1687.  
  1688.     for (idx = 0; szFilter[idx] != '\0'; idx++)
  1689.     if (szFilter[idx] == '|')
  1690.         szFilter[idx] = '\0';
  1691.  
  1692.     ofn.lStructSize = sizeof (OPENFILENAME);
  1693.     ofn.hwndOwner = 0;
  1694.     ofn.hInstance = 0;
  1695.     ofn.lpstrFilter = szFilter;
  1696.     ofn.lpstrCustomFilter = NULL;
  1697.     ofn.nMaxCustFilter = 0L;
  1698.     ofn.nFilterIndex = 1L;
  1699.     ofn.lpstrFile = szFileName;
  1700.     ofn.nMaxFile = 256;
  1701.     ofn.lpstrFileTitle = szFileTitle;
  1702.     ofn.nMaxFileTitle = 16;
  1703.     ofn.lpstrInitialDir = szDirName;
  1704.     ofn.lpstrTitle = "Attach";
  1705.     ofn.nFileOffset = 0;
  1706.     ofn.nFileExtension = 0;
  1707.     ofn.lpstrDefExt = NULL;
  1708.     ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
  1709.  
  1710.     if (!GetOpenFileName (&ofn))
  1711.     return MAPI_USER_ABORT;
  1712.  
  1713.     /* Save the directory for the next time we call this */
  1714.  
  1715.     lstrcpy (szDirName, szFileName);
  1716.     if (lpszEndPath = strstr (szDirName, szFileTitle))
  1717.     *(--lpszEndPath) = '\0';
  1718.  
  1719.     lpAttach = (lpMapiFileDesc)PvAlloc(((*lpcAttach) + 1) * sizeof (MapiFileDesc));
  1720.  
  1721.     if(!lpAttach)
  1722.     goto err;
  1723.  
  1724.     memset (lpAttach, 0, (size_t)(*lpcAttach + 1) * sizeof (MapiFileDesc));
  1725.  
  1726.     lpAttachT = *lppAttach;
  1727.  
  1728.     for (idx = 0; idx < *lpcAttach; idx++)
  1729.     if(ulResult = CopyAttachment (lpAttach, &lpAttach[idx], &lpAttachT[idx]))
  1730.         goto err;
  1731.  
  1732.     lpAttach[idx].ulReserved = 0;
  1733.     lpAttach[idx].flFlags = 0;
  1734.     lpAttach[idx].nPosition = (ULONG)(-1);
  1735.     lpAttach[idx].lpFileType = NULL;
  1736.  
  1737.     lpAttach[idx].lpszPathName = (LPTSTR)PvAllocMore(lstrlen (szFileName) + 1,
  1738.         (LPVOID)lpAttach);
  1739.  
  1740.     if(!lpAttach[idx].lpszPathName)
  1741.     goto err;
  1742.  
  1743.     lpAttach[idx].lpszFileName = (LPTSTR)PvAllocMore(lstrlen (szFileTitle) + 1,
  1744.         (LPVOID)lpAttach);
  1745.  
  1746.     if(!lpAttach[idx].lpszFileName)
  1747.     goto err;
  1748.  
  1749.     lstrcpy (lpAttach[idx].lpszPathName, szFileName);
  1750.     lstrcpy (lpAttach[idx].lpszFileName, szFileTitle);
  1751.  
  1752.     PvFree(lpAttachT);
  1753.  
  1754.     *lppAttach = lpAttach;
  1755.     (*lpcAttach)++;
  1756.  
  1757. err:
  1758.     if(ulResult)
  1759.     PvFree(lpAttach);
  1760.  
  1761.     return ulResult;
  1762. }
  1763.  
  1764. /*
  1765.  -  CopyAttachment
  1766.  -
  1767.  *  Purpose:
  1768.  *      Called in support of GetNextFile() to re-build an array
  1769.  *      of chained MapiFileDescs.
  1770.  *
  1771.  *  Parameters:
  1772.  *      lpParent        - Parent memory that allocations get chained to
  1773.  *      lpDest          - Destination Recipient
  1774.  *      lpSrc           - Source Recipient
  1775.  *
  1776.  *  Return:
  1777.  *      Void.
  1778.  */
  1779.  
  1780. ULONG
  1781. CopyAttachment (lpMapiFileDesc lpParent,
  1782.     lpMapiFileDesc lpDest,
  1783.     lpMapiFileDesc lpSrc)
  1784. {
  1785.     lpDest->ulReserved = lpSrc->ulReserved;
  1786.     lpDest->flFlags = lpSrc->flFlags;
  1787.     lpDest->nPosition = lpSrc->nPosition;
  1788.     lpDest->lpFileType = lpSrc->lpFileType;
  1789.  
  1790.     if (lpSrc->lpszPathName)
  1791.     {
  1792.     lpDest->lpszPathName = (LPTSTR)PvAllocMore(lstrlen (lpSrc->lpszPathName) + 1,
  1793.             (LPVOID)lpParent);
  1794.  
  1795.     if (!lpDest->lpszPathName)
  1796.         return MAPI_E_INSUFFICIENT_MEMORY;
  1797.  
  1798.     lstrcpy (lpDest->lpszPathName, lpSrc->lpszPathName);
  1799.     }
  1800.     else
  1801.     lpDest->lpszPathName = NULL;
  1802.  
  1803.     if (lpSrc->lpszFileName)
  1804.     {
  1805.     lpDest->lpszFileName = (LPTSTR)PvAllocMore(lstrlen (lpSrc->lpszFileName) + 1,
  1806.             (LPVOID)lpParent);
  1807.  
  1808.     if (!lpDest->lpszFileName)
  1809.         return MAPI_E_INSUFFICIENT_MEMORY;
  1810.  
  1811.     lstrcpy (lpDest->lpszFileName, lpSrc->lpszFileName);
  1812.     }
  1813.     else
  1814.     lpDest->lpszFileName = NULL;
  1815.  
  1816.     return SUCCESS_SUCCESS;
  1817.  
  1818. }
  1819.  
  1820. /*
  1821.  -  FNameInList
  1822.  -
  1823.  *  Purpose:
  1824.  *      To find lpszName in an array of recipients.  Used to determine
  1825.  *      if user name has already been resolved.
  1826.  *
  1827.  *  Parameters:
  1828.  *      lpszName        - Friendly name to search for
  1829.  *      cRecips         - Count of recipients in lpRecips
  1830.  *      lpRecips        - Array of MapiRecipDescs
  1831.  *
  1832.  *  Return:
  1833.  *      TRUE/FALSE
  1834.  */
  1835.  
  1836. BOOL
  1837. FNameInList (LPSTR lpszName, ULONG cRecips, lpMapiRecipDesc lpRecips)
  1838. {
  1839.     /* Case sensitive compare of each friendly name in list.  */
  1840.  
  1841.     if (!cRecips || !lpRecips)
  1842.     return FALSE;
  1843.  
  1844.     while (cRecips--)
  1845.     if (!lstrcmp (lpszName, lpRecips[cRecips].lpszName))
  1846.         return TRUE;
  1847.  
  1848.     return FALSE;
  1849. }
  1850.  
  1851.  
  1852. /*
  1853.  -  MakeMsgNode
  1854.  -
  1855.  *  Purpose:
  1856.  *      Allocate memory for a new MSGID node and initialize its
  1857.  *      data members to the values passed in.
  1858.  *
  1859.  *  Parameters:
  1860.  *      lpMsg           - Pointer to a MapiMessage
  1861.  *      lpszMsgID       - Opaque message identifier
  1862.  *
  1863.  *  Return:
  1864.  *      lpMsgNode       - Pointer to new node
  1865.  */
  1866.  
  1867. LPMSGID
  1868. MakeMsgNode (lpMapiMessage lpMsg, LPSTR lpszMsgID)
  1869. {
  1870.     LPMSGID lpMsgNode = NULL;
  1871.  
  1872.     if (!lpMsg || !lpszMsgID)
  1873.     goto err;
  1874.  
  1875.     lpMsgNode = (LPMSGID)PvAlloc(sizeof (MSGID));
  1876.  
  1877.     if (!lpMsgNode)
  1878.     goto err;
  1879.  
  1880.     memset (lpMsgNode, 0, sizeof (MSGID));
  1881.  
  1882.     if (lpMsg->nFileCount)
  1883.     lpMsgNode->fHasAttach = TRUE;
  1884.  
  1885.     if (lpMsg->flFlags & MAPI_UNREAD)
  1886.     lpMsgNode->fUnRead = TRUE;
  1887.  
  1888.     lpMsgNode->lpszMsgID = (LPTSTR)PvAllocMore(lstrlen (lpszMsgID) + 1,
  1889.         (LPVOID)lpMsgNode);
  1890.  
  1891.     if (!lpMsgNode->lpszMsgID)
  1892.     goto err;
  1893.  
  1894.     lstrcpy (lpMsgNode->lpszMsgID, lpszMsgID);
  1895.  
  1896.     if (lpMsg->lpOriginator && lpMsg->lpOriginator->lpszName)
  1897.     {
  1898.     lpMsgNode->lpszFrom = (LPTSTR)PvAllocMore(lstrlen(lpMsg->lpOriginator->lpszName) + 1,
  1899.             (LPVOID)lpMsgNode);
  1900.  
  1901.     if (!lpMsgNode->lpszFrom)
  1902.         goto err;
  1903.  
  1904.     lstrcpy (lpMsgNode->lpszFrom, lpMsg->lpOriginator->lpszName);
  1905.     }
  1906.  
  1907.     if (lpMsg->lpszSubject)
  1908.     {
  1909.     lpMsgNode->lpszSubject = (LPTSTR)PvAllocMore(lstrlen (lpMsg->lpszSubject) + 1,
  1910.             (LPVOID)lpMsgNode);
  1911.  
  1912.     if (!lpMsgNode->lpszSubject)
  1913.         goto err;
  1914.  
  1915.     lstrcpy (lpMsgNode->lpszSubject, lpMsg->lpszSubject);
  1916.     }
  1917.  
  1918.     if (lpMsg->lpszDateReceived)
  1919.     {
  1920.     lpMsgNode->lpszDateRec = (LPTSTR)PvAllocMore(lstrlen (lpMsg->lpszDateReceived) + 1,
  1921.             (LPVOID)lpMsgNode);
  1922.  
  1923.     if (!lpMsgNode->lpszDateRec)
  1924.         goto err;
  1925.  
  1926.     lstrcpy (lpMsgNode->lpszDateRec, lpMsg->lpszDateReceived);
  1927.     }
  1928.  
  1929.     return lpMsgNode;
  1930.  
  1931. err:
  1932.     PvFree(lpMsgNode);
  1933.     return NULL;
  1934. }
  1935.  
  1936. /*
  1937.  -  InsertMsgNode
  1938.  -
  1939.  *  Purpose:
  1940.  *      Currently (for simplicity) we will insert the nodes
  1941.  *      at the beginning of the list.  This can later be
  1942.  *      replaced with a routine that can insert sorted on
  1943.  *      different criteria, like DateReceived, From, or
  1944.  *      Subject.  But for now...
  1945.  *
  1946.  *  Parameters:
  1947.  *      lpMsgNode       - Pointer to a MSGID node
  1948.  *      lppMsgHead      - Pointer to the head of the list
  1949.  *
  1950.  *  Return:
  1951.  *      Void.
  1952.  */
  1953.  
  1954. void
  1955. InsertMsgNode (LPMSGID lpMsgNode, LPMSGID * lppMsgHead)
  1956. {
  1957.     if (*lppMsgHead)
  1958.     {
  1959.     lpMsgNode->lpNext = *lppMsgHead;
  1960.     (*lppMsgHead)->lpPrev = lpMsgNode;
  1961.     }
  1962.     else
  1963.     lpMsgNode->lpNext = NULL;
  1964.  
  1965.     /* The next 2 assignments are here in case the node came from somewhere */
  1966.     /* other than a call to MakeMsgNode () in which case we aren't sure */
  1967.     /* they're already NULL. */
  1968.  
  1969.     lpMsgNode->lpPrev = NULL;
  1970.     *lppMsgHead = lpMsgNode;
  1971. }
  1972.  
  1973. /*
  1974.  -  DeleteMsgNode
  1975.  -
  1976.  *  Purpose:
  1977.  *      Removes the node passed in from the list.  This
  1978.  *      may seem like a strange way to do this but it's
  1979.  *      not, because the Owner-Drawn List Box gives us
  1980.  *      direct access to elements in the list that makes
  1981.  *      it easier to do things this way.
  1982.  *
  1983.  *  Parameters:
  1984.  *      lpMsgNode       - Pointer to the MSGID node to delete
  1985.  *      lppMsgHead      - Pointer to the head of the list
  1986.  *
  1987.  *  Return:
  1988.  *      Void.
  1989.  */
  1990.  
  1991. void
  1992. DeleteMsgNode (LPMSGID lpMsgNode, LPMSGID * lppMsgHead)
  1993. {
  1994.     if (!lpMsgNode)
  1995.     return;
  1996.  
  1997.     /* Check if we are the first node */
  1998.  
  1999.     if (lpMsgNode->lpPrev)
  2000.     lpMsgNode->lpPrev->lpNext = lpMsgNode->lpNext;
  2001.  
  2002.     /* Check if we are the last node */
  2003.  
  2004.     if (lpMsgNode->lpNext)
  2005.     lpMsgNode->lpNext->lpPrev = lpMsgNode->lpPrev;
  2006.  
  2007.     /* check if we are the only node */
  2008.  
  2009.     if(lpMsgNode == *lppMsgHead)
  2010.     *lppMsgHead = NULL;
  2011.  
  2012.     PvFree(lpMsgNode);
  2013.     return;
  2014. }
  2015.  
  2016.  
  2017.  
  2018. /*
  2019.  -  FindNode
  2020.  -
  2021.  *  Purpose:
  2022.  *      Returns a pointer to the node containing lpszMsgID.
  2023.  *      Returns NULL if node doesn't exist or lpszMsgID is NULL.
  2024.  *
  2025.  *  Parameters:
  2026.  *      lpMsgHead       - Pointer to the head of the list
  2027.  *      lpszMsgID       - Message ID to search for
  2028.  *
  2029.  *  Return:
  2030.  *      lpMsgNode       - Pointer to the node returned
  2031.  */
  2032.  
  2033. LPMSGID
  2034. FindNode (LPMSGID lpMsgHead, LPSTR lpszMsgID)
  2035. {
  2036.     if (!lpszMsgID)
  2037.     return NULL;
  2038.  
  2039.     while (lpMsgHead)
  2040.     {
  2041.     if (!lstrcmp (lpMsgHead->lpszMsgID, lpszMsgID))
  2042.         break;
  2043.  
  2044.     lpMsgHead = lpMsgHead->lpNext;
  2045.     }
  2046.  
  2047.     return lpMsgHead;
  2048. }
  2049.  
  2050.  
  2051.  
  2052. /*
  2053.  -  FreeMsgList
  2054.  -
  2055.  *  Purpose:
  2056.  *      Walks down the MsgList and frees each node.
  2057.  *
  2058.  *  Parameters:
  2059.  *      lpMsgHead       - Pointer to the head of the list
  2060.  *
  2061.  *  Return:
  2062.  *      Void.
  2063.  */
  2064.  
  2065. void
  2066. FreeMsgList (LPMSGID lpMsgHead)
  2067. {
  2068.     LPMSGID lpT;
  2069.  
  2070.     while (lpMsgHead)
  2071.     {
  2072.     lpT = lpMsgHead;
  2073.     lpMsgHead = lpMsgHead->lpNext;
  2074.     PvFree(lpT);
  2075.     }
  2076. }
  2077.  
  2078. /*
  2079.  -  MakeDisplayNameStr
  2080.  -
  2081.  *  Purpose:
  2082.  *      Finds all recipients of type ulRecipClass in lpRecips and adds
  2083.  *      their friendly name to the display string.
  2084.  *
  2085.  *  Parameters:
  2086.  *      lpszDisplay         - Destination string for names
  2087.  *      ulRecipClass        - Recipient types to search for
  2088.  *      cRecips             - Count of recipients in lpRecips
  2089.  *      lpRecips            - Pointer to array of MapiRecipDescs
  2090.  *
  2091.  *  Return:
  2092.  *      Void.
  2093.  */
  2094.  
  2095. void
  2096. MakeDisplayNameStr (LPSTR lpszDisplay, ULONG ulRecipClass,
  2097.     ULONG cRecips, lpMapiRecipDesc lpRecips)
  2098. {
  2099.     ULONG idx;
  2100.  
  2101.     *lpszDisplay = '\0';
  2102.  
  2103.     for (idx = 0; idx < cRecips; idx++)
  2104.     {
  2105.     if (lpRecips[idx].ulRecipClass == ulRecipClass)
  2106.     {
  2107.         lstrcat (lpszDisplay, lpRecips[idx].lpszName);
  2108.         lstrcat (lpszDisplay, "; ");
  2109.     }
  2110.     }
  2111.  
  2112.     if (*lpszDisplay)
  2113.     lpszDisplay[lstrlen (lpszDisplay) - 2] = '\0';
  2114. }
  2115.  
  2116.  
  2117.  
  2118. /*
  2119.  -  SaveMsgChanges
  2120.  -
  2121.  *  Purpose:
  2122.  *      If while reading a message the user changes the notetext at all
  2123.  *      then this function is called to save those changes in the Inbox.
  2124.  *
  2125.  *  Parameters:
  2126.  *      hWnd            - handle to the window/dialog who called us
  2127.  *      lpMsg           - pointer to the MAPI message to be saved
  2128.  *      lpszMsgID       - ID of the message to save
  2129.  *
  2130.  *  Return:
  2131.  *      ulResult        - Indicating success/failure
  2132.  */
  2133.  
  2134. ULONG
  2135. SaveMsgChanges (HWND hWnd, lpMapiMessage lpMsg, LPSTR lpszMsgID)
  2136. {
  2137.     LPSTR lpszT;
  2138.     LPSTR lpszNoteText = NULL;
  2139.     LONG cLines, cb;
  2140.     ULONG ulResult = MAPI_E_INSUFFICIENT_MEMORY;
  2141.  
  2142.     lpszT = lpMsg->lpszNoteText;
  2143.  
  2144.     cLines = SendDlgItemMessage (hWnd, IDC_READNOTE, EM_GETLINECOUNT, 0, 0L);
  2145.     cb = SendDlgItemMessage (hWnd, IDC_READNOTE, EM_LINEINDEX, (UINT)cLines - 1, 0L);
  2146.     cb += SendDlgItemMessage (hWnd, IDC_READNOTE, EM_LINELENGTH, (UINT)cb, 0L);
  2147.     cb += cLines * 2;
  2148.  
  2149.     lpszNoteText = (LPTSTR)PvAlloc(cb + 1);
  2150.  
  2151.     if (!lpszNoteText)
  2152.     goto err;
  2153.  
  2154.     SendDlgItemMessage (hWnd, IDC_READNOTE, WM_GETTEXT,
  2155.     (WPARAM) cb, (LPARAM) lpszNoteText);
  2156.  
  2157.     lpMsg->lpszNoteText = lpszNoteText;
  2158.     ulResult = MAPISaveMail (lhSession, (ULONG) hWnd, lpMsg, MAPI_LONG_MSGID,
  2159.         0, lpReadMsgNode->lpszMsgID);
  2160.  
  2161.     PvFree(lpszNoteText);
  2162.  
  2163. err:
  2164.     lpMsg->lpszNoteText = lpszT;
  2165.     return ulResult;
  2166. }
  2167.  
  2168.  
  2169.  
  2170. /*
  2171.  -  MakeNewMessage
  2172.  -
  2173.  *  Purpose:
  2174.  *      This function is used to construct a new message for the
  2175.  *      ComposeNote UI.  This gets called as a result of a Reply,
  2176.  *      ReplyAll, or a Forward action on a message being read.
  2177.  *      The destination for the new message is lpmsg, the global
  2178.  *      MapiMessage struct pointer used by ComposeNoteDlgProc.
  2179.  *      ComposeNoteDlgProc always frees the memory consumed by
  2180.  *      this object whether it allocated it or not.
  2181.  *
  2182.  *  Parameters:
  2183.  *      lpSrcMsg            - MapiMessage to be copied
  2184.  *      flType              - Specifies the action that caused this call
  2185.  *                            either: IDC_REPLY, IDC_REPLYALL, or IDC_FORWARD
  2186.  *
  2187.  *  Return:
  2188.  *      ulResult            - Indicates success/failure
  2189.  */
  2190.  
  2191. ULONG
  2192. MakeNewMessage (lpMapiMessage lpSrcMsg, UINT flType)
  2193. {
  2194.     ULONG idx;
  2195.     ULONG ulResult = SUCCESS_SUCCESS;
  2196.  
  2197.     if (!lpSrcMsg)
  2198.     return MAPI_E_FAILURE;
  2199.  
  2200.     lpmsg = (lpMapiMessage)PvAlloc(sizeof (MapiMessage));
  2201.  
  2202.     if (!lpmsg)
  2203.     goto err;
  2204.  
  2205.     memset (lpmsg, 0, sizeof (MapiMessage));
  2206.  
  2207.     lpmsg->flFlags = flSendMsgFlags;
  2208.  
  2209.     if (lpSrcMsg->lpszSubject)
  2210.     {
  2211.     lpmsg->lpszSubject = (LPTSTR)PvAlloc(lstrlen(lpSrcMsg->lpszSubject) + 5);
  2212.  
  2213.     if (!lpmsg->lpszSubject)
  2214.         goto err;
  2215.  
  2216.     if (flType == IDC_FORWARD)
  2217.         lstrcpy (lpmsg->lpszSubject, "FW: ");
  2218.     else
  2219.         lstrcpy (lpmsg->lpszSubject, "RE: ");
  2220.  
  2221.     lstrcat (lpmsg->lpszSubject, lpSrcMsg->lpszSubject);
  2222.     }
  2223.  
  2224.     if (lpSrcMsg->lpszNoteText)
  2225.     {
  2226.     lpmsg->lpszNoteText = (LPTSTR)PvAlloc(lstrlen(lpSrcMsg->lpszNoteText) + 32);
  2227.  
  2228.     if (!lpmsg->lpszNoteText)
  2229.         goto err;
  2230.  
  2231.     lstrcpy (lpmsg->lpszNoteText, "\r\n--------------------------\r\n");
  2232.     lstrcat (lpmsg->lpszNoteText, lpSrcMsg->lpszNoteText);
  2233.     }
  2234.  
  2235.     if (lpSrcMsg->lpszMessageType)
  2236.     {
  2237.     lpmsg->lpszMessageType = (LPTSTR)PvAlloc(lstrlen (lpSrcMsg->lpszMessageType) + 1);
  2238.  
  2239.     if (!lpmsg->lpszMessageType)
  2240.         goto err;
  2241.  
  2242.     lstrcpy (lpmsg->lpszMessageType, lpSrcMsg->lpszMessageType);
  2243.     }
  2244.  
  2245.     if (lpSrcMsg->lpszConversationID)
  2246.     {
  2247.     lpmsg->lpszConversationID = (LPTSTR)PvAlloc(lstrlen(lpSrcMsg->lpszConversationID) + 1);
  2248.  
  2249.     if (!lpmsg->lpszConversationID)
  2250.         goto err;
  2251.  
  2252.     lstrcpy (lpmsg->lpszConversationID, lpSrcMsg->lpszConversationID);
  2253.     }
  2254.  
  2255.     if (lpSrcMsg->nFileCount && flType == IDC_FORWARD )
  2256.     {
  2257.     lpmsg->nFileCount = lpSrcMsg->nFileCount;
  2258.  
  2259.     lpmsg->lpFiles = (lpMapiFileDesc)PvAlloc(lpmsg->nFileCount * sizeof (MapiFileDesc));
  2260.  
  2261.     if (!lpmsg->lpFiles)
  2262.         goto err;
  2263.         memset (lpmsg->lpFiles, 0, (size_t)lpmsg->nFileCount * sizeof (MapiFileDesc));
  2264.  
  2265.         for (idx = 0; idx < lpmsg->nFileCount; idx++)
  2266.     {       
  2267.         CopyAttachment (lpmsg->lpFiles, &lpmsg->lpFiles[idx],
  2268.         &lpSrcMsg->lpFiles[idx]);
  2269.         
  2270.             if ((&lpmsg->lpFiles[idx])->nPosition != (ULONG) -1)
  2271.             {       
  2272.                 /*lpmsg->lpszNoteText[(&lpmsg->lpFiles[idx])->nPosition 
  2273.                             + lstrlen("\r\n--------------------------\r\n")] = '+';*/
  2274.                 (&lpmsg->lpFiles[idx])->nPosition = (ULONG) -1;
  2275.                 
  2276.             }
  2277.                                 
  2278.             
  2279.         }
  2280.     }
  2281.  
  2282.     if (flType == IDC_REPLY || flType == IDC_REPLYALL)
  2283.     {
  2284.         ULONG idxSrc;
  2285.  
  2286.     if(lpSrcMsg->lpOriginator)
  2287.         lpmsg->nRecipCount = 1;
  2288.  
  2289.     if (flType == IDC_REPLYALL)
  2290.         lpmsg->nRecipCount += lpSrcMsg->nRecipCount;
  2291.  
  2292.         if(!lpmsg->nRecipCount)
  2293.             return ulResult;
  2294.  
  2295.     lpmsg->lpRecips = (lpMapiRecipDesc)PvAlloc(lpmsg->nRecipCount * sizeof (MapiRecipDesc));
  2296.  
  2297.     if (!lpmsg->lpRecips)
  2298.         goto err;
  2299.  
  2300.         memset (lpmsg->lpRecips, 0, (size_t)lpmsg->nRecipCount * sizeof (MapiRecipDesc));
  2301.         idx = 0;
  2302.  
  2303.         if(lpSrcMsg->lpOriginator)
  2304.         {
  2305.         lpSrcMsg->lpOriginator->ulRecipClass = MAPI_TO;
  2306.         CopyRecipient (lpmsg->lpRecips, lpmsg->lpRecips,
  2307.                 lpSrcMsg->lpOriginator);
  2308.         lpSrcMsg->lpOriginator->ulRecipClass = MAPI_ORIG;
  2309.             idx = 1;
  2310.         }
  2311.  
  2312.     for (idxSrc = 0; idx < lpmsg->nRecipCount; idxSrc++, idx++)
  2313.         CopyRecipient (lpmsg->lpRecips, &lpmsg->lpRecips[idx],
  2314.         &lpSrcMsg->lpRecips[idxSrc]);
  2315.     }
  2316.  
  2317.     return ulResult;
  2318.  
  2319. err:
  2320.     if(lpmsg)
  2321.     {
  2322.         PvFree(lpmsg->lpszSubject);
  2323.     PvFree(lpmsg->lpszNoteText);
  2324.         PvFree(lpmsg->lpszMessageType);
  2325.         PvFree(lpmsg->lpszConversationID);
  2326.         PvFree(lpmsg->lpRecips);
  2327.         PvFree(lpmsg->lpFiles);
  2328.         PvFree(lpmsg);
  2329.         lpmsg = NULL;
  2330.     }
  2331.     return ulResult;
  2332. }
  2333.  
  2334.  
  2335.  
  2336. /*
  2337.  -  LogSendMail
  2338.  -
  2339.  *  Purpose:
  2340.  *      Used to track how many messages were sent with this client.
  2341.  *      This information is used strictly for gathering stats on
  2342.  *      how many messages were pumped through the spooler/transport.
  2343.  *
  2344.  *  Usage:
  2345.  *      Add the following to the win.ini file:
  2346.  *          [MAPI Client]
  2347.  *          LogFile=filepath
  2348.  *
  2349.  *      where: filepath can be a full UNC path or some local path & file
  2350.  *
  2351.  *  Parameters:
  2352.  *      ulResult        - Currently unused; should be used to count errors
  2353.  *
  2354.  *  Result:
  2355.  *      Void.
  2356.  */
  2357.  
  2358. void LogSendMail(ULONG ulResult)
  2359. {
  2360.     char szLogFile[128];
  2361.     char szCount[32];
  2362.     OFSTRUCT ofs;
  2363.     HFILE hf = HFILE_ERROR;
  2364.     int cSent = 1;
  2365.  
  2366.     if(!GetProfileString("MAPI Client", "LogFile", "mapicli.log",
  2367.         szLogFile, sizeof(szLogFile)))
  2368.     return;
  2369.  
  2370.     if((hf = OpenFile(szLogFile, &ofs, OF_READWRITE)) == HFILE_ERROR)
  2371.     {
  2372.     if((hf = OpenFile(szLogFile, &ofs, OF_CREATE|OF_READWRITE)) == HFILE_ERROR)
  2373.         return;
  2374.     }
  2375.     else
  2376.     {
  2377.     if(!_lread(hf, szCount, sizeof(szCount)))
  2378.     {
  2379.         _lclose(hf);
  2380.         return;
  2381.     }
  2382.  
  2383.     cSent = atoi(szCount) + 1;
  2384.     }
  2385.  
  2386.     wsprintf(szCount, "%d", cSent);
  2387.  
  2388.     _llseek(hf, 0, 0);
  2389.  
  2390.     _lwrite(hf, szCount, lstrlen(szCount));
  2391.     _lclose(hf);
  2392.  
  2393.     return;
  2394. }
  2395.  
  2396.  
  2397.  
  2398. /*
  2399.  -  SaveFileAttachments
  2400.  -
  2401.  *  Purpose:
  2402.  *      Displays a 'Save As' common dialog to allow the user to save
  2403.  *      file attachments contained in the current message.
  2404.  *
  2405.  *  Parameters:
  2406.  *      hWnd            - Window handle of calling WndProc
  2407.  *      cFiles          - Count of the files in the file array
  2408.  *      lpFiles         - Array of MapiFileDescs
  2409.  *
  2410.  *  Return:
  2411.  *      Void.
  2412.  */
  2413.  
  2414. void SaveFileAttachments(HWND hWnd, lpMapiFileDesc lpFile)
  2415. {
  2416.     OPENFILENAME ofn;
  2417.     char szFileName[256] = "";
  2418.     char szFilter[256];
  2419.     static char szFileTitle[16];
  2420.     static char szDirName[256] = "";
  2421.     LPSTR lpszEndPath;
  2422.     ULONG idx;
  2423.  
  2424.     if (!lpFile)
  2425.     return;
  2426.  
  2427.     if (!szDirName[0])
  2428.     GetTempPath (sizeof(szDirName), szDirName);
  2429.  
  2430.     LoadString(hInst, IDS_FILTER, szFilter, sizeof(szFilter));
  2431.  
  2432.     for (idx = 0; szFilter[idx] != '\0'; idx++)
  2433.     if (szFilter[idx] == '|')
  2434.         szFilter[idx] = '\0';
  2435.  
  2436.     lstrcpy (szFileName, lpFile->lpszFileName);
  2437.  
  2438.     ofn.lStructSize = sizeof (OPENFILENAME);
  2439.     ofn.hwndOwner = hWnd;
  2440.     ofn.hInstance = 0;
  2441.     ofn.lpstrFilter = szFilter;
  2442.     ofn.lpstrCustomFilter = NULL;
  2443.     ofn.nMaxCustFilter = 0L;
  2444.     ofn.nFilterIndex = 1L;
  2445.     ofn.lpstrFile = szFileName;
  2446.     ofn.nMaxFile = sizeof(szFileName);
  2447.     ofn.lpstrFileTitle = szFileTitle;
  2448.     ofn.nMaxFileTitle = sizeof(szFileTitle);
  2449.     ofn.lpstrInitialDir = szDirName;
  2450.     ofn.lpstrTitle = "Save Attachment";
  2451.     ofn.nFileOffset = 0;
  2452.     ofn.nFileExtension = 0;
  2453.     ofn.lpstrDefExt = NULL;
  2454.     ofn.Flags = OFN_SHOWHELP | OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
  2455.  
  2456.     if (!GetSaveFileName (&ofn))
  2457.     return;
  2458.  
  2459.     /* Save the directory for the next time we call this */
  2460.  
  2461.     lstrcpy (szDirName, szFileName);
  2462.     if (lpszEndPath = strstr (szDirName, szFileTitle))
  2463.     *(--lpszEndPath) = '\0';
  2464.  
  2465.     /* Use CopyFile to carry out the operation. */
  2466.  
  2467.     if(!CopyFile(lpFile->lpszPathName, szFileName, FALSE))
  2468.     MakeMessageBox (hWnd, 0, IDS_SAVEATTACHERROR, MBS_ERROR);
  2469. }
  2470.  
  2471.  
  2472.  
  2473. /*
  2474.  -  ToggleMenuState
  2475.  -
  2476.  *  Purpose:
  2477.  *      Enables/Disables menu items depending on the session state.
  2478.  *
  2479.  *  Parameters:
  2480.  *      hWnd            - handle to the window/dialog who called us
  2481.  *      fLoggedOn       - TRUE if logged on, FALSE if logged off
  2482.  *
  2483.  *  Return:
  2484.  *      Void.
  2485.  */
  2486.  
  2487. void ToggleMenuState(HWND hWnd, BOOL fLoggedOn)
  2488. {
  2489.     EnableMenuItem (GetMenu (hWnd), IDM_LOGOFF,   !fLoggedOn);
  2490.     EnableMenuItem (GetMenu (hWnd), IDM_COMPOSE,  !fLoggedOn);
  2491.     EnableMenuItem (GetMenu (hWnd), IDM_READ,     !fLoggedOn);
  2492.     EnableMenuItem (GetMenu (hWnd), IDM_SEND,     !fLoggedOn);
  2493.     EnableMenuItem (GetMenu (hWnd), IDM_ADDRBOOK, !fLoggedOn);
  2494.     EnableMenuItem (GetMenu (hWnd), IDM_DETAILS,  !fLoggedOn);
  2495.     EnableMenuItem (GetMenu (hWnd), IDM_LOGON,    fLoggedOn);
  2496.     EnableMenuItem (GetMenu (hWnd), IDM_EXIT,           FALSE);
  2497. }
  2498.  
  2499. //
  2500. //  SecureMenu
  2501. //
  2502. //  Purpose:
  2503. //      Enables/Disables Logon and Exit menu items.
  2504. //      CMCLogon might yield control to Windows, so the user might be able to
  2505. //      access the window menu (for example click Logon) after we call
  2506. //      MAPILogon, but before it returns.
  2507. //
  2508. //  Parameters:
  2509. //      hWnd            - handle to the window/dialog who called us
  2510. //      fBeforeLogon    - TRUE when this function is called when we are about
  2511. //                      to call MAPILogon, FALSE if called after logon (failed)
  2512. //                      if Logon succeddes ToggleMenuState is called instead of
  2513. //                      this function.
  2514. //
  2515. //  Return:
  2516. //      Void.
  2517. //
  2518.  
  2519.  
  2520. void SecureMenu(HWND hWnd, BOOL fBeforeLogon)
  2521. {
  2522.     EnableMenuItem (GetMenu (hWnd), IDM_LOGON, fBeforeLogon);
  2523.     EnableMenuItem (GetMenu (hWnd), IDM_EXIT,  fBeforeLogon);
  2524. }
  2525.