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.

2988 lines
86 KiB

  1. ////////////////////////////////////////////////////////////////////////
  2. //
  3. // UTIL.CPP
  4. //
  5. // Purpose:
  6. // misc utility functions
  7. //
  8. // Owner:
  9. // Sung Rhee ([email protected])
  10. //
  11. // Copyright (C) Microsoft Corp. 1994, 1995.
  12. //
  13. ////////////////////////////////////////////////////////////////////////
  14. #include <pch.hxx>
  15. #include <shlwapip.h>
  16. #include "storfldr.h"
  17. #include "options.h"
  18. #include <io.h>
  19. #include "docobj.h"
  20. #include <string.h>
  21. #include <mbstring.h>
  22. #include "spell.h"
  23. #include "cmdtargt.h"
  24. #include "mimeolep.h"
  25. #include "oleutil.h"
  26. #include "regutil.h"
  27. #include "secutil.h"
  28. #include "imagelst.h"
  29. #include "inetcfg.h"
  30. #include "url.h"
  31. #include <mshtmcid.h>
  32. #include <mshtmhst.h>
  33. #include "bodyutil.h"
  34. #include "htmlstr.h"
  35. #include "sigs.h"
  36. #include "imsgcont.h"
  37. #include <dlgs.h>
  38. #include "msgfldr.h"
  39. #include "shared.h"
  40. #include "demand.h"
  41. #include "note.h"
  42. #include "ipab.h"
  43. #include "menures.h"
  44. #include <iert.h>
  45. #include <multiusr.h>
  46. #include "mirror.h"
  47. ASSERTDATA
  48. #define IS_EXTENDED(ch) ((ch > 126 || ch < 32) && ch != '\t' && ch != '\n' && ch != '\r')
  49. #define IS_BINARY(ch) ((ch < 32) && ch != '\t' && ch != '\n' && ch != '\r')
  50. #define MAX_SIG_SIZE 4096
  51. INT_PTR CALLBACK DontShowAgainDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  52. BOOL CALLBACK EnumThreadCB(HWND hwnd, LPARAM lParam);
  53. enum
  54. {
  55. SAVEAS_RFC822 =1, // KEEP IN ORDER of FILTER IN SAVEAS DIALOG
  56. SAVEAS_TEXT,
  57. SAVEAS_UNICODETEXT,
  58. SAVEAS_HTML,
  59. SAVEAS_NUMTYPES = SAVEAS_HTML
  60. };
  61. HRESULT HrSaveMsgSourceToFile(LPMIMEMESSAGE pMsg, DWORD dwSaveAs, LPWSTR pwszFile, BOOL fCanBeDirty);
  62. #define CBPATHMAX 512
  63. VOID DoReadme(HWND hwndOwner)
  64. {
  65. TCHAR szbuf[MAX_PATH];
  66. LPTSTR psz;
  67. if((fIsNT5() && g_OSInfo.dwMinorVersion >=1) ||
  68. ((g_OSInfo.dwMajorVersion > 5) && (g_OSInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)))
  69. {
  70. AthMessageBox(hwndOwner, MAKEINTRESOURCE(idsAthena), MAKEINTRESOURCE(idsReadme), NULL, MB_OK);
  71. return;
  72. }
  73. if (GetExePath(c_szIexploreExe, szbuf, ARRAYSIZE(szbuf), TRUE))
  74. {
  75. // need to delete stup ';' in IE path
  76. TCHAR *pch = CharPrev(szbuf, szbuf + lstrlen(szbuf));
  77. *pch = TEXT('\0');
  78. PathAddBackslash(szbuf);
  79. StrCatBuff(szbuf, c_szReadme, ARRAYSIZE(szbuf));
  80. ShellExecute(hwndOwner, "open", (LPCTSTR)szbuf, NULL, NULL, SW_SHOWNORMAL);
  81. }
  82. }
  83. void AthErrorMessage(HWND hwnd, LPTSTR pszTitle, LPTSTR pszError, HRESULT hrDetail)
  84. {
  85. LPWSTR pwszTitle = NULL,
  86. pwszError = NULL;
  87. // Title can be null. So is PszToUnicode fails, we are ok. Title just becomes "Error"
  88. pwszTitle = IS_INTRESOURCE(pszTitle) ? (LPWSTR)pszTitle : PszToUnicode(CP_ACP, pszTitle);
  89. pwszError = IS_INTRESOURCE(pszError) ? (LPWSTR)pszError : PszToUnicode(CP_ACP, pszError);
  90. // pwszError must be valid. If not, don't do the error box.
  91. if (pwszError)
  92. AthErrorMessageW(hwnd, pwszTitle, pwszError, hrDetail);
  93. if (!IS_INTRESOURCE(pszTitle))
  94. MemFree(pwszTitle);
  95. if (!IS_INTRESOURCE(pszError))
  96. MemFree(pwszError);
  97. }
  98. void AthErrorMessageW(HWND hwnd, LPWSTR pwszTitle, LPWSTR pwszError, HRESULT hrDetail)
  99. {
  100. register WORD ids;
  101. Assert(FAILED(hrDetail));
  102. switch (hrDetail)
  103. {
  104. case E_OUTOFMEMORY:
  105. ids = idsMemory;
  106. break;
  107. case DB_E_CREATEFILEMAPPING:
  108. case STG_E_MEDIUMFULL:
  109. case DB_E_DISKFULL:
  110. case hrDiskFull:
  111. ids = idsDiskFull;
  112. break;
  113. case DB_E_ACCESSDENIED:
  114. ids = idsDBAccessDenied;
  115. break;
  116. case hrFolderIsLocked:
  117. ids = idsFolderLocked;
  118. break;
  119. case hrEmptyDistList:
  120. ids = idsErrOneOrMoreEmptyDistLists;
  121. break;
  122. case hrNoSubject:
  123. ids = idsErrNoSubject;
  124. break;
  125. case hrNoSender:
  126. ids = idsErrNoPoster;
  127. break;
  128. case HR_E_POST_WITHOUT_NEWS:
  129. ids = idsErrPostWithoutNewsgroup;
  130. break;
  131. case HR_E_CONFIGURE_SERVER:
  132. ids = idsErrConfigureServer;
  133. break;
  134. case hrEmptyRecipientAddress:
  135. ids = idsErrEmptyRecipientAddress;
  136. break;
  137. case MIME_E_URL_NOTFOUND:
  138. ids = idsErrSendDownloadFail;
  139. break;
  140. case hrUnableToLoadMapi32Dll:
  141. ids = idsCantLoadMapi32Dll;
  142. break;
  143. case hrImportLoad:
  144. ids = idsErrImportLoad;
  145. break;
  146. case hrFolderNameConflict:
  147. ids = idsErrFolderNameConflict;
  148. break;
  149. case STORE_E_CANTRENAMESPECIAL:
  150. ids = idsErrRenameSpecialFld;
  151. break;
  152. case STORE_E_BADFOLDERNAME:
  153. ids = idsErrBadFolderName;
  154. break;
  155. case MAPI_E_INVALID_ENTRYID:
  156. ids = idsErrBadRecips;
  157. break;
  158. case MIME_E_SECURITY_CERTERROR:
  159. ids = idsSecCerificateErr;
  160. break;
  161. case MIME_E_SECURITY_NOCERT:
  162. ids = idsNoCerificateErr;
  163. break;
  164. case HR_E_COULDNOTFINDACCOUNT:
  165. ids = idsErrNoSendAccounts; //:idsErrConfigureServer;
  166. break;
  167. case hrDroppedConn:
  168. ids = idsErrPeerClosed;
  169. break;
  170. case hrInvalidPassword:
  171. ids = idsErrAuthenticate;
  172. break;
  173. case hrCantMoveIntoSubfolder:
  174. ids = idsErrCantMoveIntoSubfolder;
  175. break;
  176. case STORE_E_CANTDELETESPECIAL:
  177. case hrCantDeleteSpecialFolder:
  178. ids = idsErrDeleteSpecialFolder;
  179. break;
  180. case hrNoRecipients:
  181. ids = idsErrNoRecipients;
  182. break;
  183. case hrBadRecipients:
  184. ids = idsErrBadRecipients;
  185. break;
  186. case HR_E_ATHSEC_NOCERTTOSIGN:
  187. {
  188. ids = idsErrSecurityNoSigningCert;
  189. if(DialogBoxParam(g_hLocRes,
  190. MAKEINTRESOURCE(iddErrSecurityNoSigningCert), hwnd,
  191. ErrSecurityNoSigningCertDlgProc, NULL) == idGetDigitalIDs)
  192. GetDigitalIDs(NULL);
  193. return;
  194. }
  195. break;
  196. case HR_E_ATHSEC_CERTBEGONE:
  197. ids = idsErrSecurityCertDisappeared;
  198. break;
  199. case MIME_E_SECURITY_NOSIGNINGCERT:
  200. //N for the MIME error, may need to do better
  201. // ? delete the reg key if invalid? sure, they
  202. // can always go to the combo box again. Maybe
  203. // prompt them toward this
  204. ids = idsErrSecurityNoSigningCert;
  205. break;
  206. case hrCantMoveSpecialFolder:
  207. ids = idsErrCannotMoveSpecial;
  208. break;
  209. case MIME_E_SECURITY_LABELACCESSDENIED:
  210. case MIME_E_SECURITY_LABELACCESSCANCELLED:
  211. case MIME_E_SECURITY_LABELCORRUPT:
  212. ids = idsErrAccessDenied;
  213. break;
  214. default:
  215. ids = idsGenericError;
  216. break;
  217. }
  218. AthMessageBoxW(hwnd, pwszTitle, pwszError, MAKEINTRESOURCEW(ids), MB_OK | MB_ICONEXCLAMATION);
  219. }
  220. INT_PTR CALLBACK ErrSecurityNoSigningCertDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  221. {
  222. INT id;
  223. switch(msg)
  224. {
  225. case WM_INITDIALOG:
  226. CenterDialog(hwnd);
  227. return TRUE;
  228. case WM_COMMAND:
  229. switch(id=GET_WM_COMMAND_ID(wParam, lParam))
  230. {
  231. case idGetDigitalIDs:
  232. /* GetDigitalIDs(NULL);
  233. break; */
  234. case IDCANCEL:
  235. EndDialog(hwnd, id);
  236. break;
  237. }
  238. }
  239. return FALSE;
  240. }
  241. BOOL FNewMessage(HWND hwnd, BOOL fModal, BOOL fNoStationery, BOOL fNews, FOLDERID folderID, IUnknown *pUnkPump)
  242. {
  243. INIT_MSGSITE_STRUCT initStruct;
  244. DWORD dwCreateFlags = 0;
  245. HRESULT hr;
  246. FOLDERTYPE ftype;
  247. ftype = fNews ? FOLDER_NEWS : FOLDER_LOCAL;
  248. ProcessICW(hwnd, ftype);
  249. // Create new mail message
  250. initStruct.dwInitType = OEMSIT_VIRGIN;
  251. initStruct.folderID = folderID;
  252. if(fNoStationery)
  253. dwCreateFlags = OENCF_NOSTATIONERY;
  254. if (fModal)
  255. dwCreateFlags |= OENCF_MODAL;
  256. if (fNews)
  257. dwCreateFlags |= OENCF_NEWSFIRST;
  258. hr = CreateAndShowNote(OENA_COMPOSE, dwCreateFlags, &initStruct, hwnd, pUnkPump);
  259. return (SUCCEEDED(hr) || (MAPI_E_USER_CANCEL == hr));
  260. }
  261. // ********* WARNING THESE ARE NOT READY FOR PRIME TIME USE *********//
  262. // I put them here so that they are in the right place. brent,03/24
  263. // I will clean them up when I return from Florida.
  264. HRESULT CreateNewShortCut(LPWSTR pwszPathName, LPWSTR pwszLinkPath, DWORD cchLink)
  265. {
  266. WCHAR wszDisplayName[MAX_PATH];
  267. Assert(pwszPathName);
  268. Assert(pwszLinkPath);
  269. Assert(0 < cchLink);
  270. if (!FBuildTempPathW(pwszPathName, pwszLinkPath, cchLink, TRUE))
  271. return(E_FAIL);
  272. GetDisplayNameForFile(pwszPathName, wszDisplayName, ARRAYSIZE(wszDisplayName));
  273. return CreateLink(pwszPathName, pwszLinkPath, wszDisplayName);
  274. }
  275. //===================================================
  276. //
  277. // HRESULT GetDisplayNameForFile
  278. //
  279. //===================================================
  280. void GetDisplayNameForFile(LPWSTR pwszPathName, LPWSTR pwszDisplayName, ULONG cchDisplayName)
  281. {
  282. SHFILEINFOW sfi={0};
  283. SHGetFileInfoWrapW(pwszPathName, NULL, &sfi, sizeof(sfi), SHGFI_DISPLAYNAME);
  284. StrCpyNW(pwszDisplayName, sfi.szDisplayName, cchDisplayName);
  285. }
  286. //===================================================
  287. //
  288. // HRESULT CreateLink()
  289. //
  290. /*
  291. * CreateLink
  292. *
  293. * uses the shell's IShellLink and IPersistFile interfaces
  294. * to create and store a shortcut to the specified object.
  295. * Returns the result of calling the member functions of the interfaces.
  296. * lpszPathObj - address of a buffer containing the path of the object
  297. * lpszPathLink - address of a buffer containing the path where the
  298. * shell link is to be stored
  299. * lpszDesc - address of a buffer containing the description of the
  300. * shell link
  301. */
  302. HRESULT CreateLink(LPWSTR pwszPathObj, LPWSTR pwszPathLink, LPWSTR pwszDesc)
  303. {
  304. HRESULT hr;
  305. IShellLink *psl = NULL;
  306. IShellLinkW *pslW = NULL;
  307. LPSTR pszPathObj = NULL,
  308. pszDesc = NULL;
  309. // Get a pointer to the IShellLink interface.
  310. hr = CoCreateInstance( CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
  311. IID_IShellLinkW, (LPVOID *)&pslW);
  312. if(SUCCEEDED(hr))
  313. {
  314. // Set the path to the shortcut target, and add the description.
  315. pslW->SetPath(pwszPathObj);
  316. pslW->SetDescription(pwszDesc);
  317. hr = HrIPersistFileSaveW((LPUNKNOWN)pslW, pwszPathLink);
  318. }
  319. else
  320. {
  321. hr = CoCreateInstance( CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
  322. IID_IShellLink, (LPVOID *)&psl);
  323. if(SUCCEEDED(hr))
  324. {
  325. IF_NULLEXIT(pszPathObj = PszToANSI(CP_ACP, pwszPathObj));
  326. IF_NULLEXIT(pszDesc = PszToANSI(CP_ACP, pwszDesc));
  327. // Set the path to the shortcut target, and add the description.
  328. psl->SetPath(pszPathObj);
  329. psl->SetDescription(pszDesc);
  330. hr = HrIPersistFileSaveW((LPUNKNOWN)psl, pwszPathLink);
  331. }
  332. }
  333. exit:
  334. ReleaseObj(psl);
  335. ReleaseObj(pslW);
  336. MemFree(pszPathObj);
  337. MemFree(pszDesc);
  338. return hr;
  339. }
  340. DWORD DwGetDontShowAgain (LPCSTR pszRegString)
  341. {
  342. DWORD dwDontShow, dwType;
  343. ULONG cb;
  344. cb = sizeof(DWORD);
  345. if (AthUserGetValue(c_szRegPathDontShowDlgs, pszRegString, &dwType, (LPBYTE)&dwDontShow, &cb) != ERROR_SUCCESS ||
  346. dwType != REG_DWORD ||
  347. cb != sizeof(DWORD))
  348. {
  349. dwDontShow = 0; // default to show if something fails!
  350. }
  351. return dwDontShow;
  352. }
  353. VOID SetDontShowAgain (DWORD dwDontShow, LPCSTR pszRegString)
  354. {
  355. AthUserSetValue(c_szRegPathDontShowDlgs, pszRegString, REG_DWORD, (LPBYTE)&dwDontShow, sizeof(DWORD));
  356. }
  357. typedef struct _tagDONTSHOWPARAMS
  358. {
  359. LPTSTR pszMessage;
  360. LPTSTR pszTitle;
  361. UINT uType;
  362. } DONTSHOWPARAMS, *LPDONTSHOWPARAMS;
  363. void SetDlgButtonText(HWND hBtn, int ids)
  364. {
  365. TCHAR szBuf[CCHMAX_STRINGRES];
  366. int id;
  367. AthLoadString(ids, szBuf, sizeof(szBuf));
  368. SetWindowText(hBtn, szBuf);
  369. switch (ids)
  370. {
  371. case idsYES: id = IDYES; break;
  372. case idsNO: id = IDNO; break;
  373. case idsCANCEL: id = IDCANCEL; break;
  374. case idsOK: id = IDOK; break;
  375. default: AssertSz(FALSE, "Bad button type."); return;
  376. }
  377. SetWindowLong(hBtn, GWL_ID, id);
  378. }
  379. void DoDontShowInitDialog(HWND hwnd, LPDONTSHOWPARAMS pParams)
  380. {
  381. int btnTop,
  382. heightDelta = 0,
  383. btnLeftDelta = 0,
  384. nShowStyle1 = SWP_SHOWWINDOW,
  385. nShowStyle2 = SWP_SHOWWINDOW,
  386. nShowStyle3 = SWP_SHOWWINDOW;
  387. TCHAR rgchTitle[CCHMAX_STRINGRES], rgchMsg[CCHMAX_STRINGRES], rgchCheck[CCHMAX_STRINGRES];
  388. HWND hText, hBtn1, hBtn2, hBtn3, hCheck, hIconStat;
  389. HICON hIcon;
  390. LONG uBtnStyle;
  391. UINT idsCheckBoxString = 0;
  392. UINT uShowBtns = (MB_OK|MB_OKCANCEL|MB_YESNO|MB_YESNOCANCEL) & pParams->uType;
  393. UINT uDefBtn = (MB_DEFBUTTON1|MB_DEFBUTTON2|MB_DEFBUTTON3) & pParams->uType;
  394. UINT uIconStyle = (MB_ICONASTERISK|MB_ICONEXCLAMATION|MB_ICONHAND|MB_ICONEXCLAMATION ) & pParams->uType;
  395. RECT rc;
  396. LPTSTR szTitle = pParams->pszTitle,
  397. szMessage = pParams->pszMessage;
  398. if (0 == uShowBtns)
  399. uShowBtns= MB_OK;
  400. if (0 == uDefBtn)
  401. uDefBtn = MB_DEFBUTTON1;
  402. if (!uIconStyle)
  403. {
  404. switch(uShowBtns)
  405. {
  406. case MB_OK:
  407. uIconStyle = MB_ICONINFORMATION;
  408. idsCheckBoxString = idsDontShowMeAgain;
  409. break;
  410. case MB_OKCANCEL:
  411. uIconStyle = MB_ICONEXCLAMATION;
  412. idsCheckBoxString = idsDontShowMeAgain;
  413. break;
  414. case MB_YESNO:
  415. case MB_YESNOCANCEL:
  416. uIconStyle = MB_ICONEXCLAMATION ;
  417. idsCheckBoxString = idsDontAskMeAgain;
  418. break;
  419. default:
  420. AssertSz(FALSE, "Didn't get a valid box type");
  421. uIconStyle = MB_ICONWARNING;
  422. break;
  423. }
  424. }
  425. if (IS_INTRESOURCE(szTitle))
  426. {
  427. // its a string resource id
  428. if (0 == AthLoadString(PtrToUlong(szTitle), rgchTitle, sizeof(rgchTitle)))
  429. return;
  430. szTitle = rgchTitle;
  431. }
  432. if (IS_INTRESOURCE(szMessage))
  433. {
  434. // its a string resource id
  435. if (0 == AthLoadString(PtrToUlong(szMessage), rgchMsg, sizeof(rgchMsg)))
  436. return;
  437. szMessage = rgchMsg;
  438. }
  439. switch(uIconStyle)
  440. {
  441. case MB_ICONASTERISK: hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_ASTERISK)); break;
  442. case MB_ICONEXCLAMATION: hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_EXCLAMATION)); break;
  443. case MB_ICONHAND: hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_HAND)); break;
  444. case MB_ICONQUESTION : hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_EXCLAMATION)); break; // fixes BUG 18105
  445. default: hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION)); break;
  446. }
  447. AssertSz(hIcon, "Didn't get the appropriate system icon.");
  448. hIconStat = GetDlgItem(hwnd, ico1);
  449. AssertSz(hIconStat, "Didn't get the handle to the static icon dgl item.");
  450. SendMessage(hIconStat, STM_SETICON, (WPARAM)hIcon, 0);
  451. CenterDialog(hwnd);
  452. hText = GetDlgItem(hwnd, stc1);
  453. AssertSz(hText, "Didn't get a static text handle.");
  454. GetChildRect(hwnd, hText, &rc);
  455. HDC dc = GetDC(hwnd);
  456. if (dc)
  457. {
  458. switch (uShowBtns)
  459. {
  460. case MB_OK:
  461. {
  462. nShowStyle1 = SWP_HIDEWINDOW;
  463. nShowStyle3 = SWP_HIDEWINDOW;
  464. break;
  465. }
  466. case MB_OKCANCEL:
  467. case MB_YESNO:
  468. {
  469. nShowStyle3 = SWP_HIDEWINDOW;
  470. break;
  471. }
  472. }
  473. // Size the static text
  474. heightDelta = DrawText(dc, szMessage, -1, &rc, DT_CALCRECT|DT_WORDBREAK|DT_CENTER);
  475. ReleaseDC(hwnd, dc);
  476. SetWindowPos(hText, 0, 0, 0, rc.right-rc.left, heightDelta, SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOZORDER);
  477. }
  478. // Move buttons
  479. hBtn1 = GetDlgItem(hwnd, psh1);
  480. hBtn2 = GetDlgItem(hwnd, psh2);
  481. hBtn3 = GetDlgItem(hwnd, psh3);
  482. AssertSz(hBtn1 && hBtn2 && hBtn3, "Didn't get one of button handles.");
  483. GetChildRect(hwnd, hBtn1, &rc);
  484. btnTop = rc.top+heightDelta;
  485. // With these two cases, buttons must be shifted a bit to the right
  486. if ((MB_OKCANCEL == uShowBtns) || (MB_YESNO == uShowBtns))
  487. {
  488. RECT tempRC;
  489. GetChildRect(hwnd, hBtn2, &tempRC);
  490. btnLeftDelta = (tempRC.left - rc.left) / 2;
  491. }
  492. SetWindowPos(hBtn1, 0, rc.left+btnLeftDelta, btnTop, 0, 0, nShowStyle1|SWP_NOSIZE|SWP_NOZORDER);
  493. GetChildRect(hwnd, hBtn2, &rc);
  494. SetWindowPos(hBtn2, 0, rc.left+btnLeftDelta, btnTop, 0, 0, nShowStyle2|SWP_NOSIZE|SWP_NOZORDER);
  495. GetChildRect(hwnd, hBtn3, &rc);
  496. SetWindowPos(hBtn3, 0, rc.left+btnLeftDelta, btnTop, 0, 0, nShowStyle3|SWP_NOSIZE|SWP_NOZORDER);
  497. // Move check box
  498. hCheck = GetDlgItem(hwnd, idchkDontShowMeAgain);
  499. AssertSz(hCheck, "Didn't get a handle to the check box.");
  500. GetChildRect(hwnd, hCheck, &rc);
  501. SetWindowPos(hCheck, 0, rc.left, rc.top+heightDelta, 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOZORDER);
  502. AthLoadString(idsCheckBoxString, rgchCheck, sizeof(rgchCheck));
  503. SetWindowText(hCheck, rgchCheck);
  504. // Size dialog
  505. GetWindowRect(hwnd, &rc);
  506. heightDelta += rc.bottom - rc.top;
  507. SetWindowPos(hwnd, 0, 0, 0, rc.right-rc.left, heightDelta, SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOOWNERZORDER);
  508. SetWindowText(hText, szMessage);
  509. SetWindowText(hwnd, szTitle);
  510. switch(uShowBtns)
  511. {
  512. case MB_OK:
  513. {
  514. SetFocus(hBtn2);
  515. SetDlgButtonText(hBtn2, idsOK);
  516. break;
  517. }
  518. case MB_OKCANCEL:
  519. case MB_YESNO:
  520. {
  521. SetFocus((MB_DEFBUTTON1 == uDefBtn) ? hBtn1 : hBtn2);
  522. if (MB_OKCANCEL == uShowBtns)
  523. {
  524. SetDlgButtonText(hBtn1, idsOK);
  525. SetDlgButtonText(hBtn2, idsCANCEL);
  526. }
  527. else
  528. {
  529. SetDlgButtonText(hBtn1, idsYES);
  530. SetDlgButtonText(hBtn2, idsNO);
  531. }
  532. break;
  533. }
  534. case MB_YESNOCANCEL:
  535. {
  536. switch (uDefBtn)
  537. {
  538. case MB_DEFBUTTON1: SetFocus(hBtn1); break;
  539. case MB_DEFBUTTON2: SetFocus(hBtn2); break;
  540. case MB_DEFBUTTON3: SetFocus(hBtn3); break;
  541. default: SetFocus(hBtn1); break;
  542. }
  543. SetDlgButtonText(hBtn1, idsYES);
  544. SetDlgButtonText(hBtn2, idsNO);
  545. SetDlgButtonText(hBtn3, idsCANCEL);
  546. break;
  547. }
  548. default:
  549. AssertSz(FALSE, "Not a valid box type.");
  550. }
  551. }
  552. INT_PTR CALLBACK DontShowAgainDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  553. {
  554. switch(msg)
  555. {
  556. case WM_INITDIALOG:
  557. DoDontShowInitDialog(hwnd, (LPDONTSHOWPARAMS)lParam);
  558. return FALSE;
  559. case WM_COMMAND:
  560. if(GET_WM_COMMAND_ID(wParam, lParam) == IDOK ||
  561. GET_WM_COMMAND_ID(wParam, lParam) == IDYES ||
  562. GET_WM_COMMAND_ID(wParam, lParam) == IDNO ||
  563. GET_WM_COMMAND_ID(wParam, lParam) == IDCANCEL)
  564. // We'll put the yes, no, cancel return value in the HIWORD of
  565. // the return, and the don't show again status in the LOWORD.
  566. EndDialog(hwnd, (int) MAKELPARAM(IsDlgButtonChecked(hwnd, idchkDontShowMeAgain),
  567. GET_WM_COMMAND_ID(wParam, lParam)));
  568. }
  569. return FALSE;
  570. }
  571. LRESULT DoDontShowMeAgainDlg(HWND hwndOwner, LPCSTR pszRegString, LPTSTR pszTitle, LPTSTR pszMessage, UINT uType)
  572. {
  573. DWORD dwDontShow=0;
  574. LRESULT lResult;
  575. DONTSHOWPARAMS dlgParams;
  576. AssertSz(pszRegString, "Pass me a reg key string!");
  577. AssertSz(pszRegString, "Pass me a message to display!");
  578. AssertSz(pszRegString, "Pass me a title to display!");
  579. // read the folder view from the registry...
  580. dwDontShow = DwGetDontShowAgain (pszRegString);
  581. if (dwDontShow) // return what was stored as if the user clicked on the button stored
  582. return (LRESULT) dwDontShow;
  583. dlgParams.pszMessage = pszMessage;
  584. dlgParams.pszTitle = pszTitle;
  585. dlgParams.uType = uType;
  586. lResult = (LRESULT) DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddDontShow), hwndOwner,
  587. DontShowAgainDlgProc, (LPARAM)&dlgParams);
  588. if((IDCANCEL != HIWORD(lResult)) && LOWORD(lResult))
  589. {
  590. // save the dontshow flag
  591. SetDontShowAgain (HIWORD(lResult), pszRegString);
  592. }
  593. return (HIWORD(lResult));
  594. }
  595. HRESULT SubstituteWelcomeURLs(LPSTREAM pstmIn, LPSTREAM *ppstmOut)
  596. {
  597. HRESULT hr;
  598. IHTMLDocument2 *pDoc;
  599. LPSTREAM pstm=0;
  600. // BUGBUG: this cocreate should also go thro' the same code path as the DocHost one
  601. // so that if this is the first trident in the process, we keep it's CF around
  602. hr = MimeEditDocumentFromStream(pstmIn, IID_IHTMLDocument2, (LPVOID *)&pDoc);
  603. if (SUCCEEDED(hr))
  604. {
  605. URLSUB rgUrlSub[] = {
  606. { "mslink", idsHelpMSWebHome },
  607. { "certlink", idsHelpMSWebCert },
  608. };
  609. if (SUCCEEDED(hr = SubstituteURLs(pDoc, rgUrlSub, ARRAYSIZE(rgUrlSub))))
  610. {
  611. hr = MimeOleCreateVirtualStream(&pstm);
  612. if (!FAILED(hr))
  613. {
  614. IPersistStreamInit *pPSI;
  615. HrSetDirtyFlagImpl(pDoc, TRUE);
  616. hr = pDoc->QueryInterface(IID_IPersistStreamInit, (LPVOID*)&pPSI);
  617. if (!FAILED(hr))
  618. {
  619. hr = pPSI->Save(pstm, TRUE);
  620. pPSI->Release();
  621. }
  622. }
  623. }
  624. pDoc->Release();
  625. }
  626. if (!FAILED(hr))
  627. {
  628. Assert(pstm);
  629. *ppstmOut=pstm;
  630. pstm->AddRef();
  631. }
  632. ReleaseObj(pstm);
  633. return hr;
  634. }
  635. HRESULT IAddWelcomeMessage(IMessageFolder *pfolder, LPWABAL pWabal, LPCTSTR szFile, LPCTSTR szRes)
  636. {
  637. PROPVARIANT pv;
  638. SYSTEMTIME st;
  639. HRESULT hr;
  640. LPMIMEMESSAGE pMsg;
  641. LPSTREAM pstmBody,
  642. pstmSub,
  643. pstmStore;
  644. TCHAR sz[CCHMAX_STRINGRES];
  645. // Create the mail msg
  646. if (FAILED(hr = HrCreateMessage(&pMsg)))
  647. return(hr);
  648. HrSetWabalOnMsg(pMsg, pWabal);
  649. // Subject
  650. SideAssert(LoadString(g_hLocRes, idsWelcomeMessageSubj, sz, ARRAYSIZE(sz)));
  651. MimeOleSetBodyPropA(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_SUBJECT), NOFLAGS, sz);
  652. // Set Date
  653. pv.vt = VT_FILETIME;
  654. GetSystemTime(&st);
  655. SystemTimeToFileTime(&st, &pv.filetime);
  656. pMsg->SetProp(PIDTOSTR(PID_ATT_SENTTIME), 0, &pv);
  657. pstmBody = NULL;
  658. pstmSub = NULL;
  659. if (szFile == NULL || *szFile == 0)
  660. {
  661. if (SUCCEEDED(hr = HrLoadStreamFileFromResource(szRes, &pstmBody)))
  662. {
  663. if (SUCCEEDED(SubstituteWelcomeURLs(pstmBody, &pstmSub)))
  664. {
  665. pMsg->SetTextBody(TXT_HTML, IET_DECODED, NULL, pstmSub, NULL);
  666. pstmSub->Release();
  667. }
  668. else
  669. {
  670. pMsg->SetTextBody(TXT_HTML, IET_DECODED, NULL, pstmBody, NULL);
  671. }
  672. pstmBody->Release();
  673. }
  674. }
  675. else
  676. {
  677. if (SUCCEEDED(hr = OpenFileStream((TCHAR *)szFile, OPEN_EXISTING, GENERIC_READ, &pstmBody)))
  678. {
  679. pMsg->SetTextBody(TXT_HTML, IET_DECODED, NULL, pstmBody, NULL);
  680. pstmBody->Release();
  681. }
  682. }
  683. // Get a stream from the store
  684. if (SUCCEEDED(hr))
  685. {
  686. // set encoding options
  687. pv.vt = VT_UI4;
  688. pv.ulVal = SAVE_RFC1521;
  689. pMsg->SetOption(OID_SAVE_FORMAT, &pv);
  690. pv.ulVal = (ULONG)IET_QP;
  691. pMsg->SetOption(OID_TRANSMIT_TEXT_ENCODING, &pv);
  692. pv.boolVal = FALSE;
  693. pMsg->SetOption(OID_WRAP_BODY_TEXT, &pv);
  694. hr = pMsg->Commit(0);
  695. if (!FAILED(hr))
  696. {
  697. hr = pfolder->SaveMessage(NULL, SAVE_MESSAGE_GENID, NOFLAGS, 0, pMsg, NOSTORECALLBACK);
  698. }
  699. }
  700. pMsg->Release();
  701. return(hr);
  702. }
  703. static const TCHAR c_szWelcomeMsgHotmailHtm[] = TEXT("welcome.htm");
  704. static const TCHAR c_szWelcomeMsgHtm[] = TEXT("welcome2.htm");
  705. void AddWelcomeMessage(IMessageFolder *pfolder)
  706. {
  707. HRESULT hr;
  708. LPWABAL pWabal;
  709. TCHAR szName[CCHMAX_DISPLAY_NAME + 1],
  710. szEmail[CCHMAX_EMAIL_ADDRESS + 1],
  711. szFromName[CCHMAX_STRINGRES],
  712. szFromEmail[CCHMAX_STRINGRES],
  713. szHtm[MAX_PATH],
  714. szExpanded[MAX_PATH];
  715. LPTSTR psz = szHtm;
  716. DWORD type, cb;
  717. HKEY hkey;
  718. BOOL fName, fEmail, fFromName, fFromEmail;
  719. IImnEnumAccounts *pEnum;
  720. IImnAccount *pAccount;
  721. if (FAILED(HrCreateWabalObject(&pWabal)))
  722. return;
  723. fName = FALSE;
  724. fEmail = FALSE;
  725. fFromName = FALSE;
  726. fFromEmail = FALSE;
  727. *szHtm = 0;
  728. if (ERROR_SUCCESS == AthUserOpenKey(c_szRegPathMail, KEY_READ, &hkey))
  729. {
  730. cb = sizeof(szHtm);
  731. if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szWelcomeHtm, NULL, &type, (LPBYTE)szHtm, &cb))
  732. {
  733. if (REG_EXPAND_SZ == type)
  734. {
  735. ExpandEnvironmentStrings(szHtm, szExpanded, ARRAYSIZE(szExpanded));
  736. psz = szExpanded;
  737. }
  738. if (PathFileExists(psz))
  739. {
  740. cb = sizeof(szFromName);
  741. if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szWelcomeName, NULL, &type, (LPBYTE)szFromName, &cb) &&
  742. cb > sizeof(TCHAR))
  743. fFromName = TRUE;
  744. cb = sizeof(szFromEmail);
  745. if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szWelcomeEmail, NULL, &type, (LPBYTE)szFromEmail, &cb) &&
  746. cb > sizeof(TCHAR))
  747. fFromEmail = TRUE;
  748. }
  749. else
  750. {
  751. *psz = 0;
  752. }
  753. }
  754. RegCloseKey(hkey);
  755. }
  756. Assert(g_pAcctMan != NULL);
  757. if (SUCCEEDED(g_pAcctMan->Enumerate(SRV_IMAP | SRV_SMTP | SRV_POP3, &pEnum)))
  758. {
  759. Assert(pEnum != NULL);
  760. while (!fName || !fEmail)
  761. {
  762. hr = pEnum->GetNext(&pAccount);
  763. if (FAILED(hr) || pAccount == NULL)
  764. break;
  765. if (!fName)
  766. {
  767. if (!FAILED(pAccount->GetPropSz(AP_SMTP_DISPLAY_NAME, szName, ARRAYSIZE(szName)))
  768. && !FIsEmpty(szName))
  769. fName = TRUE;
  770. }
  771. if (!fEmail)
  772. {
  773. if (!FAILED(pAccount->GetPropSz(AP_SMTP_EMAIL_ADDRESS, szEmail, ARRAYSIZE(szEmail)))
  774. && SUCCEEDED(ValidEmailAddress(szEmail)))
  775. fEmail = TRUE;
  776. }
  777. pAccount->Release();
  778. }
  779. pEnum->Release();
  780. }
  781. // Add Recipient
  782. if (!fName)
  783. LoadString(g_hLocRes, idsNewAthenaUser, szName, ARRAYSIZE(szName));
  784. if (!fFromName)
  785. LoadString(g_hLocRes, idsWelcomeFromDisplay, szFromName, ARRAYSIZE(szFromName));
  786. if (!fFromEmail)
  787. LoadString(g_hLocRes, idsWelcomeFromEmail, szFromEmail, ARRAYSIZE(szFromEmail));
  788. // add recipient and sender
  789. if (SUCCEEDED(pWabal->HrAddEntryA(szName, fEmail ? szEmail : NULL, MAPI_TO)) &&
  790. SUCCEEDED(pWabal->HrAddEntryA(szFromName, szFromEmail, MAPI_ORIG)))
  791. {
  792. if (SUCCEEDED(IAddWelcomeMessage(pfolder, pWabal, psz, HideHotmail() ? c_szWelcomeMsgHtm:c_szWelcomeMsgHotmailHtm)))
  793. {
  794. SetDwOption(OPT_NEEDWELCOMEMSG, FALSE, NULL, 0);
  795. }
  796. }
  797. pWabal->Release();
  798. }
  799. // Direct WM_HELP/WM_CONTEXTMENU help here:
  800. BOOL OnContextHelp(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, HELPMAP const * rgCtxMap)
  801. {
  802. if (uMsg == WM_HELP)
  803. {
  804. LPHELPINFO lphi = (LPHELPINFO) lParam;
  805. if (lphi->iContextType == HELPINFO_WINDOW) // must be for a control
  806. {
  807. OEWinHelp ((HWND)lphi->hItemHandle,
  808. c_szCtxHelpFile,
  809. HELP_WM_HELP,
  810. (DWORD_PTR)(LPVOID)rgCtxMap);
  811. }
  812. return (TRUE);
  813. }
  814. else if (uMsg == WM_CONTEXTMENU)
  815. {
  816. OEWinHelp ((HWND) wParam,
  817. c_szCtxHelpFile,
  818. HELP_CONTEXTMENU,
  819. (DWORD_PTR)(LPVOID)rgCtxMap);
  820. return (TRUE);
  821. }
  822. Assert(0);
  823. return FALSE;
  824. }
  825. HRESULT HrSaveMessageToFile(HWND hwnd, LPMIMEMESSAGE pMsg, LPMIMEMESSAGE pDelSecMsg, BOOL fNews, BOOL fCanBeDirty)
  826. {
  827. OPENFILENAMEW ofn;
  828. WCHAR wszFile[MAX_PATH],
  829. wszTitle[CCHMAX_STRINGRES],
  830. wszFilter[MAX_PATH],
  831. wszDefExt[30];
  832. LPWSTR pwszSubject=0;
  833. HRESULT hr;
  834. int rgidsSaveAsFilter[SAVEAS_NUMTYPES],
  835. rgFilterType[SAVEAS_NUMTYPES],
  836. cFilter=0;
  837. DWORD dwFlags=0;
  838. if(!pMsg || !hwnd)
  839. return E_INVALIDARG;
  840. *wszDefExt=0;
  841. *wszTitle=0;
  842. *wszFile=0;
  843. *wszFilter=0;
  844. pMsg->GetFlags(&dwFlags);
  845. // Load Res Strings
  846. rgidsSaveAsFilter[cFilter] = fNews?idsNwsFileFilter:idsEmlFileFilter;
  847. rgFilterType[cFilter++] = SAVEAS_RFC822;
  848. AthLoadStringW(fNews?idsDefNewsExt:idsDefMailExt, wszDefExt, ARRAYSIZE(wszDefExt));
  849. if (dwFlags & IMF_PLAIN)
  850. {
  851. rgidsSaveAsFilter[cFilter] = idsTextFileFilter;
  852. rgFilterType[cFilter++] = SAVEAS_TEXT;
  853. rgidsSaveAsFilter[cFilter] = idsUniTextFileFilter;
  854. rgFilterType[cFilter++] = SAVEAS_UNICODETEXT;
  855. }
  856. if (dwFlags & IMF_HTML)
  857. {
  858. rgidsSaveAsFilter[cFilter] = idsHtmlFileFilter;
  859. rgFilterType[cFilter++] = SAVEAS_HTML;
  860. }
  861. CombineFiltersW(rgidsSaveAsFilter, cFilter, wszFilter);
  862. AthLoadStringW(idsMailSaveAsTitle, wszTitle, ARRAYSIZE(wszTitle));
  863. // Use Subject ?
  864. hr=MimeOleGetBodyPropW(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_SUBJECT), NOFLAGS, &pwszSubject);
  865. if (!FAILED(hr))
  866. {
  867. wnsprintfW(wszFile, ARRAYSIZE(wszFile), L"%.240s", pwszSubject);
  868. // Bug 84793. "." is not valid char for filename: "test.com"
  869. ULONG ich=0;
  870. ULONG cch=lstrlenW(wszFile);
  871. // Loop and remove invalids
  872. while (ich < cch)
  873. {
  874. // Illeagl file name character ?
  875. if (!FIsValidFileNameCharW(wszFile[ich]) || (wszFile[ich] == L'.'))
  876. wszFile[ich]=L'_';
  877. ich++;
  878. }
  879. }
  880. // Setup Save file struct
  881. ZeroMemory (&ofn, sizeof (ofn));
  882. ofn.lStructSize = sizeof (ofn);
  883. ofn.hwndOwner = hwnd;
  884. ofn.lpstrFilter = wszFilter;
  885. ofn.nFilterIndex = 1;
  886. ofn.lpstrFile = wszFile;
  887. ofn.nMaxFile = ARRAYSIZE(wszFile);
  888. ofn.lpstrTitle = wszTitle;
  889. ofn.lpstrDefExt = wszDefExt;
  890. ofn.Flags = OFN_NOREADONLYRETURN | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
  891. // Show SaveAs Dialog
  892. if (HrAthGetFileNameW(&ofn, FALSE)!=S_OK)
  893. {
  894. // usercancel is cool.
  895. hr=hrUserCancel;
  896. goto error;
  897. }
  898. // ofn.nFilterIndex returns the currently selected filter. this is the index into
  899. // the filter pair specified by lpstrFilter = idsMailSaveAsFilter. currently:
  900. // 1 => eml
  901. // 2 => txt
  902. // 3 => unicode txt
  903. // 4 => html
  904. Assert ((int)ofn.nFilterIndex -1 < cFilter);
  905. if(ofn.nFilterIndex != SAVEAS_RFC822)
  906. {
  907. if(IsEncrypted(pMsg, TRUE))
  908. {
  909. if(AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsSaveEncrypted), NULL, MB_YESNO) == IDNO)
  910. {
  911. hr=hrUserCancel;
  912. goto error;
  913. }
  914. }
  915. hr = HrSaveMsgSourceToFile((pDelSecMsg ? pDelSecMsg : pMsg), rgFilterType[ofn.nFilterIndex-1], wszFile, fCanBeDirty);
  916. }
  917. else
  918. hr = HrSaveMsgSourceToFile(pMsg, rgFilterType[ofn.nFilterIndex-1], wszFile, fCanBeDirty);
  919. error:
  920. MemFree(pwszSubject);
  921. if (FAILED(hr) && hr!=hrUserCancel)
  922. AthErrorMessageW(hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsUnableToSaveMessage), hr);
  923. return hr;
  924. };
  925. VOID OnHelpGoto(HWND hwnd, UINT id)
  926. {
  927. UINT idh;
  928. DWORD cb;
  929. HRESULT hr;
  930. CLSID clsid;
  931. LPWSTR pwszCLSID;
  932. IContextMenu *pMenu;
  933. CMINVOKECOMMANDINFO info;
  934. TCHAR szURL[INTERNET_MAX_URL_LENGTH];
  935. if (id == ID_MSWEB_SEARCH)
  936. {
  937. cb = sizeof(szURL);
  938. if (ERROR_SUCCESS == RegQueryValue(HKEY_LOCAL_MACHINE, c_szRegIEWebSearch, szURL, (LONG *)&cb))
  939. {
  940. pwszCLSID = PszToUnicode(CP_ACP, szURL);
  941. if (pwszCLSID != NULL)
  942. {
  943. hr = CLSIDFromString(pwszCLSID, &clsid);
  944. if (SUCCEEDED(hr))
  945. {
  946. hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IContextMenu, (void **)&pMenu);
  947. if (SUCCEEDED(hr))
  948. {
  949. ZeroMemory(&info, sizeof(CMINVOKECOMMANDINFO));
  950. info.cbSize = sizeof(CMINVOKECOMMANDINFO);
  951. info.hwnd = hwnd;
  952. pMenu->InvokeCommand(&info);
  953. pMenu->Release();
  954. }
  955. }
  956. MemFree(pwszCLSID);
  957. }
  958. }
  959. return;
  960. }
  961. hr = E_FAIL;
  962. if (id == ID_MSWEB_SUPPORT)
  963. {
  964. cb = sizeof(szURL);
  965. if (ERROR_SUCCESS == AthUserGetValue(NULL, c_szRegHelpUrl, NULL, (LPBYTE)szURL, &cb) &&
  966. !FIsEmpty(szURL))
  967. hr = S_OK;
  968. }
  969. if (hr != S_OK)
  970. {
  971. idh = id - ID_MSWEB_BASE;
  972. hr = URLSubLoadStringA(idsHelpMSWebFirst + idh, szURL, ARRAYSIZE(szURL), URLSUB_ALL, NULL);
  973. }
  974. if (SUCCEEDED(hr))
  975. ShellExecute(NULL, "open", szURL, c_szEmpty, c_szEmpty, SW_SHOWNORMAL);
  976. }
  977. VOID OnMailGoto(HWND hwnd)
  978. {
  979. OpenClient(hwnd, c_szRegPathMail);
  980. }
  981. VOID OnNewsGoto(HWND hwnd)
  982. {
  983. OpenClient(hwnd, c_szRegPathNews);
  984. }
  985. // Get the command line to launch the requested client.
  986. BOOL GetClientCmdLine(LPCTSTR szClient, LPTSTR szCmdLine, int cch)
  987. {
  988. HKEY hKey = 0;
  989. TCHAR sz[MAX_PATH];
  990. TCHAR szClientKey[MAX_PATH];
  991. TCHAR szClientPath[MAX_PATH];
  992. TCHAR szExpanded[MAX_PATH];
  993. LPTSTR psz;
  994. DWORD dwType;
  995. DWORD cb;
  996. szCmdLine[0] = 0;
  997. wnsprintf(sz, ARRAYSIZE(sz), TEXT("%s%s%s"), c_szRegPathClients, g_szBackSlash, szClient);
  998. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, sz, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
  999. goto LErr;
  1000. cb = ARRAYSIZE(szClientKey);
  1001. if (RegQueryValueEx(hKey, c_szEmpty, NULL, &dwType, (LPBYTE) szClientKey, &cb) != ERROR_SUCCESS)
  1002. goto LErr;
  1003. if (dwType != REG_SZ || szClientKey[0] == 0)
  1004. goto LErr;
  1005. StrCatBuff(sz, g_szBackSlash, ARRAYSIZE(sz));
  1006. StrCatBuff(sz, szClientKey, ARRAYSIZE(sz));
  1007. StrCatBuff(sz, g_szBackSlash, ARRAYSIZE(sz));
  1008. StrCatBuff(sz, c_szRegClientPath, ARRAYSIZE(sz));
  1009. if (RegCloseKey(hKey) != ERROR_SUCCESS)
  1010. goto LErr;
  1011. hKey = 0;
  1012. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, sz, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
  1013. goto LErr;
  1014. cb = ARRAYSIZE(szClientPath);
  1015. if (RegQueryValueEx(hKey, c_szEmpty, NULL, &dwType, (LPBYTE) szClientPath, &cb) != ERROR_SUCCESS)
  1016. goto LErr;
  1017. if (REG_EXPAND_SZ == dwType)
  1018. {
  1019. ExpandEnvironmentStrings(szClientPath, szExpanded, ARRAYSIZE(szExpanded));
  1020. psz = szExpanded;
  1021. }
  1022. else if (dwType != REG_SZ || szClientPath[0] == 0)
  1023. goto LErr;
  1024. else
  1025. psz=szClientPath;
  1026. StrCpyN(szCmdLine, psz, cch);
  1027. LErr:
  1028. if (hKey)
  1029. RegCloseKey(hKey);
  1030. return (szCmdLine[0] != '\0');
  1031. }
  1032. VOID OpenClient(HWND hwnd, LPCTSTR szClient)
  1033. {
  1034. TCHAR szCmdLine[MAX_PATH];
  1035. if (!GetClientCmdLine(szClient, szCmdLine, MAX_PATH))
  1036. {
  1037. // TODO: Report error
  1038. return;
  1039. }
  1040. ShellExecute(hwnd, NULL, szCmdLine, NULL, NULL, SW_SHOW);
  1041. }
  1042. VOID OnBrowserGoto(HWND hwnd, LPCTSTR szRegPage, UINT idDefault)
  1043. {
  1044. HKEY hKey = 0;
  1045. TCHAR szStartPage[INTERNET_MAX_URL_LENGTH];
  1046. DWORD dw;
  1047. DWORD cb;
  1048. if (RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegStartPageKey, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
  1049. return;
  1050. szStartPage[0] = 0;
  1051. cb = sizeof(szStartPage) / sizeof(TCHAR);
  1052. if (RegQueryValueEx(hKey, szRegPage, NULL, &dw, (LPBYTE) szStartPage, &cb) != ERROR_SUCCESS ||
  1053. dw != REG_SZ ||
  1054. szStartPage[0] == 0)
  1055. {
  1056. URLSubLoadStringA(idDefault, szStartPage, ARRAYSIZE(szStartPage), URLSUB_ALL, NULL);
  1057. }
  1058. if (szStartPage[0])
  1059. ShellExecute(NULL, NULL, szStartPage, "", "", SW_SHOWNORMAL);
  1060. if (hKey)
  1061. RegCloseKey(hKey);
  1062. }
  1063. // --------------------------------------------------------------------------------
  1064. // AthLoadStringW
  1065. // --------------------------------------------------------------------------------
  1066. LPWSTR AthLoadStringW(UINT id, LPWSTR sz, int cch)
  1067. {
  1068. LPWSTR szT;
  1069. if (sz == NULL)
  1070. {
  1071. if (!MemAlloc((LPVOID*)&szT, CCHMAX_STRINGRES*sizeof(WCHAR)))
  1072. return(NULL);
  1073. cch = CCHMAX_STRINGRES;
  1074. }
  1075. else
  1076. szT = sz;
  1077. cch = LoadStringWrapW(g_hLocRes, id, szT, cch);
  1078. Assert(cch > 0);
  1079. if (cch == 0)
  1080. {
  1081. if (sz == NULL)
  1082. MemFree(szT);
  1083. szT = NULL;
  1084. }
  1085. return(szT);
  1086. }
  1087. // --------------------------------------------------------------------------------
  1088. // AthLoadString
  1089. // --------------------------------------------------------------------------------
  1090. LPTSTR AthLoadString(UINT id, LPTSTR sz, int cch)
  1091. {
  1092. LPTSTR szT;
  1093. if (sz == NULL)
  1094. {
  1095. if (!MemAlloc((LPVOID*)&szT, CCHMAX_STRINGRES))
  1096. return(NULL);
  1097. cch = CCHMAX_STRINGRES;
  1098. }
  1099. else
  1100. szT = sz;
  1101. cch = LoadString(g_hLocRes, id, szT, cch);
  1102. Assert(cch > 0);
  1103. if (cch == 0)
  1104. {
  1105. if (sz == NULL)
  1106. MemFree(szT);
  1107. szT = NULL;
  1108. }
  1109. return(szT);
  1110. }
  1111. /*
  1112. * hwnd - hwnd for error UI
  1113. * fHtmlOk - if html sigs are cool or not. If not and a html sig is chosen it will be spewed as plain-text
  1114. * pdwSigOpts - returns sig options
  1115. * pbstr - returns a BSTR of the HTML signature
  1116. * uCodePage - codepage to use when converting multibyte
  1117. * fMail - use mail or news options
  1118. */
  1119. HRESULT HrGetMailNewsSignature(GETSIGINFO *pSigInfo, LPDWORD pdwSigOptions, BSTR *pbstr)
  1120. {
  1121. PROPVARIANT var;
  1122. IOptionBucket *pSig = NULL;
  1123. TCHAR szSigID[MAXSIGID+2];
  1124. unsigned char rgchSig[MAX_SIG_SIZE+2]; // might have to append a unicode null
  1125. unsigned char *pszSig;
  1126. DWORD dwSigOptions;
  1127. LPSTREAM pstm=0;
  1128. ULONG i,
  1129. cb=0;
  1130. BOOL fFile,
  1131. fUniPlainText = FALSE;
  1132. LPWSTR lpwsz=0;
  1133. LPSTR lpsz=0;
  1134. HRESULT hr;
  1135. BSTR bstr=0;
  1136. Assert(pSigInfo != NULL);
  1137. Assert(pdwSigOptions != NULL);
  1138. dwSigOptions = SIGOPT_TOP;
  1139. if (!pSigInfo->fMail) // news sigs. always have the prefix.
  1140. dwSigOptions |= SIGOPT_PREFIX;
  1141. *szSigID = 0;
  1142. if (pSigInfo->szSigID != NULL)
  1143. {
  1144. Assert(*pSigInfo->szSigID != 0);
  1145. StrCpyN((LPTSTR)szSigID, pSigInfo->szSigID, ARRAYSIZE(szSigID));
  1146. }
  1147. else if (pSigInfo->pAcct != NULL)
  1148. {
  1149. pSigInfo->pAcct->GetPropSz(pSigInfo->fMail ? AP_SMTP_SIGNATURE : AP_NNTP_SIGNATURE,
  1150. (LPTSTR)szSigID, ARRAYSIZE(szSigID));
  1151. // TODO: should we validate the sig here???
  1152. // if the sig has been deleted and for some reason the acct wasn't updated, this
  1153. // could point to a non-existent sig or a different sig. this shouldn't happen if
  1154. // everything else works properly...
  1155. }
  1156. if (*szSigID == 0)
  1157. {
  1158. Assert(g_pSigMgr != NULL);
  1159. hr = g_pSigMgr->GetDefaultSignature((LPTSTR)szSigID, ARRAYSIZE(szSigID));
  1160. if (FAILED(hr))
  1161. return(hr);
  1162. }
  1163. hr = g_pSigMgr->GetSignature((LPTSTR)szSigID, &pSig);
  1164. if (FAILED(hr))
  1165. return(hr);
  1166. Assert(pSig != NULL);
  1167. hr = pSig->GetProperty(MAKEPROPSTRING(SIG_TYPE), &var, 0);
  1168. Assert(SUCCEEDED(hr));
  1169. Assert(var.vt == VT_UI4);
  1170. fFile = (var.ulVal == SIGTYPE_FILE);
  1171. hr = pSig->GetProperty(fFile ? MAKEPROPSTRING(SIG_FILE) : MAKEPROPSTRING(SIG_TEXT), &var, 0);
  1172. Assert(SUCCEEDED(hr));
  1173. if(fFile)
  1174. {
  1175. Assert(var.vt == VT_LPWSTR);
  1176. Assert(var.pwszVal != NULL);
  1177. lpwsz = var.pwszVal;
  1178. }
  1179. else
  1180. {
  1181. Assert(var.vt == VT_LPSTR);
  1182. Assert(var.pszVal != NULL);
  1183. lpsz = var.pszVal;
  1184. }
  1185. if (fFile && FIsHTMLFileW(lpwsz))
  1186. dwSigOptions |= SIGOPT_HTML; // we're giving back a HTML sig
  1187. if (pbstr)
  1188. {
  1189. *pbstr = 0;
  1190. if (!fFile)
  1191. {
  1192. StrCpyN((char *)rgchSig, lpsz, ARRAYSIZE(rgchSig));
  1193. }
  1194. else
  1195. {
  1196. // if it has a htm or html extension then assume it's a html file
  1197. hr=CreateStreamOnHFileW(lpwsz, GENERIC_READ, FILE_SHARE_READ, NULL,
  1198. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL, &pstm);
  1199. if (FAILED(hr))
  1200. {
  1201. DWORD dwErr;
  1202. dwErr=GetLastError();
  1203. if(dwErr==ERROR_PATH_NOT_FOUND || dwErr==ERROR_FILE_NOT_FOUND)
  1204. {
  1205. // Don't turn off auto sig settings, just remove current.
  1206. g_pSigMgr->DeleteSignature((LPTSTR)szSigID);
  1207. // if filenotfound, warn user and disable the option
  1208. AthMessageBoxW(pSigInfo->hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsWarnSigNotFound), NULL, MB_OK);
  1209. }
  1210. goto error;
  1211. }
  1212. // perform the boundary check and binary check only on signature files
  1213. // on others, we let them insert whatever they want.
  1214. *rgchSig=0;
  1215. pstm->Read(rgchSig, MAX_SIG_SIZE, &cb);
  1216. rgchSig[cb]=0; // null term
  1217. pszSig=rgchSig;
  1218. fUniPlainText = ((cb > 2) && (0xFF == pszSig[0]) && (0xFE == pszSig[1]) && (0 == (dwSigOptions & SIGOPT_HTML)));
  1219. if (!fUniPlainText)
  1220. for(i=0; i<cb; i++)
  1221. {
  1222. if(IS_BINARY(*pszSig))
  1223. {
  1224. // Don't turn off auto sig settings, just remove current.
  1225. g_pSigMgr->DeleteSignature((LPTSTR)szSigID);
  1226. // signature contains invalid binary. Fail and disable option
  1227. AthMessageBoxW(pSigInfo->hwnd, MAKEINTRESOURCEW(idsAthena),
  1228. MAKEINTRESOURCEW(idsWarnSigBinary), NULL, MB_OK);
  1229. hr=E_FAIL;
  1230. goto error;
  1231. }
  1232. pszSig++;
  1233. }
  1234. // warn that size is too large and we have truncated. Don't disable option
  1235. if(cb==MAX_SIG_SIZE)
  1236. {
  1237. AthMessageBoxW(pSigInfo->hwnd, MAKEINTRESOURCEW(idsAthena),
  1238. MAKEINTRESOURCEW(idsWarnSigTruncated),
  1239. NULL, MB_OK);
  1240. }
  1241. SafeRelease(pstm);
  1242. }
  1243. // pstm contains our MultiByte data, let's convert the first cb bytes to a WideStream
  1244. if (dwSigOptions & SIGOPT_HTML)
  1245. {
  1246. if (pSigInfo->fHtmlOk)
  1247. {
  1248. // the sig is already HTML. Let's just alloc a bstr
  1249. hr = HrLPSZCPToBSTR(pSigInfo->uCodePage, (LPSTR)rgchSig, pbstr);
  1250. }
  1251. else
  1252. {
  1253. // the sig is HTML, but that's not cool. So let's downgrade it to plain-text
  1254. LPSTREAM pstmPlainW;
  1255. ULARGE_INTEGER uli;
  1256. // if the signature is HTML and the user want's a plain-text signature. They we need to convert the HTML to plain-text (strip formatting)
  1257. // and then convert the stripped plain-text to HTML.
  1258. Assert (pstm==NULL);
  1259. if (FAILED(hr=MimeOleCreateVirtualStream(&pstm)))
  1260. goto error;
  1261. pstm->Write(rgchSig, cb, NULL);
  1262. // $REVIEW: this is a little odd. For a non-html sig file, we'll use the codepage that
  1263. // the message is in (passed into this function). For a html file, we'll let Trident parse
  1264. // the meta tag and figure out the code page as we convert to plain-text via trident
  1265. if (!FAILED(hr=HrConvertHTMLToPlainText(pstm, &pstmPlainW, CF_UNICODETEXT)))
  1266. {
  1267. hr = HrIStreamWToBSTR(pstmPlainW, pbstr);
  1268. pstmPlainW->Release();
  1269. }
  1270. }
  1271. }
  1272. else
  1273. {
  1274. // the signature is Plain-Text
  1275. if (fUniPlainText)
  1276. {
  1277. // We had added an ANSI NULL, now let's make it a unicode null
  1278. rgchSig[cb+1] = 0;
  1279. *pbstr = SysAllocString((LPWSTR)(&rgchSig[2]));
  1280. if (NULL == pbstr)
  1281. hr = E_OUTOFMEMORY;
  1282. }
  1283. else
  1284. hr = HrLPSZCPToBSTR(pSigInfo->uCodePage, (LPSTR)rgchSig, pbstr);
  1285. }
  1286. AssertSz((FAILED(hr) || *pbstr), "how come we succeeded with no BSTR allocated?");
  1287. }
  1288. *pdwSigOptions = dwSigOptions;
  1289. error:
  1290. MemFree(lpwsz);
  1291. MemFree(lpsz);
  1292. SafeRelease(pstm);
  1293. SafeRelease(pSig);
  1294. return hr;
  1295. }
  1296. HRESULT HrSaveMsgSourceToFile(LPMIMEMESSAGE pMsg, DWORD dwSaveAs, LPWSTR pwszFile, BOOL fCanBeDirty)
  1297. {
  1298. LPSTREAM pstmFile=0,
  1299. pstm=0;
  1300. HRESULT hr;
  1301. TCHAR sz[CCHMAX_STRINGRES],
  1302. szCset[CCHMAX_CSET_NAME];
  1303. HCHARSET hCharset;
  1304. hr = CreateStreamOnHFileW(pwszFile, GENERIC_READ|GENERIC_WRITE, NULL,
  1305. NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0, &pstmFile);
  1306. if (FAILED(hr))
  1307. goto error;
  1308. //N need to be able to save txt files as insecure messages
  1309. switch(dwSaveAs)
  1310. {
  1311. case SAVEAS_RFC822:
  1312. hr = pMsg->GetMessageSource(&pstm, fCanBeDirty ? COMMIT_ONLYIFDIRTY : 0);
  1313. break;
  1314. case SAVEAS_TEXT:
  1315. hr = HrGetDataStream((LPUNKNOWN)pMsg, CF_TEXT, &pstm);
  1316. break;
  1317. case SAVEAS_UNICODETEXT:
  1318. hr = HrGetDataStream((LPUNKNOWN)pMsg, CF_UNICODETEXT, &pstm);
  1319. if (SUCCEEDED(hr))
  1320. {
  1321. BYTE bUniMark = 0xFF;
  1322. hr = pstmFile->Write(&bUniMark, sizeof(bUniMark), NULL);
  1323. if (SUCCEEDED(hr))
  1324. {
  1325. bUniMark = 0xFE;
  1326. hr = pstmFile->Write(&bUniMark, sizeof(bUniMark), NULL);
  1327. }
  1328. }
  1329. break;
  1330. case SAVEAS_HTML:
  1331. // if saving as HTML always get the internet cset
  1332. hr = pMsg->GetTextBody(TXT_HTML, IET_INETCSET, &pstm, NULL);
  1333. break;
  1334. default:
  1335. break;
  1336. hr = E_FAIL;
  1337. }
  1338. if (FAILED(hr))
  1339. goto error;
  1340. hr = HrRewindStream(pstm);
  1341. if (FAILED(hr))
  1342. goto error;
  1343. if (dwSaveAs == SAVEAS_HTML)
  1344. {
  1345. // if saving as HTML, append a meta charset into the head of the document
  1346. if (SUCCEEDED(pMsg->GetCharset(&hCharset)) && SUCCEEDED(HrGetMetaTagName(hCharset, szCset, ARRAYSIZE(szCset))))
  1347. {
  1348. wnsprintf(sz, ARRAYSIZE(sz), c_szHtml_MetaTagf, szCset);
  1349. pstmFile->Write(sz, lstrlen(sz)*sizeof(*sz), NULL);
  1350. }
  1351. }
  1352. hr = HrCopyStream(pstm, pstmFile, NULL);
  1353. if (FAILED(hr))
  1354. goto error;
  1355. hr = pstmFile->Commit(STGC_DEFAULT);
  1356. if (FAILED(hr))
  1357. goto error;
  1358. error:
  1359. ReleaseObj(pstm);
  1360. ReleaseObj(pstmFile);
  1361. return hr;
  1362. }
  1363. void nyi(LPSTR lpsz)
  1364. {
  1365. TCHAR rgch[CCHMAX_STRINGRES];
  1366. TCHAR rgchNYI[CCHMAX_STRINGRES];
  1367. if (IS_INTRESOURCE(lpsz))
  1368. {
  1369. // its a string resource id
  1370. if (!LoadString(g_hLocRes, PtrToUlong(lpsz), rgch, CCHMAX_STRINGRES))
  1371. return;
  1372. lpsz = rgch;
  1373. }
  1374. if (!LoadString(g_hLocRes, idsNYITitle, rgchNYI, CCHMAX_STRINGRES))
  1375. return;
  1376. MessageBox(GetFocus(), lpsz, rgchNYI, MB_OK|MB_ICONSTOP|MB_SETFOREGROUND);
  1377. }
  1378. //NOTE: if *ppstm == NULL, then the stream is created.
  1379. //Otherwise it is written to.
  1380. HRESULT HrLoadStreamFileFromResource(LPCSTR lpszResourceName, LPSTREAM *ppstm)
  1381. {
  1382. HRESULT hr=E_FAIL;
  1383. HRSRC hres;
  1384. HGLOBAL hGlobal;
  1385. LPBYTE pb;
  1386. DWORD cb;
  1387. if (!ppstm || !lpszResourceName)
  1388. return E_INVALIDARG;
  1389. hres = FindResource(g_hLocRes, lpszResourceName, MAKEINTRESOURCE(RT_FILE));
  1390. if (!hres)
  1391. goto error;
  1392. hGlobal = LoadResource(g_hLocRes, hres);
  1393. if (!hGlobal)
  1394. goto error;
  1395. pb = (LPBYTE)LockResource(hGlobal);
  1396. if (!pb)
  1397. goto error;
  1398. cb = SizeofResource(g_hLocRes, hres);
  1399. if (!cb)
  1400. goto error;
  1401. if (*ppstm)
  1402. hr = (*ppstm)->Write(pb, cb, NULL);
  1403. else
  1404. {
  1405. if (SUCCEEDED(hr = MimeOleCreateVirtualStream(ppstm)))
  1406. hr = (*ppstm)->Write (pb, cb, NULL);
  1407. }
  1408. error:
  1409. return hr;
  1410. }
  1411. void ConvertTabsToSpaces(LPSTR lpsz)
  1412. {
  1413. if (lpsz)
  1414. {
  1415. while(*lpsz)
  1416. {
  1417. if (*lpsz == '\t')
  1418. *lpsz = ' ';
  1419. lpsz=CharNext(lpsz);
  1420. }
  1421. }
  1422. }
  1423. void ConvertTabsToSpacesW(LPWSTR lpsz)
  1424. {
  1425. if (lpsz)
  1426. {
  1427. while(*lpsz)
  1428. {
  1429. if (*lpsz == L'\t')
  1430. *lpsz = L' ';
  1431. lpsz++;
  1432. }
  1433. }
  1434. }
  1435. // =================================================================================
  1436. // From strutil.cpp
  1437. // =================================================================================
  1438. #define SPECIAL_CHAR '|'
  1439. #define SPECIAL_CHAR_W L'|'
  1440. int LoadStringReplaceSpecial(UINT id, LPTSTR sz, int cch)
  1441. {
  1442. int cchRet=0;
  1443. if(sz)
  1444. {
  1445. cchRet=LoadString(g_hLocRes, id, sz, cch);
  1446. ReplaceChars(sz, SPECIAL_CHAR, '\0');
  1447. }
  1448. return cchRet;
  1449. }
  1450. int LoadStringReplaceSpecialW(UINT id, LPWSTR wsz, int cch)
  1451. {
  1452. int cchRet=0;
  1453. if(wsz)
  1454. {
  1455. cchRet=LoadStringWrapW(g_hLocRes, id, wsz, cch);
  1456. ReplaceCharsW(wsz, SPECIAL_CHAR_W, L'\0');
  1457. }
  1458. return cchRet;
  1459. }
  1460. void CombineFilters(int *rgidsFilter, int nFilters, LPSTR pszFilter)
  1461. {
  1462. DWORD cchFilter,
  1463. dw,
  1464. cch;
  1465. Assert (rgidsFilter);
  1466. Assert (nFilters);
  1467. Assert (pszFilter);
  1468. // we pray to the resource-editing gods that rgchFilter (MAX_PATH) is big enough...
  1469. *pszFilter = 0;
  1470. cchFilter = 0;
  1471. for (dw = 0; dw < (DWORD)nFilters; dw++)
  1472. {
  1473. cch = LoadStringReplaceSpecial(rgidsFilter[dw], &pszFilter[cchFilter], MAX_PATH);
  1474. Assert(cch);
  1475. cchFilter += cch-1; // -1 as each filter is double null terminated
  1476. }
  1477. }
  1478. void CombineFiltersW(int *rgidsFilter, int nFilters, LPWSTR pwszFilter)
  1479. {
  1480. DWORD cchFilter,
  1481. dw,
  1482. cch;
  1483. Assert (rgidsFilter);
  1484. Assert (nFilters);
  1485. Assert (pwszFilter);
  1486. // we pray to the resource-editing gods that rgchFilter (MAX_PATH) is big enough...
  1487. *pwszFilter = 0;
  1488. cchFilter = 0;
  1489. for (dw = 0; dw < (DWORD)nFilters; dw++)
  1490. {
  1491. cch = LoadStringReplaceSpecialW(rgidsFilter[dw], &pwszFilter[cchFilter], MAX_PATH);
  1492. Assert(cch);
  1493. cchFilter += cch-1; // -1 as each filter is double null terminated
  1494. }
  1495. }
  1496. void AthFormatSizeK(DWORD dw, LPTSTR szOut, UINT uiBufSize)
  1497. {
  1498. TCHAR szFmt[CCHMAX_STRINGRES];
  1499. TCHAR szBuf[CCHMAX_STRINGRES];
  1500. AthLoadString(idsFormatK, szFmt, ARRAYSIZE(szFmt));
  1501. if (dw == 0)
  1502. wnsprintf(szBuf, ARRAYSIZE(szBuf), szFmt, 0);
  1503. else if (dw <= 1024)
  1504. wnsprintf(szBuf, ARRAYSIZE(szBuf), szFmt, 1);
  1505. else
  1506. wnsprintf(szBuf, ARRAYSIZE(szBuf), szFmt, (dw + 512) / 1024);
  1507. StrCpyN(szOut, szBuf, uiBufSize);
  1508. }
  1509. void GetDigitalIDs(IImnAccount *pCertAccount)
  1510. {
  1511. HRESULT hr;
  1512. TCHAR szTemp[INTERNET_MAX_URL_LENGTH];
  1513. TCHAR szURL[INTERNET_MAX_URL_LENGTH];
  1514. DWORD cchOut = ARRAYSIZE(szURL);
  1515. CHAR szIexplore[MAX_PATH];
  1516. if (FAILED(hr = URLSubLoadStringA(idsHelpMSWebCertSubName, szTemp, ARRAYSIZE(szTemp), URLSUB_ALL, pCertAccount)) ||
  1517. FAILED(hr = UrlEscape(szTemp, szURL, &cchOut, URL_ESCAPE_SPACES_ONLY)))
  1518. hr = URLSubLoadStringA(idsHelpMSWebCert, szURL, ARRAYSIZE(szURL), URLSUB_ALL, pCertAccount);
  1519. // NOTE: we shellexec iexplore.exe here NOT the default handler for http://
  1520. // links. We have to make sure we launch this link with IE even if
  1521. // netscape is the browser. see georgeh for explanation of why.
  1522. if (SUCCEEDED(hr) && GetExePath(c_szIexploreExe, szIexplore, ARRAYSIZE(szIexplore), FALSE))
  1523. ShellExecute(NULL, "open", szIexplore, szURL, NULL, SW_SHOWNORMAL);
  1524. }
  1525. BOOL FGetSelectedCachedMsg(IMsgContainer *pIMC, HWND hwndList, BOOL fSecure, LPMIMEMESSAGE *ppMsg)
  1526. {
  1527. int iSel;
  1528. BOOL fCached = FALSE;
  1529. // Get the selected article header from the list view
  1530. iSel = ListView_GetFirstSel(hwndList);
  1531. if (-1 != iSel)
  1532. {
  1533. Assert(pIMC);
  1534. if (pIMC->HasBody(iSel))
  1535. pIMC->GetMsgByIndex(iSel, ppMsg, NULL, &fCached, FALSE, fSecure);
  1536. }
  1537. return fCached;
  1538. }
  1539. //---------------------------------------------------------------------------
  1540. // Cached Password Support
  1541. //---------------------------------------------------------------------------
  1542. //-----------------
  1543. // Data Structures
  1544. //-----------------
  1545. typedef struct tagCACHED_PASSWORD {
  1546. DWORD dwPort;
  1547. char szServer[CCHMAX_SERVER_NAME];
  1548. char szUsername[CCHMAX_PASSWORD];
  1549. char szPassword[CCHMAX_PASSWORD];
  1550. struct tagCACHED_PASSWORD *pNext;
  1551. } CACHED_PASSWORD;
  1552. //------------------
  1553. // Static Variables
  1554. //------------------
  1555. static CACHED_PASSWORD *s_pPasswordList = NULL;
  1556. //***************************************************************************
  1557. // Function: SavePassword
  1558. //
  1559. // Purpose:
  1560. // This function saves a password for later retrieval using GetPassword.
  1561. // It allows OE to cache passwords for the session in order to avoid asking
  1562. // a user for his password more than once. If the given password has already
  1563. // been cached, this function replaces the old password with the new password.
  1564. // It is assumed that a password's recipient may be uniquely identified
  1565. // by servername and port number.
  1566. //
  1567. // Arguments:
  1568. // DWORD dwPort [in] - the port number of the server we are trying to
  1569. // connect to. This allows us to keep separate passwords for SMTP and
  1570. // POP/IMAP servers on the same machine.
  1571. // LPSTR pszServer [in] - the server name for which the password was
  1572. // supplied. Server names are treated as case-insensitive.
  1573. // LPSTR pszUsername [in] - the username for which the password was supplied.
  1574. // LPSTR pszPassword [in] - the password for this server and port number.
  1575. //
  1576. // Returns:
  1577. // HRESULT indicating success or failure.
  1578. //***************************************************************************
  1579. HRESULT SavePassword(DWORD dwPort, LPSTR pszServer, LPSTR pszUsername, LPSTR pszPassword)
  1580. {
  1581. CACHED_PASSWORD *pExisting;
  1582. HRESULT hrResult = S_OK;
  1583. EnterCriticalSection(&s_csPasswordList);
  1584. // Check if we already have a cached password entry for this server
  1585. pExisting = s_pPasswordList;
  1586. while (NULL != pExisting)
  1587. {
  1588. if (dwPort == pExisting->dwPort &&
  1589. 0 == lstrcmpi(pszServer, pExisting->szServer) &&
  1590. 0 == lstrcmp(pszUsername, pExisting->szUsername))
  1591. break;
  1592. pExisting = pExisting->pNext;
  1593. }
  1594. if (NULL == pExisting)
  1595. {
  1596. CACHED_PASSWORD *pNewPassword;
  1597. // Insert new password at head of linked list
  1598. pNewPassword = new CACHED_PASSWORD;
  1599. if (NULL == pNewPassword)
  1600. {
  1601. hrResult = E_OUTOFMEMORY;
  1602. goto exit;
  1603. }
  1604. pNewPassword->dwPort = dwPort;
  1605. StrCpyN(pNewPassword->szServer, pszServer, ARRAYSIZE(pNewPassword->szServer));
  1606. StrCpyN(pNewPassword->szUsername, pszUsername, ARRAYSIZE(pNewPassword->szUsername));
  1607. StrCpyN(pNewPassword->szPassword, pszPassword, ARRAYSIZE(pNewPassword->szPassword));
  1608. pNewPassword->pNext = s_pPasswordList;
  1609. s_pPasswordList = pNewPassword;
  1610. }
  1611. else
  1612. // Replace existing cached value
  1613. StrCpyN(pExisting->szPassword, pszPassword, ARRAYSIZE(pExisting->szPassword));
  1614. exit:
  1615. LeaveCriticalSection(&s_csPasswordList);
  1616. return hrResult;
  1617. } // SavePassword
  1618. //***************************************************************************
  1619. // Function: GetPassword
  1620. //
  1621. // Purpose:
  1622. // This function retrieves a password previously saved using SavePassword.
  1623. //
  1624. // Arguments:
  1625. // DWORD dwPort [in] - the port number of the server we are trying to
  1626. // connect to. This allows us to keep separate passwords for SMTP and
  1627. // POP/IMAP servers on the same machine.
  1628. // LPSTR pszServer [in] - the server name which we are trying to connect to.
  1629. // Server names are treated as case-insensitive.
  1630. // LPSTR pszUsername [in] - the username which we are trying to connect for.
  1631. // LPSTR pszPassword [out] - if successful, the function returns the password
  1632. // for the given server and port number here. If the caller only wants to
  1633. // check if a password is cached, he may pass in NULL.
  1634. // DWORD dwSizeOfPassword [in] - the size of the buffer pointed to by
  1635. // pszPassword, to avoid overflow.
  1636. //
  1637. // Returns:
  1638. // HRESULT indicating success or failure.
  1639. //***************************************************************************
  1640. HRESULT GetPassword(DWORD dwPort, LPSTR pszServer, LPSTR pszUsername,
  1641. LPSTR pszPassword, DWORD dwSizeOfPassword)
  1642. {
  1643. HRESULT hrResult = E_FAIL;
  1644. CACHED_PASSWORD *pCurrent;
  1645. EnterCriticalSection(&s_csPasswordList);
  1646. // Traverse the linked list looking for password
  1647. pCurrent = s_pPasswordList;
  1648. while (NULL != pCurrent)
  1649. {
  1650. if (dwPort == pCurrent->dwPort &&
  1651. 0 == lstrcmpi(pszServer, pCurrent->szServer) &&
  1652. 0 == lstrcmp(pszUsername, pCurrent->szUsername))
  1653. {
  1654. if (NULL != pszPassword && 0 != dwSizeOfPassword)
  1655. StrCpyN(pszPassword, pCurrent->szPassword, dwSizeOfPassword);
  1656. hrResult = S_OK;
  1657. goto exit;
  1658. }
  1659. pCurrent = pCurrent->pNext;
  1660. } // while
  1661. exit:
  1662. LeaveCriticalSection(&s_csPasswordList);
  1663. return hrResult;
  1664. } // GetPassword
  1665. //***************************************************************************
  1666. // Function: DestroyPasswordList
  1667. // Purpose:
  1668. // This function deallocates all cached passwords saved using SavePassword.
  1669. //***************************************************************************
  1670. void DestroyPasswordList(void)
  1671. {
  1672. CACHED_PASSWORD *pCurrent;
  1673. EnterCriticalSection(&s_csPasswordList);
  1674. pCurrent = s_pPasswordList;
  1675. while (NULL != pCurrent)
  1676. {
  1677. CACHED_PASSWORD *pDeleteMe;
  1678. pDeleteMe = pCurrent;
  1679. pCurrent = pCurrent->pNext;
  1680. delete pDeleteMe;
  1681. } // while
  1682. s_pPasswordList = NULL;
  1683. LeaveCriticalSection(&s_csPasswordList);
  1684. } // DestroyPasswordList
  1685. HRESULT CALLBACK FreeAthenaDataObj(PDATAOBJINFO pDataObjInfo, DWORD celt)
  1686. {
  1687. // Loop through the data and free it all
  1688. if (pDataObjInfo)
  1689. {
  1690. for (DWORD i = 0; i < celt; i++)
  1691. {
  1692. SafeMemFree(pDataObjInfo[i].pData);
  1693. }
  1694. SafeMemFree(pDataObjInfo);
  1695. }
  1696. return S_OK;
  1697. }
  1698. HRESULT _IsSameObject(IUnknown* punk1, IUnknown* punk2)
  1699. {
  1700. IUnknown* punkI1;
  1701. HRESULT hres = punk1->QueryInterface(IID_IUnknown, (LPVOID*)&punkI1);
  1702. if (FAILED(hres))
  1703. {
  1704. Assert(0);
  1705. return hres;
  1706. }
  1707. IUnknown* punkI2;
  1708. hres = punk2->QueryInterface(IID_IUnknown, (LPVOID*)&punkI2);
  1709. if (SUCCEEDED(hres))
  1710. {
  1711. hres = (punkI1 == punkI2) ? S_OK : S_FALSE;
  1712. punkI2->Release();
  1713. }
  1714. else
  1715. {
  1716. Assert(0);
  1717. }
  1718. punkI1->Release();
  1719. return hres;
  1720. }
  1721. BOOL FileExists(TCHAR *szFile, BOOL fNew)
  1722. {
  1723. WIN32_FIND_DATA fd;
  1724. HANDLE hnd;
  1725. BOOL fRet;
  1726. fRet = FALSE;
  1727. hnd = FindFirstFile(szFile, &fd);
  1728. if (hnd != INVALID_HANDLE_VALUE)
  1729. {
  1730. FindClose(hnd);
  1731. if (fNew)
  1732. fRet = TRUE;
  1733. else
  1734. fRet = (0 == (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY));
  1735. }
  1736. return(fRet);
  1737. }
  1738. BOOL FIsSubDir(LPCSTR szOld, LPCSTR szNew)
  1739. {
  1740. BOOL fRet;
  1741. int cchNew, cchOld;
  1742. Assert(szOld != NULL);
  1743. Assert(szNew != NULL);
  1744. cchOld = lstrlen(szOld);
  1745. cchNew = lstrlen(szNew);
  1746. fRet = (cchNew > cchOld &&
  1747. szNew[cchOld] == '\\' &&
  1748. 0 == StrCmpNI(szOld, szNew, cchOld));
  1749. return(fRet);
  1750. }
  1751. BOOL CALLBACK EnumThreadCB(HWND hwnd, LPARAM lParam);
  1752. #define SetMenuItem(hmenu, id, fOn) EnableMenuItem(hmenu, id, fOn?MF_ENABLED:MF_DISABLED|MF_GRAYED);
  1753. HWND GetTopMostParent(HWND hwndChild)
  1754. {
  1755. HWND hwnd=hwndChild;
  1756. LONG_PTR lStyle;
  1757. if (FALSE == IsWindow(hwndChild))
  1758. {
  1759. goto exit;
  1760. }
  1761. do
  1762. {
  1763. hwnd = hwndChild;
  1764. // Get the style of the current window
  1765. lStyle = GetWindowLongPtr(hwnd, GWL_STYLE);
  1766. // Are we at the top window?
  1767. if (0 == (lStyle & WS_CHILD))
  1768. {
  1769. goto exit;
  1770. }
  1771. // Get the parent of the window
  1772. } while (NULL != (hwndChild = GetParent(hwnd)));
  1773. exit:
  1774. return hwnd;
  1775. }
  1776. HCURSOR HourGlass()
  1777. {
  1778. return SetCursor(LoadCursor(NULL, IDC_WAIT));
  1779. }
  1780. HRESULT CEmptyList::Show(HWND hwndList, LPTSTR pszString)
  1781. {
  1782. // We're already doing a window
  1783. if (m_hwndList)
  1784. {
  1785. Hide();
  1786. }
  1787. // Keep a copy of the listview window handle
  1788. m_hwndList = hwndList;
  1789. if (IS_INTRESOURCE(pszString))
  1790. {
  1791. // If the provided string is actually a resource ID, load it
  1792. m_pszString = AthLoadString(PtrToUlong(pszString), NULL, 0);
  1793. }
  1794. else
  1795. {
  1796. // Otherwise make a copy
  1797. m_pszString = PszDupA(pszString);
  1798. }
  1799. // Get the header window handle from the listview
  1800. m_hwndHeader = ListView_GetHeader(m_hwndList);
  1801. // Save our this pointer on the listview window
  1802. SetProp(m_hwndList, _T("EmptyListClass"), (HANDLE) this);
  1803. // Subclass the listview so we can steal sizing messages
  1804. if (!m_pfnWndProc)
  1805. m_pfnWndProc = SubclassWindow(m_hwndList, SubclassWndProc);
  1806. // Create our window on top
  1807. if (!m_hwndBlocker)
  1808. {
  1809. m_hwndBlocker = CreateWindow(_T("Static"), _T("Blocker!"),
  1810. WS_CHILD | WS_TABSTOP | WS_CLIPSIBLINGS | SS_CENTER,
  1811. 0, 0, 10, 10, m_hwndList, 0, g_hInst, NULL);
  1812. Assert(m_hwndBlocker);
  1813. }
  1814. // Set the text for the blocker
  1815. SetWindowText(m_hwndBlocker, m_pszString);
  1816. // Set the font for the blocker
  1817. HFONT hf = (HFONT) SendMessage(m_hwndList, WM_GETFONT, 0, 0);
  1818. SendMessage(m_hwndBlocker, WM_SETFONT, (WPARAM) hf, MAKELPARAM(TRUE, 0));
  1819. // Position the blocker
  1820. RECT rcList, rcHead;
  1821. GetClientRect(m_hwndList, &rcList);
  1822. GetClientRect(m_hwndHeader, &rcHead);
  1823. SetWindowPos(m_hwndBlocker, 0, 0, rcHead.bottom, rcList.right,
  1824. rcList.bottom - rcHead.bottom, SWP_NOACTIVATE | SWP_NOZORDER);
  1825. // Show the thing
  1826. ShowWindow(m_hwndBlocker, SW_SHOW);
  1827. return (S_OK);
  1828. }
  1829. HRESULT CEmptyList::Hide(void)
  1830. {
  1831. // Verify we have the blocker up first
  1832. if (m_pfnWndProc)
  1833. {
  1834. // Hide the window
  1835. ShowWindow(m_hwndBlocker, SW_HIDE);
  1836. // Unsubclass the window
  1837. SubclassWindow(m_hwndList, m_pfnWndProc);
  1838. // Delete the property
  1839. RemoveProp(m_hwndList, _T("EmptyListClass"));
  1840. // Free the string
  1841. SafeMemFree(m_pszString);
  1842. // NULL everything out
  1843. m_pfnWndProc = 0;
  1844. m_hwndList = 0;
  1845. }
  1846. return (S_OK);
  1847. }
  1848. LRESULT CEmptyList::SubclassWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  1849. {
  1850. CEmptyList* pThis = (CEmptyList *) GetProp(hwnd, _T("EmptyListClass"));
  1851. Assert(pThis);
  1852. switch (uMsg)
  1853. {
  1854. case WM_SIZE:
  1855. if (pThis && IsWindow(pThis->m_hwndBlocker))
  1856. {
  1857. RECT rcHeader;
  1858. GetClientRect(pThis->m_hwndHeader, &rcHeader);
  1859. SetWindowPos(pThis->m_hwndBlocker, 0, 0, 0, LOWORD(lParam),
  1860. HIWORD(lParam) - rcHeader.bottom,
  1861. SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
  1862. InvalidateRect(pThis->m_hwndBlocker, NULL, FALSE);
  1863. }
  1864. break;
  1865. case WM_CTLCOLORSTATIC:
  1866. if ((HWND) lParam == pThis->m_hwndBlocker)
  1867. {
  1868. if (!pThis->m_hbrBack)
  1869. {
  1870. pThis->m_hbrBack = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  1871. }
  1872. SetBkColor((HDC) wParam, GetSysColor(COLOR_WINDOW));
  1873. return (LRESULT) pThis->m_hbrBack;
  1874. }
  1875. break;
  1876. case WM_SYSCOLORCHANGE:
  1877. if (pThis)
  1878. {
  1879. DeleteObject(pThis->m_hbrBack);
  1880. pThis->m_hbrBack = 0;
  1881. SendMessage(pThis->m_hwndBlocker, uMsg, wParam, lParam);
  1882. }
  1883. break;
  1884. case WM_WININICHANGE:
  1885. case WM_FONTCHANGE:
  1886. if (pThis)
  1887. {
  1888. LRESULT lResult = CallWindowProc(pThis->m_pfnWndProc, hwnd, uMsg, wParam, lParam);
  1889. SendMessage(pThis->m_hwndBlocker, uMsg, wParam, lParam);
  1890. HFONT hf = (HFONT) SendMessage(pThis->m_hwndList, WM_GETFONT, 0, 0);
  1891. SendMessage(pThis->m_hwndBlocker, WM_SETFONT, (WPARAM) hf, MAKELPARAM(TRUE, 0));
  1892. return (lResult);
  1893. }
  1894. case WM_DESTROY:
  1895. {
  1896. if (pThis)
  1897. {
  1898. WNDPROC pfn = pThis->m_pfnWndProc;
  1899. pThis->Hide();
  1900. return (CallWindowProc(pfn, hwnd, uMsg, wParam, lParam));
  1901. }
  1902. }
  1903. break;
  1904. }
  1905. if (pThis)
  1906. return (CallWindowProc(pThis->m_pfnWndProc, hwnd, uMsg, wParam, lParam));
  1907. return 0;
  1908. }
  1909. BOOL AllocStringFromDlg(HWND hwnd, UINT id, LPTSTR * lplpsz)
  1910. {
  1911. UINT cb;
  1912. HWND hwndEdit;
  1913. if (*lplpsz)
  1914. {
  1915. MemFree(*lplpsz);
  1916. }
  1917. *lplpsz = NULL;
  1918. hwndEdit = GetDlgItem(hwnd, id);
  1919. if (hwndEdit == NULL)
  1920. return(TRUE);
  1921. cb = Edit_GetTextLength(hwndEdit);
  1922. if (cb)
  1923. {
  1924. cb++; // null terminator
  1925. MemAlloc((LPVOID *) lplpsz, cb * sizeof(TCHAR));
  1926. if (*lplpsz)
  1927. {
  1928. Edit_GetText(hwndEdit, *lplpsz, cb);
  1929. return TRUE;
  1930. }
  1931. else
  1932. return FALSE;
  1933. }
  1934. return TRUE;
  1935. }
  1936. void GetChildRect(HWND hwndDlg, HWND hwndChild, RECT *prc)
  1937. {
  1938. RECT rc;
  1939. POINT pt;
  1940. Assert(IsWindow(hwndDlg)&&IsWindow(hwndChild));
  1941. Assert(GetParent(hwndChild)==hwndDlg);
  1942. Assert(prc);
  1943. GetWindowRect(hwndChild, &rc);
  1944. // a-msadek; Do not check for hwndChild since we already disabled mirroring
  1945. // for Richedit controls
  1946. pt.x= IS_WINDOW_RTL_MIRRORED(hwndDlg)? rc.right : rc.left;
  1947. pt.y=rc.top;
  1948. ScreenToClient(hwndDlg, &pt);
  1949. SetRect(prc, pt.x, pt.y, pt.x+(rc.right-rc.left), pt.y+(rc.bottom-rc.top));
  1950. }
  1951. void GetEditDisableFlags(HWND hwndEdit, DWORD *pdwFlags)
  1952. {
  1953. DWORD dwFlags=0;
  1954. Assert(pdwFlags);
  1955. *pdwFlags=0;
  1956. // RICHEDIT's
  1957. // Figure out whether the edit has any selection or content
  1958. if(GetFocus()==hwndEdit)
  1959. dwFlags|=edfEditFocus;
  1960. if(SendMessage(hwndEdit, EM_SELECTIONTYPE, 0, 0)!=SEL_EMPTY)
  1961. {
  1962. dwFlags |= edfEditHasSel;
  1963. if(!FReadOnlyEdit(hwndEdit))
  1964. dwFlags |= edfEditHasSelAndIsRW;
  1965. }
  1966. if (Edit_CanUndo(hwndEdit))
  1967. dwFlags |= edfUndo;
  1968. if (SendMessage(hwndEdit, EM_CANPASTE, 0, 0))
  1969. dwFlags |= edfPaste;
  1970. *pdwFlags=dwFlags;
  1971. }
  1972. void EnableDisableEditToolbar(HWND hwndToolbar, DWORD dwFlags)
  1973. {
  1974. SendMessage(hwndToolbar, TB_ENABLEBUTTON, ID_CUT,
  1975. MAKELONG(dwFlags&edfEditHasSelAndIsRW,0));
  1976. SendMessage(hwndToolbar, TB_ENABLEBUTTON, ID_COPY,
  1977. MAKELONG(dwFlags&edfEditHasSel,0));
  1978. SendMessage(hwndToolbar, TB_ENABLEBUTTON, ID_PASTE,
  1979. MAKELONG(dwFlags&edfPaste,0));
  1980. SendMessage(hwndToolbar, TB_ENABLEBUTTON, ID_UNDO,
  1981. MAKELONG(dwFlags&edfUndo,0));
  1982. }
  1983. void EnableDisableEditMenu(HMENU hmenuEdit, DWORD dwFlags)
  1984. {
  1985. if(!hmenuEdit)
  1986. return;
  1987. SetMenuItem(hmenuEdit, ID_UNDO, dwFlags&edfUndo);
  1988. SetMenuItem(hmenuEdit, ID_CUT, dwFlags&edfEditHasSelAndIsRW);
  1989. SetMenuItem(hmenuEdit, ID_COPY, dwFlags&edfEditHasSel);
  1990. SetMenuItem(hmenuEdit, ID_PASTE, dwFlags&edfPaste);
  1991. SetMenuItem(hmenuEdit, ID_SELECT_ALL, dwFlags&edfEditFocus);
  1992. }
  1993. void StopBlockingPaints(HWND hwndBlock)
  1994. {
  1995. if (hwndBlock)
  1996. DestroyWindow(hwndBlock);
  1997. }
  1998. LRESULT CALLBACK BlockingWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1999. {
  2000. if (msg==WM_PAINT)
  2001. {
  2002. PAINTSTRUCT ps;
  2003. BeginPaint(hwnd, &ps);
  2004. EndPaint(hwnd, &ps);
  2005. return 1;
  2006. }
  2007. if(msg==WM_ERASEBKGND)
  2008. return 1;
  2009. return DefWindowProc(hwnd, msg, wParam, lParam);
  2010. }
  2011. HWND HwndStartBlockingPaints(HWND hwnd)
  2012. {
  2013. WNDCLASS wc;
  2014. RECT rc;
  2015. HWND hwndBlock;
  2016. // Create WNDCLASS for Paint Block
  2017. if (!GetClassInfo(g_hInst, c_szBlockingPaintsClass, &wc))
  2018. {
  2019. ZeroMemory(&wc, sizeof(WNDCLASS));
  2020. wc.hInstance = g_hInst;
  2021. wc.lpfnWndProc = BlockingWndProc;
  2022. wc.hCursor = LoadCursor(NULL, IDC_WAIT);
  2023. wc.lpszClassName = c_szBlockingPaintsClass;
  2024. if (!RegisterClass(&wc))
  2025. return NULL;
  2026. }
  2027. GetWindowRect(hwnd, &rc);
  2028. if(hwndBlock = CreateWindow(c_szBlockingPaintsClass, NULL,
  2029. WS_POPUP, rc.left, rc.top,
  2030. rc.right - rc.left, rc.bottom - rc.top,
  2031. hwnd, NULL, g_hInst, NULL))
  2032. ShowWindow(hwndBlock, SW_SHOWNA);
  2033. return hwndBlock;
  2034. }
  2035. void SaveFocus(BOOL fActive, HWND *phwnd)
  2036. {
  2037. if(fActive&&IsWindow(*phwnd))
  2038. SetFocus(*phwnd);
  2039. else
  2040. *phwnd=GetFocus();
  2041. #ifdef DEBUG
  2042. if(fActive)
  2043. DOUTL(4, "Setting focus to 0x%x", *phwnd);
  2044. else
  2045. DOUTL(4, "Focus was on 0x%x", *phwnd);
  2046. #endif
  2047. }
  2048. void DoToolbarDropdown(HWND hwnd, LPNMHDR lpnmh, HMENU hmenu)
  2049. {
  2050. RECT rc;
  2051. DWORD dwCmd;
  2052. NMTOOLBAR *ptbn = (NMTOOLBAR *) lpnmh;
  2053. rc = ptbn->rcButton;
  2054. MapWindowRect(lpnmh->hwndFrom, HWND_DESKTOP, &rc);
  2055. dwCmd = TrackPopupMenuEx(hmenu, TPM_RETURNCMD | TPM_LEFTALIGN,
  2056. rc.left, rc.bottom, hwnd, NULL);
  2057. if (dwCmd)
  2058. PostMessage(hwnd, WM_COMMAND, dwCmd, 0);
  2059. }
  2060. HWND FindModalOwner()
  2061. {
  2062. HWND hwndPopup = NULL;
  2063. HWND hwnd;
  2064. DWORD dwThreadId = GetCurrentThreadId();
  2065. // Check the windows in Z-Order to find one that belongs to this
  2066. // task.
  2067. hwnd = GetLastActivePopup(GetActiveWindow());
  2068. while (IsWindow(hwnd) && IsWindowVisible(hwnd))
  2069. {
  2070. if (GetWindowThreadProcessId(hwnd, NULL) == dwThreadId)
  2071. {
  2072. hwndPopup = hwnd;
  2073. break;
  2074. }
  2075. hwnd = GetNextWindow(hwnd, GW_HWNDNEXT);
  2076. }
  2077. return hwndPopup;
  2078. }
  2079. //
  2080. // FUNCTION: FreeMessageInfo
  2081. //
  2082. // PURPOSE: Free all of the memory in a MESSAGEINFO structure.
  2083. // All non-allocated pointers should be null on entry.
  2084. // Freed pointers will be nulled on return. The
  2085. // pMsgInfo is not freed.
  2086. //
  2087. // PARAMETERS:
  2088. // pMsgInfo - Pointer to an LPMESSAGEINFO structure.
  2089. //
  2090. // RETURN VALUE:
  2091. // ignored
  2092. //
  2093. void FreeMessageInfo(LPMESSAGEINFO pMsgInfo)
  2094. {
  2095. SafeMemFree(pMsgInfo->pszMessageId);
  2096. SafeMemFree(pMsgInfo->pszSubject);
  2097. SafeMemFree(pMsgInfo->pszFromHeader);
  2098. SafeMemFree(pMsgInfo->pszReferences);
  2099. SafeMemFree(pMsgInfo->pszXref);
  2100. SafeMemFree(pMsgInfo->pszServer);
  2101. SafeMemFree(pMsgInfo->pszDisplayFrom);
  2102. SafeMemFree(pMsgInfo->pszEmailFrom);
  2103. SafeMemFree(pMsgInfo->pszDisplayTo);
  2104. SafeMemFree(pMsgInfo->pszEmailTo);
  2105. SafeMemFree(pMsgInfo->pszUidl);
  2106. SafeMemFree(pMsgInfo->pszPartialId);
  2107. SafeMemFree(pMsgInfo->pszForwardTo);
  2108. SafeMemFree(pMsgInfo->pszAcctName);
  2109. SafeMemFree(pMsgInfo->pszAcctId);
  2110. SafeMemFree(pMsgInfo->pszUrlComponent);
  2111. SafeMemFree(pMsgInfo->pszFolder);
  2112. SafeMemFree(pMsgInfo->pszMSOESRec);
  2113. }
  2114. //
  2115. // FUNCTION: Util_EnumFiles()
  2116. //
  2117. // PURPOSE: Enumerates files in a directory that match a wildcard
  2118. //
  2119. // PARAMETERS:
  2120. // <in> pszDir - Handle of a window we can display UI over.
  2121. // <in> pszMatch - wildcard to match (*.nch)
  2122. //
  2123. // RETURN VALUE:
  2124. // double-null terminated list of filenames
  2125. //
  2126. LPWSTR Util_EnumFiles(LPCWSTR pwszDir, LPCWSTR pwszMatch)
  2127. {
  2128. // Locals
  2129. WCHAR wszSearchPath[MAX_PATH];
  2130. LPWSTR pwszFiles=NULL;
  2131. WIN32_FIND_DATAW rfd;
  2132. HANDLE hFind = INVALID_HANDLE_VALUE;
  2133. ULONG iFiles = 0,
  2134. cbFileName,
  2135. cbFiles = 0;
  2136. HRESULT hr = S_OK;
  2137. // Check Params
  2138. Assert(pwszDir);
  2139. Assert(pwszMatch);
  2140. // Make Search Path
  2141. wnsprintfW(wszSearchPath, ARRAYSIZE(wszSearchPath), c_wszPathWildExtFmt, pwszDir, pwszMatch);
  2142. // Build list of file names
  2143. hFind = FindFirstFileWrapW(wszSearchPath, &rfd);
  2144. // Good ...
  2145. while (hFind != INVALID_HANDLE_VALUE)
  2146. {
  2147. // Get Length of file name
  2148. cbFileName = (lstrlenW(rfd.cFileName) + 1)*sizeof(WCHAR);
  2149. // Add onto cbFiles
  2150. cbFiles += cbFileName;
  2151. // Realloc pszFiles
  2152. // sizeof(WCHAR) to handle the final double null
  2153. IF_NULLEXIT(MemRealloc((LPVOID *)&pwszFiles, cbFiles+sizeof(WCHAR)));
  2154. // Copy String - include null terminator
  2155. CopyMemory(pwszFiles + iFiles, rfd.cFileName, cbFileName);
  2156. // Increment iFiles
  2157. iFiles += cbFileName/sizeof(WCHAR);
  2158. // Find Next
  2159. if (FindNextFileWrapW(hFind, &rfd) == FALSE)
  2160. {
  2161. FindClose (hFind);
  2162. hFind = INVALID_HANDLE_VALUE;
  2163. }
  2164. }
  2165. // Double null terminator at the end
  2166. if (pwszFiles)
  2167. *(pwszFiles + iFiles) = L'\0';
  2168. exit:
  2169. // Cleanup
  2170. if (hFind != INVALID_HANDLE_VALUE)
  2171. FindClose (hFind);
  2172. if (FAILED(hr))
  2173. SafeMemFree(pwszFiles);
  2174. // Done
  2175. return pwszFiles;
  2176. }
  2177. //
  2178. // FUNCTION: GetDefaultNewsServer()
  2179. //
  2180. // PURPOSE: Returns the id of the user's default news server.
  2181. //
  2182. // PARAMETERS:
  2183. // pszServer - Pointer to the string where the server account id should
  2184. // be returned.
  2185. // cchMax - Size of the string pszServer.
  2186. //
  2187. HRESULT GetDefaultNewsServer(LPTSTR pszServerId, DWORD cchMax)
  2188. {
  2189. IImnAccount* pAcct;
  2190. HRESULT hr;
  2191. ULONG cSrv;
  2192. if (SUCCEEDED(hr = g_pAcctMan->GetDefaultAccount(ACCT_NEWS, &pAcct)))
  2193. {
  2194. hr = pAcct->GetPropSz(AP_ACCOUNT_ID, pszServerId, cchMax);
  2195. pAcct->Release();
  2196. }
  2197. Assert(!FAILED(hr) || (!FAILED(g_pAcctMan->GetAccountCount(ACCT_NEWS, &cSrv)) && cSrv == 0));
  2198. return(hr);
  2199. }
  2200. BOOL WINAPI EnumTopLevelWindows(HWND hwnd, LPARAM lParam)
  2201. {
  2202. HWNDLIST *pHwndList = (HWNDLIST *)lParam;
  2203. // Add the window to the list only if it is active and visible
  2204. // if ETW_OE_WINDOWS_ONLY is set, only add registered OE windows to the list
  2205. // [PaulHi] 6/4/99 Raid 76713
  2206. // We need to also enumerate disabled windows, for the enumeration that
  2207. // closes them. Otherwise they will remain open and the user will be
  2208. // unable to close them.
  2209. if (/* IsWindowVisible(hwnd) && IsWindowEnabled(hwnd) && */
  2210. (!(pHwndList->dwFlags & ETW_OE_WINDOWS_ONLY) || GetProp(hwnd, c_szOETopLevel)))
  2211. {
  2212. // If pHwndList->cAlloc is 0 then we are only counting
  2213. // the active windows
  2214. if (pHwndList->cAlloc)
  2215. {
  2216. Assert(pHwndList->cHwnd < pHwndList->cAlloc);
  2217. pHwndList->rgHwnd[pHwndList->cHwnd] = hwnd;
  2218. }
  2219. pHwndList->cHwnd++;
  2220. }
  2221. return TRUE;
  2222. }
  2223. HRESULT EnableThreadWindows(HWNDLIST *pHwndList, BOOL fEnable, DWORD dwFlags, HWND hwndExcept)
  2224. {
  2225. if (fEnable)
  2226. {
  2227. // Enable keyboard and mouse input on the list of windows
  2228. for (int i = 0; i < pHwndList->cHwnd; i++)
  2229. {
  2230. if (hwndExcept != pHwndList->rgHwnd[i])
  2231. {
  2232. if (dwFlags & ETW_OE_WINDOWS_ONLY)
  2233. SendMessage(pHwndList->rgHwnd[i], WM_OE_ENABLETHREADWINDOW, TRUE, 0);
  2234. else
  2235. EnableWindow(pHwndList->rgHwnd[i], TRUE);
  2236. }
  2237. }
  2238. if (pHwndList->rgHwnd)
  2239. MemFree(pHwndList->rgHwnd);
  2240. ZeroMemory(pHwndList, sizeof(HWNDLIST));
  2241. return S_OK;
  2242. }
  2243. else
  2244. {
  2245. ZeroMemory(pHwndList, sizeof(HWNDLIST));
  2246. pHwndList->dwFlags = dwFlags;
  2247. // Count the number of active and visible windows
  2248. EnumThreadWindows(GetCurrentThreadId(), EnumTopLevelWindows, (DWORD_PTR)pHwndList);
  2249. // Allocate space for the window list
  2250. if (pHwndList->cHwnd)
  2251. {
  2252. if (!MemAlloc((LPVOID*)&pHwndList->rgHwnd, pHwndList->cHwnd * sizeof(HWND)))
  2253. return E_OUTOFMEMORY;
  2254. pHwndList->cAlloc = pHwndList->cHwnd;
  2255. pHwndList->cHwnd = 0;
  2256. }
  2257. // List the active and visible windows
  2258. EnumThreadWindows(GetCurrentThreadId(), EnumTopLevelWindows, (DWORD_PTR)pHwndList);
  2259. // Disable keyboard and mouse input on the active and visible windows
  2260. for (int i = 0; i < pHwndList->cHwnd; i++)
  2261. {
  2262. if ( (hwndExcept != pHwndList->rgHwnd[i]) &&
  2263. IsWindowVisible(pHwndList->rgHwnd[i]) && IsWindowEnabled(pHwndList->rgHwnd[i]) )
  2264. {
  2265. if (dwFlags & ETW_OE_WINDOWS_ONLY)
  2266. SendMessage(pHwndList->rgHwnd[i], WM_OE_ENABLETHREADWINDOW, FALSE, 0);
  2267. else
  2268. EnableWindow(pHwndList->rgHwnd[i], FALSE);
  2269. }
  2270. }
  2271. return S_OK;
  2272. }
  2273. }
  2274. void ActivatePopupWindow(HWND hwnd)
  2275. {
  2276. HWND hwndOwner;
  2277. // set the popup to be active
  2278. SetActiveWindow(hwnd);
  2279. // walk the owner chain, and z-order the windows behind it
  2280. while(hwndOwner = GetWindow(hwnd, GW_OWNER))
  2281. {
  2282. SetWindowPos(hwndOwner, hwnd, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER);
  2283. hwnd = hwndOwner;
  2284. }
  2285. }
  2286. HRESULT GetOEUserName(BSTR *pbstr)
  2287. {
  2288. TCHAR rgch[CCHMAX_STRINGRES];
  2289. HRESULT hr=E_FAIL;
  2290. LPCSTR pszName;
  2291. IImnAccount *pAccount;
  2292. Assert (pbstr);
  2293. *pbstr=NULL;
  2294. // get multi-user name, if applicable
  2295. pszName = MU_GetCurrentIdentityName();
  2296. if (pszName && *pszName)
  2297. hr = HrLPSZToBSTR(pszName, pbstr);
  2298. else
  2299. {
  2300. if (g_pAcctMan &&
  2301. g_pAcctMan->GetDefaultAccount(ACCT_MAIL, &pAccount)==S_OK)
  2302. {
  2303. if (pAccount->GetPropSz(AP_SMTP_DISPLAY_NAME, rgch, ARRAYSIZE(rgch))==S_OK && *rgch)
  2304. hr = HrLPSZToBSTR(rgch, pbstr);
  2305. pAccount->Release();
  2306. }
  2307. }
  2308. return hr;
  2309. }
  2310. HRESULT CloseThreadWindows(HWND hwndExcept, DWORD uiThreadId)
  2311. {
  2312. HWNDLIST HwndList = {0};
  2313. // Count the number of active and visible windows
  2314. HwndList.dwFlags = ETW_OE_WINDOWS_ONLY;
  2315. EnumThreadWindows(uiThreadId, EnumTopLevelWindows, ((DWORD_PTR) &HwndList));
  2316. // Allocate space for the window list
  2317. if (HwndList.cHwnd)
  2318. {
  2319. if (!MemAlloc((LPVOID*)&(HwndList.rgHwnd), HwndList.cHwnd * sizeof(HWND)))
  2320. return E_OUTOFMEMORY;
  2321. HwndList.cAlloc = HwndList.cHwnd;
  2322. HwndList.cHwnd = 0;
  2323. }
  2324. // List the active and visible windows
  2325. EnumThreadWindows(uiThreadId, EnumTopLevelWindows, ((DWORD_PTR)&HwndList));
  2326. // Close all OE top level windows
  2327. for (int i = 0; i < HwndList.cHwnd; i++)
  2328. {
  2329. if (hwndExcept != HwndList.rgHwnd[i])
  2330. {
  2331. SendMessage(HwndList.rgHwnd[i], WM_CLOSE, 0, 0);
  2332. }
  2333. }
  2334. MemFree(HwndList.rgHwnd);
  2335. return S_OK;
  2336. }
  2337. BOOL HideHotmail()
  2338. {
  2339. int cch;
  2340. DWORD dw, cb, type;
  2341. char sz[8];
  2342. cch = LoadString(g_hLocRes, idsHideHotmailMenu, sz, ARRAYSIZE(sz));
  2343. if (cch == 1 && *sz == '1')
  2344. return(TRUE);
  2345. cb = sizeof(dw);
  2346. if (ERROR_SUCCESS == SHGetValue(HKEY_LOCAL_MACHINE, c_szRegFlat, c_szRegDisableHotmail, &type, &dw, &cb) &&
  2347. dw == 2)
  2348. return(FALSE);
  2349. cb = sizeof(dw);
  2350. if (ERROR_SUCCESS == SHGetValue(HKEY_CURRENT_USER, c_szRegFlat, c_szRegDisableHotmail, &type, &dw, &cb) &&
  2351. dw == 2)
  2352. return(FALSE);
  2353. return(TRUE);
  2354. }
  2355. BOOL FIsIMAPOrHTTPAvailable(VOID)
  2356. {
  2357. BOOL fRet = FALSE;
  2358. IImnEnumAccounts * pEnumAcct = NULL;
  2359. IImnAccount * pAccount = NULL;
  2360. // Get the account enumerator
  2361. Assert(g_pAcctMan);
  2362. if (FAILED(g_pAcctMan->Enumerate(SRV_HTTPMAIL | SRV_IMAP, &pEnumAcct)))
  2363. {
  2364. fRet = FALSE;
  2365. goto exit;
  2366. }
  2367. // Do we have any accounts?
  2368. if ((SUCCEEDED(pEnumAcct->GetNext(&pAccount))) && (NULL != pAccount))
  2369. {
  2370. fRet = TRUE;
  2371. }
  2372. exit:
  2373. SafeRelease(pAccount);
  2374. SafeRelease(pEnumAcct);
  2375. return fRet;
  2376. }
  2377. // HACKHACK [neilbren]
  2378. // A recent public header change wrapped some CALENDAR constants from winnls.h
  2379. // in a WINVER >= 5. It's too late to change our WINVER, so we'll manually
  2380. // define these - a problem waiting to happen :-(
  2381. #ifndef CAL_GREGORIAN_ARABIC
  2382. #define CAL_GREGORIAN_ARABIC 10 // Gregorian Arabic calendar
  2383. #endif
  2384. #ifndef CAL_GREGORIAN_XLIT_ENGLISH
  2385. #define CAL_GREGORIAN_XLIT_ENGLISH 11 // Gregorian Transliterated English calendar
  2386. #endif
  2387. #ifndef CAL_GREGORIAN_XLIT_FRENCH
  2388. #define CAL_GREGORIAN_XLIT_FRENCH 12 // Gregorian Transliterated French calendar
  2389. #endif
  2390. BOOL IsBiDiCalendar(void)
  2391. {
  2392. TCHAR chCalendar[32];
  2393. CALTYPE defCalendar;
  2394. static BOOL bRet = (BOOL)(DWORD)-1;
  2395. if (bRet != (BOOL)(DWORD)-1)
  2396. {
  2397. return bRet;
  2398. }
  2399. bRet = FALSE;
  2400. //
  2401. // Let's verify the calendar type whether it's gregorian or not.
  2402. if (GetLocaleInfo(LOCALE_USER_DEFAULT,
  2403. LOCALE_ICALENDARTYPE,
  2404. (TCHAR *) &chCalendar[0],
  2405. ARRAYSIZE(chCalendar)))
  2406. {
  2407. defCalendar = StrToInt((TCHAR *)&chCalendar[0]);
  2408. if ((defCalendar == CAL_HIJRI) ||
  2409. (defCalendar == CAL_HEBREW) ||
  2410. (defCalendar == CAL_GREGORIAN_ARABIC) ||
  2411. (defCalendar == CAL_GREGORIAN_XLIT_ENGLISH) ||
  2412. (defCalendar == CAL_GREGORIAN_XLIT_FRENCH))
  2413. {
  2414. bRet = TRUE;
  2415. }
  2416. }
  2417. return bRet;
  2418. }
  2419. LPSTR PszAllocResUrl(LPSTR pszRelative)
  2420. {
  2421. TCHAR rgch[MAX_PATH];
  2422. LPSTR psz;
  2423. *rgch = 0;
  2424. GetModuleFileName(g_hLocRes, rgch, MAX_PATH);
  2425. DWORD cchSize = (lstrlen(rgch) + lstrlen(pszRelative) + 8);
  2426. psz = PszAllocA(cchSize); //+8 "res:///0"
  2427. if (psz)
  2428. wnsprintf(psz, cchSize, "res://%s/%s", rgch, pszRelative);
  2429. return psz;
  2430. }
  2431. //
  2432. // If you are calling this function and you use the result to draw text, you
  2433. // must use a function that supports font substitution (DrawTextWrapW, ExtTextOutWrapW).
  2434. //
  2435. BOOL GetTextExtentPoint32AthW(HDC hdc, LPCWSTR lpwString, int cchString, LPSIZE lpSize, DWORD dwFlags)
  2436. {
  2437. RECT rect = {0};
  2438. int rc;
  2439. rc = DrawTextWrapW(hdc, lpwString, cchString, &rect, DT_CALCRECT | dwFlags);
  2440. lpSize->cx = rect.right - rect.left + 1;
  2441. lpSize->cy = rect.bottom - rect.top + 1;
  2442. return((BOOL)rc);
  2443. }