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.

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