/******************************Module*Header*******************************\ * Module Name: drvobj.cxx * * DRVOBJ object code. The DRVOBJ is an engine object which tracks * driver managed pre-process resource that need to be freed upon * client-side process termination. * * Created: 18-Jan-1994 19:27:17 * Author: Gilman Wong [gilmanw] * * Copyright (c) 1994-1999 Microsoft Corporation * \**************************************************************************/ #include "precomp.hxx" /******************************Public*Routine******************************\ * EngCreateDriverObj * * Allocate an object that will be own by the process and cleaned up at * process termination if it's still left around. * * History: * 18-Jan-1994 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/ HDRVOBJ APIENTRY EngCreateDriverObj(PVOID pvObj, FREEOBJPROC pFreeObjProc, HDEV hdev) { HDRVOBJ hdoRet = (HDRVOBJ) 0; PDRVOBJ pdo = (PDRVOBJ) ALLOCOBJ(sizeof(DRVOBJ), DRVOBJ_TYPE, FALSE); if (pdo != (PDRVOBJ) NULL) { PDEVOBJ po(hdev); pdo->pvObj = pvObj; pdo->pFreeProc = pFreeObjProc; pdo->hdev = hdev; pdo->dhpdev = po.dhpdev(); pdo->Process = PsGetCurrentProcess(); hdoRet = (HDRVOBJ) HmgInsertObject((HOBJ) pdo, 0, DRVOBJ_TYPE); if (hdoRet != (HDRVOBJ) 0) { // Don't free the PDEV until the DRIVEROBJ is destroyed. po.vReferencePdev(); } else { WARNING("EngCreateDriverObj(): HmgInsertObject failed\n"); FREEOBJ(pdo, DRVOBJ_TYPE); } } else { WARNING("EngCreateDriverObj(): ALLOCOBJ failed\n"); } return(hdoRet); } /******************************Public*Routine******************************\ * EngLockDriverObj * * This grabs an exclusive lock on this object for the calling thread. * This will fail if the handle is invalid, the object is already locked * by another thread, or the caller isn't the correct PID (the PID that * created the object). * * History: * 31-May-1994 -by- Patrick Haluptzok patrickh * Wrote it. \**************************************************************************/ DRIVEROBJ * APIENTRY EngLockDriverObj(HDRVOBJ hdo) { DRIVEROBJ *pDriverObj = NULL; DRVOBJ *pdo = (DRVOBJ *) HmgLock((HOBJ) hdo, DRVOBJ_TYPE); if (pdo) { PDEVOBJ po(pdo->hdev); ASSERTGDI(po.bValid(), "Expected a valid hdev"); // // Since a DRVOBJ is derived from a DRIVEROBJ, this automatically // points to the DRIVEROBJ part of the object: // pDriverObj = pdo; } return(pDriverObj); } /******************************Public*Routine******************************\ * EngUnlockDriverObj * * Unlocks the handle. Note this call assumes the handle passed in is * valid, if it isn't we are in big trouble, the handle table will be * corrupted, a particular object will have its lock count messed up * making it undeletable. * * History: * 31-May-1994 -by- Patrick Haluptzok patrickh * Wrote it. \**************************************************************************/ BOOL APIENTRY EngUnlockDriverObj(HDRVOBJ hdo) { // // Note to be paranoid we could lock it again and if that succeeds // unlock it twice to make the engine immune to hosed up drivers. // PBYTE pjTemp = (PBYTE) HmgLock((HOBJ) hdo, DRVOBJ_TYPE); ASSERTGDI(pjTemp != NULL, "ERROR EngUnlockDriverObj failed - bad handle, driver error"); if (pjTemp) { DEC_EXCLUSIVE_REF_CNT(pjTemp); DEC_EXCLUSIVE_REF_CNT(pjTemp); return(TRUE); } return(FALSE); } /******************************Public*Routine******************************\ * EngDeleteDriverObj * * This is called by the driver to delete the handle it created for the * object it created. * * Deletes the DRVOBJ. The FreeObjProc in the DRVOBJ is optionally called * before the DRVOBJ is freed. * * Returns: * TRUE if sucessful, FALSE otherwise. * * History: * 18-Jan-1994 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/ BOOL APIENTRY EngDeleteDriverObj(HDRVOBJ hdo, BOOL bCallFreeProc, BOOL bLocked) { GDIFunctionID(EngDeleteDriverObj); PDRVOBJ pdo; DRIVEROBJ *pDriverObj; if (pdo = (PDRVOBJ) HmgLock((HOBJ) hdo, DRVOBJ_TYPE)) { PDEVOBJ po(pdo->hdev); BOOL bDeleteOK = TRUE; ASSERTGDI(po.bValid(), "Expected valid hdev"); pDriverObj = pdo; if (bCallFreeProc) { ASSERTGDI(PsGetCurrentProcess() == pdo->Process, "Unexpected process context for clean-up"); GreAcquireSemaphoreEx(po.hsemDevLock(), SEMORDER_DEVLOCK, NULL); bDeleteOK = (*pdo->pFreeProc)(pDriverObj); GreReleaseSemaphoreEx(po.hsemDevLock()); } if(bDeleteOK) { PDRVOBJ pdoTemp; if ((pdoTemp = (PDRVOBJ) HmgRemoveObject((HOBJ) hdo, bLocked ? 2 : 1, 0, TRUE, DRVOBJ_TYPE)) != NULL) { po.vUnreferencePdev(); FREEOBJ(pdoTemp, DRVOBJ_TYPE); return(TRUE); } else { WARNING("HmgRemoveObject failed\n"); } } else { WARNING("Driver failed to delete the object\n"); } DEC_EXCLUSIVE_REF_CNT(pdo); } else { WARNING("Failed to lock hdo\n"); } return(FALSE); }