//#define GDI_DEBUG
-#include <w32k.h>
+#include <win32k.h>
#define NDEBUG
#include <debug.h>
#include "gdidbg.c"
-/* static */ /* FIXME: -fno-unit-at-a-time breaks this */
+static
BOOL INTERNAL_CALL GDI_CleanupDummy(PVOID ObjectBody);
/** GLOBALS *******************************************************************/
/** 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)
{
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;
}
newObject->cExclusiveLock = 1;
newObject->Tid = Thread;
+ AllocTypeDataDump(TypeInfo);
+
/* unlock the entry */
(void)InterlockedExchangePointer((PVOID*)&Entry->ProcessId, CurrentProcessId);
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);
}
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));
+ /* Set NULL owner. This will permit an other process to kill the object
+ * 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, PrevProcId);
/* Don't wait on shared locks */
return FALSE;
hPtr = GdiHandleCache->Handle + Offset;
- if ( oType == hctRegionHandle)
+ if ( pAttr && oType == hctRegionHandle)
{
if ( Number < CACHE_REGION_ENTRIES )
{
((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;
}
}
break;
case GDI_OBJECT_TYPE_REGION:
- if (bPEBCacheHandle(hObject, hctRegionHandle, pAttr))
+ /* If pAttr NULL, the probability is high for System Region. */
+ if ( pAttr &&
+ bPEBCacheHandle(hObject, hctRegionHandle, pAttr))
{
+ /* User space handle only! */
return TRUE;
}
if (pAttr)
{
- KeEnterCriticalRegion();
FreeObjectAttr(pAttr);
- KeLeaveCriticalRegion();
+ Entry->UserData = NULL;
}
break;
POBJ Object = NULL;
ULONG 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);
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);
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)
if (NewOwner != NULL)
{
- ProcessId = PsGetProcessId(NewOwner);
-
/* Increase the new process' object counter */
W32Process = (PPROCESSINFO)NewOwner->Win32Process;
if (W32Process != NULL)
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);
/** PUBLIC FUNCTIONS **********************************************************/
+BOOL
+FASTCALL
+IntGdiSetRegionOwner(HRGN hRgn, DWORD OwnerMask)
+{
+ INT Index;
+ PGDI_TABLE_ENTRY Entry;
+/*
+ System Regions:
+ These regions do not use attribute sections and when allocated, use gdiobj
+ level functions.
+ */
+ // FIXME! HAX!!! Remove this once we get everything right!
+ Index = GDI_HANDLE_GET_INDEX(hRgn);
+ Entry = &GdiHandleTable->Entries[Index];
+ if (Entry->UserData) FreeObjectAttr(Entry->UserData);
+ Entry->UserData = NULL;
+ //
+ if ((OwnerMask == GDI_OBJ_HMGR_PUBLIC) || OwnerMask == GDI_OBJ_HMGR_NONE)
+ {
+ return GDIOBJ_SetOwnership(hRgn, NULL);
+ }
+ if (OwnerMask == GDI_OBJ_HMGR_POWNED)
+ {
+ return GDIOBJ_SetOwnership((HGDIOBJ) hRgn, PsGetCurrentProcess() );
+ }
+ return FALSE;
+}
+
BOOL
FASTCALL
IntGdiSetBrushOwner(PBRUSH pbr, DWORD OwnerMask)
return TRUE;
}
-
BOOL
FASTCALL
IntGdiSetDCOwnerEx( HDC hDC, DWORD OwnerMask, BOOL NoSetBrush)
return Ret;
}
-
W32KAPI
HANDLE
APIENTRY