1 /* $Id: registry.c,v 1.121 2004/02/07 17:30:14 hbirr 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 #define NTOS_MODE_KERNEL
19 #include <internal/ob.h>
20 #include <reactos/bugcodes.h>
21 #include <rosrtl/string.h>
24 #include <internal/debug.h>
28 /* GLOBALS ******************************************************************/
30 POBJECT_TYPE CmiKeyType
= NULL
;
31 PREGISTRY_HIVE CmiVolatileHive
= NULL
;
32 KSPIN_LOCK CmiKeyListLock
;
34 LIST_ENTRY CmiHiveListHead
;
35 ERESOURCE CmiHiveListLock
;
37 volatile BOOLEAN CmiHiveSyncEnabled
= FALSE
;
38 volatile BOOLEAN CmiHiveSyncPending
= FALSE
;
40 KTIMER CmiHiveSyncTimer
;
42 static GENERIC_MAPPING CmiKeyMapping
=
43 {KEY_READ
, KEY_WRITE
, KEY_EXECUTE
, KEY_ALL_ACCESS
};
48 CmiCheckKey(BOOLEAN Verbose
,
52 CmiCreateCurrentControlSetLink(VOID
);
55 CmiHiveSyncDpcRoutine(PKDPC Dpc
,
56 PVOID DeferredContext
,
57 PVOID SystemArgument1
,
58 PVOID SystemArgument2
);
60 /* FUNCTIONS ****************************************************************/
63 CmiCheckSubKeys(BOOLEAN Verbose
,
66 OBJECT_ATTRIBUTES ObjectAttributes
;
67 PKEY_NODE_INFORMATION KeyInfo
;
68 WCHAR KeyBuffer
[MAX_PATH
];
69 UNICODE_STRING KeyPath
;
80 BufferSize
= sizeof(KEY_NODE_INFORMATION
) + 4096;
81 KeyInfo
= ExAllocatePool(PagedPool
, BufferSize
);
83 Status
= NtEnumerateKey(Key
,
89 if (!NT_SUCCESS(Status
))
92 if (Status
== STATUS_NO_MORE_ENTRIES
)
93 Status
= STATUS_SUCCESS
;
99 KeyInfo
->NameLength
/ sizeof(WCHAR
));
103 DbgPrint("Key: %S\n", Name
);
106 /* FIXME: Check info. */
110 wcscpy(KeyBuffer
, L
"\\Registry\\");
111 wcscat(KeyBuffer
, Name
);
113 RtlInitUnicodeString(&KeyPath
, KeyBuffer
);
115 InitializeObjectAttributes(&ObjectAttributes
,
117 OBJ_CASE_INSENSITIVE
,
121 Status
= NtOpenKey(&SubKey
,
125 assert(NT_SUCCESS(Status
));
127 CmiCheckKey(Verbose
, SubKey
);
134 assert(NT_SUCCESS(Status
));
139 CmiCheckValues(BOOLEAN Verbose
,
142 PKEY_NODE_INFORMATION ValueInfo
;
143 WCHAR Name
[MAX_PATH
];
152 BufferSize
= sizeof(KEY_NODE_INFORMATION
) + 4096;
153 ValueInfo
= ExAllocatePool(PagedPool
, BufferSize
);
155 Status
= NtEnumerateValueKey(Key
,
161 if (!NT_SUCCESS(Status
))
163 ExFreePool(ValueInfo
);
164 if (Status
== STATUS_NO_MORE_ENTRIES
)
165 Status
= STATUS_SUCCESS
;
171 ValueInfo
->NameLength
/ sizeof(WCHAR
));
175 DbgPrint("Value: %S\n", Name
);
178 /* FIXME: Check info. */
180 ExFreePool(ValueInfo
);
185 assert(NT_SUCCESS(Status
));
190 CmiCheckKey(BOOLEAN Verbose
,
193 CmiCheckValues(Verbose
, Key
);
194 CmiCheckSubKeys(Verbose
, Key
);
199 CmiCheckByName(BOOLEAN Verbose
,
202 OBJECT_ATTRIBUTES ObjectAttributes
;
203 WCHAR KeyPathBuffer
[MAX_PATH
];
204 UNICODE_STRING KeyPath
;
208 wcscpy(KeyPathBuffer
, L
"\\Registry\\");
209 wcscat(KeyPathBuffer
, KeyName
);
211 RtlInitUnicodeString(&KeyPath
, KeyPathBuffer
);
213 InitializeObjectAttributes(&ObjectAttributes
,
215 OBJ_CASE_INSENSITIVE
,
219 Status
= NtOpenKey(&Key
,
225 if (!NT_SUCCESS(Status
))
227 DbgPrint("KeyPath %wZ Status: %.08x", KeyPath
, Status
);
228 DbgPrint("KeyPath %S Status: %.08x", KeyPath
.Buffer
, Status
);
229 assert(NT_SUCCESS(Status
));
233 CmiCheckKey(Verbose
, Key
);
240 CmiCheckRegistry(BOOLEAN Verbose
)
243 DbgPrint("Checking registry internals\n");
245 CmiCheckByName(Verbose
, L
"Machine");
246 CmiCheckByName(Verbose
, L
"User");
251 CmInitializeRegistry(VOID
)
253 OBJECT_ATTRIBUTES ObjectAttributes
;
254 UNICODE_STRING KeyName
;
256 HANDLE RootKeyHandle
;
260 /* Initialize the Key object type */
261 CmiKeyType
= ExAllocatePool(NonPagedPool
, sizeof(OBJECT_TYPE
));
263 CmiKeyType
->TotalObjects
= 0;
264 CmiKeyType
->TotalHandles
= 0;
265 CmiKeyType
->MaxObjects
= LONG_MAX
;
266 CmiKeyType
->MaxHandles
= LONG_MAX
;
267 CmiKeyType
->PagedPoolCharge
= 0;
268 CmiKeyType
->NonpagedPoolCharge
= sizeof(KEY_OBJECT
);
269 CmiKeyType
->Mapping
= &CmiKeyMapping
;
270 CmiKeyType
->Dump
= NULL
;
271 CmiKeyType
->Open
= NULL
;
272 CmiKeyType
->Close
= NULL
;
273 CmiKeyType
->Delete
= CmiObjectDelete
;
274 CmiKeyType
->Parse
= CmiObjectParse
;
275 CmiKeyType
->Security
= CmiObjectSecurity
;
276 CmiKeyType
->QueryName
= CmiObjectQueryName
;
277 CmiKeyType
->OkayToClose
= NULL
;
278 CmiKeyType
->Create
= CmiObjectCreate
;
279 CmiKeyType
->DuplicationNotify
= NULL
;
280 RtlInitUnicodeString(&CmiKeyType
->TypeName
, L
"Key");
282 ObpCreateTypeObject (CmiKeyType
);
284 /* Initialize the hive list */
285 InitializeListHead(&CmiHiveListHead
);
286 ExInitializeResourceLite(&CmiHiveListLock
);
288 /* Build volatile registry store */
289 Status
= CmiCreateVolatileHive (&CmiVolatileHive
);
290 assert(NT_SUCCESS(Status
));
292 /* Create '\Registry' key. */
293 RtlInitUnicodeString(&KeyName
, REG_ROOT_KEY_NAME
);
294 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, 0, NULL
, NULL
);
295 Status
= ObCreateObject(KernelMode
,
304 assert(NT_SUCCESS(Status
));
305 Status
= ObInsertObject(RootKey
,
307 STANDARD_RIGHTS_REQUIRED
,
311 assert(NT_SUCCESS(Status
));
312 RootKey
->RegistryHive
= CmiVolatileHive
;
313 RootKey
->KeyCellOffset
= CmiVolatileHive
->HiveHeader
->RootKeyOffset
;
314 RootKey
->KeyCell
= CmiGetCell (CmiVolatileHive
, RootKey
->KeyCellOffset
, NULL
);
315 RootKey
->ParentKey
= RootKey
;
317 RootKey
->NumberOfSubKeys
= 0;
318 RootKey
->SubKeys
= NULL
;
319 RootKey
->SizeOfSubKeys
= 0;
320 Status
= RtlCreateUnicodeString(&RootKey
->Name
, L
"Registry");
321 assert(NT_SUCCESS(Status
));
323 KeInitializeSpinLock(&CmiKeyListLock
);
325 /* Create '\Registry\Machine' key. */
326 RtlInitUnicodeString(&KeyName
,
328 InitializeObjectAttributes(&ObjectAttributes
,
333 Status
= NtCreateKey(&KeyHandle
,
334 STANDARD_RIGHTS_REQUIRED
,
340 assert(NT_SUCCESS(Status
));
342 /* Create '\Registry\User' key. */
343 RtlInitUnicodeString(&KeyName
,
345 InitializeObjectAttributes(&ObjectAttributes
,
350 Status
= NtCreateKey(&KeyHandle
,
351 STANDARD_RIGHTS_REQUIRED
,
357 assert(NT_SUCCESS(Status
));
362 CmInit2(PCHAR CommandLine
)
368 /* FIXME: Store system start options */
372 /* Create the 'CurrentControlSet' link. */
373 Status
= CmiCreateCurrentControlSetLink();
374 if (!NT_SUCCESS(Status
))
376 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
379 /* Set PICE 'Start' value to 1, if PICE debugging is enabled */
381 p1
= (PCHAR
)CommandLine
;
382 while (p1
&& (p2
= strchr(p1
, '/')))
385 if (_strnicmp(p2
, "DEBUGPORT", 9) == 0)
391 if (_strnicmp(p2
, "PICE", 4) == 0)
401 Status
= RtlWriteRegistryValue(RTL_REGISTRY_SERVICES
,
407 if (!NT_SUCCESS(Status
))
409 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
415 CmiCreateCurrentControlSetLink(VOID
)
417 RTL_QUERY_REGISTRY_TABLE QueryTable
[5];
418 WCHAR TargetNameBuffer
[80];
419 ULONG TargetNameLength
;
420 UNICODE_STRING LinkName
;
421 UNICODE_STRING LinkValue
;
427 OBJECT_ATTRIBUTES ObjectAttributes
;
430 DPRINT("CmiCreateCurrentControlSetLink() called\n");
432 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
434 QueryTable
[0].Name
= L
"Current";
435 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
436 QueryTable
[0].EntryContext
= &CurrentSet
;
438 QueryTable
[1].Name
= L
"Default";
439 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
440 QueryTable
[1].EntryContext
= &DefaultSet
;
442 QueryTable
[2].Name
= L
"Failed";
443 QueryTable
[2].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
444 QueryTable
[2].EntryContext
= &Failed
;
446 QueryTable
[3].Name
= L
"LastKnownGood";
447 QueryTable
[3].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
448 QueryTable
[3].EntryContext
= &LastKnownGood
;
450 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
451 L
"\\Registry\\Machine\\SYSTEM\\Select",
455 if (!NT_SUCCESS(Status
))
460 DPRINT("Current %ld Default %ld\n", CurrentSet
, DefaultSet
);
462 swprintf(TargetNameBuffer
,
463 L
"\\Registry\\Machine\\SYSTEM\\ControlSet%03lu",
465 TargetNameLength
= wcslen(TargetNameBuffer
) * sizeof(WCHAR
);
467 DPRINT("Link target '%S'\n", TargetNameBuffer
);
469 RtlRosInitUnicodeStringFromLiteral(&LinkName
,
470 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
471 InitializeObjectAttributes(&ObjectAttributes
,
473 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_OPENLINK
,
476 Status
= NtCreateKey(&KeyHandle
,
477 KEY_ALL_ACCESS
| KEY_CREATE_LINK
,
481 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
483 if (!NT_SUCCESS(Status
))
485 DPRINT1("NtCreateKey() failed (Status %lx)\n", Status
);
489 RtlRosInitUnicodeStringFromLiteral(&LinkValue
,
490 L
"SymbolicLinkValue");
491 Status
= NtSetValueKey(KeyHandle
,
495 (PVOID
)TargetNameBuffer
,
497 if (!NT_SUCCESS(Status
))
499 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
509 CmiConnectHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
510 IN PREGISTRY_HIVE RegistryHive
)
512 UNICODE_STRING RemainingPath
;
513 PKEY_OBJECT ParentKey
;
518 DPRINT("CmiConnectHive(%p, %p) called.\n",
519 KeyObjectAttributes
, RegistryHive
);
521 Status
= ObFindObject(KeyObjectAttributes
,
525 if (!NT_SUCCESS(Status
))
530 DPRINT ("RemainingPath %wZ\n", &RemainingPath
);
532 if ((RemainingPath
.Buffer
== NULL
) || (RemainingPath
.Buffer
[0] == 0))
534 ObDereferenceObject (ParentKey
);
535 RtlFreeUnicodeString(&RemainingPath
);
536 return STATUS_OBJECT_NAME_COLLISION
;
539 /* If RemainingPath contains \ we must return error
540 because CmiConnectHive() can not create trees */
541 SubName
= RemainingPath
.Buffer
;
542 if (*SubName
== L
'\\')
545 if (wcschr (SubName
, L
'\\') != NULL
)
547 ObDereferenceObject (ParentKey
);
548 RtlFreeUnicodeString(&RemainingPath
);
549 return STATUS_OBJECT_NAME_NOT_FOUND
;
552 DPRINT("RemainingPath %wZ ParentKey %p\n",
553 &RemainingPath
, ParentKey
);
555 Status
= ObCreateObject(KernelMode
,
564 if (!NT_SUCCESS(Status
))
566 DPRINT1 ("ObCreateObject() failed (Status %lx)\n", Status
);
567 ObDereferenceObject (ParentKey
);
568 RtlFreeUnicodeString(&RemainingPath
);
572 NewKey
->RegistryHive
= RegistryHive
;
573 NewKey
->KeyCellOffset
= RegistryHive
->HiveHeader
->RootKeyOffset
;
574 NewKey
->KeyCell
= CmiGetCell (RegistryHive
, NewKey
->KeyCellOffset
, NULL
);
576 NewKey
->NumberOfSubKeys
= 0;
577 NewKey
->SubKeys
= ExAllocatePool(PagedPool
,
578 NewKey
->KeyCell
->NumberOfSubKeys
* sizeof(ULONG
));
580 if ((NewKey
->SubKeys
== NULL
) && (NewKey
->KeyCell
->NumberOfSubKeys
!= 0))
582 DPRINT("NumberOfSubKeys %d\n", NewKey
->KeyCell
->NumberOfSubKeys
);
583 ObDereferenceObject (NewKey
);
584 ObDereferenceObject (ParentKey
);
585 RtlFreeUnicodeString(&RemainingPath
);
586 return STATUS_INSUFFICIENT_RESOURCES
;
589 if (SubName
== RemainingPath
.Buffer
)
591 NewKey
->Name
= RemainingPath
;
595 Status
= RtlCreateUnicodeString(&NewKey
->Name
,
597 RtlFreeUnicodeString(&RemainingPath
);
598 if (!NT_SUCCESS(Status
))
600 DPRINT1("RtlCreateUnicodeString() failed (Status %lx)\n", Status
);
601 if (NewKey
->SubKeys
!= NULL
)
603 ExFreePool (NewKey
->SubKeys
);
605 ObDereferenceObject (NewKey
);
606 ObDereferenceObject (ParentKey
);
607 return STATUS_INSUFFICIENT_RESOURCES
;
611 CmiAddKeyToList (ParentKey
, NewKey
);
612 ObDereferenceObject (ParentKey
);
614 VERIFY_KEY_OBJECT(NewKey
);
616 /* Note: Do not dereference NewKey here! */
618 return STATUS_SUCCESS
;
623 CmiDisconnectHive (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
624 OUT PREGISTRY_HIVE
*RegistryHive
)
626 PKEY_OBJECT KeyObject
;
631 DPRINT("CmiDisconnectHive() called\n");
633 *RegistryHive
= NULL
;
635 Status
= ObOpenObjectByName (KeyObjectAttributes
,
639 STANDARD_RIGHTS_REQUIRED
,
642 if (!NT_SUCCESS(Status
))
644 DPRINT1 ("ObOpenObjectByName() failed (Status %lx)\n", Status
);
648 Status
= ObReferenceObjectByHandle (KeyHandle
,
649 STANDARD_RIGHTS_REQUIRED
,
655 if (!NT_SUCCESS(Status
))
657 DPRINT1 ("ObReferenceObjectByName() failed (Status %lx)\n", Status
);
660 DPRINT ("KeyObject %p Hive %p\n", KeyObject
, KeyObject
->RegistryHive
);
662 if (!(KeyObject
->KeyCell
->Flags
& REG_KEY_ROOT_CELL
))
664 DPRINT1 ("Key is not the Hive-Root-Key\n");
665 ObDereferenceObject (KeyObject
);
666 return STATUS_INVALID_PARAMETER
;
669 if (ObGetObjectHandleCount (KeyObject
) != 0 ||
670 ObGetObjectPointerCount (KeyObject
) != 2)
672 DPRINT1 ("Hive is still in use\n");
673 ObDereferenceObject (KeyObject
);
674 return STATUS_UNSUCCESSFUL
;
677 Hive
= KeyObject
->RegistryHive
;
679 /* Dereference KeyObject twice to delete it */
680 ObDereferenceObject (KeyObject
);
681 ObDereferenceObject (KeyObject
);
683 *RegistryHive
= Hive
;
685 DPRINT ("CmiDisconnectHive() done\n");
687 return STATUS_SUCCESS
;
692 CmiInitControlSetLink (VOID
)
694 OBJECT_ATTRIBUTES ObjectAttributes
;
695 UNICODE_STRING ControlSetKeyName
;
696 UNICODE_STRING ControlSetLinkName
;
697 UNICODE_STRING ControlSetValueName
;
701 /* Create 'ControlSet001' key */
702 RtlRosInitUnicodeStringFromLiteral (&ControlSetKeyName
,
703 L
"\\Registry\\Machine\\SYSTEM\\ControlSet001");
704 InitializeObjectAttributes (&ObjectAttributes
,
706 OBJ_CASE_INSENSITIVE
,
709 Status
= NtCreateKey (&KeyHandle
,
714 REG_OPTION_NON_VOLATILE
,
716 if (!NT_SUCCESS(Status
))
718 DPRINT1 ("NtCreateKey() failed (Status %lx)\n", Status
);
723 /* Link 'CurrentControlSet' to 'ControlSet001' key */
724 RtlRosInitUnicodeStringFromLiteral (&ControlSetLinkName
,
725 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
726 InitializeObjectAttributes (&ObjectAttributes
,
728 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_OPENLINK
,
731 Status
= NtCreateKey (&KeyHandle
,
732 KEY_ALL_ACCESS
| KEY_CREATE_LINK
,
736 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
738 if (!NT_SUCCESS(Status
))
740 DPRINT1 ("NtCreateKey() failed (Status %lx)\n", Status
);
744 RtlRosInitUnicodeStringFromLiteral (&ControlSetValueName
,
745 L
"SymbolicLinkValue");
746 Status
= NtSetValueKey (KeyHandle
,
747 &ControlSetValueName
,
750 (PVOID
)ControlSetKeyName
.Buffer
,
751 ControlSetKeyName
.Length
);
752 if (!NT_SUCCESS(Status
))
754 DPRINT1 ("NtSetValueKey() failed (Status %lx)\n", Status
);
758 return STATUS_SUCCESS
;
763 CmiInitHives(BOOLEAN SetupBoot
)
765 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
766 OBJECT_ATTRIBUTES ObjectAttributes
;
767 UNICODE_STRING FileName
;
768 UNICODE_STRING KeyName
;
769 UNICODE_STRING ValueName
;
774 WCHAR ConfigPath
[MAX_PATH
];
781 DPRINT("CmiInitHives() called\n");
783 if (SetupBoot
== TRUE
)
785 RtlRosInitUnicodeStringFromLiteral(&KeyName
,
786 L
"\\Registry\\Machine\\HARDWARE");
787 InitializeObjectAttributes(&ObjectAttributes
,
789 OBJ_CASE_INSENSITIVE
,
792 Status
= NtOpenKey(&KeyHandle
,
795 if (!NT_SUCCESS(Status
))
797 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status
);
801 RtlRosInitUnicodeStringFromLiteral(&ValueName
,
804 BufferSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 4096;
805 ValueInfo
= ExAllocatePool(PagedPool
,
807 if (ValueInfo
== NULL
)
810 return(STATUS_INSUFFICIENT_RESOURCES
);
813 Status
= NtQueryValueKey(KeyHandle
,
815 KeyValuePartialInformation
,
820 if (!NT_SUCCESS(Status
))
822 ExFreePool(ValueInfo
);
826 RtlCopyMemory(ConfigPath
,
828 ValueInfo
->DataLength
);
829 ConfigPath
[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = (WCHAR
)0;
830 ExFreePool(ValueInfo
);
834 wcscpy(ConfigPath
, L
"\\SystemRoot");
836 wcscat(ConfigPath
, L
"\\system32\\config");
838 DPRINT("ConfigPath: %S\n", ConfigPath
);
840 EndPtr
= ConfigPath
+ wcslen(ConfigPath
);
844 /* FIXME: Save boot log */
846 /* Connect the SYSTEM hive only if it has been created */
847 if (SetupBoot
== TRUE
)
849 wcscpy(EndPtr
, REG_SYSTEM_FILE_NAME
);
850 DPRINT ("ConfigPath: %S\n", ConfigPath
);
852 RtlInitUnicodeString (&KeyName
,
853 REG_SYSTEM_KEY_NAME
);
854 InitializeObjectAttributes(&ObjectAttributes
,
856 OBJ_CASE_INSENSITIVE
,
860 RtlInitUnicodeString (&FileName
,
862 Status
= CmiLoadHive (&ObjectAttributes
,
865 if (!NT_SUCCESS(Status
))
867 DPRINT1 ("CmiLoadHive() failed (Status %lx)\n", Status
);
871 Status
= CmiInitControlSetLink ();
872 if (!NT_SUCCESS(Status
))
874 DPRINT1("CmiInitControlSetLink() failed (Status %lx)\n", Status
);
879 /* Connect the SOFTWARE hive */
880 wcscpy(EndPtr
, REG_SOFTWARE_FILE_NAME
);
881 RtlInitUnicodeString (&FileName
,
883 DPRINT ("ConfigPath: %S\n", ConfigPath
);
885 RtlInitUnicodeString (&KeyName
,
886 REG_SOFTWARE_KEY_NAME
);
887 InitializeObjectAttributes(&ObjectAttributes
,
889 OBJ_CASE_INSENSITIVE
,
893 Status
= CmiLoadHive (&ObjectAttributes
,
896 if (!NT_SUCCESS(Status
))
898 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
902 /* Connect the SAM hive */
903 wcscpy(EndPtr
, REG_SAM_FILE_NAME
);
904 RtlInitUnicodeString (&FileName
,
906 DPRINT ("ConfigPath: %S\n", ConfigPath
);
908 RtlInitUnicodeString (&KeyName
,
910 InitializeObjectAttributes(&ObjectAttributes
,
912 OBJ_CASE_INSENSITIVE
,
915 Status
= CmiLoadHive (&ObjectAttributes
,
918 if (!NT_SUCCESS(Status
))
920 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
924 /* Connect the SECURITY hive */
925 wcscpy(EndPtr
, REG_SEC_FILE_NAME
);
926 RtlInitUnicodeString (&FileName
,
928 DPRINT ("ConfigPath: %S\n", ConfigPath
);
930 RtlInitUnicodeString (&KeyName
,
932 InitializeObjectAttributes(&ObjectAttributes
,
934 OBJ_CASE_INSENSITIVE
,
937 Status
= CmiLoadHive (&ObjectAttributes
,
940 if (!NT_SUCCESS(Status
))
942 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
946 /* Connect the DEFAULT hive */
947 wcscpy(EndPtr
, REG_DEFAULT_USER_FILE_NAME
);
948 RtlInitUnicodeString (&FileName
,
950 DPRINT ("ConfigPath: %S\n", ConfigPath
);
952 RtlInitUnicodeString (&KeyName
,
953 REG_DEFAULT_USER_KEY_NAME
);
954 InitializeObjectAttributes(&ObjectAttributes
,
956 OBJ_CASE_INSENSITIVE
,
959 Status
= CmiLoadHive (&ObjectAttributes
,
962 if (!NT_SUCCESS(Status
))
964 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
968 // CmiCheckRegistry(TRUE);
970 /* Start automatic hive synchronization */
971 KeInitializeDpc(&CmiHiveSyncDpc
,
972 CmiHiveSyncDpcRoutine
,
974 KeInitializeTimer(&CmiHiveSyncTimer
);
975 CmiHiveSyncEnabled
= TRUE
;
977 DPRINT("CmiInitHives() done\n");
979 return(STATUS_SUCCESS
);
984 CmShutdownRegistry(VOID
)
989 DPRINT1("CmShutdownRegistry() called\n");
991 /* Stop automatic hive synchronization */
992 CmiHiveSyncEnabled
= FALSE
;
994 /* Cancel pending hive synchronization */
995 if (CmiHiveSyncPending
== TRUE
)
997 KeCancelTimer(&CmiHiveSyncTimer
);
998 CmiHiveSyncPending
= FALSE
;
1001 /* Acquire hive list lock exclusively */
1002 KeEnterCriticalRegion();
1003 ExAcquireResourceExclusiveLite(&CmiHiveListLock
, TRUE
);
1005 Entry
= CmiHiveListHead
.Flink
;
1006 while (Entry
!= &CmiHiveListHead
)
1008 Hive
= CONTAINING_RECORD(Entry
, REGISTRY_HIVE
, HiveList
);
1010 if (!(IsNoFileHive(Hive
) || IsNoSynchHive(Hive
)))
1012 /* Acquire hive resource exclusively */
1013 ExAcquireResourceExclusiveLite(&Hive
->HiveResource
,
1016 /* Flush non-volatile hive */
1017 CmiFlushRegistryHive(Hive
);
1019 /* Release hive resource */
1020 ExReleaseResourceLite(&Hive
->HiveResource
);
1023 Entry
= Entry
->Flink
;
1026 /* Release hive list lock */
1027 ExReleaseResourceLite(&CmiHiveListLock
);
1028 KeLeaveCriticalRegion();
1030 DPRINT1("CmShutdownRegistry() done\n");
1035 CmiHiveSyncRoutine(PVOID DeferredContext
)
1037 PREGISTRY_HIVE Hive
;
1040 DPRINT("CmiHiveSyncRoutine() called\n");
1042 CmiHiveSyncPending
= FALSE
;
1044 /* Acquire hive list lock exclusively */
1045 KeEnterCriticalRegion();
1046 ExAcquireResourceExclusiveLite(&CmiHiveListLock
, TRUE
);
1048 Entry
= CmiHiveListHead
.Flink
;
1049 while (Entry
!= &CmiHiveListHead
)
1051 Hive
= CONTAINING_RECORD(Entry
, REGISTRY_HIVE
, HiveList
);
1053 if (!(IsNoFileHive(Hive
) || IsNoSynchHive(Hive
)))
1055 /* Acquire hive resource exclusively */
1056 ExAcquireResourceExclusiveLite(&Hive
->HiveResource
,
1059 /* Flush non-volatile hive */
1060 CmiFlushRegistryHive(Hive
);
1062 /* Release hive resource */
1063 ExReleaseResourceLite(&Hive
->HiveResource
);
1066 Entry
= Entry
->Flink
;
1069 /* Release hive list lock */
1070 ExReleaseResourceLite(&CmiHiveListLock
);
1071 KeLeaveCriticalRegion();
1073 DPRINT("DeferredContext %x\n", DeferredContext
);
1074 ExFreePool(DeferredContext
);
1076 DPRINT("CmiHiveSyncRoutine() done\n");
1081 CmiHiveSyncDpcRoutine(PKDPC Dpc
,
1082 PVOID DeferredContext
,
1083 PVOID SystemArgument1
,
1084 PVOID SystemArgument2
)
1086 PWORK_QUEUE_ITEM WorkQueueItem
;
1088 WorkQueueItem
= ExAllocatePool(NonPagedPool
,
1089 sizeof(WORK_QUEUE_ITEM
));
1090 if (WorkQueueItem
== NULL
)
1092 DbgPrint("Failed to allocate work item\n");
1096 ExInitializeWorkItem(WorkQueueItem
,
1100 DPRINT("DeferredContext %x\n", WorkQueueItem
);
1101 ExQueueWorkItem(WorkQueueItem
,
1109 LARGE_INTEGER Timeout
;
1111 DPRINT("CmiSyncHives() called\n");
1113 if (CmiHiveSyncEnabled
== FALSE
||
1114 CmiHiveSyncPending
== TRUE
)
1117 CmiHiveSyncPending
= TRUE
;
1120 #if defined(__GNUC__)
1121 Timeout
.QuadPart
= -50000000LL;
1123 Timeout
.QuadPart
= -50000000;
1125 KeSetTimer(&CmiHiveSyncTimer
,