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.

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