reactos/win32ss/gdi/eng/driverobj.c

161 lines
3.2 KiB
C
Raw Normal View History

/*
* COPYRIGHT: GPL, see COPYING in the top level directory
* PROJECT: ReactOS win32 kernel mode sunsystem
* PURPOSE: GDI DRIVEROBJ Functions
* FILE: win32ss/gdi/eng/driverobj.c
* PROGRAMER: Timo Kreuzer
*/
/** Includes ******************************************************************/
#include <win32k.h>
#define NDEBUG
#include <debug.h>
/** Internal interface ********************************************************/
/*!
* \brief DRIVEROBJ cleanup function
*/
VOID
NTAPI
DRIVEROBJ_vCleanup(PVOID pObject)
{
PEDRIVEROBJ pedo = pObject;
FREEOBJPROC pFreeProc;
pFreeProc = pedo->drvobj.pFreeProc;
if (pFreeProc)
{
NT_VERIFY(pFreeProc(&pedo->drvobj));
}
}
/** Public interface **********************************************************/
_Must_inspect_result_
HDRVOBJ
APIENTRY
EngCreateDriverObj(
_In_ PVOID pvObj,
_In_opt_ FREEOBJPROC pFreeObjProc,
_In_ HDEV hdev)
{
PEDRIVEROBJ pedo;
HDRVOBJ hdo;
PDEVOBJ *ppdev = (PDEVOBJ*)hdev;
/* Allocate a new DRIVEROBJ */
pedo = DRIVEROBJ_AllocObjectWithHandle();
if (!pedo)
{
return NULL;
}
hdo = pedo->baseobj.hHmgr;
/* Fill in fields */
pedo->drvobj.pvObj = pvObj;
pedo->drvobj.pFreeProc = pFreeObjProc;
pedo->drvobj.hdev = hdev;
pedo->drvobj.dhpdev = ppdev->dhpdev;
/* Unlock the object */
DRIVEROBJ_UnlockObject(pedo);
/* Return the handle */
return hdo;
}
BOOL
APIENTRY
EngDeleteDriverObj(
_In_ _Post_ptr_invalid_ HDRVOBJ hdo,
_In_ BOOL bCallBack,
_In_ BOOL bLocked)
{
PEDRIVEROBJ pedo;
/* Lock the object */
pedo = DRIVEROBJ_TryLockObject(hdo);
if (!pedo)
{
return FALSE;
}
/* Manually call cleanup callback */
if (bCallBack)
{
if (!pedo->drvobj.pFreeProc(&pedo->drvobj))
{
/* Callback failed */
DRIVEROBJ_UnlockObject(pedo);
return FALSE;
}
}
/* Prevent cleanup callback from being called again */
pedo->drvobj.pFreeProc = NULL;
/* Unlock if the caller indicates it is locked */
if (bLocked)
DRIVEROBJ_UnlockObject(pedo);
/* Now delete the object */
[WIN32K] Rewrite of the GDI handle manager - The old handle manager used a completely retarded spinlock in combination with KeDelayExecutionThread() for both exclusive and shared locks. This is probably the most uneffective algorithm possible. It was also duplicating code everywhere and it was a overall mess It is now replaced with a lock-free reference counter for shared locks and a pushlock for exclusive locks. -> Better performance and scalability. - Allocate user mode object attributes from the new gdi pool. This way, we don't need any caching, since the pool serves as a cache. Its also much faster and uses much less memory. - Allow object allocations of different size, instead of fixed size from a table. This way a single allocation can take care of actual needs. - Allow allcoating objects without a handle and insert them into the handle table later - Properly synchronize the process GDIHandleCount. Now gdiview and taskmanager show the correct number of gdi handles. - Implement a new event tracking system, that is capable of tracking all reverences and locks of objects and pool allocations to help track possible leaks - Make sure that all objects of a process are deleted in cleanup - Make sure all usermode memory allocations are freed, when cleaning up the process pool. - Make sure that each object type is using the correct type of lock (either shared or exclusive, not a mixture) - Fix some object / reference leaks - Lots of inferface improvements - Use global variables for certain things instead of members in the mapped gdi handle table - Make IntSysCreateRectpRgn create a region without a handle - Fix detection od source and mask use in GreStretchBltMask - Use GDIOBJ_bLockMultipleObjects in NtGdiCombineRegion to avoid possible deadlocks - Fix NtGdiAbortPath to reset DCPATH_ACTIVE flag in the dc and only bail out on error, instead of always - Replace DC_AllocateDcAttr and DC_AllocDcAttr with DC_bAllocDcAttr using the new user mode pool - Remove DCU_SyncDcAttrtoUser and DCU_SynchDcAttrtoUser. Those functions were unused and didn't do anything useful anyway, - Replace IntGdiSetDCOwnerEx and DC_SetOwnership with GreSetDCOwner, remove unused NoSetBrush parameter - Replace GDIOBJ_bValidateHandle and IsObjectDead with GreIsHandleValid - Chage GDIOBJ_bLockMultipleObjects: pass object type, return a BOOL, whether all objects could be locked, cleanup on failure svn path=/trunk/; revision=51470
2011-04-28 08:26:46 +00:00
GDIOBJ_vDeleteObject(&pedo->baseobj);
return TRUE;
}
PDRIVEROBJ
APIENTRY
EngLockDriverObj(
_In_ HDRVOBJ hdo)
{
PEDRIVEROBJ pedo;
/* Lock the object */
pedo = DRIVEROBJ_TryLockObject(hdo);
/* Return pointer to the DRIVEROBJ structure */
return pedo ? &pedo->drvobj : NULL;
}
BOOL
APIENTRY
EngUnlockDriverObj(
_In_ _Post_ptr_invalid_ HDRVOBJ hdo)
{
PEDRIVEROBJ pedo;
ULONG cLocks;
/* First lock to get a pointer to the object */
pedo = DRIVEROBJ_TryLockObject(hdo);
if(!pedo)
{
/* Object could not be locked, fail. */
return FALSE;
}
/* Unlock object */
[WIN32K] Rewrite of the GDI handle manager - The old handle manager used a completely retarded spinlock in combination with KeDelayExecutionThread() for both exclusive and shared locks. This is probably the most uneffective algorithm possible. It was also duplicating code everywhere and it was a overall mess It is now replaced with a lock-free reference counter for shared locks and a pushlock for exclusive locks. -> Better performance and scalability. - Allocate user mode object attributes from the new gdi pool. This way, we don't need any caching, since the pool serves as a cache. Its also much faster and uses much less memory. - Allow object allocations of different size, instead of fixed size from a table. This way a single allocation can take care of actual needs. - Allow allcoating objects without a handle and insert them into the handle table later - Properly synchronize the process GDIHandleCount. Now gdiview and taskmanager show the correct number of gdi handles. - Implement a new event tracking system, that is capable of tracking all reverences and locks of objects and pool allocations to help track possible leaks - Make sure that all objects of a process are deleted in cleanup - Make sure all usermode memory allocations are freed, when cleaning up the process pool. - Make sure that each object type is using the correct type of lock (either shared or exclusive, not a mixture) - Fix some object / reference leaks - Lots of inferface improvements - Use global variables for certain things instead of members in the mapped gdi handle table - Make IntSysCreateRectpRgn create a region without a handle - Fix detection od source and mask use in GreStretchBltMask - Use GDIOBJ_bLockMultipleObjects in NtGdiCombineRegion to avoid possible deadlocks - Fix NtGdiAbortPath to reset DCPATH_ACTIVE flag in the dc and only bail out on error, instead of always - Replace DC_AllocateDcAttr and DC_AllocDcAttr with DC_bAllocDcAttr using the new user mode pool - Remove DCU_SyncDcAttrtoUser and DCU_SynchDcAttrtoUser. Those functions were unused and didn't do anything useful anyway, - Replace IntGdiSetDCOwnerEx and DC_SetOwnership with GreSetDCOwner, remove unused NoSetBrush parameter - Replace GDIOBJ_bValidateHandle and IsObjectDead with GreIsHandleValid - Chage GDIOBJ_bLockMultipleObjects: pass object type, return a BOOL, whether all objects could be locked, cleanup on failure svn path=/trunk/; revision=51470
2011-04-28 08:26:46 +00:00
cLocks = pedo->baseobj.cExclusiveLock;
DRIVEROBJ_UnlockObject(pedo);
/* Check if we still hold a lock */
[WIN32K] Rewrite of the GDI handle manager - The old handle manager used a completely retarded spinlock in combination with KeDelayExecutionThread() for both exclusive and shared locks. This is probably the most uneffective algorithm possible. It was also duplicating code everywhere and it was a overall mess It is now replaced with a lock-free reference counter for shared locks and a pushlock for exclusive locks. -> Better performance and scalability. - Allocate user mode object attributes from the new gdi pool. This way, we don't need any caching, since the pool serves as a cache. Its also much faster and uses much less memory. - Allow object allocations of different size, instead of fixed size from a table. This way a single allocation can take care of actual needs. - Allow allcoating objects without a handle and insert them into the handle table later - Properly synchronize the process GDIHandleCount. Now gdiview and taskmanager show the correct number of gdi handles. - Implement a new event tracking system, that is capable of tracking all reverences and locks of objects and pool allocations to help track possible leaks - Make sure that all objects of a process are deleted in cleanup - Make sure all usermode memory allocations are freed, when cleaning up the process pool. - Make sure that each object type is using the correct type of lock (either shared or exclusive, not a mixture) - Fix some object / reference leaks - Lots of inferface improvements - Use global variables for certain things instead of members in the mapped gdi handle table - Make IntSysCreateRectpRgn create a region without a handle - Fix detection od source and mask use in GreStretchBltMask - Use GDIOBJ_bLockMultipleObjects in NtGdiCombineRegion to avoid possible deadlocks - Fix NtGdiAbortPath to reset DCPATH_ACTIVE flag in the dc and only bail out on error, instead of always - Replace DC_AllocateDcAttr and DC_AllocDcAttr with DC_bAllocDcAttr using the new user mode pool - Remove DCU_SyncDcAttrtoUser and DCU_SynchDcAttrtoUser. Those functions were unused and didn't do anything useful anyway, - Replace IntGdiSetDCOwnerEx and DC_SetOwnership with GreSetDCOwner, remove unused NoSetBrush parameter - Replace GDIOBJ_bValidateHandle and IsObjectDead with GreIsHandleValid - Chage GDIOBJ_bLockMultipleObjects: pass object type, return a BOOL, whether all objects could be locked, cleanup on failure svn path=/trunk/; revision=51470
2011-04-28 08:26:46 +00:00
if (cLocks < 2)
{
/* Object wasn't locked before, fail. */
return FALSE;
}
/* Unlock again */
DRIVEROBJ_UnlockObject(pedo);
/* Success */
return TRUE;
}