Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2524 lines
63 KiB

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