- Moved the definition of REG_NOTIFY_CLASS from cm.h to winddk.h.  
- Release the rundown protection if the callback function returns an error (in CmiCallRegisteredCallbacks).  
- Call the registry callback functions in most of the Nt/ZW registry functions.
Modified: trunk/reactos/ntoskrnl/cm/cm.h
Modified: trunk/reactos/ntoskrnl/cm/ntfunc.c
Modified: trunk/reactos/w32api/include/ddk/winddk.h

Modified: trunk/reactos/ntoskrnl/cm/cm.h
--- trunk/reactos/ntoskrnl/cm/cm.h	2005-09-24 18:28:04 UTC (rev 18030)
+++ trunk/reactos/ntoskrnl/cm/cm.h	2005-09-24 18:42:37 UTC (rev 18031)
@@ -378,55 +378,11 @@
 
 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 (STDCALL *PEX_CALLBACK_FUNCTION ) (
     IN PVOID CallbackContext,
-    IN PVOID Argument1,
+    IN REG_NOTIFY_CLASS Argument1,
     IN PVOID Argument2
     );
 

Modified: trunk/reactos/ntoskrnl/cm/ntfunc.c
--- trunk/reactos/ntoskrnl/cm/ntfunc.c	2005-09-24 18:28:04 UTC (rev 18030)
+++ trunk/reactos/ntoskrnl/cm/ntfunc.c	2005-09-24 18:42:37 UTC (rev 18031)
@@ -133,6 +133,7 @@
                            IN PVOID Argument2)
 {
   PLIST_ENTRY CurrentEntry;
+  NTSTATUS Status = STATUS_SUCCESS;
 
   PAGED_CODE();
 
@@ -148,31 +149,29 @@
     if(!CurrentCallback->PendingDelete &&
        ExAcquireRundownProtectionEx(&CurrentCallback->RundownRef, 1))
     {
-      NTSTATUS Status;
-
       /* don't hold locks during the callbacks! */
       ExReleaseFastMutex(&CmiCallbackLock);
 
       Status = CurrentCallback->Function(CurrentCallback->Context,
-                                         (PVOID)Argument1,
+                                         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);
+      if(!NT_SUCCESS(Status))
+      {
+        /* one callback returned failure, don't call any more callbacks */
+        break;
+      }
     }
   }
 
   ExReleaseFastMutex(&CmiCallbackLock);
 
-  return STATUS_SUCCESS;
+  return Status;
 }
 
 
@@ -193,6 +192,8 @@
   UNICODE_STRING ObjectName;
   OBJECT_CREATE_INFORMATION ObjectCreateInfo;
   unsigned i;
+  REG_PRE_CREATE_KEY_INFORMATION PreCreateKeyInfo;
+  REG_POST_CREATE_KEY_INFORMATION PostCreateKeyInfo;
 
   PAGED_CODE();
 
@@ -201,28 +202,41 @@
 	 KeyHandle,
 	 ObjectAttributes->RootDirectory);
 
-   /* Capture all the info */
-   DPRINT("Capturing Create Info\n");
-   Status = ObpCaptureObjectAttributes(ObjectAttributes,
-                                       KeGetPreviousMode(),
-                                       CmiKeyType,
-                                       &ObjectCreateInfo,
-                                       &ObjectName);
-   if (!NT_SUCCESS(Status))
-     {
-	DPRINT("ObpCaptureObjectAttributes() failed (Status %lx)\n", Status);
-	return Status;
-     }
+  /* Capture all the info */
+  DPRINT("Capturing Create Info\n");
+  Status = ObpCaptureObjectAttributes(ObjectAttributes,
+                                      KeGetPreviousMode(),
+                                      CmiKeyType,
+                                      &ObjectCreateInfo,
+                                      &ObjectName);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT("ObpCaptureObjectAttributes() failed (Status %lx)\n", Status);
+      return Status;
+    }
 
