1 /* $Id: registry.c,v 1.117 2004/01/08 15:02:45 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 #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 CmiHiveLinkListHead
;
35 LIST_ENTRY CmiHiveListHead
;
36 ERESOURCE CmiHiveListLock
;
38 volatile BOOLEAN CmiHiveSyncEnabled
= FALSE
;
39 volatile BOOLEAN CmiHiveSyncPending
= FALSE
;
41 KTIMER CmiHiveSyncTimer
;
43 static GENERIC_MAPPING CmiKeyMapping
=
44 {KEY_READ
, KEY_WRITE
, KEY_EXECUTE
, KEY_ALL_ACCESS
};
49 CmiCheckKey(BOOLEAN Verbose
,
53 CmiCreateCurrentControlSetLink(VOID
);
56 CmiHiveSyncDpcRoutine(PKDPC Dpc
,
57 PVOID DeferredContext
,
58 PVOID SystemArgument1
,
59 PVOID SystemArgument2
);
61 /* FUNCTIONS ****************************************************************/
64 CmiCheckSubKeys(BOOLEAN Verbose
,
67 OBJECT_ATTRIBUTES ObjectAttributes
;
68 PKEY_NODE_INFORMATION KeyInfo
;
69 WCHAR KeyBuffer
[MAX_PATH
];
70 UNICODE_STRING KeyPath
;
81 BufferSize
= sizeof(KEY_NODE_INFORMATION
) + 4096;
82 KeyInfo
= ExAllocatePool(PagedPool
, BufferSize
);
84 Status
= NtEnumerateKey(Key
,
90 if (!NT_SUCCESS(Status
))
93 if (Status
== STATUS_NO_MORE_ENTRIES
)
94 Status
= STATUS_SUCCESS
;
100 KeyInfo
->NameLength
/ sizeof(WCHAR
));
104 DbgPrint("Key: %S\n", Name
);
107 /* FIXME: Check info. */
111 wcscpy(KeyBuffer
, L
"\\Registry\\");
112 wcscat(KeyBuffer
, Name
);
114 RtlInitUnicodeString(&KeyPath
, KeyBuffer
);
116 InitializeObjectAttributes(&ObjectAttributes
,
118 OBJ_CASE_INSENSITIVE
,
122 Status
= NtOpenKey(&SubKey
,
126 assert(NT_SUCCESS(Status
));
128 CmiCheckKey(Verbose
, SubKey
);
135 assert(NT_SUCCESS(Status
));
140 CmiCheckValues(BOOLEAN Verbose
,
143 PKEY_NODE_INFORMATION ValueInfo
;
144 WCHAR Name
[MAX_PATH
];
153 BufferSize
= sizeof(KEY_NODE_INFORMATION
) + 4096;
154 ValueInfo
= ExAllocatePool(PagedPool
, BufferSize
);
156 Status
= NtEnumerateValueKey(Key
,
162 if (!NT_SUCCESS(Status
))
164 ExFreePool(ValueInfo
);
165 if (Status
== STATUS_NO_MORE_ENTRIES
)
166 Status
= STATUS_SUCCESS
;
172 ValueInfo
->NameLength
/ sizeof(WCHAR
));
176 DbgPrint("Value: %S\n", Name
);
179 /* FIXME: Check info. */
181 ExFreePool(ValueInfo
);
186 assert(NT_SUCCESS(Status
));
191 CmiCheckKey(BOOLEAN Verbose
,
194 CmiCheckValues(Verbose
, Key
);
195 CmiCheckSubKeys(Verbose
, Key
);
200 CmiCheckByName(BOOLEAN Verbose
,
203 OBJECT_ATTRIBUTES ObjectAttributes
;
204 WCHAR KeyPathBuffer
[MAX_PATH
];
205 UNICODE_STRING KeyPath
;
209 wcscpy(KeyPathBuffer
, L
"\\Registry\\");
210 wcscat(KeyPathBuffer
, KeyName
);
212 RtlInitUnicodeString(&KeyPath
, KeyPathBuffer
);
214 InitializeObjectAttributes(&ObjectAttributes
,
216 OBJ_CASE_INSENSITIVE
,
220 Status
= NtOpenKey(&Key
,
226 if (!NT_SUCCESS(Status
))
228 DbgPrint("KeyPath %wZ Status: %.08x", KeyPath
, Status
);
229 DbgPrint("KeyPath %S Status: %.08x", KeyPath
.Buffer
, Status
);
230 assert(NT_SUCCESS(Status
));
234 CmiCheckKey(Verbose
, Key
);
241 CmiCheckRegistry(BOOLEAN Verbose
)
244 DbgPrint("Checking registry internals\n");
246 CmiCheckByName(Verbose
, L
"Machine");
247 CmiCheckByName(Verbose
, L
"User");
252 CmInitializeRegistry(VOID
)
254 OBJECT_ATTRIBUTES ObjectAttributes
;
255 UNICODE_STRING KeyName
;
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
= CmiObjectQueryName
;
278 CmiKeyType
->OkayToClose
= NULL
;
279 CmiKeyType
->Create
= CmiObjectCreate
;
280 CmiKeyType
->DuplicationNotify
= NULL
;
281 RtlInitUnicodeString(&CmiKeyType
->TypeName
, L
"Key");
283 ObpCreateTypeObject (CmiKeyType
);
285 /* Initialize the hive link list */
286 InitializeListHead(&CmiHiveLinkListHead
);
288 /* Initialize the hive list */
289 InitializeListHead(&CmiHiveListHead
);
290 ExInitializeResourceLite(&CmiHiveListLock
);
292 /* Build volatile registry store */
293 Status
= CmiCreateVolatileHive (&CmiVolatileHive
);
294 assert(NT_SUCCESS(Status
));
296 /* Create '\Registry' key. */
297 RtlInitUnicodeString(&KeyName
, REG_ROOT_KEY_NAME
);
298 InitializeObjectAttributes(&ObjectAttributes
, &KeyName
, 0, NULL
, NULL
);
299 Status
= ObCreateObject(KernelMode
,
308 assert(NT_SUCCESS(Status
));
309 Status
= ObInsertObject(RootKey
,
311 STANDARD_RIGHTS_REQUIRED
,
315 assert(NT_SUCCESS(Status
));
316 RootKey
->RegistryHive
= CmiVolatileHive
;
317 RootKey
->KeyCellOffset
= CmiVolatileHive
->HiveHeader
->RootKeyOffset
;
318 RootKey
->KeyCell
= CmiGetCell (CmiVolatileHive
, RootKey
->KeyCellOffset
, NULL
);
319 RootKey
->ParentKey
= RootKey
;
321 RootKey
->NumberOfSubKeys
= 0;
322 RootKey
->SubKeys
= NULL
;
323 RootKey
->SizeOfSubKeys
= 0;
324 Status
= RtlCreateUnicodeString(&RootKey
->Name
, L
"Registry");
325 assert(NT_SUCCESS(Status
));
327 KeInitializeSpinLock(&CmiKeyListLock
);
329 /* Create '\Registry\Machine' key. */
330 RtlInitUnicodeString(&KeyName
,
332 InitializeObjectAttributes(&ObjectAttributes
,
337 Status
= NtCreateKey(&KeyHandle
,
338 STANDARD_RIGHTS_REQUIRED
,
344 assert(NT_SUCCESS(Status
));
346 /* Create '\Registry\User' key. */
347 RtlInitUnicodeString(&KeyName
,
349 InitializeObjectAttributes(&ObjectAttributes
,
354 Status
= NtCreateKey(&KeyHandle
,
355 STANDARD_RIGHTS_REQUIRED
,
361 assert(NT_SUCCESS(Status
));
366 CmInit2(PCHAR CommandLine
)
372 /* FIXME: Store system start options */
376 /* Create the 'CurrentControlSet' link. */
377 Status
= CmiCreateCurrentControlSetLink();
378 if (!NT_SUCCESS(Status
))
380 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
383 /* Set PICE 'Start' value to 1, if PICE debugging is enabled */
385 p1
= (PCHAR
)CommandLine
;
386 while (p1
&& (p2
= strchr(p1
, '/')))
389 if (_strnicmp(p2
, "DEBUGPORT", 9) == 0)
395 if (_strnicmp(p2
, "PICE", 4) == 0)
405 Status
= RtlWriteRegistryValue(RTL_REGISTRY_SERVICES
,
411 if (!NT_SUCCESS(Status
))
413 KEBUGCHECK(CONFIG_INITIALIZATION_FAILED
);
419 CmiCreateCurrentControlSetLink(VOID
)
421 RTL_QUERY_REGISTRY_TABLE QueryTable
[5];
422 WCHAR TargetNameBuffer
[80];
423 ULONG TargetNameLength
;
424 UNICODE_STRING LinkName
;
425 UNICODE_STRING LinkValue
;
431 OBJECT_ATTRIBUTES ObjectAttributes
;
434 DPRINT("CmiCreateCurrentControlSetLink() called\n");
436 RtlZeroMemory(&QueryTable
, sizeof(QueryTable
));
438 QueryTable
[0].Name
= L
"Current";
439 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
440 QueryTable
[0].EntryContext
= &CurrentSet
;
442 QueryTable
[1].Name
= L
"Default";
443 QueryTable
[1].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
444 QueryTable
[1].EntryContext
= &DefaultSet
;
446 QueryTable
[2].Name
= L
"Failed";
447 QueryTable
[2].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
448 QueryTable
[2].EntryContext
= &Failed
;
450 QueryTable
[3].Name
= L
"LastKnownGood";
451 QueryTable
[3].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
452 QueryTable
[3].EntryContext
= &LastKnownGood
;
454 Status
= RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE
,
455 L
"\\Registry\\Machine\\SYSTEM\\Select",
459 if (!NT_SUCCESS(Status
))
464 DPRINT("Current %ld Default %ld\n", CurrentSet
, DefaultSet
);
466 swprintf(TargetNameBuffer
,
467 L
"\\Registry\\Machine\\SYSTEM\\ControlSet%03lu",
469 TargetNameLength
= wcslen(TargetNameBuffer
) * sizeof(WCHAR
);
471 DPRINT("Link target '%S'\n", TargetNameBuffer
);
473 RtlRosInitUnicodeStringFromLiteral(&LinkName
,
474 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
475 InitializeObjectAttributes(&ObjectAttributes
,
477 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_OPENLINK
,
480 Status
= NtCreateKey(&KeyHandle
,
481 KEY_ALL_ACCESS
| KEY_CREATE_LINK
,
485 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
487 if (!NT_SUCCESS(Status
))
489 DPRINT1("NtCreateKey() failed (Status %lx)\n", Status
);
493 RtlRosInitUnicodeStringFromLiteral(&LinkValue
,
494 L
"SymbolicLinkValue");
495 Status
= NtSetValueKey(KeyHandle
,
499 (PVOID
)TargetNameBuffer
,
501 if (!NT_SUCCESS(Status
))
503 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status
);
513 CmiConnectHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
514 IN PREGISTRY_HIVE RegistryHive
)
516 UNICODE_STRING RemainingPath
;
517 PKEY_OBJECT ParentKey
;
522 DPRINT("CmiConnectHive(%p, %p) called.\n",
523 KeyObjectAttributes
, RegistryHive
);
525 Status
= ObFindObject(KeyObjectAttributes
,
529 if (!NT_SUCCESS(Status
))
534 DPRINT ("RemainingPath %wZ\n", &RemainingPath
);
536 if ((RemainingPath
.Buffer
== NULL
) || (RemainingPath
.Buffer
[0] == 0))
538 ObDereferenceObject (ParentKey
);
539 return STATUS_OBJECT_NAME_COLLISION
;
542 /* If RemainingPath contains \ we must return error
543 because CmiConnectHive() can not create trees */
544 SubName
= RemainingPath
.Buffer
;
545 if (*SubName
== L
'\\')
548 if (wcschr (SubName
, L
'\\') != NULL
)
550 ObDereferenceObject (ParentKey
);
551 return STATUS_OBJECT_NAME_NOT_FOUND
;
554 DPRINT("RemainingPath %wZ ParentKey %p\n",
555 &RemainingPath
, ParentKey
);
557 Status
= ObCreateObject(KernelMode
,
566 if (!NT_SUCCESS(Status
))
568 DPRINT1 ("ObCreateObject() failed (Status %lx)\n", Status
);
569 ObDereferenceObject (ParentKey
);
573 NewKey
->RegistryHive
= RegistryHive
;
574 NewKey
->KeyCellOffset
= RegistryHive
->HiveHeader
->RootKeyOffset
;
575 NewKey
->KeyCell
= CmiGetCell (RegistryHive
, NewKey
->KeyCellOffset
, NULL
);
577 NewKey
->NumberOfSubKeys
= 0;
578 NewKey
->SubKeys
= ExAllocatePool(PagedPool
,
579 NewKey
->KeyCell
->NumberOfSubKeys
* sizeof(ULONG
));
581 if ((NewKey
->SubKeys
== NULL
) && (NewKey
->KeyCell
->NumberOfSubKeys
!= 0))
583 DPRINT("NumberOfSubKeys %d\n", NewKey
->KeyCell
->NumberOfSubKeys
);
584 ObDereferenceObject (NewKey
);
585 ObDereferenceObject (ParentKey
);
586 return STATUS_INSUFFICIENT_RESOURCES
;
589 Status
= RtlCreateUnicodeString(&NewKey
->Name
,
591 if (!NT_SUCCESS(Status
))
593 DPRINT1("RtlCreateUnicodeString() failed (Status %lx)\n", Status
);
594 if (NewKey
->SubKeys
!= NULL
)
596 ExFreePool (NewKey
->SubKeys
);
598 ObDereferenceObject (NewKey
);
599 ObDereferenceObject (ParentKey
);
600 return STATUS_INSUFFICIENT_RESOURCES
;
603 Status
= CmiAddKeyToHashTable(ParentKey
->RegistryHive
,
605 ParentKey
->KeyCellOffset
,
606 NewKey
->RegistryHive
,
608 NewKey
->KeyCellOffset
);
609 if (!NT_SUCCESS(Status
))
611 DPRINT1("CmiAddKeyToHashTable() failed (Status %lx)\n", Status
);
612 if (NewKey
->SubKeys
!= NULL
)
614 ExFreePool (NewKey
->SubKeys
);
616 ObDereferenceObject (NewKey
);
617 ObDereferenceObject (ParentKey
);
621 CmiAddKeyToList (ParentKey
, NewKey
);
623 VERIFY_KEY_OBJECT(NewKey
);
625 ObDereferenceObject (NewKey
);
626 ObDereferenceObject (ParentKey
);
628 return STATUS_SUCCESS
;
633 CmiDisconnectHive (IN POBJECT_ATTRIBUTES KeyObjectAttributes
,
634 OUT PREGISTRY_HIVE
*RegistryHive
)
636 PKEY_OBJECT KeyObject
;
641 PKEY_CELL ParentKeyCell
;
642 PHASH_TABLE_CELL HashCell
;
645 DPRINT("CmiDisconnectHive() called\n");
647 *RegistryHive
= NULL
;
649 Status
= ObOpenObjectByName (KeyObjectAttributes
,
653 STANDARD_RIGHTS_REQUIRED
,
656 if (!NT_SUCCESS(Status
))
658 DPRINT1 ("ObOpenObjectByName() failed (Status %lx)\n", Status
);
662 Status
= ObReferenceObjectByHandle (KeyHandle
,
663 STANDARD_RIGHTS_REQUIRED
,
669 if (!NT_SUCCESS(Status
))
671 DPRINT1 ("ObReferenceObjectByName() failed (Status %lx)\n", Status
);
674 DPRINT ("KeyObject %p Hive %p\n", KeyObject
, KeyObject
->RegistryHive
);
676 if (!(KeyObject
->KeyCell
->Flags
& REG_KEY_ROOT_CELL
))
678 DPRINT1 ("Key is not the Hive-Root-Key\n");
679 ObDereferenceObject (KeyObject
);
680 return STATUS_INVALID_PARAMETER
;
683 if (ObGetObjectHandleCount (KeyObject
) != 0 ||
684 ObGetObjectPointerCount (KeyObject
) != 2)
686 DPRINT1 ("Hive is still in use\n");
687 ObDereferenceObject (KeyObject
);
688 return STATUS_UNSUCCESSFUL
;
691 Hive
= KeyObject
->RegistryHive
;
693 CmiRemoveKeyFromList (KeyObject
);
695 /* Remove hive link and hash table entry */
696 Entry
= CmiHiveLinkListHead
.Flink
;
697 while (Entry
!= &CmiHiveLinkListHead
)
699 HiveLink
= CONTAINING_RECORD(Entry
, HIVE_LINK
, Entry
);
700 if (HiveLink
->SubKeyRegistryHive
== Hive
&&
701 HiveLink
->SubKeyCellOffset
== KeyObject
->KeyCellOffset
)
703 ParentKeyCell
= CmiGetCell (HiveLink
->ParentKeyRegistryHive
,
704 HiveLink
->ParentKeyCellOffset
,
706 if (ParentKeyCell
!= NULL
)
708 HashCell
= CmiGetCell (HiveLink
->ParentKeyRegistryHive
,
709 ParentKeyCell
->HashTableOffset
,
711 if (HashCell
!= NULL
)
713 CmiRemoveKeyFromHashTable(HiveLink
->ParentKeyRegistryHive
,
715 (BLOCK_OFFSET
)((ULONG
)HiveLink
| 1));
716 ParentKeyCell
->NumberOfSubKeys
--;
720 RemoveEntryList (Entry
);
725 Entry
= Entry
->Flink
;
728 ObDereferenceObject (KeyObject
);
730 *RegistryHive
= Hive
;
732 DPRINT ("CmiDisconnectHive() done\n");
734 return STATUS_SUCCESS
;
739 CmiInitControlSetLink (VOID
)
741 OBJECT_ATTRIBUTES ObjectAttributes
;
742 UNICODE_STRING ControlSetKeyName
;
743 UNICODE_STRING ControlSetLinkName
;
744 UNICODE_STRING ControlSetValueName
;
748 /* Create 'ControlSet001' key */
749 RtlRosInitUnicodeStringFromLiteral (&ControlSetKeyName
,
750 L
"\\Registry\\Machine\\SYSTEM\\ControlSet001");
751 InitializeObjectAttributes (&ObjectAttributes
,
753 OBJ_CASE_INSENSITIVE
,
756 Status
= NtCreateKey (&KeyHandle
,
761 REG_OPTION_NON_VOLATILE
,
763 if (!NT_SUCCESS(Status
))
765 DPRINT1 ("NtCreateKey() failed (Status %lx)\n", Status
);
770 /* Link 'CurrentControlSet' to 'ControlSet001' key */
771 RtlRosInitUnicodeStringFromLiteral (&ControlSetLinkName
,
772 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet");
773 InitializeObjectAttributes (&ObjectAttributes
,
775 OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
| OBJ_OPENLINK
,
778 Status
= NtCreateKey (&KeyHandle
,
779 KEY_ALL_ACCESS
| KEY_CREATE_LINK
,
783 REG_OPTION_VOLATILE
| REG_OPTION_CREATE_LINK
,
785 if (!NT_SUCCESS(Status
))
787 DPRINT1 ("NtCreateKey() failed (Status %lx)\n", Status
);
791 RtlRosInitUnicodeStringFromLiteral (&ControlSetValueName
,
792 L
"SymbolicLinkValue");
793 Status
= NtSetValueKey (KeyHandle
,
794 &ControlSetValueName
,
797 (PVOID
)ControlSetKeyName
.Buffer
,
798 ControlSetKeyName
.Length
);
799 if (!NT_SUCCESS(Status
))
801 DPRINT1 ("NtSetValueKey() failed (Status %lx)\n", Status
);
805 return STATUS_SUCCESS
;
810 CmiInitHives(BOOLEAN SetupBoot
)
812 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
813 OBJECT_ATTRIBUTES ObjectAttributes
;
814 UNICODE_STRING FileName
;
815 UNICODE_STRING KeyName
;
816 UNICODE_STRING ValueName
;
821 WCHAR ConfigPath
[MAX_PATH
];
828 DPRINT("CmiInitHives() called\n");
830 if (SetupBoot
== TRUE
)
832 RtlRosInitUnicodeStringFromLiteral(&KeyName
,
833 L
"\\Registry\\Machine\\HARDWARE");
834 InitializeObjectAttributes(&ObjectAttributes
,
836 OBJ_CASE_INSENSITIVE
,
839 Status
= NtOpenKey(&KeyHandle
,
842 if (!NT_SUCCESS(Status
))
844 DPRINT1("NtOpenKey() failed (Status %lx)\n", Status
);
848 RtlRosInitUnicodeStringFromLiteral(&ValueName
,
851 BufferSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + 4096;
852 ValueInfo
= ExAllocatePool(PagedPool
,
854 if (ValueInfo
== NULL
)
857 return(STATUS_INSUFFICIENT_RESOURCES
);
860 Status
= NtQueryValueKey(KeyHandle
,
862 KeyValuePartialInformation
,
867 if (!NT_SUCCESS(Status
))
869 ExFreePool(ValueInfo
);
873 RtlCopyMemory(ConfigPath
,
875 ValueInfo
->DataLength
);
876 ConfigPath
[ValueInfo
->DataLength
/ sizeof(WCHAR
)] = (WCHAR
)0;
877 ExFreePool(ValueInfo
);
881 wcscpy(ConfigPath
, L
"\\SystemRoot");
883 wcscat(ConfigPath
, L
"\\system32\\config");
885 DPRINT("ConfigPath: %S\n", ConfigPath
);
887 EndPtr
= ConfigPath
+ wcslen(ConfigPath
);
891 /* FIXME: Save boot log */
893 /* Connect the SYSTEM hive only if it has been created */
894 if (SetupBoot
== TRUE
)
896 wcscpy(EndPtr
, REG_SYSTEM_FILE_NAME
);
897 DPRINT ("ConfigPath: %S\n", ConfigPath
);
899 RtlInitUnicodeString (&KeyName
,
900 REG_SYSTEM_KEY_NAME
);
901 InitializeObjectAttributes(&ObjectAttributes
,
903 OBJ_CASE_INSENSITIVE
,
907 RtlInitUnicodeString (&FileName
,
909 Status
= CmiLoadHive (&ObjectAttributes
,
912 if (!NT_SUCCESS(Status
))
914 DPRINT1 ("CmiLoadHive() failed (Status %lx)\n", Status
);
918 Status
= CmiInitControlSetLink ();
919 if (!NT_SUCCESS(Status
))
921 DPRINT1("CmiInitControlSetLink() failed (Status %lx)\n", Status
);
926 /* Connect the SOFTWARE hive */
927 wcscpy(EndPtr
, REG_SOFTWARE_FILE_NAME
);
928 RtlInitUnicodeString (&FileName
,
930 DPRINT ("ConfigPath: %S\n", ConfigPath
);
932 RtlInitUnicodeString (&KeyName
,
933 REG_SOFTWARE_KEY_NAME
);
934 InitializeObjectAttributes(&ObjectAttributes
,
936 OBJ_CASE_INSENSITIVE
,
940 Status
= CmiLoadHive (&ObjectAttributes
,
943 if (!NT_SUCCESS(Status
))
945 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
949 /* Connect the SAM hive */
950 wcscpy(EndPtr
, REG_SAM_FILE_NAME
);
951 RtlInitUnicodeString (&FileName
,
953 DPRINT ("ConfigPath: %S\n", ConfigPath
);
955 RtlInitUnicodeString (&KeyName
,
957 InitializeObjectAttributes(&ObjectAttributes
,
959 OBJ_CASE_INSENSITIVE
,
962 Status
= CmiLoadHive (&ObjectAttributes
,
965 if (!NT_SUCCESS(Status
))
967 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
971 /* Connect the SECURITY hive */
972 wcscpy(EndPtr
, REG_SEC_FILE_NAME
);
973 RtlInitUnicodeString (&FileName
,
975 DPRINT ("ConfigPath: %S\n", ConfigPath
);
977 RtlInitUnicodeString (&KeyName
,
979 InitializeObjectAttributes(&ObjectAttributes
,
981 OBJ_CASE_INSENSITIVE
,
984 Status
= CmiLoadHive (&ObjectAttributes
,
987 if (!NT_SUCCESS(Status
))
989 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
993 /* Connect the DEFAULT hive */
994 wcscpy(EndPtr
, REG_DEFAULT_USER_FILE_NAME
);
995 RtlInitUnicodeString (&FileName
,
997 DPRINT ("ConfigPath: %S\n", ConfigPath
);
999 RtlInitUnicodeString (&KeyName
,
1000 REG_DEFAULT_USER_KEY_NAME
);
1001 InitializeObjectAttributes(&ObjectAttributes
,
1003 OBJ_CASE_INSENSITIVE
,
1006 Status
= CmiLoadHive (&ObjectAttributes
,
1009 if (!NT_SUCCESS(Status
))
1011 DPRINT1("CmiInitializeHive() failed (Status %lx)\n", Status
);
1015 // CmiCheckRegistry(TRUE);
1017 /* Start automatic hive synchronization */
1018 KeInitializeDpc(&CmiHiveSyncDpc
,
1019 CmiHiveSyncDpcRoutine
,
1021 KeInitializeTimer(&CmiHiveSyncTimer
);
1022 CmiHiveSyncEnabled
= TRUE
;
1024 DPRINT("CmiInitHives() done\n");
1026 return(STATUS_SUCCESS
);
1031 CmShutdownRegistry(VOID
)
1033 PREGISTRY_HIVE Hive
;
1036 DPRINT1("CmShutdownRegistry() called\n");
1038 /* Stop automatic hive synchronization */
1039 CmiHiveSyncEnabled
= FALSE
;
1041 /* Cancel pending hive synchronization */
1042 if (CmiHiveSyncPending
== TRUE
)
1044 KeCancelTimer(&CmiHiveSyncTimer
);
1045 CmiHiveSyncPending
= FALSE
;
1048 /* Acquire hive list lock exclusively */
1049 KeEnterCriticalRegion();
1050 ExAcquireResourceExclusiveLite(&CmiHiveListLock
, TRUE
);
1052 Entry
= CmiHiveListHead
.Flink
;
1053 while (Entry
!= &CmiHiveListHead
)
1055 Hive
= CONTAINING_RECORD(Entry
, REGISTRY_HIVE
, HiveList
);
1057 if (!(IsNoFileHive(Hive
) || IsNoSynchHive(Hive
)))
1059 /* Acquire hive resource exclusively */
1060 ExAcquireResourceExclusiveLite(&Hive
->HiveResource
,
1063 /* Flush non-volatile hive */
1064 CmiFlushRegistryHive(Hive
);
1066 /* Release hive resource */
1067 ExReleaseResourceLite(&Hive
->HiveResource
);
1070 Entry
= Entry
->Flink
;
1073 /* Release hive list lock */
1074 ExReleaseResourceLite(&CmiHiveListLock
);
1075 KeLeaveCriticalRegion();
1077 DPRINT1("CmShutdownRegistry() done\n");
1082 CmiHiveSyncRoutine(PVOID DeferredContext
)
1084 PREGISTRY_HIVE Hive
;
1087 DPRINT("CmiHiveSyncRoutine() called\n");
1089 CmiHiveSyncPending
= FALSE
;
1091 /* Acquire hive list lock exclusively */
1092 KeEnterCriticalRegion();
1093 ExAcquireResourceExclusiveLite(&CmiHiveListLock
, TRUE
);
1095 Entry
= CmiHiveListHead
.Flink
;
1096 while (Entry
!= &CmiHiveListHead
)
1098 Hive
= CONTAINING_RECORD(Entry
, REGISTRY_HIVE
, HiveList
);
1100 if (!(IsNoFileHive(Hive
) || IsNoSynchHive(Hive
)))
1102 /* Acquire hive resource exclusively */
1103 ExAcquireResourceExclusiveLite(&Hive
->HiveResource
,
1106 /* Flush non-volatile hive */
1107 CmiFlushRegistryHive(Hive
);
1109 /* Release hive resource */
1110 ExReleaseResourceLite(&Hive
->HiveResource
);
1113 Entry
= Entry
->Flink
;
1116 /* Release hive list lock */
1117 ExReleaseResourceLite(&CmiHiveListLock
);
1118 KeLeaveCriticalRegion();
1120 DPRINT("DeferredContext %x\n", DeferredContext
);
1121 ExFreePool(DeferredContext
);
1123 DPRINT("CmiHiveSyncRoutine() done\n");
1128 CmiHiveSyncDpcRoutine(PKDPC Dpc
,
1129 PVOID DeferredContext
,
1130 PVOID SystemArgument1
,
1131 PVOID SystemArgument2
)
1133 PWORK_QUEUE_ITEM WorkQueueItem
;
1135 WorkQueueItem
= ExAllocatePool(NonPagedPool
,
1136 sizeof(WORK_QUEUE_ITEM
));
1137 if (WorkQueueItem
== NULL
)
1139 DbgPrint("Failed to allocate work item\n");
1143 ExInitializeWorkItem(WorkQueueItem
,
1147 DPRINT("DeferredContext %x\n", WorkQueueItem
);
1148 ExQueueWorkItem(WorkQueueItem
,
1156 LARGE_INTEGER Timeout
;
1158 DPRINT("CmiSyncHives() called\n");
1160 if (CmiHiveSyncEnabled
== FALSE
||
1161 CmiHiveSyncPending
== TRUE
)
1164 CmiHiveSyncPending
= TRUE
;
1167 #if defined(__GNUC__)
1168 Timeout
.QuadPart
= -50000000LL;
1170 Timeout
.QuadPart
= -50000000;
1172 KeSetTimer(&CmiHiveSyncTimer
,