ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

cmsysini.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.