Source code of Windows XP (NT5)
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.

1530 lines
49 KiB

  1. #include <windows.h>
  2. #include <shlobj.h>
  3. #include <shlwapi.h>
  4. #include <shlwapip.h>
  5. #include <inetreg.h>
  6. #include <advpub.h>
  7. #include <debug.h>
  8. #include <inetreg.h>
  9. #include <shlobj.h>
  10. #include <advpub.h>
  11. #include <xpsp1res.h>
  12. #include <regstr.h>
  13. #include "shmgdefs.h"
  14. HINSTANCE g_hInstResLib = NULL;
  15. const WCHAR c_szIEApp[] = L"iexplore.exe";
  16. const WCHAR c_szOEApp[] = L"msimn.exe";
  17. const WCHAR c_szWMP[] = L"wmplayer.exe";
  18. const WCHAR c_szMessenger[] = L"msmsgs.exe";
  19. const WCHAR c_szIECanonicalName[] = L"IEXPLORE.EXE";
  20. const WCHAR c_szOECanonicalName[] = L"Outlook Express";
  21. #ifndef INTERNET_MAX_PATH_LENGTH
  22. #define INTERNET_MAX_PATH_LENGTH 2048
  23. #endif
  24. #ifdef _TNOONAN_TEST_WIN64
  25. #define _WIN64
  26. #undef CSIDL_PROGRAM_FILESX86
  27. #define CSIDL_PROGRAM_FILESX86 CSIDL_PROGRAM_FILES
  28. #endif
  29. //
  30. // We must create our shortcuts in the same language as the install
  31. // language. If the install language is USEnglish, we cannot use
  32. // LoadString because MUI might redirect us to the localized string,
  33. // so we have a hard-coded list of USEnglish strings. We need that
  34. // anyway in the Hide case, where we may need to delete old USEnglish
  35. // versions of the shortcut left over from previous versions of IE.
  36. //
  37. enum { // Localized Shortcut Name
  38. LSN_SM_IE,
  39. LSN_QL_IE,
  40. LSN_SM_OE,
  41. LSN_QL_OE,
  42. LSN_NOSHOW_OE,
  43. LSN_NOSHOW_IE,
  44. #ifdef _WIN64
  45. LSN_SM_IE32,
  46. #endif
  47. // special sentinel value
  48. LSN_NONE = -1,
  49. };
  50. struct LOCALIZEDSHORTCUTINFO
  51. {
  52. LPCWSTR pszExe; // The application to run
  53. LPCWSTR pszUSEnglish; // Use if native OS is USEnglish or MUI-localized
  54. UINT idsLocalized; // Use if native OS is fully-localized (relative to xpsp1res)
  55. UINT idsDescription; // Shortcut description (relative to xpsp1res)
  56. BOOL fNeverShowShortcut; // Use if we should never show (only hide)
  57. };
  58. const LOCALIZEDSHORTCUTINFO c_rglsi[] = {
  59. { // LSN_SM_IE
  60. c_szIEApp,
  61. L"Internet Explorer",
  62. IDS_OC_IESHORTCUTNAME_SM,
  63. IDS_OC_IEDESCRIPTION,
  64. FALSE,
  65. },
  66. { // LSN_QL_IE
  67. c_szIEApp,
  68. L"Launch Internet Explorer Browser",
  69. IDS_OC_IESHORTCUTNAME_QL,
  70. IDS_OC_IEDESCRIPTION,
  71. FALSE,
  72. },
  73. { // LSN_SM_OE
  74. c_szOEApp,
  75. L"Outlook Express",
  76. IDS_OC_OESHORTCUTNAME_SM,
  77. IDS_OC_OEDESCRIPTION,
  78. FALSE,
  79. },
  80. { // LSN_QL_OE
  81. c_szOEApp,
  82. L"Launch Outlook Express",
  83. IDS_OC_OESHORTCUTNAME_QL,
  84. IDS_OC_OEDESCRIPTION,
  85. TRUE,
  86. },
  87. { // LSN_NOSHOW_OE
  88. c_szOEApp,
  89. L"Outlook Express",
  90. IDS_OC_OESHORTCUTNAME_SM,
  91. IDS_OC_OEDESCRIPTION,
  92. TRUE,
  93. },
  94. { // LSN_NOSHOW_IE
  95. c_szIEApp,
  96. L"Internet Explorer",
  97. IDS_OC_OESHORTCUTNAME_SM,
  98. IDS_OC_OEDESCRIPTION,
  99. TRUE,
  100. },
  101. #ifdef _WIN64
  102. { // LSN_SM_IE32
  103. NULL, // Special-cased in CreateShortcut since it's not in App Paths
  104. L"Internet Explorer (32-bit)",
  105. IDS_OC_IESHORTCUTNAME_SM64,
  106. IDS_OC_IEDESCRIPTION,
  107. FALSE,
  108. },
  109. #endif
  110. };
  111. #ifdef _WIN64
  112. WCHAR g_szIE32Path[MAX_PATH];
  113. #endif
  114. const WCHAR c_szIMN[] = L"Internet Mail and News";
  115. const WCHAR c_szNTOS[] = L"Microsoft(R) Windows NT(TM) Operating System";
  116. const WCHAR c_szHotmail[] = L"Hotmail";
  117. const WCHAR c_szUrlDll[] = L"url.dll";
  118. const WCHAR c_szMailNewsDll[] = L"mailnews.dll";
  119. const WCHAR c_szIEInstallInfoKey[] = L"Software\\Clients\\StartMenuInternet\\IEXPLORE.EXE\\InstallInfo";
  120. const WCHAR c_szOEInstallInfoKey[] = L"Software\\Clients\\Mail\\Outlook Express\\InstallInfo";
  121. const WCHAR c_szIconsVisible[] = L"IconsVisible";
  122. const WCHAR c_szReinstallCommand[] = L"ReinstallCommand";
  123. const WCHAR c_szHideIconsCommand[] = L"HideIconsCommand";
  124. const WCHAR c_szShowIconsCommand[] = L"ShowIconsCommand";
  125. const WCHAR c_szReinstallCommandOE[] = L"%SystemRoot%\\system32\\shmgrate.exe OCInstallReinstallOE";
  126. const WCHAR c_szHideIconsCommandOE[] = L"%SystemRoot%\\system32\\shmgrate.exe OCInstallHideOE";
  127. const WCHAR c_szShowIconsCommandOE[] = L"%SystemRoot%\\system32\\shmgrate.exe OCInstallShowOE";
  128. const WCHAR c_szStartMenuInternetClientKey[] = L"Software\\Clients\\StartMenuInternet";
  129. const WCHAR c_szMailClientKey[] = L"Software\\Clients\\Mail";
  130. #ifdef _WIN64
  131. const WCHAR c_szMailClientKeyWOW32[] = L"Software\\Wow6432Node\\Clients\\Mail";
  132. #endif
  133. const WCHAR c_szJavaVMKey[] = L"CLSID\\{08B0E5C0-4FCB-11CF-AAA5-00401C608501}";
  134. const WCHAR c_szInitiallyClearKey[] = L"Software\\Microsoft\\Active Setup\\Installed Components\\InitiallyClear";
  135. const WCHAR c_szIEAccessKey[] = L"Software\\Microsoft\\Active Setup\\Installed Components\\>{26923b43-4d38-484f-9b9e-de460746276c}";
  136. const WCHAR c_szOEAccessKey[] = L"Software\\Microsoft\\Active Setup\\Installed Components\\>{881dd1c5-3dcf-431b-b061-f3f88e8be88a}";
  137. const WCHAR c_szIsInstalled[] = L"IsInstalled";
  138. const WCHAR c_szLocale[] = L"Locale";
  139. const WCHAR c_szVersion[] = L"Version";
  140. const WCHAR c_szOCManagerSubComponents[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Setup\\OC Manager\\Subcomponents";
  141. const WCHAR c_szIEAccess[] = L"IEAccess";
  142. const WCHAR c_szOEAccess[] = L"OEAccess";
  143. const WCHAR c_szKeyComponentFormat[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\%s\\ShellFolder";
  144. const WCHAR c_szIEDesktopCLSID[] = L"{871C5380-42A0-1069-A2EA-08002B30309D}";
  145. const WCHAR c_szShellFolder[] = L"ShellFolder";
  146. const WCHAR c_szAttribute[] = L"Attributes";
  147. void ShellFree(LPITEMIDLIST pidl)
  148. {
  149. if (pidl)
  150. {
  151. IMalloc *pMalloc;
  152. if (SUCCEEDED(SHGetMalloc(&pMalloc)))
  153. {
  154. pMalloc->Free(pidl);
  155. pMalloc->Release();
  156. }
  157. }
  158. }
  159. HINSTANCE GetResLibInstance()
  160. {
  161. if (NULL == g_hInstResLib)
  162. {
  163. g_hInstResLib = LoadLibraryEx(L"xpsp1res.dll", NULL, LOAD_LIBRARY_AS_DATAFILE);
  164. }
  165. return g_hInstResLib;
  166. }
  167. BOOL IsServer()
  168. {
  169. OSVERSIONINFOEX osvi;
  170. osvi.dwOSVersionInfoSize = sizeof(osvi);
  171. return (GetVersionEx((OSVERSIONINFO *)&osvi) &&
  172. ((VER_NT_SERVER == osvi.wProductType) || (VER_NT_DOMAIN_CONTROLLER == osvi.wProductType)));
  173. }
  174. LONG GetStringValue(
  175. IN HKEY hkey,
  176. IN LPCWSTR pwszSubKey, OPTIONAL
  177. IN LPCWSTR pwszValue, OPTIONAL
  178. OUT LPVOID pvData, OPTIONAL
  179. OUT LPDWORD pcbData) OPTIONAL
  180. {
  181. DWORD dwType;
  182. DWORD cbData = pcbData ? *pcbData : 0;
  183. LONG lResult = SHGetValueW(hkey, pwszSubKey, pwszValue, &dwType, pvData, pcbData);
  184. if ((ERROR_SUCCESS == lResult) && (REG_SZ == dwType))
  185. {
  186. // NULL terminate this puppy...
  187. if (pvData && cbData)
  188. {
  189. WCHAR *psz = (WCHAR *)pvData;
  190. psz[(cbData / sizeof(WCHAR)) - 1] = 0;
  191. }
  192. }
  193. else
  194. {
  195. lResult = ERROR_BADKEY;
  196. }
  197. return lResult;
  198. }
  199. inline HRESULT FailedHresultFromWin32()
  200. {
  201. DWORD dwGLE = GetLastError();
  202. return (dwGLE != NOERROR) ? HRESULT_FROM_WIN32(dwGLE) : E_UNEXPECTED;
  203. }
  204. void SendChangeNotification(int csidl)
  205. {
  206. LPITEMIDLIST pidl;
  207. if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, csidl, &pidl)))
  208. {
  209. SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_IDLIST, pidl, NULL);
  210. ShellFree(pidl);
  211. }
  212. }
  213. BOOL IsNtSetupRunning()
  214. {
  215. BOOL fSetupRunning = FALSE;
  216. DWORD dwSetupRunning;
  217. DWORD cbValue = sizeof(dwSetupRunning);
  218. long lResult = SHGetValue(HKEY_LOCAL_MACHINE, L"system\\Setup", L"SystemSetupInProgress", NULL, &dwSetupRunning, &cbValue);
  219. if ((ERROR_SUCCESS == lResult) && (dwSetupRunning))
  220. {
  221. fSetupRunning = TRUE;
  222. }
  223. else
  224. {
  225. cbValue = sizeof(dwSetupRunning);
  226. lResult = SHGetValue(HKEY_LOCAL_MACHINE, L"system\\Setup", L"UpgradeInProgress", NULL, &dwSetupRunning, &cbValue);
  227. if ((ERROR_SUCCESS == lResult) && (dwSetupRunning))
  228. {
  229. fSetupRunning = TRUE;
  230. }
  231. }
  232. return fSetupRunning;
  233. }
  234. BOOL IsIgnorableClientProgram(LPCWSTR pszCurrentClient, LPCWSTR *ppszIgnoreList)
  235. {
  236. BOOL fResult = (lstrlen(pszCurrentClient) == 0);
  237. if (!fResult && (NULL != ppszIgnoreList))
  238. {
  239. while (NULL != *ppszIgnoreList)
  240. {
  241. if (0 == StrCmpI(pszCurrentClient, *ppszIgnoreList))
  242. {
  243. fResult = TRUE;
  244. break;
  245. }
  246. ppszIgnoreList++;
  247. }
  248. }
  249. return fResult;
  250. }
  251. void SetDefaultClientProgram(HKEY hkeyRoot, LPCWSTR pszClientKey, LPCWSTR pszCanonicalName, LPCWSTR *ppszIgnoreList, BOOL fShow, BOOL fForce)
  252. {
  253. HKEY hKey;
  254. LONG lResult = RegOpenKeyEx(hkeyRoot, pszClientKey, 0, KEY_QUERY_VALUE | KEY_SET_VALUE, &hKey);
  255. if (ERROR_SUCCESS == lResult)
  256. {
  257. WCHAR szCurrentClient[MAX_PATH];
  258. DWORD cbCurrentClient = sizeof(szCurrentClient);
  259. lResult = GetStringValue(hKey, NULL, NULL, szCurrentClient, &cbCurrentClient);
  260. // If we're meant to show ourselves then just show set the key
  261. if (fShow)
  262. {
  263. if (fForce ||
  264. ((ERROR_SUCCESS != lResult) || IsIgnorableClientProgram(szCurrentClient, ppszIgnoreList)))
  265. {
  266. RegSetValue(hKey, NULL, REG_SZ, pszCanonicalName, lstrlen(pszCanonicalName) * sizeof(WCHAR));
  267. }
  268. }
  269. else
  270. {
  271. // If we're meant to disappear then clear the key only if we're the one that is currently set.
  272. if (fForce || ((ERROR_SUCCESS == lResult) && (0 == StrCmpI(pszCanonicalName, szCurrentClient))))
  273. {
  274. RegSetValue(hKey, NULL, REG_SZ, L"", 0);
  275. }
  276. }
  277. RegCloseKey(hKey);
  278. }
  279. else
  280. {
  281. TraceMsg(TF_ERROR, "Error opening client key %s - 0x%08x", pszClientKey, lResult);
  282. }
  283. }
  284. BOOL IsInstalled(LPCWSTR pszComponent)
  285. {
  286. DWORD dwType;
  287. DWORD dwValue;
  288. DWORD cbValue = sizeof(dwValue);
  289. DWORD dwResult = SHGetValueW(HKEY_LOCAL_MACHINE, pszComponent, c_szIsInstalled, &dwType, &dwValue, &cbValue);
  290. BOOL fIsInstalled = ((ERROR_SUCCESS == dwResult) && (REG_DWORD == dwType) && (dwValue));
  291. return fIsInstalled;
  292. }
  293. void SetBool(LPCWSTR pszKey, LPCWSTR pszValue, BOOL fValue)
  294. {
  295. HKEY hKey;
  296. DWORD dwDisposition;
  297. LONG lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE, pszKey, 0, NULL, REG_OPTION_NON_VOLATILE,
  298. KEY_SET_VALUE, NULL, &hKey, &dwDisposition);
  299. if (ERROR_SUCCESS == lResult)
  300. {
  301. DWORD dwValue = fValue ? TRUE : FALSE;
  302. lResult = RegSetValueEx(hKey, pszValue, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue));
  303. if (ERROR_SUCCESS != lResult)
  304. {
  305. TraceMsg(TF_ERROR, "Error setting value %s - 0x%08x", pszValue, lResult);
  306. }
  307. RegCloseKey(hKey);
  308. }
  309. else
  310. {
  311. TraceMsg(TF_ERROR, "Error creating %s key - 0x%08x", pszKey, lResult);
  312. }
  313. }
  314. //Copy data from HKLM to HKCU
  315. LONG CopyRegValue(LPCWSTR pszSubKey, LPCWSTR pszValue)
  316. {
  317. HKEY hKeySrc;
  318. LONG lResult;
  319. lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszSubKey, 0, KEY_QUERY_VALUE, &hKeySrc);
  320. if (ERROR_SUCCESS == lResult)
  321. {
  322. BYTE buffer[128];
  323. DWORD dwSize = sizeof(buffer);
  324. lResult = RegQueryValueEx(hKeySrc, pszValue, NULL, NULL, (LPBYTE)buffer, &dwSize);
  325. RegCloseKey(hKeySrc);
  326. if (ERROR_SUCCESS == lResult)
  327. {
  328. HKEY hKeyDst;
  329. lResult = RegCreateKeyEx(HKEY_CURRENT_USER, pszSubKey, 0, NULL,
  330. REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKeyDst, NULL);
  331. if (ERROR_SUCCESS == lResult)
  332. {
  333. lResult = RegSetValueEx(hKeyDst, pszValue, NULL, REG_SZ, (CONST BYTE *)buffer, dwSize);
  334. }
  335. RegCloseKey(hKeyDst);
  336. }
  337. }
  338. return lResult;
  339. }
  340. void UpdateActiveSetupValues(LPCWSTR pszKeyName, BOOL fInstall)
  341. {
  342. if (fInstall)
  343. {
  344. CopyRegValue(pszKeyName, c_szLocale);
  345. CopyRegValue(pszKeyName, c_szVersion);
  346. }
  347. else
  348. {
  349. RegDeleteKey(HKEY_CURRENT_USER, pszKeyName);
  350. }
  351. }
  352. LONG GetExeAppPathWorker(LPCWSTR pszAppName, LPWSTR pszExePath, UINT cchExePath, LPCWSTR pszFmt)
  353. {
  354. WCHAR szExeKey[MAX_PATH];
  355. HKEY hKey;
  356. wnsprintf(szExeKey, ARRAYSIZE(szExeKey), pszFmt, pszAppName);
  357. LONG lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szExeKey, 0, KEY_QUERY_VALUE, &hKey);
  358. if (ERROR_SUCCESS == lResult)
  359. {
  360. LONG cbExePath = cchExePath * sizeof(WCHAR);
  361. lResult = RegQueryValue(hKey, NULL, pszExePath, &cbExePath);
  362. if (ERROR_SUCCESS != lResult)
  363. {
  364. TraceMsg(TF_ERROR, "Error querying for app path value - 0x%08x", lResult);
  365. }
  366. RegCloseKey(hKey);
  367. }
  368. return lResult;
  369. }
  370. LONG GetExeAppPath(LPCWSTR pszAppName, LPWSTR pszExePath, UINT cchExePath)
  371. {
  372. return GetExeAppPathWorker(pszAppName, pszExePath, cchExePath, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s");
  373. }
  374. #ifdef _WIN64
  375. LONG GetWow32ExeAppPath(LPCWSTR pszAppName, LPWSTR pszExePath, UINT cchExePath)
  376. {
  377. return GetExeAppPathWorker(pszAppName, pszExePath, cchExePath, L"Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s");
  378. }
  379. #endif
  380. void ShowHideFile(LPCWSTR pszFileName, BOOL fShow)
  381. {
  382. DWORD dwAttrs = GetFileAttributes(pszFileName);
  383. if (fShow)
  384. {
  385. dwAttrs &= ~(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM);
  386. }
  387. else
  388. {
  389. dwAttrs |= FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
  390. }
  391. SetFileAttributes(pszFileName, dwAttrs);
  392. }
  393. void ShowHideExe(LPCWSTR pszAppName, BOOL fShow)
  394. {
  395. WCHAR szExePath[MAX_PATH];
  396. if (ERROR_SUCCESS == GetExeAppPath(pszAppName, szExePath, ARRAYSIZE(szExePath)))
  397. {
  398. ShowHideFile(szExePath, fShow);
  399. }
  400. }
  401. #ifdef _WIN64
  402. void ShowHideWow32Exe(LPCWSTR pszAppName, BOOL fShow)
  403. {
  404. WCHAR szExePath[MAX_PATH];
  405. if (ERROR_SUCCESS == GetWow32ExeAppPath(pszAppName, szExePath, ARRAYSIZE(szExePath)))
  406. {
  407. ShowHideFile(szExePath, fShow);
  408. }
  409. }
  410. #endif
  411. void CreateShortcut(LPCWSTR pszExePath, LPWSTR pszLinkFullFilePath, int idName, int idDescription)
  412. {
  413. IShellLink *pShellLink;
  414. HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&pShellLink);
  415. if (SUCCEEDED(hr))
  416. {
  417. if (idDescription)
  418. {
  419. WCHAR szDescription[MAX_PATH];
  420. wnsprintf(szDescription, ARRAYSIZE(szDescription), L"@xpsp1res.dll,-%d", idDescription);
  421. pShellLink->SetDescription(szDescription);
  422. }
  423. pShellLink->SetWorkingDirectory(L"%HOMEDRIVE%%HOMEPATH%");
  424. if (SUCCEEDED(pShellLink->SetPath(pszExePath)))
  425. {
  426. IPersistFile *pPersistFile;
  427. if (SUCCEEDED(pShellLink->QueryInterface(IID_IPersistFile, (void **)&pPersistFile)))
  428. {
  429. if (SUCCEEDED(pPersistFile->Save(pszLinkFullFilePath, TRUE)))
  430. {
  431. SHSetLocalizedName(pszLinkFullFilePath, L"xpsp1res.dll", idName);
  432. }
  433. pPersistFile->Release();
  434. }
  435. }
  436. pShellLink->Release();
  437. }
  438. else
  439. {
  440. TraceMsg(TF_ERROR, "Couldn't create shell link object - hr = 0x%08x", hr);
  441. }
  442. }
  443. void FindAndNukeIcons(LPCWSTR pszLinkPath, LPCWSTR pszLongExePath)
  444. {
  445. WCHAR szStartDir[MAX_PATH];
  446. WCHAR szShortExePath[MAX_PATH];
  447. DWORD cch = GetShortPathName(pszLongExePath, szShortExePath, ARRAYSIZE(szShortExePath));
  448. if (!cch || (cch >= ARRAYSIZE(szShortExePath)))
  449. {
  450. szShortExePath[0] = 0;
  451. }
  452. if (GetCurrentDirectory(ARRAYSIZE(szStartDir), szStartDir))
  453. {
  454. if (SetCurrentDirectory(pszLinkPath))
  455. {
  456. WIN32_FIND_DATA fd;
  457. HANDLE hFind = FindFirstFile(L"*.lnk", &fd);
  458. if (INVALID_HANDLE_VALUE != hFind)
  459. {
  460. IShellLink *pShellLink;
  461. HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&pShellLink);
  462. if (SUCCEEDED(hr))
  463. {
  464. IPersistFile *pPersistFile;
  465. hr = pShellLink->QueryInterface(IID_IPersistFile, (void **)&pPersistFile);
  466. if (SUCCEEDED(hr))
  467. {
  468. do
  469. {
  470. WCHAR szLinkPath[MAX_PATH];
  471. WCHAR szArgs[INTERNET_MAX_PATH_LENGTH];
  472. if (SUCCEEDED(pPersistFile->Load(fd.cFileName, STGM_READ)) &&
  473. SUCCEEDED(pShellLink->GetPath(szLinkPath, ARRAYSIZE(szLinkPath), NULL, 0)) &&
  474. ((0 == StrCmpI(pszLongExePath, szLinkPath)) || (0 == StrCmpI(szShortExePath, szLinkPath))) &&
  475. SUCCEEDED(pShellLink->GetArguments(szArgs, ARRAYSIZE(szArgs))))
  476. {
  477. PathRemoveBlanks(szArgs);
  478. if (!szArgs[0])
  479. {
  480. SetFileAttributes(fd.cFileName, FILE_ATTRIBUTE_NORMAL);
  481. DeleteFile(fd.cFileName);
  482. }
  483. }
  484. }
  485. while (FindNextFile(hFind, &fd));
  486. pPersistFile->Release();
  487. }
  488. pShellLink->Release();
  489. }
  490. FindClose(hFind);
  491. }
  492. }
  493. SetCurrentDirectory(szStartDir);
  494. }
  495. }
  496. void ShowShortcut(LPCWSTR pszLinkPath, int lsn, BOOL fShow)
  497. {
  498. WCHAR szLinkFullFilePath[MAX_PATH];
  499. WCHAR szLinkFileName[MAX_PATH];
  500. szLinkFileName[0] = 0;
  501. // If we should use the localized name as the filename, then try to get it.
  502. // We should use the localized name if the install language is not USEnglish.
  503. if (LANGIDFROMLCID(GetSystemDefaultUILanguage()) != MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US))
  504. {
  505. LoadString(GetResLibInstance(), c_rglsi[lsn].idsLocalized,
  506. szLinkFileName, ARRAYSIZE(szLinkFileName));
  507. }
  508. // If we couldn't (or shouldn't) get the localized name, then
  509. // use the USEnglish name instead.
  510. if (!szLinkFileName[0])
  511. {
  512. lstrcpyn(szLinkFileName, c_rglsi[lsn].pszUSEnglish, ARRAYSIZE(szLinkFileName));
  513. }
  514. PathAddExtension(szLinkFileName, L".lnk");
  515. PathCombine(szLinkFullFilePath, pszLinkPath, szLinkFileName);
  516. WCHAR szExePath[MAX_PATH];
  517. LONG lResult;
  518. #ifdef _WIN64
  519. if (lsn == LSN_SM_IE32)
  520. {
  521. StrCpyN(szExePath, g_szIE32Path, ARRAYSIZE(szExePath));
  522. lResult = ERROR_SUCCESS;
  523. }
  524. else
  525. #endif
  526. {
  527. lResult = GetExeAppPath(c_rglsi[lsn].pszExe, szExePath, ARRAYSIZE(szExePath));
  528. }
  529. if (ERROR_SUCCESS == lResult)
  530. {
  531. if (fShow)
  532. {
  533. if (!c_rglsi[lsn].fNeverShowShortcut)
  534. {
  535. CreateShortcut(szExePath, szLinkFullFilePath, c_rglsi[lsn].idsLocalized, c_rglsi[lsn].idsDescription);
  536. }
  537. }
  538. else
  539. {
  540. FindAndNukeIcons(pszLinkPath, szExePath);
  541. }
  542. }
  543. }
  544. LONG QueryExplorerCLSIDFlags(LPCWSTR pszCLSID, DWORD *pdwFlags)
  545. {
  546. WCHAR szKeyComponent[MAX_PATH];
  547. wnsprintf(szKeyComponent, ARRAYSIZE(szKeyComponent), c_szKeyComponentFormat, pszCLSID);
  548. DWORD dwSize = sizeof(*pdwFlags);
  549. return SHGetValueW(HKEY_CURRENT_USER, szKeyComponent, c_szAttribute, NULL, pdwFlags, &dwSize);
  550. }
  551. void SetExplorerCLSIDFlags(LPCWSTR pszCLSID, DWORD dwAndFlags, DWORD dwOrFlags)
  552. {
  553. DWORD dwFlags = 0;
  554. WCHAR szKeyComponent[MAX_PATH];
  555. wnsprintf(szKeyComponent, ARRAYSIZE(szKeyComponent), c_szKeyComponentFormat, pszCLSID);
  556. DWORD dwSize = sizeof(dwFlags);
  557. SHGetValueW(HKEY_CURRENT_USER, szKeyComponent, c_szAttribute, NULL, &dwFlags, &dwSize);
  558. dwFlags &= dwAndFlags;
  559. dwFlags |= dwOrFlags;
  560. SHSetValue(HKEY_CURRENT_USER, szKeyComponent, c_szAttribute, REG_DWORD, &dwFlags, sizeof(dwFlags));
  561. }
  562. void NukeFiles(LPCWSTR pszPath, LPCWSTR pszFileSpec)
  563. {
  564. WCHAR szStartDir[MAX_PATH];
  565. if (GetCurrentDirectory(ARRAYSIZE(szStartDir), szStartDir))
  566. {
  567. if (SetCurrentDirectory(pszPath))
  568. {
  569. WIN32_FIND_DATA fd;
  570. HANDLE hFind = FindFirstFile(pszFileSpec, &fd);
  571. if (INVALID_HANDLE_VALUE != hFind)
  572. {
  573. do
  574. {
  575. SetFileAttributes(fd.cFileName, FILE_ATTRIBUTE_NORMAL);
  576. DeleteFile(fd.cFileName);
  577. }
  578. while (FindNextFile(hFind, &fd));
  579. FindClose(hFind);
  580. }
  581. }
  582. SetCurrentDirectory(szStartDir);
  583. }
  584. }
  585. void NukeDesktopCleanupIcons()
  586. {
  587. WCHAR szPath[MAX_PATH];
  588. HINSTANCE hInstCleaner = LoadLibraryEx(L"fldrclnr.dll", NULL, LOAD_LIBRARY_AS_DATAFILE);
  589. WCHAR szUnusedShortcutFolder[MAX_PATH];
  590. // From nt\shell\applets\cleanup\fldrclnr\resource.h:
  591. #define IDS_ARCHIVEFOLDER 8
  592. #define IDS_ARCHIVEFOLDER_FIRSTBOOT 15
  593. // From nt\shell\applets\cleanup\fldrclnr\cleanupwiz.h:
  594. #define REGSTR_OEM_PATH REGSTR_PATH_SETUP TEXT("\\OemStartMenuData")
  595. #define REGSTR_OEM_TITLEVAL TEXT("DesktopShortcutsFolderName")
  596. if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_DESKTOPDIRECTORY, FALSE))
  597. {
  598. NukeFiles(szPath, L"*.{871C5380-42A0-1069-A2EA-08002B30309D}");
  599. if (hInstCleaner &&
  600. LoadString(hInstCleaner, IDS_ARCHIVEFOLDER, szUnusedShortcutFolder, ARRAYSIZE(szUnusedShortcutFolder)))
  601. {
  602. PathAppend(szPath, szUnusedShortcutFolder);
  603. NukeFiles(szPath, L"*.{871C5380-42A0-1069-A2EA-08002B30309D}");
  604. }
  605. }
  606. DWORD cb = sizeof(szUnusedShortcutFolder);
  607. DWORD dwType;
  608. // Get the folder name from either the registry or fldrclnr.dll and get the startmenu\programs folder
  609. if (
  610. (
  611. (ERROR_SUCCESS == SHGetValue(HKEY_LOCAL_MACHINE, REGSTR_OEM_PATH, REGSTR_OEM_TITLEVAL, &dwType, szUnusedShortcutFolder, &cb))
  612. ||
  613. (hInstCleaner && LoadString(hInstCleaner, IDS_ARCHIVEFOLDER_FIRSTBOOT, szUnusedShortcutFolder, ARRAYSIZE(szUnusedShortcutFolder)))
  614. )
  615. &&
  616. SHGetSpecialFolderPath(NULL, szPath, CSIDL_PROGRAMS, FALSE)
  617. )
  618. {
  619. PathAppend(szPath, szUnusedShortcutFolder);
  620. NukeFiles(szPath, L"*.{871C5380-42A0-1069-A2EA-08002B30309D}");
  621. }
  622. if (hInstCleaner)
  623. {
  624. FreeLibrary(hInstCleaner);
  625. }
  626. }
  627. void RemoveIcons(int lsn, int *pcsidlList, DWORD nEntries)
  628. {
  629. for (DWORD i = 0; i < nEntries; i++)
  630. {
  631. WCHAR szPath[MAX_PATH];
  632. if (SHGetSpecialFolderPath(NULL, szPath, pcsidlList[i], FALSE))
  633. {
  634. ShowShortcut(szPath, lsn, FALSE);
  635. }
  636. }
  637. }
  638. void RemoveAnAnnoyingIESubFolderIcon(int csidl)
  639. {
  640. WCHAR szPath[MAX_PATH];
  641. if (SHGetSpecialFolderPath(NULL, szPath, csidl, FALSE))
  642. {
  643. WCHAR szIEFolder[MAX_PATH];
  644. PathCombine(szIEFolder, szPath, L"Internet Explorer");
  645. ShowShortcut(szIEFolder, LSN_NOSHOW_IE, FALSE);
  646. WCHAR szLocalizedName[MAX_PATH];
  647. LoadString(GetResLibInstance(), IDS_OC_IESHORTCUTNAME_SM, szLocalizedName, ARRAYSIZE(szLocalizedName));
  648. PathRemoveExtension(szLocalizedName);
  649. PathCombine(szIEFolder, szPath, szLocalizedName);
  650. ShowShortcut(szIEFolder, LSN_NOSHOW_IE, FALSE);
  651. LoadString(GetResLibInstance(), IDS_OC_IESHORTCUTNAME_QL, szLocalizedName, ARRAYSIZE(szLocalizedName));
  652. PathRemoveExtension(szLocalizedName);
  653. PathCombine(szIEFolder, szPath, szLocalizedName);
  654. ShowShortcut(szIEFolder, LSN_NOSHOW_IE, FALSE);
  655. }
  656. }
  657. void RemoveAnnoyingIESubFolderIcons()
  658. {
  659. RemoveAnAnnoyingIESubFolderIcon(CSIDL_PROGRAMS);
  660. RemoveAnAnnoyingIESubFolderIcon(CSIDL_COMMON_PROGRAMS);
  661. }
  662. void ShowIEDesktopIcon(BOOL fShow)
  663. {
  664. if (fShow)
  665. {
  666. SetExplorerCLSIDFlags(c_szIEDesktopCLSID, ~SFGAO_NONENUMERATED, 0);
  667. }
  668. else
  669. {
  670. NukeDesktopCleanupIcons();
  671. SetExplorerCLSIDFlags(c_szIEDesktopCLSID, 0xffffffff, SFGAO_NONENUMERATED);
  672. }
  673. SendChangeNotification(CSIDL_DESKTOP);
  674. SendChangeNotification(CSIDL_DESKTOPDIRECTORY);
  675. }
  676. // Ensure a handler is in place for all the important things
  677. void FixupIEAssociations(BOOL fForceAssociations)
  678. {
  679. // In order for shdocvw to do its magic, IEXPLORE.EXE must be properly
  680. // registered. Setup runs OC Manager before it runs IE.INF, so don't
  681. // call shdocvw to try to do something he can't do. (He'll assert if
  682. // you try.)
  683. HKEY hk;
  684. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\IEXPLORE.EXE"),
  685. 0, KEY_READ, &hk) != ERROR_SUCCESS)
  686. {
  687. // ie.inf hasn't run yet - shdocvw can't do its thing
  688. return;
  689. }
  690. RegCloseKey(hk);
  691. // Shdocvw does a pretty good job of this, let's give him a crack at it
  692. HINSTANCE hinst = LoadLibrary(L"shdocvw.dll");
  693. if (NULL != hinst)
  694. {
  695. typedef HRESULT (WINAPI *DLLINSTALL)(BOOL bInstall, LPCWSTR pszCmdLine);
  696. DLLINSTALL pfnDllInstall = (DLLINSTALL)GetProcAddress(hinst, "DllInstall");
  697. if (pfnDllInstall)
  698. {
  699. pfnDllInstall(TRUE, (fForceAssociations ? L"ForceAssoc" : L""));
  700. }
  701. else
  702. {
  703. TraceMsg(TF_ERROR, "Error getting DllInstall entry point - GLE = 0x%08x", GetLastError());
  704. }
  705. FreeLibrary(hinst);
  706. }
  707. else
  708. {
  709. TraceMsg(TF_ERROR, "Error loading shdocvw - GLE = 0x%08x", GetLastError());
  710. }
  711. }
  712. // This will create or delete shortcuts in Start Menu\Programs and the Quick Launch bar
  713. void ShowUserShortcuts(int lsnSM, int lsnQL, BOOL fShow)
  714. {
  715. WCHAR szPath[MAX_PATH];
  716. if (lsnSM >= 0 && SHGetSpecialFolderPath(NULL, szPath, CSIDL_PROGRAMS, fShow))
  717. {
  718. ShowShortcut(szPath, lsnSM, fShow);
  719. }
  720. if (lsnQL >= 0 && SHGetSpecialFolderPath(NULL, szPath, CSIDL_APPDATA, fShow))
  721. {
  722. WCHAR szQuickLaunchPath[MAX_PATH];
  723. LoadString(GetResLibInstance(), IDS_OC_QLAUNCHAPPDATAPATH, szQuickLaunchPath, ARRAYSIZE(szQuickLaunchPath));
  724. PathAppend(szPath, szQuickLaunchPath);
  725. // In case we're the first ones through, create the Quick Launch dir
  726. CreateDirectory(szPath, NULL);
  727. ShowShortcut(szPath, lsnQL, fShow);
  728. }
  729. }
  730. // Internet Explorer optional component goo
  731. void UserConfigIE()
  732. {
  733. BOOL fIsInstalled = IsInstalled(c_szIEAccessKey);
  734. ShowIEDesktopIcon(fIsInstalled);
  735. ShowUserShortcuts(LSN_SM_IE, LSN_QL_IE, fIsInstalled);
  736. #ifdef _WIN64
  737. WCHAR szLinkDir[MAX_PATH];
  738. if (SHGetSpecialFolderPath(NULL, szLinkDir, CSIDL_PROGRAMS, fIsInstalled))
  739. {
  740. WCHAR szExePath[MAX_PATH];
  741. if (SHGetSpecialFolderPath(NULL, szExePath, CSIDL_PROGRAM_FILESX86, FALSE))
  742. {
  743. PathCombine(g_szIE32Path, szExePath, L"Internet Explorer\\iexplore.exe");
  744. ShowShortcut(szLinkDir, LSN_SM_IE32, fIsInstalled);
  745. }
  746. }
  747. #endif
  748. if (!fIsInstalled)
  749. {
  750. int csidlList[] = { CSIDL_DESKTOPDIRECTORY, CSIDL_COMMON_DESKTOPDIRECTORY, CSIDL_COMMON_PROGRAMS };
  751. RemoveIcons(LSN_NOSHOW_IE, csidlList, ARRAYSIZE(csidlList));
  752. RemoveAnnoyingIESubFolderIcons();
  753. }
  754. SHSendMessageBroadcast(WM_SETTINGCHANGE, 0, (LPARAM)L"Software\\Clients\\StartMenuInternet");
  755. }
  756. void SetIEShowHideFlags(BOOL fShow)
  757. {
  758. SetBool(c_szIEAccessKey, c_szIsInstalled, fShow);
  759. SetBool(c_szIEInstallInfoKey, c_szIconsVisible, fShow);
  760. SetBool(c_szOCManagerSubComponents, c_szIEAccess, fShow);
  761. }
  762. void ShowHideIE(BOOL fShow, BOOL fForceAssociations, BOOL fNonUpdateInstall)
  763. {
  764. SetIEShowHideFlags(fShow);
  765. if (fShow)
  766. {
  767. if (fNonUpdateInstall)
  768. {
  769. FixupIEAssociations(fForceAssociations);
  770. }
  771. SetDefaultClientProgram(HKEY_LOCAL_MACHINE, c_szStartMenuInternetClientKey, c_szIECanonicalName, NULL, TRUE, fForceAssociations);
  772. }
  773. else
  774. {
  775. SetDefaultClientProgram(HKEY_LOCAL_MACHINE, c_szStartMenuInternetClientKey, c_szIECanonicalName, NULL, FALSE, FALSE);
  776. int csidlList[] = { CSIDL_COMMON_DESKTOPDIRECTORY, CSIDL_COMMON_PROGRAMS };
  777. RemoveIcons(LSN_NOSHOW_IE, csidlList, ARRAYSIZE(csidlList));
  778. RemoveAnAnnoyingIESubFolderIcon(CSIDL_COMMON_PROGRAMS);
  779. }
  780. if (fNonUpdateInstall && !IsNtSetupRunning())
  781. {
  782. SetDefaultClientProgram(HKEY_CURRENT_USER, c_szStartMenuInternetClientKey, c_szIECanonicalName, NULL, FALSE, fShow);
  783. UserConfigIE();
  784. UpdateActiveSetupValues(c_szIEAccessKey, fShow);
  785. SendChangeNotification(CSIDL_DESKTOP);
  786. }
  787. else
  788. {
  789. SHSendMessageBroadcast(WM_SETTINGCHANGE, 0, (LPARAM)L"Software\\Clients\\StartMenuInternet");
  790. }
  791. ShowHideExe(c_szIEApp, fShow);
  792. #ifdef _WIN64
  793. ShowHideWow32Exe(c_szIEApp, fShow);
  794. #endif
  795. }
  796. // Outlook Express optional component goo
  797. void UserConfigOE()
  798. {
  799. BOOL fIsInstalled = IsInstalled(c_szOEAccessKey);
  800. ShowUserShortcuts(LSN_SM_OE, LSN_QL_OE, fIsInstalled);
  801. SHSendMessageBroadcastW(WM_WININICHANGE, 0, (LPARAM)REGSTR_PATH_MAILCLIENTS);
  802. if (!fIsInstalled)
  803. {
  804. // ShowUserShortcuts(fInstalled=FALSE) already cleaned up any
  805. // old OE Quick Launch shortcuts, so all that's left to remove
  806. // is the desktop icon
  807. int csidlList[] = { CSIDL_DESKTOPDIRECTORY, CSIDL_COMMON_DESKTOPDIRECTORY, CSIDL_COMMON_PROGRAMS };
  808. RemoveIcons(LSN_NOSHOW_OE, csidlList, ARRAYSIZE(csidlList));
  809. }
  810. }
  811. void SetOEShowHideFlags(BOOL fShow)
  812. {
  813. SetBool(c_szOEAccessKey, c_szIsInstalled, fShow);
  814. SetBool(c_szOEInstallInfoKey, c_szIconsVisible, fShow);
  815. SetBool(c_szOCManagerSubComponents, c_szOEAccess, fShow);
  816. }
  817. void FixupOEAssociations(BOOL fForceAssociations, LPCWSTR *ppszIgnoreList)
  818. {
  819. if (!IsNtSetupRunning())
  820. {
  821. long lResult;
  822. if (!fForceAssociations)
  823. {
  824. WCHAR szValue[MAX_PATH];
  825. DWORD cbValue = sizeof(szValue);
  826. DWORD dwType;
  827. lResult = SHGetValueW(HKEY_CLASSES_ROOT, L"mailto\\shell\\open\\command", NULL, &dwType, szValue, &cbValue);
  828. if ((REG_SZ == dwType) &&
  829. ((ERROR_MORE_DATA == lResult) || ((ERROR_SUCCESS == lResult) && (cbValue >= (2 * sizeof(WCHAR))))))
  830. {
  831. // Some sort of valid string data at least character in length -- see if it's one we should stomp,
  832. // otherwise leave it alone
  833. if (NULL != ppszIgnoreList)
  834. {
  835. while (NULL != *ppszIgnoreList)
  836. {
  837. if (NULL != StrStrIW(szValue, *ppszIgnoreList))
  838. {
  839. fForceAssociations = TRUE;
  840. break;
  841. }
  842. ppszIgnoreList++;
  843. }
  844. }
  845. }
  846. else
  847. {
  848. // Either it's not a string or it's zero length
  849. fForceAssociations = TRUE;
  850. }
  851. }
  852. if (fForceAssociations)
  853. {
  854. HKEY hkey;
  855. DWORD dwDisposition;
  856. SHDeleteKey(HKEY_CLASSES_ROOT, L"mailto");
  857. lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, L"mailto", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE,
  858. NULL, &hkey, &dwDisposition);
  859. if (ERROR_SUCCESS == lResult)
  860. {
  861. SHCopyKey(HKEY_LOCAL_MACHINE, L"Software\\Clients\\Mail\\Outlook Express\\Protocols\\mailto", hkey, 0);
  862. RegCloseKey(hkey);
  863. }
  864. }
  865. }
  866. }
  867. void ShowHideOE(BOOL fShow, BOOL fForceAssociations, BOOL fNonUpdateInstall)
  868. {
  869. if (!IsServer())
  870. {
  871. static LPCWSTR ppszIgnoreClientsNormal[] = { c_szIMN, c_szNTOS, NULL };
  872. static LPCWSTR ppszIgnoreClientsSetup[] = { c_szIMN, c_szNTOS, c_szHotmail, NULL };
  873. LPCWSTR *ppszIgnoreClients = !IsNtSetupRunning() ? ppszIgnoreClientsNormal : ppszIgnoreClientsSetup;
  874. static LPCWSTR ppszIgnoreMailto[] = { c_szUrlDll, c_szMailNewsDll, NULL };
  875. SetOEShowHideFlags(fShow);
  876. if (fShow)
  877. {
  878. FixupOEAssociations(fForceAssociations, ppszIgnoreMailto);
  879. SetDefaultClientProgram(HKEY_LOCAL_MACHINE, c_szMailClientKey, c_szOECanonicalName, ppszIgnoreClients, TRUE, fForceAssociations);
  880. #ifdef _WIN64
  881. SetDefaultClientProgram(HKEY_LOCAL_MACHINE, c_szMailClientKeyWOW32, c_szOECanonicalName, ppszIgnoreClients, TRUE, fForceAssociations);
  882. #endif
  883. }
  884. else
  885. {
  886. FixupOEAssociations(FALSE, ppszIgnoreMailto);
  887. int csidlList[] = { CSIDL_COMMON_DESKTOPDIRECTORY, CSIDL_COMMON_PROGRAMS };
  888. RemoveIcons(LSN_NOSHOW_OE, csidlList, ARRAYSIZE(csidlList));
  889. SetDefaultClientProgram(HKEY_LOCAL_MACHINE, c_szMailClientKey, c_szOECanonicalName, ppszIgnoreClients, FALSE, FALSE);
  890. #ifdef _WIN64
  891. SetDefaultClientProgram(HKEY_LOCAL_MACHINE, c_szMailClientKeyWOW32, c_szOECanonicalName, ppszIgnoreClients, FALSE, FALSE);
  892. #endif
  893. }
  894. if (fNonUpdateInstall && !IsNtSetupRunning())
  895. {
  896. SetDefaultClientProgram(HKEY_CURRENT_USER, c_szMailClientKey, c_szOECanonicalName, ppszIgnoreClients, FALSE, fShow);
  897. UserConfigOE();
  898. UpdateActiveSetupValues(c_szOEAccessKey, fShow);
  899. SendChangeNotification(CSIDL_DESKTOP);
  900. }
  901. else
  902. {
  903. SHSendMessageBroadcastW(WM_WININICHANGE, 0, (LPARAM)REGSTR_PATH_MAILCLIENTS);
  904. }
  905. }
  906. ShowHideExe(c_szOEApp, fShow);
  907. #ifdef _WIN64
  908. ShowHideWow32Exe(c_szOEApp, fShow);
  909. #endif
  910. }
  911. HRESULT CallRegisterServer(LPCWSTR pszModule, BOOL fRegister)
  912. {
  913. HRESULT hr;
  914. HINSTANCE hinst = LoadLibrary(pszModule);
  915. if (NULL != hinst)
  916. {
  917. typedef HRESULT (WINAPI *DLLREGISTERSERVER)();
  918. LPCSTR pszRegFuncName = fRegister ? "DllRegisterServer" : "DllUnregisterServer";
  919. DLLREGISTERSERVER pfnDllRegisterServer = (DLLREGISTERSERVER)GetProcAddress(hinst, pszRegFuncName);
  920. if (pfnDllRegisterServer)
  921. {
  922. hr = pfnDllRegisterServer();
  923. }
  924. else
  925. {
  926. TraceMsg(TF_ERROR, "Error getting DllRegisterServer entry point - GLE = 0x%08x", GetLastError());
  927. hr = FailedHresultFromWin32();
  928. }
  929. FreeLibrary(hinst);
  930. }
  931. else
  932. {
  933. TraceMsg(TF_ERROR, "Error loading %s - GLE = 0x%08x", pszModule, GetLastError());
  934. hr = FailedHresultFromWin32();
  935. }
  936. return hr;
  937. }
  938. void ReinstallVM()
  939. {
  940. #if 0
  941. SHDeleteKey(HKEY_CLASSES_ROOT, c_szJavaVMKey);
  942. CallRegisterServer(L"msjava.dll", TRUE);
  943. #endif
  944. }
  945. void FixupMailClientKey()
  946. {
  947. SHSetValueW(HKEY_LOCAL_MACHINE, c_szOEInstallInfoKey, c_szReinstallCommand, REG_EXPAND_SZ, c_szReinstallCommandOE, sizeof(c_szReinstallCommandOE));
  948. SHSetValueW(HKEY_LOCAL_MACHINE, c_szOEInstallInfoKey, c_szHideIconsCommand, REG_EXPAND_SZ, c_szHideIconsCommandOE, sizeof(c_szHideIconsCommandOE));
  949. SHSetValueW(HKEY_LOCAL_MACHINE, c_szOEInstallInfoKey, c_szShowIconsCommand, REG_EXPAND_SZ, c_szShowIconsCommandOE, sizeof(c_szShowIconsCommandOE));
  950. SetBool(c_szOEInstallInfoKey, c_szIconsVisible, IsInstalled(c_szOEAccessKey));
  951. }
  952. extern "C" void FixupOptionalComponents()
  953. {
  954. // Need to do this here since the app paths weren't set during setup.
  955. ShowHideExe(c_szIEApp, IsInstalled(c_szIEAccessKey));
  956. ShowHideExe(c_szOEApp, IsInstalled(c_szOEAccessKey));
  957. #ifdef _WIN64
  958. ShowHideWow32Exe(c_szIEApp, IsInstalled(c_szIEAccessKey));
  959. ShowHideWow32Exe(c_szOEApp, IsInstalled(c_szOEAccessKey));
  960. #endif
  961. // OE likes to nuke the whole branch and start from scratch.
  962. FixupMailClientKey();
  963. }
  964. #define FC_QUICKLAUNCH 0x00000001
  965. #define FC_ALLPROGRAMS 0x00000002
  966. #define FC_DESKTOP 0x00000004
  967. #define FC_EXPLORERCLSID 0x00000008
  968. #define FC_MAX 0x00000008
  969. struct SHORTCUTFINDENTRY
  970. {
  971. LPCTSTR pszExe;
  972. LPCTSTR pszExplorerCLSID;
  973. DWORD dwFoldersToCheck;
  974. DWORD dwFoldersToRecurseCheck;
  975. };
  976. SHORTCUTFINDENTRY scfEntries[] =
  977. {
  978. { c_szIEApp, c_szIEDesktopCLSID, FC_QUICKLAUNCH | FC_ALLPROGRAMS | FC_EXPLORERCLSID, 0 },
  979. { c_szOEApp, NULL, FC_QUICKLAUNCH | FC_ALLPROGRAMS, 0 },
  980. { c_szWMP, NULL, FC_QUICKLAUNCH | FC_ALLPROGRAMS, FC_ALLPROGRAMS },
  981. { c_szMessenger, NULL, FC_QUICKLAUNCH | FC_ALLPROGRAMS, FC_ALLPROGRAMS },
  982. };
  983. HRESULT FindAnyIcons(LPCWSTR pszLinkPath, LPCWSTR pszLongExePath, BOOL fRecurse, BOOL *pfFound)
  984. {
  985. // Pretty straightforward here. Loop through all the .lnk files in a directory and see if we
  986. // find a shortcut pointing to the EXE in question. This function will also recurse if asked.
  987. WCHAR szStartDir[MAX_PATH];
  988. HRESULT hr = E_FAIL;
  989. *pfFound = FALSE;
  990. WCHAR szShortExePath[MAX_PATH];
  991. DWORD cch = GetShortPathName(pszLongExePath, szShortExePath, ARRAYSIZE(szShortExePath));
  992. if (!cch || (cch >= ARRAYSIZE(szShortExePath)))
  993. {
  994. szShortExePath[0] = 0;
  995. }
  996. if (GetCurrentDirectory(ARRAYSIZE(szStartDir), szStartDir))
  997. {
  998. if (SetCurrentDirectory(pszLinkPath))
  999. {
  1000. WIN32_FIND_DATA fd;
  1001. HANDLE hFind = FindFirstFile(fRecurse ? L"*" : L"*.lnk", &fd);
  1002. if (INVALID_HANDLE_VALUE != hFind)
  1003. {
  1004. IShellLink *pShellLink;
  1005. hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&pShellLink);
  1006. if (SUCCEEDED(hr))
  1007. {
  1008. IPersistFile *pPersistFile;
  1009. hr = pShellLink->QueryInterface(IID_IPersistFile, (void **)&pPersistFile);
  1010. if (SUCCEEDED(hr))
  1011. {
  1012. do
  1013. {
  1014. if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  1015. {
  1016. if ((0 != StrCmpI(fd.cFileName, L".")) && (0 != StrCmpI(fd.cFileName, L"..")) && fRecurse)
  1017. {
  1018. hr = FindAnyIcons(fd.cFileName, pszLongExePath, fRecurse, pfFound);
  1019. }
  1020. }
  1021. else if (0 == StrCmpIC(PathFindExtension(fd.cFileName), L".lnk"))
  1022. {
  1023. WCHAR szLinkPath[MAX_PATH];
  1024. if (SUCCEEDED(pPersistFile->Load(fd.cFileName, STGM_READ)) &&
  1025. SUCCEEDED(pShellLink->GetPath(szLinkPath, ARRAYSIZE(szLinkPath), NULL, 0)) &&
  1026. ((0 == StrCmpI(pszLongExePath, szLinkPath)) || (0 == StrCmpI(szShortExePath, szLinkPath))))
  1027. {
  1028. *pfFound = TRUE;
  1029. }
  1030. }
  1031. }
  1032. while (SUCCEEDED(hr) && (FALSE == *pfFound) && FindNextFile(hFind, &fd));
  1033. pPersistFile->Release();
  1034. }
  1035. pShellLink->Release();
  1036. }
  1037. FindClose(hFind);
  1038. }
  1039. }
  1040. SetCurrentDirectory(szStartDir);
  1041. }
  1042. return hr;
  1043. }
  1044. void GetCurrentIconInvisibility()
  1045. {
  1046. // Loop through our list of "interesting" .EXEs. For each one, look in "interesting" places to see if
  1047. // the shortcut is NOT present. If the shortcut is missing, then presumably the user did this on purpose.
  1048. // The problem is that a bunch of per-user install stubs will get rerun after an SP and recreate the
  1049. // shortcuts. This is a no-no.
  1050. for (int i = 0; i < ARRAYSIZE(scfEntries); i++)
  1051. {
  1052. WCHAR szExePath[MAX_PATH];
  1053. if (ERROR_SUCCESS == GetExeAppPath(scfEntries[i].pszExe, szExePath, ARRAYSIZE(szExePath)))
  1054. {
  1055. DWORD dwInitiallyClear = 0;
  1056. // Loop through each of the bits, look to see if the icon is NOT there. If it's not there, then
  1057. // we'll set that bit in dwInitiallyClear.
  1058. //
  1059. // Note that we err on the side of leaving the bit unset so in failure cases we may allow an icon
  1060. // to be recreated -- this is generally a better approach since most of the time the icons will
  1061. // not be deleted.
  1062. for (DWORD dwFolderClass = FC_QUICKLAUNCH; dwFolderClass <= FC_MAX; dwFolderClass <<= 1)
  1063. {
  1064. if (dwFolderClass & scfEntries[i].dwFoldersToCheck)
  1065. {
  1066. if (FC_EXPLORERCLSID != dwFolderClass)
  1067. {
  1068. HRESULT hr = E_FAIL;
  1069. WCHAR szPath[MAX_PATH];
  1070. switch (dwFolderClass)
  1071. {
  1072. case FC_QUICKLAUNCH:
  1073. if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_APPDATA, FALSE))
  1074. {
  1075. WCHAR szQuickLaunchPath[MAX_PATH];
  1076. LoadString(GetResLibInstance(), IDS_OC_QLAUNCHAPPDATAPATH, szQuickLaunchPath, ARRAYSIZE(szQuickLaunchPath));
  1077. PathAppend(szPath, szQuickLaunchPath);
  1078. hr = S_OK;
  1079. }
  1080. break;
  1081. case FC_ALLPROGRAMS:
  1082. hr = SHGetSpecialFolderPath(NULL, szPath, CSIDL_PROGRAMS, FALSE) ? S_OK : E_FAIL;
  1083. break;
  1084. case FC_DESKTOP:
  1085. hr = SHGetSpecialFolderPath(NULL, szPath, CSIDL_DESKTOPDIRECTORY, FALSE) ? S_OK : E_FAIL;
  1086. break;
  1087. default:
  1088. hr = E_UNEXPECTED;
  1089. break;
  1090. }
  1091. if (SUCCEEDED(hr))
  1092. {
  1093. BOOL fFound;
  1094. hr = FindAnyIcons(szPath, szExePath,
  1095. dwFolderClass & scfEntries[i].dwFoldersToRecurseCheck, &fFound);
  1096. if (SUCCEEDED(hr) && !fFound)
  1097. {
  1098. dwInitiallyClear |= dwFolderClass;
  1099. }
  1100. }
  1101. }
  1102. else
  1103. {
  1104. // This will only work for the currently logged in user...
  1105. DWORD dwFlags;
  1106. ASSERT(NULL != scfEntries[i].pszExplorerCLSID);
  1107. if (ERROR_SUCCESS == QueryExplorerCLSIDFlags(scfEntries[i].pszExplorerCLSID, &dwFlags))
  1108. {
  1109. if (dwFlags & SFGAO_NONENUMERATED)
  1110. {
  1111. dwInitiallyClear |= FC_EXPLORERCLSID;
  1112. }
  1113. }
  1114. }
  1115. }
  1116. }
  1117. // Only record a value for this app if there is a shortcut missing...
  1118. if (dwInitiallyClear)
  1119. {
  1120. SHSetValue(HKEY_CURRENT_USER, c_szInitiallyClearKey, scfEntries[i].pszExe, REG_DWORD, &dwInitiallyClear, sizeof(dwInitiallyClear));
  1121. }
  1122. }
  1123. }
  1124. }
  1125. extern "C" void OCInstallUpdate()
  1126. {
  1127. DWORD dwType;
  1128. DWORD dwValue;
  1129. DWORD cbValue = sizeof(dwValue);
  1130. DWORD dwResult = SHGetValueW(HKEY_LOCAL_MACHINE, c_szOCManagerSubComponents, c_szIEAccess, &dwType, &dwValue, &cbValue);
  1131. BOOL fIEAccessIsOn = ((ERROR_SUCCESS == dwResult) && (REG_DWORD == dwType) && (dwValue));
  1132. ShowHideIE(fIEAccessIsOn, FALSE, FALSE);
  1133. // If IE is on, then we go ahead and write the active setup values in case the IE version is not updated as well.
  1134. // This way we don't recreate icons for this user when there is no change to IE.
  1135. if (fIEAccessIsOn)
  1136. {
  1137. UpdateActiveSetupValues(c_szIEAccessKey, TRUE);
  1138. }
  1139. cbValue = sizeof(dwValue);
  1140. dwResult = SHGetValueW(HKEY_LOCAL_MACHINE, c_szOCManagerSubComponents, c_szOEAccess, &dwType, &dwValue, &cbValue);
  1141. BOOL fOEAccessIsOn = TRUE;
  1142. if ((ERROR_SUCCESS == dwResult) && (REG_DWORD == dwType) && !dwValue)
  1143. {
  1144. fOEAccessIsOn = FALSE;
  1145. }
  1146. ShowHideOE(fOEAccessIsOn, FALSE, FALSE);
  1147. // If OE is on, then we go ahead and write the active setup values in case the OE version is not updated as well.
  1148. // This way we don't recreate icons for this user when there is no change to OE.
  1149. if (fOEAccessIsOn)
  1150. {
  1151. UpdateActiveSetupValues(c_szOEAccessKey, TRUE);
  1152. }
  1153. GetCurrentIconInvisibility();
  1154. }
  1155. extern "C" void OCInstallCleanupInitiallyClear()
  1156. {
  1157. HKEY hKey;
  1158. // This code runs through and sees if we need to delete any shortcuts that were created by an SP update install
  1159. // that the user had previously deleted. The idea is that we shouldn't be recreating them.
  1160. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, c_szInitiallyClearKey, 0, KEY_QUERY_VALUE, &hKey))
  1161. {
  1162. int nRegEnum = 0;
  1163. while (1)
  1164. {
  1165. WCHAR szExe[MAX_PATH];
  1166. DWORD cchExe = ARRAYSIZE(szExe);
  1167. DWORD dwType;
  1168. DWORD dwFlags;
  1169. DWORD cbFlags = sizeof(dwFlags);
  1170. LONG lResult = RegEnumValue(hKey, nRegEnum, szExe, &cchExe, NULL, &dwType, (LPBYTE)&dwFlags, &cbFlags);
  1171. if (ERROR_NO_MORE_ITEMS == lResult)
  1172. {
  1173. break;
  1174. }
  1175. else if ((ERROR_SUCCESS == lResult) && (REG_DWORD == dwType))
  1176. {
  1177. WCHAR szExePath[MAX_PATH];
  1178. if (ERROR_SUCCESS == GetExeAppPath(szExe, szExePath, ARRAYSIZE(szExePath)))
  1179. {
  1180. // Once we have the EXE, loop through each bit and see if it was initially clear (meaning
  1181. // the shorcut was not present before update ran).
  1182. for (DWORD dwFolderClass = FC_QUICKLAUNCH; dwFolderClass <= FC_MAX; dwFolderClass <<= 1)
  1183. {
  1184. if (dwFlags & dwFolderClass)
  1185. {
  1186. if (FC_EXPLORERCLSID != dwFolderClass)
  1187. {
  1188. HRESULT hr = E_FAIL;
  1189. WCHAR szPath[MAX_PATH];
  1190. switch (dwFolderClass)
  1191. {
  1192. case FC_QUICKLAUNCH:
  1193. if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_APPDATA, FALSE))
  1194. {
  1195. WCHAR szQuickLaunchPath[MAX_PATH];
  1196. LoadString(GetResLibInstance(), IDS_OC_QLAUNCHAPPDATAPATH, szQuickLaunchPath, ARRAYSIZE(szQuickLaunchPath));
  1197. PathAppend(szPath, szQuickLaunchPath);
  1198. hr = S_OK;
  1199. }
  1200. break;
  1201. case FC_ALLPROGRAMS:
  1202. hr = SHGetSpecialFolderPath(NULL, szPath, CSIDL_PROGRAMS, FALSE) ? S_OK : E_FAIL;
  1203. break;
  1204. case FC_DESKTOP:
  1205. hr = SHGetSpecialFolderPath(NULL, szPath, CSIDL_DESKTOPDIRECTORY, FALSE) ? S_OK : E_FAIL;
  1206. break;
  1207. default:
  1208. hr = E_UNEXPECTED;
  1209. break;
  1210. }
  1211. if (SUCCEEDED(hr))
  1212. {
  1213. FindAndNukeIcons(szPath, szExePath);
  1214. }
  1215. }
  1216. else
  1217. {
  1218. // need to grovel for the CLSID in this case.
  1219. for (int i = 0; i < ARRAYSIZE(scfEntries); i++)
  1220. {
  1221. if (0 == StrCmpI(szExe, scfEntries[i].pszExe))
  1222. {
  1223. SetExplorerCLSIDFlags(scfEntries[i].pszExplorerCLSID, 0xffffffff, SFGAO_NONENUMERATED);
  1224. break;
  1225. }
  1226. }
  1227. }
  1228. }
  1229. }
  1230. }
  1231. }
  1232. nRegEnum++;
  1233. }
  1234. RegCloseKey(hKey);
  1235. }
  1236. // This makes sure that we only get called once.
  1237. SHDeleteKey(HKEY_CURRENT_USER, c_szInitiallyClearKey);
  1238. }