Use vectored exceptions to get rid of VIRTUAL_SetFaultHandler().
This commit is contained in:
parent
4b9f767845
commit
41c2482984
@ -38,11 +38,25 @@
|
|||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
#include "wingdi.h"
|
#include "wingdi.h"
|
||||||
#include "x11drv.h"
|
#include "x11drv.h"
|
||||||
|
#include "excpt.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
|
WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
|
||||||
WINE_DECLARE_DEBUG_CHANNEL(x11drv);
|
WINE_DECLARE_DEBUG_CHANNEL(x11drv);
|
||||||
|
|
||||||
|
static struct list dibs_list = LIST_INIT(dibs_list);
|
||||||
|
|
||||||
|
static CRITICAL_SECTION dibs_cs;
|
||||||
|
static CRITICAL_SECTION_DEBUG dibs_cs_debug =
|
||||||
|
{
|
||||||
|
0, 0, &dibs_cs,
|
||||||
|
{ &dibs_cs_debug.ProcessLocksList, &dibs_cs_debug.ProcessLocksList },
|
||||||
|
0, 0, { 0, (DWORD)(__FILE__ ": dibs_cs") }
|
||||||
|
};
|
||||||
|
static CRITICAL_SECTION dibs_cs = { &dibs_cs_debug, -1, 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
static PVOID dibs_handler;
|
||||||
|
|
||||||
static int ximageDepthTable[32];
|
static int ximageDepthTable[32];
|
||||||
|
|
||||||
/* This structure holds the arguments for DIB_SetImageBits() */
|
/* This structure holds the arguments for DIB_SetImageBits() */
|
||||||
@ -4102,10 +4116,8 @@ INT X11DRV_GetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan,
|
|||||||
static void X11DRV_DIB_DoProtectDIBSection( X_PHYSBITMAP *physBitmap, DWORD new_prot )
|
static void X11DRV_DIB_DoProtectDIBSection( X_PHYSBITMAP *physBitmap, DWORD new_prot )
|
||||||
{
|
{
|
||||||
DWORD old_prot;
|
DWORD old_prot;
|
||||||
DIBSECTION dib;
|
|
||||||
|
|
||||||
GetObjectW( physBitmap->hbitmap, sizeof(dib), &dib );
|
VirtualProtect(physBitmap->base, physBitmap->size, new_prot, &old_prot);
|
||||||
VirtualProtect(dib.dsBm.bmBits, dib.dsBmih.biSizeImage, new_prot, &old_prot);
|
|
||||||
TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
|
TRACE("Changed protection from %ld to %ld\n", old_prot, new_prot);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4268,22 +4280,43 @@ static void X11DRV_DIB_DoUpdateDIBSection(X_PHYSBITMAP *physBitmap, BOOL toDIB)
|
|||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* X11DRV_DIB_FaultHandler
|
* X11DRV_DIB_FaultHandler
|
||||||
*/
|
*/
|
||||||
static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr )
|
static LONG CALLBACK X11DRV_DIB_FaultHandler( PEXCEPTION_POINTERS ep )
|
||||||
{
|
{
|
||||||
X_PHYSBITMAP *physBitmap = res;
|
X_PHYSBITMAP *physBitmap = NULL;
|
||||||
INT state = X11DRV_DIB_Lock( physBitmap, DIB_Status_None, FALSE );
|
BOOL found = FALSE;
|
||||||
|
const BYTE *addr;
|
||||||
|
struct list *ptr;
|
||||||
|
|
||||||
if (state != DIB_Status_InSync) {
|
if (ep->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
|
||||||
/* no way to tell whether app needs read or write yet,
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
* try read first */
|
|
||||||
X11DRV_DIB_Coerce( physBitmap, DIB_Status_InSync, FALSE );
|
|
||||||
} else {
|
|
||||||
/* hm, apparently the app must have write access */
|
|
||||||
X11DRV_DIB_Coerce( physBitmap, DIB_Status_AppMod, FALSE );
|
|
||||||
}
|
|
||||||
X11DRV_DIB_Unlock( physBitmap, TRUE );
|
|
||||||
|
|
||||||
return TRUE;
|
addr = (const BYTE*)ep->ExceptionRecord->ExceptionInformation[1];
|
||||||
|
|
||||||
|
EnterCriticalSection(&dibs_cs);
|
||||||
|
LIST_FOR_EACH( ptr, &dibs_list )
|
||||||
|
{
|
||||||
|
physBitmap = LIST_ENTRY( ptr, X_PHYSBITMAP, entry );
|
||||||
|
if ((physBitmap->base <= addr) && (addr < physBitmap->base + physBitmap->size))
|
||||||
|
{
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LeaveCriticalSection(&dibs_cs);
|
||||||
|
|
||||||
|
if (!found) return EXCEPTION_CONTINUE_SEARCH;
|
||||||
|
|
||||||
|
X11DRV_DIB_Lock( physBitmap, DIB_Status_None, FALSE );
|
||||||
|
if (ep->ExceptionRecord->ExceptionInformation[0]) {
|
||||||
|
/* the app tried to write the DIB bits */
|
||||||
|
X11DRV_DIB_Coerce( physBitmap, DIB_Status_AppMod, FALSE );
|
||||||
|
} else {
|
||||||
|
/* the app tried to read the DIB bits */
|
||||||
|
X11DRV_DIB_Coerce( physBitmap, DIB_Status_InSync, FALSE );
|
||||||
|
}
|
||||||
|
X11DRV_DIB_Unlock( physBitmap, TRUE );
|
||||||
|
|
||||||
|
return EXCEPTION_CONTINUE_EXECUTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
@ -4566,7 +4599,6 @@ static XImage *X11DRV_XShmCreateImage( int width, int height, int bpp,
|
|||||||
HBITMAP X11DRV_CreateDIBSection( X11DRV_PDEVICE *physDev, HBITMAP hbitmap,
|
HBITMAP X11DRV_CreateDIBSection( X11DRV_PDEVICE *physDev, HBITMAP hbitmap,
|
||||||
const BITMAPINFO *bmi, UINT usage )
|
const BITMAPINFO *bmi, UINT usage )
|
||||||
{
|
{
|
||||||
extern BOOL VIRTUAL_SetFaultHandler(LPCVOID addr, BOOL (*proc)(LPVOID, LPCVOID), LPVOID arg);
|
|
||||||
X_PHYSBITMAP *physBitmap;
|
X_PHYSBITMAP *physBitmap;
|
||||||
DIBSECTION dib;
|
DIBSECTION dib;
|
||||||
|
|
||||||
@ -4602,11 +4634,18 @@ HBITMAP X11DRV_CreateDIBSection( X11DRV_PDEVICE *physDev, HBITMAP hbitmap,
|
|||||||
|
|
||||||
/* install fault handler */
|
/* install fault handler */
|
||||||
InitializeCriticalSection( &physBitmap->lock );
|
InitializeCriticalSection( &physBitmap->lock );
|
||||||
if (VIRTUAL_SetFaultHandler(dib.dsBm.bmBits, X11DRV_DIB_FaultHandler, physBitmap))
|
|
||||||
{
|
physBitmap->base = dib.dsBm.bmBits;
|
||||||
X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
|
physBitmap->size = dib.dsBmih.biSizeImage;
|
||||||
physBitmap->status = DIB_Status_AppMod;
|
physBitmap->status = DIB_Status_AppMod;
|
||||||
}
|
|
||||||
|
if (!dibs_handler)
|
||||||
|
dibs_handler = AddVectoredExceptionHandler( TRUE, X11DRV_DIB_FaultHandler );
|
||||||
|
EnterCriticalSection( &dibs_cs );
|
||||||
|
list_add_head( &dibs_list, &physBitmap->entry );
|
||||||
|
LeaveCriticalSection( &dibs_cs );
|
||||||
|
|
||||||
|
X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE );
|
||||||
|
|
||||||
return hbitmap;
|
return hbitmap;
|
||||||
}
|
}
|
||||||
@ -4616,6 +4655,19 @@ HBITMAP X11DRV_CreateDIBSection( X11DRV_PDEVICE *physDev, HBITMAP hbitmap,
|
|||||||
*/
|
*/
|
||||||
void X11DRV_DIB_DeleteDIBSection(X_PHYSBITMAP *physBitmap, DIBSECTION *dib)
|
void X11DRV_DIB_DeleteDIBSection(X_PHYSBITMAP *physBitmap, DIBSECTION *dib)
|
||||||
{
|
{
|
||||||
|
BOOL last;
|
||||||
|
|
||||||
|
EnterCriticalSection( &dibs_cs );
|
||||||
|
list_remove( &physBitmap->entry );
|
||||||
|
last = list_empty( &dibs_list );
|
||||||
|
LeaveCriticalSection( &dibs_cs );
|
||||||
|
|
||||||
|
if (last)
|
||||||
|
{
|
||||||
|
RemoveVectoredExceptionHandler( dibs_handler );
|
||||||
|
dibs_handler = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (dib->dshSection)
|
if (dib->dshSection)
|
||||||
X11DRV_DIB_Coerce(physBitmap, DIB_Status_InSync, FALSE);
|
X11DRV_DIB_Coerce(physBitmap, DIB_Status_InSync, FALSE);
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@ typedef int Status;
|
|||||||
#include "winuser.h"
|
#include "winuser.h"
|
||||||
#include "ddrawi.h"
|
#include "ddrawi.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
|
#include "wine/list.h"
|
||||||
|
|
||||||
#define MAX_PIXELFORMATS 8
|
#define MAX_PIXELFORMATS 8
|
||||||
|
|
||||||
@ -111,6 +112,9 @@ typedef struct
|
|||||||
#ifdef HAVE_LIBXXSHM
|
#ifdef HAVE_LIBXXSHM
|
||||||
XShmSegmentInfo shminfo; /* shared memory segment info */
|
XShmSegmentInfo shminfo; /* shared memory segment info */
|
||||||
#endif
|
#endif
|
||||||
|
struct list entry; /* Entry in global DIB list */
|
||||||
|
const BYTE *base; /* Base address */
|
||||||
|
SIZE_T size; /* Size in bytes */
|
||||||
} X_PHYSBITMAP;
|
} X_PHYSBITMAP;
|
||||||
|
|
||||||
/* X physical font */
|
/* X physical font */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user