Jacek Caban : gdi32: Handle EMF recording clean up in DeleteDC.

Alexandre Julliard julliard at winehq.org
Mon Aug 23 16:24:14 CDT 2021


Module: wine
Branch: master
Commit: 233af3fdbfa49c3a505a0aa0807ad96c3798f52d
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=233af3fdbfa49c3a505a0aa0807ad96c3798f52d

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Mon Aug 23 13:51:23 2021 +0200

gdi32: Handle EMF recording clean up in DeleteDC.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/gdi32/dc.c             |  2 +-
 dlls/gdi32/enhmfdrv/init.c  | 95 +++++++++++++++++++++------------------------
 dlls/gdi32/gdi_private.h    |  1 +
 dlls/gdi32/gdidc.c          |  4 ++
 dlls/gdi32/tests/metafile.c |  1 -
 5 files changed, 50 insertions(+), 53 deletions(-)

diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c
index 2414c41d785..7e9dff645b1 100644
--- a/dlls/gdi32/dc.c
+++ b/dlls/gdi32/dc.c
@@ -402,7 +402,7 @@ static BOOL reset_dc_state( HDC hdc )
     NtGdiSetVirtualResolution( hdc, 0, 0, 0, 0 );
     GDISelectPalette( hdc, GetStockObject( DEFAULT_PALETTE ), FALSE );
     NtGdiSetBoundsRect( hdc, NULL, DCB_DISABLE );
-    AbortPath( hdc );
+    NtGdiAbortPath( hdc );
 
     if (dc->hClipRgn) DeleteObject( dc->hClipRgn );
     if (dc->hMetaRgn) DeleteObject( dc->hMetaRgn );
diff --git a/dlls/gdi32/enhmfdrv/init.c b/dlls/gdi32/enhmfdrv/init.c
index 026583c40b1..03df3d08547 100644
--- a/dlls/gdi32/enhmfdrv/init.c
+++ b/dlls/gdi32/enhmfdrv/init.c
@@ -142,18 +142,24 @@ static const struct gdi_dc_funcs emfdrv_driver =
 static BOOL CDECL EMFDRV_DeleteDC( PHYSDEV dev )
 {
     EMFDRV_PDEVICE *physDev = get_emf_physdev( dev );
-    UINT index;
-
-    HeapFree( GetProcessHeap(), 0, physDev->emh );
-    for(index = 0; index < physDev->handles_size; index++)
-        if(physDev->handles[index])
-	    GDI_hdc_not_using_object(physDev->handles[index], dev->hdc);
-    HeapFree( GetProcessHeap(), 0, physDev->handles );
     HeapFree( GetProcessHeap(), 0, physDev );
     return TRUE;
 }
 
 
