You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1021 lines
26 KiB
1021 lines
26 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: DdHmgr.cxx
|
|
*
|
|
* DirectDraw handle manager API entry points
|
|
*
|
|
* Created: 30-Apr-1999 23:03:03
|
|
* Author: Lindsay Steventon [linstev]
|
|
*
|
|
* Copyright (c) 1989-1999 Microsoft Corporation
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.hxx"
|
|
|
|
ULONG gcSizeDdHmgr = DD_TABLESIZE_DELTA; // Start table size
|
|
DD_ENTRY *gpentDdHmgrLast = NULL; // Previous handle table
|
|
DD_ENTRY *gpentDdHmgr = NULL; // Points to handle table
|
|
HDD_OBJ ghFreeDdHmgr; // Free handle
|
|
ULONG gcMaxDdHmgr; // Max handle alloc-ed so far
|
|
HSEMAPHORE ghsemHmgr = NULL; // Synchronization of the handle manager
|
|
PLARGE_INTEGER gpLockShortDelay;
|
|
|
|
// Prototype for a handy debugging routine.
|
|
#if DBG
|
|
extern "C"
|
|
VOID
|
|
DdHmgPrintBadHandle(
|
|
HDD_OBJ hobj,
|
|
DD_OBJTYPE objt
|
|
);
|
|
#else
|
|
#define DdHmgPrintBadHandle(hobj, objt)
|
|
#endif
|
|
|
|
HDD_OBJ hDdGetFreeHandle(DD_OBJTYPE objt);
|
|
VOID DdFreeObject(PVOID pvFree, ULONG ulType);
|
|
HDD_OBJ FASTCALL DdHmgNextOwned(HDD_OBJ hobj, W32PID pid);
|
|
|
|
/*****************************Exported*Routine*****************************\
|
|
* DdHmgCreate()
|
|
*
|
|
* Initializes a new handle manager with an initial allocation.
|
|
*
|
|
* History:
|
|
*
|
|
* 30-Apr-1999 -by- Lindsay Steventon [linstev]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
DdHmgCreate()
|
|
{
|
|
//
|
|
// Initialize the handle manager allocation database.
|
|
//
|
|
|
|
ghFreeDdHmgr = 0; // No free handles
|
|
gcMaxDdHmgr = DD_HMGR_HANDLE_BASE; // Initialize with handle index base
|
|
|
|
//
|
|
// Create memory block for handle table
|
|
//
|
|
|
|
gpentDdHmgr = (DD_ENTRY *)PALLOCMEM(sizeof(DD_ENTRY) * gcSizeDdHmgr, 'ddht');
|
|
if (gpentDdHmgr == NULL)
|
|
{
|
|
WARNING("Could not allocated DDraw handle table.");
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Initialize exclusion stuff.
|
|
//
|
|
|
|
if ((ghsemHmgr = EngCreateSemaphore()) == NULL)
|
|
{
|
|
WARNING("Could not allocated DDraw handle semaphore.");
|
|
VFREEMEM(gpentDdHmgr);
|
|
gpentDdHmgr = NULL;
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// allocate and initialize the timeout lock for the handle manager.
|
|
//
|
|
|
|
gpLockShortDelay = (PLARGE_INTEGER) PALLOCNONPAGED(sizeof(LARGE_INTEGER),
|
|
'iniG');
|
|
|
|
if (gpLockShortDelay == NULL)
|
|
{
|
|
WARNING("Could not allocated DDraw shortdelay.");
|
|
EngDeleteSemaphore(ghsemHmgr);
|
|
ghsemHmgr = NULL;
|
|
VFREEMEM(gpentDdHmgr);
|
|
gpentDdHmgr = NULL;
|
|
return(FALSE);
|
|
}
|
|
|
|
gpLockShortDelay->LowPart = (ULONG) -100000;
|
|
gpLockShortDelay->HighPart = -1;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/*****************************Exported*Routine*****************************\
|
|
* DdHmgDestroy()
|
|
*
|
|
* Free memory allocated by the handle manager. This happens on system
|
|
* shutdown. Always succeeds.
|
|
*
|
|
* History:
|
|
*
|
|
* 30-Apr-1999 -by- Lindsay Steventon [linstev]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
DdHmgDestroy()
|
|
{
|
|
ghFreeDdHmgr = 0; // Zero free handles
|
|
gcMaxDdHmgr = 0; // Zero current last handle
|
|
gcSizeDdHmgr = 0; // Handle table size
|
|
gpentDdHmgrLast = NULL; // Zero previos handle table pointer
|
|
|
|
if (gpentDdHmgr) // Free handle table
|
|
{
|
|
VFREEMEM(gpentDdHmgr);
|
|
gpentDdHmgr = NULL;
|
|
}
|
|
|
|
if (ghsemHmgr)
|
|
{
|
|
EngDeleteSemaphore(ghsemHmgr);
|
|
ghsemHmgr = NULL;
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/*****************************Exported*Routine*****************************\
|
|
* DdHmgCloseProcess()
|
|
*
|
|
* Free handles in handle table from process. Occurs on process cleanup.
|
|
*
|
|
* History:
|
|
*
|
|
* 30-Apr-1999 -by- Lindsay Steventon [linstev]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
DdHmgCloseProcess(W32PID W32Pid)
|
|
{
|
|
BOOL bRes = TRUE;
|
|
|
|
HDD_OBJ hobj;
|
|
|
|
DdHmgAcquireHmgrSemaphore();
|
|
|
|
hobj = DdHmgNextOwned((HDD_OBJ) 0, W32Pid);
|
|
|
|
DdHmgReleaseHmgrSemaphore();
|
|
|
|
while (hobj != (HDD_OBJ) NULL)
|
|
{
|
|
switch (DdHmgObjtype(hobj))
|
|
{
|
|
case DD_DIRECTDRAW_TYPE:
|
|
bRes = bDdDeleteDirectDrawObject((HANDLE)hobj, TRUE);
|
|
break;
|
|
|
|
case DD_SURFACE_TYPE:
|
|
bRes = bDdDeleteSurfaceObject((HANDLE)hobj, NULL);
|
|
break;
|
|
|
|
case DD_MOTIONCOMP_TYPE:
|
|
bRes = bDdDeleteMotionCompObject((HANDLE)hobj, NULL);
|
|
break;
|
|
|
|
case DD_VIDEOPORT_TYPE:
|
|
bRes = bDdDeleteVideoPortObject((HANDLE)hobj, NULL);
|
|
break;
|
|
|
|
case D3D_HANDLE_TYPE:
|
|
HRESULT hr;
|
|
bRes = D3dDeleteHandle((HANDLE)hobj, 0, NULL, &hr) ==
|
|
DDHAL_DRIVER_HANDLED;
|
|
break;
|
|
|
|
default:
|
|
bRes = FALSE;
|
|
break;
|
|
}
|
|
|
|
#if DBG
|
|
if (bRes == FALSE)
|
|
{
|
|
DbgPrint("DDRAW ERROR: DdHmgCloseProcess couldn't delete "
|
|
"obj = %p, type j=%lx\n", hobj, DdHmgObjtype(hobj));
|
|
}
|
|
#endif
|
|
|
|
// Move on to next object.
|
|
|
|
DdHmgAcquireHmgrSemaphore();
|
|
|
|
hobj = DdHmgNextOwned(hobj, W32Pid);
|
|
|
|
DdHmgReleaseHmgrSemaphore();
|
|
}
|
|
|
|
return (bRes);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* DdHmgValidHandle
|
|
*
|
|
* Returns TRUE if the handle is valid, FALSE if not.
|
|
*
|
|
* Note we don't need to lock the semaphore, we aren't changing anything,
|
|
* we are just looking.
|
|
*
|
|
* History:
|
|
*
|
|
* 30-Apr-1999 -by- Lindsay Steventon [linstev]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
DdHmgValidHandle(
|
|
HDD_OBJ hobj,
|
|
DD_OBJTYPE objt)
|
|
{
|
|
BOOL bRes = FALSE;
|
|
PDD_ENTRY pentTmp;
|
|
UINT uiIndex = (UINT) (UINT) DdHmgIfromH(hobj);
|
|
|
|
//
|
|
// Acquire the handle manager lock before touching gpentDdHmgr
|
|
//
|
|
|
|
DdHmgAcquireHmgrSemaphore();
|
|
|
|
if ((uiIndex < gcMaxDdHmgr) &&
|
|
((pentTmp = &gpentDdHmgr[uiIndex])->Objt == objt) &&
|
|
(pentTmp->FullUnique == DdHmgUfromH(hobj)))
|
|
{
|
|
ASSERTGDI(pentTmp->einfo.pobj != (PDD_OBJ) NULL, "ERROR how can it be NULL");
|
|
bRes = TRUE;
|
|
}
|
|
|
|
DdHmgReleaseHmgrSemaphore();
|
|
|
|
return (bRes);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* DdHmgRemoveObject
|
|
*
|
|
* Removes an object from the handle table if certain conditions are met.
|
|
*
|
|
* History:
|
|
*
|
|
* 30-Apr-1999 -by- Lindsay Steventon [linstev]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
PVOID
|
|
DdHmgRemoveObject(
|
|
HDD_OBJ hobj,
|
|
LONG cExclusiveLock,
|
|
LONG cShareLock,
|
|
BOOL bIgnoreUndeletable,
|
|
DD_OBJTYPE objt)
|
|
{
|
|
PDD_OBJ pobj;
|
|
UINT uiIndex = (UINT) DdHmgIfromH(hobj);
|
|
|
|
if (uiIndex < gcMaxDdHmgr)
|
|
{
|
|
//
|
|
// Acquire the handle manager lock before touching gpentDdHmgr
|
|
//
|
|
|
|
DdHmgAcquireHmgrSemaphore();
|
|
|
|
//
|
|
// lock handle
|
|
//
|
|
|
|
PDD_ENTRY pentTmp = &gpentDdHmgr[uiIndex];
|
|
|
|
if (VerifyObjectOwner(pentTmp))
|
|
{
|
|
//
|
|
// verify objt and unique
|
|
//
|
|
|
|
if ((pentTmp->Objt == objt) &&
|
|
(pentTmp->FullUnique == DdHmgUfromH(hobj)))
|
|
{
|
|
pobj = pentTmp->einfo.pobj;
|
|
|
|
if ((pobj->cExclusiveLock == (USHORT)cExclusiveLock) &&
|
|
(pobj->ulShareCount == (ULONG)cShareLock))
|
|
{
|
|
if (bIgnoreUndeletable || (!(pentTmp->Flags & DD_HMGR_ENTRY_UNDELETABLE)))
|
|
{
|
|
//
|
|
// set the handle in the object to NULL
|
|
// to prevent/catch accidental decrement of the
|
|
// shared reference count
|
|
//
|
|
|
|
pobj->hHmgr = NULL;
|
|
|
|
//
|
|
// free the handle
|
|
//
|
|
|
|
((DD_ENTRYOBJ *) pentTmp)->vFree(uiIndex);
|
|
}
|
|
else
|
|
{
|
|
WARNING1("DdHmgRemove failed object is undeletable\n");
|
|
pobj = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// object is busy
|
|
//
|
|
|
|
WARNING1("DdHmgRemove failed - object busy elsewhere\n");
|
|
pobj = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING1("DdHmgRemove: bad objt or unique\n");
|
|
pobj = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING1("DdHmgRemove: failed to lock handle\n");
|
|
pobj = NULL;
|
|
}
|
|
|
|
DdHmgReleaseHmgrSemaphore();
|
|
}
|
|
else
|
|
{
|
|
WARNING1("DdHmgRemove failed invalid index\n");
|
|
pobj = NULL;
|
|
}
|
|
|
|
return((PVOID)pobj);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* DdAllocateObject
|
|
*
|
|
* Allocates an object out of the heap.
|
|
*
|
|
* History:
|
|
*
|
|
* 30-Apr-1999 -by- Lindsay Steventon [linstev]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
//
|
|
// This struct and the following union can be thrown away
|
|
// when someone fixes the BASEOBJECT cExclusiveLock and BaseFlags sharing
|
|
// the same DWORD.
|
|
//
|
|
|
|
struct SplitLockAndFlags {
|
|
USHORT c_cExclusiveLock;
|
|
USHORT c_BaseFlags;
|
|
};
|
|
|
|
union SplitOrCombinedLockAndFlags {
|
|
SplitLockAndFlags S;
|
|
ULONG W;
|
|
};
|
|
|
|
PVOID
|
|
DdAllocateObject(
|
|
ULONG cBytes,
|
|
ULONG ulType,
|
|
BOOL bZero)
|
|
{
|
|
|
|
PVOID pvReturn = NULL;
|
|
|
|
ASSERTGDI(ulType != DD_DEF_TYPE, "DdAllocateObject ulType is bad");
|
|
ASSERTGDI(cBytes >= sizeof(DD_BASEOBJECT), "DdAllocateObject cBytes is bad");
|
|
|
|
//
|
|
// Debug check to avoid assert in ExAllocatePool
|
|
//
|
|
|
|
#if DBG
|
|
if (cBytes >= (PAGE_SIZE * 10000))
|
|
{
|
|
WARNING("DdAllocateObject: cBytes >= 10000 pages");
|
|
return(NULL);
|
|
}
|
|
#endif
|
|
|
|
|
|
ULONG ulTag = '0 hD';
|
|
ulTag += ulType << 24;
|
|
|
|
//
|
|
// BASEOBJECT is always zero-initialized.
|
|
//
|
|
|
|
if (bZero)
|
|
{
|
|
pvReturn = PALLOCMEM(cBytes, ulTag);
|
|
}
|
|
else
|
|
{
|
|
pvReturn = PALLOCNOZ(cBytes, ulTag);
|
|
|
|
//
|
|
// At least the BASEOBJECT should be initialized.
|
|
//
|
|
|
|
if (pvReturn)
|
|
{
|
|
RtlZeroMemory(pvReturn, (UINT) sizeof(DD_BASEOBJECT));
|
|
}
|
|
}
|
|
|
|
//
|
|
// If the allocation failed again, then set the extended
|
|
// error status and return an invalid handle.
|
|
//
|
|
|
|
if (!pvReturn)
|
|
{
|
|
KdPrint(("DXG: DdAllocateObject failed alloc of %lu bytes\n", (cBytes)));
|
|
SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
|
|
return NULL;
|
|
}
|
|
|
|
return(pvReturn);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* DdHmgAlloc
|
|
*
|
|
* Allocate an object from Handle Manager.
|
|
*
|
|
* WARNING:
|
|
* --------
|
|
*
|
|
* If the object is share-lockable via an API, you MUST use DdHmgInsertObject
|
|
* instead. If the object is only exclusive-lockable via an API, you MUST
|
|
* either use DdHmgInsertObject or specify HMGR_ALLOC_LOCK.
|
|
*
|
|
* (This is because if you use DdHmgAlloc, a malicious multi-threaded
|
|
* application could guess the handle and cause it to be dereferenced
|
|
* before you've finished initializing it, possibly causing an access
|
|
* violation.)
|
|
*
|
|
* History:
|
|
*
|
|
* 30-Apr-1999 -by- Lindsay Steventon [linstev]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
HDD_OBJ
|
|
DdHmgAlloc(
|
|
ULONGSIZE_T cb,
|
|
DD_OBJTYPE objt,
|
|
FSHORT fs) // fs can be a combination of the following:
|
|
// HMGR_NO_ZERO_INIT - Don't zero initialize
|
|
// HMGR_MAKE_PUBLIC - Allow object to be lockable by
|
|
// any process
|
|
// HMGR_ALLOC_LOCK - Do an DdHmgLock on the object and
|
|
// return a pointer instead of handle
|
|
{
|
|
HDD_OBJ Handle;
|
|
PVOID pv;
|
|
|
|
ASSERTGDI(objt != (DD_OBJTYPE) DD_DEF_TYPE, "DdHmgAlloc objt is bad");
|
|
ASSERTGDI(cb >= 8, "ERROR DdHmgr writes in first 8 bytes");
|
|
|
|
//
|
|
// Allocate a pointer.
|
|
//
|
|
|
|
pv = DdAllocateObject(cb, (ULONG) objt, ((fs & HMGR_NO_ZERO_INIT) == 0));
|
|
|
|
if (pv != (PVOID) NULL)
|
|
{
|
|
//
|
|
// We need the semaphore to access the free list
|
|
//
|
|
|
|
DdHmgAcquireHmgrSemaphore();
|
|
|
|
//
|
|
// Allocate a handle: can only fail if we run out of memory or bits to
|
|
// store the handle index.
|
|
//
|
|
|
|
Handle = hDdGetFreeHandle(objt);
|
|
|
|
if (Handle != (HDD_OBJ) 0)
|
|
{
|
|
//
|
|
// Store a pointer to the object in the entry corresponding to the
|
|
// allocated handle and initialize the handle data.
|
|
//
|
|
|
|
((DD_ENTRYOBJ *) &(gpentDdHmgr[DdHmgIfromH(Handle)]))->vSetup((PDD_OBJ) pv, objt, fs);
|
|
|
|
//
|
|
// Store the object handle at the beginning of the object memory.
|
|
//
|
|
|
|
((DD_OBJECT *)pv)->hHmgr = (HANDLE)Handle;
|
|
|
|
DdHmgReleaseHmgrSemaphore();
|
|
|
|
return ((fs & HMGR_ALLOC_LOCK) ? (HDD_OBJ)pv : Handle);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We just failed a handle allocation. Release the memory.
|
|
//
|
|
|
|
WARNING("Failed DdHmgAlloc to allocate a handle\n");
|
|
|
|
DdHmgReleaseHmgrSemaphore();
|
|
DdFreeObject(pv,(ULONG) objt);
|
|
}
|
|
}
|
|
|
|
return((HDD_OBJ) 0);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* DdFreeObject
|
|
*
|
|
* Frees the object from where it was allocated. We have this as a separate
|
|
* function in case we implement lookaside lists (as in GDI) later.
|
|
*
|
|
* History:
|
|
*
|
|
* 30-Apr-1999 -by- Lindsay Steventon [linstev]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
DdFreeObject(PVOID pvFree, ULONG ulType)
|
|
{
|
|
VFREEMEM(pvFree);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* DdHmgFree
|
|
*
|
|
* Free an object from the handle manager.
|
|
*
|
|
* History:
|
|
*
|
|
* 30-Apr-1999 -by- Lindsay Steventon [linstev]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
DdHmgFree(HDD_OBJ hobj)
|
|
{
|
|
UINT uiIndex = (UINT) DdHmgIfromH(hobj);
|
|
PDD_OBJ pobjTmp;
|
|
DD_OBJTYPE objtTmp;
|
|
|
|
ASSERTGDI(uiIndex != 0, "ERROR DdHmgFree invalid 0 handle");
|
|
|
|
if (uiIndex < gcMaxDdHmgr)
|
|
{
|
|
//
|
|
// Acquire the handle manager lock before touching gpentDdHmgr
|
|
//
|
|
|
|
DdHmgAcquireHmgrSemaphore();
|
|
|
|
|
|
PDD_ENTRY pentTmp = &gpentDdHmgr[uiIndex];
|
|
|
|
pobjTmp = pentTmp->einfo.pobj;
|
|
objtTmp = pentTmp->Objt;
|
|
|
|
//
|
|
// Free the object handle
|
|
//
|
|
|
|
((DD_ENTRYOBJ *) pentTmp)->vFree(uiIndex);
|
|
|
|
|
|
DdHmgReleaseHmgrSemaphore();
|
|
|
|
if (pobjTmp)
|
|
{
|
|
DdFreeObject((PVOID)pobjTmp, (ULONG) objtTmp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING1("DdHmgFree: bad handle index");
|
|
}
|
|
}
|
|
|
|
/*****************************Exported*Routine*****************************\
|
|
* HDD_OBJ DdHmgNextOwned(hobj, pid)
|
|
*
|
|
* Report the next object owned by specified process
|
|
*
|
|
* Must be called with the Hmgr semaphore acquired.
|
|
*
|
|
* History:
|
|
*
|
|
* 30-Apr-1999 -by- Lindsay Steventon [linstev]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
HDD_OBJ
|
|
FASTCALL
|
|
DdHmgNextOwned(
|
|
HDD_OBJ hobj,
|
|
W32PID pid)
|
|
{
|
|
PDD_ENTRYOBJ pentTmp;
|
|
UINT uiIndex = (UINT) DdHmgIfromH(hobj);
|
|
|
|
//
|
|
// If we are passed 0 we inc to 1 because 0 can never be valid.
|
|
// If we are passed != 0 we inc 1 to find the next one valid.
|
|
//
|
|
|
|
uiIndex++;
|
|
|
|
while (uiIndex < gcMaxDdHmgr)
|
|
{
|
|
pentTmp = (PDD_ENTRYOBJ) &gpentDdHmgr[uiIndex];
|
|
|
|
if (pentTmp->bOwnedBy(pid))
|
|
{
|
|
LONG_PTR uiIndex1 = (LONG_PTR)DD_MAKE_HMGR_HANDLE(uiIndex,pentTmp->FullUnique);
|
|
|
|
return((HDD_OBJ)(uiIndex1 & 0xFFFFFFFF));
|
|
}
|
|
|
|
// Advance to next object
|
|
uiIndex++;
|
|
}
|
|
|
|
// No objects found
|
|
|
|
return((HDD_OBJ) 0);
|
|
}
|
|
|
|
/*****************************Exported*Routine*****************************\
|
|
* HDD_OBJ DdHmgNextObjt
|
|
*
|
|
* Report the next object of a certain type.
|
|
*
|
|
* Must be called with the Hmgr semaphore acquired.
|
|
*
|
|
* History:
|
|
*
|
|
* 30-Apr-1999 -by- Lindsay Steventon [linstev]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
PDD_OBJ
|
|
FASTCALL
|
|
DdHmgNextObjt(
|
|
HDD_OBJ hobj,
|
|
DD_OBJTYPE objt)
|
|
{
|
|
PDD_ENTRYOBJ pentTmp;
|
|
UINT uiIndex = (UINT) DdHmgIfromH(hobj);
|
|
|
|
//
|
|
// If we are passed 0 we inc to 1 because 0 can never be valid.
|
|
// If we are passed != 0 we inc 1 to find the next one valid.
|
|
//
|
|
|
|
uiIndex++;
|
|
|
|
while (uiIndex < gcMaxDdHmgr)
|
|
{
|
|
pentTmp = (PDD_ENTRYOBJ) &gpentDdHmgr[uiIndex];
|
|
|
|
if (pentTmp->Objt == objt)
|
|
{
|
|
return(pentTmp->einfo.pobj);
|
|
}
|
|
|
|
//
|
|
// Advance to next object
|
|
//
|
|
|
|
uiIndex++;
|
|
}
|
|
|
|
//
|
|
// no objects found
|
|
//
|
|
|
|
return((PDD_OBJ) 0);
|
|
}
|
|
|
|
/*******************************Routine************************************\
|
|
* DdHmgLock
|
|
*
|
|
* Description:
|
|
*
|
|
* Acquire an exclusive lock on an object, PID owner must match current PID
|
|
* or be a public.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* hobj - Handle to lock
|
|
* objt - Check to make sure handle is of expected type
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Pointer to object or NULL
|
|
*
|
|
* History:
|
|
*
|
|
* 30-Apr-1999 -by- Lindsay Steventon [linstev]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
PDD_OBJ
|
|
FASTCALL
|
|
DdHmgLock(
|
|
HDD_OBJ hobj,
|
|
DD_OBJTYPE objt,
|
|
BOOL underSemaphore
|
|
)
|
|
{
|
|
PDD_OBJ pobj = (PDD_OBJ)NULL;
|
|
UINT uiIndex = (UINT)DdHmgIfromH(hobj);
|
|
|
|
//
|
|
// Acquire the handle manager lock before touching gpentDdHmgr
|
|
// Only do this if we are not already under the semaphore
|
|
//
|
|
|
|
if (!underSemaphore) {
|
|
DdHmgAcquireHmgrSemaphore();
|
|
}
|
|
|
|
if (uiIndex < gcMaxDdHmgr)
|
|
{
|
|
PDD_ENTRY pentry = &gpentDdHmgr[uiIndex];
|
|
|
|
if (VerifyObjectOwner(pentry))
|
|
{
|
|
if ((pentry->Objt == objt) &&
|
|
(pentry->FullUnique == DdHmgUfromH(hobj)))
|
|
{
|
|
ULONG_PTR thread = (ULONG_PTR)PsGetCurrentThread();
|
|
|
|
pobj = pentry->einfo.pobj;
|
|
|
|
if ((pobj->cExclusiveLock == 0) ||
|
|
(pobj->Tid == thread))
|
|
{
|
|
INC_EXCLUSIVE_REF_CNT(pobj);
|
|
pobj->Tid = thread;
|
|
}
|
|
else
|
|
{
|
|
WARNING1("DdHmgLock: object already locked by another thread");
|
|
pobj = (PDD_OBJ)NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DdHmgPrintBadHandle(hobj, objt);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DdHmgPrintBadHandle(hobj, objt);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DdHmgPrintBadHandle(hobj, objt);
|
|
}
|
|
|
|
if (!underSemaphore) {
|
|
DdHmgReleaseHmgrSemaphore();
|
|
}
|
|
|
|
return(pobj);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* DdHmgQueryLock
|
|
*
|
|
* This returns the number of times an object has been Locked.
|
|
*
|
|
* Expects: A valid handle. The handle should be validated and locked
|
|
* before calling this. Note we don't need to grab the semaphore
|
|
* because this call assumes the handle has already been locked
|
|
* down and we are just reading memory.
|
|
*
|
|
* Returns: The number of times the object has been locked.
|
|
*
|
|
* History:
|
|
*
|
|
* 30-Apr-1999 -by- Lindsay Steventon [linstev]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
ULONG
|
|
FASTCALL
|
|
DdHmgQueryLock(HDD_OBJ hobj)
|
|
{
|
|
//
|
|
// Acquire the handle manager lock before touching gpentDdHmgr
|
|
//
|
|
|
|
DdHmgAcquireHmgrSemaphore();
|
|
|
|
UINT uiIndex = (UINT)DdHmgIfromH(hobj);
|
|
ASSERTGDI(uiIndex < gcMaxDdHmgr, "DdHmgQueryLock invalid handle");
|
|
|
|
ULONG ulRes = gpentDdHmgr[uiIndex].einfo.pobj->cExclusiveLock;
|
|
|
|
DdHmgReleaseHmgrSemaphore();
|
|
|
|
return ulRes;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* HDD_OBJ hDdGetFreeHandle()
|
|
*
|
|
* Get the next available handle. If the handle table is full, we grow it.
|
|
* This function can fail under any of these circumstances:
|
|
* 1. Handle manager didn't initialize
|
|
* 2. Insufficient memory to grow the handle table
|
|
* 3. Insufficient bits to store the handle index
|
|
*
|
|
* Note:
|
|
* We must already have the HmgrSemaphore
|
|
*
|
|
* History:
|
|
*
|
|
* 30-Apr-1999 -by- Lindsay Steventon [linstev]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
HDD_OBJ
|
|
hDdGetFreeHandle(
|
|
DD_OBJTYPE objt
|
|
)
|
|
{
|
|
LONG_PTR uiIndex;
|
|
|
|
//
|
|
// Handle manager initialized and bounds check
|
|
//
|
|
|
|
if ((gpentDdHmgr == NULL) || (gcMaxDdHmgr == DD_MAX_HANDLE_COUNT))
|
|
{
|
|
return ((HDD_OBJ)0);
|
|
}
|
|
|
|
//
|
|
// Check if there is a free handle we can use
|
|
//
|
|
|
|
if (ghFreeDdHmgr != (HDD_OBJ) 0)
|
|
{
|
|
PDD_ENTRYOBJ pentTmp;
|
|
|
|
uiIndex = (LONG_PTR)ghFreeDdHmgr;
|
|
pentTmp = (PDD_ENTRYOBJ) &gpentDdHmgr[uiIndex];
|
|
ghFreeDdHmgr = pentTmp->einfo.hFree;
|
|
|
|
pentTmp->FullUnique = DD_USUNIQUE(pentTmp->FullUnique,objt);
|
|
|
|
uiIndex = (LONG_PTR)DD_MAKE_HMGR_HANDLE(uiIndex,pentTmp->FullUnique);
|
|
|
|
return((HDD_OBJ)(uiIndex & 0xFFFFFFFF));
|
|
}
|
|
|
|
//
|
|
// Check if we've run out of handles
|
|
//
|
|
|
|
if (gcMaxDdHmgr == gcSizeDdHmgr)
|
|
{
|
|
// Increase the table size
|
|
|
|
ULONG dwNewSize = gcSizeDdHmgr + DD_TABLESIZE_DELTA;
|
|
|
|
// Allocate a new block
|
|
DD_ENTRY *ptHmgr = (DD_ENTRY *)PALLOCMEM(sizeof(DD_ENTRY) * dwNewSize, 'ddht');
|
|
|
|
if (ptHmgr == NULL)
|
|
{
|
|
WARNING("DdHmgr failed to grow handle table\n");
|
|
return ((HDD_OBJ) 0);
|
|
}
|
|
|
|
//
|
|
// Copy the old handles into the new table
|
|
//
|
|
|
|
RtlMoveMemory(ptHmgr, gpentDdHmgr, sizeof(DD_ENTRY) * gcSizeDdHmgr);
|
|
|
|
gcSizeDdHmgr = dwNewSize;
|
|
gpentDdHmgrLast = gpentDdHmgr;
|
|
VFREEMEM(gpentDdHmgr);
|
|
gpentDdHmgr = ptHmgr;
|
|
}
|
|
|
|
//
|
|
// Allocate a new handle table entry and set the uniqueness value.
|
|
//
|
|
|
|
uiIndex = DD_USUNIQUE(DD_UNIQUE_INCREMENT,objt);
|
|
gpentDdHmgr[gcMaxDdHmgr].FullUnique = (USHORT) uiIndex;
|
|
uiIndex = (LONG_PTR)DD_MAKE_HMGR_HANDLE(gcMaxDdHmgr,uiIndex);
|
|
gcMaxDdHmgr++;
|
|
|
|
return((HDD_OBJ)(uiIndex & 0xFFFFFFFF));
|
|
}
|
|
|
|
/******************************Public*Routines*****************************\
|
|
* DdHmgAcquireHmgrSemaphore *
|
|
* DdHmgReleaseHmgrSemaphore *
|
|
* *
|
|
* Convenience functions for the handle manager semaphore. *
|
|
* *
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
DdHmgAcquireHmgrSemaphore()
|
|
{
|
|
EngAcquireSemaphore(ghsemHmgr);
|
|
}
|
|
|
|
VOID
|
|
DdHmgReleaseHmgrSemaphore()
|
|
{
|
|
EngReleaseSemaphore(ghsemHmgr);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* DdHmgPrintBadHandle
|
|
*
|
|
* Simple routine that prints out a warning when a handle manager
|
|
* lock fails due to a bad handle.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
#if DBG
|
|
|
|
CONST CHAR* aszDdType[] = {
|
|
"hdef", // DD_DEF_TYPE
|
|
"hddraw", // DD_DIRECTDRAW_TYPE
|
|
"hddrawsurf", // DD_SURFACE_TYPE
|
|
"hd3d", // D3D_HANDLE_TYPE
|
|
"hddrawvport", // DD_VIDEOPORT_TYPE
|
|
"hmotioncomp", // DD_MOTIONCOMP_TYPE
|
|
"hunused", //
|
|
};
|
|
|
|
VOID
|
|
DdHmgPrintBadHandle(
|
|
HDD_OBJ hobj,
|
|
DD_OBJTYPE objt
|
|
)
|
|
{
|
|
static CHAR *szSystem = "System";
|
|
static CHAR *szUnknown = "???";
|
|
CHAR *pszImage;
|
|
|
|
{
|
|
PETHREAD pet;
|
|
PEPROCESS pep;
|
|
|
|
if (pep = PsGetCurrentProcess())
|
|
{
|
|
pszImage = (CHAR *)PsGetProcessImageFileName(pep);
|
|
if (*pszImage == '\0')
|
|
{
|
|
pszImage = szSystem;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pszImage = szUnknown;
|
|
}
|
|
}
|
|
|
|
KdPrint(("DXG: %s or DLL gave bad handle 0x%p as an %s.\n",
|
|
pszImage, hobj, aszDdType[objt]));
|
|
}
|
|
|
|
#endif
|
|
|
|
|