Added reference counting and delayed destruction of GDI objects.
diff --git a/objects/dc.c b/objects/dc.c
index 2299361..675c9db 100644
--- a/objects/dc.c
+++ b/objects/dc.c
@@ -757,6 +757,7 @@
SelectObject( hdc, GetStockObject(BLACK_PEN) );
SelectObject( hdc, GetStockObject(WHITE_BRUSH) );
SelectObject( hdc, GetStockObject(SYSTEM_FONT) );
+ SelectObject( hdc, GetStockObject(DEFAULT_BITMAP) );
funcs = dc->funcs;
if (dc->funcs->pDeleteDC) dc->funcs->pDeleteDC(dc);
}
diff --git a/objects/gdiobj.c b/objects/gdiobj.c
index ec5b254..c667902 100644
--- a/objects/gdiobj.c
+++ b/objects/gdiobj.c
@@ -145,6 +145,48 @@
/***********************************************************************
+ * inc_ref_count
+ *
+ * Increment the reference count of a GDI object.
+ */
+inline static void inc_ref_count( HGDIOBJ handle )
+{
+ GDIOBJHDR *header;
+
+ if ((header = GDI_GetObjPtr( handle, MAGIC_DONTCARE )))
+ {
+ header->dwCount++;
+ GDI_ReleaseObj( handle );
+ }
+}
+
+
+/***********************************************************************
+ * dec_ref_count
+ *
+ * Decrement the reference count of a GDI object.
+ */
+inline static void dec_ref_count( HGDIOBJ handle )
+{
+ GDIOBJHDR *header;
+
+ if ((header = GDI_GetObjPtr( handle, MAGIC_DONTCARE )))
+ {
+ if (header->dwCount) header->dwCount--;
+ if (header->dwCount != 0x80000000) GDI_ReleaseObj( handle );
+ else
+ {
+ /* handle delayed DeleteObject*/
+ header->dwCount = 0;
+ GDI_ReleaseObj( handle );
+ TRACE( "executing delayed DeleteObject for %04x\n", handle );
+ DeleteObject( handle );
+ }
+ }
+}
+
+
+/***********************************************************************
* GDI_Init
*
* GDI initialization.
@@ -243,7 +285,6 @@
*/
void *GDI_AllocObject( WORD size, WORD magic, HGDIOBJ *handle )
{
- static DWORD count = 0;
GDIOBJHDR *obj;
_EnterSysLevel( &GDI_level );
@@ -269,7 +310,7 @@
obj->hNext = 0;
obj->wMagic = magic|OBJECT_NOSYSTEM;
- obj->dwCount = ++count;
+ obj->dwCount = 0;
TRACE_SEC( *handle, "enter" );
return obj;
@@ -427,7 +468,15 @@
GDI_ReleaseObj( obj );
return TRUE;
}
-
+
+ if (header->dwCount)
+ {
+ TRACE("delayed for %04x because object in use, count %ld\n", obj, header->dwCount );
+ header->dwCount |= 0x80000000; /* mark for delete */
+ GDI_ReleaseObj( obj );
+ return TRUE;
+ }
+
TRACE("%04x\n", obj );
/* Delete object */
@@ -701,6 +750,12 @@
if (dc->funcs->pSelectObject)
ret = dc->funcs->pSelectObject( dc, handle );
GDI_ReleaseObj( hdc );
+
+ if (ret && ret != handle)
+ {
+ inc_ref_count( handle );
+ dec_ref_count( ret );
+ }
return ret;
}