From de831f334c8a2b09a96bc881f8359a6f1c766729 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 28 Jan 2009 18:45:21 +0100 Subject: [PATCH] gdi32: Release GDI handles before freeing the object. This makes it unnecessary to hold the GDI lock during destruction. --- dlls/gdi32/bitmap.c | 10 +++++++--- dlls/gdi32/brush.c | 4 ++-- dlls/gdi32/dc.c | 5 ++--- dlls/gdi32/enhmetafile.c | 4 ++-- dlls/gdi32/font.c | 8 +++++--- dlls/gdi32/gdi_private.h | 2 +- dlls/gdi32/gdiobj.c | 24 ++++++++++++++---------- dlls/gdi32/metafile.c | 5 ++--- dlls/gdi32/palette.c | 4 ++-- dlls/gdi32/pen.c | 4 ++-- dlls/gdi32/region.c | 12 +++++++----- 11 files changed, 46 insertions(+), 36 deletions(-) diff --git a/dlls/gdi32/bitmap.c b/dlls/gdi32/bitmap.c index 520964d15cc..8bb21f2ba2c 100644 --- a/dlls/gdi32/bitmap.c +++ b/dlls/gdi32/bitmap.c @@ -628,12 +628,16 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc ) */ static BOOL BITMAP_DeleteObject( HGDIOBJ handle ) { + const DC_FUNCTIONS *funcs; BITMAPOBJ *bmp = GDI_GetObjPtr( handle, OBJ_BITMAP ); if (!bmp) return FALSE; + funcs = bmp->funcs; + GDI_ReleaseObj( handle ); - if (bmp->funcs && bmp->funcs->pDeleteBitmap) - bmp->funcs->pDeleteBitmap( handle ); + if (funcs && funcs->pDeleteBitmap) funcs->pDeleteBitmap( handle ); + + if (!(bmp = free_gdi_handle( handle ))) return FALSE; HeapFree( GetProcessHeap(), 0, bmp->bitmap.bmBits ); @@ -665,7 +669,7 @@ static BOOL BITMAP_DeleteObject( HGDIOBJ handle ) } HeapFree(GetProcessHeap(), 0, bmp->color_table); } - return GDI_FreeObject( handle, bmp ); + return HeapFree( GetProcessHeap(), 0, bmp ); } diff --git a/dlls/gdi32/brush.c b/dlls/gdi32/brush.c index 6b0369b6fc7..885fe88b13a 100644 --- a/dlls/gdi32/brush.c +++ b/dlls/gdi32/brush.c @@ -416,7 +416,7 @@ static HGDIOBJ BRUSH_SelectObject( HGDIOBJ handle, HDC hdc ) */ static BOOL BRUSH_DeleteObject( HGDIOBJ handle ) { - BRUSHOBJ *brush = GDI_GetObjPtr( handle, OBJ_BRUSH ); + BRUSHOBJ *brush = free_gdi_handle( handle ); if (!brush) return FALSE; switch(brush->logbrush.lbStyle) @@ -428,7 +428,7 @@ static BOOL BRUSH_DeleteObject( HGDIOBJ handle ) GlobalFree16( (HGLOBAL16)brush->logbrush.lbHatch ); break; } - return GDI_FreeObject( handle, brush ); + return HeapFree( GetProcessHeap(), 0, brush ); } diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c index 5b05973faf7..3648f64b8cc 100644 --- a/dlls/gdi32/dc.c +++ b/dlls/gdi32/dc.c @@ -163,9 +163,8 @@ DC *alloc_dc_ptr( const DC_FUNCTIONS *funcs, WORD magic ) BOOL free_dc_ptr( DC *dc ) { assert( dc->refcount == 1 ); - /* grab the gdi lock again */ - if (!GDI_GetObjPtr( dc->hSelf, 0 )) return FALSE; /* shouldn't happen */ - return GDI_FreeObject( dc->hSelf, dc ); + if (free_gdi_handle( dc->hSelf ) != dc) return FALSE; /* shouldn't happen */ + return HeapFree( GetProcessHeap(), 0, dc ); } diff --git a/dlls/gdi32/enhmetafile.c b/dlls/gdi32/enhmetafile.c index f77237b4706..9ca85177eb9 100644 --- a/dlls/gdi32/enhmetafile.c +++ b/dlls/gdi32/enhmetafile.c @@ -276,7 +276,7 @@ HENHMETAFILE EMF_Create_HENHMETAFILE(ENHMETAHEADER *emh, BOOL on_disk ) */ static BOOL EMF_Delete_HENHMETAFILE( HENHMETAFILE hmf ) { - ENHMETAFILEOBJ *metaObj = GDI_GetObjPtr( hmf, OBJ_ENHMETAFILE ); + ENHMETAFILEOBJ *metaObj = free_gdi_handle( hmf ); if(!metaObj) return FALSE; @@ -284,7 +284,7 @@ static BOOL EMF_Delete_HENHMETAFILE( HENHMETAFILE hmf ) UnmapViewOfFile( metaObj->emh ); else HeapFree( GetProcessHeap(), 0, metaObj->emh ); - return GDI_FreeObject( hmf, metaObj ); + return HeapFree( GetProcessHeap(), 0, metaObj ); } /****************************************************************** diff --git a/dlls/gdi32/font.c b/dlls/gdi32/font.c index 2941f2c5db9..409761a0f98 100644 --- a/dlls/gdi32/font.c +++ b/dlls/gdi32/font.c @@ -559,10 +559,12 @@ static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer ) */ static BOOL FONT_DeleteObject( HGDIOBJ handle ) { - FONTOBJ *obj = GDI_GetObjPtr( handle, OBJ_FONT ); /* to grab the GDI lock (FIXME) */ - if (!obj) return FALSE; + FONTOBJ *obj; + WineEngDestroyFontInstance( handle ); - return GDI_FreeObject( handle, obj ); + + if (!(obj = free_gdi_handle( handle ))) return FALSE; + return HeapFree( GetProcessHeap(), 0, obj ); } diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index f2d383005b7..e78e496e32d 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -439,7 +439,7 @@ extern BOOL WineEngRemoveFontResourceEx(LPCWSTR, DWORD, PVOID) DECLSPEC_HIDDEN; extern BOOL GDI_Init(void) DECLSPEC_HIDDEN; extern HGDIOBJ alloc_gdi_handle( GDIOBJHDR *obj, WORD type, const struct gdi_obj_funcs *funcs ) DECLSPEC_HIDDEN; extern void *GDI_ReallocObject( WORD, HGDIOBJ, void *obj ) DECLSPEC_HIDDEN; -extern BOOL GDI_FreeObject( HGDIOBJ, void *obj ) DECLSPEC_HIDDEN; +extern void *free_gdi_handle( HGDIOBJ handle ) DECLSPEC_HIDDEN; extern void *GDI_GetObjPtr( HGDIOBJ, WORD ) DECLSPEC_HIDDEN; extern void GDI_ReleaseObj( HGDIOBJ ) DECLSPEC_HIDDEN; extern void GDI_CheckNotLock(void) DECLSPEC_HIDDEN; diff --git a/dlls/gdi32/gdiobj.c b/dlls/gdi32/gdiobj.c index 647dcb82e23..cc87c6ecf34 100644 --- a/dlls/gdi32/gdiobj.c +++ b/dlls/gdi32/gdiobj.c @@ -689,25 +689,29 @@ void *GDI_ReallocObject( WORD size, HGDIOBJ handle, void *object ) /*********************************************************************** - * GDI_FreeObject + * free_gdi_handle + * + * Free a GDI handle and return a pointer to the object. */ -BOOL GDI_FreeObject( HGDIOBJ handle, void *ptr ) +void *free_gdi_handle( HGDIOBJ handle ) { - GDIOBJHDR *object = ptr; + GDIOBJHDR *object = NULL; int i; - object->type = 0; /* Mark it as invalid */ - object->funcs = NULL; i = ((ULONG_PTR)handle >> 2) - FIRST_LARGE_HANDLE; if (i >= 0 && i < MAX_LARGE_HANDLES) { - HeapFree( GetProcessHeap(), 0, large_handles[i] ); + _EnterSysLevel( &GDI_level ); + object = large_handles[i]; large_handles[i] = NULL; + _LeaveSysLevel( &GDI_level ); } - else ERR( "Invalid handle %p\n", handle ); - TRACE("(%p): leave %d\n", handle, GDI_level.crst.RecursionCount); - _LeaveSysLevel( &GDI_level ); - return TRUE; + if (object) + { + object->type = 0; /* mark it as invalid */ + object->funcs = NULL; + } + return object; } diff --git a/dlls/gdi32/metafile.c b/dlls/gdi32/metafile.c index bfa4bddbe98..ea75ae85183 100644 --- a/dlls/gdi32/metafile.c +++ b/dlls/gdi32/metafile.c @@ -163,11 +163,10 @@ static POINT *convert_points( UINT count, POINT16 *pt16 ) BOOL WINAPI DeleteMetaFile( HMETAFILE hmf ) { - METAFILEOBJ * metaObj = GDI_GetObjPtr( hmf, OBJ_METAFILE ); + METAFILEOBJ * metaObj = free_gdi_handle( hmf ); if (!metaObj) return FALSE; HeapFree( GetProcessHeap(), 0, metaObj->mh ); - GDI_FreeObject( hmf, metaObj ); - return TRUE; + return HeapFree( GetProcessHeap(), 0, metaObj ); } /****************************************************************** diff --git a/dlls/gdi32/palette.c b/dlls/gdi32/palette.c index 8f1c84afae1..a6584402dd0 100644 --- a/dlls/gdi32/palette.c +++ b/dlls/gdi32/palette.c @@ -679,8 +679,8 @@ static BOOL PALETTE_DeleteObject( HGDIOBJ handle ) PALETTEOBJ *obj; PALETTE_UnrealizeObject( handle ); - if (!(obj = GDI_GetObjPtr( handle, OBJ_PAL ))) return FALSE; - return GDI_FreeObject( handle, obj ); + if (!(obj = free_gdi_handle( handle ))) return FALSE; + return HeapFree( GetProcessHeap(), 0, obj ); } diff --git a/dlls/gdi32/pen.c b/dlls/gdi32/pen.c index 52e6d8cb862..a130b1fdd46 100644 --- a/dlls/gdi32/pen.c +++ b/dlls/gdi32/pen.c @@ -254,10 +254,10 @@ static HGDIOBJ PEN_SelectObject( HGDIOBJ handle, HDC hdc ) */ static BOOL PEN_DeleteObject( HGDIOBJ handle ) { - PENOBJ *pen = GDI_GetObjPtr( handle, 0 ); + PENOBJ *pen = free_gdi_handle( handle ); if (!pen) return FALSE; - return GDI_FreeObject( handle, pen ); + return HeapFree( GetProcessHeap(), 0, pen ); } diff --git a/dlls/gdi32/region.c b/dlls/gdi32/region.c index 92ea70b5e1a..b957bb8c086 100644 --- a/dlls/gdi32/region.c +++ b/dlls/gdi32/region.c @@ -542,11 +542,12 @@ static void REGION_DestroyWineRegion( WINEREGION* pReg ) */ static BOOL REGION_DeleteObject( HGDIOBJ handle ) { - RGNOBJ *rgn = GDI_GetObjPtr( handle, OBJ_REGION ); + RGNOBJ *rgn = free_gdi_handle( handle ); if (!rgn) return FALSE; REGION_DestroyWineRegion( rgn->rgn ); - return GDI_FreeObject( handle, rgn ); + HeapFree( GetProcessHeap(), 0, rgn ); + return TRUE; } /*********************************************************************** @@ -2820,7 +2821,8 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count, if (! (pETEs = HeapAlloc( GetProcessHeap(), 0, sizeof(EdgeTableEntry) * total ))) { REGION_DestroyWineRegion( region ); - GDI_FreeObject( hrgn, obj ); + free_gdi_handle( hrgn ); + HeapFree( GetProcessHeap(), 0, obj ); return 0; } pts = FirstPtBlock.pts; @@ -2911,8 +2913,8 @@ HRGN WINAPI CreatePolyPolygonRgn(const POINT *Pts, const INT *Count, if(!tmpPtBlock) { WARN("Can't alloc tPB\n"); REGION_DestroyWineRegion( region ); - GDI_FreeObject( hrgn, obj ); - HeapFree( GetProcessHeap(), 0, pETEs ); + free_gdi_handle( hrgn ); + HeapFree( GetProcessHeap(), 0, obj ); return 0; } curPtBlock->next = tmpPtBlock;