From: Jacek Caban jacek@codeweavers.com
--- dlls/win32u/Makefile.in | 1 + dlls/win32u/imm.c | 148 ++++++++++++++++++++++++++++++++++++++++ dlls/win32u/syscall.c | 4 ++ dlls/win32u/win32u.spec | 8 +-- dlls/wow64win/syscall.h | 4 ++ dlls/wow64win/user.c | 31 +++++++++ include/ntuser.h | 13 ++++ 7 files changed, 205 insertions(+), 4 deletions(-) create mode 100644 dlls/win32u/imm.c
diff --git a/dlls/win32u/Makefile.in b/dlls/win32u/Makefile.in index 153f5f45d9f..692b2d5c9f2 100644 --- a/dlls/win32u/Makefile.in +++ b/dlls/win32u/Makefile.in @@ -32,6 +32,7 @@ C_SRCS = \ freetype.c \ gdiobj.c \ hook.c \ + imm.c \ input.c \ main.c \ mapping.c \ diff --git a/dlls/win32u/imm.c b/dlls/win32u/imm.c new file mode 100644 index 00000000000..8778ea4f514 --- /dev/null +++ b/dlls/win32u/imm.c @@ -0,0 +1,148 @@ +/* + * Input Context implementation + * + * Copyright 2022 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#if 0 +#pragma makedep unix +#endif + +#include "win32u_private.h" +#include "ntuser_private.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(imm); + + +struct imc +{ + struct user_object obj; + DWORD thread_id; + UINT_PTR client_ptr; +}; + + +static struct imc *get_imc_ptr( HIMC handle ) +{ + struct imc *imc = get_user_handle_ptr( handle, NTUSER_OBJ_IMC ); + if (imc && imc != OBJ_OTHER_PROCESS) return imc; + WARN( "invalid handle %p\n", handle ); + SetLastError( ERROR_INVALID_HANDLE ); + return NULL; +} + +static void release_imc_ptr( struct imc *imc ) +{ + release_user_handle_ptr( imc ); +} + +/****************************************************************************** + * NtUserCreateInputContext (win32u.@) + */ +HIMC WINAPI NtUserCreateInputContext( UINT_PTR client_ptr ) +{ + struct imc *imc; + HIMC handle; + + if (!(imc = malloc( sizeof(*imc) ))) return 0; + imc->client_ptr = client_ptr; + imc->thread_id = GetCurrentThreadId(); + if (!(handle = alloc_user_handle( &imc->obj, NTUSER_OBJ_IMC ))) + { + free( imc ); + return 0; + } + + TRACE( "%lx returning %p\n", client_ptr, handle ); + return handle; +} + +/****************************************************************************** + * NtUserDestroyInputContext (win32u.@) + */ +BOOL WINAPI NtUserDestroyInputContext( HIMC handle ) +{ + struct imc *imc; + + TRACE( "%p\n", handle ); + + if (!(imc = free_user_handle( handle, NTUSER_OBJ_IMC ))) return FALSE; + if (imc == OBJ_OTHER_PROCESS) + { + FIXME( "other process handle %p\n", handle ); + return FALSE; + } + free( imc ); + return TRUE; +} + +/****************************************************************************** + * NtUserUpdateInputContext (win32u.@) + */ +BOOL WINAPI NtUserUpdateInputContext( HIMC handle, UINT attr, UINT_PTR value ) +{ + struct imc *imc; + BOOL ret = TRUE; + + TRACE( "%p %u %lx\n", handle, attr, value ); + + if (!(imc = get_imc_ptr( handle ))) return FALSE; + + switch (attr) + { + case NtUserInputContextClientPtr: + imc->client_ptr = value; + break; + + default: + FIXME( "unknown attr %u\n", attr ); + ret = FALSE; + }; + + release_imc_ptr( imc ); + return ret; +} + +/****************************************************************************** + * NtUserQueryInputContext (win32u.@) + */ +UINT_PTR WINAPI NtUserQueryInputContext( HIMC handle, UINT attr ) +{ + struct imc *imc; + UINT_PTR ret; + + if (!(imc = get_imc_ptr( handle ))) return FALSE; + + switch (attr) + { + case NtUserInputContextClientPtr: + ret = imc->client_ptr; + break; + + case NtUserInputContextThreadId: + ret = imc->thread_id; + break; + + default: + FIXME( "unknown attr %u\n", attr ); + ret = 0; + }; + + release_imc_ptr( imc ); + return ret; +} diff --git a/dlls/win32u/syscall.c b/dlls/win32u/syscall.c index e68519f15e5..5ba65e08de0 100644 --- a/dlls/win32u/syscall.c +++ b/dlls/win32u/syscall.c @@ -111,9 +111,11 @@ static void * const syscalls[] = NtUserCopyAcceleratorTable, NtUserCreateAcceleratorTable, NtUserCreateDesktopEx, + NtUserCreateInputContext, NtUserCreateWindowStation, NtUserDeleteMenu, NtUserDestroyAcceleratorTable, + NtUserDestroyInputContext, NtUserEndMenu, NtUserFindExistingCursorIcon, NtUserFindWindowEx, @@ -163,6 +165,7 @@ static void * const syscalls[] = NtUserOpenDesktop, NtUserOpenInputDesktop, NtUserOpenWindowStation, + NtUserQueryInputContext, NtUserRegisterRawInputDevices, NtUserRemoveClipboardFormatListener, NtUserRemoveMenu, @@ -183,6 +186,7 @@ static void * const syscalls[] = NtUserThunkedMenuItemInfo, NtUserUnhookWinEvent, NtUserUnhookWindowsHookEx, + NtUserUpdateInputContext, NtUserWindowFromDC, };
diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index a2369364877..87447e59a28 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -811,7 +811,7 @@ @ stub NtUserCreateDCompositionHwndTarget @ stdcall -syscall NtUserCreateDesktopEx(ptr ptr ptr long long long) @ stub NtUserCreateEmptyCursorObject -@ stub NtUserCreateInputContext +@ stdcall -syscall NtUserCreateInputContext(ptr) @ stub NtUserCreateLocalMemHandle @ stub NtUserCreatePalmRejectionDelayZone @ stdcall NtUserCreateWindowEx(long ptr ptr ptr long long long long long long long long ptr long long long long) @@ -831,7 +831,7 @@ @ stub NtUserDestroyActivationObject @ stdcall NtUserDestroyCursor(long long) @ stub NtUserDestroyDCompositionHwndTarget -@ stub NtUserDestroyInputContext +@ stdcall -syscall NtUserDestroyInputContext(long) @ stdcall NtUserDestroyMenu(long) @ stub NtUserDestroyPalmRejectionDelayZone @ stdcall NtUserDestroyWindow(long) @@ -1114,7 +1114,7 @@ @ stub NtUserQueryBSDRWindow @ stub NtUserQueryDisplayConfig @ stub NtUserQueryInformationThread -@ stub NtUserQueryInputContext +@ stdcall -syscall NtUserQueryInputContext(long long) @ stub NtUserQuerySendMessage @ stub NtUserQueryWindow @ stub NtUserRealChildWindowFromPoint @@ -1293,7 +1293,7 @@ @ stub NtUserUnregisterSessionPort @ stub NtUserUnregisterUserApiHook @ stub NtUserUpdateDefaultDesktopThumbnail -@ stub NtUserUpdateInputContext +@ stdcall -syscall NtUserUpdateInputContext(long long ptr) @ stub NtUserUpdateInstance @ stdcall NtUserUpdateLayeredWindow(long long ptr ptr long ptr long ptr long ptr) @ stub NtUserUpdatePerUserSystemParameters diff --git a/dlls/wow64win/syscall.h b/dlls/wow64win/syscall.h index 30b6795f8e8..43e2bc8c838 100644 --- a/dlls/wow64win/syscall.h +++ b/dlls/wow64win/syscall.h @@ -98,9 +98,11 @@ SYSCALL_ENTRY( NtUserCopyAcceleratorTable ) \ SYSCALL_ENTRY( NtUserCreateAcceleratorTable ) \ SYSCALL_ENTRY( NtUserCreateDesktopEx ) \ + SYSCALL_ENTRY( NtUserCreateInputContext ) \ SYSCALL_ENTRY( NtUserCreateWindowStation ) \ SYSCALL_ENTRY( NtUserDeleteMenu ) \ SYSCALL_ENTRY( NtUserDestroyAcceleratorTable ) \ + SYSCALL_ENTRY( NtUserDestroyInputContext ) \ SYSCALL_ENTRY( NtUserEndMenu ) \ SYSCALL_ENTRY( NtUserFindExistingCursorIcon ) \ SYSCALL_ENTRY( NtUserFindWindowEx ) \ @@ -150,6 +152,7 @@ SYSCALL_ENTRY( NtUserOpenDesktop ) \ SYSCALL_ENTRY( NtUserOpenInputDesktop ) \ SYSCALL_ENTRY( NtUserOpenWindowStation ) \ + SYSCALL_ENTRY( NtUserQueryInputContext ) \ SYSCALL_ENTRY( NtUserRegisterRawInputDevices ) \ SYSCALL_ENTRY( NtUserRemoveClipboardFormatListener ) \ SYSCALL_ENTRY( NtUserRemoveMenu ) \ @@ -170,6 +173,7 @@ SYSCALL_ENTRY( NtUserThunkedMenuItemInfo ) \ SYSCALL_ENTRY( NtUserUnhookWinEvent ) \ SYSCALL_ENTRY( NtUserUnhookWindowsHookEx ) \ + SYSCALL_ENTRY( NtUserUpdateInputContext ) \ SYSCALL_ENTRY( NtUserWindowFromDC )
#endif /* __WOW64WIN_SYSCALL_H */ diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index 2ed13ac424a..cd5a805bea7 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -226,6 +226,13 @@ NTSTATUS WINAPI wow64_NtUserCreateDesktopEx( UINT *args ) return HandleToUlong( ret ); }
+NTSTATUS WINAPI wow64_NtUserCreateInputContext( UINT *args ) +{ + UINT_PTR client_ptr = get_ulong( &args ); + + return HandleToUlong( NtUserCreateInputContext( client_ptr )); +} + NTSTATUS WINAPI wow64_NtUserCreateWindowStation( UINT *args ) { OBJECT_ATTRIBUTES32 *attr32 = get_ptr( &args ); @@ -258,6 +265,13 @@ NTSTATUS WINAPI wow64_NtUserDestroyAcceleratorTable( UINT *args ) return NtUserDestroyAcceleratorTable( handle ); }
+NTSTATUS WINAPI wow64_NtUserDestroyInputContext( UINT *args ) +{ + HIMC handle = get_handle( &args ); + + return NtUserDestroyInputContext( handle ); +} + NTSTATUS WINAPI wow64_NtUserEndMenu( UINT *args ) { return NtUserEndMenu(); @@ -848,6 +862,14 @@ NTSTATUS WINAPI wow64_NtUserOpenWindowStation( UINT *args ) return HandleToUlong( NtUserOpenWindowStation( objattr_32to64( &attr, attr32 ), access )); }
+NTSTATUS WINAPI wow64_NtUserQueryInputContext( UINT *args ) +{ + HIMC handle = get_handle( &args ); + UINT attr = get_ulong( &args ); + + return NtUserQueryInputContext( handle, attr ); +} + NTSTATUS WINAPI wow64_NtUserRegisterRawInputDevices( UINT *args ) { const RAWINPUTDEVICE32 *devices32 = get_ptr( &args ); @@ -1105,6 +1127,15 @@ NTSTATUS WINAPI wow64_NtUserUnhookWindowsHookEx( UINT *args ) return NtUserUnhookWindowsHookEx( handle ); }
+NTSTATUS WINAPI wow64_NtUserUpdateInputContext( UINT *args ) +{ + HIMC handle = get_handle( &args ); + UINT attr = get_ulong( &args ); + UINT_PTR value = get_ulong( &args ); + + return NtUserUpdateInputContext( handle, attr, value ); +} + NTSTATUS WINAPI wow64_NtUserWindowFromDC( UINT *args ) { HDC hdc = get_handle( &args ); diff --git a/include/ntuser.h b/include/ntuser.h index 34701d21533..41ed5a779e5 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -21,6 +21,7 @@
#include <winuser.h> #include <wingdi.h> +#include <imm.h> #include <winternl.h>
/* KernelCallbackTable codes, not compatible with Windows */ @@ -265,6 +266,7 @@ struct send_message_callback_params #define NTUSER_OBJ_WINPOS 0x04 #define NTUSER_OBJ_ACCEL 0x08 #define NTUSER_OBJ_HOOK 0x0f +#define NTUSER_OBJ_IMC 0x11
/* NtUserScrollWindowEx flag */ #define SW_NODCCACHE 0x8000 @@ -358,6 +360,13 @@ struct draw_scroll_bar_params BOOL vertical; };
+/* NtUserUpdateInputContext param, not compatible with Window */ +enum input_context_attr +{ + NtUserInputContextClientPtr, + NtUserInputContextThreadId, +}; + /* internal messages codes */ enum wine_internal_message { @@ -558,6 +567,7 @@ BOOL WINAPI NtUserCreateCaret( HWND hwnd, HBITMAP bitmap, int width, int heig HDESK WINAPI NtUserCreateDesktopEx( OBJECT_ATTRIBUTES *attr, UNICODE_STRING *device, DEVMODEW *devmode, DWORD flags, ACCESS_MASK access, ULONG heap_size ); +HIMC WINAPI NtUserCreateInputContext( UINT_PTR client_ptr ); HWND WINAPI NtUserCreateWindowEx( DWORD ex_style, UNICODE_STRING *class_name, UNICODE_STRING *version, UNICODE_STRING *window_name, DWORD style, INT x, INT y, INT cx, INT cy, @@ -570,6 +580,7 @@ HDWP WINAPI NtUserDeferWindowPosAndBand( HDWP hdwp, HWND hwnd, HWND after, IN BOOL WINAPI NtUserDeleteMenu( HMENU menu, UINT id, UINT flags ); BOOL WINAPI NtUserDestroyAcceleratorTable( HACCEL handle ); BOOL WINAPI NtUserDestroyCursor( HCURSOR cursor, ULONG arg ); +BOOL WINAPI NtUserDestroyInputContext( HIMC handle ); BOOL WINAPI NtUserDestroyMenu( HMENU menu ); BOOL WINAPI NtUserDestroyWindow( HWND hwnd ); LRESULT WINAPI NtUserDispatchMessage( const MSG *msg ); @@ -686,6 +697,7 @@ HDESK WINAPI NtUserOpenInputDesktop( DWORD flags, BOOL inherit, ACCESS_MASK ac BOOL WINAPI NtUserPeekMessage( MSG *msg_out, HWND hwnd, UINT first, UINT last, UINT flags ); BOOL WINAPI NtUserPostMessage( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ); BOOL WINAPI NtUserPostThreadMessage( DWORD thread, UINT msg, WPARAM wparam, LPARAM lparam ); +UINT_PTR WINAPI NtUserQueryInputContext( HIMC handle, UINT attr ); BOOL WINAPI NtUserRedrawWindow( HWND hwnd, const RECT *rect, HRGN hrgn, UINT flags ); ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING *name, UNICODE_STRING *version, struct client_menu_name *client_menu_name, DWORD fnid, DWORD flags, @@ -763,6 +775,7 @@ BOOL WINAPI NtUserUnhookWindowsHookEx( HHOOK handle ); BOOL WINAPI NtUserUnregisterClass( UNICODE_STRING *name, HINSTANCE instance, struct client_menu_name *client_menu_name ); BOOL WINAPI NtUserUnregisterHotKey( HWND hwnd, INT id ); +BOOL WINAPI NtUserUpdateInputContext( HIMC handle, UINT attr, UINT_PTR value ); BOOL WINAPI NtUserUpdateLayeredWindow( HWND hwnd, HDC hdc_dst, const POINT *pts_dst, const SIZE *size, HDC hdc_src, const POINT *pts_src, COLORREF key, const BLENDFUNCTION *blend, DWORD flags, const RECT *dirty );