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.

796 lines
22 KiB

  1. //
  2. // REGFINFO.C
  3. //
  4. // Copyright (C) Microsoft Corporation, 1995
  5. //
  6. #include "pch.h"
  7. LPFILE_INFO g_RgFileInfoList = NULL;
  8. const char g_RgDotBackslashPath[] = ".\\";
  9. #ifdef VXD
  10. #pragma VxD_RARE_CODE_SEG
  11. #endif
  12. //
  13. // RgCreateFileInfoNew
  14. //
  15. // If CFIN_VOLATILE is specified, then we skip trying to create the backing
  16. // store for the FILE_INFO. lpFileName should point at a null byte so we can
  17. // initialize the FILE_INFO properly.
  18. //
  19. // CFIN_PRIMARY and CFIN_SECONDARY are used to determine the FHT_* constant
  20. // to put in the file header.
  21. //
  22. int
  23. INTERNAL
  24. RgCreateFileInfoNew(
  25. LPFILE_INFO FAR* lplpFileInfo,
  26. LPCSTR lpFileName,
  27. UINT Flags
  28. )
  29. {
  30. int ErrorCode;
  31. LPFILE_INFO lpFileInfo;
  32. HFILE hFile;
  33. LPKEYNODE lpKeynode;
  34. DWORD KeynodeIndex;
  35. if (IsNullPtr((lpFileInfo = (LPFILE_INFO)
  36. RgSmAllocMemory(sizeof(FILE_INFO) + StrLen(lpFileName))))) {
  37. ErrorCode = ERROR_OUTOFMEMORY;
  38. goto ErrorReturn;
  39. }
  40. ZeroMemory(lpFileInfo, sizeof(FILE_INFO));
  41. StrCpy(lpFileInfo-> FileName, lpFileName);
  42. // For volatile FILE_INFOs, we obviously don't need to create the backing
  43. // store.
  44. if (!(Flags & CFIN_VOLATILE)) {
  45. // Attempt to the create the given filename.
  46. if ((hFile = RgCreateFile(lpFileName)) == HFILE_ERROR) {
  47. ErrorCode = ERROR_REGISTRY_IO_FAILED;
  48. goto ErrorDestroyFileInfo;
  49. }
  50. RgCloseFile(hFile);
  51. }
  52. lpFileInfo-> Flags = FI_DIRTY | FI_KEYNODEDIRTY;
  53. // lpFileInfo-> lpHiveInfoList = NULL;
  54. // lpFileInfo-> lpParentFileInfo = NULL;
  55. // lpFileInfo-> lpNotifyChangeList = NULL;
  56. // lpFileInfo-> lpKeynodeBlockInfo = NULL;
  57. // lpFileInfo-> NumKeynodeBlocks = 0;
  58. // lpFileInfo-> NumAllocKNBlocks = 0;
  59. // lpFileInfo-> CurTotalKnSize = 0;
  60. // lpFileInfo-> lpDatablockInfo = NULL;
  61. // lpFileInfo-> DatablockInfoAllocCount = 0;
  62. if (Flags & CFIN_VOLATILE)
  63. lpFileInfo-> Flags |= FI_VOLATILE;
  64. // Initialize the file header.
  65. lpFileInfo-> FileHeader.Signature = FH_SIGNATURE;
  66. // If we're using compact keynodes, up the version number to make sure
  67. // Win95 doesn't try to load this hive.
  68. if (Flags & CFIN_VERSION20) {
  69. lpFileInfo-> FileHeader.Version = FH_VERSION20;
  70. lpFileInfo-> Flags |= FI_VERSION20;
  71. } else {
  72. lpFileInfo-> FileHeader.Version = FH_VERSION10;
  73. }
  74. // lpFileInfo-> FileHeader.Size = 0;
  75. // lpFileInfo-> FileHeader.Checksum = 0;
  76. // lpFileInfo-> FileHeader.BlockCount = 0;
  77. lpFileInfo-> FileHeader.Flags = FHF_DIRTY;
  78. lpFileInfo-> FileHeader.Type = ((Flags & CFIN_SECONDARY) ? FHT_SECONDARY :
  79. FHT_PRIMARY);
  80. // Initialize the keynode header.
  81. lpFileInfo-> KeynodeHeader.Signature = KH_SIGNATURE;
  82. // lpFileInfo-> KeynodeHeader.FileKnSize = 0;
  83. lpFileInfo-> KeynodeHeader.RootIndex = REG_NULL;
  84. lpFileInfo-> KeynodeHeader.FirstFreeIndex = REG_NULL;
  85. lpFileInfo-> KeynodeHeader.Flags = KHF_DIRTY | KHF_NEWHASH;
  86. // lpFileInfo-> KeynodeHeader.Checksum = 0;
  87. // Init the keynode data structures.
  88. if ((ErrorCode = RgInitKeynodeInfo(lpFileInfo)) != ERROR_SUCCESS)
  89. goto ErrorDeleteFile;
  90. // For uncompacted keynode tables, the keynode table now includes at least
  91. // the header itself.
  92. if (!(lpFileInfo-> Flags & FI_VERSION20))
  93. lpFileInfo-> CurTotalKnSize = sizeof(KEYNODE_HEADER);
  94. // Init the datablock data structures.
  95. if ((ErrorCode = RgInitDatablockInfo(lpFileInfo, HFILE_ERROR)) !=
  96. ERROR_SUCCESS)
  97. goto ErrorDeleteFile;
  98. // Allocate the keynode for the root of the file.
  99. if ((ErrorCode = RgAllocKeynode(lpFileInfo, &KeynodeIndex, &lpKeynode)) !=
  100. ERROR_SUCCESS)
  101. goto ErrorDeleteFile;
  102. lpFileInfo-> KeynodeHeader.RootIndex = KeynodeIndex;
  103. lpKeynode-> ParentIndex = REG_NULL;
  104. lpKeynode-> NextIndex = REG_NULL;
  105. lpKeynode-> ChildIndex = REG_NULL;
  106. lpKeynode-> Hash = 0;
  107. // Note that we don't allocate a key record for this root keynode. Win95
  108. // didn't do this either, so we already must handle this case in code that
  109. // needs a key record. Our code is smaller if we just don't allocate this
  110. // key record which is rarely ever used anyway...
  111. lpKeynode-> BlockIndex = NULL_BLOCK_INDEX;
  112. RgUnlockKeynode(lpFileInfo, KeynodeIndex, TRUE);
  113. if ((ErrorCode = RgFlushFileInfo(lpFileInfo)) != ERROR_SUCCESS)
  114. goto ErrorDeleteFile;
  115. // Link this FILE_INFO into the global file info list.
  116. lpFileInfo-> lpNextFileInfo = g_RgFileInfoList;
  117. g_RgFileInfoList = lpFileInfo;
  118. *lplpFileInfo = lpFileInfo;
  119. return ERROR_SUCCESS;
  120. ErrorDeleteFile:
  121. if (!(Flags & CFIN_VOLATILE))
  122. RgDeleteFile(lpFileName);
  123. ErrorDestroyFileInfo:
  124. RgDestroyFileInfo(lpFileInfo);
  125. ErrorReturn:
  126. TRACE(("RgCreateFileInfoNew: returning %d\n", ErrorCode));
  127. return ErrorCode;
  128. }
  129. //
  130. // RgCreateFileInfoExisting
  131. //
  132. int
  133. INTERNAL
  134. RgCreateFileInfoExisting(
  135. LPFILE_INFO FAR* lplpFileInfo,
  136. LPCSTR lpFileName
  137. )
  138. {
  139. int ErrorCode;
  140. LPFILE_INFO lpFileInfo;
  141. HFILE hFile;
  142. DWORD FileAttributes;
  143. if (IsNullPtr((lpFileInfo = (LPFILE_INFO)
  144. RgSmAllocMemory(sizeof(FILE_INFO) + StrLen(lpFileName))))) {
  145. ErrorCode = ERROR_OUTOFMEMORY;
  146. goto ErrorReturn;
  147. }
  148. ZeroMemory(lpFileInfo, sizeof(FILE_INFO));
  149. StrCpy(lpFileInfo-> FileName, lpFileName);
  150. // lpFileInfo-> Flags = 0;
  151. // lpFileInfo-> lpHiveInfoList = NULL;
  152. // lpFileInfo-> lpParentFileInfo = NULL;
  153. // lpFileInfo-> lpNotifyChangeList = NULL;
  154. // lpFileInfo-> lpKeynodeBlockInfo = NULL;
  155. // lpFileInfo-> NumKeynodeBlocks = 0;
  156. // lpFileInfo-> NumAllocKNBlocks = 0;
  157. // lpFileInfo-> CurTotalKnSize = 0;
  158. // lpFileInfo-> lpDatablockInfo = NULL;
  159. // lpFileInfo-> DatablockInfoAllocCount = 0;
  160. ErrorCode = ERROR_REGISTRY_IO_FAILED; // Assume this error code
  161. // Attempt to the open the given filename.
  162. if ((hFile = RgOpenFile(lpFileName, OF_READ)) == HFILE_ERROR)
  163. goto ErrorDestroyFileInfo;
  164. // Read and validate the file header.
  165. if (!RgReadFile(hFile, &lpFileInfo-> FileHeader, sizeof(FILE_HEADER)))
  166. goto ErrorCloseFile;
  167. if (!RgIsValidFileHeader(&lpFileInfo-> FileHeader)) {
  168. ErrorCode = ERROR_BADDB;
  169. goto ErrorCloseFile;
  170. }
  171. lpFileInfo-> FileHeader.Flags &= ~(FHF_DIRTY | FHF_HASCHECKSUM);
  172. if (lpFileInfo-> FileHeader.Version == FH_VERSION20)
  173. lpFileInfo-> Flags |= FI_VERSION20;
  174. // Read and validate the keynode header.
  175. if (!RgReadFile(hFile, &lpFileInfo-> KeynodeHeader,
  176. sizeof(KEYNODE_HEADER)))
  177. goto ErrorCloseFile;
  178. if (lpFileInfo-> KeynodeHeader.Signature != KH_SIGNATURE) {
  179. ErrorCode = ERROR_BADDB;
  180. goto ErrorCloseFile;
  181. }
  182. // Init the keynode data structures.
  183. if ((ErrorCode = RgInitKeynodeInfo(lpFileInfo)) != ERROR_SUCCESS)
  184. goto ErrorCloseFile;
  185. // Init the datablock data structures.
  186. if ((ErrorCode = RgInitDatablockInfo(lpFileInfo, hFile)) != ERROR_SUCCESS)
  187. goto ErrorCloseFile;
  188. RgCloseFile(hFile);
  189. // Check if the file can be written to. We did this in Win95 by getting
  190. // the current file attributes and then slamming them back on the file. If
  191. // this failed, then we treated the file as read-only (such as hive from
  192. // a read-only network share). This seems to work, so why change?
  193. if ((FileAttributes = RgGetFileAttributes(lpFileName)) != (DWORD) -1) {
  194. if (!RgSetFileAttributes(lpFileName, (UINT) FileAttributes))
  195. lpFileInfo-> Flags |= FI_READONLY;
  196. }
  197. // Link this FILE_INFO into the global file info list.
  198. lpFileInfo-> lpNextFileInfo = g_RgFileInfoList;
  199. g_RgFileInfoList = lpFileInfo;
  200. *lplpFileInfo = lpFileInfo;
  201. return ERROR_SUCCESS;
  202. ErrorCloseFile:
  203. RgCloseFile(hFile);
  204. ErrorDestroyFileInfo:
  205. RgDestroyFileInfo(lpFileInfo);
  206. ErrorReturn:
  207. TRACE(("RgCreateFileInfoExisting: returning %d\n", ErrorCode));
  208. return ErrorCode;
  209. }
  210. //
  211. // RgIsValidFileHeader
  212. //
  213. // Returns TRUE if lpFileHeader is a valid FILE_HEADER structure.
  214. //
  215. BOOL
  216. INTERNAL
  217. RgIsValidFileHeader(
  218. LPFILE_HEADER lpFileHeader
  219. )
  220. {
  221. if (lpFileHeader-> Signature != FH_SIGNATURE ||
  222. (lpFileHeader-> Version != FH_VERSION10 &&
  223. lpFileHeader-> Version != FH_VERSION20))
  224. return FALSE;
  225. if (lpFileHeader-> Flags & FHF_HASCHECKSUM &&
  226. RgChecksum(lpFileHeader, sizeof(FILE_HEADER)) != 0)
  227. return FALSE;
  228. return TRUE;
  229. }
  230. //
  231. // RgDestroyFileInfo
  232. //
  233. // Unlinks the FILE_INFO from the global list, if appropriate, and frees all
  234. // memory associated with the structure including the structure itself.
  235. //
  236. // If the FILE_INFO is dirty, then all changes will be lost. Call
  237. // RgFlushFileInfo first if the file should be flushed.
  238. //
  239. int
  240. INTERNAL
  241. RgDestroyFileInfo(
  242. LPFILE_INFO lpFileInfo
  243. )
  244. {
  245. LPFILE_INFO lpPrevFileInfo;
  246. LPFILE_INFO lpCurrFileInfo;
  247. #ifdef WANT_HIVE_SUPPORT
  248. LPHIVE_INFO lpHiveInfo;
  249. LPHIVE_INFO lpTempHiveInfo;
  250. #endif
  251. #ifdef WANT_NOTIFY_CHANGE_SUPPORT
  252. LPNOTIFY_CHANGE lpNotifyChange;
  253. LPNOTIFY_CHANGE lpTempNotifyChange;
  254. #endif
  255. UINT Counter;
  256. LPKEYNODE_BLOCK_INFO lpKeynodeBlockInfo;
  257. LPDATABLOCK_INFO lpDatablockInfo;
  258. ASSERT(!IsNullPtr(lpFileInfo));
  259. RgInvalidateKeyHandles(lpFileInfo, (UINT) -1);
  260. //
  261. // Unlink this FILE_INFO from the the file info list. Note that the
  262. // structure may not have actually been linked in if we're called as a
  263. // result of an error in one of the create file info functions.
  264. //
  265. lpPrevFileInfo = NULL;
  266. lpCurrFileInfo = g_RgFileInfoList;
  267. while (!IsNullPtr(lpCurrFileInfo)) {
  268. if (lpCurrFileInfo == lpFileInfo) {
  269. if (IsNullPtr(lpPrevFileInfo))
  270. g_RgFileInfoList = lpCurrFileInfo-> lpNextFileInfo;
  271. else
  272. lpPrevFileInfo-> lpNextFileInfo = lpCurrFileInfo->
  273. lpNextFileInfo;
  274. break;
  275. }
  276. lpPrevFileInfo = lpCurrFileInfo;
  277. lpCurrFileInfo = lpCurrFileInfo-> lpNextFileInfo;
  278. }
  279. #ifdef WANT_HIVE_SUPPORT
  280. //
  281. // Delete all of the hives connected to this FILE_INFO.
  282. //
  283. lpHiveInfo = lpFileInfo-> lpHiveInfoList;
  284. while (!IsNullPtr(lpHiveInfo)) {
  285. RgDestroyFileInfo(lpHiveInfo-> lpFileInfo);
  286. lpTempHiveInfo = lpHiveInfo;
  287. lpHiveInfo = lpHiveInfo-> lpNextHiveInfo;
  288. RgSmFreeMemory(lpTempHiveInfo);
  289. }
  290. #endif
  291. #ifdef WANT_NOTIFY_CHANGE_SUPPORT
  292. //
  293. // Signal and free all of the change notifications. On NT, a hive cannot
  294. // be unloaded if there are any open handles referencing it. Change
  295. // notifications are cleaned up when a key handle is closed. So this
  296. // cleanup is unique to our registry code.
  297. //
  298. lpNotifyChange = lpFileInfo-> lpNotifyChangeList;
  299. while (!IsNullPtr(lpNotifyChange)) {
  300. RgSetAndReleaseEvent(lpNotifyChange-> hEvent);
  301. lpTempNotifyChange = lpNotifyChange;
  302. lpNotifyChange = lpNotifyChange-> lpNextNotifyChange;
  303. RgSmFreeMemory(lpTempNotifyChange);
  304. }
  305. #endif
  306. //
  307. // Free all memory associated with the keynode table.
  308. //
  309. if (!IsNullPtr(lpFileInfo-> lpKeynodeBlockInfo)) {
  310. for (Counter = 0, lpKeynodeBlockInfo = lpFileInfo-> lpKeynodeBlockInfo;
  311. Counter < lpFileInfo-> KeynodeBlockCount; Counter++,
  312. lpKeynodeBlockInfo++) {
  313. if (!IsNullPtr(lpKeynodeBlockInfo-> lpKeynodeBlock))
  314. RgFreeMemory(lpKeynodeBlockInfo-> lpKeynodeBlock);
  315. }
  316. RgSmFreeMemory(lpFileInfo-> lpKeynodeBlockInfo);
  317. }
  318. //
  319. // Free all memory associated with the datablocks.
  320. //
  321. if (!IsNullPtr(lpFileInfo-> lpDatablockInfo)) {
  322. for (Counter = 0, lpDatablockInfo = lpFileInfo-> lpDatablockInfo;
  323. Counter < lpFileInfo-> FileHeader.BlockCount; Counter++,
  324. lpDatablockInfo++)
  325. RgFreeDatablockInfoBuffers(lpDatablockInfo);
  326. RgSmFreeMemory(lpFileInfo-> lpDatablockInfo);
  327. }
  328. //
  329. // Free the FILE_INFO itself.
  330. //
  331. RgSmFreeMemory(lpFileInfo);
  332. return ERROR_SUCCESS;
  333. }
  334. #ifdef VXD
  335. #pragma VxD_PAGEABLE_CODE_SEG
  336. #endif
  337. //
  338. // RgFlushFileInfo
  339. //
  340. int
  341. INTERNAL
  342. RgFlushFileInfo(
  343. LPFILE_INFO lpFileInfo
  344. )
  345. {
  346. int ErrorCode;
  347. HFILE hSourceFile;
  348. HFILE hDestinationFile;
  349. char TempFileName[MAX_PATH];
  350. UINT Index;
  351. ASSERT(!IsNullPtr(lpFileInfo));
  352. if (!IsPostCriticalInit() || IsFileAccessDisabled())
  353. return ERROR_SUCCESS; // Win95 compatibility.
  354. if (!(lpFileInfo-> Flags & FI_DIRTY))
  355. return ERROR_SUCCESS;
  356. // If we're currently flushing this FILE_INFO and are called again because
  357. // of low memory conditions, ignore this request. Or if this is a memory
  358. // only registry file, there's nothing to flush to.
  359. if (lpFileInfo-> Flags & (FI_FLUSHING | FI_VOLATILE))
  360. return ERROR_SUCCESS;
  361. lpFileInfo-> Flags |= FI_FLUSHING;
  362. ErrorCode = ERROR_REGISTRY_IO_FAILED; // Assume this error code
  363. hSourceFile = HFILE_ERROR;
  364. hDestinationFile = HFILE_ERROR;
  365. if (!RgSetFileAttributes(lpFileInfo-> FileName, FILE_ATTRIBUTE_NONE))
  366. goto CleanupAfterError;
  367. if (lpFileInfo-> Flags & FI_EXTENDED) {
  368. if ((Index = StrLen(lpFileInfo-> FileName)) >= MAX_PATH)
  369. goto CleanupAfterError;
  370. StrCpy(TempFileName, lpFileInfo-> FileName);
  371. // Back up to the last backslash (or the start of the string) and
  372. // null-terminate.
  373. do {
  374. Index--;
  375. } while (Index > 0 && TempFileName[Index] != '\\');
  376. // If we found a backslash, then null terminate the string after the
  377. // backslash. Otherwise, we don't have a full qualified pathname, so
  378. // make the temporary file in the current directory and pray that's
  379. // where the registry file is.
  380. if (Index != 0)
  381. TempFileName[Index + 1] = '\0';
  382. else
  383. StrCpy(TempFileName, g_RgDotBackslashPath);
  384. if ((hDestinationFile = RgCreateTempFile(TempFileName)) ==
  385. HFILE_ERROR)
  386. goto CleanupAfterError;
  387. if ((hSourceFile = RgOpenFile(lpFileInfo-> FileName, OF_READ)) ==
  388. HFILE_ERROR)
  389. goto CleanupAfterError;
  390. TRACE(("rewriting to TempFileName = \""));
  391. TRACE((TempFileName));
  392. TRACE(("\"\n"));
  393. }
  394. else {
  395. if ((hDestinationFile = RgOpenFile(lpFileInfo-> FileName, OF_WRITE)) ==
  396. HFILE_ERROR)
  397. goto CleanupAfterError;
  398. }
  399. // Write out the file header.
  400. if (hSourceFile != HFILE_ERROR || lpFileInfo-> FileHeader.Flags &
  401. FHF_DIRTY) {
  402. // Note that RgWriteDatablocks and RgWriteDatablocksComplete uses this
  403. // value, too.
  404. if (lpFileInfo-> Flags & FI_VERSION20)
  405. lpFileInfo-> FileHeader.Size = sizeof(VERSION20_HEADER_PAGE) +
  406. lpFileInfo-> CurTotalKnSize;
  407. else
  408. lpFileInfo-> FileHeader.Size = sizeof(FILE_HEADER) +
  409. lpFileInfo-> CurTotalKnSize;
  410. if (!RgWriteFile(hDestinationFile, &lpFileInfo-> FileHeader,
  411. sizeof(FILE_HEADER)))
  412. goto CleanupAfterError;
  413. }
  414. // Write out the keynode header and table.
  415. if ((ErrorCode = RgWriteKeynodes(lpFileInfo, hSourceFile,
  416. hDestinationFile)) != ERROR_SUCCESS) {
  417. TRACE(("RgWriteKeynodes returned error %d\n", ErrorCode));
  418. goto CleanupAfterError;
  419. }
  420. // Write out the datablocks.
  421. if ((ErrorCode = RgWriteDatablocks(lpFileInfo, hSourceFile,
  422. hDestinationFile)) != ERROR_SUCCESS) {
  423. TRACE(("RgWriteDatablocks returned error %d\n", ErrorCode));
  424. goto CleanupAfterError;
  425. }
  426. RgCloseFile(hDestinationFile);
  427. // If we're extending the file, we now go back and delete the current file
  428. // and replace it with our temporary file.
  429. if (hSourceFile != HFILE_ERROR) {
  430. RgCloseFile(hSourceFile);
  431. ErrorCode = ERROR_REGISTRY_IO_FAILED; // Assume this error code
  432. if (!RgDeleteFile(lpFileInfo-> FileName))
  433. goto CleanupAfterFilesClosed;
  434. if (!RgRenameFile(TempFileName, lpFileInfo-> FileName)) {
  435. DEBUG_OUT(("RgFlushFileInfo failed to replace backing file\n"));
  436. goto CleanupAfterFilesClosed;
  437. }
  438. }
  439. // Go back and tell everyone that the write is complete-- the file has
  440. // been successfully written to disk.
  441. RgWriteDatablocksComplete(lpFileInfo);
  442. RgWriteKeynodesComplete(lpFileInfo);
  443. lpFileInfo-> FileHeader.Flags &= ~FHF_DIRTY;
  444. lpFileInfo-> Flags &= ~(FI_DIRTY | FI_EXTENDED);
  445. ErrorCode = ERROR_SUCCESS;
  446. CleanupAfterFilesClosed:
  447. RgSetFileAttributes(lpFileInfo-> FileName, FILE_ATTRIBUTE_READONLY |
  448. FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM);
  449. lpFileInfo-> Flags &= ~FI_FLUSHING;
  450. if (ErrorCode != ERROR_SUCCESS)
  451. DEBUG_OUT(("RgFlushFileInfo() returning error %d\n", ErrorCode));
  452. return ErrorCode;
  453. CleanupAfterError:
  454. if (hSourceFile != HFILE_ERROR)
  455. RgCloseFile(hSourceFile);
  456. if (hDestinationFile != HFILE_ERROR) {
  457. // If both hSourceFile and hDestinationFile were valid, then we must
  458. // have created a temporary file. Delete it now that we've failed.
  459. if (hSourceFile != HFILE_ERROR)
  460. RgDeleteFile(TempFileName);
  461. RgSetFileAttributes(lpFileInfo-> FileName, FILE_ATTRIBUTE_READONLY |
  462. FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM);
  463. }
  464. goto CleanupAfterFilesClosed;
  465. }
  466. //
  467. // RgSweepFileInfo
  468. //
  469. int
  470. INTERNAL
  471. RgSweepFileInfo(
  472. LPFILE_INFO lpFileInfo
  473. )
  474. {
  475. ASSERT(!IsNullPtr(lpFileInfo));
  476. // If we're currently sweeping this FILE_INFO and are called again because
  477. // of low memory conditions, ignore this request. Or if this is a memory
  478. // only registry file, we can't sweep anything out.
  479. if (lpFileInfo-> Flags & (FI_FLUSHING | FI_VOLATILE))
  480. return ERROR_SUCCESS;
  481. lpFileInfo-> Flags |= FI_SWEEPING;
  482. RgSweepKeynodes(lpFileInfo);
  483. RgSweepDatablocks(lpFileInfo);
  484. lpFileInfo-> Flags &= ~FI_SWEEPING;
  485. return ERROR_SUCCESS;
  486. }
  487. //
  488. // RgEnumFileInfos
  489. //
  490. // Enumerates over all FILE_INFO structures, passing each to the provided
  491. // callback. Currently, all errors from callbacks are ignored.
  492. //
  493. VOID
  494. INTERNAL
  495. RgEnumFileInfos(
  496. LPENUMFILEINFOPROC lpEnumFileInfoProc
  497. )
  498. {
  499. LPFILE_INFO lpFileInfo;
  500. LPFILE_INFO lpTempFileInfo;
  501. lpFileInfo = g_RgFileInfoList;
  502. while (!IsNullPtr(lpFileInfo)) {
  503. lpTempFileInfo = lpFileInfo;
  504. lpFileInfo = lpFileInfo-> lpNextFileInfo;
  505. (*lpEnumFileInfoProc)(lpTempFileInfo);
  506. }
  507. }
  508. #ifdef VXD
  509. #pragma VxD_RARE_CODE_SEG
  510. #endif
  511. //
  512. // RgInitRootKeyFromFileInfo
  513. //
  514. // Using the FILE_INFO contained in the key, initialize the rest of the members
  515. // of the key. If any errors occur, then the FILE_INFO is destroyed.
  516. //
  517. int
  518. INTERNAL
  519. RgInitRootKeyFromFileInfo(
  520. HKEY hKey
  521. )
  522. {
  523. int ErrorCode;
  524. LPKEYNODE lpKeynode;
  525. hKey-> KeynodeIndex = hKey-> lpFileInfo-> KeynodeHeader.RootIndex;
  526. if ((ErrorCode = RgLockInUseKeynode(hKey-> lpFileInfo, hKey-> KeynodeIndex,
  527. &lpKeynode)) == ERROR_SUCCESS) {
  528. hKey-> Signature = KEY_SIGNATURE;
  529. hKey-> Flags &= ~(KEYF_INVALID | KEYF_DELETED | KEYF_ENUMKEYCACHED);
  530. hKey-> ChildKeynodeIndex = lpKeynode-> ChildIndex;
  531. hKey-> BlockIndex = (WORD) lpKeynode-> BlockIndex;
  532. hKey-> KeyRecordIndex = (BYTE) lpKeynode-> KeyRecordIndex;
  533. RgUnlockKeynode(hKey-> lpFileInfo, hKey-> KeynodeIndex, FALSE);
  534. }
  535. else
  536. RgDestroyFileInfo(hKey-> lpFileInfo);
  537. return ErrorCode;
  538. }
  539. #ifdef VXD
  540. #pragma VxD_INIT_CODE_SEG
  541. #endif
  542. //
  543. // VMMRegMapPredefKeyToFile2 -- Alternate version of VMMRegMapPredefKeyToFile that
  544. // allows remapping of HKCU. (Called by VMMRegMapPredefKeyToFile.)
  545. //
  546. LONG
  547. REGAPI
  548. VMMRegMapPredefKeyToFile2(
  549. HKEY hKey,
  550. LPCSTR lpFileName,
  551. UINT Flags,
  552. BOOL fAllowMapToHKCU
  553. )
  554. {
  555. int ErrorCode;
  556. #ifdef WIN32
  557. char FullPathName[MAX_PATH];
  558. #endif
  559. UINT CreateNewFlags;
  560. if (!( hKey == HKEY_LOCAL_MACHINE ||
  561. hKey == HKEY_USERS ||
  562. (hKey == HKEY_CURRENT_USER && fAllowMapToHKCU))) {
  563. return ERROR_INVALID_PARAMETER;
  564. }
  565. if (IsBadOptionalStringPtr(lpFileName, (UINT) -1))
  566. return ERROR_INVALID_PARAMETER;
  567. if (!RgLockRegistry())
  568. return ERROR_LOCK_FAILED;
  569. RgValidateAndConvertKeyHandle(&hKey);
  570. if (!(hKey-> Flags & KEYF_INVALID))
  571. RgDestroyFileInfo(hKey-> lpFileInfo);
  572. // Specifying NULL "unmaps" the key and leaves it invalidated.
  573. if (IsNullPtr(lpFileName))
  574. return ERROR_SUCCESS;
  575. #ifdef WIN32
  576. // For users of the Win32 DLL, resolve the path name so they don't have to.
  577. if ((GetFullPathName(lpFileName, sizeof(FullPathName), FullPathName,
  578. NULL)) != 0)
  579. lpFileName = FullPathName;
  580. #endif
  581. if (Flags & MPKF_CREATENEW) {
  582. CreateNewFlags = CFIN_PRIMARY | ((Flags & MPKF_VERSION20) ?
  583. CFIN_VERSION20 : 0);
  584. ErrorCode = RgCreateFileInfoNew(&hKey-> lpFileInfo, lpFileName,
  585. CreateNewFlags);
  586. }
  587. else {
  588. ErrorCode = RgCreateFileInfoExisting(&hKey-> lpFileInfo, lpFileName);
  589. }
  590. if (ErrorCode == ERROR_SUCCESS)
  591. ErrorCode = RgInitRootKeyFromFileInfo(hKey);
  592. RgUnlockRegistry();
  593. return ErrorCode;
  594. }
  595. //
  596. // VMMRegMapPredefKeyToFile
  597. //
  598. LONG
  599. REGAPI
  600. VMMRegMapPredefKeyToFile(
  601. HKEY hKey,
  602. LPCSTR lpFileName,
  603. UINT Flags
  604. )
  605. {
  606. return VMMRegMapPredefKeyToFile2(hKey, lpFileName, Flags, FALSE);
  607. }