From 8e5e003f09a972f6a125c4f5cb7b9151cd20c780 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Mon, 20 Aug 2001 19:17:28 +0000 Subject: [PATCH] Added reference counting and delayed destruction of GDI objects. --- objects/dc.c | 1 + objects/gdiobj.c | 61 +++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/objects/dc.c b/objects/dc.c index 22993616890..675c9dbef3f 100644 --- a/objects/dc.c +++ b/objects/dc.c @@ -757,6 +757,7 @@ BOOL WINAPI DeleteDC( HDC hdc ) 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 ec5b254e2a2..c667902e2d6 100644 --- a/objects/gdiobj.c +++ b/objects/gdiobj.c @@ -144,6 +144,48 @@ static HFONT create_stock_font( char const *fontName, const LOGFONTW *font, HKEY TRACE("(%04x): " text " %ld\n", (handle), GDI_level.crst.RecursionCount) +/*********************************************************************** + * 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 * @@ -243,7 +285,6 @@ inline static GDIOBJHDR *alloc_large_heap( WORD size, HGDIOBJ *handle ) */ void *GDI_AllocObject( WORD size, WORD magic, HGDIOBJ *handle ) { - static DWORD count = 0; GDIOBJHDR *obj; _EnterSysLevel( &GDI_level ); @@ -269,7 +310,7 @@ void *GDI_AllocObject( WORD size, WORD magic, HGDIOBJ *handle ) obj->hNext = 0; obj->wMagic = magic|OBJECT_NOSYSTEM; - obj->dwCount = ++count; + obj->dwCount = 0; TRACE_SEC( *handle, "enter" ); return obj; @@ -427,7 +468,15 @@ BOOL WINAPI DeleteObject( HGDIOBJ obj ) 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 @@ HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ handle ) 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; }