- Implement GDIOBJ_TryLockObject and used it for DRIVEROBJs
 - Fix EngUnlockDriverObj

svn path=/trunk/; revision=61883
This commit is contained in:
Jérôme Gardou 2014-01-29 18:32:14 +00:00
parent ad76a6a077
commit e2be2729b0
5 changed files with 92 additions and 8 deletions

View file

@ -80,7 +80,7 @@ EngDeleteDriverObj(
PEDRIVEROBJ pedo;
/* Lock the object */
pedo = DRIVEROBJ_LockObject(hdo);
pedo = DRIVEROBJ_TryLockObject(hdo);
if (!pedo)
{
return FALSE;
@ -100,10 +100,11 @@ EngDeleteDriverObj(
/* 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 @@ EngLockDriverObj(
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 @@ EngUnlockDriverObj(
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. */

View file

@ -20,7 +20,7 @@ BOOL NTAPI DRIVEROBJ_Cleanup(PVOID pObject);
FORCEINLINE
PEDRIVEROBJ
DRIVEROBJ_LockObject(HDRVOBJ hdo)
DRIVEROBJ_TryLockObject(HDRVOBJ hdo)
{
return GDIOBJ_LockObject(hdo, GDIObjType_DRVOBJ_TYPE);
return GDIOBJ_TryLockObject(hdo, GDIObjType_DRVOBJ_TYPE);
}

View file

@ -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)
@ -621,6 +624,72 @@ GDIOBJ_vReferenceObjectByPointer(POBJ pobj)
DBG_LOGEVENT(&pobj->slhLog, EVENT_REFERENCE, cRefs);
}
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(

View file

@ -141,6 +141,12 @@ GDIOBJ_LockObject(
HGDIOBJ hobj,
UCHAR objt);
PGDIOBJ
NTAPI
GDIOBJ_TryLockObject(
HGDIOBJ hobj,
UCHAR objt);
VOID
NTAPI
GDIOBJ_vUnlockObject(

View file

@ -112,6 +112,14 @@ ExAcquirePushLockExclusive(PEX_PUSH_LOCK PushLock)
}
}
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)