diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c index 20cbf070334..efbf2099fe7 100644 --- a/dlls/user32/cursoricon.c +++ b/dlls/user32/cursoricon.c @@ -52,46 +52,10 @@ WINE_DECLARE_DEBUG_CHANNEL(resource); ( (DWORD)(BYTE)(c2) << 16 ) | ( (DWORD)(BYTE)(c3) << 24 ) ) #define PNG_SIGN RIFF_FOURCC(0x89,'P','N','G') -static struct list icon_cache = LIST_INIT( icon_cache ); - /********************************************************************** * User objects management */ -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_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; - }; -}; - static HBITMAP create_color_bitmap( int width, int height ) { HDC hdc = get_display_dc(); @@ -151,50 +115,6 @@ static void free_icon_frame( struct cursoricon_frame *frame ) if (frame->mask) DeleteObject( frame->mask ); } -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_PTR param = obj->param; - UINT i; - - assert( !obj->rsrc ); /* shared icons can't be freed */ - - if (!obj->is_ani) - { - free_icon_frame( &obj->frame ); - } - 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; - } - } - } - HeapFree( GetProcessHeap(), 0, obj->ani.frames ); - } - if (!IS_INTRESOURCE( obj->resname )) HeapFree( GetProcessHeap(), 0, obj->resname ); - HeapFree( GetProcessHeap(), 0, obj ); - if (wow_handlers.free_icon_param && param) wow_handlers.free_icon_param( param ); - USER_Driver->pDestroyCursorIcon( handle ); - return TRUE; - } - return FALSE; -} - ULONG_PTR get_icon_param( HICON handle ) { ULONG_PTR ret = 0; @@ -875,123 +795,6 @@ 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 */ @@ -1262,7 +1065,7 @@ static HICON create_cursoricon_object( struct cursoricon_desc *desc, BOOL is_ico UNICODE_STRING res_str = { 0 }; HICON handle; - if (!(handle = alloc_cursoricon_handle( is_icon ))) return 0; + if (!(handle = UlongToHandle( NtUserCallOneParam( is_icon, NtUserCreateCursorIcon )))) return 0; if (module) LdrGetDllFullName( module, &module_name ); @@ -1276,7 +1079,7 @@ static HICON create_cursoricon_object( struct cursoricon_desc *desc, BOOL is_ico if (!NtUserSetCursorIconData( handle, &module_name, &res_str, desc )) { - DestroyCursor( handle ); + NtUserDestroyCursor( handle, 0 ); return 0; } @@ -1727,24 +1530,16 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name, /* If shared icon, check whether it was already loaded */ if (loadflags & LR_SHARED) { - WCHAR buf[MAX_PATH]; - UNICODE_STRING module = { 0, sizeof(buf) - sizeof(WCHAR), buf }; - struct cursoricon_object *ptr; + WCHAR module_buf[MAX_PATH]; + UNICODE_STRING module_str, res_str; - if (!LdrGetDllFullName( hInstance, &module )) - { - 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; - if (ptr->rsrc != hRsrc) continue; - hIcon = ptr->obj.handle; - break; - } - USER_Unlock(); - if (hIcon) return hIcon; - } + res_str.Length = 0; + res_str.Buffer = MAKEINTRESOURCEW(wResId); + module_str.Buffer = module_buf; + module_str.MaximumLength = sizeof(module_buf); + if (!LdrGetDllFullName( hInstance, &module_str ) && + (hIcon = NtUserFindExistingCursorIcon( &module_str, &res_str, hRsrc ))) + return hIcon; } if (!(handle = LoadResource( hInstance, hRsrc ))) return 0; @@ -1892,19 +1687,7 @@ HICON WINAPI CopyIcon( HICON icon ) */ BOOL WINAPI DestroyIcon( HICON hIcon ) { - BOOL ret = FALSE; - struct cursoricon_object *obj = get_icon_ptr( hIcon ); - - TRACE_(icon)("%p\n", hIcon ); - - if (obj) - { - BOOL shared = obj->is_shared; - release_user_handle_ptr( obj ); - ret = (NtUserGetCursor() != hIcon); - if (!shared) free_icon_handle( hIcon ); - } - return ret; + return NtUserDestroyCursor( hIcon, 0 ); } diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c index 7e9f63ad1c7..2edc5f2780d 100644 --- a/dlls/user32/driver.c +++ b/dlls/user32/driver.c @@ -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); diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c index 47f7ec7513a..1bab804185b 100644 --- a/dlls/user32/user_main.c +++ b/dlls/user32/user_main.c @@ -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, }; diff --git a/dlls/win32u/cursoricon.c b/dlls/win32u/cursoricon.c index cafea198809..d0e3701f75f 100644 --- a/dlls/win32u/cursoricon.c +++ b/dlls/win32u/cursoricon.c @@ -28,12 +28,15 @@ #pragma makedep unix #endif +#include #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, ¶m, 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; +} diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c index 5e6cee33bc6..dc858cdc0ce 100644 --- a/dlls/win32u/driver.c +++ b/dlls/win32u/driver.c @@ -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, diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c index 66ad2b2bba3..9d29b37c72b 100644 --- a/dlls/win32u/gdiobj.c +++ b/dlls/win32u/gdiobj.c @@ -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, diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 27fa97926cb..db1a08ff102 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -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 */ diff --git a/dlls/win32u/syscall.c b/dlls/win32u/syscall.c index 2d37d605479..b4255449b83 100644 --- a/dlls/win32u/syscall.c +++ b/dlls/win32u/syscall.c @@ -108,6 +108,7 @@ static void * const syscalls[] = NtUserCloseWindowStation, NtUserCreateDesktopEx, NtUserCreateWindowStation, + NtUserFindExistingCursorIcon, NtUserGetClipboardFormatName, NtUserGetClipboardOwner, NtUserGetClipboardSequenceNumber, diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 01da03c5a6f..70d310646ef 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -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: diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index 03ab1ff885c..2dc75d65f9e 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -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 diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 34b3b545129..e13de0dc7a8 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -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 */ diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 277d523e3c5..7b58f33f05c 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -99,6 +99,15 @@ void set_user_handle_ptr( HANDLE handle, struct user_object *ptr ) InterlockedExchangePointer( &user_handles[index], ptr ); } +/*********************************************************************** + * release_user_handle_ptr + */ +void release_user_handle_ptr( void *ptr ) +{ + assert( ptr && ptr != OBJ_OTHER_PROCESS ); + user_unlock(); +} + /*********************************************************************** * free_user_handle */ diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c index 922e5a26b00..e4aa668b756 100644 --- a/dlls/win32u/wrappers.c +++ b/dlls/win32u/wrappers.c @@ -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; diff --git a/dlls/wow64win/syscall.h b/dlls/wow64win/syscall.h index 22140c33f80..0141a216ee9 100644 --- a/dlls/wow64win/syscall.h +++ b/dlls/wow64win/syscall.h @@ -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 ) \ diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index a2be5fedb36..cd345429af7 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -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 ); diff --git a/include/ntuser.h b/include/ntuser.h index cfd0d1a74d3..4f72186754c 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -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);