diff --git a/reactos/include/reactos/win32k/ntgdihdl.h b/reactos/include/reactos/win32k/ntgdihdl.h index c69a266427d..244d8242a6f 100644 --- a/reactos/include/reactos/win32k/ntgdihdl.h +++ b/reactos/include/reactos/win32k/ntgdihdl.h @@ -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 diff --git a/reactos/subsystems/win32/win32k/eng/driverobj.c b/reactos/subsystems/win32/win32k/eng/driverobj.c index 3c12fd5bd27..6706c0036f9 100644 --- a/reactos/subsystems/win32/win32k/eng/driverobj.c +++ b/reactos/subsystems/win32/win32k/eng/driverobj.c @@ -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: See COPYING in the top level directory - * PROJECT: ReactOS kernel + * COPYRIGHT: GPL, see COPYING in the top level directory + * PROJECT: ReactOS win32 kernel mode sunsystem * PURPOSE: GDI DRIVEROBJ Functions - * FILE: subsys/win32k/eng/driverobj.c - * PROGRAMER: Gregor Anich - * REVISION HISTORY: - * 04/01/2005: Created + * FILE: subsystems/win32k/eng/driverobj.c + * PROGRAMER: Timo Kreuzer */ +/** Includes ******************************************************************/ + #include #define NDEBUG #include -/*!\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 - */ -VOID FASTCALL -IntEngCleanupDriverObjs(struct _EPROCESS *Process, - PW32PROCESS Win32Process) -{ - PDRIVERGDI DrvObjInt; - PW32PROCESS CurrentWin32Process; - CurrentWin32Process = PsGetCurrentProcessWin32Process(); - IntEngLockProcessDriverObjs(CurrentWin32Process); - while (!IsListEmpty(&Win32Process->DriverObjListHead)) +/** Internal interface ********************************************************/ + +/*! + * \brief DRIVEROBJ cleanup function + */ +BOOL INTERNAL_CALL +DRIVEROBJ_Cleanup(PVOID pObject) +{ + PEDRIVEROBJ pedo = pObject; + FREEOBJPROC pFreeProc; + + 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 **********************************************************/ -/* - * @implemented - */ HDRVOBJ APIENTRY EngCreateDriverObj( - IN PVOID pvObj, - IN FREEOBJPROC pFreeObjProc, - IN HDEV hdev - ) + IN PVOID pvObj, + IN FREEOBJPROC pFreeObjProc, + IN HDEV hdev) { - PDRIVERGDI DrvObjInt; - PDRIVEROBJ DrvObjUser; - PW32PROCESS CurrentWin32Process; + PEDRIVEROBJ pedo; + HDRVOBJ hdo; + GDIDEVICE *ppdev = (GDIDEVICE*)hdev; - /* Create DRIVEROBJ */ - DrvObjInt = EngAllocMem(0, sizeof (DRIVERGDI), TAG_DRIVEROBJ); - if (DrvObjInt == NULL) + /* Allocate a new DRIVEROBJ */ + pedo = DRIVEROBJ_AllocObjectWithHandle(); + if (!pedo) { - DPRINT1("Failed to allocate memory for a DRIVERGDI structure!\n"); - return NULL; + return NULL; } + hdo = pedo->baseobj.hHmgr; - /* fill user object */ - DrvObjUser = GDIToObj(DrvObjInt, DRIVER); - DrvObjUser->pvObj = pvObj; - DrvObjUser->pFreeProc = pFreeObjProc; - DrvObjUser->hdev = hdev; - DrvObjUser->dhpdev = ((GDIDEVICE*)hdev)->hPDev; + /* Fill in fields */ + pedo->drvobj.pvObj = pvObj; + pedo->drvobj.pFreeProc = pFreeObjProc; + pedo->drvobj.hdev = hdev; + pedo->drvobj.dhpdev = ppdev->hPDev; - /* fill internal object */ - ExInitializeFastMutex(&DrvObjInt->Lock); - CurrentWin32Process = PsGetCurrentProcessWin32Process(); - IntEngLockProcessDriverObjs(CurrentWin32Process); - InsertTailList(&CurrentWin32Process->DriverObjListHead, &DrvObjInt->ListEntry); - IntEngUnLockProcessDriverObjs(CurrentWin32Process); + /* Unlock the object */ + DRIVEROBJ_UnlockObject(pedo); - return (HDRVOBJ)DrvObjUser; + /* Return the handle */ + return hdo; } -/* - * @implemented - */ BOOL APIENTRY EngDeleteDriverObj( - IN HDRVOBJ hdo, - IN BOOL bCallBack, - IN BOOL bLocked - ) + IN HDRVOBJ hdo, + IN BOOL bCallBack, + IN BOOL bLocked) { - PDRIVEROBJ DrvObjUser = (PDRIVEROBJ)hdo; - PDRIVERGDI DrvObjInt = ObjToGDI(DrvObjUser, DRIVER); - PW32PROCESS CurrentWin32Process; + PEDRIVEROBJ pedo; - /* Make sure the obj is locked */ - if (!bLocked) + /* Lock the object */ + pedo = DRIVEROBJ_LockObject(hdo); + if (!pedo) { - if (!ExTryToAcquireFastMutex(&DrvObjInt->Lock)) + return FALSE; + } + + /* Manually call cleanup callback */ + if (bCallBack) + { + if (!pedo->drvobj.pFreeProc(pedo->drvobj.pvObj)) { - return FALSE; + /* Callback failed */ + DRIVEROBJ_UnlockObject(pedo); + return FALSE; } } - /* Call the free-proc */ - if (bCallBack) - { - if (!DrvObjUser->pFreeProc(DrvObjUser)) - { - return FALSE; - } - } + /* Prevent cleanup callback from being called again */ + pedo->drvobj.pFreeProc = NULL; - /* Free the DRIVEROBJ */ - CurrentWin32Process = PsGetCurrentProcessWin32Process(); - IntEngLockProcessDriverObjs(CurrentWin32Process); - RemoveEntryList(&DrvObjInt->ListEntry); - IntEngUnLockProcessDriverObjs(CurrentWin32Process); - EngFreeMem(DrvObjInt); + /* NOTE: We don't care about the bLocked param, as our handle manager + allows freeing the object, while we hold any number of locks. */ - return TRUE; + /* Free the object */ + return DRIVEROBJ_FreeObjectByHandle(hdo); } -/* - * @implemented - */ PDRIVEROBJ APIENTRY -EngLockDriverObj( IN HDRVOBJ hdo ) +EngLockDriverObj( + IN HDRVOBJ hdo) { - PDRIVEROBJ DrvObjUser = (PDRIVEROBJ)hdo; - PDRIVERGDI DrvObjInt = ObjToGDI(DrvObjUser, DRIVER); + PEDRIVEROBJ pedo; - if (!ExTryToAcquireFastMutex(&DrvObjInt->Lock)) - { - return NULL; - } + /* Lock the object */ + pedo = DRIVEROBJ_LockObject(hdo); - return DrvObjUser; + /* Return pointer to the DRIVEROBJ structure */ + return &pedo->drvobj; } -/* - * @implemented - */ BOOL APIENTRY -EngUnlockDriverObj ( IN HDRVOBJ hdo ) +EngUnlockDriverObj( + IN HDRVOBJ hdo) { - PDRIVERGDI DrvObjInt = ObjToGDI((PDRIVEROBJ)hdo, DRIVER); + PEDRIVEROBJ pedo; - ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&DrvObjInt->Lock); - return TRUE; + /* First lock to get a pointer to the object */ + pedo = DRIVEROBJ_LockObject(hdo); + if(!pedo) + { + /* Object could not be locked, fail. */ + return FALSE; + } + + /* 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; } -/* EOF */ - diff --git a/reactos/subsystems/win32/win32k/eng/objects.h b/reactos/subsystems/win32/win32k/eng/objects.h index 35515ae3c8d..f8500de90fb 100644 --- a/reactos/subsystems/win32/win32k/eng/objects.h +++ b/reactos/subsystems/win32/win32k/eng/objects.h @@ -51,12 +51,6 @@ typedef struct _CLIPGDI { 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 { HDEV hdev; diff --git a/reactos/subsystems/win32/win32k/include/driverobj.h b/reactos/subsystems/win32/win32k/include/driverobj.h new file mode 100644 index 00000000000..0799465484a --- /dev/null +++ b/reactos/subsystems/win32/win32k/include/driverobj.h @@ -0,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 */ diff --git a/reactos/subsystems/win32/win32k/include/inteng.h b/reactos/subsystems/win32/win32k/include/inteng.h index 53b1fd00750..88e9a3f41c4 100644 --- a/reactos/subsystems/win32/win32k/include/inteng.h +++ b/reactos/subsystems/win32/win32k/include/inteng.h @@ -34,16 +34,6 @@ typedef struct tagSPAN /* 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, CLIPOBJ *Clip, diff --git a/reactos/subsystems/win32/win32k/include/win32k.h b/reactos/subsystems/win32/win32k/include/win32k.h index f8c8a5f3504..7ffcac53bf1 100644 --- a/reactos/subsystems/win32/win32k/include/win32k.h +++ b/reactos/subsystems/win32/win32k/include/win32k.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include diff --git a/reactos/subsystems/win32/win32k/main/dllmain.c b/reactos/subsystems/win32/win32k/main/dllmain.c index 69df156c199..fdb5df2cb70 100644 --- a/reactos/subsystems/win32/win32k/main/dllmain.c +++ b/reactos/subsystems/win32/win32k/main/dllmain.c @@ -136,7 +136,6 @@ Win32kProcessCallback(struct _EPROCESS *Process, 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! */ diff --git a/reactos/subsystems/win32/win32k/objects/gdiobj.c b/reactos/subsystems/win32/win32k/objects/gdiobj.c index ac81d7cb2b0..4b6e29ba3a5 100644 --- a/reactos/subsystems/win32/win32k/objects/gdiobj.c +++ b/reactos/subsystems/win32/win32k/objects/gdiobj.c @@ -70,7 +70,7 @@ OBJ_TYPE_INFO ObjTypeInfo[BASE_OBJTYPE_COUNT] = {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 @@ LockHandle: Object = Entry->KernelData; - if (Object->cExclusiveLock == 0) + if (Object->cExclusiveLock == 0 || + Object->Tid == (PW32THREAD)PsGetCurrentThreadWin32Thread()) { BOOL Ret; PW32PROCESS W32Process = PsGetCurrentProcessWin32Process(); @@ -571,14 +572,16 @@ LockHandle: 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