-- v2: win32u: Implement NtUserBuildHimcList syscall. win32u: Introduce new next_user_handle_ptr helper. win32u/tests: Test NtUserBuildHimcList syscall. win32u: Stub NtUserBuildHimcList syscall. win32u/tests: Test NtUserCreateInputContext (et al.).
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/tests/win32u.c | 98 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+)
diff --git a/dlls/win32u/tests/win32u.c b/dlls/win32u/tests/win32u.c index 60ef2d38b5f..51a67a697f5 100644 --- a/dlls/win32u/tests/win32u.c +++ b/dlls/win32u/tests/win32u.c @@ -221,6 +221,103 @@ static void test_class(void)
}
+static void test_NtUserCreateInputContext(void) +{ + UINT_PTR value, attr3; + HIMC himc; + UINT ret; + + SetLastError( 0xdeadbeef ); + himc = NtUserCreateInputContext( 0 ); + todo_wine + ok( !himc, "NtUserCreateInputContext succeeded\n" ); + todo_wine + ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + ret = NtUserDestroyInputContext( himc ); + todo_wine + ok( !ret, "NtUserDestroyInputContext succeeded\n" ); + todo_wine + ok( GetLastError() == ERROR_INVALID_HANDLE, "got error %lu\n", GetLastError() ); + + + himc = NtUserCreateInputContext( 0xdeadbeef ); + ok( !!himc, "NtUserCreateInputContext failed, error %lu\n", GetLastError() ); + + SetLastError( 0xdeadbeef ); + value = NtUserQueryInputContext( himc, 0 ); + todo_wine + ok( value == GetCurrentProcessId(), "NtUserQueryInputContext 0 returned %#Ix\n", value ); + ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + value = NtUserQueryInputContext( himc, 1 ); + ok( value == GetCurrentThreadId(), "NtUserQueryInputContext 1 returned %#Ix\n", value ); + ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + value = NtUserQueryInputContext( himc, 2 ); + ok( value == 0, "NtUserQueryInputContext 2 returned %#Ix\n", value ); + ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + value = NtUserQueryInputContext( himc, 3 ); + todo_wine + ok( !!value, "NtUserQueryInputContext 3 returned %#Ix\n", value ); + ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() ); + attr3 = value; + SetLastError( 0xdeadbeef ); + value = NtUserQueryInputContext( himc, 4 ); + todo_wine + ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() ); + + SetLastError( 0xdeadbeef ); + ret = NtUserUpdateInputContext( himc, 0, 0 ); + todo_wine + ok( !ret, "NtUserUpdateInputContext 0 succeeded\n" ); + todo_wine + ok( GetLastError() == ERROR_ALREADY_INITIALIZED, "got error %lu\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + ret = NtUserUpdateInputContext( himc, 1, 0xdeadbeef ); + todo_wine + ok( !!ret, "NtUserUpdateInputContext 1 failed\n" ); + ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + ret = NtUserUpdateInputContext( himc, 2, 0xdeadbeef ); + ok( !ret, "NtUserUpdateInputContext 2 succeeded\n" ); + ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + ret = NtUserUpdateInputContext( himc, 3, 0x0badf00d ); + ok( !ret, "NtUserUpdateInputContext 3 succeeded\n" ); + ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + ret = NtUserUpdateInputContext( himc, 4, 0xdeadbeef ); + ok( !ret, "NtUserUpdateInputContext 4 succeeded\n" ); + ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() ); + + SetLastError( 0xdeadbeef ); + value = NtUserQueryInputContext( himc, 0 ); + todo_wine + ok( value == GetCurrentProcessId(), "NtUserQueryInputContext 0 returned %#Ix\n", value ); + ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + value = NtUserQueryInputContext( himc, 1 ); + ok( value == GetCurrentThreadId(), "NtUserQueryInputContext 1 returned %#Ix\n", value ); + ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + value = NtUserQueryInputContext( himc, 2 ); + ok( value == 0, "NtUserQueryInputContext 2 returned %#Ix\n", value ); + ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + value = NtUserQueryInputContext( himc, 3 ); + ok( value == attr3, "NtUserQueryInputContext 3 returned %#Ix\n", value ); + ok( GetLastError() == 0xdeadbeef, "got error %lu\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + value = NtUserQueryInputContext( himc, 4 ); + todo_wine + ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() ); + + ret = NtUserDestroyInputContext( himc ); + ok( !!ret, "NtUserDestroyInputContext failed, error %lu\n", GetLastError() ); +} + static BOOL WINAPI count_win( HWND hwnd, LPARAM lparam ) { ULONG *cnt = (ULONG *)lparam; @@ -1148,6 +1245,7 @@ START_TEST(win32u) test_NtUserEnumDisplayDevices(); test_window_props(); test_class(); + test_NtUserCreateInputContext(); test_NtUserBuildHwndList(); test_cursoricon(); test_message_call();
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/imm.c | 11 +++++++++++ dlls/win32u/syscall.c | 1 + dlls/win32u/win32u.spec | 2 +- dlls/wow64win/syscall.h | 1 + dlls/wow64win/user.c | 19 +++++++++++++++++++ include/ntuser.h | 1 + 6 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/dlls/win32u/imm.c b/dlls/win32u/imm.c index 1ccc09c97b2..dc10eedd903 100644 --- a/dlls/win32u/imm.c +++ b/dlls/win32u/imm.c @@ -25,6 +25,8 @@ #endif
#include <pthread.h> +#include "ntstatus.h" +#define WIN32_NO_STATUS #include "win32u_private.h" #include "ntuser_private.h" #include "immdev.h" @@ -393,6 +395,15 @@ void cleanup_imm_thread(void) NtUserDestroyInputContext( UlongToHandle( thread_info->client_info.default_imc )); }
+/***************************************************************************** + * NtUserBuildHimcList (win32u.@) + */ +NTSTATUS WINAPI NtUserBuildHimcList( UINT thread_id, UINT count, HIMC *buffer, UINT *size ) +{ + FIXME( "thread_id %#x, count %u, buffer %p, size %p stub!\n", thread_id, count, buffer, size ); + return STATUS_NOT_IMPLEMENTED; +} + BOOL WINAPI DECLSPEC_HIDDEN ImmProcessKey( HWND hwnd, HKL hkl, UINT vkey, LPARAM key_data, DWORD unknown ) { struct imm_process_key_params params = diff --git a/dlls/win32u/syscall.c b/dlls/win32u/syscall.c index 9020aa01126..f93ba9b804b 100644 --- a/dlls/win32u/syscall.c +++ b/dlls/win32u/syscall.c @@ -106,6 +106,7 @@ static void * const syscalls[] = NtUserAssociateInputContext, NtUserAttachThreadInput, NtUserBeginPaint, + NtUserBuildHimcList, NtUserBuildHwndList, NtUserCallHwnd, NtUserCallHwndParam, diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index 6e1a0a51175..544f375d637 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -762,7 +762,7 @@ @ stub NtUserBitBltSysBmp @ stub NtUserBlockInput @ stub NtUserBroadcastThemeChangeEvent -@ stub NtUserBuildHimcList +@ stdcall -syscall NtUserBuildHimcList(long long ptr ptr) @ stdcall -syscall NtUserBuildHwndList(long long long long long long ptr ptr) @ stub NtUserBuildNameList @ stub NtUserBuildPropList diff --git a/dlls/wow64win/syscall.h b/dlls/wow64win/syscall.h index 4977013c595..7e2b7af7846 100644 --- a/dlls/wow64win/syscall.h +++ b/dlls/wow64win/syscall.h @@ -92,6 +92,7 @@ SYSCALL_ENTRY( NtUserAssociateInputContext ) \ SYSCALL_ENTRY( NtUserAttachThreadInput ) \ SYSCALL_ENTRY( NtUserBeginPaint ) \ + SYSCALL_ENTRY( NtUserBuildHimcList ) \ SYSCALL_ENTRY( NtUserBuildHwndList ) \ SYSCALL_ENTRY( NtUserCallHwnd ) \ SYSCALL_ENTRY( NtUserCallHwndParam ) \ diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index 2ce82907a88..e1ce2dd8321 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -1182,6 +1182,25 @@ NTSTATUS WINAPI wow64_NtUserBeginPaint( UINT *args ) return HandleToUlong( ret ); }
+NTSTATUS WINAPI wow64_NtUserBuildHimcList( UINT *args ) +{ + ULONG thread_id = get_ulong( &args ); + ULONG count = get_ulong( &args ); + UINT32 *buffer32 = get_ptr( &args ); + UINT *size = get_ptr( &args ); + + HIMC *buffer; + ULONG i; + NTSTATUS status; + + if (!(buffer = Wow64AllocateTemp( count * sizeof(*buffer) ))) return STATUS_NO_MEMORY; + + if ((status = NtUserBuildHimcList( thread_id, count, buffer, size ))) return status; + + for (i = 0; i < *size; i++) buffer32[i] = HandleToUlong( buffer[i] ); + return status; +} + NTSTATUS WINAPI wow64_NtUserBuildHwndList( UINT *args ) { HDESK desktop = get_handle( &args ); diff --git a/include/ntuser.h b/include/ntuser.h index 35ead9750c6..629f6353fa3 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -648,6 +648,7 @@ BOOL WINAPI NtUserAddClipboardFormatListener( HWND hwnd ); UINT WINAPI NtUserAssociateInputContext( HWND hwnd, HIMC ctx, ULONG flags ); BOOL WINAPI NtUserAttachThreadInput( DWORD from, DWORD to, BOOL attach ); HDC WINAPI NtUserBeginPaint( HWND hwnd, PAINTSTRUCT *ps ); +NTSTATUS WINAPI NtUserBuildHimcList( UINT thread_id, UINT count, HIMC *buffer, UINT *size ); NTSTATUS WINAPI NtUserBuildHwndList( HDESK desktop, ULONG unk2, ULONG unk3, ULONG unk4, ULONG thread_id, ULONG count, HWND *buffer, ULONG *size ); ULONG_PTR WINAPI NtUserCallHwnd( HWND hwnd, DWORD code );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/tests/win32u.c | 134 +++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+)
diff --git a/dlls/win32u/tests/win32u.c b/dlls/win32u/tests/win32u.c index 51a67a697f5..975716045cf 100644 --- a/dlls/win32u/tests/win32u.c +++ b/dlls/win32u/tests/win32u.c @@ -318,6 +318,139 @@ static void test_NtUserCreateInputContext(void) ok( !!ret, "NtUserDestroyInputContext failed, error %lu\n", GetLastError() ); }
+static int himc_compare( const void *a, const void *b ) +{ + return (UINT_PTR)*(HIMC *)a - (UINT_PTR)*(HIMC *)b; +} + +static DWORD CALLBACK test_NtUserBuildHimcList_thread( void *arg ) +{ + HIMC buf[8], *himc = arg; + NTSTATUS status; + UINT size; + + size = 0xdeadbeef; + memset( buf, 0xcd, sizeof(buf) ); + status = NtUserBuildHimcList( GetCurrentThreadId(), ARRAYSIZE( buf ), buf, &size ); + todo_wine + ok( !status, "NtUserBuildHimcList failed: %#lx\n", status ); + todo_wine + ok( size == 1, "size = %u\n", size ); + ok( !!buf[0], "buf[0] = %p\n", buf[0] ); + + todo_wine + ok( buf[0] != himc[0], "buf[0] = %p\n", buf[0] ); + ok( buf[0] != himc[1], "buf[0] = %p\n", buf[0] ); + himc[2] = buf[0]; + qsort( himc, 3, sizeof(*himc), himc_compare ); + + size = 0xdeadbeef; + memset( buf, 0xcd, sizeof(buf) ); + status = NtUserBuildHimcList( -1, ARRAYSIZE( buf ), buf, &size ); + todo_wine + ok( !status, "NtUserBuildHimcList failed: %#lx\n", status ); + todo_wine + ok( size == 3, "size = %u\n", size ); + + qsort( buf, size, sizeof(*buf), himc_compare ); + ok( buf[0] == himc[0], "buf[0] = %p\n", buf[0] ); + ok( buf[1] == himc[1], "buf[1] = %p\n", buf[1] ); + todo_wine + ok( buf[2] == himc[2], "buf[2] = %p\n", buf[2] ); + + return 0; +} + +static void test_NtUserBuildHimcList(void) +{ + HIMC buf[8], himc[3], new_himc; + NTSTATUS status; + UINT size, ret; + HANDLE thread; + + size = 0xdeadbeef; + memset( buf, 0xcd, sizeof(buf) ); + status = NtUserBuildHimcList( GetCurrentThreadId(), ARRAYSIZE( buf ), buf, &size ); + todo_wine + ok( !status, "NtUserBuildHimcList failed: %#lx\n", status ); + todo_wine + ok( size == 1, "size = %u\n", size ); + ok( !!buf[0], "buf[0] = %p\n", buf[0] ); + himc[0] = buf[0]; + + + new_himc = NtUserCreateInputContext( 0xdeadbeef ); + ok( !!new_himc, "NtUserCreateInputContext failed, error %lu\n", GetLastError() ); + + himc[1] = new_himc; + qsort( himc, 2, sizeof(*himc), himc_compare ); + + size = 0xdeadbeef; + memset( buf, 0xcd, sizeof(buf) ); + status = NtUserBuildHimcList( GetCurrentThreadId(), ARRAYSIZE( buf ), buf, &size ); + todo_wine + ok( !status, "NtUserBuildHimcList failed: %#lx\n", status ); + todo_wine + ok( size == 2, "size = %u\n", size ); + + qsort( buf, size, sizeof(*buf), himc_compare ); + ok( buf[0] == himc[0], "buf[0] = %p\n", buf[0] ); + todo_wine + ok( buf[1] == himc[1], "buf[1] = %p\n", buf[1] ); + + size = 0xdeadbeef; + memset( buf, 0xcd, sizeof(buf) ); + status = NtUserBuildHimcList( 0, ARRAYSIZE( buf ), buf, &size ); + todo_wine + ok( !status, "NtUserBuildHimcList failed: %#lx\n", status ); + todo_wine + ok( size == 2, "size = %u\n", size ); + + qsort( buf, size, sizeof(*buf), himc_compare ); + ok( buf[0] == himc[0], "buf[0] = %p\n", buf[0] ); + todo_wine + ok( buf[1] == himc[1], "buf[1] = %p\n", buf[1] ); + + size = 0xdeadbeef; + memset( buf, 0xcd, sizeof(buf) ); + status = NtUserBuildHimcList( -1, ARRAYSIZE( buf ), buf, &size ); + todo_wine + ok( !status, "NtUserBuildHimcList failed: %#lx\n", status ); + todo_wine + ok( size == 2, "size = %u\n", size ); + + qsort( buf, size, sizeof(*buf), himc_compare ); + ok( buf[0] == himc[0], "buf[0] = %p\n", buf[0] ); + todo_wine + ok( buf[1] == himc[1], "buf[1] = %p\n", buf[1] ); + + thread = CreateThread( NULL, 0, test_NtUserBuildHimcList_thread, himc, 0, NULL ); + ok( !!thread, "CreateThread failed, error %lu\n", GetLastError() ); + ret = WaitForSingleObject( thread, 5000 ); + ok( !ret, "WaitForSingleObject returned %#x\n", ret ); + + size = 0xdeadbeef; + status = NtUserBuildHimcList( 1, ARRAYSIZE( buf ), buf, &size ); + todo_wine + ok( status == STATUS_INVALID_PARAMETER, "NtUserBuildHimcList returned %#lx\n", status ); + size = 0xdeadbeef; + status = NtUserBuildHimcList( GetCurrentProcessId(), ARRAYSIZE( buf ), buf, &size ); + todo_wine + ok( status == STATUS_INVALID_PARAMETER, "NtUserBuildHimcList returned %#lx\n", status ); + size = 0xdeadbeef; + status = NtUserBuildHimcList( GetCurrentThreadId(), 1, NULL, &size ); + todo_wine + ok( status == STATUS_UNSUCCESSFUL, "NtUserBuildHimcList returned %#lx\n", status ); + size = 0xdeadbeef; + status = NtUserBuildHimcList( GetCurrentThreadId(), 0, buf, &size ); + todo_wine + ok( !status, "NtUserBuildHimcList failed: %#lx\n", status ); + ok( size == 0, "size = %u\n", size ); + + ret = NtUserDestroyInputContext( new_himc ); + ok( !!ret, "NtUserDestroyInputContext failed, error %lu\n", GetLastError() ); +} + static BOOL WINAPI count_win( HWND hwnd, LPARAM lparam ) { ULONG *cnt = (ULONG *)lparam; @@ -1246,6 +1379,7 @@ START_TEST(win32u) test_window_props(); test_class(); test_NtUserCreateInputContext(); + test_NtUserBuildHimcList(); test_NtUserBuildHwndList(); test_cursoricon(); test_message_call();
From: Rémi Bernon rbernon@codeweavers.com
And use it instead of next_thread_window_ptr. --- dlls/win32u/ntuser_private.h | 1 + dlls/win32u/window.c | 49 ++++++++++++++++++------------------ 2 files changed, 26 insertions(+), 24 deletions(-)
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 5c337c722a7..79c2a85c276 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -54,6 +54,7 @@ struct user_object
HANDLE alloc_user_handle( struct user_object *ptr, unsigned int type ) DECLSPEC_HIDDEN; void *get_user_handle_ptr( HANDLE handle, unsigned int type ) DECLSPEC_HIDDEN; +void *next_user_handle_ptr( HANDLE *handle, unsigned int type ) DECLSPEC_HIDDEN; void release_user_handle_ptr( void *ptr ) DECLSPEC_HIDDEN; void *free_user_handle( HANDLE handle, unsigned int type ) DECLSPEC_HIDDEN;
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 4db9d99884c..ea65bff6cb4 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -101,6 +101,26 @@ void *get_user_handle_ptr( HANDLE handle, unsigned int type ) return ptr; }
+/*********************************************************************** + * next_user_handle_ptr + */ +void *next_user_handle_ptr( HANDLE *handle, unsigned int type ) +{ + struct user_object *ptr; + WORD index = *handle ? USER_HANDLE_TO_INDEX( *handle ) + 1 : 0; + + user_lock(); + while (index < NB_USER_HANDLES) + { + if (!(ptr = user_handles[index++])) continue; + if (ptr->type != type) continue; + *handle = ptr->handle; + return ptr; + } + user_unlock(); + return NULL; +} + /*********************************************************************** * set_user_handle_ptr */ @@ -142,27 +162,6 @@ void *free_user_handle( HANDLE handle, unsigned int type ) return ptr; }
-/*********************************************************************** - * next_thread_window - */ -static WND *next_thread_window_ptr( HWND *hwnd ) -{ - struct user_object *ptr; - WND *win; - WORD index = *hwnd ? USER_HANDLE_TO_INDEX( *hwnd ) + 1 : 0; - - while (index < NB_USER_HANDLES) - { - if (!(ptr = user_handles[index++])) continue; - if (ptr->type != NTUSER_OBJ_WINDOW) continue; - win = (WND *)ptr; - if (win->tid != GetCurrentThreadId()) continue; - *hwnd = ptr->handle; - return win; - } - return NULL; -} - /******************************************************************* * get_hwnd_message_parent * @@ -4846,13 +4845,15 @@ BOOL WINAPI NtUserDestroyWindow( HWND hwnd ) void destroy_thread_windows(void) { WND *win, *free_list = NULL; - HWND hwnd = 0; + HANDLE handle = 0;
user_lock(); - while ((win = next_thread_window_ptr( &hwnd ))) + while ((win = next_user_handle_ptr( &handle, NTUSER_OBJ_WINDOW ))) { + release_user_handle_ptr( win ); + if (win->tid != GetCurrentThreadId()) continue; free_dce( win->dce, win->obj.handle ); - set_user_handle_ptr( hwnd, NULL ); + set_user_handle_ptr( handle, NULL ); win->obj.handle = free_list; free_list = win; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/imm.c | 20 +++++++++++++++++++- dlls/win32u/tests/win32u.c | 19 +++---------------- 2 files changed, 22 insertions(+), 17 deletions(-)
diff --git a/dlls/win32u/imm.c b/dlls/win32u/imm.c index dc10eedd903..a092b992756 100644 --- a/dlls/win32u/imm.c +++ b/dlls/win32u/imm.c @@ -400,8 +400,26 @@ void cleanup_imm_thread(void) */ NTSTATUS WINAPI NtUserBuildHimcList( UINT thread_id, UINT count, HIMC *buffer, UINT *size ) { + HANDLE handle = 0; + struct imc *imc; + FIXME( "thread_id %#x, count %u, buffer %p, size %p stub!\n", thread_id, count, buffer, size ); - return STATUS_NOT_IMPLEMENTED; + + if (!buffer) return STATUS_UNSUCCESSFUL; + if (!thread_id) thread_id = GetCurrentThreadId(); + + *size = 0; + user_lock(); + while (count && (imc = next_user_handle_ptr( &handle, NTUSER_OBJ_IMC ))) + { + release_imc_ptr( imc ); + if (thread_id != -1 && imc->thread_id != thread_id) continue; + buffer[(*size)++] = handle; + count--; + } + user_unlock(); + + return STATUS_SUCCESS; }
BOOL WINAPI DECLSPEC_HIDDEN ImmProcessKey( HWND hwnd, HKL hkl, UINT vkey, LPARAM key_data, DWORD unknown ) diff --git a/dlls/win32u/tests/win32u.c b/dlls/win32u/tests/win32u.c index 975716045cf..04e5a2e7932 100644 --- a/dlls/win32u/tests/win32u.c +++ b/dlls/win32u/tests/win32u.c @@ -332,13 +332,11 @@ static DWORD CALLBACK test_NtUserBuildHimcList_thread( void *arg ) size = 0xdeadbeef; memset( buf, 0xcd, sizeof(buf) ); status = NtUserBuildHimcList( GetCurrentThreadId(), ARRAYSIZE( buf ), buf, &size ); - todo_wine ok( !status, "NtUserBuildHimcList failed: %#lx\n", status ); todo_wine ok( size == 1, "size = %u\n", size ); ok( !!buf[0], "buf[0] = %p\n", buf[0] );
- todo_wine ok( buf[0] != himc[0], "buf[0] = %p\n", buf[0] ); ok( buf[0] != himc[1], "buf[0] = %p\n", buf[0] ); himc[2] = buf[0]; @@ -347,13 +345,15 @@ static DWORD CALLBACK test_NtUserBuildHimcList_thread( void *arg ) size = 0xdeadbeef; memset( buf, 0xcd, sizeof(buf) ); status = NtUserBuildHimcList( -1, ARRAYSIZE( buf ), buf, &size ); - todo_wine ok( !status, "NtUserBuildHimcList failed: %#lx\n", status ); todo_wine ok( size == 3, "size = %u\n", size );
qsort( buf, size, sizeof(*buf), himc_compare ); + /* FIXME: Wine only lazily creates a default thread IMC */ + todo_wine ok( buf[0] == himc[0], "buf[0] = %p\n", buf[0] ); + todo_wine ok( buf[1] == himc[1], "buf[1] = %p\n", buf[1] ); todo_wine ok( buf[2] == himc[2], "buf[2] = %p\n", buf[2] ); @@ -371,9 +371,7 @@ static void test_NtUserBuildHimcList(void) size = 0xdeadbeef; memset( buf, 0xcd, sizeof(buf) ); status = NtUserBuildHimcList( GetCurrentThreadId(), ARRAYSIZE( buf ), buf, &size ); - todo_wine ok( !status, "NtUserBuildHimcList failed: %#lx\n", status ); - todo_wine ok( size == 1, "size = %u\n", size ); ok( !!buf[0], "buf[0] = %p\n", buf[0] ); himc[0] = buf[0]; @@ -388,40 +386,31 @@ static void test_NtUserBuildHimcList(void) size = 0xdeadbeef; memset( buf, 0xcd, sizeof(buf) ); status = NtUserBuildHimcList( GetCurrentThreadId(), ARRAYSIZE( buf ), buf, &size ); - todo_wine ok( !status, "NtUserBuildHimcList failed: %#lx\n", status ); - todo_wine ok( size == 2, "size = %u\n", size );
qsort( buf, size, sizeof(*buf), himc_compare ); ok( buf[0] == himc[0], "buf[0] = %p\n", buf[0] ); - todo_wine ok( buf[1] == himc[1], "buf[1] = %p\n", buf[1] );
size = 0xdeadbeef; memset( buf, 0xcd, sizeof(buf) ); status = NtUserBuildHimcList( 0, ARRAYSIZE( buf ), buf, &size ); - todo_wine ok( !status, "NtUserBuildHimcList failed: %#lx\n", status ); - todo_wine ok( size == 2, "size = %u\n", size );
qsort( buf, size, sizeof(*buf), himc_compare ); ok( buf[0] == himc[0], "buf[0] = %p\n", buf[0] ); - todo_wine ok( buf[1] == himc[1], "buf[1] = %p\n", buf[1] );
size = 0xdeadbeef; memset( buf, 0xcd, sizeof(buf) ); status = NtUserBuildHimcList( -1, ARRAYSIZE( buf ), buf, &size ); - todo_wine ok( !status, "NtUserBuildHimcList failed: %#lx\n", status ); - todo_wine ok( size == 2, "size = %u\n", size );
qsort( buf, size, sizeof(*buf), himc_compare ); ok( buf[0] == himc[0], "buf[0] = %p\n", buf[0] ); - todo_wine ok( buf[1] == himc[1], "buf[1] = %p\n", buf[1] );
thread = CreateThread( NULL, 0, test_NtUserBuildHimcList_thread, himc, 0, NULL ); @@ -439,11 +428,9 @@ static void test_NtUserBuildHimcList(void) ok( status == STATUS_INVALID_PARAMETER, "NtUserBuildHimcList returned %#lx\n", status ); size = 0xdeadbeef; status = NtUserBuildHimcList( GetCurrentThreadId(), 1, NULL, &size ); - todo_wine ok( status == STATUS_UNSUCCESSFUL, "NtUserBuildHimcList returned %#lx\n", status ); size = 0xdeadbeef; status = NtUserBuildHimcList( GetCurrentThreadId(), 0, buf, &size ); - todo_wine ok( !status, "NtUserBuildHimcList failed: %#lx\n", status ); ok( size == 0, "size = %u\n", size );
v2: Rebase before widl breakage, use `UINT` instead of `ULONG` to avoid casts, test output size and initialize it to 0 in the implementation.
Jacek Caban (@jacek) commented about dlls/win32u/window.c:
return ptr;
}
+/***********************************************************************
next_user_handle_ptr
- */
+void *next_user_handle_ptr( HANDLE *handle, unsigned int type ) +{
- struct user_object *ptr;
- WORD index = *handle ? USER_HANDLE_TO_INDEX( *handle ) + 1 : 0;
- user_lock();
Callers need to lock themselves to be able to use this helper properly anyway. Additional locking here is not needed and I think it makes the caller look a bit more questionable with the additional release.
On Fri Mar 17 14:18:24 2023 +0000, Jacek Caban wrote:
Callers need to lock themselves to be able to use this helper properly anyway. Additional locking here is not needed and I think it makes the caller look a bit more questionable with the additional release.
Right, I was actually unsure about this. For some reason I wanted to keep it close to `get_user_handle_ptr` but I guess it's pointless.