Commit bb895f4f authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

win32u: Move cursor icon handle management from user32.

parent 018f8014
......@@ -128,10 +128,6 @@ static void CDECL nulldrv_UnregisterHotKey( HWND hwnd, UINT modifiers, UINT vk )
{
}
static void CDECL nulldrv_DestroyCursorIcon( HCURSOR cursor )
{
}
static void CDECL nulldrv_SetCursor( HCURSOR cursor )
{
}
......@@ -355,7 +351,7 @@ static struct user_driver_funcs lazy_load_driver =
loaderdrv_UnregisterHotKey,
NULL,
/* cursor/icon functions */
nulldrv_DestroyCursorIcon,
NULL,
loaderdrv_SetCursor,
NULL,
loaderdrv_SetCursorPos,
......@@ -415,7 +411,6 @@ void CDECL __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT v
SET_USER_FUNC(RegisterHotKey);
SET_USER_FUNC(UnregisterHotKey);
SET_USER_FUNC(DestroyCursorIcon);
SET_USER_FUNC(SetCursor);
SET_USER_FUNC(SetCursorPos);
SET_USER_FUNC(ClipCursor);
......
......@@ -143,10 +143,16 @@ static const struct user_callbacks user_funcs =
WindowFromDC,
};
static void WINAPI User32CallFreeIcon( ULONG *param, ULONG size )
{
wow_handlers.free_icon_param( *param );
}
static const void *kernel_callback_table[NtUserCallCount] =
{
User32CallEnumDisplayMonitor,
User32CallWinEventHook,
User32CallFreeIcon,
};
......
......@@ -28,12 +28,15 @@
#pragma makedep unix
#endif
#include <assert.h>
#include "win32u_private.h"
#include "ntuser_private.h"
#include "wine/server.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(cursor);
static struct list icon_cache = LIST_INIT( icon_cache );
/***********************************************************************
* NtUserShowCursor (win32u.@)
......@@ -155,3 +158,217 @@ BOOL get_clip_cursor( RECT *rect )
}
return ret;
}
HICON alloc_cursoricon_handle( BOOL is_icon )
{
struct cursoricon_object *obj;
HICON handle;
if (!(obj = calloc( 1, sizeof(*obj) ))) return NULL;
obj->is_icon = is_icon;
if (!(handle = alloc_user_handle( &obj->obj, NTUSER_OBJ_ICON ))) free( obj );
return handle;
}
static struct cursoricon_object *get_icon_ptr( HICON handle )
{
struct cursoricon_object *obj = get_user_handle_ptr( handle, NTUSER_OBJ_ICON );
if (obj == OBJ_OTHER_PROCESS)
{
WARN( "icon handle %p from other process\n", handle );
obj = NULL;
}
return obj;
}
static BOOL free_icon_handle( HICON handle )
{
struct cursoricon_object *obj = free_user_handle( handle, NTUSER_OBJ_ICON );
if (obj == OBJ_OTHER_PROCESS) WARN( "icon handle %p from other process\n", handle );
else if (obj)
{
ULONG param = obj->param;
void *ret_ptr;
ULONG ret_len;
UINT i;
assert( !obj->rsrc ); /* shared icons can't be freed */
if (!obj->is_ani)
{
if (obj->frame.alpha) NtGdiDeleteObjectApp( obj->frame.alpha );
if (obj->frame.color) NtGdiDeleteObjectApp( obj->frame.color );
if (obj->frame.mask) NtGdiDeleteObjectApp( obj->frame.mask );
}
else
{
for (i = 0; i < obj->ani.num_steps; i++)
{
HICON hFrame = obj->ani.frames[i];
if (hFrame)
{
UINT j;
free_icon_handle( obj->ani.frames[i] );
for (j = 0; j < obj->ani.num_steps; j++)
{
if (obj->ani.frames[j] == hFrame) obj->ani.frames[j] = 0;
}
}
}
free( obj->ani.frames );
}
if (!IS_INTRESOURCE( obj->resname )) free( obj->resname );
free( obj );
if (param) KeUserModeCallback( NtUserCallFreeIcon, &param, sizeof(param), &ret_ptr, &ret_len );
user_driver->pDestroyCursorIcon( handle );
return TRUE;
}
return FALSE;
}
/***********************************************************************
* NtUserDestroyCursor (win32u.@)
*/
BOOL WINAPI NtUserDestroyCursor( HCURSOR cursor, ULONG arg )
{
struct cursoricon_object *obj;
BOOL shared, ret;
TRACE( "%p\n", cursor );
if (!(obj = get_icon_ptr( cursor ))) return FALSE;
shared = obj->is_shared;
release_user_handle_ptr( obj );
ret = NtUserGetCursor() != cursor;
if (!shared) free_icon_handle( cursor );
return ret;
}
/***********************************************************************
* NtUserSetCursorIconData (win32u.@)
*/
BOOL WINAPI NtUserSetCursorIconData( HCURSOR cursor, UNICODE_STRING *module, UNICODE_STRING *res_name,
struct cursoricon_desc *desc )
{
struct cursoricon_object *obj;
UINT i, j;
if (!(obj = get_icon_ptr( cursor ))) return FALSE;
if (obj->is_ani || obj->frame.width)
{
/* already initialized */
release_user_handle_ptr( obj );
SetLastError( ERROR_INVALID_CURSOR_HANDLE );
return FALSE;
}
obj->delay = desc->delay;
if (desc->num_steps)
{
if (!(obj->ani.frames = calloc( desc->num_steps, sizeof(*obj->ani.frames) )))
{
release_user_handle_ptr( obj );
return FALSE;
}
obj->is_ani = TRUE;
obj->ani.num_steps = desc->num_steps;
obj->ani.num_frames = desc->num_frames;
}
else obj->frame = desc->frames[0];
if (!res_name)
obj->resname = NULL;
else if (res_name->Length)
{
obj->resname = malloc( res_name->Length + sizeof(WCHAR) );
if (obj->resname)
{
memcpy( obj->resname, res_name->Buffer, res_name->Length );
obj->resname[res_name->Length / sizeof(WCHAR)] = 0;
}
}
else
obj->resname = MAKEINTRESOURCEW( LOWORD(res_name->Buffer) );
if (module && module->Length && (obj->module.Buffer = malloc( module->Length )))
{
memcpy( obj->module.Buffer, module->Buffer, module->Length );
obj->module.Length = module->Length;
}
if (obj->is_ani)
{
/* Setup the animated frames in the correct sequence */
for (i = 0; i < desc->num_steps; i++)
{
struct cursoricon_desc frame_desc;
DWORD frame_id;
if (obj->ani.frames[i]) continue; /* already set */
frame_id = desc->frame_seq ? desc->frame_seq[i] : i;
if (frame_id >= obj->ani.num_frames)
{
frame_id = obj->ani.num_frames - 1;
ERR_(cursor)( "Sequence indicates frame past end of list, corrupt?\n" );
}
memset( &frame_desc, 0, sizeof(frame_desc) );
frame_desc.delay = desc->frame_rates ? desc->frame_rates[i] : desc->delay;
frame_desc.frames = &desc->frames[frame_id];
if (!(obj->ani.frames[i] = alloc_cursoricon_handle( obj->is_icon )) ||
!NtUserSetCursorIconData( obj->ani.frames[i], NULL, NULL, &frame_desc ))
{
release_user_handle_ptr( obj );
return 0;
}
if (desc->frame_seq)
{
for (j = i + 1; j < obj->ani.num_steps; j++)
{
if (desc->frame_seq[j] == frame_id) obj->ani.frames[j] = obj->ani.frames[i];
}
}
}
}
if (desc->flags & LR_SHARED)
{
obj->is_shared = TRUE;
if (obj->module.Length)
{
obj->rsrc = desc->rsrc;
list_add_head( &icon_cache, &obj->entry );
}
}
release_user_handle_ptr( obj );
return TRUE;
}
/***********************************************************************
* NtUserFindExistingCursorIcon (win32u.@)
*/
HICON WINAPI NtUserFindExistingCursorIcon( UNICODE_STRING *module, UNICODE_STRING *res_name, void *desc )
{
struct cursoricon_object *ptr;
HICON ret = 0;
user_lock();
LIST_FOR_EACH_ENTRY( ptr, &icon_cache, struct cursoricon_object, entry )
{
if (ptr->module.Length != module->Length) continue;
if (memcmp( ptr->module.Buffer, module->Buffer, module->Length )) continue;
/* We pass rsrc as desc argument, this is not compatible with Windows */
if (ptr->rsrc != desc) continue;
ret = ptr->obj.handle;
break;
}
user_unlock();
return ret;
}
......@@ -1045,6 +1045,7 @@ static const struct user_driver_funcs lazy_load_driver =
.pUnregisterHotKey = loaderdrv_UnregisterHotKey,
.pVkKeyScanEx = loaderdrv_VkKeyScanEx,
/* cursor/icon functions */
.pDestroyCursorIcon = nulldrv_DestroyCursorIcon,
.pSetCursor = loaderdrv_SetCursor,
.pGetCursorPos = loaderdrv_GetCursorPos,
.pSetCursorPos = loaderdrv_SetCursorPos,
......
......@@ -1156,6 +1156,7 @@ static struct unix_funcs unix_funcs =
NtUserChangeDisplaySettings,
NtUserClipCursor,
NtUserCountClipboardFormats,
NtUserDestroyCursor,
NtUserEnumDisplayDevices,
NtUserEnumDisplayMonitors,
NtUserEnumDisplaySettings,
......@@ -1170,6 +1171,7 @@ static struct unix_funcs unix_funcs =
NtUserMapVirtualKeyEx,
NtUserScrollDC,
NtUserSelectPalette,
NtUserSetCursorIconData,
NtUserSetCursorPos,
NtUserSetSysColors,
NtUserShowCursor,
......
......@@ -23,6 +23,7 @@
#define __WINE_NTUSER_PRIVATE_H
#include "ntuser.h"
#include "wine/list.h"
struct user_callbacks
{
......@@ -124,4 +125,37 @@ struct user_key_state_info
BYTE state[256]; /* State for each key */
};
struct cursoricon_object
{
struct user_object obj; /* object header */
struct list entry; /* entry in shared icons list */
ULONG_PTR param; /* opaque param used by 16-bit code */
UNICODE_STRING module; /* module for icons loaded from resources */
LPWSTR resname; /* resource name for icons loaded from resources */
HRSRC rsrc; /* resource for shared icons */
BOOL is_shared; /* whether this object is shared */
BOOL is_icon; /* whether icon or cursor */
BOOL is_ani; /* whether this object is a static cursor or an animated cursor */
UINT delay; /* delay between this frame and the next (in jiffies) */
union
{
struct cursoricon_frame frame; /* frame-specific icon data */
struct
{
UINT num_frames; /* number of frames in the icon/cursor */
UINT num_steps; /* number of sequence steps in the icon/cursor */
HICON *frames; /* list of animated cursor frames */
} ani;
};
};
/* cursoricon.c */
HICON alloc_cursoricon_handle( BOOL is_icon ) DECLSPEC_HIDDEN;
/* window.c */
HANDLE alloc_user_handle( struct user_object *ptr, unsigned int type ) DECLSPEC_HIDDEN;
void *free_user_handle( HANDLE handle, unsigned int type ) DECLSPEC_HIDDEN;
void *get_user_handle_ptr( HANDLE handle, unsigned int type ) DECLSPEC_HIDDEN;
void release_user_handle_ptr( void *ptr ) DECLSPEC_HIDDEN;
#endif /* __WINE_NTUSER_PRIVATE_H */
......@@ -108,6 +108,7 @@ static void * const syscalls[] =
NtUserCloseWindowStation,
NtUserCreateDesktopEx,
NtUserCreateWindowStation,
NtUserFindExistingCursorIcon,
NtUserGetClipboardFormatName,
NtUserGetClipboardOwner,
NtUserGetClipboardSequenceNumber,
......
......@@ -4552,6 +4552,8 @@ ULONG_PTR WINAPI NtUserCallOneParam( ULONG_PTR arg, ULONG code )
{
switch(code)
{
case NtUserCreateCursorIcon:
return HandleToUlong( alloc_cursoricon_handle( arg ));
case NtUserGetClipCursor:
return get_clip_cursor( (RECT *)arg );
case NtUserGetCursorPos:
......
......@@ -829,7 +829,7 @@
@ stub NtUserDestroyAcceleratorTable
@ stub NtUserDestroyActivationGroup
@ stub NtUserDestroyActivationObject
@ stub NtUserDestroyCursor
@ stdcall NtUserDestroyCursor(long long)
@ stub NtUserDestroyDCompositionHwndTarget
@ stub NtUserDestroyInputContext
@ stub NtUserDestroyMenu
......@@ -881,7 +881,7 @@
@ stub NtUserEvent
@ stub NtUserExcludeUpdateRgn
@ stub NtUserFillWindow
@ stub NtUserFindExistingCursorIcon
@ stdcall -syscall NtUserFindExistingCursorIcon(ptr ptr ptr)
@ stub NtUserFindWindowEx
@ stub NtUserFlashWindowEx
@ stub NtUserForceWindowToDpiForTest
......@@ -1180,7 +1180,7 @@
@ stub NtUserSetCoreWindowPartner
@ stub NtUserSetCursor
@ stub NtUserSetCursorContents
@ stub NtUserSetCursorIconData
@ stdcall NtUserSetCursorIconData(long ptr ptr ptr)
@ stdcall NtUserSetCursorPos(long long)
@ stub NtUserSetDesktopColorTransform
@ stub NtUserSetDesktopVisualInputSink
......
......@@ -190,6 +190,7 @@ struct unix_funcs
DWORD flags, void *lparam );
BOOL (WINAPI *pNtUserClipCursor)( const RECT *rect );
INT (WINAPI *pNtUserCountClipboardFormats)(void);
BOOL (WINAPI *pNtUserDestroyCursor)( HCURSOR cursor, ULONG arg );
NTSTATUS (WINAPI *pNtUserEnumDisplayDevices)( UNICODE_STRING *device, DWORD index,
DISPLAY_DEVICEW *info, DWORD flags );
BOOL (WINAPI *pNtUserEnumDisplayMonitors)( HDC hdc, RECT *rect, MONITORENUMPROC proc, LPARAM lp );
......@@ -208,6 +209,8 @@ struct unix_funcs
BOOL (WINAPI *pNtUserScrollDC)( HDC hdc, INT dx, INT dy, const RECT *scroll, const RECT *clip,
HRGN ret_update_rgn, RECT *update_rect );
HPALETTE (WINAPI *pNtUserSelectPalette)( HDC hdc, HPALETTE hpal, WORD bkg );
BOOL (WINAPI *pNtUserSetCursorIconData)( HCURSOR cursor, UNICODE_STRING *module,
UNICODE_STRING *res_name, struct cursoricon_desc *desc );
BOOL (WINAPI *pNtUserSetCursorPos)( INT x, INT y );
BOOL (WINAPI *pNtUserSetSysColors)( INT count, const INT *colors, const COLORREF *values );
INT (WINAPI *pNtUserShowCursor)( BOOL show );
......@@ -237,6 +240,7 @@ struct unix_funcs
};
/* cursoricon.c */
extern HICON alloc_cursoricon_handle( BOOL is_icon ) DECLSPEC_HIDDEN;
extern BOOL get_clip_cursor( RECT *rect ) DECLSPEC_HIDDEN;
/* hook.c */
......
......@@ -100,6 +100,15 @@ void set_user_handle_ptr( HANDLE handle, struct user_object *ptr )
}
/***********************************************************************
* release_user_handle_ptr
*/
void release_user_handle_ptr( void *ptr )
{
assert( ptr && ptr != OBJ_OTHER_PROCESS );
user_unlock();
}
/***********************************************************************
* free_user_handle
*/
void *free_user_handle( HANDLE handle, unsigned int type )
......
......@@ -738,6 +738,12 @@ INT WINAPI NtUserCountClipboardFormats(void)
return unix_funcs->pNtUserCountClipboardFormats();
}
BOOL WINAPI NtUserDestroyCursor( HCURSOR cursor, ULONG arg )
{
if (!unix_funcs) return FALSE;
return unix_funcs->pNtUserDestroyCursor( cursor, arg );
}
NTSTATUS WINAPI NtUserEnumDisplayDevices( UNICODE_STRING *device, DWORD index,
DISPLAY_DEVICEW *info, DWORD flags )
{
......@@ -826,6 +832,13 @@ HPALETTE WINAPI NtUserSelectPalette( HDC hdc, HPALETTE hpal, WORD bkg )
return unix_funcs->pNtUserSelectPalette( hdc, hpal, bkg );
}
BOOL WINAPI NtUserSetCursorIconData( HCURSOR cursor, UNICODE_STRING *module, UNICODE_STRING *res_name,
struct cursoricon_desc *desc )
{
if (!unix_funcs) return FALSE;
return unix_funcs->pNtUserSetCursorIconData( cursor, module, res_name, desc );
}
BOOL WINAPI NtUserSetCursorPos( INT x, INT y )
{
if (!unix_funcs) return FALSE;
......
......@@ -95,6 +95,7 @@
SYSCALL_ENTRY( NtUserCloseWindowStation ) \
SYSCALL_ENTRY( NtUserCreateDesktopEx ) \
SYSCALL_ENTRY( NtUserCreateWindowStation ) \
SYSCALL_ENTRY( NtUserFindExistingCursorIcon ) \
SYSCALL_ENTRY( NtUserGetClipboardFormatName ) \
SYSCALL_ENTRY( NtUserGetClipboardOwner ) \
SYSCALL_ENTRY( NtUserGetClipboardSequenceNumber ) \
......
......@@ -264,6 +264,21 @@ NTSTATUS WINAPI wow64_NtUserGetCursor( UINT *args )
return HandleToUlong( NtUserGetCursor() );
}
NTSTATUS WINAPI wow64_NtUserFindExistingCursorIcon( UINT *args )
{
UNICODE_STRING32 *module32 = get_ptr( &args );
UNICODE_STRING32 *res_name32 = get_ptr( &args );
void *desc = get_ptr( &args );
UNICODE_STRING module;
UNICODE_STRING res_name;
HICON ret;
ret = NtUserFindExistingCursorIcon( unicode_str_32to64( &module, module32 ),
unicode_str_32to64( &res_name, res_name32 ), desc );
return HandleToUlong( ret );
}
NTSTATUS WINAPI wow64_NtUserAttachThreadInput( UINT *args )
{
DWORD from = get_ulong( &args );
......
......@@ -26,8 +26,12 @@
/* KernelCallbackTable codes, not compatible with Windows */
enum
{
/* user32 callbacks */
NtUserCallEnumDisplayMonitor,
NtUserCallWinEventHook,
/* win16 hooks */
NtUserCallFreeIcon,
/* Vulkan support */
NtUserCallVulkanDebugReportCallback,
NtUserCallVulkanDebugUtilsCallback,
NtUserCallCount
......@@ -73,6 +77,7 @@ enum
/* NtUserCallOneParam codes, not compatible with Windows */
enum
{
NtUserCreateCursorIcon,
NtUserGetClipCursor,
NtUserGetCursorPos,
NtUserGetPrimaryMonitorRect,
......@@ -120,6 +125,16 @@ enum
#define NTUSER_OBJ_HOOK 0x0f
/* NtUserSetCursorIconData parameter, not compatible with Windows */
struct cursoricon_frame
{
UINT width; /* frame-specific width */
UINT height; /* frame-specific height */
HBITMAP color; /* color bitmap */
HBITMAP alpha; /* pre-multiplied alpha bitmap for 32-bpp icons */
HBITMAP mask; /* mask bitmap (followed by color for 1-bpp icons) */
POINT hotspot;
};
struct cursoricon_desc
{
UINT flags;
......@@ -170,11 +185,14 @@ HDESK WINAPI NtUserCreateDesktopEx( OBJECT_ATTRIBUTES *attr, UNICODE_STRING *d
ULONG heap_size );
HWINSTA WINAPI NtUserCreateWindowStation( OBJECT_ATTRIBUTES *attr, ACCESS_MASK mask, ULONG arg3,
ULONG arg4, ULONG arg5, ULONG arg6, ULONG arg7 );
BOOL WINAPI NtUserDestroyCursor( HCURSOR cursor, ULONG arg );
NTSTATUS WINAPI NtUserEnumDisplayDevices( UNICODE_STRING *device, DWORD index,
DISPLAY_DEVICEW *info, DWORD flags );
BOOL WINAPI NtUserEnumDisplayMonitors( HDC hdc, RECT *rect, MONITORENUMPROC proc, LPARAM lp );
BOOL WINAPI NtUserEnumDisplaySettings( UNICODE_STRING *device, DWORD mode,
DEVMODEW *dev_mode, DWORD flags );
HICON WINAPI NtUserFindExistingCursorIcon( UNICODE_STRING *module, UNICODE_STRING *res_name,
void *desc );
SHORT WINAPI NtUserGetAsyncKeyState( INT key );
INT WINAPI NtUserGetClipboardFormatName( UINT format, WCHAR *buffer, INT maxlen );
HWND WINAPI NtUserGetClipboardOwner(void);
......
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