+void EMFDC_DeleteDC( DC_ATTR *dc_attr )
+{
+    EMFDRV_PDEVICE *emf = dc_attr->emf;
+    UINT index;
+
+    HeapFree( GetProcessHeap(), 0, emf->emh );
+    for (index = 0; index < emf->handles_size; index++)
+        if (emf->handles[index])
+	    GDI_hdc_not_using_object( emf->handles[index], emf->dev.hdc );
+    HeapFree( GetProcessHeap(), 0, emf->handles );
+}
+
+
 /******************************************************************
  *         EMFDRV_WriteRecord
  *
@@ -440,75 +446,62 @@ HDC WINAPI CreateEnhMetaFileW(
 HENHMETAFILE WINAPI CloseEnhMetaFile(HDC hdc) /* [in] metafile DC */
 {
     HENHMETAFILE hmf;
-    EMFDRV_PDEVICE *physDev;
-    DC *dc;
+    EMFDRV_PDEVICE *emf;
+    DC_ATTR *dc_attr;
     EMREOF emr;
     HANDLE hMapping = 0;
 
     TRACE("(%p)\n", hdc );
 
-    if (!(dc = get_dc_ptr( hdc ))) return NULL;
-    if (GetObjectType( hdc ) != OBJ_ENHMETADC)
-    {
-        release_dc_ptr( dc );
-        return NULL;
-    }
-    if (dc->refcount != 1)
-    {
-        FIXME( "not deleting busy DC %p refcount %u\n", hdc, dc->refcount );
-        release_dc_ptr( dc );
-        return NULL;
-    }
-    physDev = get_emf_physdev( find_dc_driver( dc, &emfdrv_driver ));
+    if (!(dc_attr = get_dc_attr( hdc )) || !dc_attr->emf) return 0;
+    emf = dc_attr->emf;
 
-    if (dc->attr->save_level)
+    if (dc_attr->save_level)
         RestoreDC( hdc, 1 );
 
-    if (physDev->dc_brush) DeleteObject( physDev->dc_brush );
-    if (physDev->dc_pen) DeleteObject( physDev->dc_pen );
+    if (emf->dc_brush) DeleteObject( emf->dc_brush );
+    if (emf->dc_pen) DeleteObject( emf->dc_pen );
 
     emr.emr.iType = EMR_EOF;
     emr.emr.nSize = sizeof(emr);
     emr.nPalEntries = 0;
     emr.offPalEntries = FIELD_OFFSET(EMREOF, nSizeLast);
     emr.nSizeLast = emr.emr.nSize;
-    EMFDRV_WriteRecord( &physDev->dev, &emr.emr );
+    EMFDRV_WriteRecord( &emf->dev, &emr.emr );
 
-    physDev->emh->rclBounds = dc->attr->emf_bounds;
+    emf->emh->rclBounds = dc_attr->emf_bounds;
 
     /* Update rclFrame if not initialized in CreateEnhMetaFile */
-    if(physDev->emh->rclFrame.left > physDev->emh->rclFrame.right) {
-        physDev->emh->rclFrame.left = physDev->emh->rclBounds.left *
-	  physDev->emh->szlMillimeters.cx * 100 / physDev->emh->szlDevice.cx;
-        physDev->emh->rclFrame.top = physDev->emh->rclBounds.top *
-	  physDev->emh->szlMillimeters.cy * 100 / physDev->emh->szlDevice.cy;
-        physDev->emh->rclFrame.right = physDev->emh->rclBounds.right *
-	  physDev->emh->szlMillimeters.cx * 100 / physDev->emh->szlDevice.cx;
-        physDev->emh->rclFrame.bottom = physDev->emh->rclBounds.bottom *
-	  physDev->emh->szlMillimeters.cy * 100 / physDev->emh->szlDevice.cy;
+    if (emf->emh->rclFrame.left > emf->emh->rclFrame.right)
+    {
+        emf->emh->rclFrame.left = emf->emh->rclBounds.left *
+            emf->emh->szlMillimeters.cx * 100 / emf->emh->szlDevice.cx;
+        emf->emh->rclFrame.top = emf->emh->rclBounds.top *
+            emf->emh->szlMillimeters.cy * 100 / emf->emh->szlDevice.cy;
+        emf->emh->rclFrame.right = emf->emh->rclBounds.right *
+            emf->emh->szlMillimeters.cx * 100 / emf->emh->szlDevice.cx;
+        emf->emh->rclFrame.bottom = emf->emh->rclBounds.bottom *
+            emf->emh->szlMillimeters.cy * 100 / emf->emh->szlDevice.cy;
     }
 
-    if (physDev->hFile)  /* disk based metafile */
+    if (emf->hFile)  /* disk based metafile */
     {
-        if (!WriteFile(physDev->hFile, physDev->emh, physDev->emh->nBytes,
-                       NULL, NULL))
+        if (!WriteFile( emf->hFile, emf->emh, emf->emh->nBytes, NULL, NULL ))
         {
-            CloseHandle( physDev->hFile );
-            free_dc_ptr( dc );
+            CloseHandle( emf->hFile );
             return 0;
         }
-	HeapFree( GetProcessHeap(), 0, physDev->emh );
-        hMapping = CreateFileMappingA(physDev->hFile, NULL, PAGE_READONLY, 0,
-				      0, NULL);
-	TRACE("hMapping = %p\n", hMapping );
-	physDev->emh = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
-	TRACE("view = %p\n", physDev->emh );
+        HeapFree( GetProcessHeap(), 0, emf->emh );
+        hMapping = CreateFileMappingA( emf->hFile, NULL, PAGE_READONLY, 0, 0, NULL );
+        TRACE( "hMapping = %p\n", hMapping );
+        emf->emh = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 );
+        TRACE( "view = %p\n", emf->emh );
         CloseHandle( hMapping );
-        CloseHandle( physDev->hFile );
+        CloseHandle( emf->hFile );
     }
 
-    hmf = EMF_Create_HENHMETAFILE( physDev->emh, physDev->emh->nBytes, (physDev->hFile != 0) );
-    physDev->emh = NULL;  /* So it won't be deleted */
-    free_dc_ptr( dc );
+    hmf = EMF_Create_HENHMETAFILE( emf->emh, emf->emh->nBytes, emf->hFile != 0 );
+    emf->emh = NULL;  /* So it won't be deleted */
+    DeleteDC( hdc );
     return hmf;
 }
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index bf7684b53a7..ce89dbc6ff5 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -137,6 +137,7 @@ extern BOOL EMFDC_BeginPath( DC_ATTR *dc_attr ) DECLSPEC_HIDDEN;
 extern BOOL EMFDC_BitBlt( DC_ATTR *dc_attr, INT x_dst, INT y_dst, INT width, INT height,
                           HDC hdc_src, INT x_src, INT y_src, DWORD rop );
 extern BOOL EMFDC_CloseFigure( DC_ATTR *dc_attr ) DECLSPEC_HIDDEN;
