On Sun, Apr 17, 2005 at 08:44:57AM -0500, Rob Shearman wrote:
Why don't you free area here?
Details, details. But if you insist ... :)
Index: dlls/ntdll/ntdll.spec =================================================================== RCS file: /var/cvs/wine/dlls/ntdll/ntdll.spec,v retrieving revision 1.175 diff -u -p -r1.175 ntdll.spec --- dlls/ntdll/ntdll.spec 30 Mar 2005 10:22:51 -0000 1.175 +++ dlls/ntdll/ntdll.spec 17 Apr 2005 04:18:44 -0000 @@ -1035,4 +1035,3 @@ @ cdecl MODULE_DllThreadAttach(ptr) @ cdecl MODULE_GetLoadOrderW(ptr wstr wstr) @ cdecl VERSION_Init(wstr) -@ cdecl VIRTUAL_SetFaultHandler(ptr ptr ptr) Index: dlls/ntdll/virtual.c =================================================================== RCS file: /var/cvs/wine/dlls/ntdll/virtual.c,v retrieving revision 1.46 diff -u -p -r1.46 virtual.c --- dlls/ntdll/virtual.c 22 Feb 2005 19:33:50 -0000 1.46 +++ dlls/ntdll/virtual.c 17 Apr 2005 04:20:14 -0000 @@ -1098,25 +1104,6 @@ void virtual_init(void)
/*********************************************************************** - * VIRTUAL_SetFaultHandler - */ -BOOL VIRTUAL_SetFaultHandler( LPCVOID addr, HANDLERPROC proc, LPVOID arg ) -{ - FILE_VIEW *view; - BOOL ret = FALSE; - - RtlEnterCriticalSection( &csVirtual ); - if ((view = VIRTUAL_FindView( addr ))) - { - view->handlerProc = proc; - view->handlerArg = arg; - ret = TRUE; - } - RtlLeaveCriticalSection( &csVirtual ); - return ret; -} - -/*********************************************************************** * VIRTUAL_HandleFault */ DWORD VIRTUAL_HandleFault( LPCVOID addr ) Index: dlls/x11drv/dib.c =================================================================== RCS file: /var/cvs/wine/dlls/x11drv/dib.c,v retrieving revision 1.35 diff -u -p -r1.35 dib.c --- dlls/x11drv/dib.c 14 Apr 2005 12:48:31 -0000 1.35 +++ dlls/x11drv/dib.c 17 Apr 2005 15:10:03 -0000 @@ -38,11 +38,32 @@ #include "winbase.h" #include "wingdi.h" #include "x11drv.h" +#include "excpt.h" +#include "wine/list.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(bitmap); WINE_DECLARE_DEBUG_CHANNEL(x11drv);
+struct mem_area +{ + struct list entry; /* Entry in global mem area list */ + const void *base; /* Base address */ + UINT size; /* Size in bytes */ + void *data; /* Data associated with this area */ +}; + +static struct list mem_areas_list = LIST_INIT(mem_areas_list); + +static CRITICAL_SECTION csMemAreas; +static CRITICAL_SECTION_DEBUG csMemAreas_debug = +{ + 0, 0, &csMemAreas, + { &csMemAreas_debug.ProcessLocksList, &csMemAreas_debug.ProcessLocksList }, + 0, 0, { 0, (DWORD)(__FILE__ ": csMemAreas") } +}; +static CRITICAL_SECTION csMemAreas = { &csMemAreas_debug, -1, 0, 0, 0, 0 }; + static int ximageDepthTable[32];
/* This structure holds the arguments for DIB_SetImageBits() */ @@ -88,6 +109,89 @@ static INT X11DRV_DIB_Coerce(X_PHYSBITMA static INT X11DRV_DIB_Lock(X_PHYSBITMAP *,INT,BOOL); static void X11DRV_DIB_Unlock(X_PHYSBITMAP *,BOOL);
+/*********************************************************************** + * mem_area_find + * + * Find the memory area containing a given address. + * The csMemAreas section must be held by caller. + * + * PARAMS + * addr [I] Address + * + * RETURNS + * Success: area + * Failure: NULL + */ +static struct mem_area *mem_area_find( const void *addr ) +{ + struct list *ptr; + + LIST_FOR_EACH( ptr, &mem_areas_list ) + { + struct mem_area *area = LIST_ENTRY( ptr, struct mem_area, entry ); + if (area->base > addr) break; + if ((const char*)addr < (const char*)area->base + area->size) return area; + } + return NULL; +} + +/*********************************************************************** + * mem_area_add + * + * Adds a memory area to the list. + * + * PARAMS + * base [I] Beginning address of the area + * size [I] Size of the area + * data [I] Data associated with the area + * + */ +static struct mem_area *mem_area_add( const void *base, UINT size, void *data ) +{ + struct mem_area *area; + + area = HeapAlloc(GetProcessHeap(), 0, sizeof(*area)); + if (!area) return NULL; + + area->base = base; + area->size = size; + area->data = data; + + EnterCriticalSection( &csMemAreas ); + list_add_head( &mem_areas_list, &area->entry ); + LeaveCriticalSection( &csMemAreas ); + + return area; +} + + +/*********************************************************************** + * mem_area_del + * + * Removes a memory area from the list. + * + * PARAMS + * addr [I] Address + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +static BOOL mem_area_del( const void *addr ) +{ + struct mem_area *area; + + EnterCriticalSection( &csMemAreas ); + area = mem_area_find( addr ); + if (area) list_remove( &area->entry ); + LeaveCriticalSection( &csMemAreas ); + + HeapFree(GetProcessHeap(), 0, area); + + return area != NULL; +} + + /* Some of the following helper functions are duplicated in dlls/gdi/dib.c @@ -4268,22 +4372,34 @@ static void X11DRV_DIB_DoUpdateDIBSectio /*********************************************************************** * X11DRV_DIB_FaultHandler */ -static BOOL X11DRV_DIB_FaultHandler( LPVOID res, LPCVOID addr ) +LONG CALLBACK X11DRV_DIB_FaultHandler( PEXCEPTION_POINTERS ep ) { - X_PHYSBITMAP *physBitmap = res; - INT state = X11DRV_DIB_Lock( physBitmap, DIB_Status_None, FALSE ); + struct mem_area *area; + X_PHYSBITMAP *physBitmap; + INT state;
- if (state != DIB_Status_InSync) { - /* no way to tell whether app needs read or write yet, - * 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 ); + if (ep->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) + return EXCEPTION_CONTINUE_SEARCH;
- return TRUE; + EnterCriticalSection(&csMemAreas); + area = mem_area_find(ep->ExceptionRecord->ExceptionAddress); + if (area) physBitmap = (X_PHYSBITMAP *)area->data; + else physBitmap = NULL; + LeaveCriticalSection(&csMemAreas); + + if (!physBitmap) return EXCEPTION_CONTINUE_SEARCH; + + state = X11DRV_DIB_Lock( physBitmap, DIB_Status_None, FALSE ); + if (state != DIB_Status_InSync) { + /* no way to tell whether app needs read or write yet, 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 EXCEPTION_CONTINUE_EXECUTION; }
/*********************************************************************** @@ -4566,7 +4682,6 @@ static XImage *X11DRV_XShmCreateImage( i HBITMAP X11DRV_CreateDIBSection( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, const BITMAPINFO *bmi, UINT usage ) { - extern BOOL VIRTUAL_SetFaultHandler(LPCVOID addr, BOOL (*proc)(LPVOID, LPCVOID), LPVOID arg); X_PHYSBITMAP *physBitmap; DIBSECTION dib;
@@ -4602,7 +4717,7 @@ HBITMAP X11DRV_CreateDIBSection( X11DRV_
/* install fault handler */ InitializeCriticalSection( &physBitmap->lock ); - if (VIRTUAL_SetFaultHandler(dib.dsBm.bmBits, X11DRV_DIB_FaultHandler, physBitmap)) + if (mem_area_add(dib.dsBm.bmBits, dib.dsBmih.biSize, physBitmap)) { X11DRV_DIB_DoProtectDIBSection( physBitmap, PAGE_READWRITE ); physBitmap->status = DIB_Status_AppMod; @@ -4616,6 +4731,8 @@ HBITMAP X11DRV_CreateDIBSection( X11DRV_ */ void X11DRV_DIB_DeleteDIBSection(X_PHYSBITMAP *physBitmap, DIBSECTION *dib) { + mem_area_del(dib->dsBm.bmBits); + if (dib->dshSection) X11DRV_DIB_Coerce(physBitmap, DIB_Status_InSync, FALSE);
Index: dlls/x11drv/x11drv.h =================================================================== RCS file: /var/cvs/wine/dlls/x11drv/x11drv.h,v retrieving revision 1.69 diff -u -p -r1.69 x11drv.h --- dlls/x11drv/x11drv.h 14 Apr 2005 12:48:11 -0000 1.69 +++ dlls/x11drv/x11drv.h 17 Apr 2005 03:42:32 -0000 @@ -234,6 +234,7 @@ extern BOOL X11DRV_SwapBuffers(X11DRV_PD extern void X11DRV_BITMAP_Init(void); extern void X11DRV_FONT_Init( int log_pixels_x, int log_pixels_y );
+extern LONG CALLBACK X11DRV_DIB_FaultHandler( PEXCEPTION_POINTERS ep ); extern int X11DRV_DIB_BitmapInfoSize( const BITMAPINFO * info, WORD coloruse ); extern XImage *X11DRV_DIB_CreateXImage( int width, int height, int depth ); extern HGLOBAL X11DRV_DIB_CreateDIBFromBitmap(HDC hdc, HBITMAP hBmp); Index: dlls/x11drv/x11drv_main.c =================================================================== RCS file: /var/cvs/wine/dlls/x11drv/x11drv_main.c,v retrieving revision 1.102 diff -u -p -r1.102 x11drv_main.c --- dlls/x11drv/x11drv_main.c 14 Apr 2005 12:48:11 -0000 1.102 +++ dlls/x11drv/x11drv_main.c 16 Apr 2005 16:59:03 -0000 @@ -362,6 +362,9 @@ static BOOL process_attach(void) using_wine_desktop = 1; }
+ /* initialize DIB handling */ + AddVectoredExceptionHandler( TRUE, X11DRV_DIB_FaultHandler ); + /* initialize GDI */ X11DRV_GDI_Initialize( display );
@@ -422,6 +425,9 @@ static void process_detach(void) /* cleanup GDI */ X11DRV_GDI_Finalize();
+ /* cleanup DIB handling */ + RemoveVectoredExceptionHandler( X11DRV_DIB_FaultHandler ); + DeleteCriticalSection( &X11DRV_CritSection ); }