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.

730 lines
23 KiB

  1. #include "pch.hxx"
  2. #include <regutil.h>
  3. #ifndef THOR_SETUP
  4. #include <strconst.h>
  5. #include "shared.h"
  6. #else
  7. #include "strings.h"
  8. #include "util.h"
  9. #endif
  10. #include <ourguid.h>
  11. #include <resource.h>
  12. #ifndef THOR_SETUP
  13. #include <shlwapi.h>
  14. #include "shlwapip.h"
  15. #define strstr StrStr
  16. #define RegDeleteKeyRecursive SHDeleteKey
  17. #endif // THOR_SETUP
  18. #include "demand.h"
  19. typedef HINSTANCE (STDAPICALLTYPE FGETCOMPONENTPATH)();
  20. typedef FGETCOMPONENTPATH *LPFGETCOMPONENTPATH;
  21. typedef HINSTANCE (STDAPICALLTYPE FIXMAPI)();
  22. typedef FIXMAPI *LPFIXMAPI;
  23. BOOL IsXPSP1OrLater()
  24. {
  25. BOOL fResult = FALSE;
  26. OSVERSIONINFO osvi;
  27. osvi.dwOSVersionInfoSize = sizeof(osvi);
  28. if (GetVersionEx(&osvi))
  29. {
  30. if (VER_PLATFORM_WIN32_NT == osvi.dwPlatformId)
  31. {
  32. if (osvi.dwMajorVersion > 5)
  33. {
  34. fResult = TRUE;
  35. }
  36. else if (osvi.dwMajorVersion == 5)
  37. {
  38. if (osvi.dwMinorVersion > 1)
  39. {
  40. fResult = TRUE;
  41. }
  42. else if (osvi.dwMinorVersion == 1)
  43. {
  44. if (osvi.dwBuildNumber > 2600)
  45. {
  46. fResult = TRUE;
  47. }
  48. else if (osvi.dwBuildNumber == 2600)
  49. {
  50. HKEY hkey;
  51. // HIVESFT.INF and UPDATE.INF set this for service packs:
  52. // HKLM,SYSTEM\CurrentControlSet\Control\Windows,"CSDVersion",0x10001,0x100
  53. LONG lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\Windows"), 0, KEY_QUERY_VALUE, &hkey);
  54. if (ERROR_SUCCESS == lResult)
  55. {
  56. DWORD dwValue;
  57. DWORD cbValue = sizeof(dwValue);
  58. DWORD dwType;
  59. lResult = RegQueryValueEx(hkey, TEXT("CSDVersion"), NULL, &dwType, (LPBYTE)&dwValue, &cbValue);
  60. if ((ERROR_SUCCESS == lResult) && (REG_DWORD == dwType) && (dwValue >= 0x100))
  61. {
  62. fResult = TRUE;
  63. }
  64. RegCloseKey(hkey);
  65. }
  66. }
  67. }
  68. }
  69. }
  70. }
  71. return fResult;
  72. }
  73. // ********* Tests
  74. // Looks in the registry at a value placed there by msoe.dll's selfreg
  75. BOOL GetAthenaRegPath(TCHAR *szAthenaDll, DWORD cch)
  76. {
  77. BOOL fRet;
  78. HKEY hkey;
  79. TCHAR szPath[MAX_PATH], szExpanded[MAX_PATH];
  80. DWORD dwType, cb;
  81. LPTSTR psz;
  82. szPath[0] = '\0';
  83. fRet = FALSE;
  84. wnsprintf(szExpanded, ARRAYSIZE(szExpanded), c_szProtocolPath, c_szMail, c_szMOE);
  85. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szExpanded, 0, KEY_QUERY_VALUE, &hkey))
  86. {
  87. cb = sizeof(szPath);
  88. if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szRegDllPath, 0, &dwType, (LPBYTE)szPath, &cb) && cb)
  89. {
  90. // Remove %values% if needed
  91. if (REG_EXPAND_SZ == dwType)
  92. {
  93. ExpandEnvironmentStrings(szPath, szExpanded, ARRAYSIZE(szExpanded));
  94. psz = szExpanded;
  95. }
  96. else
  97. psz = szPath;
  98. StrCpyN(szAthenaDll, psz, cch);
  99. fRet = TRUE;
  100. }
  101. RegCloseKey(hkey);
  102. }
  103. return(fRet);
  104. }
  105. #ifdef THOR_SETUP
  106. BOOL GetExePath(LPCTSTR szExe, TCHAR *szPath, DWORD cch, BOOL fDirOnly)
  107. {
  108. BOOL fRet;
  109. HKEY hkey;
  110. DWORD dwType, cb;
  111. TCHAR sz[MAX_PATH], szT[MAX_PATH];
  112. Assert(szExe != NULL);
  113. Assert(szPath != NULL);
  114. fRet = FALSE;
  115. wnsprintf(sz, ARRAYSIZE(sz),c_szPathFileFmt, c_szAppPaths, szExe);
  116. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, sz, 0, KEY_QUERY_VALUE, &hkey))
  117. {
  118. cb = sizeof(szT);
  119. if (ERROR_SUCCESS == RegQueryValueEx(hkey, fDirOnly ? c_szRegPath : NULL, 0, &dwType, (LPBYTE)szT, &cb) && cb)
  120. {
  121. if (dwType == REG_EXPAND_SZ)
  122. {
  123. cb = ExpandEnvironmentStrings(szT, szPath, cch);
  124. if (cb != 0 && cb <= cch)
  125. fRet = TRUE;
  126. }
  127. else
  128. {
  129. Assert(dwType == REG_SZ);
  130. StrCpyN(szPath, szT, cch);
  131. fRet = TRUE;
  132. }
  133. }
  134. RegCloseKey(hkey);
  135. }
  136. return(fRet);
  137. }
  138. #endif
  139. HRESULT GetCLSIDFromSubKey(HKEY hKey, LPSTR rgchBuf, ULONG *pcbBuf)
  140. {
  141. HKEY hKeyCLSID;
  142. DWORD dwType;
  143. HRESULT hr=E_FAIL;
  144. // Lets open they server key
  145. if (RegOpenKeyEx(hKey, c_szCLSID, 0, KEY_READ, &hKeyCLSID) == ERROR_SUCCESS)
  146. {
  147. if (ERROR_SUCCESS == RegQueryValueEx(hKeyCLSID, NULL, 0, &dwType, (LPBYTE)rgchBuf, pcbBuf) && *pcbBuf)
  148. hr = S_OK;
  149. RegCloseKey(hKeyCLSID);
  150. }
  151. return hr;
  152. }
  153. // FUNCTION: FAssocsOK()
  154. //
  155. // PURPOSE: Checks to see if our file-type associations are in place
  156. //
  157. // Returns:
  158. BOOL FAssocsOK(LPCTSTR pszClient, LPCTSTR pszProduct)
  159. {
  160. HKEY hkeyProtocols;
  161. HKEY hkeyRealProt;
  162. HKEY hkeyAppsProt;
  163. TCHAR szProtPath[MAX_PATH];
  164. TCHAR szRealPath[MAX_PATH];
  165. TCHAR szAppPath [MAX_PATH];
  166. TCHAR szTemp [MAX_PATH];
  167. DWORD dwIndex = 0;
  168. DWORD cb;
  169. DWORD cbMaxProtocolLen;
  170. DWORD dwType, dwType2;
  171. LPTSTR pszURL;
  172. BOOL fNoProbs = TRUE;
  173. // Open up the corresponding protocols key
  174. wnsprintf(szProtPath, ARRAYSIZE(szProtPath), c_szProtocolPath, pszClient, pszProduct);
  175. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szProtPath, 0, KEY_READ, &hkeyProtocols))
  176. {
  177. // Figure out the longest protocol name
  178. if (ERROR_SUCCESS == RegQueryInfoKey(hkeyProtocols, NULL, NULL, NULL, NULL,
  179. &cbMaxProtocolLen, NULL, NULL, NULL, NULL, NULL, NULL))
  180. {
  181. // Allow for "\Shell\Open\Command" whose length is 19 + 1 for NT's RegQueryInfoKey
  182. cbMaxProtocolLen += 20;
  183. // Allocate buffer for string
  184. if (MemAlloc((LPVOID*)&pszURL, cbMaxProtocolLen * sizeof(TCHAR)))
  185. {
  186. // Enumerate the protocol subkeys
  187. cb = cbMaxProtocolLen;
  188. while (fNoProbs && ERROR_SUCCESS == RegEnumKeyEx(hkeyProtocols, dwIndex++, pszURL, &cb, NULL, NULL, NULL, NULL))
  189. {
  190. fNoProbs = FALSE;
  191. StrCatBuff(pszURL, c_szRegOpen, cbMaxProtocolLen);
  192. // Open up the real protocol\shell\open\command key
  193. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, pszURL, 0, KEY_READ, &hkeyRealProt))
  194. {
  195. // Open up app's protocol\shell\open\command key
  196. if (ERROR_SUCCESS == RegOpenKeyEx(hkeyProtocols, pszURL, 0, KEY_READ, &hkeyAppsProt))
  197. {
  198. // Grab the current registered handler
  199. cb = ARRAYSIZE(szRealPath);
  200. if (ERROR_SUCCESS == RegQueryValueEx(hkeyRealProt, NULL, 0, &dwType, (LPBYTE)szRealPath, &cb))
  201. {
  202. // Grab the App's Path
  203. cb = ARRAYSIZE(szAppPath);
  204. if (ERROR_SUCCESS == RegQueryValueEx(hkeyAppsProt, NULL, 0, &dwType2, (LPBYTE)szAppPath, &cb))
  205. {
  206. if (REG_EXPAND_SZ == dwType2)
  207. {
  208. ExpandEnvironmentStrings(szAppPath, szTemp, ARRAYSIZE(szTemp));
  209. StrCpyN(szAppPath, szTemp, ARRAYSIZE(szAppPath));
  210. }
  211. if (REG_EXPAND_SZ == dwType)
  212. {
  213. ExpandEnvironmentStrings(szRealPath, szTemp, ARRAYSIZE(szTemp));
  214. StrCpyN(szRealPath, szTemp, ARRAYSIZE(szRealPath));
  215. }
  216. // Do a simple case insensitive comparison
  217. if (!lstrcmpi(szAppPath, szRealPath))
  218. fNoProbs = TRUE;
  219. }
  220. }
  221. RegCloseKey(hkeyAppsProt);
  222. }
  223. RegCloseKey(hkeyRealProt);
  224. }
  225. // Reset cb
  226. cb = cbMaxProtocolLen;
  227. }
  228. MemFree(pszURL);
  229. }
  230. }
  231. RegCloseKey(hkeyProtocols);
  232. }
  233. return (fNoProbs);
  234. }
  235. // FUNCTION: FExchangeServerInstalled()
  236. //
  237. // PURPOSE: Checks to see if Exchange Server is installed
  238. //
  239. // Based on code provided by msmith from OL
  240. //
  241. BOOL FExchangeServerInstalled()
  242. {
  243. HKEY hkeyServices;
  244. BOOL fInstalled = FALSE;
  245. // Get HKLM\Software\Microsoft\Exchange\Setup registry key
  246. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szExchangeSetup, 0, KEY_READ, &hkeyServices))
  247. {
  248. // Does Services registry value exist?
  249. fInstalled = ERROR_SUCCESS == RegQueryValueEx(hkeyServices, c_szServices, NULL, NULL, NULL, NULL);
  250. RegCloseKey(hkeyServices);
  251. }
  252. return (fInstalled);
  253. }
  254. // FUNCTION: FMapiStub()
  255. //
  256. // PURPOSE: Checks to see if the mapi32.dll is Outlook's
  257. //
  258. // Based on code provided by [email protected]
  259. //
  260. // Return Value: TRUE - all is well
  261. // *pdw = Failure type if Return value is FALSE:
  262. // 1 = No mapi32.dll
  263. // 2 = Different mapi32.dll
  264. //
  265. BOOL FMapiStub(DWORD *pdw)
  266. {
  267. HINSTANCE hMapiStub;
  268. TCHAR szSystemPath[MAX_PATH];
  269. TCHAR szMapiPath[MAX_PATH];
  270. BOOL fMapiStub = FALSE;
  271. Assert(pdw);
  272. *pdw = 0;
  273. // If Exchange server is installed, their stub is in place, so leave it be
  274. if (FExchangeServerInstalled())
  275. return TRUE;
  276. // Build a path to mapi32.dll
  277. GetSystemDirectory(szSystemPath, ARRAYSIZE(szSystemPath));
  278. MakeFilePath(szSystemPath, c_szMAPIDLL, c_szEmpty, szMapiPath, ARRAYSIZE(szMapiPath));
  279. hMapiStub = LoadLibrary(szMapiPath);
  280. if (hMapiStub)
  281. {
  282. fMapiStub = NULL != (LPFGETCOMPONENTPATH)GetProcAddress(hMapiStub, TEXT("FGetComponentPath")); // STRING_OK Msmith
  283. if (!fMapiStub)
  284. *pdw = 2;
  285. FreeLibrary(hMapiStub);
  286. }
  287. else
  288. *pdw = 1;
  289. return fMapiStub;
  290. }
  291. BOOL FValidClient(LPCTSTR pszClient, LPCTSTR pszProduct)
  292. {
  293. TCHAR szBuffer[MAX_PATH];
  294. HKEY hkey2;
  295. BOOL fValid = FALSE;
  296. wnsprintf(szBuffer, ARRAYSIZE(szBuffer), c_szRegPathSpecificClient, pszClient, pszProduct);
  297. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuffer, 0, KEY_QUERY_VALUE, &hkey2))
  298. {
  299. RegCloseKey(hkey2);
  300. fValid = TRUE;
  301. }
  302. return fValid;
  303. }
  304. int DefaultClientSet(LPCTSTR pszClient)
  305. {
  306. int iRet;
  307. TCHAR sz[MAX_PATH], sz2[MAX_PATH];
  308. HKEY hkey, hkeyT;
  309. DWORD dwType, cb;
  310. iRet = NOT_HANDLED;
  311. wnsprintf(sz, ARRAYSIZE(sz), c_szPathFileFmt, c_szRegPathClients, pszClient);
  312. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, sz, 0, KEY_QUERY_VALUE, &hkey))
  313. {
  314. cb = sizeof(sz);
  315. if (ERROR_SUCCESS == RegQueryValueEx(hkey, NULL, NULL, &dwType, (LPBYTE)&sz, &cb))
  316. {
  317. // Sanity check - is the current client even valid?
  318. wnsprintf(sz2, ARRAYSIZE(sz2), c_szRegPathSpecificClient, pszClient, sz);
  319. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, sz2, 0, KEY_QUERY_VALUE, &hkeyT))
  320. {
  321. RegCloseKey(hkeyT);
  322. if (0 == lstrcmpi(c_szMOE, sz))
  323. iRet = HANDLED_CURR;
  324. else if (0 == lstrcmpi(c_szIMN, sz))
  325. iRet = NOT_HANDLED;
  326. else if (0 == lstrcmpi(c_szOutlook, sz))
  327. iRet = HANDLED_OUTLOOK;
  328. else if (0 == lstrcmpi(c_szNT, sz))
  329. iRet = NOT_HANDLED;
  330. else if (*sz != 0)
  331. iRet = HANDLED_OTHER;
  332. }
  333. }
  334. RegCloseKey(hkey);
  335. }
  336. return(iRet);
  337. }
  338. //
  339. // FUNCTION: FIsDefaultNewsConfiged()
  340. //
  341. // PURPOSE: Determines if Athena is currently the default news handler.
  342. //
  343. BOOL WINAPI FIsDefaultNewsConfiged(DWORD dwFlags)
  344. {
  345. BOOL fRet;
  346. if (0 == (dwFlags & DEFAULT_OUTNEWS))
  347. fRet = (HANDLED_CURR == DefaultClientSet(c_szNews)) && FAssocsOK(c_szNews, c_szMOE);
  348. else
  349. fRet = (HANDLED_OUTLOOK == DefaultClientSet(c_szNews)) && FAssocsOK(c_szNews, c_szOutlook);
  350. return(fRet);
  351. }
  352. //
  353. // FUNCTION: FIsDefaultMailConfiged()
  354. //
  355. // PURPOSE: Determines if Athena is currently the default mail handler.
  356. //
  357. BOOL WINAPI FIsDefaultMailConfiged()
  358. {
  359. DWORD dwTemp;
  360. return (HANDLED_CURR == DefaultClientSet(c_szMail) && FAssocsOK(c_szMail, c_szMOE) && FMapiStub(&dwTemp));
  361. }
  362. // ********* Actions
  363. // Set up the URL with our handler
  364. BOOL AddUrlHandler(LPCTSTR pszURL, LPCTSTR pszClient, LPCTSTR pszProduct, DWORD dwFlags)
  365. {
  366. HKEY hKey, hKeyProt;
  367. TCHAR szBuffer[MAX_PATH], szBuffer1[MAX_PATH];
  368. DWORD dwDisp, cb;
  369. BOOL fCreate = TRUE;
  370. // Try to detect if this URL is set or not...
  371. if (dwFlags & DEFAULT_DONTFORCE)
  372. {
  373. DWORD dwLen = lstrlen(pszURL);
  374. LPTSTR pszTemp;
  375. // 20 = 19 (length of "\Shell\Open\Command") + 1 for NULL
  376. DWORD cchSize = (dwLen+20);
  377. if (MemAlloc((LPVOID*)&pszTemp, cchSize * sizeof(pszTemp[0])))
  378. {
  379. StrCpyN(pszTemp, pszURL, cchSize);
  380. StrCatBuff(pszTemp, c_szRegOpen, cchSize);
  381. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, pszTemp, 0, KEY_READ, &hKey))
  382. {
  383. cb = sizeof(szBuffer);
  384. if (ERROR_SUCCESS == RegQueryValueEx(hKey, NULL, 0, NULL, (LPBYTE)szBuffer, &cb))
  385. {
  386. // Special case URL.DLL and MAILNEWS.DLL as okay to overwrite
  387. if (!strstr(szBuffer, c_szUrlDll) && !strstr(szBuffer, c_szMailNewsDllOld))
  388. fCreate = FALSE;
  389. }
  390. RegCloseKey(hKey);
  391. }
  392. MemFree(pszTemp);
  393. }
  394. }
  395. // Clear out any old info about this URL
  396. if (fCreate)
  397. {
  398. RegDeleteKeyRecursive(HKEY_CLASSES_ROOT, pszURL);
  399. // Figure out the source for the info
  400. wnsprintf(szBuffer1, ARRAYSIZE(szBuffer1), c_szProtocolPath, pszClient, pszProduct);
  401. wnsprintf(szBuffer, ARRAYSIZE(szBuffer), c_szPathFileFmt, szBuffer1, pszURL);
  402. // Copy the info to its new location
  403. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuffer, 0, KEY_READ, &hKeyProt))
  404. {
  405. if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CLASSES_ROOT, pszURL, 0,
  406. NULL, REG_OPTION_NON_VOLATILE,
  407. KEY_WRITE, NULL, &hKey, &dwDisp))
  408. {
  409. CopyRegistry(hKeyProt, hKey);
  410. RegCloseKey(hKey);
  411. }
  412. RegCloseKey(hKeyProt);
  413. }
  414. }
  415. return(TRUE);
  416. }
  417. void SetDefaultClient(LPCTSTR pszClient, LPCTSTR pszProduct, DWORD dwFlags)
  418. {
  419. TCHAR sz[MAX_PATH];
  420. HKEY hkey;
  421. DWORD dwDisp;
  422. BOOL fOK = TRUE;
  423. if (DEFAULT_DONTFORCE & dwFlags)
  424. {
  425. if (NOT_HANDLED != DefaultClientSet(pszClient))
  426. fOK = FALSE;
  427. }
  428. if (fOK)
  429. {
  430. wnsprintf(sz, ARRAYSIZE(sz), c_szPathFileFmt, c_szRegPathClients, pszClient);
  431. if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, sz,
  432. 0, NULL, REG_OPTION_NON_VOLATILE,
  433. KEY_SET_VALUE, NULL, &hkey, &dwDisp))
  434. {
  435. RegSetValueEx(hkey, NULL, 0, REG_SZ, (LPBYTE)pszProduct,
  436. (lstrlen(pszProduct) + 1) * sizeof(TCHAR));
  437. #ifndef THOR_SETUP
  438. // Bug 32136 in IE6 database
  439. SHSendMessageBroadcast(WM_SETTINGCHANGE, 0, (LPARAM)sz);
  440. #endif // THOR_SETUP
  441. RegCloseKey(hkey);
  442. }
  443. }
  444. }
  445. // Make sure MAPI32.dll is really Outlook's MAPISTUB
  446. BOOL EnsureMAPIStub(DWORD dwFlags)
  447. {
  448. BOOL fOK = FALSE;
  449. DWORD dwReason, dwReason2;
  450. HINSTANCE hMapiStub = NULL;
  451. TCHAR szSystemPath[MAX_PATH];
  452. TCHAR szPath[MAX_PATH];
  453. LPFGETCOMPONENTPATH pfnFixMAPI;
  454. HKEY hkeyRunOnce;
  455. BOOL fUI = dwFlags & DEFAULT_UI;
  456. UINT cch;
  457. // Is the mapistub already in place?
  458. if (FMapiStub(&dwReason))
  459. {
  460. fOK = TRUE;
  461. goto exit;
  462. }
  463. switch (dwReason)
  464. {
  465. case 0:
  466. AssertSz(FALSE, "EnsureMAPIStub failed for no reason.");
  467. goto exit;
  468. case 1: // NonExistent
  469. case 2: // Different
  470. // Should be able to just load mapistub and FixMAPI
  471. // Build a path to mapistub.dll
  472. cch = GetSystemDirectory(szSystemPath, ARRAYSIZE(szSystemPath));
  473. if (cch && cch <= ARRAYSIZE(szSystemPath))
  474. {
  475. MakeFilePath(szSystemPath, c_szMAPIStub, c_szEmpty, szPath, ARRAYSIZE(szPath));
  476. // Try to load
  477. hMapiStub = LoadLibrary(szPath);
  478. } // else we fall through with NULL hMapiStub to failure case
  479. if (hMapiStub)
  480. {
  481. // Look for the FixMAPI function
  482. pfnFixMAPI = (LPFIXMAPI)GetProcAddress(hMapiStub, TEXT("FixMAPI"));
  483. if (pfnFixMAPI)
  484. {
  485. // Found the entry point, run it
  486. pfnFixMAPI();
  487. // Did that fix mapi32?
  488. if (!FMapiStub(&dwReason2))
  489. {
  490. // No, maybe the old one was in use...
  491. if (2 == dwReason)
  492. {
  493. // Add a runonce entry for fixmapi
  494. if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szMAPIRunOnce, 0, NULL, REG_OPTION_NON_VOLATILE,
  495. KEY_WRITE, NULL, &hkeyRunOnce, &dwReason))
  496. {
  497. // 12 = (11 + 1) where 11 is length of fixmapi.exe + 1 for the null
  498. if (ERROR_SUCCESS == RegSetValueEx(hkeyRunOnce, c_szMAPIRunOnceEntry, 0, REG_SZ, (LPBYTE)c_szFixMAPI, 12 * sizeof(TCHAR)))
  499. {
  500. #ifndef THOR_SETUP
  501. // Tell the user to reboot
  502. if (fUI)
  503. AthMessageBoxW(GetDesktopWindow(), MAKEINTRESOURCEW(idsSimpleMAPI), MAKEINTRESOURCEW(idsMAPISTUBNeedsReboot), NULL, MB_OK);
  504. #endif
  505. // Probable success
  506. fOK = TRUE;
  507. }
  508. RegCloseKey(hkeyRunOnce);
  509. }
  510. }
  511. else
  512. {
  513. #ifndef THOR_SETUP
  514. if (fUI)
  515. AthMessageBoxW(GetDesktopWindow(), MAKEINTRESOURCEW(idsSimpleMAPI), MAKEINTRESOURCEW(idsMAPISTUBFailed), NULL, MB_OK);
  516. #endif
  517. }
  518. }
  519. else
  520. // Success!
  521. fOK = TRUE;
  522. }
  523. // Eek, where is FixMAPI?
  524. else
  525. {
  526. #ifndef THOR_SETUP
  527. if (fUI)
  528. AthMessageBoxW(GetDesktopWindow(), MAKEINTRESOURCEW(idsSimpleMAPI), MAKEINTRESOURCEW(idsMAPISTUBMissingExport), NULL, MB_OK);
  529. #endif
  530. }
  531. FreeLibrary(hMapiStub);
  532. }
  533. else
  534. {
  535. // Dll missing or unloadable
  536. #ifndef THOR_SETUP
  537. if (fUI)
  538. AthMessageBoxW(GetDesktopWindow(), MAKEINTRESOURCEW(idsSimpleMAPI), MAKEINTRESOURCEW(idsMAPISTUBNoLoad), NULL, MB_OK);
  539. #endif
  540. }
  541. break;
  542. default:
  543. AssertSz(FALSE, "EnsureMAPIStub returned an unknown failure. Bailing");
  544. goto exit;
  545. }
  546. exit:
  547. return fOK;
  548. }
  549. // Change the Default News handler
  550. HRESULT ISetDefaultNewsHandler(LPCTSTR pszProduct, DWORD dwFlags)
  551. {
  552. AddUrlHandler(c_szURLNews, c_szNews, pszProduct, dwFlags);
  553. AddUrlHandler(c_szURLNNTP, c_szNews, pszProduct, dwFlags);
  554. AddUrlHandler(c_szURLSnews, c_szNews, pszProduct, dwFlags);
  555. SetDefaultClient(c_szNews, pszProduct, dwFlags);
  556. return (S_OK);
  557. }
  558. // Change the Default Mail handler
  559. HRESULT ISetDefaultMailHandler(LPCTSTR pszProduct, DWORD dwFlags)
  560. {
  561. // May change default handler to owner of mapi32.dll
  562. EnsureMAPIStub(dwFlags);
  563. AddUrlHandler(c_szURLMailTo, c_szMail, pszProduct, dwFlags);
  564. if ((dwFlags & DEFAULT_SETUPMODE) && IsXPSP1OrLater())
  565. {
  566. // running setup50.exe on XPSP1 or later, let OE Access handle it from here.
  567. }
  568. else
  569. {
  570. // Non setup50.exe case (like "would you like to make OE your default mail client?")
  571. // or we're running downlevel -- go ahead and do it.
  572. SetDefaultClient(c_szMail, pszProduct, dwFlags);
  573. }
  574. return (S_OK);
  575. }
  576. //
  577. // FUNCTION: SetDefaultMailHandler()
  578. //
  579. // PURPOSE: Adds the keys to the registry to make Athena the user's
  580. // default mail reader.
  581. //
  582. // RETURN VALUE:
  583. // HRESULT
  584. //
  585. // ATTENZIONE! if you change the parameters for this function, make sure
  586. // that you make the proper change to athena\msoeacct\silent.cpp (it calls
  587. // this via GetProcAddress)
  588. HRESULT WINAPI SetDefaultMailHandler(DWORD dwFlags)
  589. {
  590. return ISetDefaultMailHandler(c_szMOE, dwFlags | DEFAULT_MAIL);
  591. }
  592. //
  593. // FUNCTION: SetDefaultNewsHandler()
  594. //
  595. // PURPOSE: Adds the keys to the registry to make Athena the user's
  596. // default news reader.
  597. //
  598. // RETURN VALUE:
  599. // HRESULT
  600. //
  601. // ATTENZIONE! if you change the parameters for this function, make sure
  602. // that you make the proper change to athena\msoeacct\silent.cpp (it calls
  603. // this via GetProcAddress)
  604. HRESULT WINAPI SetDefaultNewsHandler(DWORD dwFlags)
  605. {
  606. if (dwFlags & DEFAULT_OUTNEWS)
  607. return ISetDefaultNewsHandler(c_szOutlook, dwFlags);
  608. else
  609. return ISetDefaultNewsHandler(c_szMOE, dwFlags | DEFAULT_NEWS);
  610. }