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.

1930 lines
71 KiB

  1. /***************************************************************************
  2. * dll.c
  3. *
  4. * Standard DLL entry-point functions
  5. *
  6. ***************************************************************************/
  7. #include "shellprv.h"
  8. #include <ntpsapi.h> // for NtQuery
  9. #include <ntverp.h>
  10. #include <advpub.h> // For REGINSTALL
  11. #include "fstreex.h"
  12. #include "ids.h"
  13. #include "filefldr.h"
  14. #include "uemapp.h"
  15. #include <xpsp1res.h>
  16. #define DECL_CRTFREE
  17. #include <crtfree.h>
  18. #define INSTALL_MSI 1
  19. #include <msi.h> // For MSI_Install()
  20. void MSI_Install(LPTSTR pszMSIFile);
  21. void DoFusion();
  22. STDAPI_(void) Control_FillCache_RunDLL( HWND hwndStub, HINSTANCE hAppInstance, LPSTR pszCmdLine, int nCmdShow );
  23. BOOL CopyRegistryValues (HKEY hKeyBaseSource, LPCTSTR pszSource, HKEY hKeyBaseTarget, LPCTSTR pszTarget);
  24. // DllGetVersion - New for IE 4.0 shell integrated mode
  25. //
  26. // All we have to do is declare this puppy and CCDllGetVersion does the rest
  27. //
  28. DLLVER_DUALBINARY(VER_PRODUCTVERSION_DW, VER_PRODUCTBUILD_QFE);
  29. HRESULT CallRegInstall(LPCSTR szSection)
  30. {
  31. HRESULT hr = E_FAIL;
  32. HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL"));
  33. if (hinstAdvPack)
  34. {
  35. REGINSTALL pfnri = (REGINSTALL)GetProcAddress(hinstAdvPack, "RegInstall");
  36. if (pfnri)
  37. {
  38. char szShdocvwPath[MAX_PATH];
  39. STRENTRY seReg[] = {
  40. { "SHDOCVW_PATH", szShdocvwPath },
  41. { "25", "%SystemRoot%" },
  42. { "11", "%SystemRoot%\\system32" },
  43. };
  44. STRTABLE stReg = { ARRAYSIZE(seReg), seReg };
  45. // Get the location of shdocvw.dll
  46. lstrcpyA(szShdocvwPath, "%SystemRoot%\\system32");
  47. PathAppendA(szShdocvwPath, "shdocvw.dll");
  48. hr = pfnri(g_hinst, szSection, &stReg);
  49. }
  50. // since we only do this from DllInstall() don't load and unload advpack over and over
  51. // FreeLibrary(hinstAdvPack);
  52. }
  53. return hr;
  54. }
  55. BOOL UnregisterTypeLibrary(const CLSID* piidLibrary)
  56. {
  57. TCHAR szScratch[GUIDSTR_MAX];
  58. HKEY hk;
  59. BOOL f = FALSE;
  60. // convert the libid into a string.
  61. //
  62. SHStringFromGUID(*piidLibrary, szScratch, ARRAYSIZE(szScratch));
  63. if (RegOpenKey(HKEY_CLASSES_ROOT, TEXT("TypeLib"), &hk) == ERROR_SUCCESS)
  64. {
  65. f = RegDeleteKey(hk, szScratch);
  66. RegCloseKey(hk);
  67. }
  68. return f;
  69. }
  70. HRESULT Shell32RegTypeLib(void)
  71. {
  72. TCHAR szPath[MAX_PATH];
  73. WCHAR wszPath[MAX_PATH];
  74. // Load and register our type library.
  75. //
  76. GetModuleFileName(HINST_THISDLL, szPath, ARRAYSIZE(szPath));
  77. SHTCharToUnicode(szPath, wszPath, ARRAYSIZE(wszPath));
  78. ITypeLib *pTypeLib;
  79. HRESULT hr = LoadTypeLib(wszPath, &pTypeLib);
  80. if (SUCCEEDED(hr))
  81. {
  82. // call the unregister type library as we had some old junk that
  83. // was registered by a previous version of OleAut32, which is now causing
  84. // the current version to not work on NT...
  85. UnregisterTypeLibrary(&LIBID_Shell32);
  86. hr = RegisterTypeLib(pTypeLib, wszPath, NULL);
  87. if (FAILED(hr))
  88. {
  89. TraceMsg(TF_WARNING, "SHELL32: RegisterTypeLib failed (%x)", hr);
  90. }
  91. pTypeLib->Release();
  92. }
  93. else
  94. {
  95. TraceMsg(TF_WARNING, "SHELL32: LoadTypeLib failed (%x)", hr);
  96. }
  97. return hr;
  98. }
  99. STDAPI CreateShowDesktopOnQuickLaunch()
  100. {
  101. // delete the "_Current Item" key used for tip rotation in welcome.exe on every upgrade
  102. HKEY hkey;
  103. if ( ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Setup\\Welcome"), 0, MAXIMUM_ALLOWED, &hkey ) )
  104. {
  105. RegDeleteValue(hkey, TEXT("_Current Item"));
  106. RegCloseKey(hkey);
  107. }
  108. // create the "Show Desktop" icon in the quick launch tray
  109. TCHAR szPath[MAX_PATH];
  110. if ( SHGetSpecialFolderPath(NULL, szPath, CSIDL_APPDATA, TRUE) )
  111. {
  112. TCHAR szQuickLaunch[MAX_PATH];
  113. LoadString(g_hinst, IDS_QUICKLAUNCH, szQuickLaunch, ARRAYSIZE(szQuickLaunch));
  114. if ( PathAppend( szPath, szQuickLaunch ) )
  115. {
  116. WritePrivateProfileSection( TEXT("Shell"), TEXT("Command=2\0IconFile=explorer.exe,3\0"), szPath );
  117. WritePrivateProfileSection( TEXT("Taskbar"), TEXT("Command=ToggleDesktop\0"), szPath );
  118. return S_OK;
  119. }
  120. }
  121. return E_FAIL;
  122. }
  123. void _DoMyDocsPerUserInit(void)
  124. {
  125. // mydocs!PerUserInit is invoked to setup the desktop.ini and do all the other work
  126. // required to make this correct.
  127. HINSTANCE hInstMyDocs = LoadLibrary(TEXT("mydocs.dll"));
  128. if (hInstMyDocs != NULL)
  129. {
  130. typedef void (*PFNPerUserInit)(void);
  131. PFNPerUserInit pfnPerUserInit = (PFNPerUserInit)GetProcAddress(hInstMyDocs, "PerUserInit");
  132. if (pfnPerUserInit)
  133. {
  134. pfnPerUserInit();
  135. }
  136. FreeLibrary(hInstMyDocs);
  137. }
  138. }
  139. void _NoDriveAutorunTweak()
  140. {
  141. HKEY hkey;
  142. DWORD dwDisp;
  143. if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER,
  144. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"),
  145. 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwDisp))
  146. {
  147. DWORD dwRest;
  148. DWORD cbSize = sizeof(dwRest);
  149. if (ERROR_SUCCESS != RegQueryValueEx(hkey, TEXT("NoDriveTypeAutoRun"), NULL, NULL,
  150. (PBYTE)&dwRest, &cbSize))
  151. {
  152. dwRest = 0;
  153. }
  154. if ((0x95 == dwRest) || (0 == dwRest))
  155. {
  156. // Did not change or is not there, let's put 0x91
  157. dwRest = 0x91;
  158. RegSetValueEx(hkey, TEXT("NoDriveTypeAutoRun"), 0, REG_DWORD, (PBYTE)&dwRest, sizeof(dwRest));
  159. }
  160. else
  161. {
  162. // Did change, leave it as is
  163. }
  164. RegCloseKey(hkey);
  165. }
  166. }
  167. // code moved from grpconv.exe
  168. // we'd much rather have new firm links than old floppy ones
  169. // clear out any old ones made by previous runs of setup
  170. void _DeleteOldFloppyLinks(LPITEMIDLIST pidlSendTo, IPersistFile *ppf, IShellLink *psl)
  171. {
  172. IShellFolder *psfSendTo;
  173. if (SUCCEEDED(SHBindToObjectEx(NULL, pidlSendTo, NULL, IID_PPV_ARG(IShellFolder, &psfSendTo))))
  174. {
  175. IEnumIDList *penum;
  176. if (SUCCEEDED(psfSendTo->EnumObjects(NULL, SHCONTF_NONFOLDERS, &penum)))
  177. {
  178. LPITEMIDLIST pidl;
  179. ULONG celt;
  180. while (penum->Next(1, &pidl, &celt) == S_OK)
  181. {
  182. // is it a link???
  183. if (SHGetAttributes(psfSendTo, pidl, SFGAO_LINK))
  184. {
  185. // get the target
  186. LPITEMIDLIST pidlFullPath = ILCombine(pidlSendTo, pidl);
  187. if (pidlFullPath)
  188. {
  189. WCHAR szPath[MAX_PATH];
  190. if (SHGetPathFromIDList(pidlFullPath, szPath) &&
  191. SUCCEEDED(ppf->Load(szPath, 0)))
  192. {
  193. LPITEMIDLIST pidlTarget;
  194. if (SUCCEEDED(psl->GetIDList(&pidlTarget)))
  195. {
  196. TCHAR szTargetPath[MAX_PATH];
  197. // its possible for the old drive letters to have changed. for example if you
  198. // move a removable drive from M:\ to N:\, the shortcut will be invalid, so
  199. // we check against DRIVE_NO_ROOT_DIR.
  200. // unfortunately we can't tell if we should remove it if they used to have a zip
  201. // drive on D:\, and then upgraded and it turned into a hard drive on D:\. the
  202. // shortcut will resolve as DRIVE_FIXED and we dont remove it because they might
  203. // have created a shortcut to the fixed drive before the upgrade.
  204. if (SHGetPathFromIDList(pidlTarget, szTargetPath) &&
  205. PathIsRoot(szTargetPath) &&
  206. ((DriveType(PathGetDriveNumber(szTargetPath)) == DRIVE_REMOVABLE) ||
  207. (DriveType(PathGetDriveNumber(szTargetPath)) == DRIVE_NO_ROOT_DIR)))
  208. {
  209. Win32DeleteFile(szPath);
  210. }
  211. ILFree(pidlTarget);
  212. }
  213. }
  214. ILFree(pidlFullPath);
  215. }
  216. }
  217. ILFree(pidl);
  218. }
  219. penum->Release();
  220. }
  221. psfSendTo->Release();
  222. }
  223. }
  224. void _DeleteOldRemovableLinks()
  225. {
  226. IShellLink *psl;
  227. if (SUCCEEDED(CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IShellLink, &psl))))
  228. {
  229. IPersistFile *ppf;
  230. if (SUCCEEDED(psl->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf))) )
  231. {
  232. LPITEMIDLIST pidlSendTo = SHCloneSpecialIDList(NULL, CSIDL_SENDTO, TRUE);
  233. if (pidlSendTo)
  234. {
  235. // we no longer build a list of removable drives here, since that's done on the fly
  236. // by the sendto menu. just delete any links that we owned before.
  237. _DeleteOldFloppyLinks(pidlSendTo, ppf, psl);
  238. ILFree(pidlSendTo);
  239. }
  240. ppf->Release();
  241. }
  242. psl->Release();
  243. }
  244. }
  245. static const struct
  246. {
  247. PCWSTR pszExt;
  248. }
  249. _DeleteSendToList[] =
  250. {
  251. // make sure these extensions are definitely owned by us, since we're deleting all of them.
  252. { L".cdburn" }, // clean up after XP beta2 upgrade
  253. { L".publishwizard" } // clean up after XP beta1 upgrade
  254. };
  255. void _DeleteSendToEntries()
  256. {
  257. TCHAR szSendTo[MAX_PATH];
  258. if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_SENDTO, NULL, 0, szSendTo)))
  259. {
  260. for (int i = 0; i < ARRAYSIZE(_DeleteSendToList); i++)
  261. {
  262. TCHAR szSearch[MAX_PATH];
  263. StrCpyN(szSearch, szSendTo, ARRAYSIZE(szSearch));
  264. PathAppend(szSearch, TEXT("*"));
  265. StrCatBuff(szSearch, _DeleteSendToList[i].pszExt, ARRAYSIZE(szSearch));
  266. WIN32_FIND_DATA fd;
  267. HANDLE hfind = FindFirstFile(szSearch, &fd);
  268. if (hfind != INVALID_HANDLE_VALUE)
  269. {
  270. do
  271. {
  272. TCHAR szFile[MAX_PATH];
  273. StrCpyN(szFile, szSendTo, ARRAYSIZE(szFile));
  274. PathAppend(szFile, fd.cFileName);
  275. DeleteFile(szFile);
  276. } while (FindNextFile(hfind, &fd));
  277. FindClose(hfind);
  278. }
  279. }
  280. }
  281. // next kill old removable drives
  282. _DeleteOldRemovableLinks();
  283. }
  284. DWORD _GetProcessorSpeed() // in MHz
  285. {
  286. static DWORD s_dwSpeed = 0;
  287. if (s_dwSpeed == 0)
  288. {
  289. DWORD cb = sizeof(s_dwSpeed);
  290. SHGetValue(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"),
  291. TEXT("~MHz"), NULL, &s_dwSpeed, &cb);
  292. s_dwSpeed += 1; // fudge factor, my 400 Mhz machine reports 399
  293. }
  294. return s_dwSpeed;
  295. }
  296. DWORD _GetPhysicalMemory() // in MBs
  297. {
  298. NTSTATUS Status;
  299. SYSTEM_BASIC_INFORMATION BasicInfo;
  300. Status = NtQuerySystemInformation(
  301. SystemBasicInformation,
  302. &BasicInfo,
  303. sizeof(BasicInfo),
  304. NULL
  305. );
  306. if (NT_SUCCESS(Status))
  307. {
  308. return ((BasicInfo.NumberOfPhysicalPages * BasicInfo.PageSize) / (1024 * 1024)) + 1; // fudge factor, my 256 Meg machine reports 255
  309. }
  310. else
  311. {
  312. return 64; // Default to 64 Meg (something lame, so that we turn a bunch of stuff off)
  313. }
  314. }
  315. const TCHAR g_cszLetters[] = TEXT("The Quick Brown Fox Jumped Over The Lazy Dog");
  316. BOOL _PerfTestSmoothFonts(void)
  317. {
  318. int cchLength = lstrlen(g_cszLetters);
  319. HDC hdc;
  320. LOGFONT lf;
  321. HFONT hfont;
  322. HFONT hfontOld;
  323. int bkmodeOld;
  324. int iIter;
  325. int iIter2;
  326. int iIter3;
  327. LARGE_INTEGER liFrequency;
  328. LARGE_INTEGER liStart;
  329. LARGE_INTEGER liStop;
  330. LARGE_INTEGER liTotal;
  331. COLORREF colorref;
  332. SIZE size;
  333. DOUBLE eTime[2];
  334. BYTE lfQuality[2];
  335. HDC hdcScreen = GetDC(NULL);
  336. hdc = CreateCompatibleDC(hdcScreen);
  337. HBITMAP hbm = CreateCompatibleBitmap(hdcScreen,200,20);
  338. HBITMAP hbmOld = (HBITMAP)SelectObject(hdc,hbm);
  339. ReleaseDC(NULL,hdcScreen);
  340. bkmodeOld = SetBkMode(hdc, TRANSPARENT);
  341. QueryPerformanceFrequency( &liFrequency );
  342. lfQuality[0] = NONANTIALIASED_QUALITY;
  343. lfQuality[1] = ANTIALIASED_QUALITY;
  344. memset(&lf,0,sizeof(lf));
  345. lstrcpy(lf.lfFaceName,TEXT("Arial"));
  346. lf.lfWeight = FW_BOLD;
  347. for (iIter3 = 0; iIter3 < 2; iIter3++)
  348. {
  349. liTotal.QuadPart = 0;
  350. for (iIter2 = 0; iIter2 < 5; iIter2++)
  351. {
  352. //
  353. // First, Flush the constructed font cache
  354. //
  355. for (iIter = 0; iIter < 64; iIter++)
  356. {
  357. lf.lfHeight = -14-iIter; // 10+ pt
  358. lf.lfQuality = NONANTIALIASED_QUALITY;
  359. hfont = CreateFontIndirect(&lf);
  360. hfontOld = (HFONT)SelectObject(hdc, hfont);
  361. TextOut(hdc, 0, 0, g_cszLetters, cchLength);
  362. SelectObject(hdc, hfontOld);
  363. DeleteObject(hfont);
  364. }
  365. GdiFlush();
  366. colorref = GetPixel(hdc,0,0);
  367. //
  368. // Now measure how long it takes to construct and use a this font
  369. //
  370. lf.lfHeight = -13; // 10 pt
  371. lf.lfQuality = lfQuality[iIter3];
  372. QueryPerformanceCounter( &liStart );
  373. hfont = CreateFontIndirect(&lf);
  374. hfontOld = (HFONT)SelectObject(hdc, hfont);
  375. for (iIter = 0; iIter < 10; iIter++)
  376. {
  377. TextOut(hdc, 0, 0, g_cszLetters, cchLength);
  378. }
  379. GdiFlush();
  380. colorref = GetPixel(hdc,0,0);
  381. QueryPerformanceCounter( &liStop );
  382. liTotal.QuadPart += liStop.QuadPart - liStart.QuadPart;
  383. GetTextExtentPoint(hdc, g_cszLetters, cchLength, &size);
  384. SelectObject(hdc, hfontOld);
  385. DeleteObject(hfont);
  386. }
  387. eTime[iIter3] = (double)liTotal.QuadPart / (double)liFrequency.QuadPart;
  388. }
  389. SetBkMode(hdc, bkmodeOld);
  390. SelectObject(hdc,hbmOld);
  391. DeleteObject(hbm);
  392. DeleteDC(hdc);
  393. return (eTime[1]/eTime[0] <= 4.0);
  394. }
  395. BOOL _PerfTestAlphaLayer(void)
  396. {
  397. DOUBLE eTime = 100.0; // 100 is too large to enable features
  398. int cx = 200;
  399. int cy = 500;
  400. LARGE_INTEGER liFrequency;
  401. QueryPerformanceFrequency( &liFrequency );
  402. BITMAPINFO bmi;
  403. memset(&bmi, 0, sizeof(bmi));
  404. bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  405. bmi.bmiHeader.biWidth = cx;
  406. bmi.bmiHeader.biHeight = cy;
  407. bmi.bmiHeader.biPlanes = 1;
  408. bmi.bmiHeader.biBitCount = 32;
  409. bmi.bmiHeader.biCompression = BI_RGB;
  410. //
  411. // Create the image we want to alpha blend onto the screen
  412. //
  413. HDC hdcScreen = GetDC(NULL);
  414. HDC hdcImage = CreateCompatibleDC(NULL);
  415. if (hdcImage != NULL)
  416. {
  417. PVOID pbits;
  418. HBITMAP hbmImage = CreateDIBSection(hdcImage, &bmi, DIB_RGB_COLORS,
  419. &pbits, NULL, NULL);
  420. if (hbmImage != NULL)
  421. {
  422. HBITMAP hbmOld = (HBITMAP)SelectObject(hdcImage, hbmImage);
  423. BitBlt(hdcImage, 0, 0, cx, cy, hdcScreen, 0, 0, SRCCOPY);
  424. if (pbits != NULL)
  425. {
  426. RGBQUAD *prgb = (RGBQUAD *)pbits;
  427. for (int y = 0; y < cy; y++)
  428. {
  429. for (int x = 0; x < cx; x++)
  430. {
  431. BYTE color_r;
  432. BYTE color_g;
  433. BYTE color_b;
  434. color_r = prgb->rgbRed;
  435. color_g = prgb->rgbBlue;
  436. color_b = prgb->rgbGreen;
  437. color_r = color_r / 2;
  438. color_g = color_g / 2;
  439. color_b = color_b / 2;
  440. prgb->rgbRed = color_r;
  441. prgb->rgbBlue = color_g;
  442. prgb->rgbGreen = color_b;
  443. prgb->rgbReserved = 0x80;
  444. prgb++;
  445. }
  446. }
  447. }
  448. HWND hwnd1 = CreateWindowEx( WS_EX_TRANSPARENT | WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TOOLWINDOW,
  449. TEXT("Button"),
  450. TEXT("Windows XP"),
  451. WS_POPUPWINDOW,
  452. 0, 0,
  453. cx, cy,
  454. NULL, NULL,
  455. 0,
  456. NULL);
  457. HWND hwnd2 = CreateWindowEx( WS_EX_TRANSPARENT | WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TOOLWINDOW,
  458. TEXT("Button"),
  459. TEXT("Windows XP"),
  460. WS_POPUPWINDOW,
  461. 0, 0,
  462. cx, cy,
  463. NULL, NULL,
  464. 0,
  465. NULL);
  466. if (hwnd1 != NULL && hwnd2 != NULL)
  467. {
  468. SetWindowPos(hwnd1, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW);
  469. SetWindowPos(hwnd2, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW);
  470. BLENDFUNCTION blend;
  471. blend.BlendOp = AC_SRC_OVER;
  472. blend.BlendFlags = 0;
  473. blend.SourceConstantAlpha = 0xFF;
  474. blend.AlphaFormat = AC_SRC_ALPHA;
  475. HDC hdc1 = GetDC(hwnd1);
  476. HDC hdc2 = GetDC(hwnd2);
  477. POINT ptSrc;
  478. SIZE size;
  479. ptSrc.x = 0;
  480. ptSrc.y = 0;
  481. size.cx = cx;
  482. size.cy = cy;
  483. COLORREF colorref;
  484. LARGE_INTEGER liStart;
  485. LARGE_INTEGER liStop;
  486. LARGE_INTEGER liTotal;
  487. GdiFlush();
  488. colorref = GetPixel(hdc1,0,0);
  489. colorref = GetPixel(hdc2,0,0);
  490. colorref = GetPixel(hdcScreen,0,0);
  491. QueryPerformanceCounter( &liStart );
  492. for (int iIter = 0; iIter < 10; iIter++)
  493. {
  494. UpdateLayeredWindow(hwnd1, hdc1, NULL, &size,
  495. hdcImage, &ptSrc, 0,
  496. &blend, ULW_ALPHA);
  497. UpdateLayeredWindow(hwnd2, hdc2, NULL, &size,
  498. hdcImage, &ptSrc, 0,
  499. &blend, ULW_ALPHA);
  500. }
  501. GdiFlush();
  502. colorref = GetPixel(hdc1,0,0);
  503. colorref = GetPixel(hdc2,0,0);
  504. colorref = GetPixel(hdcScreen,0,0);
  505. QueryPerformanceCounter( &liStop );
  506. liTotal.QuadPart = liStop.QuadPart - liStart.QuadPart;
  507. eTime = ((DOUBLE)liTotal.QuadPart * 1000.0) / (DOUBLE)liFrequency.QuadPart;
  508. eTime = eTime / 10.0;
  509. ReleaseDC(hwnd1, hdc1);
  510. ReleaseDC(hwnd2, hdc2);
  511. }
  512. if (hwnd1)
  513. {
  514. DestroyWindow(hwnd1);
  515. }
  516. if (hwnd2)
  517. {
  518. DestroyWindow(hwnd2);
  519. }
  520. SelectObject(hdcImage,hbmOld);
  521. DeleteObject(hbmImage);
  522. }
  523. DeleteDC(hdcImage);
  524. }
  525. ReleaseDC(NULL, hdcScreen);
  526. return (eTime <= 75.0);
  527. }
  528. BOOL g_fPerfFont = FALSE;
  529. BOOL g_fPerfAlpha = FALSE;
  530. #define VISUALEFFECTS_KEY TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VisualEffects")
  531. #define VISUALEFFECTS_CHECK TEXT("CheckedValue")
  532. #define VISUALEFFECTS_UNCHECK TEXT("UncheckedValue")
  533. #define VISUALEFFECTS_DEFAULT TEXT("DefaultValue")
  534. #define VISUALEFFECTS_APPLIED TEXT("DefaultApplied")
  535. #define VISUALEFFECTS_MINCPU TEXT("MinimumCPU")
  536. #define VISUALEFFECTS_MINMEM TEXT("MinimumMEM")
  537. #define VISUALEFFECTS_FONT TEXT("DefaultByFontTest")
  538. #define VISUALEFFECTS_ALPHA TEXT("DefaultByAlphaTest")
  539. #define VISUALEFFECTS_VER 1
  540. void _ApplyDefaultVisualEffect(HKEY hkey,HKEY hkeyUser)
  541. {
  542. //
  543. // blow this off completely on TS client to avoid stepping
  544. // on TS client's toes
  545. //
  546. if (!IsOS(OS_TERMINALCLIENT))
  547. {
  548. DWORD cb;
  549. DWORD dwDefaultApplied = 0;
  550. if (0 != hkeyUser)
  551. {
  552. cb = sizeof(dwDefaultApplied);
  553. RegQueryValueEx(hkeyUser, VISUALEFFECTS_APPLIED, NULL, NULL, (LPBYTE)&dwDefaultApplied, &cb);
  554. }
  555. //
  556. // Apply defaults only if the version number is old
  557. //
  558. if (VISUALEFFECTS_VER > dwDefaultApplied)
  559. {
  560. LPTSTR pszValue = NULL; // use the default value
  561. DWORD dwMinimumCPU = 0;
  562. DWORD dwMinimumMEM = 0;
  563. BOOL fFontTestDefault = FALSE;
  564. BOOL fAlphaTestDefault = FALSE;
  565. //
  566. // see if a minimum physical memory value is specified
  567. //
  568. cb = sizeof(dwMinimumMEM);
  569. RegQueryValueEx(hkey, VISUALEFFECTS_MINMEM, NULL, NULL, (LPBYTE)&dwMinimumMEM, &cb);
  570. //
  571. // see if a minimum CPU speed is specified
  572. //
  573. cb = sizeof(dwMinimumCPU);
  574. RegQueryValueEx(hkey, VISUALEFFECTS_MINCPU, NULL, NULL, (LPBYTE)&dwMinimumCPU, &cb);
  575. //
  576. // see if the font performance test value is needed
  577. //
  578. cb = sizeof(fFontTestDefault);
  579. RegQueryValueEx(hkey, VISUALEFFECTS_FONT, NULL, NULL, (LPBYTE)&fFontTestDefault, &cb);
  580. //
  581. // see if the alpha performance test value is needed
  582. //
  583. cb = sizeof(fAlphaTestDefault);
  584. RegQueryValueEx(hkey, VISUALEFFECTS_ALPHA, NULL, NULL, (LPBYTE)&fAlphaTestDefault, &cb);
  585. if ( dwMinimumCPU > 0
  586. || dwMinimumMEM > 0
  587. || fFontTestDefault
  588. || fAlphaTestDefault)
  589. {
  590. pszValue = VISUALEFFECTS_CHECK;
  591. if (_GetProcessorSpeed() < dwMinimumCPU)
  592. {
  593. pszValue = VISUALEFFECTS_UNCHECK;
  594. }
  595. if (_GetPhysicalMemory() < dwMinimumMEM)
  596. {
  597. pszValue = VISUALEFFECTS_UNCHECK;
  598. }
  599. if (fFontTestDefault && !g_fPerfFont)
  600. {
  601. pszValue = VISUALEFFECTS_UNCHECK;
  602. }
  603. if (fAlphaTestDefault && !g_fPerfAlpha)
  604. {
  605. pszValue = VISUALEFFECTS_UNCHECK;
  606. }
  607. }
  608. if (IsOS(OS_ANYSERVER))
  609. {
  610. //
  611. // on server, we default to best performance (*everything* off)
  612. //
  613. pszValue = VISUALEFFECTS_UNCHECK;
  614. }
  615. DWORD dwValue = 0;
  616. cb = sizeof(dwValue);
  617. if (pszValue)
  618. {
  619. //
  620. // set the default according to the chosen value
  621. //
  622. RegQueryValueEx(hkey, pszValue, NULL, NULL, (LPBYTE)&dwValue, &cb);
  623. //
  624. // when figuring out settings that need to adjust the default
  625. // value the VISUALEFFECTS_DEFAULT value must be re-applied
  626. // to the per-user key.
  627. //
  628. if (0 != hkeyUser)
  629. {
  630. RegSetValueEx(hkeyUser, VISUALEFFECTS_DEFAULT, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue));
  631. }
  632. }
  633. else
  634. {
  635. //
  636. // read in the default value
  637. //
  638. RegQueryValueEx(hkey, VISUALEFFECTS_DEFAULT, NULL, NULL, (LPBYTE)&dwValue, &cb);
  639. }
  640. //
  641. // how do we apply this setting?
  642. //
  643. DWORD uiAction;
  644. TCHAR szBuf[MAX_PATH];
  645. if (cb = sizeof(szBuf),
  646. ERROR_SUCCESS == RegQueryValueEx(hkey, TEXT("CLSID"), NULL, NULL, (LPBYTE)&szBuf, &cb))
  647. {
  648. //
  649. // by CLSID
  650. //
  651. CLSID clsid;
  652. GUIDFromString(szBuf, &clsid);
  653. IRegTreeItem* pti;
  654. if (SUCCEEDED(CoCreateInstance(clsid, NULL, CLSCTX_ALL, IID_PPV_ARG(IRegTreeItem, &pti))))
  655. {
  656. pti->SetCheckState(dwValue);
  657. pti->Release();
  658. }
  659. }
  660. else if (cb = sizeof(uiAction),
  661. ERROR_SUCCESS == RegQueryValueEx(hkey, TEXT("SPIActionSet"), NULL, NULL, (LPBYTE)&uiAction, &cb))
  662. {
  663. //
  664. // by SPI
  665. //
  666. SHBoolSystemParametersInfo(uiAction, &dwValue);
  667. }
  668. else if (cb = sizeof(szBuf),
  669. ERROR_SUCCESS == RegQueryValueEx(hkey, TEXT("RegPath"), NULL, NULL, (LPBYTE)&szBuf, &cb))
  670. {
  671. //
  672. // by reg key
  673. //
  674. TCHAR szValueName[96];
  675. cb = sizeof(szValueName);
  676. if (ERROR_SUCCESS == RegQueryValueEx(hkey, TEXT("ValueName"), NULL, NULL, (LPBYTE)&szValueName, &cb))
  677. {
  678. SHSetValue(HKEY_CURRENT_USER, szBuf, szValueName, REG_DWORD, &dwValue, sizeof(dwValue));
  679. }
  680. }
  681. if (0 != hkeyUser)
  682. {
  683. dwDefaultApplied = VISUALEFFECTS_VER;
  684. RegSetValueEx(hkeyUser, VISUALEFFECTS_APPLIED, 0, REG_DWORD, (LPBYTE)&dwDefaultApplied, sizeof(dwDefaultApplied));
  685. }
  686. }
  687. }
  688. }
  689. void _DefaultVisualEffects(void)
  690. {
  691. HKEY hkeyUser;
  692. DWORD dw;
  693. g_fPerfFont = _PerfTestSmoothFonts();
  694. g_fPerfAlpha = _PerfTestAlphaLayer();
  695. if (ERROR_SUCCESS == RegCreateKeyExW(HKEY_CURRENT_USER, VISUALEFFECTS_KEY, 0, TEXTW(""), 0, KEY_SET_VALUE,
  696. NULL, &hkeyUser, &dw))
  697. {
  698. HKEY hkey;
  699. REGSAM samDesired = KEY_READ;
  700. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, VISUALEFFECTS_KEY, 0, samDesired, &hkey))
  701. {
  702. TCHAR szName[96];
  703. for (int i = 0; ERROR_SUCCESS == RegEnumKey(hkey, i, szName, ARRAYSIZE(szName)); i++)
  704. {
  705. HKEY hkeyUserItem;
  706. if (ERROR_SUCCESS == RegCreateKeyExW(hkeyUser, szName, 0, TEXTW(""), 0, KEY_QUERY_VALUE | KEY_SET_VALUE,
  707. NULL, &hkeyUserItem, &dw))
  708. {
  709. HKEY hkeyItem;
  710. if (ERROR_SUCCESS == RegOpenKeyEx(hkey, szName, 0, samDesired, &hkeyItem))
  711. {
  712. // only apply the default for the setting if the "NoApplyDefault" reg value is NOT present
  713. if (RegQueryValueEx(hkeyItem, TEXT("NoApplyDefault"), NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
  714. {
  715. _ApplyDefaultVisualEffect(hkeyItem, hkeyUserItem);
  716. }
  717. RegCloseKey(hkeyItem);
  718. }
  719. RegCloseKey(hkeyUserItem);
  720. }
  721. }
  722. RegCloseKey(hkey);
  723. }
  724. RegCloseKey(hkeyUser);
  725. }
  726. }
  727. STDAPI CDeskHtmlProp_RegUnReg(BOOL bInstall);
  728. STDAPI_(BOOL) ApplyRegistrySecurity();
  729. STDAPI_(void) FixPlusIcons();
  730. STDAPI_(void) CleanupFileSystem();
  731. STDAPI_(void) InitializeSharedDocs(BOOL fOnWow64);
  732. #define KEEP_FAILURE(hrSum, hrLast) if (FAILED(hrLast)) hrSum = hrLast;
  733. #ifdef _WIN64
  734. // On IA64 machines we need to copy the EULA file (eula.txt) from %SytemRoot%\System32, to
  735. // %SystemRoot%\SysWOW64. This is needed because when you do help|about on a 32-bit app running
  736. // under wow64 it will look in the syswow64 directory for the file.
  737. //
  738. // Why is shell32.dll doing this and not setup you might ask? The EULA has to be installed by textmode
  739. // since it is unsigned (and changes for every sku). Since txtmode setup does a MOVE instead of a copy, we
  740. // cannot have it installed into two places. Thus the easies thing to do is to simply copy the file
  741. // from the System32 directory to the SysWOW64 directory here. Sigh.
  742. BOOL CopyEULAForWow6432()
  743. {
  744. BOOL bRet = FALSE;
  745. TCHAR szEULAPath[MAX_PATH];
  746. TCHAR szWow6432EULAPath[MAX_PATH];
  747. if (GetSystemWindowsDirectory(szEULAPath, ARRAYSIZE(szEULAPath)))
  748. {
  749. lstrcpyn(szWow6432EULAPath, szEULAPath, ARRAYSIZE(szWow6432EULAPath));
  750. if (PathAppend(szEULAPath, TEXT("System32\\eula.txt")) &&
  751. PathAppend(szWow6432EULAPath, TEXT("SysWOW64\\eula.txt")))
  752. {
  753. // now we have the source (%SystemRoot%\System32\eula.txt) and dest (%SystemRoot%\SysWOW64\eula.txt)
  754. // paths, lets do the copy!
  755. bRet = CopyFile(szEULAPath, szWow6432EULAPath, FALSE);
  756. }
  757. }
  758. return bRet;
  759. }
  760. #endif // _WIN64
  761. //
  762. // Upgrades from Win9x are internally handled by setup as "clean" installs followed by some
  763. // migration of settings. So, the following function does the job of truly detecting a win9x
  764. // upgrade.
  765. // The way it detects: Look in %windir%\system32\$winnt$.inf in the section [Data]
  766. // for Win9xUpgrade=Yes if it is a Win9x upgrade.
  767. //
  768. BOOL IsUpgradeFromWin9x()
  769. {
  770. TCHAR szFilePath[MAX_PATH];
  771. TCHAR szYesOrNo[10];
  772. GetSystemDirectory(szFilePath, ARRAYSIZE(szFilePath));
  773. PathAppend(szFilePath, TEXT("$WINNT$.INF"));
  774. GetPrivateProfileString(TEXT("Data"), // Section name.
  775. TEXT("Win9xUpgrade"), // Key name.
  776. TEXT("No"), // Default string, if key is missing.
  777. szYesOrNo,
  778. ARRAYSIZE(szYesOrNo),
  779. szFilePath); // Full path to "$winnt$.inf" file.
  780. return (0 == lstrcmpi(szYesOrNo, TEXT("Yes")));
  781. }
  782. BOOL IsCleanInstallInProgress()
  783. {
  784. LPCTSTR szKeyName = TEXT("SYSTEM\\Setup");
  785. HKEY hKeySetup;
  786. BOOL fCleanInstall = FALSE;
  787. if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, szKeyName, 0,
  788. KEY_READ, &hKeySetup) == ERROR_SUCCESS)
  789. {
  790. DWORD dwSize;
  791. LONG lResult;
  792. DWORD dwSystemSetupInProgress = 0;
  793. dwSize = sizeof(DWORD);
  794. lResult = RegQueryValueEx (hKeySetup, TEXT("SystemSetupInProgress"), NULL,
  795. NULL, (LPBYTE) &dwSystemSetupInProgress, &dwSize);
  796. if (lResult == ERROR_SUCCESS)
  797. {
  798. DWORD dwMiniSetupInProgress = 0;
  799. dwSize = sizeof(DWORD);
  800. RegQueryValueEx (hKeySetup, TEXT("MiniSetupInProgress"), NULL,
  801. NULL, (LPBYTE) &dwMiniSetupInProgress, &dwSize);
  802. if(dwSystemSetupInProgress && !dwMiniSetupInProgress)
  803. {
  804. DWORD dwUpgradeInProgress = 0;
  805. dwSize = sizeof(DWORD);
  806. //Setup is in progress and MiniSetup is NOT in progress.
  807. //That means that we are in the GUI mode of setup!
  808. //On clean installs, this value won't be there and the following call will fail.
  809. RegQueryValueEx (hKeySetup, TEXT("UpgradeInProgress"), NULL,
  810. NULL, (LPBYTE) &dwUpgradeInProgress, &dwSize);
  811. fCleanInstall = !dwUpgradeInProgress;
  812. }
  813. }
  814. RegCloseKey (hKeySetup);
  815. }
  816. if(fCleanInstall)
  817. {
  818. // Caution: An upgrade from Win9x is internally done by setup as a "clean" install.
  819. // So, we need to figure out if this is really a clean install or an upgrade from
  820. // win9x.
  821. fCleanInstall = !IsUpgradeFromWin9x();
  822. }
  823. return fCleanInstall ;
  824. }
  825. //
  826. // Set the default MFU to be picked up when each user logs on for the
  827. // first time. The string block must be 16 strings long (_0 through _15).
  828. //
  829. STDAPI SetDefaultMFU(UINT ids)
  830. {
  831. HKEY hkMFU;
  832. LONG lRc = RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\SMDEn"),
  833. 0, NULL, 0, KEY_WRITE, NULL, &hkMFU, NULL);
  834. if (lRc == ERROR_SUCCESS)
  835. {
  836. for (int i = 0; lRc == ERROR_SUCCESS && i < 16; i++)
  837. {
  838. TCHAR szValue[80];
  839. TCHAR szData[80];
  840. wnsprintf(szValue, ARRAYSIZE(szValue), TEXT("Link%d"), i);
  841. wnsprintf(szData, ARRAYSIZE(szData), TEXT("@xpsp1res.dll,-%d"), ids + i);
  842. DWORD cbData = (lstrlen(szData) + 1) * sizeof(TCHAR);
  843. lRc = RegSetValueEx(hkMFU, szValue, 0, REG_SZ, (LPBYTE)szData, cbData);
  844. }
  845. RegCloseKey(hkMFU);
  846. }
  847. return HRESULT_FROM_WIN32(lRc);
  848. }
  849. STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine)
  850. {
  851. HRESULT hrTemp, hr = S_OK;
  852. // 99/05/03 vtan: If you're reading this section then you are considering
  853. // adding code to the registration/installation of shell32.dll. There are
  854. // now 3 schemes to accomplish this task:
  855. // 1. IE4UINIT.EXE
  856. // Check HKLM\Software\Microsoft\Active Setup\Installed Components\{89820200-ECBD-11cf-8B85-00AA005B4383}
  857. // This says that if there is a new version of IE5 to launch ie4uinit.exe.
  858. // You can add code to this executable if you wish. You need to enlist in
  859. // the setup project on \\trango\slmadd using "ieenlist setup"
  860. // 2. REGSVR32.EXE /n /i:U shell32.dll
  861. // Check HKLM\Software\Microsoft\Active Setup\Installed Components\{89820200-ECBD-11cf-8B85-00AA005B4340}
  862. // This is executed using the same scheme as IE4UINIT.EXE except that the
  863. // executable used is regsvr32.exe with a command line passed to
  864. // shell32!DllInstall. Add your code in the section for "U" below.
  865. // If you put the code in the section which is NOT "U" then your
  866. // code is executed at GUI setup and any changes you make to HKCU
  867. // go into the default user (template). Be careful when putting
  868. // things here as winlogon.exe (or some other process) may put
  869. // your changes into a user profile unconditionally.
  870. // 3. HIVEUSD.INX
  871. // Checks NT build numbers and does command based on the previous build
  872. // number and the current build number only executing the changes between
  873. // the builds. If you wish to add something using this method, currently
  874. // you have to enlist in the setup project on \\rastaman\ntwin using
  875. // "enlist -fgs \\rastaman\ntwin -p setup". To find hiveusd.inx go to
  876. // nt\private\setup\inf\win4\inf. Add the build number which the delta
  877. // is required and a command to launch %SystemRoot%\System32\shmgrate.exe
  878. // with one or two parameters. The first parameter tells what command to
  879. // execute. The second parameter is optional. shmgrate.exe then finds
  880. // shell32.dll and calls shell32!FirstUserLogon. Code here is for upgrading
  881. // HKCU user profiles from one NT build to another NT build.
  882. // Code is executed in the process context shmgrate.exe and is executed
  883. // at a time where no UI is possible. Always use HKLM\Software\Microsoft
  884. // \Windows NT\CurrentVersion\Image File Execution Options\Debugger with
  885. // "-d".
  886. // Schemes 1 and 2 work on either Win9x or WinNT but have the sometimes
  887. // unwanted side effect of ALWAYS getting executed on version upgrades.
  888. // Scheme 3 only gets executed on build number deltas. Because schemes 1
  889. // and 2 are always executed, if a user changes (or deletes) that setting
  890. // it will always get put back. Not so with scheme 3.
  891. // Ideally, the best solution is have an internal shell32 build number
  892. // delta scheme which determines the from build and the to build and does
  893. // a similar mechanism to what hiveusd.inx and shmgrate.exe do. This
  894. // would probably involve either a common installation function (such as
  895. // FirstUserLogon()) which is called differently from Win9x and WinNT or
  896. // common functions to do the upgrade and two entry points (such as
  897. // FirstUserLogonNT() and FirstUserLogonWin9X().
  898. if (bInstall)
  899. {
  900. NT_PRODUCT_TYPE type = NtProductWinNt;
  901. RtlGetNtProductType(&type);
  902. // "U" means it's the per user install call
  903. BOOL fPerUser = pszCmdLine && (StrCmpIW(pszCmdLine, L"U") == 0);
  904. if (fPerUser)
  905. {
  906. // NOTE: Code in this segment get run during first login. We want first
  907. // login to be as quick as possible so try to minimize this section.
  908. // Put per-user install stuff here. Any HKCU registration
  909. // done here is suspect. (If you are setting defaults, do
  910. // so in HKLM and use the SHRegXXXUSValue functions.)
  911. // WARNING: we get called by the ie4unit.exe (ieunit.inf) scheme:
  912. // %11%\shell32.dll,NI,U
  913. // this happens per user, to test this code "regsvr32 /n /i:U shell32.dll"
  914. // Some of this stuff we don't want to do on all upgrades (in particular XP Gold -> XP SPn)
  915. BOOL fUpgradeUserSettings = TRUE;
  916. WCHAR szVersion[50]; // plenty big for aaaa,bbbb,cccc,dddd
  917. DWORD cbVersion = sizeof(szVersion);
  918. if (ERROR_SUCCESS==SHGetValueW(HKEY_CURRENT_USER,
  919. L"Software\\Microsoft\\Active Setup\\Installed Components\\{89820200-ECBD-11cf-8B85-00AA005B4340}",L"Version", // guid is Shell32's Active Setup
  920. NULL, szVersion, &cbVersion))
  921. {
  922. __int64 nverUpgradeFrom;
  923. __int64 nverWinXP;
  924. if (SUCCEEDED(GetVersionFromString64(szVersion, &nverUpgradeFrom)) &&
  925. SUCCEEDED(GetVersionFromString64(L"6,0,2600,0000", &nverWinXP)))
  926. {
  927. fUpgradeUserSettings = nverUpgradeFrom < nverWinXP;
  928. }
  929. }
  930. #ifdef INSTALL_MSI
  931. // Install the Office WebFolders shell namespace extension per user.
  932. MSI_Install(TEXT("webfldrs.msi"));
  933. #endif
  934. hrTemp = CreateShowDesktopOnQuickLaunch();
  935. KEEP_FAILURE(hrTemp, hr);
  936. // upgrade the recent folder.
  937. WCHAR sz[MAX_PATH];
  938. SHGetFolderPath(NULL, CSIDL_RECENT | CSIDL_FLAG_CREATE | CSIDL_FLAG_PER_USER_INIT, NULL, SHGFP_TYPE_CURRENT, sz);
  939. SHGetFolderPath(NULL, CSIDL_FAVORITES | CSIDL_FLAG_CREATE | CSIDL_FLAG_PER_USER_INIT, NULL, SHGFP_TYPE_CURRENT, sz);
  940. // torch this value on upgrade.
  941. // insuring the warning that they will see the ugly desktop.ini files
  942. if (fUpgradeUserSettings)
  943. {
  944. SKDeleteValue(SHELLKEY_HKCU_EXPLORER, L"Advanced", L"ShowSuperHidden");
  945. }
  946. HKEY hk = SHGetShellKey(SHELLKEY_HKCULM_MUICACHE, NULL, FALSE);
  947. if (hk)
  948. {
  949. SHDeleteKeyA(hk, NULL);
  950. RegCloseKey(hk);
  951. }
  952. // delete old sendto entries we dont want any more
  953. _DeleteSendToEntries();
  954. // handle the per user init for this guy
  955. _DoMyDocsPerUserInit();
  956. _DefaultVisualEffects();
  957. // handle the per user change of value for NoDriveAutoRun
  958. if (!IsOS(OS_ANYSERVER))
  959. {
  960. _NoDriveAutorunTweak();
  961. }
  962. }
  963. else
  964. {
  965. // Delete any old registration entries, then add the new ones.
  966. // Keep ADVPACK.DLL loaded across multiple calls to RegInstall.
  967. // (The inf engine doesn't guarantee DelReg/AddReg order, that's
  968. // why we explicitly unreg and reg here.)
  969. //
  970. hrTemp = CallRegInstall("RegDll");
  971. KEEP_FAILURE(hrTemp, hr);
  972. // I suppose we should call out NT-only registrations, just in case
  973. // we ever have to ship a win9x based shell again
  974. hrTemp = CallRegInstall("RegDllNT");
  975. KEEP_FAILURE(hrTemp, hr);
  976. // If we are on NT server, do additional stuff
  977. if (type != NtProductWinNt)
  978. {
  979. hrTemp = CallRegInstall("RegDllNTServer");
  980. KEEP_FAILURE(hrTemp, hr);
  981. }
  982. else // workstation
  983. {
  984. if (!IsOS(OS_PERSONAL))
  985. {
  986. hrTemp = CallRegInstall("RegDllNTPro");
  987. KEEP_FAILURE(hrTemp, hr);
  988. //
  989. // NTRAID#NTBUG9-418621-2001/06/27-jeffreys
  990. //
  991. // If the ForceGuest value is unset, e.g. on upgrade
  992. // from Win2k, set the SimpleSharing/DefaultValue to 0.
  993. //
  994. DWORD dwForceGuest;
  995. DWORD cb = sizeof(dwForceGuest);
  996. if (ERROR_SUCCESS != SHGetValue(HKEY_LOCAL_MACHINE, TEXT("System\\CurrentControlSet\\Control\\Lsa"), TEXT("ForceGuest"), NULL, &dwForceGuest, &cb))
  997. {
  998. dwForceGuest = 0;
  999. SHSetValue(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\Folder\\SimpleSharing"), TEXT("DefaultValue"), REG_DWORD, &dwForceGuest, sizeof(dwForceGuest));
  1000. }
  1001. }
  1002. // Service Pack is not allowed to change selfreg.inf
  1003. // so we need to do this manually. Must do this after
  1004. // RegDll so we can overwrite his settings.
  1005. #ifdef _WIN64
  1006. hrTemp = SetDefaultMFU(IDS_SHELL32_PROMFU64_0);
  1007. #else
  1008. hrTemp = SetDefaultMFU(IDS_SHELL32_PROMFU32_0);
  1009. #endif
  1010. KEEP_FAILURE(hrTemp, hr);
  1011. }
  1012. //
  1013. // If this is clean install, then hide some desktop icons.
  1014. //
  1015. if(IsCleanInstallInProgress())
  1016. {
  1017. hrTemp = CallRegInstall("RegHideDeskIcons");
  1018. KEEP_FAILURE(hrTemp, hr);
  1019. }
  1020. // This is apparently the only way to get setup to remove all the registry backup
  1021. // for old names no longer in use...
  1022. hrTemp = CallRegInstall("CleanupOldRollback1");
  1023. KEEP_FAILURE(hrTemp, hr);
  1024. hrTemp = CallRegInstall("CleanupOldRollback2");
  1025. KEEP_FAILURE(hrTemp, hr);
  1026. // REVIEW (ToddB): Move this to DllRegisterServer.
  1027. hrTemp = Shell32RegTypeLib();
  1028. KEEP_FAILURE(hrTemp, hr);
  1029. ApplyRegistrySecurity();
  1030. FixPlusIcons();
  1031. // Filesystem stuff should be done only on the native platform
  1032. // (don't do it when in the emulator) since there is only one
  1033. // filesystem. Otherwise the 32-bit version writes 32-bit goo
  1034. // into the filesystem that the 64-bit shell32 can't handle
  1035. if (!IsOS(OS_WOW6432))
  1036. {
  1037. CleanupFileSystem();
  1038. }
  1039. #ifdef _WIN64
  1040. // this will copy eula.txt to the %SystemRoot%\SysWOW64 directory for
  1041. // 32-bit apps running on IA64 under emulation
  1042. CopyEULAForWow6432();
  1043. #endif
  1044. // Initialize the shared documents objects
  1045. InitializeSharedDocs(IsOS(OS_WOW6432));
  1046. DoFusion();
  1047. }
  1048. }
  1049. else
  1050. {
  1051. // We only need one unreg call since all our sections share
  1052. // the same backup information
  1053. hrTemp = CallRegInstall("UnregDll");
  1054. KEEP_FAILURE(hrTemp, hr);
  1055. UnregisterTypeLibrary(&LIBID_Shell32);
  1056. }
  1057. CDeskHtmlProp_RegUnReg(bInstall);
  1058. return hr;
  1059. }
  1060. STDAPI DllRegisterServer(void)
  1061. {
  1062. // NT5 setup calls this so it is now safe to put code here.
  1063. return S_OK;
  1064. }
  1065. STDAPI DllUnregisterServer(void)
  1066. {
  1067. return S_OK;
  1068. }
  1069. BOOL CopyRegistryValues (HKEY hKeyBaseSource, LPCTSTR pszSource, HKEY hKeyBaseTarget, LPCTSTR pszTarget)
  1070. {
  1071. DWORD dwDisposition, dwMaxValueNameSize, dwMaxValueDataSize;
  1072. HKEY hKeySource, hKeyTarget;
  1073. BOOL fSuccess = FALSE; //Assume error!
  1074. hKeySource = hKeyTarget = NULL;
  1075. if ((ERROR_SUCCESS == RegOpenKeyEx(hKeyBaseSource,
  1076. pszSource,
  1077. 0,
  1078. KEY_READ,
  1079. &hKeySource)) &&
  1080. (ERROR_SUCCESS == RegCreateKeyEx(hKeyBaseTarget,
  1081. pszTarget,
  1082. 0,
  1083. TEXT(""),
  1084. REG_OPTION_NON_VOLATILE,
  1085. KEY_ALL_ACCESS,
  1086. NULL,
  1087. &hKeyTarget,
  1088. &dwDisposition)) &&
  1089. (ERROR_SUCCESS == RegQueryInfoKey(hKeySource,
  1090. NULL,
  1091. NULL,
  1092. NULL,
  1093. NULL,
  1094. NULL,
  1095. NULL,
  1096. NULL,
  1097. &dwMaxValueNameSize,
  1098. &dwMaxValueDataSize,
  1099. NULL,
  1100. NULL)))
  1101. {
  1102. TCHAR *pszValueName;
  1103. void *pValueData;
  1104. pszValueName = reinterpret_cast<TCHAR*>(LocalAlloc(LMEM_FIXED, ++dwMaxValueNameSize * sizeof(TCHAR)));
  1105. if (pszValueName != NULL)
  1106. {
  1107. pValueData = LocalAlloc(LMEM_FIXED, dwMaxValueDataSize);
  1108. if (pValueData != NULL)
  1109. {
  1110. DWORD dwIndex, dwType, dwValueNameSize, dwValueDataSize;
  1111. dwIndex = 0;
  1112. dwValueNameSize = dwMaxValueNameSize;
  1113. dwValueDataSize = dwMaxValueDataSize;
  1114. while (ERROR_SUCCESS == RegEnumValue(hKeySource,
  1115. dwIndex,
  1116. pszValueName,
  1117. &dwValueNameSize,
  1118. NULL,
  1119. &dwType,
  1120. reinterpret_cast<LPBYTE>(pValueData),
  1121. &dwValueDataSize))
  1122. {
  1123. RegSetValueEx(hKeyTarget,
  1124. pszValueName,
  1125. 0,
  1126. dwType,
  1127. reinterpret_cast<LPBYTE>(pValueData),
  1128. dwValueDataSize);
  1129. ++dwIndex;
  1130. dwValueNameSize = dwMaxValueNameSize;
  1131. dwValueDataSize = dwMaxValueDataSize;
  1132. }
  1133. LocalFree(pValueData);
  1134. fSuccess = TRUE; //Succeeded!
  1135. }
  1136. LocalFree(pszValueName);
  1137. }
  1138. }
  1139. if(hKeySource)
  1140. RegCloseKey(hKeySource);
  1141. if(hKeyTarget)
  1142. RegCloseKey(hKeyTarget);
  1143. return fSuccess;
  1144. }
  1145. STDAPI MergeDesktopAndNormalStreams(void)
  1146. {
  1147. static const TCHAR scszBaseRegistryLocation[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer");
  1148. static const int sciMaximumStreams = 128;
  1149. static const TCHAR sccOldMRUListBase = TEXT('a');
  1150. // Upgrade from NT4 (classic shell) to Windows 2000 (integrated shell)
  1151. // This involves TWO major changes and one minor change:
  1152. // 1. Merging DesktopStreamMRU and StreamMRU
  1153. // 2. Upgrading the MRUList to MRUListEx
  1154. // 3. Leaving the old settings alone for the roaming user profile scenario
  1155. // This also involves special casing the users desktop PIDL because this is
  1156. // stored as an absolute path PIDL in DesktopStream and needs to be stored
  1157. // in Streams\Desktop instead.
  1158. // The conversion is performed in-situ and simultaneously.
  1159. // 1. Open all the keys we are going to need to do the conversion.
  1160. HKEY hKeyBase, hKeyDesktopStreamMRU, hKeyDesktopStreams, hKeyStreamMRU, hKeyStreams;
  1161. hKeyBase = hKeyDesktopStreamMRU = hKeyDesktopStreams = hKeyStreamMRU = hKeyStreams = NULL;
  1162. if ((ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER,
  1163. scszBaseRegistryLocation,
  1164. 0,
  1165. KEY_ALL_ACCESS,
  1166. &hKeyBase)) &&
  1167. (ERROR_SUCCESS == RegOpenKeyEx(hKeyBase,
  1168. TEXT("DesktopStreamMRU"),
  1169. 0,
  1170. KEY_ALL_ACCESS,
  1171. &hKeyDesktopStreamMRU)) &&
  1172. (ERROR_SUCCESS == RegOpenKeyEx(hKeyBase,
  1173. TEXT("DesktopStreams"),
  1174. 0,
  1175. KEY_ALL_ACCESS,
  1176. &hKeyDesktopStreams)) &&
  1177. (ERROR_SUCCESS == RegOpenKeyEx(hKeyBase,
  1178. TEXT("StreamMRU"),
  1179. 0,
  1180. KEY_ALL_ACCESS,
  1181. &hKeyStreamMRU)) &&
  1182. (ERROR_SUCCESS == RegOpenKeyEx(hKeyBase,
  1183. TEXT("Streams"),
  1184. 0,
  1185. KEY_ALL_ACCESS,
  1186. &hKeyStreams)) &&
  1187. // 2. Determine whether this upgrade is needed at all. If the presence of
  1188. // StreamMRU\MRUListEx is detected then stop.
  1189. (ERROR_SUCCESS != RegQueryValueEx(hKeyStreamMRU,
  1190. TEXT("MRUListEx"),
  1191. NULL,
  1192. NULL,
  1193. NULL,
  1194. NULL)))
  1195. {
  1196. DWORD *pdwMRUListEx, *pdwMRUListExBase;
  1197. pdwMRUListExBase = pdwMRUListEx = reinterpret_cast<DWORD*>(LocalAlloc(LPTR, sciMaximumStreams * sizeof(DWORD) * 2));
  1198. if (pdwMRUListEx != NULL)
  1199. {
  1200. DWORD dwLastFreeSlot, dwMRUListSize, dwType;
  1201. TCHAR *pszMRUList, szMRUList[sciMaximumStreams];
  1202. // 3. Read the StreamMRU\MRUList, iterate thru this list
  1203. // and convert as we go.
  1204. dwLastFreeSlot = 0;
  1205. dwMRUListSize = sizeof(szMRUList);
  1206. if (ERROR_SUCCESS == RegQueryValueEx(hKeyStreamMRU,
  1207. TEXT("MRUList"),
  1208. NULL,
  1209. &dwType,
  1210. reinterpret_cast<LPBYTE>(szMRUList),
  1211. &dwMRUListSize))
  1212. {
  1213. pszMRUList = szMRUList;
  1214. while (*pszMRUList != TEXT('\0'))
  1215. {
  1216. DWORD dwValueDataSize;
  1217. TCHAR szValue[16];
  1218. // Read the PIDL information based on the letter in
  1219. // the MRUList.
  1220. szValue[0] = *pszMRUList++;
  1221. szValue[1] = TEXT('\0');
  1222. if (ERROR_SUCCESS == RegQueryValueEx(hKeyStreamMRU,
  1223. szValue,
  1224. NULL,
  1225. NULL,
  1226. NULL,
  1227. &dwValueDataSize))
  1228. {
  1229. DWORD dwValueType;
  1230. void *pValueData;
  1231. pValueData = LocalAlloc(LMEM_FIXED, dwValueDataSize);
  1232. if ((pValueData != NULL) &&
  1233. (ERROR_SUCCESS == RegQueryValueEx(hKeyStreamMRU,
  1234. szValue,
  1235. NULL,
  1236. &dwValueType,
  1237. reinterpret_cast<LPBYTE>(pValueData),
  1238. &dwValueDataSize)))
  1239. {
  1240. // Allocate a new number in the MRUListEx for the PIDL.
  1241. *pdwMRUListEx = szValue[0] - sccOldMRUListBase;
  1242. wsprintf(szValue, TEXT("%d"), *pdwMRUListEx++);
  1243. ++dwLastFreeSlot;
  1244. RegSetValueEx(hKeyStreamMRU,
  1245. szValue,
  1246. NULL,
  1247. dwValueType,
  1248. reinterpret_cast<LPBYTE>(pValueData),
  1249. dwValueDataSize);
  1250. LocalFree(pValueData);
  1251. }
  1252. }
  1253. }
  1254. }
  1255. // 4. Read the DesktopStreamMRU\MRUList, iterate thru this
  1256. // this and append to the new MRUListEx that is being
  1257. // created as well as copying both the PIDL in DesktopStreamMRU
  1258. // and the view information in DesktopStreams.
  1259. dwMRUListSize = sizeof(szMRUList);
  1260. if (ERROR_SUCCESS == RegQueryValueEx(hKeyDesktopStreamMRU,
  1261. TEXT("MRUList"),
  1262. NULL,
  1263. &dwType,
  1264. reinterpret_cast<LPBYTE>(szMRUList),
  1265. &dwMRUListSize))
  1266. {
  1267. bool fConvertedEmptyPIDL;
  1268. TCHAR szDesktopDirectoryPath[MAX_PATH];
  1269. fConvertedEmptyPIDL = false;
  1270. SHGetFolderPath(NULL, CSIDL_DESKTOPDIRECTORY, NULL, SHGFP_TYPE_CURRENT, szDesktopDirectoryPath);
  1271. pszMRUList = szMRUList;
  1272. while (*pszMRUList != TEXT('\0'))
  1273. {
  1274. DWORD dwValueDataSize;
  1275. TCHAR szSource[16];
  1276. // Read the PIDL information based on the letter in
  1277. // the MRUList.
  1278. szSource[0] = *pszMRUList++;
  1279. szSource[1] = TEXT('\0');
  1280. if (ERROR_SUCCESS == RegQueryValueEx(hKeyDesktopStreamMRU,
  1281. szSource,
  1282. NULL,
  1283. NULL,
  1284. NULL,
  1285. &dwValueDataSize))
  1286. {
  1287. DWORD dwValueType;
  1288. void *pValueData;
  1289. pValueData = LocalAlloc(LMEM_FIXED, dwValueDataSize);
  1290. if ((pValueData != NULL) &&
  1291. (ERROR_SUCCESS == RegQueryValueEx(hKeyDesktopStreamMRU,
  1292. szSource,
  1293. NULL,
  1294. &dwValueType,
  1295. reinterpret_cast<LPBYTE>(pValueData),
  1296. &dwValueDataSize)))
  1297. {
  1298. TCHAR szTarget[16], szStreamPath[MAX_PATH];
  1299. if ((SHGetPathFromIDList(reinterpret_cast<LPCITEMIDLIST>(pValueData), szStreamPath) != 0) &&
  1300. (0 == lstrcmpi(szStreamPath, szDesktopDirectoryPath)))
  1301. {
  1302. if (!fConvertedEmptyPIDL)
  1303. {
  1304. // 99/05/24 #343721 vtan: Prefer the desktop relative PIDL
  1305. // (empty PIDL) when given a choice of two PIDLs that refer
  1306. // to the desktop. The old absolute PIDL is from SP3 and
  1307. // earlier days. The new relative PIDL is from SP4 and
  1308. // later days. An upgraded SP3 -> SP4 -> SPx -> Windows
  1309. // 2000 system will possibly have old absolute PIDLs.
  1310. // Check for the empty PIDL. If this is encountered already
  1311. // then don't process this stream.
  1312. fConvertedEmptyPIDL = ILIsEmpty(reinterpret_cast<LPCITEMIDLIST>(pValueData));
  1313. wsprintf(szSource, TEXT("%d"), szSource[0] - sccOldMRUListBase);
  1314. CopyRegistryValues(hKeyDesktopStreams, szSource, hKeyStreams, TEXT("Desktop"));
  1315. }
  1316. }
  1317. else
  1318. {
  1319. // Allocate a new number in the MRUListEx for the PIDL.
  1320. *pdwMRUListEx++ = dwLastFreeSlot;
  1321. wsprintf(szTarget, TEXT("%d"), dwLastFreeSlot++);
  1322. if (ERROR_SUCCESS == RegSetValueEx(hKeyStreamMRU,
  1323. szTarget,
  1324. NULL,
  1325. dwValueType,
  1326. reinterpret_cast<LPBYTE>(pValueData),
  1327. dwValueDataSize))
  1328. {
  1329. // Copy the view information from DesktopStreams to Streams
  1330. wsprintf(szSource, TEXT("%d"), szSource[0] - sccOldMRUListBase);
  1331. CopyRegistryValues(hKeyDesktopStreams, szSource, hKeyStreams, szTarget);
  1332. }
  1333. }
  1334. LocalFree(pValueData);
  1335. }
  1336. }
  1337. }
  1338. }
  1339. *pdwMRUListEx++ = static_cast<DWORD>(-1);
  1340. RegSetValueEx(hKeyStreamMRU,
  1341. TEXT("MRUListEx"),
  1342. NULL,
  1343. REG_BINARY,
  1344. reinterpret_cast<LPCBYTE>(pdwMRUListExBase),
  1345. ++dwLastFreeSlot * sizeof(DWORD));
  1346. LocalFree(reinterpret_cast<HLOCAL>(pdwMRUListExBase));
  1347. }
  1348. }
  1349. if (hKeyStreams != NULL)
  1350. RegCloseKey(hKeyStreams);
  1351. if (hKeyStreamMRU != NULL)
  1352. RegCloseKey(hKeyStreamMRU);
  1353. if (hKeyDesktopStreams != NULL)
  1354. RegCloseKey(hKeyDesktopStreams);
  1355. if (hKeyDesktopStreamMRU != NULL)
  1356. RegCloseKey(hKeyDesktopStreamMRU);
  1357. if (hKeyBase != NULL)
  1358. RegCloseKey(hKeyBase);
  1359. return(S_OK);
  1360. }
  1361. static const int s_ciMaximumNumericString = 32;
  1362. int GetRegistryStringValueAsInteger (HKEY hKey, LPCTSTR pszValue, int iDefaultValue)
  1363. {
  1364. int iResult;
  1365. DWORD dwType, dwStringSize;
  1366. TCHAR szString[s_ciMaximumNumericString];
  1367. dwStringSize = sizeof(szString);
  1368. if (ERROR_SUCCESS == RegQueryValueEx(hKey,
  1369. pszValue,
  1370. NULL,
  1371. &dwType,
  1372. reinterpret_cast<LPBYTE>(szString),
  1373. &dwStringSize) && (dwType == REG_SZ))
  1374. {
  1375. iResult = StrToInt(szString);
  1376. }
  1377. else
  1378. {
  1379. iResult = iDefaultValue;
  1380. }
  1381. return(iResult);
  1382. }
  1383. void SetRegistryIntegerAsStringValue (HKEY hKey, LPCTSTR pszValue, int iValue)
  1384. {
  1385. TCHAR szString[s_ciMaximumNumericString];
  1386. wnsprintf(szString, ARRAYSIZE(szString), TEXT("%d"), iValue);
  1387. TW32(RegSetValueEx(hKey,
  1388. pszValue,
  1389. 0,
  1390. REG_SZ,
  1391. reinterpret_cast<LPBYTE>(szString),
  1392. (lstrlen(szString) + sizeof('\0')) * sizeof(TCHAR)));
  1393. }
  1394. STDAPI MoveAndAdjustIconMetrics(void)
  1395. {
  1396. // 99/06/06 #309198 vtan: The following comes from hiveusd.inx which is
  1397. // where this functionality used to be executed. It used to consist of
  1398. // simple registry deletion and addition. This doesn't work on upgrade
  1399. // when the user has large icons (Shell Icon Size == 48).
  1400. // In this case that metric must be moved and the new values adjusted
  1401. // so that the metric is preserved should the user then decide to turn
  1402. // off large icons.
  1403. // To restore old functionality, remove the entry in hiveusd.inx at
  1404. // build 1500 which is where this function is invoked and copy the
  1405. // old text back in.
  1406. /*
  1407. HKR,"1508\Hive\2","Action",0x00010001,3
  1408. HKR,"1508\Hive\2","KeyName",0000000000,"Control Panel\Desktop\WindowMetrics"
  1409. HKR,"1508\Hive\2","Value",0000000000,"75"
  1410. HKR,"1508\Hive\2","ValueName",0000000000,"IconSpacing"
  1411. HKR,"1508\Hive\3","Action",0x00010001,3
  1412. HKR,"1508\Hive\3","KeyName",0000000000,"Control Panel\Desktop\WindowMetrics"
  1413. HKR,"1508\Hive\3","Value",0000000000,"1"
  1414. HKR,"1508\Hive\3","ValueName",0000000000,"IconTitleWrap"
  1415. */
  1416. // Icon metric keys have moved from HKCU\Control Panel\Desktop\Icon*
  1417. // to HKCU\Control Panel\Desktop\WindowMetrics\Icon* but only 3 values
  1418. // should be moved. These are "IconSpacing", "IconTitleWrap" and
  1419. // "IconVerticalSpacing". This code is executed before the deletion
  1420. // entry in hiveusd.inx so that it can get the values before they
  1421. // are deleted. The addition section has been remove (it's above).
  1422. static const TCHAR s_cszIconSpacing[] = TEXT("IconSpacing");
  1423. static const TCHAR s_cszIconTitleWrap[] = TEXT("IconTitleWrap");
  1424. static const TCHAR s_cszIconVerticalSpacing[] = TEXT("IconVerticalSpacing");
  1425. static const int s_ciStandardOldIconSpacing = 75;
  1426. static const int s_ciStandardNewIconSpacing = -1125;
  1427. HKEY hKeyDesktop, hKeyWindowMetrics;
  1428. hKeyDesktop = hKeyWindowMetrics = NULL;
  1429. if ((ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER,
  1430. TEXT("Control Panel\\Desktop"),
  1431. 0,
  1432. KEY_ALL_ACCESS,
  1433. &hKeyDesktop)) &&
  1434. (ERROR_SUCCESS == RegOpenKeyEx(hKeyDesktop,
  1435. TEXT("WindowMetrics"),
  1436. 0,
  1437. KEY_ALL_ACCESS,
  1438. &hKeyWindowMetrics)))
  1439. {
  1440. int iIconSpacing, iIconTitleWrap, iIconVerticalSpacing;
  1441. // 1. Read the values that we wish the move and adjust.
  1442. iIconSpacing = GetRegistryStringValueAsInteger(hKeyDesktop, s_cszIconSpacing, s_ciStandardOldIconSpacing);
  1443. iIconTitleWrap = GetRegistryStringValueAsInteger(hKeyDesktop, s_cszIconTitleWrap, 1);
  1444. iIconVerticalSpacing = GetRegistryStringValueAsInteger(hKeyDesktop, s_cszIconVerticalSpacing, s_ciStandardOldIconSpacing);
  1445. // 2. Perform the adjustment.
  1446. iIconSpacing = s_ciStandardNewIconSpacing * iIconSpacing / s_ciStandardOldIconSpacing;
  1447. iIconVerticalSpacing = s_ciStandardNewIconSpacing * iIconVerticalSpacing / s_ciStandardOldIconSpacing;
  1448. // 3. Write the values back out in the new (moved) location.
  1449. SetRegistryIntegerAsStringValue(hKeyWindowMetrics, s_cszIconSpacing, iIconSpacing);
  1450. SetRegistryIntegerAsStringValue(hKeyWindowMetrics, s_cszIconTitleWrap, iIconTitleWrap);
  1451. SetRegistryIntegerAsStringValue(hKeyWindowMetrics, s_cszIconVerticalSpacing, iIconVerticalSpacing);
  1452. // 4. Let winlogon continue processing hiveusd.inx and delete the
  1453. // old entries in the process. We already created the new entries
  1454. // and that has been removed from hiveusd.inx.
  1455. }
  1456. if (hKeyWindowMetrics != NULL)
  1457. TW32(RegCloseKey(hKeyWindowMetrics));
  1458. if (hKeyDesktop != NULL)
  1459. TW32(RegCloseKey(hKeyDesktop));
  1460. return(S_OK);
  1461. }
  1462. STDAPI FirstUserLogon(LPCSTR pcszCommand, LPCSTR pcszOptionalArguments)
  1463. {
  1464. const struct
  1465. {
  1466. LPCSTR pcszCommand;
  1467. HRESULT (WINAPI *pfn)();
  1468. }
  1469. sCommands[] =
  1470. {
  1471. { "MergeDesktopAndNormalStreams", MergeDesktopAndNormalStreams },
  1472. { "MoveAndAdjustIconMetrics", MoveAndAdjustIconMetrics },
  1473. };
  1474. HRESULT hr = E_FAIL;
  1475. // Match what shmgrate.exe passed us and execute the command.
  1476. // Only use the optional argument if required. Note this is
  1477. // done ANSI because the original command line is ANSI from
  1478. // shmgrate.exe.
  1479. for (int i = 0; i < ARRAYSIZE(sCommands); ++i)
  1480. {
  1481. if (lstrcmpA(pcszCommand, sCommands[i].pcszCommand) == 0)
  1482. {
  1483. hr = sCommands[i].pfn();
  1484. break;
  1485. }
  1486. }
  1487. return hr;
  1488. }
  1489. #ifdef INSTALL_MSI
  1490. //
  1491. // WebFolders namespace extension installation.
  1492. // This is the code that initially installs the Office WebFolders
  1493. // shell namespace extension on the computer. Code in shmgrate.exe
  1494. // (see private\windows\shell\migrate) performs per-user
  1495. // web folders registration duties.
  1496. //
  1497. typedef UINT (WINAPI * PFNMSIINSTALLPRODUCT)(LPCTSTR, LPCTSTR);
  1498. typedef INSTALLUILEVEL (WINAPI * PFNMSISETINTERNALUI)(INSTALLUILEVEL, HWND *);
  1499. #define GETPROC(var, hmod, ptype, fn) ptype var = (ptype)GetProcAddress(hmod, fn)
  1500. #define API_MSISETINTERNALUI "MsiSetInternalUI"
  1501. #ifdef UNICODE
  1502. # define API_MSIINSTALLPRODUCT "MsiInstallProductW"
  1503. #else
  1504. # define API_MSIINSTALLPRODUCT "MsiInstallProductA"
  1505. #endif
  1506. void MSI_Install(LPTSTR pszMSIFile)
  1507. {
  1508. HMODULE hmod = LoadLibrary(TEXT("msi.dll"));
  1509. if (hmod)
  1510. {
  1511. BOOL bFreeLib = FALSE;
  1512. GETPROC(pfnMsiSetInternalUI, hmod, PFNMSISETINTERNALUI, API_MSISETINTERNALUI);
  1513. GETPROC(pfnMsiInstallProduct, hmod, PFNMSIINSTALLPRODUCT, API_MSIINSTALLPRODUCT);
  1514. if (pfnMsiSetInternalUI && pfnMsiInstallProduct)
  1515. {
  1516. TCHAR szPath[MAX_PATH];
  1517. GetSystemDirectory(szPath, ARRAYSIZE(szPath));
  1518. PathAppend(szPath, pszMSIFile);
  1519. //
  1520. // Use "silent" install mode. No UI.
  1521. //
  1522. INSTALLUILEVEL oldUILevel = pfnMsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
  1523. // Install the MSI package.
  1524. // Old code did this polling loop on a background thread, but that doesn't
  1525. // work since we're called at DllInstall time, and the process will
  1526. // go away before the install completes. Must do it all on this thread.
  1527. // Wait a little bit before re-trying.
  1528. UINT uRet = 0;
  1529. do {
  1530. uRet = pfnMsiInstallProduct(szPath, TEXT(""));
  1531. } while ((uRet == ERROR_INSTALL_ALREADY_RUNNING) && (Sleep(100),TRUE));
  1532. pfnMsiSetInternalUI(oldUILevel, NULL);
  1533. }
  1534. if (bFreeLib)
  1535. FreeLibrary(hmod);
  1536. }
  1537. }
  1538. #endif // INSTALL_MSI
  1539. // now is the time on sprockets when we lock down the registry
  1540. STDAPI_(BOOL) ApplyRegistrySecurity()
  1541. {
  1542. BOOL fSuccess = FALSE; // assume failure
  1543. SHELL_USER_PERMISSION supEveryone;
  1544. SHELL_USER_PERMISSION supSystem;
  1545. SHELL_USER_PERMISSION supAdministrators;
  1546. PSHELL_USER_PERMISSION aPerms[3] = {&supEveryone, &supSystem, &supAdministrators};
  1547. // we want the "Everyone" to have read access
  1548. supEveryone.susID = susEveryone;
  1549. supEveryone.dwAccessType = ACCESS_ALLOWED_ACE_TYPE;
  1550. supEveryone.dwAccessMask = KEY_READ;
  1551. supEveryone.fInherit = TRUE;
  1552. supEveryone.dwInheritMask = (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  1553. supEveryone.dwInheritAccessMask = GENERIC_READ;
  1554. // we want the "SYSTEM" to have full control
  1555. supSystem.susID = susSystem;
  1556. supSystem.dwAccessType = ACCESS_ALLOWED_ACE_TYPE;
  1557. supSystem.dwAccessMask = KEY_ALL_ACCESS;
  1558. supSystem.fInherit = TRUE;
  1559. supSystem.dwInheritMask = (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  1560. supSystem.dwInheritAccessMask = GENERIC_ALL;
  1561. // we want the "Administrators" to have full control
  1562. supAdministrators.susID = susAdministrators;
  1563. supAdministrators.dwAccessType = ACCESS_ALLOWED_ACE_TYPE;
  1564. supAdministrators.dwAccessMask = KEY_ALL_ACCESS;
  1565. supAdministrators.fInherit = TRUE;
  1566. supAdministrators.dwInheritMask = (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
  1567. supAdministrators.dwInheritAccessMask = GENERIC_ALL;
  1568. SECURITY_DESCRIPTOR* psd = GetShellSecurityDescriptor(aPerms, ARRAYSIZE(aPerms));
  1569. if (psd)
  1570. {
  1571. HKEY hkLMBitBucket;
  1572. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\BitBucket"), 0, KEY_ALL_ACCESS, &hkLMBitBucket) == ERROR_SUCCESS)
  1573. {
  1574. if (RegSetKeySecurity(hkLMBitBucket, DACL_SECURITY_INFORMATION, psd) == ERROR_SUCCESS)
  1575. {
  1576. // victory is mine!
  1577. fSuccess = TRUE;
  1578. }
  1579. RegCloseKey(hkLMBitBucket);
  1580. }
  1581. LocalFree(psd);
  1582. }
  1583. return fSuccess;
  1584. }
  1585. CComModule _Module;
  1586. BEGIN_OBJECT_MAP(ObjectMap)
  1587. // nothing in here, use clsobj.c class table instead
  1588. END_OBJECT_MAP()
  1589. // ATL DllMain, needed to support our ATL classes that depend on _Module
  1590. // REVIEW: confirm that _Module is really needed
  1591. STDAPI_(BOOL) ATL_DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
  1592. {
  1593. if (dwReason == DLL_PROCESS_ATTACH)
  1594. {
  1595. _Module.Init(ObjectMap, hInstance);
  1596. }
  1597. else if (dwReason == DLL_PROCESS_DETACH)
  1598. {
  1599. _Module.Term();
  1600. }
  1601. return TRUE; // ok
  1602. }
  1603. #define FUSION_FLAG_SYSTEM32 0
  1604. #define FUSION_FLAG_WINDOWS 1
  1605. #define FUSION_FLAG_PROGRAMFILES 2
  1606. #define FUSION_ENTRY(x, z) {L#x, NULL, z},
  1607. #define FUSION_ENTRY_DEST(x, y, z) {L#x, L#y, z},
  1608. struct
  1609. {
  1610. PWSTR pszAppName;
  1611. PWSTR pszDestination;
  1612. DWORD dwFlags;
  1613. }
  1614. g_FusionizedApps[] =
  1615. {
  1616. FUSION_ENTRY(ncpa.cpl, FUSION_FLAG_SYSTEM32)
  1617. FUSION_ENTRY(nwc.cpl, FUSION_FLAG_SYSTEM32)
  1618. FUSION_ENTRY(sapi.cpl, FUSION_FLAG_SYSTEM32)
  1619. FUSION_ENTRY(wuaucpl.cpl, FUSION_FLAG_SYSTEM32)
  1620. FUSION_ENTRY(cdplayer.exe, FUSION_FLAG_SYSTEM32)
  1621. FUSION_ENTRY_DEST(msimn.exe, "OutLook Express", FUSION_FLAG_PROGRAMFILES)
  1622. // WARNING: Do NOT add iexplorer or Explorer.exe! This will cause all apps to get fusioned; which is bad, mkay?
  1623. };
  1624. void DoFusion()
  1625. {
  1626. TCHAR szManifest[MAX_PATH];
  1627. // We will however generate a manifest for other apps
  1628. for (int i = 0; i < ARRAYSIZE(g_FusionizedApps); i++)
  1629. {
  1630. switch(g_FusionizedApps[i].dwFlags)
  1631. {
  1632. case FUSION_FLAG_SYSTEM32:
  1633. GetSystemDirectory(szManifest, ARRAYSIZE(szManifest));
  1634. break;
  1635. case FUSION_FLAG_WINDOWS:
  1636. GetWindowsDirectory(szManifest, ARRAYSIZE(szManifest));
  1637. break;
  1638. case FUSION_FLAG_PROGRAMFILES:
  1639. SHGetSpecialFolderPath(NULL, szManifest, CSIDL_PROGRAM_FILES, FALSE);
  1640. PathCombine(szManifest, szManifest, g_FusionizedApps[i].pszDestination);
  1641. break;
  1642. }
  1643. PathCombine(szManifest, szManifest, g_FusionizedApps[i].pszAppName);
  1644. StrCatBuff(szManifest, TEXT(".manifest"), ARRAYSIZE(szManifest));
  1645. SHSquirtManifest(HINST_THISDLL, IDS_EXPLORERMANIFEST, szManifest);
  1646. }
  1647. SHGetManifest(szManifest, ARRAYSIZE(szManifest));
  1648. SHSquirtManifest(HINST_THISDLL, IDS_EXPLORERMANIFEST, szManifest);
  1649. }