From 45f191dc2a754a1bf340dab5675e0b121f515763 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 16 Mar 2011 21:45:39 +0100 Subject: [PATCH] gdi32: Properly manage the driver stack during DC creation and deletion. --- dlls/gdi32/dc.c | 48 ++++++++++++++++++++------------------ dlls/gdi32/driver.c | 18 ++++++++++++-- dlls/gdi32/enhmfdrv/init.c | 29 +++++++++++------------ dlls/gdi32/gdi_private.h | 4 ++-- dlls/gdi32/mfdrv/init.c | 31 ++++++++++++------------ 5 files changed, 72 insertions(+), 58 deletions(-) diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c index c5e513edcfd..8633d0bbad2 100644 --- a/dlls/gdi32/dc.c +++ b/dlls/gdi32/dc.c @@ -71,13 +71,13 @@ static inline DC *get_dc_obj( HDC hdc ) /*********************************************************************** * alloc_dc_ptr */ -DC *alloc_dc_ptr( const DC_FUNCTIONS *funcs, WORD magic ) +DC *alloc_dc_ptr( WORD magic ) { DC *dc; if (!(dc = HeapAlloc( GetProcessHeap(), 0, sizeof(*dc) ))) return NULL; - dc->funcs = funcs; + dc->funcs = &null_driver; dc->nulldrv.funcs = &null_driver; dc->nulldrv.next = NULL; dc->physDev = &dc->nulldrv; @@ -179,6 +179,8 @@ static void free_dc_state( DC *dc ) void free_dc_ptr( DC *dc ) { assert( dc->refcount == 1 ); + + while (dc->physDev != &dc->nulldrv) pop_dc_driver( dc, dc->physDev ); free_gdi_handle( dc->hSelf ); free_dc_state( dc ); } @@ -244,8 +246,9 @@ void update_dc( DC *dc ) * * Push a driver on top of the DC driver stack. */ -void push_dc_driver( DC * dc, PHYSDEV physdev ) +void push_dc_driver( DC * dc, PHYSDEV physdev, const DC_FUNCTIONS *funcs ) { + physdev->funcs = funcs; physdev->next = dc->physDev; physdev->hdc = dc->hSelf; dc->physDev = physdev; @@ -264,6 +267,7 @@ void pop_dc_driver( DC * dc, PHYSDEV physdev ) assert( physdev != &dc->nulldrv ); dc->physDev = physdev->next; dc->funcs = dc->physDev->funcs; + physdev->funcs->pDeleteDC( physdev ); } @@ -618,7 +622,6 @@ HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output, { HDC hdc; DC * dc; - PHYSDEV physdev; const DC_FUNCTIONS *funcs; WCHAR buf[300]; @@ -639,7 +642,7 @@ HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output, ERR( "no driver found for %s\n", debugstr_w(buf) ); return 0; } - if (!(dc = alloc_dc_ptr( funcs, OBJ_DC ))) goto error; + if (!(dc = alloc_dc_ptr( OBJ_DC ))) goto error; hdc = dc->hSelf; dc->hBitmap = GDI_inc_ref_count( GetStockObject( DEFAULT_BITMAP )); @@ -648,16 +651,17 @@ HDC WINAPI CreateDCW( LPCWSTR driver, LPCWSTR device, LPCWSTR output, TRACE("(driver=%s, device=%s, output=%s): returning %p\n", debugstr_w(driver), debugstr_w(device), debugstr_w(output), dc->hSelf ); - if (dc->funcs->pCreateDC && - !dc->funcs->pCreateDC( hdc, &physdev, buf, device, output, initData )) + if (funcs->pCreateDC) { - WARN("creation aborted by device\n" ); - goto error; + PHYSDEV physdev; + if (!funcs->pCreateDC( hdc, &physdev, buf, device, output, initData )) + { + WARN("creation aborted by device\n" ); + goto error; + } + push_dc_driver( dc, physdev, funcs ); } - physdev->funcs = funcs; - push_dc_driver( dc, physdev ); - dc->vis_rect.left = 0; dc->vis_rect.top = 0; dc->vis_rect.right = GetDeviceCaps( hdc, DESKTOPHORZRES ); @@ -750,15 +754,15 @@ HDC WINAPI CreateCompatibleDC( HDC hdc ) if (!(origDC = get_dc_ptr( hdc ))) return 0; if (GetObjectType( hdc ) == OBJ_DC) { - funcs = origDC->funcs; physDev = origDC->physDev; + funcs = physDev->funcs; } release_dc_ptr( origDC ); } if (!funcs && !(funcs = DRIVER_get_display_driver())) return 0; - if (!(dc = alloc_dc_ptr( funcs, OBJ_MEMDC ))) goto error; + if (!(dc = alloc_dc_ptr( OBJ_MEMDC ))) goto error; TRACE("(%p): returning %p\n", hdc, dc->hSelf ); @@ -774,15 +778,15 @@ HDC WINAPI CreateCompatibleDC( HDC hdc ) /* Pass the driver-specific physical device info into * the new DC. The driver may use this read-only info * while creating the compatible DC. */ - if (dc->funcs->pCreateDC && - !dc->funcs->pCreateDC( dc->hSelf, &physDev, NULL, NULL, NULL, NULL )) + if (funcs->pCreateDC) { - WARN("creation aborted by device\n"); - goto error; + if (!funcs->pCreateDC( dc->hSelf, &physDev, NULL, NULL, NULL, NULL )) + { + WARN("creation aborted by device\n"); + goto error; + } + push_dc_driver( dc, physDev, funcs ); } - - physDev->funcs = funcs; - push_dc_driver( dc, physDev ); DC_InitDC( dc ); release_dc_ptr( dc ); return ret; @@ -832,8 +836,6 @@ BOOL WINAPI DeleteDC( HDC hdc ) SelectObject( hdc, GetStockObject(SYSTEM_FONT) ); SelectObject( hdc, GetStockObject(DEFAULT_BITMAP) ); - if (dc->funcs->pDeleteDC) dc->funcs->pDeleteDC(dc->physDev); - dc->physDev = NULL; free_dc_ptr( dc ); return TRUE; } diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c index fa77a2ee481..4b7a16549f4 100644 --- a/dlls/gdi32/driver.c +++ b/dlls/gdi32/driver.c @@ -22,6 +22,7 @@ #include "config.h" #include "wine/port.h" +#include #include #include #include @@ -339,6 +340,13 @@ static BOOL CDECL nulldrv_CreateBitmap( PHYSDEV dev, HBITMAP bitmap, LPVOID bits return TRUE; } +static BOOL CDECL nulldrv_CreateDC( HDC hdc, PHYSDEV *dev, LPCWSTR driver, LPCWSTR device, + LPCWSTR output, const DEVMODEW *devmode ) +{ + assert(0); /* should never be called */ + return FALSE; +} + static HBITMAP CDECL nulldrv_CreateDIBSection( PHYSDEV dev, HBITMAP bitmap, const BITMAPINFO *info, UINT usage ) { @@ -350,6 +358,12 @@ static BOOL CDECL nulldrv_DeleteBitmap( HBITMAP bitmap ) return TRUE; } +static BOOL CDECL nulldrv_DeleteDC( PHYSDEV dev ) +{ + assert(0); /* should never be called */ + return TRUE; +} + static BOOL CDECL nulldrv_DeleteObject( PHYSDEV dev, HGDIOBJ obj ) { return TRUE; @@ -753,10 +767,10 @@ const DC_FUNCTIONS null_driver = nulldrv_Chord, /* pChord */ nulldrv_CloseFigure, /* pCloseFigure */ nulldrv_CreateBitmap, /* pCreateBitmap */ - NULL, /* pCreateDC */ + nulldrv_CreateDC, /* pCreateDC */ nulldrv_CreateDIBSection, /* pCreateDIBSection */ nulldrv_DeleteBitmap, /* pDeleteBitmap */ - NULL, /* pDeleteDC */ + nulldrv_DeleteDC, /* pDeleteDC */ nulldrv_DeleteObject, /* pDeleteObject */ nulldrv_DescribePixelFormat, /* pDescribePixelFormat */ nulldrv_DeviceCapabilities, /* pDeviceCapabilities */ diff --git a/dlls/gdi32/enhmfdrv/init.c b/dlls/gdi32/enhmfdrv/init.c index 1c04d95239c..ac3fa4f3e39 100644 --- a/dlls/gdi32/enhmfdrv/init.c +++ b/dlls/gdi32/enhmfdrv/init.c @@ -32,6 +32,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(enhmetafile); +static BOOL EMFDRV_DeleteDC( PHYSDEV dev ); + static const DC_FUNCTIONS EMFDRV_Funcs = { NULL, /* pAbortDoc */ @@ -49,7 +51,7 @@ static const DC_FUNCTIONS EMFDRV_Funcs = NULL, /* pCreateDC */ NULL, /* pCreateDIBSection */ NULL, /* pDeleteBitmap */ - NULL, /* pDeleteDC */ + EMFDRV_DeleteDC, /* pDeleteDC */ EMFDRV_DeleteObject, /* pDeleteObject */ NULL, /* pDescribePixelFormat */ NULL, /* pDeviceCapabilities */ @@ -160,9 +162,9 @@ static const DC_FUNCTIONS EMFDRV_Funcs = /********************************************************************** * EMFDRV_DeleteDC */ -static BOOL EMFDRV_DeleteDC( DC *dc ) +static BOOL EMFDRV_DeleteDC( PHYSDEV dev ) { - EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dc->physDev; + EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev; UINT index; if (physDev->emh) HeapFree( GetProcessHeap(), 0, physDev->emh ); @@ -171,8 +173,6 @@ static BOOL EMFDRV_DeleteDC( DC *dc ) GDI_hdc_not_using_object(physDev->handles[index], physDev->hdc); HeapFree( GetProcessHeap(), 0, physDev->handles ); HeapFree( GetProcessHeap(), 0, physDev ); - dc->physDev = NULL; - free_dc_ptr( dc ); return TRUE; } @@ -313,17 +313,13 @@ HDC WINAPI CreateEnhMetaFileW( TRACE("%s\n", debugstr_w(filename) ); - if (!(dc = alloc_dc_ptr( &EMFDRV_Funcs, OBJ_ENHMETADC ))) return 0; + if (!(dc = alloc_dc_ptr( OBJ_ENHMETADC ))) return 0; physDev = HeapAlloc(GetProcessHeap(),0,sizeof(*physDev)); if (!physDev) { free_dc_ptr( dc ); return 0; } - physDev->dev.funcs = &EMFDRV_Funcs; - push_dc_driver( dc, &physDev->dev ); - physDev->hdc = dc->hSelf; - if(description) { /* App name\0Title\0\0 */ length = lstrlenW(description); length += lstrlenW(description + length + 1); @@ -338,6 +334,9 @@ HDC WINAPI CreateEnhMetaFileW( return 0; } + push_dc_driver( dc, &physDev->dev, &EMFDRV_Funcs ); + physDev->hdc = dc->hSelf; + physDev->handles = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, HANDLE_LIST_INC * sizeof(physDev->handles[0])); physDev->handles_size = HANDLE_LIST_INC; physDev->cur_handles = 1; @@ -407,11 +406,11 @@ HDC WINAPI CreateEnhMetaFileW( { if ((hFile = CreateFileW(filename, GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) { - EMFDRV_DeleteDC( dc ); + free_dc_ptr( dc ); return 0; } if (!WriteFile( hFile, physDev->emh, size, NULL, NULL )) { - EMFDRV_DeleteDC( dc ); + free_dc_ptr( dc ); return 0; } physDev->hFile = hFile; @@ -484,7 +483,7 @@ HENHMETAFILE WINAPI CloseEnhMetaFile(HDC hdc) /* [in] metafile DC */ if (SetFilePointer(physDev->hFile, 0, NULL, FILE_BEGIN) != 0) { CloseHandle( physDev->hFile ); - EMFDRV_DeleteDC( dc ); + free_dc_ptr( dc ); return 0; } @@ -492,7 +491,7 @@ HENHMETAFILE WINAPI CloseEnhMetaFile(HDC hdc) /* [in] metafile DC */ NULL, NULL)) { CloseHandle( physDev->hFile ); - EMFDRV_DeleteDC( dc ); + free_dc_ptr( dc ); return 0; } HeapFree( GetProcessHeap(), 0, physDev->emh ); @@ -507,6 +506,6 @@ HENHMETAFILE WINAPI CloseEnhMetaFile(HDC hdc) /* [in] metafile DC */ hmf = EMF_Create_HENHMETAFILE( physDev->emh, (physDev->hFile != 0) ); physDev->emh = NULL; /* So it won't be deleted */ - EMFDRV_DeleteDC( dc ); + free_dc_ptr( dc ); return hmf; } diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index 2dd1569f833..9db7c3291f0 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -374,12 +374,12 @@ extern INT BITMAP_GetWidthBytes( INT bmWidth, INT bpp ) DECLSPEC_HIDDEN; extern void CLIPPING_UpdateGCRegion( DC * dc ) DECLSPEC_HIDDEN; /* dc.c */ -extern DC *alloc_dc_ptr( const DC_FUNCTIONS *funcs, WORD magic ) DECLSPEC_HIDDEN; +extern DC *alloc_dc_ptr( WORD magic ) DECLSPEC_HIDDEN; extern void free_dc_ptr( DC *dc ) DECLSPEC_HIDDEN; extern DC *get_dc_ptr( HDC hdc ) DECLSPEC_HIDDEN; extern void release_dc_ptr( DC *dc ) DECLSPEC_HIDDEN; extern void update_dc( DC *dc ) DECLSPEC_HIDDEN; -extern void push_dc_driver( DC * dc, PHYSDEV physdev ) DECLSPEC_HIDDEN; +extern void push_dc_driver( DC * dc, PHYSDEV physdev, const DC_FUNCTIONS *funcs ) DECLSPEC_HIDDEN; extern void pop_dc_driver( DC * dc, PHYSDEV physdev ) DECLSPEC_HIDDEN; extern void DC_InitDC( DC * dc ) DECLSPEC_HIDDEN; extern void DC_UpdateXforms( DC * dc ) DECLSPEC_HIDDEN; diff --git a/dlls/gdi32/mfdrv/init.c b/dlls/gdi32/mfdrv/init.c index 63f067fc302..03af2e8885a 100644 --- a/dlls/gdi32/mfdrv/init.c +++ b/dlls/gdi32/mfdrv/init.c @@ -30,6 +30,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(metafile); +static BOOL MFDRV_DeleteDC( PHYSDEV dev ); + static const DC_FUNCTIONS MFDRV_Funcs = { NULL, /* pAbortDoc */ @@ -47,7 +49,7 @@ static const DC_FUNCTIONS MFDRV_Funcs = NULL, /* pCreateDC */ NULL, /* pCreateDIBSection */ NULL, /* pDeleteBitmap */ - NULL, /* pDeleteDC */ + MFDRV_DeleteDC, /* pDeleteDC */ MFDRV_DeleteObject, /* pDeleteObject */ NULL, /* pDescribePixelFormat */ NULL, /* pDeviceCapabilities */ @@ -164,7 +166,7 @@ static DC *MFDRV_AllocMetaFile(void) DC *dc; METAFILEDRV_PDEVICE *physDev; - if (!(dc = alloc_dc_ptr( &MFDRV_Funcs, OBJ_METADC ))) return NULL; + if (!(dc = alloc_dc_ptr( OBJ_METADC ))) return NULL; physDev = HeapAlloc(GetProcessHeap(),0,sizeof(*physDev)); if (!physDev) @@ -172,10 +174,6 @@ static DC *MFDRV_AllocMetaFile(void) free_dc_ptr( dc ); return NULL; } - physDev->dev.funcs = &MFDRV_Funcs; - push_dc_driver( dc, &physDev->dev ); - physDev->hdc = dc->hSelf; - if (!(physDev->mh = HeapAlloc( GetProcessHeap(), 0, sizeof(*physDev->mh) ))) { HeapFree( GetProcessHeap(), 0, physDev ); @@ -183,6 +181,9 @@ static DC *MFDRV_AllocMetaFile(void) return NULL; } + push_dc_driver( dc, &physDev->dev, &MFDRV_Funcs ); + physDev->hdc = dc->hSelf; + physDev->handles = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, HANDLE_LIST_INC * sizeof(physDev->handles[0])); physDev->handles_size = HANDLE_LIST_INC; physDev->cur_handles = 0; @@ -205,9 +206,9 @@ static DC *MFDRV_AllocMetaFile(void) /********************************************************************** * MFDRV_DeleteDC */ -static BOOL MFDRV_DeleteDC( DC *dc ) +static BOOL MFDRV_DeleteDC( PHYSDEV dev ) { - METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev; + METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev; DWORD index; HeapFree( GetProcessHeap(), 0, physDev->mh ); @@ -216,8 +217,6 @@ static BOOL MFDRV_DeleteDC( DC *dc ) GDI_hdc_not_using_object(physDev->handles[index], physDev->hdc); HeapFree( GetProcessHeap(), 0, physDev->handles ); HeapFree( GetProcessHeap(), 0, physDev ); - dc->physDev = NULL; - free_dc_ptr( dc ); return TRUE; } @@ -251,12 +250,12 @@ HDC WINAPI CreateMetaFileW( LPCWSTR filename ) physDev->mh->mtType = METAFILE_DISK; if ((hFile = CreateFileW(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) { - MFDRV_DeleteDC( dc ); + free_dc_ptr( dc ); return 0; } if (!WriteFile( hFile, physDev->mh, sizeof(*physDev->mh), NULL, NULL )) { - MFDRV_DeleteDC( dc ); + free_dc_ptr( dc ); return 0; } physDev->hFile = hFile; @@ -328,21 +327,21 @@ static DC *MFDRV_CloseMetaFile( HDC hdc ) if (!MFDRV_MetaParam0(dc->physDev, META_EOF)) { - MFDRV_DeleteDC( dc ); + free_dc_ptr( dc ); return 0; } if (physDev->mh->mtType == METAFILE_DISK) /* disk based metafile */ { if (SetFilePointer(physDev->hFile, 0, NULL, FILE_BEGIN) != 0) { - MFDRV_DeleteDC( dc ); + free_dc_ptr( dc ); return 0; } physDev->mh->mtType = METAFILE_MEMORY; /* This is what windows does */ if (!WriteFile(physDev->hFile, physDev->mh, sizeof(*physDev->mh), NULL, NULL)) { - MFDRV_DeleteDC( dc ); + free_dc_ptr( dc ); return 0; } CloseHandle(physDev->hFile); @@ -377,7 +376,7 @@ HMETAFILE WINAPI CloseMetaFile(HDC hdc) hmf = MF_Create_HMETAFILE( physDev->mh ); physDev->mh = NULL; /* So it won't be deleted */ - MFDRV_DeleteDC( dc ); + free_dc_ptr( dc ); return hmf; }