1 /* $Id: registry.c,v 1.95 2003/05/13 21:28:26 chorns 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 /* Initialize the Key object type */
262 CmiKeyType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
264 CmiKeyType
->TotalObjects
= 0;
265 CmiKeyType
->TotalHandles
= 0;
266 CmiKeyType
->MaxObjects
= LONG_MAX
;
267 CmiKeyType
->MaxHandles
= LONG_MAX
;
268 CmiKeyType
->PagedPoolCharge
= 0;
269 CmiKeyType
->NonpagedPoolCharge
= sizeof(KEY_OBJECT
);
270 CmiKeyType
->Mapping
= &CmiKeyMapping
;
271 CmiKeyType
->Dump
= NULL
;
272 CmiKeyType
->Open
= NULL
;
273 CmiKeyType
->Close
= NULL
;
274 CmiKeyType
->Delete
= CmiObjectDelete
;
275 CmiKeyType
->Parse
= CmiObjectParse
;
276 CmiKeyType
->Security
= CmiObjectSecurity
;
277 CmiKeyType
->QueryName
= NULL
;
278 CmiKeyType
->OkayToClose
= NULL
;
279 CmiKeyType
->Create
= CmiObjectCreate
;
280 CmiKeyType
->DuplicationNotify
= NULL
;
281 RtlInitUnicodeString(&CmiKeyType
->TypeName
, L
"Key");
283 /* Initialize the hive list */
284 InitializeListHead(&CmiHiveListHead
);
285 ExInitializeResourceLite(&CmiHiveListLock
);
287 /* Build volatile registry store */
288 Status
= CmiCreateRegistryHive(NULL
, &CmiVolatileHive
, FALSE
);
289 assert(NT_SUCCESS(Status
));
291 /* Create '\Registry' key. */
292 RtlInitUnicodeString(&RootKeyName
, REG_ROOT_KEY_NAME
);
293 InitializeObjectAttributes(&ObjectAttributes
, &RootKeyName
, 0, NULL
, NULL
);
294 Status
= ObCreateObject(&RootKeyHandle
,
295 STANDARD_RIGHTS_REQUIRED
,
299 assert(NT_SUCCESS(Status
));
300 Status
= ObReferenceObjectByHandle(RootKeyHandle
,
301 STANDARD_RIGHTS_REQUIRED
,
306 assert(NT_SUCCESS(Status
));
307 RootKey
->RegistryHive
= CmiVolatileHive
;
308 RootKey
->BlockOffset
= CmiVolatileHive
->HiveHeader
->RootKeyCell
;
309 RootKey
->KeyCell
= CmiGetBlock(CmiVolatileHive
, RootKey
->BlockOffset
, NULL
);
311 RootKey
->NumberOfSubKeys
= 0;
312 RootKey
->SubKeys
= NULL
;
313 RootKey
->SizeOfSubKeys
= 0;
314 RootKey
->NameSize
= strlen("Registry");
315 RootKey
->Name
= ExAllocatePool(PagedPool
, RootKey
->NameSize
);
316 RtlCopyMemory(RootKey
->Name
, "Registry", RootKey
->NameSize
);
318 KeInitializeSpinLock(&CmiKeyListLock
);
320 /* Create '\Registry\Machine' key. */
321 Status
= ObCreateObject(&KeyHandle
,
322 STANDARD_RIGHTS_REQUIRED
,
325 (PVOID
*)&MachineKey
);
326 assert(NT_SUCCESS(Status
));
327 Status
= CmiAddSubKey(CmiVolatileHive
,
331 wcslen(L
"Machine") * sizeof(WCHAR
),
335 assert(NT_SUCCESS(Status
));
336 MachineKey
->RegistryHive
= CmiVolatileHive
;
337 MachineKey
->Flags
= 0;
338 MachineKey
->NumberOfSubKeys
= 0;
339 MachineKey
->SubKeys
= NULL
;
340 MachineKey
->SizeOfSubKeys
= MachineKey
->KeyCell
->NumberOfSubKeys
;
341 MachineKey
->NameSize
= strlen("Machine");
342 MachineKey
->Name
= ExAllocatePool(PagedPool
, MachineKey
->NameSize
);
343 RtlCopyMemory(MachineKey
->Name
, "Machine", MachineKey
->NameSize
);
344 CmiAddKeyToList(RootKey
, MachineKey
);
346 /* Create '\Registry\User' key. */
347 Status
= ObCreateObject(&KeyHandle
,
348 STANDARD_RIGHTS_REQUIRED
,
352 assert(NT_SUCCESS(Status
));
353 Status
= CmiAddSubKey(CmiVolatileHive
,
357 wcslen(L
"User") * sizeof(WCHAR
),
361 assert(NT_SUCCESS(Status
));
362 UserKey
->RegistryHive
= CmiVolatileHive
;
364 UserKey
->NumberOfSubKeys
= 0;
365 UserKey
->SubKeys
= NULL
;
366 UserKey
->SizeOfSubKeys
= UserKey
->KeyCell
->NumberOfSubKeys
;
367 UserKey
->NameSize
= strlen("User");
368 UserKey
->Name
= ExAllocatePool(PagedPool
, UserKey
->NameSize
);
369 RtlCopyMemory(UserKey
->Name
, "User", UserKey
->NameSize
);
370 CmiAddKeyToList(RootKey
, UserKey
);
375 CmInit2(PCHAR CommandLine
)
381 /* FIXME: Store system start options */
385 /* Create the 'CurrentControlSet' link. */
386 Status
= CmiCreateCurrentControlSetLink();
387 if (!NT_SUCCESS(Status
))
389 KeBugCheck(CONFIG_INITIALIZATION_FAILED
);
392 /* Set PICE 'Start' value to 1, if PICE debugging is enabled */
394 p1
= (PCHAR
)CommandLine
;
395 while (p1
&& (p2
= strchr(p1
, '/')))
398 if (_strnicmp(p2
, "DEBUGPORT", 9) == 0)
404 if (_strnicmp(p2
, "PICE", 4) == 0)
414 Status
= RtlWriteRegistryValue(RTL_REGISTRY_SERVICES
,
420 if (!NT_SUCCESS(Status
))
422 KeBugCheck(CONFIG_INITIALIZATION_FAILED
);
428 CmiCreateCurrentControlSetLink(VOID
)
430 RTL_QUERY_REGISTRY_TABLE QueryTable
[5];
431 WCHAR TargetNameBuffer
[80];
432 ULONG TargetNameLength
;
433 UNICODE_STRING LinkName
;
434 UNICODE_STRING LinkValue
;
440 OBJECT_ATTRIBUTES ObjectAttributes
;
443 DPRINT("CmiCreateCurrentControlSetLink() called\n");
445 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
447 QueryTable
[0].Name
= L
"Current";
448 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
449 QueryTable
[0].EntryContext
= &CurrentSet
;
451 QueryTable
[1].Name
= L
"Default";
452 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
453 QueryTable
[1].EntryContext
= &DefaultSet
;
455 QueryTable
[2].Name
= L
"Failed";
456 QueryTable
[2].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
457 QueryTable
[2].EntryContext
= &Failed
;
459 QueryTable
[3].Name
= L
"LastKnownGood";
460 QueryTable
[3].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
461 QueryTable
[3].EntryContext
= &LastKnownGood
;
463 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
464 L
"\\Registry\\Machine\\SYSTEM\\Select",
468 if (!NT_SUCCESS(Status
))
473 DPRINT("Current %ld Default %ld\n", CurrentSet
, DefaultSet
);
475 swprintf(TargetNameBuffer
,
476 L
"\\Registry\\Machine\\SYSTEM\\ControlSet%03lu",
478 TargetNameLength
= wcslen(TargetNameBuffer
) * sizeof(WCHAR
);
480 DPRINT("Link target '%S'\n", TargetNameBuffer
);
482 RtlInitUnicodeStringFromLiteral(&LinkName
,
483 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
484 InitializeObjectAttributes(&ObjectAttributes
,
486 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_OPENLINK
,
489 Status
= NtCreateKey(&KeyHandle
,
490 KEY_ALL_ACCESS
| KEY_CREATE_LINK
,
494 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
496 if (!NT_SUCCESS(Status
))
498 DPRINT1("NtCreateKey() failed (Status %lx)\n", Status
);
502 RtlInitUnicodeStringFromLiteral(&LinkValue
,
503 L
"SymbolicLinkValue");
504 Status
= NtSetValueKey(KeyHandle
,
508 (PVOID
)TargetNameBuffer
,
510 if (!NT_SUCCESS(Status
))
512 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
522 CmiConnectHive(PREGISTRY_HIVE RegistryHive
,
523 PUNICODE_STRING KeyName
)
525 OBJECT_ATTRIBUTES ObjectAttributes
;
526 UNICODE_STRING ParentKeyName
;
527 PKEY_OBJECT ParentKey
;
533 DPRINT("CmiConnectHive(%p, %wZ) called.\n",
534 RegistryHive
, KeyName
);
536 SubName
= wcsrchr (KeyName
->Buffer
, L
'\\');
539 return STATUS_UNSUCCESSFUL
;
542 ParentKeyName
.Length
= (USHORT
)(SubName
- KeyName
->Buffer
) * sizeof(WCHAR
);
543 ParentKeyName
.MaximumLength
= ParentKeyName
.Length
+ sizeof(WCHAR
);
544 ParentKeyName
.Buffer
= ExAllocatePool (NonPagedPool
,
545 ParentKeyName
.MaximumLength
);
546 RtlCopyMemory (ParentKeyName
.Buffer
,
548 ParentKeyName
.Length
);
549 ParentKeyName
.Buffer
[ParentKeyName
.Length
/ sizeof(WCHAR
)] = 0;
552 Status
= ObReferenceObjectByName (&ParentKeyName
,
553 OBJ_CASE_INSENSITIVE
,
555 STANDARD_RIGHTS_REQUIRED
,
560 RtlFreeUnicodeString (&ParentKeyName
);
561 if (!NT_SUCCESS(Status
))
563 DPRINT1 ("ObReferenceObjectByName() failed (Status %lx)\n", Status
);
567 InitializeObjectAttributes(&ObjectAttributes
,
573 Status
= ObCreateObject(&KeyHandle
,
574 STANDARD_RIGHTS_REQUIRED
,
578 if (!NT_SUCCESS(Status
))
580 DPRINT1 ("ObCreateObject() failed (Status %lx)\n", Status
);
581 ObDereferenceObject (ParentKey
);
585 NewKey
->RegistryHive
= RegistryHive
;
586 NewKey
->BlockOffset
= RegistryHive
->HiveHeader
->RootKeyCell
;
587 NewKey
->KeyCell
= CmiGetBlock(RegistryHive
, NewKey
->BlockOffset
, NULL
);
589 NewKey
->NumberOfSubKeys
= 0;
590 NewKey
->SubKeys
= ExAllocatePool(PagedPool
,
591 NewKey
->KeyCell
->NumberOfSubKeys
* sizeof(ULONG
));
593 if ((NewKey
->SubKeys
== NULL
) && (NewKey
->KeyCell
->NumberOfSubKeys
!= 0))
595 DPRINT("NumberOfSubKeys %d\n", NewKey
->KeyCell
->NumberOfSubKeys
);
597 ObDereferenceObject (ParentKey
);
598 return(STATUS_INSUFFICIENT_RESOURCES
);
601 NewKey
->SizeOfSubKeys
= NewKey
->KeyCell
->NumberOfSubKeys
;
602 NewKey
->NameSize
= wcslen (SubName
);
603 NewKey
->Name
= ExAllocatePool(PagedPool
, NewKey
->NameSize
);
605 if ((NewKey
->Name
== NULL
) && (NewKey
->NameSize
!= 0))
607 DPRINT("NewKey->NameSize %d\n", NewKey
->NameSize
);
608 if (NewKey
->SubKeys
!= NULL
)
609 ExFreePool(NewKey
->SubKeys
);
611 ObDereferenceObject (ParentKey
);
612 return(STATUS_INSUFFICIENT_RESOURCES
);
615 wcstombs (NewKey
->Name
,
619 CmiAddKeyToList (ParentKey
, NewKey
);
620 ObDereferenceObject (ParentKey
);
622 VERIFY_KEY_OBJECT(NewKey
);
624 return(STATUS_SUCCESS
);
629 CmiInitializeSystemHive (PWSTR FileName
,
630 PUNICODE_STRING KeyName
)
632 OBJECT_ATTRIBUTES ObjectAttributes
;
633 UNICODE_STRING ControlSetKeyName
;
634 UNICODE_STRING ControlSetLinkName
;
635 UNICODE_STRING ControlSetValueName
;
638 PREGISTRY_HIVE RegistryHive
;
640 Status
= CmiCreateRegistryHive (FileName
,
643 if (!NT_SUCCESS(Status
))
645 DPRINT1 ("CmiCreateRegistryHive() failed (Status %lx)\n", Status
);
649 Status
= CmiConnectHive (RegistryHive
,
651 if (!NT_SUCCESS(Status
))
653 DPRINT1 ("CmiConnectHive() failed (Status %lx)\n", Status
);
654 CmiRemoveRegistryHive (RegistryHive
);
658 /* Create 'ControlSet001' key */
659 RtlInitUnicodeStringFromLiteral (&ControlSetKeyName
,
660 L
"\\Registry\\Machine\\SYSTEM\\ControlSet001");
661 InitializeObjectAttributes (&ObjectAttributes
,
663 OBJ_CASE_INSENSITIVE
,
666 Status
= NtCreateKey (&KeyHandle
,
671 REG_OPTION_NON_VOLATILE
,
673 if (!NT_SUCCESS(Status
))
675 DPRINT1 ("NtCreateKey() failed (Status %lx)\n", Status
);
680 /* Link 'CurrentControlSet' to 'ControlSet001' key */
681 RtlInitUnicodeStringFromLiteral (&ControlSetLinkName
,
682 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
683 InitializeObjectAttributes (&ObjectAttributes
,
685 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_OPENLINK
,
688 Status
= NtCreateKey (&KeyHandle
,
689 KEY_ALL_ACCESS
| KEY_CREATE_LINK
,
693 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
695 if (!NT_SUCCESS(Status
))
697 DPRINT1 ("NtCreateKey() failed (Status %lx)\n", Status
);
701 RtlInitUnicodeStringFromLiteral (&ControlSetValueName
,
702 L
"SymbolicLinkValue");
703 Status
= NtSetValueKey (KeyHandle
,
704 &ControlSetValueName
,
707 (PVOID
)ControlSetKeyName
.Buffer
,
708 ControlSetKeyName
.Length
);
709 if (!NT_SUCCESS(Status
))
711 DPRINT1 ("NtSetValueKey() failed (Status %lx)\n", Status
);
715 return STATUS_SUCCESS
;
720 CmiInitializeHive(PWSTR FileName
,
721 PUNICODE_STRING KeyName
,
724 PREGISTRY_HIVE RegistryHive
;
727 DPRINT("CmiInitializeHive(%s) called\n", KeyName
);
729 Status
= CmiCreateRegistryHive(FileName
,
732 if (!NT_SUCCESS(Status
))
734 DPRINT1("CmiCreateRegistryHive() failed (Status %lx)\n", Status
);
736 /* FIXME: Try to load the backup hive */
742 /* Connect the hive */
743 Status
= CmiConnectHive(RegistryHive
,
745 if (!NT_SUCCESS(Status
))
747 DPRINT1("CmiConnectHive() failed (Status %lx)\n", Status
);
748 CmiRemoveRegistryHive(RegistryHive
);
752 DPRINT("CmiInitializeHive() done\n");
754 return(STATUS_SUCCESS
);
759 CmiInitHives(BOOLEAN SetupBoot
)
761 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
762 OBJECT_ATTRIBUTES ObjectAttributes
;
763 UNICODE_STRING KeyName
;
764 UNICODE_STRING ValueName
;
769 WCHAR ConfigPath
[MAX_PATH
];
776 DPRINT("CmiInitHives() called\n");
778 if (SetupBoot
== TRUE
)
780 RtlInitUnicodeStringFromLiteral(&KeyName
,
781 L
"\\Registry\\Machine\\HARDWARE");
782 InitializeObjectAttributes(&ObjectAttributes
,
784 OBJ_CASE_INSENSITIVE
,
787 Status
= NtOpenKey(&KeyHandle
,
790 if (!NT_SUCCESS(Status
))
792 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status
);
796 RtlInitUnicodeStringFromLiteral(&ValueName
,
799 BufferSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 4096;
800 ValueInfo
= ExAllocatePool(PagedPool
,
802 if (ValueInfo
== NULL
)
805 return(STATUS_INSUFFICIENT_RESOURCES
);
808 Status
= NtQueryValueKey(KeyHandle
,
810 KeyValuePartialInformation
,
815 if (!NT_SUCCESS(Status
))
817 ExFreePool(ValueInfo
);
821 RtlCopyMemory(ConfigPath
,
823 ValueInfo
->DataLength
);
824 ConfigPath
[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = (WCHAR
)0;
825 ExFreePool(ValueInfo
);
829 wcscpy(ConfigPath
, L
"\\SystemRoot");
831 wcscat(ConfigPath
, L
"\\system32\\config");
833 DPRINT("ConfigPath: %S\n", ConfigPath
);
835 EndPtr
= ConfigPath
+ wcslen(ConfigPath
);
839 /* FIXME: Save boot log */
841 /* Connect the SYSTEM hive only if it has been created */
842 if (SetupBoot
== TRUE
)
844 wcscpy(EndPtr
, REG_SYSTEM_FILE_NAME
);
845 DPRINT ("ConfigPath: %S\n", ConfigPath
);
847 RtlInitUnicodeString (&KeyName
,
848 REG_SYSTEM_KEY_NAME
);
849 Status
= CmiInitializeSystemHive (ConfigPath
,
851 if (!NT_SUCCESS(Status
))
853 DPRINT1("CmiInitializeSystemHive() failed (Status %lx)\n", Status
);
858 /* Connect the SOFTWARE hive */
859 wcscpy(EndPtr
, REG_SOFTWARE_FILE_NAME
);
860 DPRINT ("ConfigPath: %S\n", ConfigPath
);
862 RtlInitUnicodeString (&KeyName
,
863 REG_SOFTWARE_KEY_NAME
);
864 Status
= CmiInitializeHive(ConfigPath
,
867 if (!NT_SUCCESS(Status
))
869 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
873 /* Connect the SAM hive */
874 wcscpy(EndPtr
, REG_SAM_FILE_NAME
);
875 DPRINT ("ConfigPath: %S\n", ConfigPath
);
877 RtlInitUnicodeString (&KeyName
,
879 Status
= CmiInitializeHive(ConfigPath
,
882 if (!NT_SUCCESS(Status
))
884 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
888 /* Connect the SECURITY hive */
889 wcscpy(EndPtr
, REG_SEC_FILE_NAME
);
890 DPRINT ("ConfigPath: %S\n", ConfigPath
);
892 RtlInitUnicodeString (&KeyName
,
894 Status
= CmiInitializeHive(ConfigPath
,
897 if (!NT_SUCCESS(Status
))
899 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
903 /* Connect the DEFAULT hive */
904 wcscpy(EndPtr
, REG_USER_FILE_NAME
);
905 DPRINT ("ConfigPath: %S\n", ConfigPath
);
907 RtlInitUnicodeString (&KeyName
,
909 Status
= CmiInitializeHive(ConfigPath
,
912 if (!NT_SUCCESS(Status
))
914 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
918 // CmiCheckRegistry(TRUE);
920 /* Start automatic hive synchronization */
921 KeInitializeDpc(&CmiHiveSyncDpc
,
922 CmiHiveSyncDpcRoutine
,
924 KeInitializeTimer(&CmiHiveSyncTimer
);
925 CmiHiveSyncEnabled
= TRUE
;
927 DPRINT("CmiInitHives() done\n");
929 return(STATUS_SUCCESS
);
934 CmShutdownRegistry(VOID
)
939 DPRINT1("CmShutdownRegistry() called\n");
941 /* Stop automatic hive synchronization */
942 CmiHiveSyncEnabled
= FALSE
;
944 /* Acquire hive list lock exclusively */
945 ExAcquireResourceExclusiveLite(&CmiHiveListLock
, TRUE
);
947 Entry
= CmiHiveListHead
.Flink
;
948 while (Entry
!= &CmiHiveListHead
)
950 Hive
= CONTAINING_RECORD(Entry
, REGISTRY_HIVE
, HiveList
);
952 if (!IsVolatileHive(Hive
))
954 /* Acquire hive resource exclusively */
955 ExAcquireResourceExclusiveLite(&Hive
->HiveResource
,
958 /* Flush non-volatile hive */
959 CmiFlushRegistryHive(Hive
);
961 /* Release hive resource */
962 ExReleaseResourceLite(&Hive
->HiveResource
);
965 Entry
= Entry
->Flink
;
968 /* Release hive list lock */
969 ExReleaseResourceLite(&CmiHiveListLock
);
971 DPRINT1("CmShutdownRegistry() done\n");
976 CmiHiveSyncRoutine(PVOID DeferredContext
)
981 DPRINT("CmiHiveSyncRoutine() called\n");
983 CmiHiveSyncPending
= FALSE
;
985 /* Acquire hive list lock exclusively */
986 ExAcquireResourceExclusiveLite(&CmiHiveListLock
, TRUE
);
988 Entry
= CmiHiveListHead
.Flink
;
989 while (Entry
!= &CmiHiveListHead
)
991 Hive
= CONTAINING_RECORD(Entry
, REGISTRY_HIVE
, HiveList
);
993 if (!IsVolatileHive(Hive
))
995 /* Acquire hive resource exclusively */
996 ExAcquireResourceExclusiveLite(&Hive
->HiveResource
,
999 /* Flush non-volatile hive */
1000 CmiFlushRegistryHive(Hive
);
1002 /* Release hive resource */
1003 ExReleaseResourceLite(&Hive
->HiveResource
);
1006 Entry
= Entry
->Flink
;
1009 /* Release hive list lock */
1010 ExReleaseResourceLite(&CmiHiveListLock
);
1012 DPRINT("DeferredContext %x\n", DeferredContext
);
1013 ExFreePool(DeferredContext
);
1015 DPRINT("CmiHiveSyncRoutine() done\n");
1020 CmiHiveSyncDpcRoutine(PKDPC Dpc
,
1021 PVOID DeferredContext
,
1022 PVOID SystemArgument1
,
1023 PVOID SystemArgument2
)
1025 PWORK_QUEUE_ITEM WorkQueueItem
;
1027 WorkQueueItem
= ExAllocatePool(NonPagedPool
,
1028 sizeof(WORK_QUEUE_ITEM
));
1029 if (WorkQueueItem
== NULL
)
1031 DbgPrint("Failed to allocate work item\n");
1035 ExInitializeWorkItem(WorkQueueItem
,
1039 DPRINT("DeferredContext %x\n", WorkQueueItem
);
1040 ExQueueWorkItem(WorkQueueItem
,
1048 LARGE_INTEGER Timeout
;
1050 DPRINT("CmiSyncHives() called\n");
1052 if (CmiHiveSyncEnabled
== FALSE
||
1053 CmiHiveSyncPending
== TRUE
)
1056 CmiHiveSyncPending
= TRUE
;
1059 Timeout
.QuadPart
= -50000000LL;
1060 KeSetTimer(&CmiHiveSyncTimer
,