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.

2295 lines
81 KiB

  1. #include "pch.hxx"
  2. #include <regutil.h>
  3. #include <initguid.h>
  4. #include <shlguid.h>
  5. #include "util.h"
  6. #include "strings.h"
  7. #include "msident.h"
  8. #include <shellapi.h>
  9. ASSERTDATA
  10. const LPCTSTR c_szVers[] = { c_szVERnone, c_szVER1_0, c_szVER1_1, c_szVER4_0, c_szVER5B1 };
  11. const LPCTSTR c_szBlds[] = { c_szBLDnone, c_szBLD1_0, c_szBLD1_1, c_szBLD4_0, c_szBLD5B1 };
  12. #ifdef SETUP_LOG
  13. const LPTSTR c_szLOGVERS[] = {"None", "1.0", "1.1", "4.0x", "5.0B1", "5.0x", "6.0x", "Unknown"};
  14. C_ASSERT((sizeof(c_szLOGVERS)/sizeof(c_szLOGVERS[0]) == VER_MAX+1));
  15. #endif
  16. #define FORCE_DEL(_sz) { \
  17. if ((dwAttr = GetFileAttributes(_sz)) != 0xFFFFFFFF) \
  18. { \
  19. SetFileAttributes(_sz, dwAttr & ~FILE_ATTRIBUTE_READONLY); \
  20. DeleteFile(_sz); \
  21. } }
  22. /*******************************************************************
  23. NAME: CreateLink
  24. ********************************************************************/
  25. // Target Arguments File for link Description File w/ Icon Icn Index
  26. HRESULT CreateLink(LPCTSTR lpszPathObj, LPCTSTR lpszArg, LPCTSTR lpszPathLink, LPCTSTR lpszDesc, LPCTSTR lpszIcon, int iIcon)
  27. {
  28. HRESULT hres;
  29. IShellLink* psl;
  30. Assert(lpszPathObj != NULL);
  31. Assert(lpszPathLink != NULL);
  32. // Get a pointer to the IShellLink interface.
  33. hres = CoCreateInstance(CLSID_ShellLink, NULL,
  34. CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
  35. if (SUCCEEDED(hres))
  36. {
  37. IPersistFile* ppf;
  38. TCHAR szTarget[MAX_PATH];
  39. // Use REG_EXPAND_SZ if possible
  40. AddEnvInPath(lpszPathObj, szTarget, ARRAYSIZE(szTarget));
  41. // Set the path to the shortcut target, and add the
  42. // description.
  43. if (SUCCEEDED(psl->SetPath(szTarget)) &&
  44. (lpszArg == NULL || SUCCEEDED(psl->SetArguments(lpszArg))) &&
  45. (NULL == lpszDesc || SUCCEEDED(psl->SetDescription(lpszDesc))) &&
  46. (lpszIcon == NULL || SUCCEEDED(psl->SetIconLocation(lpszIcon, iIcon))))
  47. {
  48. // Query IShellLink for the IPersistFile interface for saving the
  49. // shortcut in persistent storage.
  50. hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
  51. if (SUCCEEDED(hres))
  52. {
  53. WORD wsz[MAX_PATH];
  54. // Ensure that the string is ANSI.
  55. MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1, wsz, MAX_PATH);
  56. // Save the link by calling IPersistFile::Save.
  57. hres = ppf->Save(wsz, TRUE);
  58. ppf->Release();
  59. }
  60. }
  61. psl->Release();
  62. }
  63. return hres;
  64. }
  65. /*******************************************************************
  66. NAME: FRedistMode
  67. ********************************************************************/
  68. BOOL FRedistMode()
  69. {
  70. HKEY hkey;
  71. DWORD cb;
  72. DWORD dwInstallMode=0;
  73. static BOOL s_fRedistInit = FALSE;
  74. static BOOL s_fRedistMode = FALSE;
  75. if (!s_fRedistInit)
  76. {
  77. s_fRedistInit = TRUE;
  78. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, si.pszVerInfo, 0, KEY_READ, &hkey))
  79. {
  80. cb = sizeof(dwInstallMode);
  81. if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szIEInstallMode, 0, NULL, (LPBYTE)&dwInstallMode, &cb))
  82. {
  83. s_fRedistMode = !!(dwInstallMode);
  84. }
  85. RegCloseKey(hkey);
  86. }
  87. }
  88. return s_fRedistMode;
  89. }
  90. /*******************************************************************
  91. NAME: SetHandlers
  92. ********************************************************************/
  93. void SetHandlers()
  94. {
  95. switch (si.saApp)
  96. {
  97. case APP_OE:
  98. if (!FRedistMode())
  99. {
  100. ISetDefaultNewsHandler(c_szMOE, DEFAULT_DONTFORCE);
  101. ISetDefaultMailHandler(c_szMOE, DEFAULT_DONTFORCE | DEFAULT_SETUPMODE);
  102. }
  103. break;
  104. case APP_WAB:
  105. break;
  106. default:
  107. break;
  108. }
  109. }
  110. /*******************************************************************
  111. NAME: AddWABCustomStrings
  112. SYNOPSIS: Adds machine-specific strings to WAB inf
  113. ********************************************************************/
  114. void AddWABCustomStrings()
  115. {
  116. HKEY hkey;
  117. TCHAR szTemp[MAX_PATH];
  118. TCHAR szINFFile[MAX_PATH];
  119. DWORD cb;
  120. BOOL fOK = FALSE;
  121. // People don't want us creating a new Accessories group in our
  122. // install language if it differs from the system language
  123. // Soln: Advpack writes the name of the group for us, use that
  124. // Construct INF file name from dir and filename
  125. wnsprintf(szINFFile, ARRAYSIZE(szINFFile), c_szFileEntryFmt, si.szInfDir, si.pszInfFile);
  126. // We want to enclose the string in quotes
  127. szTemp[0] = '"';
  128. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegWinCurrVer, 0, KEY_READ, &hkey))
  129. {
  130. cb = ARRAYSIZE(szTemp) - 1;
  131. fOK = (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szSMAccessories, 0, NULL, (LPBYTE)&szTemp[1], &cb));
  132. // We want cb to tell us where to put the closing quote. RegQueryValueEx includes null in length, so we'd
  133. // normally -1, but thanks to the opening quote in [0], the string is as long as cb
  134. //cb--;
  135. RegCloseKey(hkey);
  136. }
  137. if (fOK)
  138. {
  139. // Append closing quote
  140. szTemp[cb++] = '"';
  141. szTemp[cb] = 0;
  142. // Add string to INF so per-user stub will create right link
  143. WritePrivateProfileString(c_szStringSection, c_szAccessoriesString, szTemp, szINFFile);
  144. }
  145. // INF ships with a default value in case Advpack let us down
  146. }
  147. /*******************************************************************
  148. NAME: RunPostSetup
  149. ********************************************************************/
  150. void RunPostSetup()
  151. {
  152. switch (si.saApp)
  153. {
  154. case APP_OE:
  155. RegisterExes(TRUE);
  156. break;
  157. case APP_WAB:
  158. AddWABCustomStrings();
  159. break;
  160. default:
  161. break;
  162. }
  163. }
  164. /*******************************************************************
  165. NAME: OpenDirectory
  166. SYNOPSIS: checks for existence of directory, if it doesn't exist
  167. it is created
  168. ********************************************************************/
  169. HRESULT OpenDirectory(TCHAR *szDir)
  170. {
  171. TCHAR *sz, ch;
  172. HRESULT hr;
  173. Assert(szDir != NULL);
  174. hr = S_OK;
  175. if (!CreateDirectory(szDir, NULL) && ERROR_ALREADY_EXISTS != GetLastError())
  176. {
  177. Assert(szDir[1] == _T(':'));
  178. Assert(szDir[2] == _T('\\'));
  179. sz = &szDir[3];
  180. while (TRUE)
  181. {
  182. while (*sz != 0)
  183. {
  184. if (!IsDBCSLeadByte(*sz))
  185. {
  186. if (*sz == _T('\\'))
  187. break;
  188. }
  189. sz = CharNext(sz);
  190. }
  191. ch = *sz;
  192. *sz = 0;
  193. if (!CreateDirectory(szDir, NULL))
  194. {
  195. if (GetLastError() != ERROR_ALREADY_EXISTS)
  196. {
  197. hr = E_FAIL;
  198. *sz = ch;
  199. break;
  200. }
  201. }
  202. *sz = ch;
  203. if (*sz == 0)
  204. break;
  205. sz++;
  206. }
  207. }
  208. return(hr);
  209. }
  210. BOOL PathAddSlash(LPTSTR pszPath, DWORD *pcb)
  211. {
  212. Assert(pszPath && pcb);
  213. DWORD cb = *pcb;
  214. LPTSTR pszEnd;
  215. *pcb = 0;
  216. if (!cb)
  217. cb = lstrlen(pszPath);
  218. pszEnd = CharPrev(pszPath, pszPath+cb);
  219. // Who knows why this is here... :-)
  220. if (';' == *pszEnd)
  221. {
  222. cb--;
  223. pszEnd--;
  224. }
  225. if (*pszEnd != '\\')
  226. {
  227. pszPath[cb++] = '\\';
  228. pszPath[cb] = 0;
  229. }
  230. *pcb = cb;
  231. return TRUE;
  232. }
  233. BOOL FGetSpecialFolder(int iFolder, LPTSTR pszPath)
  234. {
  235. BOOL fOK = FALSE;
  236. LPITEMIDLIST pidl = NULL;
  237. pszPath[0] = 0;
  238. if (S_OK == SHGetSpecialFolderLocation(NULL, iFolder, &pidl) && SHGetPathFromIDList(pidl, pszPath))
  239. fOK = TRUE;
  240. SafeMemFree(pidl);
  241. return fOK;
  242. }
  243. /*******************************************************************
  244. NAME: FGetOELinkInfo
  245. ********************************************************************/
  246. BOOL FGetOELinkInfo(OEICON iIcon, BOOL fCreate, LPTSTR pszPath, LPTSTR pszTarget, LPTSTR pszDesc, DWORD *pdwInfo)
  247. {
  248. BOOL fDir = FALSE;
  249. HKEY hkey;
  250. DWORD cb = 0;
  251. DWORD dwType;
  252. TCHAR szTemp[MAX_PATH];
  253. TCHAR szRes[CCHMAX_RES];
  254. Assert(pdwInfo);
  255. Assert(pszPath || pszTarget || pszDesc);
  256. *pdwInfo = 0;
  257. ZeroMemory(szTemp, ARRAYSIZE(szTemp));
  258. switch(iIcon)
  259. {
  260. // The MEMPHIS ICW erroneously creates an all-user desktop icon for OE
  261. case ICON_ICWBAD:
  262. // Find the location of the all-users desktop
  263. if (FGetSpecialFolder(CSIDL_COMMON_DESKTOPDIRECTORY, pszPath))
  264. {
  265. fDir = TRUE;
  266. }
  267. // Memphis doesn't support CSIDL_COMMON_DESKTOP
  268. else if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegFolders, 0, KEY_QUERY_VALUE, &hkey))
  269. {
  270. cb = MAX_PATH * sizeof(TCHAR);
  271. if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szValueCommonDTop, NULL, &dwType, (LPBYTE)pszPath, &cb))
  272. {
  273. if (REG_EXPAND_SZ == dwType)
  274. {
  275. // ExpandEnvironmentStrings ret value doesn't seem to match the docs :-(
  276. cb = ExpandEnvironmentStrings(pszPath, szTemp, ARRAYSIZE(szTemp));
  277. if (fDir = cb != 0)
  278. {
  279. StrCpyN(pszPath, szTemp, MAX_PATH);
  280. cb = lstrlen(pszPath);
  281. }
  282. }
  283. else
  284. {
  285. fDir = TRUE;
  286. // RegQueryValueEx includes NULL in count
  287. cb--;
  288. }
  289. }
  290. RegCloseKey(hkey);
  291. }
  292. if (fDir && PathAddSlash(pszPath, &cb) && SUCCEEDED(OpenDirectory(pszPath)))
  293. {
  294. // 1 for a null
  295. LoadString(g_hInstance, IDS_ATHENA, szRes, MAX_PATH - cb - 1 - c_szLinkFmt_LEN);
  296. wnsprintf(&pszPath[cb], MAX_PATH - cb, c_szLinkFmt, szRes);
  297. *pdwInfo |= LI_PATH;
  298. }
  299. break;
  300. case ICON_QLAUNCH:
  301. case ICON_QLAUNCH_OLD:
  302. if (FGetSpecialFolder(CSIDL_APPDATA, pszPath))
  303. {
  304. fDir = TRUE;
  305. }
  306. else if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER, c_szRegFolders, 0, NULL, REG_OPTION_NON_VOLATILE,
  307. KEY_WRITE | KEY_READ, NULL, &hkey, &dwType))
  308. {
  309. cb = MAX_PATH * sizeof(TCHAR);
  310. if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szValueAppData, NULL, &dwType, (LPBYTE)pszPath, &cb))
  311. {
  312. if (REG_EXPAND_SZ == dwType)
  313. {
  314. cb = ExpandEnvironmentStrings(pszPath, szTemp, ARRAYSIZE(szTemp));
  315. if (fDir = 0 != cb)
  316. {
  317. StrCpyN(pszPath, szTemp, MAX_PATH);
  318. cb = lstrlen(pszPath);
  319. }
  320. }
  321. else
  322. {
  323. // RegQueryValueEx includes NULL in their counts
  324. cb--;
  325. fDir = TRUE;
  326. }
  327. }
  328. else
  329. {
  330. StrCpyN(pszPath, si.szWinDir, MAX_PATH);
  331. cb = lstrlen(pszPath);
  332. cb += LoadString(g_hInstance, IDS_APPLICATION_DATA, &pszPath[cb], MAX_PATH - cb);
  333. // + 1 for NULL
  334. RegSetValueEx(hkey, c_szValueAppData, 0, REG_SZ, (LPBYTE)pszPath, (cb + 1) * sizeof(TCHAR));
  335. fDir = TRUE;
  336. }
  337. RegCloseKey(hkey);
  338. }
  339. if (fDir && PathAddSlash(pszPath, &cb))
  340. {
  341. StrCpyN(&pszPath[cb], c_szQuickLaunchDir, MAX_PATH - cb);
  342. cb += c_szQuickLaunchDir_LEN;
  343. if (SUCCEEDED(OpenDirectory(pszPath)))
  344. {
  345. // 5 = 1 for null + 4 for .lnk
  346. LoadString(g_hInstance, ICON_QLAUNCH == iIcon ? IDS_LAUNCH_ATHENA : IDS_MAIL, szRes, MAX_PATH - cb - 5);
  347. wnsprintf(&pszPath[cb], MAX_PATH - cb, c_szLinkFmt, szRes);
  348. *pdwInfo |= LI_PATH;
  349. // We need more details for ICON_QLAUNCH
  350. if (ICON_QLAUNCH == iIcon && fCreate)
  351. {
  352. // Don't use Description because NT5 shows name and comment
  353. //lstrcpy(pszDesc, szRes);
  354. //*pdwInfo |= LI_DESC;
  355. if (GetExePath(c_szMainExe, pszTarget, MAX_PATH, FALSE))
  356. *pdwInfo |= LI_TARGET;
  357. }
  358. }
  359. }
  360. break;
  361. case ICON_MAPIRECIP:
  362. if (FGetSpecialFolder(CSIDL_SENDTO, pszPath) && PathAddSlash(pszPath, &cb) && SUCCEEDED(OpenDirectory(pszPath)))
  363. {
  364. // 10 = 1 for NULL + 9 for .MAPIMAIL
  365. LoadString(g_hInstance, IDS_MAIL_RECIPIENT, szRes, MAX_PATH - cb - 10);
  366. wnsprintf(&pszPath[cb], MAX_PATH - cb, c_szFmtMapiMailExt, szRes);
  367. *pdwInfo |= LI_PATH;
  368. }
  369. break;
  370. case ICON_DESKTOP:
  371. if (FGetSpecialFolder(CSIDL_DESKTOP, pszPath))
  372. fDir = TRUE;
  373. // HACK to workaround TW Memphis: Try the registry
  374. else if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegFolders, 0, KEY_READ, &hkey))
  375. {
  376. cb = MAX_PATH * sizeof(TCHAR);
  377. if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szDesktop, 0, &dwType, (LPBYTE)pszPath, &cb))
  378. {
  379. // Handle REG_EXPAND_SZ
  380. if (REG_EXPAND_SZ == dwType)
  381. {
  382. cb = ExpandEnvironmentStrings(pszPath, szTemp, ARRAYSIZE(szTemp));
  383. if (fDir = cb != 0)
  384. {
  385. StrCpyN(pszPath, szTemp, MAX_PATH);
  386. fDir = TRUE;
  387. }
  388. }
  389. else
  390. {
  391. // RegQueryValueEx includes NULL
  392. cb--;
  393. fDir = TRUE;
  394. }
  395. }
  396. RegCloseKey(hkey);
  397. }
  398. if (fDir && PathAddSlash(pszPath, &cb) && SUCCEEDED(OpenDirectory(pszPath)))
  399. {
  400. // 5 = 1 for NULL + 4 for .lnk
  401. LoadString(g_hInstance, IDS_ATHENA, szRes, MAX_PATH - cb - 5);
  402. wnsprintf(&pszPath[cb], MAX_PATH - cb, c_szLinkFmt, szRes);
  403. *pdwInfo |= LI_PATH;
  404. if (fCreate)
  405. {
  406. // Description for Desktop link
  407. LoadString(g_hInstance, IDS_OEDTOP_TIP, pszDesc, CCHMAX_RES);
  408. *pdwInfo |= LI_DESC;
  409. if (GetExePath(c_szMainExe, pszTarget, MAX_PATH, FALSE))
  410. *pdwInfo |= LI_TARGET;
  411. }
  412. }
  413. break;
  414. }
  415. if (*pdwInfo)
  416. return TRUE;
  417. else
  418. return FALSE;
  419. }
  420. /*******************************************************************
  421. NAME: FProcessOEIcon
  422. SYNOPSIS: Should we manipulate this icon?
  423. ********************************************************************/
  424. BOOL FProcessOEIcon(OEICON iIcon, BOOL fCreate)
  425. {
  426. BOOL fProcess = TRUE;
  427. switch (iIcon)
  428. {
  429. case ICON_ICWBAD:
  430. // Don't delete the ICW's bad icon in redist mode or on NT5 as we won't create a replacement
  431. if (((VER_PLATFORM_WIN32_NT == si.osv.dwPlatformId) && (si.osv.dwMajorVersion >= 5)) || FRedistMode())
  432. {
  433. fProcess = FALSE;
  434. }
  435. break;
  436. case ICON_DESKTOP:
  437. // Don't create the desktop icon on NT5+, Win98 OSR+ or if we are in redist mode
  438. if (fCreate && ( ((VER_PLATFORM_WIN32_NT == si.osv.dwPlatformId) && (si.osv.dwMajorVersion >= 5)) ||
  439. // Disabled this temporarily (through techbeta)
  440. #if 0
  441. ((VER_PLATFORM_WIN32_WINDOWS == si.osv.dwPlatformId) &&
  442. (((4 == si.osv.dwMajorVersion) && (10 == si.osv.dwMinorVersion) && (LOWORD(si.osv.dwBuildNumber) > 1998)) ||
  443. ((4 == si.osv.dwMajorVersion) && (si.osv.dwMinorVersion > 10)) ||
  444. (si.osv.dwMajorVersion > 4)) ) ||
  445. #endif
  446. FRedistMode() ) )
  447. fProcess = FALSE;
  448. break;
  449. case ICON_QLAUNCH:
  450. case ICON_QLAUNCH_OLD:
  451. // No Quick Launch Icon on whistler
  452. if(fCreate &&
  453. VER_PLATFORM_WIN32_NT == si.osv.dwPlatformId &&
  454. (si.osv.dwMajorVersion > 5 ||
  455. (si.osv.dwMajorVersion == 5 && si.osv.dwMinorVersion > 0)))
  456. fProcess = FALSE;
  457. break;
  458. }
  459. return fProcess;
  460. }
  461. /*******************************************************************
  462. NAME: HandleOEIcon
  463. SYNOPSIS: Performs actual work on Icon
  464. ********************************************************************/
  465. void HandleOEIcon(OEICON icn, BOOL fCreate, LPTSTR pszPath, LPTSTR pszTarget, LPTSTR pszDesc)
  466. {
  467. DWORD dwAttr;
  468. HANDLE hFile;
  469. switch (icn)
  470. {
  471. case ICON_QLAUNCH_OLD:
  472. case ICON_ICWBAD:
  473. if (pszPath)
  474. FORCE_DEL(pszPath);
  475. break;
  476. case ICON_QLAUNCH:
  477. case ICON_DESKTOP:
  478. if (pszPath)
  479. {
  480. FORCE_DEL(pszPath);
  481. if (fCreate && pszTarget && !IsXPSP1OrLater())
  482. {
  483. CreateLink(pszTarget, NULL, pszPath, pszDesc, pszTarget, -2);
  484. SetFileAttributes(pszPath, FILE_ATTRIBUTE_READONLY);
  485. }
  486. }
  487. break;
  488. case ICON_MAPIRECIP:
  489. if (fCreate && pszPath)
  490. {
  491. hFile = CreateFile(pszPath, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
  492. NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  493. if (hFile != INVALID_HANDLE_VALUE)
  494. CloseHandle(hFile);
  495. }
  496. break;
  497. }
  498. }
  499. /*******************************************************************
  500. NAME: HandleOELinks
  501. ********************************************************************/
  502. void HandleOELinks(BOOL fCreate)
  503. {
  504. int i;
  505. TCHAR szPath[MAX_PATH];
  506. TCHAR szTarget[MAX_PATH];
  507. TCHAR szDescription[CCHMAX_RES];
  508. DWORD dwInfo;
  509. // Process each Icon in turn
  510. for (i = 0; i < ICON_LAST_ICON; i++)
  511. {
  512. if (FProcessOEIcon((OEICON)i, fCreate))
  513. {
  514. if(FGetOELinkInfo((OEICON)i, fCreate, szPath, szTarget, szDescription, &dwInfo))
  515. {
  516. HandleOEIcon((OEICON)i, fCreate,
  517. (dwInfo & LI_PATH) ? szPath : NULL,
  518. (dwInfo & LI_TARGET) ? szTarget : NULL,
  519. (dwInfo & LI_DESC) ? szDescription : NULL);
  520. }
  521. }
  522. }
  523. }
  524. /*******************************************************************
  525. NAME: HandleLinks
  526. ********************************************************************/
  527. void HandleLinks(BOOL fCreate)
  528. {
  529. switch (si.saApp)
  530. {
  531. case APP_OE:
  532. HandleOELinks(fCreate);
  533. break;
  534. case APP_WAB:
  535. break;
  536. default:
  537. break;
  538. }
  539. }
  540. /*******************************************************************
  541. NAME: TranslateVers
  542. SYNOPSIS: Takes 5.0B1 versions and translates to bld numbers
  543. ********************************************************************/
  544. BOOL TranslateVers(SETUPVER *psv, LPTSTR pszVer, int cch)
  545. {
  546. BOOL fTranslated = FALSE;
  547. *psv = VER_NONE;
  548. // Special case builds 624-702
  549. if (!lstrcmp(pszVer, c_szVER5B1old))
  550. {
  551. StrCpyN(pszVer, c_szBlds[VER_5_0_B1], cch);
  552. *psv = VER_5_0_B1;
  553. fTranslated = TRUE;
  554. }
  555. else
  556. for (int i = VER_NONE; i < VER_5_0; i++)
  557. if (!lstrcmp(c_szVers[i], pszVer))
  558. {
  559. // HACK! Special case WAB 1_0 match - it could be 1_1...
  560. // Don't care on Win9X or NT as data is still stored in same place
  561. if (APP_WAB == si.saApp && VER_1_0 == i && CALLER_IE == si.caller)
  562. {
  563. // Is Windows\WAB.exe backed up as part of OE?
  564. TCHAR szTemp[MAX_PATH];
  565. wnsprintf(szTemp, ARRAYSIZE(szTemp), c_szFileEntryFmt, si.szWinDir, "wab.exe");
  566. if (OEFileBackedUp(szTemp, ARRAYSIZE(szTemp)))
  567. i = VER_1_1;
  568. }
  569. StrCpyN(pszVer, c_szBlds[i], cch);
  570. *psv = (SETUPVER)i;
  571. fTranslated = TRUE;
  572. break;
  573. }
  574. return fTranslated;
  575. }
  576. /*******************************************************************
  577. NAME: DetectPrevVer
  578. SYNOPSIS: Called when there is no ver info for current app
  579. ********************************************************************/
  580. SETUPVER DetectPrevVer(LPTSTR pszVer, int cch)
  581. {
  582. SETUPVER sv;
  583. TCHAR szVer[VERLEN] = {0};
  584. WORD wVer[4];
  585. TCHAR szFile[MAX_PATH];
  586. TCHAR szFile2[MAX_PATH];
  587. UINT uLen;
  588. DWORD dwAttr;
  589. Assert(pszVer);
  590. StrCpyN(szFile, si.szSysDir, ARRAYSIZE(szFile));
  591. uLen = lstrlen(szFile);
  592. switch (si.saApp)
  593. {
  594. case APP_OE:
  595. LOG("Sniffing for OE... Detected:");
  596. StrCpyN(&szFile[uLen], c_szMAILNEWS, ARRAYSIZE(szFile) - uLen);
  597. // See what version we've told IE Setup, is installed
  598. // Or what version msimn.exe is (to cover the case in which the
  599. // ASetup info has been damaged - OE 5.01 80772)
  600. if (GetASetupVer(c_szOEGUID, wVer, szVer, ARRAYSIZE(szVer)) ||
  601. SUCCEEDED(GetExeVer(c_szOldMainExe, wVer, szVer, ARRAYSIZE(szVer))))
  602. sv = ConvertVerToEnum(wVer);
  603. else
  604. {
  605. // 1.0 or none
  606. // Does mailnews.dll exist?
  607. if(0xFFFFFFFF == GetFileAttributes(szFile))
  608. sv = VER_NONE;
  609. else
  610. sv = VER_1_0;
  611. }
  612. // If active setup, these will be rollably deleted
  613. if (CALLER_IE != si.caller)
  614. FORCE_DEL(szFile);
  615. LOG2(c_szLOGVERS[sv]);
  616. break;
  617. case APP_WAB:
  618. LOG("Sniffing for WAB... Detected:");
  619. StrCpyN(&szFile[uLen], c_szWAB32, ARRAYSIZE(szFile) - uLen);
  620. StrCpyN(szFile2, si.szWinDir, ARRAYSIZE(szFile2));
  621. StrCatBuff(szFile2, c_szWABEXE, ARRAYSIZE(szFile2));
  622. if (GetASetupVer(c_szWABGUID, wVer, szVer, ARRAYSIZE(szVer)))
  623. {
  624. // 5.0 or later
  625. if (5 == wVer[0])
  626. sv = VER_5_0;
  627. else
  628. sv = VER_MAX;
  629. }
  630. else if (GetASetupVer(c_szOEGUID, wVer, szVer, ARRAYSIZE(szVer)) ||
  631. SUCCEEDED(GetExeVer(c_szOldMainExe, wVer, szVer, ARRAYSIZE(szVer))))
  632. {
  633. // 4.0x or 5.0 Beta 1
  634. if (5 == wVer[0])
  635. sv = VER_5_0_B1;
  636. else if (4 == wVer[0])
  637. sv = VER_4_0;
  638. else
  639. sv = VER_MAX;
  640. }
  641. else
  642. {
  643. // 1.0, 1.1 or none
  644. // WAB32.dll around?
  645. if(0xFFFFFFFF == GetFileAttributes(szFile))
  646. sv = VER_NONE;
  647. else
  648. {
  649. // \Windows\Wab.exe around?
  650. if(0xFFFFFFFF == GetFileAttributes(szFile2))
  651. sv = VER_1_0;
  652. else
  653. sv = VER_1_1;
  654. }
  655. }
  656. // If active setup, these will be rollably deleted
  657. if (CALLER_IE != si.caller)
  658. {
  659. FORCE_DEL(szFile);
  660. FORCE_DEL(szFile2);
  661. }
  662. LOG2(c_szLOGVERS[sv]);
  663. break;
  664. default:
  665. sv = VER_NONE;
  666. }
  667. // Figure out the build number for this ver
  668. if (szVer[0])
  669. // Use real ver
  670. StrCpyN(pszVer, szVer, cch);
  671. else
  672. // Fake Ver
  673. StrCpyN(pszVer, sv > sizeof(c_szBlds)/sizeof(c_szBlds[0]) ? c_szBlds[0] : c_szBlds[sv], cch);
  674. return sv;
  675. }
  676. /*******************************************************************
  677. NAME: HandleVersionInfo
  678. ********************************************************************/
  679. void HandleVersionInfo(BOOL fAfterInstall)
  680. {
  681. HKEY hkeyT,hkey;
  682. DWORD cb, dwDisp;
  683. TCHAR szCurrVer[VERLEN]={0};
  684. TCHAR szPrevVer[VERLEN]={0};
  685. LPTSTR psz;
  686. SETUPVER svCurr = VER_MAX, svPrev = VER_MAX;
  687. WORD wVer[4];
  688. BOOL fReg=FALSE;
  689. Assert(si.pszVerInfo);
  690. // Are we dealing with the "current" entry?
  691. if (fAfterInstall)
  692. {
  693. LPCTSTR pszGUID;
  694. TCHAR szVer[VERLEN];
  695. switch (si.saApp)
  696. {
  697. case APP_OE:
  698. pszGUID = c_szOEGUID;
  699. break;
  700. case APP_WAB:
  701. pszGUID = c_szWABGUID;
  702. break;
  703. default:
  704. AssertSz(FALSE, "Unknown app is trying to be installed. Abandon hope...");
  705. return;
  706. }
  707. if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, si.pszVerInfo, 0, NULL, REG_OPTION_NON_VOLATILE,
  708. KEY_SET_VALUE, NULL, &hkeyT, &dwDisp))
  709. {
  710. if (!GetASetupVer(pszGUID, wVer, szVer, ARRAYSIZE(szVer)))
  711. {
  712. // Uh oh, couldn't find our ASetup key - this is not good!
  713. MsgBox(NULL, IDS_WARN_NOASETUPVER, MB_ICONEXCLAMATION, MB_OK);
  714. RegSetValueEx(hkeyT, c_szRegCurrVer, 0, REG_SZ, (LPBYTE)c_szBLDnew, (lstrlen(c_szBLDnew) + 1) * sizeof(TCHAR));
  715. }
  716. else
  717. RegSetValueEx(hkeyT, c_szRegCurrVer, 0, REG_SZ, (LPBYTE)szVer, (lstrlen(szVer) + 1) * sizeof(TCHAR));
  718. RegCloseKey(hkeyT);
  719. }
  720. return;
  721. }
  722. // Handling "Previous" entry...
  723. // Always try to use the version info
  724. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, si.pszVerInfo, 0, KEY_QUERY_VALUE, &hkeyT))
  725. {
  726. cb = sizeof(szPrevVer);
  727. RegQueryValueEx(hkeyT, c_szRegPrevVer, NULL, NULL, (LPBYTE)szPrevVer, &cb);
  728. // Change to a bld # if needed
  729. if (!TranslateVers(&svPrev, szPrevVer, ARRAYSIZE(szPrevVer)))
  730. {
  731. // Convert bld to enum
  732. ConvertStrToVer(szPrevVer, wVer);
  733. svPrev = ConvertVerToEnum(wVer);
  734. }
  735. // If version info shows that a ver info aware version was uninstalled, throw out the info
  736. // and redetect
  737. if (VER_NONE == svPrev)
  738. // Sniff the machine for current version
  739. svCurr = DetectPrevVer(szCurrVer, ARRAYSIZE(szCurrVer));
  740. else
  741. {
  742. // There was previous version reg goo - and it's legit
  743. fReg = TRUE;
  744. cb = sizeof(szCurrVer);
  745. RegQueryValueEx(hkeyT, c_szRegCurrVer, NULL, NULL, (LPBYTE)szCurrVer, &cb);
  746. // Change to a bld # if needed
  747. if (!TranslateVers(&svCurr, szCurrVer, ARRAYSIZE(szCurrVer)))
  748. {
  749. // Convert bld to enum
  750. ConvertStrToVer(szCurrVer, wVer);
  751. svCurr = ConvertVerToEnum(wVer);
  752. }
  753. }
  754. RegCloseKey(hkeyT);
  755. }
  756. else
  757. {
  758. // Sniff the machine for current version
  759. svCurr = DetectPrevVer(szCurrVer, ARRAYSIZE(szCurrVer));
  760. }
  761. if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, si.pszVerInfo, 0, NULL, REG_OPTION_NON_VOLATILE,
  762. KEY_SET_VALUE, NULL, &hkeyT, &dwDisp))
  763. {
  764. // Should we change the previous version entry?
  765. if (VER_6_0 != svCurr)
  766. {
  767. // Know this is B1 OE if we translated
  768. // Know this is B1 WAB if we detected it
  769. if (VER_5_0_B1 == svCurr)
  770. {
  771. RegSetValueEx(hkeyT, c_szRegInterimVer, 0, REG_DWORD, (LPBYTE)&svCurr, sizeof(SETUPVER));
  772. // Did we read a previous value?
  773. if (fReg)
  774. // As there were reg entries, just translate the previous entry
  775. psz = szPrevVer;
  776. else
  777. {
  778. // We don't have a bld number and yet we are B1, better be the WAB
  779. Assert(APP_WAB == si.saApp);
  780. // Peek at OE's ver info
  781. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegVerInfo, 0, KEY_QUERY_VALUE, &hkey))
  782. {
  783. cb = sizeof(szPrevVer);
  784. // Read a build or a string
  785. RegQueryValueExA(hkey, c_szRegPrevVer, NULL, NULL, (LPBYTE)szPrevVer, &cb);
  786. // If it's a string, convert it to a build
  787. TranslateVers(&svPrev, szPrevVer, ARRAYSIZE(szPrevVer));
  788. // We'll use the build (translated or direct)
  789. psz = szPrevVer;
  790. RegCloseKey(hkey);
  791. }
  792. }
  793. }
  794. else
  795. {
  796. RegDeleteValue(hkeyT, c_szRegInterimVer);
  797. // Make the old current ver, the previous ver
  798. psz = szCurrVer;
  799. }
  800. RegSetValueEx(hkeyT, c_szRegPrevVer, 0, REG_SZ, (LPBYTE)psz, (lstrlen(psz) + 1) * sizeof(TCHAR));
  801. }
  802. RegCloseKey(hkeyT);
  803. }
  804. }
  805. /*******************************************************************
  806. NAME: UpgradeOESettings
  807. ********************************************************************/
  808. BOOL UpgradeOESettings(SETUPVER svPrev, HKEY hkeyDest)
  809. {
  810. LPCTSTR pszSrc;
  811. HKEY hkeySrc;
  812. BOOL fMig;
  813. Assert(hkeyDest);
  814. // Figure out where the data is coming FROM...
  815. switch (svPrev)
  816. {
  817. default:
  818. // Nothing to do
  819. return TRUE;
  820. case VER_4_0:
  821. pszSrc = c_szRegFlat;
  822. break;
  823. case VER_5_0_B1:
  824. pszSrc = c_szRegRoot;
  825. break;
  826. }
  827. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, pszSrc, 0, KEY_READ, &hkeySrc))
  828. {
  829. CopyRegistry(hkeySrc, hkeyDest);
  830. RegCloseKey(hkeySrc);
  831. fMig = TRUE;
  832. }
  833. else
  834. fMig = FALSE;
  835. return fMig;
  836. }
  837. /*******************************************************************
  838. NAME: UpgradeWABSettings
  839. ********************************************************************/
  840. BOOL UpgradeWABSettings(SETUPVER svPrev, HKEY hkeyDest)
  841. {
  842. LPCTSTR pszSrc;
  843. BOOL fMig;
  844. HKEY hkeySrc;
  845. Assert(hkeyDest);
  846. // Figure out where the data is coming FROM...
  847. switch (svPrev)
  848. {
  849. default:
  850. // Nothing to do
  851. return TRUE;
  852. case VER_4_0:
  853. case VER_5_0_B1:
  854. pszSrc = c_szInetAcctMgrRegKey;
  855. break;
  856. }
  857. // IAM\Accounts
  858. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, pszSrc, 0, KEY_READ, &hkeySrc))
  859. {
  860. CopyRegistry(hkeySrc, hkeyDest);
  861. RegCloseKey(hkeySrc);
  862. fMig = TRUE;
  863. }
  864. else
  865. fMig = FALSE;
  866. return fMig;
  867. }
  868. /*******************************************************************
  869. NAME: UpgradeOESettingsToMU
  870. SYNOPSIS: Copies forward settings as needed and returns TRUE
  871. if we did migrate.
  872. ********************************************************************/
  873. BOOL UpgradeOESettingsToMU()
  874. {
  875. SETUPVER svMachinePrev = VER_NONE, svUserPrev = VER_NONE;
  876. HKEY hkeySrc, hkeyID;
  877. DWORD dwTemp;
  878. BOOL fUpgraded = FALSE, fAlreadyDone = FALSE;
  879. IUserIdentityManager *pManager=NULL;
  880. IUserIdentity *pIdentity=NULL;
  881. TCHAR szVer[VERLEN];
  882. HKEY hkeySettings, hkeyT;
  883. DWORD dwDisp;
  884. GUID guid;
  885. int i;
  886. // Get an identity manager
  887. if (SUCCEEDED(CoCreateInstance(CLSID_UserIdentityManager, NULL, CLSCTX_INPROC_SERVER,
  888. IID_IUserIdentityManager, (void **)&pManager)))
  889. {
  890. Assert(pManager);
  891. // Get Default Identity
  892. if (SUCCEEDED(pManager->GetIdentityByCookie((GUID*)&UID_GIBC_DEFAULT_USER, &pIdentity)))
  893. {
  894. Assert(pIdentity);
  895. // Ensure that we have an identity and can get to its registry
  896. if (SUCCEEDED(pIdentity->OpenIdentityRegKey(KEY_WRITE, &hkeyID)))
  897. {
  898. // Create the place for their OE settings
  899. if (ERROR_SUCCESS == RegCreateKeyEx(hkeyID, c_szRegRoot, 0, NULL, REG_OPTION_NON_VOLATILE,
  900. KEY_WRITE, NULL, &hkeySettings, &dwDisp))
  901. {
  902. if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER, c_szRegSharedSetup, 0, NULL,
  903. REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE, NULL, &hkeyT, &dwDisp))
  904. {
  905. // Is there already a migrated default user?
  906. if (ERROR_SUCCESS != RegQueryValueEx(hkeyT, c_szSettingsToLWP, 0, &dwTemp, NULL, NULL))
  907. {
  908. // Record that we are about to do
  909. ZeroMemory(&guid, sizeof(guid));
  910. pIdentity->GetCookie(&guid);
  911. RegSetValueEx(hkeyT, c_szSettingsToLWP, 0, REG_BINARY, (LPBYTE)&guid, sizeof(guid));
  912. // Note today's version
  913. if (GetASetupVer(c_szOEGUID, NULL, szVer, ARRAYSIZE(szVer)))
  914. RegSetValueEx(hkeyT, c_szSettingsToLWPVer, 0, REG_SZ, (LPBYTE)szVer, sizeof(szVer));
  915. // Close the key now as it will be a while before we leave this block
  916. RegCloseKey(hkeyT);
  917. // Figure out which version's settings we will be looking for
  918. if (!InterimBuild(&svMachinePrev))
  919. GetVerInfo(NULL, &svMachinePrev);
  920. // Go backwards through list of versions, and look for user info
  921. // the same age or older than the previous version on the machine
  922. for (i = svMachinePrev; i >= VER_NONE; i--)
  923. {
  924. if (bVerInfoExists((SETUPVER)i))
  925. {
  926. svUserPrev = (SETUPVER)i;
  927. break;
  928. }
  929. }
  930. // Begin with default values
  931. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegDefaultSettings, 0, KEY_READ, &hkeySrc))
  932. {
  933. CopyRegistry(hkeySrc, hkeySettings);
  934. RegCloseKey(hkeySrc);
  935. }
  936. // Apply previous version settings if any
  937. fUpgraded = UpgradeOESettings(svUserPrev, hkeySettings);
  938. // Tell msoe.dll's migration code that this is not a new user and migration should be done
  939. dwDisp = 0;
  940. RegSetValueEx(hkeySettings, c_szOEVerStamp, 0, REG_DWORD, (LPBYTE)&dwDisp, sizeof(dwDisp));
  941. }
  942. else
  943. {
  944. // Check for TechBeta Builds
  945. if (REG_DWORD == dwTemp)
  946. {
  947. ZeroMemory(&guid, sizeof(guid));
  948. pIdentity->GetCookie(&guid);
  949. RegSetValueEx(hkeyT, c_szSettingsToLWP, 0, REG_BINARY, (LPBYTE)&guid, sizeof(guid));
  950. }
  951. fAlreadyDone = TRUE;
  952. RegCloseKey(hkeyT);
  953. }
  954. }
  955. RegCloseKey(hkeySettings);
  956. }
  957. RegCloseKey(hkeyID);
  958. }
  959. pIdentity->Release();
  960. }
  961. pManager->Release();
  962. }
  963. return fAlreadyDone ? FALSE : fUpgraded;
  964. }
  965. BOOL UpgradeSettings()
  966. {
  967. switch (si.saApp)
  968. {
  969. case APP_OE:
  970. return UpgradeOESettingsToMU();
  971. case APP_WAB:
  972. return TRUE;
  973. default:
  974. return FALSE;
  975. }
  976. }
  977. /*******************************************************************
  978. NAME: bOEVerInfoExists
  979. ********************************************************************/
  980. BOOL bOEVerInfoExists(SETUPVER sv)
  981. {
  982. BOOL bExists = FALSE;
  983. HKEY hkey;
  984. switch (sv)
  985. {
  986. default:
  987. bExists = FALSE;
  988. break;
  989. case VER_1_0:
  990. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegRoot_V1, 0 ,KEY_QUERY_VALUE,&hkey))
  991. {
  992. bExists = (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szRegStoreRootDir, NULL, NULL, NULL, NULL));
  993. RegCloseKey(hkey);
  994. }
  995. break;
  996. case VER_4_0:
  997. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegFlat,0,KEY_QUERY_VALUE,&hkey))
  998. {
  999. bExists = (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szRegStoreRootDir, NULL, NULL, NULL, NULL));
  1000. RegCloseKey(hkey);
  1001. }
  1002. break;
  1003. case VER_5_0_B1:
  1004. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegRoot ,0 , KEY_QUERY_VALUE, &hkey))
  1005. {
  1006. bExists = TRUE;
  1007. RegCloseKey(hkey);
  1008. }
  1009. break;
  1010. }
  1011. return bExists;
  1012. }
  1013. /*******************************************************************
  1014. NAME: bWABVerInfoExists
  1015. ********************************************************************/
  1016. BOOL bWABVerInfoExists(SETUPVER sv)
  1017. {
  1018. BOOL bExists = FALSE;
  1019. HKEY hkey;
  1020. switch (sv)
  1021. {
  1022. default:
  1023. bExists = FALSE;
  1024. break;
  1025. case VER_1_1:
  1026. case VER_1_0:
  1027. bExists = bOEVerInfoExists(VER_1_0);
  1028. break;
  1029. case VER_4_0:
  1030. case VER_5_0_B1:
  1031. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, c_szInetAcctMgrRegKey, 0, KEY_QUERY_VALUE,&hkey))
  1032. {
  1033. bExists = TRUE;
  1034. RegCloseKey(hkey);
  1035. }
  1036. break;
  1037. }
  1038. return bExists;
  1039. }
  1040. /*******************************************************************
  1041. NAME: bVerInfoExists
  1042. ********************************************************************/
  1043. BOOL bVerInfoExists(SETUPVER sv)
  1044. {
  1045. switch (si.saApp)
  1046. {
  1047. case APP_OE:
  1048. return bOEVerInfoExists(sv);
  1049. case APP_WAB:
  1050. return bWABVerInfoExists(sv);
  1051. default:
  1052. return FALSE;
  1053. }
  1054. }
  1055. /*******************************************************************
  1056. NAME: PreRollable
  1057. ********************************************************************/
  1058. void PreRollable()
  1059. {
  1060. }
  1061. /*******************************************************************
  1062. NAME: ApplyActiveSetupVer()
  1063. SYNOPS
  1064. ********************************************************************/
  1065. void ApplyActiveSetupVer()
  1066. {
  1067. TCHAR szVer[VERLEN];
  1068. TCHAR szPath[MAX_PATH];
  1069. LPCTSTR pszGuid;
  1070. LPCTSTR pszVerString;
  1071. int cLen;
  1072. HKEY hkey;
  1073. switch (si.saApp)
  1074. {
  1075. case APP_OE:
  1076. pszGuid = c_szOEGUID;
  1077. pszVerString = c_szVersionOE;
  1078. break;
  1079. case APP_WAB:
  1080. pszGuid = c_szWABGUID;
  1081. pszVerString = c_szValueVersion;
  1082. break;
  1083. default:
  1084. AssertSz(FALSE, "Applying ActiveSetupVer for unknown APP!");
  1085. return;
  1086. }
  1087. // Get the version out of the INF file
  1088. wnsprintf(szPath, ARRAYSIZE(szPath), c_szFileEntryFmt, si.szInfDir, si.pszInfFile);
  1089. cLen = GetPrivateProfileString(c_szStringSection, pszVerString, c_szBLDnew, szVer, ARRAYSIZE(szVer), szPath);
  1090. // Write the version in the registry
  1091. wnsprintf(szPath, ARRAYSIZE(szPath), c_szPathFileFmt, c_szRegASetup, pszGuid);
  1092. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szPath, 0, KEY_SET_VALUE, &hkey))
  1093. {
  1094. RegSetValueEx(hkey, c_szValueVersion, 0, REG_SZ, (LPBYTE)szVer, (cLen+1)*sizeof(TCHAR));
  1095. RegCloseKey(hkey);
  1096. #ifdef _WIN64
  1097. // !! HACKHACK !!
  1098. // We put the same string in the Wow6432Node of the registry so that the 32-bit Outlook2000 running on ia64
  1099. // will not complain that OE is not installed.
  1100. //
  1101. // This should not be necessary, but currently (and it might stay this way) msoe50.inf is adding RunOnceEx entries
  1102. // under the Wow6432Node and the are not being "reflected" to the normal HKLM branch. Thus, the below reg entry is
  1103. // never added.
  1104. wnsprintf(szPath, ARRAYSIZE(szPath), c_szPathFileFmt, TEXT("Software\\Wow6432Node\\Microsoft\\Active Setup\\Installed Components"), pszGuid);
  1105. // call RegCreateKeyEx in case the 32-bit stuff hasen't run yet
  1106. if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  1107. szPath,
  1108. 0,
  1109. NULL,
  1110. REG_OPTION_NON_VOLATILE,
  1111. KEY_SET_VALUE,
  1112. NULL,
  1113. &hkey,
  1114. NULL))
  1115. {
  1116. RegSetValueEx(hkey, c_szValueVersion, 0, REG_SZ, (LPBYTE)szVer, (cLen+1)*sizeof(TCHAR));
  1117. RegCloseKey(hkey);
  1118. }
  1119. #endif // _WIN64
  1120. }
  1121. else
  1122. {
  1123. LOG("[ERROR]: App's ASetup Key hasn't been created.");
  1124. }
  1125. }
  1126. /*******************************************************************
  1127. NAME: GetDirNames
  1128. SYNOPSIS: Figures out commonly used dir names
  1129. dwWant should have the nth bit set if you want the
  1130. nth string argument set
  1131. ********************************************************************/
  1132. DWORD GetDirNames(DWORD dwWant, LPTSTR pszOE, LPTSTR pszSystem, LPTSTR pszServices, LPTSTR pszStationery)
  1133. {
  1134. HKEY hkeyT;
  1135. DWORD cb;
  1136. DWORD dwType;
  1137. TCHAR szTemp[MAX_PATH];
  1138. TCHAR szTemp2[MAX_PATH];
  1139. DWORD dwReturned = 0;
  1140. ZeroMemory(szTemp, ARRAYSIZE(szTemp));
  1141. // Do they want the OE Install Directory?
  1142. if (dwWant & 1)
  1143. {
  1144. Assert(pszOE);
  1145. pszOE[0] = 0;
  1146. // OE Install Dir
  1147. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegFlat, 0, KEY_QUERY_VALUE, &hkeyT))
  1148. {
  1149. cb = MAX_PATH * sizeof(TCHAR);
  1150. if (ERROR_SUCCESS == RegQueryValueEx(hkeyT, c_szInstallRoot, 0, &dwType, (LPBYTE)pszOE, &cb))
  1151. {
  1152. // Forget about the null in count
  1153. cb--;
  1154. if (*CharPrev(pszOE, pszOE+cb) != '\\')
  1155. {
  1156. pszOE[cb++] = '\\';
  1157. pszOE[cb] = 0;
  1158. }
  1159. if (REG_EXPAND_SZ == dwType)
  1160. {
  1161. ExpandEnvironmentStrings(pszOE, szTemp, ARRAYSIZE(szTemp));
  1162. StrCpyN(pszOE, szTemp, MAX_PATH);
  1163. }
  1164. dwReturned |= 1;
  1165. }
  1166. RegCloseKey(hkeyT);
  1167. }
  1168. }
  1169. // Do they want the Common Files\System Directory?
  1170. if (dwWant & 2)
  1171. {
  1172. Assert(pszSystem);
  1173. pszSystem[0] = 0;
  1174. }
  1175. // Do they want the Common Files\Services Directory?
  1176. if (dwWant & 4)
  1177. {
  1178. Assert(pszServices);
  1179. pszServices[0] = 0;
  1180. }
  1181. // Do they want the Common Files\Microsoft Shared\Stationery Directory?
  1182. if (dwWant & 8)
  1183. {
  1184. Assert(pszStationery);
  1185. pszStationery[0] = 0;
  1186. }
  1187. // Program Files\Common Files\System and \Services
  1188. if (dwWant & (2 | 4 | 8))
  1189. {
  1190. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegWinCurrVer, 0, KEY_QUERY_VALUE, &hkeyT))
  1191. {
  1192. cb = sizeof(szTemp2);
  1193. if (ERROR_SUCCESS == RegQueryValueEx(hkeyT, c_szCommonFilesDir, 0, &dwType, (LPBYTE)szTemp2, &cb))
  1194. {
  1195. // Forget about the null in count
  1196. cb--;
  1197. if (*CharPrev(szTemp2, szTemp2+cb) != '\\')
  1198. {
  1199. szTemp2[cb++] = '\\';
  1200. szTemp2[cb]=0;
  1201. }
  1202. if (REG_EXPAND_SZ == dwType)
  1203. {
  1204. ExpandEnvironmentStrings(szTemp2, szTemp, ARRAYSIZE(szTemp));
  1205. StrCpyN(szTemp2, szTemp, ARRAYSIZE(szTemp2));
  1206. }
  1207. cb = lstrlen(szTemp2);
  1208. if (dwWant & 2)
  1209. {
  1210. StrCpyN(pszSystem, szTemp2, MAX_PATH);
  1211. // "System" could be localized
  1212. LoadString(g_hInstance, IDS_DIR_SYSTEM, &pszSystem[cb], MAX_PATH-cb);
  1213. dwWant |= 2;
  1214. }
  1215. if (dwWant & 4)
  1216. {
  1217. StrCpyN(pszServices, szTemp2, MAX_PATH);
  1218. // "Services" could be localized
  1219. LoadString(g_hInstance, IDS_DIR_SERVICES, &pszServices[cb], MAX_PATH-cb);
  1220. dwWant |= 4;
  1221. }
  1222. if (dwWant & 8)
  1223. {
  1224. StrCpyN(pszStationery, szTemp2, MAX_PATH);
  1225. // "Microsoft Shared\Stationery could be localized
  1226. LoadString(g_hInstance, IDS_DIR_STAT, &pszStationery[cb], MAX_PATH-cb);
  1227. dwWant |= 8;
  1228. }
  1229. }
  1230. RegCloseKey(hkeyT);
  1231. }
  1232. }
  1233. return dwWant;
  1234. }
  1235. /*******************************************************************
  1236. NAME: RepairBeta1Install
  1237. SYNOPSIS: See what happens when people make late design decisions!
  1238. ********************************************************************/
  1239. typedef struct tagRepairInfo
  1240. {
  1241. LPTSTR pszFile;
  1242. LPTSTR pszDir;
  1243. } REPAIRINFO;
  1244. typedef struct tagRegInfo
  1245. {
  1246. LPCTSTR pszRoot;
  1247. LPTSTR pszSub;
  1248. LPCTSTR pszValue;
  1249. } REGINFO;
  1250. void RepairBeta1Install()
  1251. {
  1252. HKEY hkeyOE, hkeyWAB;
  1253. TCHAR szOEUninstallFile [MAX_PATH];
  1254. TCHAR szOEUninstallDir [MAX_PATH];
  1255. TCHAR szWABUninstallFile[MAX_PATH];
  1256. TCHAR szWABUninstallDir [MAX_PATH];
  1257. TCHAR szTemp [MAX_PATH];
  1258. DWORD cb, dwType, dwTemp;
  1259. LOG("Attempting to repair Beta 1 Install...");
  1260. ZeroMemory(szTemp, ARRAYSIZE(szTemp));
  1261. switch (si.saApp)
  1262. {
  1263. case APP_WAB:
  1264. // Do we have the needed Advpack functionality?
  1265. if (NULL == si.pfnAddDel || NULL == si.pfnRegRestore)
  1266. {
  1267. LOG("[ERROR]: Extended Advpack functionality is needed but could not be found");
  1268. break;
  1269. }
  1270. // Figure out where the OE backup is
  1271. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegAdvInfoOE, 0, KEY_READ, &hkeyOE))
  1272. {
  1273. // Make sure we can create the AddressBook Key
  1274. if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szRegAdvInfoWAB, 0, NULL, REG_OPTION_NON_VOLATILE,
  1275. KEY_READ | KEY_WRITE, NULL, &hkeyWAB, &cb))
  1276. {
  1277. cb = sizeof(szOEUninstallFile);
  1278. if (ERROR_SUCCESS == RegQueryValueEx(hkeyOE, c_szBackupFileName, 0, &dwType, (LPBYTE)szOEUninstallFile, &cb))
  1279. {
  1280. UINT uLenWAB, uLenOE;
  1281. if (REG_EXPAND_SZ == dwType)
  1282. {
  1283. ExpandEnvironmentStrings(szOEUninstallFile, szTemp, ARRAYSIZE(szTemp));
  1284. StrCpyN(szOEUninstallFile, szTemp, ARRAYSIZE(szOEUninstallFile));
  1285. // Figure out where to change the extension for OE (4 = .DAT)
  1286. uLenOE = lstrlen(szOEUninstallFile) - 4;
  1287. }
  1288. else
  1289. // Figure out where to change the extension for OE (5 = .DAT + NULL from Query)
  1290. uLenOE = cb - 5;
  1291. // Can we get to it?
  1292. if (0xFFFFFFFF != GetFileAttributes(szOEUninstallFile))
  1293. {
  1294. LPTSTR pszSlash, pszCurrent;
  1295. cb = sizeof(szOEUninstallDir);
  1296. if (ERROR_SUCCESS == RegQueryValueEx(hkeyOE, c_szBackupPath, 0, &dwType, (LPBYTE)szOEUninstallDir, &cb))
  1297. {
  1298. if (REG_EXPAND_SZ == dwType)
  1299. {
  1300. ExpandEnvironmentStrings(szOEUninstallDir, szTemp, ARRAYSIZE(szTemp));
  1301. StrCpyN(szOEUninstallDir, szTemp, ARRAYSIZE(szOEUninstallDir));
  1302. }
  1303. // Figure out the destination for the file
  1304. StrCpyN(szWABUninstallDir, szOEUninstallDir, ARRAYSIZE(szWABUninstallDir));
  1305. pszCurrent = szWABUninstallDir;
  1306. pszSlash = NULL;
  1307. // Parse the string looking for the last slash
  1308. while (*pszCurrent)
  1309. {
  1310. if (*pszCurrent == TEXT('\\'))
  1311. pszSlash = CharNext(pszCurrent);
  1312. pszCurrent = CharNext(pszCurrent);
  1313. }
  1314. if (NULL != pszSlash)
  1315. {
  1316. TCHAR szOE [MAX_PATH];
  1317. TCHAR szCommonSys[MAX_PATH];
  1318. TCHAR szHelp [MAX_PATH];
  1319. TCHAR szStat [MAX_PATH];
  1320. TCHAR szServices [MAX_PATH];
  1321. TCHAR szFiles[5 * MAX_PATH];
  1322. int i,j;
  1323. szOE[0] = 0;
  1324. szCommonSys[0] = 0;
  1325. szHelp[0] = 0;
  1326. szStat[0] = 0;
  1327. szServices[0] = 0;
  1328. #if 0
  1329. // Files to remove from OE and WAB - 0
  1330. const REPAIRINFO BOTHDel[]= {};
  1331. #endif
  1332. // Files to remove from OE - 19
  1333. const REPAIRINFO OEDel[] = {
  1334. {"wab32.dll", szCommonSys}, {"wab.hlp" , szHelp}, {"wab.chm", szHelp}, {"wab.exe", szOE},
  1335. {"wabmig.exe", szOE}, {"wabimp.dll", szOE}, {"wabfind.dll", szOE}, {"msoeacct.dll", si.szSysDir},
  1336. {"msoert2.dll", si.szSysDir}, {"msoeacct.hlp", szHelp}, {"conn_oe.hlp", szHelp}, {"conn_oe.cnt", szHelp},
  1337. {"wab.cnt", szHelp}, {"wab32.dll", si.szSysDir}, {"wabfind.dll", si.szSysDir}, {"wabimp.dll", si.szSysDir},
  1338. {"wab.exe", si.szWinDir}, {"wabmig.exe", si.szWinDir}};
  1339. // Files to remove from WAB - 62
  1340. const REPAIRINFO WABDel[] = {
  1341. {"msoeres.dll", szOE}, {"msoe.dll", szOE}, {"msoe.hlp", szHelp}, {"msoe.chm", szHelp},
  1342. {"msoe.txt", szOE}, {"oeimport.dll", szOE}, {"inetcomm.dll", si.szSysDir}, {"inetres.dll", si.szSysDir},
  1343. {"msoemapi.dll", si.szSysDir}, {"msimn.exe", szOE}, {"inetcomm.hlp", szHelp}, {"msimn.cnt", szHelp},
  1344. {"msimn.hlp", szHelp}, {"msimn.chm", szHelp}, {"msimn.gid", szHelp}, {"_isetup.exe", szOE},
  1345. {"msimnui.dll", szOE}, {"msimn.txt", szOE}, {"mnlicens.txt", szOE}, {"msimnimp.dll", szOE},
  1346. {"msimn.inf", si.szInfDir}, {"msoert.dll", si.szSysDir},
  1347. {"bigfoot.bmp", szServices}, {"verisign.bmp", szServices}, {"yahoo.bmp", szServices},
  1348. {"infospce.bmp", szServices}, {"infospbz.bmp", szServices}, {"swtchbrd.bmp", szServices},
  1349. {"Baby News.htm", szStat}, {"Balloon Party Invitation.htm", szStat},
  1350. {"Chicken Soup.htm", szStat}, {"Formal Announcement.htm", szStat},
  1351. {"For Sale.htm", szStat}, {"Fun Bus.htm", szStat},
  1352. {"Holiday Letter.htm", szStat}, {"Mabel.htm", szStat},
  1353. {"Running Birthday.htm", szStat}, {"Story Book.htm", szStat},
  1354. {"Tiki Lounge.htm", szStat}, {"Ivy.htm", szStat},
  1355. {"One Green Balloon.gif", szStat}, {"Baby News Bkgrd.gif", szStat},
  1356. {"Chess.gif", szStat}, {"Chicken Soup Bkgrd.gif", szStat},
  1357. {"Formal Announcement Bkgrd.gif", szStat}, {"For Sale Bkgrd.gif", szStat},
  1358. {"FunBus.gif", szStat}, {"Holiday Letter Bkgrd.gif", szStat},
  1359. {"MabelT.gif", szStat}, {"MabelB.gif", szStat},
  1360. {"Running.gif", szStat}, {"Santa Workshop.gif", szStat},
  1361. {"Soup Bowl.gif", szStat}, {"Squiggles.gif", szStat},
  1362. {"StoryBook.gif", szStat}, {"Tiki.gif", szStat},
  1363. {"Christmas Trees.gif", szStat}, {"Ivy.gif", szStat},
  1364. {"Balloon Party Invitation Bkgrd.jpg", szStat}, {"Technical.htm", szStat},
  1365. {"Chess.htm", szStat}, {"Tech.gif", szStat}};
  1366. // Reg settings to remove from OE -
  1367. const REGINFO OERegDel[] = {
  1368. {c_szHKLM, "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\wab.exe", c_szEmpty},
  1369. {c_szHKLM, "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\wab.exe", c_szRegPath},
  1370. {c_szHKLM, "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\wabmig.exe", c_szEmpty},
  1371. {c_szHKLM, "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\wabmig.exe", c_szRegPath},
  1372. {c_szHKLM, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\InternetMailNews", NULL}};
  1373. //{c_szHKLM, "Software\\Microsoft\\Outlook Express", c_szInstallRoot}};
  1374. const REGINFO WABRegDel[] = {
  1375. {c_szHKLM, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\OptionalComponents\\OutlookExpress", "Installed"},
  1376. {c_szHKLM, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OutlookExpress", "DisplayName"},
  1377. {c_szHKLM, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OutlookExpress", "UninstallString"},
  1378. {c_szHKLM, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OutlookExpress", "QuietUninstallString"},
  1379. {c_szHKLM, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OutlookExpress", c_szRequiresIESys},
  1380. {c_szHKLM, "Software\\Microsoft\\Outlook Express", "InstallRoot"},
  1381. {c_szHKLM, "Software\\Microsoft\\Outlook Express\\Inetcomm", "DllPath"},
  1382. {c_szHKLM, "Software\\Microsoft\\Outlook Express", "Beta"},
  1383. {c_szHKLM, "Software\\Clients\\Mail\\Outlook Express", NULL},
  1384. {c_szHKLM, "Software\\Clients\\News\\Outlook Express", NULL},
  1385. {c_szHKLM, "Software\\Clients\\Mail\\Internet Mail and News", NULL},
  1386. {c_szHKLM, "Software\\Clients\\News\\Internet Mail and News", NULL},
  1387. {c_szHKLM, "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\InternetMailNews", NULL}};
  1388. //{c_szHKLM, "Software\\Microsoft\\Outlook Express", c_szInstallRoot}};
  1389. // Append the path to the addressbook dir
  1390. StrCpyN(pszSlash, c_szWABComponent, ARRAYSIZE(szWABUninstallDir) - (DWORD)(pszSlash - szWABUninstallDir));
  1391. // Create a directory
  1392. CreateDirectoryEx(szOEUninstallDir, szWABUninstallDir, NULL);
  1393. // Copy Reg
  1394. CopyRegistry(hkeyOE, hkeyWAB);
  1395. // If running on 9X, copy the AINF file too
  1396. if (VER_PLATFORM_WIN32_WINDOWS == si.osv.dwPlatformId)
  1397. {
  1398. cb = sizeof(szTemp);
  1399. if (ERROR_SUCCESS == RegQueryValueEx(hkeyOE, c_szBackupRegPathName, 0, NULL, (LPBYTE)szTemp, &cb))
  1400. {
  1401. // Can't be REG_EXPAND_SZ, this is Win9X!
  1402. // Strip all but the filename
  1403. pszCurrent = szTemp;
  1404. pszSlash = NULL;
  1405. // Parse the string looking for the last slash
  1406. while (*pszCurrent)
  1407. {
  1408. if ('\\' == *pszCurrent)
  1409. pszSlash = CharNext(pszCurrent);
  1410. pszCurrent = CharNext(pszCurrent);
  1411. }
  1412. if (pszSlash)
  1413. {
  1414. TCHAR szWABShortDir[MAX_PATH];
  1415. // Combine the WAB dir name and the name of the OE file
  1416. wnsprintf(szWABShortDir, ARRAYSIZE(szWABShortDir), c_szPathFileFmt, szWABUninstallDir, pszSlash);
  1417. // Shorten destination
  1418. GetShortPathName(szWABShortDir, szWABShortDir, ARRAYSIZE(szWABShortDir));
  1419. // Write it into the registry (+1 for the NULL)
  1420. RegSetValueEx(hkeyWAB, c_szBackupRegPathName, 0, REG_SZ, (LPBYTE)szWABShortDir, (lstrlen(szWABShortDir)+1)*sizeof(TCHAR));
  1421. // Copy the file
  1422. CopyFile(szTemp, szWABShortDir, TRUE);
  1423. }
  1424. }
  1425. }
  1426. // Figure out the path the to wab INI and DAT
  1427. StrCpyN(szWABUninstallFile, szWABUninstallDir, ARRAYSIZE(szWABUninstallFile));
  1428. // Add Slash and component
  1429. StrCatBuff(szWABUninstallFile, c_szSlashWABComponent, ARRAYSIZE(szWABUninstallFile));
  1430. // Calculate the length for extension placement
  1431. uLenWAB = lstrlen(szWABUninstallFile);
  1432. // Do the DAT first
  1433. StrCpyN(&szWABUninstallFile[uLenWAB], c_szDotDAT, ARRAYSIZE(szWABUninstallFile) - uLenWAB);
  1434. // Patch the path names in the registry
  1435. cb = (lstrlen(szWABUninstallDir) + 1) * sizeof(TCHAR);
  1436. RegSetValueEx(hkeyWAB, c_szBackupPath, 0, REG_SZ, (LPBYTE)szWABUninstallDir, cb);
  1437. cb = (lstrlen(szWABUninstallFile) + 1) * sizeof(TCHAR);
  1438. RegSetValueEx(hkeyWAB, c_szBackupFileName, 0, REG_SZ, (LPBYTE)szWABUninstallFile, cb);
  1439. // ---- CALCULATE DIRECTORY NAMES
  1440. dwTemp = GetDirNames(1 | 2 | 4 | 8, szOE, szCommonSys, szServices, szStat);
  1441. if (VER_PLATFORM_WIN32_WINDOWS == si.osv.dwPlatformId)
  1442. {
  1443. if (dwTemp & 1)
  1444. GetShortPathName(szOE, szOE, ARRAYSIZE(szOE));
  1445. if (dwTemp & 2)
  1446. GetShortPathName(szCommonSys, szCommonSys, ARRAYSIZE(szCommonSys));
  1447. if (dwTemp & 4)
  1448. GetShortPathName(szServices, szServices, ARRAYSIZE(szServices));
  1449. if (dwTemp & 8)
  1450. GetShortPathName(szStat, szStat, ARRAYSIZE(szStat));
  1451. }
  1452. // Help Dir
  1453. StrCpyN(szHelp, si.szWinDir, ARRAYSIZE(szHelp));
  1454. cb = lstrlen(szHelp);
  1455. LoadString(g_hInstance, IDS_DIR_HELP, &szHelp[cb], ARRAYSIZE(szHelp)-cb);
  1456. if (VER_PLATFORM_WIN32_WINDOWS == si.osv.dwPlatformId)
  1457. GetShortPathName(szHelp, szHelp, ARRAYSIZE(szHelp));
  1458. // ---- MANIPULATE FILES
  1459. // Copy the DAT file to AddressBook land
  1460. CopyFile(szOEUninstallFile, szWABUninstallFile, TRUE);
  1461. StrCpyN(&szOEUninstallFile[uLenOE], c_szDotINI, ARRAYSIZE(szOEUninstallFile) - uLenOE);
  1462. StrCpyN(&szWABUninstallFile[uLenWAB], c_szDotINI, ARRAYSIZE(szWABUninstallFile) - uLenWAB);
  1463. // Copy the INI file to AddressBook land
  1464. CopyFile(szOEUninstallFile, szWABUninstallFile, TRUE);
  1465. // Purge Files from OE - 5 at a time
  1466. for (i=0; i < ARRAYSIZE(OEDel);)
  1467. {
  1468. for (j=i, cb=0; i < ARRAYSIZE(OEDel) && i-j < 5; i++)
  1469. cb += wnsprintf(&szFiles[cb++], ARRAYSIZE(szFiles) - cb,
  1470. c_szFileEntryFmt, OEDel[i].pszDir, OEDel[i].pszFile);
  1471. szFiles[cb] = 0;
  1472. (*si.pfnAddDel)(szFiles, szOEUninstallDir, c_szOEComponent, AADBE_DEL_ENTRY);
  1473. }
  1474. // Purge Files from WAB - 5 at a time
  1475. for (i=0; i<ARRAYSIZE(WABDel);)
  1476. {
  1477. for (j=i, cb=0; i < ARRAYSIZE(WABDel) && i-j < 5; i++)
  1478. cb += wnsprintf(&szFiles[cb++], ARRAYSIZE(szFiles) - cb,
  1479. c_szFileEntryFmt, WABDel[i].pszDir, WABDel[i].pszFile);
  1480. szFiles[cb] = 0;
  1481. (*si.pfnAddDel)(szFiles, szWABUninstallDir, c_szWABComponent, AADBE_DEL_ENTRY);
  1482. }
  1483. // ---- REPAIR Registry
  1484. HKEY hkeyOEBak=NULL;
  1485. HKEY hkeyWABBak=NULL;
  1486. if (VER_PLATFORM_WIN32_WINDOWS != si.osv.dwPlatformId)
  1487. {
  1488. // On non-Win95, we need to open a sub key of the backup info
  1489. RegOpenKeyEx(hkeyOE, c_szRegBackup, 0, KEY_READ | KEY_WRITE, &hkeyOEBak);
  1490. RegOpenKeyEx(hkeyWAB, c_szRegBackup, 0, KEY_READ | KEY_WRITE, &hkeyWABBak);
  1491. }
  1492. else
  1493. {
  1494. hkeyOEBak = hkeyOE;
  1495. hkeyWABBak = hkeyWAB;
  1496. }
  1497. if (NULL != hkeyOEBak)
  1498. {
  1499. // Remove settings from OE that we want bundled with the WAB
  1500. for (i=0; i<ARRAYSIZE(OERegDel); i++)
  1501. {
  1502. (*si.pfnRegRestore)(NULL, NULL, hkeyOEBak, OERegDel[i].pszRoot, OERegDel[i].pszSub,
  1503. OERegDel[i].pszValue, ARSR_RESTORE | ARSR_REMOVREGBKDATA | ARSR_NOMESSAGES);
  1504. }
  1505. if (VER_PLATFORM_WIN32_WINDOWS != si.osv.dwPlatformId)
  1506. RegCloseKey(hkeyOEBak);
  1507. }
  1508. if (NULL != hkeyWABBak)
  1509. {
  1510. // Remove settings from WAB that we want bundled with OE
  1511. for (i=0; i<ARRAYSIZE(WABRegDel); i++)
  1512. {
  1513. (*si.pfnRegRestore)(NULL, NULL, hkeyWABBak, WABRegDel[i].pszRoot, WABRegDel[i].pszSub,
  1514. WABRegDel[i].pszValue, ARSR_RESTORE | ARSR_REMOVREGBKDATA | ARSR_NOMESSAGES);
  1515. }
  1516. if (VER_PLATFORM_WIN32_WINDOWS != si.osv.dwPlatformId)
  1517. RegCloseKey(hkeyWABBak);
  1518. }
  1519. // If v1 or v1.1 preceded Beta1, restore reg settings that Beta1 deleted so we can roll them
  1520. SETUPVER svPrev;
  1521. GetVerInfo(NULL, &svPrev);
  1522. if (VER_1_0 == svPrev || VER_1_1 == svPrev)
  1523. {
  1524. // Restore IMN reg
  1525. wnsprintf(szTemp, ARRAYSIZE(szTemp), c_szFileEntryFmt, si.szInfDir, si.pszInfFile);
  1526. (*si.pfnRunSetup)(NULL, szTemp, (VER_1_1 == svPrev ? c_szRestoreV1WithWAB : c_szRestoreV1),
  1527. si.szInfDir, si.szAppName, NULL, RSC_FLAG_INF | RSC_FLAG_NGCONV | OE_QUIET, 0);
  1528. }
  1529. }
  1530. }
  1531. }
  1532. }
  1533. RegCloseKey(hkeyWAB);
  1534. }
  1535. RegCloseKey(hkeyOE);
  1536. }
  1537. break;
  1538. default:
  1539. break;
  1540. }
  1541. LOG("Repair attempt complete.");
  1542. }
  1543. /*******************************************************************
  1544. NAME: RespectRedistMode()
  1545. SYNOPSIS: Sees if IE is installing in redist mode, and persists
  1546. state so per-user install stubs can respect it
  1547. ********************************************************************/
  1548. void RespectRedistMode()
  1549. {
  1550. HKEY hkey;
  1551. BOOL fRedistMode = FALSE;
  1552. DWORD dwDisp;
  1553. DWORD dwInstallMode = 0;
  1554. DWORD dwType;
  1555. DWORD cb;
  1556. // Is IE Setup running in redist mode, /x or /x:1?
  1557. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szIESetupKey, 0, KEY_READ, &hkey))
  1558. {
  1559. cb = sizeof(dwInstallMode);
  1560. if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szIEInstallMode, 0, &dwType, (LPBYTE)&dwInstallMode, &cb))
  1561. {
  1562. if (REG_DWORD == dwType)
  1563. fRedistMode = ((REDIST_REMOVELINKS | REDIST_DONT_TAKE_ASSOCIATION) & dwInstallMode) > 0;
  1564. else
  1565. AssertSz(FALSE, "IE has changed the encoding of their redist mode flag, ignoring");
  1566. }
  1567. RegCloseKey(hkey);
  1568. }
  1569. // Let setup know which mode to run in
  1570. if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, si.pszVerInfo, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkey, &dwDisp))
  1571. {
  1572. if (fRedistMode)
  1573. {
  1574. // Our setup only has one redist mode
  1575. dwInstallMode = 1;
  1576. RegSetValueEx(hkey, c_szIEInstallMode, 0, REG_DWORD, (LPBYTE)&dwInstallMode, sizeof(dwInstallMode));
  1577. }
  1578. else
  1579. {
  1580. RegDeleteValue(hkey, c_szIEInstallMode);
  1581. }
  1582. RegCloseKey(hkey);
  1583. }
  1584. }
  1585. /*******************************************************************
  1586. NAME: FDependenciesPresent
  1587. ********************************************************************/
  1588. BOOL FDependenciesPresent(BOOL fPerm)
  1589. {
  1590. BOOL fPresent = FALSE;
  1591. TCHAR szOE[MAX_PATH];
  1592. TCHAR szCommonSys[MAX_PATH];
  1593. TCHAR szTemp[MAX_PATH];
  1594. REPAIRINFO *pRI;
  1595. int n, i;
  1596. HINSTANCE hInst;
  1597. if (VER_PLATFORM_WIN32_NT == si.osv.dwPlatformId)
  1598. {
  1599. LOG("Avoiding run-time dependency check as we are on NT. Reboot will be required.");
  1600. return FALSE;
  1601. }
  1602. LOG("Verifying run-time dependencies...");
  1603. // List of Dlls that we regsvr32 in OE
  1604. const REPAIRINFO OEDlls[] = {
  1605. {"inetcomm.dll", si.szSysDir}, {"msoe.dll", szOE}, {"oeimport.dll", szOE}};
  1606. // List of Dlls that we regsvr32 in WAB
  1607. const REPAIRINFO WABDlls[] = {
  1608. {"msoeacct.dll", si.szSysDir}, {"wab32.dll", szCommonSys}, {"wabfind.dll", szOE}, {"wabimp.dll", szOE}};
  1609. // List of Dlls that we regsvr32 permanently in OE
  1610. const REPAIRINFO OEDllsPerm[] = {
  1611. {"directdb.dll", szCommonSys}, {"oemiglib.dll", szOE}};
  1612. // List of Dlls that we regsvr32 permanently in WAB
  1613. //const REPAIRINFO WABDllsPerm[] = {};
  1614. switch (si.saApp)
  1615. {
  1616. case APP_OE:
  1617. if (fPerm)
  1618. {
  1619. // Need OE dir and common sys dir for OEDllsPerm
  1620. if (3 == GetDirNames(1 | 2, szOE, szCommonSys, NULL, NULL))
  1621. {
  1622. pRI = (REPAIRINFO*)OEDllsPerm;
  1623. n = ARRAYSIZE(OEDllsPerm);
  1624. }
  1625. else
  1626. return FALSE;
  1627. }
  1628. else
  1629. {
  1630. // Only need OE dir for OEDlls
  1631. if (1 == GetDirNames(1, szOE, NULL, NULL, NULL))
  1632. {
  1633. pRI = (REPAIRINFO*)OEDlls;
  1634. n = ARRAYSIZE(OEDlls);
  1635. }
  1636. else
  1637. return FALSE;
  1638. }
  1639. break;
  1640. case APP_WAB:
  1641. if (fPerm)
  1642. {
  1643. //pRI = (REPAIRINFO*)OEDllsPerm;
  1644. //n = ARRAYSIZE(OEDllsPerm);
  1645. return TRUE;
  1646. }
  1647. else
  1648. {
  1649. if (3 == GetDirNames(1 | 2, szOE, szCommonSys, NULL, NULL))
  1650. {
  1651. pRI = (REPAIRINFO*)WABDlls;
  1652. n = ARRAYSIZE(WABDlls);
  1653. }
  1654. else
  1655. return FALSE;
  1656. }
  1657. break;
  1658. default:
  1659. Assert(FALSE);
  1660. return FALSE;
  1661. }
  1662. fPresent = TRUE;
  1663. for (i = 0; fPresent && (i < n); i++)
  1664. {
  1665. Assert(*(pRI[i].pszDir));
  1666. Assert(*(pRI[i].pszFile));
  1667. wnsprintf(szTemp, ARRAYSIZE(szTemp), c_szFileEntryFmt, pRI[i].pszDir, pRI[i].pszFile);
  1668. if (hInst = LoadLibrary(szTemp))
  1669. FreeLibrary(hInst);
  1670. else
  1671. {
  1672. LOG("Unable to load ");
  1673. LOG2(szTemp);
  1674. LOG("Reboot required.");
  1675. fPresent = FALSE;
  1676. }
  1677. }
  1678. return fPresent;
  1679. }
  1680. /*******************************************************************
  1681. NAME: UpdateStubInfo
  1682. ********************************************************************/
  1683. void UpdateStubInfo(BOOL fInstall)
  1684. {
  1685. LPCTSTR pszGUID;
  1686. HKEY hkeySrcRoot, hkeySrc, hkeyDestRoot, hkeyDest;
  1687. DWORD cb, dwType;
  1688. TCHAR szTemp[MAX_PATH];
  1689. switch (si.saApp)
  1690. {
  1691. case APP_OE:
  1692. pszGUID = c_szOEGUID;
  1693. break;
  1694. case APP_WAB:
  1695. pszGUID = c_szWABGUID;
  1696. break;
  1697. default:
  1698. return;
  1699. }
  1700. if (fInstall)
  1701. {
  1702. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegASetup, 0, KEY_READ, &hkeySrcRoot))
  1703. {
  1704. if (ERROR_SUCCESS == RegOpenKeyEx(hkeySrcRoot, pszGUID, 0, KEY_QUERY_VALUE, &hkeySrc))
  1705. {
  1706. if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER, c_szRegASetup, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkeyDestRoot, &dwType))
  1707. {
  1708. if (ERROR_SUCCESS == RegCreateKeyEx(hkeyDestRoot, pszGUID, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hkeyDest, &dwType))
  1709. {
  1710. // Copy Version and Locale
  1711. // BUGBUG: Make this extensible via a registry list of values to copy
  1712. cb = sizeof(szTemp);
  1713. if (ERROR_SUCCESS == RegQueryValueEx(hkeySrc, c_szValueVersion, 0, &dwType, (LPBYTE)szTemp, &cb))
  1714. RegSetValueEx(hkeyDest, c_szValueVersion, 0, dwType, (LPBYTE)szTemp, cb);
  1715. cb = sizeof(szTemp);
  1716. if (ERROR_SUCCESS == RegQueryValueEx(hkeySrc, c_szLocale, 0, &dwType, (LPBYTE)szTemp, &cb))
  1717. RegSetValueEx(hkeyDest, c_szLocale, 0, dwType, (LPBYTE)szTemp, cb);
  1718. RegCloseKey(hkeyDest);
  1719. }
  1720. RegCloseKey(hkeyDestRoot);
  1721. }
  1722. RegCloseKey(hkeySrc);
  1723. }
  1724. RegCloseKey(hkeySrcRoot);
  1725. }
  1726. }
  1727. else
  1728. {
  1729. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, c_szRegASetup, 0, KEY_WRITE | KEY_READ, &hkeyDestRoot))
  1730. {
  1731. RegDeleteKeyRecursive(hkeyDestRoot, pszGUID);
  1732. RegCloseKey(hkeyDestRoot);
  1733. }
  1734. }
  1735. }
  1736. /*******************************************************************
  1737. NAME: LaunchINFSectionExWorks
  1738. SYNOPSIS: IE 5.0 has a bug in which LaunchINFSectionEx does not
  1739. work properly (it can return S_OK when files are in
  1740. use). IE backed out my fix as it broke the 12 lang
  1741. packs. This should be fixed soon though. If we
  1742. ship 5.0 with OSR we can just tweak the INF to turn
  1743. on the correct behaviour.
  1744. ********************************************************************/
  1745. BOOL LaunchINFSectionExWorks()
  1746. {
  1747. HKEY hkey;
  1748. DWORD dw=0, cb;
  1749. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, si.pszVerInfo, 0, KEY_QUERY_VALUE, &hkey))
  1750. {
  1751. cb = sizeof(dw);
  1752. RegQueryValueEx(hkey, c_szLaunchWorks, 0, NULL, (LPBYTE)&dw, &cb);
  1753. RegCloseKey(hkey);
  1754. }
  1755. return !!dw;
  1756. }
  1757. /*******************************************************************
  1758. NAME: InstallMachine
  1759. ********************************************************************/
  1760. HRESULT InstallMachine()
  1761. {
  1762. TCHAR szInfFile[MAX_PATH], szArgs[MAX_PATH * 2];
  1763. SETUPVER svPrevVer;
  1764. BOOL fNeedReboot = FALSE;
  1765. BOOL fLaunchEx;
  1766. HRESULT hrT;
  1767. // Update version info for previous ver
  1768. HandleVersionInfo(FALSE);
  1769. if (CALLER_IE == si.caller)
  1770. {
  1771. // See if IE is installing in redist mode
  1772. // For more info see: http://ie/specs/secure/corpsetup/batchinstall.htm
  1773. RespectRedistMode();
  1774. // Bug 66967
  1775. // LaunchINFSectionEx for IE 5.0 does not return accurate reboot info
  1776. fLaunchEx = LaunchINFSectionExWorks();
  1777. // Special case OE5 B1
  1778. if (InterimBuild(&svPrevVer) && VER_5_0_B1 == svPrevVer)
  1779. RepairBeta1Install();
  1780. // Perform Permanent portion of setup (excluding DLL reg)
  1781. wnsprintf(szInfFile, ARRAYSIZE(szInfFile), c_szPathFileFmt, si.szCurrentDir, si.pszInfFile);
  1782. hrT = (*si.pfnRunSetup)(NULL, szInfFile, c_szMachineInstallSection, si.szCurrentDir, si.szAppName, NULL, RSC_FLAG_INF | RSC_FLAG_NGCONV | OE_QUIET, 0);
  1783. // See if the file copies need a reboot
  1784. if (!fLaunchEx || (ERROR_SUCCESS_REBOOT_REQUIRED == hrT))
  1785. fNeedReboot = TRUE;
  1786. else
  1787. // See if we are going to need a reboot anyway because our perm dlls won't load
  1788. fNeedReboot = !FDependenciesPresent(TRUE);
  1789. // Register the Perm dlls keeping in mind whether we'll need a reboot
  1790. (*si.pfnRunSetup)(NULL, szInfFile, c_szRegisterPermOCX, si.szCurrentDir, si.szAppName, NULL, RSC_FLAG_INF | RSC_FLAG_NGCONV | OE_QUIET | (fNeedReboot ? RSC_FLAG_DELAYREGISTEROCX : 0), 0);
  1791. PreRollable();
  1792. // Perform Rollable portion of setup (excluding DLL reg)
  1793. wnsprintf(szArgs, ARRAYSIZE(szArgs), c_szLaunchFmt, szInfFile, c_szMachineInstallSectionEx, c_szEmpty, ALINF_BKINSTALL | ALINF_NGCONV | OE_QUIET | (fNeedReboot ? RSC_FLAG_DELAYREGISTEROCX : 0));
  1794. hrT = (*si.pfnLaunchEx)(NULL, NULL, szArgs, 0);
  1795. // If we've gotten away without needing a reboot so far...
  1796. if (!fNeedReboot)
  1797. {
  1798. // See if the file copies need a reboot
  1799. if (ERROR_SUCCESS_REBOOT_REQUIRED == hrT)
  1800. fNeedReboot = TRUE;
  1801. else
  1802. // See if we are going to need a reboot anyway because our rollable dlls won't load
  1803. fNeedReboot = !FDependenciesPresent(FALSE);
  1804. }
  1805. // Register OCXs
  1806. (*si.pfnRunSetup)(NULL, szInfFile, c_szRegisterOCX, si.szCurrentDir, si.szAppName, NULL, RSC_FLAG_INF | RSC_FLAG_NGCONV | OE_QUIET | (fNeedReboot ? RSC_FLAG_DELAYREGISTEROCX : 0), 0);
  1807. }
  1808. else
  1809. // We delayed writing the active setup ver so that HandleVersionInfo could sniff it, but must put it in now.
  1810. ApplyActiveSetupVer();
  1811. // Run any need post setup goo
  1812. RunPostSetup();
  1813. // Handle setting default handlers
  1814. SetHandlers();
  1815. // Update version info for current version
  1816. HandleVersionInfo(TRUE);
  1817. // Run the User stub if we can (don't run per-user goo at the end of NT GUI mode setup)
  1818. if (!fNeedReboot && (CALLER_WINNT != si.caller))
  1819. {
  1820. InstallUser();
  1821. // Ensure stub cleanup will run if they immediately uninstall
  1822. UpdateStubInfo(TRUE);
  1823. return S_OK;
  1824. }
  1825. return ERROR_SUCCESS_REBOOT_REQUIRED;
  1826. }
  1827. /*******************************************************************
  1828. NAME: InstallUser
  1829. ********************************************************************/
  1830. void InstallUser()
  1831. {
  1832. TCHAR szInfFile[MAX_PATH];
  1833. // Move settings under this version's key in the registry
  1834. UpgradeSettings();
  1835. // Call the UserInstall section of the inf
  1836. wnsprintf(szInfFile, ARRAYSIZE(szInfFile), c_szFileEntryFmt, si.szInfDir, si.pszInfFile);
  1837. const TCHAR *pszUserInstallSection;
  1838. // If it's OE and we're on XP SP1 or later, we will let the OEAccess component in shmgrate.exe
  1839. // take care of showing/hiding icons
  1840. if ((0 == lstrcmpi(c_szMsimnInf, si.pszInfFile)) && IsXPSP1OrLater())
  1841. {
  1842. pszUserInstallSection = c_szUserInstallSectionOEOnXPSP1OrLater;
  1843. }
  1844. else
  1845. {
  1846. pszUserInstallSection = c_szUserInstallSection;
  1847. }
  1848. (*si.pfnRunSetup)(NULL, szInfFile, pszUserInstallSection, si.szInfDir, si.szAppName, NULL, RSC_FLAG_INF | OE_QUIET, 0);
  1849. // Create Desktop, Quick launch and start menu icons
  1850. HandleLinks(TRUE);
  1851. if (IsXPSP1OrLater())
  1852. {
  1853. TCHAR szCmdLine[MAX_PATH];
  1854. GetSystemDirectory(szCmdLine, ARRAYSIZE(szCmdLine));
  1855. DWORD cb = 0;
  1856. PathAddSlash(szCmdLine, &cb);
  1857. int cch = lstrlen(szCmdLine);
  1858. StrCpyN(szCmdLine + cch, ("shmgrate.exe"), ARRAYSIZE(szCmdLine) - cch);
  1859. ShellExecute(NULL, NULL, szCmdLine, TEXT("OCInstallUserConfigOE"), NULL, SW_SHOWDEFAULT);
  1860. }
  1861. }