Author: jgardou Date: Wed Jan 29 18:32:14 2014 New Revision: 61883
URL: http://svn.reactos.org/svn/reactos?rev=61883&view=rev Log: [WIN32K] - Implement GDIOBJ_TryLockObject and used it for DRIVEROBJs - Fix EngUnlockDriverObj
Modified: trunk/reactos/win32ss/gdi/eng/driverobj.c trunk/reactos/win32ss/gdi/eng/driverobj.h trunk/reactos/win32ss/gdi/ntgdi/gdiobj.c trunk/reactos/win32ss/gdi/ntgdi/gdiobj.h trunk/reactos/win32ss/gdi/ntgdi/misc.h
Modified: trunk/reactos/win32ss/gdi/eng/driverobj.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/eng/driverobj.c... ============================================================================== --- trunk/reactos/win32ss/gdi/eng/driverobj.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/gdi/eng/driverobj.c [iso-8859-1] Wed Jan 29 18:32:14 2014 @@ -80,7 +80,7 @@ PEDRIVEROBJ pedo;
/* Lock the object */ - pedo = DRIVEROBJ_LockObject(hdo); + pedo = DRIVEROBJ_TryLockObject(hdo); if (!pedo) { return FALSE; @@ -100,10 +100,11 @@ /* Prevent cleanup callback from being called again */ pedo->drvobj.pFreeProc = NULL;
- /* NOTE: We don't care about the bLocked param, as our handle manager - allows freeing the object, while we hold any number of locks. */ + /* Unlock if the caller indicates it is locked */ + if (bLocked) + DRIVEROBJ_UnlockObject(pedo);
- /* Delete the object */ + /* Now delete the object */ GDIOBJ_vDeleteObject(&pedo->baseobj); return TRUE; } @@ -117,7 +118,7 @@ PEDRIVEROBJ pedo;
/* Lock the object */ - pedo = DRIVEROBJ_LockObject(hdo); + pedo = DRIVEROBJ_TryLockObject(hdo);
/* Return pointer to the DRIVEROBJ structure */ return &pedo->drvobj; @@ -133,7 +134,7 @@ ULONG cLocks;
/* First lock to get a pointer to the object */ - pedo = DRIVEROBJ_LockObject(hdo); + pedo = DRIVEROBJ_TryLockObject(hdo); if(!pedo) { /* Object could not be locked, fail. */
Modified: trunk/reactos/win32ss/gdi/eng/driverobj.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/eng/driverobj.h... ============================================================================== --- trunk/reactos/win32ss/gdi/eng/driverobj.h [iso-8859-1] (original) +++ trunk/reactos/win32ss/gdi/eng/driverobj.h [iso-8859-1] Wed Jan 29 18:32:14 2014 @@ -20,7 +20,7 @@
FORCEINLINE PEDRIVEROBJ -DRIVEROBJ_LockObject(HDRVOBJ hdo) +DRIVEROBJ_TryLockObject(HDRVOBJ hdo) { - return GDIOBJ_LockObject(hdo, GDIObjType_DRVOBJ_TYPE); + return GDIOBJ_TryLockObject(hdo, GDIObjType_DRVOBJ_TYPE); }
Modified: trunk/reactos/win32ss/gdi/ntgdi/gdiobj.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/gdiobj.c?... ============================================================================== --- trunk/reactos/win32ss/gdi/ntgdi/gdiobj.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/gdi/ntgdi/gdiobj.c [iso-8859-1] Wed Jan 29 18:32:14 2014 @@ -52,11 +52,14 @@ #define ASSERT_EXCLUSIVE_OBJECT_TYPE(objt) \ ASSERT((objt) == GDIObjType_DC_TYPE || \ (objt) == GDIObjType_RGN_TYPE) +#define ASSERT_TRYLOCK_OBJECT_TYPE(objt) \ + ASSERT((objt) == GDIObjType_DRVOBJ_TYPE) #else #define DBG_INCREASE_LOCK_COUNT(ppi, hobj) #define DBG_DECREASE_LOCK_COUNT(x, y) #define ASSERT_SHARED_OBJECT_TYPE(objt) #define ASSERT_EXCLUSIVE_OBJECT_TYPE(objt) +#define ASSERT_TRYLOCK_OBJECT_TYPE(objt) #endif
#if defined(_M_IX86) || defined(_M_AMD64) @@ -623,6 +626,72 @@
PGDIOBJ NTAPI +GDIOBJ_TryLockObject( + HGDIOBJ hobj, + UCHAR objt) +{ + PENTRY pentry; + POBJ pobj; + DWORD dwThreadId; + + /* Check if the handle type matches */ + ASSERT_TRYLOCK_OBJECT_TYPE(objt); + if ((((ULONG_PTR)hobj >> 16) & 0x1f) != objt) + { + DPRINT("Wrong object type: hobj=0x%p, objt=0x%x\n", hobj, objt); + return NULL; + } + + /* Reference the handle entry */ + pentry = ENTRY_ReferenceEntryByHandle(hobj, 0); + if (!pentry) + { + DPRINT("GDIOBJ: Requested handle 0x%p is not valid.\n", hobj); + return NULL; + } + + /* Get the pointer to the BASEOBJECT */ + pobj = pentry->einfo.pobj; + + /* Check if we already own the lock */ + dwThreadId = PtrToUlong(PsGetCurrentThreadId()); + if (pobj->dwThreadId != dwThreadId) + { + /* Disable APCs and try acquiring the push lock */ + KeEnterCriticalRegion(); + if(!ExTryAcquirePushLockExclusive(&pobj->pushlock)) + { + ULONG cRefs, ulIndex; + /* Already owned. Clean up and leave. */ + KeLeaveCriticalRegion(); + + /* Calculate the index */ + ulIndex = GDI_HANDLE_GET_INDEX(pobj->hHmgr); + + /* Decrement reference count */ + ASSERT((gpaulRefCount[ulIndex] & REF_MASK_COUNT) > 0); + cRefs = InterlockedDecrement((LONG*)&gpaulRefCount[ulIndex]); + ASSERT(cRefs & REF_MASK_VALID); + + return NULL; + } + + /* Set us as lock owner */ + ASSERT(pobj->dwThreadId == 0); + pobj->dwThreadId = dwThreadId; + } + + /* Increase lock count */ + pobj->cExclusiveLock++; + DBG_INCREASE_LOCK_COUNT(PsGetCurrentProcessWin32Process(), hobj); + DBG_LOGEVENT(&pobj->slhLog, EVENT_LOCK, 0); + + /* Return the object */ + return pobj; +} + +PGDIOBJ +NTAPI GDIOBJ_LockObject( HGDIOBJ hobj, UCHAR objt)
Modified: trunk/reactos/win32ss/gdi/ntgdi/gdiobj.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/gdiobj.h?... ============================================================================== --- trunk/reactos/win32ss/gdi/ntgdi/gdiobj.h [iso-8859-1] (original) +++ trunk/reactos/win32ss/gdi/ntgdi/gdiobj.h [iso-8859-1] Wed Jan 29 18:32:14 2014 @@ -141,6 +141,12 @@ HGDIOBJ hobj, UCHAR objt);
+PGDIOBJ +NTAPI +GDIOBJ_TryLockObject( + HGDIOBJ hobj, + UCHAR objt); + VOID NTAPI GDIOBJ_vUnlockObject(
Modified: trunk/reactos/win32ss/gdi/ntgdi/misc.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/gdi/ntgdi/misc.h?re... ============================================================================== --- trunk/reactos/win32ss/gdi/ntgdi/misc.h [iso-8859-1] (original) +++ trunk/reactos/win32ss/gdi/ntgdi/misc.h [iso-8859-1] Wed Jan 29 18:32:14 2014 @@ -113,6 +113,14 @@ }
FORCEINLINE +BOOLEAN +ExTryAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock) +{ + /* Try acquiring the lock */ + return !InterlockedBitTestAndSet((PLONG)PushLock, EX_PUSH_LOCK_LOCK_V); +} + +FORCEINLINE VOID ExReleasePushLockExclusive(PEX_PUSH_LOCK PushLock) {