Alexandre Julliard : gdi32: Release GDI handles before freeing the object.

Alexandre Julliard julliard at winehq.org
Thu Jan 29 09:14:41 CST 2009


Module: wine
Branch: master
Commit: de831f334c8a2b09a96bc881f8359a6f1c766729
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=de831f334c8a2b09a96bc881f8359a6f1c766729

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Jan 28 18:45:21 2009 +0100

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 520964d..8bb21f2 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 (funcs && funcs->pDeleteBitmap) funcs->pDeleteBitmap( handle );
 
-    if (bmp->funcs && bmp->funcs->pDeleteBitmap)
-        bmp->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 6b0369b..885fe88 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 5b05973..3648f64 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 f77237b..9ca8517 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 2941f2c..409761a 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 f2d3830..e78e496 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 647dcb8..cc87c6e 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 bfa4bdd..ea75ae8 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 8f1c84a..a658440 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 52e6d8c..a130b1f 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 92ea70b..b957bb8 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;




More information about the wine-cvs mailing list