2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/config/cmsysini.c
5 * PURPOSE: Configuration Manager - System Initialization Code
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
15 POBJECT_TYPE CmpKeyObjectType
;
16 PCMHIVE CmiVolatileHive
;
17 LIST_ENTRY CmpHiveListHead
;
18 ERESOURCE CmpRegistryLock
;
19 KGUARDED_MUTEX CmpSelfHealQueueLock
;
20 LIST_ENTRY CmpSelfHealQueueListHead
;
21 KEVENT CmpLoadWorkerEvent
;
22 LONG CmpLoadWorkerIncrement
;
23 PEPROCESS CmpSystemProcess
;
24 BOOLEAN HvShutdownComplete
;
25 PVOID CmpRegistryLockCallerCaller
, CmpRegistryLockCaller
;
26 BOOLEAN CmpFlushStarveWriters
;
27 BOOLEAN CmpFlushOnLockRelease
;
28 BOOLEAN CmpSpecialBootCondition
;
30 BOOLEAN CmpForceForceFlush
;
31 BOOLEAN CmpWasSetupBoot
;
33 extern BOOLEAN CmFirstTime
;
35 /* FUNCTIONS *****************************************************************/
39 CmpDeleteKeyObject(PVOID DeletedObject
)
41 PCM_KEY_BODY KeyBody
= (PCM_KEY_BODY
)DeletedObject
;
42 PCM_KEY_CONTROL_BLOCK Kcb
;
43 REG_KEY_HANDLE_CLOSE_INFORMATION KeyHandleCloseInfo
;
44 REG_POST_OPERATION_INFORMATION PostOperationInfo
;
48 /* First off, prepare the handle close information callback */
49 PostOperationInfo
.Object
= KeyBody
;
50 KeyHandleCloseInfo
.Object
= KeyBody
;
51 Status
= CmiCallRegisteredCallbacks(RegNtPreKeyHandleClose
,
53 if (!NT_SUCCESS(Status
))
55 /* If we failed, notify the post routine */
56 PostOperationInfo
.Status
= Status
;
57 CmiCallRegisteredCallbacks(RegNtPostKeyHandleClose
, &PostOperationInfo
);
61 /* Acquire hive lock */
64 /* Make sure this is a valid key body */
65 if (KeyBody
->Type
== TAG('k', 'y', '0', '2'))
68 Kcb
= KeyBody
->KeyControlBlock
;
72 DelistKeyBodyFromKCB(KeyBody
, FALSE
);
75 /* Dereference the KCB */
76 CmpDelayDerefKeyControlBlock(Kcb
);
80 /* Release the registry lock */
83 /* Do the post callback */
84 PostOperationInfo
.Status
= STATUS_SUCCESS
;
85 CmiCallRegisteredCallbacks(RegNtPostKeyHandleClose
, &PostOperationInfo
);
90 CmpCloseKeyObject(IN PEPROCESS Process OPTIONAL
,
92 IN ACCESS_MASK GrantedAccess
,
93 IN ULONG ProcessHandleCount
,
94 IN ULONG SystemHandleCount
)
96 PCM_KEY_BODY KeyBody
= (PCM_KEY_BODY
)Object
;
99 /* Don't do anything if we're not the last handle */
100 if (SystemHandleCount
> 1) return;
102 /* Make sure we're a valid key body */
103 if (KeyBody
->Type
== TAG('k', 'y', '0', '2'))
105 /* Don't do anything if we don't have a notify block */
106 if (!KeyBody
->NotifyBlock
) return;
108 /* This shouldn't happen yet */
115 CmpQueryKeyName(IN PVOID ObjectBody
,
117 IN OUT POBJECT_NAME_INFORMATION ObjectNameInfo
,
119 OUT PULONG ReturnLength
,
120 IN KPROCESSOR_MODE PreviousMode
)
122 DPRINT1("CmpQueryKeyName() called\n");
124 return STATUS_SUCCESS
;
129 CmpInitHiveFromFile(IN PCUNICODE_STRING HiveName
,
135 ULONG HiveDisposition
, LogDisposition
;
136 HANDLE FileHandle
= NULL
, LogHandle
= NULL
;
138 ULONG Operation
, FileType
;
145 /* Open or create the hive files */
146 Status
= CmpOpenHiveFiles(HiveName
,
156 if (!NT_SUCCESS(Status
)) return Status
;
158 /* Check if we have a log handle */
159 FileType
= (LogHandle
) ? HFILE_TYPE_LOG
: HFILE_TYPE_PRIMARY
;
161 /* Check if we created or opened the hive */
162 if (HiveDisposition
== FILE_CREATED
)
164 /* Do a create operation */
165 Operation
= HINIT_CREATE
;
170 /* Open it as a file */
171 Operation
= HINIT_FILE
;
175 /* Check if we're sharing hives */
176 if (CmpShareSystemHives
)
178 /* Then force using the primary hive */
179 FileType
= HFILE_TYPE_PRIMARY
;
182 /* Get rid of the log handle */
188 /* Check if we're too late */
189 if (HvShutdownComplete
)
193 if (LogHandle
) ZwClose(LogHandle
);
194 return STATUS_TOO_LATE
;
197 /* Initialize the hive */
198 Status
= CmpInitializeHive((PCMHIVE
*)&NewHive
,
208 if (!NT_SUCCESS(Status
))
212 if (LogHandle
) ZwClose(LogHandle
);
216 /* Success, return hive */
219 /* ROS: Init root key cell and prepare the hive */
220 if (Operation
== HINIT_CREATE
) CmCreateRootNode(&NewHive
->Hive
, L
"");
222 /* Duplicate the hive name */
223 NewHive
->FileFullPath
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
226 if (NewHive
->FileFullPath
.Buffer
)
228 /* Copy the string */
229 RtlCopyMemory(NewHive
->FileFullPath
.Buffer
,
232 NewHive
->FileFullPath
.Length
= HiveName
->Length
;
233 NewHive
->FileFullPath
.MaximumLength
= HiveName
->MaximumLength
;
237 return STATUS_SUCCESS
;
242 CmpSetSystemValues(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
244 OBJECT_ATTRIBUTES ObjectAttributes
;
245 UNICODE_STRING KeyName
, ValueName
= {0};
248 ASSERT(LoaderBlock
!= NULL
);
250 /* Setup attributes for loader options */
251 RtlInitUnicodeString(&KeyName
,
252 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\"
254 InitializeObjectAttributes(&ObjectAttributes
,
256 OBJ_CASE_INSENSITIVE
,
259 Status
= NtOpenKey(&KeyHandle
, KEY_WRITE
, &ObjectAttributes
);
260 if (!NT_SUCCESS(Status
)) goto Quickie
;
262 /* Key opened, now write to the key */
263 RtlInitUnicodeString(&KeyName
, L
"SystemStartOptions");
264 Status
= NtSetValueKey(KeyHandle
,
268 CmpLoadOptions
.Buffer
,
269 CmpLoadOptions
.Length
);
270 if (!NT_SUCCESS(Status
)) goto Quickie
;
272 /* Setup value name for system boot device */
273 RtlInitUnicodeString(&KeyName
, L
"SystemBootDevice");
274 RtlCreateUnicodeStringFromAsciiz(&ValueName
, LoaderBlock
->NtBootPathName
);
275 Status
= NtSetValueKey(KeyHandle
,
283 /* Free the buffers */
284 RtlFreeUnicodeString(&ValueName
);
286 /* Close the key and return */
289 /* Return the status */
290 return (ExpInTextModeSetup
? STATUS_SUCCESS
: Status
);
295 CmpCreateControlSet(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
297 UNICODE_STRING ConfigName
= RTL_CONSTANT_STRING(L
"Control\\IDConfigDB");
298 UNICODE_STRING SelectName
=
299 RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\System\\Select");
300 UNICODE_STRING KeyName
;
301 OBJECT_ATTRIBUTES ObjectAttributes
;
302 CHAR ValueInfoBuffer
[128];
303 PKEY_VALUE_FULL_INFORMATION ValueInfo
;
305 WCHAR UnicodeBuffer
[128];
306 HANDLE SelectHandle
, KeyHandle
, ConfigHandle
= NULL
, ProfileHandle
= NULL
;
307 HANDLE ParentHandle
= NULL
;
308 ULONG ControlSet
, HwProfile
;
309 ANSI_STRING TempString
;
311 ULONG ResultLength
, Disposition
;
312 PLOADER_PARAMETER_EXTENSION LoaderExtension
;
315 /* Open the select key */
316 InitializeObjectAttributes(&ObjectAttributes
,
318 OBJ_CASE_INSENSITIVE
,
321 Status
= NtOpenKey(&SelectHandle
, KEY_READ
, &ObjectAttributes
);
322 if (!NT_SUCCESS(Status
))
324 /* ReactOS Hack: Hard-code current to 001 for SetupLdr */
325 if (!LoaderBlock
->RegistryBase
)
327 /* Build the ControlSet001 key */
328 RtlInitUnicodeString(&KeyName
,
329 L
"\\Registry\\Machine\\System\\ControlSet001");
330 InitializeObjectAttributes(&ObjectAttributes
,
332 OBJ_CASE_INSENSITIVE
,
335 Status
= NtCreateKey(&KeyHandle
,
342 if (!NT_SUCCESS(Status
)) return Status
;
344 /* Don't need the handle */
347 /* Use hard-coded setting */
352 /* Fail for real boots */
356 /* Open the current value */
357 RtlInitUnicodeString(&KeyName
, L
"Current");
358 Status
= NtQueryValueKey(SelectHandle
,
360 KeyValueFullInformation
,
362 sizeof(ValueInfoBuffer
),
364 NtClose(SelectHandle
);
365 if (!NT_SUCCESS(Status
)) return Status
;
367 /* Get the actual value pointer, and get the control set ID */
368 ValueInfo
= (PKEY_VALUE_FULL_INFORMATION
)ValueInfoBuffer
;
369 ControlSet
= *(PULONG
)((PUCHAR
)ValueInfo
+ ValueInfo
->DataOffset
);
371 /* Create the current control set key */
373 RtlInitUnicodeString(&KeyName
,
374 L
"\\Registry\\Machine\\System\\CurrentControlSet");
375 InitializeObjectAttributes(&ObjectAttributes
,
377 OBJ_CASE_INSENSITIVE
,
380 Status
= NtCreateKey(&KeyHandle
,
385 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
387 if (!NT_SUCCESS(Status
)) return Status
;
390 ASSERT(Disposition
== REG_CREATED_NEW_KEY
);
392 /* Initialize the symbolic link name */
394 "\\Registry\\Machine\\System\\ControlSet%03ld",
396 RtlInitAnsiString(&TempString
, Buffer
);
398 /* Create a Unicode string out of it */
399 KeyName
.MaximumLength
= sizeof(UnicodeBuffer
);
400 KeyName
.Buffer
= UnicodeBuffer
;
401 Status
= RtlAnsiStringToUnicodeString(&KeyName
, &TempString
, FALSE
);
404 Status
= NtSetValueKey(KeyHandle
,
405 &CmSymbolicLinkValueName
,
410 if (!NT_SUCCESS(Status
)) return Status
;
412 /* Get the configuration database key */
413 InitializeObjectAttributes(&ObjectAttributes
,
415 OBJ_CASE_INSENSITIVE
,
418 Status
= NtOpenKey(&ConfigHandle
, KEY_READ
, &ObjectAttributes
);
421 /* Check if we don't have one */
422 if (!NT_SUCCESS(Status
))
424 /* Cleanup and exit */
429 /* Now get the current config */
430 RtlInitUnicodeString(&KeyName
, L
"CurrentConfig");
431 Status
= NtQueryValueKey(ConfigHandle
,
433 KeyValueFullInformation
,
435 sizeof(ValueInfoBuffer
),
438 /* Set pointer to buffer */
439 ValueInfo
= (PKEY_VALUE_FULL_INFORMATION
)ValueInfoBuffer
;
441 /* Check if we failed or got a non DWORD-value */
442 if (!(NT_SUCCESS(Status
)) || (ValueInfo
->Type
!= REG_DWORD
)) goto Cleanup
;
444 /* Get the hadware profile */
445 HwProfile
= *(PULONG
)((PUCHAR
)ValueInfo
+ ValueInfo
->DataOffset
);
447 /* Open the hardware profile key */
448 RtlInitUnicodeString(&KeyName
,
449 L
"\\Registry\\Machine\\System\\CurrentControlSet"
450 L
"\\Hardware Profiles");
451 InitializeObjectAttributes(&ObjectAttributes
,
453 OBJ_CASE_INSENSITIVE
,
456 Status
= NtOpenKey(&ParentHandle
, KEY_READ
, &ObjectAttributes
);
457 if (!NT_SUCCESS(Status
))
459 /* Exit and clean up */
464 /* Build the profile name */
465 sprintf(Buffer
, "%04ld", HwProfile
);
466 RtlInitAnsiString(&TempString
, Buffer
);
468 /* Convert it to Unicode */
469 KeyName
.MaximumLength
= sizeof(UnicodeBuffer
);
470 KeyName
.Buffer
= UnicodeBuffer
;
471 Status
= RtlAnsiStringToUnicodeString(&KeyName
,
474 ASSERT(Status
== STATUS_SUCCESS
);
476 /* Open the associated key */
477 InitializeObjectAttributes(&ObjectAttributes
,
479 OBJ_CASE_INSENSITIVE
,
482 Status
= NtOpenKey(&ProfileHandle
,
483 KEY_READ
| KEY_WRITE
,
485 if (!NT_SUCCESS (Status
))
487 /* Cleanup and exit */
492 /* Check if we have a loader block extension */
493 LoaderExtension
= LoaderBlock
->Extension
;
496 ASSERTMSG("ReactOS doesn't support NTLDR Profiles yet!\n", FALSE
);
499 /* Create the current hardware profile key */
500 RtlInitUnicodeString(&KeyName
,
501 L
"\\Registry\\Machine\\System\\CurrentControlSet\\"
502 L
"Hardware Profiles\\Current");
503 InitializeObjectAttributes(&ObjectAttributes
,
505 OBJ_CASE_INSENSITIVE
,
508 Status
= NtCreateKey(&KeyHandle
,
513 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
515 if (NT_SUCCESS(Status
))
518 ASSERT(Disposition
== REG_CREATED_NEW_KEY
);
520 /* Create the profile name */
522 "\\Registry\\Machine\\System\\CurrentControlSet\\"
523 "Hardware Profiles\\%04ld",
525 RtlInitAnsiString(&TempString
, Buffer
);
527 /* Convert it to Unicode */
528 KeyName
.MaximumLength
= sizeof(UnicodeBuffer
);
529 KeyName
.Buffer
= UnicodeBuffer
;
530 Status
= RtlAnsiStringToUnicodeString(&KeyName
,
533 ASSERT(STATUS_SUCCESS
== Status
);
536 Status
= NtSetValueKey(KeyHandle
,
537 &CmSymbolicLinkValueName
,
545 /* Close every opened handle */
547 if (ConfigHandle
) NtClose(ConfigHandle
);
548 if (ProfileHandle
) NtClose(ProfileHandle
);
549 if (ParentHandle
) NtClose(ParentHandle
);
552 return STATUS_SUCCESS
;
557 CmpLinkHiveToMaster(IN PUNICODE_STRING LinkName
,
558 IN HANDLE RootDirectory
,
559 IN PCMHIVE RegistryHive
,
561 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
563 OBJECT_ATTRIBUTES ObjectAttributes
;
565 CM_PARSE_CONTEXT ParseContext
= {0};
567 PCM_KEY_BODY KeyBody
;
570 /* Setup the object attributes */
571 InitializeObjectAttributes(&ObjectAttributes
,
573 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
577 /* Setup the parse context */
578 ParseContext
.CreateLink
= TRUE
;
579 ParseContext
.CreateOperation
= TRUE
;
580 ParseContext
.ChildHive
.KeyHive
= &RegistryHive
->Hive
;
582 /* Check if we have a root keycell or if we need to create it */
586 ParseContext
.ChildHive
.KeyCell
= HCELL_NIL
;
591 ParseContext
.ChildHive
.KeyCell
= RegistryHive
->Hive
.BaseBlock
->RootCell
;
594 /* Create the link node */
595 Status
= ObOpenObjectByName(&ObjectAttributes
,
599 KEY_READ
| KEY_WRITE
,
600 (PVOID
)&ParseContext
,
602 if (!NT_SUCCESS(Status
)) return Status
;
604 /* Mark the hive as clean */
605 RegistryHive
->Hive
.DirtyFlag
= FALSE
;
607 /* ReactOS Hack: Keep alive */
608 Status
= ObReferenceObjectByHandle(KeyHandle
,
614 ASSERT(NT_SUCCESS(Status
));
616 /* Close the extra handle */
618 return STATUS_SUCCESS
;
623 CmpInitializeSystemHive(IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
626 ANSI_STRING LoadString
;
631 UNICODE_STRING KeyName
;
632 PCMHIVE SystemHive
= NULL
;
633 UNICODE_STRING HiveName
= RTL_CONSTANT_STRING(L
"SYSTEM");
634 PSECURITY_DESCRIPTOR SecurityDescriptor
;
637 /* Setup the ansi string */
638 RtlInitAnsiString(&LoadString
, LoaderBlock
->LoadOptions
);
640 /* Allocate the unicode buffer */
641 Length
= LoadString
.Length
* sizeof(WCHAR
) + sizeof(UNICODE_NULL
);
642 Buffer
= ExAllocatePoolWithTag(PagedPool
, Length
, TAG_CM
);
646 KEBUGCHECKEX(BAD_SYSTEM_CONFIG_INFO
, 3, 1, (ULONG_PTR
)LoaderBlock
, 0);
649 /* Setup the unicode string */
650 RtlInitEmptyUnicodeString(&CmpLoadOptions
, Buffer
, (USHORT
)Length
);
652 /* Add the load options and null-terminate */
653 RtlAnsiStringToUnicodeString(&CmpLoadOptions
, &LoadString
, FALSE
);
654 CmpLoadOptions
.Buffer
[LoadString
.Length
] = UNICODE_NULL
;
655 CmpLoadOptions
.Length
+= sizeof(WCHAR
);
657 /* Get the System Hive base address */
658 HiveBase
= LoaderBlock
->RegistryBase
;
662 ((PHBASE_BLOCK
)HiveBase
)->Length
= LoaderBlock
->RegistryLength
;
663 Status
= CmpInitializeHive((PCMHIVE
*)&SystemHive
,
673 if (!NT_SUCCESS(Status
)) return FALSE
;
675 /* Set the hive filename */
676 RtlCreateUnicodeString(&SystemHive
->FileFullPath
,
677 L
"\\SystemRoot\\System32\\Config\\SYSTEM");
679 /* We imported, no need to create a new hive */
682 /* Manually set the hive as volatile, if in Live CD mode */
683 if (CmpShareSystemHives
) SystemHive
->Hive
.HiveFlags
= HIVE_VOLATILE
;
688 Status
= CmpInitializeHive(&SystemHive
,
698 if (!NT_SUCCESS(Status
)) return FALSE
;
700 /* Set the hive filename */
701 RtlCreateUnicodeString(&SystemHive
->FileFullPath
,
702 L
"\\SystemRoot\\System32\\Config\\SYSTEM");
704 /* Tell CmpLinkHiveToMaster to allocate a hive */
708 /* Save the boot type */
709 if (SystemHive
) CmpBootType
= SystemHive
->Hive
.BaseBlock
->BootType
;
711 /* Are we in self-healing mode? */
714 /* Disable self-healing internally and check if boot type wanted it */
718 /* We're disabled, so bugcheck */
719 KEBUGCHECKEX(BAD_SYSTEM_CONFIG_INFO
,
722 (ULONG_PTR
)SystemHive
,
727 /* Create the default security descriptor */
728 SecurityDescriptor
= CmpHiveRootSecurityDescriptor();
730 /* Attach it to the system key */
731 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\SYSTEM");
732 Status
= CmpLinkHiveToMaster(&KeyName
,
738 /* Free the security descriptor */
739 ExFreePool(SecurityDescriptor
);
740 if (!NT_SUCCESS(Status
)) return FALSE
;
742 /* Add the hive to the hive list */
743 CmpMachineHiveList
[3].CmHive
= (PCMHIVE
)SystemHive
;
751 CmpCreateObjectTypes(VOID
)
753 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
755 GENERIC_MAPPING CmpKeyMapping
= {KEY_READ
,
761 /* Initialize the Key object type */
762 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
763 RtlInitUnicodeString(&Name
, L
"Key");
764 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
765 ObjectTypeInitializer
.DefaultPagedPoolCharge
= sizeof(CM_KEY_BODY
);
766 ObjectTypeInitializer
.GenericMapping
= CmpKeyMapping
;
767 ObjectTypeInitializer
.PoolType
= PagedPool
;
768 ObjectTypeInitializer
.ValidAccessMask
= KEY_ALL_ACCESS
;
769 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
770 ObjectTypeInitializer
.DeleteProcedure
= CmpDeleteKeyObject
;
771 ObjectTypeInitializer
.ParseProcedure
= CmpParseKey
;
772 ObjectTypeInitializer
.SecurityProcedure
= CmpSecurityMethod
;
773 ObjectTypeInitializer
.QueryNameProcedure
= CmpQueryKeyName
;
774 ObjectTypeInitializer
.CloseProcedure
= CmpCloseKeyObject
;
775 ObjectTypeInitializer
.SecurityRequired
= TRUE
;
778 return ObCreateObjectType(&Name
, &ObjectTypeInitializer
, NULL
, &CmpKeyObjectType
);
783 CmpCreateRootNode(IN PHHIVE Hive
,
785 OUT PHCELL_INDEX Index
)
787 UNICODE_STRING KeyName
;
788 PCM_KEY_NODE KeyCell
;
789 LARGE_INTEGER SystemTime
;
792 /* Initialize the node name and allocate it */
793 RtlInitUnicodeString(&KeyName
, Name
);
794 *Index
= HvAllocateCell(Hive
,
795 FIELD_OFFSET(CM_KEY_NODE
, Name
) +
796 CmpNameSize(Hive
, &KeyName
),
799 if (*Index
== HCELL_NIL
) return FALSE
;
801 /* Set the cell index and get the data */
802 Hive
->BaseBlock
->RootCell
= *Index
;
803 KeyCell
= (PCM_KEY_NODE
)HvGetCell(Hive
, *Index
);
804 if (!KeyCell
) return FALSE
;
807 KeyCell
->Signature
= (USHORT
)CM_KEY_NODE_SIGNATURE
;
808 KeyCell
->Flags
= KEY_HIVE_ENTRY
| KEY_NO_DELETE
;
809 KeQuerySystemTime(&SystemTime
);
810 KeyCell
->LastWriteTime
= SystemTime
;
811 KeyCell
->Parent
= HCELL_NIL
;
812 KeyCell
->SubKeyCounts
[Stable
] = 0;
813 KeyCell
->SubKeyCounts
[Volatile
] = 0;
814 KeyCell
->SubKeyLists
[Stable
] = HCELL_NIL
;
815 KeyCell
->SubKeyLists
[Volatile
] = HCELL_NIL
;
816 KeyCell
->ValueList
.Count
= 0;
817 KeyCell
->ValueList
.List
= HCELL_NIL
;
818 KeyCell
->Security
= HCELL_NIL
;
819 KeyCell
->Class
= HCELL_NIL
;
820 KeyCell
->ClassLength
= 0;
821 KeyCell
->MaxNameLen
= 0;
822 KeyCell
->MaxClassLen
= 0;
823 KeyCell
->MaxValueNameLen
= 0;
824 KeyCell
->MaxValueDataLen
= 0;
826 /* Copy the name (this will also set the length) */
827 KeyCell
->NameLength
= CmpCopyName(Hive
, (PWCHAR
)KeyCell
->Name
, &KeyName
);
829 /* Check if the name was compressed */
830 if (KeyCell
->NameLength
< KeyName
.Length
)
833 KeyCell
->Flags
|= KEY_COMP_NAME
;
837 HvReleaseCell(Hive
, *Index
);
843 CmpCreateRegistryRoot(VOID
)
845 UNICODE_STRING KeyName
;
846 OBJECT_ATTRIBUTES ObjectAttributes
;
847 PCM_KEY_BODY RootKey
;
848 HCELL_INDEX RootIndex
;
850 PCM_KEY_NODE KeyCell
;
851 PSECURITY_DESCRIPTOR SecurityDescriptor
;
852 PCM_KEY_CONTROL_BLOCK Kcb
;
855 /* Setup the root node */
856 if (!CmpCreateRootNode(&CmiVolatileHive
->Hive
, L
"REGISTRY", &RootIndex
))
862 /* Create '\Registry' key. */
863 RtlInitUnicodeString(&KeyName
, L
"\\REGISTRY");
864 SecurityDescriptor
= CmpHiveRootSecurityDescriptor();
865 InitializeObjectAttributes(&ObjectAttributes
,
867 OBJ_CASE_INSENSITIVE
,
870 Status
= ObCreateObject(KernelMode
,
879 ExFreePool(SecurityDescriptor
);
880 if (!NT_SUCCESS(Status
)) return FALSE
;
882 /* Sanity check, and get the key cell */
883 ASSERT((&CmiVolatileHive
->Hive
)->ReleaseCellRoutine
== NULL
);
884 KeyCell
= (PCM_KEY_NODE
)HvGetCell(&CmiVolatileHive
->Hive
, RootIndex
);
885 if (!KeyCell
) return FALSE
;
888 RtlInitUnicodeString(&KeyName
, L
"\\REGISTRY");
889 Kcb
= CmpCreateKeyControlBlock(&CmiVolatileHive
->Hive
,
895 if (!Kcb
) return FALSE
;
897 /* Initialize the object */
898 RootKey
->KeyControlBlock
= Kcb
;
899 RootKey
->Type
= TAG('k', 'y', '0', '2');
900 RootKey
->NotifyBlock
= NULL
;
901 RootKey
->ProcessID
= PsGetCurrentProcessId();
904 EnlistKeyBodyWithKCB(RootKey
, 0);
906 /* Insert the key into the namespace */
907 Status
= ObInsertObject(RootKey
,
912 &CmpRegistryRootHandle
);
913 if (!NT_SUCCESS(Status
)) return FALSE
;
915 /* Reference the key again so that we never lose it */
916 Status
= ObReferenceObjectByHandle(CmpRegistryRootHandle
,
922 if (!NT_SUCCESS(Status
)) return FALSE
;
924 /* Completely sucessful */
930 CmpGetRegistryPath(IN PWCHAR ConfigPath
)
932 OBJECT_ATTRIBUTES ObjectAttributes
;
935 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
936 UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\HARDWARE");
937 UNICODE_STRING ValueName
= RTL_CONSTANT_STRING(L
"InstallPath");
938 ULONG BufferSize
, ResultSize
;
940 /* Check if we are booted in setup */
941 if (ExpInTextModeSetup
)
943 /* Setup the object attributes */
944 InitializeObjectAttributes(&ObjectAttributes
,
946 OBJ_CASE_INSENSITIVE
,
950 Status
= ZwOpenKey(&KeyHandle
,
953 if (!NT_SUCCESS(Status
)) return Status
;
955 /* Allocate the buffer */
956 BufferSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 4096;
957 ValueInfo
= ExAllocatePoolWithTag(PagedPool
, BufferSize
, TAG_CM
);
962 return STATUS_INSUFFICIENT_RESOURCES
;
965 /* Query the value */
966 Status
= ZwQueryValueKey(KeyHandle
,
968 KeyValuePartialInformation
,
973 if (!NT_SUCCESS(Status
))
976 ExFreePool(ValueInfo
);
980 /* Copy the config path and null-terminate it */
981 RtlCopyMemory(ConfigPath
,
983 ValueInfo
->DataLength
);
984 ConfigPath
[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
985 ExFreePool(ValueInfo
);
989 /* Just use default path */
990 wcscpy(ConfigPath
, L
"\\SystemRoot");
993 /* Add registry path */
994 wcscat(ConfigPath
, L
"\\System32\\Config\\");
997 return STATUS_SUCCESS
;
1002 CmpLoadHiveThread(IN PVOID StartContext
)
1004 WCHAR FileBuffer
[MAX_PATH
], RegBuffer
[MAX_PATH
], ConfigPath
[MAX_PATH
];
1005 UNICODE_STRING TempName
, FileName
, RegName
;
1006 ULONG FileStart
, RegStart
, i
, ErrorResponse
, WorkerCount
, Length
;
1007 ULONG PrimaryDisposition
, SecondaryDisposition
, ClusterSize
;
1009 HANDLE PrimaryHandle
, LogHandle
;
1010 NTSTATUS Status
= STATUS_SUCCESS
;
1011 PVOID ErrorParameters
;
1014 /* Get the hive index, make sure it makes sense */
1015 i
= (ULONG
)StartContext
;
1016 ASSERT(CmpMachineHiveList
[i
].Name
!= NULL
);
1018 /* We were started */
1019 CmpMachineHiveList
[i
].ThreadStarted
= TRUE
;
1021 /* Build the file name and registry name strings */
1022 RtlInitEmptyUnicodeString(&FileName
, FileBuffer
, MAX_PATH
);
1023 RtlInitEmptyUnicodeString(&RegName
, RegBuffer
, MAX_PATH
);
1025 /* Now build the system root path */
1026 CmpGetRegistryPath(ConfigPath
);
1027 RtlInitUnicodeString(&TempName
, ConfigPath
);
1028 RtlAppendStringToString((PSTRING
)&FileName
, (PSTRING
)&TempName
);
1029 FileStart
= FileName
.Length
;
1031 /* And build the registry root path */
1032 RtlInitUnicodeString(&TempName
, L
"\\REGISTRY\\");
1033 RtlAppendStringToString((PSTRING
)&RegName
, (PSTRING
)&TempName
);
1034 RegStart
= RegName
.Length
;
1036 /* Build the base name */
1037 RegName
.Length
= RegStart
;
1038 RtlInitUnicodeString(&TempName
, CmpMachineHiveList
[i
].BaseName
);
1039 RtlAppendStringToString((PSTRING
)&RegName
, (PSTRING
)&TempName
);
1041 /* Check if this is a child of the root */
1042 if (RegName
.Buffer
[RegName
.Length
/ sizeof(WCHAR
) - 1] == '\\')
1044 /* Then setup the whole name */
1045 RtlInitUnicodeString(&TempName
, CmpMachineHiveList
[i
].Name
);
1046 RtlAppendStringToString((PSTRING
)&RegName
, (PSTRING
)&TempName
);
1049 /* Now add the rest of the file name */
1050 RtlInitUnicodeString(&TempName
, CmpMachineHiveList
[i
].Name
);
1051 FileName
.Length
= FileStart
;
1052 RtlAppendStringToString((PSTRING
)&FileName
, (PSTRING
)&TempName
);
1053 if (!CmpMachineHiveList
[i
].CmHive
)
1055 /* We need to allocate a new hive structure */
1056 CmpMachineHiveList
[i
].Allocate
= TRUE
;
1058 /* Load the hive file */
1059 Status
= CmpInitHiveFromFile(&FileName
,
1060 CmpMachineHiveList
[i
].HHiveFlags
,
1062 &CmpMachineHiveList
[i
].Allocate
,
1064 if (!(NT_SUCCESS(Status
)) ||
1065 (!(CmHive
->FileHandles
[HFILE_TYPE_LOG
]) && !(CmpMiniNTBoot
))) // HACK
1067 /* We failed or couldn't get a log file, raise a hard error */
1068 ErrorParameters
= &FileName
;
1069 NtRaiseHardError(STATUS_CANNOT_LOAD_REGISTRY_FILE
,
1072 (PULONG_PTR
)&ErrorParameters
,
1077 /* Set the hive flags and newly allocated hive pointer */
1078 CmHive
->Flags
= CmpMachineHiveList
[i
].CmHiveFlags
;
1079 CmpMachineHiveList
[i
].CmHive2
= CmHive
;
1083 /* We already have a hive, is it volatile? */
1084 CmHive
= CmpMachineHiveList
[i
].CmHive
;
1085 if (!(CmHive
->Hive
.HiveFlags
& HIVE_VOLATILE
))
1087 /* It's now, open the hive file and log */
1088 Status
= CmpOpenHiveFiles(&FileName
,
1092 &PrimaryDisposition
,
1093 &SecondaryDisposition
,
1098 if (!(NT_SUCCESS(Status
)) || !(LogHandle
))
1100 /* Couldn't open the hive or its log file, raise a hard error */
1101 ErrorParameters
= &FileName
;
1102 NtRaiseHardError(STATUS_CANNOT_LOAD_REGISTRY_FILE
,
1105 (PULONG_PTR
)&ErrorParameters
,
1109 /* And bugcheck for posterity's sake */
1110 KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO
, 9, 0, i
, Status
);
1113 /* Save the file handles. This should remove our sync hacks */
1114 CmHive
->FileHandles
[HFILE_TYPE_LOG
] = LogHandle
;
1115 CmHive
->FileHandles
[HFILE_TYPE_PRIMARY
] = PrimaryHandle
;
1117 /* Allow lazy flushing since the handles are there -- remove sync hacks */
1118 //ASSERT(CmHive->Hive.HiveFlags & HIVE_NOLAZYFLUSH);
1119 CmHive
->Hive
.HiveFlags
&= ~HIVE_NOLAZYFLUSH
;
1121 /* Get the real size of the hive */
1122 Length
= CmHive
->Hive
.Storage
[Stable
].Length
+ HBLOCK_SIZE
;
1124 /* Check if the cluster size doesn't match */
1125 if (CmHive
->Hive
.Cluster
!= ClusterSize
) ASSERT(FALSE
);
1127 /* Set the file size */
1128 //if (!CmpFileSetSize((PHHIVE)CmHive, HFILE_TYPE_PRIMARY, Length, Length))
1130 /* This shouldn't fail */
1134 /* Another thing we don't support is NTLDR-recovery */
1135 if (CmHive
->Hive
.BaseBlock
->BootRecover
) ASSERT(FALSE
);
1137 /* Finally, set our allocated hive to the same hive we've had */
1138 CmpMachineHiveList
[i
].CmHive2
= CmHive
;
1139 ASSERT(CmpMachineHiveList
[i
].CmHive
== CmpMachineHiveList
[i
].CmHive2
);
1144 CmpMachineHiveList
[i
].ThreadFinished
= TRUE
;
1146 /* Check if we're the last worker */
1147 WorkerCount
= InterlockedIncrement(&CmpLoadWorkerIncrement
);
1148 if (WorkerCount
== CM_NUMBER_OF_MACHINE_HIVES
)
1150 /* Signal the event */
1151 KeSetEvent(&CmpLoadWorkerEvent
, 0, FALSE
);
1154 /* Kill the thread */
1155 PsTerminateSystemThread(Status
);
1160 CmpInitializeHiveList(IN USHORT Flag
)
1162 WCHAR FileBuffer
[MAX_PATH
], RegBuffer
[MAX_PATH
], ConfigPath
[MAX_PATH
];
1163 UNICODE_STRING TempName
, FileName
, RegName
;
1166 ULONG FileStart
, RegStart
, i
;
1167 PSECURITY_DESCRIPTOR SecurityDescriptor
;
1170 /* Allow writing for now */
1173 /* Build the file name and registry name strings */
1174 RtlInitEmptyUnicodeString(&FileName
, FileBuffer
, MAX_PATH
);
1175 RtlInitEmptyUnicodeString(&RegName
, RegBuffer
, MAX_PATH
);
1177 /* Now build the system root path */
1178 CmpGetRegistryPath(ConfigPath
);
1179 RtlInitUnicodeString(&TempName
, ConfigPath
);
1180 RtlAppendStringToString((PSTRING
)&FileName
, (PSTRING
)&TempName
);
1181 FileStart
= FileName
.Length
;
1183 /* And build the registry root path */
1184 RtlInitUnicodeString(&TempName
, L
"\\REGISTRY\\");
1185 RtlAppendStringToString((PSTRING
)&RegName
, (PSTRING
)&TempName
);
1186 RegStart
= RegName
.Length
;
1188 /* Setup the event to synchronize workers */
1189 KeInitializeEvent(&CmpLoadWorkerEvent
, SynchronizationEvent
, FALSE
);
1191 /* Enter special boot condition */
1192 CmpSpecialBootCondition
= TRUE
;
1194 /* Create the SD for the root hives */
1195 SecurityDescriptor
= CmpHiveRootSecurityDescriptor();
1197 /* Loop every hive we care about */
1198 for (i
= 0; i
< CM_NUMBER_OF_MACHINE_HIVES
; i
++)
1200 /* Make sure the list is setup */
1201 ASSERT(CmpMachineHiveList
[i
].Name
!= NULL
);
1203 /* Create a thread to handle this hive */
1204 Status
= PsCreateSystemThread(&Thread
,
1211 if (NT_SUCCESS(Status
))
1213 /* We don't care about the handle -- the thread self-terminates */
1218 /* Can't imagine this happening */
1219 KeBugCheckEx(BAD_SYSTEM_CONFIG_INFO
, 9, 3, i
, Status
);
1223 /* Make sure we've reached the end of the list */
1224 ASSERT(CmpMachineHiveList
[i
].Name
== NULL
);
1226 /* Wait for hive loading to finish */
1227 KeWaitForSingleObject(&CmpLoadWorkerEvent
,
1233 /* Exit the special boot condition and make sure all workers completed */
1234 CmpSpecialBootCondition
= FALSE
;
1235 ASSERT(CmpLoadWorkerIncrement
== CM_NUMBER_OF_MACHINE_HIVES
);
1237 /* Loop hives again */
1238 for (i
= 0; i
< CM_NUMBER_OF_MACHINE_HIVES
; i
++)
1240 /* Make sure the thread ran and finished */
1241 ASSERT(CmpMachineHiveList
[i
].ThreadFinished
== TRUE
);
1242 ASSERT(CmpMachineHiveList
[i
].ThreadStarted
== TRUE
);
1244 /* Check if this was a new hive */
1245 if (!CmpMachineHiveList
[i
].CmHive
)
1247 /* Make sure we allocated something */
1248 ASSERT(CmpMachineHiveList
[i
].CmHive2
!= NULL
);
1250 /* Build the base name */
1251 RegName
.Length
= RegStart
;
1252 RtlInitUnicodeString(&TempName
, CmpMachineHiveList
[i
].BaseName
);
1253 RtlAppendStringToString((PSTRING
)&RegName
, (PSTRING
)&TempName
);
1255 /* Check if this is a child of the root */
1256 if (RegName
.Buffer
[RegName
.Length
/ sizeof(WCHAR
) - 1] == '\\')
1258 /* Then setup the whole name */
1259 RtlInitUnicodeString(&TempName
, CmpMachineHiveList
[i
].Name
);
1260 RtlAppendStringToString((PSTRING
)&RegName
, (PSTRING
)&TempName
);
1263 /* Now link the hive to its master */
1264 Status
= CmpLinkHiveToMaster(&RegName
,
1266 CmpMachineHiveList
[i
].CmHive2
,
1267 CmpMachineHiveList
[i
].Allocate
,
1268 SecurityDescriptor
);
1269 if (Status
!= STATUS_SUCCESS
)
1271 /* Linking needs to work */
1272 KeBugCheckEx(CONFIG_LIST_FAILED
, 11, Status
, i
, (ULONG_PTR
)&RegName
);
1275 /* Check if we had to allocate a new hive */
1276 if (CmpMachineHiveList
[i
].Allocate
)
1278 /* Sync the new hive */
1279 //HvSyncHive((PHHIVE)(CmpMachineHiveList[i].CmHive2));
1283 /* Check if we created a new hive */
1284 if (CmpMachineHiveList
[i
].CmHive2
)
1286 /* TODO: Add to HiveList key */
1290 /* Get rid of the SD */
1291 ExFreePool(SecurityDescriptor
);
1293 /* FIXME: Link SECURITY to SAM */
1295 /* FIXME: Link S-1-5-18 to .Default */
1302 OBJECT_ATTRIBUTES ObjectAttributes
;
1303 UNICODE_STRING KeyName
;
1306 PCMHIVE HardwareHive
;
1307 PSECURITY_DESCRIPTOR SecurityDescriptor
;
1310 /* Check if this is PE-boot */
1311 if (InitIsWinPEMode
)
1313 /* Set registry to PE mode */
1314 CmpMiniNTBoot
= TRUE
;
1315 CmpShareSystemHives
= TRUE
;
1318 /* Initialize the hive list and lock */
1319 InitializeListHead(&CmpHiveListHead
);
1320 ExInitializePushLock((PVOID
)&CmpHiveListHeadLock
);
1321 ExInitializePushLock((PVOID
)&CmpLoadHiveLock
);
1323 /* Initialize registry lock */
1324 ExInitializeResourceLite(&CmpRegistryLock
);
1326 /* Initialize the cache */
1327 CmpInitializeCache();
1329 /* Initialize allocation and delayed dereferencing */
1330 CmpInitCmPrivateAlloc();
1331 CmpInitCmPrivateDelayAlloc();
1332 CmpInitDelayDerefKCBEngine();
1334 /* Initialize callbacks */
1337 /* Initialize self healing */
1338 KeInitializeGuardedMutex(&CmpSelfHealQueueLock
);
1339 InitializeListHead(&CmpSelfHealQueueListHead
);
1341 /* Save the current process and lock the registry */
1342 CmpSystemProcess
= PsGetCurrentProcess();
1344 /* Create the key object types */
1345 Status
= CmpCreateObjectTypes();
1346 if (!NT_SUCCESS(Status
))
1349 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED
, 1, 1, Status
, 0);
1352 /* Build the master hive */
1353 Status
= CmpInitializeHive((PCMHIVE
*)&CmiVolatileHive
,
1363 if (!NT_SUCCESS(Status
))
1366 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED
, 1, 2, Status
, 0);
1369 /* Create the \REGISTRY key node */
1370 if (!CmpCreateRegistryRoot())
1373 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED
, 1, 3, 0, 0);
1376 /* Create the default security descriptor */
1377 SecurityDescriptor
= CmpHiveRootSecurityDescriptor();
1379 /* Create '\Registry\Machine' key. */
1380 RtlInitUnicodeString(&KeyName
, L
"\\REGISTRY\\MACHINE");
1381 InitializeObjectAttributes(&ObjectAttributes
,
1383 OBJ_CASE_INSENSITIVE
,
1385 SecurityDescriptor
);
1386 Status
= NtCreateKey(&KeyHandle
,
1387 KEY_READ
| KEY_WRITE
,
1393 if (!NT_SUCCESS(Status
))
1396 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED
, 1, 5, Status
, 0);
1399 /* Close the handle */
1402 /* Create '\Registry\User' key. */
1403 RtlInitUnicodeString(&KeyName
, L
"\\REGISTRY\\USER");
1404 InitializeObjectAttributes(&ObjectAttributes
,
1406 OBJ_CASE_INSENSITIVE
,
1408 SecurityDescriptor
);
1409 Status
= NtCreateKey(&KeyHandle
,
1410 KEY_READ
| KEY_WRITE
,
1416 if (!NT_SUCCESS(Status
))
1419 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED
, 1, 6, Status
, 0);
1422 /* Close the handle */
1425 /* Initialize the system hive */
1426 if (!CmpInitializeSystemHive(KeLoaderBlock
))
1429 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED
, 1, 7, 0, 0);
1432 /* Create the 'CurrentControlSet' link. */
1433 Status
= CmpCreateControlSet(KeLoaderBlock
);
1434 if (!NT_SUCCESS(Status
))
1437 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED
, 1, 8, Status
, 0);
1440 /* Create the hardware hive */
1441 Status
= CmpInitializeHive((PCMHIVE
*)&HardwareHive
,
1451 if (!NT_SUCCESS(Status
))
1454 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED
, 1, 11, Status
, 0);
1457 /* Add the hive to the hive list */
1458 CmpMachineHiveList
[0].CmHive
= (PCMHIVE
)HardwareHive
;
1460 /* Attach it to the machine key */
1461 RtlInitUnicodeString(&KeyName
, L
"\\Registry\\Machine\\HARDWARE");
1462 Status
= CmpLinkHiveToMaster(&KeyName
,
1464 (PCMHIVE
)HardwareHive
,
1466 SecurityDescriptor
);
1467 if (!NT_SUCCESS(Status
))
1470 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED
, 1, 12, Status
, 0);
1473 /* FIXME: Add to HiveList key */
1475 /* Free the security descriptor */
1476 ExFreePool(SecurityDescriptor
);
1478 /* Fill out the Hardware key with the ARC Data from the Loader */
1479 Status
= CmpInitializeHardwareConfiguration(KeLoaderBlock
);
1480 if (!NT_SUCCESS(Status
))
1483 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED
, 1, 13, Status
, 0);
1486 /* Initialize machine-dependent information into the registry */
1487 Status
= CmpInitializeMachineDependentConfiguration(KeLoaderBlock
);
1488 if (!NT_SUCCESS(Status
))
1491 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED
, 1, 14, Status
, 0);
1494 /* Initialize volatile registry settings */
1495 Status
= CmpSetSystemValues(KeLoaderBlock
);
1496 if (!NT_SUCCESS(Status
))
1499 KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED
, 1, 15, Status
, 0);
1502 /* Free the load options */
1503 ExFreePool(CmpLoadOptions
.Buffer
);
1505 /* If we got here, all went well */
1511 CmpLockRegistryExclusive(VOID
)
1513 /* Enter a critical region and lock the registry */
1514 KeEnterCriticalRegion();
1515 ExAcquireResourceExclusiveLite(&CmpRegistryLock
, TRUE
);
1518 ASSERT(CmpFlushStarveWriters
== 0);
1519 RtlGetCallersAddress(&CmpRegistryLockCaller
, &CmpRegistryLockCallerCaller
);
1524 CmpLockRegistry(VOID
)
1526 /* Enter a critical region */
1527 KeEnterCriticalRegion();
1529 /* Check if we have to starve writers */
1530 if (CmpFlushStarveWriters
)
1532 /* Starve exlusive waiters */
1533 ExAcquireSharedStarveExclusive(&CmpRegistryLock
, TRUE
);
1537 /* Just grab the lock */
1538 ExAcquireResourceSharedLite(&CmpRegistryLock
, TRUE
);
1544 CmpTestRegistryLock(VOID
)
1547 return !ExIsResourceAcquiredSharedLite(&CmpRegistryLock
) ? FALSE
: TRUE
;
1552 CmpTestRegistryLockExclusive(VOID
)
1555 return !ExIsResourceAcquiredExclusiveLite(&CmpRegistryLock
) ? FALSE
: TRUE
;
1560 CmpUnlockRegistry(VOID
)
1563 CMP_ASSERT_REGISTRY_LOCK();
1565 /* Check if we should flush the registry */
1566 if (CmpFlushOnLockRelease
)
1568 /* The registry should be exclusively locked for this */
1569 CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK();
1571 /* Flush the registry */
1572 CmpDoFlushAll(TRUE
);
1573 CmpFlushOnLockRelease
= FALSE
;
1576 /* Release the lock and leave the critical region */
1577 ExReleaseResourceLite(&CmpRegistryLock
);
1578 KeLeaveCriticalRegion();
1583 CmpAcquireTwoKcbLocksExclusiveByKey(IN ULONG ConvKey1
,
1586 ULONG Index1
, Index2
;
1589 CMP_ASSERT_REGISTRY_LOCK();
1591 /* Get hash indexes */
1592 Index1
= GET_HASH_INDEX(ConvKey1
);
1593 Index2
= GET_HASH_INDEX(ConvKey2
);
1595 /* See which one is highest */
1596 if (Index1
< Index2
)
1598 /* Grab them in the proper order */
1599 CmpAcquireKcbLockExclusiveByKey(ConvKey1
);
1600 CmpAcquireKcbLockExclusiveByKey(ConvKey2
);
1604 /* Grab the second one first, then the first */
1605 CmpAcquireKcbLockExclusiveByKey(ConvKey2
);
1606 if (Index1
!= Index2
) CmpAcquireKcbLockExclusiveByKey(ConvKey1
);
1612 CmpReleaseTwoKcbLockByKey(IN ULONG ConvKey1
,
1615 ULONG Index1
, Index2
;
1618 CMP_ASSERT_REGISTRY_LOCK();
1620 /* Get hash indexes */
1621 Index1
= GET_HASH_INDEX(ConvKey1
);
1622 Index2
= GET_HASH_INDEX(ConvKey2
);
1623 ASSERT((GET_HASH_ENTRY(CmpCacheTable
, ConvKey2
).Owner
== KeGetCurrentThread()) ||
1624 (CmpTestRegistryLockExclusive()));
1626 /* See which one is highest */
1627 if (Index1
< Index2
)
1629 /* Grab them in the proper order */
1630 ASSERT((GET_HASH_ENTRY(CmpCacheTable
, ConvKey1
).Owner
== KeGetCurrentThread()) ||
1631 (CmpTestRegistryLockExclusive()));
1632 CmpReleaseKcbLockByKey(ConvKey2
);
1633 CmpReleaseKcbLockByKey(ConvKey1
);
1637 /* Release the first one first, then the second */
1638 if (Index1
!= Index2
)
1640 ASSERT((GET_HASH_ENTRY(CmpCacheTable
, ConvKey1
).Owner
== KeGetCurrentThread()) ||
1641 (CmpTestRegistryLockExclusive()));
1642 CmpReleaseKcbLockByKey(ConvKey1
);
1644 CmpReleaseKcbLockByKey(ConvKey2
);
1650 CmShutdownSystem(VOID
)
1652 /* Kill the workers and flush all hives */
1653 if (!CmFirstTime
) CmpShutdownWorkers();
1654 CmpDoFlushAll(TRUE
);