[ros-diffs] [tkreuzer] 33618: - Fix wrong debug output when a process is terminated, by deleting the it's objects in a proper order, fixes bug 2954 - remove Fireball's, ugly nasty hack. - Fix debug output to show the right problem - For all people who think the handle table might be messed up: add a function that validates the handle table integrity after a process is closed, when GDI_DEBUG is defined. - fix the BaseObjects hHmgr field when converting an object to a stock object. - move all GDI_DEBUG stuff into it's own file See issue #2954 for more details.

tkreuzer at svn.reactos.org tkreuzer at svn.reactos.org
Tue May 20 22:39:32 CEST 2008


Author: tkreuzer
Date: Tue May 20 15:39:32 2008
New Revision: 33618

URL: http://svn.reactos.org/svn/reactos?rev=33618&view=rev
Log:
- Fix wrong debug output when a process is terminated, by deleting the it's objects in a proper order, fixes bug 2954
- remove Fireball's, ugly nasty hack.
- Fix debug output to show the right problem
- For all people who think the handle table might be messed up: add a function that validates the handle table integrity after a process is closed, when GDI_DEBUG is defined.
- fix the BaseObjects hHmgr field when converting an object to a stock object.
- move all GDI_DEBUG stuff into it's own file

See issue #2954 for more details.

Added:
    trunk/reactos/subsystems/win32/win32k/objects/gdidbg.c   (with props)
Modified:
    trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c

