Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygencmsysini.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: BSD - See COPYING.ARM in the top level directory 00004 * FILE: ntoskrnl/config/cmsysini.c 00005 * PURPOSE: Configuration Manager - System Initialization Code 00006 * PROGRAMMERS: ReactOS Portable Systems Group 00007 * Alex Ionescu (alex.ionescu@reactos.org) 00008 */ 00009 00010 /* INCLUDES *******************************************************************/ 00011 00012 #include "ntoskrnl.h" 00013 #define NDEBUG 00014 #include "debug.h" 00015 00016 POBJECT_TYPE CmpKeyObjectType; 00017 PCMHIVE CmiVolatileHive; 00018 LIST_ENTRY CmpHiveListHead; 00019 ERESOURCE CmpRegistryLock; 00020 KGUARDED_MUTEX CmpSelfHealQueueLock; 00021 LIST_ENTRY CmpSelfHealQueueListHead; 00022 KEVENT CmpLoadWorkerEvent; 00023 LONG CmpLoadWorkerIncrement; 00024 PEPROCESS CmpSystemProcess; 00025 BOOLEAN HvShutdownComplete; 00026 PVOID CmpRegistryLockCallerCaller, CmpRegistryLockCaller; 00027 BOOLEAN CmpFlushOnLockRelease; 00028 BOOLEAN CmpSpecialBootCondition; 00029 BOOLEAN CmpNoWrite; 00030 BOOLEAN CmpWasSetupBoot; 00031 BOOLEAN CmpProfileLoaded; 00032 ULONG CmpTraceLevel = 0; 00033 00034 extern LONG CmpFlushStarveWriters; 00035 extern BOOLEAN CmFirstTime; 00036 00037 /* FUNCTIONS ******************************************************************/ 00038 00039 VOID 00040 NTAPI 00041 CmpDeleteKeyObject(PVOID DeletedObject) 00042 { 00043 PCM_KEY_BODY KeyBody = (PCM_KEY_BODY)DeletedObject; 00044 PCM_KEY_CONTROL_BLOCK Kcb; 00045 REG_KEY_HANDLE_CLOSE_INFORMATION KeyHandleCloseInfo; 00046 REG_POST_OPERATION_INFORMATION PostOperationInfo; 00047 NTSTATUS Status; 00048 PAGED_CODE(); 00049 00050 /* First off, prepare the handle close information callback */ 00051 PostOperationInfo.Object = KeyBody; 00052 KeyHandleCloseInfo.Object = KeyBody; 00053 Status = CmiCallRegisteredCallbacks(RegNtPreKeyHandleClose, 00054 &KeyHandleCloseInfo); 00055 if (!NT_SUCCESS(Status)) 00056 { 00057 /* If we failed, notify the post routine */ 00058 PostOperationInfo.Status = Status; 00059 CmiCallRegisteredCallbacks(RegNtPostKeyHandleClose, &PostOperationInfo); 00060 return; 00061 } 00062 00063 /* Acquire hive lock */ 00064 CmpLockRegistry(); 00065 00066 /* Make sure this is a valid key body */ 00067 if (KeyBody->Type == '20yk') 00068 { 00069 /* Get the KCB */ 00070 Kcb = KeyBody->KeyControlBlock; 00071 if (Kcb) 00072 { 00073 /* Delist the key */ 00074 DelistKeyBodyFromKCB(KeyBody, FALSE); 00075 00076 /* Dereference the KCB */ 00077 CmpDelayDerefKeyControlBlock(Kcb); 00078 } 00079 } 00080 00081 /* Release the registry lock */ 00082 CmpUnlockRegistry(); 00083 00084 /* Do the post callback */ 00085 PostOperationInfo.Status = STATUS_SUCCESS; 00086 CmiCallRegisteredCallbacks(RegNtPostKeyHandleClose, &PostOperationInfo); 00087 } 00088 00089 VOID 00090 NTAPI 00091 CmpCloseKeyObject(IN PEPROCESS Process OPTIONAL, 00092 IN PVOID Object, 00093 IN ACCESS_MASK GrantedAccess, 00094 IN ULONG ProcessHandleCount, 00095 IN ULONG SystemHandleCount) 00096 { 00097 PCM_KEY_BODY KeyBody = (PCM_KEY_BODY)Object; 00098 PAGED_CODE(); 00099 00100 /* Don't do anything if we're not the last handle */ 00101 if (SystemHandleCount > 1) return; 00102 00103 /* Make sure we're a valid key body */ 00104 if (KeyBody->Type == '20yk') 00105 { 00106 /* Don't do anything if we don't have a notify block */ 00107 if (!KeyBody->NotifyBlock) return; 00108 00109 /* This shouldn't happen yet */ 00110 ASSERT(FALSE); 00111 } 00112 } 00113 00114 NTSTATUS 00115 NTAPI 00116 CmpQueryKeyName(IN PVOID ObjectBody, 00117 IN BOOLEAN HasName, 00118 IN OUT POBJECT_NAME_INFORMATION ObjectNameInfo, 00119 IN ULONG Length, 00120 OUT PULONG ReturnLength, 00121 IN KPROCESSOR_MODE PreviousMode) 00122 { 00123 PUNICODE_STRING KeyName; 00124 ULONG BytesToCopy; 00125 NTSTATUS Status = STATUS_SUCCESS; 00126 PCM_KEY_BODY KeyBody = (PCM_KEY_BODY)ObjectBody; 00127 PCM_KEY_CONTROL_BLOCK Kcb = KeyBody->KeyControlBlock; 00128 00129 /* Acquire hive lock */ 00130 CmpLockRegistry(); 00131 00132 /* Lock KCB shared */ 00133 CmpAcquireKcbLockShared(Kcb); 00134 00135 /* Check if it's a deleted block */ 00136 if (Kcb->Delete) 00137 { 00138 /* Release the locks */ 00139 CmpReleaseKcbLock(Kcb); 00140 CmpUnlockRegistry(); 00141 00142 /* Let the caller know it's deleted */ 00143 return STATUS_KEY_DELETED; 00144 } 00145 00146 /* Get the name */ 00147 KeyName = CmpConstructName(Kcb); 00148 00149 /* Release the locks */ 00150 CmpReleaseKcbLock(Kcb); 00151 CmpUnlockRegistry(); 00152 00153 /* Check if we got the name */ 00154 if (!KeyName) return STATUS_INSUFFICIENT_RESOURCES; 00155 00156 /* Set the returned length */ 00157 *ReturnLength = KeyName->Length + sizeof(OBJECT_NAME_INFORMATION) + sizeof(WCHAR); 00158 00159 /* Calculate amount of bytes to copy into the buffer */ 00160 BytesToCopy = KeyName->Length + sizeof(WCHAR); 00161 00162 /* Check if the provided buffer is too small to fit even anything */ 00163 if ((Length <= sizeof(OBJECT_NAME_INFORMATION)) || 00164 ((Length < (*ReturnLength)) && (BytesToCopy < sizeof(WCHAR)))) 00165 { 00166 /* Free the buffer allocated by CmpConstructName */ 00167 ExFreePool(KeyName); 00168 00169 /* Return buffer length failure without writing anything there because nothing fits */ 00170 return STATUS_INFO_LENGTH_MISMATCH; 00171 } 00172 00173 /* Check if the provided buffer can be partially written */ 00174 if (Length < (*ReturnLength)) 00175 { 00176 /* Yes, indicate so in the return status */ 00177 Status = STATUS_INFO_LENGTH_MISMATCH; 00178 00179 /* Calculate amount of bytes which the provided buffer could handle */ 00180 BytesToCopy = Length - sizeof(OBJECT_NAME_INFORMATION); 00181 } 00182 00183 /* Remove the null termination character from the size */ 00184 BytesToCopy -= sizeof(WCHAR); 00185 00186 /* Fill in the result */ 00187 _SEH2_TRY 00188 { 00189 /* Return data to user */ 00190 ObjectNameInfo->Name.Buffer = (PWCHAR)(ObjectNameInfo + 1); 00191 ObjectNameInfo->Name.MaximumLength = KeyName->Length; 00192 ObjectNameInfo->Name.Length = KeyName->Length; 00193 00194 /* Copy string content*/ 00195 RtlCopyMemory(ObjectNameInfo->Name.Buffer, 00196 KeyName->Buffer, 00197 BytesToCopy); 00198 00199 /* Null terminate it */ 00200 ObjectNameInfo->Name.Buffer[BytesToCopy / sizeof(WCHAR)] = 0; 00201 } 00202 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00203 { 00204 /* Get the status */ 00205 Status = _SEH2_GetExceptionCode(); 00206 } 00207 _SEH2_END; 00208 00209 /* Free the buffer allocated by CmpConstructName */ 00210 ExFreePool(KeyName); 00211 00212 /* Return status */ 00213 return Status; 00214 } 00215 00216 NTSTATUS 00217 NTAPI 00218 CmpInitHiveFromFile(IN PCUNICODE_STRING HiveName, 00219 IN ULONG HiveFlags, 00220 OUT PCMHIVE *Hive, 00221 IN OUT PBOOLEAN New, 00222 IN ULONG CheckFlags) 00223 { 00224 ULONG HiveDisposition, LogDisposition; 00225 HANDLE FileHandle = NULL, LogHandle = NULL; 00226 NTSTATUS Status; 00227 ULONG Operation, FileType; 00228 PCMHIVE NewHive; 00229 PAGED_CODE(); 00230 00231 /* Assume failure */ 00232 *Hive = NULL; 00233 00234 /* Open or create the hive files */ 00235 Status = CmpOpenHiveFiles(HiveName, 00236 L".LOG", 00237 &FileHandle, 00238 &LogHandle, 00239 &HiveDisposition, 00240 &LogDisposition, 00241 *New, 00242 FALSE, 00243 TRUE, 00244 NULL); 00245 if (!NT_SUCCESS(Status)) return Status; 00246 00247 /* Check if we have a log handle */ 00248 FileType = (LogHandle) ? HFILE_TYPE_LOG : HFILE_TYPE_PRIMARY; 00249 00250 /* Check if we created or opened the hive */ 00251 if (HiveDisposition == FILE_CREATED) 00252 { 00253 /* Do a create operation */ 00254 Operation = HINIT_CREATE; 00255 *New = TRUE; 00256 } 00257 else 00258 { 00259 /* Open it as a file */ 00260 Operation = HINIT_FILE; 00261 *New = FALSE; 00262 } 00263 00264 /* Check if we're sharing hives */ 00265 if (CmpShareSystemHives) 00266 { 00267 /* Then force using the primary hive */ 00268 FileType = HFILE_TYPE_PRIMARY; 00269 if (LogHandle) 00270 { 00271 /* Get rid of the log handle */ 00272 ZwClose(LogHandle); 00273 LogHandle = NULL; 00274 } 00275 } 00276 00277 /* Check if we're too late */ 00278 if (HvShutdownComplete) 00279 { 00280 /* Fail */ 00281 ZwClose(FileHandle); 00282 if (LogHandle) ZwClose(LogHandle); 00283 return STATUS_TOO_LATE; 00284 } 00285 00286 /* Initialize the hive */ 00287 Status = CmpInitializeHive((PCMHIVE*)&NewHive, 00288 Operation, 00289 HiveFlags, 00290 FileType, 00291 NULL, 00292 FileHandle, 00293 LogHandle, 00294 NULL, 00295 HiveName, 00296 0); 00297 if (!NT_SUCCESS(Status)) 00298 { 00299 /* Fail */ 00300 ZwClose(FileHandle); 00301 if (LogHandle) ZwClose(LogHandle); 00302 return Status; 00303 } 00304 00305 /* Success, return hive */ 00306 *Hive = NewHive; 00307 00308 /* ROS: Init root key cell and prepare the hive */ 00309 if (Operation == HINIT_CREATE) CmCreateRootNode(&NewHive->Hive, L""); 00310 00311 /* Duplicate the hive name */ 00312 NewHive->FileFullPath.Buffer = ExAllocatePoolWithTag(PagedPool, 00313 HiveName->Length, 00314 TAG_CM); 00315 if (NewHive->FileFullPath.Buffer) 00316 { 00317 /* Copy the string */ 00318 RtlCopyMemory(NewHive->FileFullPath.Buffer, 00319 HiveName->Buffer, 00320 HiveName->Length); 00321 NewHive->FileFullPath.Length = HiveName->Length; 00322 NewHive->FileFullPath.MaximumLength = HiveName->MaximumLength; 00323 } 00324 00325 /* Return success */ 00326 return STATUS_SUCCESS; 00327 } 00328 00329 NTSTATUS 00330 NTAPI 00331 INIT_FUNCTION 00332 CmpSetSystemValues(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 00333 { 00334 OBJECT_ATTRIBUTES ObjectAttributes; 00335 UNICODE_STRING KeyName, ValueName = { 0, 0, NULL }; 00336 HANDLE KeyHandle = NULL; 00337 NTSTATUS Status; 00338 ASSERT(LoaderBlock != NULL); 00339 00340 /* Setup attributes for loader options */ 00341 RtlInitUnicodeString(&KeyName, 00342 L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\" 00343 L"Control"); 00344 InitializeObjectAttributes(&ObjectAttributes, 00345 &KeyName, 00346 OBJ_CASE_INSENSITIVE, 00347 NULL, 00348 NULL); 00349 Status = NtOpenKey(&KeyHandle, KEY_WRITE, &ObjectAttributes); 00350 if (!NT_SUCCESS(Status)) goto Quickie; 00351 00352 /* Key opened, now write to the key */ 00353 RtlInitUnicodeString(&KeyName, L"SystemStartOptions"); 00354 Status = NtSetValueKey(KeyHandle, 00355 &KeyName, 00356 0, 00357 REG_SZ, 00358 CmpLoadOptions.Buffer, 00359 CmpLoadOptions.Length); 00360 if (!NT_SUCCESS(Status)) goto Quickie; 00361 00362 /* Setup value name for system boot device */ 00363 RtlInitUnicodeString(&KeyName, L"SystemBootDevice"); 00364 RtlCreateUnicodeStringFromAsciiz(&ValueName, LoaderBlock->NtBootPathName); 00365 Status = NtSetValueKey(KeyHandle, 00366 &KeyName, 00367 0, 00368 REG_SZ, 00369 ValueName.Buffer, 00370 ValueName.Length); 00371 00372 Quickie: 00373 /* Free the buffers */ 00374 RtlFreeUnicodeString(&ValueName); 00375 00376 /* Close the key and return */ 00377 if (KeyHandle) NtClose(KeyHandle); 00378 00379 /* Return the status */ 00380 return (ExpInTextModeSetup ? STATUS_SUCCESS : Status); 00381 } 00382 00383 NTSTATUS 00384 NTAPI 00385 INIT_FUNCTION 00386 CmpCreateControlSet(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 00387 { 00388 UNICODE_STRING ConfigName = RTL_CONSTANT_STRING(L"Control\\IDConfigDB"); 00389 UNICODE_STRING SelectName = 00390 RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\Select"); 00391 UNICODE_STRING KeyName; 00392 OBJECT_ATTRIBUTES ObjectAttributes; 00393 CHAR ValueInfoBuffer[128]; 00394 PKEY_VALUE_FULL_INFORMATION ValueInfo; 00395 CHAR Buffer[128]; 00396 WCHAR UnicodeBuffer[128]; 00397 HANDLE SelectHandle, KeyHandle, ConfigHandle = NULL, ProfileHandle = NULL; 00398 HANDLE ParentHandle = NULL; 00399 ULONG ControlSet, HwProfile; 00400 ANSI_STRING TempString; 00401 NTSTATUS Status; 00402 ULONG ResultLength, Disposition; 00403 PLOADER_PARAMETER_EXTENSION LoaderExtension; 00404 PAGED_CODE(); 00405 00406 /* Open the select key */ 00407 InitializeObjectAttributes(&ObjectAttributes, 00408 &SelectName, 00409 OBJ_CASE_INSENSITIVE, 00410 NULL, 00411 NULL); 00412 Status = NtOpenKey(&SelectHandle, KEY_READ, &ObjectAttributes); 00413 if (!NT_SUCCESS(Status)) 00414 { 00415 /* ReactOS Hack: Hard-code current to 001 for SetupLdr */ 00416 if (!LoaderBlock->RegistryBase) 00417 { 00418 /* Build the ControlSet001 key */ 00419 RtlInitUnicodeString(&KeyName, 00420 L"\\Registry\\Machine\\System\\ControlSet001"); 00421 InitializeObjectAttributes(&ObjectAttributes, 00422 &KeyName, 00423 OBJ_CASE_INSENSITIVE, 00424 NULL, 00425 NULL); 00426 Status = NtCreateKey(&KeyHandle, 00427 KEY_ALL_ACCESS, 00428 &ObjectAttributes, 00429 0, 00430 NULL, 00431 0, 00432 &Disposition); 00433 if (!NT_SUCCESS(Status)) return Status; 00434 00435 /* Don't need the handle */ 00436 ZwClose(KeyHandle); 00437 00438 /* Use hard-coded setting */ 00439 ControlSet = 1; 00440 goto UseSet; 00441 } 00442 00443 /* Fail for real boots */ 00444 return Status; 00445 } 00446 00447 /* Open the current value */ 00448 RtlInitUnicodeString(&KeyName, L"Current"); 00449 Status = NtQueryValueKey(SelectHandle, 00450 &KeyName, 00451 KeyValueFullInformation, 00452 ValueInfoBuffer, 00453 sizeof(ValueInfoBuffer), 00454 &ResultLength); 00455 NtClose(SelectHandle); 00456 if (!NT_SUCCESS(Status)) return Status; 00457 00458 /* Get the actual value pointer, and get the control set ID */ 00459 ValueInfo = (PKEY_VALUE_FULL_INFORMATION)ValueInfoBuffer; 00460 ControlSet = *(PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset); 00461 00462 /* Create the current control set key */ 00463 UseSet: 00464 RtlInitUnicodeString(&KeyName, 00465 L"\\Registry\\Machine\\System\\CurrentControlSet"); 00466 InitializeObjectAttributes(&ObjectAttributes, 00467 &KeyName, 00468 OBJ_CASE_INSENSITIVE, 00469 NULL, 00470 NULL); 00471 Status = NtCreateKey(&KeyHandle, 00472 KEY_CREATE_LINK, 00473 &ObjectAttributes, 00474 0, 00475 NULL, 00476 REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK, 00477 &Disposition); 00478 if (!NT_SUCCESS(Status)) return Status; 00479 00480 /* Sanity check */ 00481 ASSERT(Disposition == REG_CREATED_NEW_KEY); 00482 00483 /* Initialize the symbolic link name */ 00484 sprintf(Buffer, 00485 "\\Registry\\Machine\\System\\ControlSet%03ld", 00486 ControlSet); 00487 RtlInitAnsiString(&TempString, Buffer); 00488 00489 /* Create a Unicode string out of it */ 00490 KeyName.MaximumLength = sizeof(UnicodeBuffer); 00491 KeyName.Buffer = UnicodeBuffer; 00492 Status = RtlAnsiStringToUnicodeString(&KeyName, &TempString, FALSE); 00493 00494 /* Set the value */ 00495 Status = NtSetValueKey(KeyHandle, 00496 &CmSymbolicLinkValueName, 00497 0, 00498 REG_LINK, 00499 KeyName.Buffer, 00500 KeyName.Length); 00501 if (!NT_SUCCESS(Status)) return Status; 00502 00503 /* Get the configuration database key */ 00504 InitializeObjectAttributes(&ObjectAttributes, 00505 &ConfigName, 00506 OBJ_CASE_INSENSITIVE, 00507 KeyHandle, 00508 NULL); 00509 Status = NtOpenKey(&ConfigHandle, KEY_READ, &ObjectAttributes); 00510 NtClose(KeyHandle); 00511 00512 /* Check if we don't have one */ 00513 if (!NT_SUCCESS(Status)) 00514 { 00515 /* Cleanup and exit */ 00516 ConfigHandle = 0; 00517 goto Cleanup; 00518 } 00519 00520 /* Now get the current config */ 00521 RtlInitUnicodeString(&KeyName, L"CurrentConfig"); 00522 Status = NtQueryValueKey(ConfigHandle, 00523 &KeyName, 00524 KeyValueFullInformation, 00525 ValueInfoBuffer, 00526 sizeof(ValueInfoBuffer), 00527 &ResultLength); 00528 00529 /* Set pointer to buffer */ 00530 ValueInfo = (PKEY_VALUE_FULL_INFORMATION)ValueInfoBuffer; 00531 00532 /* Check if we failed or got a non DWORD-value */ 00533 if (!(NT_SUCCESS(Status)) || (ValueInfo->Type != REG_DWORD)) goto Cleanup; 00534 00535 /* Get the hadware profile */ 00536 HwProfile = *(PULONG)((PUCHAR)ValueInfo + ValueInfo->DataOffset); 00537 00538 /* Open the hardware profile key */ 00539 RtlInitUnicodeString(&KeyName, 00540 L"\\Registry\\Machine\\System\\CurrentControlSet" 00541 L"\\Hardware Profiles"); 00542 InitializeObjectAttributes(&ObjectAttributes, 00543 &KeyName, 00544 OBJ_CASE_INSENSITIVE, 00545 NULL, 00546 NULL); 00547 Status = NtOpenKey(&ParentHandle, KEY_READ, &ObjectAttributes); 00548 if (!NT_SUCCESS(Status)) 00549 { 00550 /* Exit and clean up */ 00551 ParentHandle = 0; 00552 goto Cleanup; 00553 } 00554 00555 /* Build the profile name */ 00556 sprintf(Buffer, "%04ld", HwProfile); 00557 RtlInitAnsiString(&TempString, Buffer); 00558 00559 /* Convert it to Unicode */ 00560 KeyName.MaximumLength = sizeof(UnicodeBuffer); 00561 KeyName.Buffer = UnicodeBuffer; 00562 Status = RtlAnsiStringToUnicodeString(&KeyName, 00563 &TempString, 00564 FALSE); 00565 ASSERT(Status == STATUS_SUCCESS); 00566 00567 /* Open the associated key */ 00568 InitializeObjectAttributes(&ObjectAttributes, 00569 &KeyName, 00570 OBJ_CASE_INSENSITIVE, 00571 ParentHandle, 00572 NULL); 00573 Status = NtOpenKey(&ProfileHandle, 00574 KEY_READ | KEY_WRITE, 00575 &ObjectAttributes); 00576 if (!NT_SUCCESS (Status)) 00577 { 00578 /* Cleanup and exit */ 00579 ProfileHandle = 0; 00580 goto Cleanup; 00581 } 00582 00583 /* Check if we have a loader block extension */ 00584 LoaderExtension = LoaderBlock->Extension; 00585 if (LoaderExtension) 00586 { 00587 ASSERTMSG("ReactOS doesn't support NTLDR Profiles yet!\n", FALSE); 00588 } 00589 00590 /* Create the current hardware profile key */ 00591 RtlInitUnicodeString(&KeyName, 00592 L"\\Registry\\Machine\\System\\CurrentControlSet\\" 00593 L"Hardware Profiles\\Current"); 00594 InitializeObjectAttributes(&ObjectAttributes, 00595 &KeyName, 00596 OBJ_CASE_INSENSITIVE, 00597 NULL, 00598 NULL); 00599 Status = NtCreateKey(&KeyHandle, 00600 KEY_CREATE_LINK, 00601 &ObjectAttributes, 00602 0, 00603 NULL, 00604 REG_OPTION_VOLATILE | REG_OPTION_CREATE_LINK, 00605 &Disposition); 00606 if (NT_SUCCESS(Status)) 00607 { 00608 /* Sanity check */ 00609 ASSERT(Disposition == REG_CREATED_NEW_KEY); 00610 00611 /* Create the profile name */ 00612 sprintf(Buffer, 00613 "\\Registry\\Machine\\System\\CurrentControlSet\\" 00614 "Hardware Profiles\\%04ld", 00615 HwProfile); 00616 RtlInitAnsiString(&TempString, Buffer); 00617 00618 /* Convert it to Unicode */ 00619 KeyName.MaximumLength = sizeof(UnicodeBuffer); 00620 KeyName.Buffer = UnicodeBuffer; 00621 Status = RtlAnsiStringToUnicodeString(&KeyName, 00622 &TempString, 00623 FALSE); 00624 ASSERT(STATUS_SUCCESS == Status); 00625 00626 /* Set it */ 00627 Status = NtSetValueKey(KeyHandle, 00628 &CmSymbolicLinkValueName, 00629 0, 00630 REG_LINK, 00631 KeyName.Buffer, 00632 KeyName.Length); 00633 NtClose(KeyHandle); 00634 } 00635 00636 /* Close every opened handle */ 00637 Cleanup: 00638 if (ConfigHandle) NtClose(ConfigHandle); 00639 if (ProfileHandle) NtClose(ProfileHandle); 00640 if (ParentHandle) NtClose(ParentHandle); 00641 00642 /* Return success */ 00643 return STATUS_SUCCESS; 00644 } 00645 00646 NTSTATUS 00647 NTAPI 00648 CmpLinkHiveToMaster(IN PUNICODE_STRING LinkName, 00649 IN HANDLE RootDirectory, 00650 IN PCMHIVE RegistryHive, 00651 IN BOOLEAN Allocate, 00652 IN PSECURITY_DESCRIPTOR SecurityDescriptor) 00653 { 00654 OBJECT_ATTRIBUTES ObjectAttributes; 00655 NTSTATUS Status; 00656 CM_PARSE_CONTEXT ParseContext = {0}; 00657 HANDLE KeyHandle; 00658 PCM_KEY_BODY KeyBody; 00659 PAGED_CODE(); 00660 00661 /* Setup the object attributes */ 00662 InitializeObjectAttributes(&ObjectAttributes, 00663 LinkName, 00664 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 00665 RootDirectory, 00666 SecurityDescriptor); 00667 00668 /* Setup the parse context */ 00669 ParseContext.CreateLink = TRUE; 00670 ParseContext.CreateOperation = TRUE; 00671 ParseContext.ChildHive.KeyHive = &RegistryHive->Hive; 00672 00673 /* Check if we have a root keycell or if we need to create it */ 00674 if (Allocate) 00675 { 00676 /* Create it */ 00677 ParseContext.ChildHive.KeyCell = HCELL_NIL; 00678 } 00679 else 00680 { 00681 /* We have one */ 00682 ParseContext.ChildHive.KeyCell = RegistryHive->Hive.BaseBlock->RootCell; 00683 } 00684 00685 /* Create the link node */ 00686 Status = ObOpenObjectByName(&ObjectAttributes, 00687 CmpKeyObjectType, 00688 KernelMode, 00689 NULL, 00690 KEY_READ | KEY_WRITE, 00691 (PVOID)&ParseContext, 00692 &KeyHandle); 00693 if (!NT_SUCCESS(Status)) return Status; 00694 00695 /* Mark the hive as clean */ 00696 RegistryHive->Hive.DirtyFlag = FALSE; 00697 00698 /* ReactOS Hack: Keep alive */ 00699 Status = ObReferenceObjectByHandle(KeyHandle, 00700 0, 00701 CmpKeyObjectType, 00702 KernelMode, 00703 (PVOID*)&KeyBody, 00704 NULL); 00705 ASSERT(NT_SUCCESS(Status)); 00706 00707 /* Close the extra handle */ 00708 ZwClose(KeyHandle); 00709 return STATUS_SUCCESS; 00710 } 00711 00712 BOOLEAN 00713 NTAPI 00714 INIT_FUNCTION 00715 CmpInitializeSystemHive(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 00716 { 00717 PVOID HiveBase; 00718 ANSI_STRING LoadString; 00719 PVOID Buffer; 00720 ULONG Length; 00721 NTSTATUS Status; 00722 BOOLEAN Allocate; 00723 UNICODE_STRING KeyName; 00724 PCMHIVE SystemHive = NULL; 00725 UNICODE_STRING HiveName = RTL_CONSTANT_STRING(L"SYSTEM"); 00726 PSECURITY_DESCRIPTOR SecurityDescriptor; 00727 PAGED_CODE(); 00728 00729 /* Setup the ansi string */ 00730 RtlInitAnsiString(&LoadString, LoaderBlock->LoadOptions); 00731 00732 /* Allocate the unicode buffer */ 00733 Length = LoadString.Length * sizeof(WCHAR) + sizeof(UNICODE_NULL); 00734 Buffer = ExAllocatePoolWithTag(PagedPool, Length, TAG_CM); 00735 if (!Buffer) 00736 { 00737 /* Fail */ 00738 KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 3, 1, (ULONG_PTR)LoaderBlock, 0); 00739 } 00740 00741 /* Setup the unicode string */ 00742 RtlInitEmptyUnicodeString(&CmpLoadOptions, Buffer, (USHORT)Length); 00743 00744 /* Add the load options and null-terminate */ 00745 RtlAnsiStringToUnicodeString(&CmpLoadOptions, &LoadString, FALSE); 00746 CmpLoadOptions.Buffer[LoadString.Length] = UNICODE_NULL; 00747 CmpLoadOptions.Length += sizeof(WCHAR); 00748 00749 /* Get the System Hive base address */ 00750 HiveBase = LoaderBlock->RegistryBase; 00751 if (HiveBase) 00752 { 00753 /* Import it */ 00754 ((PHBASE_BLOCK)HiveBase)->Length = LoaderBlock->RegistryLength; 00755 Status = CmpInitializeHive((PCMHIVE*)&SystemHive, 00756 HINIT_MEMORY, 00757 HIVE_NOLAZYFLUSH, 00758 HFILE_TYPE_LOG, 00759 HiveBase, 00760 NULL, 00761 NULL, 00762 NULL, 00763 &HiveName, 00764 2); 00765 if (!NT_SUCCESS(Status)) return FALSE; 00766 00767 /* Set the hive filename */ 00768 RtlCreateUnicodeString(&SystemHive->FileFullPath, 00769 L"\\SystemRoot\\System32\\Config\\SYSTEM"); 00770 00771 /* We imported, no need to create a new hive */ 00772 Allocate = FALSE; 00773 00774 /* Manually set the hive as volatile, if in Live CD mode */ 00775 if (CmpShareSystemHives) SystemHive->Hive.HiveFlags = HIVE_VOLATILE; 00776 } 00777 else 00778 { 00779 /* Create it */ 00780 Status = CmpInitializeHive(&SystemHive, 00781 HINIT_CREATE, 00782 HIVE_NOLAZYFLUSH, 00783 HFILE_TYPE_LOG, 00784 NULL, 00785 NULL, 00786 NULL, 00787 NULL, 00788 &HiveName, 00789 0); 00790 if (!NT_SUCCESS(Status)) return FALSE; 00791 00792 /* Set the hive filename */ 00793 RtlCreateUnicodeString(&SystemHive->FileFullPath, 00794 L"\\SystemRoot\\System32\\Config\\SYSTEM"); 00795 00796 /* Tell CmpLinkHiveToMaster to allocate a hive */ 00797 Allocate = TRUE; 00798 } 00799 00800 /* Save the boot type */ 00801 CmpBootType = SystemHive->Hive.BaseBlock->BootType; 00802 00803 /* Are we in self-healing mode? */ 00804 if (!CmSelfHeal) 00805 { 00806 /* Disable self-healing internally and check if boot type wanted it */ 00807 CmpSelfHeal = FALSE; 00808 if (CmpBootType & 4) 00809 { 00810 /* We're disabled, so bugcheck */ 00811 KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 00812 3, 00813 3, 00814 (ULONG_PTR)SystemHive, 00815 0); 00816 } 00817 } 00818 00819 /* Create the default security descriptor */ 00820 SecurityDescriptor = CmpHiveRootSecurityDescriptor(); 00821 00822 /* Attach it to the system key */ 00823 RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\SYSTEM"); 00824 Status = CmpLinkHiveToMaster(&KeyName, 00825 NULL, 00826 (PCMHIVE)SystemHive, 00827 Allocate, 00828 SecurityDescriptor); 00829 00830 /* Free the security descriptor */ 00831 ExFreePoolWithTag(SecurityDescriptor, TAG_CM); 00832 if (!NT_SUCCESS(Status)) return FALSE; 00833 00834 /* Add the hive to the hive list */ 00835 CmpMachineHiveList[3].CmHive = (PCMHIVE)SystemHive; 00836 00837 /* Success! */ 00838 return TRUE; 00839 } 00840 00841 NTSTATUS 00842 NTAPI 00843 INIT_FUNCTION 00844 CmpCreateObjectTypes(VOID) 00845 { 00846 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; 00847 UNICODE_STRING Name; 00848 GENERIC_MAPPING CmpKeyMapping = {KEY_READ, 00849 KEY_WRITE, 00850 KEY_EXECUTE, 00851 KEY_ALL_ACCESS}; 00852 PAGED_CODE(); 00853 00854 /* Initialize the Key object type */ 00855 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); 00856 RtlInitUnicodeString(&Name, L"Key"); 00857 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); 00858 ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(CM_KEY_BODY); 00859 ObjectTypeInitializer.GenericMapping = CmpKeyMapping; 00860 ObjectTypeInitializer.PoolType = PagedPool; 00861 ObjectTypeInitializer.ValidAccessMask = KEY_ALL_ACCESS; 00862 ObjectTypeInitializer.UseDefaultObject = TRUE; 00863 ObjectTypeInitializer.DeleteProcedure = CmpDeleteKeyObject; 00864 ObjectTypeInitializer.ParseProcedure = CmpParseKey; 00865 ObjectTypeInitializer.SecurityProcedure = CmpSecurityMethod; 00866 ObjectTypeInitializer.QueryNameProcedure = CmpQueryKeyName; 00867 ObjectTypeInitializer.CloseProcedure = CmpCloseKeyObject; 00868 ObjectTypeInitializer.SecurityRequired = TRUE; 00869 00870 /* Create it */ 00871 return ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &CmpKeyObjectType); 00872 } 00873 00874 BOOLEAN 00875 NTAPI 00876 INIT_FUNCTION 00877 CmpCreateRootNode(IN PHHIVE Hive, 00878 IN PCWSTR Name, 00879 OUT PHCELL_INDEX Index) 00880 { 00881 UNICODE_STRING KeyName; 00882 PCM_KEY_NODE KeyCell; 00883 LARGE_INTEGER SystemTime; 00884 PAGED_CODE(); 00885 00886 /* Initialize the node name and allocate it */ 00887 RtlInitUnicodeString(&KeyName, Name); 00888 *Index = HvAllocateCell(Hive, 00889 FIELD_OFFSET(CM_KEY_NODE, Name) + 00890 CmpNameSize(Hive, &KeyName), 00891 Stable, 00892 HCELL_NIL); 00893 if (*Index == HCELL_NIL) return FALSE; 00894 00895 /* Set the cell index and get the data */ 00896 Hive->BaseBlock->RootCell = *Index; 00897 KeyCell = (PCM_KEY_NODE)HvGetCell(Hive, *Index); 00898 if (!KeyCell) return FALSE; 00899 00900 /* Setup the cell */ 00901 KeyCell->Signature = (USHORT)CM_KEY_NODE_SIGNATURE; 00902 KeyCell->Flags = KEY_HIVE_ENTRY | KEY_NO_DELETE; 00903 KeQuerySystemTime(&SystemTime); 00904 KeyCell->LastWriteTime = SystemTime; 00905 KeyCell->Parent = HCELL_NIL; 00906 KeyCell->SubKeyCounts[Stable] = 0; 00907 KeyCell->SubKeyCounts[Volatile] = 0; 00908 KeyCell->SubKeyLists[Stable] = HCELL_NIL; 00909 KeyCell->SubKeyLists[Volatile] = HCELL_NIL; 00910 KeyCell->ValueList.Count = 0; 00911 KeyCell->ValueList.List = HCELL_NIL; 00912 KeyCell->Security = HCELL_NIL; 00913 KeyCell->Class = HCELL_NIL; 00914 KeyCell->ClassLength = 0; 00915 KeyCell->MaxNameLen = 0; 00916 KeyCell->MaxClassLen = 0; 00917 KeyCell->MaxValueNameLen = 0; 00918 KeyCell->MaxValueDataLen = 0; 00919 00920 /* Copy the name (this will also set the length) */ 00921 KeyCell->NameLength = CmpCopyName(Hive, (PWCHAR)KeyCell->Name, &KeyName); 00922 00923 /* Check if the name was compressed */ 00924 if (KeyCell->NameLength < KeyName.Length) 00925 { 00926 /* Set the flag */ 00927 KeyCell->Flags |= KEY_COMP_NAME; 00928 } 00929 00930 /* Return success */ 00931 HvReleaseCell(Hive, *Index); 00932 return TRUE; 00933 } 00934 00935 BOOLEAN 00936 NTAPI 00937 INIT_FUNCTION 00938 CmpCreateRegistryRoot(VOID) 00939 { 00940 UNICODE_STRING KeyName; 00941 OBJECT_ATTRIBUTES ObjectAttributes; 00942 PCM_KEY_BODY RootKey; 00943 HCELL_INDEX RootIndex; 00944 NTSTATUS Status; 00945 PCM_KEY_NODE KeyCell; 00946 PSECURITY_DESCRIPTOR SecurityDescriptor; 00947 PCM_KEY_CONTROL_BLOCK Kcb; 00948 PAGED_CODE(); 00949 00950 /* Setup the root node */ 00951 if (!CmpCreateRootNode(&CmiVolatileHive->Hive, L"REGISTRY", &RootIndex)) 00952 { 00953 /* We failed */ 00954 return FALSE; 00955 } 00956 00957 /* Create '\Registry' key. */ 00958 RtlInitUnicodeString(&KeyName, L"\\REGISTRY"); 00959 SecurityDescriptor = CmpHiveRootSecurityDescriptor(); 00960 InitializeObjectAttributes(&ObjectAttributes, 00961 &KeyName, 00962 OBJ_CASE_INSENSITIVE, 00963 NULL, 00964 NULL); 00965 Status = ObCreateObject(KernelMode, 00966 CmpKeyObjectType, 00967 &ObjectAttributes, 00968 KernelMode, 00969 NULL, 00970 sizeof(CM_KEY_BODY), 00971 0, 00972 0, 00973 (PVOID*)&RootKey); 00974 ExFreePoolWithTag(SecurityDescriptor, TAG_CM); 00975 if (!NT_SUCCESS(Status)) return FALSE; 00976 00977 /* Sanity check, and get the key cell */ 00978 ASSERT((&CmiVolatileHive->Hive)->ReleaseCellRoutine == NULL); 00979 KeyCell = (PCM_KEY_NODE)HvGetCell(&CmiVolatileHive->Hive, RootIndex); 00980 if (!KeyCell) return FALSE; 00981 00982 /* Create the KCB */ 00983 RtlInitUnicodeString(&KeyName, L"\\REGISTRY"); 00984 Kcb = CmpCreateKeyControlBlock(&CmiVolatileHive->Hive, 00985 RootIndex, 00986 KeyCell, 00987 NULL, 00988 0, 00989 &KeyName); 00990 if (!Kcb) return FALSE; 00991 00992 /* Initialize the object */ 00993 RootKey->KeyControlBlock = Kcb; 00994 RootKey->Type = '20yk'; 00995 RootKey->NotifyBlock = NULL; 00996 RootKey->ProcessID = PsGetCurrentProcessId(); 00997 00998 /* Link with KCB */ 00999 EnlistKeyBodyWithKCB(RootKey, 0); 01000 01001 /* Insert the key into the namespace */ 01002 Status = ObInsertObject(RootKey, 01003 NULL, 01004 KEY_ALL_ACCESS, 01005 0, 01006 NULL, 01007 &CmpRegistryRootHandle); 01008 if (!NT_SUCCESS(Status)) return FALSE; 01009 01010 /* Reference the key again so that we never lose it */ 01011 Status = ObReferenceObjectByHandle(CmpRegistryRootHandle, 01012 KEY_READ, 01013 NULL, 01014 KernelMode, 01015 (PVOID*)&RootKey, 01016 NULL); 01017 if (!NT_SUCCESS(Status)) return FALSE; 01018 01019 /* Completely sucessful */ 01020 return TRUE; 01021 } 01022 01023 NTSTATUS 01024 NTAPI 01025 CmpGetRegistryPath(IN PWCHAR ConfigPath) 01026 { 01027 OBJECT_ATTRIBUTES ObjectAttributes; 01028 NTSTATUS Status; 01029 HANDLE KeyHandle; 01030 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo; 01031 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\HARDWARE"); 01032 UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"InstallPath"); 01033 ULONG BufferSize, ResultSize; 01034 01035 /* Check if we are booted in setup */ 01036 if (ExpInTextModeSetup) 01037 { 01038 /* Setup the object attributes */ 01039 InitializeObjectAttributes(&ObjectAttributes, 01040 &KeyName, 01041 OBJ_CASE_INSENSITIVE, 01042 NULL, 01043 NULL); 01044 /* Open the key */ 01045 Status = ZwOpenKey(&KeyHandle, 01046 KEY_ALL_ACCESS, 01047 &ObjectAttributes); 01048 if (!NT_SUCCESS(Status)) return Status; 01049 01050 /* Allocate the buffer */ 01051 BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4096; 01052 ValueInfo = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_CM); 01053 if (!ValueInfo) 01054 { 01055 /* Fail */ 01056 ZwClose(KeyHandle); 01057 return STATUS_INSUFFICIENT_RESOURCES; 01058 } 01059 01060 /* Query the value */ 01061 Status = ZwQueryValueKey(KeyHandle, 01062 &ValueName, 01063 KeyValuePartialInformation, 01064 ValueInfo, 01065 BufferSize, 01066 &ResultSize); 01067 ZwClose(KeyHandle); 01068 if (!NT_SUCCESS(Status)) 01069 { 01070 /* Fail */ 01071 ExFreePoolWithTag(ValueInfo, TAG_CM); 01072 return Status; 01073 } 01074 01075 /* Copy the config path and null-terminate it */ 01076 RtlCopyMemory(ConfigPath, 01077 ValueInfo->Data, 01078 ValueInfo->DataLength); 01079 ConfigPath[ValueInfo->DataLength / sizeof(WCHAR)] = UNICODE_NULL; 01080 ExFreePoolWithTag(ValueInfo, TAG_CM); 01081 } 01082 else 01083 { 01084 /* Just use default path */ 01085 wcscpy(ConfigPath, L"\\SystemRoot"); 01086 } 01087 01088 /* Add registry path */ 01089 wcscat(ConfigPath, L"\\System32\\Config\\"); 01090 01091 /* Done */ 01092 return STATUS_SUCCESS; 01093 } 01094 01095 VOID 01096 NTAPI 01097 CmpLoadHiveThread(IN PVOID StartContext) 01098 { 01099 WCHAR FileBuffer[MAX_PATH], RegBuffer[MAX_PATH], ConfigPath[MAX_PATH]; 01100 UNICODE_STRING TempName, FileName, RegName; 01101 ULONG i, ErrorResponse, WorkerCount, Length; 01102 USHORT FileStart; 01103 //ULONG RegStart; 01104 ULONG PrimaryDisposition, SecondaryDisposition, ClusterSize; 01105 PCMHIVE CmHive; 01106 HANDLE PrimaryHandle, LogHandle; 01107 NTSTATUS Status = STATUS_SUCCESS; 01108 PVOID ErrorParameters; 01109 PAGED_CODE(); 01110 01111 /* Get the hive index, make sure it makes sense */ 01112 i = PtrToUlong(StartContext); 01113 ASSERT(CmpMachineHiveList[i].Name != NULL); 01114 01115 /* We were started */ 01116 CmpMachineHiveList[i].ThreadStarted = TRUE; 01117 01118 /* Build the file name and registry name strings */ 01119 RtlInitEmptyUnicodeString(&FileName, FileBuffer, MAX_PATH); 01120 RtlInitEmptyUnicodeString(&RegName, RegBuffer, MAX_PATH); 01121 01122 /* Now build the system root path */ 01123 CmpGetRegistryPath(ConfigPath); 01124 RtlInitUnicodeString(&TempName, ConfigPath); 01125 RtlAppendStringToString((PSTRING)&FileName, (PSTRING)&TempName); 01126 FileStart = FileName.Length; 01127 01128 /* And build the registry root path */ 01129 RtlInitUnicodeString(&TempName, L"\\REGISTRY\\"); 01130 RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName); 01131 //RegStart = RegName.Length; 01132 01133 /* Build the base name */ 01134 RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].BaseName); 01135 RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName); 01136 01137 /* Check if this is a child of the root */ 01138 if (RegName.Buffer[RegName.Length / sizeof(WCHAR) - 1] == '\\') 01139 { 01140 /* Then setup the whole name */ 01141 RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].Name); 01142 RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName); 01143 } 01144 01145 /* Now add the rest of the file name */ 01146 RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].Name); 01147 FileName.Length = FileStart; 01148 RtlAppendStringToString((PSTRING)&FileName, (PSTRING)&TempName); 01149 if (!CmpMachineHiveList[i].CmHive) 01150 { 01151 /* We need to allocate a new hive structure */ 01152 CmpMachineHiveList[i].Allocate = TRUE; 01153 01154 /* Load the hive file */ 01155 Status = CmpInitHiveFromFile(&FileName, 01156 CmpMachineHiveList[i].HHiveFlags, 01157 &CmHive, 01158 &CmpMachineHiveList[i].Allocate, 01159 0); 01160 if (!(NT_SUCCESS(Status)) || 01161 (!(CmHive->FileHandles[HFILE_TYPE_LOG]) && !(CmpMiniNTBoot))) // HACK 01162 { 01163 /* We failed or couldn't get a log file, raise a hard error */ 01164 ErrorParameters = &FileName; 01165 NtRaiseHardError(STATUS_CANNOT_LOAD_REGISTRY_FILE, 01166 1, 01167 1, 01168 (PULONG_PTR)&ErrorParameters, 01169 OptionOk, 01170 &ErrorResponse); 01171 } 01172 01173 /* Set the hive flags and newly allocated hive pointer */ 01174 CmHive->Flags = CmpMachineHiveList[i].CmHiveFlags; 01175 CmpMachineHiveList[i].CmHive2 = CmHive; 01176 } 01177 else 01178 { 01179 /* We already have a hive, is it volatile? */ 01180 CmHive = CmpMachineHiveList[i].CmHive; 01181 if (!(CmHive->Hive.HiveFlags & HIVE_VOLATILE)) 01182 { 01183 /* It's now, open the hive file and log */ 01184 Status = CmpOpenHiveFiles(&FileName, 01185 L".LOG", 01186 &PrimaryHandle, 01187 &LogHandle, 01188 &PrimaryDisposition, 01189 &SecondaryDisposition, 01190 TRUE, 01191 TRUE, 01192 FALSE, 01193 &ClusterSize); 01194 if (!(NT_SUCCESS(Status)) || !(LogHandle)) 01195 { 01196 /* Couldn't open the hive or its log file, raise a hard error */ 01197 ErrorParameters = &FileName; 01198 NtRaiseHardError(STATUS_CANNOT_LOAD_REGISTRY_FILE, 01199 1, 01200 1, 01201 (PULONG_PTR)&ErrorParameters, 01202 OptionOk, 01203 &ErrorResponse); 01204 01205 /* And bugcheck for posterity's sake */ 01206 KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 9, 0, i, Status); 01207 } 01208 01209 /* Save the file handles. This should remove our sync hacks */ 01210 CmHive->FileHandles[HFILE_TYPE_LOG] = LogHandle; 01211 CmHive->FileHandles[HFILE_TYPE_PRIMARY] = PrimaryHandle; 01212 01213 /* Allow lazy flushing since the handles are there -- remove sync hacks */ 01214 //ASSERT(CmHive->Hive.HiveFlags & HIVE_NOLAZYFLUSH); 01215 CmHive->Hive.HiveFlags &= ~HIVE_NOLAZYFLUSH; 01216 01217 /* Get the real size of the hive */ 01218 Length = CmHive->Hive.Storage[Stable].Length + HBLOCK_SIZE; 01219 01220 /* Check if the cluster size doesn't match */ 01221 if (CmHive->Hive.Cluster != ClusterSize) ASSERT(FALSE); 01222 01223 /* Set the file size */ 01224 DPRINT("FIXME: Should set file size: %lx\n", Length); 01225 //if (!CmpFileSetSize((PHHIVE)CmHive, HFILE_TYPE_PRIMARY, Length, Length)) 01226 { 01227 /* This shouldn't fail */ 01228 //ASSERT(FALSE); 01229 } 01230 01231 /* Another thing we don't support is NTLDR-recovery */ 01232 if (CmHive->Hive.BaseBlock->BootRecover) ASSERT(FALSE); 01233 01234 /* Finally, set our allocated hive to the same hive we've had */ 01235 CmpMachineHiveList[i].CmHive2 = CmHive; 01236 ASSERT(CmpMachineHiveList[i].CmHive == CmpMachineHiveList[i].CmHive2); 01237 } 01238 } 01239 01240 /* We're done */ 01241 CmpMachineHiveList[i].ThreadFinished = TRUE; 01242 01243 /* Check if we're the last worker */ 01244 WorkerCount = InterlockedIncrement(&CmpLoadWorkerIncrement); 01245 if (WorkerCount == CM_NUMBER_OF_MACHINE_HIVES) 01246 { 01247 /* Signal the event */ 01248 KeSetEvent(&CmpLoadWorkerEvent, 0, FALSE); 01249 } 01250 01251 /* Kill the thread */ 01252 PsTerminateSystemThread(Status); 01253 } 01254 01255 VOID 01256 NTAPI 01257 CmpInitializeHiveList(IN USHORT Flag) 01258 { 01259 WCHAR FileBuffer[MAX_PATH], RegBuffer[MAX_PATH], ConfigPath[MAX_PATH]; 01260 UNICODE_STRING TempName, FileName, RegName; 01261 HANDLE Thread; 01262 NTSTATUS Status; 01263 ULONG i; 01264 USHORT RegStart; 01265 PSECURITY_DESCRIPTOR SecurityDescriptor; 01266 PAGED_CODE(); 01267 01268 /* Allow writing for now */ 01269 CmpNoWrite = FALSE; 01270 01271 /* Build the file name and registry name strings */ 01272 RtlInitEmptyUnicodeString(&FileName, FileBuffer, MAX_PATH); 01273 RtlInitEmptyUnicodeString(&RegName, RegBuffer, MAX_PATH); 01274 01275 /* Now build the system root path */ 01276 CmpGetRegistryPath(ConfigPath); 01277 RtlInitUnicodeString(&TempName, ConfigPath); 01278 RtlAppendStringToString((PSTRING)&FileName, (PSTRING)&TempName); 01279 01280 /* And build the registry root path */ 01281 RtlInitUnicodeString(&TempName, L"\\REGISTRY\\"); 01282 RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName); 01283 RegStart = RegName.Length; 01284 01285 /* Setup the event to synchronize workers */ 01286 KeInitializeEvent(&CmpLoadWorkerEvent, SynchronizationEvent, FALSE); 01287 01288 /* Enter special boot condition */ 01289 CmpSpecialBootCondition = TRUE; 01290 01291 /* Create the SD for the root hives */ 01292 SecurityDescriptor = CmpHiveRootSecurityDescriptor(); 01293 01294 /* Loop every hive we care about */ 01295 for (i = 0; i < CM_NUMBER_OF_MACHINE_HIVES; i++) 01296 { 01297 /* Make sure the list is setup */ 01298 ASSERT(CmpMachineHiveList[i].Name != NULL); 01299 01300 /* Create a thread to handle this hive */ 01301 Status = PsCreateSystemThread(&Thread, 01302 THREAD_ALL_ACCESS, 01303 NULL, 01304 0, 01305 NULL, 01306 CmpLoadHiveThread, 01307 UlongToPtr(i)); 01308 if (NT_SUCCESS(Status)) 01309 { 01310 /* We don't care about the handle -- the thread self-terminates */ 01311 ZwClose(Thread); 01312 } 01313 else 01314 { 01315 /* Can't imagine this happening */ 01316 KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO, 9, 3, i, Status); 01317 } 01318 } 01319 01320 /* Make sure we've reached the end of the list */ 01321 ASSERT(CmpMachineHiveList[i].Name == NULL); 01322 01323 /* Wait for hive loading to finish */ 01324 KeWaitForSingleObject(&CmpLoadWorkerEvent, 01325 Executive, 01326 KernelMode, 01327 FALSE, 01328 NULL); 01329 01330 /* Exit the special boot condition and make sure all workers completed */ 01331 CmpSpecialBootCondition = FALSE; 01332 ASSERT(CmpLoadWorkerIncrement == CM_NUMBER_OF_MACHINE_HIVES); 01333 01334 /* Loop hives again */ 01335 for (i = 0; i < CM_NUMBER_OF_MACHINE_HIVES; i++) 01336 { 01337 /* Make sure the thread ran and finished */ 01338 ASSERT(CmpMachineHiveList[i].ThreadFinished == TRUE); 01339 ASSERT(CmpMachineHiveList[i].ThreadStarted == TRUE); 01340 01341 /* Check if this was a new hive */ 01342 if (!CmpMachineHiveList[i].CmHive) 01343 { 01344 /* Make sure we allocated something */ 01345 ASSERT(CmpMachineHiveList[i].CmHive2 != NULL); 01346 01347 /* Build the base name */ 01348 RegName.Length = RegStart; 01349 RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].BaseName); 01350 RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName); 01351 01352 /* Check if this is a child of the root */ 01353 if (RegName.Buffer[RegName.Length / sizeof(WCHAR) - 1] == '\\') 01354 { 01355 /* Then setup the whole name */ 01356 RtlInitUnicodeString(&TempName, CmpMachineHiveList[i].Name); 01357 RtlAppendStringToString((PSTRING)&RegName, (PSTRING)&TempName); 01358 } 01359 01360 /* Now link the hive to its master */ 01361 Status = CmpLinkHiveToMaster(&RegName, 01362 NULL, 01363 CmpMachineHiveList[i].CmHive2, 01364 CmpMachineHiveList[i].Allocate, 01365 SecurityDescriptor); 01366 if (Status != STATUS_SUCCESS) 01367 { 01368 /* Linking needs to work */ 01369 KeBugCheckEx(CONFIG_LIST_FAILED, 11, Status, i, (ULONG_PTR)&RegName); 01370 } 01371 01372 /* Check if we had to allocate a new hive */ 01373 if (CmpMachineHiveList[i].Allocate) 01374 { 01375 /* Sync the new hive */ 01376 //HvSyncHive((PHHIVE)(CmpMachineHiveList[i].CmHive2)); 01377 } 01378 } 01379 01380 /* Check if we created a new hive */ 01381 if (CmpMachineHiveList[i].CmHive2) 01382 { 01383 /* TODO: Add to HiveList key */ 01384 } 01385 } 01386 01387 /* Get rid of the SD */ 01388 ExFreePoolWithTag(SecurityDescriptor, TAG_CM); 01389 01390 /* FIXME: Link SECURITY to SAM */ 01391 01392 /* FIXME: Link S-1-5-18 to .Default */ 01393 } 01394 01395 BOOLEAN 01396 NTAPI 01397 INIT_FUNCTION 01398 CmInitSystem1(VOID) 01399 { 01400 OBJECT_ATTRIBUTES ObjectAttributes; 01401 UNICODE_STRING KeyName; 01402 HANDLE KeyHandle; 01403 NTSTATUS Status; 01404 PCMHIVE HardwareHive; 01405 PSECURITY_DESCRIPTOR SecurityDescriptor; 01406 PAGED_CODE(); 01407 01408 /* Check if this is PE-boot */ 01409 if (InitIsWinPEMode) 01410 { 01411 /* Set registry to PE mode */ 01412 CmpMiniNTBoot = TRUE; 01413 CmpShareSystemHives = TRUE; 01414 } 01415 01416 /* Initialize the hive list and lock */ 01417 InitializeListHead(&CmpHiveListHead); 01418 ExInitializePushLock(&CmpHiveListHeadLock); 01419 ExInitializePushLock(&CmpLoadHiveLock); 01420 01421 /* Initialize registry lock */ 01422 ExInitializeResourceLite(&CmpRegistryLock); 01423 01424 /* Initialize the cache */ 01425 CmpInitializeCache(); 01426 01427 /* Initialize allocation and delayed dereferencing */ 01428 CmpInitCmPrivateAlloc(); 01429 CmpInitCmPrivateDelayAlloc(); 01430 CmpInitDelayDerefKCBEngine(); 01431 01432 /* Initialize callbacks */ 01433 CmpInitCallback(); 01434 01435 /* Initialize self healing */ 01436 KeInitializeGuardedMutex(&CmpSelfHealQueueLock); 01437 InitializeListHead(&CmpSelfHealQueueListHead); 01438 01439 /* Save the current process and lock the registry */ 01440 CmpSystemProcess = PsGetCurrentProcess(); 01441 01442 /* Create the key object types */ 01443 Status = CmpCreateObjectTypes(); 01444 if (!NT_SUCCESS(Status)) 01445 { 01446 /* Bugcheck */ 01447 KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 1, Status, 0); 01448 } 01449 01450 /* Build the master hive */ 01451 Status = CmpInitializeHive((PCMHIVE*)&CmiVolatileHive, 01452 HINIT_CREATE, 01453 HIVE_VOLATILE, 01454 HFILE_TYPE_PRIMARY, 01455 NULL, 01456 NULL, 01457 NULL, 01458 NULL, 01459 NULL, 01460 0); 01461 if (!NT_SUCCESS(Status)) 01462 { 01463 /* Bugcheck */ 01464 KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 2, Status, 0); 01465 } 01466 01467 /* Create the \REGISTRY key node */ 01468 if (!CmpCreateRegistryRoot()) 01469 { 01470 /* Bugcheck */ 01471 KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 3, 0, 0); 01472 } 01473 01474 /* Create the default security descriptor */ 01475 SecurityDescriptor = CmpHiveRootSecurityDescriptor(); 01476 01477 /* Create '\Registry\Machine' key. */ 01478 RtlInitUnicodeString(&KeyName, L"\\REGISTRY\\MACHINE"); 01479 InitializeObjectAttributes(&ObjectAttributes, 01480 &KeyName, 01481 OBJ_CASE_INSENSITIVE, 01482 NULL, 01483 SecurityDescriptor); 01484 Status = NtCreateKey(&KeyHandle, 01485 KEY_READ | KEY_WRITE, 01486 &ObjectAttributes, 01487 0, 01488 NULL, 01489 0, 01490 NULL); 01491 if (!NT_SUCCESS(Status)) 01492 { 01493 /* Bugcheck */ 01494 KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 5, Status, 0); 01495 } 01496 01497 /* Close the handle */ 01498 NtClose(KeyHandle); 01499 01500 /* Create '\Registry\User' key. */ 01501 RtlInitUnicodeString(&KeyName, L"\\REGISTRY\\USER"); 01502 InitializeObjectAttributes(&ObjectAttributes, 01503 &KeyName, 01504 OBJ_CASE_INSENSITIVE, 01505 NULL, 01506 SecurityDescriptor); 01507 Status = NtCreateKey(&KeyHandle, 01508 KEY_READ | KEY_WRITE, 01509 &ObjectAttributes, 01510 0, 01511 NULL, 01512 0, 01513 NULL); 01514 if (!NT_SUCCESS(Status)) 01515 { 01516 /* Bugcheck */ 01517 KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 6, Status, 0); 01518 } 01519 01520 /* Close the handle */ 01521 NtClose(KeyHandle); 01522 01523 /* Initialize the system hive */ 01524 if (!CmpInitializeSystemHive(KeLoaderBlock)) 01525 { 01526 /* Bugcheck */ 01527 KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 7, 0, 0); 01528 } 01529 01530 /* Create the 'CurrentControlSet' link. */ 01531 Status = CmpCreateControlSet(KeLoaderBlock); 01532 if (!NT_SUCCESS(Status)) 01533 { 01534 /* Bugcheck */ 01535 KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 8, Status, 0); 01536 } 01537 01538 /* Create the hardware hive */ 01539 Status = CmpInitializeHive((PCMHIVE*)&HardwareHive, 01540 HINIT_CREATE, 01541 HIVE_VOLATILE, 01542 HFILE_TYPE_PRIMARY, 01543 NULL, 01544 NULL, 01545 NULL, 01546 NULL, 01547 NULL, 01548 0); 01549 if (!NT_SUCCESS(Status)) 01550 { 01551 /* Bugcheck */ 01552 KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 11, Status, 0); 01553 } 01554 01555 /* Add the hive to the hive list */ 01556 CmpMachineHiveList[0].CmHive = (PCMHIVE)HardwareHive; 01557 01558 /* Attach it to the machine key */ 01559 RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\HARDWARE"); 01560 Status = CmpLinkHiveToMaster(&KeyName, 01561 NULL, 01562 (PCMHIVE)HardwareHive, 01563 TRUE, 01564 SecurityDescriptor); 01565 if (!NT_SUCCESS(Status)) 01566 { 01567 /* Bugcheck */ 01568 KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 12, Status, 0); 01569 } 01570 01571 /* FIXME: Add to HiveList key */ 01572 01573 /* Free the security descriptor */ 01574 ExFreePoolWithTag(SecurityDescriptor, TAG_CM); 01575 01576 /* Fill out the Hardware key with the ARC Data from the Loader */ 01577 Status = CmpInitializeHardwareConfiguration(KeLoaderBlock); 01578 if (!NT_SUCCESS(Status)) 01579 { 01580 /* Bugcheck */ 01581 KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 13, Status, 0); 01582 } 01583 01584 /* Initialize machine-dependent information into the registry */ 01585 Status = CmpInitializeMachineDependentConfiguration(KeLoaderBlock); 01586 if (!NT_SUCCESS(Status)) 01587 { 01588 /* Bugcheck */ 01589 KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 14, Status, 0); 01590 } 01591 01592 /* Initialize volatile registry settings */ 01593 Status = CmpSetSystemValues(KeLoaderBlock); 01594 if (!NT_SUCCESS(Status)) 01595 { 01596 /* Bugcheck */ 01597 KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 1, 15, Status, 0); 01598 } 01599 01600 /* Free the load options */ 01601 ExFreePoolWithTag(CmpLoadOptions.Buffer, TAG_CM); 01602 01603 /* If we got here, all went well */ 01604 return TRUE; 01605 } 01606 01607 VOID 01608 NTAPI 01609 INIT_FUNCTION 01610 CmpFreeDriverList(IN PHHIVE Hive, 01611 IN PLIST_ENTRY DriverList) 01612 { 01613 PLIST_ENTRY NextEntry, OldEntry; 01614 PBOOT_DRIVER_NODE DriverNode; 01615 PAGED_CODE(); 01616 01617 /* Parse the current list */ 01618 NextEntry = DriverList->Flink; 01619 while (NextEntry != DriverList) 01620 { 01621 /* Get the driver node */ 01622 DriverNode = CONTAINING_RECORD(NextEntry, BOOT_DRIVER_NODE, ListEntry.Link); 01623 01624 /* Get the next entry now, since we're going to free it later */ 01625 OldEntry = NextEntry; 01626 NextEntry = NextEntry->Flink; 01627 01628 /* Was there a name? */ 01629 if (DriverNode->Name.Buffer) 01630 { 01631 /* Free it */ 01632 CmpFree(DriverNode->Name.Buffer, DriverNode->Name.Length); 01633 } 01634 01635 /* Was there a registry path? */ 01636 if (DriverNode->ListEntry.RegistryPath.Buffer) 01637 { 01638 /* Free it */ 01639 CmpFree(DriverNode->ListEntry.RegistryPath.Buffer, 01640 DriverNode->ListEntry.RegistryPath.MaximumLength); 01641 } 01642 01643 /* Was there a file path? */ 01644 if (DriverNode->ListEntry.FilePath.Buffer) 01645 { 01646 /* Free it */ 01647 CmpFree(DriverNode->ListEntry.FilePath.Buffer, 01648 DriverNode->ListEntry.FilePath.MaximumLength); 01649 } 01650 01651 /* Now free the node, and move on */ 01652 CmpFree(OldEntry, sizeof(BOOT_DRIVER_NODE)); 01653 } 01654 } 01655 01656 PUNICODE_STRING* 01657 NTAPI 01658 INIT_FUNCTION 01659 CmGetSystemDriverList(VOID) 01660 { 01661 LIST_ENTRY DriverList; 01662 OBJECT_ATTRIBUTES ObjectAttributes; 01663 NTSTATUS Status; 01664 PCM_KEY_BODY KeyBody; 01665 PHHIVE Hive; 01666 HCELL_INDEX RootCell, ControlCell; 01667 HANDLE KeyHandle; 01668 UNICODE_STRING KeyName; 01669 PLIST_ENTRY NextEntry; 01670 ULONG i; 01671 PUNICODE_STRING* ServicePath = NULL; 01672 BOOLEAN Success, AutoSelect; 01673 PBOOT_DRIVER_LIST_ENTRY DriverEntry; 01674 PAGED_CODE(); 01675 01676 /* Initialize the driver list */ 01677 InitializeListHead(&DriverList); 01678 01679 /* Open the system hive key */ 01680 RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\System"); 01681 InitializeObjectAttributes(&ObjectAttributes, 01682 &KeyName, 01683 OBJ_CASE_INSENSITIVE, 01684 NULL, 01685 NULL); 01686 Status = NtOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes); 01687 if (!NT_SUCCESS(Status)) return NULL; 01688 01689 /* Reference the key object to get the root hive/cell to access directly */ 01690 Status = ObReferenceObjectByHandle(KeyHandle, 01691 KEY_QUERY_VALUE, 01692 CmpKeyObjectType, 01693 KernelMode, 01694 (PVOID*)&KeyBody, 01695 NULL); 01696 if (!NT_SUCCESS(Status)) 01697 { 01698 /* Fail */ 01699 NtClose(KeyHandle); 01700 return NULL; 01701 } 01702 01703 /* Do all this under the registry lock */ 01704 CmpLockRegistryExclusive(); 01705 01706 /* Get the hive and key cell */ 01707 Hive = KeyBody->KeyControlBlock->KeyHive; 01708 RootCell = KeyBody->KeyControlBlock->KeyCell; 01709 01710 /* Open the current control set key */ 01711 RtlInitUnicodeString(&KeyName, L"Current"); 01712 ControlCell = CmpFindControlSet(Hive, RootCell, &KeyName, &AutoSelect); 01713 if (ControlCell == HCELL_NIL) goto EndPath; 01714 01715 /* Find all system drivers */ 01716 Success = CmpFindDrivers(Hive, ControlCell, SystemLoad, NULL, &DriverList); 01717 if (!Success) goto EndPath; 01718 01719 /* Sort by group/tag */ 01720 if (!CmpSortDriverList(Hive, ControlCell, &DriverList)) goto EndPath; 01721 01722 /* Remove circular dependencies (cycles) and sort */ 01723 if (!CmpResolveDriverDependencies(&DriverList)) goto EndPath; 01724 01725 /* Loop the list to count drivers */ 01726 for (i = 0, NextEntry = DriverList.Flink; 01727 NextEntry != &DriverList; 01728 i++, NextEntry = NextEntry->Flink); 01729 01730 /* Allocate the array */ 01731 ServicePath = ExAllocatePool(NonPagedPool, (i + 1) * sizeof(PUNICODE_STRING)); 01732 if (!ServicePath) KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 2, 1, 0, 0); 01733 01734 /* Loop the driver list */ 01735 for (i = 0, NextEntry = DriverList.Flink; 01736 NextEntry != &DriverList; 01737 i++, NextEntry = NextEntry->Flink) 01738 { 01739 /* Get the entry */ 01740 DriverEntry = CONTAINING_RECORD(NextEntry, BOOT_DRIVER_LIST_ENTRY, Link); 01741 01742 /* Allocate the path for the caller and duplicate the registry path */ 01743 ServicePath[i] = ExAllocatePool(NonPagedPool, sizeof(UNICODE_STRING)); 01744 RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, 01745 &DriverEntry->RegistryPath, 01746 ServicePath[i]); 01747 } 01748 01749 /* Terminate the list */ 01750 ServicePath[i] = NULL; 01751 01752 EndPath: 01753 /* Free the driver list if we had one */ 01754 if (!IsListEmpty(&DriverList)) CmpFreeDriverList(Hive, &DriverList); 01755 01756 /* Unlock the registry */ 01757 CmpUnlockRegistry(); 01758 01759 /* Close the key handle and dereference the object, then return the path */ 01760 ObDereferenceObject(KeyBody); 01761 NtClose(KeyHandle); 01762 return ServicePath; 01763 } 01764 01765 VOID 01766 NTAPI 01767 CmpLockRegistryExclusive(VOID) 01768 { 01769 /* Enter a critical region and lock the registry */ 01770 KeEnterCriticalRegion(); 01771 ExAcquireResourceExclusiveLite(&CmpRegistryLock, TRUE); 01772 01773 /* Sanity check */ 01774 ASSERT(CmpFlushStarveWriters == 0); 01775 RtlGetCallersAddress(&CmpRegistryLockCaller, &CmpRegistryLockCallerCaller); 01776 } 01777 01778 VOID 01779 NTAPI 01780 CmpLockRegistry(VOID) 01781 { 01782 /* Enter a critical region */ 01783 KeEnterCriticalRegion(); 01784 01785 /* Check if we have to starve writers */ 01786 if (CmpFlushStarveWriters) 01787 { 01788 /* Starve exlusive waiters */ 01789 ExAcquireSharedStarveExclusive(&CmpRegistryLock, TRUE); 01790 } 01791 else 01792 { 01793 /* Just grab the lock */ 01794 ExAcquireResourceSharedLite(&CmpRegistryLock, TRUE); 01795 } 01796 } 01797 01798 BOOLEAN 01799 NTAPI 01800 CmpTestRegistryLock(VOID) 01801 { 01802 /* Test the lock */ 01803 return !ExIsResourceAcquiredSharedLite(&CmpRegistryLock) ? FALSE : TRUE; 01804 } 01805 01806 BOOLEAN 01807 NTAPI 01808 CmpTestRegistryLockExclusive(VOID) 01809 { 01810 /* Test the lock */ 01811 return !ExIsResourceAcquiredExclusiveLite(&CmpRegistryLock) ? FALSE : TRUE; 01812 } 01813 01814 VOID 01815 NTAPI 01816 CmpLockHiveFlusherExclusive(IN PCMHIVE Hive) 01817 { 01818 /* Lock the flusher. We should already be in a critical section */ 01819 CMP_ASSERT_REGISTRY_LOCK_OR_LOADING(Hive); 01820 ASSERT((ExIsResourceAcquiredShared(Hive->FlusherLock) == 0) && 01821 (ExIsResourceAcquiredExclusiveLite(Hive->FlusherLock) == 0)); 01822 ExAcquireResourceExclusiveLite(Hive->FlusherLock, TRUE); 01823 } 01824 01825 VOID 01826 NTAPI 01827 CmpLockHiveFlusherShared(IN PCMHIVE Hive) 01828 { 01829 /* Lock the flusher. We should already be in a critical section */ 01830 CMP_ASSERT_REGISTRY_LOCK_OR_LOADING(Hive); 01831 ASSERT((ExIsResourceAcquiredShared(Hive->FlusherLock) == 0) && 01832 (ExIsResourceAcquiredExclusiveLite(Hive->FlusherLock) == 0)); 01833 ExAcquireResourceSharedLite(Hive->FlusherLock, TRUE); 01834 } 01835 01836 VOID 01837 NTAPI 01838 CmpUnlockHiveFlusher(IN PCMHIVE Hive) 01839 { 01840 /* Sanity check */ 01841 CMP_ASSERT_REGISTRY_LOCK_OR_LOADING(Hive); 01842 CMP_ASSERT_FLUSH_LOCK(Hive); 01843 01844 /* Release the lock */ 01845 ExReleaseResourceLite(Hive->FlusherLock); 01846 } 01847 01848 BOOLEAN 01849 NTAPI 01850 CmpTestHiveFlusherLockShared(IN PCMHIVE Hive) 01851 { 01852 /* Test the lock */ 01853 return !ExIsResourceAcquiredSharedLite(Hive->FlusherLock) ? FALSE : TRUE; 01854 } 01855 01856 BOOLEAN 01857 NTAPI 01858 CmpTestHiveFlusherLockExclusive(IN PCMHIVE Hive) 01859 { 01860 /* Test the lock */ 01861 return !ExIsResourceAcquiredExclusiveLite(Hive->FlusherLock) ? FALSE : TRUE; 01862 } 01863 01864 VOID 01865 NTAPI 01866 CmpUnlockRegistry(VOID) 01867 { 01868 /* Sanity check */ 01869 CMP_ASSERT_REGISTRY_LOCK(); 01870 01871 /* Check if we should flush the registry */ 01872 if (CmpFlushOnLockRelease) 01873 { 01874 /* The registry should be exclusively locked for this */ 01875 CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK(); 01876 01877 /* Flush the registry */ 01878 CmpDoFlushAll(TRUE); 01879 CmpFlushOnLockRelease = FALSE; 01880 } 01881 01882 /* Release the lock and leave the critical region */ 01883 ExReleaseResourceLite(&CmpRegistryLock); 01884 KeLeaveCriticalRegion(); 01885 } 01886 01887 VOID 01888 NTAPI 01889 CmpAcquireTwoKcbLocksExclusiveByKey(IN ULONG ConvKey1, 01890 IN ULONG ConvKey2) 01891 { 01892 ULONG Index1, Index2; 01893 01894 /* Sanity check */ 01895 CMP_ASSERT_REGISTRY_LOCK(); 01896 01897 /* Get hash indexes */ 01898 Index1 = GET_HASH_INDEX(ConvKey1); 01899 Index2 = GET_HASH_INDEX(ConvKey2); 01900 01901 /* See which one is highest */ 01902 if (Index1 < Index2) 01903 { 01904 /* Grab them in the proper order */ 01905 CmpAcquireKcbLockExclusiveByKey(ConvKey1); 01906 CmpAcquireKcbLockExclusiveByKey(ConvKey2); 01907 } 01908 else 01909 { 01910 /* Grab the second one first, then the first */ 01911 CmpAcquireKcbLockExclusiveByKey(ConvKey2); 01912 if (Index1 != Index2) CmpAcquireKcbLockExclusiveByKey(ConvKey1); 01913 } 01914 } 01915 01916 VOID 01917 NTAPI 01918 CmpReleaseTwoKcbLockByKey(IN ULONG ConvKey1, 01919 IN ULONG ConvKey2) 01920 { 01921 ULONG Index1, Index2; 01922 01923 /* Sanity check */ 01924 CMP_ASSERT_REGISTRY_LOCK(); 01925 01926 /* Get hash indexes */ 01927 Index1 = GET_HASH_INDEX(ConvKey1); 01928 Index2 = GET_HASH_INDEX(ConvKey2); 01929 ASSERT((GET_HASH_ENTRY(CmpCacheTable, ConvKey2).Owner == KeGetCurrentThread()) || 01930 (CmpTestRegistryLockExclusive())); 01931 01932 /* See which one is highest */ 01933 if (Index1 < Index2) 01934 { 01935 /* Grab them in the proper order */ 01936 ASSERT((GET_HASH_ENTRY(CmpCacheTable, ConvKey1).Owner == KeGetCurrentThread()) || 01937 (CmpTestRegistryLockExclusive())); 01938 CmpReleaseKcbLockByKey(ConvKey2); 01939 CmpReleaseKcbLockByKey(ConvKey1); 01940 } 01941 else 01942 { 01943 /* Release the first one first, then the second */ 01944 if (Index1 != Index2) 01945 { 01946 ASSERT((GET_HASH_ENTRY(CmpCacheTable, ConvKey1).Owner == KeGetCurrentThread()) || 01947 (CmpTestRegistryLockExclusive())); 01948 CmpReleaseKcbLockByKey(ConvKey1); 01949 } 01950 CmpReleaseKcbLockByKey(ConvKey2); 01951 } 01952 } 01953 01954 VOID 01955 NTAPI 01956 CmShutdownSystem(VOID) 01957 { 01958 /* Kill the workers */ 01959 if (!CmFirstTime) CmpShutdownWorkers(); 01960 01961 /* Flush all hives */ 01962 CmpLockRegistryExclusive(); 01963 CmpDoFlushAll(TRUE); 01964 CmpUnlockRegistry(); 01965 } 01966 01967 VOID 01968 NTAPI 01969 CmpSetVersionData(VOID) 01970 { 01971 OBJECT_ATTRIBUTES ObjectAttributes; 01972 UNICODE_STRING KeyName; 01973 UNICODE_STRING ValueName; 01974 UNICODE_STRING ValueData; 01975 HANDLE SoftwareKeyHandle = NULL; 01976 HANDLE MicrosoftKeyHandle = NULL; 01977 HANDLE WindowsNtKeyHandle = NULL; 01978 HANDLE CurrentVersionKeyHandle = NULL; 01979 WCHAR Buffer[128]; 01980 NTSTATUS Status; 01981 01982 /* Open the 'CurrentVersion' key */ 01983 RtlInitUnicodeString(&KeyName, 01984 L"\\REGISTRY\\MACHINE\\SOFTWARE"); 01985 01986 InitializeObjectAttributes(&ObjectAttributes, 01987 &KeyName, 01988 OBJ_CASE_INSENSITIVE, 01989 NULL, 01990 NULL); 01991 01992 Status = NtCreateKey(&SoftwareKeyHandle, 01993 KEY_CREATE_SUB_KEY, 01994 &ObjectAttributes, 01995 0, 01996 NULL, 01997 0, 01998 NULL); 01999 if (!NT_SUCCESS(Status)) 02000 { 02001 DPRINT1("Failed to create key %wZ (Status: %08lx)\n", &KeyName, Status); 02002 return; 02003 } 02004 02005 /* Open the 'CurrentVersion' key */ 02006 RtlInitUnicodeString(&KeyName, 02007 L"Microsoft"); 02008 02009 InitializeObjectAttributes(&ObjectAttributes, 02010 &KeyName, 02011 OBJ_CASE_INSENSITIVE, 02012 SoftwareKeyHandle, 02013 NULL); 02014 02015 Status = NtCreateKey(&MicrosoftKeyHandle, 02016 KEY_CREATE_SUB_KEY, 02017 &ObjectAttributes, 02018 0, 02019 NULL, 02020 0, 02021 NULL); 02022 if (!NT_SUCCESS(Status)) 02023 { 02024 DPRINT1("Failed to create key %wZ (Status: %08lx)\n", &KeyName, Status); 02025 goto done; 02026 } 02027 02028 /* Open the 'CurrentVersion' key */ 02029 RtlInitUnicodeString(&KeyName, 02030 L"Windows NT"); 02031 02032 InitializeObjectAttributes(&ObjectAttributes, 02033 &KeyName, 02034 OBJ_CASE_INSENSITIVE, 02035 MicrosoftKeyHandle, 02036 NULL); 02037 02038 Status = NtCreateKey(&WindowsNtKeyHandle, 02039 KEY_CREATE_SUB_KEY, 02040 &ObjectAttributes, 02041 0, 02042 NULL, 02043 0, 02044 NULL); 02045 if (!NT_SUCCESS(Status)) 02046 { 02047 DPRINT1("Failed to create key %wZ (Status: %08lx)\n", &KeyName, Status); 02048 goto done; 02049 } 02050 02051 /* Open the 'CurrentVersion' key */ 02052 RtlInitUnicodeString(&KeyName, 02053 L"CurrentVersion"); 02054 02055 InitializeObjectAttributes(&ObjectAttributes, 02056 &KeyName, 02057 OBJ_CASE_INSENSITIVE, 02058 WindowsNtKeyHandle, 02059 NULL); 02060 02061 Status = NtCreateKey(&CurrentVersionKeyHandle, 02062 KEY_CREATE_SUB_KEY | KEY_SET_VALUE, 02063 &ObjectAttributes, 02064 0, 02065 NULL, 02066 0, 02067 NULL); 02068 if (!NT_SUCCESS(Status)) 02069 { 02070 DPRINT1("Failed to create key %wZ (Status: %08lx)\n", &KeyName, Status); 02071 goto done; 02072 } 02073 02074 /* Set the 'CurrentType' value */ 02075 RtlInitUnicodeString(&ValueName, 02076 L"CurrentType"); 02077 02078 #ifdef CONFIG_SMP 02079 wcscpy(Buffer, L"Multiprocessor"); 02080 #else 02081 wcscpy(Buffer, L"Uniprocessor"); 02082 #endif 02083 02084 wcscat(Buffer, L" "); 02085 02086 #if (DBG == 1) 02087 wcscat(Buffer, L"Checked"); 02088 #else 02089 wcscat(Buffer, L"Free"); 02090 #endif 02091 02092 RtlInitUnicodeString(&ValueData, 02093 Buffer); 02094 02095 NtSetValueKey(CurrentVersionKeyHandle, 02096 &ValueName, 02097 0, 02098 REG_SZ, 02099 ValueData.Buffer, 02100 ValueData.Length + sizeof(WCHAR)); 02101 02102 done:; 02103 /* Close the keys */ 02104 if (CurrentVersionKeyHandle != NULL) 02105 NtClose(CurrentVersionKeyHandle); 02106 02107 if (WindowsNtKeyHandle != NULL) 02108 NtClose(WindowsNtKeyHandle); 02109 02110 if (MicrosoftKeyHandle != NULL) 02111 NtClose(MicrosoftKeyHandle); 02112 02113 if (SoftwareKeyHandle != NULL) 02114 NtClose(SoftwareKeyHandle); 02115 } 02116 02117 /* EOF */ Generated on Sun May 27 2012 04:37:08 for ReactOS by
1.7.6.1
|