Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

cminit.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1992 Microsoft Corporation 00004 00005 Module Name: 00006 00007 cminit.c 00008 00009 Abstract: 00010 00011 This module contains init support for the CM level of the 00012 config manager/hive. 00013 00014 Author: 00015 00016 Bryan M. Willman (bryanwi) 2-Apr-1992 00017 00018 Revision History: 00019 00020 --*/ 00021 00022 #include "cmp.h" 00023 00024 // 00025 // Prototypes local to this module 00026 // 00027 NTSTATUS 00028 CmpOpenFileWithExtremePrejudice( 00029 OUT PHANDLE Primary, 00030 IN POBJECT_ATTRIBUTES Obja, 00031 IN ULONG IoFlags, 00032 IN ULONG AttributeFlags 00033 ); 00034 00035 #ifdef ALLOC_PRAGMA 00036 #pragma alloc_text(PAGE,CmpOpenHiveFiles) 00037 #pragma alloc_text(PAGE,CmpInitializeHive) 00038 #pragma alloc_text(PAGE,CmpDestroyHive) 00039 #pragma alloc_text(PAGE,CmpOpenFileWithExtremePrejudice) 00040 #endif 00041 00042 extern PCMHIVE CmpMasterHive; 00043 extern LIST_ENTRY CmpHiveListHead; 00044 00045 NTSTATUS 00046 CmpOpenHiveFiles( 00047 PUNICODE_STRING BaseName, 00048 PWSTR Extension OPTIONAL, 00049 PHANDLE Primary, 00050 PHANDLE Secondary, 00051 PULONG PrimaryDisposition, 00052 PULONG SecondaryDisposition, 00053 BOOLEAN CreateAllowed, 00054 BOOLEAN MarkAsSystemHive, 00055 OUT OPTIONAL PULONG ClusterSize 00056 ) 00057 /*++ 00058 00059 Routine Description: 00060 00061 Open/Create Primary, Alternate, and Log files for Hives. 00062 00063 BaseName is some name like "\winnt\system32\config\system". 00064 Extension is ".alt" or ".log" or NULL. 00065 00066 If extension is NULL skip secondary work. 00067 00068 If extension is .alt or .log, open/create a secondary file 00069 (e.g. "\winnt\system32\config\system.alt") 00070 00071 If extension is .log, open secondary for buffered I/O, else, 00072 open for non-buffered I/O. Primary always uses non-buffered I/O. 00073 00074 If primary is newly created, supersede secondary. If secondary 00075 does not exist, simply create (other code will complain if Log 00076 is needed but does not exist.) 00077 00078 WARNING: If Secondary handle is NULL, you have no log 00079 or alternate! 00080 00081 Arguments: 00082 00083 BaseName - unicode string of base hive file, must have space for 00084 extension if that is used. 00085 00086 Extension - unicode type extension of secondary file, including 00087 the leading "." 00088 00089 Primary - will get handle to primary file 00090 00091 Secondary - will get handle to secondary, or NULL 00092 00093 PrimaryDisposition - STATUS_SUCCESS or STATUS_CREATED, of primary file. 00094 00095 SecondaryDisposition - STATUS_SUCCESS or STATUS_CREATED, of secondary file. 00096 00097 CreateAllowed - if TRUE will create nonexistent primary, if FALSE will 00098 fail if primary does not exist. no effect on log 00099 00100 MarkAsSystemHive - if TRUE will call into file system to mark this 00101 as a critical system hive. 00102 00103 ClusterSize - if not NULL, will compute and return the appropriate 00104 cluster size for the primary file. 00105 00106 Return Value: 00107 00108 status - if status is success, Primay succeeded, check Secondary 00109 value to see if it succeeded. 00110 00111 --*/ 00112 { 00113 IO_STATUS_BLOCK IoStatus; 00114 IO_STATUS_BLOCK FsctlIoStatus; 00115 FILE_FS_SIZE_INFORMATION FsSizeInformation; 00116 ULONG Cluster; 00117 ULONG CreateDisposition; 00118 OBJECT_ATTRIBUTES ObjectAttributes; 00119 NTSTATUS status; 00120 UNICODE_STRING ExtName; 00121 UNICODE_STRING WorkName; 00122 PVOID WorkBuffer; 00123 USHORT NameSize; 00124 ULONG IoFlags; 00125 ULONG AttributeFlags; 00126 USHORT CompressionState; 00127 HANDLE hEvent; 00128 PKEVENT pEvent; 00129 00130 // 00131 // Allocate an event to use for our overlapped I/O 00132 // 00133 status = CmpCreateEvent(NotificationEvent, &hEvent, &pEvent); 00134 if (!NT_SUCCESS(status)) { 00135 return(status); 00136 } 00137 00138 // 00139 // Allocate a buffer big enough to hold the full name 00140 // 00141 WorkName.Length = 0; 00142 WorkName.MaximumLength = 0; 00143 WorkName.Buffer = NULL; 00144 WorkBuffer = NULL; 00145 00146 NameSize = BaseName->Length; 00147 if (ARGUMENT_PRESENT(Extension)) { 00148 NameSize += (wcslen(Extension)+1) * sizeof(WCHAR); 00149 WorkBuffer = ExAllocatePool(PagedPool, NameSize); 00150 WorkName.Buffer = WorkBuffer; 00151 if (WorkBuffer == NULL) { 00152 ObDereferenceObject(pEvent); 00153 ZwClose(hEvent); 00154 return STATUS_NO_MEMORY; 00155 } 00156 WorkName.MaximumLength = NameSize; 00157 RtlAppendStringToString((PSTRING)&WorkName, (PSTRING)BaseName); 00158 } else { 00159 WorkName = *BaseName; 00160 } 00161 00162 00163 // 00164 // Open/Create the primary 00165 // 00166 InitializeObjectAttributes( 00167 &ObjectAttributes, 00168 &WorkName, 00169 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 00170 NULL, 00171 NULL 00172 ); 00173 00174 if (CreateAllowed) { 00175 CreateDisposition = FILE_OPEN_IF; 00176 } else { 00177 CreateDisposition = FILE_OPEN; 00178 } 00179 00180 ASSERT_PASSIVE_LEVEL(); 00181 00182 status = ZwCreateFile( 00183 Primary, 00184 FILE_READ_DATA | FILE_WRITE_DATA, 00185 &ObjectAttributes, 00186 &IoStatus, 00187 NULL, // alloc size = none 00188 FILE_ATTRIBUTE_NORMAL, 00189 0, // share nothing 00190 CreateDisposition, 00191 FILE_NO_INTERMEDIATE_BUFFERING | 00192 FILE_OPEN_FOR_BACKUP_INTENT | 00193 FILE_NO_COMPRESSION, 00194 NULL, // eabuffer 00195 0 // ealength 00196 ); 00197 if (status == STATUS_ACCESS_DENIED) { 00198 00199 // 00200 // This means some foolish person has put a read-only attribute 00201 // on one of the critical system hive files. Remove it so they 00202 // don't hurt themselves. 00203 // 00204 00205 status = CmpOpenFileWithExtremePrejudice(Primary, 00206 &ObjectAttributes, 00207 FILE_NO_INTERMEDIATE_BUFFERING | 00208 FILE_OPEN_FOR_BACKUP_INTENT | 00209 FILE_NO_COMPRESSION, 00210 FILE_ATTRIBUTE_NORMAL); 00211 } 00212 00213 if ((MarkAsSystemHive) && 00214 (NT_SUCCESS(status))) { 00215 00216 ASSERT_PASSIVE_LEVEL(); 00217 status = ZwFsControlFile(*Primary, 00218 hEvent, 00219 NULL, 00220 NULL, 00221 &FsctlIoStatus, 00222 FSCTL_MARK_AS_SYSTEM_HIVE, 00223 NULL, 00224 0, 00225 NULL, 00226 0); 00227 if (status == STATUS_PENDING) { 00228 KeWaitForSingleObject(pEvent, 00229 Executive, 00230 KernelMode, 00231 FALSE, 00232 NULL); 00233 status = FsctlIoStatus.Status; 00234 } 00235 00236 // 00237 // STATUS_INVALID_DEVICE_REQUEST is OK. 00238 // 00239 00240 if (status == STATUS_INVALID_DEVICE_REQUEST) { 00241 status = STATUS_SUCCESS; 00242 00243 } else if (!NT_SUCCESS(status)) { 00244 ZwClose(*Primary); 00245 } 00246 } 00247 00248 if (!NT_SUCCESS(status)) { 00249 CMLOG(CML_BUGCHECK, CMS_INIT_ERROR) { 00250 KdPrint(("CMINIT: CmpOpenHiveFile: ")); 00251 KdPrint(("\tPrimary Open/Create failed for:\n")); 00252 KdPrint(("\t%wZ\n", &WorkName)); 00253 KdPrint(("\tstatus = %08lx\n", status)); 00254 } 00255 if (WorkBuffer != NULL) { 00256 ExFreePool(WorkBuffer); 00257 } 00258 ObDereferenceObject(pEvent); 00259 ZwClose(hEvent); 00260 return status; 00261 } 00262 00263 // 00264 // Make sure the file is uncompressed in order to prevent the filesystem 00265 // from failing our updates due to disk full conditions. 00266 // 00267 // Do not fail to open the file if this fails, we don't want to prevent 00268 // people from booting just because their disk is full. Although they 00269 // will not be able to update their registry, they will at lease be 00270 // able to delete some files. 00271 // 00272 CompressionState = 0; 00273 ASSERT_PASSIVE_LEVEL(); 00274 status = ZwFsControlFile(*Primary, 00275 hEvent, 00276 NULL, 00277 NULL, 00278 &FsctlIoStatus, 00279 FSCTL_SET_COMPRESSION, 00280 &CompressionState, 00281 sizeof(CompressionState), 00282 NULL, 00283 0); 00284 if (status == STATUS_PENDING) { 00285 KeWaitForSingleObject(pEvent, 00286 Executive, 00287 KernelMode, 00288 FALSE, 00289 NULL); 00290 } 00291 00292 *PrimaryDisposition = (ULONG) IoStatus.Information; 00293 00294 if (ARGUMENT_PRESENT(ClusterSize)) { 00295 00296 ASSERT_PASSIVE_LEVEL(); 00297 status = ZwQueryVolumeInformationFile(*Primary, 00298 &IoStatus, 00299 &FsSizeInformation, 00300 sizeof(FILE_FS_SIZE_INFORMATION), 00301 FileFsSizeInformation); 00302 if (!NT_SUCCESS(status)) { 00303 ObDereferenceObject(pEvent); 00304 ZwClose(hEvent); 00305 return(status); 00306 } 00307 if (FsSizeInformation.BytesPerSector > HBLOCK_SIZE) { 00308 CMLOG(CML_BUGCHECK, CMS_INIT_ERROR) { 00309 KdPrint(("CmpOpenHiveFiles: sectorsize %lx > HBLOCK_SIZE\n")); 00310 } 00311 ObDereferenceObject(pEvent); 00312 ZwClose(hEvent); 00313 return(STATUS_CANNOT_LOAD_REGISTRY_FILE); 00314 } 00315 00316 Cluster = FsSizeInformation.BytesPerSector / HSECTOR_SIZE; 00317 *ClusterSize = (Cluster < 1) ? 1 : Cluster; 00318 00319 } 00320 00321 if ( ! ARGUMENT_PRESENT(Extension)) { 00322 if (WorkBuffer != NULL) { 00323 ExFreePool(WorkBuffer); 00324 } 00325 ObDereferenceObject(pEvent); 00326 ZwClose(hEvent); 00327 return STATUS_SUCCESS; 00328 } 00329 00330 // 00331 // Open/Create the secondary 00332 // 00333 CreateDisposition = FILE_OPEN_IF; 00334 if (*PrimaryDisposition == FILE_CREATED) { 00335 CreateDisposition = FILE_SUPERSEDE; 00336 } 00337 00338 RtlInitUnicodeString(&ExtName,Extension); 00339 status = RtlAppendStringToString((PSTRING)&WorkName, (PSTRING)&ExtName); 00340 00341 InitializeObjectAttributes(&ObjectAttributes, 00342 &WorkName, 00343 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 00344 NULL, 00345 NULL); 00346 00347 IoFlags = FILE_NO_COMPRESSION; 00348 if (_wcsnicmp(Extension, L".log", 4) != 0) { 00349 IoFlags |= FILE_NO_INTERMEDIATE_BUFFERING; 00350 AttributeFlags = FILE_ATTRIBUTE_NORMAL; 00351 } else { 00352 AttributeFlags = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_HIDDEN; 00353 } 00354 00355 ASSERT_PASSIVE_LEVEL(); 00356 status = ZwCreateFile( 00357 Secondary, 00358 FILE_READ_DATA | FILE_WRITE_DATA, 00359 &ObjectAttributes, 00360 &IoStatus, 00361 NULL, // alloc size = none 00362 AttributeFlags, 00363 0, // share nothing 00364 CreateDisposition, 00365 IoFlags, 00366 NULL, // eabuffer 00367 0 // ealength 00368 ); 00369 00370 if (status == STATUS_ACCESS_DENIED) { 00371 00372 // 00373 // This means some foolish person has put a read-only attribute 00374 // on one of the critical system hive files. Remove it so they 00375 // don't hurt themselves. 00376 // 00377 00378 status = CmpOpenFileWithExtremePrejudice(Secondary, 00379 &ObjectAttributes, 00380 IoFlags, 00381 AttributeFlags); 00382 } 00383 00384 if ((MarkAsSystemHive) && 00385 (NT_SUCCESS(status))) { 00386 00387 ASSERT_PASSIVE_LEVEL(); 00388 status = ZwFsControlFile(*Secondary, 00389 hEvent, 00390 NULL, 00391 NULL, 00392 &FsctlIoStatus, 00393 FSCTL_MARK_AS_SYSTEM_HIVE, 00394 NULL, 00395 0, 00396 NULL, 00397 0); 00398 if (status == STATUS_PENDING) { 00399 KeWaitForSingleObject(pEvent, 00400 Executive, 00401 KernelMode, 00402 FALSE, 00403 NULL); 00404 status = FsctlIoStatus.Status; 00405 } 00406 // 00407 // STATUS_INVALID_DEVICE_REQUEST is OK. 00408 // 00409 00410 if (status == STATUS_INVALID_DEVICE_REQUEST) { 00411 status = STATUS_SUCCESS; 00412 00413 } else if (!NT_SUCCESS(status)) { 00414 00415 ZwClose(*Secondary); 00416 } 00417 } 00418 00419 if (!NT_SUCCESS(status)) { 00420 CMLOG(CML_BUGCHECK, CMS_INIT_ERROR) { 00421 KdPrint(("CMINIT: CmpOpenHiveFile: ")); 00422 KdPrint(("\tSecondary Open/Create failed for:\n")); 00423 KdPrint(("\t%wZ\n", &WorkName)); 00424 KdPrint(("\tstatus = %08lx\n", status)); 00425 } 00426 *Secondary = NULL; 00427 } 00428 00429 *SecondaryDisposition = (ULONG) IoStatus.Information; 00430 00431 // 00432 // Make sure the file is uncompressed in order to prevent the filesystem 00433 // from failing our updates due to disk full conditions. 00434 // 00435 // Do not fail to open the file if this fails, we don't want to prevent 00436 // people from booting just because their disk is full. Although they 00437 // will not be able to update their registry, they will at lease be 00438 // able to delete some files. 00439 // 00440 CompressionState = 0; 00441 00442 ASSERT_PASSIVE_LEVEL(); 00443 status = ZwFsControlFile(*Secondary, 00444 hEvent, 00445 NULL, 00446 NULL, 00447 &FsctlIoStatus, 00448 FSCTL_SET_COMPRESSION, 00449 &CompressionState, 00450 sizeof(CompressionState), 00451 NULL, 00452 0); 00453 if (status == STATUS_PENDING) { 00454 KeWaitForSingleObject(pEvent, 00455 Executive, 00456 KernelMode, 00457 FALSE, 00458 NULL); 00459 } 00460 00461 if (WorkBuffer != NULL) { 00462 ExFreePool(WorkBuffer); 00463 } 00464 ObDereferenceObject(pEvent); 00465 ZwClose(hEvent); 00466 return STATUS_SUCCESS; 00467 } 00468 00469 00470 NTSTATUS 00471 CmpInitializeHive( 00472 PCMHIVE *CmHive, 00473 ULONG OperationType, 00474 ULONG HiveFlags, 00475 ULONG FileType, 00476 PVOID HiveData OPTIONAL, 00477 HANDLE Primary, 00478 HANDLE Alternate, 00479 HANDLE Log, 00480 HANDLE External, 00481 PUNICODE_STRING FileName OPTIONAL 00482 ) 00483 /*++ 00484 00485 Routine Description: 00486 00487 Initialize a hive. 00488 00489 Arguments: 00490 00491 CmHive - pointer to a variable to receive a pointer to the CmHive structure 00492 00493 OperationType - specifies whether to create a new hive from scratch, 00494 from a memory image, or by reading a file from disk. 00495 [HINIT_CREATE | HINIT_MEMORY | HINIT_FILE ] 00496 00497 HiveFlags - HIVE_VOLATILE - Entire hive is to be volatile, regardless 00498 of the types of cells allocated 00499 HIVE_NO_LAZY_FLUSH - Data in this hive is never written 00500 to disk except by an explicit FlushKey 00501 00502 FileType - HFILE_TYPE_*, HFILE_TYPE_LOG or HFILE_TYPE_ALTERNATE set 00503 up for logging or alternate support respectively. 00504 00505 HiveData - if present, supplies a pointer to an in memory image of 00506 from which to init the hive. Only useful when OperationType 00507 is set to HINIT_MEMORY. 00508 00509 Primary - File handle for primary hive file (e.g. SYSTEM) 00510 00511 Alternate - File handle for alternate hive file (e.g. SYSTEM.ALT) 00512 00513 Log - File handle for log hive file (e.g. SOFTWARE.LOG) 00514 00515 External - File handle for primary hive file (e.g. BACKUP.REG) 00516 00517 FileName - some path like "...\system32\config\system", which will 00518 be written into the base block as an aid to debugging. 00519 may be NULL. 00520 00521 Return Value: 00522 00523 NTSTATUS 00524 00525 --*/ 00526 { 00527 FILE_FS_SIZE_INFORMATION FsSizeInformation; 00528 IO_STATUS_BLOCK IoStatusBlock; 00529 ULONG Cluster; 00530 NTSTATUS Status; 00531 PCMHIVE cmhive2; 00532 ULONG rc; 00533 00534 CMLOG(CML_MAJOR, CMS_INIT) { 00535 KdPrint(("CmpInitializeHive:\t\n")); 00536 } 00537 00538 // 00539 // Reject illegal parms 00540 // 00541 if ( (Alternate && Log) || 00542 (External && (Primary || Alternate || Log)) || 00543 (Alternate && !Primary) || 00544 (Log && !Primary) || 00545 ((HiveFlags & HIVE_VOLATILE) && (Alternate || Primary || External || Log)) || 00546 ((OperationType == HINIT_MEMORY) && (!ARGUMENT_PRESENT(HiveData))) || 00547 (Log && (FileType != HFILE_TYPE_LOG)) || 00548 (Alternate && (FileType != HFILE_TYPE_ALTERNATE)) 00549 ) 00550 { 00551 return (STATUS_INVALID_PARAMETER); 00552 } 00553 00554 // 00555 // compute control 00556 // 00557 if (Primary) { 00558 00559 ASSERT_PASSIVE_LEVEL(); 00560 Status = ZwQueryVolumeInformationFile( 00561 Primary, 00562 &IoStatusBlock, 00563 &FsSizeInformation, 00564 sizeof(FILE_FS_SIZE_INFORMATION), 00565 FileFsSizeInformation 00566 ); 00567 if (!NT_SUCCESS(Status)) { 00568 return (Status); 00569 } 00570 if (FsSizeInformation.BytesPerSector > HBLOCK_SIZE) { 00571 return (STATUS_REGISTRY_IO_FAILED); 00572 } 00573 Cluster = FsSizeInformation.BytesPerSector / HSECTOR_SIZE; 00574 Cluster = (Cluster < 1) ? 1 : Cluster; 00575 } else { 00576 Cluster = 1; 00577 } 00578 00579 cmhive2 = CmpAllocate(sizeof(CMHIVE), FALSE); 00580 if (cmhive2 == NULL) { 00581 return (STATUS_INSUFFICIENT_RESOURCES); 00582 } 00583 00584 // 00585 // Allocate the mutex from NonPagedPool so it will not be swapped to the disk 00586 // 00587 cmhive2->HiveLock = (PFAST_MUTEX)ExAllocatePoolWithTag(NonPagedPool, sizeof(FAST_MUTEX), CM_POOL_TAG ); 00588 if( cmhive2->HiveLock == NULL ) { 00589 CmpFree(cmhive2, sizeof(CMHIVE)); 00590 return (STATUS_INSUFFICIENT_RESOURCES); 00591 } 00592 00593 // 00594 // Initialize the Cm hive control block 00595 // 00596 // 00597 ASSERT((HFILE_TYPE_EXTERNAL+1) == HFILE_TYPE_MAX); 00598 cmhive2->FileHandles[HFILE_TYPE_PRIMARY] = Primary; 00599 cmhive2->FileHandles[HFILE_TYPE_ALTERNATE] = Alternate; 00600 cmhive2->FileHandles[HFILE_TYPE_LOG] = Log; 00601 cmhive2->FileHandles[HFILE_TYPE_EXTERNAL] = External; 00602 00603 cmhive2->NotifyList.Flink = NULL; 00604 cmhive2->NotifyList.Blink = NULL; 00605 00606 ExInitializeFastMutex(cmhive2->HiveLock); 00607 00608 // 00609 // Initialize the Hv hive control block 00610 // 00611 Status = HvInitializeHive( 00612 &(cmhive2->Hive), 00613 OperationType, 00614 HiveFlags, 00615 FileType, 00616 HiveData, 00617 CmpAllocate, 00618 CmpFree, 00619 CmpFileSetSize, 00620 CmpFileWrite, 00621 CmpFileRead, 00622 CmpFileFlush, 00623 Cluster, 00624 FileName 00625 ); 00626 if (!NT_SUCCESS(Status)) { 00627 CMLOG(CML_MAJOR, CMS_INIT_ERROR) { 00628 KdPrint(("CmpInitializeHive: ")); 00629 KdPrint(("HvInitializeHive failed, Status = %08lx\n", Status)); 00630 } 00631 ASSERT( cmhive2->HiveLock ); 00632 ExFreePool(cmhive2->HiveLock); 00633 CmpFree(cmhive2, sizeof(CMHIVE)); 00634 return (Status); 00635 } 00636 if ( (OperationType == HINIT_FILE) || 00637 (OperationType == HINIT_MEMORY) || 00638 (OperationType == HINIT_MEMORY_INPLACE)) 00639 { 00640 rc = CmCheckRegistry(cmhive2, TRUE); 00641 if (rc != 0) { 00642 CMLOG(CML_MAJOR, CMS_INIT_ERROR) { 00643 KdPrint(("CmpInitializeHive: ")); 00644 KdPrint(("CmCheckRegistry failed, rc = %08lx\n",rc)); 00645 } 00646 // 00647 // in theory we should do this for MEMORY and MEMORY_INPLACE 00648 // as well, but they're only used at init time. 00649 // 00650 if (OperationType == HINIT_FILE) { 00651 HvFreeHive((PHHIVE)cmhive2); 00652 } 00653 ASSERT( cmhive2->HiveLock ); 00654 ExFreePool(cmhive2->HiveLock); 00655 CmpFree(cmhive2, sizeof(CMHIVE)); 00656 return(STATUS_REGISTRY_CORRUPT); 00657 } 00658 } 00659 00660 InsertHeadList(&CmpHiveListHead, &(cmhive2->HiveList)); 00661 *CmHive = cmhive2; 00662 return (STATUS_SUCCESS); 00663 } 00664 00665 00666 BOOLEAN 00667 CmpDestroyHive( 00668 IN PHHIVE Hive, 00669 IN HCELL_INDEX Cell 00670 ) 00671 00672 /*++ 00673 00674 Routine Description: 00675 00676 This routine tears down a cmhive. 00677 00678 Arguments: 00679 00680 Hive - Supplies a pointer to the hive to be freed. 00681 00682 Cell - Supplies index of the hive's root cell. 00683 00684 Return Value: 00685 00686 TRUE if successful 00687 FALSE if some failure occurred 00688 00689 --*/ 00690 00691 { 00692 PCELL_DATA CellData; 00693 HCELL_INDEX LinkCell; 00694 NTSTATUS Status; 00695 00696 // 00697 // First find the link cell. 00698 // 00699 CellData = HvGetCell(Hive, Cell); 00700 LinkCell = CellData->u.KeyNode.Parent; 00701 00702 // 00703 // Now delete the link cell. 00704 // 00705 ASSERT(FIELD_OFFSET(CMHIVE, Hive) == 0); 00706 Status = CmpFreeKeyByCell((PHHIVE)CmpMasterHive, LinkCell, TRUE); 00707 00708 if (NT_SUCCESS(Status)) { 00709 // 00710 // Take the hive out of the hive list 00711 // 00712 RemoveEntryList(&( ((PCMHIVE)Hive)->HiveList)); 00713 return(TRUE); 00714 } else { 00715 return(FALSE); 00716 } 00717 } 00718 00719 00720 NTSTATUS 00721 CmpOpenFileWithExtremePrejudice( 00722 OUT PHANDLE Primary, 00723 IN POBJECT_ATTRIBUTES Obja, 00724 IN ULONG IoFlags, 00725 IN ULONG AttributeFlags 00726 ) 00727 00728 /*++ 00729 00730 Routine Description: 00731 00732 This routine opens a hive file that some foolish person has put a 00733 read-only attribute on. It is used to prevent people from hurting 00734 themselves by making the critical system hive files read-only. 00735 00736 Arguments: 00737 00738 Primary - Returns handle to file 00739 00740 Obja - Supplies Object Attributes of file. 00741 00742 IoFlags - Supplies flags to pass to ZwCreateFile 00743 00744 Return Value: 00745 00746 NTSTATUS 00747 00748 --*/ 00749 00750 { 00751 NTSTATUS Status; 00752 HANDLE Handle; 00753 IO_STATUS_BLOCK IoStatusBlock; 00754 FILE_BASIC_INFORMATION FileInfo; 00755 00756 // 00757 // Get the current file attributes 00758 // 00759 ASSERT_PASSIVE_LEVEL(); 00760 Status = ZwQueryAttributesFile(Obja, &FileInfo); 00761 if (!NT_SUCCESS(Status)) { 00762 return(Status); 00763 } 00764 00765 // 00766 // Clear the readonly bit. 00767 // 00768 FileInfo.FileAttributes &= ~FILE_ATTRIBUTE_READONLY; 00769 00770 // 00771 // Open the file 00772 // 00773 Status = ZwOpenFile(&Handle, 00774 FILE_WRITE_ATTRIBUTES, 00775 Obja, 00776 &IoStatusBlock, 00777 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 00778 FILE_OPEN_FOR_BACKUP_INTENT); 00779 if (!NT_SUCCESS(Status)) { 00780 return(Status); 00781 } 00782 00783 // 00784 // Set the new attributes 00785 // 00786 Status = ZwSetInformationFile(Handle, 00787 &IoStatusBlock, 00788 &FileInfo, 00789 sizeof(FileInfo), 00790 FileBasicInformation); 00791 ZwClose(Handle); 00792 if (NT_SUCCESS(Status)) { 00793 // 00794 // Reopen the file with the access that we really need. 00795 // 00796 Status = ZwCreateFile(Primary, 00797 FILE_READ_DATA | FILE_WRITE_DATA, 00798 Obja, 00799 &IoStatusBlock, 00800 NULL, 00801 AttributeFlags, 00802 0, 00803 FILE_OPEN, 00804 IoFlags, 00805 NULL, 00806 0); 00807 } 00808 00809 return(Status); 00810 00811 }

Generated on Sat May 15 19:39:28 2004 for test by doxygen 1.3.7