Added: trunk/reactos/subsystems/win32/win32k/objects/gdidbg.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/objects/gdidbg.c?rev=33618&view=auto
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/objects/gdidbg.c (added)
+++ trunk/reactos/subsystems/win32/win32k/objects/gdidbg.c [iso-8859-1] Tue May 20 15:39:32 2008
@@ -1,0 +1,272 @@
+#ifdef GDI_DEBUG
+
+BOOLEAN STDCALL KiRosPrintAddress(PVOID Address);
+NTSYSAPI ULONG NTAPI RtlWalkFrameChain(OUT PVOID *Callers, IN ULONG Count, IN ULONG Flags);
+
+static int leak_reported = 0;
+#define GDI_STACK_LEVELS 12
+static ULONG GDIHandleAllocator[GDI_HANDLE_COUNT][GDI_STACK_LEVELS+1];
+static ULONG GDIHandleLocker[GDI_HANDLE_COUNT][GDI_STACK_LEVELS+1];
+struct DbgOpenGDIHandle
+{
+    ULONG idx;
+    int count;
+};
+#define H 1024
+static struct DbgOpenGDIHandle h[H];
+
+void IntDumpHandleTable(PGDI_HANDLE_TABLE HandleTable)
+{
+    int i, n = 0, j, k, J;
+
+    if (leak_reported)
+    {
+        DPRINT1("gdi handle abusers already reported!\n");
+        return;
+    }
+
+    leak_reported = 1;
+    DPRINT1("reporting gdi handle abusers:\n");
+
+    /* step through GDI handle table and find out who our culprit is... */
+    for (i = RESERVE_ENTRIES_COUNT; i < GDI_HANDLE_COUNT; i++)
+    {
+        for (j = 0; j < n; j++)
+        {
+next:
+            J = h[j].idx;
+            for (k = 0; k < GDI_STACK_LEVELS; k++)
+            {
+                if (GDIHandleAllocator[i][k]
+                        != GDIHandleAllocator[J][k])
+                {
+                    if (++j == n)
+                        goto done;
+                    else
+                        goto next;
+                }
+            }
+            goto done;
+        }
+done:
+        if (j < H)
+        {
+            if (j == n)
+            {
+                h[j].idx = i;
+                h[j].count = 1;
+                n = n + 1;
+            }
+            else
+                h[j].count++;
+        }
+    }
+    /* bubble sort time! weeeeee!! */
+    for (i = 0; i < n-1; i++)
+    {
+        if (h[i].count < h[i+1].count)
+        {
+            struct DbgOpenGDIHandle t;
+            t = h[i+1];
+            h[i+1] = h[i];
+            j = i;
+            while (j > 0 && h[j-1].count < t.count)
+                j--;
+            h[j] = t;
+        }
+    }
+    /* print the worst offenders... */
+    DbgPrint("Worst GDI Handle leak offenders (out of %i unique locations):\n", n);
+    for (i = 0; i < n && h[i].count > 1; i++)
+    {
+        int j;
+        DbgPrint(" %i allocs: ", h[i].count);
+        for (j = 0; j < GDI_STACK_LEVELS; j++)
+        {
+            ULONG Addr = GDIHandleAllocator[h[i].idx][j];
+            if (!KiRosPrintAddress((PVOID)Addr))
+                DbgPrint("<%X>", Addr);
+        }
+        DbgPrint("\n");
+    }
+    if (i < n && h[i].count == 1)
+        DbgPrint("(list terminated - the remaining entries have 1 allocation only)\n");
+}
+
+ULONG
+CaptureStackBackTace(PVOID* pFrames, ULONG nFramesToCapture)
+{
+    ULONG nFrameCount;
+
+    memset(pFrames, 0x00, (nFramesToCapture + 1) * sizeof(PVOID));
+
+    nFrameCount = RtlCaptureStackBackTrace(1, nFramesToCapture, pFrames, NULL);
+
+    if (nFrameCount < nFramesToCapture)
+    {
+        nFrameCount += RtlWalkFrameChain(pFrames + nFrameCount, nFramesToCapture - nFrameCount, 1);
+    }
+
+    return nFrameCount;
+}
+
+BOOL
+GdiDbgHTIntegrityCheck()
+{
+	ULONG i, nDeleted = 0, nFree = 0, nUsed = 0;
+	PGDI_TABLE_ENTRY pEntry;
+	BOOL r = 1;
+
+	KeEnterCriticalRegion();
+
+	/* FIXME: check reserved entries */
+
+	/* Now go through the deleted objects */
+	i = GdiHandleTable->FirstFree;
+	if (i)
+	{
+		pEntry = &GdiHandleTable->Entries[i];
+		for (;;)
+		{
+			nDeleted++;
+
+			/* Check the entry */
+			if ((pEntry->Type & GDI_ENTRY_BASETYPE_MASK) != 0)
+			{
+				r = 0;
+				DPRINT1("Deleted Entry has a type != 0\n");
+			}
+			if ((ULONG_PTR)pEntry->KernelData >= GDI_HANDLE_COUNT)
+			{
+				r = 0;
+				DPRINT1("Deleted entries KernelPointer too big\n");
+			}
+			if (pEntry->UserData != NULL)
+			{
+				r = 0;
+				DPRINT1("Deleted entry has UserData != 0\n");
+			}
+			if (pEntry->ProcessId != 0)
+			{
+				r = 0;
+				DPRINT1("Deleted entry has ProcessId != 0\n");
+			}
+
+			i = (ULONG_PTR)pEntry->KernelData;
+			if (!i)
+			{
+				break;
+			}
+			pEntry = &GdiHandleTable->Entries[i];
+		}
+	}
+
+	for (i = GdiHandleTable->FirstUnused;
+	     i < GDI_HANDLE_COUNT;
+	     i++)
+	{
+		pEntry = &GdiHandleTable->Entries[i];
+
+		if ((pEntry->Type) != 0)
+		{
+			r = 0;
+			DPRINT1("Free Entry has a type != 0\n");
+		}
+		if ((ULONG_PTR)pEntry->KernelData != 0)
+		{
+			r = 0;
+			DPRINT1("Free entries KernelPointer != 0\n");
+		}
+		if (pEntry->UserData != NULL)
+		{
+			r = 0;
+			DPRINT1("Free entry has UserData != 0\n");
+		}
+		if (pEntry->ProcessId != 0)
+		{
+			r = 0;
+			DPRINT1("Free entry has ProcessId != 0\n");
+		}
+		nFree++;
+	}
+
+	for (i = RESERVE_ENTRIES_COUNT; i < GDI_HANDLE_COUNT; i++)
+	{
+		HGDIOBJ Handle;
+		ULONG Type;
+
+		pEntry = &GdiHandleTable->Entries[i];
+		Type = pEntry->Type;
+		Handle = (HGDIOBJ)((Type << GDI_ENTRY_UPPER_SHIFT) + i);
+
+		if (Type & GDI_ENTRY_BASETYPE_MASK)
+		{
+			if (pEntry->KernelData == NULL)
+			{
+				r = 0;
+				DPRINT1("Used entry has KernelData == 0\n");
+			}
+			if (pEntry->KernelData <= MmHighestUserAddress)
+			{
+				r = 0;
+				DPRINT1("Used entry invalid KernelData\n");
+			}
+			if (((POBJ)(pEntry->KernelData))->hHmgr != Handle)
+			{
+				r = 0;
+				DPRINT1("Used entry %ld, has invalid hHmg %p (expected: %p)\n",
+				        i, ((POBJ)(pEntry->KernelData))->hHmgr, Handle);
+			}
+			nUsed++;
+		}
+	}
+
+	if (RESERVE_ENTRIES_COUNT + nDeleted + nFree + nUsed != GDI_HANDLE_COUNT)
+	{
+		r = 0;
+		DPRINT1("Number of all entries incorrect: RESERVE_ENTRIES_COUNT = %ld, nDeleted = %ld, nFree = %ld, nUsed = %ld\n",
+		        RESERVE_ENTRIES_COUNT, nDeleted, nFree, nUsed);
+	}
+
+	KeLeaveCriticalRegion();
+
+	return r;
+}
+
+
+#define GDIDBG_TRACECALLER() \
+  DPRINT1("-> called from:\n"); \
+  KeRosDumpStackFrames(NULL, 20);
+#define GDIDBG_TRACEALLOCATOR(index) \
+  DPRINT1("-> allocated from:\n"); \
+  KeRosDumpStackFrames(GDIHandleAllocator[index], GDI_STACK_LEVELS);
+#define GDIDBG_TRACELOCKER(index) \
+  DPRINT1("-> locked from:\n"); \
+  KeRosDumpStackFrames(GDIHandleLocker[index], GDI_STACK_LEVELS);
+#define GDIDBG_CAPTUREALLOCATOR(index) \
+  CaptureStackBackTace((PVOID*)GDIHandleAllocator[index], GDI_STACK_LEVELS);
+#define GDIDBG_CAPTURELOCKER(index) \
+  CaptureStackBackTace((PVOID*)GDIHandleLocker[index], GDI_STACK_LEVELS);
+#define GDIDBG_DUMPHANDLETABLE() \
+  IntDumpHandleTable(GdiHandleTable)
+#define GDIDBG_INITLOOPTRACE() \
+  ULONG Attempts = 0;
+#define GDIDBG_TRACELOOP(Handle, PrevThread, Thread) \
+  if ((++Attempts % 20) == 0) \
+  { \
+    DPRINT1("[%d] Handle 0x%p Locked by 0x%x (we're 0x%x)\n", Attempts, Handle, PrevThread, Thread); \
+  }
+
+#else
+
+#define GDIDBG_TRACECALLER()
+#define GDIDBG_TRACEALLOCATOR(index)
+#define GDIDBG_TRACELOCKER(index)
+#define GDIDBG_CAPTUREALLOCATOR(index)
+#define GDIDBG_CAPTURELOCKER(index)
+#define GDIDBG_DUMPHANDLETABLE()
+#define GDIDBG_INITLOOPTRACE()
+#define GDIDBG_TRACELOOP(Handle, PrevThread, Thread)
+
+#endif /* GDI_DEBUG */
+