+  PostCreateKeyInfo.CompleteName = &ObjectName;
+  PreCreateKeyInfo.CompleteName = &ObjectName;
+  Status = CmiCallRegisteredCallbacks(RegNtPreCreateKey, &PreCreateKeyInfo);
+  if (!NT_SUCCESS(Status))
+    {
+      ObpReleaseCapturedAttributes(&ObjectCreateInfo);
+      if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
+      return Status;
+    }
+    
   Status = ObFindObject(&ObjectCreateInfo,
                         &ObjectName,
-			            (PVOID*)&Object,
+			(PVOID*)&Object,
                         &RemainingPath,
                         CmiKeyType);
-     ObpReleaseCapturedAttributes(&ObjectCreateInfo);
-   if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
+  ObpReleaseCapturedAttributes(&ObjectCreateInfo);
   if (!NT_SUCCESS(Status))
     {
+      PostCreateKeyInfo.Object = NULL;
+      PostCreateKeyInfo.Status = Status;
+      CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
+      if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
       DPRINT("CmpFindObject failed, Status: 0x%x\n", Status);
       return(Status);
     }
@@ -236,6 +250,10 @@
 	{
 	  ObDereferenceObject(Object);
 	  RtlFreeUnicodeString(&RemainingPath);
+          PostCreateKeyInfo.Object = NULL;
+          PostCreateKeyInfo.Status = STATUS_UNSUCCESSFUL;
+          CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
+          if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
 	  DPRINT("Object marked for delete!\n");
 	  return(STATUS_UNSUCCESSFUL);
 	}
@@ -252,6 +270,10 @@
       DPRINT("ObpCreateHandle failed Status 0x%x\n", Status);
       ObDereferenceObject(Object);
       RtlFreeUnicodeString(&RemainingPath);
+      PostCreateKeyInfo.Object = NULL;
+      PostCreateKeyInfo.Status = Status;
+      CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
+      if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
       return Status;
     }
 
@@ -268,6 +290,10 @@
           ObDereferenceObject(Object);
           DPRINT1("NtCreateKey() doesn't create trees! (found \'\\\' in remaining path: \"%wZ\"!)\n", &RemainingPath);
           RtlFreeUnicodeString(&RemainingPath);
+          PostCreateKeyInfo.Object = NULL;
+          PostCreateKeyInfo.Status = STATUS_OBJECT_NAME_NOT_FOUND;
+          CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
+          if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
           return STATUS_OBJECT_NAME_NOT_FOUND;
         }
     }
@@ -286,6 +312,10 @@
   if (!NT_SUCCESS(Status))
     {
       DPRINT1("ObCreateObject() failed!\n");
+      PostCreateKeyInfo.Object = NULL;
+      PostCreateKeyInfo.Status = Status;
+      CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
+      if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
       return(Status);
     }
 
@@ -300,6 +330,10 @@
       ObDereferenceObject(KeyObject);
       RtlFreeUnicodeString(&RemainingPath);
       DPRINT1("ObInsertObject() failed!\n");
+      PostCreateKeyInfo.Object = NULL;
+      PostCreateKeyInfo.Status = Status;
+      CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
+      if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
       return(Status);
     }
 
@@ -338,6 +372,10 @@
       ObDereferenceObject(KeyObject);
       ObDereferenceObject(Object);
       RtlFreeUnicodeString(&RemainingPath);
+      PostCreateKeyInfo.Object = NULL;
+      PostCreateKeyInfo.Status = STATUS_UNSUCCESSFUL;
+      CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
+      if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
       return STATUS_UNSUCCESSFUL;
     }
 
@@ -382,6 +420,11 @@
   if (Disposition)
     *Disposition = REG_CREATED_NEW_KEY;
 
+  PostCreateKeyInfo.Object = KeyObject;
+  PostCreateKeyInfo.Status = Status;
+  CmiCallRegisteredCallbacks(RegNtPostCreateKey, &PostCreateKeyInfo);
+  if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
+
   CmiSyncHives();
 
   return Status;
