[FLTMGR}
[reactos.git] / reactos / drivers / filters / fltmgr / Object.c
index d0cf795..5daf903 100644 (file)
@@ -1,7 +1,7 @@
 /*
 * PROJECT:         Filesystem Filter Manager
 * LICENSE:         GPL - See COPYING in the top level directory
-* FILE:            drivers/fs_minifilter/fltmgr/Object.c
+* FILE:            drivers/filters/fltmgr/Object.c
 * PURPOSE:         Miscellaneous library functions
 * PROGRAMMERS:     Ged Murphy (gedmurphy@reactos.org)
 */
@@ -12,6 +12,7 @@
 /* INCLUDES ******************************************************************/
 
 #include "fltmgr.h"
+#include "fltmgrint.h"
 
 #define NDEBUG
 #include <debug.h>
 
 /* DATA *********************************************************************/
 
+#define ExpChangePushlock(x, y, z) InterlockedCompareExchangePointer((PVOID*)x, (PVOID)y, (PVOID)z)
 
+//
+// Pushlock bits
+//
+#define EX_PUSH_LOCK_LOCK_V             ((ULONG_PTR)0x0)
+#define EX_PUSH_LOCK_LOCK               ((ULONG_PTR)0x1)
+#define EX_PUSH_LOCK_WAITING            ((ULONG_PTR)0x2)
+#define EX_PUSH_LOCK_WAKING             ((ULONG_PTR)0x4)
+#define EX_PUSH_LOCK_MULTIPLE_SHARED    ((ULONG_PTR)0x8)
+#define EX_PUSH_LOCK_SHARE_INC          ((ULONG_PTR)0x10)
+#define EX_PUSH_LOCK_PTR_BITS           ((ULONG_PTR)0xf)
 
 /* EXPORTED FUNCTIONS ******************************************************/
 
 
 NTSTATUS
-NTAPI
-FltObjectReference(_Inout_ PFLT_OBJECT Object)
+FLTAPI
+FltObjectReference(_Inout_ PVOID Object)
 {
-    if (!FltpExAcquireRundownProtection(&Object->RundownRef))
+    if (!FltpExAcquireRundownProtection(&((PFLT_OBJECT)Object)->RundownRef))
     {
         return STATUS_FLT_DELETING_OBJECT;
     }
@@ -36,11 +48,90 @@ FltObjectReference(_Inout_ PFLT_OBJECT Object)
     return STATUS_SUCCESS;
 }
 
-BOOLEAN
-NTAPI
-FltObjectDereference(_Inout_ PFLT_OBJECT Object)
+VOID
+FLTAPI
+FltObjectDereference(_Inout_ PVOID Object)
+{
+    FltpExReleaseRundownProtection(&((PFLT_OBJECT)Object)->RundownRef);
+}
+
+
+_Acquires_lock_(_Global_critical_region_)
+_IRQL_requires_max_(APC_LEVEL)
+VOID
+FLTAPI
+FltAcquirePushLockExclusive(_Inout_ _Requires_lock_not_held_(*_Curr_) _Acquires_lock_(*_Curr_) PEX_PUSH_LOCK PushLock)
 {
-    return FltpExReleaseRundownProtection(&Object->RundownRef);
+    KeEnterCriticalRegion();
+
+    /* Try acquiring the lock */
+    if (InterlockedBitTestAndSet((PLONG)PushLock, EX_PUSH_LOCK_LOCK_V))
+    {
+        /* Someone changed it, use the slow path */
+        ExfAcquirePushLockExclusive(PushLock);
+    }
+
+    /* Sanity check */
+    FLT_ASSERT(PushLock->Locked);
+}
+
+
+_Acquires_lock_(_Global_critical_region_)
+_IRQL_requires_max_(APC_LEVEL)
+VOID
+FLTAPI
+FltAcquirePushLockShared(_Inout_ _Requires_lock_not_held_(*_Curr_) _Acquires_lock_(*_Curr_) PEX_PUSH_LOCK PushLock)
+{
+    EX_PUSH_LOCK NewValue;
+
+    KeEnterCriticalRegion();
+
+    /* Try acquiring the lock */
+    NewValue.Value = EX_PUSH_LOCK_LOCK | EX_PUSH_LOCK_SHARE_INC;
+    if (ExpChangePushlock(PushLock, NewValue.Ptr, 0))
+    {
+        /* Someone changed it, use the slow path */
+        ExfAcquirePushLockShared(PushLock);
+    }
+
+    /* Sanity checks */
+    ASSERT(PushLock->Locked);
+}
+
+_Releases_lock_(_Global_critical_region_)
+_IRQL_requires_max_(APC_LEVEL)
+VOID
+FLTAPI
+FltReleasePushLock(_Inout_ _Requires_lock_held_(*_Curr_) _Releases_lock_(*_Curr_) PEX_PUSH_LOCK PushLock)
+{
+    EX_PUSH_LOCK OldValue = *PushLock;
+    EX_PUSH_LOCK NewValue;
+
+    /* Sanity checks */
+    FLT_ASSERT(OldValue.Locked);
+
+    /* Check if the pushlock is shared */
+    if (OldValue.Shared > 1)
+    {
+        /* Decrease the share count */
+        NewValue.Value = OldValue.Value - EX_PUSH_LOCK_SHARE_INC;
+    }
+    else
+    {
+        /* Clear the pushlock entirely */
+        NewValue.Value = 0;
+    }
+
+    /* Check if nobody is waiting on us and try clearing the lock here */
+    if ((OldValue.Waiting) ||
+        (ExpChangePushlock(PushLock, NewValue.Ptr, OldValue.Ptr) !=
+         OldValue.Ptr))
+    {
+        /* We have waiters, use the long path */
+        ExfReleasePushLock(PushLock);
+    }
+
+    KeLeaveCriticalRegion();
 }
 
 
@@ -156,3 +247,26 @@ FltpGetObjectName(_In_ PVOID Object,
 
     return Status;
 }
+
+ULONG
+FltpObjectPointerReference(_In_ PFLT_OBJECT Object)
+{
+    PULONG Result;
+
+    /* Store the old count and increment */
+    Result = &Object->PointerCount;
+    InterlockedIncrement((PLONG)&Object->PointerCount);
+
+    /* Return the initial value */
+    return *Result;
+}
+
+VOID
+FltpObjectPointerDereference(_In_ PFLT_OBJECT Object)
+{
+    if (!InterlockedDecrement((PLONG)Object->PointerCount))
+    {
+        // Cleanup
+        FLT_ASSERT(FALSE);
+    }
+}
\ No newline at end of file