Propchange: trunk/reactos/subsystems/win32/win32k/objects/gdidbg.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c?rev=33618&r1=33617&r2=33618&view=diff
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c [iso-8859-1] Tue May 20 15:39:32 2008
@@ -17,11 +17,6 @@
 VOID NTAPI KeRosDumpStackFrames(PULONG, ULONG);
 
 //#define GDI_DEBUG
-
-#ifdef GDI_DEBUG
-BOOLEAN STDCALL KiRosPrintAddress(PVOID Address);
-NTSYSAPI ULONG NTAPI RtlWalkFrameChain(OUT PVOID *Callers, IN ULONG Count, IN ULONG Flags);
-#endif
 
 #define GDI_ENTRY_TO_INDEX(ht, e)                                              \
   (((ULONG_PTR)(e) - (ULONG_PTR)&((ht)->Entries[0])) / sizeof(GDI_TABLE_ENTRY))
@@ -89,151 +84,7 @@
 
 /** DEBUGGING *****************************************************************/
 
-#ifdef GDI_DEBUG
-
-static int leak_reported = 0;
-#define GDI_STACK_LEVELS 12
-static ULONG GDIHandleAllocator[GDI_HANDLE_COUNT][GDI_STACK_LEVELS+1];
-static ULONG GDIHandleLocker[GDI_HANDLE_COUNT][GDI_STACK_LEVELS+1];
-struct DbgOpenGDIHandle
-{
-    ULONG idx;
-    int count;
-};
-#define H 1024
-static struct DbgOpenGDIHandle h[H];
-
-void IntDumpHandleTable(PGDI_HANDLE_TABLE HandleTable)
-{
-    int i, n = 0, j, k, J;
-
-    if (leak_reported)
-    {
-        DPRINT1("gdi handle abusers already reported!\n");
-        return;
-    }
-
-    leak_reported = 1;
-    DPRINT1("reporting gdi handle abusers:\n");
-
-    /* step through GDI handle table and find out who our culprit is... */
-    for (i = RESERVE_ENTRIES_COUNT; i < GDI_HANDLE_COUNT; i++)
-    {
-        for (j = 0; j < n; j++)
-        {
-next:
-            J = h[j].idx;
-            for (k = 0; k < GDI_STACK_LEVELS; k++)
-            {
-                if (GDIHandleAllocator[i][k]
-                        != GDIHandleAllocator[J][k])
-                {
-                    if (++j == n)
-                        goto done;
-                    else
-                        goto next;
-                }
-            }
-            goto done;
-        }
-done:
-        if (j < H)
-        {
-            if (j == n)
-            {
-                h[j].idx = i;
-                h[j].count = 1;
-                n = n + 1;
-            }
-            else
-                h[j].count++;
-        }
-    }
-    /* bubble sort time! weeeeee!! */
-    for (i = 0; i < n-1; i++)
-    {
-        if (h[i].count < h[i+1].count)
-        {
-            struct DbgOpenGDIHandle t;
-            t = h[i+1];
-            h[i+1] = h[i];
-            j = i;
-            while (j > 0 && h[j-1].count < t.count)
-                j--;
-            h[j] = t;
-        }
-    }
-    /* print the worst offenders... */
-    DbgPrint("Worst GDI Handle leak offenders (out of %i unique locations):\n", n);
-    for (i = 0; i < n && h[i].count > 1; i++)
-    {
-        int j;
-        DbgPrint(" %i allocs: ", h[i].count);
-        for (j = 0; j < GDI_STACK_LEVELS; j++)
-        {
-            ULONG Addr = GDIHandleAllocator[h[i].idx][j];
-            if (!KiRosPrintAddress((PVOID)Addr))
-                DbgPrint("<%X>", Addr);
-        }
-        DbgPrint("\n");
-    }
-    if (i < n && h[i].count == 1)
-        DbgPrint("(list terminated - the remaining entries have 1 allocation only)\n");
-}
-
-ULONG
-CaptureStackBackTace(PVOID* pFrames, ULONG nFramesToCapture)
-{
-    ULONG nFrameCount;
-
-    memset(pFrames, 0x00, (nFramesToCapture + 1) * sizeof(PVOID));
-
-    nFrameCount = RtlCaptureStackBackTrace(1, nFramesToCapture, pFrames, NULL);
-
-    if (nFrameCount < nFramesToCapture)
-    {
-        nFrameCount += RtlWalkFrameChain(pFrames + nFrameCount, nFramesToCapture - nFrameCount, 1);
-    }
-
-    return nFrameCount;
-}
-
-#define GDIDBG_TRACECALLER() \
-  DPRINT1("-> called from:\n"); \
-  KeRosDumpStackFrames(NULL, 20);
-#define GDIDBG_TRACEALLOCATOR(index) \
-  DPRINT1("-> allocated from:\n"); \
-  KeRosDumpStackFrames(GDIHandleAllocator[index], GDI_STACK_LEVELS);
-#define GDIDBG_TRACELOCKER(index) \
-  DPRINT1("-> locked from:\n"); \
-  KeRosDumpStackFrames(GDIHandleLocker[index], GDI_STACK_LEVELS);
-#define GDIDBG_CAPTUREALLOCATOR(index) \
-  CaptureStackBackTace((PVOID*)GDIHandleAllocator[index], GDI_STACK_LEVELS);
-#define GDIDBG_CAPTURELOCKER(index) \
-  CaptureStackBackTace((PVOID*)GDIHandleLocker[index], GDI_STACK_LEVELS);
-#define GDIDBG_DUMPHANDLETABLE() \
-  IntDumpHandleTable(GdiHandleTable)
-#define GDIDBG_INITLOOPTRACE() \
-  ULONG Attempts = 0;
-#define GDIDBG_TRACELOOP(Handle, PrevThread, Thread) \
-  if ((++Attempts % 20) == 0) \
-  { \
-    DPRINT1("[%d] Handle 0x%p Locked by 0x%x (we're 0x%x)\n", Attempts, Handle, PrevThread, Thread); \
-  }
-
-#else
-
-#define GDIDBG_TRACECALLER()
-#define GDIDBG_TRACEALLOCATOR(index)
-#define GDIDBG_TRACELOCKER(index)
-#define GDIDBG_CAPTUREALLOCATOR(index)
-#define GDIDBG_CAPTURELOCKER(index)
-#define GDIDBG_DUMPHANDLETABLE()
-#define GDIDBG_INITLOOPTRACE()
-#define GDIDBG_TRACELOOP(Handle, PrevThread, Thread)
-
-#endif /* GDI_DEBUG */
-
+#include "gdidbg.c"
 
 /** INTERNAL FUNCTIONS ********************************************************/
 
