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.

1153 lines
35 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 <regstr.h>
  12. #include "shmgdefs.h"
  13. #include "res.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_szIECanonicalName[] = L"IEXPLORE.EXE";
  18. const WCHAR c_szOECanonicalName[] = L"Outlook Express";
  19. #ifndef INTERNET_MAX_PATH_LENGTH
  20. #define INTERNET_MAX_PATH_LENGTH 2048
  21. #endif
  22. #ifdef _TNOONAN_TEST_WIN64
  23. #define _WIN64
  24. #undef CSIDL_PROGRAM_FILESX86
  25. #define CSIDL_PROGRAM_FILESX86 CSIDL_PROGRAM_FILES
  26. #endif
  27. //
  28. // We must create our shortcuts in the same language as the install
  29. // language. If the install language is USEnglish, we cannot use
  30. // LoadString because MUI might redirect us to the localized string,
  31. // so we have a hard-coded list of USEnglish strings. We need that
  32. // anyway in the Hide case, where we may need to delete old USEnglish
  33. // versions of the shortcut left over from previous versions of IE.
  34. //
  35. enum { // Localized Shortcut Name
  36. LSN_SM_IE,
  37. LSN_QL_IE,
  38. LSN_SM_OE,
  39. LSN_QL_OE,
  40. #ifdef _WIN64
  41. LSN_SM_IE32,
  42. #endif
  43. // special sentinel value
  44. LSN_NONE = -1,
  45. };
  46. struct LOCALIZEDSHORTCUTINFO
  47. {
  48. LPCWSTR pszExe; // The application to run
  49. LPCWSTR pszUSEnglish; // Use if native OS is USEnglish or MUI-localized
  50. UINT idsLocalized; // Use if native OS is fully-localized (relative to shmgrate.exe)
  51. UINT idsDescription; // Shortcut description (relative to shmgrate.exe)
  52. BOOL fNeverShowShortcut; // Use if we should never show (only hide)
  53. };
  54. const LOCALIZEDSHORTCUTINFO c_rglsi[] = {
  55. { // LSN_SM_IE
  56. c_szIEApp,
  57. L"Internet Explorer",
  58. IDS_OC_IESHORTCUTNAME_SM,
  59. IDS_OC_IEDESCRIPTION,
  60. FALSE,
  61. },
  62. { // LSN_QL_IE
  63. c_szIEApp,
  64. L"Launch Internet Explorer Browser",
  65. IDS_OC_IESHORTCUTNAME_QL,
  66. IDS_OC_IEDESCRIPTION,
  67. FALSE,
  68. },
  69. { // LSN_SM_OE
  70. c_szOEApp,
  71. L"Outlook Express",
  72. IDS_OC_OESHORTCUTNAME_SM,
  73. IDS_OC_OEDESCRIPTION,
  74. FALSE,
  75. },
  76. { // LSN_QL_OE
  77. c_szOEApp,
  78. L"Launch Outlook Express",
  79. IDS_OC_OESHORTCUTNAME_QL,
  80. IDS_OC_OEDESCRIPTION,
  81. TRUE,
  82. },
  83. #ifdef _WIN64
  84. { // LSN_SM_IE32
  85. NULL, // Special-cased in CreateShortcut since it's not in App Paths
  86. L"Internet Explorer (32-bit)",
  87. IDS_OC_IESHORTCUTNAME_SM64,
  88. IDS_OC_IEDESCRIPTION,
  89. FALSE,
  90. }
  91. #endif
  92. };
  93. #ifdef _WIN64
  94. WCHAR g_szIE32Path[MAX_PATH];
  95. #endif
  96. const WCHAR c_szIMN[] = L"Internet Mail and News";
  97. const WCHAR c_szNTOS[] = L"Microsoft(R) Windows NT(TM) Operating System";
  98. const WCHAR c_szHotmail[] = L"Hotmail";
  99. const WCHAR c_szUrlDll[] = L"url.dll";
  100. const WCHAR c_szMailNewsDll[] = L"mailnews.dll";
  101. const WCHAR c_szIEInstallInfoKey[] = L"Software\\Clients\\StartMenuInternet\\IEXPLORE.EXE\\InstallInfo";
  102. const WCHAR c_szOEInstallInfoKey[] = L"Software\\Clients\\Mail\\Outlook Express\\InstallInfo";
  103. const WCHAR c_szIconsVisible[] = L"IconsVisible";
  104. const WCHAR c_szReinstallCommand[] = L"ReinstallCommand";
  105. const WCHAR c_szHideIconsCommand[] = L"HideIconsCommand";
  106. const WCHAR c_szShowIconsCommand[] = L"ShowIconsCommand";
  107. const WCHAR c_szReinstallCommandOE[] = L"%SystemRoot%\\system32\\shmgrate.exe OCInstallReinstallOE";
  108. const WCHAR c_szHideIconsCommandOE[] = L"%SystemRoot%\\system32\\shmgrate.exe OCInstallHideOE";
  109. const WCHAR c_szShowIconsCommandOE[] = L"%SystemRoot%\\system32\\shmgrate.exe OCInstallShowOE";
  110. const WCHAR c_szStartMenuInternetClientKey[] = L"Software\\Clients\\StartMenuInternet";
  111. const WCHAR c_szMailClientKey[] = L"Software\\Clients\\Mail";
  112. #ifdef _WIN64
  113. const WCHAR c_szMailClientKeyWOW32[] = L"Software\\Wow6432Node\\Clients\\Mail";
  114. #endif
  115. const WCHAR c_szJavaVMKey[] = L"CLSID\\{08B0E5C0-4FCB-11CF-AAA5-00401C608501}";
  116. const WCHAR c_szIEAccessKey[] = L"Software\\Microsoft\\Active Setup\\Installed Components\\>{26923b43-4d38-484f-9b9e-de460746276c}";
  117. const WCHAR c_szOEAccessKey[] = L"Software\\Microsoft\\Active Setup\\Installed Components\\>{881dd1c5-3dcf-431b-b061-f3f88e8be88a}";
  118. const WCHAR c_szOCSyncKey[] = L"Software\\Microsoft\\Active Setup\\Optional Component Sync";
  119. const WCHAR c_szIsInstalled[] = L"IsInstalled";
  120. const WCHAR c_szLocale[] = L"Locale";
  121. const WCHAR c_szVersion[] = L"Version";
  122. const WCHAR c_szOCManagerSubComponents[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Setup\\OC Manager\\Subcomponents";
  123. const WCHAR c_szIEAccess[] = L"IEAccess";
  124. const WCHAR c_szOEAccess[] = L"OEAccess";
  125. const WCHAR c_szKeyComponent[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\{871C5380-42A0-1069-A2EA-08002B30309D}";
  126. const WCHAR c_szShellFolder[] = L"ShellFolder";
  127. const WCHAR c_szAttribute[] = L"Attributes";
  128. void ShellFree(LPITEMIDLIST pidl)
  129. {
  130. if (pidl)
  131. {
  132. IMalloc *pMalloc;
  133. if (SUCCEEDED(SHGetMalloc(&pMalloc)))
  134. {
  135. pMalloc->Free(pidl);
  136. pMalloc->Release();
  137. }
  138. }
  139. }
  140. HINSTANCE GetResLibInstance()
  141. {
  142. if (NULL == g_hInstResLib)
  143. {
  144. g_hInstResLib = GetModuleHandle(NULL);
  145. }
  146. return g_hInstResLib;
  147. }
  148. BOOL IsServer()
  149. {
  150. OSVERSIONINFOEX osvi;
  151. osvi.dwOSVersionInfoSize = sizeof(osvi);
  152. return (GetVersionEx((OSVERSIONINFO *)&osvi) &&
  153. ((VER_NT_SERVER == osvi.wProductType) || (VER_NT_DOMAIN_CONTROLLER == osvi.wProductType)));
  154. }
  155. LONG GetStringValue(
  156. IN HKEY hkey,
  157. IN LPCWSTR pwszSubKey, OPTIONAL
  158. IN LPCWSTR pwszValue, OPTIONAL
  159. OUT LPVOID pvData, OPTIONAL
  160. OUT LPDWORD pcbData) OPTIONAL
  161. {
  162. DWORD dwType;
  163. DWORD cbData = pcbData ? *pcbData : 0;
  164. LONG lResult = SHGetValueW(hkey, pwszSubKey, pwszValue, &dwType, pvData, pcbData);
  165. if ((ERROR_SUCCESS == lResult) && (REG_SZ == dwType))
  166. {
  167. // NULL terminate this puppy...
  168. if (pvData && cbData)
  169. {
  170. WCHAR *psz = (WCHAR *)pvData;
  171. psz[(cbData / sizeof(WCHAR)) - 1] = 0;
  172. }
  173. }
  174. else
  175. {
  176. lResult = ERROR_BADKEY;
  177. }
  178. return lResult;
  179. }
  180. inline HRESULT FailedHresultFromWin32()
  181. {
  182. DWORD dwGLE = GetLastError();
  183. return (dwGLE != NOERROR) ? HRESULT_FROM_WIN32(dwGLE) : E_UNEXPECTED;
  184. }
  185. void SendChangeNotification(int csidl)
  186. {
  187. LPITEMIDLIST pidl;
  188. if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, csidl, &pidl)))
  189. {
  190. SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_IDLIST, pidl, NULL);
  191. ShellFree(pidl);
  192. }
  193. }
  194. BOOL IsNtSetupRunning()
  195. {
  196. BOOL fSetupRunning = FALSE;
  197. DWORD dwSetupRunning;
  198. DWORD cbValue = sizeof(dwSetupRunning);
  199. long lResult = SHGetValue(HKEY_LOCAL_MACHINE, L"system\\Setup", L"SystemSetupInProgress", NULL, &dwSetupRunning, &cbValue);
  200. if ((ERROR_SUCCESS == lResult) && (dwSetupRunning))
  201. {
  202. fSetupRunning = TRUE;
  203. }
  204. else
  205. {
  206. cbValue = sizeof(dwSetupRunning);
  207. lResult = SHGetValue(HKEY_LOCAL_MACHINE, L"system\\Setup", L"UpgradeInProgress", NULL, &dwSetupRunning, &cbValue);
  208. if ((ERROR_SUCCESS == lResult) && (dwSetupRunning))
  209. {
  210. fSetupRunning = TRUE;
  211. }
  212. }
  213. return fSetupRunning;
  214. }
  215. BOOL IsIgnorableClientProgram(LPCWSTR pszCurrentClient, LPCWSTR *ppszIgnoreList)
  216. {
  217. BOOL fResult = (lstrlen(pszCurrentClient) == 0);
  218. if (!fResult && (NULL != ppszIgnoreList))
  219. {
  220. while (NULL != *ppszIgnoreList)
  221. {
  222. if (0 == StrCmpI(pszCurrentClient, *ppszIgnoreList))
  223. {
  224. fResult = TRUE;
  225. break;
  226. }
  227. ppszIgnoreList++;
  228. }
  229. }
  230. return fResult;
  231. }
  232. void SetDefaultClientProgram(HKEY hkeyRoot, LPCWSTR pszClientKey, LPCWSTR pszCanonicalName, LPCWSTR *ppszIgnoreList, BOOL fShow, BOOL fForce)
  233. {
  234. HKEY hKey;
  235. LONG lResult;
  236. if (fShow)
  237. {
  238. DWORD dwDisposition;
  239. lResult = RegCreateKeyEx(hkeyRoot, pszClientKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_QUERY_VALUE | KEY_SET_VALUE,
  240. NULL, &hKey, &dwDisposition);
  241. }
  242. else
  243. {
  244. lResult = RegOpenKeyEx(hkeyRoot, pszClientKey, 0, KEY_QUERY_VALUE | KEY_SET_VALUE, &hKey);
  245. }
  246. if (ERROR_SUCCESS == lResult)
  247. {
  248. WCHAR szCurrentClient[MAX_PATH];
  249. DWORD cbCurrentClient = sizeof(szCurrentClient);
  250. lResult = GetStringValue(hKey, NULL, NULL, szCurrentClient, &cbCurrentClient);
  251. // If we're meant to show ourselves then just show set the key
  252. if (fShow)
  253. {
  254. if (fForce ||
  255. ((ERROR_SUCCESS != lResult) || IsIgnorableClientProgram(szCurrentClient, ppszIgnoreList)))
  256. {
  257. RegSetValue(hKey, NULL, REG_SZ, pszCanonicalName, lstrlen(pszCanonicalName) * sizeof(WCHAR));
  258. }
  259. }
  260. else
  261. {
  262. // If we're meant to disappear then clear the key only if we're the one that is currently set.
  263. if (fForce || ((ERROR_SUCCESS == lResult) && (0 == StrCmpI(pszCanonicalName, szCurrentClient))))
  264. {
  265. RegSetValue(hKey, NULL, REG_SZ, L"", 0);
  266. }
  267. }
  268. RegCloseKey(hKey);
  269. }
  270. else
  271. {
  272. TraceMsg(TF_ERROR, "Error opening client key %s - 0x%08x", pszClientKey, lResult);
  273. }
  274. }
  275. BOOL IsInstalled(LPCWSTR pszComponent)
  276. {
  277. BOOL fIsInstalled;
  278. // We're always installed on server!
  279. if (!IsServer())
  280. {
  281. DWORD dwType;
  282. DWORD dwValue;
  283. DWORD cbValue = sizeof(dwValue);
  284. DWORD dwResult = SHGetValueW(HKEY_LOCAL_MACHINE, pszComponent, c_szIsInstalled, &dwType, &dwValue, &cbValue);
  285. fIsInstalled = ((ERROR_SUCCESS == dwResult) && (REG_DWORD == dwType) && (dwValue));
  286. }
  287. else
  288. {
  289. fIsInstalled = TRUE;
  290. }
  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"@shmgrate.exe,-%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"shmgrate.exe", 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, LPCWSTR pszShortExePath)
  444. {
  445. WCHAR szStartDir[MAX_PATH];
  446. if (GetCurrentDirectory(ARRAYSIZE(szStartDir), szStartDir))
  447. {
  448. if (SetCurrentDirectory(pszLinkPath))
  449. {
  450. WIN32_FIND_DATA fd;
  451. HANDLE hFind = FindFirstFile(L"*.lnk", &fd);
  452. if (INVALID_HANDLE_VALUE != hFind)
  453. {
  454. IShellLink *pShellLink;
  455. HRESULT hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&pShellLink);
  456. if (SUCCEEDED(hr))
  457. {
  458. IPersistFile *pPersistFile;
  459. hr = pShellLink->QueryInterface(IID_IPersistFile, (void **)&pPersistFile);
  460. if (SUCCEEDED(hr))
  461. {
  462. do
  463. {
  464. WCHAR szLinkPath[MAX_PATH];
  465. WCHAR szArgs[INTERNET_MAX_PATH_LENGTH];
  466. if (SUCCEEDED(pPersistFile->Load(fd.cFileName, STGM_READ)) &&
  467. SUCCEEDED(pShellLink->GetPath(szLinkPath, ARRAYSIZE(szLinkPath), NULL, 0)) &&
  468. ((0 == StrCmpI(pszLongExePath, szLinkPath)) || (0 == StrCmpI(pszShortExePath, szLinkPath))) &&
  469. SUCCEEDED(pShellLink->GetArguments(szArgs, ARRAYSIZE(szArgs))))
  470. {
  471. PathRemoveBlanks(szArgs);
  472. if (!szArgs[0])
  473. {
  474. SetFileAttributes(fd.cFileName, FILE_ATTRIBUTE_NORMAL);
  475. DeleteFile(fd.cFileName);
  476. }
  477. }
  478. }
  479. while (FindNextFile(hFind, &fd));
  480. pPersistFile->Release();
  481. }
  482. pShellLink->Release();
  483. }
  484. FindClose(hFind);
  485. }
  486. }
  487. SetCurrentDirectory(szStartDir);
  488. }
  489. }
  490. void ShowShortcut(LPCWSTR pszLinkPath, int lsn, BOOL fShow)
  491. {
  492. WCHAR szLinkFullFilePath[MAX_PATH];
  493. WCHAR szLinkFileName[MAX_PATH];
  494. szLinkFileName[0] = 0;
  495. // If we should use the localized name as the filename, then try to get it.
  496. // We should use the localized name if the install language is not USEnglish.
  497. if (LANGIDFROMLCID(GetSystemDefaultUILanguage()) != MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US))
  498. {
  499. LoadString(GetResLibInstance(), c_rglsi[lsn].idsLocalized,
  500. szLinkFileName, ARRAYSIZE(szLinkFileName));
  501. }
  502. // If we couldn't (or shouldn't) get the localized name, then
  503. // use the USEnglish name instead.
  504. if (!szLinkFileName[0])
  505. {
  506. lstrcpyn(szLinkFileName, c_rglsi[lsn].pszUSEnglish, ARRAYSIZE(szLinkFileName));
  507. }
  508. PathAddExtension(szLinkFileName, L".lnk");
  509. PathCombine(szLinkFullFilePath, pszLinkPath, szLinkFileName);
  510. WCHAR szExePath[MAX_PATH];
  511. LONG lResult;
  512. #ifdef _WIN64
  513. if (lsn == LSN_SM_IE32)
  514. {
  515. StrCpyN(szExePath, g_szIE32Path, ARRAYSIZE(szExePath));
  516. lResult = ERROR_SUCCESS;
  517. }
  518. else
  519. #endif
  520. {
  521. lResult = GetExeAppPath(c_rglsi[lsn].pszExe, szExePath, ARRAYSIZE(szExePath));
  522. }
  523. if (ERROR_SUCCESS == lResult)
  524. {
  525. if (fShow)
  526. {
  527. if (!c_rglsi[lsn].fNeverShowShortcut)
  528. {
  529. CreateShortcut(szExePath, szLinkFullFilePath, c_rglsi[lsn].idsLocalized, c_rglsi[lsn].idsDescription);
  530. }
  531. }
  532. else
  533. {
  534. WCHAR szShortExePath[MAX_PATH];
  535. DWORD cch = GetShortPathName(szExePath, szShortExePath, ARRAYSIZE(szShortExePath));
  536. if (!cch || (cch >= ARRAYSIZE(szShortExePath)))
  537. {
  538. szShortExePath[0] = 0;
  539. }
  540. FindAndNukeIcons(pszLinkPath, szExePath, szShortExePath);
  541. }
  542. }
  543. }
  544. void ShowIEDesktopIcon(BOOL fShow)
  545. {
  546. DWORD dwValue;
  547. DWORD dwSize;
  548. DWORD dwDisposition;
  549. HKEY hKeyComponent, hKeyShellFolder;
  550. LONG lResult;
  551. lResult = RegCreateKeyEx(HKEY_CURRENT_USER, c_szKeyComponent, NULL, NULL, REG_OPTION_NON_VOLATILE,
  552. KEY_CREATE_SUB_KEY, NULL, &hKeyComponent, &dwDisposition);
  553. if (ERROR_SUCCESS == lResult)
  554. {
  555. lResult = RegCreateKeyEx(hKeyComponent, c_szShellFolder, NULL, NULL, REG_OPTION_NON_VOLATILE,
  556. KEY_QUERY_VALUE | KEY_SET_VALUE, NULL, &hKeyShellFolder, &dwDisposition);
  557. if (ERROR_SUCCESS == lResult)
  558. {
  559. dwSize = sizeof(dwValue);
  560. lResult = RegQueryValueEx(hKeyShellFolder, c_szAttribute, NULL, NULL, (LPBYTE)&dwValue, &dwSize);
  561. if (ERROR_SUCCESS != lResult)
  562. {
  563. dwValue = 0;
  564. }
  565. if (fShow)
  566. {
  567. dwValue &= ~ SFGAO_NONENUMERATED;
  568. }
  569. else
  570. {
  571. dwValue |= SFGAO_NONENUMERATED;
  572. }
  573. lResult = RegSetValueEx(hKeyShellFolder, c_szAttribute, NULL, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue));
  574. SendChangeNotification(CSIDL_DESKTOP);
  575. SendChangeNotification(CSIDL_DESKTOPDIRECTORY);
  576. RegCloseKey(hKeyShellFolder);
  577. }
  578. RegCloseKey(hKeyComponent);
  579. }
  580. }
  581. // Ensure a handler is in place for all the important things
  582. void FixupIEAssociations(BOOL fForceAssociations)
  583. {
  584. // In order for shdocvw to do its magic, IEXPLORE.EXE must be properly
  585. // registered. Setup runs OC Manager before it runs IE.INF, so don't
  586. // call shdocvw to try to do something he can't do. (He'll assert if
  587. // you try.)
  588. HKEY hk;
  589. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\IEXPLORE.EXE"),
  590. 0, KEY_READ, &hk) != ERROR_SUCCESS)
  591. {
  592. // ie.inf hasn't run yet - shdocvw can't do its thing
  593. return;
  594. }
  595. RegCloseKey(hk);
  596. // Shdocvw does a pretty good job of this, let's give him a crack at it
  597. HINSTANCE hinst = LoadLibrary(L"shdocvw.dll");
  598. if (NULL != hinst)
  599. {
  600. typedef HRESULT (WINAPI *DLLINSTALL)(BOOL bInstall, LPCWSTR pszCmdLine);
  601. DLLINSTALL pfnDllInstall = (DLLINSTALL)GetProcAddress(hinst, "DllInstall");
  602. if (pfnDllInstall)
  603. {
  604. pfnDllInstall(TRUE, (fForceAssociations ? L"ForceAssoc" : L""));
  605. }
  606. else
  607. {
  608. TraceMsg(TF_ERROR, "Error getting DllInstall entry point - GLE = 0x%08x", GetLastError());
  609. }
  610. FreeLibrary(hinst);
  611. }
  612. else
  613. {
  614. TraceMsg(TF_ERROR, "Error loading shdocvw - GLE = 0x%08x", GetLastError());
  615. }
  616. }
  617. // This will create or delete shortcuts in Start Menu\Programs and the Quick Launch bar
  618. void ShowUserShortcuts(int lsnSM, int lsnQL, BOOL fShow)
  619. {
  620. WCHAR szPath[MAX_PATH];
  621. if (lsnSM >= 0 && SHGetSpecialFolderPath(NULL, szPath, CSIDL_PROGRAMS, fShow))
  622. {
  623. ShowShortcut(szPath, lsnSM, fShow);
  624. }
  625. if (lsnQL >= 0 && SHGetSpecialFolderPath(NULL, szPath, CSIDL_APPDATA, fShow))
  626. {
  627. WCHAR szQuickLaunchPath[MAX_PATH];
  628. LoadString(GetResLibInstance(), IDS_OC_QLAUNCHAPPDATAPATH, szQuickLaunchPath, ARRAYSIZE(szQuickLaunchPath));
  629. PathAppend(szPath, szQuickLaunchPath);
  630. // In case we're the first ones through, create the Quick Launch dir
  631. CreateDirectory(szPath, NULL);
  632. ShowShortcut(szPath, lsnQL, fShow);
  633. }
  634. }
  635. void NukeFiles(LPCWSTR pszPath, LPCWSTR pszFileSpec)
  636. {
  637. WCHAR szStartDir[MAX_PATH];
  638. if (GetCurrentDirectory(ARRAYSIZE(szStartDir), szStartDir))
  639. {
  640. if (SetCurrentDirectory(pszPath))
  641. {
  642. WIN32_FIND_DATA fd;
  643. HANDLE hFind = FindFirstFile(pszFileSpec, &fd);
  644. if (INVALID_HANDLE_VALUE != hFind)
  645. {
  646. do
  647. {
  648. SetFileAttributes(fd.cFileName, FILE_ATTRIBUTE_NORMAL);
  649. DeleteFile(fd.cFileName);
  650. }
  651. while (FindNextFile(hFind, &fd));
  652. FindClose(hFind);
  653. }
  654. }
  655. SetCurrentDirectory(szStartDir);
  656. }
  657. }
  658. void NukeDesktopCleanupIcons()
  659. {
  660. WCHAR szPath[MAX_PATH];
  661. HINSTANCE hInstCleaner = LoadLibraryEx(L"fldrclnr.dll", NULL, LOAD_LIBRARY_AS_DATAFILE);
  662. WCHAR szUnusedShortcutFolder[MAX_PATH];
  663. // From nt\shell\applets\cleanup\fldrclnr\resource.h:
  664. #define IDS_ARCHIVEFOLDER 8
  665. #define IDS_ARCHIVEFOLDER_FIRSTBOOT 15
  666. // From nt\shell\applets\cleanup\fldrclnr\cleanupwiz.h:
  667. #define REGSTR_OEM_PATH REGSTR_PATH_SETUP TEXT("\\OemStartMenuData")
  668. #define REGSTR_OEM_TITLEVAL TEXT("DesktopShortcutsFolderName")
  669. if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_DESKTOPDIRECTORY, FALSE))
  670. {
  671. NukeFiles(szPath, L"*.{871C5380-42A0-1069-A2EA-08002B30309D}");
  672. if (hInstCleaner &&
  673. LoadString(hInstCleaner, IDS_ARCHIVEFOLDER, szUnusedShortcutFolder, ARRAYSIZE(szUnusedShortcutFolder)))
  674. {
  675. PathAppend(szPath, szUnusedShortcutFolder);
  676. NukeFiles(szPath, L"*.{871C5380-42A0-1069-A2EA-08002B30309D}");
  677. }
  678. }
  679. DWORD cb = sizeof(szUnusedShortcutFolder);
  680. DWORD dwType;
  681. // Get the folder name from either the registry or fldrclnr.dll and get the startmenu\programs folder
  682. if (
  683. (
  684. (ERROR_SUCCESS == SHGetValue(HKEY_LOCAL_MACHINE, REGSTR_OEM_PATH, REGSTR_OEM_TITLEVAL, &dwType, szUnusedShortcutFolder, &cb))
  685. ||
  686. (hInstCleaner && LoadString(hInstCleaner, IDS_ARCHIVEFOLDER_FIRSTBOOT, szUnusedShortcutFolder, ARRAYSIZE(szUnusedShortcutFolder)))
  687. )
  688. &&
  689. SHGetSpecialFolderPath(NULL, szPath, CSIDL_PROGRAMS, FALSE)
  690. )
  691. {
  692. PathAppend(szPath, szUnusedShortcutFolder);
  693. NukeFiles(szPath, L"*.{871C5380-42A0-1069-A2EA-08002B30309D}");
  694. }
  695. if (hInstCleaner)
  696. {
  697. FreeLibrary(hInstCleaner);
  698. }
  699. }
  700. // Internet Explorer optional component goo
  701. void UserConfigIE()
  702. {
  703. BOOL fIsInstalled = IsInstalled(c_szIEAccessKey);
  704. ShowIEDesktopIcon(fIsInstalled);
  705. if (!fIsInstalled)
  706. {
  707. NukeDesktopCleanupIcons();
  708. }
  709. ShowUserShortcuts(LSN_SM_IE, LSN_QL_IE, fIsInstalled);
  710. #ifdef _WIN64
  711. WCHAR szLinkDir[MAX_PATH];
  712. if (SHGetSpecialFolderPath(NULL, szLinkDir, CSIDL_PROGRAMS, fIsInstalled))
  713. {
  714. WCHAR szExePath[MAX_PATH];
  715. if (SHGetSpecialFolderPath(NULL, szExePath, CSIDL_PROGRAM_FILESX86, FALSE))
  716. {
  717. PathCombine(g_szIE32Path, szExePath, L"Internet Explorer\\iexplore.exe");
  718. ShowShortcut(szLinkDir, LSN_SM_IE32, fIsInstalled);
  719. }
  720. }
  721. #endif
  722. SHSendMessageBroadcast(WM_SETTINGCHANGE, 0, (LPARAM)L"Software\\Clients\\StartMenuInternet");
  723. }
  724. void SetIEShowHideFlags(BOOL fShow)
  725. {
  726. SetBool(c_szIEAccessKey, c_szIsInstalled, fShow);
  727. SetBool(c_szIEInstallInfoKey, c_szIconsVisible, fShow);
  728. SetBool(c_szOCManagerSubComponents, c_szIEAccess, fShow);
  729. }
  730. void ShowHideIE(BOOL fShow, BOOL fForceAssociations, BOOL fMayRunPerUserConfig)
  731. {
  732. if (fShow || !IsServer())
  733. {
  734. SetIEShowHideFlags(fShow);
  735. if (fShow)
  736. {
  737. FixupIEAssociations(fForceAssociations);
  738. SetDefaultClientProgram(HKEY_LOCAL_MACHINE, c_szStartMenuInternetClientKey, c_szIECanonicalName, NULL, TRUE, fForceAssociations);
  739. }
  740. else
  741. {
  742. SetDefaultClientProgram(HKEY_LOCAL_MACHINE, c_szStartMenuInternetClientKey, c_szIECanonicalName, NULL, FALSE, FALSE);
  743. }
  744. if (fMayRunPerUserConfig && !IsNtSetupRunning())
  745. {
  746. SetDefaultClientProgram(HKEY_CURRENT_USER, c_szStartMenuInternetClientKey, c_szIECanonicalName, NULL, FALSE, fShow);
  747. UserConfigIE();
  748. UpdateActiveSetupValues(c_szIEAccessKey, fShow);
  749. }
  750. else
  751. {
  752. SHSendMessageBroadcast(WM_SETTINGCHANGE, 0, (LPARAM)L"Software\\Clients\\StartMenuInternet");
  753. }
  754. ShowHideExe(c_szIEApp, fShow);
  755. #ifdef _WIN64
  756. ShowHideWow32Exe(c_szIEApp, fShow);
  757. #endif
  758. }
  759. }
  760. // Outlook Express optional component goo
  761. void RemoveOEDesktopIcon()
  762. {
  763. WCHAR szPath[MAX_PATH];
  764. if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_DESKTOPDIRECTORY, FALSE))
  765. {
  766. ShowShortcut(szPath, LSN_SM_OE, FALSE);
  767. SendChangeNotification(CSIDL_DESKTOP);
  768. SendChangeNotification(CSIDL_DESKTOPDIRECTORY);
  769. }
  770. if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_COMMON_DESKTOPDIRECTORY, FALSE))
  771. {
  772. ShowShortcut(szPath, LSN_SM_OE, FALSE);
  773. SendChangeNotification(CSIDL_COMMON_DESKTOPDIRECTORY);
  774. }
  775. }
  776. void UserConfigOE()
  777. {
  778. BOOL fIsInstalled = IsInstalled(c_szOEAccessKey);
  779. ShowUserShortcuts(LSN_SM_OE, LSN_QL_OE, fIsInstalled);
  780. SHSendMessageBroadcastW(WM_WININICHANGE, 0, (LPARAM)REGSTR_PATH_MAILCLIENTS);
  781. if (!fIsInstalled)
  782. {
  783. // ShowUserShortcuts(fInstalled=FALSE) already cleaned up any
  784. // old OE Quick Launch shortcuts, so all that's left to remove
  785. // is the desktop icon
  786. RemoveOEDesktopIcon();
  787. }
  788. }
  789. void SetOEShowHideFlags(BOOL fShow)
  790. {
  791. SetBool(c_szOEAccessKey, c_szIsInstalled, fShow);
  792. SetBool(c_szOEInstallInfoKey, c_szIconsVisible, fShow);
  793. SetBool(c_szOCManagerSubComponents, c_szOEAccess, fShow);
  794. }
  795. void FixupOEAssociations(BOOL fForceAssociations, LPCWSTR *ppszIgnoreList)
  796. {
  797. if (!IsNtSetupRunning())
  798. {
  799. long lResult;
  800. if (!fForceAssociations)
  801. {
  802. WCHAR szValue[MAX_PATH];
  803. DWORD cbValue = sizeof(szValue);
  804. DWORD dwType;
  805. lResult = SHGetValueW(HKEY_CLASSES_ROOT, L"mailto\\shell\\open\\command", NULL, &dwType, szValue, &cbValue);
  806. if ((REG_SZ == dwType) &&
  807. ((ERROR_MORE_DATA == lResult) || ((ERROR_SUCCESS == lResult) && (cbValue >= (2 * sizeof(WCHAR))))))
  808. {
  809. // Some sort of valid string data at least character in length -- see if it's one we should stomp,
  810. // otherwise leave it alone
  811. if (NULL != ppszIgnoreList)
  812. {
  813. while (NULL != *ppszIgnoreList)
  814. {
  815. if (NULL != StrStrIW(szValue, *ppszIgnoreList))
  816. {
  817. fForceAssociations = TRUE;
  818. break;
  819. }
  820. ppszIgnoreList++;
  821. }
  822. }
  823. }
  824. else
  825. {
  826. // Either it's not a string or it's zero length
  827. fForceAssociations = TRUE;
  828. }
  829. }
  830. if (fForceAssociations)
  831. {
  832. HKEY hkey;
  833. DWORD dwDisposition;
  834. SHDeleteKey(HKEY_CLASSES_ROOT, L"mailto");
  835. lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, L"mailto", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE,
  836. NULL, &hkey, &dwDisposition);
  837. if (ERROR_SUCCESS == lResult)
  838. {
  839. SHCopyKey(HKEY_LOCAL_MACHINE, L"Software\\Clients\\Mail\\Outlook Express\\Protocols\\mailto", hkey, 0);
  840. RegCloseKey(hkey);
  841. }
  842. }
  843. }
  844. }
  845. void ShowHideOE(BOOL fShow, BOOL fForceAssociations, BOOL fMayRunPerUserConfig)
  846. {
  847. if (fShow || !IsServer())
  848. {
  849. static LPCWSTR ppszIgnoreClientsNormal[] = { c_szIMN, c_szNTOS, NULL };
  850. static LPCWSTR ppszIgnoreClientsSetup[] = { c_szIMN, c_szNTOS, c_szHotmail, NULL };
  851. LPCWSTR *ppszIgnoreClients = !IsNtSetupRunning() ? ppszIgnoreClientsNormal : ppszIgnoreClientsSetup;
  852. static LPCWSTR ppszIgnoreMailto[] = { c_szUrlDll, c_szMailNewsDll, NULL };
  853. SetOEShowHideFlags(fShow);
  854. if (fShow)
  855. {
  856. FixupOEAssociations(fForceAssociations, ppszIgnoreMailto);
  857. SetDefaultClientProgram(HKEY_LOCAL_MACHINE, c_szMailClientKey, c_szOECanonicalName, ppszIgnoreClients, TRUE, fForceAssociations);
  858. #ifdef _WIN64
  859. SetDefaultClientProgram(HKEY_LOCAL_MACHINE, c_szMailClientKeyWOW32, c_szOECanonicalName, ppszIgnoreClients, TRUE, fForceAssociations);
  860. #endif
  861. }
  862. else
  863. {
  864. FixupOEAssociations(FALSE, ppszIgnoreMailto);
  865. SetDefaultClientProgram(HKEY_LOCAL_MACHINE, c_szMailClientKey, c_szOECanonicalName, ppszIgnoreClients, FALSE, FALSE);
  866. #ifdef _WIN64
  867. SetDefaultClientProgram(HKEY_LOCAL_MACHINE, c_szMailClientKeyWOW32, c_szOECanonicalName, ppszIgnoreClients, FALSE, FALSE);
  868. #endif
  869. }
  870. if (fMayRunPerUserConfig && !IsNtSetupRunning())
  871. {
  872. SetDefaultClientProgram(HKEY_CURRENT_USER, c_szMailClientKey, c_szOECanonicalName, ppszIgnoreClients, FALSE, fShow);
  873. UserConfigOE();
  874. UpdateActiveSetupValues(c_szOEAccessKey, fShow);
  875. }
  876. else
  877. {
  878. SHSendMessageBroadcastW(WM_WININICHANGE, 0, (LPARAM)REGSTR_PATH_MAILCLIENTS);
  879. }
  880. ShowHideExe(c_szOEApp, fShow);
  881. #ifdef _WIN64
  882. ShowHideWow32Exe(c_szOEApp, fShow);
  883. #endif
  884. }
  885. }
  886. HRESULT CallRegisterServer(LPCWSTR pszModule, BOOL fRegister)
  887. {
  888. HRESULT hr;
  889. HINSTANCE hinst = LoadLibrary(pszModule);
  890. if (NULL != hinst)
  891. {
  892. typedef HRESULT (WINAPI *DLLREGISTERSERVER)();
  893. LPCSTR pszRegFuncName = fRegister ? "DllRegisterServer" : "DllUnregisterServer";
  894. DLLREGISTERSERVER pfnDllRegisterServer = (DLLREGISTERSERVER)GetProcAddress(hinst, pszRegFuncName);
  895. if (pfnDllRegisterServer)
  896. {
  897. hr = pfnDllRegisterServer();
  898. }
  899. else
  900. {
  901. TraceMsg(TF_ERROR, "Error getting DllRegisterServer entry point - GLE = 0x%08x", GetLastError());
  902. hr = FailedHresultFromWin32();
  903. }
  904. FreeLibrary(hinst);
  905. }
  906. else
  907. {
  908. TraceMsg(TF_ERROR, "Error loading %s - GLE = 0x%08x", pszModule, GetLastError());
  909. hr = FailedHresultFromWin32();
  910. }
  911. return hr;
  912. }
  913. void ReinstallVM()
  914. {
  915. #if 0
  916. SHDeleteKey(HKEY_CLASSES_ROOT, c_szJavaVMKey);
  917. CallRegisterServer(L"msjava.dll", TRUE);
  918. #endif
  919. }
  920. void FixupMailClientKey()
  921. {
  922. SHSetValueW(HKEY_LOCAL_MACHINE, c_szOEInstallInfoKey, c_szReinstallCommand, REG_EXPAND_SZ, c_szReinstallCommandOE, sizeof(c_szReinstallCommandOE));
  923. SHSetValueW(HKEY_LOCAL_MACHINE, c_szOEInstallInfoKey, c_szHideIconsCommand, REG_EXPAND_SZ, c_szHideIconsCommandOE, sizeof(c_szHideIconsCommandOE));
  924. SHSetValueW(HKEY_LOCAL_MACHINE, c_szOEInstallInfoKey, c_szShowIconsCommand, REG_EXPAND_SZ, c_szShowIconsCommandOE, sizeof(c_szShowIconsCommandOE));
  925. SetBool(c_szOEInstallInfoKey, c_szIconsVisible, IsInstalled(c_szOEAccessKey));
  926. }
  927. extern "C" void FixupOptionalComponents()
  928. {
  929. // Need to do this here since the app paths weren't set during setup.
  930. ShowHideExe(c_szIEApp, IsInstalled(c_szIEAccessKey));
  931. ShowHideExe(c_szOEApp, IsInstalled(c_szOEAccessKey));
  932. #ifdef _WIN64
  933. ShowHideWow32Exe(c_szIEApp, IsInstalled(c_szIEAccessKey));
  934. ShowHideWow32Exe(c_szOEApp, IsInstalled(c_szOEAccessKey));
  935. #endif
  936. // OE likes to nuke the whole branch and start from scratch.
  937. FixupMailClientKey();
  938. }