implemented CmUnRegisterCallback() and CmUnRegisterCallback()

svn path=/trunk/; revision=13701
This commit is contained in:
Thomas Bluemel 2005-02-21 02:41:16 +00:00
parent 838bea2661
commit a7b3295667
3 changed files with 177 additions and 7 deletions

View file

@ -372,13 +372,71 @@ extern LIST_ENTRY CmiHiveListHead;
extern ERESOURCE CmiRegistryLock;
typedef enum _REG_NOTIFY_CLASS
{
RegNtDeleteKey,
RegNtPreDeleteKey = RegNtDeleteKey,
RegNtSetValueKey,
RegNtPreSetValueKey = RegNtSetValueKey,
RegNtDeleteValueKey,
RegNtPreDeleteValueKey = RegNtDeleteValueKey,
RegNtSetInformationKey,
RegNtPreSetInformationKey = RegNtSetInformationKey,
RegNtRenameKey,
RegNtPreRenameKey = RegNtRenameKey,
RegNtEnumerateKey,
RegNtPreEnumerateKey = RegNtEnumerateKey,
RegNtEnumerateValueKey,
RegNtPreEnumerateValueKey = RegNtEnumerateValueKey,
RegNtQueryKey,
RegNtPreQueryKey = RegNtQueryKey,
RegNtQueryValueKey,
RegNtPreQueryValueKey = RegNtQueryValueKey,
RegNtQueryMultipleValueKey,
RegNtPreQueryMultipleValueKey = RegNtQueryMultipleValueKey,
RegNtPreCreateKey,
RegNtPostCreateKey,
RegNtPreOpenKey,
RegNtPostOpenKey,
RegNtKeyHandleClose,
RegNtPreKeyHandleClose = RegNtKeyHandleClose,
RegNtPostDeleteKey,
RegNtPostSetValueKey,
RegNtPostDeleteValueKey,
RegNtPostSetInformationKey,
RegNtPostRenameKey,
RegNtPostEnumerateKey,
RegNtPostEnumerateValueKey,
RegNtPostQueryKey,
RegNtPostQueryValueKey,
RegNtPostQueryMultipleValueKey,
RegNtPostKeyHandleClose,
RegNtPreCreateKeyEx,
RegNtPostCreateKeyEx,
RegNtPreOpenKeyEx,
RegNtPostOpenKeyEx
} REG_NOTIFY_CLASS, *PREG_NOTIFY_CLASS;
/* Registry Callback Function */
typedef NTSTATUS (*PEX_CALLBACK_FUNCTION ) (
IN PVOID CallbackContext,
IN PVOID Argument1,
IN REG_NOTIFY_CLASS Argument1,
IN PVOID Argument2
);
typedef struct _REGISTRY_CALLBACK
{
LIST_ENTRY ListEntry;
EX_RUNDOWN_REF RundownRef;
PEX_CALLBACK_FUNCTION Function;
PVOID Context;
LARGE_INTEGER Cookie;
} REGISTRY_CALLBACK, *PREGISTRY_CALLBACK;
NTSTATUS
CmiCallRegisteredCallbacks(IN REG_NOTIFY_CLASS Argument1,
IN PVOID Argument2);
VOID
CmiVerifyBinHeader(PHBIN BinHeader);
VOID

View file

@ -24,30 +24,136 @@ extern PREGISTRY_HIVE CmiVolatileHive;
static BOOLEAN CmiRegistryInitialized = FALSE;
LIST_ENTRY CmiCallbackHead;
FAST_MUTEX CmiCallbackLock;
/* FUNCTIONS ****************************************************************/
/*
* @unimplemented
* @implemented
*/
NTSTATUS STDCALL
CmRegisterCallback(IN PEX_CALLBACK_FUNCTION Function,
IN PVOID Context,
IN OUT PLARGE_INTEGER Cookie)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
PREGISTRY_CALLBACK Callback;
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;
/* 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;
}
/*
* @unimplemented
* @implemented
*/
NTSTATUS STDCALL
CmUnRegisterCallback(IN LARGE_INTEGER Cookie)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
PLIST_ENTRY CurrentEntry;
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)
{
/* found the callback, don't unlink it from the list yet so we don't screw
the calling loop */
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;
}
}
ExReleaseFastMutex(&CmiCallbackLock);
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
CmiCallRegisteredCallbacks(IN REG_NOTIFY_CLASS Argument1,
IN PVOID Argument2)
{
PLIST_ENTRY CurrentEntry;
ExAcquireFastMutex(&CmiCallbackLock);
for(CurrentEntry = CmiCallbackHead.Flink;
CurrentEntry != &CmiCallbackHead;
CurrentEntry = CurrentEntry->Flink)
{
PREGISTRY_CALLBACK CurrentCallback;
CurrentCallback = CONTAINING_RECORD(CurrentEntry, REGISTRY_CALLBACK, ListEntry);
if(ExAcquireRundownProtectionEx(&CurrentCallback->RundownRef, 1))
{
NTSTATUS Status;
/* don't hold locks during the callbacks! */
ExReleaseFastMutex(&CmiCallbackLock);
Status = CurrentCallback->Function(CurrentCallback->Context,
Argument1,
Argument2);
if(!NT_SUCCESS(Status))
{
/* one callback returned failure, don't call any more callbacks */
return Status;
}
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 */
ExReleaseRundownProtectionEx(&CurrentCallback->RundownRef, 1);
}
}
ExReleaseFastMutex(&CmiCallbackLock);
return STATUS_SUCCESS;
}

View file

@ -49,6 +49,9 @@ CmiHiveSyncDpcRoutine(PKDPC Dpc,
PVOID SystemArgument1,
PVOID SystemArgument2);
extern LIST_ENTRY CmiCallbackHead;
extern FAST_MUTEX CmiCallbackLock;
/* FUNCTIONS ****************************************************************/
VOID
@ -287,6 +290,9 @@ CmInitializeRegistry(VOID)
Status = CmiCreateVolatileHive (&CmiVolatileHive);
ASSERT(NT_SUCCESS(Status));
InitializeListHead(&CmiCallbackHead);
ExInitializeFastMutex(&CmiCallbackLock);
/* Create '\Registry' key. */
RtlInitUnicodeString(&KeyName, REG_ROOT_KEY_NAME);
InitializeObjectAttributes(&ObjectAttributes, &KeyName, 0, NULL, NULL);