Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2118 lines
55 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, ARRAYSIZE(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, ARRAYSIZE(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, ARRAYSIZE(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. IN DWORD OutObStrSizeInTchars
  477. )
  478. {
  479. DATAOBJECT InObject, OutObject;
  480. BOOL b;
  481. if (!CreateObjectStruct (InObStr, &InObject, WIN95OBJECT)) {
  482. return FALSE;
  483. }
  484. b = CreateRenamedObjectStruct (RenameTable, &InObject, &OutObject);
  485. CreateObjectString (&OutObject, OutObStr, OutObStrSizeInTchars);
  486. FreeObjectStruct (&InObject);
  487. if (b) {
  488. FreeObjectStruct (&OutObject);
  489. }
  490. return b;
  491. }
  492. BOOL
  493. pForceCopy (
  494. HINF InfFile
  495. )
  496. {
  497. INFCONTEXT ic;
  498. TCHAR SrcObjectStr[MAX_ENCODED_RULE];
  499. TCHAR DestObjectStr[MAX_ENCODED_RULE];
  500. DATAOBJECT SrcObject, DestObject, DupObject;
  501. BOOL b = TRUE;
  502. FILTERRETURN fr;
  503. //
  504. // Look in INF for [ForceCopy] section
  505. //
  506. if (SetupFindFirstLine (InfFile, S_MERGE_FORCECOPY, NULL, &ic)) {
  507. //
  508. // For each line in this section, get the encoded object in
  509. // field 0 (the source) and copy it to the encoded object in
  510. // field 1 (the destination).
  511. //
  512. do {
  513. *DestObjectStr = 0;
  514. if (SetupGetStringField (&ic, 0, SrcObjectStr, MAX_ENCODED_RULE, NULL) &&
  515. SetupGetStringField (&ic, 1, DestObjectStr, MAX_ENCODED_RULE, NULL)
  516. ) {
  517. if (!(*DestObjectStr)) {
  518. StringCopy (DestObjectStr, SrcObjectStr);
  519. }
  520. if (!CreateObjectStruct (SrcObjectStr, &SrcObject, WIN95OBJECT)) {
  521. DEBUGMSG ((DBG_WARNING, "pForceCopy: Source object invalid (Section line %u of %s)",
  522. ic.Line, g_InfFileName));
  523. continue;
  524. }
  525. if (!CreateObjectStruct (DestObjectStr, &DestObject, WINNTOBJECT)) {
  526. DEBUGMSG ((DBG_WARNING, "pForceCopy: Destination object invalid (Section line %u of %s)",
  527. ic.Line, g_InfFileName));
  528. FreeObjectStruct (&SrcObject);
  529. continue;
  530. }
  531. if (b = DuplicateObjectStruct (&DupObject, &SrcObject)) {
  532. if (b = CombineObjectStructs (&DupObject, &DestObject)) {
  533. //
  534. // Copy source to dest
  535. //
  536. fr = CopyObject (&SrcObject, &DupObject, NULL, NULL);
  537. if (fr == FILTER_RETURN_FAIL) {
  538. LOG ((LOG_ERROR, "Force Copy: CopyObject failed for %s=%s in %s", SrcObjectStr, DestObjectStr, g_InfFileName));
  539. b = FALSE;
  540. }
  541. }
  542. FreeObjectStruct (&DupObject);
  543. }
  544. FreeObjectStruct (&SrcObject);
  545. FreeObjectStruct (&DestObject);
  546. } else {
  547. LOG ((LOG_ERROR, "Force Copy: syntax error in line %u of section %s in %s",
  548. ic.Line, S_MERGE_FORCECOPY, g_InfFileName));
  549. }
  550. TickProgressBar ();
  551. } while (b && SetupFindNextLine (&ic, &ic));
  552. }
  553. return TRUE;
  554. }
  555. BOOL
  556. pForceCopyFromMemDb (
  557. VOID
  558. )
  559. {
  560. MEMDB_ENUM e;
  561. TCHAR key [MEMDB_MAX];
  562. TCHAR SrcObjectStr[MAX_ENCODED_RULE];
  563. TCHAR DestObjectStr[MAX_ENCODED_RULE];
  564. DATAOBJECT SrcObject, DestObject, DupObject;
  565. BOOL b = TRUE;
  566. FILTERRETURN fr;
  567. //
  568. // Look in MemDb for ForceCopy tree
  569. //
  570. MemDbBuildKey (key, MEMDB_CATEGORY_FORCECOPY, TEXT("*"), NULL, NULL);
  571. if (MemDbEnumFirstValue (&e, key, MEMDB_ALL_SUBLEVELS, MEMDB_ENDPOINTS_ONLY)) {
  572. //
  573. // For each key here the offset points to the destination
  574. //
  575. do {
  576. if (e.dwValue != 0) {
  577. if(_tcslen(e.szName) >= ARRAYSIZE(SrcObjectStr)){
  578. LOG ((LOG_WARNING, "pForceCopyFromMemDb: Not enough buffer for string copy %s", e.szName));
  579. continue;
  580. }
  581. StackStringCopy (SrcObjectStr, e.szName);
  582. if (MemDbBuildKeyFromOffset (e.dwValue, DestObjectStr, 1, NULL)) {
  583. if (!(*DestObjectStr)) {
  584. StringCopy (DestObjectStr, SrcObjectStr);
  585. }
  586. if (!CreateObjectStruct (SrcObjectStr, &SrcObject, WIN95OBJECT)) {
  587. DEBUGMSG ((DBG_WARNING, "pForceCopyFromMemDb: Source object invalid %s",
  588. SrcObjectStr));
  589. continue;
  590. }
  591. if (!CreateObjectStruct (DestObjectStr, &DestObject, WINNTOBJECT)) {
  592. DEBUGMSG ((DBG_WARNING, "pForceCopyFromMemDb: Destination object invalid %s",
  593. DestObjectStr));
  594. FreeObjectStruct (&SrcObject);
  595. continue;
  596. }
  597. if (b = DuplicateObjectStruct (&DupObject, &SrcObject)) {
  598. if (b = CombineObjectStructs (&DupObject, &DestObject)) {
  599. //
  600. // Copy source to dest
  601. //
  602. fr = CopyObject (&SrcObject, &DupObject, NULL, NULL);
  603. if (fr == FILTER_RETURN_FAIL) {
  604. LOG ((LOG_ERROR, "Force Copy from MemDb: CopyObject failed for %s=%s", SrcObjectStr, DestObjectStr));
  605. b = FALSE;
  606. }
  607. }
  608. FreeObjectStruct (&DupObject);
  609. }
  610. FreeObjectStruct (&SrcObject);
  611. FreeObjectStruct (&DestObject);
  612. }
  613. }
  614. TickProgressBar ();
  615. } while (b && MemDbEnumNextValue (&e));
  616. }
  617. return TRUE;
  618. }
  619. #define S_MERGE_DELETEAFTERMIGRATION TEXT("Delete After Migration")
  620. BOOL
  621. pDeleteAfterMigration (
  622. IN HINF InfFile
  623. )
  624. {
  625. BOOL rSuccess = TRUE;
  626. TCHAR objectString[MAX_ENCODED_RULE];
  627. DATAOBJECT object;
  628. INFCONTEXT ic;
  629. HKEY key;
  630. //
  631. // Look in INF for [DeleteAfterMigration] section
  632. //
  633. if (SetupFindFirstLine (InfFile, S_MERGE_DELETEAFTERMIGRATION, NULL, &ic)) {
  634. //
  635. // For each line in this section, get the encoded object in
  636. // field 0 and delete it from the registry.
  637. //
  638. do {
  639. if (SetupGetStringField(&ic,0,objectString,MAX_ENCODED_RULE,NULL)) {
  640. FixUpUserSpecifiedObject(objectString);
  641. if (!CreateObjectStruct(objectString,&object,WINNTOBJECT)) {
  642. LOG((
  643. LOG_ERROR,
  644. "Delete After Migration: ObjectString invalid. (Section line %u of %s)",
  645. ic.Line,
  646. g_InfFileName
  647. ));
  648. continue;
  649. }
  650. //
  651. // We have a good object. Delete it!
  652. //
  653. if (object.ValueName) {
  654. //
  655. // Value is specified. Delete it.
  656. //
  657. if (!RegDeleteValue(object.KeyPtr->OpenKey,object.ValueName)) {
  658. DEBUGMSG((DBG_WARNING,"pDeleteAfterMigration: RegDeleteValue failed for %s [%s]",
  659. object.KeyPtr->KeyString,
  660. object.ValueName ? object.ValueName : TEXT("<DEFAULT>")
  661. ));
  662. }
  663. }
  664. else {
  665. key = GetRootKeyFromOffset (object.RootItem);
  666. pSetupRegistryDelnode (key == HKEY_ROOT ? g_hKeyRootNT : key, object.KeyPtr->KeyString);
  667. }
  668. //
  669. // Free our resources.
  670. //
  671. FreeObjectStruct(&object);
  672. }
  673. } while (SetupFindNextLine(&ic,&ic));
  674. }
  675. return rSuccess;
  676. }
  677. BOOL
  678. pCreateRenameTable (
  679. IN HINF InfFile,
  680. OUT PVOID *RenameTablePtr
  681. )
  682. {
  683. INFCONTEXT ic;
  684. TCHAR SrcObjectStr[MAX_ENCODED_RULE];
  685. TCHAR DestObjectStr[MAX_ENCODED_RULE];
  686. LONG rc;
  687. DATAOBJECT OrgOb;
  688. DATAOBJECT NewOb;
  689. PCTSTR DestStr;
  690. //
  691. // Look in INF for [Rename] section
  692. //
  693. if (SetupFindFirstLine (InfFile, S_MERGE_RENAME, NULL, &ic)) {
  694. //
  695. // Create string table
  696. //
  697. *RenameTablePtr = pSetupStringTableInitializeEx (sizeof (PCTSTR), 0);
  698. if (!(*RenameTablePtr)) {
  699. LOG ((LOG_ERROR, "Create Rename Table: Cannot allocate a string table"));
  700. return FALSE;
  701. }
  702. do {
  703. if (SetupGetStringField (&ic, 0, SrcObjectStr, MAX_ENCODED_RULE, NULL) &&
  704. SetupGetStringField (&ic, 1, DestObjectStr, MAX_ENCODED_RULE, NULL)
  705. ) {
  706. // Ignore bad lines
  707. FixUpUserSpecifiedObject (SrcObjectStr);
  708. FixUpUserSpecifiedObject (DestObjectStr);
  709. if (!CreateObjectStruct (SrcObjectStr, &OrgOb, WIN95OBJECT)) {
  710. DEBUGMSG ((DBG_WARNING, "pCreateRenameTable: Source object invalid (Section line %u of %s)",
  711. ic.Line, g_InfFileName));
  712. continue;
  713. }
  714. if (!CreateObjectStruct (DestObjectStr, &NewOb, WINNTOBJECT)) {
  715. FreeObjectStruct (&OrgOb);
  716. DEBUGMSG ((DBG_WARNING, "pCreateRenameTable: Dest object invalid (Section line %u of %s)",
  717. ic.Line, g_InfFileName));
  718. continue;
  719. }
  720. //
  721. // Convert DestObjectStr into complete object string
  722. //
  723. if (!CombineObjectStructs (&OrgOb, &NewOb)) {
  724. FreeObjectStruct (&NewOb);
  725. FreeObjectStruct (&OrgOb);
  726. DEBUGMSG ((DBG_WARNING, "pCreateRenameTable: Can't perform the rename (Section line %u in %s)",
  727. ic.Line, g_InfFileName));
  728. continue;
  729. }
  730. // Disable tree for destination object
  731. OrgOb.ObjectType &= ~OT_TREE;
  732. CreateObjectString (&OrgOb, DestObjectStr, ARRAYSIZE(DestObjectStr));
  733. FreeObjectStruct (&NewOb);
  734. FreeObjectStruct (&OrgOb);
  735. DestStr = PoolMemDuplicateString (g_RenamePool, DestObjectStr);
  736. if (!DestStr) {
  737. break;
  738. }
  739. rc = pSetupStringTableAddStringEx (
  740. *RenameTablePtr,
  741. (PTSTR) SrcObjectStr,
  742. STRTAB_CASE_INSENSITIVE,
  743. (PBYTE) &DestStr,
  744. sizeof (PCTSTR)
  745. );
  746. if (rc == -1) {
  747. SetLastError (rc);
  748. LOG ((LOG_ERROR, "Create Rename Table: Cannot add string to string table"));
  749. break;
  750. }
  751. SetObjectStringFlag (SrcObjectStr, REGMERGE_95_RENAME, REGMERGE_95_RENAME);
  752. SetObjectStringFlag (DestStr, REGMERGE_NT_SUPPRESS, REGMERGE_NT_MASK);
  753. } else {
  754. LOG ((LOG_ERROR, "Create Rename Table: syntax error in line %u of section %s in %s",
  755. ic.Line, S_MERGE_RENAME, g_InfFileName));
  756. }
  757. TickProgressBar ();
  758. } while (SetupFindNextLine (&ic, &ic));
  759. } else {
  760. return FALSE;
  761. }
  762. return TRUE;
  763. }
  764. BOOL
  765. CopyRenameTableEntry (
  766. PVOID StringTable,
  767. LONG StringID,
  768. PCTSTR SrcObjectStr,
  769. PVOID ExtraData,
  770. UINT ExtraDataSize,
  771. LPARAM lParam
  772. )
  773. {
  774. PCTSTR DestObjectStr = *((PCTSTR *) ExtraData);
  775. DATAOBJECT SrcOb, DestOb;
  776. FILTERRETURN fr = FILTER_RETURN_FAIL;
  777. DWORD Val;
  778. // See if src has been processed
  779. if (MemDbGetValue (SrcObjectStr, &Val) && (Val & REGMERGE_95_RENAME_SUPPRESS)) {
  780. return TRUE;
  781. }
  782. // If not, copy Win95 src to WinNT dest
  783. if (CreateObjectStruct (SrcObjectStr, &SrcOb, WIN95OBJECT)) {
  784. if (CreateObjectStruct (DestObjectStr, &DestOb, WINNTOBJECT)) {
  785. fr = CopyObject (&SrcOb, &DestOb, SuppressFilter95, NULL);
  786. FreeObjectStruct (&DestOb);
  787. }
  788. FreeObjectStruct (&SrcOb);
  789. }
  790. return fr != FILTER_RETURN_FAIL;
  791. }
  792. BOOL
  793. pProcessRenameTable (
  794. IN PVOID RenameTable
  795. )
  796. {
  797. PCTSTR DataBuf;
  798. return pSetupStringTableEnum (RenameTable, (PVOID) &DataBuf, sizeof (DataBuf), CopyRenameTableEntry, 0);
  799. }
  800. BOOL
  801. pSpecialConversion (
  802. IN HINF InfFile,
  803. IN PCTSTR User,
  804. IN PVOID RenameTable
  805. )
  806. {
  807. INFCONTEXT ic;
  808. TCHAR FunctionStr[MAX_ENCODED_RULE];
  809. TCHAR SrcObjectStr[MAX_ENCODED_RULE];
  810. TCHAR RenamedObjectStr[MAX_ENCODED_RULE];
  811. PROCESSINGFN Fn;
  812. PVOID Arg;
  813. //
  814. // Look in INF for [SpecialConversion] section
  815. //
  816. if (SetupFindFirstLine (InfFile, S_MERGE_WIN9X_CONVERSION, NULL, &ic)) {
  817. //
  818. // For each line, get the function and the source object, then call
  819. // the function.
  820. //
  821. do {
  822. if (SetupGetStringField (&ic, 0, FunctionStr, MAX_ENCODED_RULE, NULL) &&
  823. SetupGetStringField (&ic, 1, SrcObjectStr, MAX_ENCODED_RULE, NULL)
  824. ) {
  825. FixUpUserSpecifiedObject (SrcObjectStr);
  826. Fn = RuleHlpr_GetFunctionAddr (FunctionStr, &Arg);
  827. if (!Fn) {
  828. LOG ((LOG_ERROR, "Special Conversion: Invalid function %s in %s", FunctionStr, g_InfFileName));
  829. continue;
  830. }
  831. CreateRenamedObjectString (RenameTable, SrcObjectStr, RenamedObjectStr, ARRAYSIZE(RenamedObjectStr));
  832. if (!Fn (SrcObjectStr, RenamedObjectStr, User, Arg)) {
  833. if (GetLastError () == ERROR_SUCCESS) {
  834. continue;
  835. }
  836. LOG ((LOG_ERROR, "Processing of Special Conversion was aborted because %s failed.", FunctionStr));
  837. break;
  838. }
  839. SetObjectStringFlag (
  840. SrcObjectStr,
  841. REGMERGE_95_SUPPRESS|REGMERGE_95_RENAME_SUPPRESS,
  842. REGMERGE_95_SUPPRESS|REGMERGE_95_RENAME_SUPPRESS
  843. );
  844. SetObjectStringFlag (RenamedObjectStr, REGMERGE_NT_SUPPRESS, REGMERGE_NT_MASK);
  845. } else {
  846. LOG ((LOG_ERROR, "Special Conversion: syntax error in line %u of section %s in %s",
  847. ic.Line, S_MERGE_WIN9X_CONVERSION, g_InfFileName));
  848. }
  849. TickProgressBar ();
  850. } while (SetupFindNextLine (&ic, &ic));
  851. }
  852. return TRUE;
  853. }
  854. BOOL
  855. SetFlagsForObject (
  856. IN HINF InfFile,
  857. IN PCTSTR Section,
  858. IN DWORD Flag,
  859. IN DWORD RemoveFlag
  860. )
  861. {
  862. INFCONTEXT ic;
  863. TCHAR SrcObjectStr[MAX_ENCODED_RULE];
  864. //
  865. // Look in INF for section
  866. //
  867. if (SetupFindFirstLine (InfFile, Section, NULL, &ic)) {
  868. //
  869. // For each line, get the object and mark it as suppressed.
  870. //
  871. do {
  872. if (SetupGetStringField (&ic, 1, SrcObjectStr, MAX_ENCODED_RULE, NULL)
  873. ) {
  874. FixUpUserSpecifiedObject (SrcObjectStr);
  875. SetObjectStringFlag (SrcObjectStr, Flag, RemoveFlag);
  876. } else {
  877. LOG ((LOG_ERROR, "Set Flags For Object: syntax error in line %u of section %s in %s",
  878. ic.Line, Section, g_InfFileName));
  879. }
  880. TickProgressBar ();
  881. } while (SetupFindNextLine (&ic, &ic));
  882. } else {
  883. DEBUGMSG ((DBG_VERBOSE, "SetFlagsForObject: Section %s can't be found", Section));
  884. }
  885. return TRUE;
  886. }
  887. BOOL
  888. pProcessSuppressList (
  889. IN HINF InfFile,
  890. IN PCTSTR SectionName
  891. )
  892. {
  893. return SetFlagsForObject (
  894. InfFile,
  895. SectionName,
  896. REGMERGE_95_SUPPRESS,
  897. REGMERGE_95_SUPPRESS
  898. );
  899. }
  900. BOOL
  901. pProcessHardwareSuppressList (
  902. IN HINF InfFile
  903. )
  904. {
  905. return SetFlagsForObject (InfFile, S_MERGE_WIN9X_SUPPRESS_HW, REGMERGE_95_SUPPRESS, REGMERGE_95_SUPPRESS);
  906. }
  907. BOOL
  908. pSuppressNTDefaults (
  909. IN HINF InfFile,
  910. IN PCTSTR SectionName
  911. )
  912. {
  913. //
  914. // The objects listed in Suppress WinNT Settings are enumerated,
  915. // and they are blocked from being transferred from the NT default
  916. // user to the new user.
  917. //
  918. return SetFlagsForObject (
  919. InfFile,
  920. SectionName,
  921. REGMERGE_NT_SUPPRESS,
  922. REGMERGE_NT_SUPPRESS
  923. );
  924. }
  925. BOOL
  926. pDontCombineWithDefaults (
  927. IN HINF InfFile,
  928. IN PCTSTR SectionName
  929. )
  930. {
  931. //
  932. // The objects listed in Merge WinNT with Win9x are enumerated,
  933. // and they are blocked from being transferred from the NT default
  934. // user to the new user. In addition, they are put in a list
  935. // to be processed at the end of user registry migration. This
  936. // last step uses CombineFilter to make sure the NT values do
  937. // not overwrite the 9x values.
  938. //
  939. return SetFlagsForObject (
  940. InfFile,
  941. SectionName,
  942. REGMERGE_NT_IGNORE_DEFAULTS,
  943. REGMERGE_NT_IGNORE_DEFAULTS
  944. );
  945. }
  946. BOOL
  947. pForceNTDefaults (
  948. IN HINF InfFile,
  949. IN PCTSTR SectionName
  950. )
  951. {
  952. //
  953. // The objects listed in Force WinNT Settings are enumerated,
  954. // and they are blocked from being processed during the general
  955. // 9x to NT copy. In addition, they are put in a list to be
  956. // processed at the end of user registry migration. This last
  957. // step forces the entire key to be copied from the default
  958. // user to the new user, overwriting any previously migrated
  959. // settings.
  960. //
  961. // It is important to note that the special conversion functions
  962. // are not suppressed here, but the converted settings may be
  963. // overwritten.
  964. //
  965. return SetFlagsForObject (
  966. InfFile,
  967. SectionName,
  968. REGMERGE_NT_PRIORITY_NT|REGMERGE_95_SUPPRESS,
  969. REGMERGE_NT_PRIORITY_NT|REGMERGE_95_SUPPRESS
  970. );
  971. }
  972. BOOL
  973. pForceNTDefaultsHack (
  974. IN HINF InfFile,
  975. IN PCTSTR SectionName
  976. )
  977. {
  978. //
  979. // Take away the REGMERGE_95_SUPPRESS flag now, because the general
  980. // 9x merge has completed, but we get confused between an actual
  981. // suppress and a suppress done for the priority-nt case.
  982. //
  983. return SetFlagsForObject (
  984. InfFile,
  985. SectionName,
  986. REGMERGE_NT_PRIORITY_NT,
  987. REGMERGE_NT_PRIORITY_NT|REGMERGE_95_SUPPRESS
  988. );
  989. }
  990. FILTERRETURN
  991. SuppressFilter95 (
  992. IN CPDATAOBJECT SrcObjectPtr,
  993. IN CPDATAOBJECT DestObjectPtr, OPTIONAL
  994. IN FILTERTYPE FilterType,
  995. IN PVOID DontCare
  996. )
  997. {
  998. TCHAR ObStr[MAX_ENCODED_RULE];
  999. DWORD Val;
  1000. PTSTR p, q, r;
  1001. TCHAR Node[MEMDB_MAX];
  1002. if (FilterType == FILTER_CREATE_KEY) {
  1003. //
  1004. // Check if this tree is suppressed
  1005. //
  1006. MYASSERT (SrcObjectPtr->ObjectType & OT_TREE);
  1007. MYASSERT (SrcObjectPtr->KeyPtr);
  1008. MYASSERT (!(SrcObjectPtr->ValueName));
  1009. // Query setting for HKR\Sub\Key\*
  1010. CreateObjectString (SrcObjectPtr, ObStr, ARRAYSIZE(ObStr));
  1011. if (MemDbGetValue (ObStr, &Val)) {
  1012. if (Val & REGMERGE_95_SUPPRESS) {
  1013. return FILTER_RETURN_DONE;
  1014. }
  1015. if (!g_ProcessRenameTable && (Val & REGMERGE_95_RENAME)) {
  1016. return FILTER_RETURN_DONE;
  1017. }
  1018. }
  1019. // If key is a GUID and GUID is suppressed, suppress the tree
  1020. p = (PTSTR) SrcObjectPtr->ChildKey;
  1021. if (p && _tcsnextc (p) == TEXT('{')) {
  1022. // Look for matching curly brace
  1023. q = _tcschr (p, TEXT('}'));
  1024. if (q) {
  1025. q = _tcsinc (q);
  1026. // Create GUIDS\{a-b-c-d-e}
  1027. *Node = 0;
  1028. r = _tcsappend (Node, MEMDB_CATEGORY_GUIDS);
  1029. r = _tcsappend (r, TEXT("\\"));
  1030. StringCopyAB (r, p, q);
  1031. // Look for match
  1032. if (MemDbGetValue (Node, NULL)) {
  1033. DEBUGMSG ((DBG_VERBOSE, "Suppressed %s found in %s", Node, ObStr));
  1034. return FILTER_RETURN_DONE;
  1035. }
  1036. }
  1037. }
  1038. }
  1039. else if (FilterType == FILTER_PROCESS_VALUES) {
  1040. //
  1041. // Check if this node is suppressed
  1042. //
  1043. MYASSERT (!(SrcObjectPtr->ObjectType & OT_TREE));
  1044. MYASSERT (SrcObjectPtr->KeyPtr);
  1045. MYASSERT (!(SrcObjectPtr->ValueName));
  1046. CreateObjectString (SrcObjectPtr, ObStr, ARRAYSIZE(ObStr));
  1047. // Query setting for HKR\Sub\Key
  1048. if (!MemDbGetValue (ObStr, &Val)) {
  1049. Val = 0;
  1050. }
  1051. if (Val & REGMERGE_95_SUPPRESS) {
  1052. return FILTER_RETURN_HANDLED;
  1053. }
  1054. if (!g_ProcessRenameTable && (Val & REGMERGE_95_RENAME)) {
  1055. return FILTER_RETURN_HANDLED;
  1056. }
  1057. }
  1058. else if (FilterType == FILTER_VALUENAME_ENUM) {
  1059. //
  1060. // Check if this value is suppressed
  1061. //
  1062. MYASSERT (!(SrcObjectPtr->ObjectType & OT_TREE));
  1063. MYASSERT (SrcObjectPtr->KeyPtr);
  1064. MYASSERT (SrcObjectPtr->ValueName);
  1065. CreateObjectString (SrcObjectPtr, ObStr, ARRAYSIZE(ObStr));
  1066. // If value name is a GUID and GUID is suppressed, suppress the value
  1067. p = (PTSTR) SrcObjectPtr->ValueName;
  1068. if (_tcsnextc (p) == TEXT('{')) {
  1069. MemDbBuildKey (Node, MEMDB_CATEGORY_GUIDS, NULL, NULL, p);
  1070. if (MemDbGetValue (Node, NULL)) {
  1071. return FILTER_RETURN_HANDLED;
  1072. }
  1073. }
  1074. if (!MemDbGetValue (ObStr, &Val)) {
  1075. Val = 0;
  1076. }
  1077. if (Val & REGMERGE_95_SUPPRESS) {
  1078. return FILTER_RETURN_HANDLED;
  1079. }
  1080. if (!g_ProcessRenameTable && (Val & REGMERGE_95_RENAME)) {
  1081. return FILTER_RETURN_HANDLED;
  1082. }
  1083. }
  1084. else if (FilterType == FILTER_VALUE_COPY) {
  1085. //
  1086. // Don't copy if value has a suppressed GUID
  1087. //
  1088. p = pGetStringFromObjectData (SrcObjectPtr);
  1089. if (p && _tcsnextc (p) == TEXT('{')) {
  1090. MemDbBuildKey (Node, MEMDB_CATEGORY_GUIDS, NULL, NULL, p);
  1091. if (MemDbGetValue (Node, NULL)) {
  1092. return FILTER_RETURN_HANDLED;
  1093. }
  1094. }
  1095. }
  1096. return FILTER_RETURN_CONTINUE;
  1097. }
  1098. FILTERRETURN
  1099. SuppressFilterNT (
  1100. IN CPDATAOBJECT SrcObjectPtr,
  1101. IN CPDATAOBJECT DestObjectPtr, OPTIONAL
  1102. IN FILTERTYPE FilterType,
  1103. IN PVOID DontCare
  1104. )
  1105. {
  1106. TCHAR ObStr[MAX_ENCODED_RULE];
  1107. DWORD Val;
  1108. PTSTR p;
  1109. if (FilterType == FILTER_CREATE_KEY) {
  1110. //
  1111. // Check if this tree is suppressed
  1112. //
  1113. MYASSERT (DestObjectPtr->ObjectType & OT_TREE);
  1114. MYASSERT (DestObjectPtr->KeyPtr);
  1115. MYASSERT (!(DestObjectPtr->ValueName));
  1116. CreateObjectString (DestObjectPtr, ObStr, ARRAYSIZE(ObStr));
  1117. if (MemDbGetValue (ObStr, &Val) && (Val & REGMERGE_NT_MASK)) {
  1118. return FILTER_RETURN_DONE;
  1119. }
  1120. }
  1121. else if (FilterType == FILTER_PROCESS_VALUES) {
  1122. DATAOBJECT CopyOfDestOb;
  1123. DWORD rc;
  1124. DWORD ValueCount;
  1125. //
  1126. // Does destination already exist?
  1127. //
  1128. CopyMemory (&CopyOfDestOb, DestObjectPtr, sizeof (DATAOBJECT));
  1129. if (OpenObject (&CopyOfDestOb)) {
  1130. //
  1131. // Does it have values?
  1132. //
  1133. MYASSERT (!IsWin95Object (&CopyOfDestOb));
  1134. rc = RegQueryInfoKey (
  1135. CopyOfDestOb.KeyPtr->OpenKey,
  1136. NULL, // class
  1137. NULL, // class size
  1138. NULL, // reserved
  1139. NULL, // subkey count
  1140. NULL, // max subkey length
  1141. NULL, // max class length
  1142. &ValueCount,
  1143. NULL, // max value name size
  1144. NULL, // max value size
  1145. NULL, // security
  1146. NULL // last changed time
  1147. );
  1148. if (rc == ERROR_SUCCESS && ValueCount > 0) {
  1149. CloseObject (&CopyOfDestOb);
  1150. return FILTER_RETURN_HANDLED;
  1151. }
  1152. }
  1153. //
  1154. // Check if this node is suppressed
  1155. //
  1156. MYASSERT (DestObjectPtr->ObjectType & OT_TREE);
  1157. MYASSERT (DestObjectPtr->KeyPtr);
  1158. MYASSERT (!(DestObjectPtr->ValueName));
  1159. CreateObjectString (DestObjectPtr, ObStr, ARRAYSIZE(ObStr));
  1160. p = _tcsrchr (ObStr, TEXT('\\'));
  1161. if (p) {
  1162. *p = 0;
  1163. }
  1164. if (MemDbGetValue (ObStr, &Val) && (Val & REGMERGE_NT_MASK)) {
  1165. return FILTER_RETURN_HANDLED;
  1166. }
  1167. }
  1168. else if (FilterType == FILTER_VALUENAME_ENUM) {
  1169. //
  1170. // Check if this value is suppressed
  1171. //
  1172. MYASSERT (!(DestObjectPtr->ObjectType & OT_TREE));
  1173. MYASSERT (DestObjectPtr->KeyPtr);
  1174. MYASSERT (DestObjectPtr->ValueName);
  1175. CreateObjectString (DestObjectPtr, ObStr, ARRAYSIZE(ObStr));
  1176. if (MemDbGetValue (ObStr, &Val) && (Val & REGMERGE_NT_MASK)) {
  1177. return FILTER_RETURN_HANDLED;
  1178. }
  1179. }
  1180. return FILTER_RETURN_CONTINUE;
  1181. }
  1182. FILTERRETURN
  1183. CombineFilter (
  1184. IN CPDATAOBJECT SrcObjectPtr,
  1185. IN CPDATAOBJECT DestObjectPtr, OPTIONAL
  1186. IN FILTERTYPE FilterType,
  1187. IN PVOID DontCare
  1188. )
  1189. {
  1190. BOOL b;
  1191. if (FilterType == FILTER_VALUE_COPY) {
  1192. //
  1193. // Check if destination already exists in the registry
  1194. //
  1195. MYASSERT (!(SrcObjectPtr->ObjectType & OT_TREE));
  1196. MYASSERT (SrcObjectPtr->KeyPtr);
  1197. MYASSERT (SrcObjectPtr->ValueName);
  1198. MYASSERT (!(DestObjectPtr->ObjectType & OT_TREE));
  1199. MYASSERT (DestObjectPtr->KeyPtr);
  1200. MYASSERT (DestObjectPtr->ValueName);
  1201. b = CheckIfNtKeyExists (DestObjectPtr);
  1202. if (b) {
  1203. return FILTER_RETURN_HANDLED;
  1204. } else if (GetLastError() != ERROR_SUCCESS) {
  1205. return FILTER_RETURN_FAIL;
  1206. }
  1207. }
  1208. return FILTER_RETURN_CONTINUE;
  1209. }
  1210. FILTERRETURN
  1211. pSuppressDefaultUserFilter (
  1212. IN CPDATAOBJECT SrcObjectPtr,
  1213. IN CPDATAOBJECT DestObjectPtr, OPTIONAL
  1214. IN FILTERTYPE FilterType,
  1215. IN PVOID DontCare
  1216. )
  1217. {
  1218. TCHAR ObStr[MAX_ENCODED_RULE];
  1219. DWORD Val;
  1220. PTSTR p;
  1221. if (FilterType == FILTER_CREATE_KEY) {
  1222. //
  1223. // Check if this tree is suppressed
  1224. //
  1225. MYASSERT (DestObjectPtr->ObjectType & OT_TREE);
  1226. MYASSERT (DestObjectPtr->KeyPtr);
  1227. MYASSERT (!(DestObjectPtr->ValueName));
  1228. CreateObjectString (DestObjectPtr, ObStr, ARRAYSIZE(ObStr));
  1229. if (MemDbGetValue (ObStr, &Val) && (Val & REGMERGE_NT_IGNORE_DEFAULTS)) {
  1230. return FILTER_RETURN_DONE;
  1231. }
  1232. }
  1233. else if (FilterType == FILTER_PROCESS_VALUES) {
  1234. //
  1235. // Check if this node is suppressed
  1236. //
  1237. MYASSERT (DestObjectPtr->ObjectType & OT_TREE);
  1238. MYASSERT (DestObjectPtr->KeyPtr);
  1239. MYASSERT (!(DestObjectPtr->ValueName));
  1240. CreateObjectString (DestObjectPtr, ObStr, ARRAYSIZE(ObStr));
  1241. p = _tcsrchr (ObStr, TEXT('\\'));
  1242. if (p) {
  1243. *p = 0;
  1244. }
  1245. if (MemDbGetValue (ObStr, &Val) && (Val & REGMERGE_NT_IGNORE_DEFAULTS)) {
  1246. return FILTER_RETURN_HANDLED;
  1247. }
  1248. }
  1249. else if (FilterType == FILTER_VALUENAME_ENUM) {
  1250. //
  1251. // Check if this value is suppressed
  1252. //
  1253. MYASSERT (!(DestObjectPtr->ObjectType & OT_TREE));
  1254. MYASSERT (DestObjectPtr->KeyPtr);
  1255. MYASSERT (DestObjectPtr->ValueName);
  1256. CreateObjectString (DestObjectPtr, ObStr, ARRAYSIZE(ObStr));
  1257. if (MemDbGetValue (ObStr, &Val) && (Val & REGMERGE_NT_IGNORE_DEFAULTS)) {
  1258. return FILTER_RETURN_HANDLED;
  1259. }
  1260. }
  1261. return CombineFilter (SrcObjectPtr, DestObjectPtr, FilterType, DontCare);
  1262. }
  1263. FILTERRETURN
  1264. CopyNoOverwriteFilter (
  1265. IN CPDATAOBJECT SrcObjectPtr,
  1266. IN CPDATAOBJECT DestObjectPtr, OPTIONAL
  1267. IN FILTERTYPE FilterType,
  1268. IN PVOID DontCare
  1269. )
  1270. {
  1271. FILTERRETURN fr;
  1272. fr = SuppressFilter95 (SrcObjectPtr, DestObjectPtr, FilterType, DontCare);
  1273. if (fr != FILTER_RETURN_CONTINUE) {
  1274. return fr;
  1275. }
  1276. return CombineFilter (SrcObjectPtr, DestObjectPtr, FilterType, DontCare);
  1277. }
  1278. BOOL
  1279. pMergeWin95WithUser (
  1280. IN PVOID RenameTable
  1281. )
  1282. {
  1283. DATAOBJECT SrcOb, DestOb;
  1284. BOOL b;
  1285. FILTERRETURN fr;
  1286. //
  1287. // Copy unsuppressed Win95 keys to NT user hive
  1288. //
  1289. b = CreateObjectStruct (TEXT("HKR\\*"), &SrcOb, WIN95OBJECT);
  1290. MYASSERT (b);
  1291. b = CreateObjectStruct (TEXT("HKR\\*"), &DestOb, WINNTOBJECT);
  1292. MYASSERT (b);
  1293. fr = CopyObject (&SrcOb, &DestOb, SuppressFilter95, NULL);
  1294. FreeObjectStruct (&SrcOb);
  1295. FreeObjectStruct (&DestOb);
  1296. if (fr == FILTER_RETURN_FAIL) {
  1297. LOG ((LOG_ERROR, "Merge Win95 With User: CopyObject failed"));
  1298. return FALSE;
  1299. }
  1300. return TRUE;
  1301. }
  1302. VOID
  1303. RegistryCombineWorker (
  1304. DWORD Flag,
  1305. FILTERFUNCTION FilterFn,
  1306. PCTSTR MemDbRoot,
  1307. PCTSTR SrcRoot,
  1308. DWORD SrcObjectType
  1309. )
  1310. {
  1311. MEMDB_ENUM e;
  1312. TCHAR SrcRegKey[MEMDB_MAX];
  1313. TCHAR DestRegKey[MEMDB_MAX];
  1314. PTSTR SrcPtr, DestPtr;
  1315. DATAOBJECT SrcOb, DestOb;
  1316. FILTERRETURN fr;
  1317. TCHAR Pattern[32];
  1318. wsprintf (Pattern, TEXT("%s\\*"), MemDbRoot);
  1319. //
  1320. // Enumerate all keys in memdb and call CopyObject for them
  1321. //
  1322. *SrcRegKey = 0;
  1323. *DestRegKey = 0;
  1324. SrcPtr = _tcsappend (SrcRegKey, SrcRoot);
  1325. SrcPtr = _tcsappend (SrcPtr, TEXT("\\"));
  1326. DestPtr = _tcsappend (DestRegKey, MemDbRoot);
  1327. DestPtr = _tcsappend (DestPtr, TEXT("\\"));
  1328. if (MemDbEnumFirstValue (
  1329. &e,
  1330. Pattern,
  1331. MEMDB_ALL_SUBLEVELS,
  1332. MEMDB_ENDPOINTS_ONLY
  1333. )) {
  1334. do {
  1335. if ((e.dwValue & REGMERGE_NT_MASK) & Flag) {
  1336. StringCopy (SrcPtr, e.szName);
  1337. StringCopy (DestPtr, e.szName);
  1338. if (!CreateObjectStruct (SrcRegKey, &SrcOb, SrcObjectType)) {
  1339. LOG ((LOG_ERROR, "Merge NT Defaults With User: Can't create object for %s", SrcRegKey));
  1340. continue;
  1341. }
  1342. if (!CreateObjectStruct (DestRegKey, &DestOb, WINNTOBJECT)) {
  1343. FreeObjectStruct (&SrcOb);
  1344. LOG ((LOG_ERROR, "Merge NT Defaults With User: Can't create object for %s", SrcRegKey));
  1345. continue;
  1346. }
  1347. fr = CopyObject (&SrcOb, &DestOb, FilterFn, NULL);
  1348. if (fr == FILTER_RETURN_FAIL) {
  1349. LOG ((LOG_ERROR, "Merge NT Defaults With User: Can't copy %s to %s", SrcRegKey, DestRegKey));
  1350. }
  1351. FreeObjectStruct (&SrcOb);
  1352. FreeObjectStruct (&DestOb);
  1353. }
  1354. TickProgressBar ();
  1355. } while (MemDbEnumNextValue (&e));
  1356. }
  1357. }
  1358. BOOL
  1359. pMergeNTDefaultsWithUser (
  1360. HINF hInf
  1361. )
  1362. {
  1363. DATAOBJECT SrcOb, DestOb;
  1364. FILTERRETURN fr;
  1365. BOOL b;
  1366. //
  1367. // Copy unsuppressed NT defaults to NT user hive
  1368. //
  1369. b = CreateObjectStruct (
  1370. TEXT("HKLM\\") S_MAPPED_DEFAULT_USER_KEY TEXT("\\*"),
  1371. &SrcOb,
  1372. WINNTOBJECT
  1373. );
  1374. MYASSERT (b);
  1375. b = CreateObjectStruct (TEXT("HKR\\*"), &DestOb, WINNTOBJECT);
  1376. MYASSERT (b);
  1377. __try {
  1378. b = FALSE;
  1379. fr = CopyObject (&SrcOb, &DestOb, SuppressFilterNT, NULL);
  1380. if (fr == FILTER_RETURN_FAIL) {
  1381. LOG ((LOG_ERROR, "Merge NT Defaults With User: CopyObject failed"));
  1382. __leave;
  1383. }
  1384. //
  1385. // Copy forced NT defaults to NT user hive, then copy all NT defaults
  1386. // that need to be combined with Win95 settings.
  1387. //
  1388. RegistryCombineWorker (
  1389. REGMERGE_NT_PRIORITY_NT,
  1390. NULL,
  1391. TEXT("HKR"),
  1392. TEXT("HKLM\\") S_MAPPED_DEFAULT_USER_KEY,
  1393. WINNTOBJECT
  1394. );
  1395. fr = CopyObject (&SrcOb, &DestOb, pSuppressDefaultUserFilter, NULL);
  1396. if (fr == FILTER_RETURN_FAIL) {
  1397. LOG ((LOG_ERROR, "Combine NT Defaults With User: CopyObject failed"));
  1398. __leave;
  1399. }
  1400. b = TRUE;
  1401. }
  1402. __finally {
  1403. FreeObjectStruct (&SrcOb);
  1404. FreeObjectStruct (&DestOb);
  1405. }
  1406. return b;
  1407. }
  1408. BOOL
  1409. pCopyWin9xValuesNotInNt (
  1410. HINF hInf
  1411. )
  1412. {
  1413. DATAOBJECT SrcOb, DestOb;
  1414. FILTERRETURN fr;
  1415. BOOL b;
  1416. //
  1417. // Copy Win9x values that NT does not have
  1418. //
  1419. b = CreateObjectStruct (
  1420. TEXT("HKLM\\*"),
  1421. &SrcOb,
  1422. WIN95OBJECT
  1423. );
  1424. MYASSERT (b);
  1425. b = CreateObjectStruct (TEXT("HKR\\*"), &DestOb, WINNTOBJECT);
  1426. MYASSERT (b);
  1427. __try {
  1428. b = FALSE;
  1429. fr = CopyObject (&SrcOb, &DestOb, SuppressFilterNT, NULL);
  1430. if (fr == FILTER_RETURN_FAIL) {
  1431. LOG ((LOG_ERROR, "Merge NT Defaults With User: CopyObject failed"));
  1432. __leave;
  1433. }
  1434. //
  1435. // Copy forced NT defaults to NT user hive, then copy all NT defaults
  1436. // that need to be combined with Win95 settings.
  1437. //
  1438. RegistryCombineWorker (
  1439. REGMERGE_NT_PRIORITY_NT,
  1440. NULL,
  1441. TEXT("HKR"),
  1442. TEXT("HKLM\\") S_MAPPED_DEFAULT_USER_KEY,
  1443. WINNTOBJECT
  1444. );
  1445. fr = CopyObject (&SrcOb, &DestOb, pSuppressDefaultUserFilter, NULL);
  1446. if (fr == FILTER_RETURN_FAIL) {
  1447. LOG ((LOG_ERROR, "Combine NT Defaults With User: CopyObject failed"));
  1448. __leave;
  1449. }
  1450. b = TRUE;
  1451. }
  1452. __finally {
  1453. FreeObjectStruct (&SrcOb);
  1454. FreeObjectStruct (&DestOb);
  1455. }
  1456. return b;
  1457. }
  1458. BOOL
  1459. pMergeWin95WithSystem (
  1460. VOID
  1461. )
  1462. /*++
  1463. Routine Description:
  1464. pMergeWin95WithSystem copies the Win95 registry to NT, skipping values
  1465. that already exist on NT.
  1466. Arguments:
  1467. none
  1468. Return Value:
  1469. TRUE if success, FALSE if failure.
  1470. --*/
  1471. {
  1472. RegistryCombineWorker (
  1473. REGMERGE_NT_PRIORITY_NT,
  1474. CopyNoOverwriteFilter,
  1475. TEXT("HKLM"), // memdb root and dest root
  1476. TEXT("HKLM"), // source root
  1477. WIN95OBJECT
  1478. );
  1479. return TRUE;
  1480. }
  1481. BOOL
  1482. pCopyWin95ToSystem (
  1483. VOID
  1484. )
  1485. /*++
  1486. Routine Description:
  1487. pCopyWin95ToSystem copies all Win95 settings to NT, unless the setting
  1488. is supressed. This achieves a copy with overwrite capability.
  1489. Arguments:
  1490. none
  1491. Return Value:
  1492. TRUE if success, FALSE if failure.
  1493. --*/
  1494. {
  1495. DATAOBJECT SrcOb, DestOb;
  1496. BOOL b;
  1497. FILTERRETURN fr;
  1498. b = CreateObjectStruct (TEXT("HKLM\\*"), &SrcOb, WIN95OBJECT);
  1499. MYASSERT (b);
  1500. b = CreateObjectStruct (TEXT("HKLM\\*"), &DestOb, WINNTOBJECT);
  1501. MYASSERT (b);
  1502. fr = CopyObject (&SrcOb, &DestOb, SuppressFilter95, NULL);
  1503. FreeObjectStruct (&SrcOb);
  1504. FreeObjectStruct (&DestOb);
  1505. if (fr == FILTER_RETURN_FAIL) {
  1506. LOG ((LOG_ERROR, "Copy Win95 To System: CopyObject failed"));
  1507. return FALSE;
  1508. }
  1509. return TRUE;
  1510. }
  1511. BOOL
  1512. pSpecialConversionNT (
  1513. IN HINF InfFile,
  1514. IN PCTSTR User,
  1515. IN BOOL PerUser
  1516. )
  1517. {
  1518. INFCONTEXT ic;
  1519. DATAOBJECT SrcOb, DestOb;
  1520. TCHAR FunctionStr[MAX_ENCODED_RULE];
  1521. TCHAR SrcObjectStr[MAX_ENCODED_RULE];
  1522. TCHAR DestObjectStr[MAX_ENCODED_RULE];
  1523. PROCESSINGFN Fn;
  1524. PVOID Arg;
  1525. PTSTR p;
  1526. //
  1527. // Look in INF for [SpecialConversionNT] section
  1528. //
  1529. if (SetupFindFirstLine (InfFile, S_MERGE_WINNT_CONVERSION, NULL, &ic)) {
  1530. //
  1531. // For each line, get the function and the source object, then call
  1532. // the function.
  1533. //
  1534. do {
  1535. if (SetupGetStringField (&ic, 0, FunctionStr, MAX_ENCODED_RULE, NULL) &&
  1536. SetupGetStringField (&ic, 1, DestObjectStr, MAX_ENCODED_RULE, NULL)
  1537. ) {
  1538. FixUpUserSpecifiedObject (DestObjectStr);
  1539. Fn = RuleHlpr_GetFunctionAddr (FunctionStr, &Arg);
  1540. if (!Fn) {
  1541. LOG ((LOG_ERROR, "Special Conversion: Invalid function %s in %s", FunctionStr, g_InfFileName));
  1542. continue;
  1543. }
  1544. if (PerUser) {
  1545. //
  1546. // Make source off of HKLM\MappedDefaultUser
  1547. //
  1548. if (!CreateObjectStruct (DestObjectStr, &SrcOb, WINNTOBJECT)) {
  1549. continue;
  1550. }
  1551. if (!(SrcOb.RootItem)) {
  1552. LOG ((LOG_ERROR, "Special Conversion NT: Invalid function object %s", DestObjectStr));
  1553. FreeObjectStruct (&SrcOb);
  1554. continue;
  1555. }
  1556. CreateObjectStruct (TEXT("HKLM"), &DestOb, WINNTOBJECT);
  1557. CombineObjectStructs (&SrcOb, &DestOb);
  1558. StringCopy (SrcObjectStr, S_MAPPED_DEFAULT_USER_KEY TEXT("\\"));
  1559. p = GetEndOfString (SrcObjectStr);
  1560. CreateObjectString (&SrcOb, p, ARRAYSIZE(SrcObjectStr) - (p - SrcObjectStr));
  1561. FreeObjectStruct (&DestOb);
  1562. FreeObjectStruct (&SrcOb);
  1563. } else {
  1564. if (!CreateObjectStruct (DestObjectStr, &SrcOb, WINNTOBJECT)) {
  1565. continue;
  1566. }
  1567. if (!(SrcOb.RootItem)) {
  1568. LOG ((LOG_ERROR, "Special Conversion NT: Invalid function object %s", DestObjectStr));
  1569. FreeObjectStruct (&SrcOb);
  1570. continue;
  1571. }
  1572. CreateObjectString (&SrcOb, SrcObjectStr, ARRAYSIZE(SrcObjectStr));
  1573. FreeObjectStruct (&SrcOb);
  1574. }
  1575. if (!Fn (SrcObjectStr, PerUser ? DestObjectStr : SrcObjectStr, User, Arg)) {
  1576. if (GetLastError () == ERROR_SUCCESS) {
  1577. continue;
  1578. }
  1579. LOG ((LOG_ERROR, "Processing of Special Conversion was aborted because %s failed.", FunctionStr));
  1580. break;
  1581. }
  1582. SetObjectStringFlag (SrcObjectStr, REGMERGE_NT_SUPPRESS, REGMERGE_NT_MASK);
  1583. } else {
  1584. LOG ((LOG_ERROR, "Special Conversion NT: syntax error in line %u of section %s in %s",
  1585. ic.Line, S_MERGE_WINNT_CONVERSION, g_InfFileName));
  1586. }
  1587. TickProgressBar ();
  1588. } while (SetupFindNextLine (&ic, &ic));
  1589. }
  1590. return TRUE;
  1591. }
  1592. BOOL
  1593. SuppressWin95Object (
  1594. IN PCTSTR ObjectStr
  1595. )
  1596. {
  1597. return SetObjectStringFlag (ObjectStr, REGMERGE_95_SUPPRESS, REGMERGE_95_SUPPRESS);
  1598. }
  1599. BOOL
  1600. CheckIfNtKeyExists (
  1601. IN CPDATAOBJECT SrcObjectPtr
  1602. )
  1603. /*++
  1604. Routine Description:
  1605. CheckIfNtKeyExists takes a 9x object and tests to see if the same NT
  1606. setting exists. The 9x object must have a key and value name.
  1607. Arguments:
  1608. SrcObjectPtr - Specifies the 9x object to test.
  1609. Return Value:
  1610. TRUE if the object exists in NT, FALSE if it doesn't or if an error occurs.
  1611. GetLastError indicates the error (if any).
  1612. --*/
  1613. {
  1614. DATAOBJECT NtObject;
  1615. BOOL b;
  1616. PCSTR value1;
  1617. PCSTR value2;
  1618. PCWSTR value3;
  1619. PCWSTR oldValueName;
  1620. HKEY oldRoot;
  1621. if (!DuplicateObjectStruct (&NtObject, SrcObjectPtr)) {
  1622. LOG ((LOG_ERROR, "Combine Filter: destination is invalid"));
  1623. return FALSE;
  1624. }
  1625. SetPlatformType (&NtObject, FALSE);
  1626. b = OpenObject (&NtObject);
  1627. if (!b && g_DuHandle) {
  1628. oldRoot = GetRegRoot();
  1629. SetRegRoot (g_DuHandle);
  1630. b = OpenObject (&NtObject);
  1631. SetRegRoot (oldRoot);
  1632. }
  1633. if (b) {
  1634. b = ReadObject (&NtObject);
  1635. if (!b) {
  1636. if (OurGetACP() == 932) {
  1637. //
  1638. // Katakana special case
  1639. //
  1640. oldValueName = NtObject.ValueName;
  1641. value1 = ConvertWtoA (NtObject.ValueName);
  1642. value2 = ConvertSBtoDB (NULL, value1, NULL);
  1643. value3 = ConvertAtoW (value2);
  1644. NtObject.ValueName = value3;
  1645. FreeObjectVal (&NtObject);
  1646. b = ReadObject (&NtObject);
  1647. FreeConvertedStr (value3);
  1648. FreePathStringA (value2);
  1649. FreeConvertedStr (value1);
  1650. NtObject.ValueName = oldValueName;
  1651. }
  1652. }
  1653. }
  1654. FreeObjectStruct (&NtObject);
  1655. SetLastError (ERROR_SUCCESS);
  1656. return b;
  1657. }