@@ -394,6 +437,8 @@
   KPROCESSOR_MODE PreviousMode;
   PKEY_OBJECT KeyObject;
   NTSTATUS Status;
+  REG_DELETE_KEY_INFORMATION DeleteKeyInfo;
+  REG_POST_OPERATION_INFORMATION PostOperationInfo;
 
   PAGED_CODE();
 
@@ -414,6 +459,17 @@
       return Status;
     }
 
+  PostOperationInfo.Object = (PVOID)KeyObject;
+  DeleteKeyInfo.Object = (PVOID)KeyObject;
+  Status = CmiCallRegisteredCallbacks(RegNtPreSetValueKey, &DeleteKeyInfo);
+  if (!NT_SUCCESS(Status))
+    {
+      PostOperationInfo.Status = Status;
+      CmiCallRegisteredCallbacks(RegNtDeleteKey, &PostOperationInfo);
+      ObDereferenceObject(KeyObject);
+      return Status;
+    }
+
   /* Acquire hive lock */
   KeEnterCriticalRegion();
   ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
@@ -438,14 +494,18 @@
 
   DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject));
 
-  /* Dereference the object */
-  ObDereferenceObject(KeyObject);
   /* Remove the keep-alive reference */
   ObDereferenceObject(KeyObject);
 
   if (KeyObject->RegistryHive != KeyObject->ParentKey->RegistryHive)
     ObDereferenceObject(KeyObject);
 
+  PostOperationInfo.Status = Status;
+  CmiCallRegisteredCallbacks(RegNtPostDeleteKey, &PostOperationInfo);
+
+  /* Dereference the object */
+  ObDereferenceObject(KeyObject);
+
   DPRINT("PointerCount %lu\n", ObGetObjectPointerCount((PVOID)KeyObject));
   DPRINT("HandleCount %lu\n", ObGetObjectHandleCount((PVOID)KeyObject));
 
@@ -480,6 +540,8 @@
   ULONG NameSize, ClassSize;
   KPROCESSOR_MODE PreviousMode;
   NTSTATUS Status;
+  REG_ENUMERATE_KEY_INFORMATION EnumerateKeyInfo;
+  REG_POST_OPERATION_INFORMATION PostOperationInfo;
 
   PAGED_CODE();
 
@@ -506,6 +568,20 @@
       return(Status);
     }
 
+  PostOperationInfo.Object = (PVOID)KeyObject;
+  EnumerateKeyInfo.Object = (PVOID)KeyObject;
+  EnumerateKeyInfo.Index = Index;
+  EnumerateKeyInfo.KeyInformationClass = KeyInformationClass;
+  EnumerateKeyInfo.Length = Length;
+  EnumerateKeyInfo.ResultLength = ResultLength;
+
+  Status = CmiCallRegisteredCallbacks(RegNtEnumerateKey, &EnumerateKeyInfo);
+  if (!NT_SUCCESS(Status))
+    {
+      ObDereferenceObject(KeyObject);
+      return Status;
+    }
+
   /* Acquire hive lock */
   KeEnterCriticalRegion();
   ExAcquireResourceSharedLite(&CmiRegistryLock, TRUE);
