/***********************************************************************
- * 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) );
}
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 );
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;
}
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 )
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
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;
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
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;
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;
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
*
{
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;
}
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;
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 );
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;
}
TRACE_(icon)("%p\n", hIcon );
if (CURSORICON_DelSharedIcon( hIcon ) == -1)
- wow_handlers.free_icon_handle( hIcon );
+ free_icon_handle( hIcon );
return TRUE;
}
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;
}
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;
/* 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;
{
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 );
}
}
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);
iconinfo->hbmMask = CreateBitmap ( ciconinfo->nWidth, height,
1, 1, ciconinfo + 1);
- wow_handlers.release_icon_ptr( hIcon, ciconinfo );
+ release_icon_ptr( hIcon, ciconinfo );
return TRUE;
}
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)
dst_bits, &bminfo, DIB_RGB_COLORS );
}
}
- wow_handlers.release_icon_ptr( hObj, info );
+ release_icon_ptr( hObj, info );
}
return hObj;
}
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;
}
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;
}
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.@)
*
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;
}
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 */
};