@@ -716,25 +567,19 @@
     {
         if (!Silent)
         {
-            if (((ULONG_PTR)PrevProcId & ~0x1) == 0)
+            if ((Entry->Type & GDI_ENTRY_BASETYPE_MASK) == 0)
+            {
+                DPRINT1("Attempted to free gdi handle 0x%x that is already deleted!\n", hObj);
+            }
+            else if (((ULONG_PTR)PrevProcId & ~0x1) == 0)
             {
                 DPRINT1("Attempted to free global gdi handle 0x%x, caller needs to get ownership first!!!\n", hObj);
-                DPRINT1("Type = 0x%lx, KernelData = 0x%p, ProcessId = 0x%p\n", Entry->Type, Entry->KernelData, Entry->ProcessId);
-
-                /* HACK: Ugly and nasty */
-                if ((ULONG_PTR)Entry->KernelData < 0x1000)
-                {
-                    /* It's a memory-corruption bug (probably?),
-                       overcome it by just saying "yes, object destroyed" */
-                    DPRINT1("Bad kerneldata!!! Blame Win32k developers!\n");
-                    return TRUE;
-                }
-
             }
             else
             {
                 DPRINT1("Attempted to free foreign handle: 0x%x Owner: 0x%x from Caller: 0x%x\n", hObj, (ULONG_PTR)PrevProcId & ~0x1, (ULONG_PTR)ProcessId & ~0x1);
             }
+            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));
         }
