Commit f89aaa65 authored by Alexandre Julliard's avatar Alexandre Julliard

user32: Store 32-bit and 16-bit cursors/icons in independent structures.

parent 08b83254
......@@ -2671,29 +2671,11 @@ HWND create_window16( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE instance,
/***********************************************************************
* cursor/icon handles
* free_icon_param
*/
static HICON alloc_icon_handle( unsigned int size )
{
HGLOBAL16 handle = GlobalAlloc16( GMEM_MOVEABLE, size );
FarSetOwner16( handle, 0 );
return (HICON)(ULONG_PTR)handle;
}
static struct tagCURSORICONINFO *get_icon_ptr( HICON handle )
{
return GlobalLock16( LOWORD(handle) );
}
static void release_icon_ptr( HICON handle, struct tagCURSORICONINFO *ptr )
{
GlobalUnlock16( LOWORD(handle) );
}
static int free_icon_handle( HICON handle )
static void free_icon_param( ULONG_PTR param )
{
return GlobalFree16( LOWORD(handle) );
GlobalFree16( LOWORD(param) );
}
......@@ -2712,10 +2694,7 @@ void register_wow_handlers(void)
create_window16,
call_window_proc_Ato16,
call_dialog_proc_Ato16,
alloc_icon_handle,
get_icon_ptr,
release_icon_ptr,
free_icon_handle
free_icon_param
};
UserRegisterWowHandlers( &handlers16, &wow_handlers32 );
......
......@@ -269,7 +269,10 @@ static const WORD ICON_HOTSPOT = 0x4242;
static HICON16 alloc_icon_handle( unsigned int size )
{
HGLOBAL16 handle = GlobalAlloc16( GMEM_MOVEABLE, size );
HGLOBAL16 handle = GlobalAlloc16( GMEM_MOVEABLE, size + sizeof(ULONG_PTR) );
char *ptr = GlobalLock16( handle );
memset( ptr + size, 0, sizeof(ULONG_PTR) );
GlobalUnlock16( handle );
FarSetOwner16( handle, 0 );
return handle;
}
......@@ -284,19 +287,125 @@ static void release_icon_ptr( HICON16 handle, CURSORICONINFO *ptr )
GlobalUnlock16( handle );
}
static HICON store_icon_32( HICON16 icon16, HICON icon )
{
HICON ret = 0;
CURSORICONINFO *ptr = get_icon_ptr( icon16 );
if (ptr)
{
unsigned int and_size = ptr->nHeight * get_bitmap_width_bytes( ptr->nWidth, 1 );
unsigned int xor_size = ptr->nHeight * get_bitmap_width_bytes( ptr->nWidth, ptr->bBitsPerPixel );
if (GlobalSize16( icon16 ) >= sizeof(*ptr) + sizeof(ULONG_PTR) + and_size + xor_size )
{
memcpy( &ret, (char *)(ptr + 1) + and_size + xor_size, sizeof(ret) );
memcpy( (char *)(ptr + 1) + and_size + xor_size, &icon, sizeof(icon) );
wow_handlers32.set_icon_param( icon, icon16 );
}
release_icon_ptr( icon16, ptr );
}
return ret;
}
static int free_icon_handle( HICON16 handle )
{
HICON icon32;
if ((icon32 = store_icon_32( handle, 0 ))) DestroyIcon( icon32 );
return GlobalFree16( handle );
}
/* retrieve the 32-bit counterpart of a 16-bit icon, creating it if needed */
HICON get_icon_32( HICON16 icon16 )
{
return (HICON)(ULONG_PTR)icon16;
HICON ret = 0;
CURSORICONINFO *ptr = get_icon_ptr( icon16 );
if (ptr)
{
unsigned int and_size = ptr->nHeight * get_bitmap_width_bytes( ptr->nWidth, 1 );
unsigned int xor_size = ptr->nHeight * get_bitmap_width_bytes( ptr->nWidth, ptr->bBitsPerPixel );
if (GlobalSize16( icon16 ) >= sizeof(*ptr) + sizeof(ULONG_PTR) + xor_size + and_size )
{
memcpy( &ret, (char *)(ptr + 1) + xor_size + and_size, sizeof(ret) );
if (!ret)
{
ICONINFO iinfo;
iinfo.fIcon = (ptr->ptHotSpot.x == ICON_HOTSPOT) && (ptr->ptHotSpot.y == ICON_HOTSPOT);
iinfo.xHotspot = ptr->ptHotSpot.x;
iinfo.yHotspot = ptr->ptHotSpot.y;
iinfo.hbmMask = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1, ptr + 1 );
iinfo.hbmColor = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes, ptr->bBitsPerPixel,
(char *)(ptr + 1) + and_size );
ret = CreateIconIndirect( &iinfo );
DeleteObject( iinfo.hbmMask );
DeleteObject( iinfo.hbmColor );
memcpy( (char *)(ptr + 1) + xor_size + and_size, &ret, sizeof(ret) );
wow_handlers32.set_icon_param( ret, icon16 );
}
}
release_icon_ptr( icon16, ptr );
}
return ret;
}
/* retrieve the 16-bit counterpart of a 32-bit icon, creating it if needed */
HICON16 get_icon_16( HICON icon )
{
return LOWORD( icon );
HICON16 ret = wow_handlers32.get_icon_param( icon );
if (!ret)
{
ICONINFO info;
BITMAP bm;
UINT and_size, xor_size;
void *xor_bits = NULL, *and_bits;
CURSORICONINFO cinfo;
if (!(GetIconInfo( icon, &info ))) return 0;
GetObjectW( info.hbmMask, sizeof(bm), &bm );
and_size = bm.bmHeight * bm.bmWidthBytes;
if (!(and_bits = HeapAlloc( GetProcessHeap(), 0, and_size ))) goto done;
GetBitmapBits( info.hbmMask, and_size, and_bits );
if (info.hbmColor)
{
GetObjectW( info.hbmColor, sizeof(bm), &bm );
xor_size = bm.bmHeight * bm.bmWidthBytes;
if (!(xor_bits = HeapAlloc( GetProcessHeap(), 0, xor_size ))) goto done;
GetBitmapBits( info.hbmColor, xor_size, xor_bits );
}
else
{
bm.bmHeight /= 2;
xor_bits = (char *)and_bits + and_size / 2;
}
if (!info.fIcon)
{
cinfo.ptHotSpot.x = info.xHotspot;
cinfo.ptHotSpot.y = info.yHotspot;
}
else cinfo.ptHotSpot.x = cinfo.ptHotSpot.y = ICON_HOTSPOT;
cinfo.nWidth = bm.bmWidth;
cinfo.nHeight = bm.bmHeight;
cinfo.nWidthBytes = bm.bmWidthBytes;
cinfo.bPlanes = bm.bmPlanes;
cinfo.bBitsPerPixel = bm.bmBitsPixel;
if ((ret = CreateCursorIconIndirect16( 0, &cinfo, and_bits, xor_bits )))
store_icon_32( ret, icon );
done:
if (info.hbmColor)
{
HeapFree( GetProcessHeap(), 0, xor_bits );
DeleteObject( info.hbmColor );
}
HeapFree( GetProcessHeap(), 0, and_bits );
DeleteObject( info.hbmMask );
}
return ret;
}
static void add_shared_icon( HINSTANCE16 inst, HRSRC16 rsrc, HRSRC16 group, HICON16 icon )
......
......@@ -46,10 +46,7 @@ struct wow_handlers16
HWND (*create_window)(CREATESTRUCTW*,LPCWSTR,HINSTANCE,BOOL);
LRESULT (*call_window_proc)(HWND,UINT,WPARAM,LPARAM,LRESULT*,void*);
LRESULT (*call_dialog_proc)(HWND,UINT,WPARAM,LPARAM,LRESULT*,void*);
HICON (*alloc_icon_handle)(UINT);
struct tagCURSORICONINFO *(*get_icon_ptr)(HICON);
void (*release_icon_ptr)(HICON,struct tagCURSORICONINFO*);
int (*free_icon_handle)(HICON);
void (*free_icon_param)(ULONG_PTR);
};
struct wow_handlers32
......@@ -67,6 +64,8 @@ struct wow_handlers32
WNDPROC (*alloc_winproc)(WNDPROC,BOOL);
struct tagDIALOGINFO *(*get_dialog_info)(HWND,BOOL);
INT (*dialog_box_loop)(HWND,HWND);
ULONG_PTR (*get_icon_param)(HICON);
ULONG_PTR (*set_icon_param)(HICON,ULONG_PTR);
};
extern struct wow_handlers32 wow_handlers32 DECLSPEC_HIDDEN;
......
......@@ -100,10 +100,7 @@ struct wow_handlers16
HWND (*create_window)(CREATESTRUCTW*,LPCWSTR,HINSTANCE,BOOL);
LRESULT (*call_window_proc)(HWND,UINT,WPARAM,LPARAM,LRESULT*,void*);
LRESULT (*call_dialog_proc)(HWND,UINT,WPARAM,LPARAM,LRESULT*,void*);
HICON (*alloc_icon_handle)(UINT);
struct tagCURSORICONINFO *(*get_icon_ptr)(HICON);
void (*release_icon_ptr)(HICON,struct tagCURSORICONINFO*);
int (*free_icon_handle)(HICON);
void (*free_icon_param)(ULONG_PTR);
};
struct wow_handlers32
......@@ -121,6 +118,8 @@ struct wow_handlers32
WNDPROC (*alloc_winproc)(WNDPROC,BOOL);
struct tagDIALOGINFO *(*get_dialog_info)(HWND,BOOL);
INT (*dialog_box_loop)(HWND,HWND);
ULONG_PTR (*get_icon_param)(HICON);
ULONG_PTR (*set_icon_param)(HICON,ULONG_PTR);
};
extern struct wow_handlers16 wow_handlers DECLSPEC_HIDDEN;
......@@ -133,6 +132,9 @@ extern LRESULT MDIClientWndProc_common(HWND,UINT,WPARAM,LPARAM,BOOL) DECLSPEC_HI
extern LRESULT ScrollBarWndProc_common(HWND,UINT,WPARAM,LPARAM,BOOL) DECLSPEC_HIDDEN;
extern LRESULT StaticWndProc_common(HWND,UINT,WPARAM,LPARAM,BOOL) DECLSPEC_HIDDEN;
extern ULONG_PTR get_icon_param( HICON handle ) DECLSPEC_HIDDEN;
extern ULONG_PTR set_icon_param( HICON handle, ULONG_PTR param ) DECLSPEC_HIDDEN;
/* Class functions */
struct tagCLASS; /* opaque structure */
struct tagWND;
......
......@@ -126,6 +126,86 @@ static CRITICAL_SECTION IconCrst = { &critsect_debug, -1, 0, 0, 0, 0 };
static const WORD ICON_HOTSPOT = 0x4242;
/**********************************************************************
* User objects management
*/
struct cursoricon_object
{
struct user_object obj; /* object header */
ULONG_PTR param; /* opaque param used by 16-bit code */
/* followed by cursor data in CURSORICONINFO format */
};
static HICON alloc_icon_handle( unsigned int size )
{
struct cursoricon_object *obj = HeapAlloc( GetProcessHeap(), 0, sizeof(*obj) + size );
if (!obj) return 0;
obj->param = 0;
return alloc_user_handle( &obj->obj, USER_ICON );
}
static struct tagCURSORICONINFO *get_icon_ptr( HICON handle )
{
struct cursoricon_object *obj = get_user_handle_ptr( handle, USER_ICON );
if (obj == OBJ_OTHER_PROCESS)
{
WARN( "icon handle %p from other process\n", handle );
obj = NULL;
}
return obj ? (struct tagCURSORICONINFO *)(obj + 1) : NULL;
}
static void release_icon_ptr( HICON handle, struct tagCURSORICONINFO *ptr )
{
release_user_handle_ptr( (struct cursoricon_object *)ptr - 1 );
}
static BOOL free_icon_handle( HICON handle )
{
struct cursoricon_object *obj = free_user_handle( handle, USER_ICON );
if (obj == OBJ_OTHER_PROCESS) WARN( "icon handle %p from other process\n", handle );
else if (obj)
{
ULONG_PTR param = obj->param;
HeapFree( GetProcessHeap(), 0, obj );
if (wow_handlers.free_icon_param && param) wow_handlers.free_icon_param( param );
return TRUE;
}
return FALSE;
}
ULONG_PTR get_icon_param( HICON handle )
{
ULONG_PTR ret = 0;
struct cursoricon_object *obj = get_user_handle_ptr( handle, USER_ICON );
if (obj == OBJ_OTHER_PROCESS) WARN( "icon handle %p from other process\n", handle );
else if (obj)
{
ret = obj->param;
release_user_handle_ptr( obj );
}
return ret;
}
ULONG_PTR set_icon_param( HICON handle, ULONG_PTR param )
{
ULONG_PTR ret = 0;
struct cursoricon_object *obj = get_user_handle_ptr( handle, USER_ICON );
if (obj == OBJ_OTHER_PROCESS) WARN( "icon handle %p from other process\n", handle );
else if (obj)
{
ret = obj->param;
obj->param = param;
release_user_handle_ptr( obj );
}
return ret;
}
/***********************************************************************
* map_fileW
*
......@@ -451,10 +531,10 @@ BOOL get_icon_size( HICON handle, SIZE *size )
{
CURSORICONINFO *info;
if (!(info = wow_handlers.get_icon_ptr( handle ))) return FALSE;
if (!(info = get_icon_ptr( handle ))) return FALSE;
size->cx = info->nWidth;
size->cy = info->nHeight;
wow_handlers.release_icon_ptr( handle, info );
release_icon_ptr( handle, info );
return TRUE;
}
......@@ -831,10 +911,10 @@ static HICON CURSORICON_CreateIconFromBMI( BITMAPINFO *bmi,
sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
hObj = wow_handlers.alloc_icon_handle( sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
hObj = alloc_icon_handle( sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
if (hObj)
{
CURSORICONINFO *info = wow_handlers.get_icon_ptr( hObj );
CURSORICONINFO *info = get_icon_ptr( hObj );
info->ptHotSpot.x = hotspot.x;
info->ptHotSpot.y = hotspot.y;
......@@ -848,7 +928,7 @@ static HICON CURSORICON_CreateIconFromBMI( BITMAPINFO *bmi,
GetBitmapBits( hAndBits, sizeAnd, info + 1 );
GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
wow_handlers.release_icon_ptr( hObj, info );
release_icon_ptr( hObj, info );
}
DeleteObject( hAndBits );
......@@ -1451,15 +1531,15 @@ HICON WINAPI CopyIcon( HICON hIcon )
int size;
HICON hNew;
if (!(ptrOld = wow_handlers.get_icon_ptr( hIcon ))) return 0;
if (!(ptrOld = get_icon_ptr( hIcon ))) return 0;
size = sizeof(CURSORICONINFO);
size += ptrOld->nHeight * get_bitmap_width_bytes( ptrOld->nWidth, 1 ); /* and bitmap */
size += ptrOld->nHeight * ptrOld->nWidthBytes; /* xor bitmap */
hNew = wow_handlers.alloc_icon_handle( size );
ptrNew = wow_handlers.get_icon_ptr( hNew );
hNew = alloc_icon_handle( size );
ptrNew = get_icon_ptr( hNew );
memcpy( ptrNew, ptrOld, size );
wow_handlers.release_icon_ptr( hIcon, ptrOld );
wow_handlers.release_icon_ptr( hNew, ptrNew );
release_icon_ptr( hIcon, ptrOld );
release_icon_ptr( hNew, ptrNew );
return hNew;
}
......@@ -1472,7 +1552,7 @@ BOOL WINAPI DestroyIcon( HICON hIcon )
TRACE_(icon)("%p\n", hIcon );
if (CURSORICON_DelSharedIcon( hIcon ) == -1)
wow_handlers.free_icon_handle( hIcon );
free_icon_handle( hIcon );
return TRUE;
}
......@@ -1572,10 +1652,10 @@ BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
TRACE("%p, (%d,%d), %p\n", hdc, x, y, hIcon);
if (!(ptr = wow_handlers.get_icon_ptr( hIcon ))) return FALSE;
if (!(ptr = get_icon_ptr( hIcon ))) return FALSE;
if (!(hMemDC = CreateCompatibleDC( hdc )))
{
wow_handlers.release_icon_ptr( hIcon, ptr );
release_icon_ptr( hIcon, ptr );
return FALSE;
}
......@@ -1641,7 +1721,7 @@ BOOL WINAPI DrawIcon( HDC hdc, INT x, INT y, HICON hIcon )
DeleteDC( hMemDC );
if (hXorBits) DeleteObject( hXorBits );
if (hAndBits) DeleteObject( hAndBits );
wow_handlers.release_icon_ptr( hIcon, ptr );
release_icon_ptr( hIcon, ptr );
SetTextColor( hdc, oldFg );
SetBkColor( hdc, oldBg );
return TRUE;
......@@ -1667,9 +1747,9 @@ HCURSOR WINAPI DECLSPEC_HOTPATCH SetCursor( HCURSOR hCursor /* [in] Handle of cu
/* Change the cursor shape only if it is visible */
if (thread_info->cursor_count >= 0)
{
CURSORICONINFO *info = wow_handlers.get_icon_ptr( hCursor );
CURSORICONINFO *info = get_icon_ptr( hCursor );
/* release before calling driver (FIXME) */
if (info) wow_handlers.release_icon_ptr( hCursor, info );
if (info) release_icon_ptr( hCursor, info );
USER_Driver->pSetCursor( info );
}
return hOldCursor;
......@@ -1688,9 +1768,9 @@ INT WINAPI DECLSPEC_HOTPATCH ShowCursor( BOOL bShow )
{
if (++thread_info->cursor_count == 0) /* Show it */
{
CURSORICONINFO *info = wow_handlers.get_icon_ptr( thread_info->cursor );
CURSORICONINFO *info = get_icon_ptr( thread_info->cursor );
/* release before calling driver (FIXME) */
if (info) wow_handlers.release_icon_ptr( thread_info->cursor, info );
if (info) release_icon_ptr( thread_info->cursor, info );
USER_Driver->pSetCursor( info );
}
}
......@@ -1868,7 +1948,7 @@ BOOL WINAPI GetIconInfo(HICON hIcon, PICONINFO iconinfo)
CURSORICONINFO *ciconinfo;
INT height;
if (!(ciconinfo = wow_handlers.get_icon_ptr( hIcon ))) return FALSE;
if (!(ciconinfo = get_icon_ptr( hIcon ))) return FALSE;
TRACE("%p => %dx%d, %d bpp\n", hIcon,
ciconinfo->nWidth, ciconinfo->nHeight, ciconinfo->bBitsPerPixel);
......@@ -1905,7 +1985,7 @@ BOOL WINAPI GetIconInfo(HICON hIcon, PICONINFO iconinfo)
iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, height,
1, 1, ciconinfo + 1);
wow_handlers.release_icon_ptr( hIcon, ciconinfo );
release_icon_ptr( hIcon, ciconinfo );
return TRUE;
}
......@@ -1946,10 +2026,10 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
sizeAnd = bmpAnd.bmHeight * get_bitmap_width_bytes(bmpAnd.bmWidth, 1);
hObj = wow_handlers.alloc_icon_handle( sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
hObj = alloc_icon_handle( sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
if (hObj)
{
CURSORICONINFO *info = wow_handlers.get_icon_ptr( hObj );
CURSORICONINFO *info = get_icon_ptr( hObj );
/* If we are creating an icon, the hotspot is unused */
if (iconinfo->fIcon)
......@@ -2058,7 +2138,7 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
dst_bits, &bminfo, DIB_RGB_COLORS );
}
}
wow_handlers.release_icon_ptr( hObj, info );
release_icon_ptr( hObj, info );
}
return hObj;
}
......@@ -2099,10 +2179,10 @@ BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
TRACE_(icon)("(hdc=%p,pos=%d.%d,hicon=%p,extend=%d.%d,istep=%d,br=%p,flags=0x%08x)\n",
hdc,x0,y0,hIcon,cxWidth,cyWidth,istep,hbr,flags );
if (!(ptr = wow_handlers.get_icon_ptr( hIcon ))) return FALSE;
if (!(ptr = get_icon_ptr( hIcon ))) return FALSE;
if (!(hMemDC = CreateCompatibleDC( hdc )))
{
wow_handlers.release_icon_ptr( hIcon, ptr );
release_icon_ptr( hIcon, ptr );
return FALSE;
}
......@@ -2250,7 +2330,7 @@ BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
if (hMemDC) DeleteDC( hMemDC );
if (hDC_off) DeleteDC(hDC_off);
if (hB_off) DeleteObject(hB_off);
wow_handlers.release_icon_ptr( hIcon, ptr );
release_icon_ptr( hIcon, ptr );
return result;
}
......
......@@ -1128,37 +1128,6 @@ static DWORD wait_message( DWORD count, CONST HANDLE *handles, DWORD timeout, DW
return ret;
}
static HICON alloc_icon_handle( unsigned int size )
{
struct user_object *obj = HeapAlloc( GetProcessHeap(), 0, sizeof(*obj) + size );
if (!obj) return 0;
return alloc_user_handle( obj, USER_ICON );
}
static struct tagCURSORICONINFO *get_icon_ptr( HICON handle )
{
struct user_object *obj = get_user_handle_ptr( handle, USER_ICON );
if (obj == OBJ_OTHER_PROCESS)
{
WARN( "cursor handle %p from other process\n", handle );
obj = NULL;
}
return obj ? (struct tagCURSORICONINFO *)(obj + 1) : NULL;
}
static void release_icon_ptr( HICON handle, struct tagCURSORICONINFO *ptr )
{
release_user_handle_ptr( (struct user_object *)ptr - 1 );
}
static int free_icon_handle( HICON handle )
{
struct user_object *obj = free_user_handle( handle, USER_ICON );
HeapFree( GetProcessHeap(), 0, obj );
return !obj;
}
/**********************************************************************
* UserRegisterWowHandlers (USER32.@)
*
......@@ -1180,6 +1149,8 @@ void WINAPI UserRegisterWowHandlers( const struct wow_handlers16 *new, struct wo
orig->alloc_winproc = WINPROC_AllocProc;
orig->get_dialog_info = DIALOG_get_info;
orig->dialog_box_loop = DIALOG_DoDialogBox;
orig->get_icon_param = get_icon_param;
orig->set_icon_param = set_icon_param;
wow_handlers = *new;
}
......@@ -1197,8 +1168,5 @@ struct wow_handlers16 wow_handlers =
WIN_CreateWindowEx,
NULL, /* call_window_proc */
NULL, /* call_dialog_proc */
alloc_icon_handle,
get_icon_ptr,
release_icon_ptr,
free_icon_handle
NULL, /* free_icon_param */
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment