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.

2111 lines
52 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. merge.c
  5. Abstract:
  6. Registry merge code
  7. Author:
  8. Jim Schmidt (jimschm) 17-Feb-1997
  9. Revision History:
  10. jimschm 23-Sep-1998 String mapping mechanism
  11. jimschm 24-Mar-1998 Added more complex hkcr processing
  12. --*/
  13. #include "pch.h"
  14. #include "mergep.h"
  15. static PCTSTR g_InfFileName;
  16. BOOL g_ProcessRenameTable = FALSE;
  17. DWORD g_ProgressBarCounter;
  18. HKEY g_DuHandle;
  19. BOOL
  20. pForceCopy (
  21. HINF InfFile
  22. );
  23. BOOL
  24. pForceCopyFromMemDb (
  25. VOID
  26. );
  27. BOOL
  28. pCreateRenameTable (
  29. IN HINF InfFile,
  30. OUT PVOID *RenameTablePtr
  31. );
  32. BOOL
  33. pProcessRenameTable (
  34. IN PVOID RenameTable
  35. );
  36. BOOL
  37. pSpecialConversion (
  38. IN HINF InfFile,
  39. IN PCTSTR User,
  40. IN PVOID RenameTable
  41. );
  42. BOOL
  43. pProcessSuppressList (
  44. IN HINF InfFile,
  45. IN PCTSTR SectionName
  46. );
  47. BOOL
  48. pProcessHardwareSuppressList (
  49. IN HINF InfFile
  50. );
  51. BOOL
  52. pSuppressNTDefaults (
  53. IN HINF InfFile,
  54. IN PCTSTR SectionName
  55. );
  56. BOOL
  57. pDontCombineWithDefaults (
  58. IN HINF InfFile,
  59. IN PCTSTR SectionName
  60. );
  61. BOOL
  62. pForceNTDefaults (
  63. IN HINF InfFile,
  64. IN PCTSTR SectionName
  65. );
  66. BOOL
  67. pForceNTDefaultsHack (
  68. IN HINF InfFile,
  69. IN PCTSTR SectionName
  70. );
  71. BOOL
  72. pMergeWin95WithUser (
  73. IN PVOID RenameTable
  74. );
  75. BOOL
  76. pSpecialConversionNT (
  77. IN HINF InfFile,
  78. IN PCTSTR User,
  79. IN BOOL PerUser
  80. );
  81. BOOL
  82. pMergeNTDefaultsWithUser (
  83. IN HINF InfFile
  84. );
  85. BOOL
  86. pCopyWin95ToSystem (
  87. VOID
  88. );
  89. BOOL
  90. pMergeWin95WithSystem (
  91. VOID
  92. );
  93. BOOL
  94. pDeleteAfterMigration (
  95. IN HINF InfFile
  96. );
  97. FILTERRETURN
  98. SuppressFilter95 (
  99. IN CPDATAOBJECT SrcObjectPtr,
  100. IN CPDATAOBJECT DestObjectPtr, OPTIONAL
  101. IN FILTERTYPE FilterType,
  102. IN PVOID DontCare
  103. );
  104. //
  105. // Globals
  106. //
  107. POOLHANDLE g_TempPool;
  108. POOLHANDLE g_RenamePool;
  109. PMAPSTRUCT g_CompleteMatchMap;
  110. PMAPSTRUCT g_SubStringMap;
  111. BOOL
  112. WINAPI
  113. Merge_Entry (
  114. IN HINSTANCE hinstDLL,
  115. IN DWORD dwReason,
  116. IN PVOID lpv
  117. )
  118. /*++
  119. Routine Description:
  120. DllMain is called after the C runtime is initialized, and its purpose
  121. is to initialize the globals for this process.
  122. Arguments:
  123. hinstDLL - (OS-supplied) Instance handle for the DLL
  124. dwReason - (OS-supplied) Type of initialization or termination
  125. lpv - (OS-supplied) Unused
  126. Return Value:
  127. TRUE because DLL always initializes properly.
  128. --*/
  129. {
  130. switch (dwReason)
  131. {
  132. case DLL_PROCESS_ATTACH:
  133. if(!pSetupInitializeUtils()) {
  134. return FALSE;
  135. }
  136. g_CompleteMatchMap = CreateStringMapping();
  137. g_SubStringMap = CreateStringMapping();
  138. break;
  139. case DLL_PROCESS_DETACH:
  140. DestroyStringMapping (g_CompleteMatchMap);
  141. DestroyStringMapping (g_SubStringMap);
  142. pSetupUninitializeUtils();
  143. break;
  144. }
  145. return TRUE;
  146. }
  147. BOOL
  148. MergeRegistry (
  149. IN PCTSTR FileName,
  150. IN PCTSTR User
  151. )
  152. {
  153. HINF hInf; // handle to the INF being processed
  154. BOOL b = FALSE; // Return value
  155. PVOID RenameTable = NULL;
  156. BOOL LogonAccount = FALSE;
  157. BOOL DefaultUserAccount = FALSE;
  158. g_ProgressBarCounter = 0;
  159. //
  160. // Open the INF
  161. //
  162. g_InfFileName = FileName;
  163. hInf = InfOpenInfFile (FileName);
  164. if (hInf == INVALID_HANDLE_VALUE) {
  165. LOG ((LOG_ERROR, "MergeRegistry: SetupOpenInfFile failed for %s", FileName));
  166. return FALSE;
  167. }
  168. g_TempPool = PoolMemInitNamedPool ("Merge: temp pool");
  169. g_RenamePool = PoolMemInitNamedPool ("Merge: Rename pool");
  170. if (!g_TempPool || !g_RenamePool) {
  171. DEBUGMSG ((DBG_ERROR, "MergeRegistry: Can't init pool"));
  172. goto c0;
  173. }
  174. PoolMemSetMinimumGrowthSize (g_TempPool, 16384);
  175. if (User) {
  176. SetCurrentUserW (g_FixedUserName);
  177. }
  178. //
  179. // Perform forced copy of Win95 registry, build rename table,
  180. // execute registry value conversions, convert types, and mark
  181. // specified keys as suppressed.
  182. //
  183. if (!pForceCopy (hInf)) {
  184. goto c0;
  185. }
  186. if (!User) {
  187. if (!pForceCopyFromMemDb ()) {
  188. goto c0;
  189. }
  190. }
  191. if (!pCreateRenameTable (hInf, &RenameTable)) {
  192. goto c0;
  193. }
  194. //
  195. // Identify the logon account or default user account
  196. //
  197. if (User) {
  198. if (*User == 0 || StringIMatch (User, S_DOT_DEFAULT)) {
  199. DEBUGMSG ((DBG_NAUSEA, "The logon user account is indicated by user name '%s'", User));
  200. LogonAccount = TRUE;
  201. } else if (StringIMatch (User, S_DEFAULT_USER)) {
  202. DEBUGMSG ((DBG_NAUSEA, "The default user account template is indicated by user name '%s'", User));
  203. DefaultUserAccount = TRUE;
  204. }
  205. }
  206. //
  207. // Prepare flags for registry merging
  208. //
  209. if (!pProcessSuppressList (hInf, S_MERGE_WIN9X_SUPPRESS)) {
  210. goto c0;
  211. }
  212. if (User) {
  213. //
  214. // These functions read usermig.inf and set flags
  215. // for the keys, key trees or values, as specified in
  216. // the INF.
  217. //
  218. if (!pSuppressNTDefaults (hInf, S_MERGE_WINNT_SUPPRESS)) {
  219. goto c0;
  220. }
  221. if (!pDontCombineWithDefaults (hInf, S_MERGE_DONT_COMBINE_WITH_DEFAULT)) {
  222. goto c0;
  223. }
  224. if (!pForceNTDefaults (hInf, S_MERGE_FORCE_NT_DEFAULTS)) {
  225. goto c0;
  226. }
  227. if (LogonAccount) {
  228. if (!pProcessSuppressList (hInf, S_MERGE_WIN9X_SUPPRESS_LU)) {
  229. goto c0;
  230. }
  231. }
  232. if (DefaultUserAccount) {
  233. if (!pProcessSuppressList (hInf, S_MERGE_WIN9X_SUPPRESS_DU)) {
  234. goto c0;
  235. }
  236. }
  237. g_DuHandle = OpenRegKeyStr (L"hklm\\" S_MAPPED_DEFAULT_USER_KEY);
  238. } else {
  239. if (!pForceNTDefaults (hInf, S_MERGE_FORCE_NT_DEFAULTS)) {
  240. goto c0;
  241. }
  242. if (!pProcessHardwareSuppressList (hInf)) {
  243. goto c0;
  244. }
  245. }
  246. if (!pSpecialConversion (hInf, User, RenameTable)) {
  247. goto c0;
  248. }
  249. //
  250. // Perform merge
  251. //
  252. if (User) {
  253. // User merge
  254. if (!pMergeWin95WithUser (RenameTable)) {
  255. goto c0;
  256. }
  257. if (!pSpecialConversionNT (hInf, User, TRUE)) {
  258. goto c0;
  259. }
  260. if (!LogonAccount && !DefaultUserAccount) {
  261. // Non-default user, not logon prompt account
  262. if (!pMergeNTDefaultsWithUser (hInf)) {
  263. goto c0;
  264. }
  265. }
  266. }
  267. else {
  268. // Workstation merge
  269. if (!pCopyWin95ToSystem()) {
  270. goto c0;
  271. }
  272. if (!pForceNTDefaultsHack (hInf, S_MERGE_FORCE_NT_DEFAULTS)) {
  273. goto c0;
  274. }
  275. if (!pMergeWin95WithSystem()) {
  276. goto c0;
  277. }
  278. if (!CopyHardwareProfiles (hInf)) {
  279. goto c0;
  280. }
  281. TickProgressBar ();
  282. if (!pSpecialConversionNT (hInf, NULL, FALSE)) {
  283. goto c0;
  284. }
  285. TickProgressBar ();
  286. }
  287. g_ProcessRenameTable = TRUE;
  288. b = pProcessRenameTable (RenameTable);
  289. TickProgressBar ();
  290. g_ProcessRenameTable = FALSE;
  291. //
  292. // Once we are done with the complete registry merge, process the special section
  293. // [Delete After Migration]
  294. //
  295. if (!pDeleteAfterMigration (hInf)) {
  296. LOG((LOG_ERROR,"Registry Merge: Delete After Migration failed."));
  297. goto c0;
  298. }
  299. c0:
  300. if (RenameTable) {
  301. pSetupStringTableDestroy (RenameTable);
  302. }
  303. if (User) {
  304. SetCurrentUserW (NULL);
  305. }
  306. if (g_TempPool) {
  307. PoolMemDestroyPool (g_TempPool);
  308. }
  309. if (g_RenamePool) {
  310. PoolMemDestroyPool (g_RenamePool);
  311. }
  312. if (g_DuHandle) {
  313. CloseRegKey (g_DuHandle);
  314. g_DuHandle = NULL;
  315. }
  316. InfCloseInfFile (hInf);
  317. return b;
  318. }
  319. PTSTR
  320. pGetStringFromObjectData (
  321. IN CPDATAOBJECT ObPtr
  322. )
  323. {
  324. PTSTR p;
  325. PTSTR end;
  326. //
  327. // Value type has to be a registry object
  328. //
  329. if (!DoesObjectHaveValue (ObPtr) ||
  330. !IsRegistryTypeSpecified (ObPtr)
  331. ) {
  332. return NULL;
  333. }
  334. if (ObPtr->Type == REG_DWORD) {
  335. return NULL;
  336. }
  337. if (ObPtr->Value.Size & 1) {
  338. return NULL;
  339. }
  340. p = (PTSTR) ObPtr->Value.Buffer;
  341. end = (PTSTR) ((PBYTE) p + ObPtr->Value.Size);
  342. if ((end - p) >= MAX_PATH) {
  343. return NULL;
  344. }
  345. if (ObPtr->Type == REG_SZ || ObPtr->Type == REG_EXPAND_SZ) {
  346. return p;
  347. }
  348. //
  349. // For REG_NONE and REG_BINARY, give it a try by looking for a terminated string
  350. //
  351. if (*(end - 1)) {
  352. return NULL;
  353. }
  354. return p;
  355. }
  356. BOOL
  357. SetObjectStringFlag (
  358. IN PCTSTR ObjectStr,
  359. IN DWORD Flag,
  360. IN DWORD RemoveFlag
  361. )
  362. {
  363. DWORD Val;
  364. if (!MemDbGetValue (ObjectStr, &Val)) {
  365. Val = 0;
  366. }
  367. if (Val & RemoveFlag) {
  368. if (Val & RemoveFlag & (~Flag)) {
  369. DEBUGMSG ((DBG_WARNING, "SetObjectStringFlag: Removing flag %x from val %x in %s",
  370. Val & RemoveFlag, Val, ObjectStr));
  371. Val = Val & (~RemoveFlag);
  372. }
  373. }
  374. Val |= Flag;
  375. return MemDbSetValue (ObjectStr, Val);
  376. }
  377. BOOL
  378. SetObjectStructFlag (
  379. IN CPDATAOBJECT ObPtr,
  380. DWORD Flag,
  381. DWORD RemoveFlag
  382. )
  383. {
  384. TCHAR EncodedObject[MAX_ENCODED_RULE];
  385. CreateObjectString (ObPtr, EncodedObject);
  386. return SetObjectStringFlag (EncodedObject, Flag, RemoveFlag);
  387. }
  388. BOOL
  389. CreateRenamedObjectStruct (
  390. IN PVOID RenameTable,
  391. IN PDATAOBJECT InObPtr,
  392. OUT PDATAOBJECT OutObPtr
  393. )
  394. // returns TRUE when OutObPtr is different than InObPtr
  395. {
  396. LONG rc;
  397. PCTSTR NewPtr;
  398. PTSTR p;
  399. PCTSTR Tail;
  400. PCTSTR RealValueName;
  401. TCHAR EncodedObject[MAX_ENCODED_RULE];
  402. TCHAR CopyOfEncodedObject[MAX_ENCODED_RULE];
  403. PTSTR NewEncodedObject;
  404. BOOL b = FALSE;
  405. ZeroMemory (OutObPtr, sizeof (DATAOBJECT));
  406. if (InObPtr->KeyPtr) {
  407. // Look for HKR\sub\key
  408. InObPtr->ObjectType &= ~(OT_TREE);
  409. RealValueName = InObPtr->ValueName;
  410. InObPtr->ValueName = NULL;
  411. CreateObjectString (InObPtr, EncodedObject);
  412. StringCopy (CopyOfEncodedObject, EncodedObject);
  413. InObPtr->ValueName = RealValueName;
  414. rc = pSetupStringTableLookUpStringEx (RenameTable,
  415. EncodedObject,
  416. STRTAB_CASE_INSENSITIVE,
  417. (PBYTE) &NewPtr,
  418. sizeof (NewPtr)
  419. );
  420. if (rc != -1) {
  421. CreateObjectStruct (NewPtr, OutObPtr, WINNTOBJECT);
  422. b = TRUE;
  423. } else if (*EncodedObject) {
  424. // Look for HKR\sub\key\*, HKR\sub\* and HKR\*
  425. p = GetEndOfString (EncodedObject);
  426. do {
  427. StringCopy (p, TEXT("\\*"));
  428. rc = pSetupStringTableLookUpStringEx (RenameTable,
  429. EncodedObject,
  430. STRTAB_CASE_INSENSITIVE,
  431. (PBYTE) &NewPtr,
  432. sizeof (NewPtr)
  433. );
  434. if (rc != -1) {
  435. Tail = CopyOfEncodedObject + (p - EncodedObject);
  436. NewEncodedObject = JoinPaths (NewPtr, Tail);
  437. CreateObjectStruct (NewEncodedObject, OutObPtr, WINNTOBJECT);
  438. FreePathString (NewEncodedObject);
  439. b = TRUE;
  440. break;
  441. }
  442. do {
  443. // _tcsdec is fixed in strings.h
  444. p = _tcsdec2 (EncodedObject, p);
  445. } while (p && _tcsnextc (p) != TEXT('\\'));
  446. } while (p);
  447. }
  448. }
  449. if (InObPtr->ValueName) {
  450. if (InObPtr->KeyPtr) {
  451. // Look for HKR\sub\key\[value]
  452. CreateObjectString (InObPtr, EncodedObject);
  453. rc = pSetupStringTableLookUpStringEx (RenameTable,
  454. EncodedObject,
  455. STRTAB_CASE_INSENSITIVE,
  456. (PBYTE) &NewPtr,
  457. sizeof (NewPtr)
  458. );
  459. if (rc != -1) {
  460. CreateObjectStruct (NewPtr, OutObPtr, WINNTOBJECT);
  461. b = TRUE;
  462. }
  463. }
  464. }
  465. if (!b) {
  466. // If rename not found, copy in object to out object
  467. CopyMemory (OutObPtr, InObPtr, sizeof (DATAOBJECT));
  468. }
  469. return b;
  470. }
  471. BOOL
  472. CreateRenamedObjectString (
  473. IN PVOID RenameTable,
  474. IN PCTSTR InObStr,
  475. OUT PTSTR OutObStr
  476. )
  477. {
  478. DATAOBJECT InObject, OutObject;
  479. BOOL b;
  480. if (!CreateObjectStruct (InObStr, &InObject, WIN95OBJECT)) {
  481. return FALSE;
  482. }
  483. b = CreateRenamedObjectStruct (RenameTable, &InObject, &OutObject);
  484. CreateObjectString (&OutObject, OutObStr);
  485. FreeObjectStruct (&InObject);
  486. if (b) {
  487. FreeObjectStruct (&OutObject);
  488. }
  489. return b;
  490. }
  491. BOOL
  492. pForceCopy (
  493. HINF InfFile
  494. )
  495. {
  496. INFCONTEXT ic;
  497. TCHAR SrcObjectStr[MAX_ENCODED_RULE];
  498. TCHAR DestObjectStr[MAX_ENCODED_RULE];
  499. DATAOBJECT SrcObject, DestObject, DupObject;
  500. BOOL b = TRUE;
  501. FILTERRETURN fr;
  502. //
  503. // Look in INF for [ForceCopy] section
  504. //
  505. if (SetupFindFirstLine (InfFile, S_MERGE_FORCECOPY, NULL, &ic)) {
  506. //
  507. // For each line in this section, get the encoded object in
  508. // field 0 (the source) and copy it to the encoded object in
  509. // field 1 (the destination).
  510. //
  511. do {
  512. *DestObjectStr = 0;
  513. if (SetupGetStringField (&ic, 0, SrcObjectStr, MAX_ENCODED_RULE, NULL) &&
  514. SetupGetStringField (&ic, 1, DestObjectStr, MAX_ENCODED_RULE, NULL)
  515. ) {
  516. if (!(*DestObjectStr)) {
  517. StringCopy (DestObjectStr, SrcObjectStr);
  518. }
  519. if (!CreateObjectStruct (SrcObjectStr, &SrcObject, WIN95OBJECT)) {
  520. DEBUGMSG ((DBG_WARNING, "pForceCopy: Source object invalid (Section line %u of %s)",
  521. ic.Line, g_InfFileName));
  522. continue;
  523. }
  524. if (!CreateObjectStruct (DestObjectStr, &DestObject, WINNTOBJECT)) {
  525. DEBUGMSG ((DBG_WARNING, "pForceCopy: Destination object invalid (Section line %u of %s)",
  526. ic.Line, g_InfFileName));
  527. FreeObjectStruct (&SrcObject);
  528. continue;
  529. }
  530. if (b = DuplicateObjectStruct (&DupObject, &SrcObject)) {
  531. if (b = CombineObjectStructs (&DupObject, &DestObject)) {
  532. //
  533. // Copy source to dest
  534. //
  535. fr = CopyObject (&SrcObject, &DupObject, NULL, NULL);
  536. if (fr == FILTER_RETURN_FAIL) {
  537. LOG ((LOG_ERROR, "Force Copy: CopyObject failed for %s=%s in %s", SrcObjectStr, DestObjectStr, g_InfFileName));
  538. b = FALSE;
  539. }
  540. }
  541. FreeObjectStruct (&DupObject);
  542. }
  543. FreeObjectStruct (&SrcObject);
  544. FreeObjectStruct (&DestObject);
  545. } else {
  546. LOG ((LOG_ERROR, "Force Copy: syntax error in line %u of section %s in %s",
  547. ic.Line, S_MERGE_FORCECOPY, g_InfFileName));
  548. }
  549. TickProgressBar ();
  550. } while (b && SetupFindNextLine (&ic, &ic));
  551. }
  552. return TRUE;
  553. }
  554. BOOL
  555. pForceCopyFromMemDb (
  556. VOID
  557. )
  558. {
  559. MEMDB_ENUM e;
  560. TCHAR key [MEMDB_MAX];
  561. TCHAR SrcObjectStr[MAX_ENCODED_RULE];
  562. TCHAR DestObjectStr[MAX_ENCODED_RULE];
  563. DATAOBJECT SrcObject, DestObject, DupObject;
  564. BOOL b = TRUE;
  565. FILTERRETURN fr;
  566. //
  567. // Look in MemDb for ForceCopy tree
  568. //
  569. MemDbBuildKey (key, MEMDB_CATEGORY_FORCECOPY, TEXT("*"), NULL, NULL);
  570. if (MemDbEnumFirstValue (&e, key, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) {
  571. //
  572. // For each key here the offset points to the destination
  573. //
  574. do {
  575. if (e.dwValue != 0) {
  576. StringCopy (SrcObjectStr, e.szName);
  577. if (MemDbBuildKeyFromOffset (e.dwValue, DestObjectStr, 1, NULL)) {
  578. if (!(*DestObjectStr)) {
  579. StringCopy (DestObjectStr, SrcObjectStr);
  580. }
  581. if (!CreateObjectStruct (SrcObjectStr, &SrcObject, WIN95OBJECT)) {
  582. DEBUGMSG ((DBG_WARNING, "pForceCopyFromMemDb: Source object invalid %s",
  583. SrcObjectStr));
  584. continue;
  585. }
  586. if (!CreateObjectStruct (DestObjectStr, &DestObject, WINNTOBJECT)) {
  587. DEBUGMSG ((DBG_WARNING, "pForceCopyFromMemDb: Destination object invalid %s",
  588. DestObjectStr));
  589. FreeObjectStruct (&SrcObject);
  590. continue;
  591. }
  592. if (b = DuplicateObjectStruct (&DupObject, &SrcObject)) {
  593. if (b = CombineObjectStructs (&DupObject, &DestObject)) {
  594. //
  595. // Copy source to dest
  596. //
  597. fr = CopyObject (&SrcObject, &DupObject, NULL, NULL);
  598. if (fr == FILTER_RETURN_FAIL) {
  599. LOG ((LOG_ERROR, "Force Copy from MemDb: CopyObject failed for %s=%s", SrcObjectStr, DestObjectStr));
  600. b = FALSE;
  601. }
  602. }
  603. FreeObjectStruct (&DupObject);
  604. }
  605. FreeObjectStruct (&SrcObject);
  606. FreeObjectStruct (&DestObject);
  607. }
  608. }
  609. TickProgressBar ();
  610. } while (b && MemDbEnumNextValue (&e));
  611. }
  612. return TRUE;
  613. }
  614. #define S_MERGE_DELETEAFTERMIGRATION TEXT("Delete After Migration")
  615. BOOL
  616. pDeleteAfterMigration (
  617. IN HINF InfFile
  618. )
  619. {
  620. BOOL rSuccess = TRUE;
  621. TCHAR objectString[MAX_ENCODED_RULE];
  622. DATAOBJECT object;
  623. INFCONTEXT ic;
  624. HKEY key;
  625. //
  626. // Look in INF for [DeleteAfterMigration] section
  627. //
  628. if (SetupFindFirstLine (InfFile, S_MERGE_DELETEAFTERMIGRATION, NULL, &ic)) {
  629. //
  630. // For each line in this section, get the encoded object in
  631. // field 0 and delete it from the registry.
  632. //
  633. do {
  634. if (SetupGetStringField(&ic,0,objectString,MAX_ENCODED_RULE,NULL)) {
  635. FixUpUserSpecifiedObject(objectString);
  636. if (!CreateObjectStruct(objectString,&object,WINNTOBJECT)) {
  637. LOG((
  638. LOG_ERROR,
  639. "Delete After Migration: ObjectString invalid. (Section line %u of %s)",
  640. ic.Line,
  641. g_InfFileName
  642. ));
  643. continue;
  644. }
  645. //
  646. // We have a good object. Delete it!
  647. //
  648. if (object.ValueName) {
  649. //
  650. // Value is specified. Delete it.
  651. //
  652. if (!RegDeleteValue(object.KeyPtr->OpenKey,object.ValueName)) {
  653. DEBUGMSG((DBG_WARNING,"pDeleteAfterMigration: RegDeleteValue failed for %s [%s]",
  654. object.KeyPtr->KeyString,
  655. object.ValueName ? object.ValueName : TEXT("<DEFAULT>")
  656. ));
  657. }
  658. }
  659. else {
  660. key = GetRootKeyFromOffset (object.RootItem);
  661. pSetupRegistryDelnode (key == HKEY_ROOT ? g_hKeyRootNT : key, object.KeyPtr->KeyString);
  662. }
  663. //
  664. // Free our resources.
  665. //
  666. FreeObjectStruct(&object);
  667. }
  668. } while (SetupFindNextLine(&ic,&ic));
  669. }
  670. return rSuccess;
  671. }
  672. BOOL
  673. pCreateRenameTable (
  674. IN HINF InfFile,
  675. OUT PVOID *RenameTablePtr
  676. )
  677. {
  678. INFCONTEXT ic;
  679. TCHAR SrcObjectStr[MAX_ENCODED_RULE];
  680. TCHAR DestObjectStr[MAX_ENCODED_RULE];
  681. LONG rc;
  682. DATAOBJECT OrgOb;
  683. DATAOBJECT NewOb;
  684. PCTSTR DestStr;
  685. //
  686. // Look in INF for [Rename] section
  687. //
  688. if (SetupFindFirstLine (InfFile, S_MERGE_RENAME, NULL, &ic)) {
  689. //
  690. // Create string table
  691. //
  692. *RenameTablePtr = pSetupStringTableInitializeEx (sizeof (PCTSTR), 0);
  693. if (!(*RenameTablePtr)) {
  694. LOG ((LOG_ERROR, "Create Rename Table: Cannot allocate a string table"));
  695. return FALSE;
  696. }
  697. do {
  698. if (SetupGetStringField (&ic, 0, SrcObjectStr, MAX_ENCODED_RULE, NULL) &&
  699. SetupGetStringField (&ic, 1, DestObjectStr, MAX_ENCODED_RULE, NULL)
  700. ) {
  701. // Ignore bad lines
  702. FixUpUserSpecifiedObject (SrcObjectStr);
  703. FixUpUserSpecifiedObject (DestObjectStr);
  704. if (!CreateObjectStruct (SrcObjectStr, &OrgOb, WIN95OBJECT)) {
  705. DEBUGMSG ((DBG_WARNING, "pCreateRenameTable: Source object invalid (Section line %u of %s)",
  706. ic.Line, g_InfFileName));
  707. continue;
  708. }
  709. if (!CreateObjectStruct (DestObjectStr, &NewOb, WINNTOBJECT)) {
  710. FreeObjectStruct (&OrgOb);
  711. DEBUGMSG ((DBG_WARNING, "pCreateRenameTable: Dest object invalid (Section line %u of %s)",
  712. ic.Line, g_InfFileName));
  713. continue;
  714. }
  715. //
  716. // Convert DestObjectStr into complete object string
  717. //
  718. if (!CombineObjectStructs (&OrgOb, &NewOb)) {
  719. FreeObjectStruct (&NewOb);
  720. FreeObjectStruct (&OrgOb);
  721. DEBUGMSG ((DBG_WARNING, "pCreateRenameTable: Can't perform the rename (Section line %u in %s)",
  722. ic.Line, g_InfFileName));
  723. continue;
  724. }
  725. // Disable tree for destination object
  726. OrgOb.ObjectType &= ~OT_TREE;
  727. CreateObjectString (&OrgOb, DestObjectStr);
  728. FreeObjectStruct (&NewOb);
  729. FreeObjectStruct (&OrgOb);
  730. DestStr = PoolMemDuplicateString (g_RenamePool, DestObjectStr);
  731. if (!DestStr) {
  732. break;
  733. }
  734. rc = pSetupStringTableAddStringEx (
  735. *RenameTablePtr,
  736. (PTSTR) SrcObjectStr,
  737. STRTAB_CASE_INSENSITIVE,
  738. (PBYTE) &DestStr,
  739. sizeof (PCTSTR)
  740. );
  741. if (rc == -1) {
  742. SetLastError (rc);
  743. LOG ((LOG_ERROR, "Create Rename Table: Cannot add string to string table"));
  744. break;
  745. }
  746. SetObjectStringFlag (SrcObjectStr, REGMERGE_95_RENAME, REGMERGE_95_RENAME);
  747. SetObjectStringFlag (DestStr, REGMERGE_NT_SUPPRESS, REGMERGE_NT_MASK);
  748. } else {
  749. LOG ((LOG_ERROR, "Create Rename Table: syntax error in line %u of section %s in %s",
  750. ic.Line, S_MERGE_RENAME, g_InfFileName));
  751. }
  752. TickProgressBar ();
  753. } while (SetupFindNextLine (&ic, &ic));
  754. } else {
  755. return FALSE;
  756. }
  757. return TRUE;
  758. }
  759. BOOL
  760. CopyRenameTableEntry (
  761. PVOID StringTable,
  762. LONG StringID,
  763. PCTSTR SrcObjectStr,
  764. PVOID ExtraData,
  765. UINT ExtraDataSize,
  766. LPARAM lParam
  767. )
  768. {
  769. PCTSTR DestObjectStr = *((PCTSTR *) ExtraData);
  770. DATAOBJECT SrcOb, DestOb;
  771. FILTERRETURN fr = FILTER_RETURN_FAIL;
  772. DWORD Val;
  773. // See if src has been processed
  774. if (MemDbGetValue (SrcObjectStr, &Val) && (Val & REGMERGE_95_RENAME_SUPPRESS)) {
  775. return TRUE;
  776. }
  777. // If not, copy Win95 src to WinNT dest
  778. if (CreateObjectStruct (SrcObjectStr, &SrcOb, WIN95OBJECT)) {
  779. if (CreateObjectStruct (DestObjectStr, &DestOb, WINNTOBJECT)) {
  780. fr = CopyObject (&SrcOb, &DestOb, SuppressFilter95, NULL);
  781. FreeObjectStruct (&DestOb);
  782. }
  783. FreeObjectStruct (&SrcOb);
  784. }
  785. return fr != FILTER_RETURN_FAIL;
  786. }
  787. BOOL
  788. pProcessRenameTable (
  789. IN PVOID RenameTable
  790. )
  791. {
  792. PCTSTR DataBuf;
  793. return pSetupStringTableEnum (RenameTable, (PVOID) &DataBuf, sizeof (DataBuf), CopyRenameTableEntry, 0);
  794. }
  795. BOOL
  796. pSpecialConversion (
  797. IN HINF InfFile,
  798. IN PCTSTR User,
  799. IN PVOID RenameTable
  800. )
  801. {
  802. INFCONTEXT ic;
  803. TCHAR FunctionStr[MAX_ENCODED_RULE];
  804. TCHAR SrcObjectStr[MAX_ENCODED_RULE];
  805. TCHAR RenamedObjectStr[MAX_ENCODED_RULE];
  806. PROCESSINGFN Fn;
  807. PVOID Arg;
  808. //
  809. // Look in INF for [SpecialConversion] section
  810. //
  811. if (SetupFindFirstLine (InfFile, S_MERGE_WIN9X_CONVERSION, NULL, &ic)) {
  812. //
  813. // For each line, get the function and the source object, then call
  814. // the function.
  815. //
  816. do {
  817. if (SetupGetStringField (&ic, 0, FunctionStr, MAX_ENCODED_RULE, NULL) &&
  818. SetupGetStringField (&ic, 1, SrcObjectStr, MAX_ENCODED_RULE, NULL)
  819. ) {
  820. FixUpUserSpecifiedObject (SrcObjectStr);
  821. Fn = RuleHlpr_GetFunctionAddr (FunctionStr, &Arg);
  822. if (!Fn) {
  823. LOG ((LOG_ERROR, "Special Conversion: Invalid function %s in %s", FunctionStr, g_InfFileName));
  824. continue;
  825. }
  826. CreateRenamedObjectString (RenameTable, SrcObjectStr, RenamedObjectStr);
  827. if (!Fn (SrcObjectStr, RenamedObjectStr, User, Arg)) {
  828. if (GetLastError () == ERROR_SUCCESS) {
  829. continue;
  830. }
  831. LOG ((LOG_ERROR, "Processing of Special Conversion was aborted because %s failed.", FunctionStr));
  832. break;
  833. }
  834. SetObjectStringFlag (
  835. SrcObjectStr,
  836. REGMERGE_95_SUPPRESS|REGMERGE_95_RENAME_SUPPRESS,
  837. REGMERGE_95_SUPPRESS|REGMERGE_95_RENAME_SUPPRESS
  838. );
  839. SetObjectStringFlag (RenamedObjectStr, REGMERGE_NT_SUPPRESS, REGMERGE_NT_MASK);
  840. } else {
  841. LOG ((LOG_ERROR, "Special Conversion: syntax error in line %u of section %s in %s",
  842. ic.Line, S_MERGE_WIN9X_CONVERSION, g_InfFileName));
  843. }
  844. TickProgressBar ();
  845. } while (SetupFindNextLine (&ic, &ic));
  846. }
  847. return TRUE;
  848. }
  849. BOOL
  850. SetFlagsForObject (
  851. IN HINF InfFile,
  852. IN PCTSTR Section,
  853. IN DWORD Flag,
  854. IN DWORD RemoveFlag
  855. )
  856. {
  857. INFCONTEXT ic;
  858. TCHAR SrcObjectStr[MAX_ENCODED_RULE];
  859. //
  860. // Look in INF for section
  861. //
  862. if (SetupFindFirstLine (InfFile, Section, NULL, &ic)) {
  863. //
  864. // For each line, get the object and mark it as suppressed.
  865. //
  866. do {
  867. if (SetupGetStringField (&ic, 1, SrcObjectStr, MAX_ENCODED_RULE, NULL)
  868. ) {
  869. FixUpUserSpecifiedObject (SrcObjectStr);
  870. SetObjectStringFlag (SrcObjectStr, Flag, RemoveFlag);
  871. } else {
  872. LOG ((LOG_ERROR, "Set Flags For Object: syntax error in line %u of section %s in %s",
  873. ic.Line, Section, g_InfFileName));
  874. }
  875. TickProgressBar ();
  876. } while (SetupFindNextLine (&ic, &ic));
  877. } else {
  878. DEBUGMSG ((DBG_VERBOSE, "SetFlagsForObject: Section %s can't be found", Section));
  879. }
  880. return TRUE;
  881. }
  882. BOOL
  883. pProcessSuppressList (
  884. IN HINF InfFile,
  885. IN PCTSTR SectionName
  886. )
  887. {
  888. return SetFlagsForObject (
  889. InfFile,
  890. SectionName,
  891. REGMERGE_95_SUPPRESS,
  892. REGMERGE_95_SUPPRESS
  893. );
  894. }
  895. BOOL
  896. pProcessHardwareSuppressList (
  897. IN HINF InfFile
  898. )
  899. {
  900. return SetFlagsForObject (InfFile, S_MERGE_WIN9X_SUPPRESS_HW, REGMERGE_95_SUPPRESS, REGMERGE_95_SUPPRESS);
  901. }
  902. BOOL
  903. pSuppressNTDefaults (
  904. IN HINF InfFile,
  905. IN PCTSTR SectionName
  906. )
  907. {
  908. //
  909. // The objects listed in Suppress WinNT Settings are enumerated,
  910. // and they are blocked from being transferred from the NT default
  911. // user to the new user.
  912. //
  913. return SetFlagsForObject (
  914. InfFile,
  915. SectionName,
  916. REGMERGE_NT_SUPPRESS,
  917. REGMERGE_NT_SUPPRESS
  918. );
  919. }
  920. BOOL
  921. pDontCombineWithDefaults (
  922. IN HINF InfFile,
  923. IN PCTSTR SectionName
  924. )
  925. {
  926. //
  927. // The objects listed in Merge WinNT with Win9x are enumerated,
  928. // and they are blocked from being transferred from the NT default
  929. // user to the new user. In addition, they are put in a list
  930. // to be processed at the end of user registry migration. This
  931. // last step uses CombineFilter to make sure the NT values do
  932. // not overwrite the 9x values.
  933. //
  934. return SetFlagsForObject (
  935. InfFile,
  936. SectionName,
  937. REGMERGE_NT_IGNORE_DEFAULTS,
  938. REGMERGE_NT_IGNORE_DEFAULTS
  939. );
  940. }
  941. BOOL
  942. pForceNTDefaults (
  943. IN HINF InfFile,
  944. IN PCTSTR SectionName
  945. )
  946. {
  947. //
  948. // The objects listed in Force WinNT Settings are enumerated,
  949. // and they are blocked from being processed during the general
  950. // 9x to NT copy. In addition, they are put in a list to be
  951. // processed at the end of user registry migration. This last
  952. // step forces the entire key to be copied from the default
  953. // user to the new user, overwriting any previously migrated
  954. // settings.
  955. //
  956. // It is important to note that the special conversion functions
  957. // are not suppressed here, but the converted settings may be
  958. // overwritten.
  959. //
  960. return SetFlagsForObject (
  961. InfFile,
  962. SectionName,
  963. REGMERGE_NT_PRIORITY_NT|REGMERGE_95_SUPPRESS,
  964. REGMERGE_NT_PRIORITY_NT|REGMERGE_95_SUPPRESS
  965. );
  966. }
  967. BOOL
  968. pForceNTDefaultsHack (
  969. IN HINF InfFile,
  970. IN PCTSTR SectionName
  971. )
  972. {
  973. //
  974. // Take away the REGMERGE_95_SUPPRESS flag now, because the general
  975. // 9x merge has completed, but we get confused between an actual
  976. // suppress and a suppress done for the priority-nt case.
  977. //
  978. return SetFlagsForObject (
  979. InfFile,
  980. SectionName,
  981. REGMERGE_NT_PRIORITY_NT,
  982. REGMERGE_NT_PRIORITY_NT|REGMERGE_95_SUPPRESS
  983. );
  984. }
  985. FILTERRETURN
  986. SuppressFilter95 (
  987. IN CPDATAOBJECT SrcObjectPtr,
  988. IN CPDATAOBJECT DestObjectPtr, OPTIONAL
  989. IN FILTERTYPE FilterType,
  990. IN PVOID DontCare
  991. )
  992. {
  993. TCHAR ObStr[MAX_ENCODED_RULE];
  994. DWORD Val;
  995. PTSTR p, q, r;
  996. TCHAR Node[MEMDB_MAX];
  997. if (FilterType == FILTER_CREATE_KEY) {
  998. //
  999. // Check if this tree is suppressed
  1000. //
  1001. MYASSERT (SrcObjectPtr->ObjectType & OT_TREE);
  1002. MYASSERT (SrcObjectPtr->KeyPtr);
  1003. MYASSERT (!(SrcObjectPtr->ValueName));
  1004. // Query setting for HKR\Sub\Key\*
  1005. CreateObjectString (SrcObjectPtr, ObStr);
  1006. if (MemDbGetValue (ObStr, &Val)) {
  1007. if (Val & REGMERGE_95_SUPPRESS) {
  1008. return FILTER_RETURN_DONE;
  1009. }
  1010. if (!g_ProcessRenameTable && (Val & REGMERGE_95_RENAME)) {
  1011. return FILTER_RETURN_DONE;
  1012. }
  1013. }
  1014. // If key is a GUID and GUID is suppressed, suppress the tree
  1015. p = (PTSTR) SrcObjectPtr->ChildKey;
  1016. if (p && _tcsnextc (p) == TEXT('{')) {
  1017. // Look for matching curly brace
  1018. q = _tcschr (p, TEXT('}'));
  1019. if (q) {
  1020. q = _tcsinc (q);
  1021. // Create GUIDS\{a-b-c-d-e}
  1022. *Node = 0;
  1023. r = _tcsappend (Node, MEMDB_CATEGORY_GUIDS);
  1024. r = _tcsappend (r, TEXT("\\"));
  1025. StringCopyAB (r, p, q);
  1026. // Look for match
  1027. if (MemDbGetValue (Node, NULL)) {
  1028. DEBUGMSG ((DBG_VERBOSE, "Suppressed %s found in %s", Node, ObStr));
  1029. return FILTER_RETURN_DONE;
  1030. }
  1031. }
  1032. }
  1033. }
  1034. else if (FilterType == FILTER_PROCESS_VALUES) {
  1035. //
  1036. // Check if this node is suppressed
  1037. //
  1038. MYASSERT (!(SrcObjectPtr->ObjectType & OT_TREE));
  1039. MYASSERT (SrcObjectPtr->KeyPtr);
  1040. MYASSERT (!(SrcObjectPtr->ValueName));
  1041. CreateObjectString (SrcObjectPtr, ObStr);
  1042. // Query setting for HKR\Sub\Key
  1043. if (!MemDbGetValue (ObStr, &Val)) {
  1044. Val = 0;
  1045. }
  1046. if (Val & REGMERGE_95_SUPPRESS) {
  1047. return FILTER_RETURN_HANDLED;
  1048. }
  1049. if (!g_ProcessRenameTable && (Val & REGMERGE_95_RENAME)) {
  1050. return FILTER_RETURN_HANDLED;
  1051. }
  1052. }
  1053. else if (FilterType == FILTER_VALUENAME_ENUM) {
  1054. //
  1055. // Check if this value is suppressed
  1056. //
  1057. MYASSERT (!(SrcObjectPtr->ObjectType & OT_TREE));
  1058. MYASSERT (SrcObjectPtr->KeyPtr);
  1059. MYASSERT (SrcObjectPtr->ValueName);
  1060. CreateObjectString (SrcObjectPtr, ObStr);
  1061. // If value name is a GUID and GUID is suppressed, suppress the value
  1062. p = (PTSTR) SrcObjectPtr->ValueName;
  1063. if (_tcsnextc (p) == TEXT('{')) {
  1064. MemDbBuildKey (Node, MEMDB_CATEGORY_GUIDS, NULL, NULL, p);
  1065. if (MemDbGetValue (Node, NULL)) {
  1066. return FILTER_RETURN_HANDLED;
  1067. }
  1068. }
  1069. if (!MemDbGetValue (ObStr, &Val)) {
  1070. Val = 0;
  1071. }
  1072. if (Val & REGMERGE_95_SUPPRESS) {
  1073. return FILTER_RETURN_HANDLED;
  1074. }
  1075. if (!g_ProcessRenameTable && (Val & REGMERGE_95_RENAME)) {
  1076. return FILTER_RETURN_HANDLED;
  1077. }
  1078. }
  1079. else if (FilterType == FILTER_VALUE_COPY) {
  1080. //
  1081. // Don't copy if value has a suppressed GUID
  1082. //
  1083. p = pGetStringFromObjectData (SrcObjectPtr);
  1084. if (p && _tcsnextc (p) == TEXT('{')) {
  1085. MemDbBuildKey (Node, MEMDB_CATEGORY_GUIDS, NULL, NULL, p);
  1086. if (MemDbGetValue (Node, NULL)) {
  1087. return FILTER_RETURN_HANDLED;
  1088. }
  1089. }
  1090. }
  1091. return FILTER_RETURN_CONTINUE;
  1092. }
  1093. FILTERRETURN
  1094. SuppressFilterNT (
  1095. IN CPDATAOBJECT SrcObjectPtr,
  1096. IN CPDATAOBJECT DestObjectPtr, OPTIONAL
  1097. IN FILTERTYPE FilterType,
  1098. IN PVOID DontCare
  1099. )
  1100. {
  1101. TCHAR ObStr[MAX_ENCODED_RULE];
  1102. DWORD Val;
  1103. PTSTR p;
  1104. if (FilterType == FILTER_CREATE_KEY) {
  1105. //
  1106. // Check if this tree is suppressed
  1107. //
  1108. MYASSERT (DestObjectPtr->ObjectType & OT_TREE);
  1109. MYASSERT (DestObjectPtr->KeyPtr);
  1110. MYASSERT (!(DestObjectPtr->ValueName));
  1111. CreateObjectString (DestObjectPtr, ObStr);
  1112. if (MemDbGetValue (ObStr, &Val) && (Val & REGMERGE_NT_MASK)) {
  1113. return FILTER_RETURN_DONE;
  1114. }
  1115. }
  1116. else if (FilterType == FILTER_PROCESS_VALUES) {
  1117. DATAOBJECT CopyOfDestOb;
  1118. DWORD rc;
  1119. DWORD ValueCount;
  1120. //
  1121. // Does destination already exist?
  1122. //
  1123. CopyMemory (&CopyOfDestOb, DestObjectPtr, sizeof (DATAOBJECT));
  1124. if (OpenObject (&CopyOfDestOb)) {
  1125. //
  1126. // Does it have values?
  1127. //
  1128. MYASSERT (!IsWin95Object (&CopyOfDestOb));
  1129. rc = RegQueryInfoKey (
  1130. CopyOfDestOb.KeyPtr->OpenKey,
  1131. NULL, // class
  1132. NULL, // class size
  1133. NULL, // reserved
  1134. NULL, // subkey count
  1135. NULL, // max subkey length
  1136. NULL, // max class length
  1137. &ValueCount,
  1138. NULL, // max value name size
  1139. NULL, // max value size
  1140. NULL, // security
  1141. NULL // last changed time
  1142. );
  1143. if (rc == ERROR_SUCCESS && ValueCount > 0) {
  1144. CloseObject (&CopyOfDestOb);
  1145. return FILTER_RETURN_HANDLED;
  1146. }
  1147. }
  1148. //
  1149. // Check if this node is suppressed
  1150. //
  1151. MYASSERT (DestObjectPtr->ObjectType & OT_TREE);
  1152. MYASSERT (DestObjectPtr->KeyPtr);
  1153. MYASSERT (!(DestObjectPtr->ValueName));
  1154. CreateObjectString (DestObjectPtr, ObStr);
  1155. p = _tcsrchr (ObStr, TEXT('\\'));
  1156. if (p) {
  1157. *p = 0;
  1158. }
  1159. if (MemDbGetValue (ObStr, &Val) && (Val & REGMERGE_NT_MASK)) {
  1160. return FILTER_RETURN_HANDLED;
  1161. }
  1162. }
  1163. else if (FilterType == FILTER_VALUENAME_ENUM) {
  1164. //
  1165. // Check if this value is suppressed
  1166. //
  1167. MYASSERT (!(DestObjectPtr->ObjectType & OT_TREE));
  1168. MYASSERT (DestObjectPtr->KeyPtr);
  1169. MYASSERT (DestObjectPtr->ValueName);
  1170. CreateObjectString (DestObjectPtr, ObStr);
  1171. if (MemDbGetValue (ObStr, &Val) && (Val & REGMERGE_NT_MASK)) {
  1172. return FILTER_RETURN_HANDLED;
  1173. }
  1174. }
  1175. return FILTER_RETURN_CONTINUE;
  1176. }
  1177. FILTERRETURN
  1178. CombineFilter (
  1179. IN CPDATAOBJECT SrcObjectPtr,
  1180. IN CPDATAOBJECT DestObjectPtr, OPTIONAL
  1181. IN FILTERTYPE FilterType,
  1182. IN PVOID DontCare
  1183. )
  1184. {
  1185. BOOL b;
  1186. if (FilterType == FILTER_VALUE_COPY) {
  1187. //
  1188. // Check if destination already exists in the registry
  1189. //
  1190. MYASSERT (!(SrcObjectPtr->ObjectType & OT_TREE));
  1191. MYASSERT (SrcObjectPtr->KeyPtr);
  1192. MYASSERT (SrcObjectPtr->ValueName);
  1193. MYASSERT (!(DestObjectPtr->ObjectType & OT_TREE));
  1194. MYASSERT (DestObjectPtr->KeyPtr);
  1195. MYASSERT (DestObjectPtr->ValueName);
  1196. b = CheckIfNtKeyExists (DestObjectPtr);
  1197. if (b) {
  1198. return FILTER_RETURN_HANDLED;
  1199. } else if (GetLastError() != ERROR_SUCCESS) {
  1200. return FILTER_RETURN_FAIL;
  1201. }
  1202. }
  1203. return FILTER_RETURN_CONTINUE;
  1204. }
  1205. FILTERRETURN
  1206. pSuppressDefaultUserFilter (
  1207. IN CPDATAOBJECT SrcObjectPtr,
  1208. IN CPDATAOBJECT DestObjectPtr, OPTIONAL
  1209. IN FILTERTYPE FilterType,
  1210. IN PVOID DontCare
  1211. )
  1212. {
  1213. TCHAR ObStr[MAX_ENCODED_RULE];
  1214. DWORD Val;
  1215. PTSTR p;
  1216. if (FilterType == FILTER_CREATE_KEY) {
  1217. //
  1218. // Check if this tree is suppressed
  1219. //
  1220. MYASSERT (DestObjectPtr->ObjectType & OT_TREE);
  1221. MYASSERT (DestObjectPtr->KeyPtr);
  1222. MYASSERT (!(DestObjectPtr->ValueName));
  1223. CreateObjectString (DestObjectPtr, ObStr);
  1224. if (MemDbGetValue (ObStr, &Val) && (Val & REGMERGE_NT_IGNORE_DEFAULTS)) {
  1225. return FILTER_RETURN_DONE;
  1226. }
  1227. }
  1228. else if (FilterType == FILTER_PROCESS_VALUES) {
  1229. //
  1230. // Check if this node is suppressed
  1231. //
  1232. MYASSERT (DestObjectPtr->ObjectType & OT_TREE);
  1233. MYASSERT (DestObjectPtr->KeyPtr);
  1234. MYASSERT (!(DestObjectPtr->ValueName));
  1235. CreateObjectString (DestObjectPtr, ObStr);
  1236. p = _tcsrchr (ObStr, TEXT('\\'));
  1237. if (p) {
  1238. *p = 0;
  1239. }
  1240. if (MemDbGetValue (ObStr, &Val) && (Val & REGMERGE_NT_IGNORE_DEFAULTS)) {
  1241. return FILTER_RETURN_HANDLED;
  1242. }
  1243. }
  1244. else if (FilterType == FILTER_VALUENAME_ENUM) {
  1245. //
  1246. // Check if this value is suppressed
  1247. //
  1248. MYASSERT (!(DestObjectPtr->ObjectType & OT_TREE));
  1249. MYASSERT (DestObjectPtr->KeyPtr);
  1250. MYASSERT (DestObjectPtr->ValueName);
  1251. CreateObjectString (DestObjectPtr, ObStr);
  1252. if (MemDbGetValue (ObStr, &Val) && (Val & REGMERGE_NT_IGNORE_DEFAULTS)) {
  1253. return FILTER_RETURN_HANDLED;
  1254. }
  1255. }
  1256. return CombineFilter (SrcObjectPtr, DestObjectPtr, FilterType, DontCare);
  1257. }
  1258. FILTERRETURN
  1259. CopyNoOverwriteFilter (
  1260. IN CPDATAOBJECT SrcObjectPtr,
  1261. IN CPDATAOBJECT DestObjectPtr, OPTIONAL
  1262. IN FILTERTYPE FilterType,
  1263. IN PVOID DontCare
  1264. )
  1265. {
  1266. FILTERRETURN fr;
  1267. fr = SuppressFilter95 (SrcObjectPtr, DestObjectPtr, FilterType, DontCare);
  1268. if (fr != FILTER_RETURN_CONTINUE) {
  1269. return fr;
  1270. }
  1271. return CombineFilter (SrcObjectPtr, DestObjectPtr, FilterType, DontCare);
  1272. }
  1273. BOOL
  1274. pMergeWin95WithUser (
  1275. IN PVOID RenameTable
  1276. )
  1277. {
  1278. DATAOBJECT SrcOb, DestOb;
  1279. BOOL b;
  1280. FILTERRETURN fr;
  1281. //
  1282. // Copy unsuppressed Win95 keys to NT user hive
  1283. //
  1284. b = CreateObjectStruct (TEXT("HKR\\*"), &SrcOb, WIN95OBJECT);
  1285. MYASSERT (b);
  1286. b = CreateObjectStruct (TEXT("HKR\\*"), &DestOb, WINNTOBJECT);
  1287. MYASSERT (b);
  1288. fr = CopyObject (&SrcOb, &DestOb, SuppressFilter95, NULL);
  1289. FreeObjectStruct (&SrcOb);
  1290. FreeObjectStruct (&DestOb);
  1291. if (fr == FILTER_RETURN_FAIL) {
  1292. LOG ((LOG_ERROR, "Merge Win95 With User: CopyObject failed"));
  1293. return FALSE;
  1294. }
  1295. return TRUE;
  1296. }
  1297. VOID
  1298. RegistryCombineWorker (
  1299. DWORD Flag,
  1300. FILTERFUNCTION FilterFn,
  1301. PCTSTR MemDbRoot,
  1302. PCTSTR SrcRoot,
  1303. DWORD SrcObjectType
  1304. )
  1305. {
  1306. MEMDB_ENUM e;
  1307. TCHAR SrcRegKey[MEMDB_MAX];
  1308. TCHAR DestRegKey[MEMDB_MAX];
  1309. PTSTR SrcPtr, DestPtr;
  1310. DATAOBJECT SrcOb, DestOb;
  1311. FILTERRETURN fr;
  1312. TCHAR Pattern[32];
  1313. wsprintf (Pattern, TEXT("%s\\*"), MemDbRoot);
  1314. //
  1315. // Enumerate all keys in memdb and call CopyObject for them
  1316. //
  1317. *SrcRegKey = 0;
  1318. *DestRegKey = 0;
  1319. SrcPtr = _tcsappend (SrcRegKey, SrcRoot);
  1320. SrcPtr = _tcsappend (SrcPtr, TEXT("\\"));
  1321. DestPtr = _tcsappend (DestRegKey, MemDbRoot);
  1322. DestPtr = _tcsappend (DestPtr, TEXT("\\"));
  1323. if (MemDbEnumFirstValue (
  1324. &e,
  1325. Pattern,
  1326. MEMDB_ALL_SUBLEVELS,
  1327. MEMDB_ENDPOINTS_ONLY
  1328. )) {
  1329. do {
  1330. if ((e.dwValue & REGMERGE_NT_MASK) & Flag) {
  1331. StringCopy (SrcPtr, e.szName);
  1332. StringCopy (DestPtr, e.szName);
  1333. if (!CreateObjectStruct (SrcRegKey, &SrcOb, SrcObjectType)) {
  1334. LOG ((LOG_ERROR, "Merge NT Defaults With User: Can't create object for %s", SrcRegKey));
  1335. continue;
  1336. }
  1337. if (!CreateObjectStruct (DestRegKey, &DestOb, WINNTOBJECT)) {
  1338. FreeObjectStruct (&SrcOb);
  1339. LOG ((LOG_ERROR, "Merge NT Defaults With User: Can't create object for %s", SrcRegKey));
  1340. continue;
  1341. }
  1342. fr = CopyObject (&SrcOb, &DestOb, FilterFn, NULL);
  1343. if (fr == FILTER_RETURN_FAIL) {
  1344. LOG ((LOG_ERROR, "Merge NT Defaults With User: Can't copy %s to %s", SrcRegKey, DestRegKey));
  1345. }
  1346. FreeObjectStruct (&SrcOb);
  1347. FreeObjectStruct (&DestOb);
  1348. }
  1349. TickProgressBar ();
  1350. } while (MemDbEnumNextValue (&e));
  1351. }
  1352. }
  1353. BOOL
  1354. pMergeNTDefaultsWithUser (
  1355. HINF hInf
  1356. )
  1357. {
  1358. DATAOBJECT SrcOb, DestOb;
  1359. FILTERRETURN fr;
  1360. BOOL b;
  1361. //
  1362. // Copy unsuppressed NT defaults to NT user hive
  1363. //
  1364. b = CreateObjectStruct (
  1365. TEXT("HKLM\\") S_MAPPED_DEFAULT_USER_KEY TEXT("\\*"),
  1366. &SrcOb,
  1367. WINNTOBJECT
  1368. );
  1369. MYASSERT (b);
  1370. b = CreateObjectStruct (TEXT("HKR\\*"), &DestOb, WINNTOBJECT);
  1371. MYASSERT (b);
  1372. __try {
  1373. b = FALSE;
  1374. fr = CopyObject (&SrcOb, &DestOb, SuppressFilterNT, NULL);
  1375. if (fr == FILTER_RETURN_FAIL) {
  1376. LOG ((LOG_ERROR, "Merge NT Defaults With User: CopyObject failed"));
  1377. __leave;
  1378. }
  1379. //
  1380. // Copy forced NT defaults to NT user hive, then copy all NT defaults
  1381. // that need to be combined with Win95 settings.
  1382. //
  1383. RegistryCombineWorker (
  1384. REGMERGE_NT_PRIORITY_NT,
  1385. NULL,
  1386. TEXT("HKR"),
  1387. TEXT("HKLM\\") S_MAPPED_DEFAULT_USER_KEY,
  1388. WINNTOBJECT
  1389. );
  1390. fr = CopyObject (&SrcOb, &DestOb, pSuppressDefaultUserFilter, NULL);
  1391. if (fr == FILTER_RETURN_FAIL) {
  1392. LOG ((LOG_ERROR, "Combine NT Defaults With User: CopyObject failed"));
  1393. __leave;
  1394. }
  1395. b = TRUE;
  1396. }
  1397. __finally {
  1398. FreeObjectStruct (&SrcOb);
  1399. FreeObjectStruct (&DestOb);
  1400. }
  1401. return b;
  1402. }
  1403. BOOL
  1404. pCopyWin9xValuesNotInNt (
  1405. HINF hInf
  1406. )
  1407. {
  1408. DATAOBJECT SrcOb, DestOb;
  1409. FILTERRETURN fr;
  1410. BOOL b;
  1411. //
  1412. // Copy Win9x values that NT does not have
  1413. //
  1414. b = CreateObjectStruct (
  1415. TEXT("HKLM\\*"),
  1416. &SrcOb,
  1417. WIN95OBJECT
  1418. );
  1419. MYASSERT (b);
  1420. b = CreateObjectStruct (TEXT("HKR\\*"), &DestOb, WINNTOBJECT);
  1421. MYASSERT (b);
  1422. __try {
  1423. b = FALSE;
  1424. fr = CopyObject (&SrcOb, &DestOb, SuppressFilterNT, NULL);
  1425. if (fr == FILTER_RETURN_FAIL) {
  1426. LOG ((LOG_ERROR, "Merge NT Defaults With User: CopyObject failed"));
  1427. __leave;
  1428. }
  1429. //
  1430. // Copy forced NT defaults to NT user hive, then copy all NT defaults
  1431. // that need to be combined with Win95 settings.
  1432. //
  1433. RegistryCombineWorker (
  1434. REGMERGE_NT_PRIORITY_NT,
  1435. NULL,
  1436. TEXT("HKR"),
  1437. TEXT("HKLM\\") S_MAPPED_DEFAULT_USER_KEY,
  1438. WINNTOBJECT
  1439. );
  1440. fr = CopyObject (&SrcOb, &DestOb, pSuppressDefaultUserFilter, NULL);
  1441. if (fr == FILTER_RETURN_FAIL) {
  1442. LOG ((LOG_ERROR, "Combine NT Defaults With User: CopyObject failed"));
  1443. __leave;
  1444. }
  1445. b = TRUE;
  1446. }
  1447. __finally {
  1448. FreeObjectStruct (&SrcOb);
  1449. FreeObjectStruct (&DestOb);
  1450. }
  1451. return b;
  1452. }
  1453. BOOL
  1454. pMergeWin95WithSystem (
  1455. VOID
  1456. )
  1457. /*++
  1458. Routine Description:
  1459. pMergeWin95WithSystem copies the Win95 registry to NT, skipping values
  1460. that already exist on NT.
  1461. Arguments:
  1462. none
  1463. Return Value:
  1464. TRUE if success, FALSE if failure.
  1465. --*/
  1466. {
  1467. RegistryCombineWorker (
  1468. REGMERGE_NT_PRIORITY_NT,
  1469. CopyNoOverwriteFilter,
  1470. TEXT("HKLM"), // memdb root and dest root
  1471. TEXT("HKLM"), // source root
  1472. WIN95OBJECT
  1473. );
  1474. return TRUE;
  1475. }
  1476. BOOL
  1477. pCopyWin95ToSystem (
  1478. VOID
  1479. )
  1480. /*++
  1481. Routine Description:
  1482. pCopyWin95ToSystem copies all Win95 settings to NT, unless the setting
  1483. is supressed. This achieves a copy with overwrite capability.
  1484. Arguments:
  1485. none
  1486. Return Value:
  1487. TRUE if success, FALSE if failure.
  1488. --*/
  1489. {
  1490. DATAOBJECT SrcOb, DestOb;
  1491. BOOL b;
  1492. FILTERRETURN fr;
  1493. b = CreateObjectStruct (TEXT("HKLM\\*"), &SrcOb, WIN95OBJECT);
  1494. MYASSERT (b);
  1495. b = CreateObjectStruct (TEXT("HKLM\\*"), &DestOb, WINNTOBJECT);
  1496. MYASSERT (b);
  1497. fr = CopyObject (&SrcOb, &DestOb, SuppressFilter95, NULL);
  1498. FreeObjectStruct (&SrcOb);
  1499. FreeObjectStruct (&DestOb);
  1500. if (fr == FILTER_RETURN_FAIL) {
  1501. LOG ((LOG_ERROR, "Copy Win95 To System: CopyObject failed"));
  1502. return FALSE;
  1503. }
  1504. return TRUE;
  1505. }
  1506. BOOL
  1507. pSpecialConversionNT (
  1508. IN HINF InfFile,
  1509. IN PCTSTR User,
  1510. IN BOOL PerUser
  1511. )
  1512. {
  1513. INFCONTEXT ic;
  1514. DATAOBJECT SrcOb, DestOb;
  1515. TCHAR FunctionStr[MAX_ENCODED_RULE];
  1516. TCHAR SrcObjectStr[MAX_ENCODED_RULE];
  1517. TCHAR DestObjectStr[MAX_ENCODED_RULE];
  1518. PROCESSINGFN Fn;
  1519. PVOID Arg;
  1520. //
  1521. // Look in INF for [SpecialConversionNT] section
  1522. //
  1523. if (SetupFindFirstLine (InfFile, S_MERGE_WINNT_CONVERSION, NULL, &ic)) {
  1524. //
  1525. // For each line, get the function and the source object, then call
  1526. // the function.
  1527. //
  1528. do {
  1529. if (SetupGetStringField (&ic, 0, FunctionStr, MAX_ENCODED_RULE, NULL) &&
  1530. SetupGetStringField (&ic, 1, DestObjectStr, MAX_ENCODED_RULE, NULL)
  1531. ) {
  1532. FixUpUserSpecifiedObject (DestObjectStr);
  1533. Fn = RuleHlpr_GetFunctionAddr (FunctionStr, &Arg);
  1534. if (!Fn) {
  1535. LOG ((LOG_ERROR, "Special Conversion: Invalid function %s in %s", FunctionStr, g_InfFileName));
  1536. continue;
  1537. }
  1538. if (PerUser) {
  1539. //
  1540. // Make source off of HKLM\MappedDefaultUser
  1541. //
  1542. if (!CreateObjectStruct (DestObjectStr, &SrcOb, WINNTOBJECT)) {
  1543. continue;
  1544. }
  1545. if (!(SrcOb.RootItem)) {
  1546. LOG ((LOG_ERROR, "Special Conversion NT: Invalid function object %s", DestObjectStr));
  1547. FreeObjectStruct (&SrcOb);
  1548. continue;
  1549. }
  1550. CreateObjectStruct (TEXT("HKLM"), &DestOb, WINNTOBJECT);
  1551. CombineObjectStructs (&SrcOb, &DestOb);
  1552. StringCopy (SrcObjectStr, S_MAPPED_DEFAULT_USER_KEY TEXT("\\"));
  1553. CreateObjectString (&SrcOb, GetEndOfString (SrcObjectStr));
  1554. FreeObjectStruct (&DestOb);
  1555. FreeObjectStruct (&SrcOb);
  1556. } else {
  1557. if (!CreateObjectStruct (DestObjectStr, &SrcOb, WINNTOBJECT)) {
  1558. continue;
  1559. }
  1560. if (!(SrcOb.RootItem)) {
  1561. LOG ((LOG_ERROR, "Special Conversion NT: Invalid function object %s", DestObjectStr));
  1562. FreeObjectStruct (&SrcOb);
  1563. continue;
  1564. }
  1565. CreateObjectString (&SrcOb, SrcObjectStr);
  1566. FreeObjectStruct (&SrcOb);
  1567. }
  1568. if (!Fn (SrcObjectStr, PerUser ? DestObjectStr : SrcObjectStr, User, Arg)) {
  1569. if (GetLastError () == ERROR_SUCCESS) {
  1570. continue;
  1571. }
  1572. LOG ((LOG_ERROR, "Processing of Special Conversion was aborted because %s failed.", FunctionStr));
  1573. break;
  1574. }
  1575. SetObjectStringFlag (SrcObjectStr, REGMERGE_NT_SUPPRESS, REGMERGE_NT_MASK);
  1576. } else {
  1577. LOG ((LOG_ERROR, "Special Conversion NT: syntax error in line %u of section %s in %s",
  1578. ic.Line, S_MERGE_WINNT_CONVERSION, g_InfFileName));
  1579. }
  1580. TickProgressBar ();
  1581. } while (SetupFindNextLine (&ic, &ic));
  1582. }
  1583. return TRUE;
  1584. }
  1585. BOOL
  1586. SuppressWin95Object (
  1587. IN PCTSTR ObjectStr
  1588. )
  1589. {
  1590. return SetObjectStringFlag (ObjectStr, REGMERGE_95_SUPPRESS, REGMERGE_95_SUPPRESS);
  1591. }
  1592. BOOL
  1593. CheckIfNtKeyExists (
  1594. IN CPDATAOBJECT SrcObjectPtr
  1595. )
  1596. /*++
  1597. Routine Description:
  1598. CheckIfNtKeyExists takes a 9x object and tests to see if the same NT
  1599. setting exists. The 9x object must have a key and value name.
  1600. Arguments:
  1601. SrcObjectPtr - Specifies the 9x object to test.
  1602. Return Value:
  1603. TRUE if the object exists in NT, FALSE if it doesn't or if an error occurs.
  1604. GetLastError indicates the error (if any).
  1605. --*/
  1606. {
  1607. DATAOBJECT NtObject;
  1608. BOOL b;
  1609. PCSTR value1;
  1610. PCSTR value2;
  1611. PCWSTR value3;
  1612. PCWSTR oldValueName;
  1613. HKEY oldRoot;
  1614. if (!DuplicateObjectStruct (&NtObject, SrcObjectPtr)) {
  1615. LOG ((LOG_ERROR, "Combine Filter: destination is invalid"));
  1616. return FALSE;
  1617. }
  1618. SetPlatformType (&NtObject, FALSE);
  1619. b = OpenObject (&NtObject);
  1620. if (!b && g_DuHandle) {
  1621. oldRoot = GetRegRoot();
  1622. SetRegRoot (g_DuHandle);
  1623. b = OpenObject (&NtObject);
  1624. SetRegRoot (oldRoot);
  1625. }
  1626. if (b) {
  1627. b = ReadObject (&NtObject);
  1628. if (!b) {
  1629. if (OurGetACP() == 932) {
  1630. //
  1631. // Katakana special case
  1632. //
  1633. oldValueName = NtObject.ValueName;
  1634. value1 = ConvertWtoA (NtObject.ValueName);
  1635. value2 = ConvertSBtoDB (NULL, value1, NULL);
  1636. value3 = ConvertAtoW (value2);
  1637. NtObject.ValueName = value3;
  1638. FreeObjectVal (&NtObject);
  1639. b = ReadObject (&NtObject);
  1640. FreeConvertedStr (value3);
  1641. FreePathStringA (value2);
  1642. FreeConvertedStr (value1);
  1643. NtObject.ValueName = oldValueName;
  1644. }
  1645. }
  1646. }
  1647. FreeObjectStruct (&NtObject);
  1648. SetLastError (ERROR_SUCCESS);
  1649. return b;
  1650. }