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.

1071 lines
32 KiB

  1. // =================================================================================
  2. // L I N K S . C P P
  3. // =================================================================================
  4. #include "pch.hxx"
  5. #include "resource.h"
  6. #include "hotlinks.h"
  7. #include <shlwapi.h>
  8. #include <string.h>
  9. #include "baui.h"
  10. #include "clutil.h"
  11. #include <mapi.h>
  12. #include "msoert.h"
  13. #ifndef CharSizeOf
  14. #define CharSizeOf(x) (sizeof(x) / sizeof(TCHAR))
  15. #endif
  16. // explicit implementation of CharSizeOf
  17. #define CharSizeOf_A(x) (sizeof(x) / sizeof(CHAR))
  18. #define CharSizeOf_W(x) (sizeof(x) / sizeof(WCHAR))
  19. const LPTSTR szDefMailKey = TEXT("Software\\Clients\\Mail");
  20. const LPTSTR szDefContactsKey = TEXT("Software\\Clients\\Contacts");
  21. const LPTSTR szIEContactsArea = TEXT("Software\\Microsoft\\Internet Explorer\\Bar\\Contacts");
  22. const LPTSTR szDisableMessnegerArea = TEXT("Software\\Policies\\Microsoft\\Internet Explorer\\Contacts");
  23. const LPTSTR szPhoenixArea = TEXT("tel\\shell\\open\\command");
  24. const LPTSTR szOEDllPathKey = TEXT("DllPath");
  25. const LPTSTR szOEName = TEXT("Outlook Express");
  26. const LPTSTR szOutlookName = TEXT("Microsoft Outlook");
  27. const LPTSTR szContactOptions = TEXT("Options");
  28. const LPTSTR szContactDisabled = TEXT("Disabled");
  29. const LPTSTR szUseIM = TEXT("Use_IM");
  30. const LPTSTR szDisableIM = TEXT("Disable_IM");
  31. // =================================================================================
  32. // Globals
  33. // =================================================================================
  34. static COLORREF g_crLink = RGB(0,0,128);
  35. static COLORREF g_crLinkVisited = RGB(128,0,0);
  36. const TCHAR c_szIESettingsPath[] = "Software\\Microsoft\\Internet Explorer\\Settings";
  37. const TCHAR c_szLinkVisitedColorIE[] = "Anchor Color Visited";
  38. const TCHAR c_szLinkColorIE[] = "Anchor Color";
  39. const TCHAR c_szNSSettingsPath[] = "Software\\Netscape\\Netscape Navigator\\Settings";
  40. const TCHAR c_szLinkColorNS[] = "Link Color";
  41. const TCHAR c_szLinkVisitedColorNS[] = "Followed Link Color";
  42. typedef struct _MailParams
  43. {
  44. HWND hWnd;
  45. ULONG nRecipCount;
  46. LPRECIPLIST lpList;
  47. BOOL bUseOEForSendMail; // True means check and use OE before checking for Simple MAPI client
  48. } MAIL_PARAMS, * LPMAIL_PARAMS;
  49. /***************************************************************************
  50. Name : LocalFreeAndNull
  51. Purpose : Frees a local allocation and null's the pointer
  52. Parameters: lppv = pointer to LocalAlloc pointer to free
  53. Returns : void
  54. Comment : Remember to pass in the pointer to the pointer. The
  55. compiler is not smart enough to tell if you are doing this
  56. right or not, but you will know at runtime!
  57. ***************************************************************************/
  58. // void __fastcall LocalFreeAndNull(LPVOID * lppv) {
  59. void __fastcall LocalFreeAndNull(LPVOID * lppv) {
  60. if (lppv && *lppv) {
  61. LocalFree(*lppv);
  62. *lppv = NULL;
  63. }
  64. }
  65. /*
  66. -
  67. - LPCSTR ConvertWtoA(LPWSTR lpszW);
  68. *
  69. * LocalAllocs a ANSI version of an LPWSTR
  70. *
  71. * Caller is responsible for freeing
  72. */
  73. LPSTR ConvertWtoA(LPCWSTR lpszW)
  74. {
  75. int cch;
  76. LPSTR lpC = NULL;
  77. if ( !lpszW)
  78. goto ret;
  79. // cch = lstrlenW( lpszW ) + 1;
  80. cch = WideCharToMultiByte( CP_ACP, 0, lpszW, -1, NULL, 0, NULL, NULL );
  81. cch = cch + 1;
  82. if(lpC = (LPSTR) LocalAlloc(LMEM_ZEROINIT, cch))
  83. {
  84. WideCharToMultiByte( CP_ACP, 0, lpszW, -1, lpC, cch, NULL, NULL );
  85. }
  86. ret:
  87. return lpC;
  88. }
  89. // --------------------------------------------------------------------------
  90. // IEIsSpace
  91. // --------------------------------------------------------------------------
  92. BOOL IEIsSpace(LPSTR psz)
  93. {
  94. WORD wType = 0;
  95. if (IsDBCSLeadByte(*psz))
  96. GetStringTypeExA(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 2, &wType);
  97. else
  98. GetStringTypeExA(LOCALE_USER_DEFAULT, CT_CTYPE1, psz, 1, &wType);
  99. return (wType & C1_SPACE);
  100. }
  101. // =============================================================================================
  102. // StringTok - similiar to strtok
  103. // =============================================================================================
  104. BOOL FStringTok (LPCTSTR lpcszString,
  105. ULONG *piString,
  106. LPTSTR lpcszTokens,
  107. TCHAR *chToken,
  108. LPTSTR lpszValue,
  109. ULONG cbValueMax,
  110. BOOL fStripTrailingWhitespace)
  111. {
  112. // Locals
  113. LPTSTR lpszStringLoop,
  114. lpszTokenLoop;
  115. ULONG cbValue=0,
  116. nLen=0,
  117. cCharsSinceSpace=0,
  118. iLastSpace=0;
  119. BOOL fTokenFound = FALSE;
  120. // Check Params
  121. _ASSERT (lpcszString && piString && lpcszTokens/*, "These should have been checked."*/);
  122. // INit = better be on a dbcs boundary
  123. lpszStringLoop = (LPTSTR)(lpcszString + (*piString));
  124. // Loop current
  125. while (*lpszStringLoop)
  126. {
  127. // If DBCS Lead Byte, skip it, it will never match the type of tokens I'm looking for
  128. // Or, If an escape character, don't check delimiters
  129. if (IsDBCSLeadByte(*lpszStringLoop) || *lpszStringLoop == _T('\\'))
  130. {
  131. cCharsSinceSpace+=2;
  132. lpszStringLoop+=2;
  133. cbValue+=2;
  134. continue;
  135. }
  136. // Mark and remember last space
  137. if (cCharsSinceSpace && IEIsSpace(lpszStringLoop))
  138. {
  139. cCharsSinceSpace=0;
  140. iLastSpace=cbValue;
  141. }
  142. // Count number of characters since last space
  143. else
  144. cCharsSinceSpace++;
  145. // Look for a tokens
  146. lpszTokenLoop=lpcszTokens;
  147. while(*lpszTokenLoop)
  148. {
  149. // Token Match ?
  150. if (*lpszStringLoop == *lpszTokenLoop)
  151. {
  152. // Save the found token
  153. if (chToken)
  154. *chToken = *lpszStringLoop;
  155. // Don't count this character as a charcter seen since last space
  156. cCharsSinceSpace--;
  157. // Were done
  158. fTokenFound = TRUE;
  159. goto done;
  160. }
  161. // Next Token
  162. lpszTokenLoop++;
  163. }
  164. // Next Char
  165. lpszStringLoop++;
  166. cbValue++;
  167. }
  168. done:
  169. // If reached end of string, this is a default token
  170. if (*lpszStringLoop == _T('\0'))
  171. {
  172. if (chToken)
  173. *chToken = *lpszStringLoop;
  174. fTokenFound = TRUE;
  175. }
  176. // Copy value if token found
  177. if (fTokenFound)
  178. {
  179. if (lpszValue && cbValueMax > 0 && cbValue)
  180. {
  181. if (cbValue+1 <= cbValueMax)
  182. {
  183. StrCpyN (lpszValue, lpcszString + (*piString), cbValue+1);
  184. nLen = cbValue-1;
  185. }
  186. else
  187. {
  188. _ASSERT (FALSE/*, "Buffer is too small."*/);
  189. StrCpyN (lpszValue, lpcszString + (*piString), cbValueMax);
  190. nLen = cbValueMax-1;
  191. }
  192. // Strip Trailing Whitespace ?
  193. if (fStripTrailingWhitespace && cCharsSinceSpace == 0)
  194. {
  195. *(lpszValue + iLastSpace) = _T('\0');
  196. nLen = iLastSpace - 1;
  197. }
  198. }
  199. // No Text
  200. else
  201. {
  202. if (lpszValue)
  203. *lpszValue = _T('\0');
  204. nLen = 0;
  205. cbValue = 0;
  206. }
  207. // Set new string index
  208. *piString += cbValue + 1;
  209. }
  210. // Return whether we found a token
  211. return fTokenFound;
  212. }
  213. // =================================================================================
  214. // ParseLinkColorFromSz
  215. // =================================================================================
  216. VOID ParseLinkColorFromSz(LPTSTR lpszLinkColor, LPCOLORREF pcr)
  217. {
  218. // Locals
  219. ULONG iString = 0;
  220. TCHAR chToken,
  221. szColor[5];
  222. DWORD dwR,
  223. dwG,
  224. dwB;
  225. // Red
  226. if (!FStringTok (lpszLinkColor, &iString, ",", &chToken, szColor, 5, TRUE) || chToken != _T(','))
  227. goto exit;
  228. dwR = StrToInt(szColor);
  229. // Green
  230. if (!FStringTok (lpszLinkColor, &iString, ",", &chToken, szColor, 5, TRUE) || chToken != _T(','))
  231. goto exit;
  232. dwG = StrToInt(szColor);
  233. // Blue
  234. if (!FStringTok (lpszLinkColor, &iString, ",", &chToken, szColor, 5, TRUE) || chToken != _T('\0'))
  235. goto exit;
  236. dwB = StrToInt(szColor);
  237. // Create color
  238. *pcr = RGB(dwR, dwG, dwB);
  239. exit:
  240. // Done
  241. return;
  242. }
  243. // =================================================================================
  244. // LookupLinkColors
  245. // =================================================================================
  246. BOOL LookupLinkColors(LPCOLORREF pclrLink, LPCOLORREF pclrViewed)
  247. {
  248. // Locals
  249. HKEY hReg=NULL;
  250. TCHAR szLinkColor[255],
  251. szLinkVisitedColor[255];
  252. LONG lResult;
  253. DWORD cb;
  254. // Init
  255. *szLinkColor = _T('\0');
  256. *szLinkVisitedColor = _T('\0');
  257. // Look for IE's link color
  258. if (RegOpenKeyEx (HKEY_CURRENT_USER, (LPTSTR)c_szIESettingsPath, 0, KEY_ALL_ACCESS, &hReg) != ERROR_SUCCESS)
  259. goto tryns;
  260. // Query for value
  261. cb = sizeof (szLinkVisitedColor);
  262. RegQueryValueEx(hReg, (LPTSTR)c_szLinkVisitedColorIE, 0, NULL, (LPBYTE)szLinkVisitedColor, &cb);
  263. cb = sizeof (szLinkColor);
  264. lResult = RegQueryValueEx(hReg, (LPTSTR)c_szLinkColorIE, 0, NULL, (LPBYTE)szLinkColor, &cb);
  265. // Close Reg
  266. RegCloseKey(hReg);
  267. // Did we find it
  268. if (lResult == ERROR_SUCCESS)
  269. goto found;
  270. tryns:
  271. // Try Netscape
  272. if (RegOpenKeyEx (HKEY_CURRENT_USER, (LPTSTR)c_szNSSettingsPath, 0, KEY_ALL_ACCESS, &hReg) != ERROR_SUCCESS)
  273. goto exit;
  274. // Query for value
  275. cb = sizeof (szLinkVisitedColor);
  276. RegQueryValueEx(hReg, (LPTSTR)c_szLinkVisitedColorNS, 0, NULL, (LPBYTE)szLinkVisitedColor, &cb);
  277. cb = sizeof (szLinkColor);
  278. lResult = RegQueryValueEx(hReg, (LPTSTR)c_szLinkColorNS, 0, NULL, (LPBYTE)szLinkColor, &cb);
  279. // Close Reg
  280. RegCloseKey(hReg);
  281. // Did we find it
  282. if (lResult == ERROR_SUCCESS)
  283. goto found;
  284. // Not Found
  285. goto exit;
  286. found:
  287. // Parse Link
  288. ParseLinkColorFromSz(szLinkColor, &g_crLink);
  289. ParseLinkColorFromSz(szLinkVisitedColor, &g_crLinkVisited);
  290. if (pclrLink)
  291. *pclrLink = g_crLink;
  292. if (pclrViewed)
  293. *pclrViewed = g_crLinkVisited;
  294. return (TRUE);
  295. exit:
  296. // Done
  297. return (FALSE);
  298. }
  299. //$$///////////////////////////////////////////////////////////////////////
  300. //
  301. // CheckForWAB(void)
  302. //
  303. // return TRUE if default Contacts sectionselected as "Address Book" means WAB
  304. // also We need to be sure that Microsoft Outlook is default email client,
  305. // if Microsoft Outlook selected as default Contacts
  306. //////////////////////////////////////////////////////////////////////////
  307. BOOL CheckForWAB(void)
  308. {
  309. BOOL bRet = TRUE;
  310. HKEY hKeyContacts = NULL;
  311. DWORD dwErr = 0;
  312. DWORD dwSize = 0;
  313. DWORD dwType = 0;
  314. TCHAR szBuf[MAX_PATH];
  315. // Open the key for default Contacts client
  316. // HKLM\Software\Clients\Contacts
  317. dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szDefContactsKey, 0, KEY_READ, &hKeyContacts);
  318. if(dwErr != ERROR_SUCCESS)
  319. {
  320. // DebugTrace( TEXT("RegopenKey %s Failed -> %u\n"), szDefContactsKey, dwErr);
  321. goto out;
  322. }
  323. dwSize = CharSizeOf(szBuf); // Expect ERROR_MORE_DATA
  324. dwErr = RegQueryValueEx(hKeyContacts, NULL, NULL, &dwType, (LPBYTE)szBuf, &dwSize);
  325. if(dwErr != ERROR_SUCCESS)
  326. goto out;
  327. if(!lstrcmpi(szBuf, szOutlookName))
  328. {
  329. // Yes its Microsoft Outlook
  330. bRet = FALSE;
  331. }
  332. else
  333. goto out;
  334. #ifdef NEED
  335. RegCloseKey(hKeyContacts);
  336. // Check that default email is Microsoft Outlook too.
  337. // Open the key for default internet mail client
  338. // HKLM\Software\Clients\Mail
  339. dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szDefMailKey, 0, KEY_READ, &hKeyContacts);
  340. if(dwErr != ERROR_SUCCESS)
  341. {
  342. // DebugTrace( TEXT("RegopenKey %s Failed -> %u\n"), szDefMailKey, dwErr);
  343. bRet = TRUE;
  344. goto out;
  345. }
  346. dwSize = CharSizeOf(szBuf); // Expect ERROR_MORE_DATA
  347. dwErr = RegQueryValueEx( hKeyContacts, NULL, NULL, &dwType, (LPBYTE)szBuf, &dwSize);
  348. if(dwErr != ERROR_SUCCESS)
  349. {
  350. bRet = TRUE;
  351. goto out;
  352. }
  353. if(lstrcmpi(szBuf, szOutlookName))
  354. {
  355. // Yes its not Microsoft Outlook
  356. bRet = TRUE;
  357. }
  358. #endif // NEED
  359. out:
  360. if(hKeyContacts)
  361. RegCloseKey(hKeyContacts);
  362. return(bRet);
  363. }
  364. //$$///////////////////////////////////////////////////////////////////////
  365. //
  366. // CheckForOutlookExpress
  367. //
  368. // szDllPath - is a big enough buffer that will contain the path for
  369. // the OE dll ..
  370. //
  371. //////////////////////////////////////////////////////////////////////////
  372. BOOL CheckForOutlookExpress(LPTSTR szDllPath, DWORD cchDllPath)
  373. {
  374. HKEY hKeyMail = NULL;
  375. HKEY hKeyOE = NULL;
  376. DWORD dwErr = 0;
  377. DWORD dwSize = 0;
  378. TCHAR szBuf[MAX_PATH];
  379. TCHAR szPathExpand[MAX_PATH];
  380. DWORD dwType = 0;
  381. BOOL bRet = FALSE;
  382. if (!szDllPath)
  383. goto out;
  384. szDllPath[0] = 0;
  385. szPathExpand[0] = 0;
  386. // Open the key for default internet mail client
  387. // HKLM\Software\Clients\Mail
  388. dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szDefMailKey, 0, KEY_READ, &hKeyMail);
  389. if(dwErr != ERROR_SUCCESS)
  390. {
  391. // DebugTrace( TEXT("RegopenKey %s Failed -> %u\n"), szDefMailKey, dwErr);
  392. goto out;
  393. }
  394. dwSize = CharSizeOf(szBuf); // Expect ERROR_MORE_DATA
  395. dwErr = RegQueryValueEx( hKeyMail, NULL, NULL, &dwType, (LPBYTE)szBuf, &dwSize);
  396. if(dwErr != ERROR_SUCCESS)
  397. {
  398. goto out;
  399. }
  400. if(!lstrcmpi(szBuf, szOEName))
  401. {
  402. // Yes its outlook express ..
  403. bRet = TRUE;
  404. }
  405. //Get the DLL Path anyway whether this is the default key or not
  406. // Get the DLL Path
  407. dwErr = RegOpenKeyEx(hKeyMail, szOEName, 0, KEY_READ, &hKeyOE);
  408. if(dwErr != ERROR_SUCCESS)
  409. {
  410. // DebugTrace( TEXT("RegopenKey %s Failed -> %u\n"), szDefMailKey, dwErr);
  411. goto out;
  412. }
  413. dwSize = ARRAYSIZE(szBuf);
  414. szBuf[0] = 0;
  415. dwErr = RegQueryValueEx(hKeyOE, szOEDllPathKey, NULL, &dwType, (LPBYTE)szBuf, &dwSize);
  416. if (REG_EXPAND_SZ == dwType)
  417. {
  418. ExpandEnvironmentStrings(szBuf, szPathExpand, ARRAYSIZE(szPathExpand));
  419. StrCpyN(szBuf, szPathExpand, ARRAYSIZE(szBuf));
  420. }
  421. if(dwErr != ERROR_SUCCESS)
  422. {
  423. goto out;
  424. }
  425. if(lstrlen(szBuf))
  426. StrCpyN(szDllPath, szBuf, cchDllPath);
  427. out:
  428. if(hKeyOE)
  429. RegCloseKey(hKeyOE);
  430. if(hKeyMail)
  431. RegCloseKey(hKeyMail);
  432. return bRet;
  433. }
  434. //$$//////////////////////////////////////////////////////////////////////
  435. //
  436. // HrSendMail - does the actual mail sending
  437. // Our first priority is to Outlook Express which currently has a
  438. // different code path than the regular MAPI client .. so we look
  439. // under HKLM\Software\Clients\Mail .. if the client is OE then
  440. // we just loadlibrary and getprocaddress for sendmail
  441. // If its not OE, then we call the mapi32.dll and load it ..
  442. // If both fail we will not be able to send mail ...
  443. //
  444. // This function will free the lpList no matter what happens
  445. // so caller should not expect to reuse it (This is so we can
  446. // give the pointer to a seperate thread and not worry about it)
  447. //
  448. //////////////////////////////////////////////////////////////////////////
  449. HRESULT HrSendMail(HWND hWndParent, ULONG nRecipCount, LPRECIPLIST lpList, BOOL bUseOEForSendMail)
  450. {
  451. HRESULT hr = E_FAIL;
  452. HINSTANCE hLibMapi = NULL;
  453. BOOL bIsOE = FALSE; // right now there is a different code path
  454. // for OE vs other MAPI clients
  455. TCHAR szBuf[MAX_PATH];
  456. LPMAPISENDMAIL lpfnMAPISendMail = NULL;
  457. LHANDLE hMapiSession = 0;
  458. LPMAPILOGON lpfnMAPILogon = NULL;
  459. LPMAPILOGOFF lpfnMAPILogoff = NULL;
  460. LPBYTE lpbName, lpbAddrType, lpbEmail;
  461. ULONG ulMapiDataType;
  462. ULONG cbEntryID = 0;
  463. LPENTRYID lpEntryID = NULL;
  464. MapiMessage Msg = {0};
  465. MapiRecipDesc * lprecips = NULL;
  466. if(!nRecipCount)
  467. {
  468. hr = MAPI_W_ERRORS_RETURNED;
  469. goto out;
  470. }
  471. // Check if OutlookExpress is the default current client ..
  472. bIsOE = CheckForOutlookExpress(szBuf, ARRAYSIZE(szBuf));
  473. // Turn off all notifications for simple MAPI send mail, if the default
  474. // email client is Outlook. This is necessary because Outlook changes the
  475. // WAB MAPI allocation functions during simple MAPI and we don't want any
  476. // internal WAB functions using these allocators.
  477. #ifdef LATER
  478. if (!bIsOE && !bUseOEForSendMail)
  479. vTurnOffAllNotifications();
  480. // if OE is the default client or OE launched this WAB, use OE for SendMail
  481. if(lstrlen(szBuf) && (bIsOE||bUseOEForSendMail))
  482. {
  483. hLibMapi = LoadLibrary(szBuf);
  484. }
  485. else
  486. #endif
  487. {
  488. // Check if simple mapi is installed
  489. if(GetProfileInt( TEXT("mail"), TEXT("mapi"), 0) == 1)
  490. hLibMapi = LoadLibrary( TEXT("mapi32.dll"));
  491. if(!hLibMapi) // try loading the OE MAPI dll directly
  492. {
  493. // Load the path to the msimnui.dll
  494. CheckForOutlookExpress(szBuf, ARRAYSIZE(szBuf));
  495. if(lstrlen(szBuf)) // Load the dll directly - dont bother going through msoemapi.dll
  496. hLibMapi = LoadLibrary(szBuf);
  497. }
  498. }
  499. if(!hLibMapi)
  500. {
  501. _ASSERT(FALSE); // DebugPrintError(( TEXT("Could not load/find simple mapi\n")));
  502. hr = MAPI_E_NOT_FOUND;
  503. goto out;
  504. }
  505. else if(hLibMapi)
  506. {
  507. lpfnMAPILogon = (LPMAPILOGON) GetProcAddress (hLibMapi, "MAPILogon");
  508. lpfnMAPILogoff= (LPMAPILOGOFF)GetProcAddress (hLibMapi, "MAPILogoff");
  509. lpfnMAPISendMail = (LPMAPISENDMAIL) GetProcAddress (hLibMapi, "MAPISendMail");
  510. if(!lpfnMAPISendMail || !lpfnMAPILogon || !lpfnMAPILogoff)
  511. {
  512. _ASSERT(FALSE); // DebugPrintError(( TEXT("MAPI proc not found\n")));
  513. hr = MAPI_E_NOT_FOUND;
  514. goto out;
  515. }
  516. hr = lpfnMAPILogon( (ULONG_PTR)hWndParent, NULL,
  517. NULL, // No password needed.
  518. 0L, // Use shared session.
  519. 0L, // Reserved; must be 0.
  520. &hMapiSession); // Session handle.
  521. if(hr != SUCCESS_SUCCESS)
  522. {
  523. // DebugTrace( TEXT("MAPILogon failed\n"));
  524. // its possible the logon failed since there was no shared logon session
  525. // Try again to create a new session with UI
  526. hr = lpfnMAPILogon( (ULONG_PTR)hWndParent, NULL,
  527. NULL, // No password needed.
  528. MAPI_LOGON_UI | MAPI_NEW_SESSION, // Use shared session.
  529. 0L, // Reserved; must be 0.
  530. &hMapiSession); // Session handle.
  531. if(hr != SUCCESS_SUCCESS)
  532. {
  533. // DebugTrace( TEXT("MAPILogon failed\n"));
  534. goto out;
  535. }
  536. }
  537. }
  538. // Load the MAPI functions here ...
  539. //
  540. lprecips = (MapiRecipDesc *) LocalAlloc(LMEM_ZEROINIT, sizeof(MapiRecipDesc) * nRecipCount);
  541. {
  542. LPRECIPLIST lpTemp = lpList;
  543. ULONG count = 0;
  544. while(lpTemp)
  545. {
  546. lprecips[count].ulRecipClass = MAPI_TO;
  547. lprecips[count].lpszName = lpTemp->lpszName;
  548. lprecips[count].lpszAddress = lpTemp->lpszEmail;
  549. #ifdef LATER
  550. // [PaulHi] 4/20/99 Raid 73455
  551. // Convert Unicode EID OneOff strings to ANSI
  552. if ( IsWABEntryID(lpTemp->lpSB->cb, (LPVOID)lpTemp->lpSB->lpb,
  553. &lpbName, &lpbAddrType, &lpbEmail, (LPVOID *)&ulMapiDataType, NULL) == WAB_ONEOFF )
  554. {
  555. if (ulMapiDataType & MAPI_UNICODE)
  556. {
  557. hr = CreateWABEntryIDEx(
  558. FALSE, // Don't want Unicode EID strings
  559. WAB_ONEOFF, // EID type
  560. (LPWSTR)lpbName,
  561. (LPWSTR)lpbAddrType,
  562. (LPWSTR)lpbEmail,
  563. 0,
  564. 0,
  565. NULL,
  566. &cbEntryID,
  567. &lpEntryID);
  568. if (FAILED(hr))
  569. goto out;
  570. lprecips[count].ulEIDSize = cbEntryID;
  571. lprecips[count].lpEntryID = lpEntryID;
  572. }
  573. else
  574. {
  575. lprecips[count].ulEIDSize = lpTemp->lpSB->cb;
  576. lprecips[count].lpEntryID = (LPVOID)lpTemp->lpSB->lpb;
  577. }
  578. }
  579. #endif // LATER
  580. lpTemp = lpTemp->lpNext;
  581. count++;
  582. }
  583. }
  584. Msg.nRecipCount = nRecipCount;
  585. Msg.lpRecips = lprecips;
  586. hr = lpfnMAPISendMail (hMapiSession, (ULONG_PTR)hWndParent,
  587. &Msg, // the message being sent
  588. MAPI_DIALOG, // allow the user to edit the message
  589. 0L); // reserved; must be 0
  590. if(hr != SUCCESS_SUCCESS)
  591. goto out;
  592. hr = S_OK;
  593. out:
  594. if (lpEntryID)
  595. LocalFreeAndNull((void **)&lpEntryID);
  596. // The simple MAPI session should end after this
  597. if(hMapiSession && lpfnMAPILogoff)
  598. lpfnMAPILogoff(hMapiSession,0L,0L,0L);
  599. if(hLibMapi)
  600. FreeLibrary(hLibMapi);
  601. #ifdef LATER
  602. // Turn all notifications back on and refresh the WAB UI (just in case)
  603. if (!bIsOE && !bUseOEForSendMail)
  604. {
  605. vTurnOnAllNotifications();
  606. if (lpIAB->hWndBrowse)
  607. PostMessage(lpIAB->hWndBrowse, WM_COMMAND, (WPARAM) IDM_VIEW_REFRESH, 0);
  608. }
  609. if(lprecips)
  610. {
  611. ULONG i = 0;
  612. for(i=0;i < nRecipCount;i++)
  613. {
  614. LocalFreeAndNull((void **)&lprecips[i].lpszName);
  615. LocalFreeAndNull((void **)&lprecips[i].lpszAddress);
  616. }
  617. LocalFree(lprecips);
  618. }
  619. #endif
  620. // The one-off here was allocated before the simple MAPI session and so used
  621. // the default WAB allocators.
  622. if(lpList)
  623. FreeLPRecipList(lpList);
  624. switch(hr)
  625. {
  626. case S_OK:
  627. case MAPI_E_USER_CANCEL:
  628. case MAPI_E_USER_ABORT:
  629. break;
  630. case MAPI_W_ERRORS_RETURNED:
  631. _ASSERT(FALSE); // ShowMessageBox(hWndParent, idsSendMailToNoEmail, MB_ICONEXCLAMATION | MB_OK);
  632. break;
  633. case MAPI_E_NOT_FOUND:
  634. _ASSERT(FALSE); // ShowMessageBox(hWndParent, idsSendMailNoMapi, MB_ICONEXCLAMATION | MB_OK);
  635. break;
  636. default:
  637. _ASSERT(FALSE); // ShowMessageBox(hWndParent, idsSendMailError, MB_ICONEXCLAMATION | MB_OK);
  638. break;
  639. }
  640. return hr;
  641. }
  642. //$$//////////////////////////////////////////////////////////////////////
  643. //
  644. // MailThreadProc - does the actual sendmail and cleans up
  645. //
  646. //////////////////////////////////////////////////////////////////////////
  647. DWORD WINAPI MailThreadProc( LPVOID lpParam )
  648. {
  649. LPMAIL_PARAMS lpMP = (LPMAIL_PARAMS) lpParam;
  650. #ifdef LATER
  651. LPPTGDATA lpPTGData = GetThreadStoragePointer(); // Bug - if this new thread accesses the WAB we lose a hunka memory
  652. // So add this thing here ourselves and free it when this thread's work is done
  653. #endif
  654. if(!lpMP)
  655. return 0;
  656. // DebugTrace( TEXT("Mail Thread ID = 0x%.8x\n"),GetCurrentThreadId());
  657. HrSendMail(lpMP->hWnd, lpMP->nRecipCount, lpMP->lpList, lpMP->bUseOEForSendMail);
  658. LocalFree(lpMP);
  659. return 0;
  660. }
  661. //$$//////////////////////////////////////////////////////////////////////
  662. //
  663. // HrStartMailThread
  664. //
  665. // Starts a seperate thread to send mapi based mail from
  666. //
  667. //////////////////////////////////////////////////////////////////////////
  668. HRESULT HrStartMailThread(HWND hWndParent, ULONG nRecipCount, LPRECIPLIST lpList, BOOL bUseOEForSendMail)
  669. {
  670. LPMAIL_PARAMS lpMP = NULL;
  671. HRESULT hr = E_FAIL;
  672. lpMP = (LPMAIL_PARAMS) LocalAlloc(LMEM_ZEROINIT, sizeof(MAIL_PARAMS));
  673. if(!lpMP)
  674. goto out;
  675. {
  676. HANDLE hThread = NULL;
  677. DWORD dwThreadID = 0;
  678. lpMP->hWnd = hWndParent;
  679. lpMP->nRecipCount = nRecipCount;
  680. lpMP->lpList = lpList;
  681. lpMP->bUseOEForSendMail = bUseOEForSendMail;
  682. hThread = CreateThread(
  683. NULL, // no security attributes
  684. 0, // use default stack size
  685. MailThreadProc, // thread function
  686. (LPVOID) lpMP, // argument to thread function
  687. 0, // use default creation flags
  688. &dwThreadID); // returns the thread identifier
  689. if(hThread == NULL)
  690. goto out;
  691. hr = S_OK;
  692. CloseHandle(hThread);
  693. }
  694. out:
  695. if(HR_FAILED(hr))
  696. {
  697. _ASSERT(FALSE);
  698. #ifdef LATER
  699. ShowMessageBox(hWndParent, idsSendMailError, MB_OK | MB_ICONEXCLAMATION);
  700. #endif
  701. // we can assume that HrSendMail never got called so we should free lpList & lpMP
  702. if(lpMP)
  703. LocalFree(lpMP);
  704. if(lpList)
  705. FreeLPRecipList(lpList);
  706. }
  707. return hr;
  708. }
  709. //$$/////////////////////////////////////////////////////////////////////
  710. //
  711. // FreeLPRecipList
  712. //
  713. // Frees a linked list containing the above structures
  714. //
  715. /////////////////////////////////////////////////////////////////////////
  716. void FreeLPRecipList(LPRECIPLIST lpList)
  717. {
  718. if(lpList)
  719. {
  720. LPRECIPLIST lpTemp = lpList;
  721. while(lpTemp)
  722. {
  723. lpList = lpTemp->lpNext;
  724. if(lpTemp->lpszName)
  725. LocalFree(lpTemp->lpszName);
  726. if(lpTemp->lpszEmail)
  727. LocalFree(lpTemp->lpszEmail);
  728. if(lpTemp->lpSB)
  729. LocalFree(lpTemp->lpSB);
  730. LocalFree(lpTemp);
  731. lpTemp = lpList;
  732. }
  733. }
  734. }
  735. //$$/////////////////////////////////////////////////////////////////////
  736. //
  737. // FreeLPRecipList
  738. //
  739. // Frees a linked list containing the above structures
  740. //
  741. /////////////////////////////////////////////////////////////////////////
  742. LPRECIPLIST AddTeimToRecipList(LPRECIPLIST lpList, WCHAR *pwszEmail, WCHAR *pwszName, LPSBinary lpSB)
  743. {
  744. LPRECIPLIST lpTemp = NULL;
  745. lpTemp = (RECIPLIST*) LocalAlloc(LMEM_ZEROINIT, sizeof(RECIPLIST));
  746. if(!lpTemp)
  747. return NULL;
  748. if(pwszEmail)
  749. {
  750. LPTSTR pszEmail = LPTSTRfromBstr(pwszEmail);
  751. if(pszEmail)
  752. {
  753. ULONG cchSize = lstrlenW(pwszEmail)+1;
  754. lpTemp->lpszEmail = (TCHAR *) LocalAlloc(LMEM_ZEROINIT, cchSize*sizeof(lpTemp->lpszEmail[0]));
  755. if(lpTemp->lpszEmail)
  756. StrCpyN(lpTemp->lpszEmail, pszEmail, cchSize);
  757. MemFree(pszEmail);
  758. }
  759. }
  760. if(pwszName)
  761. {
  762. LPTSTR pszName = LPTSTRfromBstr(pwszName);
  763. if(pszName)
  764. {
  765. ULONG cchSize = lstrlen(pszName)+1;
  766. lpTemp->lpszName = (TCHAR *) LocalAlloc(LMEM_ZEROINIT, cchSize*sizeof(lpTemp->lpszEmail[0]));
  767. if(lpTemp->lpszName)
  768. StrCpyN(lpTemp->lpszName, pszName, cchSize);
  769. MemFree(pszName);
  770. }
  771. }
  772. if(lpSB)
  773. {
  774. lpTemp->lpSB = (SBinary *) LocalAlloc(LMEM_ZEROINIT, sizeof(SBinary));
  775. if(lpTemp->lpSB )
  776. *(lpTemp->lpSB) = *lpSB;
  777. }
  778. if(lpList)
  779. lpList->lpNext = lpTemp;
  780. return lpTemp;
  781. }
  782. const static TCHAR lpszWABDLLRegPathKey[] = TEXT("Software\\Microsoft\\WAB\\DLLPath");
  783. const static TCHAR lpszWABEXERegPathKey[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\wab.exe");
  784. const static TCHAR lpszWABEXE[] = TEXT("wab.exe");
  785. // =============================================================================
  786. // HrLoadPathWABEXE - creaetd vikramm 5/14/97 - loads the registered path of the
  787. // latest wab.exe
  788. // szPath - pointer to a buffer
  789. // cbPath - sizeof buffer
  790. // =============================================================================
  791. // ~~~~ @TODO dhaws Might need to convert this
  792. HRESULT HrLoadPathWABEXE(LPWSTR szPath, ULONG cbPath)
  793. {
  794. DWORD dwType;
  795. ULONG cbData = MAX_PATH;
  796. HKEY hKey;
  797. TCHAR szTmpPath[MAX_PATH];
  798. _ASSERT(szPath != NULL);
  799. _ASSERT(cbPath > 0);
  800. *szPath = '\0';
  801. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpszWABEXERegPathKey, 0, KEY_READ, &hKey))
  802. {
  803. SHQueryValueEx( hKey, "", NULL, &dwType, (LPBYTE) szTmpPath, &cbData);
  804. RegCloseKey(hKey);
  805. }
  806. if(!lstrlen(szTmpPath))
  807. {
  808. if(!MultiByteToWideChar(GetACP(), 0, lpszWABEXE, -1, szPath, cbPath))
  809. return(E_FAIL);
  810. }
  811. else
  812. {
  813. if(!MultiByteToWideChar(GetACP(), 0, szTmpPath, -1, szPath, cbPath))
  814. return(E_FAIL);
  815. }
  816. return S_OK;
  817. }
  818. DWORD DwGetMessStatus(void)
  819. {
  820. HKEY hKey;
  821. DWORD dwType = 0;
  822. DWORD dwVal = 0;
  823. ULONG cbData = sizeof(dwType);
  824. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szDisableMessnegerArea, 0, KEY_READ, &hKey))
  825. {
  826. RegQueryValueEx(hKey, szUseIM, NULL, &dwType, (LPBYTE) &dwVal, &cbData);
  827. RegCloseKey(hKey);
  828. }
  829. return dwVal;
  830. }
  831. DWORD DwGetDisableMessenger(void)
  832. {
  833. HKEY hKey;
  834. DWORD dwType = 0;
  835. DWORD dwVal = 0;
  836. ULONG cbData = sizeof(dwType);
  837. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, szIEContactsArea, 0, KEY_READ, &hKey))
  838. {
  839. RegQueryValueEx(hKey, szDisableIM, NULL, &dwType, (LPBYTE) &dwVal, &cbData);
  840. RegCloseKey(hKey);
  841. }
  842. return dwVal;
  843. }
  844. DWORD DwSetDisableMessenger(DWORD dwVal)
  845. {
  846. HKEY hKey;
  847. ULONG cbData = sizeof(DWORD);
  848. if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER, szIEContactsArea, 0, NULL, 0,
  849. KEY_ALL_ACCESS, NULL, &hKey, NULL))
  850. {
  851. RegSetValueEx(hKey, szDisableIM, NULL, REG_DWORD, (LPBYTE) &dwVal, cbData);
  852. RegCloseKey(hKey);
  853. }
  854. return dwVal;
  855. }
  856. DWORD DwGetOptions(void)
  857. {
  858. HKEY hKey;
  859. DWORD dwType = 0;
  860. DWORD dwVal = 0;
  861. ULONG cbData = sizeof(dwType);
  862. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, szIEContactsArea, 0, KEY_READ, &hKey))
  863. {
  864. RegQueryValueEx(hKey, szContactOptions, NULL, &dwType, (LPBYTE) &dwVal, &cbData);
  865. RegCloseKey(hKey);
  866. }
  867. return dwVal;
  868. }
  869. DWORD DwSetOptions(DWORD dwVal)
  870. {
  871. HKEY hKey;
  872. ULONG cbData = sizeof(DWORD);
  873. if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER, szIEContactsArea, 0, NULL, 0,
  874. KEY_ALL_ACCESS, NULL, &hKey, NULL))
  875. {
  876. RegSetValueEx(hKey, szContactOptions, NULL, REG_DWORD, (LPBYTE) &dwVal, cbData);
  877. RegCloseKey(hKey);
  878. }
  879. return dwVal;
  880. }
  881. BOOL IsTelInstalled(void)
  882. {
  883. HKEY hKey;
  884. BOOL fRet = FALSE;
  885. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, szPhoenixArea, 0, KEY_READ, &hKey))
  886. {
  887. RegCloseKey(hKey);
  888. fRet = TRUE;
  889. }
  890. return(fRet);
  891. }