1 /* $Id: registry.c,v 1.92 2003/04/12 15:09:57 ekohl Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/cm/registry.c
6 * PURPOSE: Registry functions
7 * PROGRAMMERS: Rex Jolliff
14 #include <ddk/ntddk.h>
18 #include <internal/pool.h>
19 #include <internal/registry.h>
20 #include <reactos/bugcodes.h>
23 #include <internal/debug.h>
27 /* GLOBALS ******************************************************************/
29 POBJECT_TYPE CmiKeyType
= NULL
;
30 PREGISTRY_HIVE CmiVolatileHive
= NULL
;
31 KSPIN_LOCK CmiKeyListLock
;
33 LIST_ENTRY CmiHiveListHead
;
34 ERESOURCE CmiHiveListLock
;
36 volatile BOOLEAN CmiHiveSyncEnabled
= FALSE
;
37 volatile BOOLEAN CmiHiveSyncPending
= FALSE
;
39 KTIMER CmiHiveSyncTimer
;
41 static GENERIC_MAPPING CmiKeyMapping
=
42 {KEY_READ
, KEY_WRITE
, KEY_EXECUTE
, KEY_ALL_ACCESS
};
47 CmiCheckKey(BOOLEAN Verbose
,
51 CmiCreateCurrentControlSetLink(VOID
);
54 CmiHiveSyncDpcRoutine(PKDPC Dpc
,
55 PVOID DeferredContext
,
56 PVOID SystemArgument1
,
57 PVOID SystemArgument2
);
59 /* FUNCTIONS ****************************************************************/
62 CmiCheckSubKeys(BOOLEAN Verbose
,
65 OBJECT_ATTRIBUTES ObjectAttributes
;
66 PKEY_NODE_INFORMATION KeyInfo
;
67 WCHAR KeyBuffer
[MAX_PATH
];
68 UNICODE_STRING KeyPath
;
79 BufferSize
= sizeof(KEY_NODE_INFORMATION
) + 4096;
80 KeyInfo
= ExAllocatePool(PagedPool
, BufferSize
);
82 Status
= NtEnumerateKey(Key
,
88 if (!NT_SUCCESS(Status
))
91 if (Status
== STATUS_NO_MORE_ENTRIES
)
92 Status
= STATUS_SUCCESS
;
98 KeyInfo
->NameLength
/ sizeof(WCHAR
));
102 DbgPrint("Key: %S\n", Name
);
105 /* FIXME: Check info. */
109 wcscpy(KeyBuffer
, L
"\\Registry\\");
110 wcscat(KeyBuffer
, Name
);
112 RtlInitUnicodeString(&KeyPath
, KeyBuffer
);
114 InitializeObjectAttributes(&ObjectAttributes
,
116 OBJ_CASE_INSENSITIVE
,
120 Status
= NtOpenKey(&SubKey
,
124 assert(NT_SUCCESS(Status
));
126 CmiCheckKey(Verbose
, SubKey
);
133 assert(NT_SUCCESS(Status
));
138 CmiCheckValues(BOOLEAN Verbose
,
141 PKEY_NODE_INFORMATION ValueInfo
;
142 WCHAR Name
[MAX_PATH
];
151 BufferSize
= sizeof(KEY_NODE_INFORMATION
) + 4096;
152 ValueInfo
= ExAllocatePool(PagedPool
, BufferSize
);
154 Status
= NtEnumerateValueKey(Key
,
160 if (!NT_SUCCESS(Status
))
162 ExFreePool(ValueInfo
);
163 if (Status
== STATUS_NO_MORE_ENTRIES
)
164 Status
= STATUS_SUCCESS
;
170 ValueInfo
->NameLength
/ sizeof(WCHAR
));
174 DbgPrint("Value: %S\n", Name
);
177 /* FIXME: Check info. */
179 ExFreePool(ValueInfo
);
184 assert(NT_SUCCESS(Status
));
189 CmiCheckKey(BOOLEAN Verbose
,
192 CmiCheckValues(Verbose
, Key
);
193 CmiCheckSubKeys(Verbose
, Key
);
198 CmiCheckByName(BOOLEAN Verbose
,
201 OBJECT_ATTRIBUTES ObjectAttributes
;
202 WCHAR KeyPathBuffer
[MAX_PATH
];
203 UNICODE_STRING KeyPath
;
207 wcscpy(KeyPathBuffer
, L
"\\Registry\\");
208 wcscat(KeyPathBuffer
, KeyName
);
210 RtlInitUnicodeString(&KeyPath
, KeyPathBuffer
);
212 InitializeObjectAttributes(&ObjectAttributes
,
214 OBJ_CASE_INSENSITIVE
,
218 Status
= NtOpenKey(&Key
,
224 if (!NT_SUCCESS(Status
))
226 DbgPrint("KeyPath %wZ Status: %.08x", KeyPath
, Status
);
227 DbgPrint("KeyPath %S Status: %.08x", KeyPath
.Buffer
, Status
);
228 assert(NT_SUCCESS(Status
));
232 CmiCheckKey(Verbose
, Key
);
239 CmiCheckRegistry(BOOLEAN Verbose
)
242 DbgPrint("Checking registry internals\n");
244 CmiCheckByName(Verbose
, L
"Machine");
245 CmiCheckByName(Verbose
, L
"User");
250 CmInitializeRegistry(VOID
)
252 OBJECT_ATTRIBUTES ObjectAttributes
;
253 UNICODE_STRING RootKeyName
;
255 PKEY_OBJECT MachineKey
;
257 HANDLE RootKeyHandle
;
261 /* FIXME: remove the hardware keys before the hardware hive is imported */
262 PKEY_OBJECT HardwareKey
;
266 /* Initialize the Key object type */
267 CmiKeyType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
269 CmiKeyType
->TotalObjects
= 0;
270 CmiKeyType
->TotalHandles
= 0;
271 CmiKeyType
->MaxObjects
= LONG_MAX
;
272 CmiKeyType
->MaxHandles
= LONG_MAX
;
273 CmiKeyType
->PagedPoolCharge
= 0;
274 CmiKeyType
->NonpagedPoolCharge
= sizeof(KEY_OBJECT
);
275 CmiKeyType
->Mapping
= &CmiKeyMapping
;
276 CmiKeyType
->Dump
= NULL
;
277 CmiKeyType
->Open
= NULL
;
278 CmiKeyType
->Close
= NULL
;
279 CmiKeyType
->Delete
= CmiObjectDelete
;
280 CmiKeyType
->Parse
= CmiObjectParse
;
281 CmiKeyType
->Security
= CmiObjectSecurity
;
282 CmiKeyType
->QueryName
= NULL
;
283 CmiKeyType
->OkayToClose
= NULL
;
284 CmiKeyType
->Create
= CmiObjectCreate
;
285 CmiKeyType
->DuplicationNotify
= NULL
;
286 RtlInitUnicodeString(&CmiKeyType
->TypeName
, L
"Key");
288 /* Initialize the hive list */
289 InitializeListHead(&CmiHiveListHead
);
290 ExInitializeResourceLite(&CmiHiveListLock
);
292 /* Build volatile registry store */
293 Status
= CmiCreateRegistryHive(NULL
, &CmiVolatileHive
, FALSE
);
294 assert(NT_SUCCESS(Status
));
296 /* Create '\Registry' key. */
297 RtlInitUnicodeString(&RootKeyName
, REG_ROOT_KEY_NAME
);
298 InitializeObjectAttributes(&ObjectAttributes
, &RootKeyName
, 0, NULL
, NULL
);
299 Status
= ObCreateObject(&RootKeyHandle
,
300 STANDARD_RIGHTS_REQUIRED
,
304 assert(NT_SUCCESS(Status
));
305 Status
= ObReferenceObjectByHandle(RootKeyHandle
,
306 STANDARD_RIGHTS_REQUIRED
,
311 assert(NT_SUCCESS(Status
));
312 RootKey
->RegistryHive
= CmiVolatileHive
;
313 RootKey
->BlockOffset
= CmiVolatileHive
->HiveHeader
->RootKeyCell
;
314 RootKey
->KeyCell
= CmiGetBlock(CmiVolatileHive
, RootKey
->BlockOffset
, NULL
);
316 RootKey
->NumberOfSubKeys
= 0;
317 RootKey
->SubKeys
= NULL
;
318 RootKey
->SizeOfSubKeys
= 0;
319 RootKey
->NameSize
= strlen("Registry");
320 RootKey
->Name
= ExAllocatePool(PagedPool
, RootKey
->NameSize
);
321 RtlCopyMemory(RootKey
->Name
, "Registry", RootKey
->NameSize
);
323 KeInitializeSpinLock(&CmiKeyListLock
);
325 /* Create '\Registry\Machine' key. */
326 Status
= ObCreateObject(&KeyHandle
,
327 STANDARD_RIGHTS_REQUIRED
,
330 (PVOID
*)&MachineKey
);
331 assert(NT_SUCCESS(Status
));
332 Status
= CmiAddSubKey(CmiVolatileHive
,
336 wcslen(L
"Machine") * sizeof(WCHAR
),
340 assert(NT_SUCCESS(Status
));
341 MachineKey
->RegistryHive
= CmiVolatileHive
;
342 MachineKey
->Flags
= 0;
343 MachineKey
->NumberOfSubKeys
= 0;
344 MachineKey
->SubKeys
= NULL
;
345 MachineKey
->SizeOfSubKeys
= MachineKey
->KeyCell
->NumberOfSubKeys
;
346 MachineKey
->NameSize
= strlen("Machine");
347 MachineKey
->Name
= ExAllocatePool(PagedPool
, MachineKey
->NameSize
);
348 RtlCopyMemory(MachineKey
->Name
, "Machine", MachineKey
->NameSize
);
349 CmiAddKeyToList(RootKey
, MachineKey
);
351 /* Create '\Registry\User' key. */
352 Status
= ObCreateObject(&KeyHandle
,
353 STANDARD_RIGHTS_REQUIRED
,
357 assert(NT_SUCCESS(Status
));
358 Status
= CmiAddSubKey(CmiVolatileHive
,
362 wcslen(L
"User") * sizeof(WCHAR
),
366 assert(NT_SUCCESS(Status
));
367 UserKey
->RegistryHive
= CmiVolatileHive
;
369 UserKey
->NumberOfSubKeys
= 0;
370 UserKey
->SubKeys
= NULL
;
371 UserKey
->SizeOfSubKeys
= UserKey
->KeyCell
->NumberOfSubKeys
;
372 UserKey
->NameSize
= strlen("User");
373 UserKey
->Name
= ExAllocatePool(PagedPool
, UserKey
->NameSize
);
374 RtlCopyMemory(UserKey
->Name
, "User", UserKey
->NameSize
);
375 CmiAddKeyToList(RootKey
, UserKey
);
378 /* FIXME: remove the hardware keys before the hardware hive is imported */
380 /* Create '\Registry\Machine\HARDWARE' key. */
381 Status
= ObCreateObject(&KeyHandle
,
382 STANDARD_RIGHTS_REQUIRED
,
385 (PVOID
*)&HardwareKey
);
386 assert(NT_SUCCESS(Status
));
387 Status
= CmiAddSubKey(CmiVolatileHive
,
391 wcslen(L
"HARDWARE") * sizeof(WCHAR
),
395 assert(NT_SUCCESS(Status
));
396 HardwareKey
->RegistryHive
= CmiVolatileHive
;
397 HardwareKey
->Flags
= 0;
398 HardwareKey
->NumberOfSubKeys
= 0;
399 HardwareKey
->SubKeys
= NULL
;
400 HardwareKey
->SizeOfSubKeys
= HardwareKey
->KeyCell
->NumberOfSubKeys
;
401 HardwareKey
->NameSize
= strlen("HARDWARE");
402 HardwareKey
->Name
= ExAllocatePool(PagedPool
, strlen("HARDWARE"));
403 RtlCopyMemory(HardwareKey
->Name
, "HARDWARE", HardwareKey
->NameSize
);
404 CmiAddKeyToList(MachineKey
, HardwareKey
);
406 /* Create '\Registry\Machine\HARDWARE\DESCRIPTION' key. */
407 Status
= ObCreateObject(&KeyHandle
,
408 STANDARD_RIGHTS_REQUIRED
,
412 assert(NT_SUCCESS(Status
));
413 Status
= CmiAddSubKey(CmiVolatileHive
,
417 wcslen(L
"DESCRIPTION") * sizeof(WCHAR
),
421 assert(NT_SUCCESS(Status
));
422 NewKey
->RegistryHive
= CmiVolatileHive
;
424 NewKey
->NumberOfSubKeys
= 0;
425 NewKey
->SubKeys
= NULL
;
426 NewKey
->SizeOfSubKeys
= NewKey
->KeyCell
->NumberOfSubKeys
;
427 NewKey
->NameSize
= strlen("DESCRIPTION");
428 NewKey
->Name
= ExAllocatePool(PagedPool
, NewKey
->NameSize
);
429 RtlCopyMemory(NewKey
->Name
, "DESCRIPTION", NewKey
->NameSize
);
430 CmiAddKeyToList(HardwareKey
, NewKey
);
432 /* Create '\Registry\Machine\HARDWARE\DEVICEMAP' key. */
433 Status
= ObCreateObject(&KeyHandle
,
434 STANDARD_RIGHTS_REQUIRED
,
438 assert(NT_SUCCESS(Status
));
439 Status
= CmiAddSubKey(CmiVolatileHive
,
443 wcslen(L
"DEVICEMAP") * sizeof(WCHAR
),
447 assert(NT_SUCCESS(Status
));
448 NewKey
->RegistryHive
= CmiVolatileHive
;
450 NewKey
->NumberOfSubKeys
= 0;
451 NewKey
->SubKeys
= NULL
;
452 NewKey
->SizeOfSubKeys
= NewKey
->KeyCell
->NumberOfSubKeys
;
453 NewKey
->NameSize
= strlen("DEVICEMAP");
454 NewKey
->Name
= ExAllocatePool(PagedPool
, NewKey
->NameSize
);
455 RtlCopyMemory(NewKey
->Name
, "DEVICEMAP", NewKey
->NameSize
);
456 CmiAddKeyToList(HardwareKey
,NewKey
);
458 /* Create '\Registry\Machine\HARDWARE\RESOURCEMAP' key. */
459 Status
= ObCreateObject(&KeyHandle
,
460 STANDARD_RIGHTS_REQUIRED
,
464 assert(NT_SUCCESS(Status
));
465 Status
= CmiAddSubKey(CmiVolatileHive
,
469 wcslen(L
"RESOURCEMAP") * sizeof(WCHAR
),
473 assert(NT_SUCCESS(Status
));
474 NewKey
->RegistryHive
= CmiVolatileHive
;
476 NewKey
->NumberOfSubKeys
= 0;
477 NewKey
->SubKeys
= NULL
;
478 NewKey
->SizeOfSubKeys
= NewKey
->KeyCell
->NumberOfSubKeys
;
479 NewKey
->NameSize
= strlen("RESOURCEMAP");
480 NewKey
->Name
= ExAllocatePool(PagedPool
, NewKey
->NameSize
);
481 RtlCopyMemory(NewKey
->Name
, "RESOURCEMAP", NewKey
->NameSize
);
482 CmiAddKeyToList(HardwareKey
, NewKey
);
487 CmInit2(PCHAR CommandLine
)
493 /* FIXME: Store system start options */
497 /* Create the 'CurrentControlSet' link. */
498 Status
= CmiCreateCurrentControlSetLink();
499 if (!NT_SUCCESS(Status
))
501 KeBugCheck(CONFIG_INITIALIZATION_FAILED
);
504 /* Set PICE 'Start' value to 1, if PICE debugging is enabled */
506 p1
= (PCHAR
)CommandLine
;
507 while (p1
&& (p2
= strchr(p1
, '/')))
510 if (_strnicmp(p2
, "DEBUGPORT", 9) == 0)
516 if (_strnicmp(p2
, "PICE", 4) == 0)
526 Status
= RtlWriteRegistryValue(RTL_REGISTRY_SERVICES
,
532 if (!NT_SUCCESS(Status
))
534 KeBugCheck(CONFIG_INITIALIZATION_FAILED
);
540 CmiCreateCurrentControlSetLink(VOID
)
542 RTL_QUERY_REGISTRY_TABLE QueryTable
[5];
543 WCHAR TargetNameBuffer
[80];
544 ULONG TargetNameLength
;
545 UNICODE_STRING LinkName
;
546 UNICODE_STRING LinkValue
;
552 OBJECT_ATTRIBUTES ObjectAttributes
;
555 DPRINT("CmiCreateCurrentControlSetLink() called\n");
557 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
559 QueryTable
[0].Name
= L
"Current";
560 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
561 QueryTable
[0].EntryContext
= &CurrentSet
;
563 QueryTable
[1].Name
= L
"Default";
564 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
565 QueryTable
[1].EntryContext
= &DefaultSet
;
567 QueryTable
[2].Name
= L
"Failed";
568 QueryTable
[2].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
569 QueryTable
[2].EntryContext
= &Failed
;
571 QueryTable
[3].Name
= L
"LastKnownGood";
572 QueryTable
[3].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
573 QueryTable
[3].EntryContext
= &LastKnownGood
;
575 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
576 L
"\\Registry\\Machine\\SYSTEM\\Select",
580 if (!NT_SUCCESS(Status
))
585 DPRINT("Current %ld Default %ld\n", CurrentSet
, DefaultSet
);
587 swprintf(TargetNameBuffer
,
588 L
"\\Registry\\Machine\\SYSTEM\\ControlSet%03lu",
590 TargetNameLength
= wcslen(TargetNameBuffer
) * sizeof(WCHAR
);
592 DPRINT("Link target '%S'\n", TargetNameBuffer
);
594 RtlInitUnicodeStringFromLiteral(&LinkName
,
595 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
596 InitializeObjectAttributes(&ObjectAttributes
,
598 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_OPENLINK
,
601 Status
= NtCreateKey(&KeyHandle
,
602 KEY_ALL_ACCESS
| KEY_CREATE_LINK
,
606 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
608 if (!NT_SUCCESS(Status
))
610 DPRINT1("NtCreateKey() failed (Status %lx)\n", Status
);
614 RtlInitUnicodeStringFromLiteral(&LinkValue
,
615 L
"SymbolicLinkValue");
616 Status
= NtSetValueKey(KeyHandle
,
620 (PVOID
)TargetNameBuffer
,
622 if (!NT_SUCCESS(Status
))
624 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
634 CmiConnectHive(PREGISTRY_HIVE RegistryHive
,
635 PUNICODE_STRING KeyName
)
637 OBJECT_ATTRIBUTES ObjectAttributes
;
638 UNICODE_STRING ParentKeyName
;
639 PKEY_OBJECT ParentKey
;
645 DPRINT("CmiConnectHive(%p, %wZ) called.\n",
646 RegistryHive
, KeyName
);
648 SubName
= wcsrchr (KeyName
->Buffer
, L
'\\');
651 return STATUS_UNSUCCESSFUL
;
654 ParentKeyName
.Length
= (USHORT
)(SubName
- KeyName
->Buffer
) * sizeof(WCHAR
);
655 ParentKeyName
.MaximumLength
= ParentKeyName
.Length
+ sizeof(WCHAR
);
656 ParentKeyName
.Buffer
= ExAllocatePool (NonPagedPool
,
657 ParentKeyName
.MaximumLength
);
658 RtlCopyMemory (ParentKeyName
.Buffer
,
660 ParentKeyName
.Length
);
661 ParentKeyName
.Buffer
[ParentKeyName
.Length
/ sizeof(WCHAR
)] = 0;
664 Status
= ObReferenceObjectByName (&ParentKeyName
,
665 OBJ_CASE_INSENSITIVE
,
667 STANDARD_RIGHTS_REQUIRED
,
672 RtlFreeUnicodeString (&ParentKeyName
);
673 if (!NT_SUCCESS(Status
))
675 DPRINT1 ("ObReferenceObjectByName() failed (Status %lx)\n", Status
);
679 InitializeObjectAttributes(&ObjectAttributes
,
685 Status
= ObCreateObject(&KeyHandle
,
686 STANDARD_RIGHTS_REQUIRED
,
690 if (!NT_SUCCESS(Status
))
692 DPRINT1 ("ObCreateObject() failed (Status %lx)\n", Status
);
693 ObDereferenceObject (ParentKey
);
697 NewKey
->RegistryHive
= RegistryHive
;
698 NewKey
->BlockOffset
= RegistryHive
->HiveHeader
->RootKeyCell
;
699 NewKey
->KeyCell
= CmiGetBlock(RegistryHive
, NewKey
->BlockOffset
, NULL
);
701 NewKey
->NumberOfSubKeys
= 0;
702 NewKey
->SubKeys
= ExAllocatePool(PagedPool
,
703 NewKey
->KeyCell
->NumberOfSubKeys
* sizeof(ULONG
));
705 if ((NewKey
->SubKeys
== NULL
) && (NewKey
->KeyCell
->NumberOfSubKeys
!= 0))
707 DPRINT("NumberOfSubKeys %d\n", NewKey
->KeyCell
->NumberOfSubKeys
);
709 ObDereferenceObject (ParentKey
);
710 return(STATUS_INSUFFICIENT_RESOURCES
);
713 NewKey
->SizeOfSubKeys
= NewKey
->KeyCell
->NumberOfSubKeys
;
714 NewKey
->NameSize
= wcslen (SubName
);
715 NewKey
->Name
= ExAllocatePool(PagedPool
, NewKey
->NameSize
);
717 if ((NewKey
->Name
== NULL
) && (NewKey
->NameSize
!= 0))
719 DPRINT("NewKey->NameSize %d\n", NewKey
->NameSize
);
720 if (NewKey
->SubKeys
!= NULL
)
721 ExFreePool(NewKey
->SubKeys
);
723 ObDereferenceObject (ParentKey
);
724 return(STATUS_INSUFFICIENT_RESOURCES
);
727 wcstombs (NewKey
->Name
,
731 CmiAddKeyToList (ParentKey
, NewKey
);
732 ObDereferenceObject (ParentKey
);
734 VERIFY_KEY_OBJECT(NewKey
);
736 return(STATUS_SUCCESS
);
741 CmiInitializeSystemHive (PWSTR FileName
,
742 PUNICODE_STRING KeyName
)
744 OBJECT_ATTRIBUTES ObjectAttributes
;
745 UNICODE_STRING ControlSetKeyName
;
746 UNICODE_STRING ControlSetLinkName
;
747 UNICODE_STRING ControlSetValueName
;
750 PREGISTRY_HIVE RegistryHive
;
752 Status
= CmiCreateRegistryHive (FileName
,
755 if (!NT_SUCCESS(Status
))
757 DPRINT1 ("CmiCreateRegistryHive() failed (Status %lx)\n", Status
);
761 Status
= CmiConnectHive (RegistryHive
,
763 if (!NT_SUCCESS(Status
))
765 DPRINT1 ("CmiConnectHive() failed (Status %lx)\n", Status
);
766 CmiRemoveRegistryHive (RegistryHive
);
770 /* Create 'ControlSet001' key */
771 RtlInitUnicodeStringFromLiteral (&ControlSetKeyName
,
772 L
"\\Registry\\Machine\\SYSTEM\\ControlSet001");
773 InitializeObjectAttributes (&ObjectAttributes
,
775 OBJ_CASE_INSENSITIVE
,
778 Status
= NtCreateKey (&KeyHandle
,
783 REG_OPTION_NON_VOLATILE
,
785 if (!NT_SUCCESS(Status
))
787 DPRINT1 ("NtCreateKey() failed (Status %lx)\n", Status
);
792 /* Link 'CurrentControlSet' to 'ControlSet001' key */
793 RtlInitUnicodeStringFromLiteral (&ControlSetLinkName
,
794 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
795 InitializeObjectAttributes (&ObjectAttributes
,
797 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_OPENLINK
,
800 Status
= NtCreateKey (&KeyHandle
,
801 KEY_ALL_ACCESS
| KEY_CREATE_LINK
,
805 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
807 if (!NT_SUCCESS(Status
))
809 DPRINT1 ("NtCreateKey() failed (Status %lx)\n", Status
);
813 RtlInitUnicodeStringFromLiteral (&ControlSetValueName
,
814 L
"SymbolicLinkValue");
815 Status
= NtSetValueKey (KeyHandle
,
816 &ControlSetValueName
,
819 (PVOID
)ControlSetKeyName
.Buffer
,
820 ControlSetKeyName
.Length
);
821 if (!NT_SUCCESS(Status
))
823 DPRINT1 ("NtSetValueKey() failed (Status %lx)\n", Status
);
827 return STATUS_SUCCESS
;
832 CmiInitializeHive(PWSTR FileName
,
833 PUNICODE_STRING KeyName
,
836 PREGISTRY_HIVE RegistryHive
;
839 DPRINT("CmiInitializeHive(%s) called\n", KeyName
);
841 Status
= CmiCreateRegistryHive(FileName
,
844 if (!NT_SUCCESS(Status
))
846 DPRINT1("CmiCreateRegistryHive() failed (Status %lx)\n", Status
);
848 /* FIXME: Try to load the backup hive */
854 /* Connect the hive */
855 Status
= CmiConnectHive(RegistryHive
,
857 if (!NT_SUCCESS(Status
))
859 DPRINT1("CmiConnectHive() failed (Status %lx)\n", Status
);
860 CmiRemoveRegistryHive(RegistryHive
);
864 DPRINT("CmiInitializeHive() done\n");
866 return(STATUS_SUCCESS
);
871 CmiInitHives(BOOLEAN SetupBoot
)
873 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
874 OBJECT_ATTRIBUTES ObjectAttributes
;
875 UNICODE_STRING KeyName
;
876 UNICODE_STRING ValueName
;
881 WCHAR ConfigPath
[MAX_PATH
];
888 DPRINT("CmiInitHives() called\n");
890 if (SetupBoot
== TRUE
)
892 RtlInitUnicodeStringFromLiteral(&KeyName
,
893 L
"\\Registry\\Machine\\HARDWARE");
894 InitializeObjectAttributes(&ObjectAttributes
,
896 OBJ_CASE_INSENSITIVE
,
899 Status
= NtOpenKey(&KeyHandle
,
902 if (!NT_SUCCESS(Status
))
904 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status
);
908 RtlInitUnicodeStringFromLiteral(&ValueName
,
911 BufferSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 4096;
912 ValueInfo
= ExAllocatePool(PagedPool
,
914 if (ValueInfo
== NULL
)
917 return(STATUS_INSUFFICIENT_RESOURCES
);
920 Status
= NtQueryValueKey(KeyHandle
,
922 KeyValuePartialInformation
,
927 if (ValueInfo
== NULL
)
929 ExFreePool(ValueInfo
);
933 RtlCopyMemory(ConfigPath
,
935 ValueInfo
->DataLength
);
936 ConfigPath
[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = (WCHAR
)0;
937 ExFreePool(ValueInfo
);
941 wcscpy(ConfigPath
, L
"\\SystemRoot");
943 wcscat(ConfigPath
, L
"\\system32\\config");
945 DPRINT("ConfigPath: %S\n", ConfigPath
);
947 EndPtr
= ConfigPath
+ wcslen(ConfigPath
);
951 /* FIXME: Save boot log */
953 /* Connect the SYSTEM hive only if it has been created */
954 if (SetupBoot
== TRUE
)
956 wcscpy(EndPtr
, REG_SYSTEM_FILE_NAME
);
957 DPRINT ("ConfigPath: %S\n", ConfigPath
);
959 RtlInitUnicodeString (&KeyName
,
960 REG_SYSTEM_KEY_NAME
);
961 Status
= CmiInitializeSystemHive (ConfigPath
,
963 if (!NT_SUCCESS(Status
))
965 DPRINT1("CmiInitializeSystemHive() failed (Status %lx)\n", Status
);
970 /* Connect the SOFTWARE hive */
971 wcscpy(EndPtr
, REG_SOFTWARE_FILE_NAME
);
972 DPRINT ("ConfigPath: %S\n", ConfigPath
);
974 RtlInitUnicodeString (&KeyName
,
975 REG_SOFTWARE_KEY_NAME
);
976 Status
= CmiInitializeHive(ConfigPath
,
979 if (!NT_SUCCESS(Status
))
981 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
985 /* Connect the SAM hive */
986 wcscpy(EndPtr
, REG_SAM_FILE_NAME
);
987 DPRINT ("ConfigPath: %S\n", ConfigPath
);
989 RtlInitUnicodeString (&KeyName
,
991 Status
= CmiInitializeHive(ConfigPath
,
994 if (!NT_SUCCESS(Status
))
996 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
1000 /* Connect the SECURITY hive */
1001 wcscpy(EndPtr
, REG_SEC_FILE_NAME
);
1002 DPRINT ("ConfigPath: %S\n", ConfigPath
);
1004 RtlInitUnicodeString (&KeyName
,
1006 Status
= CmiInitializeHive(ConfigPath
,
1009 if (!NT_SUCCESS(Status
))
1011 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
1015 /* Connect the DEFAULT hive */
1016 wcscpy(EndPtr
, REG_USER_FILE_NAME
);
1017 DPRINT ("ConfigPath: %S\n", ConfigPath
);
1019 RtlInitUnicodeString (&KeyName
,
1021 Status
= CmiInitializeHive(ConfigPath
,
1024 if (!NT_SUCCESS(Status
))
1026 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
1030 // CmiCheckRegistry(TRUE);
1032 /* Start automatic hive synchronization */
1033 KeInitializeDpc(&CmiHiveSyncDpc
,
1034 CmiHiveSyncDpcRoutine
,
1036 KeInitializeTimer(&CmiHiveSyncTimer
);
1037 CmiHiveSyncEnabled
= TRUE
;
1039 DPRINT("CmiInitHives() done\n");
1041 return(STATUS_SUCCESS
);
1046 CmShutdownRegistry(VOID
)
1048 PREGISTRY_HIVE Hive
;
1051 DPRINT1("CmShutdownRegistry() called\n");
1053 /* Stop automatic hive synchronization */
1054 CmiHiveSyncEnabled
= FALSE
;
1056 /* Acquire hive list lock exclusively */
1057 ExAcquireResourceExclusiveLite(&CmiHiveListLock
, TRUE
);
1059 Entry
= CmiHiveListHead
.Flink
;
1060 while (Entry
!= &CmiHiveListHead
)
1062 Hive
= CONTAINING_RECORD(Entry
, REGISTRY_HIVE
, HiveList
);
1064 if (!IsVolatileHive(Hive
))
1066 /* Acquire hive resource exclusively */
1067 ExAcquireResourceExclusiveLite(&Hive
->HiveResource
,
1070 /* Flush non-volatile hive */
1071 CmiFlushRegistryHive(Hive
);
1073 /* Release hive resource */
1074 ExReleaseResourceLite(&Hive
->HiveResource
);
1077 Entry
= Entry
->Flink
;
1080 /* Release hive list lock */
1081 ExReleaseResourceLite(&CmiHiveListLock
);
1083 DPRINT1("CmShutdownRegistry() done\n");
1088 CmiHiveSyncRoutine(PVOID DeferredContext
)
1090 PREGISTRY_HIVE Hive
;
1093 DPRINT1("CmiHiveSyncRoutine() called\n");
1095 CmiHiveSyncPending
= FALSE
;
1097 /* Acquire hive list lock exclusively */
1098 ExAcquireResourceExclusiveLite(&CmiHiveListLock
, TRUE
);
1100 Entry
= CmiHiveListHead
.Flink
;
1101 while (Entry
!= &CmiHiveListHead
)
1103 Hive
= CONTAINING_RECORD(Entry
, REGISTRY_HIVE
, HiveList
);
1105 if (!IsVolatileHive(Hive
))
1107 /* Acquire hive resource exclusively */
1108 ExAcquireResourceExclusiveLite(&Hive
->HiveResource
,
1111 /* Flush non-volatile hive */
1112 CmiFlushRegistryHive(Hive
);
1114 /* Release hive resource */
1115 ExReleaseResourceLite(&Hive
->HiveResource
);
1118 Entry
= Entry
->Flink
;
1121 /* Release hive list lock */
1122 ExReleaseResourceLite(&CmiHiveListLock
);
1124 DPRINT("DeferredContext %x\n", DeferredContext
);
1125 ExFreePool(DeferredContext
);
1127 DPRINT1("CmiHiveSyncRoutine() done\n");
1132 CmiHiveSyncDpcRoutine(PKDPC Dpc
,
1133 PVOID DeferredContext
,
1134 PVOID SystemArgument1
,
1135 PVOID SystemArgument2
)
1137 PWORK_QUEUE_ITEM WorkQueueItem
;
1139 WorkQueueItem
= ExAllocatePool(NonPagedPool
,
1140 sizeof(WORK_QUEUE_ITEM
));
1141 if (WorkQueueItem
== NULL
)
1143 DbgPrint("Failed to allocate work item\n");
1147 ExInitializeWorkItem(WorkQueueItem
,
1151 DPRINT("DeferredContext %x\n", WorkQueueItem
);
1152 ExQueueWorkItem(WorkQueueItem
,
1160 LARGE_INTEGER Timeout
;
1162 DPRINT("CmiSyncHives() called\n");
1164 if (CmiHiveSyncEnabled
== FALSE
||
1165 CmiHiveSyncPending
== TRUE
)
1168 CmiHiveSyncPending
= TRUE
;
1171 Timeout
.QuadPart
= -50000000LL;
1172 KeSetTimer(&CmiHiveSyncTimer
,