Modified: trunk/reactos/ntoskrnl/cm/cm.h
Modified: trunk/reactos/ntoskrnl/cm/ntfunc.c
Modified: trunk/reactos/ntoskrnl/cm/registry.c
--- 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
--- 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,
--- 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);