user32: Introduce NtUserSetCursorIconData.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2022-02-22 13:41:40 +01:00 committed by Alexandre Julliard
parent 8ce4c07f50
commit f0176397ad
2 changed files with 168 additions and 43 deletions

View File

@ -904,6 +904,123 @@ static const CURSORICONFILEDIRENTRY *CURSORICON_FindBestIconFile( const CURSORIC
return &dir->idEntries[n];
}
static HICON alloc_cursoricon_handle( BOOL is_icon )
{
struct cursoricon_object *obj;
HICON handle;
if (!(obj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*obj) ))) return NULL;
obj->is_icon = is_icon;
if (!(handle = alloc_user_handle( &obj->obj, NTUSER_OBJ_ICON ))) free( obj );
return handle;
}
/***********************************************************************
* 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 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
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 = HeapAlloc( GetProcessHeap(), 0, 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 = HeapAlloc( GetProcessHeap(), 0, 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;
}
/***********************************************************************
* bmi_has_alpha
*/
@ -1167,6 +1284,35 @@ done:
return ret;
}
static HICON create_cursoricon_object( struct cursoricon_desc *desc, BOOL is_icon, HINSTANCE module,
const WCHAR *resname, HRSRC rsrc )
{
WCHAR buf[MAX_PATH];
UNICODE_STRING module_name = { 0, sizeof(buf), buf };
UNICODE_STRING res_str = { 0 };
HICON handle;
if (!(handle = alloc_cursoricon_handle( is_icon ))) return 0;
if (module) LdrGetDllFullName( module, &module_name );
res_str.Buffer = (WCHAR *)resname;
if (!IS_INTRESOURCE(resname))
{
res_str.Length = lstrlenW( resname ) * sizeof(WCHAR);
res_str.MaximumLength = res_str.Length + sizeof(WCHAR);
}
desc->rsrc = rsrc; /* FIXME: we should probably avoid storing rsrc */
if (!NtUserSetCursorIconData( handle, &module_name, &res_str, desc ))
{
DestroyCursor( handle );
return 0;
}
return handle;
}
/***********************************************************************
* create_icon_from_bmi
*
@ -1177,53 +1323,17 @@ static HICON create_icon_from_bmi( const BITMAPINFO *bmi, DWORD maxsize, HMODULE
UINT flags )
{
struct cursoricon_frame frame;
struct cursoricon_desc desc =
{
.flags = flags,
.frames = &frame,
};
HICON ret;
if (!create_icon_frame( bmi, maxsize, hotspot, bIcon, width, height, flags, &frame )) return 0;
ret = alloc_icon_handle( FALSE, 0 );
if (ret)
{
struct cursoricon_object *info = get_icon_ptr( ret );
info->is_icon = bIcon;
info->frame = frame;
if (!IS_INTRESOURCE(resname))
{
info->resname = HeapAlloc( GetProcessHeap(), 0, (lstrlenW(resname) + 1) * sizeof(WCHAR) );
if (info->resname) lstrcpyW( info->resname, resname );
}
else info->resname = MAKEINTRESOURCEW( LOWORD(resname) );
if (module)
{
WCHAR buf[MAX_PATH];
UNICODE_STRING module_name = { 0, sizeof(buf), buf };
if (!LdrGetDllFullName( module, &module_name ) &&
(info->module.Buffer = HeapAlloc( GetProcessHeap(), 0, module_name.Length )))
{
memcpy( info->module.Buffer, module_name.Buffer, module_name.Length );
info->module.Length = module_name.Length;
}
}
if (flags & LR_SHARED)
{
info->is_shared = TRUE;
if (module)
{
info->rsrc = rsrc;
list_add_head( &icon_cache, &info->entry );
}
}
release_user_handle_ptr( info );
}
else
{
free_icon_frame( &frame );
}
ret = create_cursoricon_object( &desc, bIcon, module, resname, rsrc );
if (!ret) free_icon_frame( &frame );
return ret;
}

View File

@ -113,6 +113,19 @@ enum
#define NTUSER_OBJ_ACCEL 0x08
#define NTUSER_OBJ_HOOK 0x0f
/* NtUserSetCursorIconData parameter, not compatible with Windows */
struct cursoricon_desc
{
UINT flags;
UINT num_steps;
UINT num_frames;
UINT delay;
struct cursoricon_frame *frames;
DWORD *frame_seq;
DWORD *frame_rates;
HRSRC rsrc;
};
/* internal messages codes */
enum wine_internal_message
{
@ -199,6 +212,8 @@ HANDLE WINAPI NtUserRemoveProp( HWND hwnd, const WCHAR *str );
BOOL WINAPI NtUserScrollDC( HDC hdc, INT dx, INT dy, const RECT *scroll, const RECT *clip,
HRGN ret_update_rgn, RECT *update_rect );
HPALETTE WINAPI NtUserSelectPalette( HDC hdc, HPALETTE palette, WORD force_background );
BOOL WINAPI NtUserSetCursorIconData( HCURSOR cursor, UNICODE_STRING *module, UNICODE_STRING *res_name,
struct cursoricon_desc *desc );
BOOL WINAPI NtUserSetCursorPos( INT x, INT y );
BOOL WINAPI NtUserSetKeyboardState( BYTE *state );
BOOL WINAPI NtUserSetProcessDpiAwarenessContext( ULONG awareness, ULONG unknown );