From 233af3fdbfa49c3a505a0aa0807ad96c3798f52d Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Mon, 23 Aug 2021 13:51:23 +0200 Subject: [PATCH] gdi32: Handle EMF recording clean up in DeleteDC. Signed-off-by: Jacek Caban Signed-off-by: Huw Davies Signed-off-by: Alexandre Julliard --- 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());