win32u: Move NtUserNotifyWinEvent implementation 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-16 12:30:12 +01:00 committed by Alexandre Julliard
parent d76b38ffb6
commit 01b3674247
12 changed files with 148 additions and 154 deletions

View File

@ -74,7 +74,7 @@ static HWND set_focus_window( HWND hwnd )
SendMessageW( ime_default, WM_IME_INTERNAL, IME_INTERNAL_ACTIVATE, (LPARAM)hwnd );
if (previous)
NotifyWinEvent( EVENT_OBJECT_FOCUS, hwnd, OBJID_CLIENT, 0 );
NtUserNotifyWinEvent( EVENT_OBJECT_FOCUS, hwnd, OBJID_CLIENT, 0 );
SendMessageW( hwnd, WM_SETFOCUS, (WPARAM)previous, 0 );
}

View File

@ -726,161 +726,30 @@ HWINEVENTHOOK WINAPI SetWinEventHook(DWORD event_min, DWORD event_max,
return NtUserSetWinEventHook( event_min, event_max, inst, &str, proc, pid, tid, flags );
}
static inline BOOL find_first_hook(DWORD id, DWORD event, HWND hwnd, LONG object_id,
LONG child_id, struct hook_info *info)
BOOL WINAPI User32CallWinEventHook( const struct win_hook_proc_params *params, ULONG size )
{
struct user_thread_info *thread_info = get_user_thread_info();
BOOL ret;
WINEVENTPROC proc = params->proc;
HMODULE free_module = 0;
if (!HOOK_IsHooked( id ))
{
TRACE( "skipping hook %s mask %x\n", hook_names[id-WH_MINHOOK], thread_info->active_hooks );
return FALSE;
}
USER_CheckNotLock(); /* FIXME: move to NtUserNotifyWinEvent */
SERVER_START_REQ( start_hook_chain )
{
req->id = id;
req->event = event;
req->window = wine_server_user_handle( hwnd );
req->object_id = object_id;
req->child_id = child_id;
wine_server_set_reply( req, info->module, sizeof(info->module)-sizeof(WCHAR) );
ret = !wine_server_call( req );
if (ret)
{
info->module[wine_server_reply_size(req) / sizeof(WCHAR)] = 0;
info->handle = wine_server_ptr_handle( reply->handle );
info->proc = wine_server_get_ptr( reply->proc );
info->tid = reply->tid;
thread_info->active_hooks = reply->active_hooks;
}
}
SERVER_END_REQ;
return ret && (info->tid || info->proc);
if (params->module[0] && !(proc = get_hook_proc( proc, params->module, &free_module ))) return FALSE;
TRACE_(relay)( "\1Call winevent hook proc %p (hhook=%p,event=%x,hwnd=%p,object_id=%x,child_id=%x,tid=%04x,time=%x)\n",
proc, params->handle, params->event, params->hwnd, params->object_id,
params->child_id, GetCurrentThreadId(), GetCurrentTime() );
proc( params->handle, params->event, params->hwnd, params->object_id, params->child_id,
GetCurrentThreadId(), GetCurrentTime() );
TRACE_(relay)( "\1Ret winevent hook proc %p (hhook=%p,event=%x,hwnd=%p,object_id=%x,child_id=%x,tid=%04x,time=%x)\n",
proc, params->handle, params->event, params->hwnd, params->object_id,
params->child_id, GetCurrentThreadId(), GetCurrentTime() );
if (free_module) FreeLibrary( free_module );
return TRUE;
}
static inline BOOL find_next_hook(DWORD event, HWND hwnd, LONG object_id,
LONG child_id, struct hook_info *info)
{
BOOL ret;
SERVER_START_REQ( get_hook_info )
{
req->handle = wine_server_user_handle( info->handle );
req->get_next = 1;
req->event = event;
req->window = wine_server_user_handle( hwnd );
req->object_id = object_id;
req->child_id = child_id;
wine_server_set_reply( req, info->module, sizeof(info->module)-sizeof(WCHAR) );
ret = !wine_server_call( req );
if (ret)
{
info->module[wine_server_reply_size(req) / sizeof(WCHAR)] = 0;
info->handle = wine_server_ptr_handle( reply->handle );
info->proc = wine_server_get_ptr( reply->proc );
info->tid = reply->tid;
}
}
SERVER_END_REQ;
return ret;
}
static inline void find_hook_close(DWORD id)
{
SERVER_START_REQ( finish_hook_chain )
{
req->id = id;
wine_server_call( req );
}
SERVER_END_REQ;
}
/***********************************************************************
* NotifyWinEvent [USER32.@]
*
* Inform the OS that an event has occurred.
*
* PARAMS
* event [I] Id of the event
* hwnd [I] Window holding the object that created the event
* object_id [I] Type of object that created the event
* child_id [I] Child object of nId, or CHILDID_SELF.
*
* RETURNS
* Nothing.
*/
void WINAPI NotifyWinEvent(DWORD event, HWND hwnd, LONG object_id, LONG child_id)
{
struct hook_info info;
TRACE("%04x,%p,%d,%d\n", event, hwnd, object_id, child_id);
if (!hwnd)
{
SetLastError(ERROR_INVALID_WINDOW_HANDLE);
return;
}
USER_CheckNotLock();
#if 0
if (event & 0x80000000)
{
/* FIXME: on 64-bit platforms we need to invent some other way for
* passing parameters, nId and nChildId can't hold full [W|L]PARAM.
* struct call_hook *hook = (LRESULT *)hWnd;
* wparam = hook->wparam;
* lparam = hook->lparam;
*/
LRESULT *ret = (LRESULT *)hwnd;
INT id, code, unicode;
id = (dwEvent & 0x7fff0000) >> 16;
code = event & 0x7fff;
unicode = event & 0x8000;
*ret = HOOK_CallHooks(id, code, object_id, child_id, unicode);
return;
}
#endif
if (!find_first_hook(WH_WINEVENT, event, hwnd, object_id, child_id, &info)) return;
do
{
WINEVENTPROC proc = info.proc;
if (proc)
{
HMODULE free_module = 0;
TRACE( "calling WH_WINEVENT hook %p event %x hwnd %p %x %x module %s\n",
proc, event, hwnd, object_id, child_id, debugstr_w(info.module) );
if (!info.module[0] || (proc = get_hook_proc( proc, info.module, &free_module )) != NULL)
{
TRACE_(relay)( "\1Call winevent hook proc %p (hhook=%p,event=%x,hwnd=%p,object_id=%x,child_id=%x,tid=%04x,time=%x)\n",
proc, info.handle, event, hwnd, object_id,
child_id, GetCurrentThreadId(), GetCurrentTime());
proc( info.handle, event, hwnd, object_id, child_id,
GetCurrentThreadId(), GetCurrentTime());
TRACE_(relay)( "\1Ret winevent hook proc %p (hhook=%p,event=%x,hwnd=%p,object_id=%x,child_id=%x,tid=%04x,time=%x)\n",
proc, info.handle, event, hwnd, object_id,
child_id, GetCurrentThreadId(), GetCurrentTime());
if (free_module) FreeLibrary(free_module);
}
}
else
break;
}
while (find_next_hook(event, hwnd, object_id, child_id, &info));
find_hook_close(WH_WINEVENT);
}
/***********************************************************************
* IsWinEventHookInstalled [USER32.@]
*

View File

@ -545,7 +545,7 @@
@ stdcall MoveWindow(long long long long long long)
@ stdcall MsgWaitForMultipleObjects(long ptr long long long)
@ stdcall MsgWaitForMultipleObjectsEx(long ptr long long long)
@ stdcall NotifyWinEvent(long long long long)
@ stdcall NotifyWinEvent(long long long long) NtUserNotifyWinEvent
@ stdcall OemKeyScan(long)
@ stdcall OemToCharA(str ptr)
@ stdcall OemToCharBuffA(ptr ptr long)

View File

@ -212,6 +212,7 @@ static void dpiaware_init(void)
static const void *kernel_callback_table[NtUserCallCount] =
{
User32CallEnumDisplayMonitor,
User32CallWinEventHook,
};

View File

@ -194,6 +194,7 @@ extern const WCHAR *CLASS_GetVersionedName(const WCHAR *classname, UINT *basenam
/* kernel callbacks */
BOOL WINAPI User32CallEnumDisplayMonitor( struct enum_display_monitor_params *params, ULONG size );
BOOL WINAPI User32CallWinEventHook( const struct win_hook_proc_params *params, ULONG size );
/* message spy definitions */

