win32u: Move cursor icon handle management from user32.

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:53:11 +01:00 committed by Alexandre Julliard
parent 018f8014a3
commit bb895f4f59
16 changed files with 339 additions and 238 deletions

View File

@ -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 );
}

View File

@ -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);

View File

@ -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,
};

View File

@ -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;
}

View File

@ -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,

View File

@ -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,

View File

@ -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 */

View File

@ -108,6 +108,7 @@ static void * const syscalls[] =
NtUserCloseWindowStation,
NtUserCreateDesktopEx,
NtUserCreateWindowStation,
NtUserFindExistingCursorIcon,
NtUserGetClipboardFormatName,
NtUserGetClipboardOwner,
NtUserGetClipboardSequenceNumber,

View File

@ -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:

View File

@ -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

View File

@ -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 */

View File

@ -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
*/

View File

@ -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;

View File

@ -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 ) \

View File

@ -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 );

View File

@ -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);