gdi32: Properly manage the driver stack during DC creation and deletion.

This commit is contained in:
Alexandre Julliard 2011-03-16 21:45:39 +01:00
parent 174e906aa5
commit 45f191dc2a
5 changed files with 72 additions and 58 deletions

View File

@ -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,15 +651,16 @@ 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)
{
PHYSDEV physdev;
if (!funcs->pCreateDC( hdc, &physdev, buf, device, output, initData ))
{
WARN("creation aborted by device\n" );
goto error;
}
physdev->funcs = funcs;
push_dc_driver( dc, physdev );
push_dc_driver( dc, physdev, funcs );
}
dc->vis_rect.left = 0;
dc->vis_rect.top = 0;
@ -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)
{
if (!funcs->pCreateDC( dc->hSelf, &physDev, NULL, NULL, NULL, NULL ))
{
WARN("creation aborted by device\n");
goto error;
}
physDev->funcs = funcs;
push_dc_driver( dc, physDev );
push_dc_driver( dc, physDev, funcs );
}
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;
}

View File

@ -22,6 +22,7 @@
#include "config.h"
#include "wine/port.h"
#include <assert.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
@ -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 */

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}