View File

@ -1777,7 +1777,7 @@ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module,
if (!USER_Driver->pCreateWindow( hwnd )) goto failed;
NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0);
NtUserNotifyWinEvent( EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0 );
/* send the size messages */

View File

@ -33,6 +33,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(hook);
#define WH_WINEVENT (WH_MAXHOOK+1)
static BOOL is_hooked( INT id )
{
struct user_thread_info *thread_info = get_user_thread_info();
if (!thread_info->active_hooks) return TRUE;
return (thread_info->active_hooks & (1 << (id - WH_MINHOOK))) != 0;
}
/***********************************************************************
* NtUserSetWinEventHook (win32u.@)
*/
@ -102,3 +110,91 @@ BOOL WINAPI NtUserUnhookWinEvent( HWINEVENTHOOK handle )
SERVER_END_REQ;
return ret;
}
/***********************************************************************
* NtUserNotifyWinEvent (win32u.@)
*/
void WINAPI NtUserNotifyWinEvent( DWORD event, HWND hwnd, LONG object_id, LONG child_id )
{
struct user_thread_info *thread_info = get_user_thread_info();
struct win_hook_proc_params info;
void *ret_ptr;
ULONG ret_len;
BOOL ret;
TRACE( "%04x, %p, %d, %d\n", event, hwnd, object_id, child_id );
if (!hwnd)
{
SetLastError( ERROR_INVALID_WINDOW_HANDLE );
return;
}
if (!is_hooked( WH_WINEVENT ))
{
TRACE( "skipping hook mask %x\n", thread_info->active_hooks );
return;
}
info.event = event;
info.hwnd = hwnd;
info.object_id = object_id;
info.child_id = child_id;
SERVER_START_REQ( start_hook_chain )
{
req->id = WH_WINEVENT;
req->event = event;
req->window = wine_server_user_handle( hwnd );
req->object_id = object_id;
req->child_id = child_id;
wine_server_set_reply( req, info.module, sizeof(info.module) - sizeof(WCHAR) );
ret = !wine_server_call( req ) && reply->proc;
if (ret)
{
info.module[wine_server_reply_size(req) / sizeof(WCHAR)] = 0;
info.handle = wine_server_ptr_handle( reply->handle );
info.proc = wine_server_get_ptr( reply->proc );
thread_info->active_hooks = reply->active_hooks;
}
}
SERVER_END_REQ;
if (!ret) return;
do
{
TRACE( "calling WH_WINEVENT hook %p event %x hwnd %p %x %x module %s\n",
info.proc, event, hwnd, object_id, child_id, debugstr_w(info.module) );
KeUserModeCallback( NtUserCallWinEventHook, &info,
FIELD_OFFSET( struct win_hook_proc_params, module[lstrlenW(info.module) + 1] ),
&ret_ptr, &ret_len );
SERVER_START_REQ( get_hook_info )
{
req->handle = wine_server_user_handle( info.handle );
req->get_next = 1;
req->event = event;
req->window = wine_server_user_handle( hwnd );
req->object_id = object_id;
req->child_id = child_id;
wine_server_set_reply( req, info.module, sizeof(info.module) - sizeof(WCHAR) );
ret = !wine_server_call( req ) && reply->proc;
if (ret)
{
info.module[wine_server_reply_size(req) / sizeof(WCHAR)] = 0;
info.handle = wine_server_ptr_handle( reply->handle );
info.proc = wine_server_get_ptr( reply->proc );
}
}
SERVER_END_REQ;
}
while (ret);
SERVER_START_REQ( finish_hook_chain )
{
req->id = WH_WINEVENT;
wine_server_call( req );
}
SERVER_END_REQ;
}

