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