gdi32: Add a generation count in the high word of GDI handles.
This commit is contained in:
parent
29b39020f7
commit
091c342f32
@ -45,7 +45,7 @@ static UINT EMFDRV_AddHandle( PHYSDEV dev, HGDIOBJ obj )
|
|||||||
physDev->handles,
|
physDev->handles,
|
||||||
physDev->handles_size * sizeof(physDev->handles[0]));
|
physDev->handles_size * sizeof(physDev->handles[0]));
|
||||||
}
|
}
|
||||||
physDev->handles[index] = obj;
|
physDev->handles[index] = get_full_gdi_handle( obj );
|
||||||
|
|
||||||
physDev->cur_handles++;
|
physDev->cur_handles++;
|
||||||
if(physDev->cur_handles > physDev->emh->nHandles)
|
if(physDev->cur_handles > physDev->emh->nHandles)
|
||||||
|
@ -304,6 +304,7 @@ extern BOOL WineEngRemoveFontResourceEx(LPCWSTR, DWORD, PVOID) DECLSPEC_HIDDEN;
|
|||||||
/* gdiobj.c */
|
/* gdiobj.c */
|
||||||
extern HGDIOBJ alloc_gdi_handle( void *obj, WORD type, const struct gdi_obj_funcs *funcs ) DECLSPEC_HIDDEN;
|
extern HGDIOBJ alloc_gdi_handle( void *obj, WORD type, const struct gdi_obj_funcs *funcs ) DECLSPEC_HIDDEN;
|
||||||
extern void *free_gdi_handle( HGDIOBJ handle ) DECLSPEC_HIDDEN;
|
extern void *free_gdi_handle( HGDIOBJ handle ) DECLSPEC_HIDDEN;
|
||||||
|
extern HGDIOBJ get_full_gdi_handle( HGDIOBJ handle ) DECLSPEC_HIDDEN;
|
||||||
extern void *GDI_GetObjPtr( HGDIOBJ, WORD ) DECLSPEC_HIDDEN;
|
extern void *GDI_GetObjPtr( HGDIOBJ, WORD ) DECLSPEC_HIDDEN;
|
||||||
extern void GDI_ReleaseObj( HGDIOBJ ) DECLSPEC_HIDDEN;
|
extern void GDI_ReleaseObj( HGDIOBJ ) DECLSPEC_HIDDEN;
|
||||||
extern void GDI_CheckNotLock(void) DECLSPEC_HIDDEN;
|
extern void GDI_CheckNotLock(void) DECLSPEC_HIDDEN;
|
||||||
|
@ -52,6 +52,7 @@ struct gdi_handle_entry
|
|||||||
void *obj; /* pointer to the object-specific data */
|
void *obj; /* pointer to the object-specific data */
|
||||||
const struct gdi_obj_funcs *funcs; /* type-specific functions */
|
const struct gdi_obj_funcs *funcs; /* type-specific functions */
|
||||||
struct hdc_list *hdcs; /* list of HDCs interested in this object */
|
struct hdc_list *hdcs; /* list of HDCs interested in this object */
|
||||||
|
WORD generation; /* generation count for reusing handle values */
|
||||||
WORD type; /* object type (one of the OBJ_* constants) */
|
WORD type; /* object type (one of the OBJ_* constants) */
|
||||||
WORD selcount; /* number of times the object is selected in a DC */
|
WORD selcount; /* number of times the object is selected in a DC */
|
||||||
WORD system : 1; /* system object flag */
|
WORD system : 1; /* system object flag */
|
||||||
@ -59,21 +60,27 @@ struct gdi_handle_entry
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct gdi_handle_entry gdi_handles[MAX_GDI_HANDLES];
|
static struct gdi_handle_entry gdi_handles[MAX_GDI_HANDLES];
|
||||||
static int next_gdi_handle;
|
static struct gdi_handle_entry *next_free;
|
||||||
|
static struct gdi_handle_entry *next_unused = gdi_handles;
|
||||||
static LONG debug_count;
|
static LONG debug_count;
|
||||||
HMODULE gdi32_module = 0;
|
HMODULE gdi32_module = 0;
|
||||||
|
|
||||||
static inline HGDIOBJ entry_to_handle( struct gdi_handle_entry *entry )
|
static inline HGDIOBJ entry_to_handle( struct gdi_handle_entry *entry )
|
||||||
{
|
{
|
||||||
unsigned int idx = entry - gdi_handles + FIRST_GDI_HANDLE;
|
unsigned int idx = entry - gdi_handles + FIRST_GDI_HANDLE;
|
||||||
return ULongToHandle( idx << 2 );
|
return LongToHandle( idx | (entry->generation << 16) );
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct gdi_handle_entry *handle_entry( HGDIOBJ handle )
|
static inline struct gdi_handle_entry *handle_entry( HGDIOBJ handle )
|
||||||
{
|
{
|
||||||
unsigned int idx = (HandleToULong(handle) >> 2) - FIRST_GDI_HANDLE;
|
unsigned int idx = LOWORD(handle) - FIRST_GDI_HANDLE;
|
||||||
|
|
||||||
if (idx < MAX_GDI_HANDLES && gdi_handles[idx].type) return &gdi_handles[idx];
|
if (idx < MAX_GDI_HANDLES && gdi_handles[idx].type)
|
||||||
|
{
|
||||||
|
if (!HIWORD( handle ) || HIWORD( handle ) == gdi_handles[idx].generation)
|
||||||
|
return &gdi_handles[idx];
|
||||||
|
}
|
||||||
|
if (handle) WARN( "invalid handle %p\n", handle );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -681,13 +688,11 @@ static void dump_gdi_objects( void )
|
|||||||
TRACE( "%u objects:\n", MAX_GDI_HANDLES );
|
TRACE( "%u objects:\n", MAX_GDI_HANDLES );
|
||||||
|
|
||||||
EnterCriticalSection( &gdi_section );
|
EnterCriticalSection( &gdi_section );
|
||||||
for (entry = gdi_handles; entry < gdi_handles + MAX_GDI_HANDLES; entry++)
|
for (entry = gdi_handles; entry < next_unused; entry++)
|
||||||
{
|
{
|
||||||
if (!entry->type)
|
if (!entry->type)
|
||||||
{
|
|
||||||
TRACE( "handle %p FREE\n", entry_to_handle( entry ));
|
TRACE( "handle %p FREE\n", entry_to_handle( entry ));
|
||||||
continue;
|
else
|
||||||
}
|
|
||||||
TRACE( "handle %p obj %p type %s selcount %u deleted %u\n",
|
TRACE( "handle %p obj %p type %s selcount %u deleted %u\n",
|
||||||
entry_to_handle( entry ), entry->obj, gdi_obj_type( entry->type ),
|
entry_to_handle( entry ), entry->obj, gdi_obj_type( entry->type ),
|
||||||
entry->selcount, entry->deleted );
|
entry->selcount, entry->deleted );
|
||||||
@ -704,23 +709,23 @@ HGDIOBJ alloc_gdi_handle( void *obj, WORD type, const struct gdi_obj_funcs *func
|
|||||||
{
|
{
|
||||||
struct gdi_handle_entry *entry;
|
struct gdi_handle_entry *entry;
|
||||||
HGDIOBJ ret;
|
HGDIOBJ ret;
|
||||||
int i;
|
|
||||||
|
|
||||||
assert( type ); /* type 0 is reserved to mark free entries */
|
assert( type ); /* type 0 is reserved to mark free entries */
|
||||||
|
|
||||||
EnterCriticalSection( &gdi_section );
|
EnterCriticalSection( &gdi_section );
|
||||||
for (i = next_gdi_handle + 1; i < MAX_GDI_HANDLES; i++)
|
|
||||||
if (!gdi_handles[i].type) goto found;
|
|
||||||
for (i = 0; i <= next_gdi_handle; i++)
|
|
||||||
if (!gdi_handles[i].type) goto found;
|
|
||||||
LeaveCriticalSection( &gdi_section );
|
|
||||||
|
|
||||||
|
entry = next_free;
|
||||||
|
if (entry)
|
||||||
|
next_free = entry->obj;
|
||||||
|
else if (next_unused < gdi_handles + MAX_GDI_HANDLES)
|
||||||
|
entry = next_unused++;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LeaveCriticalSection( &gdi_section );
|
||||||
ERR( "out of GDI object handles, expect a crash\n" );
|
ERR( "out of GDI object handles, expect a crash\n" );
|
||||||
if (TRACE_ON(gdi)) dump_gdi_objects();
|
if (TRACE_ON(gdi)) dump_gdi_objects();
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
found:
|
|
||||||
entry = &gdi_handles[i];
|
|
||||||
entry->obj = obj;
|
entry->obj = obj;
|
||||||
entry->funcs = funcs;
|
entry->funcs = funcs;
|
||||||
entry->hdcs = NULL;
|
entry->hdcs = NULL;
|
||||||
@ -728,7 +733,7 @@ HGDIOBJ alloc_gdi_handle( void *obj, WORD type, const struct gdi_obj_funcs *func
|
|||||||
entry->selcount = 0;
|
entry->selcount = 0;
|
||||||
entry->system = 0;
|
entry->system = 0;
|
||||||
entry->deleted = 0;
|
entry->deleted = 0;
|
||||||
next_gdi_handle = i;
|
if (++entry->generation == 0xffff) entry->generation = 1;
|
||||||
ret = entry_to_handle( entry );
|
ret = entry_to_handle( entry );
|
||||||
LeaveCriticalSection( &gdi_section );
|
LeaveCriticalSection( &gdi_section );
|
||||||
TRACE( "allocated %s %p %u/%u\n", gdi_obj_type(type), ret,
|
TRACE( "allocated %s %p %u/%u\n", gdi_obj_type(type), ret,
|
||||||
@ -754,12 +759,32 @@ void *free_gdi_handle( HGDIOBJ handle )
|
|||||||
InterlockedDecrement( &debug_count ) + 1, MAX_GDI_HANDLES );
|
InterlockedDecrement( &debug_count ) + 1, MAX_GDI_HANDLES );
|
||||||
object = entry->obj;
|
object = entry->obj;
|
||||||
entry->type = 0;
|
entry->type = 0;
|
||||||
|
entry->obj = next_free;
|
||||||
|
next_free = entry;
|
||||||
}
|
}
|
||||||
LeaveCriticalSection( &gdi_section );
|
LeaveCriticalSection( &gdi_section );
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* get_full_gdi_handle
|
||||||
|
*
|
||||||
|
* Return the full GDI handle from a possibly truncated value.
|
||||||
|
*/
|
||||||
|
HGDIOBJ get_full_gdi_handle( HGDIOBJ handle )
|
||||||
|
{
|
||||||
|
struct gdi_handle_entry *entry;
|
||||||
|
|
||||||
|
if (!HIWORD( handle ))
|
||||||
|
{
|
||||||
|
EnterCriticalSection( &gdi_section );
|
||||||
|
if ((entry = handle_entry( handle ))) handle = entry_to_handle( entry );
|
||||||
|
LeaveCriticalSection( &gdi_section );
|
||||||
|
}
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* GDI_GetObjPtr
|
* GDI_GetObjPtr
|
||||||
*
|
*
|
||||||
@ -779,12 +804,7 @@ void *GDI_GetObjPtr( HGDIOBJ handle, WORD type )
|
|||||||
if (!type || entry->type == type) ptr = entry->obj;
|
if (!type || entry->type == type) ptr = entry->obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ptr)
|
if (!ptr) LeaveCriticalSection( &gdi_section );
|
||||||
{
|
|
||||||
LeaveCriticalSection( &gdi_section );
|
|
||||||
WARN( "Invalid handle %p\n", handle );
|
|
||||||
}
|
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -846,6 +866,8 @@ BOOL WINAPI DeleteObject( HGDIOBJ obj )
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
obj = entry_to_handle( entry ); /* make it a full handle */
|
||||||
|
|
||||||
hdcs_head = entry->hdcs;
|
hdcs_head = entry->hdcs;
|
||||||
entry->hdcs = NULL;
|
entry->hdcs = NULL;
|
||||||
|
|
||||||
@ -960,7 +982,11 @@ INT WINAPI GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
|
|||||||
TRACE("%p %d %p\n", handle, count, buffer );
|
TRACE("%p %d %p\n", handle, count, buffer );
|
||||||
|
|
||||||
EnterCriticalSection( &gdi_section );
|
EnterCriticalSection( &gdi_section );
|
||||||
if ((entry = handle_entry( handle ))) funcs = entry->funcs;
|
if ((entry = handle_entry( handle )))
|
||||||
|
{
|
||||||
|
funcs = entry->funcs;
|
||||||
|
handle = entry_to_handle( entry ); /* make it a full handle */
|
||||||
|
}
|
||||||
LeaveCriticalSection( &gdi_section );
|
LeaveCriticalSection( &gdi_section );
|
||||||
|
|
||||||
if (funcs)
|
if (funcs)
|
||||||
@ -987,7 +1013,11 @@ INT WINAPI GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
|
|||||||
TRACE("%p %d %p\n", handle, count, buffer );
|
TRACE("%p %d %p\n", handle, count, buffer );
|
||||||
|
|
||||||
EnterCriticalSection( &gdi_section );
|
EnterCriticalSection( &gdi_section );
|
||||||
if ((entry = handle_entry( handle ))) funcs = entry->funcs;
|
if ((entry = handle_entry( handle )))
|
||||||
|
{
|
||||||
|
funcs = entry->funcs;
|
||||||
|
handle = entry_to_handle( entry ); /* make it a full handle */
|
||||||
|
}
|
||||||
LeaveCriticalSection( &gdi_section );
|
LeaveCriticalSection( &gdi_section );
|
||||||
|
|
||||||
if (funcs)
|
if (funcs)
|
||||||
@ -1091,7 +1121,11 @@ HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ hObj )
|
|||||||
TRACE( "(%p,%p)\n", hdc, hObj );
|
TRACE( "(%p,%p)\n", hdc, hObj );
|
||||||
|
|
||||||
EnterCriticalSection( &gdi_section );
|
EnterCriticalSection( &gdi_section );
|
||||||
if ((entry = handle_entry( hObj ))) funcs = entry->funcs;
|
if ((entry = handle_entry( hObj )))
|
||||||
|
{
|
||||||
|
funcs = entry->funcs;
|
||||||
|
hObj = entry_to_handle( entry ); /* make it a full handle */
|
||||||
|
}
|
||||||
LeaveCriticalSection( &gdi_section );
|
LeaveCriticalSection( &gdi_section );
|
||||||
|
|
||||||
if (funcs && funcs->pSelectObject) return funcs->pSelectObject( hObj, hdc );
|
if (funcs && funcs->pSelectObject) return funcs->pSelectObject( hObj, hdc );
|
||||||
@ -1104,11 +1138,15 @@ HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ hObj )
|
|||||||
*/
|
*/
|
||||||
BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
|
BOOL WINAPI UnrealizeObject( HGDIOBJ obj )
|
||||||
{
|
{
|
||||||
struct gdi_handle_entry *entry;
|
|
||||||
const struct gdi_obj_funcs *funcs = NULL;
|
const struct gdi_obj_funcs *funcs = NULL;
|
||||||
|
struct gdi_handle_entry *entry;
|
||||||
|
|
||||||
EnterCriticalSection( &gdi_section );
|
EnterCriticalSection( &gdi_section );
|
||||||
if ((entry = handle_entry( obj ))) funcs = entry->funcs;
|
if ((entry = handle_entry( obj )))
|
||||||
|
{
|
||||||
|
funcs = entry->funcs;
|
||||||
|
obj = entry_to_handle( entry ); /* make it a full handle */
|
||||||
|
}
|
||||||
LeaveCriticalSection( &gdi_section );
|
LeaveCriticalSection( &gdi_section );
|
||||||
|
|
||||||
if (funcs && funcs->pUnrealizeObject) return funcs->pUnrealizeObject( obj );
|
if (funcs && funcs->pUnrealizeObject) return funcs->pUnrealizeObject( obj );
|
||||||
|
@ -49,7 +49,7 @@ UINT MFDRV_AddHandle( PHYSDEV dev, HGDIOBJ obj )
|
|||||||
physDev->handles,
|
physDev->handles,
|
||||||
physDev->handles_size * sizeof(physDev->handles[0]));
|
physDev->handles_size * sizeof(physDev->handles[0]));
|
||||||
}
|
}
|
||||||
physDev->handles[index] = obj;
|
physDev->handles[index] = get_full_gdi_handle( obj );
|
||||||
|
|
||||||
physDev->cur_handles++;
|
physDev->cur_handles++;
|
||||||
if(physDev->cur_handles > physDev->mh->mtNoObjects)
|
if(physDev->cur_handles > physDev->mh->mtNoObjects)
|
||||||
|
@ -238,6 +238,7 @@ UINT WINAPI SetPaletteEntries(
|
|||||||
|
|
||||||
TRACE("hpal=%p,start=%i,count=%i\n",hpalette,start,count );
|
TRACE("hpal=%p,start=%i,count=%i\n",hpalette,start,count );
|
||||||
|
|
||||||
|
hpalette = get_full_gdi_handle( hpalette );
|
||||||
if (hpalette == GetStockObject(DEFAULT_PALETTE)) return 0;
|
if (hpalette == GetStockObject(DEFAULT_PALETTE)) return 0;
|
||||||
palPtr = GDI_GetObjPtr( hpalette, OBJ_PAL );
|
palPtr = GDI_GetObjPtr( hpalette, OBJ_PAL );
|
||||||
if (!palPtr) return 0;
|
if (!palPtr) return 0;
|
||||||
@ -310,6 +311,7 @@ BOOL WINAPI AnimatePalette(
|
|||||||
{
|
{
|
||||||
TRACE("%p (%i - %i)\n", hPal, StartIndex,StartIndex+NumEntries);
|
TRACE("%p (%i - %i)\n", hPal, StartIndex,StartIndex+NumEntries);
|
||||||
|
|
||||||
|
hPal = get_full_gdi_handle( hPal );
|
||||||
if( hPal != GetStockObject(DEFAULT_PALETTE) )
|
if( hPal != GetStockObject(DEFAULT_PALETTE) )
|
||||||
{
|
{
|
||||||
PALETTEOBJ * palPtr;
|
PALETTEOBJ * palPtr;
|
||||||
@ -590,6 +592,7 @@ HPALETTE WINAPI GDISelectPalette( HDC hdc, HPALETTE hpal, WORD wBkg)
|
|||||||
|
|
||||||
TRACE("%p %p\n", hdc, hpal );
|
TRACE("%p %p\n", hdc, hpal );
|
||||||
|
|
||||||
|
hpal = get_full_gdi_handle( hpal );
|
||||||
if (GetObjectType(hpal) != OBJ_PAL)
|
if (GetObjectType(hpal) != OBJ_PAL)
|
||||||
{
|
{
|
||||||
WARN("invalid selected palette %p\n",hpal);
|
WARN("invalid selected palette %p\n",hpal);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user