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.

3627 lines
95 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. olereg.c
  5. Abstract:
  6. Code to perform OLE registry suppression based on list of
  7. GUIDs in win95upg.inf.
  8. OLE suppression is accomplished by the following algorithm:
  9. 1. Determine all GUIDs that are Win9x-specific, load in
  10. list of manually-suppressed GUIDs. Save this list
  11. to memdb.
  12. 2. Scan registry for GUID settings, then suppress all
  13. linkage to the GUID (the ProgID, Interface, etc).
  14. Use memdb to suppress each registry key/value.
  15. 3. Suppress all shell linkage to suppressed objects
  16. including file associations and desktop links.
  17. 4. Do a sanity check on the unsuppressed objects in
  18. the checked build
  19. Author:
  20. Jim Schmidt (jimschm) 20-Mar-1997
  21. Revision History:
  22. jimschm 23-Sep-1998 Updated for new fileops code
  23. jimschm 28-Jan-1998 Added hack for ActiveSetup key
  24. jimschm 05-May-1997 Added new auto-suppression of non-OLE
  25. shell links
  26. --*/
  27. #include "pch.h"
  28. #include "sysmigp.h"
  29. #include "progbar.h"
  30. #include "oleregp.h"
  31. #include "regops.h"
  32. #define S_EXPLORER_SHELLEXECUTEHOOKS TEXT("HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellExecuteHooks")
  33. #define S_EXPLORER_CSSFILTERS TEXT("HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CSSFilters")
  34. #define S_EXPLORER_DESKTOP_NAMESPACE TEXT("HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Desktop\\NameSpace")
  35. #define S_EXPLORER_FILETYPESPROPERTYSHEETHOOK TEXT("HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileTypesPropertySheetHook")
  36. #define S_EXPLORER_FINDEXTENSIONS TEXT("HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FindExtensions")
  37. #define S_EXPLORER_MYCOMPUTER_NAMESPACE TEXT("HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\MyComputer\\NameSpace")
  38. #define S_EXPLORER_NETWORKNEIGHBORHOOD_NAMESPACE TEXT("HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\NetworkNeighborhood\\NameSpace")
  39. #define S_EXPLORER_NEWSHORTCUTHANDLERS TEXT("HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\NewShortcutHandlers")
  40. #define S_EXPLORER_REMOTECOMPUTER_NAMESPACE TEXT("HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RemoteComputer\\NameSpace")
  41. #define S_EXPLORER_SHELLICONOVERLAYIDENTIFIERS TEXT("HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers")
  42. #define S_EXPLORER_VOLUMECACHES TEXT("HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VolumeCaches")
  43. #define S_ACTIVESETUP TEXT("HKLM\\Software\\Microsoft\\Active Setup\\Installed Components")
  44. #define S_EXTSHELLVIEWS TEXT("HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\ExtShellViews")
  45. #define S_SHELLEXTENSIONS_APPROVED TEXT("HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved")
  46. #define S_SHELLSERVICEOBJECTDELAYLOAD TEXT("HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\ShellServiceObjectDelayLoad ")
  47. static TCHAR g_DefaultIcon[] = TEXT("DefaultIcon");
  48. #define DBG_OLEREG "OLE Reg"
  49. //
  50. // Strings for AutoSuppress
  51. //
  52. TCHAR g_InprocHandler[] = TEXT("InprocHandler");
  53. TCHAR g_InprocHandler32[] = TEXT("InprocHandler32");
  54. TCHAR g_InprocServer[] = TEXT("InprocServer");
  55. TCHAR g_InprocServer32[] = TEXT("InprocServer32");
  56. TCHAR g_LocalServer[] = TEXT("LocalServer");
  57. TCHAR g_LocalServer32[] = TEXT("LocalServer32");
  58. PCTSTR g_FileRefKeys[] = {
  59. g_InprocHandler,
  60. g_InprocHandler32,
  61. g_InprocServer,
  62. g_InprocServer32,
  63. g_LocalServer,
  64. g_LocalServer32,
  65. NULL
  66. };
  67. static POOLHANDLE g_OlePool;
  68. DWORD
  69. OleReg_GetProgressMax (
  70. VOID
  71. )
  72. /*++
  73. Routine Description:
  74. Estimates the amount of ticks needed to complete OLE registry processing.
  75. Arguments:
  76. none
  77. Return Value:
  78. The number of ticks, equal to the number of ticks added with a delta in
  79. SuppressOleGuids.
  80. --*/
  81. {
  82. if (REPORTONLY()) {
  83. return 0;
  84. }
  85. return TICKS_OLEREG;
  86. }
  87. BOOL
  88. pIgnoreGuid (
  89. IN PCTSTR GuidStr
  90. )
  91. {
  92. INFCONTEXT ic;
  93. MYASSERT (IsGuid (GuidStr, TRUE));
  94. if (IsReportObjectHandled (GuidStr)) {
  95. DEBUGMSG ((DBG_OLEREG, "%s is a handled GUID, will not be suppressed", GuidStr));
  96. return TRUE;
  97. }
  98. if (SetupFindFirstLine (g_Win95UpgInf, S_FORCED_GUIDS, GuidStr, &ic)) {
  99. DEBUGMSG ((DBG_OLEREG, "%s is a forced GUID, will not be suppressed", GuidStr));
  100. return TRUE;
  101. }
  102. return FALSE;
  103. }
  104. BOOL
  105. pSuppressOleGuids (
  106. VOID
  107. )
  108. /*++
  109. Routine Description:
  110. Processes the [Suppressed GUIDs] section of win95upg.inf and auto-suppresses
  111. OLE objects and GUIDs. The inf-based approach allows an OLE object and
  112. all of its linkage to be suppressed. The auto-suppress approach allows
  113. suppression of OLE objects and linkage when the implementation binary
  114. is removed from the system.
  115. Arguments:
  116. none
  117. Return Value:
  118. TRUE if suppression was successful, or FALSE if an error occurred. Call
  119. GetLastError to retrieve the error code.
  120. --*/
  121. {
  122. BOOL Result = FALSE;
  123. DWORD Ticks;
  124. if (REPORTONLY()) {
  125. return TRUE;
  126. }
  127. g_OlePool = PoolMemInitNamedPool ("OLE Reg");
  128. if (!g_OlePool) {
  129. return FALSE;
  130. }
  131. Ticks = GetTickCount();
  132. __try {
  133. ProgressBar_SetComponentById (MSG_OLEREG);
  134. //
  135. // Suppress all GUIDs from [Suppressed GUIDs] section of win95upg.inf:
  136. //
  137. // HKLM\SOFTWARE\Classes\CLSID\<GUID>
  138. // HKLM\SOFTWARE\Classes\Interface\<GUID>
  139. // HKLM\SOFTWARE\Classes\<ProgID>
  140. // HKLM\SOFTWARE\Classes\<VersionIndependentProgID>
  141. //
  142. // Suppress any GUID that has a TreatAs key that points to GUID
  143. //
  144. if (!pProcessGuidSuppressList()) {
  145. __leave;
  146. }
  147. TickProgressBar ();
  148. //
  149. // Scan ProgIDs in HKCR for reference to suppressed GUID
  150. //
  151. if (!pProcessProgIdSuppression()) {
  152. __leave;
  153. }
  154. TickProgressBar ();
  155. //
  156. // Scan HKCR for file extensions that need to be suppressed
  157. //
  158. if (!pProcessFileExtensionSuppression()) {
  159. __leave;
  160. }
  161. TickProgressBar ();
  162. //
  163. // Scan Explorer registry for references to suppressed GUIDs
  164. //
  165. if (!pProcessExplorerSuppression()) {
  166. __leave;
  167. }
  168. TickProgressBar ();
  169. //
  170. // Delete all links requiring incompatible OLE objects
  171. //
  172. if (!pSuppressLinksToSuppressedGuids()) {
  173. __leave;
  174. }
  175. TickProgressBar ();
  176. //
  177. // Preserve all files needed by DefaultIcon
  178. //
  179. if (!pDefaultIconPreservation()) {
  180. __leave;
  181. }
  182. TickProgressBar ();
  183. //
  184. // Preserve all INFs needed by ActiveSetup
  185. //
  186. if (!pActiveSetupProcessing ()) {
  187. __leave;
  188. }
  189. TickProgressBar ();
  190. #ifdef DEBUG
  191. // Checked build sanity check
  192. pProcessOleWarnings();
  193. TickProgressBar ();
  194. #endif
  195. ProgressBar_SetComponent (NULL);
  196. Result = TRUE;
  197. }
  198. __finally {
  199. PoolMemDestroyPool (g_OlePool);
  200. }
  201. Ticks = GetTickCount() - Ticks;
  202. g_ProgressBarTime += Ticks * 2;
  203. return Result;
  204. }
  205. DWORD
  206. SuppressOleGuids (
  207. IN DWORD Request
  208. )
  209. {
  210. switch (Request) {
  211. case REQUEST_QUERYTICKS:
  212. return OleReg_GetProgressMax ();
  213. case REQUEST_RUN:
  214. if (!pSuppressOleGuids ()) {
  215. return GetLastError ();
  216. }
  217. else {
  218. return ERROR_SUCCESS;
  219. }
  220. default:
  221. DEBUGMSG ((DBG_ERROR, "Bad parameter in SuppressOleGuids"));
  222. }
  223. return 0;
  224. }
  225. BOOL
  226. pProcessGuidSuppressList (
  227. VOID
  228. )
  229. /*++
  230. Routine Description:
  231. Processes [Suppressed GUIDs] and auto-suppression. Any OLE object that
  232. is listed in Suppressed GUIDs and exists on the machine is suppressed.
  233. Any OLE object that requires a suppressed object is auto-suppressed.
  234. Any OLE object that has a TreatAs entry to a suppressed object is
  235. suppressed.
  236. This routine performs all GUID suppression and must run first.
  237. ("Auto-suppress" refers to the ability to suppress related OLE objects
  238. that are not listed to be suppressed in win95upg.inf.)
  239. Arguments:
  240. none
  241. Return Value:
  242. TRUE if suppression was successful, or FALSE if an error occurred.
  243. --*/
  244. {
  245. HASHTABLE StrTab;
  246. LONG rc;
  247. REGKEY_ENUM e;
  248. HKEY GuidKey;
  249. PCTSTR Data;
  250. TCHAR Node[MEMDB_MAX];
  251. DWORD Count = 0;
  252. //
  253. // Suppress all GUIDs from [Suppressed GUIDs] section of win95upg.inf:
  254. //
  255. // HKLM\SOFTWARE\Classes\CLSID\<GUID>
  256. // HKLM\SOFTWARE\Classes\Interface\<GUID>
  257. //
  258. StrTab = HtAlloc();
  259. if (!StrTab) {
  260. LOG ((LOG_ERROR, "pProcessGuidSuppressList: Cannot create string table"));
  261. return FALSE;
  262. }
  263. pProcessAutoSuppress (StrTab);
  264. __try {
  265. //
  266. // Fill string table of all GUIDs
  267. //
  268. pFillHashTableWithKeyNames (StrTab, g_Win95UpgInf, S_SUPPRESSED_GUIDS);
  269. //
  270. // Search HKCR\CLSID for each GUID
  271. //
  272. if (EnumFirstRegKeyStr (&e, TEXT("HKCR\\CLSID"))) {
  273. do {
  274. //
  275. // Determine if item is suppressed:
  276. //
  277. // - it is on the list in [Suppressed GUIDs] of win95upg.inf
  278. // - it is in the GUIDS category of memdb (from TreatAs)
  279. //
  280. //
  281. // First, determine if it is in [Suppressed GUIDs] or from
  282. // auto suppression.
  283. //
  284. rc = (LONG) HtFindString (StrTab, e.SubKeyName);
  285. if (!rc) {
  286. MemDbBuildKey (Node, MEMDB_CATEGORY_GUIDS, e.SubKeyName, NULL, NULL);
  287. if (MemDbGetValue (Node, NULL)) {
  288. rc = 0;
  289. } else {
  290. rc = -1;
  291. }
  292. }
  293. if (rc != -1) {
  294. pSuppressGuidInClsId (e.SubKeyName);
  295. }
  296. //
  297. // If not suppressed, check for TreatAs, and if TreatAs is found,
  298. // put TreatAs GUID in unsuppressed mapping. This is how we handle
  299. // the case where a GUID that is not normally suppressed, but has a
  300. // TreatAs member that points to a suppressed GUID will be suppressed
  301. // as well.
  302. //
  303. else {
  304. GuidKey = OpenRegKey (e.KeyHandle, e.SubKeyName);
  305. if (GuidKey) {
  306. Data = (PCTSTR) GetRegKeyData (GuidKey, TEXT("TreatAs"));
  307. if (Data) {
  308. //
  309. // Determine if TreatAs GUID is suppressed, and if it
  310. // is, suppress this GUID, otherwise put it on the
  311. // unsuppressed TreatAs list.
  312. //
  313. MemDbBuildKey (
  314. Node,
  315. MEMDB_CATEGORY_GUIDS,
  316. Data,
  317. NULL,
  318. NULL
  319. );
  320. if (MemDbGetValue (Node, NULL)) {
  321. pSuppressGuidInClsId (e.SubKeyName);
  322. } else {
  323. pAddUnsuppressedTreatAsGuid (Data, e.SubKeyName);
  324. }
  325. MemFree (g_hHeap, 0, Data);
  326. }
  327. CloseRegKey (GuidKey);
  328. }
  329. }
  330. Count++;
  331. if (!(Count % 128)) {
  332. TickProgressBar ();
  333. }
  334. } while (EnumNextRegKey (&e));
  335. }
  336. }
  337. __finally {
  338. //
  339. // Clean up string table and memdb
  340. //
  341. HtFree (StrTab);
  342. pRemoveUnsuppressedTreatAsGuids();
  343. }
  344. return TRUE;
  345. }
  346. BOOL
  347. pSuppressLinksToSuppressedGuids (
  348. VOID
  349. )
  350. /*++
  351. Routine Description:
  352. After the GUID suppression list has been made, we scan all the links that
  353. have GUIDs in their command line arguments to find ones that need to be
  354. removed.
  355. Arguments:
  356. none
  357. Return Value:
  358. TRUE if all links were processed, or FALSE if an error occurred.
  359. --*/
  360. {
  361. MEMDB_ENUM e, e2;
  362. TCHAR Node[MEMDB_MAX];
  363. if (MemDbEnumItems (&e, MEMDB_CATEGORY_LINK_GUIDS)) {
  364. do {
  365. //
  366. // Is this GUID suppressed?
  367. //
  368. MemDbBuildKey (Node, MEMDB_CATEGORY_GUIDS, NULL, NULL, e.szName);
  369. if (MemDbGetValue (Node, NULL)) {
  370. //
  371. // Yes -- enumerate all sequencers and delete the associated links
  372. //
  373. if (MemDbGetValueEx (&e2, MEMDB_CATEGORY_LINK_GUIDS, e.szName, NULL)) {
  374. do {
  375. if (MemDbBuildKeyFromOffset (e2.dwValue, Node, 1, NULL)) {
  376. //
  377. // Delete all the operations for the file in Node
  378. //
  379. RemoveAllOperationsFromPath (Node);
  380. //
  381. // Now mark file for text mode delete
  382. //
  383. MarkFileForDelete (Node);
  384. DEBUGMSG ((
  385. DBG_OLEREG,
  386. "Link %s points to an incompatible OLE object; deleting.",
  387. Node
  388. ));
  389. }
  390. } while (MemDbEnumNextValue (&e2));
  391. }
  392. }
  393. } while (MemDbEnumNextValue (&e));
  394. //
  395. // No longer needed -- recover space in memdb
  396. //
  397. MemDbDeleteTree (MEMDB_CATEGORY_LINK_GUIDS);
  398. MemDbDeleteTree (MEMDB_CATEGORY_LINK_STRINGS);
  399. }
  400. return TRUE;
  401. }
  402. BOOL
  403. pProcessFileExtensionSuppression (
  404. VOID
  405. )
  406. /*++
  407. Routine Description:
  408. Suppresses any file extension that depends on a suppressed OLE object.
  409. The GUID suppression must be complete before this routine is called.
  410. Arguments:
  411. none
  412. Return Value:
  413. TRUE if suppression was successful, or FALSE if an error occurred.
  414. --*/
  415. {
  416. REGKEY_ENUM e;
  417. PCTSTR Data;
  418. TCHAR MemDbKey[MEMDB_MAX];
  419. DWORD value;
  420. BOOL Suppress;
  421. //
  422. // Suppresss any file extension that points to suppressed ProgID
  423. //
  424. if (EnumFirstRegKey (&e, HKEY_CLASSES_ROOT)) {
  425. do {
  426. if (_tcsnextc (e.SubKeyName) != TEXT('.')) {
  427. continue;
  428. }
  429. Suppress = FALSE;
  430. Data = (PCTSTR) GetRegKeyData (e.KeyHandle, e.SubKeyName);
  431. if (Data) {
  432. MemDbBuildKey (MemDbKey, MEMDB_CATEGORY_PROGIDS, NULL, NULL, Data);
  433. if (MemDbGetValue (MemDbKey, &value) &&
  434. (value == PROGID_SUPPRESSED)
  435. ) {
  436. //
  437. // This extension points to a suppressed ProgID key, so
  438. // suppress it.
  439. //
  440. Suppress = TRUE;
  441. } else {
  442. //
  443. // Check for this special case: the extension is for a CLSID,
  444. // not for a ProgId.
  445. //
  446. if (StringIMatchCharCount (Data, TEXT("CLSID\\"), 6)) {
  447. if (pIsGuidSuppressed (Data + 6)) {
  448. Suppress = TRUE;
  449. }
  450. }
  451. }
  452. MemFree (g_hHeap, 0, Data);
  453. }
  454. if (!Suppress) {
  455. //
  456. // This tests GUIDs AND suppresses the extension if necessary
  457. //
  458. pIsShellExKeySuppressed (
  459. e.KeyHandle,
  460. e.SubKeyName,
  461. TEXT("ShellEx")
  462. );
  463. }
  464. if (Suppress) {
  465. MemDbBuildKey (
  466. MemDbKey,
  467. MEMDB_CATEGORY_HKLM,
  468. TEXT("SOFTWARE\\Classes"),
  469. NULL,
  470. e.SubKeyName
  471. );
  472. Suppress95RegSetting (MemDbKey, NULL);
  473. }
  474. } while (EnumNextRegKey (&e));
  475. }
  476. return TRUE;
  477. }
  478. #define MEMDB_CATEGORY_TMP_SUPPRESS TEXT("TmpSuppress")
  479. BOOL
  480. pIsCLSIDSuppressed (
  481. IN HKEY ParentKey,
  482. IN PCTSTR ParentKeyName,
  483. IN PCTSTR SubKeyName
  484. )
  485. {
  486. HKEY ClsIdKey;
  487. PCTSTR Data;
  488. BOOL result = FALSE;
  489. ClsIdKey = OpenRegKey (ParentKey, SubKeyName);
  490. if (ClsIdKey) {
  491. Data = GetRegKeyData (ClsIdKey, S_EMPTY);
  492. if (Data) {
  493. result = pIsGuidSuppressed (Data);
  494. DEBUGMSG_IF ((result, DBG_OLEREG, "ProgID %s has incompatible CLSID %s", ParentKeyName, Data));
  495. MemFree (g_hHeap, 0, Data);
  496. }
  497. CloseRegKey (ClsIdKey);
  498. }
  499. return result;
  500. }
  501. VOID
  502. pMarkProgIdAsLostDefault (
  503. IN PCTSTR ProgIdName
  504. )
  505. {
  506. if (ProgIdName) {
  507. MemDbSetValueEx (MEMDB_CATEGORY_PROGIDS, ProgIdName, NULL, NULL, PROGID_LOSTDEFAULT, NULL);
  508. }
  509. }
  510. BOOL
  511. pIsShellKeySuppressed (
  512. IN HKEY ParentKey,
  513. IN PCTSTR ParentKeyName,
  514. IN PCTSTR SubKeyName
  515. )
  516. {
  517. REGKEY_ENUM e;
  518. DWORD Processed, Suppressed;
  519. HKEY ShellKey;
  520. TCHAR key [MEMDB_MAX];
  521. PCTSTR Data;
  522. BOOL defaultKey = TRUE;
  523. PCTSTR defaultCommand = NULL;
  524. BOOL IsvCmdLine = FALSE;
  525. ShellKey = OpenRegKey (ParentKey, SubKeyName);
  526. Processed = Suppressed = 0;
  527. if (ShellKey) {
  528. Data = (PCTSTR) GetRegKeyData (ShellKey, S_EMPTY);
  529. if (Data) {
  530. defaultCommand = DuplicatePathString (Data, 0);
  531. defaultKey = FALSE;
  532. MemFree (g_hHeap, 0, Data);
  533. } else {
  534. defaultKey = TRUE;
  535. }
  536. if (EnumFirstRegKey (&e, ShellKey)) {
  537. do {
  538. Processed ++;
  539. if (defaultCommand) {
  540. defaultKey = StringIMatch (e.SubKeyName, defaultCommand);
  541. }
  542. MemDbBuildKey (key, e.SubKeyName, TEXT("command"), NULL, NULL);
  543. Data = (PCTSTR) GetRegKeyData (ShellKey, key);
  544. if (Data) {
  545. if (pIsCmdLineBadEx (Data, &IsvCmdLine)) {
  546. DEBUGMSG ((
  547. DBG_OLEREG,
  548. "ProgID %s has incompatible shell command: shell\\%s\\command[] = %s",
  549. ParentKeyName,
  550. e.SubKeyName,
  551. Data));
  552. MemDbSetValueEx (
  553. MEMDB_CATEGORY_TMP_SUPPRESS,
  554. ParentKeyName,
  555. SubKeyName,
  556. e.SubKeyName,
  557. 0,
  558. NULL);
  559. if (defaultKey) {
  560. pMarkProgIdAsLostDefault (ParentKeyName);
  561. }
  562. Suppressed ++;
  563. }
  564. else if (IsvCmdLine) {
  565. //
  566. // Keep this setting.
  567. //
  568. MemDbBuildKey (key, MEMDB_CATEGORY_HKLM TEXT("\\SOFTWARE\\Classes"), ParentKeyName, SubKeyName, e.SubKeyName);
  569. SuppressNtRegSetting (key, NULL);
  570. }
  571. MemFree (g_hHeap, 0, Data);
  572. }
  573. defaultKey = FALSE;
  574. } while (EnumNextRegKey (&e));
  575. }
  576. if (defaultCommand) {
  577. FreePathString (defaultCommand);
  578. }
  579. CloseRegKey (ShellKey);
  580. }
  581. if (Processed && (Processed == Suppressed)) {
  582. MemDbBuildKey (key, MEMDB_CATEGORY_TMP_SUPPRESS, ParentKeyName, SubKeyName, NULL);
  583. MemDbDeleteTree (key);
  584. MemDbSetValue (key, 0);
  585. return TRUE;
  586. }
  587. return FALSE;
  588. }
  589. BOOL
  590. pIsProtocolKeySuppressed (
  591. IN HKEY ParentKey,
  592. IN PCTSTR ParentKeyName,
  593. IN PCTSTR SubKeyName
  594. )
  595. {
  596. REGKEY_ENUM e;
  597. DWORD Processed, Suppressed;
  598. HKEY ProtocolKey;
  599. TCHAR key [MEMDB_MAX];
  600. PCTSTR Data;
  601. ProtocolKey = OpenRegKey (ParentKey, SubKeyName);
  602. Processed = Suppressed = 0;
  603. if (ProtocolKey) {
  604. if (EnumFirstRegKey (&e, ProtocolKey)) {
  605. do {
  606. Processed ++;
  607. MemDbBuildKey (key, e.SubKeyName, TEXT("server"), NULL, NULL);
  608. Data = (PCTSTR) GetRegKeyData (ProtocolKey, key);
  609. if (Data) {
  610. if (pIsCmdLineBad (Data)) {
  611. DEBUGMSG ((
  612. DBG_OLEREG,
  613. "ProgID %s has incompatible protocol command: protocol\\%s\\server[] = %s",
  614. ParentKeyName,
  615. e.SubKeyName,
  616. Data));
  617. MemDbSetValueEx (
  618. MEMDB_CATEGORY_TMP_SUPPRESS,
  619. ParentKeyName,
  620. SubKeyName,
  621. e.SubKeyName,
  622. 0,
  623. NULL);
  624. Suppressed ++;
  625. }
  626. MemFree (g_hHeap, 0, Data);
  627. }
  628. } while (EnumNextRegKey (&e));
  629. }
  630. CloseRegKey (ProtocolKey);
  631. }
  632. if (Processed && (Processed == Suppressed)) {
  633. MemDbBuildKey (key, MEMDB_CATEGORY_TMP_SUPPRESS, ParentKeyName, SubKeyName, NULL);
  634. MemDbDeleteTree (key);
  635. MemDbSetValue (key, 0);
  636. return TRUE;
  637. }
  638. return FALSE;
  639. }
  640. BOOL
  641. pIsExtensionsKeySuppressed (
  642. IN HKEY ParentKey,
  643. IN PCTSTR ParentKeyName,
  644. IN PCTSTR SubKeyName
  645. )
  646. {
  647. REGKEY_ENUM e;
  648. REGVALUE_ENUM ev;
  649. DWORD Processed, Suppressed;
  650. HKEY ExtensionsKey;
  651. TCHAR key [MEMDB_MAX];
  652. PCTSTR Data;
  653. ExtensionsKey = OpenRegKey (ParentKey, SubKeyName);
  654. Processed = Suppressed = 0;
  655. if (ExtensionsKey) {
  656. if (EnumFirstRegKey (&e, ExtensionsKey)) {
  657. do {
  658. Processed ++;
  659. Data = (PCTSTR) GetRegKeyData (ExtensionsKey, e.SubKeyName);
  660. if (Data) {
  661. if (pIsGuidSuppressed (Data)) {
  662. DEBUGMSG ((DBG_OLEREG, "ProgID %s has incompatible extensions key %s", ParentKeyName, e.SubKeyName));
  663. MemDbSetValueEx (
  664. MEMDB_CATEGORY_TMP_SUPPRESS,
  665. ParentKeyName,
  666. SubKeyName,
  667. e.SubKeyName,
  668. 0,
  669. NULL);
  670. Suppressed ++;
  671. }
  672. MemFree (g_hHeap, 0, Data);
  673. }
  674. } while (EnumNextRegKey (&e));
  675. }
  676. if (EnumFirstRegValue (&ev, ExtensionsKey)) {
  677. do {
  678. Processed ++;
  679. if (ev.Type == REG_SZ) {
  680. Data = (PCTSTR) GetRegValueData (ExtensionsKey, ev.ValueName);
  681. if (Data) {
  682. if (pIsGuidSuppressed (Data)) {
  683. DEBUGMSG ((DBG_OLEREG, "ProgID %s has incompatible extensions key %s", ParentKeyName, ev.ValueName));
  684. MemDbBuildKey (key, MEMDB_CATEGORY_TMP_SUPPRESS, ParentKeyName, SubKeyName, NULL);
  685. Data = CreateEncodedRegistryString (key, ev.ValueName);
  686. MemDbSetValue (Data, 0);
  687. FreePathString (Data);
  688. Suppressed ++;
  689. }
  690. MemFree (g_hHeap, 0, Data);
  691. }
  692. }
  693. } while (EnumNextRegValue (&ev));
  694. }
  695. CloseRegKey (ExtensionsKey);
  696. }
  697. if (Processed && (Processed == Suppressed)) {
  698. MemDbBuildKey (key, MEMDB_CATEGORY_TMP_SUPPRESS, ParentKeyName, SubKeyName, NULL);
  699. MemDbDeleteTree (key);
  700. MemDbSetValue (key, 0);
  701. return TRUE;
  702. }
  703. return FALSE;
  704. }
  705. BOOL
  706. pIsShellExKeySuppressed (
  707. IN HKEY ParentKey,
  708. IN PCTSTR ParentKeyName,
  709. IN PCTSTR SubKeyName
  710. )
  711. {
  712. REGKEY_ENUM e;
  713. DWORD Processed, Suppressed;
  714. HKEY ShellExKey;
  715. HKEY SubKey;
  716. PTSTR key;
  717. BOOL result = FALSE;
  718. PCTSTR Data;
  719. ShellExKey = OpenRegKey (ParentKey, SubKeyName);
  720. Processed = Suppressed = 0;
  721. if (ShellExKey) {
  722. if (EnumFirstRegKey (&e, ShellExKey)) {
  723. do {
  724. Processed ++;
  725. //
  726. // See if the key itself is a suppressed GUID
  727. //
  728. if (pIsGuidSuppressed (e.SubKeyName)) {
  729. DEBUGMSG ((DBG_OLEREG, "ProgID %s has incompatible shell extension %s", ParentKeyName, e.SubKeyName));
  730. MemDbSetValueEx (
  731. MEMDB_CATEGORY_TMP_SUPPRESS,
  732. ParentKeyName,
  733. SubKeyName,
  734. e.SubKeyName,
  735. 0,
  736. NULL);
  737. Suppressed ++;
  738. continue;
  739. }
  740. //
  741. // See if the default value is a suppressed GUID
  742. //
  743. SubKey = OpenRegKey (ShellExKey, e.SubKeyName);
  744. if (SubKey) {
  745. Data = (PCTSTR) GetRegKeyData (SubKey, S_EMPTY);
  746. if (Data) {
  747. if (pIsGuidSuppressed (Data)) {
  748. DEBUGMSG ((DBG_OLEREG, "ProgID %s has incompatible shell extension %s", ParentKeyName, Data));
  749. MemDbSetValueEx (
  750. MEMDB_CATEGORY_TMP_SUPPRESS,
  751. ParentKeyName,
  752. SubKeyName,
  753. e.SubKeyName,
  754. 0,
  755. NULL);
  756. Suppressed ++;
  757. MemFree (g_hHeap, 0, Data);
  758. CloseRegKey (SubKey);
  759. continue;
  760. }
  761. MemFree (g_hHeap, 0, Data);
  762. }
  763. CloseRegKey (SubKey);
  764. }
  765. //
  766. // Call recursively on this subkey
  767. //
  768. key = JoinPaths (ParentKeyName, SubKeyName);
  769. if (pIsShellExKeySuppressed (ShellExKey, key, e.SubKeyName)) {
  770. MemDbSetValueEx (
  771. MEMDB_CATEGORY_TMP_SUPPRESS,
  772. ParentKeyName,
  773. SubKeyName,
  774. e.SubKeyName,
  775. 0,
  776. NULL);
  777. Suppressed ++;
  778. }
  779. FreePathString (key);
  780. } while (EnumNextRegKey (&e));
  781. if (Processed && (Processed == Suppressed)) {
  782. key = (PTSTR)AllocPathString (MEMDB_MAX);
  783. MemDbBuildKey (key, MEMDB_CATEGORY_TMP_SUPPRESS, ParentKeyName, SubKeyName, NULL);
  784. MemDbDeleteTree (key);
  785. MemDbSetValue (key, 0);
  786. FreePathString (key);
  787. result = TRUE;
  788. }
  789. }
  790. CloseRegKey (ShellExKey);
  791. }
  792. return result;
  793. }
  794. BOOL
  795. pProcessProgIdSuppression (
  796. VOID
  797. )
  798. {
  799. REGKEY_ENUM e;
  800. REGKEY_ENUM subKey;
  801. HKEY ProgIdKey;
  802. DWORD Processed, Suppressed;
  803. TCHAR key [MEMDB_MAX];
  804. MEMDB_ENUM memEnum;
  805. BOOL HarmlessKeyFound;
  806. BOOL ActiveSuppression;
  807. DWORD Count = 0;
  808. if (EnumFirstRegKeyStr (&e, TEXT("HKCR"))) {
  809. do {
  810. if (StringIMatch (e.SubKeyName, TEXT("CLSID"))) {
  811. continue;
  812. }
  813. if (StringIMatch (e.SubKeyName, TEXT("Interface"))) {
  814. continue;
  815. }
  816. if (StringIMatch (e.SubKeyName, TEXT("Applications"))) {
  817. continue;
  818. }
  819. if (StringIMatch (e.SubKeyName, TEXT("TypeLib"))) {
  820. continue;
  821. }
  822. if (_tcsnextc (e.SubKeyName) == TEXT('.')) {
  823. continue;
  824. }
  825. ProgIdKey = OpenRegKey (e.KeyHandle, e.SubKeyName);
  826. if (ProgIdKey) {
  827. Processed = 0;
  828. Suppressed = 0;
  829. HarmlessKeyFound = 0;
  830. ActiveSuppression = FALSE;
  831. if (EnumFirstRegKey (&subKey, ProgIdKey)) {
  832. do {
  833. Processed ++;
  834. if (StringIMatch (subKey.SubKeyName, TEXT("CLSID"))) {
  835. if (pIsCLSIDSuppressed (ProgIdKey, e.SubKeyName, subKey.SubKeyName)) {
  836. AbortRegKeyEnum (&subKey);
  837. Processed = Suppressed = 1;
  838. HarmlessKeyFound = 0;
  839. ActiveSuppression = TRUE;
  840. break;
  841. }
  842. }
  843. if (StringIMatch (subKey.SubKeyName, TEXT("Shell"))) {
  844. if (pIsShellKeySuppressed (ProgIdKey, e.SubKeyName, subKey.SubKeyName)) {
  845. ActiveSuppression = TRUE;
  846. Suppressed ++;
  847. }
  848. }
  849. if (StringIMatch (subKey.SubKeyName, TEXT("Protocol"))) {
  850. if (pIsProtocolKeySuppressed (ProgIdKey, e.SubKeyName, subKey.SubKeyName)) {
  851. ActiveSuppression = TRUE;
  852. Suppressed ++;
  853. }
  854. }
  855. if (StringIMatch (subKey.SubKeyName, TEXT("Extensions"))) {
  856. if (pIsExtensionsKeySuppressed (ProgIdKey, e.SubKeyName, subKey.SubKeyName)) {
  857. ActiveSuppression = TRUE;
  858. Suppressed ++;
  859. }
  860. }
  861. if (StringIMatch (subKey.SubKeyName, TEXT("ShellEx"))) {
  862. if (pIsShellExKeySuppressed (ProgIdKey, e.SubKeyName, subKey.SubKeyName)) {
  863. ActiveSuppression = TRUE;
  864. Suppressed ++;
  865. }
  866. }
  867. if (StringIMatch (subKey.SubKeyName, TEXT("DefaultIcon"))) {
  868. HarmlessKeyFound ++;
  869. }
  870. if (StringIMatch (subKey.SubKeyName, TEXT("Insertable"))) {
  871. HarmlessKeyFound ++;
  872. }
  873. if (StringIMatch (subKey.SubKeyName, TEXT("NotInsertable"))) {
  874. HarmlessKeyFound ++;
  875. }
  876. if (StringIMatch (subKey.SubKeyName, TEXT("ShellFolder"))) {
  877. HarmlessKeyFound ++;
  878. }
  879. } while (EnumNextRegKey (&subKey));
  880. }
  881. if (ActiveSuppression && (Processed == (Suppressed + HarmlessKeyFound))) {
  882. pSuppressProgId (e.SubKeyName);
  883. } else {
  884. MemDbBuildKey (key, MEMDB_CATEGORY_TMP_SUPPRESS, e.SubKeyName, TEXT("*"), NULL);
  885. if (MemDbEnumFirstValue (&memEnum, key, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) {
  886. do {
  887. MemDbBuildKey (key, MEMDB_CATEGORY_HKLM, TEXT("SOFTWARE\\Classes"), e.SubKeyName, memEnum.szName);
  888. Suppress95RegSetting (key, NULL);
  889. } while (MemDbEnumNextValue (&memEnum));
  890. }
  891. }
  892. MemDbBuildKey (key, MEMDB_CATEGORY_TMP_SUPPRESS, e.SubKeyName, NULL, NULL);
  893. MemDbDeleteTree (key);
  894. CloseRegKey (ProgIdKey);
  895. }
  896. Count++;
  897. if (!(Count % 64)) {
  898. TickProgressBar ();
  899. }
  900. } while (EnumNextRegKey (&e));
  901. }
  902. return TRUE;
  903. }
  904. BOOL
  905. pIsGuidSuppressed (
  906. PCTSTR GuidStr
  907. )
  908. /*++
  909. Routine Description:
  910. Determines if a GUID is suppressed or not, and also determines if a
  911. GUID is handled by a migration DLL.
  912. Arguments:
  913. GuidStr - Specifies the GUID to look up, which may or may not contain
  914. the surrounding braces
  915. Return Value:
  916. TRUE if the specified GUID is suppressed, or FALSE if it is not.
  917. The return value is FALSE if the GUID is handled by a migration DLL.
  918. --*/
  919. {
  920. TCHAR Node[MEMDB_MAX];
  921. TCHAR FixedGuid[MAX_GUID];
  922. if (!FixGuid (GuidStr, FixedGuid)) {
  923. return FALSE;
  924. }
  925. if (pIgnoreGuid (FixedGuid)) {
  926. return FALSE;
  927. }
  928. MemDbBuildKey (
  929. Node,
  930. MEMDB_CATEGORY_GUIDS,
  931. NULL,
  932. NULL,
  933. FixedGuid
  934. );
  935. return MemDbGetValue (Node, NULL);
  936. }
  937. BOOL
  938. pScanSubKeysForIncompatibleGuids (
  939. IN PCTSTR ParentKey
  940. )
  941. /*++
  942. Routine Description:
  943. Suppresses the subkeys of the supplied parent key that have text
  944. referencing an incompatible GUID.
  945. Arguments:
  946. ParentKey - Specifies the parent to enumerate keys for
  947. Return Value:
  948. TRUE if everything is OK, or FALSE if an unexpected error occurred during
  949. processing.
  950. --*/
  951. {
  952. REGKEY_ENUM e;
  953. TCHAR Node[MEMDB_MAX];
  954. //
  955. // Enumerate the keys in ParentKey
  956. //
  957. if (EnumFirstRegKeyStr (&e, ParentKey)) {
  958. do {
  959. if (pIsGuidSuppressed (e.SubKeyName)) {
  960. //
  961. // Suppress the enumerated subkey
  962. //
  963. wsprintf (Node, TEXT("%s\\%s"), ParentKey, e.SubKeyName);
  964. Suppress95RegSetting (Node, NULL);
  965. }
  966. } while (EnumNextRegKey (&e));
  967. }
  968. return TRUE;
  969. }
  970. BOOL
  971. pScanValueNamesForIncompatibleGuids (
  972. IN PCTSTR ParentKey
  973. )
  974. /*++
  975. Routine Description:
  976. Suppresses the values of the supplied parent key that have value names
  977. referencing an incompatible GUID.
  978. Arguments:
  979. ParentKey - Specifies the parent to enumerate values of
  980. Return Value:
  981. TRUE if everything is OK, or FALSE if an unexpected error occurred during
  982. processing.
  983. --*/
  984. {
  985. REGVALUE_ENUM e;
  986. HKEY Key;
  987. //
  988. // Enumerate the values in ParentKey
  989. //
  990. Key = OpenRegKeyStr (ParentKey);
  991. if (Key) {
  992. if (EnumFirstRegValue (&e, Key)) {
  993. do {
  994. if (pIsGuidSuppressed (e.ValueName)) {
  995. //
  996. // Suppress the enumerated value
  997. //
  998. Suppress95RegSetting (ParentKey, e.ValueName);
  999. }
  1000. } while (EnumNextRegValue (&e));
  1001. }
  1002. CloseRegKey (Key);
  1003. }
  1004. return TRUE;
  1005. }
  1006. BOOL
  1007. pScanValueDataForIncompatibleGuids (
  1008. IN PCTSTR ParentKey
  1009. )
  1010. /*++
  1011. Routine Description:
  1012. Suppresses the values of the supplied parent key that have value data
  1013. referencing an incompatible GUID.
  1014. Arguments:
  1015. ParentKey - Specifies the parent to enumerate values of
  1016. Return Value:
  1017. TRUE if everything is OK, or FALSE if an unexpected error occurred during
  1018. processing.
  1019. --*/
  1020. {
  1021. REGVALUE_ENUM e;
  1022. HKEY Key;
  1023. PCTSTR Data;
  1024. //
  1025. // Enumerate the values in ParentKey
  1026. //
  1027. Key = OpenRegKeyStr (ParentKey);
  1028. if (Key) {
  1029. if (EnumFirstRegValue (&e, Key)) {
  1030. do {
  1031. Data = GetRegValueString (Key, e.ValueName);
  1032. if (Data) {
  1033. if (pIsGuidSuppressed (Data)) {
  1034. //
  1035. // Suppress the enumerated value
  1036. //
  1037. Suppress95RegSetting (ParentKey, e.ValueName);
  1038. }
  1039. MemFree (g_hHeap, 0, Data);
  1040. }
  1041. } while (EnumNextRegValue (&e));
  1042. }
  1043. CloseRegKey (Key);
  1044. }
  1045. return TRUE;
  1046. }
  1047. BOOL
  1048. pCheckDefaultValueForIncompatibleGuids (
  1049. IN PCTSTR KeyStr
  1050. )
  1051. /*++
  1052. Routine Description:
  1053. Suppresses the specified key if its default value is a suppressed GUID.
  1054. Arguments:
  1055. KeyStr - Specifies key string to process
  1056. Return Value:
  1057. TRUE if everything is OK, or FALSE if an unexpected error occurred during
  1058. processing.
  1059. --*/
  1060. {
  1061. PCTSTR Data;
  1062. HKEY Key;
  1063. //
  1064. // Examine the default value of KeyStr
  1065. //
  1066. Key = OpenRegKeyStr (KeyStr);
  1067. if (Key) {
  1068. Data = GetRegValueString (Key, S_EMPTY);
  1069. CloseRegKey (Key);
  1070. } else {
  1071. Data = NULL;
  1072. }
  1073. if (Data) {
  1074. if (pIsGuidSuppressed (Data)) {
  1075. //
  1076. // Suppress the specified reg key
  1077. //
  1078. Suppress95RegSetting (KeyStr, NULL);
  1079. }
  1080. MemFree (g_hHeap, 0, Data);
  1081. }
  1082. return TRUE;
  1083. }
  1084. BOOL
  1085. pScanDefaultValuesForIncompatibleGuids (
  1086. IN PCTSTR ParentKey
  1087. )
  1088. /*++
  1089. Routine Description:
  1090. Suppresses subkeys that have a default value that is a suppressed GUID.
  1091. Arguments:
  1092. ParentKey - Specifies key string to process
  1093. Return Value:
  1094. TRUE if everything is OK, or FALSE if an unexpected error occurred during
  1095. processing.
  1096. --*/
  1097. {
  1098. REGKEY_ENUM e;
  1099. TCHAR Node[MEMDB_MAX];
  1100. PCTSTR Data;
  1101. HKEY Key;
  1102. //
  1103. // Enumerate the keys in ParentKey
  1104. //
  1105. if (EnumFirstRegKeyStr (&e, ParentKey)) {
  1106. do {
  1107. Key = OpenRegKey (e.KeyHandle, e.SubKeyName);
  1108. if (Key) {
  1109. Data = GetRegValueString (Key, S_EMPTY);
  1110. } else {
  1111. Data = NULL;
  1112. }
  1113. CloseRegKey (Key);
  1114. if (Data) {
  1115. if (pIsGuidSuppressed (Data)) {
  1116. //
  1117. // Suppress the enumerated subkey
  1118. //
  1119. wsprintf (Node, TEXT("%s\\%s"), ParentKey, e.SubKeyName);
  1120. Suppress95RegSetting (Node, NULL);
  1121. }
  1122. MemFree (g_hHeap, 0, Data);
  1123. }
  1124. } while (EnumNextRegKey (&e));
  1125. }
  1126. return TRUE;
  1127. }
  1128. BOOL
  1129. pProcessExplorerSuppression (
  1130. VOID
  1131. )
  1132. /*++
  1133. Routine Description:
  1134. Suppresses the settings in
  1135. HKLM\Software\Microsoft\Windows\CurrentVersion\Explorer\ShellExecuteHooks
  1136. that reference incompatible GUIDs.
  1137. Arguments:
  1138. none
  1139. Return Value:
  1140. TRUE if everything is OK, or FALSE if an unexpected error occurred during
  1141. processing.
  1142. --*/
  1143. {
  1144. BOOL b = TRUE;
  1145. //
  1146. // Suppress Win9x-specific value data in CSSFilters
  1147. //
  1148. if (b) {
  1149. b = pScanValueDataForIncompatibleGuids (S_EXPLORER_CSSFILTERS);
  1150. }
  1151. //
  1152. // Suppress Win9x-specific keys in Desktop\NameSpace
  1153. //
  1154. if (b) {
  1155. b = pScanSubKeysForIncompatibleGuids (S_EXPLORER_DESKTOP_NAMESPACE);
  1156. }
  1157. //
  1158. // Suppress key of FileTypesPropertySheetHook if default value is Win9x-specific
  1159. //
  1160. if (b) {
  1161. b = pCheckDefaultValueForIncompatibleGuids (S_EXPLORER_FILETYPESPROPERTYSHEETHOOK);
  1162. }
  1163. //
  1164. // Suppress subkeys of FindExtensions if default value is Win9x-specific
  1165. //
  1166. if (b) {
  1167. b = pScanDefaultValuesForIncompatibleGuids (S_EXPLORER_FINDEXTENSIONS);
  1168. }
  1169. //
  1170. // Scan MyComputer\NameSpace for subkeys or subkeys with default values
  1171. // pointing to incompatible GUIDs.
  1172. //
  1173. if (b) {
  1174. b = pScanSubKeysForIncompatibleGuids (S_EXPLORER_MYCOMPUTER_NAMESPACE);
  1175. }
  1176. if (b) {
  1177. b = pScanDefaultValuesForIncompatibleGuids (S_EXPLORER_MYCOMPUTER_NAMESPACE);
  1178. }
  1179. //
  1180. // Scan NetworkNeighborhood\NameSpace for subkeys or subkeys with default values
  1181. // pointing to incompatible GUIDs.
  1182. //
  1183. if (b) {
  1184. b = pScanSubKeysForIncompatibleGuids (S_EXPLORER_NETWORKNEIGHBORHOOD_NAMESPACE);
  1185. }
  1186. if (b) {
  1187. b = pScanDefaultValuesForIncompatibleGuids (S_EXPLORER_NETWORKNEIGHBORHOOD_NAMESPACE);
  1188. }
  1189. //
  1190. // Suppress values that reference incompatible GUIDs
  1191. //
  1192. if (b) {
  1193. b = pScanValueNamesForIncompatibleGuids (S_EXPLORER_NEWSHORTCUTHANDLERS);
  1194. }
  1195. //
  1196. // Scan RemoteComputer\NameSpace for subkeys or subkeys with default values
  1197. // pointing to incompatible GUIDs.
  1198. //
  1199. if (b) {
  1200. b = pScanSubKeysForIncompatibleGuids (S_EXPLORER_REMOTECOMPUTER_NAMESPACE);
  1201. }
  1202. if (b) {
  1203. b = pScanDefaultValuesForIncompatibleGuids (S_EXPLORER_REMOTECOMPUTER_NAMESPACE);
  1204. }
  1205. //
  1206. // Scan ShellExecuteHooks for value names referencing incompatible GUIDs
  1207. //
  1208. if (b) {
  1209. b = pScanValueNamesForIncompatibleGuids (S_EXPLORER_SHELLEXECUTEHOOKS);
  1210. }
  1211. //
  1212. // Scan ShellIconOverlayIdentifiers for subkeys with default values referencing
  1213. // incompatible GUIDs
  1214. //
  1215. if (b) {
  1216. b = pScanDefaultValuesForIncompatibleGuids (S_EXPLORER_SHELLICONOVERLAYIDENTIFIERS);
  1217. }
  1218. //
  1219. // Scan VolumeCaches for subkeys with default values referencing
  1220. // incompatible GUIDs
  1221. //
  1222. if (b) {
  1223. b = pScanDefaultValuesForIncompatibleGuids (S_EXPLORER_VOLUMECACHES);
  1224. }
  1225. //
  1226. // Scan ExtShellViews for subkeys that reference incompatible GUIDs
  1227. //
  1228. if (b) {
  1229. b = pScanSubKeysForIncompatibleGuids (S_EXTSHELLVIEWS);
  1230. }
  1231. //
  1232. // Scan Shell Extensions\Approved for value names referencing incompatible
  1233. // GUIDs
  1234. //
  1235. if (b) {
  1236. b = pScanValueNamesForIncompatibleGuids (S_SHELLEXTENSIONS_APPROVED);
  1237. }
  1238. //
  1239. // Scan ShellServiceObjectDelayLoad for value data referencing incompatible
  1240. // GUIDs
  1241. //
  1242. if (b) {
  1243. b = pScanValueDataForIncompatibleGuids (S_SHELLSERVICEOBJECTDELAYLOAD);
  1244. }
  1245. return b;
  1246. }
  1247. BOOL
  1248. ExtractIconIntoDatFile (
  1249. IN PCTSTR LongPath,
  1250. IN INT IconIndex,
  1251. IN OUT PICON_EXTRACT_CONTEXT Context,
  1252. OUT PINT NewIconIndex OPTIONAL
  1253. )
  1254. /*++
  1255. Routine Description:
  1256. ExtractIconIntoDatFile preserves a Win9x icon by extracting it from the 9x
  1257. system. If the EXE and icon index pair are known good, then this function
  1258. returns FALSE. Otherwise, this function extracts the icon and saves it into
  1259. a DAT file for processing in GUI mode setup. If icon extraction fails, then
  1260. the default generic icon from shell32.dll is used.
  1261. Arguments:
  1262. LongPath - Specifies the full path to the PE image
  1263. IconIndex - Specifies the icon index to extract. Negative index values
  1264. provide a specific icon resource ID. Positive index values
  1265. indicate which icon, where 0 is the first icon, 1 is the second
  1266. icon, and so on.
  1267. Context - Specifies the extraction context that gives the DAT file and other
  1268. info (used by icon extraction utilities).
  1269. NewIconIndex - Receives the new icon index in
  1270. %windir%\system32\migicons.exe, if the function returns TRUE.
  1271. Zero otherwise.
  1272. Return Value:
  1273. TRUE if the icon was extracted, or if the icon could not be extracted but
  1274. the icon is not known-good. (The default generic icon is used in this case.)
  1275. FALSE if the icon is known-good and does not need to be extracted.
  1276. --*/
  1277. {
  1278. MULTISZ_ENUM MultiSz;
  1279. TCHAR Node[MEMDB_MAX];
  1280. TCHAR IconId[256];
  1281. TCHAR IconIndexStr[32];
  1282. PCTSTR IconList;
  1283. PCTSTR extPtr;
  1284. INT i;
  1285. DWORD Offset;
  1286. static WORD Seq = 0;
  1287. DWORD OrgSeq;
  1288. BOOL result = FALSE;
  1289. BOOL needDefaultIcon = FALSE;
  1290. if (NewIconIndex) {
  1291. *NewIconIndex = 0;
  1292. }
  1293. __try {
  1294. //
  1295. // Is this a compatible icon binary? If so, return FALSE.
  1296. //
  1297. if (IsIconKnownGood (LongPath, IconIndex)) {
  1298. __leave;
  1299. }
  1300. //
  1301. // From this point on, if we fail to extract the icon, use the default.
  1302. //
  1303. needDefaultIcon = TRUE;
  1304. if (!Seq) {
  1305. //
  1306. // Extract the icon from shell32.dll for the default icon. This is
  1307. // the "generic app" icon. We keep the Win9x generic icon instead
  1308. // of the updated NT generic icon, so there is a clear indication
  1309. // that we failed to extract the right thing from Win9x.
  1310. //
  1311. DEBUGMSG ((DBG_OLEREG, "DefaultIconExtraction: Extracting a default icon"));
  1312. Offset = SetFilePointer (Context->IconImageFile, 0, NULL, FILE_CURRENT);
  1313. wsprintf (Node, TEXT("%s\\system\\shell32.dll"), g_WinDir);
  1314. if (!CopyIcon (Context, Node, TEXT("#1"), 0)) {
  1315. DEBUGMSG ((
  1316. DBG_ERROR,
  1317. "DefaultIconExtraction: Can't extract default icon from %s",
  1318. Node
  1319. ));
  1320. } else {
  1321. MemDbBuildKey (
  1322. Node,
  1323. MEMDB_CATEGORY_ICONS,
  1324. TEXT("%s\\system\\shell32.dll"),
  1325. TEXT("0"),
  1326. NULL
  1327. );
  1328. MemDbSetValueAndFlags (Node, Offset, Seq, 0xffff);
  1329. Seq++;
  1330. }
  1331. }
  1332. //
  1333. // Has the icon been extracted already?
  1334. //
  1335. extPtr = GetFileExtensionFromPath (LongPath);
  1336. if ((IconIndex >= 0) && extPtr && (!StringIMatch (extPtr, TEXT("ICO")))) {
  1337. //
  1338. // IconIndex specifies sequential order; get list of
  1339. // resource IDs and find the right one.
  1340. //
  1341. IconList = ExtractIconNamesFromFile (LongPath, &Context->IconList);
  1342. i = IconIndex;
  1343. IconId[0] = 0;
  1344. if (IconList) {
  1345. if (EnumFirstMultiSz (&MultiSz, IconList)) {
  1346. while (i > 0) {
  1347. if (!EnumNextMultiSz (&MultiSz)) {
  1348. break;
  1349. }
  1350. i--;
  1351. }
  1352. if (!i) {
  1353. StringCopy (IconId, MultiSz.CurrentString);
  1354. }
  1355. ELSE_DEBUGMSG ((DBG_OLEREG, "Icon %i not found in %s", i, LongPath));
  1356. }
  1357. }
  1358. ELSE_DEBUGMSG ((DBG_OLEREG, "Icon %i not found in %s", i, LongPath));
  1359. } else {
  1360. //
  1361. // IconIndex specifies resource ID
  1362. //
  1363. wsprintf (IconId, TEXT("#%i"), -IconIndex);
  1364. }
  1365. if (!IconId[0]) {
  1366. //
  1367. // Failed to find icon or failed to read icon index from EXE
  1368. //
  1369. __leave;
  1370. }
  1371. wsprintf (IconIndexStr, TEXT("%i"), IconIndex);
  1372. MemDbBuildKey (Node, MEMDB_CATEGORY_ICONS, LongPath, IconIndexStr, NULL);
  1373. if (!MemDbGetValueAndFlags (Node, NULL, &OrgSeq)) {
  1374. //
  1375. // Extract the icon and save it in a file. During GUI
  1376. // mode, the icon will be saved to a resource-only DLL.
  1377. //
  1378. DEBUGMSG ((
  1379. DBG_OLEREG,
  1380. "Extracting default icon %s in file %s",
  1381. IconId,
  1382. LongPath
  1383. ));
  1384. Offset = SetFilePointer (Context->IconImageFile, 0, NULL, FILE_CURRENT);
  1385. if (!CopyIcon (Context, LongPath, IconId, 0)) {
  1386. DEBUGMSG ((
  1387. DBG_OLEREG,
  1388. "DefaultIconExtraction: CopyIcon failed for %s, %i (%s)!",
  1389. LongPath,
  1390. IconIndex,
  1391. IconId
  1392. ));
  1393. __leave;
  1394. }
  1395. if (NewIconIndex) {
  1396. *NewIconIndex = (INT) (UINT) Seq;
  1397. }
  1398. MemDbBuildKey (
  1399. Node,
  1400. MEMDB_CATEGORY_ICONS,
  1401. LongPath,
  1402. IconIndexStr,
  1403. NULL
  1404. );
  1405. MemDbSetValueAndFlags (Node, Offset, Seq, 0xffff);
  1406. Seq++;
  1407. } else {
  1408. if (NewIconIndex) {
  1409. *NewIconIndex = (INT) (UINT) OrgSeq;
  1410. }
  1411. }
  1412. result = TRUE;
  1413. }
  1414. __finally {
  1415. //
  1416. // Even if we fail, return success if we want the caller to use
  1417. // the default icon (at index 0).
  1418. //
  1419. result |= needDefaultIcon;
  1420. }
  1421. return result;
  1422. }
  1423. VOID
  1424. pExtractDefaultIcon (
  1425. PCTSTR Data,
  1426. PICON_EXTRACT_CONTEXT Context
  1427. )
  1428. {
  1429. TCHAR ArgZero[MAX_CMDLINE];
  1430. TCHAR LongPath[MAX_TCHAR_PATH];
  1431. INT IconIndex;
  1432. PCTSTR p;
  1433. BOOL LongPathFound = FALSE;
  1434. //
  1435. // Determine if the first arg of the command line points to a
  1436. // deleted file or a file to be replaced
  1437. //
  1438. ExtractArgZeroEx (Data, ArgZero, TEXT(","), FALSE);
  1439. p = (PCTSTR) ((PBYTE) Data + ByteCount (ArgZero));
  1440. while (*p == TEXT(' ')) {
  1441. p++;
  1442. }
  1443. if (*p == TEXT(',')) {
  1444. IconIndex = _ttoi (_tcsinc (p));
  1445. } else {
  1446. IconIndex = 0;
  1447. }
  1448. if (!_tcschr (ArgZero, TEXT('\\'))) {
  1449. if (SearchPath (NULL, ArgZero, NULL, MAX_TCHAR_PATH, LongPath, NULL)) {
  1450. LongPathFound = TRUE;
  1451. }
  1452. }
  1453. if (LongPathFound || OurGetLongPathName (ArgZero, LongPath, MAX_TCHAR_PATH)) {
  1454. if (FILESTATUS_UNCHANGED != GetFileStatusOnNt (LongPath)) {
  1455. ExtractIconIntoDatFile (
  1456. LongPath,
  1457. IconIndex,
  1458. Context,
  1459. NULL
  1460. );
  1461. }
  1462. }
  1463. }
  1464. VOID
  1465. pExtractAllDefaultIcons (
  1466. IN HKEY ParentKey
  1467. )
  1468. {
  1469. HKEY DefaultIconKey;
  1470. REGVALUE_ENUM e;
  1471. PCTSTR Data;
  1472. DefaultIconKey = OpenRegKey (ParentKey, TEXT("DefaultIcon"));
  1473. if (DefaultIconKey) {
  1474. //
  1475. // Check all values in DefaultIcon
  1476. //
  1477. if (EnumFirstRegValue (&e, DefaultIconKey)) {
  1478. do {
  1479. Data = (PCTSTR) GetRegValueString (DefaultIconKey, e.ValueName);
  1480. if (Data) {
  1481. pExtractDefaultIcon (Data, &g_IconContext);
  1482. MemFree (g_hHeap, 0, Data);
  1483. }
  1484. } while (EnumNextRegValue (&e));
  1485. }
  1486. CloseRegKey (DefaultIconKey);
  1487. }
  1488. }
  1489. BOOL
  1490. pDefaultIconPreservation (
  1491. VOID
  1492. )
  1493. /*++
  1494. Routine Description:
  1495. This routine scans the DefaultIcon setting of OLE classes and identifies
  1496. any default icon that will be lost by deletion. A copy of the icon is
  1497. stored away in a directory called MigIcons.
  1498. Arguments:
  1499. none
  1500. Return Value:
  1501. TRUE unless an unexpected error occurs.
  1502. --*/
  1503. {
  1504. REGKEY_ENUM e;
  1505. HKEY ProgIdKey;
  1506. TCHAR key[MEMDB_MAX];
  1507. DWORD value;
  1508. //
  1509. // Scan all ProgIDs, looking for default icons that are currently
  1510. // set for deletion. Once found, don't delete the icon, but instead
  1511. // copy the image to %windir%\setup\temp\migicons.
  1512. //
  1513. if (EnumFirstRegKeyStr (&e, TEXT("HKCR"))) {
  1514. do {
  1515. //
  1516. // We extract the icons for all ProgIds that survive on NT.
  1517. //
  1518. MemDbBuildKey (key, MEMDB_CATEGORY_PROGIDS, e.SubKeyName, NULL, NULL);
  1519. if (!MemDbGetValue (key, &value) ||
  1520. (value != PROGID_SUPPRESSED)
  1521. ) {
  1522. ProgIdKey = OpenRegKey (e.KeyHandle, e.SubKeyName);
  1523. if (ProgIdKey) {
  1524. pExtractAllDefaultIcons (ProgIdKey);
  1525. CloseRegKey (ProgIdKey);
  1526. }
  1527. }
  1528. } while (EnumNextRegKey (&e));
  1529. }
  1530. if (EnumFirstRegKeyStr (&e, TEXT("HKCR\\CLSID"))) {
  1531. do {
  1532. //
  1533. // We extract the icons for all GUIDs (even for the suppressed ones).
  1534. // The reason is that if NT installs this GUID we do want to replace
  1535. // the NT default icon with the 9x icon.
  1536. //
  1537. ProgIdKey = OpenRegKey (e.KeyHandle, e.SubKeyName);
  1538. if (ProgIdKey) {
  1539. pExtractAllDefaultIcons (ProgIdKey);
  1540. CloseRegKey (ProgIdKey);
  1541. }
  1542. } while (EnumNextRegKey (&e));
  1543. }
  1544. return TRUE;
  1545. }
  1546. BOOL
  1547. pActiveSetupProcessing (
  1548. VOID
  1549. )
  1550. /*++
  1551. Routine Description:
  1552. This routine scans the Active Setup key and suppresses incompatible GUIDs
  1553. and Installed Components subkeys that reference deleted files. If a
  1554. stub path references an INF, we preserve the INF.
  1555. Arguments:
  1556. none
  1557. Return Value:
  1558. TRUE unless an unexpected error occurs.
  1559. --*/
  1560. {
  1561. REGKEY_ENUM e;
  1562. HKEY InstalledComponentKey;
  1563. PCTSTR Data;
  1564. TCHAR ArgZero[MAX_CMDLINE];
  1565. TCHAR LongPath[MAX_TCHAR_PATH];
  1566. TCHAR Node[MEMDB_MAX];
  1567. PCTSTR p;
  1568. PTSTR q;
  1569. PTSTR DupText;
  1570. DWORD status;
  1571. //
  1572. // Scan all Installed Components
  1573. //
  1574. if (EnumFirstRegKeyStr (&e, S_ACTIVESETUP)) {
  1575. do {
  1576. //
  1577. // Determine if the GUID is suppressed, and if it is, suppress
  1578. // the entire Installed Components setting
  1579. //
  1580. if (pIsGuidSuppressed (e.SubKeyName)) {
  1581. wsprintf (Node, TEXT("%s\\%s"), S_ACTIVESETUP, e.SubKeyName);
  1582. Suppress95RegSetting (Node, NULL);
  1583. continue;
  1584. }
  1585. //
  1586. // Get StubPath and determine if it references incompatible files
  1587. //
  1588. InstalledComponentKey = OpenRegKey (e.KeyHandle, e.SubKeyName);
  1589. if (InstalledComponentKey) {
  1590. __try {
  1591. Data = GetRegValueString (InstalledComponentKey, TEXT("StubPath"));
  1592. if (Data) {
  1593. __try {
  1594. //
  1595. // Determine if the first arg of the command line points to a
  1596. // deleted file
  1597. //
  1598. ExtractArgZeroEx (Data, ArgZero, TEXT(","), FALSE);
  1599. if (OurGetLongPathName (ArgZero, LongPath, MAX_TCHAR_PATH)) {
  1600. status = GetFileStatusOnNt (LongPath);
  1601. if ((status & FILESTATUS_DELETED) == FILESTATUS_DELETED) {
  1602. //
  1603. // Suppress this key
  1604. //
  1605. wsprintf (Node, TEXT("%s\\%s"), S_ACTIVESETUP, e.SubKeyName);
  1606. Suppress95RegSetting (Node, NULL);
  1607. continue;
  1608. }
  1609. }
  1610. DupText = NULL;
  1611. //
  1612. // Scan command line for an LaunchINFSectionEx reference
  1613. //
  1614. p = _tcsistr (Data, TEXT("LaunchINF"));
  1615. if (p) {
  1616. p = _tcschr (p, TEXT(' '));
  1617. }
  1618. if (p) {
  1619. while (*p == TEXT(' ')) {
  1620. p = _tcsinc (p);
  1621. }
  1622. //
  1623. // Instead of deleting this file, lets move it
  1624. //
  1625. DupText = DuplicateText (p);
  1626. q = _tcschr (DupText, TEXT(','));
  1627. if (q) {
  1628. *q = 0;
  1629. }
  1630. }
  1631. if (!DupText) {
  1632. p = _tcsistr (Data, TEXT("InstallHInfSection"));
  1633. if (p) {
  1634. p = _tcschr (p, TEXT(' '));
  1635. if (p) {
  1636. p = _tcschr (_tcsinc (p), TEXT(' '));
  1637. // p points to end of section name or NULL
  1638. }
  1639. if (p) {
  1640. p = _tcschr (_tcsinc (p), TEXT(' '));
  1641. // p points to end of number of NULL
  1642. }
  1643. if (p) {
  1644. p = _tcsinc (p);
  1645. DupText = DuplicateText (p);
  1646. }
  1647. }
  1648. }
  1649. if (DupText) {
  1650. if (OurGetLongPathName (DupText, LongPath, MAX_TCHAR_PATH)) {
  1651. status = GetFileStatusOnNt (LongPath);
  1652. if ((status & FILESTATUS_DELETED) == FILESTATUS_DELETED) {
  1653. //
  1654. // Suppress the setting
  1655. //
  1656. wsprintf (Node, TEXT("%s\\%s"), S_ACTIVESETUP, e.SubKeyName);
  1657. Suppress95RegSetting (Node, NULL);
  1658. }
  1659. }
  1660. FreeText (DupText);
  1661. }
  1662. }
  1663. __finally {
  1664. MemFree (g_hHeap, 0, Data);
  1665. }
  1666. }
  1667. }
  1668. __finally {
  1669. CloseRegKey (InstalledComponentKey);
  1670. }
  1671. }
  1672. } while (EnumNextRegKey (&e));
  1673. }
  1674. return TRUE;
  1675. }
  1676. #ifdef DEBUG
  1677. PCTSTR g_ProgIdFileRefKeys[] = {
  1678. g_DefaultIcon,
  1679. NULL
  1680. };
  1681. TCHAR g_BaseInterface[] = TEXT("BaseInterface");
  1682. TCHAR g_ProxyStubClsId[] = TEXT("ProxyStubClsId");
  1683. TCHAR g_ProxyStubClsId32[] = TEXT("ProxyStubClsId32");
  1684. TCHAR g_TypeLib[] = TEXT("ProxyStubClsId32");
  1685. PCTSTR g_InterfaceRefKeys[] = {
  1686. g_BaseInterface,
  1687. g_ProxyStubClsId,
  1688. g_ProxyStubClsId32,
  1689. g_TypeLib,
  1690. NULL
  1691. };
  1692. BOOL
  1693. pProcessOleWarnings (
  1694. VOID
  1695. )
  1696. /*++
  1697. Routine Description:
  1698. For checked builds, this routine examines the linkage of the entire
  1699. OLE registry and identifies problems such as abandoned links and
  1700. broken inheritance.
  1701. Arguments:
  1702. none
  1703. Return Value:
  1704. TRUE unless an unexpected error occurs.
  1705. --*/
  1706. {
  1707. REGKEY_ENUM e;
  1708. HKEY ClsIdKey;
  1709. HKEY InterfaceKey;
  1710. PCTSTR Data;
  1711. TCHAR Node[MEMDB_MAX];
  1712. BOOL Suppressed;
  1713. INT i;
  1714. //
  1715. // Search HKCR\CLSID for problems
  1716. //
  1717. if (EnumFirstRegKeyStr (&e, TEXT("HKCR\\CLSID"))) {
  1718. do {
  1719. //
  1720. // Verify key is not garbage
  1721. //
  1722. if (!FixGuid (e.SubKeyName, e.SubKeyName)) {
  1723. continue;
  1724. }
  1725. ClsIdKey = OpenRegKey (e.KeyHandle, e.SubKeyName);
  1726. //
  1727. // Determine if this GUID is suppressed
  1728. //
  1729. MemDbBuildKey (Node, MEMDB_CATEGORY_GUIDS, NULL, NULL, e.SubKeyName);
  1730. Suppressed = MemDbGetValue (Node, NULL);
  1731. if (ClsIdKey) {
  1732. if (!Suppressed) {
  1733. //
  1734. // Unsuppressed GUID checks
  1735. //
  1736. // AutoConvertTo
  1737. Data = (PCTSTR) GetRegKeyData (ClsIdKey, TEXT("AutoConvertTo"));
  1738. if (Data) {
  1739. //
  1740. // Check if AutoConvertTo is pointing to suppressed GUID
  1741. //
  1742. MemDbBuildKey (Node, MEMDB_CATEGORY_GUIDS, NULL, NULL, Data);
  1743. if (MemDbGetValue (Node, NULL)) {
  1744. DEBUGMSG ((DBG_WARNING,
  1745. "GUID %s points to deleted GUID %s",
  1746. e.SubKeyName, Data
  1747. ));
  1748. pAddOleWarning (
  1749. MSG_OBJECT_POINTS_TO_DELETED_GUID,
  1750. ClsIdKey,
  1751. e.SubKeyName
  1752. );
  1753. }
  1754. MemFree (g_hHeap, 0, Data);
  1755. }
  1756. // File references
  1757. for (i = 0 ; g_FileRefKeys[i] ; i++) {
  1758. Data = (PCTSTR) GetRegKeyData (ClsIdKey, g_FileRefKeys[i]);
  1759. if (Data) {
  1760. //
  1761. // Check if the file in Data is in Win9xFileLocation for
  1762. // all users
  1763. //
  1764. pSuppressGuidIfCmdLineBad (
  1765. NULL,
  1766. Data,
  1767. ClsIdKey,
  1768. e.SubKeyName
  1769. );
  1770. MemFree (g_hHeap, 0, Data);
  1771. }
  1772. }
  1773. } else {
  1774. //
  1775. // Suppressed GUID checks
  1776. //
  1777. Data = (PCTSTR) GetRegKeyData (ClsIdKey, TEXT("Interface"));
  1778. if (Data) {
  1779. MemDbBuildKey (Node, MEMDB_CATEGORY_GUIDS, NULL, NULL, Data);
  1780. if (MemDbGetValue (Node, NULL)) {
  1781. DEBUGMSG ((DBG_WARNING,
  1782. "Suppressed GUID %s has Interface reference "
  1783. "to unsuppressed %s (potential leak)",
  1784. e.SubKeyName, Data));
  1785. pAddOleWarning (MSG_GUID_LEAK, ClsIdKey, e.SubKeyName);
  1786. }
  1787. MemFree (g_hHeap, 0, Data);
  1788. }
  1789. }
  1790. CloseRegKey (ClsIdKey);
  1791. }
  1792. } while (EnumNextRegKey (&e));
  1793. }
  1794. //
  1795. // Look for problems with an HKCR\Interface entry
  1796. //
  1797. if (EnumFirstRegKeyStr (&e, TEXT("HKCR\\Interface"))) {
  1798. do {
  1799. InterfaceKey = OpenRegKey (e.KeyHandle, e.SubKeyName);
  1800. MemDbBuildKey (Node, MEMDB_CATEGORY_GUIDS, NULL, NULL, e.SubKeyName);
  1801. Suppressed = MemDbGetValue (Node, NULL);
  1802. if (InterfaceKey) {
  1803. for (i = 0 ; g_InterfaceRefKeys[i] ; i++) {
  1804. Data = (PCTSTR) GetRegKeyData (
  1805. InterfaceKey,
  1806. g_InterfaceRefKeys[i]
  1807. );
  1808. if (Data) {
  1809. //
  1810. // Check if reference to other GUID is suppressed
  1811. //
  1812. MemDbBuildKey (Node, MEMDB_CATEGORY_GUIDS, NULL, NULL, Data);
  1813. if (MemDbGetValue (Node, NULL)) {
  1814. if (!Suppressed) {
  1815. TCHAR CompleteKey[MAX_REGISTRY_KEY];
  1816. //
  1817. // Interface is not suppressed, but it points to a
  1818. // suppressed interface.
  1819. //
  1820. wsprintf (
  1821. CompleteKey,
  1822. TEXT("HKCR\\Interface\\%s"),
  1823. e.SubKeyName
  1824. );
  1825. DEBUGMSG ((
  1826. DBG_WARNING,
  1827. "GUID %s %s subkey points to suppressed GUID %s",
  1828. e.SubKeyName,
  1829. g_InterfaceRefKeys[i],
  1830. Data
  1831. ));
  1832. pAddOleWarning (
  1833. MSG_INTERFACE_BROKEN,
  1834. InterfaceKey,
  1835. CompleteKey
  1836. );
  1837. }
  1838. } else {
  1839. if (Suppressed) {
  1840. TCHAR CompleteKey[MAX_REGISTRY_KEY];
  1841. //
  1842. // Interface is suppressed, but it points to an
  1843. // unsuppressed interface.
  1844. //
  1845. wsprintf (
  1846. CompleteKey,
  1847. TEXT("HKCR\\Interface\\%s"),
  1848. e.SubKeyName
  1849. );
  1850. DEBUGMSG ((
  1851. DBG_WARNING,
  1852. "Suppressed GUID %s %s subkey points to "
  1853. "unsuppressed GUID %s (potential leak)",
  1854. e.SubKeyName,
  1855. g_InterfaceRefKeys[i],
  1856. Data
  1857. ));
  1858. pAddOleWarning (
  1859. MSG_POTENTIAL_INTERFACE_LEAK,
  1860. InterfaceKey,
  1861. CompleteKey
  1862. );
  1863. }
  1864. }
  1865. MemFree (g_hHeap, 0, Data);
  1866. }
  1867. }
  1868. CloseRegKey (InterfaceKey);
  1869. }
  1870. } while (EnumNextRegKey (&e));
  1871. }
  1872. return TRUE;
  1873. }
  1874. #endif
  1875. VOID
  1876. pProcessAutoSuppress (
  1877. IN OUT HASHTABLE StrTab
  1878. )
  1879. /*++
  1880. Routine Description:
  1881. Performs a number of tests to identify OLE objects that are not compatible
  1882. with Windows NT. The tests are based on a list of incompatible files stored
  1883. in memdb. Any OLE object that depends on a file that will not exist on NT
  1884. is automatically suppressed.
  1885. Arguments:
  1886. StrTab - Specifies the string table that holds suppressed GUIDs
  1887. Return Value:
  1888. none
  1889. --*/
  1890. {
  1891. REGKEY_ENUM e, eVer, eNr;
  1892. HKEY ClsIdKey;
  1893. HKEY TypeLibKey;
  1894. HKEY VerKey;
  1895. HKEY NrKey;
  1896. HKEY SubSysKey;
  1897. TCHAR Node[MEMDB_MAX];
  1898. BOOL Suppressed;
  1899. PCTSTR Data;
  1900. BOOL ValidNr;
  1901. BOOL ValidVer;
  1902. BOOL ValidGUID;
  1903. //
  1904. // Search HKCR\CLSID for objects that require a Win95-specific binary
  1905. //
  1906. DEBUGMSG ((DBG_OLEREG, "Looking for CLSID problems..."));
  1907. if (EnumFirstRegKeyStr (&e, TEXT("HKCR\\CLSID"))) {
  1908. do {
  1909. //
  1910. // Verify key is not garbage
  1911. //
  1912. if (!FixGuid (e.SubKeyName, e.SubKeyName)) {
  1913. DEBUGMSG ((
  1914. DBG_OLEREG,
  1915. "Garbage key ignored: HKCR\\CLSID\\%s",
  1916. e.SubKeyName
  1917. ));
  1918. continue;
  1919. }
  1920. ClsIdKey = OpenRegKey (e.KeyHandle, e.SubKeyName);
  1921. //
  1922. // Determine if this GUID is suppressed
  1923. //
  1924. MemDbBuildKey (Node, MEMDB_CATEGORY_GUIDS, NULL, NULL, e.SubKeyName);
  1925. Suppressed = MemDbGetValue (Node, NULL);
  1926. if (ClsIdKey) {
  1927. if (!Suppressed) {
  1928. //
  1929. // Unsuppressed GUID checks
  1930. //
  1931. // AutoConvertTo
  1932. Data = (PCTSTR) GetRegKeyData (ClsIdKey, TEXT("AutoConvertTo"));
  1933. if (Data) {
  1934. //
  1935. // Check if AutoConvertTo is pointing to suppressed GUID
  1936. //
  1937. MemDbBuildKey (Node, MEMDB_CATEGORY_GUIDS, NULL, NULL, Data);
  1938. if (MemDbGetValue (Node, NULL)) {
  1939. DEBUGMSG ((
  1940. DBG_OLEREG,
  1941. "GUID %s points to deleted GUID %s -> "
  1942. "Auto-suppressed",
  1943. e.SubKeyName,
  1944. Data
  1945. ));
  1946. pAddGuidToTable (StrTab, e.SubKeyName);
  1947. }
  1948. MemFree (g_hHeap, 0, Data);
  1949. }
  1950. // File references
  1951. pSuppressGuidIfBadCmdLine (StrTab, ClsIdKey, e.SubKeyName);
  1952. }
  1953. CloseRegKey (ClsIdKey);
  1954. }
  1955. } while (EnumNextRegKey (&e));
  1956. }
  1957. DEBUGMSG ((DBG_OLEREG, "Looking for TypeLib problems..."));
  1958. if (EnumFirstRegKeyStr (&e, TEXT("HKCR\\TypeLib"))) {
  1959. do {
  1960. //
  1961. // Verify key is not garbage
  1962. //
  1963. if (!FixGuid (e.SubKeyName, e.SubKeyName)) {
  1964. DEBUGMSG ((
  1965. DBG_OLEREG,
  1966. "Garbage key ignored: HKCR\\TypeLib\\%s",
  1967. e.SubKeyName
  1968. ));
  1969. continue;
  1970. }
  1971. TypeLibKey = OpenRegKey (e.KeyHandle, e.SubKeyName);
  1972. if (TypeLibKey) {
  1973. MemDbBuildKey (Node, MEMDB_CATEGORY_GUIDS, NULL, NULL, e.SubKeyName);
  1974. Suppressed = MemDbGetValue (Node, NULL);
  1975. if (!Suppressed) {
  1976. ValidGUID = FALSE;
  1977. //
  1978. // Enumerating all versions
  1979. //
  1980. if (EnumFirstRegKey (&eVer, TypeLibKey)) {
  1981. do {
  1982. VerKey = OpenRegKey (eVer.KeyHandle, eVer.SubKeyName);
  1983. if (VerKey) {
  1984. ValidVer = FALSE;
  1985. //
  1986. // Enumerating all subkeys except HELPDIR and FLAGS
  1987. //
  1988. if (EnumFirstRegKey (&eNr, VerKey)) {
  1989. do {
  1990. if (StringIMatch (eNr.SubKeyName, TEXT("FLAGS"))) {
  1991. continue;
  1992. }
  1993. if (StringIMatch (eNr.SubKeyName, TEXT("HELPDIR"))) {
  1994. continue;
  1995. }
  1996. NrKey = OpenRegKey (eNr.KeyHandle, eNr.SubKeyName);
  1997. if (NrKey) {
  1998. ValidNr = FALSE;
  1999. SubSysKey = OpenRegKey (NrKey, TEXT("win16"));
  2000. if (SubSysKey) {
  2001. Data = GetRegValueString (SubSysKey, TEXT(""));
  2002. if (Data) {
  2003. if (pIsCmdLineBad (Data)) {
  2004. wsprintf (
  2005. Node,
  2006. "%s\\SOFTWARE\\Classes\\TypeLib\\%s\\%s\\%s\\%s",
  2007. MEMDB_CATEGORY_HKLM,
  2008. e.SubKeyName,
  2009. eVer.SubKeyName,
  2010. eNr.SubKeyName,
  2011. TEXT("win16")
  2012. );
  2013. Suppress95RegSetting(Node, NULL);
  2014. }
  2015. else {
  2016. ValidNr = TRUE;
  2017. }
  2018. MemFree (g_hHeap, 0, Data);
  2019. }
  2020. CloseRegKey (SubSysKey);
  2021. }
  2022. SubSysKey = OpenRegKey (NrKey, TEXT("win32"));
  2023. if (SubSysKey) {
  2024. Data = GetRegValueString (SubSysKey, TEXT(""));
  2025. if (Data) {
  2026. if (pIsCmdLineBad (Data)) {
  2027. wsprintf (
  2028. Node,
  2029. "%s\\SOFTWARE\\Classes\\TypeLib\\%s\\%s\\%s\\%s",
  2030. MEMDB_CATEGORY_HKLM,
  2031. e.SubKeyName,
  2032. eVer.SubKeyName,
  2033. eNr.SubKeyName,
  2034. TEXT("win32")
  2035. );
  2036. Suppress95RegSetting(Node, NULL);
  2037. }
  2038. else {
  2039. ValidNr = TRUE;
  2040. }
  2041. MemFree (g_hHeap, 0, Data);
  2042. }
  2043. CloseRegKey (SubSysKey);
  2044. }
  2045. CloseRegKey (NrKey);
  2046. if (!ValidNr) {
  2047. wsprintf (
  2048. Node,
  2049. "%s\\SOFTWARE\\Classes\\TypeLib\\%s\\%s\\%s",
  2050. MEMDB_CATEGORY_HKLM,
  2051. e.SubKeyName,
  2052. eVer.SubKeyName,
  2053. eNr.SubKeyName
  2054. );
  2055. Suppress95RegSetting(Node, NULL);
  2056. }
  2057. else {
  2058. ValidVer = TRUE;
  2059. }
  2060. }
  2061. } while (EnumNextRegKey (&eNr));
  2062. }
  2063. CloseRegKey (VerKey);
  2064. if (!ValidVer) {
  2065. wsprintf (
  2066. Node,
  2067. "%s\\SOFTWARE\\Classes\\TypeLib\\%s\\%s",
  2068. MEMDB_CATEGORY_HKLM,
  2069. e.SubKeyName,
  2070. eVer.SubKeyName
  2071. );
  2072. Suppress95RegSetting(Node, NULL);
  2073. }
  2074. else {
  2075. ValidGUID = TRUE;
  2076. }
  2077. }
  2078. } while (EnumNextRegKey (&eVer));
  2079. }
  2080. if (!ValidGUID) {
  2081. DEBUGMSG ((
  2082. DBG_OLEREG,
  2083. "TypeLib GUID %s is suppressed",
  2084. e.SubKeyName
  2085. ));
  2086. MemDbSetValueEx (MEMDB_CATEGORY_GUIDS, NULL, NULL, e.SubKeyName, 0, NULL);
  2087. }
  2088. }
  2089. CloseRegKey (TypeLibKey);
  2090. }
  2091. } while (EnumNextRegKey (&e));
  2092. }
  2093. }
  2094. BOOL
  2095. pGetFirstRegKeyThatHasGuid (
  2096. OUT PGUIDKEYSEARCH EnumPtr,
  2097. IN HKEY RootKey
  2098. )
  2099. /*++
  2100. Routine Description:
  2101. pGetFirstRegKeyThatHasGuid starts an enumeration of an OLE object's
  2102. ShellEx subkey. This subkey has zero or more handlers, and each
  2103. handler has zero or more GUIDs. This ShellEx enumerator returns
  2104. the first GUID subkey found under the supplied root.
  2105. Arguments:
  2106. EnumPtr - An uninitialized GUIDKEYSEARCH struct that is used
  2107. to maintain enumeration state and to report the match
  2108. found.
  2109. RootKey - The registry key to begin enumerating at.
  2110. Return Value:
  2111. TRUE if a GUID was found in a handler that is a subkey of RootKey, or
  2112. FALSE if no GUIDs were found.
  2113. --*/
  2114. {
  2115. EnumPtr->State = GUIDKEYSEARCH_FIRST_HANDLER;
  2116. EnumPtr->RootKey = RootKey;
  2117. return pGetNextRegKeyThatHasGuid (EnumPtr);
  2118. }
  2119. BOOL
  2120. pGetNextRegKeyThatHasGuid (
  2121. IN OUT PGUIDKEYSEARCH EnumPtr
  2122. )
  2123. /*++
  2124. Routine Description:
  2125. The "next" enumerator for ShellEx registry key enumeration. This
  2126. enumerator returns the next instance of a GUID in the registry
  2127. (under an OLE object's ShellEx subkey).
  2128. Arguments:
  2129. EnumPtr - The GUIDKEYSEARCH structure used to begin the search.
  2130. If a GUID is found, this structure holds the location
  2131. of the GUID key found.
  2132. Return Value:
  2133. TRUE if a subkey identifying a GUID was found, or FALSE if no
  2134. more instances exist.
  2135. --*/
  2136. {
  2137. BOOL Found = FALSE;
  2138. do {
  2139. switch (EnumPtr->State) {
  2140. case GUIDKEYSEARCH_FIRST_HANDLER:
  2141. //
  2142. // Get the name of the first handler
  2143. //
  2144. if (!EnumFirstRegKey (&EnumPtr->Handlers, EnumPtr->RootKey)) {
  2145. return FALSE;
  2146. }
  2147. EnumPtr->State = GUIDKEYSEARCH_FIRST_GUID;
  2148. break;
  2149. case GUIDKEYSEARCH_NEXT_HANDLER:
  2150. //
  2151. // Get the name of the next handler
  2152. //
  2153. if (!EnumNextRegKey (&EnumPtr->Handlers)) {
  2154. return FALSE;
  2155. }
  2156. EnumPtr->State = GUIDKEYSEARCH_FIRST_GUID;
  2157. break;
  2158. case GUIDKEYSEARCH_FIRST_GUID:
  2159. //
  2160. // Begin GUID key enumeration
  2161. //
  2162. EnumPtr->HandlerKey = OpenRegKey (EnumPtr->Handlers.KeyHandle,
  2163. EnumPtr->Handlers.SubKeyName);
  2164. // Assume no GUIDs
  2165. EnumPtr->State = GUIDKEYSEARCH_NEXT_HANDLER;
  2166. if (EnumPtr->HandlerKey) {
  2167. if (EnumFirstRegKey (&EnumPtr->Guids, EnumPtr->HandlerKey)) {
  2168. //
  2169. // There is at least one key that may be a GUID in this handler
  2170. //
  2171. Found = FixGuid (EnumPtr->Guids.SubKeyName, EnumPtr->Guids.SubKeyName);
  2172. EnumPtr->State = GUIDKEYSEARCH_NEXT_GUID;
  2173. } else {
  2174. CloseRegKey (EnumPtr->HandlerKey);
  2175. }
  2176. }
  2177. break;
  2178. case GUIDKEYSEARCH_NEXT_GUID:
  2179. //
  2180. // Continue GUID key enumeration
  2181. //
  2182. if (!EnumNextRegKey (&EnumPtr->Guids)) {
  2183. CloseRegKey (EnumPtr->HandlerKey);
  2184. EnumPtr->State = GUIDKEYSEARCH_NEXT_HANDLER;
  2185. } else {
  2186. Found = FixGuid (EnumPtr->Guids.SubKeyName, EnumPtr->Guids.SubKeyName);
  2187. }
  2188. break;
  2189. }
  2190. } while (!Found);
  2191. EnumPtr->KeyName = EnumPtr->Guids.SubKeyName;
  2192. return TRUE;
  2193. }
  2194. DWORD
  2195. pCountGuids (
  2196. IN PGUIDKEYSEARCH EnumPtr
  2197. )
  2198. /*++
  2199. Routine Description:
  2200. Given a valid EnumPtr, this function will count the total number
  2201. of GUIDs in the current handler.
  2202. Arguments:
  2203. EnumPtr - Must be a valid GUIDKEYSEARCH structure, prepared by
  2204. pGetFirstRegKeyThatHasGuid or pGetNextRegKeyThatHasGuid.
  2205. Return Value:
  2206. The count of valid GUIDs for the current handler.
  2207. --*/
  2208. {
  2209. REGKEY_ENUM e;
  2210. DWORD Count = 0;
  2211. //
  2212. // Count the number of GUIDs in the current handler
  2213. //
  2214. if (EnumPtr->State == GUIDKEYSEARCH_NEXT_GUID) {
  2215. if (EnumFirstRegKey (&e, EnumPtr->HandlerKey)) {
  2216. do {
  2217. Count++;
  2218. } while (EnumNextRegKey (&e));
  2219. }
  2220. }
  2221. return Count;
  2222. }
  2223. BOOL
  2224. pFillHashTableWithKeyNames (
  2225. OUT HASHTABLE Table,
  2226. IN HINF InfFile,
  2227. IN PCTSTR Section
  2228. )
  2229. /*++
  2230. Routine Description:
  2231. A general-purpose INF-to-string table copy routine. Takes the keys
  2232. in a given section and adds them to the supplied string table.
  2233. Arguments:
  2234. Table - A pointer to an initialize string table
  2235. InfFile - The handle to an open INF file
  2236. Section - Section within the INF file containing strings
  2237. Return Value:
  2238. TRUE if no errors were encountered.
  2239. --*/
  2240. {
  2241. INFCONTEXT ic;
  2242. TCHAR Key[MAX_ENCODED_RULE];
  2243. if (SetupFindFirstLine (InfFile, Section, NULL, &ic)) {
  2244. do {
  2245. if (SetupGetStringField (&ic, 0, Key, MAX_ENCODED_RULE, NULL)) {
  2246. HtAddString (Table, Key);
  2247. }
  2248. ELSE_DEBUGMSG ((
  2249. DBG_WARNING,
  2250. "No key for line in section %s (line %u)",
  2251. Section,
  2252. ic.Line
  2253. ));
  2254. } while (SetupFindNextLine (&ic, &ic));
  2255. }
  2256. ELSE_DEBUGMSG ((DBG_WARNING, "Section %s is empty", Section));
  2257. return TRUE;
  2258. }
  2259. BOOL
  2260. pSuppressProgId (
  2261. PCTSTR ProgIdName
  2262. )
  2263. /*++
  2264. Routine Description:
  2265. Suppresses a ProgID registry key.
  2266. Arguments:
  2267. ProgIdName - The name of the OLE ProgID to suppress
  2268. Return Value:
  2269. TRUE if ProgIdName is a valid ProgID on the system.
  2270. --*/
  2271. {
  2272. TCHAR RegKey[MAX_REGISTRY_KEY];
  2273. HKEY ProgIdKey;
  2274. TCHAR MemDbKey[MEMDB_MAX];
  2275. if (*ProgIdName) {
  2276. wsprintf (RegKey, TEXT("HKCR\\%s"), ProgIdName);
  2277. ProgIdKey = OpenRegKeyStr (RegKey);
  2278. if (ProgIdKey) {
  2279. CloseRegKey (ProgIdKey);
  2280. DEBUGMSG ((DBG_OLEREG, "Suppressing ProgId: %s", ProgIdName));
  2281. MemDbSetValueEx (MEMDB_CATEGORY_PROGIDS, NULL, NULL, ProgIdName, PROGID_SUPPRESSED, NULL);
  2282. MemDbBuildKey(MemDbKey,MEMDB_CATEGORY_HKLM, TEXT("SOFTWARE\\Classes"), NULL, ProgIdName);
  2283. Suppress95RegSetting(MemDbKey,NULL);
  2284. return TRUE;
  2285. }
  2286. }
  2287. return FALSE;
  2288. }
  2289. VOID
  2290. pSuppressGuidInClsId (
  2291. IN PCTSTR Guid
  2292. )
  2293. /*++
  2294. Routine Description:
  2295. Does all the work necessary to suppress a GUID and its associated
  2296. ProgID (if it has one).
  2297. Arguments:
  2298. Guid - The string identifing a GUID that is in HKCR\CLSID
  2299. Return Value:
  2300. none
  2301. --*/
  2302. {
  2303. TCHAR Node[MEMDB_MAX];
  2304. MEMDB_ENUM e;
  2305. HKEY GuidKey;
  2306. PCTSTR Data;
  2307. MYASSERT (IsGuid (Guid, TRUE));
  2308. if (pIgnoreGuid (Guid)) {
  2309. return;
  2310. }
  2311. //
  2312. // - Remove it from UGUIDS memdb category
  2313. // - Add it to GUIDS memdb category
  2314. // - Suppress HKLM\SOFTWARE\Classes\CLSID\<GUID>
  2315. // - Suppress HKLM\SOFTWARE\Classes\Interface\<GUID>
  2316. //
  2317. // Suppress all TreatAs GUIDs
  2318. if (MemDbGetValueEx (&e, MEMDB_CATEGORY_UNSUP_GUIDS, Guid, NULL)) {
  2319. do {
  2320. pSuppressGuidInClsId (e.szName);
  2321. } while (MemDbEnumNextValue (&e));
  2322. }
  2323. // Remove TreatAs GUIDs
  2324. MemDbBuildKey (Node, MEMDB_CATEGORY_UNSUP_GUIDS, Guid, NULL, NULL);
  2325. MemDbDeleteTree (Node);
  2326. // Add to suppressed GUID category and to registry suppression
  2327. MemDbSetValueEx (MEMDB_CATEGORY_GUIDS, NULL, NULL, Guid, 0, NULL);
  2328. // Get ProgID of GUID
  2329. wsprintf (Node, TEXT("HKCR\\CLSID\\%s"), Guid);
  2330. GuidKey = OpenRegKeyStr (Node);
  2331. if (GuidKey) {
  2332. BOOL ProgIdFound = FALSE;
  2333. // Suppress ProgIDs
  2334. Data = (PCTSTR) GetRegKeyData (GuidKey, TEXT("ProgID"));
  2335. if (Data) {
  2336. ProgIdFound |= pSuppressProgId (Data);
  2337. MemFree (g_hHeap, 0, Data);
  2338. }
  2339. // Version-independent ProgIDs
  2340. Data = (PCTSTR) GetRegKeyData (GuidKey, TEXT("VersionIndependentProgID"));
  2341. if (Data) {
  2342. ProgIdFound |= pSuppressProgId (Data);
  2343. MemFree (g_hHeap, 0, Data);
  2344. }
  2345. // Possibly the default name
  2346. Data = (PCTSTR) GetRegValueData (GuidKey, TEXT(""));
  2347. if (Data) {
  2348. ProgIdFound |= pSuppressProgId (Data);
  2349. MemFree (g_hHeap, 0, Data);
  2350. }
  2351. DEBUGMSG_IF ((
  2352. !ProgIdFound,
  2353. DBG_OLEREG,
  2354. "The suppressed registry key %s has no associated ProgID",
  2355. Node
  2356. ));
  2357. CloseRegKey (GuidKey);
  2358. }
  2359. }
  2360. VOID
  2361. pAddUnsuppressedTreatAsGuid (
  2362. PCTSTR Guid,
  2363. PCTSTR TreatAsGuid
  2364. )
  2365. /*++
  2366. Routine Description:
  2367. Keeps track of unsuppressed TreatAs GUIDs that need further processing.
  2368. Arguments:
  2369. Guid - A string identifying the GUID that should be treated as
  2370. another GUID
  2371. TreatAsGuid - The replacement GUID
  2372. Return Value:
  2373. none
  2374. --*/
  2375. {
  2376. MemDbSetValueEx (MEMDB_CATEGORY_UNSUP_GUIDS, Guid, NULL, TreatAsGuid, 0, NULL);
  2377. }
  2378. VOID
  2379. pRemoveUnsuppressedTreatAsGuids (
  2380. VOID
  2381. )
  2382. /*++
  2383. Routine Description:
  2384. Cleanup function for unsuppressed GUIDs.
  2385. Arguments:
  2386. none
  2387. Return Value:
  2388. none
  2389. --*/
  2390. {
  2391. TCHAR Node[MEMDB_MAX];
  2392. MemDbBuildKey (Node, MEMDB_CATEGORY_UNSUP_GUIDS, NULL, NULL, NULL);
  2393. MemDbDeleteTree (Node);
  2394. }
  2395. VOID
  2396. pAddOleWarning (
  2397. IN WORD MsgId,
  2398. IN HKEY Object, OPTIONAL
  2399. IN PCTSTR KeyName
  2400. )
  2401. /*++
  2402. Routine Description:
  2403. Adds a warning to the incompatibility report. It loads the human-readable
  2404. name from the specified OLE registry key. The message is formatted with
  2405. the human-readable object name as the first parameter and the registry
  2406. location as the second parameter.
  2407. Arguments:
  2408. MsgID - Supplies the ID of the message to display
  2409. Object - Specifies the handle of a registry key whos default value
  2410. is a human-readable object name.
  2411. KeyName - The registry key location
  2412. Return Value:
  2413. none
  2414. --*/
  2415. {
  2416. PCTSTR Data;
  2417. if (Object) {
  2418. Data = (PCTSTR) GetRegValueData (Object, S_EMPTY);
  2419. } else {
  2420. Data = NULL;
  2421. }
  2422. LOG ((LOG_WARNING, (PCSTR)MsgId, Data ? Data : S_EMPTY, KeyName, g_Win95Name));
  2423. if (Data) {
  2424. MemFree (g_hHeap, 0, Data);
  2425. }
  2426. }
  2427. VOID
  2428. pSuppressGuidIfBadCmdLine (
  2429. IN HASHTABLE StrTab,
  2430. IN HKEY ClsIdKey,
  2431. IN PCTSTR GuidStr
  2432. )
  2433. /*++
  2434. Routine Description:
  2435. Suppresses the specified GUID if its CLSID settings reference a Win9x-
  2436. specific binary. The suppression is written to a string table which
  2437. is later transfered to memdb. The transfer operation suppresses all
  2438. linkage to the GUID.
  2439. Arguments:
  2440. StrTab - The table that holds a list of suppressed GUIDs
  2441. ClsIdKey - The registry handle of a subkey of HKCR\CLSID
  2442. GuidStr - The GUID to suppress if an invalid command line is found
  2443. Return Value:
  2444. none
  2445. --*/
  2446. {
  2447. PCTSTR Data;
  2448. INT i;
  2449. BOOL b;
  2450. MYASSERT (IsGuid (GuidStr, TRUE));
  2451. if (pIgnoreGuid (GuidStr)) {
  2452. return;
  2453. }
  2454. for (i = 0 ; g_FileRefKeys[i] ; i++) {
  2455. Data = (PCTSTR) GetRegKeyData (ClsIdKey, g_FileRefKeys[i]);
  2456. if (Data) {
  2457. //
  2458. // Check if the file in Data is in Win9xFileLocation for any user
  2459. //
  2460. b = pSuppressGuidIfCmdLineBad (
  2461. StrTab,
  2462. Data,
  2463. ClsIdKey,
  2464. GuidStr
  2465. );
  2466. MemFree (g_hHeap, 0, Data);
  2467. if (b) {
  2468. return;
  2469. }
  2470. }
  2471. }
  2472. }
  2473. VOID
  2474. pSuppressProgIdWithBadCmdLine (
  2475. IN HKEY ProgId,
  2476. IN PCTSTR ProgIdStr
  2477. )
  2478. /*++
  2479. Routine Description:
  2480. Suppresses the specified ProgId if it references a Win9x-specific binary.
  2481. The suppression is written directly to memdb.
  2482. This function is called after all Suppressed GUIDs have been processed,
  2483. and is used to suppress OLE objects that are not caught by an invalid
  2484. HKCR\CLSID entry.
  2485. Arguments:
  2486. ProgId - The registry handle of a subkey of the root of HKCR
  2487. ProgIdStr - The name of the ProgID key to suppress if a bad cmd line is
  2488. found.
  2489. Return Value:
  2490. none
  2491. --*/
  2492. {
  2493. PCTSTR Data;
  2494. INT i;
  2495. for (i = 0 ; g_FileRefKeys[i]; i++) {
  2496. Data = (PCTSTR) GetRegKeyData (ProgId, g_FileRefKeys[i]);
  2497. if (Data) {
  2498. //
  2499. // Check if the file in Data is in Win9xFileLocation for any user
  2500. //
  2501. if (pIsCmdLineBad (Data)) {
  2502. DEBUGMSG ((DBG_OLEREG, "ProgID %s has incompatible command line %s", ProgId, Data));
  2503. pSuppressProgId (ProgIdStr);
  2504. break;
  2505. }
  2506. MemFree (g_hHeap, 0, Data);
  2507. }
  2508. }
  2509. }
  2510. VOID
  2511. pAddGuidToTable (
  2512. IN HASHTABLE Table,
  2513. IN PCTSTR GuidStr
  2514. )
  2515. /*++
  2516. Routine Description:
  2517. Adds a GUID to a string table. For checked builds, it does a quick
  2518. test to see how many GUIDs get suppressed more than once.
  2519. Arguments:
  2520. Table - Specifies table that receives the GUID entry
  2521. GuidStr - Specifies the string of the GUID
  2522. Return Value:
  2523. none
  2524. --*/
  2525. {
  2526. #ifdef DEBUG
  2527. //
  2528. // Just for yuks, let's see if we're wasting time by suppressing
  2529. // an already suppressed GUID...
  2530. //
  2531. DWORD rc;
  2532. if (HtFindString (Table, GuidStr)) {
  2533. DEBUGMSG ((DBG_OLEREG, "FYI - GUID %s is already suppressed", GuidStr));
  2534. }
  2535. MYASSERT (IsGuid (GuidStr, TRUE));
  2536. #endif
  2537. HtAddString (Table, GuidStr);
  2538. }
  2539. BOOL
  2540. pSuppressGuidIfCmdLineBad (
  2541. IN OUT HASHTABLE StrTab, OPTIONAL
  2542. IN PCTSTR CmdLine,
  2543. IN HKEY DescriptionKey,
  2544. IN PCTSTR GuidStr OPTIONAL
  2545. )
  2546. /*++
  2547. Routine Description:
  2548. Suppresses an OLE object if the specified command line contains a Win9x-
  2549. specific binary. Only the first argument of the command line is examined;
  2550. an other arguments that cannot be upgraded are ignored.
  2551. Arguments:
  2552. StrTab - Specifies the table that holds the list of suppressed GUIDs.
  2553. If NULL, a warning will be displayed, and GuidKey must not be
  2554. NULL.
  2555. CmdLine - Specifies the command line to examine
  2556. DescriptionKey - Specifies a key whos default value is the description of the
  2557. object.
  2558. GuidStr - Specifies the GUID string. This parameter is optional only
  2559. if StrTab is NULL.
  2560. Return Value:
  2561. TRUE if CmdLine is incompatible, FALSE otherwise.
  2562. --*/
  2563. {
  2564. BOOL b = FALSE;
  2565. if (GuidStr) {
  2566. MYASSERT (IsGuid (GuidStr, TRUE));
  2567. if (pIgnoreGuid (GuidStr)) {
  2568. return TRUE;
  2569. }
  2570. }
  2571. if (pIsCmdLineBad (CmdLine)) {
  2572. //
  2573. // OLE object points to deleted file
  2574. //
  2575. b = TRUE;
  2576. if (!StrTab) {
  2577. // Warning!!
  2578. DEBUGMSG ((DBG_WARNING,
  2579. "Reg key %s points to deleted file %s",
  2580. GuidStr, CmdLine));
  2581. pAddOleWarning (
  2582. MSG_OBJECT_POINTS_TO_DELETED_FILE,
  2583. DescriptionKey,
  2584. GuidStr
  2585. );
  2586. } else {
  2587. MYASSERT (GuidStr);
  2588. DEBUGMSG ((
  2589. DBG_OLEREG,
  2590. "Auto-suppressed %s because it requires a Win9x-specific file: %s",
  2591. GuidStr,
  2592. CmdLine
  2593. ));
  2594. pAddGuidToTable (StrTab, GuidStr);
  2595. }
  2596. }
  2597. return b;
  2598. }
  2599. BOOL
  2600. pSearchSubkeyDataForBadFiles (
  2601. IN OUT HASHTABLE SuppressTable,
  2602. IN HKEY KeyHandle,
  2603. IN PCTSTR LastKey,
  2604. IN PCTSTR GuidStr,
  2605. IN HKEY DescriptionKey
  2606. )
  2607. /*++
  2608. Routine Description:
  2609. Scans a number of OLE settings for bad command lines, including the
  2610. object's command and the default icon binary. If a reference to a
  2611. Win9x-specific binary is detected, the GUID is suppressed.
  2612. This function recurses through all subkeys of the OLE object.
  2613. Arguments:
  2614. SuppressTable - Specifies the table that holds the suppressed GUID list
  2615. KeyHandle - An open registry key of an OLE object to be examined
  2616. recursively.
  2617. LastKey - Specifies the name of the OLE object's subkey being
  2618. processed. Special processing is done for some subkeys.
  2619. GuidStr - The GUID of the OLE object.
  2620. DescriptionKey - A handle to the key who's default value identifies the
  2621. OLE object's key.
  2622. Return Value:
  2623. TRUE if an incompatible cmd line was found, FALSE otherwise.
  2624. --*/
  2625. {
  2626. REGKEY_ENUM ek;
  2627. REGVALUE_ENUM ev;
  2628. HKEY SubKeyHandle;
  2629. PCTSTR Data;
  2630. BOOL b;
  2631. MYASSERT (IsGuid (GuidStr, FALSE));
  2632. if (StringIMatch (LastKey, TEXT("Command")) ||
  2633. StringIMatch (LastKey, g_DefaultIcon)
  2634. ) {
  2635. if (EnumFirstRegValue (&ev, KeyHandle)) {
  2636. do {
  2637. Data = (PCTSTR) GetRegValueData (KeyHandle, ev.ValueName);
  2638. if (Data) {
  2639. // If this thing has a path name somewhere, process it
  2640. b = pSuppressGuidIfCmdLineBad (
  2641. SuppressTable,
  2642. Data,
  2643. DescriptionKey,
  2644. GuidStr
  2645. );
  2646. MemFree (g_hHeap, 0, Data);
  2647. if (b) {
  2648. return TRUE;
  2649. }
  2650. }
  2651. } while (EnumNextRegValue (&ev));
  2652. }
  2653. }
  2654. if (EnumFirstRegKey (&ek, KeyHandle)) {
  2655. do {
  2656. SubKeyHandle = OpenRegKey (ek.KeyHandle, ek.SubKeyName);
  2657. if (SubKeyHandle) {
  2658. b = pSearchSubkeyDataForBadFiles (
  2659. SuppressTable,
  2660. SubKeyHandle,
  2661. ek.SubKeyName,
  2662. GuidStr,
  2663. DescriptionKey
  2664. );
  2665. CloseRegKey (SubKeyHandle);
  2666. if (b) {
  2667. AbortRegKeyEnum (&ek);
  2668. return TRUE;
  2669. }
  2670. }
  2671. } while (EnumNextRegKey (&ek));
  2672. }
  2673. return FALSE;
  2674. }
  2675. BOOL
  2676. pIsCmdLineBadEx (
  2677. IN PCTSTR CmdLine,
  2678. OUT PBOOL UsableIsvCmdLine OPTIONAL
  2679. )
  2680. /*++
  2681. Routine Description:
  2682. Determines if the specified command line's first argument is listed in
  2683. memdb's Win9xFileLocation category. If it is listed, and the file is
  2684. marked for permanent removal, TRUE is returned. If it is not listed,
  2685. or if it is listed but has an NT equivalent, FALSE is returned.
  2686. Arguments:
  2687. CmdLine - Specifies the command line to examine
  2688. UsableIsvCmdLine - Optional variable that receives wether the
  2689. command line contains a compatible third
  2690. party cmd line.
  2691. Return Value:
  2692. TRUE if command line requires Win9x-specific binaries, FALSE if
  2693. the command line uses a valid binary or is not a command line.
  2694. --*/
  2695. {
  2696. BOOL FileMarked = FALSE;
  2697. TCHAR ArgZero[MAX_CMDLINE];
  2698. TCHAR LongPath[MAX_TCHAR_PATH];
  2699. DWORD status;
  2700. if (UsableIsvCmdLine) {
  2701. *UsableIsvCmdLine = FALSE;
  2702. }
  2703. //
  2704. // Determine if the first arg of the command line points to a
  2705. // deleted (or moved) file
  2706. //
  2707. ExtractArgZeroEx (CmdLine, ArgZero, TEXT(","), FALSE);
  2708. if (OurGetLongPathName (ArgZero, LongPath, MAX_TCHAR_PATH)) {
  2709. status = GetFileStatusOnNt (LongPath);
  2710. if ((status & FILESTATUS_DELETED) == FILESTATUS_DELETED) {
  2711. return TRUE;
  2712. }
  2713. else if (UsableIsvCmdLine) {
  2714. status = GetOperationsOnPath (LongPath);
  2715. if ((status & OPERATION_OS_FILE) != OPERATION_OS_FILE) {
  2716. *UsableIsvCmdLine = TRUE;
  2717. }
  2718. }
  2719. }
  2720. ELSE_DEBUGMSG ((
  2721. DBG_OLEREG,
  2722. "pIsCmdLineBad: Cannot get full path name; assuming %s is not a command line",
  2723. ArgZero
  2724. ));
  2725. return FALSE;
  2726. }
  2727. BOOL
  2728. pIsCmdLineBad (
  2729. IN PCTSTR CmdLine
  2730. )
  2731. {
  2732. return pIsCmdLineBadEx (CmdLine, NULL);
  2733. }