@@ -523,6 +599,8 @@
     {
       ExReleaseResourceLite(&CmiRegistryLock);
       KeLeaveCriticalRegion();
+      PostOperationInfo.Status = STATUS_NO_MORE_ENTRIES;
+      CmiCallRegisteredCallbacks(RegNtPostDeleteKey, &PostOperationInfo);
       ObDereferenceObject(KeyObject);
       DPRINT("No more volatile entries\n");
       return STATUS_NO_MORE_ENTRIES;
@@ -552,6 +630,8 @@
 	{
 	  ExReleaseResourceLite(&CmiRegistryLock);
 	  KeLeaveCriticalRegion();
+          PostOperationInfo.Status = STATUS_NO_MORE_ENTRIES;
+          CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
 	  ObDereferenceObject(KeyObject);
 	  DPRINT("No more non-volatile entries\n");
 	  return STATUS_NO_MORE_ENTRIES;
@@ -566,6 +646,8 @@
 	{
 	  ExReleaseResourceLite(&CmiRegistryLock);
 	  KeLeaveCriticalRegion();
+          PostOperationInfo.Status = STATUS_NO_MORE_ENTRIES;
+          CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
 	  ObDereferenceObject(KeyObject);
 	  return STATUS_NO_MORE_ENTRIES;
 	}
@@ -576,6 +658,8 @@
 	  DPRINT("CmiGetBlock() failed\n");
 	  ExReleaseResourceLite(&CmiRegistryLock);
 	  KeLeaveCriticalRegion();
+          PostOperationInfo.Status = STATUS_UNSUCCESSFUL;
+          CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
 	  ObDereferenceObject(KeyObject);
 	  return STATUS_UNSUCCESSFUL;
 	}
@@ -589,6 +673,8 @@
     {
       ExReleaseResourceLite(&CmiRegistryLock);
       KeLeaveCriticalRegion();
+      PostOperationInfo.Status = STATUS_NO_MORE_ENTRIES;
+      CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
       ObDereferenceObject(KeyObject);
       DPRINT("No more entries\n");
       return STATUS_NO_MORE_ENTRIES;
@@ -804,6 +890,10 @@
 
   ExReleaseResourceLite(&CmiRegistryLock);
   KeLeaveCriticalRegion();
+
+  PostOperationInfo.Status = Status;
+  CmiCallRegisteredCallbacks(RegNtPostEnumerateKey, &PostOperationInfo);
+
   ObDereferenceObject(KeyObject);
 
   DPRINT("Returning status %x\n", Status);
@@ -1121,11 +1211,13 @@
 {
   UNICODE_STRING RemainingPath;
   KPROCESSOR_MODE PreviousMode;
-  PVOID Object;
+  PVOID Object = NULL;
   HANDLE hKey;
   NTSTATUS Status = STATUS_SUCCESS;
   UNICODE_STRING ObjectName;
   OBJECT_CREATE_INFORMATION ObjectCreateInfo;
+  REG_PRE_OPEN_KEY_INFORMATION PreOpenKeyInfo;
+  REG_POST_OPEN_KEY_INFORMATION PostOpenKeyInfo;
 
   PAGED_CODE();
 
@@ -1176,21 +1268,31 @@
 	return Status;
      }
 
+  PostOpenKeyInfo.CompleteName = &ObjectName;
+  PreOpenKeyInfo.CompleteName = &ObjectName;
+  Status = CmiCallRegisteredCallbacks(RegNtPreOpenKey, &PreOpenKeyInfo);
+  if (!NT_SUCCESS(Status))
+    {
+      ObpReleaseCapturedAttributes(&ObjectCreateInfo);
+      if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
+      return Status;
+    }
+
+
   RemainingPath.Buffer = NULL;
 
   Status = ObFindObject(&ObjectCreateInfo,
                         &ObjectName,
-			            (PVOID*)&Object,
+	                (PVOID*)&Object,
                         &RemainingPath,
                         CmiKeyType);
-     ObpReleaseCapturedAttributes(&ObjectCreateInfo);
-   if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
+  ObpReleaseCapturedAttributes(&ObjectCreateInfo);
   if (!NT_SUCCESS(Status))
     {
       DPRINT("CmpFindObject() returned 0x%08lx\n", Status);
-	  Status = STATUS_INVALID_HANDLE; /* Because CmpFindObject returns STATUS_UNSUCCESSFUL */
-	  hKey = *KeyHandle; /* Preserve hkResult value */
-	  goto openkey_cleanup;
+      Status = STATUS_INVALID_HANDLE; /* Because CmpFindObject returns STATUS_UNSUCCESSFUL */
+      hKey = *KeyHandle; /* Preserve hkResult value */
+      goto openkey_cleanup;
     }
 
   VERIFY_KEY_OBJECT((PKEY_OBJECT) Object);
@@ -1199,11 +1301,10 @@
 
   if ((RemainingPath.Buffer != NULL) && (RemainingPath.Buffer[0] != 0))
     {
-      ObDereferenceObject(Object);
       RtlFreeUnicodeString(&RemainingPath);
       Status = STATUS_OBJECT_NAME_NOT_FOUND;
       hKey = NULL;
-	  goto openkey_cleanup;
+      goto openkey_cleanup;
     }
 
   RtlFreeUnicodeString(&RemainingPath);
@@ -1211,10 +1312,9 @@
   /* Fail if the key has been deleted */
   if (((PKEY_OBJECT)Object)->Flags & KO_MARKED_FOR_DELETE)
     {
-      ObDereferenceObject(Object);
-	  Status = STATUS_UNSUCCESSFUL;
+      Status = STATUS_UNSUCCESSFUL;
       hKey = NULL;
-	  goto openkey_cleanup;
+      goto openkey_cleanup;
     }
 
   Status = ObpCreateHandle(PsGetCurrentProcess(),
@@ -1222,12 +1322,22 @@
 			  DesiredAccess,
 			  TRUE,
 			  &hKey);
-  ObDereferenceObject(Object);
 
   if (!NT_SUCCESS(Status))
      hKey = NULL;
 
 openkey_cleanup:
+
+  PostOpenKeyInfo.Object = NT_SUCCESS(Status) ? (PVOID)Object : NULL;
+  PostOpenKeyInfo.Status = Status;
+  CmiCallRegisteredCallbacks (RegNtPostOpenKey, &PostOpenKeyInfo);
+  if (ObjectName.Buffer) ExFreePool(ObjectName.Buffer);
+
+  if (Object)
+    {
+      ObDereferenceObject(Object);
+    }
+
   _SEH_TRY
   {
     *KeyHandle = hKey;
@@ -1258,6 +1368,8 @@
   PKEY_CELL KeyCell;
   ULONG NameSize, ClassSize;
   NTSTATUS Status;
+  REG_QUERY_KEY_INFORMATION QueryKeyInfo;
+  REG_POST_OPERATION_INFORMATION PostOperationInfo;
 
   PAGED_CODE();
 
@@ -1280,6 +1392,20 @@
       return Status;
     }
 
+  PostOperationInfo.Object = (PVOID)KeyObject;
+  QueryKeyInfo.Object = (PVOID)KeyObject;
+  QueryKeyInfo.KeyInformationClass = KeyInformationClass;
+  QueryKeyInfo.KeyInformation = KeyInformation;
+  QueryKeyInfo.Length = Length;
+  QueryKeyInfo.ResultLength = ResultLength;
+  
+  Status = CmiCallRegisteredCallbacks(RegNtQueryKey, &QueryKeyInfo);
+  if (!NT_SUCCESS(Status))
+    {
+      ObDereferenceObject(KeyObject);
+      return Status;
+    }
+
   /* Acquire hive lock */
   KeEnterCriticalRegion();
   ExAcquireResourceSharedLite(&CmiRegistryLock, TRUE);
@@ -1444,6 +1570,10 @@
 
   ExReleaseResourceLite(&CmiRegistryLock);
   KeLeaveCriticalRegion();
+
+  PostOperationInfo.Status = Status;
+  CmiCallRegisteredCallbacks(RegNtPostQueryKey, &PostOperationInfo);
+
   ObDereferenceObject(KeyObject);
 
   return(Status);
@@ -1468,6 +1598,8 @@
   PKEY_VALUE_BASIC_INFORMATION  ValueBasicInformation;
   PKEY_VALUE_PARTIAL_INFORMATION  ValuePartialInformation;
   PKEY_VALUE_FULL_INFORMATION  ValueFullInformation;
+  REG_QUERY_VALUE_KEY_INFORMATION QueryValueKeyInfo;
+  REG_POST_OPERATION_INFORMATION PostOperationInfo;
 
   PAGED_CODE();
 
@@ -1487,7 +1619,21 @@
       DPRINT1("ObReferenceObjectByHandle() failed with status %x\n", Status);
       return Status;
     }
+  
+  PostOperationInfo.Object = (PVOID)KeyObject;
+  QueryValueKeyInfo.Object = (PVOID)KeyObject;
+  QueryValueKeyInfo.ValueName = ValueName;
+  QueryValueKeyInfo.KeyValueInformationClass = KeyValueInformationClass;
+  QueryValueKeyInfo.Length = Length;
+  QueryValueKeyInfo.ResultLength = ResultLength;
 
+  Status = CmiCallRegisteredCallbacks(RegNtPreQueryValueKey, &QueryValueKeyInfo);
+  if (!NT_SUCCESS(Status))
+    {
+      ObDereferenceObject(KeyObject);
+      return Status;
+    }
+
   /* Acquire hive lock */
   KeEnterCriticalRegion();
   ExAcquireResourceSharedLite(&CmiRegistryLock, TRUE);
@@ -1686,6 +1832,9 @@
 ByeBye:;
   ExReleaseResourceLite(&CmiRegistryLock);
   KeLeaveCriticalRegion();
+
+  PostOperationInfo.Status = Status;
+  CmiCallRegisteredCallbacks(RegNtPostQueryValueKey, &PostOperationInfo);
   ObDereferenceObject(KeyObject);
 
   return Status;
@@ -1710,6 +1859,8 @@
   PDATA_CELL NewDataCell;
   PHBIN pBin;
   ULONG DesiredAccess;
+  REG_SET_VALUE_KEY_INFORMATION SetValueKeyInfo;
+  REG_POST_OPERATION_INFORMATION PostOperationInfo;
 
   PAGED_CODE();
 
@@ -1728,6 +1879,20 @@
   if (!NT_SUCCESS(Status))
     return(Status);
 
+  PostOperationInfo.Object = (PVOID)KeyObject;
+  SetValueKeyInfo.Object = (PVOID)KeyObject;
+  SetValueKeyInfo.ValueName = ValueName;
+  SetValueKeyInfo.TitleIndex = TitleIndex;
+  SetValueKeyInfo.Type = Type;
+  SetValueKeyInfo.Data = Data;
+  SetValueKeyInfo.DataSize = DataSize;
+  Status = CmiCallRegisteredCallbacks(RegNtPreSetValueKey, &SetValueKeyInfo);
+  if (!NT_SUCCESS(Status))
+    {
+      ObDereferenceObject(KeyObject);
+      return Status;
+    }
+
   /* Acquire hive lock exclucively */
   KeEnterCriticalRegion();
   ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
@@ -1759,6 +1924,8 @@
 
       ExReleaseResourceLite(&CmiRegistryLock);
       KeLeaveCriticalRegion();
+      PostOperationInfo.Status = Status;
+      CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
       ObDereferenceObject(KeyObject);
       return Status;
     }
