implemented CmUnRegisterCallback() and CmUnRegisterCallback() Modified: trunk/reactos/ntoskrnl/cm/cm.h Modified: trunk/reactos/ntoskrnl/cm/ntfunc.c Modified: trunk/reactos/ntoskrnl/cm/registry.c _____
Modified: trunk/reactos/ntoskrnl/cm/cm.h --- trunk/reactos/ntoskrnl/cm/cm.h 2005-02-21 00:39:59 UTC (rev 13700) +++ trunk/reactos/ntoskrnl/cm/cm.h 2005-02-21 02:41:16 UTC (rev 13701) @@ -372,13 +372,71 @@
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 _____
Modified: trunk/reactos/ntoskrnl/cm/ntfunc.c --- trunk/reactos/ntoskrnl/cm/ntfunc.c 2005-02-21 00:39:59 UTC (rev 13700) +++ trunk/reactos/ntoskrnl/cm/ntfunc.c 2005-02-21 02:41:16 UTC (rev 13701) @@ -24,33 +24,139 @@
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; +} + + NTSTATUS STDCALL NtCreateKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, _____
Modified: trunk/reactos/ntoskrnl/cm/registry.c --- trunk/reactos/ntoskrnl/cm/registry.c 2005-02-21 00:39:59 UTC (rev 13700) +++ trunk/reactos/ntoskrnl/cm/registry.c 2005-02-21 02:41:16 UTC (rev 13701) @@ -49,6 +49,9 @@
PVOID SystemArgument1, PVOID SystemArgument2);
+extern LIST_ENTRY CmiCallbackHead; +extern FAST_MUTEX CmiCallbackLock; + /* FUNCTIONS ****************************************************************/
VOID @@ -286,6 +289,9 @@ /* Build volatile registry store */ Status = CmiCreateVolatileHive (&CmiVolatileHive); ASSERT(NT_SUCCESS(Status)); + + InitializeListHead(&CmiCallbackHead); + ExInitializeFastMutex(&CmiCallbackLock);
/* Create '\Registry' key. */ RtlInitUnicodeString(&KeyName, REG_ROOT_KEY_NAME);