View File

@ -128,6 +128,7 @@ static void * const syscalls[] =
NtUserGetProp,
NtUserGetSystemDpiForProcess,
NtUserGetThreadDesktop,
NtUserNotifyWinEvent,
NtUserOpenDesktop,
NtUserOpenInputDesktop,
NtUserOpenWindowStation,

View File

@ -1089,7 +1089,7 @@
@ stub NtUserNavigateFocus
@ stub NtUserNotifyIMEStatus
@ stub NtUserNotifyProcessCreate
@ stub NtUserNotifyWinEvent
@ stdcall -syscall NtUserNotifyWinEvent(long long long long)
@ stub NtUserOpenClipboard
@ stdcall -syscall NtUserOpenDesktop(ptr long long)
@ stdcall -syscall NtUserOpenInputDesktop(long long long)

View File

@ -115,6 +115,7 @@
SYSCALL_ENTRY( NtUserGetProp ) \
SYSCALL_ENTRY( NtUserGetSystemDpiForProcess ) \
SYSCALL_ENTRY( NtUserGetThreadDesktop ) \
SYSCALL_ENTRY( NtUserNotifyWinEvent ) \
SYSCALL_ENTRY( NtUserOpenDesktop ) \
SYSCALL_ENTRY( NtUserOpenInputDesktop ) \
SYSCALL_ENTRY( NtUserOpenWindowStation ) \