@@ -1824,6 +1991,8 @@
 
 	  ExReleaseResourceLite(&CmiRegistryLock);
 	  KeLeaveCriticalRegion();
+          PostOperationInfo.Status = Status;
+          CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
 	  ObDereferenceObject(KeyObject);
 
 	  return Status;
@@ -1849,6 +2018,8 @@
 
   ExReleaseResourceLite(&CmiRegistryLock);
   KeLeaveCriticalRegion();
+  PostOperationInfo.Status = Status;
+  CmiCallRegisteredCallbacks(RegNtPostSetValueKey, &PostOperationInfo);
   ObDereferenceObject(KeyObject);
 
   CmiSyncHives();
@@ -1865,6 +2036,8 @@
 {
   PKEY_OBJECT KeyObject;
   NTSTATUS Status;
+  REG_DELETE_VALUE_KEY_INFORMATION DeleteValueKeyInfo;
+  REG_POST_OPERATION_INFORMATION PostOperationInfo;
 
   PAGED_CODE();
 
@@ -1879,7 +2052,17 @@
     {
       return Status;
     }
+  
+  DeleteValueKeyInfo.Object = (PVOID)KeyObject;
+  DeleteValueKeyInfo.ValueName = ValueName;
 
+  Status = CmiCallRegisteredCallbacks(RegNtPreDeleteValueKey, &DeleteValueKeyInfo);
+  if (!NT_SUCCESS(Status))
+    {
+      ObDereferenceObject(KeyObject);
+      return Status;
+    }
+
   /* Acquire hive lock */
   KeEnterCriticalRegion();
   ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
@@ -1898,6 +2081,11 @@
   ExReleaseResourceLite(&CmiRegistryLock);
   KeLeaveCriticalRegion();
 
+  PostOperationInfo.Object = (PVOID)KeyObject;
+  PostOperationInfo.Status = Status;
+
+  CmiCallRegisteredCallbacks(RegNtPostDeleteValueKey, &PostOperationInfo);
+
   ObDereferenceObject (KeyObject);
 
   CmiSyncHives ();
@@ -2106,6 +2294,8 @@
   NTSTATUS Status;
   PUCHAR DataPtr;
   ULONG i;
+  REG_QUERY_MULTIPLE_VALUE_KEY_INFORMATION QueryMultipleValueKeyInfo;
+  REG_POST_OPERATION_INFORMATION PostOperationInfo;
 
   PAGED_CODE();
 
@@ -2122,6 +2312,21 @@
       return(Status);
     }
 