+extern void EMFDC_DeleteDC( DC_ATTR *dc_attr ) DECLSPEC_HIDDEN;
 extern BOOL EMFDC_Ellipse( DC_ATTR *dc_attr, INT left, INT top, INT right,
                            INT bottom ) DECLSPEC_HIDDEN;
 extern BOOL EMFDC_EndPath( DC_ATTR *dc_attr ) DECLSPEC_HIDDEN;
diff --git a/dlls/gdi32/gdidc.c b/dlls/gdi32/gdidc.c
index af529fdb8e9..e12dbfeff03 100644
--- a/dlls/gdi32/gdidc.c
+++ b/dlls/gdi32/gdidc.c
@@ -100,7 +100,11 @@ HDC WINAPI CreateICW( const WCHAR *driver, const WCHAR *device, const WCHAR *out
  */
 BOOL WINAPI DeleteDC( HDC hdc )
 {
+    DC_ATTR *dc_attr;
+
     if (is_meta_dc( hdc )) return METADC_DeleteDC( hdc );
+    if (!(dc_attr = get_dc_attr( hdc ))) return FALSE;
+    if (dc_attr->emf) EMFDC_DeleteDC( dc_attr );
     return NtGdiDeleteObjectApp( hdc );
 }
 
diff --git a/dlls/gdi32/tests/metafile.c b/dlls/gdi32/tests/metafile.c
index a7459a05ce0..b3e5e80acd9 100644
--- a/dlls/gdi32/tests/metafile.c
+++ b/dlls/gdi32/tests/metafile.c
@@ -3219,7 +3219,6 @@ static void test_enhmetafile_file(void)
 
     SetLastError(0xdeadbeef);
     metafile = CloseEnhMetaFile(dc);
-    todo_wine
     ok(!metafile && GetLastError() == ERROR_INVALID_HANDLE, "CloseMetaFile returned %p (%u)\n",
        metafile, GetLastError());
 




More information about the wine-cvs mailing list