@@ -782,6 +627,57 @@
     }
 }
 
+VOID
+FASTCALL
+IntDeleteHandlesForProcess(struct _EPROCESS *Process, ULONG ObjectType)
+{
+    PGDI_TABLE_ENTRY Entry, End;
+    ULONG Index = RESERVE_ENTRIES_COUNT;
+    HANDLE ProcId;
+    PW32PROCESS W32Process;
+
+    W32Process = (PW32PROCESS)Process->Win32Process;
+    ASSERT(W32Process);
+
+    if (W32Process->GDIObjects > 0)
+    {
+       ProcId = Process->UniqueProcessId;
+
+    /* FIXME - Instead of building the handle here and delete it using GDIOBJ_FreeObj
+               we should delete it directly here! */
+
+        End = &GdiHandleTable->Entries[GDI_HANDLE_COUNT];
+        for (Entry = &GdiHandleTable->Entries[RESERVE_ENTRIES_COUNT];
+             Entry != End;
+             Entry++, Index++)
+        {
+            /* ignore the lock bit */
+            if ( (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) == ProcId)
+            {
+                if ( (Entry->Type & GDI_ENTRY_BASETYPE_MASK) == ObjectType ||
+                     ObjectType == GDI_OBJECT_TYPE_DONTCARE)
+                {
+                    HGDIOBJ ObjectHandle;
+
+                    /* Create the object handle for the entry, the lower(!) 16 bit of the
+                       Type field includes the type of the object including the stock
+                       object flag - but since stock objects don't have a process id we can
+                       simply ignore this fact here. */
+                    ObjectHandle = (HGDIOBJ)(Index | (Entry->Type << GDI_ENTRY_UPPER_SHIFT));
+
+                    if (GDIOBJ_FreeObjByHandle(ObjectHandle, GDI_OBJECT_TYPE_DONTCARE) &&
+                        W32Process->GDIObjects == 0)
+                    {
+                        /* there are no more gdi handles for this process, bail */
+                        break;
+                    }
+                }
+            }
+        }
+    }
+}
+
+
 /*!
  * Internal function. Called when the process is destroyed to free the remaining GDI handles.
  * \param	Process - PID of the process that will be destroyed.
@@ -789,11 +685,7 @@
 BOOL INTERNAL_CALL
 GDI_CleanupForProcess(struct _EPROCESS *Process)
 {
-    PGDI_TABLE_ENTRY Entry, End;
     PEPROCESS CurrentProcess;
-    PW32PROCESS W32Process;
-    HANDLE ProcId;
-    ULONG Index = RESERVE_ENTRIES_COUNT;
 
     DPRINT("Starting CleanupForProcess prochandle %x Pid %d\n", Process, Process->UniqueProcessId);
     CurrentProcess = PsGetCurrentProcess();
@@ -801,46 +693,23 @@
     {
         KeAttachProcess(&Process->Pcb);
     }
-    W32Process = (PW32PROCESS)Process->Win32Process;
-    ASSERT(W32Process);
-
-    if (W32Process->GDIObjects > 0)
-    {
-        /* FIXME - Instead of building the handle here and delete it using GDIOBJ_FreeObj
-                   we should delete it directly here! */
-        ProcId = Process->UniqueProcessId;
-
-        End = &GdiHandleTable->Entries[GDI_HANDLE_COUNT];
-        for (Entry = &GdiHandleTable->Entries[RESERVE_ENTRIES_COUNT];
-                Entry != End;
-                Entry++, Index++)
-        {
-            /* ignore the lock bit */
-            if ( (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) == ProcId &&
-                 (Entry->Type & ~GDI_ENTRY_REUSE_MASK) != 0 )
-            {
-                HGDIOBJ ObjectHandle;
-
-                /* Create the object handle for the entry, the lower(!) 16 bit of the
-                   Type field includes the type of the object including the stock
-                   object flag - but since stock objects don't have a process id we can
-                   simply ignore this fact here. */
-                ObjectHandle = (HGDIOBJ)(Index | (Entry->Type << GDI_ENTRY_UPPER_SHIFT));
-
-                if (GDIOBJ_FreeObjByHandle(ObjectHandle, GDI_OBJECT_TYPE_DONTCARE) &&
-                        W32Process->GDIObjects == 0)
-                {
-                    /* there are no more gdi handles for this process, bail */
-                    break;
-                }
-            }
-        }
-    }
+
+    /* Delete objects. Begin with types that are not referenced by other types */
+    IntDeleteHandlesForProcess(Process, GDILoObjType_LO_DC_TYPE);
+    IntDeleteHandlesForProcess(Process, GDILoObjType_LO_BRUSH_TYPE);
+    IntDeleteHandlesForProcess(Process, GDILoObjType_LO_BITMAP_TYPE);
+
+    /* Finally finish with what's left */
+    IntDeleteHandlesForProcess(Process, GDI_OBJECT_TYPE_DONTCARE);
 
     if (CurrentProcess != Process)
     {
         KeDetachProcess();
     }
+
+#ifdef GDI_DEBUG
+	GdiDbgHTIntegrityCheck();
+#endif
 
     DPRINT("Completed cleanup for process %d\n", Process->UniqueProcessId);
 
@@ -1240,11 +1109,12 @@
                         }
                     }
 
+                    hObj = (HGDIOBJ)((ULONG)(hObj) | GDI_HANDLE_STOCK_MASK);
+                    *phObj = hObj;
+                    Object->hHmgr = hObj;
+
                     /* remove the process id lock and make it global */
                     (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, GDI_GLOBAL_PROCESS);
-
-                    hObj = (HGDIOBJ)((ULONG)(hObj) | GDI_HANDLE_STOCK_MASK);
-                    *phObj = hObj;
 
                     /* we're done, successfully converted the object */
                     return TRUE;



More information about the Ros-diffs mailing list