View File

@ -356,6 +356,17 @@ NTSTATUS WINAPI wow64_NtUserGetDoubleClickTime( UINT *args )
return NtUserGetDoubleClickTime();
}
NTSTATUS WINAPI wow64_NtUserNotifyWinEvent( UINT *args )
{
DWORD event = get_ulong( &args );
HWND hwnd = get_handle( &args );
LONG object_id = get_ulong( &args );
LONG child_id = get_ulong( &args );
NtUserNotifyWinEvent( event, hwnd, object_id, child_id );
return 0;
}
NTSTATUS WINAPI wow64_NtUserSetWinEventHook( UINT *args )
{
DWORD event_min = get_ulong( &args );

View File

@ -27,6 +27,7 @@
enum
{
NtUserCallEnumDisplayMonitor,
NtUserCallWinEventHook,
NtUserCallVulkanDebugReportCallback,
NtUserCallVulkanDebugUtilsCallback,
NtUserCallCount
@ -42,6 +43,18 @@ struct enum_display_monitor_params
LPARAM lparam;
};
/* NtUserCallWinEventHook params */
struct win_hook_proc_params
{
DWORD event;
HWND hwnd;
LONG object_id;
LONG child_id;
void *handle;
WINEVENTPROC proc;
WCHAR module[MAX_PATH];
};
/* process DPI awareness contexts */
#define NTUSER_DPI_UNAWARE 0x00006010
#define NTUSER_DPI_SYSTEM_AWARE 0x00006011
@ -163,6 +176,7 @@ HDESK WINAPI NtUserGetThreadDesktop( DWORD thread );
BOOL WINAPI NtUserGetUpdatedClipboardFormats( UINT *formats, UINT size, UINT *out_size );
BOOL WINAPI NtUserIsClipboardFormatAvailable( UINT format );
UINT WINAPI NtUserMapVirtualKeyEx( UINT code, UINT type, HKL layout );
void WINAPI NtUserNotifyWinEvent( DWORD event, HWND hwnd, LONG object_id, LONG child_id );
HWINSTA WINAPI NtUserOpenWindowStation( OBJECT_ATTRIBUTES *attr, ACCESS_MASK access );
BOOL WINAPI NtUserSetObjectInformation( HANDLE handle, INT index, void *info, DWORD len );
HDESK WINAPI NtUserOpenDesktop( OBJECT_ATTRIBUTES *attr, DWORD flags, ACCESS_MASK access );