gdi32: Properly manage the driver stack during DC creation and deletion.
This commit is contained in:
parent
174e906aa5
commit
45f191dc2a
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue