Author: tkreuzer Date: Tue Mar 17 03:30:15 2009 New Revision: 40068
URL: http://svn.reactos.org/svn/reactos?rev=40068&view=rev Log: Rewrite DRIVEROBJ api, giving the object a handle, belonging to the current process. Let the gdi obj cleanup take care for calling the callback function. Allow deleting of objects that are exclusively locked by the current thread.
Added: trunk/reactos/subsystems/win32/win32k/include/driverobj.h (with props) Modified: trunk/reactos/include/reactos/win32k/ntgdihdl.h trunk/reactos/subsystems/win32/win32k/eng/driverobj.c trunk/reactos/subsystems/win32/win32k/eng/objects.h trunk/reactos/subsystems/win32/win32k/include/inteng.h trunk/reactos/subsystems/win32/win32k/include/win32k.h trunk/reactos/subsystems/win32/win32k/main/dllmain.c trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c
Modified: trunk/reactos/include/reactos/win32k/ntgdihdl.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/win32k/ntgd... ============================================================================== --- trunk/reactos/include/reactos/win32k/ntgdihdl.h [iso-8859-1] (original) +++ trunk/reactos/include/reactos/win32k/ntgdihdl.h [iso-8859-1] Tue Mar 17 03:30:15 2009 @@ -66,6 +66,7 @@ #define GDI_OBJECT_TYPE_DD_VIDEOPORT 0x00120000 /* Should be moved away from gdi objects */ #define GDI_OBJECT_TYPE_DD_MOTIONCOMP 0x00140000 /* Should be moved away from gdi objects */ #define GDI_OBJECT_TYPE_ENUMFONT 0x00160000 +#define GDI_OBJECT_TYPE_DRIVEROBJ 0x001C0000
/* Confrim on XP value is taken from NtGdiCreateDirectDrawObject */ #define GDI_OBJECT_TYPE_DIRECTDRAW 0x00200000
Modified: trunk/reactos/subsystems/win32/win32k/eng/driverobj.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/eng... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/eng/driverobj.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/eng/driverobj.c [iso-8859-1] Tue Mar 17 03:30:15 2009 @@ -1,180 +1,156 @@ /* - * ReactOS W32 Subsystem - * Copyright (C) 2005 ReactOS Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * COPYRIGHT: GPL, see COPYING in the top level directory + * PROJECT: ReactOS win32 kernel mode sunsystem + * PURPOSE: GDI DRIVEROBJ Functions + * FILE: subsystems/win32k/eng/driverobj.c + * PROGRAMER: Timo Kreuzer */ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * PURPOSE: GDI DRIVEROBJ Functions - * FILE: subsys/win32k/eng/driverobj.c - * PROGRAMER: Gregor Anich - * REVISION HISTORY: - * 04/01/2005: Created - */ + +/** Includes ******************************************************************/
#include <w32k.h>
#define NDEBUG #include <debug.h>
-/*!\brief Called when the process is terminated. - * - * Calls the free-proc for each existing DRIVEROBJ. - * - * \param Process Pointer to the EPROCESS struct for the process beeing terminated. - * \param Win32Process Pointer to the W32PROCESS + +/** Internal interface ********************************************************/ + +/*! + * \brief DRIVEROBJ cleanup function */ -VOID FASTCALL -IntEngCleanupDriverObjs(struct _EPROCESS *Process, - PW32PROCESS Win32Process) +BOOL INTERNAL_CALL +DRIVEROBJ_Cleanup(PVOID pObject) { - PDRIVERGDI DrvObjInt; - PW32PROCESS CurrentWin32Process; + PEDRIVEROBJ pedo = pObject; + FREEOBJPROC pFreeProc;
- CurrentWin32Process = PsGetCurrentProcessWin32Process(); - IntEngLockProcessDriverObjs(CurrentWin32Process); - while (!IsListEmpty(&Win32Process->DriverObjListHead)) + pFreeProc = pedo->drvobj.pFreeProc; + if (pFreeProc) { - DrvObjInt = CONTAINING_RECORD(Win32Process->DriverObjListHead.Flink, - DRIVERGDI, ListEntry); - IntEngUnLockProcessDriverObjs(CurrentWin32Process); - EngDeleteDriverObj((HDRVOBJ)(&DrvObjInt->DriverObj), TRUE, FALSE); - IntEngLockProcessDriverObjs(CurrentWin32Process); + return pFreeProc(pedo->drvobj.pvObj); } - IntEngUnLockProcessDriverObjs(CurrentWin32Process); + + return TRUE; +} + +/** Public interface **********************************************************/ + +HDRVOBJ +APIENTRY +EngCreateDriverObj( + IN PVOID pvObj, + IN FREEOBJPROC pFreeObjProc, + IN HDEV hdev) +{ + PEDRIVEROBJ pedo; + HDRVOBJ hdo; + GDIDEVICE *ppdev = (GDIDEVICE*)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->hPDev; + + /* Unlock the object */ + DRIVEROBJ_UnlockObject(pedo); + + /* Return the handle */ + return hdo; }
-/* - * @implemented - */ -HDRVOBJ +BOOL APIENTRY -EngCreateDriverObj( - IN PVOID pvObj, - IN FREEOBJPROC pFreeObjProc, - IN HDEV hdev - ) +EngDeleteDriverObj( + IN HDRVOBJ hdo, + IN BOOL bCallBack, + IN BOOL bLocked) { - PDRIVERGDI DrvObjInt; - PDRIVEROBJ DrvObjUser; - PW32PROCESS CurrentWin32Process; + PEDRIVEROBJ pedo;
- /* Create DRIVEROBJ */ - DrvObjInt = EngAllocMem(0, sizeof (DRIVERGDI), TAG_DRIVEROBJ); - if (DrvObjInt == NULL) + /* Lock the object */ + pedo = DRIVEROBJ_LockObject(hdo); + if (!pedo) { - DPRINT1("Failed to allocate memory for a DRIVERGDI structure!\n"); - return NULL; + return FALSE; }
- /* fill user object */ - DrvObjUser = GDIToObj(DrvObjInt, DRIVER); - DrvObjUser->pvObj = pvObj; - DrvObjUser->pFreeProc = pFreeObjProc; - DrvObjUser->hdev = hdev; - DrvObjUser->dhpdev = ((GDIDEVICE*)hdev)->hPDev; + /* Manually call cleanup callback */ + if (bCallBack) + { + if (!pedo->drvobj.pFreeProc(pedo->drvobj.pvObj)) + { + /* Callback failed */ + DRIVEROBJ_UnlockObject(pedo); + return FALSE; + } + }
- /* fill internal object */ - ExInitializeFastMutex(&DrvObjInt->Lock); - CurrentWin32Process = PsGetCurrentProcessWin32Process(); - IntEngLockProcessDriverObjs(CurrentWin32Process); - InsertTailList(&CurrentWin32Process->DriverObjListHead, &DrvObjInt->ListEntry); - IntEngUnLockProcessDriverObjs(CurrentWin32Process); + /* Prevent cleanup callback from being called again */ + pedo->drvobj.pFreeProc = NULL;
- return (HDRVOBJ)DrvObjUser; + /* NOTE: We don't care about the bLocked param, as our handle manager + allows freeing the object, while we hold any number of locks. */ + + /* Free the object */ + return DRIVEROBJ_FreeObjectByHandle(hdo); }
-/* - * @implemented - */ -BOOL +PDRIVEROBJ APIENTRY -EngDeleteDriverObj( - IN HDRVOBJ hdo, - IN BOOL bCallBack, - IN BOOL bLocked - ) +EngLockDriverObj( + IN HDRVOBJ hdo) { - PDRIVEROBJ DrvObjUser = (PDRIVEROBJ)hdo; - PDRIVERGDI DrvObjInt = ObjToGDI(DrvObjUser, DRIVER); - PW32PROCESS CurrentWin32Process; + PEDRIVEROBJ pedo;
- /* Make sure the obj is locked */ - if (!bLocked) - { - if (!ExTryToAcquireFastMutex(&DrvObjInt->Lock)) - { - return FALSE; - } - } + /* Lock the object */ + pedo = DRIVEROBJ_LockObject(hdo);
- /* Call the free-proc */ - if (bCallBack) - { - if (!DrvObjUser->pFreeProc(DrvObjUser)) - { - return FALSE; - } - } - - /* Free the DRIVEROBJ */ - CurrentWin32Process = PsGetCurrentProcessWin32Process(); - IntEngLockProcessDriverObjs(CurrentWin32Process); - RemoveEntryList(&DrvObjInt->ListEntry); - IntEngUnLockProcessDriverObjs(CurrentWin32Process); - EngFreeMem(DrvObjInt); - - return TRUE; + /* Return pointer to the DRIVEROBJ structure */ + return &pedo->drvobj; }
-/* - * @implemented - */ -PDRIVEROBJ +BOOL APIENTRY -EngLockDriverObj( IN HDRVOBJ hdo ) +EngUnlockDriverObj( + IN HDRVOBJ hdo) { - PDRIVEROBJ DrvObjUser = (PDRIVEROBJ)hdo; - PDRIVERGDI DrvObjInt = ObjToGDI(DrvObjUser, DRIVER); + PEDRIVEROBJ pedo;
- if (!ExTryToAcquireFastMutex(&DrvObjInt->Lock)) + /* First lock to get a pointer to the object */ + pedo = DRIVEROBJ_LockObject(hdo); + if(!pedo) { - return NULL; + /* Object could not be locked, fail. */ + return FALSE; }
- return DrvObjUser; + /* Unlock object */ + DRIVEROBJ_UnlockObject(pedo); + + /* Check if we still hold a lock */ + if (pedo->baseobj.cExclusiveLock < 1) + { + /* Object wasn't locked before, fail. */ + return FALSE; + } + + /* Unlock again */ + DRIVEROBJ_UnlockObject(pedo); + + /* Success */ + return TRUE; }
- -/* - * @implemented - */ -BOOL -APIENTRY -EngUnlockDriverObj ( IN HDRVOBJ hdo ) -{ - PDRIVERGDI DrvObjInt = ObjToGDI((PDRIVEROBJ)hdo, DRIVER); - - ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&DrvObjInt->Lock); - return TRUE; -} - -/* EOF */ -
Modified: trunk/reactos/subsystems/win32/win32k/eng/objects.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/eng... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/eng/objects.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/eng/objects.h [iso-8859-1] Tue Mar 17 03:30:15 2009 @@ -50,12 +50,6 @@ ULONG EnumMax; ENUMRECTS EnumRects; } CLIPGDI, *PCLIPGDI; - -typedef struct _DRIVERGDI { - DRIVEROBJ DriverObj; - LIST_ENTRY ListEntry; - FAST_MUTEX Lock; -} DRIVERGDI, *PDRIVERGDI;
/*ei What is this for? */ typedef struct _DRVFUNCTIONSGDI {
Added: trunk/reactos/subsystems/win32/win32k/include/driverobj.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/driverobj.h (added) +++ trunk/reactos/subsystems/win32/win32k/include/driverobj.h [iso-8859-1] Tue Mar 17 03:30:15 2009 @@ -1,0 +1,23 @@ +#ifndef _WIN32K_DRIVEROBJ_H +#define _WIN32K_DRIVEROBJ_H + +#include "gdiobj.h" + +/* Object structure */ +typedef struct _EDRIVEROBJ +{ + BASEOBJECT baseobj; + DRIVEROBJ drvobj; + PVOID reserved; +} EDRIVEROBJ, *PEDRIVEROBJ; + +/* Cleanup function */ +BOOL INTERNAL_CALL DRIVEROBJ_Cleanup(PVOID pObject); + + +#define DRIVEROBJ_AllocObjectWithHandle() ((PEDRIVEROBJ)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_DRIVEROBJ)) +#define DRIVEROBJ_FreeObjectByHandle(hdo) GDIOBJ_FreeObjByHandle((HGDIOBJ)hdo, GDI_OBJECT_TYPE_DRIVEROBJ) +#define DRIVEROBJ_LockObject(hdo) ((PEDRIVEROBJ)GDIOBJ_LockObj((HGDIOBJ)hdo, GDI_OBJECT_TYPE_DRIVEROBJ)) +#define DRIVEROBJ_UnlockObject(pdo) GDIOBJ_UnlockObjByPtr((POBJ)pdo) + +#endif /* !_WIN32K_DRIVEROBJ_H */
Propchange: trunk/reactos/subsystems/win32/win32k/include/driverobj.h ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/subsystems/win32/win32k/include/inteng.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/inteng.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/include/inteng.h [iso-8859-1] Tue Mar 17 03:30:15 2009 @@ -33,16 +33,6 @@ #define ROP3_TO_ROP4(Rop3) ((((Rop3) >> 8) & 0xff00) | (((Rop3) >> 16) & 0x00ff))
/* Definitions of IntEngXxx functions */ - -#define IntEngLockProcessDriverObjs(W32Process) \ - ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&(W32Process)->DriverObjListLock) - -#define IntEngUnLockProcessDriverObjs(W32Process) \ - ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&(W32Process)->DriverObjListLock) - -VOID FASTCALL -IntEngCleanupDriverObjs(struct _EPROCESS *Process, - PW32PROCESS Win32Process);
BOOL APIENTRY IntEngLineTo(SURFOBJ *Surface,
Modified: trunk/reactos/subsystems/win32/win32k/include/win32k.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/win32k.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/include/win32k.h [iso-8859-1] Tue Mar 17 03:30:15 2009 @@ -28,6 +28,7 @@ #include <include/dce.h> #include <include/dib.h> #include <include/driver.h> +#include <include/driverobj.h> #include <include/error.h> #include <include/floatobj.h> #include <include/gdiobj.h>
Modified: trunk/reactos/subsystems/win32/win32k/main/dllmain.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/mai... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/main/dllmain.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/main/dllmain.c [iso-8859-1] Tue Mar 17 03:30:15 2009 @@ -136,7 +136,6 @@ DPRINT("Destroying W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql()); IntCleanupMenus(Process, Win32Process); IntCleanupCurIcons(Process, Win32Process); - IntEngCleanupDriverObjs(Process, Win32Process); CleanupMonitorImpl();
/* no process windows should exist at this point, or the function will assert! */
Modified: trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/obj... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c [iso-8859-1] Tue Mar 17 03:30:15 2009 @@ -70,7 +70,7 @@ {0, 0, TAG_TTFD, NULL}, /* 19 TTFD, unused */ {0, 0, TAG_RC, NULL}, /* 1a RC, unused */ {0, 0, TAG_TEMP, NULL}, /* 1b TEMP, unused */ - {0, 0, TAG_DRVOBJ, NULL}, /* 1c DRVOBJ, unused */ + {0, sizeof(EDRIVEROBJ), TAG_DRVOBJ, DRIVEROBJ_Cleanup},/* 1c DRVOBJ */ {0, 0, TAG_DCIOBJ, NULL}, /* 1d DCIOBJ, unused */ {0, 0, TAG_SPOOL, NULL}, /* 1e SPOOL, unused */ {0, 0, 0, NULL}, /* 1f reserved entry */ @@ -537,7 +537,8 @@
Object = Entry->KernelData;
- if (Object->cExclusiveLock == 0) + if (Object->cExclusiveLock == 0 || + Object->Tid == (PW32THREAD)PsGetCurrentThreadWin32Thread()) { BOOL Ret; PW32PROCESS W32Process = PsGetCurrentProcessWin32Process(); @@ -571,14 +572,16 @@ else { /* - * The object is currently locked, so freeing is forbidden! + * The object is currently locked by another thread, so freeing is forbidden! */ DPRINT1("Object->cExclusiveLock = %d\n", Object->cExclusiveLock); GDIDBG_TRACECALLER(); GDIDBG_TRACELOCKER(GDI_HANDLE_GET_INDEX(hObj)); (void)InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId); /* do not assert here for it will call again from dxg.sys it being call twice */ - //ASSERT(FALSE); + + DelayExecution(); + goto LockHandle; } } else