X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=reactos%2Fsubsystems%2Fwin32%2Fwin32k%2Fobjects%2Fgdiobj.c;h=f9bacf092e58cfcc42565805dc1491c60545edae;hp=ac8a1e6862c77160a2d0bda8b5ebbd8b09c88b0f;hb=684c3d3791b92777e7de259fbc6691161f6808c7;hpb=f4519c0c43d81583f5562424347e43758372d13a diff --git a/reactos/subsystems/win32/win32k/objects/gdiobj.c b/reactos/subsystems/win32/win32k/objects/gdiobj.c index ac8a1e6862c..f9bacf092e5 100644 --- a/reactos/subsystems/win32/win32k/objects/gdiobj.c +++ b/reactos/subsystems/win32/win32k/objects/gdiobj.c @@ -8,9 +8,9 @@ /** INCLUDES ******************************************************************/ -//#define GDI_DEBUG +#define GDI_DEBUG -#include +#include #define NDEBUG #include @@ -30,7 +30,7 @@ #include "gdidbg.c" -/* static */ /* FIXME: -fno-unit-at-a-time breaks this */ +static BOOL INTERNAL_CALL GDI_CleanupDummy(PVOID ObjectBody); /** GLOBALS *******************************************************************/ @@ -84,10 +84,63 @@ static LARGE_INTEGER ShortDelay; /** INTERNAL FUNCTIONS ********************************************************/ +// Audit Functions +int tDC = 0; +int tBRUSH = 0; +int tBITMAP = 0; +int tFONT = 0; +int tRGN = 0; + +VOID +AllocTypeDataDump(INT TypeInfo) +{ + switch( TypeInfo & GDI_HANDLE_TYPE_MASK ) + { + case GDILoObjType_LO_BRUSH_TYPE: + tBRUSH++; + break; + case GDILoObjType_LO_DC_TYPE: + tDC++; + break; + case GDILoObjType_LO_BITMAP_TYPE: + tBITMAP++; + break; + case GDILoObjType_LO_FONT_TYPE: + tFONT++; + break; + case GDILoObjType_LO_REGION_TYPE: + tRGN++; + break; + } +} + +VOID +DeAllocTypeDataDump(INT TypeInfo) +{ + switch( TypeInfo & GDI_HANDLE_TYPE_MASK ) + { + case GDILoObjType_LO_BRUSH_TYPE: + tBRUSH--; + break; + case GDILoObjType_LO_DC_TYPE: + tDC--; + break; + case GDILoObjType_LO_BITMAP_TYPE: + tBITMAP--; + break; + case GDILoObjType_LO_FONT_TYPE: + tFONT--; + break; + case GDILoObjType_LO_REGION_TYPE: + tRGN--; + break; + } +} + /* * Dummy GDI Cleanup Callback */ -/* static */ /* FIXME: -fno-unit-at-a-time breaks this */ +static BOOL INTERNAL_CALL GDI_CleanupDummy(PVOID ObjectBody) { @@ -361,6 +414,7 @@ GDIOBJ_AllocObjWithHandle(ULONG ObjectType) if (W32Process && W32Process->GDIHandleCount >= 0x2710) { DPRINT1("Too many objects for process!!!\n"); + DPRINT1("DC %d BRUSH %d BITMAP %d FONT %d RGN %d\n",tDC,tBRUSH,tBITMAP,tFONT,tRGN); GDIDBG_DUMPHANDLETABLE(); return NULL; } @@ -418,6 +472,8 @@ LockHandle: newObject->cExclusiveLock = 1; newObject->Tid = Thread; + AllocTypeDataDump(TypeInfo); + /* unlock the entry */ (void)InterlockedExchangePointer((PVOID*)&Entry->ProcessId, CurrentProcessId); @@ -565,6 +621,8 @@ LockHandle: TypeIndex = GDI_OBJECT_GET_TYPE_INDEX(HandleType); Ret = ObjTypeInfo[TypeIndex].CleanupProc(Object); + DeAllocTypeDataDump(HandleType); + /* Now it's time to free the memory */ GDIOBJ_FreeObj(Object, TypeIndex); @@ -573,11 +631,22 @@ LockHandle: } else if (Object->ulShareCount != 0) { + NTSTATUS Status; + PEPROCESS OldProcess; Object->BaseFlags |= BASEFLAG_READY_TO_DIE; DPRINT("Object %p, ulShareCount = %d\n", Object->hHmgr, Object->ulShareCount); - //GDIDBG_TRACECALLER(); - //GDIDBG_TRACESHARELOCKER(GDI_HANDLE_GET_INDEX(hObj)); - (void)InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId); + /* Set NULL owner. Do the work here to avoid race conditions */ + Status = PsLookupProcessByProcessId((HANDLE)((ULONG_PTR)PrevProcId & ~0x1), &OldProcess); + if (NT_SUCCESS(Status)) + { + PPROCESSINFO W32Process = (PPROCESSINFO)OldProcess->Win32Process; + if (W32Process != NULL) + { + InterlockedDecrement(&W32Process->GDIHandleCount); + } + ObDereferenceObject(OldProcess); + } + (void)InterlockedExchangePointer((PVOID*)&Entry->ProcessId, NULL); /* Don't wait on shared locks */ return FALSE; } @@ -588,7 +657,7 @@ LockHandle: */ DPRINT1("Object->cExclusiveLock = %d\n", Object->cExclusiveLock); GDIDBG_TRACECALLER(); - GDIDBG_TRACELOCKER(GDI_HANDLE_GET_INDEX(hObj)); + GDIDBG_TRACELOCKER(hObj); (void)InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId); /* do not assert here for it will call again from dxg.sys it being call twice */ @@ -630,7 +699,7 @@ LockHandle: } DPRINT1("Type = 0x%lx, KernelData = 0x%p, ProcessId = 0x%p\n", Entry->Type, Entry->KernelData, Entry->ProcessId); GDIDBG_TRACECALLER(); - GDIDBG_TRACEALLOCATOR(GDI_HANDLE_GET_INDEX(hObj)); + GDIDBG_TRACEALLOCATOR(hObj); } } @@ -702,7 +771,7 @@ bPEBCacheHandle(HGDIOBJ Handle, int oType, PVOID pAttr) ((PRGN_ATTR)pAttr)->AttrFlags |= ATTR_CACHED; hPtr[Number] = Handle; GdiHandleCache->ulNumHandles[oType]++; - DPRINT("Put Handle Count %d\n", GdiHandleCache->ulNumHandles[oType]); + DPRINT("Put Handle Count %d PEB 0x%x\n", GdiHandleCache->ulNumHandles[oType], NtCurrentTeb()->ProcessEnvironmentBlock); Ret = TRUE; } } @@ -755,15 +824,13 @@ GreDeleteObject(HGDIOBJ hObject) } if (pAttr) { - KeEnterCriticalRegion(); FreeObjectAttr(pAttr); Entry->UserData = NULL; - KeLeaveCriticalRegion(); } break; case GDI_OBJECT_TYPE_DC: - DC_FreeDcAttr(hObject); +// DC_FreeDcAttr(hObject); break; } @@ -896,12 +963,18 @@ GDIOBJ_LockObj(HGDIOBJ hObj, DWORD ExpectedType) POBJ Object = NULL; ULONG HandleType, HandleUpper; + /* Check for dummy call */ + if(hObj == NULL) + return NULL ; + + GDIDBG_INITLOOPTRACE(); + HandleIndex = GDI_HANDLE_GET_INDEX(hObj); HandleType = GDI_HANDLE_GET_TYPE(hObj); HandleUpper = GDI_HANDLE_GET_UPPER(hObj); /* Check that the handle index is valid. */ - if (HandleIndex >= GDI_HANDLE_COUNT) + if (HandleIndex >= GDI_HANDLE_COUNT ) return NULL; Entry = &GdiHandleTable->Entries[HandleIndex]; @@ -927,7 +1000,7 @@ GDIOBJ_LockObj(HGDIOBJ hObj, DWORD ExpectedType) { DPRINT1("Tried to lock object (0x%p) of wrong owner! ProcessId = %p, HandleProcessId = %p\n", hObj, ProcessId, HandleProcessId); GDIDBG_TRACECALLER(); - GDIDBG_TRACEALLOCATOR(GDI_HANDLE_GET_INDEX(hObj)); + GDIDBG_TRACEALLOCATOR(hObj); return NULL; } @@ -1003,6 +1076,7 @@ GDIOBJ_LockObj(HGDIOBJ hObj, DWORD ExpectedType) /* * The handle is currently locked, wait some time and try again. */ + GDIDBG_TRACELOOP(hObj, PrevProcId, NULL); DelayExecution(); continue; @@ -1035,6 +1109,10 @@ GDIOBJ_ShareLockObj(HGDIOBJ hObj, DWORD ExpectedType) POBJ Object = NULL; ULONG_PTR HandleType, HandleUpper; + /* Check for dummy call */ + if(hObj == NULL) + return NULL ; + HandleIndex = GDI_HANDLE_GET_INDEX(hObj); HandleType = GDI_HANDLE_GET_TYPE(hObj); HandleUpper = GDI_HANDLE_GET_UPPER(hObj); @@ -1334,6 +1412,19 @@ LockHandle: PPROCESSINFO W32Process; NTSTATUS Status; + if (NewOwner != NULL) + { + ProcessId = PsGetProcessId(NewOwner); + } + else + ProcessId = 0; + + if((ULONG_PTR)ProcessId == ((ULONG_PTR)PrevProcId & ~0x1)) + { + DPRINT("Setting same process than previous one, nothing to do\n"); + goto done; + } + /* dereference the process' object counter */ /* FIXME */ if ((ULONG_PTR)PrevProcId & ~0x1) @@ -1352,8 +1443,6 @@ LockHandle: if (NewOwner != NULL) { - ProcessId = PsGetProcessId(NewOwner); - /* Increase the new process' object counter */ W32Process = (PPROCESSINFO)NewOwner->Win32Process; if (W32Process != NULL) @@ -1361,9 +1450,8 @@ LockHandle: InterlockedIncrement(&W32Process->GDIHandleCount); } } - else - ProcessId = 0; + done: /* remove the process id lock and change it to the new process id */ (void)InterlockedExchangePointer((PVOID*)&Entry->ProcessId, ProcessId); @@ -1561,6 +1649,38 @@ GDI_MapHandleTable(PSECTION_OBJECT SectionObject, PEPROCESS Process) return MappedView; } +/* Locks 2 or 3 objects at a time */ +VOID +INTERNAL_CALL +GDIOBJ_LockMultipleObjs(ULONG ulCount, + IN HGDIOBJ* ahObj, + OUT PGDIOBJ* apObj) +{ + UINT auiIndices[3] = {0,1,2}; + UINT i, tmp ; + BOOL bUnsorted = TRUE; + + /* First is greatest */ + while(bUnsorted) + { + bUnsorted = FALSE; + for(i=1; iEntries[Index]; if (Entry->UserData) FreeObjectAttr(Entry->UserData); Entry->UserData = NULL; - KeLeaveCriticalRegion(); // if ((OwnerMask == GDI_OBJ_HMGR_PUBLIC) || OwnerMask == GDI_OBJ_HMGR_NONE) { @@ -1655,10 +1773,9 @@ IntGdiSetDCOwnerEx( HDC hDC, DWORD OwnerMask, BOOL NoSetBrush) { pDC = DC_LockDc ( hDC ); MmCopyFromCaller(&pDC->dcattr, pDC->pdcattr, sizeof(DC_ATTR)); + DC_vFreeDcAttr(pDC); DC_UnlockDc( pDC ); - DC_FreeDcAttr( hDC ); // Free the dcattr! - if (!DC_SetOwnership( hDC, NULL )) // This hDC is inaccessible! return Ret; }