diff --git a/reactos/ntoskrnl/cm/import.c b/reactos/ntoskrnl/cm/import.c
index 48cfaacee5e..f20c3a4c4ea 100644
--- a/reactos/ntoskrnl/cm/import.c
+++ b/reactos/ntoskrnl/cm/import.c
@@ -91,20 +91,9 @@ CmImportSystemHive(PCHAR ChunkBase,
{
*RegistryHive = NULL;
- DPRINT ("CmImportSystemHive() called\n");
-
- if (strncmp (ChunkBase, "regf", 4))
- {
- DPRINT1 ("Found invalid '%.*s' magic\n", 4, ChunkBase);
- return FALSE;
- }
-
- DPRINT ("Found '%.*s' magic\n", 4, ChunkBase);
-
/* Import the binary system hive (non-volatile, offset-based, permanent) */
if (!CmImportBinaryHive (ChunkBase, ChunkSize, 0, RegistryHive))
{
- DPRINT1 ("CmiImportBinaryHive() failed\n");
return FALSE;
}
@@ -125,123 +114,11 @@ CmImportHardwareHive(PCHAR ChunkBase,
ULONG ChunkSize,
OUT PEREGISTRY_HIVE *RegistryHive)
{
- OBJECT_ATTRIBUTES ObjectAttributes;
- UNICODE_STRING KeyName;
- HANDLE HardwareKey;
- ULONG Disposition;
- NTSTATUS Status;
*RegistryHive = NULL;
- DPRINT ("CmImportHardwareHive() called\n");
-
- if (ChunkBase == NULL &&
- ChunkSize == 0)
- {
- /* Create '\Registry\Machine\HARDWARE' key. */
- RtlInitUnicodeString (&KeyName,
- REG_HARDWARE_KEY_NAME);
- InitializeObjectAttributes (&ObjectAttributes,
- &KeyName,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
- Status = ZwCreateKey (&HardwareKey,
- KEY_ALL_ACCESS,
- &ObjectAttributes,
- 0,
- NULL,
- REG_OPTION_VOLATILE,
- &Disposition);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtCreateKey() failed, status: 0x%x\n", Status);
- return FALSE;
- }
- ZwClose (HardwareKey);
-
- /* Create '\Registry\Machine\HARDWARE\DESCRIPTION' key. */
- RtlInitUnicodeString(&KeyName,
- REG_DESCRIPTION_KEY_NAME);
- InitializeObjectAttributes (&ObjectAttributes,
- &KeyName,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
- Status = ZwCreateKey (&HardwareKey,
- KEY_ALL_ACCESS,
- &ObjectAttributes,
- 0,
- NULL,
- REG_OPTION_VOLATILE,
- &Disposition);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtCreateKey() failed, status: 0x%x\n", Status);
- return FALSE;
- }
- ZwClose (HardwareKey);
-
- /* Create '\Registry\Machine\HARDWARE\DEVICEMAP' key. */
- RtlInitUnicodeString (&KeyName,
- REG_DEVICEMAP_KEY_NAME);
- InitializeObjectAttributes (&ObjectAttributes,
- &KeyName,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
- Status = ZwCreateKey (&HardwareKey,
- KEY_ALL_ACCESS,
- &ObjectAttributes,
- 0,
- NULL,
- REG_OPTION_VOLATILE,
- &Disposition);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtCreateKey() failed, status: 0x%x\n", Status);
- return FALSE;
- }
- ZwClose (HardwareKey);
-
- /* Create '\Registry\Machine\HARDWARE\RESOURCEMAP' key. */
- RtlInitUnicodeString(&KeyName,
- REG_RESOURCEMAP_KEY_NAME);
- InitializeObjectAttributes (&ObjectAttributes,
- &KeyName,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
- Status = ZwCreateKey (&HardwareKey,
- KEY_ALL_ACCESS,
- &ObjectAttributes,
- 0,
- NULL,
- REG_OPTION_VOLATILE,
- &Disposition);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("NtCreateKey() failed, status: 0x%x\n", Status);
- return FALSE;
- }
- ZwClose (HardwareKey);
-
- return TRUE;
- }
-
- /* Check the hive magic */
- if (strncmp (ChunkBase, "regf", 4))
- {
- DPRINT1 ("Found invalid '%.*s' magic\n", 4, ChunkBase);
- return FALSE;
- }
-
- DPRINT ("Found '%.*s' magic\n", 4, ChunkBase);
- DPRINT ("ChunkBase %lx ChunkSize %lu\n", ChunkBase, ChunkSize);
-
/* Import the binary system hive (volatile, offset-based, permanent) */
if (!CmImportBinaryHive (ChunkBase, ChunkSize, HIVE_NO_FILE, RegistryHive))
{
- DPRINT1 ("CmiImportBinaryHive() failed\n");
return FALSE;
}
diff --git a/reactos/ntoskrnl/cm/ntfunc.c b/reactos/ntoskrnl/cm/ntfunc.c
index b32e7296253..dd3b5051b09 100644
--- a/reactos/ntoskrnl/cm/ntfunc.c
+++ b/reactos/ntoskrnl/cm/ntfunc.c
@@ -29,9 +29,6 @@ extern LIST_ENTRY CmiKeyObjectListHead;
static BOOLEAN CmiRegistryInitialized = FALSE;
-LIST_ENTRY CmiCallbackHead;
-FAST_MUTEX CmiCallbackLock;
-
/* FUNCTIONS ****************************************************************/
NTSTATUS
@@ -131,151 +128,6 @@ CmpCreateHandle(PVOID ObjectBody,
return STATUS_UNSUCCESSFUL;
}
-/*
- * @implemented
- */
-NTSTATUS STDCALL
-CmRegisterCallback(IN PEX_CALLBACK_FUNCTION Function,
- IN PVOID Context,
- IN OUT PLARGE_INTEGER Cookie)
-{
- PREGISTRY_CALLBACK Callback;
-
- PAGED_CODE();
-
- ASSERT(Function && Cookie);
-
- Callback = ExAllocatePoolWithTag(PagedPool,
- sizeof(REGISTRY_CALLBACK),
- TAG('C', 'M', 'c', 'b'));
- if(Callback != NULL)
- {
- /* initialize the callback */
- ExInitializeRundownProtection(&Callback->RundownRef);
- Callback->Function = Function;
- Callback->Context = Context;
- Callback->PendingDelete = FALSE;
-
- /* add it to the callback list and receive a cookie for the callback */
- ExAcquireFastMutex(&CmiCallbackLock);
- /* FIXME - to receive a unique cookie we'll just return the pointer to the
- callback object */
- Callback->Cookie.QuadPart = (ULONG_PTR)Callback;
- InsertTailList(&CmiCallbackHead, &Callback->ListEntry);
-
- ExReleaseFastMutex(&CmiCallbackLock);
-
- *Cookie = Callback->Cookie;
- return STATUS_SUCCESS;
- }
-
- return STATUS_INSUFFICIENT_RESOURCES;
-}
-
-
-/*
- * @implemented
- */
-NTSTATUS STDCALL
-CmUnRegisterCallback(IN LARGE_INTEGER Cookie)
-{
- PLIST_ENTRY CurrentEntry;
-
- PAGED_CODE();
-
- ExAcquireFastMutex(&CmiCallbackLock);
-
- for(CurrentEntry = CmiCallbackHead.Flink;
- CurrentEntry != &CmiCallbackHead;
- CurrentEntry = CurrentEntry->Flink)
- {
- PREGISTRY_CALLBACK CurrentCallback;
-
- CurrentCallback = CONTAINING_RECORD(CurrentEntry, REGISTRY_CALLBACK, ListEntry);
- if(CurrentCallback->Cookie.QuadPart == Cookie.QuadPart)
- {
- if(!CurrentCallback->PendingDelete)
- {
- /* found the callback, don't unlink it from the list yet so we don't screw
- the calling loop */
- CurrentCallback->PendingDelete = TRUE;
- ExReleaseFastMutex(&CmiCallbackLock);
-
- /* if the callback is currently executing, wait until it finished */
- ExWaitForRundownProtectionRelease(&CurrentCallback->RundownRef);
-
- /* time to unlink it. It's now safe because every attempt to acquire a
- runtime protection on this callback will fail */
- ExAcquireFastMutex(&CmiCallbackLock);
- RemoveEntryList(&CurrentCallback->ListEntry);
- ExReleaseFastMutex(&CmiCallbackLock);
-
- /* free the callback */
- ExFreePool(CurrentCallback);
- return STATUS_SUCCESS;
- }
- else
- {
- /* pending delete, pretend like it already is deleted */
- ExReleaseFastMutex(&CmiCallbackLock);
- return STATUS_UNSUCCESSFUL;
- }
- }
- }
-
- ExReleaseFastMutex(&CmiCallbackLock);
-
- return STATUS_UNSUCCESSFUL;
-}
-
-
-NTSTATUS
-CmiCallRegisteredCallbacks(IN REG_NOTIFY_CLASS Argument1,
- IN PVOID Argument2)
-{
- PLIST_ENTRY CurrentEntry;
- NTSTATUS Status = STATUS_SUCCESS;
-
- PAGED_CODE();
-
- ExAcquireFastMutex(&CmiCallbackLock);
-
- for(CurrentEntry = CmiCallbackHead.Flink;
- CurrentEntry != &CmiCallbackHead;
- CurrentEntry = CurrentEntry->Flink)
- {
- PREGISTRY_CALLBACK CurrentCallback;
-
- CurrentCallback = CONTAINING_RECORD(CurrentEntry, REGISTRY_CALLBACK, ListEntry);
- if(!CurrentCallback->PendingDelete &&
- ExAcquireRundownProtection(&CurrentCallback->RundownRef))
- {
- /* don't hold locks during the callbacks! */
- ExReleaseFastMutex(&CmiCallbackLock);
-
- Status = CurrentCallback->Function(CurrentCallback->Context,
- (PVOID)Argument1,
- Argument2);
-
- ExAcquireFastMutex(&CmiCallbackLock);
- /* don't release the rundown protection before holding the callback lock
- so the pointer to the next callback isn't cleared in case this callback
- get's deleted */
- ExReleaseRundownProtection(&CurrentCallback->RundownRef);
- if(!NT_SUCCESS(Status))
- {
- /* one callback returned failure, don't call any more callbacks */
- break;
- }
- }
- }
-
- ExReleaseFastMutex(&CmiCallbackLock);
-
- return Status;
-}
-
-
NTSTATUS STDCALL
NtCreateKey(OUT PHANDLE KeyHandle,
IN ACCESS_MASK DesiredAccess,
@@ -2219,22 +2071,6 @@ Fail:
return Status;
}
-
-/*
- * NOTE:
- * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
- * KeyObjectAttributes->Name specifies the name of the key to load.
- */
-NTSTATUS STDCALL
-NtLoadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes,
- IN POBJECT_ATTRIBUTES FileObjectAttributes)
-{
- return NtLoadKey2 (KeyObjectAttributes,
- FileObjectAttributes,
- 0);
-}
-
-
/*
* NOTE:
* KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
@@ -2357,52 +2193,6 @@ NtLoadKey2 (IN POBJECT_ATTRIBUTES KeyObjectAttributes,
return Status;
}
-
-NTSTATUS STDCALL
-NtNotifyChangeKey (IN HANDLE KeyHandle,
- IN HANDLE Event,
- IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
- IN PVOID ApcContext OPTIONAL,
- OUT PIO_STATUS_BLOCK IoStatusBlock,
- IN ULONG CompletionFilter,
- IN BOOLEAN WatchSubtree,
- OUT PVOID Buffer,
- IN ULONG Length,
- IN BOOLEAN Asynchronous)
-{
- UNIMPLEMENTED;
- return(STATUS_NOT_IMPLEMENTED);
-}
-
-#if 0
-NTSTATUS STDCALL
-NtNotifyChangeKey (IN HANDLE KeyHandle,
- IN HANDLE Event,
- IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
- IN PVOID ApcContext OPTIONAL,
- OUT PIO_STATUS_BLOCK IoStatusBlock,
- IN ULONG CompletionFilter,
- IN BOOLEAN WatchSubtree,
- OUT PVOID Buffer,
- IN ULONG Length,
- IN BOOLEAN Asynchronous)
-{
- return NtNotifyChangeMultipleKeys(KeyHandle,
- 0,
- NULL,
- Event,
- ApcRoutine,
- ApcContext,
- IoStatusBlock,
- CompletionFilter,
- WatchTree,
- Buffer,
- Length,
- Asynchronous);
-}
-
-#endif
-
NTSTATUS STDCALL
NtQueryMultipleValueKey (IN HANDLE KeyHandle,
IN OUT PKEY_VALUE_ENTRY ValueList,
@@ -2542,269 +2332,6 @@ NtQueryMultipleValueKey (IN HANDLE KeyHandle,
return Status;
}
-
-NTSTATUS STDCALL
-NtReplaceKey (IN POBJECT_ATTRIBUTES ObjectAttributes,
- IN HANDLE Key,
- IN POBJECT_ATTRIBUTES ReplacedObjectAttributes)
-{
- UNIMPLEMENTED;
- return(STATUS_NOT_IMPLEMENTED);
-}
-
-
-NTSTATUS STDCALL
-NtRestoreKey (IN HANDLE KeyHandle,
- IN HANDLE FileHandle,
- IN ULONG RestoreFlags)
-{
- UNIMPLEMENTED;
- return(STATUS_NOT_IMPLEMENTED);
-}
-
-
-NTSTATUS STDCALL
-NtSaveKey (IN HANDLE KeyHandle,
- IN HANDLE FileHandle)
-{
- PEREGISTRY_HIVE TempHive;
- PKEY_OBJECT KeyObject;
- NTSTATUS Status;
-
- PAGED_CODE();
-
- DPRINT ("NtSaveKey() called\n");
-
-#if 0
- if (!SeSinglePrivilegeCheck (SeBackupPrivilege, ExGetPreviousMode ()))
- return STATUS_PRIVILEGE_NOT_HELD;
-#endif
-
- Status = ObReferenceObjectByHandle (KeyHandle,
- 0,
- CmiKeyType,
- ExGetPreviousMode(),
- (PVOID *)&KeyObject,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1 ("ObReferenceObjectByHandle() failed (Status %lx)\n", Status);
- return Status;
- }
-
- /* Acquire hive lock exclucively */
- KeEnterCriticalRegion();
- ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
-
- /* Refuse to save a volatile key */
- if (KeyObject->KeyCell->Flags & REG_KEY_VOLATILE_CELL)
- {
- DPRINT1 ("Cannot save a volatile key\n");
- ExReleaseResourceLite(&CmiRegistryLock);
- KeLeaveCriticalRegion();
- ObDereferenceObject (KeyObject);
- return STATUS_ACCESS_DENIED;
- }
-
- Status = CmiCreateTempHive(&TempHive);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1 ("CmiCreateTempHive() failed (Status %lx)\n", Status);
- ExReleaseResourceLite(&CmiRegistryLock);
- KeLeaveCriticalRegion();
- ObDereferenceObject (KeyObject);
- return(Status);
- }
-
- Status = CmiCopyKey (TempHive,
- NULL,
- KeyObject->RegistryHive,
- KeyObject->KeyCell);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1 ("CmiCopyKey() failed (Status %lx)\n", Status);
- CmiRemoveRegistryHive (TempHive);
- ExReleaseResourceLite(&CmiRegistryLock);
- KeLeaveCriticalRegion();
- ObDereferenceObject (KeyObject);
- return(Status);
- }
-
- Status = CmiSaveTempHive (TempHive,
- FileHandle);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1 ("CmiSaveTempHive() failed (Status %lx)\n", Status);
- }
-
- CmiRemoveRegistryHive (TempHive);
-
- /* Release hive lock */
- ExReleaseResourceLite(&CmiRegistryLock);
- KeLeaveCriticalRegion();
-
- ObDereferenceObject (KeyObject);
-
- DPRINT ("NtSaveKey() done\n");
-
- return STATUS_SUCCESS;
-}
-
-/*
- * @unimplemented
- */
-NTSTATUS
-STDCALL
-NtSaveKeyEx(
- IN HANDLE KeyHandle,
- IN HANDLE FileHandle,
- IN ULONG Flags // REG_STANDARD_FORMAT, etc..
- )
-{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
-}
-
-
-NTSTATUS STDCALL
-NtSetInformationKey (IN HANDLE KeyHandle,
- IN KEY_SET_INFORMATION_CLASS KeyInformationClass,
- IN PVOID KeyInformation,
- IN ULONG KeyInformationLength)
-{
- PKEY_OBJECT KeyObject;
- NTSTATUS Status;
- REG_SET_INFORMATION_KEY_INFORMATION SetInformationKeyInfo;
- REG_POST_OPERATION_INFORMATION PostOperationInfo;
-
- PAGED_CODE();
-
- /* Verify that the handle is valid and is a registry key */
- Status = ObReferenceObjectByHandle (KeyHandle,
- KEY_SET_VALUE,
- CmiKeyType,
- ExGetPreviousMode(),
- (PVOID *)&KeyObject,
- NULL);
- if (!NT_SUCCESS (Status))
- {
- DPRINT ("ObReferenceObjectByHandle() failed with status %x\n", Status);
- return Status;
- }
-
- PostOperationInfo.Object = (PVOID)KeyObject;
- SetInformationKeyInfo.Object = (PVOID)KeyObject;
- SetInformationKeyInfo.KeySetInformationClass = KeyInformationClass;
- SetInformationKeyInfo.KeySetInformation = KeyInformation;
- SetInformationKeyInfo.KeySetInformationLength = KeyInformationLength;
-
- Status = CmiCallRegisteredCallbacks(RegNtPreSetInformationKey, &SetInformationKeyInfo);
- if (!NT_SUCCESS(Status))
- {
- PostOperationInfo.Status = Status;
- CmiCallRegisteredCallbacks(RegNtPostSetInformationKey, &PostOperationInfo);
- ObDereferenceObject (KeyObject);
- return Status;
- }
-
- if (KeyInformationClass != KeyWriteTimeInformation)
- {
- Status = STATUS_INVALID_INFO_CLASS;
- }
-
- else if (KeyInformationLength != sizeof (KEY_WRITE_TIME_INFORMATION))
- {
- Status = STATUS_INFO_LENGTH_MISMATCH;
- }
- else
- {
- /* Acquire hive lock */
- KeEnterCriticalRegion();
- ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
-
- VERIFY_KEY_OBJECT(KeyObject);
-
- KeyObject->KeyCell->LastWriteTime.QuadPart =
- ((PKEY_WRITE_TIME_INFORMATION)KeyInformation)->LastWriteTime.QuadPart;
-
- HvMarkCellDirty (&KeyObject->RegistryHive->Hive,
- KeyObject->KeyCellOffset);
-
- /* Release hive lock */
- ExReleaseResourceLite(&CmiRegistryLock);
- KeLeaveCriticalRegion();
- }
-
- PostOperationInfo.Status = Status;
- CmiCallRegisteredCallbacks(RegNtPostSetInformationKey, &PostOperationInfo);
-
- ObDereferenceObject (KeyObject);
-
- if (NT_SUCCESS(Status))
- {
- CmiSyncHives ();
- }
-
- DPRINT ("NtSaveKey() done\n");
-
- return STATUS_SUCCESS;
-}
-
-
-/*
- * NOTE:
- * KeyObjectAttributes->RootDirectory specifies the handle to the parent key and
- * KeyObjectAttributes->Name specifies the name of the key to unload.
- */
-NTSTATUS STDCALL
-NtUnloadKey (IN POBJECT_ATTRIBUTES KeyObjectAttributes)
-{
- PEREGISTRY_HIVE RegistryHive;
- NTSTATUS Status;
-
- PAGED_CODE();
-
- DPRINT ("NtUnloadKey() called\n");
-
-#if 0
- if (!SeSinglePrivilegeCheck (SeRestorePrivilege, ExGetPreviousMode ()))
- return STATUS_PRIVILEGE_NOT_HELD;
-#endif
-
- /* Acquire registry lock exclusively */
- KeEnterCriticalRegion();
- ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
-
- Status = CmiDisconnectHive (KeyObjectAttributes,
- &RegistryHive);
- if (!NT_SUCCESS (Status))
- {
- DPRINT1 ("CmiDisconnectHive() failed (Status %lx)\n", Status);
- ExReleaseResourceLite (&CmiRegistryLock);
- KeLeaveCriticalRegion();
- return Status;
- }
-
- DPRINT ("RegistryHive %p\n", RegistryHive);
-
-#if 0
- /* Flush hive */
- if (!IsNoFileHive (RegistryHive))
- CmiFlushRegistryHive (RegistryHive);
-#endif
-
- CmiRemoveRegistryHive (RegistryHive);
-
- /* Release registry lock */
- ExReleaseResourceLite (&CmiRegistryLock);
- KeLeaveCriticalRegion();
-
- DPRINT ("NtUnloadKey() done\n");
-
- return STATUS_SUCCESS;
-}
-
-
NTSTATUS STDCALL
NtInitializeRegistry (IN BOOLEAN SetUpBoot)
{
@@ -2842,6 +2369,14 @@ NtCompressKey(IN HANDLE Key)
return STATUS_NOT_IMPLEMENTED;
}
+NTSTATUS
+NTAPI
+NtLoadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
+ IN POBJECT_ATTRIBUTES FileObjectAttributes)
+{
+ return NtLoadKey2(KeyObjectAttributes, FileObjectAttributes, 0);
+}
+
NTSTATUS
NTAPI
NtLoadKeyEx(IN POBJECT_ATTRIBUTES TargetKey,
@@ -2892,6 +2427,33 @@ NtNotifyChangeMultipleKeys(IN HANDLE MasterKeyHandle,
return STATUS_NOT_IMPLEMENTED;
}
+NTSTATUS
+NTAPI
+NtNotifyChangeKey(IN HANDLE KeyHandle,
+ IN HANDLE Event,
+ IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ IN PVOID ApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN ULONG CompletionFilter,
+ IN BOOLEAN WatchTree,
+ OUT PVOID Buffer,
+ IN ULONG Length,
+ IN BOOLEAN Asynchronous)
+{
+ return NtNotifyChangeMultipleKeys(KeyHandle,
+ 0,
+ NULL,
+ Event,
+ ApcRoutine,
+ ApcContext,
+ IoStatusBlock,
+ CompletionFilter,
+ WatchTree,
+ Buffer,
+ Length,
+ Asynchronous);
+}
+
NTSTATUS
NTAPI
NtQueryOpenSubKeys(IN POBJECT_ATTRIBUTES TargetKey,
@@ -2912,6 +2474,45 @@ NtQueryOpenSubKeysEx(IN POBJECT_ATTRIBUTES TargetKey,
return STATUS_NOT_IMPLEMENTED;
}
+NTSTATUS
+NTAPI
+NtReplaceKey(IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN HANDLE Key,
+ IN POBJECT_ATTRIBUTES ReplacedObjectAttributes)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+NtRestoreKey(IN HANDLE KeyHandle,
+ IN HANDLE FileHandle,
+ IN ULONG RestoreFlags)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+NtSaveKey(IN HANDLE KeyHandle,
+ IN HANDLE FileHandle)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+NtSaveKeyEx(IN HANDLE KeyHandle,
+ IN HANDLE FileHandle,
+ IN ULONG Flags)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
NTSTATUS
NTAPI
NtSaveMergedKeys(IN HANDLE HighPrecedenceKeyHandle,
@@ -2922,6 +2523,25 @@ NtSaveMergedKeys(IN HANDLE HighPrecedenceKeyHandle,
return STATUS_NOT_IMPLEMENTED;
}
+NTSTATUS
+NTAPI
+NtSetInformationKey(IN HANDLE KeyHandle,
+ IN KEY_SET_INFORMATION_CLASS KeyInformationClass,
+ IN PVOID KeyInformation,
+ IN ULONG KeyInformationLength)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+NtUnloadKey(IN POBJECT_ATTRIBUTES KeyObjectAttributes)
+{
+ UNIMPLEMENTED;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
NTSTATUS
NTAPI
NtUnloadKey2(IN POBJECT_ATTRIBUTES TargetKey,
diff --git a/reactos/ntoskrnl/cm/registry.c b/reactos/ntoskrnl/cm/registry.c
index bb496a36196..e876b2dbce9 100644
--- a/reactos/ntoskrnl/cm/registry.c
+++ b/reactos/ntoskrnl/cm/registry.c
@@ -497,13 +497,6 @@ CmInitSystem1(VOID)
BaseAddress = CmpRosGetHardwareHive(&Length);
if (!CmImportHardwareHive(BaseAddress, Length, &HardwareHive))
{
- /* Create dummy keys if no hardware hive was found */
- if (!CmImportHardwareHive (NULL, 0, &HardwareHive))
- {
- /* Bugcheck */
- KEBUGCHECKEX(CONFIG_INITIALIZATION_FAILED, 1, 11, Status, 0);
- }
-
/* Don't actually link anything below */
Allocate = TRUE;
}
@@ -687,108 +680,6 @@ CmiConnectHive(IN POBJECT_ATTRIBUTES KeyObjectAttributes,
return STATUS_SUCCESS;
}
-
-NTSTATUS
-CmiDisconnectHive (IN POBJECT_ATTRIBUTES KeyObjectAttributes,
- OUT PEREGISTRY_HIVE *RegistryHive)
-{
- PKEY_OBJECT KeyObject;
- PEREGISTRY_HIVE Hive;
- HANDLE KeyHandle;
- NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND;
- PLIST_ENTRY CurrentEntry;
- PKEY_OBJECT CurrentKey;
-
- DPRINT("CmiDisconnectHive() called\n");
-
- *RegistryHive = NULL;
-
- Status = ObOpenObjectByName (KeyObjectAttributes,
- CmiKeyType,
- KernelMode,
- NULL,
- STANDARD_RIGHTS_REQUIRED,
- NULL,
- &KeyHandle);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1 ("ObOpenObjectByName() failed (Status %lx)\n", Status);
- return Status;
- }
-
- Status = ObReferenceObjectByHandle (KeyHandle,
- STANDARD_RIGHTS_REQUIRED,
- CmiKeyType,
- KernelMode,
- (PVOID*)&KeyObject,
- NULL);
- ZwClose (KeyHandle);
-
- if (!NT_SUCCESS(Status))
- {
- DPRINT1 ("ObReferenceObjectByName() failed (Status %lx)\n", Status);
- return Status;
- }
- DPRINT ("KeyObject %p Hive %p\n", KeyObject, KeyObject->RegistryHive);
-
- /* Acquire registry lock exclusively */
- KeEnterCriticalRegion();
- ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
-
- Hive = KeyObject->RegistryHive;
-
- CurrentEntry = CmiKeyObjectListHead.Flink;
- while (CurrentEntry != &CmiKeyObjectListHead)
- {
- CurrentKey = CONTAINING_RECORD(CurrentEntry, KEY_OBJECT, ListEntry);
- if (CurrentKey->RegistryHive == Hive &&
- 1 == ObGetObjectPointerCount(CurrentKey) &&
- !(CurrentKey->Flags & KO_MARKED_FOR_DELETE))
- {
- ObDereferenceObject(CurrentKey);
- CurrentEntry = CmiKeyObjectListHead.Flink;
- }
- else
- {
- CurrentEntry = CurrentEntry->Flink;
- }
- }
-
- /* FN1 */
- ObDereferenceObject (KeyObject);
-
- if (ObGetObjectHandleCount (KeyObject) != 0 ||
- ObGetObjectPointerCount (KeyObject) != 2)
- {
- DPRINT1 ("Hive is still in use (hc %d, rc %d)\n", ObGetObjectHandleCount (KeyObject), ObGetObjectPointerCount (KeyObject));
- ObDereferenceObject (KeyObject);
-
- /* Release registry lock */
- ExReleaseResourceLite (&CmiRegistryLock);
- KeLeaveCriticalRegion();
-
- return STATUS_UNSUCCESSFUL;
- }
-
- /* Dereference KeyObject twice to delete it */
- ObDereferenceObject (KeyObject);
- ObDereferenceObject (KeyObject);
-
- *RegistryHive = Hive;
-
- /* Release registry lock */
- ExReleaseResourceLite (&CmiRegistryLock);
- KeLeaveCriticalRegion();
-
- /* Release reference above */
- ObDereferenceObject (KeyObject);
-
- DPRINT ("CmiDisconnectHive() done\n");
-
- return Status;
-}
-
-
static NTSTATUS
CmiInitControlSetLink (VOID)
{
diff --git a/reactos/ntoskrnl/config/cmhook.c b/reactos/ntoskrnl/config/cmhook.c
new file mode 100644
index 00000000000..24b699f9ca9
--- /dev/null
+++ b/reactos/ntoskrnl/config/cmhook.c
@@ -0,0 +1,173 @@
+/*
+ * PROJECT: ReactOS Kernel
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: ntoskrnl/config/cmhook.c
+ * PURPOSE: Configuration Manager - Registry Notifications/Callbacks
+ * PROGRAMMERS: Thomas Weidenmueller (w3seek@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include "ntoskrnl.h"
+#include "cm.h"
+#define NDEBUG
+#include "debug.h"
+
+/* GLOBALS *******************************************************************/
+
+LIST_ENTRY CmiCallbackHead;
+FAST_MUTEX CmiCallbackLock;
+
+typedef struct _REGISTRY_CALLBACK
+{
+ LIST_ENTRY ListEntry;
+ EX_RUNDOWN_REF RundownRef;
+ PEX_CALLBACK_FUNCTION Function;
+ PVOID Context;
+ LARGE_INTEGER Cookie;
+ BOOLEAN PendingDelete;
+} REGISTRY_CALLBACK, *PREGISTRY_CALLBACK;
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+NTSTATUS
+CmiCallRegisteredCallbacks(IN REG_NOTIFY_CLASS Argument1,
+ IN PVOID Argument2)
+{
+ PLIST_ENTRY CurrentEntry;
+ NTSTATUS Status = STATUS_SUCCESS;
+ PREGISTRY_CALLBACK CurrentCallback;
+ PAGED_CODE();
+
+ ExAcquireFastMutex(&CmiCallbackLock);
+
+ for (CurrentEntry = CmiCallbackHead.Flink;
+ CurrentEntry != &CmiCallbackHead;
+ CurrentEntry = CurrentEntry->Flink)
+ {
+ CurrentCallback = CONTAINING_RECORD(CurrentEntry, REGISTRY_CALLBACK, ListEntry);
+ if (!CurrentCallback->PendingDelete &&
+ ExAcquireRundownProtection(&CurrentCallback->RundownRef))
+ {
+ /* don't hold locks during the callbacks! */
+ ExReleaseFastMutex(&CmiCallbackLock);
+
+ Status = CurrentCallback->Function(CurrentCallback->Context,
+ (PVOID)Argument1,
+ Argument2);
+
+ ExAcquireFastMutex(&CmiCallbackLock);
+
+ /* don't release the rundown protection before holding the callback lock
+ so the pointer to the next callback isn't cleared in case this callback
+ get's deleted */
+ ExReleaseRundownProtection(&CurrentCallback->RundownRef);
+ if(!NT_SUCCESS(Status))
+ {
+ /* one callback returned failure, don't call any more callbacks */
+ break;
+ }
+ }
+ }
+
+ ExReleaseFastMutex(&CmiCallbackLock);
+
+ return Status;
+}
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+CmRegisterCallback(IN PEX_CALLBACK_FUNCTION Function,
+ IN PVOID Context,
+ IN OUT PLARGE_INTEGER Cookie)
+{
+ PREGISTRY_CALLBACK Callback;
+ PAGED_CODE();
+ ASSERT(Function && Cookie);
+
+ Callback = ExAllocatePoolWithTag(PagedPool,
+ sizeof(REGISTRY_CALLBACK),
+ TAG('C', 'M', 'c', 'b'));
+ if (Callback != NULL)
+ {
+ /* initialize the callback */
+ ExInitializeRundownProtection(&Callback->RundownRef);
+ Callback->Function = Function;
+ Callback->Context = Context;
+ Callback->PendingDelete = FALSE;
+
+ /* add it to the callback list and receive a cookie for the callback */
+ ExAcquireFastMutex(&CmiCallbackLock);
+
+ /* FIXME - to receive a unique cookie we'll just return the pointer to the
+ callback object */
+ Callback->Cookie.QuadPart = (ULONG_PTR)Callback;
+ InsertTailList(&CmiCallbackHead, &Callback->ListEntry);
+
+ ExReleaseFastMutex(&CmiCallbackLock);
+
+ *Cookie = Callback->Cookie;
+ return STATUS_SUCCESS;
+ }
+
+ return STATUS_INSUFFICIENT_RESOURCES;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+CmUnRegisterCallback(IN LARGE_INTEGER Cookie)
+{
+ PLIST_ENTRY CurrentEntry;
+ PREGISTRY_CALLBACK CurrentCallback;
+ PAGED_CODE();
+
+ ExAcquireFastMutex(&CmiCallbackLock);
+
+ for (CurrentEntry = CmiCallbackHead.Flink;
+ CurrentEntry != &CmiCallbackHead;
+ CurrentEntry = CurrentEntry->Flink)
+ {
+ CurrentCallback = CONTAINING_RECORD(CurrentEntry, REGISTRY_CALLBACK, ListEntry);
+ if (CurrentCallback->Cookie.QuadPart == Cookie.QuadPart)
+ {
+ if (!CurrentCallback->PendingDelete)
+ {
+ /* found the callback, don't unlink it from the list yet so we don't screw
+ the calling loop */
+ CurrentCallback->PendingDelete = TRUE;
+ ExReleaseFastMutex(&CmiCallbackLock);
+
+ /* if the callback is currently executing, wait until it finished */
+ ExWaitForRundownProtectionRelease(&CurrentCallback->RundownRef);
+
+ /* time to unlink it. It's now safe because every attempt to acquire a
+ runtime protection on this callback will fail */
+ ExAcquireFastMutex(&CmiCallbackLock);
+ RemoveEntryList(&CurrentCallback->ListEntry);
+ ExReleaseFastMutex(&CmiCallbackLock);
+
+ /* free the callback */
+ ExFreePool(CurrentCallback);
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ /* pending delete, pretend like it already is deleted */
+ ExReleaseFastMutex(&CmiCallbackLock);
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+ }
+
+ ExReleaseFastMutex(&CmiCallbackLock);
+
+ return STATUS_UNSUCCESSFUL;
+}
diff --git a/reactos/ntoskrnl/ntoskrnl.rbuild b/reactos/ntoskrnl/ntoskrnl.rbuild
index 78c12cdd26e..ef592d7c616 100644
--- a/reactos/ntoskrnl/ntoskrnl.rbuild
+++ b/reactos/ntoskrnl/ntoskrnl.rbuild
@@ -88,6 +88,7 @@
cmcontrl.c
cmdata.c
cmindex.c
+ cmhook.c
cmmapvw.c
cmname.c
cmparse.c