PEDRIVEROBJ pedo;
/* Lock the object */
- pedo = DRIVEROBJ_LockObject(hdo);
+ pedo = DRIVEROBJ_TryLockObject(hdo);
if (!pedo)
{
return FALSE;
/* 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;
}
PEDRIVEROBJ pedo;
/* Lock the object */
- pedo = DRIVEROBJ_LockObject(hdo);
+ pedo = DRIVEROBJ_TryLockObject(hdo);
/* Return pointer to the DRIVEROBJ structure */
return &pedo->drvobj;
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. */
#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)
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(