1 /* $Id: registry.c,v 1.103 2003/06/03 07:28:01 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/ob.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 KeyName
;
255 HANDLE RootKeyHandle
;
259 /* Initialize the Key object type */
260 CmiKeyType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
262 CmiKeyType
->TotalObjects
= 0;
263 CmiKeyType
->TotalHandles
= 0;
264 CmiKeyType
->MaxObjects
= LONG_MAX
;
265 CmiKeyType
->MaxHandles
= LONG_MAX
;
266 CmiKeyType
->PagedPoolCharge
= 0;
267 CmiKeyType
->NonpagedPoolCharge
= sizeof(KEY_OBJECT
);
268 CmiKeyType
->Mapping
= &CmiKeyMapping
;
269 CmiKeyType
->Dump
= NULL
;
270 CmiKeyType
->Open
= NULL
;
271 CmiKeyType
->Close
= NULL
;
272 CmiKeyType
->Delete
= CmiObjectDelete
;
273 CmiKeyType
->Parse
= CmiObjectParse
;
274 CmiKeyType
->Security
= CmiObjectSecurity
;
275 CmiKeyType
->QueryName
= CmiObjectQueryName
;
276 CmiKeyType
->OkayToClose
= NULL
;
277 CmiKeyType
->Create
= CmiObjectCreate
;
278 CmiKeyType
->DuplicationNotify
= NULL
;
279 RtlInitUnicodeString(&CmiKeyType
->TypeName
, L
"Key");
281 /* Initialize the hive list */
282 InitializeListHead(&CmiHiveListHead
);
283 ExInitializeResourceLite(&CmiHiveListLock
);
285 /* Build volatile registry store */
286 Status
= CmiCreateVolatileHive (&CmiVolatileHive
);
287 assert(NT_SUCCESS(Status
));
289 /* Create '\Registry' key. */
290 RtlInitUnicodeString(&KeyName
, REG_ROOT_KEY_NAME
);
291 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, 0, NULL
, NULL
);
292 Status
= ObCreateObject(&RootKeyHandle
,
293 STANDARD_RIGHTS_REQUIRED
,
297 assert(NT_SUCCESS(Status
));
298 Status
= ObReferenceObjectByHandle(RootKeyHandle
,
299 STANDARD_RIGHTS_REQUIRED
,
304 assert(NT_SUCCESS(Status
));
305 RootKey
->RegistryHive
= CmiVolatileHive
;
306 RootKey
->BlockOffset
= CmiVolatileHive
->HiveHeader
->RootKeyCell
;
307 RootKey
->KeyCell
= CmiGetBlock(CmiVolatileHive
, RootKey
->BlockOffset
, NULL
);
308 RootKey
->ParentKey
= RootKey
;
310 RootKey
->NumberOfSubKeys
= 0;
311 RootKey
->SubKeys
= NULL
;
312 RootKey
->SizeOfSubKeys
= 0;
313 Status
= RtlCreateUnicodeString(&RootKey
->Name
, L
"Registry");
314 assert(NT_SUCCESS(Status
));
316 KeInitializeSpinLock(&CmiKeyListLock
);
318 /* Create '\Registry\Machine' key. */
319 RtlInitUnicodeString(&KeyName
,
321 InitializeObjectAttributes(&ObjectAttributes
,
326 Status
= NtCreateKey(&KeyHandle
,
327 STANDARD_RIGHTS_REQUIRED
,
333 assert(NT_SUCCESS(Status
));
335 /* Create '\Registry\User' key. */
336 RtlInitUnicodeString(&KeyName
,
338 InitializeObjectAttributes(&ObjectAttributes
,
343 Status
= NtCreateKey(&KeyHandle
,
344 STANDARD_RIGHTS_REQUIRED
,
350 assert(NT_SUCCESS(Status
));
355 CmInit2(PCHAR CommandLine
)
361 /* FIXME: Store system start options */
365 /* Create the 'CurrentControlSet' link. */
366 Status
= CmiCreateCurrentControlSetLink();
367 if (!NT_SUCCESS(Status
))
369 KeBugCheck(CONFIG_INITIALIZATION_FAILED
);
372 /* Set PICE 'Start' value to 1, if PICE debugging is enabled */
374 p1
= (PCHAR
)CommandLine
;
375 while (p1
&& (p2
= strchr(p1
, '/')))
378 if (_strnicmp(p2
, "DEBUGPORT", 9) == 0)
384 if (_strnicmp(p2
, "PICE", 4) == 0)
394 Status
= RtlWriteRegistryValue(RTL_REGISTRY_SERVICES
,
400 if (!NT_SUCCESS(Status
))
402 KeBugCheck(CONFIG_INITIALIZATION_FAILED
);
408 CmiCreateCurrentControlSetLink(VOID
)
410 RTL_QUERY_REGISTRY_TABLE QueryTable
[5];
411 WCHAR TargetNameBuffer
[80];
412 ULONG TargetNameLength
;
413 UNICODE_STRING LinkName
;
414 UNICODE_STRING LinkValue
;
420 OBJECT_ATTRIBUTES ObjectAttributes
;
423 DPRINT("CmiCreateCurrentControlSetLink() called\n");
425 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
427 QueryTable
[0].Name
= L
"Current";
428 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
429 QueryTable
[0].EntryContext
= &CurrentSet
;
431 QueryTable
[1].Name
= L
"Default";
432 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
433 QueryTable
[1].EntryContext
= &DefaultSet
;
435 QueryTable
[2].Name
= L
"Failed";
436 QueryTable
[2].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
437 QueryTable
[2].EntryContext
= &Failed
;
439 QueryTable
[3].Name
= L
"LastKnownGood";
440 QueryTable
[3].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
441 QueryTable
[3].EntryContext
= &LastKnownGood
;
443 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
444 L
"\\Registry\\Machine\\SYSTEM\\Select",
448 if (!NT_SUCCESS(Status
))
453 DPRINT("Current %ld Default %ld\n", CurrentSet
, DefaultSet
);
455 swprintf(TargetNameBuffer
,
456 L
"\\Registry\\Machine\\SYSTEM\\ControlSet%03lu",
458 TargetNameLength
= wcslen(TargetNameBuffer
) * sizeof(WCHAR
);
460 DPRINT("Link target '%S'\n", TargetNameBuffer
);
462 RtlInitUnicodeStringFromLiteral(&LinkName
,
463 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
464 InitializeObjectAttributes(&ObjectAttributes
,
466 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_OPENLINK
,
469 Status
= NtCreateKey(&KeyHandle
,
470 KEY_ALL_ACCESS
| KEY_CREATE_LINK
,
474 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
476 if (!NT_SUCCESS(Status
))
478 DPRINT1("NtCreateKey() failed (Status %lx)\n", Status
);
482 RtlInitUnicodeStringFromLiteral(&LinkValue
,
483 L
"SymbolicLinkValue");
484 Status
= NtSetValueKey(KeyHandle
,
488 (PVOID
)TargetNameBuffer
,
490 if (!NT_SUCCESS(Status
))
492 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
502 CmiConnectHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
503 IN PREGISTRY_HIVE RegistryHive
)
505 UNICODE_STRING RemainingPath
;
506 PKEY_OBJECT ParentKey
;
511 DPRINT("CmiConnectHive(%p, %wZ) called.\n",
512 RegistryHive
, KeyName
);
514 Status
= ObFindObject(KeyObjectAttributes
,
518 if (!NT_SUCCESS(Status
))
523 DPRINT ("RemainingPath %wZ\n", &RemainingPath
);
525 if ((RemainingPath
.Buffer
== NULL
) || (RemainingPath
.Buffer
[0] == 0))
527 ObDereferenceObject (ParentKey
);
528 return STATUS_OBJECT_NAME_COLLISION
;
531 /* If RemainingPath contains \ we must return error
532 because CmiConnectHive() can not create trees */
533 SubName
= RemainingPath
.Buffer
;
534 if (*SubName
== L
'\\')
537 if (wcschr (SubName
, L
'\\') != NULL
)
539 ObDereferenceObject (ParentKey
);
540 return STATUS_OBJECT_NAME_NOT_FOUND
;
543 DPRINT("RemainingPath %S ParentObject %x\n", RemainingPath
.Buffer
, Object
);
545 Status
= ObCreateObject(NULL
,
546 STANDARD_RIGHTS_REQUIRED
,
550 if (!NT_SUCCESS(Status
))
555 if (!NT_SUCCESS(Status
))
557 DPRINT1 ("ObCreateObject() failed (Status %lx)\n", Status
);
558 ObDereferenceObject (ParentKey
);
562 NewKey
->RegistryHive
= RegistryHive
;
563 NewKey
->BlockOffset
= RegistryHive
->HiveHeader
->RootKeyCell
;
564 NewKey
->KeyCell
= CmiGetBlock(RegistryHive
, NewKey
->BlockOffset
, NULL
);
566 NewKey
->NumberOfSubKeys
= 0;
567 NewKey
->SubKeys
= ExAllocatePool(PagedPool
,
568 NewKey
->KeyCell
->NumberOfSubKeys
* sizeof(ULONG
));
570 if ((NewKey
->SubKeys
== NULL
) && (NewKey
->KeyCell
->NumberOfSubKeys
!= 0))
572 DPRINT("NumberOfSubKeys %d\n", NewKey
->KeyCell
->NumberOfSubKeys
);
573 ObDereferenceObject (NewKey
);
574 ObDereferenceObject (ParentKey
);
575 return(STATUS_INSUFFICIENT_RESOURCES
);
578 Status
= RtlCreateUnicodeString(&NewKey
->Name
,
580 if (!NT_SUCCESS(Status
))
582 DPRINT1("RtlCreateUnicodeString() failed (Status %lx)\n", Status
);
583 if (NewKey
->SubKeys
!= NULL
)
585 ExFreePool (NewKey
->SubKeys
);
587 ObDereferenceObject (NewKey
);
588 ObDereferenceObject (ParentKey
);
589 return STATUS_INSUFFICIENT_RESOURCES
;
592 CmiAddKeyToList (ParentKey
, NewKey
);
593 ObDereferenceObject (ParentKey
);
595 VERIFY_KEY_OBJECT(NewKey
);
597 /* Note: Do not dereference NewKey here! */
599 return STATUS_SUCCESS
;
604 CmiDisconnectHive (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
605 OUT PREGISTRY_HIVE
*RegistryHive
)
607 PKEY_OBJECT KeyObject
;
612 DPRINT("CmiDisconnectHive() called\n");
614 *RegistryHive
= NULL
;
616 Status
= ObOpenObjectByName (KeyObjectAttributes
,
620 STANDARD_RIGHTS_REQUIRED
,
623 if (!NT_SUCCESS(Status
))
625 DPRINT1 ("ObOpenObjectByName() failed (Status %lx)\n", Status
);
629 Status
= ObReferenceObjectByHandle (KeyHandle
,
630 STANDARD_RIGHTS_REQUIRED
,
636 if (!NT_SUCCESS(Status
))
638 DPRINT1 ("ObReferenceObjectByName() failed (Status %lx)\n", Status
);
641 DPRINT ("KeyObject %p Hive %p\n", KeyObject
, KeyObject
->RegistryHive
);
643 if (!(KeyObject
->KeyCell
->Flags
& REG_KEY_ROOT_CELL
))
645 DPRINT1 ("Key is not the Hive-Root-Key\n");
646 ObDereferenceObject (KeyObject
);
647 return STATUS_INVALID_PARAMETER
;
650 if (ObGetObjectHandleCount (KeyObject
) != 0 ||
651 ObGetObjectPointerCount (KeyObject
) != 2)
653 DPRINT1 ("Hive is still in use\n");
654 ObDereferenceObject (KeyObject
);
655 return STATUS_UNSUCCESSFUL
;
658 Hive
= KeyObject
->RegistryHive
;
659 CmiRemoveKeyFromList (KeyObject
);
661 /* Dereference KeyObject twice to delete it */
662 ObDereferenceObject (KeyObject
);
663 ObDereferenceObject (KeyObject
);
665 *RegistryHive
= Hive
;
667 DPRINT ("CmiDisconnectHive() done\n");
669 return STATUS_SUCCESS
;
674 CmiInitControlSetLink (VOID
)
676 OBJECT_ATTRIBUTES ObjectAttributes
;
677 UNICODE_STRING ControlSetKeyName
;
678 UNICODE_STRING ControlSetLinkName
;
679 UNICODE_STRING ControlSetValueName
;
683 /* Create 'ControlSet001' key */
684 RtlInitUnicodeStringFromLiteral (&ControlSetKeyName
,
685 L
"\\Registry\\Machine\\SYSTEM\\ControlSet001");
686 InitializeObjectAttributes (&ObjectAttributes
,
688 OBJ_CASE_INSENSITIVE
,
691 Status
= NtCreateKey (&KeyHandle
,
696 REG_OPTION_NON_VOLATILE
,
698 if (!NT_SUCCESS(Status
))
700 DPRINT1 ("NtCreateKey() failed (Status %lx)\n", Status
);
705 /* Link 'CurrentControlSet' to 'ControlSet001' key */
706 RtlInitUnicodeStringFromLiteral (&ControlSetLinkName
,
707 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
708 InitializeObjectAttributes (&ObjectAttributes
,
710 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_OPENLINK
,
713 Status
= NtCreateKey (&KeyHandle
,
714 KEY_ALL_ACCESS
| KEY_CREATE_LINK
,
718 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
720 if (!NT_SUCCESS(Status
))
722 DPRINT1 ("NtCreateKey() failed (Status %lx)\n", Status
);
726 RtlInitUnicodeStringFromLiteral (&ControlSetValueName
,
727 L
"SymbolicLinkValue");
728 Status
= NtSetValueKey (KeyHandle
,
729 &ControlSetValueName
,
732 (PVOID
)ControlSetKeyName
.Buffer
,
733 ControlSetKeyName
.Length
);
734 if (!NT_SUCCESS(Status
))
736 DPRINT1 ("NtSetValueKey() failed (Status %lx)\n", Status
);
740 return STATUS_SUCCESS
;
745 CmiInitHives(BOOLEAN SetupBoot
)
747 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
748 OBJECT_ATTRIBUTES ObjectAttributes
;
749 UNICODE_STRING FileName
;
750 UNICODE_STRING KeyName
;
751 UNICODE_STRING ValueName
;
756 WCHAR ConfigPath
[MAX_PATH
];
763 DPRINT("CmiInitHives() called\n");
765 if (SetupBoot
== TRUE
)
767 RtlInitUnicodeStringFromLiteral(&KeyName
,
768 L
"\\Registry\\Machine\\HARDWARE");
769 InitializeObjectAttributes(&ObjectAttributes
,
771 OBJ_CASE_INSENSITIVE
,
774 Status
= NtOpenKey(&KeyHandle
,
777 if (!NT_SUCCESS(Status
))
779 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status
);
783 RtlInitUnicodeStringFromLiteral(&ValueName
,
786 BufferSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 4096;
787 ValueInfo
= ExAllocatePool(PagedPool
,
789 if (ValueInfo
== NULL
)
792 return(STATUS_INSUFFICIENT_RESOURCES
);
795 Status
= NtQueryValueKey(KeyHandle
,
797 KeyValuePartialInformation
,
802 if (!NT_SUCCESS(Status
))
804 ExFreePool(ValueInfo
);
808 RtlCopyMemory(ConfigPath
,
810 ValueInfo
->DataLength
);
811 ConfigPath
[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = (WCHAR
)0;
812 ExFreePool(ValueInfo
);
816 wcscpy(ConfigPath
, L
"\\SystemRoot");
818 wcscat(ConfigPath
, L
"\\system32\\config");
820 DPRINT("ConfigPath: %S\n", ConfigPath
);
822 EndPtr
= ConfigPath
+ wcslen(ConfigPath
);
826 /* FIXME: Save boot log */
828 /* Connect the SYSTEM hive only if it has been created */
829 if (SetupBoot
== TRUE
)
831 wcscpy(EndPtr
, REG_SYSTEM_FILE_NAME
);
832 DPRINT ("ConfigPath: %S\n", ConfigPath
);
834 RtlInitUnicodeString (&KeyName
,
835 REG_SYSTEM_KEY_NAME
);
836 InitializeObjectAttributes(&ObjectAttributes
,
838 OBJ_CASE_INSENSITIVE
,
842 RtlInitUnicodeString (&FileName
,
844 Status
= CmiLoadHive (&ObjectAttributes
,
847 if (!NT_SUCCESS(Status
))
849 DPRINT1 ("CmiLoadHive() failed (Status %lx)\n", Status
);
853 Status
= CmiInitControlSetLink ();
854 if (!NT_SUCCESS(Status
))
856 DPRINT1("CmiInitControlSetLink() failed (Status %lx)\n", Status
);
861 /* Connect the SOFTWARE hive */
862 wcscpy(EndPtr
, REG_SOFTWARE_FILE_NAME
);
863 RtlInitUnicodeString (&FileName
,
865 DPRINT ("ConfigPath: %S\n", ConfigPath
);
867 RtlInitUnicodeString (&KeyName
,
868 REG_SOFTWARE_KEY_NAME
);
869 InitializeObjectAttributes(&ObjectAttributes
,
871 OBJ_CASE_INSENSITIVE
,
875 Status
= CmiLoadHive (&ObjectAttributes
,
878 if (!NT_SUCCESS(Status
))
880 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
884 /* Connect the SAM hive */
885 wcscpy(EndPtr
, REG_SAM_FILE_NAME
);
886 RtlInitUnicodeString (&FileName
,
888 DPRINT ("ConfigPath: %S\n", ConfigPath
);
890 RtlInitUnicodeString (&KeyName
,
892 InitializeObjectAttributes(&ObjectAttributes
,
894 OBJ_CASE_INSENSITIVE
,
897 Status
= CmiLoadHive (&ObjectAttributes
,
900 if (!NT_SUCCESS(Status
))
902 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
906 /* Connect the SECURITY hive */
907 wcscpy(EndPtr
, REG_SEC_FILE_NAME
);
908 RtlInitUnicodeString (&FileName
,
910 DPRINT ("ConfigPath: %S\n", ConfigPath
);
912 RtlInitUnicodeString (&KeyName
,
914 InitializeObjectAttributes(&ObjectAttributes
,
916 OBJ_CASE_INSENSITIVE
,
919 Status
= CmiLoadHive (&ObjectAttributes
,
922 if (!NT_SUCCESS(Status
))
924 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
928 /* Connect the DEFAULT hive */
929 wcscpy(EndPtr
, REG_DEFAULT_USER_FILE_NAME
);
930 RtlInitUnicodeString (&FileName
,
932 DPRINT ("ConfigPath: %S\n", ConfigPath
);
934 RtlInitUnicodeString (&KeyName
,
935 REG_DEFAULT_USER_KEY_NAME
);
936 InitializeObjectAttributes(&ObjectAttributes
,
938 OBJ_CASE_INSENSITIVE
,
941 Status
= CmiLoadHive (&ObjectAttributes
,
944 if (!NT_SUCCESS(Status
))
946 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
950 // CmiCheckRegistry(TRUE);
952 /* Start automatic hive synchronization */
953 KeInitializeDpc(&CmiHiveSyncDpc
,
954 CmiHiveSyncDpcRoutine
,
956 KeInitializeTimer(&CmiHiveSyncTimer
);
957 CmiHiveSyncEnabled
= TRUE
;
959 DPRINT("CmiInitHives() done\n");
961 return(STATUS_SUCCESS
);
966 CmShutdownRegistry(VOID
)
971 DPRINT1("CmShutdownRegistry() called\n");
973 /* Stop automatic hive synchronization */
974 CmiHiveSyncEnabled
= FALSE
;
976 /* Acquire hive list lock exclusively */
977 ExAcquireResourceExclusiveLite(&CmiHiveListLock
, TRUE
);
979 Entry
= CmiHiveListHead
.Flink
;
980 while (Entry
!= &CmiHiveListHead
)
982 Hive
= CONTAINING_RECORD(Entry
, REGISTRY_HIVE
, HiveList
);
984 if (!(IsNoFileHive(Hive
) || IsNoSynchHive(Hive
)))
986 /* Acquire hive resource exclusively */
987 ExAcquireResourceExclusiveLite(&Hive
->HiveResource
,
990 /* Flush non-volatile hive */
991 CmiFlushRegistryHive(Hive
);
993 /* Release hive resource */
994 ExReleaseResourceLite(&Hive
->HiveResource
);
997 Entry
= Entry
->Flink
;
1000 /* Release hive list lock */
1001 ExReleaseResourceLite(&CmiHiveListLock
);
1003 DPRINT1("CmShutdownRegistry() done\n");
1008 CmiHiveSyncRoutine(PVOID DeferredContext
)
1010 PREGISTRY_HIVE Hive
;
1013 DPRINT("CmiHiveSyncRoutine() called\n");
1015 CmiHiveSyncPending
= FALSE
;
1017 /* Acquire hive list lock exclusively */
1018 ExAcquireResourceExclusiveLite(&CmiHiveListLock
, TRUE
);
1020 Entry
= CmiHiveListHead
.Flink
;
1021 while (Entry
!= &CmiHiveListHead
)
1023 Hive
= CONTAINING_RECORD(Entry
, REGISTRY_HIVE
, HiveList
);
1025 if (!(IsNoFileHive(Hive
) || IsNoSynchHive(Hive
)))
1027 /* Acquire hive resource exclusively */
1028 ExAcquireResourceExclusiveLite(&Hive
->HiveResource
,
1031 /* Flush non-volatile hive */
1032 CmiFlushRegistryHive(Hive
);
1034 /* Release hive resource */
1035 ExReleaseResourceLite(&Hive
->HiveResource
);
1038 Entry
= Entry
->Flink
;
1041 /* Release hive list lock */
1042 ExReleaseResourceLite(&CmiHiveListLock
);
1044 DPRINT("DeferredContext %x\n", DeferredContext
);
1045 ExFreePool(DeferredContext
);
1047 DPRINT("CmiHiveSyncRoutine() done\n");
1052 CmiHiveSyncDpcRoutine(PKDPC Dpc
,
1053 PVOID DeferredContext
,
1054 PVOID SystemArgument1
,
1055 PVOID SystemArgument2
)
1057 PWORK_QUEUE_ITEM WorkQueueItem
;
1059 WorkQueueItem
= ExAllocatePool(NonPagedPool
,
1060 sizeof(WORK_QUEUE_ITEM
));
1061 if (WorkQueueItem
== NULL
)
1063 DbgPrint("Failed to allocate work item\n");
1067 ExInitializeWorkItem(WorkQueueItem
,
1071 DPRINT("DeferredContext %x\n", WorkQueueItem
);
1072 ExQueueWorkItem(WorkQueueItem
,
1080 LARGE_INTEGER Timeout
;
1082 DPRINT("CmiSyncHives() called\n");
1084 if (CmiHiveSyncEnabled
== FALSE
||
1085 CmiHiveSyncPending
== TRUE
)
1088 CmiHiveSyncPending
= TRUE
;
1091 Timeout
.QuadPart
= -50000000LL;
1092 KeSetTimer(&CmiHiveSyncTimer
,