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.

982 lines
29 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. cminit.c
  5. Abstract:
  6. This module contains init support for the CM level of the
  7. config manager/hive.
  8. Author:
  9. Bryan M. Willman (bryanwi) 2-Apr-1992
  10. Revision History:
  11. --*/
  12. #include "cmp.h"
  13. //
  14. // Prototypes local to this module
  15. //
  16. NTSTATUS
  17. CmpOpenFileWithExtremePrejudice(
  18. OUT PHANDLE Primary,
  19. IN POBJECT_ATTRIBUTES Obja,
  20. IN ULONG IoFlags,
  21. IN ULONG AttributeFlags
  22. );
  23. #ifdef ALLOC_PRAGMA
  24. #pragma alloc_text(PAGE,CmpOpenHiveFiles)
  25. #pragma alloc_text(PAGE,CmpInitializeHive)
  26. #pragma alloc_text(PAGE,CmpDestroyHive)
  27. #pragma alloc_text(PAGE,CmpOpenFileWithExtremePrejudice)
  28. #endif
  29. extern PCMHIVE CmpMasterHive;
  30. extern LIST_ENTRY CmpHiveListHead;
  31. NTSTATUS
  32. CmpOpenHiveFiles(
  33. PUNICODE_STRING BaseName,
  34. PWSTR Extension OPTIONAL,
  35. PHANDLE Primary,
  36. PHANDLE Secondary,
  37. PULONG PrimaryDisposition,
  38. PULONG SecondaryDisposition,
  39. BOOLEAN CreateAllowed,
  40. BOOLEAN MarkAsSystemHive,
  41. BOOLEAN NoBuffering,
  42. OUT OPTIONAL PULONG ClusterSize
  43. )
  44. /*++
  45. Routine Description:
  46. Open/Create Primary, and Log files for Hives.
  47. BaseName is some name like "\winnt\system32\config\system".
  48. Extension is ".alt" or ".log" or NULL.
  49. If extension is NULL skip secondary work.
  50. If extension is .alt or .log, open/create a secondary file
  51. (e.g. "\winnt\system32\config\system.alt")
  52. If extension is .log, open secondary for buffered I/O, else,
  53. open for non-buffered I/O. Primary always uses non-buffered I/O.
  54. If primary is newly created, supersede secondary. If secondary
  55. does not exist, simply create (other code will complain if Log
  56. is needed but does not exist.)
  57. WARNING: If Secondary handle is NULL, you have no log
  58. or alternate!
  59. Arguments:
  60. BaseName - unicode string of base hive file, must have space for
  61. extension if that is used.
  62. Extension - unicode type extension of secondary file, including
  63. the leading "."
  64. Primary - will get handle to primary file
  65. Secondary - will get handle to secondary, or NULL
  66. PrimaryDisposition - STATUS_SUCCESS or STATUS_CREATED, of primary file.
  67. SecondaryDisposition - STATUS_SUCCESS or STATUS_CREATED, of secondary file.
  68. CreateAllowed - if TRUE will create nonexistent primary, if FALSE will
  69. fail if primary does not exist. no effect on log
  70. MarkAsSystemHive - if TRUE will call into file system to mark this
  71. as a critical system hive.
  72. ClusterSize - if not NULL, will compute and return the appropriate
  73. cluster size for the primary file.
  74. Return Value:
  75. status - if status is success, Primay succeeded, check Secondary
  76. value to see if it succeeded.
  77. --*/
  78. {
  79. IO_STATUS_BLOCK IoStatus;
  80. IO_STATUS_BLOCK FsctlIoStatus;
  81. FILE_FS_SIZE_INFORMATION FsSizeInformation;
  82. ULONG Cluster;
  83. ULONG CreateDisposition;
  84. OBJECT_ATTRIBUTES ObjectAttributes;
  85. NTSTATUS status;
  86. UNICODE_STRING ExtName;
  87. UNICODE_STRING WorkName;
  88. PVOID WorkBuffer;
  89. USHORT NameSize;
  90. ULONG IoFlags;
  91. ULONG AttributeFlags;
  92. ULONG ShareMode;
  93. ULONG DesiredAccess;
  94. USHORT CompressionState;
  95. HANDLE hEvent;
  96. PKEVENT pEvent;
  97. #ifdef CM_RETRY_CREATE_FILE
  98. ULONG RetryCreateCount = 0;
  99. #endif //CM_RETRY_CREATE_FILE
  100. //
  101. // Allocate an event to use for our overlapped I/O
  102. //
  103. status = CmpCreateEvent(NotificationEvent, &hEvent, &pEvent);
  104. if (!NT_SUCCESS(status)) {
  105. return(status);
  106. }
  107. //
  108. // Allocate a buffer big enough to hold the full name
  109. //
  110. WorkName.Length = 0;
  111. WorkName.MaximumLength = 0;
  112. WorkName.Buffer = NULL;
  113. WorkBuffer = NULL;
  114. NameSize = BaseName->Length;
  115. if (ARGUMENT_PRESENT(Extension)) {
  116. NameSize += (wcslen(Extension)+1) * sizeof(WCHAR);
  117. WorkBuffer = ExAllocatePool(PagedPool, NameSize);
  118. WorkName.Buffer = WorkBuffer;
  119. if (WorkBuffer == NULL) {
  120. ObDereferenceObject(pEvent);
  121. ZwClose(hEvent);
  122. return STATUS_NO_MEMORY;
  123. }
  124. WorkName.MaximumLength = NameSize;
  125. RtlAppendStringToString((PSTRING)&WorkName, (PSTRING)BaseName);
  126. } else {
  127. WorkName = *BaseName;
  128. }
  129. //
  130. // Open/Create the primary
  131. //
  132. InitializeObjectAttributes(
  133. &ObjectAttributes,
  134. &WorkName,
  135. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  136. NULL,
  137. NULL
  138. );
  139. if (CreateAllowed && !CmpShareSystemHives) {
  140. CreateDisposition = FILE_OPEN_IF;
  141. } else {
  142. CreateDisposition = FILE_OPEN;
  143. }
  144. ASSERT_PASSIVE_LEVEL();
  145. AttributeFlags = FILE_OPEN_FOR_BACKUP_INTENT | FILE_NO_COMPRESSION | FILE_RANDOM_ACCESS;
  146. if( NoBuffering == TRUE ) {
  147. AttributeFlags |= FILE_NO_INTERMEDIATE_BUFFERING;
  148. }
  149. #ifdef CM_RETRY_CREATE_FILE
  150. RetryCreate1:
  151. #endif //CM_RETRY_CREATE_FILE
  152. //
  153. // Share the file if needed
  154. //
  155. if (CmpMiniNTBoot && CmpShareSystemHives) {
  156. DesiredAccess = FILE_READ_DATA;
  157. ShareMode = FILE_SHARE_READ;
  158. } else {
  159. ShareMode = 0;
  160. DesiredAccess = FILE_READ_DATA | FILE_WRITE_DATA;
  161. }
  162. status = ZwCreateFile(
  163. Primary,
  164. DesiredAccess,
  165. &ObjectAttributes,
  166. &IoStatus,
  167. NULL, // alloc size = none
  168. FILE_ATTRIBUTE_NORMAL,
  169. ShareMode, // share nothing
  170. CreateDisposition,
  171. ////FILE_NO_INTERMEDIATE_BUFFERING |
  172. //FILE_OPEN_FOR_BACKUP_INTENT |
  173. //FILE_NO_COMPRESSION,
  174. AttributeFlags,
  175. NULL, // eabuffer
  176. 0 // ealength
  177. );
  178. #ifdef CM_RETRY_CREATE_FILE
  179. if( !NT_SUCCESS(status) ) {
  180. if( RetryCreateCount == 0 ) {
  181. RetryCreateCount++;
  182. DbgBreakPoint();
  183. goto RetryCreate1;
  184. }
  185. }
  186. //
  187. // reset it for the log
  188. //
  189. RetryCreateCount = 0;
  190. #endif //CM_RETRY_CREATE_FILE
  191. if (status == STATUS_ACCESS_DENIED) {
  192. //
  193. // This means some person has put a read-only attribute
  194. // on one of the critical system hive files. Remove it so they
  195. // don't hurt themselves.
  196. //
  197. status = CmpOpenFileWithExtremePrejudice(Primary,
  198. &ObjectAttributes,
  199. AttributeFlags,
  200. FILE_ATTRIBUTE_NORMAL);
  201. }
  202. if (!CmpShareSystemHives && (MarkAsSystemHive) &&
  203. (NT_SUCCESS(status))) {
  204. ASSERT_PASSIVE_LEVEL();
  205. status = ZwFsControlFile(*Primary,
  206. hEvent,
  207. NULL,
  208. NULL,
  209. &FsctlIoStatus,
  210. FSCTL_MARK_AS_SYSTEM_HIVE,
  211. NULL,
  212. 0,
  213. NULL,
  214. 0);
  215. if (status == STATUS_PENDING) {
  216. KeWaitForSingleObject(pEvent,
  217. Executive,
  218. KernelMode,
  219. FALSE,
  220. NULL);
  221. status = FsctlIoStatus.Status;
  222. }
  223. //
  224. // STATUS_INVALID_DEVICE_REQUEST is OK.
  225. //
  226. if (status == STATUS_INVALID_DEVICE_REQUEST) {
  227. status = STATUS_SUCCESS;
  228. } else if (!NT_SUCCESS(status)) {
  229. ZwClose(*Primary);
  230. }
  231. }
  232. if (!NT_SUCCESS(status)) {
  233. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"CMINIT: CmpOpenHiveFile: "));
  234. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"\tPrimary Open/Create failed for:\n"));
  235. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"\t%wZ\n", &WorkName));
  236. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"\tstatus = %08lx\n", status));
  237. if (WorkBuffer != NULL) {
  238. ExFreePool(WorkBuffer);
  239. }
  240. ObDereferenceObject(pEvent);
  241. ZwClose(hEvent);
  242. return status;
  243. }
  244. //
  245. // Make sure the file is uncompressed in order to prevent the filesystem
  246. // from failing our updates due to disk full conditions.
  247. //
  248. // Do not fail to open the file if this fails, we don't want to prevent
  249. // people from booting just because their disk is full. Although they
  250. // will not be able to update their registry, they will at lease be
  251. // able to delete some files.
  252. //
  253. CompressionState = 0;
  254. ASSERT_PASSIVE_LEVEL();
  255. status = ZwFsControlFile(*Primary,
  256. hEvent,
  257. NULL,
  258. NULL,
  259. &FsctlIoStatus,
  260. FSCTL_SET_COMPRESSION,
  261. &CompressionState,
  262. sizeof(CompressionState),
  263. NULL,
  264. 0);
  265. if (status == STATUS_PENDING) {
  266. KeWaitForSingleObject(pEvent,
  267. Executive,
  268. KernelMode,
  269. FALSE,
  270. NULL);
  271. }
  272. *PrimaryDisposition = (ULONG) IoStatus.Information;
  273. if( *PrimaryDisposition != FILE_CREATED ) {
  274. //
  275. // 0-lengthed file case
  276. //
  277. FILE_STANDARD_INFORMATION FileInformation;
  278. NTSTATUS status2;
  279. status2 = ZwQueryInformationFile(*Primary,
  280. &IoStatus,
  281. (PVOID)&FileInformation,
  282. sizeof( FileInformation ),
  283. FileStandardInformation
  284. );
  285. if (NT_SUCCESS( status2 )) {
  286. if(FileInformation.EndOfFile.QuadPart == 0) {
  287. //
  288. // treat it as a non-existant one.
  289. //
  290. *PrimaryDisposition = FILE_CREATED;
  291. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"Primary file is zero-lengthed => treat it as non-existant\n"));
  292. }
  293. }
  294. }
  295. if (ARGUMENT_PRESENT(ClusterSize)) {
  296. ASSERT_PASSIVE_LEVEL();
  297. status = ZwQueryVolumeInformationFile(*Primary,
  298. &IoStatus,
  299. &FsSizeInformation,
  300. sizeof(FILE_FS_SIZE_INFORMATION),
  301. FileFsSizeInformation);
  302. if (!NT_SUCCESS(status)) {
  303. ObDereferenceObject(pEvent);
  304. ZwClose(hEvent);
  305. return(status);
  306. }
  307. if (FsSizeInformation.BytesPerSector > HBLOCK_SIZE) {
  308. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"CmpOpenHiveFiles: sectorsize %lx > HBLOCK_SIZE\n"));
  309. ObDereferenceObject(pEvent);
  310. ZwClose(hEvent);
  311. return(STATUS_CANNOT_LOAD_REGISTRY_FILE);
  312. }
  313. Cluster = FsSizeInformation.BytesPerSector / HSECTOR_SIZE;
  314. *ClusterSize = (Cluster < 1) ? 1 : Cluster;
  315. }
  316. if ( ! ARGUMENT_PRESENT(Extension)) {
  317. if (WorkBuffer != NULL) {
  318. ExFreePool(WorkBuffer);
  319. }
  320. ObDereferenceObject(pEvent);
  321. ZwClose(hEvent);
  322. return STATUS_SUCCESS;
  323. }
  324. //
  325. // Open/Create the secondary
  326. //
  327. CreateDisposition = CmpShareSystemHives ? FILE_OPEN : FILE_OPEN_IF;
  328. if (*PrimaryDisposition == FILE_CREATED) {
  329. CreateDisposition = FILE_SUPERSEDE;
  330. }
  331. RtlInitUnicodeString(&ExtName,Extension);
  332. status = RtlAppendStringToString((PSTRING)&WorkName, (PSTRING)&ExtName);
  333. InitializeObjectAttributes(&ObjectAttributes,
  334. &WorkName,
  335. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  336. NULL,
  337. NULL);
  338. //
  339. // non-cached log files (or alternates)
  340. //
  341. IoFlags = FILE_NO_COMPRESSION | FILE_NO_INTERMEDIATE_BUFFERING;
  342. if (_wcsnicmp(Extension, L".log", 4) != 0) {
  343. AttributeFlags = FILE_ATTRIBUTE_NORMAL;
  344. } else {
  345. AttributeFlags = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_HIDDEN;
  346. }
  347. #ifdef CM_RETRY_CREATE_FILE
  348. RetryCreate2:
  349. #endif //CM_RETRY_CREATE_FILE
  350. ASSERT_PASSIVE_LEVEL();
  351. status = ZwCreateFile(
  352. Secondary,
  353. DesiredAccess,
  354. &ObjectAttributes,
  355. &IoStatus,
  356. NULL, // alloc size = none
  357. AttributeFlags,
  358. ShareMode,
  359. CreateDisposition,
  360. IoFlags,
  361. NULL, // eabuffer
  362. 0 // ealength
  363. );
  364. #ifdef CM_RETRY_CREATE_FILE
  365. if( !NT_SUCCESS(status) ) {
  366. if( RetryCreateCount == 0 ) {
  367. RetryCreateCount++;
  368. DbgBreakPoint();
  369. goto RetryCreate2;
  370. }
  371. }
  372. #endif //CM_RETRY_CREATE_FILE
  373. if (status == STATUS_ACCESS_DENIED) {
  374. //
  375. // This means some person has put a read-only attribute
  376. // on one of the critical system hive files. Remove it so they
  377. // don't hurt themselves.
  378. //
  379. status = CmpOpenFileWithExtremePrejudice(Secondary,
  380. &ObjectAttributes,
  381. IoFlags,
  382. AttributeFlags);
  383. }
  384. if (!CmpShareSystemHives && (MarkAsSystemHive) &&
  385. (NT_SUCCESS(status))) {
  386. ASSERT_PASSIVE_LEVEL();
  387. status = ZwFsControlFile(*Secondary,
  388. hEvent,
  389. NULL,
  390. NULL,
  391. &FsctlIoStatus,
  392. FSCTL_MARK_AS_SYSTEM_HIVE,
  393. NULL,
  394. 0,
  395. NULL,
  396. 0);
  397. if (status == STATUS_PENDING) {
  398. KeWaitForSingleObject(pEvent,
  399. Executive,
  400. KernelMode,
  401. FALSE,
  402. NULL);
  403. status = FsctlIoStatus.Status;
  404. }
  405. //
  406. // STATUS_INVALID_DEVICE_REQUEST is OK.
  407. //
  408. if (status == STATUS_INVALID_DEVICE_REQUEST) {
  409. status = STATUS_SUCCESS;
  410. } else if (!NT_SUCCESS(status)) {
  411. ZwClose(*Secondary);
  412. }
  413. }
  414. if (!NT_SUCCESS(status)) {
  415. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"CMINIT: CmpOpenHiveFile: "));
  416. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"\tSecondary Open/Create failed for:\n"));
  417. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"\t%wZ\n", &WorkName));
  418. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"\tstatus = %08lx\n", status));
  419. *Secondary = NULL;
  420. }
  421. *SecondaryDisposition = (ULONG) IoStatus.Information;
  422. //
  423. // Make sure the file is uncompressed in order to prevent the filesystem
  424. // from failing our updates due to disk full conditions.
  425. //
  426. // Do not fail to open the file if this fails, we don't want to prevent
  427. // people from booting just because their disk is full. Although they
  428. // will not be able to update their registry, they will at lease be
  429. // able to delete some files.
  430. //
  431. CompressionState = 0;
  432. ASSERT_PASSIVE_LEVEL();
  433. status = ZwFsControlFile(*Secondary,
  434. hEvent,
  435. NULL,
  436. NULL,
  437. &FsctlIoStatus,
  438. FSCTL_SET_COMPRESSION,
  439. &CompressionState,
  440. sizeof(CompressionState),
  441. NULL,
  442. 0);
  443. if (status == STATUS_PENDING) {
  444. KeWaitForSingleObject(pEvent,
  445. Executive,
  446. KernelMode,
  447. FALSE,
  448. NULL);
  449. }
  450. if (WorkBuffer != NULL) {
  451. ExFreePool(WorkBuffer);
  452. }
  453. ObDereferenceObject(pEvent);
  454. ZwClose(hEvent);
  455. return STATUS_SUCCESS;
  456. }
  457. NTSTATUS
  458. CmpInitializeHive(
  459. PCMHIVE *CmHive,
  460. ULONG OperationType,
  461. ULONG HiveFlags,
  462. ULONG FileType,
  463. PVOID HiveData OPTIONAL,
  464. HANDLE Primary,
  465. HANDLE Log,
  466. HANDLE External,
  467. PUNICODE_STRING FileName OPTIONAL,
  468. ULONG CheckFlags
  469. )
  470. /*++
  471. Routine Description:
  472. Initialize a hive.
  473. Arguments:
  474. CmHive - pointer to a variable to receive a pointer to the CmHive structure
  475. OperationType - specifies whether to create a new hive from scratch,
  476. from a memory image, or by reading a file from disk.
  477. [HINIT_CREATE | HINIT_MEMORY | HINIT_FILE | HINIT_MAPFILE]
  478. HiveFlags - HIVE_VOLATILE - Entire hive is to be volatile, regardless
  479. of the types of cells allocated
  480. HIVE_NO_LAZY_FLUSH - Data in this hive is never written
  481. to disk except by an explicit FlushKey
  482. FileType - HFILE_TYPE_*, HFILE_TYPE_LOG set up for logging support
  483. HiveData - if present, supplies a pointer to an in memory image of
  484. from which to init the hive. Only useful when OperationType
  485. is set to HINIT_MEMORY.
  486. Primary - File handle for primary hive file (e.g. SYSTEM)
  487. Log - File handle for log hive file (e.g. SOFTWARE.LOG)
  488. External - File handle for primary hive file (e.g. BACKUP.REG)
  489. FileName - some path like "...\system32\config\system", which will
  490. be written into the base block as an aid to debugging.
  491. may be NULL.
  492. CheckFlags - Flags to be passed to CmCheckRegistry
  493. usually this is CM_CHECK_REGISTRY_CHECK_CLEAN, except for the system hive
  494. where CM_CHECK_REGISTRY_FORCE_CLEAN is passed
  495. Return Value:
  496. NTSTATUS
  497. --*/
  498. {
  499. FILE_FS_SIZE_INFORMATION FsSizeInformation;
  500. IO_STATUS_BLOCK IoStatusBlock;
  501. ULONG Cluster;
  502. NTSTATUS Status;
  503. PCMHIVE cmhive2;
  504. ULONG rc;
  505. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INIT,"CmpInitializeHive:\t\n"));
  506. //
  507. // Reject illegal parms
  508. //
  509. if ( (External && (Primary || Log)) ||
  510. (Log && !Primary) ||
  511. (!CmpShareSystemHives && (HiveFlags & HIVE_VOLATILE) && (Primary || External || Log)) ||
  512. ((OperationType == HINIT_MEMORY) && (!ARGUMENT_PRESENT(HiveData))) ||
  513. (Log && (FileType != HFILE_TYPE_LOG))
  514. )
  515. {
  516. return (STATUS_INVALID_PARAMETER);
  517. }
  518. //
  519. // compute control
  520. //
  521. if (Primary) {
  522. ASSERT_PASSIVE_LEVEL();
  523. Status = ZwQueryVolumeInformationFile(
  524. Primary,
  525. &IoStatusBlock,
  526. &FsSizeInformation,
  527. sizeof(FILE_FS_SIZE_INFORMATION),
  528. FileFsSizeInformation
  529. );
  530. if (!NT_SUCCESS(Status)) {
  531. return (Status);
  532. }
  533. if (FsSizeInformation.BytesPerSector > HBLOCK_SIZE) {
  534. return (STATUS_REGISTRY_IO_FAILED);
  535. }
  536. Cluster = FsSizeInformation.BytesPerSector / HSECTOR_SIZE;
  537. Cluster = (Cluster < 1) ? 1 : Cluster;
  538. } else {
  539. Cluster = 1;
  540. }
  541. cmhive2 = CmpAllocate(sizeof(CMHIVE), FALSE,CM_FIND_LEAK_TAG10);
  542. if (cmhive2 == NULL) {
  543. return (STATUS_INSUFFICIENT_RESOURCES);
  544. }
  545. #ifdef NT_UNLOAD_KEY_EX
  546. cmhive2->UnloadEvent = NULL;
  547. cmhive2->RootKcb = NULL;
  548. cmhive2->Frozen = FALSE;
  549. cmhive2->UnloadWorkItem = NULL;
  550. #endif //NT_UNLOAD_KEY_EX
  551. cmhive2->GrowOnlyMode = FALSE;
  552. cmhive2->GrowOffset = 0;
  553. InitializeListHead(&(cmhive2->KcbConvertListHead));
  554. InitializeListHead(&(cmhive2->KnodeConvertListHead));
  555. cmhive2->CellRemapArray = NULL;
  556. //
  557. // Allocate the mutex from NonPagedPool so it will not be swapped to the disk
  558. //
  559. cmhive2->HiveLock = (PFAST_MUTEX)ExAllocatePoolWithTag(NonPagedPool, sizeof(FAST_MUTEX), CM_POOL_TAG );
  560. if( cmhive2->HiveLock == NULL ) {
  561. CmpFree(cmhive2, sizeof(CMHIVE));
  562. return (STATUS_INSUFFICIENT_RESOURCES);
  563. }
  564. cmhive2->ViewLock = (PFAST_MUTEX)ExAllocatePoolWithTag(NonPagedPool, sizeof(FAST_MUTEX), CM_POOL_TAG );
  565. if( cmhive2->ViewLock == NULL ) {
  566. ASSERT( cmhive2->HiveLock );
  567. ExFreePool(cmhive2->HiveLock);
  568. CmpFree(cmhive2, sizeof(CMHIVE));
  569. return (STATUS_INSUFFICIENT_RESOURCES);
  570. }
  571. // need to do this consistently!!!
  572. cmhive2->FileObject = NULL;
  573. cmhive2->FileFullPath.Buffer = NULL;
  574. cmhive2->FileFullPath.Length = 0;
  575. cmhive2->FileFullPath.MaximumLength = 0;
  576. cmhive2->FileUserName.Buffer = NULL;
  577. cmhive2->FileUserName.Length = 0;
  578. cmhive2->FileUserName.MaximumLength = 0;
  579. //
  580. // Initialize the Cm hive control block
  581. //
  582. //
  583. ASSERT((HFILE_TYPE_EXTERNAL+1) == HFILE_TYPE_MAX);
  584. cmhive2->FileHandles[HFILE_TYPE_PRIMARY] = Primary;
  585. cmhive2->FileHandles[HFILE_TYPE_LOG] = Log;
  586. cmhive2->FileHandles[HFILE_TYPE_EXTERNAL] = External;
  587. cmhive2->NotifyList.Flink = NULL;
  588. cmhive2->NotifyList.Blink = NULL;
  589. ExInitializeFastMutex(cmhive2->HiveLock);
  590. ExInitializeFastMutex(cmhive2->ViewLock);
  591. CmpInitHiveViewList(cmhive2);
  592. //
  593. // Initialize the view list
  594. //
  595. #if DBG
  596. if( FileName ) {
  597. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"Initializing HiveViewList for hive (%p) (%.*S) \n\n",cmhive2,FileName->Length / sizeof(WCHAR),FileName->Buffer));
  598. }
  599. #endif
  600. //
  601. // Initialize the security cache
  602. //
  603. CmpInitSecurityCache(cmhive2);
  604. //
  605. // Initialize the Hv hive control block
  606. //
  607. Status = HvInitializeHive(
  608. &(cmhive2->Hive),
  609. OperationType,
  610. HiveFlags,
  611. FileType,
  612. HiveData,
  613. CmpAllocate,
  614. CmpFree,
  615. CmpFileSetSize,
  616. CmpFileWrite,
  617. CmpFileRead,
  618. CmpFileFlush,
  619. Cluster,
  620. FileName
  621. );
  622. if (!NT_SUCCESS(Status)) {
  623. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"CmpInitializeHive: "));
  624. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"HvInitializeHive failed, Status = %08lx\n", Status));
  625. #ifdef DRAGOSS_PRIVATE_DEBUG
  626. if( OperationType == HINIT_FILE ) DbgBreakPoint();
  627. #endif //DRAGOSS_PRIVATE_DEBUG
  628. ASSERT( cmhive2->HiveLock );
  629. ExFreePool(cmhive2->HiveLock);
  630. ASSERT( cmhive2->ViewLock );
  631. ExFreePool(cmhive2->ViewLock);
  632. CmpDestroyHiveViewList(cmhive2);
  633. CmpDestroySecurityCache (cmhive2);
  634. CmpDropFileObjectForHive(cmhive2);
  635. CmpCheckForOrphanedKcbs((PHHIVE)cmhive2);
  636. CmpFree(cmhive2, sizeof(CMHIVE));
  637. return (Status);
  638. }
  639. if ( (OperationType == HINIT_FILE) ||
  640. (OperationType == HINIT_MAPFILE) ||
  641. (OperationType == HINIT_MEMORY) ||
  642. (OperationType == HINIT_MEMORY_INPLACE))
  643. {
  644. rc = CmCheckRegistry(cmhive2, CheckFlags);
  645. if (rc != 0) {
  646. PCM_VIEW_OF_FILE CmView;
  647. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"CmpInitializeHive: "));
  648. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"CmCheckRegistry failed, rc = %08lx\n",rc));
  649. //
  650. // we have dirtied some cells (by clearing the volatile information)
  651. // we need first to unpin all the views
  652. #ifdef DRAGOSS_PRIVATE_DEBUG
  653. if( OperationType == HINIT_FILE ) DbgBreakPoint();
  654. #endif //DRAGOSS_PRIVATE_DEBUG
  655. //
  656. // in theory we should do this for MEMORY and MEMORY_INPLACE
  657. // as well, but they're only used at init time.
  658. //
  659. CmpDestroyHiveViewList(cmhive2);
  660. CmpDestroySecurityCache(cmhive2);
  661. CmpDropFileObjectForHive(cmhive2);
  662. if (OperationType == HINIT_FILE) {
  663. HvFreeHive((PHHIVE)cmhive2);
  664. } else {
  665. CmpCheckForOrphanedKcbs((PHHIVE)cmhive2);
  666. }
  667. ASSERT( cmhive2->HiveLock );
  668. ExFreePool(cmhive2->HiveLock);
  669. ASSERT( cmhive2->ViewLock );
  670. ExFreePool(cmhive2->ViewLock);
  671. CmpFree(cmhive2, sizeof(CMHIVE));
  672. return(STATUS_REGISTRY_CORRUPT);
  673. }
  674. }
  675. LOCK_HIVE_LIST();
  676. InsertHeadList(&CmpHiveListHead, &(cmhive2->HiveList));
  677. UNLOCK_HIVE_LIST();
  678. *CmHive = cmhive2;
  679. return (STATUS_SUCCESS);
  680. }
  681. BOOLEAN
  682. CmpDestroyHive(
  683. IN PHHIVE Hive,
  684. IN HCELL_INDEX Cell
  685. )
  686. /*++
  687. Routine Description:
  688. This routine tears down a cmhive.
  689. Arguments:
  690. Hive - Supplies a pointer to the hive to be freed.
  691. Cell - Supplies index of the hive's root cell.
  692. Return Value:
  693. TRUE if successful
  694. FALSE if some failure occurred
  695. --*/
  696. {
  697. PCELL_DATA CellData;
  698. HCELL_INDEX LinkCell;
  699. NTSTATUS Status;
  700. //
  701. // First find the link cell.
  702. //
  703. CellData = HvGetCell(Hive, Cell);
  704. if( CellData == NULL ) {
  705. //
  706. // we couldn't map the bin containing this cell
  707. //
  708. return FALSE;
  709. }
  710. LinkCell = CellData->u.KeyNode.Parent;
  711. HvReleaseCell(Hive, Cell);
  712. //
  713. // Now delete the link cell.
  714. //
  715. ASSERT(FIELD_OFFSET(CMHIVE, Hive) == 0);
  716. Status = CmpFreeKeyByCell((PHHIVE)CmpMasterHive, LinkCell, TRUE);
  717. if (NT_SUCCESS(Status)) {
  718. //
  719. // Take the hive out of the hive list
  720. //
  721. LOCK_HIVE_LIST();
  722. CmpRemoveEntryList(&( ((PCMHIVE)Hive)->HiveList));
  723. UNLOCK_HIVE_LIST();
  724. return(TRUE);
  725. } else {
  726. return(FALSE);
  727. }
  728. }
  729. NTSTATUS
  730. CmpOpenFileWithExtremePrejudice(
  731. OUT PHANDLE Primary,
  732. IN POBJECT_ATTRIBUTES Obja,
  733. IN ULONG IoFlags,
  734. IN ULONG AttributeFlags
  735. )
  736. /*++
  737. Routine Description:
  738. This routine opens a hive file that some person has put a
  739. read-only attribute on. It is used to prevent people from hurting
  740. themselves by making the critical system hive files read-only.
  741. Arguments:
  742. Primary - Returns handle to file
  743. Obja - Supplies Object Attributes of file.
  744. IoFlags - Supplies flags to pass to ZwCreateFile
  745. Return Value:
  746. NTSTATUS
  747. --*/
  748. {
  749. NTSTATUS Status;
  750. HANDLE Handle;
  751. IO_STATUS_BLOCK IoStatusBlock;
  752. FILE_BASIC_INFORMATION FileInfo;
  753. RtlZeroMemory(&FileInfo, sizeof(FileInfo));
  754. //
  755. // Get the current file attributes
  756. //
  757. ASSERT_PASSIVE_LEVEL();
  758. Status = ZwQueryAttributesFile(Obja, &FileInfo);
  759. if (!NT_SUCCESS(Status)) {
  760. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"ZwQueryAttributesFile failed with IO status %lx\n",Status));
  761. return(Status);
  762. }
  763. //
  764. // Clear the readonly bit.
  765. //
  766. FileInfo.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
  767. //
  768. // Open the file
  769. //
  770. Status = ZwOpenFile(&Handle,
  771. FILE_WRITE_ATTRIBUTES,
  772. Obja,
  773. &IoStatusBlock,
  774. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  775. FILE_OPEN_FOR_BACKUP_INTENT);
  776. if (!NT_SUCCESS(Status)) {
  777. return(Status);
  778. }
  779. //
  780. // Set the new attributes
  781. //
  782. Status = ZwSetInformationFile(Handle,
  783. &IoStatusBlock,
  784. &FileInfo,
  785. sizeof(FileInfo),
  786. FileBasicInformation);
  787. ZwClose(Handle);
  788. if (NT_SUCCESS(Status)) {
  789. //
  790. // Reopen the file with the access that we really need.
  791. //
  792. Status = ZwCreateFile(Primary,
  793. FILE_READ_DATA | FILE_WRITE_DATA,
  794. Obja,
  795. &IoStatusBlock,
  796. NULL,
  797. AttributeFlags,
  798. 0,
  799. FILE_OPEN,
  800. IoFlags,
  801. NULL,
  802. 0);
  803. }
  804. #if DBG
  805. else {
  806. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"ZwSetInformationFile failed with IO status %lx\n",Status));
  807. }
  808. CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpOpenFileWithExtremePrejudice returns with IO status %lx\n",Status));
  809. #endif
  810. return(Status);
  811. }