+  PostOperationInfo.Object = (PVOID)KeyObject;
+  QueryMultipleValueKeyInfo.Object = (PVOID)KeyObject;
+  QueryMultipleValueKeyInfo.ValueEntries = ValueList;
+  QueryMultipleValueKeyInfo.EntryCount = NumberOfValues;
+  QueryMultipleValueKeyInfo.ValueBuffer = Buffer;
+  QueryMultipleValueKeyInfo.BufferLength = Length;
+  QueryMultipleValueKeyInfo.RequiredBufferLength = ReturnLength;
+
+  Status = CmiCallRegisteredCallbacks(RegNtPreQueryMultipleValueKey, &QueryMultipleValueKeyInfo);
+  if (!NT_SUCCESS(Status))
+    {
+      ObDereferenceObject(KeyObject);
+      return Status;
+    }
+
   /* Acquire hive lock */
   KeEnterCriticalRegion();
   ExAcquireResourceSharedLite(&CmiRegistryLock, TRUE);
@@ -2201,6 +2406,9 @@
   ExReleaseResourceLite(&CmiRegistryLock);
   KeLeaveCriticalRegion();
 
+  PostOperationInfo.Status = Status;
+  CmiCallRegisteredCallbacks(RegNtPostQueryMultipleValueKey, &PostOperationInfo);
+
   ObDereferenceObject(KeyObject);
 
   DPRINT("Return Status 0x%X\n", Status);
