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_size * sizeof(physDev->handles[0]));
|
||||
}
|
||||
physDev->handles[index] = obj;
|
||||
physDev->handles[index] = get_full_gdi_handle( obj );
|
||||
|
||||
physDev->cur_handles++;
|
||||
if(physDev->cur_handles > physDev->emh->nHandles)
|
||||
|
|
|
@ -304,6 +304,7 @@ extern BOOL WineEngRemoveFontResourceEx(LPCWSTR, DWORD, PVOID) DECLSPEC_HIDDEN;
|
|||
/* gdiobj.c */
|
||||
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 HGDIOBJ get_full_gdi_handle( HGDIOBJ handle ) DECLSPEC_HIDDEN;
|
||||
extern void *GDI_GetObjPtr( HGDIOBJ, WORD ) DECLSPEC_HIDDEN;
|
||||
extern void GDI_ReleaseObj( HGDIOBJ ) 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 */
|
||||
const struct gdi_obj_funcs *funcs; /* type-specific functions */
|
||||
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 selcount; /* number of times the object is selected in a DC */
|
||||
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 int next_gdi_handle;
|
||||
static struct gdi_handle_entry *next_free;
|
||||
static struct gdi_handle_entry *next_unused = gdi_handles;
|
||||
static LONG debug_count;
|
||||
HMODULE gdi32_module = 0;
|
||||
|
||||
static inline HGDIOBJ entry_to_handle( struct gdi_handle_entry *entry )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -681,16 +688,14 @@ static void dump_gdi_objects( void )
|
|||
TRACE( "%u objects:\n", MAX_GDI_HANDLES );
|
||||
|
||||
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)
|
||||
{
|
||||
TRACE( "handle %p FREE\n", entry_to_handle( entry ));
|
||||
continue;
|
||||
}
|
||||
TRACE( "handle %p obj %p type %s selcount %u deleted %u\n",
|
||||
entry_to_handle( entry ), entry->obj, gdi_obj_type( entry->type ),
|
||||
entry->selcount, entry->deleted );
|
||||
else
|
||||
TRACE( "handle %p obj %p type %s selcount %u deleted %u\n",
|
||||
entry_to_handle( entry ), entry->obj, gdi_obj_type( entry->type ),
|
||||
entry->selcount, entry->deleted );
|
||||
}
|
||||
LeaveCriticalSection( &gdi_section );
|
||||
}
|
||||
|
@ -704,23 +709,23 @@ HGDIOBJ alloc_gdi_handle( void *obj, WORD type, const struct gdi_obj_funcs *func
|
|||
{
|
||||
struct gdi_handle_entry *entry;
|
||||
HGDIOBJ ret;
|
||||
int i;
|
||||
|
||||
assert( type ); /* type 0 is reserved to mark free entries */
|
||||
|
||||
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 );
|
||||
|
||||
ERR( "out of GDI object handles, expect a crash\n" );
|
||||
if (TRACE_ON(gdi)) dump_gdi_objects();
|
||||
return 0;
|
||||
|
||||
found:
|
||||
entry = &gdi_handles[i];
|
||||
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" );
|
||||
if (TRACE_ON(gdi)) dump_gdi_objects();
|
||||
return 0;
|
||||
}
|
||||
entry->obj = obj;
|
||||
entry->funcs = funcs;
|
||||
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->system = 0;
|
||||
entry->deleted = 0;
|
||||
next_gdi_handle = i;
|
||||
if (++entry->generation == 0xffff) entry->generation = 1;
|
||||
ret = entry_to_handle( entry );
|
||||
LeaveCriticalSection( &gdi_section );
|
||||
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 );
|
||||
object = entry->obj;
|
||||
entry->type = 0;
|
||||
entry->obj = next_free;
|
||||
next_free = entry;
|
||||
}
|
||||
LeaveCriticalSection( &gdi_section );
|
||||
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
|
||||
*
|
||||
|
@ -779,12 +804,7 @@ void *GDI_GetObjPtr( HGDIOBJ handle, WORD type )
|
|||
if (!type || entry->type == type) ptr = entry->obj;
|
||||
}
|
||||
|
||||
if (!ptr)
|
||||
{
|
||||
LeaveCriticalSection( &gdi_section );
|
||||
WARN( "Invalid handle %p\n", handle );
|
||||
}
|
||||
|
||||
if (!ptr) LeaveCriticalSection( &gdi_section );
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
@ -846,6 +866,8 @@ BOOL WINAPI DeleteObject( HGDIOBJ obj )
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
obj = entry_to_handle( entry ); /* make it a full handle */
|
||||
|
||||
hdcs_head = entry->hdcs;
|
||||
entry->hdcs = NULL;
|
||||
|
||||
|
@ -960,7 +982,11 @@ INT WINAPI GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
|
|||
TRACE("%p %d %p\n", handle, count, buffer );
|
||||
|
||||
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 );
|
||||
|
||||
if (funcs)
|
||||
|
@ -987,7 +1013,11 @@ INT WINAPI GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
|
|||
TRACE("%p %d %p\n", handle, count, buffer );
|
||||
|
||||
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 );
|
||||
|
||||
if (funcs)
|
||||
|
@ -1091,7 +1121,11 @@ HGDIOBJ WINAPI SelectObject( HDC hdc, HGDIOBJ hObj )
|
|||
TRACE( "(%p,%p)\n", hdc, hObj );
|
||||
|
||||
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 );
|
||||
|
||||
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 )
|
||||
{
|
||||
struct gdi_handle_entry *entry;
|
||||
const struct gdi_obj_funcs *funcs = NULL;
|
||||
struct gdi_handle_entry *entry;
|
||||
|
||||
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 );
|
||||
|
||||
if (funcs && funcs->pUnrealizeObject) return funcs->pUnrealizeObject( obj );
|
||||
|
|
|
@ -49,7 +49,7 @@ UINT MFDRV_AddHandle( PHYSDEV dev, HGDIOBJ obj )
|
|||
physDev->handles,
|
||||
physDev->handles_size * sizeof(physDev->handles[0]));
|
||||
}
|
||||
physDev->handles[index] = obj;
|
||||
physDev->handles[index] = get_full_gdi_handle( obj );
|
||||
|
||||
physDev->cur_handles++;
|
||||
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 );
|
||||
|
||||
hpalette = get_full_gdi_handle( hpalette );
|
||||
if (hpalette == GetStockObject(DEFAULT_PALETTE)) return 0;
|
||||
palPtr = GDI_GetObjPtr( hpalette, OBJ_PAL );
|
||||
if (!palPtr) return 0;
|
||||
|
@ -310,6 +311,7 @@ BOOL WINAPI AnimatePalette(
|
|||
{
|
||||
TRACE("%p (%i - %i)\n", hPal, StartIndex,StartIndex+NumEntries);
|
||||
|
||||
hPal = get_full_gdi_handle( hPal );
|
||||
if( hPal != GetStockObject(DEFAULT_PALETTE) )
|
||||
{
|
||||
PALETTEOBJ * palPtr;
|
||||
|
@ -590,6 +592,7 @@ HPALETTE WINAPI GDISelectPalette( HDC hdc, HPALETTE hpal, WORD wBkg)
|
|||
|
||||
TRACE("%p %p\n", hdc, hpal );
|
||||
|
||||
hpal = get_full_gdi_handle( hpal );
|
||||
if (GetObjectType(hpal) != OBJ_PAL)
|
||||
{
|
||||
WARN("invalid selected palette %p\n",hpal);
|
||||
|
|
Loading…
Reference in New Issue