- Remove/deprecate some certain chunks of Cm which are not critical to booting and not even to applications (such as NtSaveKey, which didn't even have NtRestoreKey) and mark them as unimplemented functions.

- This doesn't do much but clean up some of our code to make it easier to see what the critical parts are and reduce bug surface exposure.
- Move and slightly reformat (without touching any of the actual code) registry callback/notification code to cmhook.c.

svn path=/trunk/; revision=26671
This commit is contained in:
Alex Ionescu 2007-05-10 09:14:15 +00:00
parent e72d90dbc8
commit 107cb5719e
5 changed files with 267 additions and 705 deletions

View file

@ -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;
}

View file

@ -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,

View file

@ -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)
{

View file

@ -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;
}

View file

@ -88,6 +88,7 @@
<file>cmcontrl.c</file>
<file>cmdata.c</file>
<file>cmindex.c</file>
<file>cmhook.c</file>
<file>cmmapvw.c</file>
<file>cmname.c</file>
<file>cmparse.c</file>