@@ -2340,15 +2548,11 @@
 {
   PKEY_OBJECT KeyObject;
   NTSTATUS Status;
+  REG_SET_INFORMATION_KEY_INFORMATION SetInformationKeyInfo;
+  REG_POST_OPERATION_INFORMATION PostOperationInfo;
 
   PAGED_CODE();
 
-  if (KeyInformationClass != KeyWriteTimeInformation)
-    return STATUS_INVALID_INFO_CLASS;
-
-  if (KeyInformationLength != sizeof (KEY_WRITE_TIME_INFORMATION))
-    return STATUS_INFO_LENGTH_MISMATCH;
-
   /* Verify that the handle is valid and is a registry key */
   Status = ObReferenceObjectByHandle (KeyHandle,
 				      KEY_SET_VALUE,
@@ -2362,25 +2566,56 @@
       return Status;
     }
 
-  /* Acquire hive lock */
-  KeEnterCriticalRegion();
-  ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
+  PostOperationInfo.Object = (PVOID)KeyObject;
+  SetInformationKeyInfo.Object = (PVOID)KeyObject;
+  SetInformationKeyInfo.KeySetInformationClass = KeyInformationClass;
+  SetInformationKeyInfo.KeySetInformation = KeyInformation;
+  SetInformationKeyInfo.KeySetInformationLength = KeyInformationLength;
 
-  VERIFY_KEY_OBJECT(KeyObject);
+  Status = CmiCallRegisteredCallbacks(RegNtSetInformationKey, &SetInformationKeyInfo);
+  if (!NT_SUCCESS(Status))
+    {
+      ObDereferenceObject (KeyObject);
+      return Status;
+    }
 
-  KeyObject->KeyCell->LastWriteTime.QuadPart =
-    ((PKEY_WRITE_TIME_INFORMATION)KeyInformation)->LastWriteTime.QuadPart;
+  if (KeyInformationClass != KeyWriteTimeInformation)
+    {
+      Status = STATUS_INVALID_INFO_CLASS;
+    }
 
-  CmiMarkBlockDirty (KeyObject->RegistryHive,
-		     KeyObject->KeyCellOffset);
+  else if (KeyInformationLength != sizeof (KEY_WRITE_TIME_INFORMATION))
+    {
+      Status = STATUS_INFO_LENGTH_MISMATCH;
+    }
+  else
+    {
+      /* Acquire hive lock */
+      KeEnterCriticalRegion();
+      ExAcquireResourceExclusiveLite(&CmiRegistryLock, TRUE);
 
-  /* Release hive lock */
-  ExReleaseResourceLite(&CmiRegistryLock);
-  KeLeaveCriticalRegion();
+      VERIFY_KEY_OBJECT(KeyObject);
 
+      KeyObject->KeyCell->LastWriteTime.QuadPart =
+        ((PKEY_WRITE_TIME_INFORMATION)KeyInformation)->LastWriteTime.QuadPart;
+
+      CmiMarkBlockDirty (KeyObject->RegistryHive,
+		         KeyObject->KeyCellOffset);
+
+      /* Release hive lock */
+      ExReleaseResourceLite(&CmiRegistryLock);
+      KeLeaveCriticalRegion();
+    }
+
+  PostOperationInfo.Status = Status;
+  CmiCallRegisteredCallbacks(RegNtPostSetInformationKey, &PostOperationInfo);
+
   ObDereferenceObject (KeyObject);
 
-  CmiSyncHives ();
+  if (NT_SUCCESS(Status))
+    {
+      CmiSyncHives ();
+    }
 
   DPRINT ("NtSaveKey() done\n");
 

Modified: trunk/reactos/w32api/include/ddk/winddk.h
--- trunk/reactos/w32api/include/ddk/winddk.h	2005-09-24 18:28:04 UTC (rev 18030)
+++ trunk/reactos/w32api/include/ddk/winddk.h	2005-09-24 18:42:37 UTC (rev 18031)
@@ -4512,10 +4512,55 @@
   TraceHandleByNameClass
 } TRACE_INFORMATION_CLASS;
 
+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;
+
 typedef NTSTATUS
 (DDKAPI *PEX_CALLBACK_FUNCTION)(
   IN PVOID  CallbackContext,
-  IN PVOID  Argument1,
+  IN REG_NOTIFY_CLASS  Argument1,
   IN PVOID  Argument2);