- Add internal macros for acquiring the object directory pushlock during lookup ...
authorAlex Ionescu <aionescu@gmail.com>
Tue, 9 Jan 2007 07:28:40 +0000 (07:28 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Tue, 9 Jan 2007 07:28:40 +0000 (07:28 +0000)
- Add internal macros for incrementing/decrementing query references, and use them where appropriate. Do not yet support the path for an object which is currently being defer deleted.
- Add internal macros for cleaning up a directory lookup (not yet used and needs renaming/cleanup), initializing a directory lookup (not yet used).
- Don't call security callback in ObpDeleteNameCheck. Make sure permanent flag is still cleared after acquiring type lock. Add special call for symboilc links. Add commented out calls to lock the object directory.

svn path=/trunk/; revision=25392

reactos/ntoskrnl/include/internal/ob_x.h
reactos/ntoskrnl/ob/obhandle.c
reactos/ntoskrnl/ob/obname.c

index 12cb5e9..cf7ce25 100644 (file)
@@ -6,6 +6,8 @@
 * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
 */
 
+#include "ex.h"
+
 #if DBG
 VOID
 FORCEINLINE
@@ -53,6 +55,193 @@ ObpCalloutEnd(IN KIRQL CalloutIrql,
 }
 #endif
 
+VOID
+FORCEINLINE
+_ObpAcquireDirectoryLockShared(IN POBJECT_DIRECTORY Directory,
+                               IN POBP_LOOKUP_CONTEXT Context)
+{
+    /* It's not, set lock flag */
+    Context->LockStateSignature = 0xBBBB1234;
+
+    /* Lock it */
+    KeEnterCriticalRegion();
+    ExAcquirePushLockShared(&Directory->Lock);
+
+    /* Update lock flag */
+    Context->LockStateSignature = 0xDDDD1234;
+}
+
+VOID
+FORCEINLINE
+_ObpAcquireDirectoryLockExclusive(IN POBJECT_DIRECTORY Directory,
+                                  IN POBP_LOOKUP_CONTEXT Context)
+{
+    /* Update lock flag */
+    Context->LockStateSignature = 0xAAAA1234;
+
+    /* Lock it */
+    KeEnterCriticalRegion();
+    ExAcquirePushLockExclusive(&Directory->Lock);
+}
+
+VOID
+FORCEINLINE
+_ObpReleaseDirectoryLock(IN POBJECT_DIRECTORY Directory,
+                         IN POBP_LOOKUP_CONTEXT Context)
+{
+    /* Release the lock */
+    ExReleasePushLock(&Directory->Lock);
+    Context->LockStateSignature = 0xEEEE1234;
+    KeLeaveCriticalRegion();
+}
+
+ULONG
+FORCEINLINE
+ObpIncrementQueryReference(IN POBJECT_HEADER ObjectHeader,
+                           IN POBJECT_HEADER_NAME_INFO ObjectNameInfo)
+{
+    ULONG NewValue, References;
+
+    /* Get the number of references */
+    NewValue = ObjectNameInfo->QueryReferences;
+    while ((NewValue != 0) && (References = NewValue))
+    {
+        /* Increment the number of references */
+        if (InterlockedCompareExchange(&ObjectNameInfo->QueryReferences,
+                                       NewValue + 1,
+                                       NewValue) == References)
+        {
+            /* Check if the object is to be deferred deleted */
+            if (ObjectHeader->Flags & OB_FLAG_DEFER_DELETE)
+            {
+                /* FIXME: Unhandled*/
+                DbgPrint("OB: Unhandled path\n");
+                KEBUGCHECK(0);
+            }
+
+            /* Done looping */
+            NewValue = ObjectNameInfo->QueryReferences;
+            break;
+        }
+    }
+
+    /* Return the number of references */
+    return NewValue;
+}
+
+VOID
+FORCEINLINE
+_ObpDecrementQueryReference(IN POBJECT_HEADER_NAME_INFO HeaderNameInfo)
+{
+    POBJECT_DIRECTORY Directory;
+
+    /* Remove a query reference and check if it was the last one */
+    if (!InterlockedExchangeAdd(&HeaderNameInfo->QueryReferences, -1))
+    {
+        /* Check if we have a name */
+        if (HeaderNameInfo->Name.Buffer)
+        {
+            /* We can get rid of the object name now */
+            ExFreePool(HeaderNameInfo->Name.Buffer);
+            RtlInitEmptyUnicodeString(&HeaderNameInfo->Name, NULL, 0);
+        }
+
+        /* Check if the object has a directory associated to it */
+        Directory = HeaderNameInfo->Directory;
+        if (Directory)
+        {
+            /* Delete the directory */
+            HeaderNameInfo->Directory = NULL;
+            ObDereferenceObjectDeferDelete(Directory);
+        }
+    }
+}
+
+VOID
+FORCEINLINE
+_ObpCleanupDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context,
+                           IN BOOLEAN DereferenceObject)
+{
+    POBJECT_HEADER ObjectHeader;
+    POBJECT_HEADER_NAME_INFO HeaderNameInfo;
+
+    /* Check if we came back with the directory locked */
+    if (Context->DirectoryLocked)
+    {
+        /* Release the lock */
+        _ObpReleaseDirectoryLock(Context->Directory, Context);
+    }
+
+    /* Clear the context  */
+    Context->Directory = NULL;
+    Context->DirectoryLocked = FALSE;
+
+    /* Check if we had found an object */
+    if (Context->Object)
+    {
+        /* Get the object name information */
+        ObjectHeader = OBJECT_TO_OBJECT_HEADER(Context->Object);
+        HeaderNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
+
+        /* Check if we do have name information */
+        if (HeaderNameInfo) _ObpDecrementQueryReference(HeaderNameInfo);
+
+        /* Check if we need to dereference it */
+        if (DereferenceObject) ObDereferenceObject(Context->Object);
+    }
+}
+
+VOID
+FORCEINLINE
+_ObpInitializeDirectoryLookup(IN POBP_LOOKUP_CONTEXT Context)
+{
+    /* Initialize a null context */
+    Context->Object = NULL;
+    Context->Directory = NULL;
+    Context->DirectoryLocked = FALSE;
+    Context->LockStateSignature = 0xFFFF1234;
+}
+
+#if _OB_DEBUG_
+#define ObpAcquireDirectoryLockShared(a, b)                                 \
+{                                                                           \
+    DbgPrint("OB QUERY: Acquiring lock at %s %d\n", __FUNCTION__, __LINE__);\
+    _ObpAcquireDirectoryLockShared(a, b);                                   \
+}
+#define ObpAcquireDirectoryLockExclusive(a, b)                              \
+{                                                                           \
+    DbgPrint("OB QUERY: Acquiring lock at %s %d\n", __FUNCTION__, __LINE__);\
+    _ObpAcquireDirectoryLockExclusive(a, b);                                \
+}
+#define ObpReleaseDirectoryLock(a, b)                                       \
+{                                                                           \
+    DbgPrint("OB QUERY: Releasing lock at %s %d\n", __FUNCTION__, __LINE__);\
+    _ObpReleaseDirectoryLock(a, b);                                         \
+}
+#define ObpInitializeDirectoryLookup(a)                                     \
+{                                                                           \
+    DbgPrint("OB QUERY: Initialization at %s %d\n", __FUNCTION__, __LINE__);\
+    _ObpInitializeDirectoryLookup(a);                                       \
+}
+#define ObpCleanupDirectoryLookup(a, b)                                     \
+{                                                                           \
+    DbgPrint("OB QUERY: Cleanup at %s %d\n", __FUNCTION__, __LINE__);       \
+    _ObpCleanupDirectoryLookup(a, b);                                       \
+}
+#define ObpDecrementQueryReference(a)                                       \
+{                                                                           \
+    DbgPrint("OB QUERY: Decrement at %s %d\n", __FUNCTION__, __LINE__);     \
+    _ObpDecrementQueryReference(a);                                         \
+}
+#else
+#define ObpDecrementQueryReference          _ObpDecrementQueryReference
+#define ObpAcquireDirectoryLockExclusive    _ObpAcquireDirectoryLockExclusive
+#define ObpAcquireDirectoryLockShared       _ObpAcquireDirectoryLockShared
+#define ObpReleaseDirectoryLock             _ObpReleaseDirectoryLock
+#define ObpInitializeDirectoryLookup        _ObpInitializeDirectoryLookup
+#define ObpCleanupDirectoryLookup           _ObpCleanupDirectoryLookup
+#endif
+
 VOID
 FORCEINLINE
 ObpEnterObjectTypeMutex(IN POBJECT_TYPE ObjectType)
