X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=reactos%2Fdrivers%2Ffilters%2Ffltmgr%2FObject.c;h=5daf9033a1106c20f6ff01dd776cba83f2912805;hp=d0cf795ccd59e876e248280d35bbd03ed7313188;hb=fb1948e7d4a7c6b2fd62c102b24ca0308f7d76fa;hpb=6e3d7d5199863a77009c46a35f2703a2742a3fd5 diff --git a/reactos/drivers/filters/fltmgr/Object.c b/reactos/drivers/filters/fltmgr/Object.c index d0cf795ccd5..5daf9033a11 100644 --- a/reactos/drivers/filters/fltmgr/Object.c +++ b/reactos/drivers/filters/fltmgr/Object.c @@ -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 @@ -19,16 +20,27 @@ /* 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