@@ -176,3 +365,5 @@ ObpFreeAndReleaseCapturedAttributes(IN POBJECT_CREATE_INFORMATION ObjectCreateIn
     ObpFreeCapturedAttributes(ObjectCreateInfo, LookasideCreateInfoList);
 }
 
+
+
index 1746b43..66700b8 100644 (file)
@@ -2352,6 +2352,16 @@ ObInsertObject(IN PVOID Object,
     ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
     ObjectType = ObjectHeader->Type;
 
+    /* Check if we have name information */
+    if (ObjectNameInfo)
+    {
+        /* Add a query reference */
+        if (!ObpIncrementQueryReference(ObjectHeader, ObjectNameInfo))
+        {
+            /* There are no query references, so the name info is invalid */
+            ObjectNameInfo = NULL;
+        }
+    }
 
     /* Check if this is an named object */
     ObjectName = NULL;
@@ -2394,6 +2404,8 @@ ObInsertObject(IN PVOID Object,
         ObpFreeAndReleaseCapturedAttributes(ObjectCreateInfo);
         ObjectHeader->ObjectCreateInfo = NULL;
 
+        /* Remove a query reference if we added one */
+        if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
 
         /* Remove the extra keep-alive reference */
         if (Handle) ObDereferenceObject(Object);
@@ -2419,6 +2431,7 @@ ObInsertObject(IN PVOID Object,
         if (!NT_SUCCESS(Status))
         {
             /* Fail */
+            if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
             ObDereferenceObject(Object);
             return Status;
         }
@@ -2489,7 +2502,10 @@ ObInsertObject(IN PVOID Object,
         /* Check if anything until now failed */
         if (!NT_SUCCESS(Status))
         {
-            /* We failed, dereference the object and delete the access state */
+            /* Remove query reference that we added */
+            if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
+
+            /* Dereference the object and delete the access state */
             ObDereferenceObject(Object);
             if (AccessState == &LocalAccessState)
             {
@@ -2554,8 +2570,10 @@ ObInsertObject(IN PVOID Object,
         /* Check if anything until now failed */
         if (!NT_SUCCESS(Status))
         {
-            /* We failed, dereference the object and delete the access state */
-            KEBUGCHECK(0);
+            /* Remove query reference that we added */
+            if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
+
+            /* Dereference the object and delete the access state */
             ObDereferenceObject(Object);
             if (AccessState == &LocalAccessState)
             {
@@ -2564,6 +2582,7 @@ ObInsertObject(IN PVOID Object,
             }
 
             /* Return failure code */
+            KEBUGCHECK(0);
             return Status;
         }
     }
@@ -2608,8 +2627,8 @@ ObInsertObject(IN PVOID Object,
         RealStatus = Status;
     }
 
-
-
+    /* Remove a query reference */
+    if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
 
     /* Remove the extra keep-alive reference */
     if (Handle) ObDereferenceObject(Object);
index c72bfe6..503a2f7 100644 (file)
@@ -173,6 +173,17 @@ ObpDeleteNameCheck(IN PVOID Object)
     ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
     ObjectType = ObjectHeader->Type;
 
+    /* Check if we have a name information structure */
+    if (ObjectNameInfo)
+    {
+        /* Add a query reference */
+        if (!ObpIncrementQueryReference(ObjectHeader, ObjectNameInfo))
+        {
+            /* No references, so the name info is invalid */
+            ObjectNameInfo = NULL;
+        }
+    }
+
     /*
      * Check if the handle count is 0, if the object is named,
      * and if the object isn't a permanent object.
@@ -182,62 +193,89 @@ ObpDeleteNameCheck(IN PVOID Object)
          (ObjectNameInfo->Name.Length) &&
          !(ObjectHeader->Flags & OB_FLAG_PERMANENT))
     {
+        /* Setup a lookup context */
         Context.Object = NULL;
 
-        /* Make sure it's still inserted */
+        /* Lock the directory */
+        //ObpAcquireDirectoryLockExclusive(ObjectNameInfo->Directory, &Context);
+
+        /* Set the lookup parameters */
         Context.Directory = ObjectNameInfo->Directory;
         Context.DirectoryLocked = TRUE;
+        Context.LockStateSignature = 0xCCCC1234;
+
+        /* Do the lookup */
         Object = ObpLookupEntryDirectory(ObjectNameInfo->Directory,
                                          &ObjectNameInfo->Name,
                                          0,
                                          FALSE,
                                          &Context);
-        if ((Object) && !(ObjectHeader->HandleCount))
+        if (Object)
         {
             /* Lock the object type */
             ObpEnterObjectTypeMutex(ObjectType);
 
-            /* First delete it from the directory */
-            ObpDeleteEntryDirectory(&Context);
-
-            /* Now check if we have a security callback */
-            if (ObjectType->TypeInfo.SecurityRequired)
+            /* Make sure we can still delete the object */
+            if (!(ObjectHeader->HandleCount) &&
+                !(ObjectHeader->Flags & OB_FLAG_PERMANENT))
             {
-                /* Call it */
-                ObjectType->TypeInfo.SecurityProcedure(Object,
-                                                       DeleteSecurityDescriptor,
-                                                       0,
-                                                       NULL,
-                                                       NULL,
-                                                       &ObjectHeader->
-                                                       SecurityDescriptor,
-                                                       ObjectType->
-                                                       TypeInfo.PoolType,
-                                                       NULL);
+                /* First delete it from the directory */
+                ObpDeleteEntryDirectory(&Context);
+
+                /* Check if this is a symbolic link */
+                if (ObjectType == ObSymbolicLinkType)
+                {
+                    /* Remove internal name */
+                    ObpDeleteSymbolicLinkName(Object);
+                }
+
+                /* Add a query reference */
+                ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
+                if (!ObpIncrementQueryReference(ObjectHeader, ObjectNameInfo))
+                {
+                    /* No references, so the name info is invalid */
+                    ObjectNameInfo = NULL;
+                }
+
+                /* Check if the magic protection flag is set */
+                if ((ObjectNameInfo) &&
+                    (ObjectNameInfo->QueryReferences & 0x40000000))
+                {
+                    /* Add deletion flag */
+                    InterlockedExchangeAdd(&ObjectNameInfo->QueryReferences,
+                                           0xC0000000);
+                }
+
+                /* Get the directory */
+                Directory = ObjectNameInfo->Directory;
             }
 
             /* Release the lock */
             ObpLeaveObjectTypeMutex(ObjectType);
+        }
 
-            /* Free the name */
-            ExFreePool(ObjectNameInfo->Name.Buffer);
-            RtlInitEmptyUnicodeString(&ObjectNameInfo->Name, NULL, 0);
-
-            Context.Object = NULL;
+        /* Cleanup after lookup */
+        //ObpCleanupDirectoryLookup(&Context, TRUE);
+        Context.Object = NULL;
 
-            /* Clear the current directory and de-reference it */
-            Directory = ObjectNameInfo->Directory;
-            ObjectNameInfo->Directory = NULL;
-        }
+        /* Remove another query reference since we added one on top */
+        ObpDecrementQueryReference(ObjectNameInfo);
 
         /* Check if we were inserted in a directory */
         if (Directory)
         {
-            /* We were, so dereference the directory and the object as well */
-            ObDereferenceObject(Directory);
+            /* We were, so first remove the extra reference we had added */
+            ObpDecrementQueryReference(ObjectNameInfo);
+
+            /* Now dereference the object as well */
             ObDereferenceObject(Object);
         }
     }
+    else
+    {
+        /* Remove the reference we added */
+        if (ObjectNameInfo) ObpDecrementQueryReference(ObjectNameInfo);
+    }
 }
 
 NTSTATUS