2021-10-12 13:33:30 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2021 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
|
|
|
|
*/
|
|
|
|
|
2021-12-10 01:06:58 +00:00
|
|
|
#include "ntstatus.h"
|
|
|
|
#define WIN32_NO_STATUS
|
|
|
|
|
2021-10-12 13:33:30 +00:00
|
|
|
#include "wine/test.h"
|
|
|
|
|
|
|
|
#include "winbase.h"
|
|
|
|
#include "ntuser.h"
|
|
|
|
|
2023-01-28 09:35:54 +00:00
|
|
|
#define check_member_( file, line, val, exp, fmt, member ) \
|
|
|
|
ok_(file, line)( (val).member == (exp).member, "got " #member " " fmt "\n", (val).member )
|
|
|
|
#define check_member( val, exp, fmt, member ) \
|
|
|
|
check_member_( __FILE__, __LINE__, val, exp, fmt, member )
|
|
|
|
|
|
|
|
static void flush_events(void)
|
|
|
|
{
|
|
|
|
int min_timeout = 100, diff = 200;
|
|
|
|
DWORD time = GetTickCount() + diff;
|
|
|
|
MSG msg;
|
|
|
|
|
|
|
|
while (diff > 0)
|
|
|
|
{
|
|
|
|
if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
|
|
|
|
while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ))
|
|
|
|
{
|
|
|
|
TranslateMessage( &msg );
|
|
|
|
DispatchMessageA( &msg );
|
|
|
|
}
|
|
|
|
diff = time - GetTickCount();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-10 01:06:58 +00:00
|
|
|
static void test_NtUserEnumDisplayDevices(void)
|
|
|
|
{
|
|
|
|
NTSTATUS ret;
|
|
|
|
DISPLAY_DEVICEW info = { sizeof(DISPLAY_DEVICEW) };
|
|
|
|
|
|
|
|
SetLastError( 0xdeadbeef );
|
|
|
|
ret = NtUserEnumDisplayDevices( NULL, 0, &info, 0 );
|
2021-12-10 01:06:59 +00:00
|
|
|
ok( !ret && GetLastError() == 0xdeadbeef,
|
2022-02-18 13:06:14 +00:00
|
|
|
"NtUserEnumDisplayDevices returned %#lx %lu\n", ret, GetLastError() );
|
2021-12-10 01:06:58 +00:00
|
|
|
|
|
|
|
SetLastError( 0xdeadbeef );
|
|
|
|
ret = NtUserEnumDisplayDevices( NULL, 12345, &info, 0 );
|
2021-12-10 01:06:59 +00:00
|
|
|
ok( ret == STATUS_UNSUCCESSFUL && GetLastError() == 0xdeadbeef,
|
2022-02-18 13:06:14 +00:00
|
|
|
"NtUserEnumDisplayDevices returned %#lx %lu\n", ret,
|
2021-12-10 01:06:58 +00:00
|
|
|
GetLastError() );
|
|
|
|
|
|
|
|
info.cb = 0;
|
|
|
|
|
|
|
|
SetLastError( 0xdeadbeef );
|
|
|
|
ret = NtUserEnumDisplayDevices( NULL, 0, &info, 0 );
|
2021-12-10 01:07:00 +00:00
|
|
|
ok( ret == STATUS_UNSUCCESSFUL && GetLastError() == 0xdeadbeef,
|
2022-02-18 13:06:14 +00:00
|
|
|
"NtUserEnumDisplayDevices returned %#lx %lu\n", ret, GetLastError() );
|
2021-12-10 01:06:58 +00:00
|
|
|
|
|
|
|
SetLastError( 0xdeadbeef );
|
|
|
|
ret = NtUserEnumDisplayDevices( NULL, 12345, &info, 0 );
|
2021-12-10 01:06:59 +00:00
|
|
|
ok( ret == STATUS_UNSUCCESSFUL && GetLastError() == 0xdeadbeef,
|
2022-02-18 13:06:14 +00:00
|
|
|
"NtUserEnumDisplayDevices returned %#lx %lu\n", ret, GetLastError() );
|
2021-12-10 01:07:00 +00:00
|
|
|
|
|
|
|
SetLastError( 0xdeadbeef );
|
|
|
|
ret = NtUserEnumDisplayDevices( NULL, 0, NULL, 0 );
|
|
|
|
ok( ret == STATUS_UNSUCCESSFUL && GetLastError() == 0xdeadbeef,
|
2022-02-18 13:06:14 +00:00
|
|
|
"NtUserEnumDisplayDevices returned %#lx %lu\n", ret, GetLastError() );
|
2021-12-10 01:07:00 +00:00
|
|
|
|
|
|
|
SetLastError( 0xdeadbeef );
|
|
|
|
ret = NtUserEnumDisplayDevices( NULL, 12345, NULL, 0 );
|
|
|
|
ok( ret == STATUS_UNSUCCESSFUL && GetLastError() == 0xdeadbeef,
|
2022-02-18 13:06:14 +00:00
|
|
|
"NtUserEnumDisplayDevices returned %#lx %lu\n", ret, GetLastError() );
|
2021-12-10 01:06:58 +00:00
|
|
|
}
|
|
|
|
|
2021-10-12 13:33:30 +00:00
|
|
|
static void test_NtUserCloseWindowStation(void)
|
|
|
|
{
|
|
|
|
BOOL ret;
|
|
|
|
|
|
|
|
SetLastError( 0xdeadbeef );
|
|
|
|
ret = NtUserCloseWindowStation( 0 );
|
|
|
|
ok( !ret && GetLastError() == ERROR_INVALID_HANDLE,
|
2022-02-18 13:06:14 +00:00
|
|
|
"NtUserCloseWindowStation returned %x %lu\n", ret, GetLastError() );
|
2021-10-12 13:33:30 +00:00
|
|
|
}
|
|
|
|
|
2021-11-08 13:48:37 +00:00
|
|
|
static void test_window_props(void)
|
|
|
|
{
|
|
|
|
HANDLE prop;
|
|
|
|
ATOM atom;
|
|
|
|
HWND hwnd;
|
|
|
|
BOOL ret;
|
|
|
|
|
|
|
|
hwnd = CreateWindowExA( 0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL );
|
|
|
|
|
|
|
|
atom = GlobalAddAtomW( L"test" );
|
|
|
|
|
|
|
|
ret = NtUserSetProp( hwnd, UlongToPtr(atom), UlongToHandle(0xdeadbeef) );
|
2022-02-18 13:06:14 +00:00
|
|
|
ok( ret, "NtUserSetProp failed: %lu\n", GetLastError() );
|
2021-11-08 13:48:37 +00:00
|
|
|
|
|
|
|
prop = GetPropW( hwnd, L"test" );
|
|
|
|
ok( prop == UlongToHandle(0xdeadbeef), "prop = %p\n", prop );
|
|
|
|
|
2021-11-08 13:48:45 +00:00
|
|
|
prop = NtUserGetProp( hwnd, UlongToPtr(atom) );
|
|
|
|
ok( prop == UlongToHandle(0xdeadbeef), "prop = %p\n", prop );
|
|
|
|
|
2021-11-08 13:48:55 +00:00
|
|
|
prop = NtUserRemoveProp( hwnd, UlongToPtr(atom) );
|
|
|
|
ok( prop == UlongToHandle(0xdeadbeef), "prop = %p\n", prop );
|
|
|
|
|
|
|
|
prop = GetPropW(hwnd, L"test");
|
|
|
|
ok(!prop, "prop = %p\n", prop);
|
|
|
|
|
2021-11-08 13:48:37 +00:00
|
|
|
GlobalDeleteAtom( atom );
|
|
|
|
DestroyWindow( hwnd );
|
|
|
|
}
|
2021-10-12 13:33:30 +00:00
|
|
|
|
2022-03-04 13:28:16 +00:00
|
|
|
static void test_class(void)
|
|
|
|
{
|
|
|
|
UNICODE_STRING name;
|
|
|
|
WCHAR buf[64];
|
|
|
|
WNDCLASSW cls;
|
|
|
|
ATOM class;
|
2022-03-04 13:28:31 +00:00
|
|
|
HWND hwnd;
|
2022-03-04 13:28:16 +00:00
|
|
|
ULONG ret;
|
|
|
|
|
|
|
|
memset( &cls, 0, sizeof(cls) );
|
|
|
|
cls.style = CS_HREDRAW | CS_VREDRAW;
|
|
|
|
cls.lpfnWndProc = DefWindowProcW;
|
|
|
|
cls.hInstance = GetModuleHandleW( NULL );
|
|
|
|
cls.hbrBackground = GetStockObject( WHITE_BRUSH );
|
|
|
|
cls.lpszMenuName = 0;
|
|
|
|
cls.lpszClassName = L"test";
|
|
|
|
|
|
|
|
class = RegisterClassW( &cls );
|
|
|
|
ok( class, "RegisterClassW failed: %lu\n", GetLastError() );
|
|
|
|
|
2022-03-04 13:28:31 +00:00
|
|
|
hwnd = CreateWindowW( L"test", L"test name", WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,
|
|
|
|
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, 0, NULL, 0 );
|
|
|
|
|
2022-03-04 13:28:16 +00:00
|
|
|
memset( buf, 0xcc, sizeof(buf) );
|
|
|
|
name.Buffer = buf;
|
|
|
|
name.Length = 0xdead;
|
|
|
|
name.MaximumLength = sizeof(buf);
|
|
|
|
ret = NtUserGetAtomName( class, &name );
|
|
|
|
ok( ret == 4, "NtUserGetAtomName returned %lu\n", ret );
|
|
|
|
ok( name.Length == 0xdead, "Length = %u\n", name.Length );
|
|
|
|
ok( name.MaximumLength == sizeof(buf), "MaximumLength = %u\n", name.MaximumLength );
|
|
|
|
ok( !wcscmp( buf, L"test" ), "buf = %s\n", debugstr_w(buf) );
|
|
|
|
|
|
|
|
memset( buf, 0xcc, sizeof(buf) );
|
|
|
|
name.Buffer = buf;
|
|
|
|
name.Length = 0xdead;
|
|
|
|
name.MaximumLength = 8;
|
|
|
|
ret = NtUserGetAtomName( class, &name );
|
|
|
|
ok( ret == 3, "NtUserGetAtomName returned %lu\n", ret );
|
|
|
|
ok( name.Length == 0xdead, "Length = %u\n", name.Length );
|
|
|
|
ok( name.MaximumLength == 8, "MaximumLength = %u\n", name.MaximumLength );
|
|
|
|
ok( !wcscmp( buf, L"tes" ), "buf = %s\n", debugstr_w(buf) );
|
|
|
|
|
|
|
|
memset( buf, 0xcc, sizeof(buf) );
|
|
|
|
name.Buffer = buf;
|
|
|
|
name.MaximumLength = 1;
|
|
|
|
SetLastError( 0xdeadbeef );
|
|
|
|
ret = NtUserGetAtomName( class, &name );
|
|
|
|
ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
|
|
|
|
"NtUserGetAtomName returned %lx %lu\n", ret, GetLastError() );
|
|
|
|
|
2022-03-04 13:28:31 +00:00
|
|
|
memset( buf, 0xcc, sizeof(buf) );
|
|
|
|
name.Buffer = buf;
|
|
|
|
name.Length = 0xdead;
|
|
|
|
name.MaximumLength = sizeof(buf);
|
|
|
|
ret = NtUserGetClassName( hwnd, FALSE, &name );
|
|
|
|
ok( ret == 4, "NtUserGetClassName returned %lu\n", ret );
|
|
|
|
ok( name.Length == 0xdead, "Length = %u\n", name.Length );
|
|
|
|
ok( name.MaximumLength == sizeof(buf), "MaximumLength = %u\n", name.MaximumLength );
|
|
|
|
ok( !wcscmp( buf, L"test" ), "buf = %s\n", debugstr_w(buf) );
|
|
|
|
|
|
|
|
memset( buf, 0xcc, sizeof(buf) );
|
|
|
|
name.Buffer = buf;
|
|
|
|
name.Length = 0xdead;
|
|
|
|
name.MaximumLength = 8;
|
|
|
|
ret = NtUserGetClassName( hwnd, FALSE, &name );
|
|
|
|
ok( ret == 3, "NtUserGetClassName returned %lu\n", ret );
|
|
|
|
ok( name.Length == 0xdead, "Length = %u\n", name.Length );
|
|
|
|
ok( name.MaximumLength == 8, "MaximumLength = %u\n", name.MaximumLength );
|
|
|
|
ok( !wcscmp( buf, L"tes" ), "buf = %s\n", debugstr_w(buf) );
|
|
|
|
|
|
|
|
memset( buf, 0xcc, sizeof(buf) );
|
|
|
|
name.Buffer = buf;
|
|
|
|
name.MaximumLength = 1;
|
|
|
|
SetLastError( 0xdeadbeef );
|
|
|
|
ret = NtUserGetClassName( hwnd, FALSE, &name );
|
|
|
|
ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
|
|
|
|
"NtUserGetClassName returned %lx %lu\n", ret, GetLastError() );
|
|
|
|
|
|
|
|
DestroyWindow( hwnd );
|
|
|
|
|
2022-03-04 13:28:16 +00:00
|
|
|
ret = UnregisterClassW( L"test", GetModuleHandleW(NULL) );
|
|
|
|
ok( ret, "UnregisterClassW failed: %lu\n", GetLastError() );
|
|
|
|
|
|
|
|
memset( buf, 0xcc, sizeof(buf) );
|
|
|
|
name.Buffer = buf;
|
|
|
|
name.MaximumLength = sizeof(buf);
|
|
|
|
SetLastError( 0xdeadbeef );
|
|
|
|
ret = NtUserGetAtomName( class, &name );
|
|
|
|
ok( !ret && GetLastError() == ERROR_INVALID_HANDLE,
|
|
|
|
"NtUserGetAtomName returned %lx %lu\n", ret, GetLastError() );
|
|
|
|
ok( buf[0] == 0xcccc, "buf = %s\n", debugstr_w(buf) );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-03-11 07:53:29 +00:00
|
|
|
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() );
|
|
|
|
}
|
|
|
|
|
2023-03-11 07:58:33 +00:00
|
|
|
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 );
|
|
|
|
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] );
|
|
|
|
|
|
|
|
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 );
|
|
|
|
ok( !status, "NtUserBuildHimcList failed: %#lx\n", status );
|
|
|
|
todo_wine
|
|
|
|
ok( size == 3, "size = %u\n", size );
|
|
|
|
|
|
|
|
qsort( buf, size, sizeof(*buf), himc_compare );
|
2023-03-17 13:54:25 +00:00
|
|
|
/* FIXME: Wine only lazily creates a default thread IMC */
|
|
|
|
todo_wine
|
2023-03-11 07:58:33 +00:00
|
|
|
ok( buf[0] == himc[0], "buf[0] = %p\n", buf[0] );
|
2023-03-17 13:54:25 +00:00
|
|
|
todo_wine
|
2023-03-11 07:58:33 +00:00
|
|
|
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 );
|
|
|
|
ok( !status, "NtUserBuildHimcList failed: %#lx\n", status );
|
|
|
|
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 );
|
|
|
|
ok( !status, "NtUserBuildHimcList failed: %#lx\n", status );
|
|
|
|
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] );
|
|
|
|
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 );
|
|
|
|
ok( !status, "NtUserBuildHimcList failed: %#lx\n", status );
|
|
|
|
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] );
|
|
|
|
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 );
|
|
|
|
ok( !status, "NtUserBuildHimcList failed: %#lx\n", status );
|
|
|
|
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] );
|
|
|
|
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 );
|
|
|
|
ok( status == STATUS_UNSUCCESSFUL, "NtUserBuildHimcList returned %#lx\n", status );
|
|
|
|
size = 0xdeadbeef;
|
|
|
|
status = NtUserBuildHimcList( GetCurrentThreadId(), 0, buf, &size );
|
|
|
|
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() );
|
|
|
|
}
|
|
|
|
|
2021-12-21 19:31:29 +00:00
|
|
|
static BOOL WINAPI count_win( HWND hwnd, LPARAM lparam )
|
|
|
|
{
|
|
|
|
ULONG *cnt = (ULONG *)lparam;
|
|
|
|
(*cnt)++;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_NtUserBuildHwndList(void)
|
|
|
|
{
|
|
|
|
ULONG size, desktop_windows_cnt;
|
|
|
|
HWND buf[512], hwnd;
|
|
|
|
NTSTATUS status;
|
|
|
|
|
|
|
|
size = 0;
|
|
|
|
status = NtUserBuildHwndList( 0, 0, 0, 0, GetCurrentThreadId(), ARRAYSIZE(buf), buf, &size );
|
2022-02-18 13:06:14 +00:00
|
|
|
ok( !status, "NtUserBuildHwndList failed: %#lx\n", status );
|
|
|
|
ok( size == 1, "size = %lu\n", size );
|
2021-12-21 19:31:29 +00:00
|
|
|
ok( buf[0] == HWND_BOTTOM, "buf[0] = %p\n", buf[0] );
|
|
|
|
|
|
|
|
hwnd = CreateWindowExA( 0, "static", NULL, WS_POPUP, 0,0,0,0,GetDesktopWindow(),0,0, NULL );
|
|
|
|
|
|
|
|
size = 0;
|
|
|
|
status = NtUserBuildHwndList( 0, 0, 0, 0, GetCurrentThreadId(), ARRAYSIZE(buf), buf, &size );
|
2022-02-18 13:06:14 +00:00
|
|
|
ok( !status, "NtUserBuildHwndList failed: %#lx\n", status );
|
|
|
|
ok( size == 3, "size = %lu\n", size );
|
2021-12-21 19:31:29 +00:00
|
|
|
ok( buf[0] == hwnd, "buf[0] = %p\n", buf[0] );
|
|
|
|
ok( buf[2] == HWND_BOTTOM, "buf[0] = %p\n", buf[2] );
|
|
|
|
|
|
|
|
size = 0;
|
|
|
|
status = NtUserBuildHwndList( 0, 0, 0, 0, GetCurrentThreadId(), 3, buf, &size );
|
2022-02-18 13:06:14 +00:00
|
|
|
ok( !status, "NtUserBuildHwndList failed: %#lx\n", status );
|
|
|
|
ok( size == 3, "size = %lu\n", size );
|
2021-12-21 19:31:29 +00:00
|
|
|
|
|
|
|
size = 0;
|
|
|
|
status = NtUserBuildHwndList( 0, 0, 0, 0, GetCurrentThreadId(), 2, buf, &size );
|
2022-02-18 13:06:14 +00:00
|
|
|
ok( status == STATUS_BUFFER_TOO_SMALL, "NtUserBuildHwndList failed: %#lx\n", status );
|
|
|
|
ok( size == 3, "size = %lu\n", size );
|
2021-12-21 19:31:29 +00:00
|
|
|
|
|
|
|
size = 0;
|
|
|
|
status = NtUserBuildHwndList( 0, 0, 0, 0, GetCurrentThreadId(), 1, buf, &size );
|
2022-02-18 13:06:14 +00:00
|
|
|
ok( status == STATUS_BUFFER_TOO_SMALL, "NtUserBuildHwndList failed: %#lx\n", status );
|
|
|
|
ok( size == 3, "size = %lu\n", size );
|
2021-12-21 19:31:29 +00:00
|
|
|
|
|
|
|
desktop_windows_cnt = 0;
|
|
|
|
EnumDesktopWindows( 0, count_win, (LPARAM)&desktop_windows_cnt );
|
|
|
|
|
|
|
|
size = 0;
|
|
|
|
status = NtUserBuildHwndList( 0, 0, 0, 1, 0, ARRAYSIZE(buf), buf, &size );
|
2022-02-18 13:06:14 +00:00
|
|
|
ok( !status, "NtUserBuildHwndList failed: %#lx\n", status );
|
|
|
|
ok( size == desktop_windows_cnt + 1, "size = %lu, expected %lu\n", size, desktop_windows_cnt + 1 );
|
2021-12-21 19:31:29 +00:00
|
|
|
|
|
|
|
desktop_windows_cnt = 0;
|
|
|
|
EnumDesktopWindows( GetThreadDesktop( GetCurrentThreadId() ), count_win, (LPARAM)&desktop_windows_cnt );
|
|
|
|
|
|
|
|
size = 0;
|
|
|
|
status = NtUserBuildHwndList( GetThreadDesktop(GetCurrentThreadId()), 0, 0, 1, 0,
|
|
|
|
ARRAYSIZE(buf), buf, &size );
|
2022-02-18 13:06:14 +00:00
|
|
|
ok( !status, "NtUserBuildHwndList failed: %#lx\n", status );
|
|
|
|
ok( size == desktop_windows_cnt + 1, "size = %lu, expected %lu\n", size, desktop_windows_cnt + 1 );
|
2021-12-21 19:31:29 +00:00
|
|
|
|
|
|
|
size = 0;
|
|
|
|
status = NtUserBuildHwndList( GetThreadDesktop(GetCurrentThreadId()), 0, 0, 0, 0,
|
|
|
|
ARRAYSIZE(buf), buf, &size );
|
2022-02-18 13:06:14 +00:00
|
|
|
ok( !status, "NtUserBuildHwndList failed: %#lx\n", status );
|
2021-12-21 19:31:29 +00:00
|
|
|
todo_wine
|
2022-02-18 13:06:14 +00:00
|
|
|
ok( size > desktop_windows_cnt + 1, "size = %lu, expected %lu\n", size, desktop_windows_cnt + 1 );
|
2021-12-21 19:31:29 +00:00
|
|
|
|
|
|
|
size = 0xdeadbeef;
|
|
|
|
status = NtUserBuildHwndList( UlongToHandle(0xdeadbeef), 0, 0, 0, 0,
|
|
|
|
ARRAYSIZE(buf), buf, &size );
|
2022-02-18 13:06:14 +00:00
|
|
|
ok( status == STATUS_INVALID_HANDLE, "NtUserBuildHwndList failed: %#lx\n", status );
|
|
|
|
ok( size == 0xdeadbeef, "size = %lu\n", size );
|
2021-12-21 19:31:29 +00:00
|
|
|
|
|
|
|
DestroyWindow( hwnd );
|
|
|
|
}
|
|
|
|
|
2022-02-23 12:39:56 +00:00
|
|
|
static void test_cursoricon(void)
|
|
|
|
{
|
2022-02-23 12:40:33 +00:00
|
|
|
WCHAR module[MAX_PATH], res_buf[MAX_PATH];
|
|
|
|
UNICODE_STRING module_str, res_str;
|
2022-02-23 12:39:56 +00:00
|
|
|
BYTE bmp_bits[1024];
|
|
|
|
LONG width, height;
|
2022-02-23 12:40:14 +00:00
|
|
|
DWORD rate, steps;
|
|
|
|
HCURSOR frame;
|
2022-02-23 12:39:56 +00:00
|
|
|
HANDLE handle;
|
2022-02-23 12:40:33 +00:00
|
|
|
ICONINFO info;
|
2022-02-23 12:39:56 +00:00
|
|
|
unsigned int i;
|
|
|
|
BOOL ret;
|
|
|
|
|
|
|
|
for (i = 0; i < sizeof(bmp_bits); ++i)
|
|
|
|
bmp_bits[i] = 111 * i;
|
|
|
|
|
|
|
|
handle = CreateIcon( 0, 16, 16, 1, 1, bmp_bits, &bmp_bits[16 * 16 / 8] );
|
|
|
|
ok(handle != 0, "CreateIcon failed\n");
|
|
|
|
|
|
|
|
ret = NtUserGetIconSize( handle, 0, &width, &height );
|
|
|
|
ok( ret, "NtUserGetIconSize failed: %lu\n", GetLastError() );
|
|
|
|
ok( width == 16, "width = %ld\n", width );
|
|
|
|
ok( height == 32, "height = %ld\n", height );
|
|
|
|
|
|
|
|
ret = NtUserGetIconSize( handle, 6, &width, &height );
|
|
|
|
ok( ret, "NtUserGetIconSize failed: %lu\n", GetLastError() );
|
|
|
|
ok( width == 16, "width = %ld\n", width );
|
|
|
|
ok( height == 32, "height = %ld\n", height );
|
|
|
|
|
2022-02-23 12:40:14 +00:00
|
|
|
frame = NtUserGetCursorFrameInfo( handle, 0, &rate, &steps );
|
|
|
|
ok( frame != NULL, "NtUserGetCursorFrameInfo failed: %lu\n", GetLastError() );
|
|
|
|
ok( frame == handle, "frame != handle\n" );
|
|
|
|
ok( rate == 0, "rate = %lu\n", rate );
|
|
|
|
ok( steps == 1, "steps = %lu\n", steps );
|
|
|
|
|
2022-02-23 12:40:33 +00:00
|
|
|
ret = NtUserGetIconInfo( handle, &info, NULL, NULL, NULL, 0 );
|
|
|
|
ok( ret, "NtUserGetIconInfo failed: %lu\n", GetLastError() );
|
|
|
|
ok( info.fIcon == TRUE, "fIcon = %x\n", info.fIcon );
|
|
|
|
ok( info.xHotspot == 8, "xHotspot = %lx\n", info.xHotspot );
|
|
|
|
ok( info.yHotspot == 8, "yHotspot = %lx\n", info.yHotspot );
|
|
|
|
DeleteObject( info.hbmColor );
|
|
|
|
DeleteObject( info.hbmMask );
|
|
|
|
|
|
|
|
memset( module, 0xcc, sizeof(module) );
|
|
|
|
module_str.Buffer = module;
|
|
|
|
module_str.Length = 0xdead;
|
|
|
|
module_str.MaximumLength = sizeof(module);
|
|
|
|
memset( res_buf, 0xcc, sizeof(res_buf) );
|
|
|
|
res_str.Buffer = res_buf;
|
|
|
|
res_str.Length = 0xdead;
|
|
|
|
res_str.MaximumLength = sizeof(res_buf);
|
|
|
|
ret = NtUserGetIconInfo( handle, &info, &module_str, &res_str, NULL, 0 );
|
|
|
|
ok( ret, "NtUserGetIconInfo failed: %lu\n", GetLastError() );
|
|
|
|
ok( info.fIcon == TRUE, "fIcon = %x\n", info.fIcon );
|
|
|
|
ok( !module_str.Length, "module_str.Length = %u\n", module_str.Length );
|
|
|
|
ok( !res_str.Length, "res_str.Length = %u\n", res_str.Length );
|
|
|
|
ok( module_str.Buffer == module, "module_str.Buffer = %p\n", module_str.Buffer );
|
|
|
|
ok( !res_str.Buffer, "res_str.Buffer = %p\n", res_str.Buffer );
|
|
|
|
ok( module[0] == 0xcccc, "module[0] = %x\n", module[0] );
|
|
|
|
ok( res_buf[0] == 0xcccc, "res_buf[0] = %x\n", res_buf[0] );
|
|
|
|
DeleteObject( info.hbmColor );
|
|
|
|
DeleteObject( info.hbmMask );
|
|
|
|
|
2022-02-23 12:39:56 +00:00
|
|
|
ret = NtUserDestroyCursor( handle, 0 );
|
|
|
|
ok( ret, "NtUserDestroyIcon failed: %lu\n", GetLastError() );
|
|
|
|
|
|
|
|
SetLastError( 0xdeadbeef );
|
|
|
|
ret = NtUserGetIconSize( handle, 0, &width, &height );
|
|
|
|
ok( !ret && GetLastError() == ERROR_INVALID_CURSOR_HANDLE,
|
|
|
|
"NtUserGetIconSize returned %x %lu\n", ret, GetLastError() );
|
|
|
|
|
|
|
|
/* Test a system icon */
|
|
|
|
handle = LoadIconA( 0, (LPCSTR)IDI_HAND );
|
|
|
|
ok( handle != NULL, "LoadIcon icon failed, error %lu\n", GetLastError() );
|
|
|
|
|
|
|
|
ret = NtUserGetIconSize( handle, 0, &width, &height );
|
|
|
|
ok( width == 32, "width = %ld\n", width );
|
|
|
|
ok( height == 64, "height = %ld\n", height );
|
|
|
|
ok( ret, "NtUserGetIconSize failed: %lu\n", GetLastError() );
|
|
|
|
|
2022-02-23 12:40:33 +00:00
|
|
|
memset( module, 0xcc, sizeof(module) );
|
|
|
|
module_str.Buffer = module;
|
|
|
|
module_str.Length = 0xdead;
|
|
|
|
module_str.MaximumLength = sizeof(module);
|
|
|
|
memset( res_buf, 0xcc, sizeof(res_buf) );
|
|
|
|
res_str.Buffer = res_buf;
|
|
|
|
res_str.Length = 0xdead;
|
|
|
|
res_str.MaximumLength = sizeof(res_buf);
|
|
|
|
ret = NtUserGetIconInfo( handle, &info, &module_str, &res_str, NULL, 0 );
|
|
|
|
ok( ret, "NtUserGetIconInfo failed: %lu\n", GetLastError() );
|
|
|
|
ok( info.fIcon == TRUE, "fIcon = %x\n", info.fIcon );
|
|
|
|
ok( module_str.Length, "module_str.Length = 0\n" );
|
|
|
|
ok( !res_str.Length, "res_str.Length = %u\n", res_str.Length );
|
|
|
|
ok( module_str.Buffer == module, "module_str.Buffer = %p\n", module_str.Buffer );
|
|
|
|
ok( res_str.Buffer == (WCHAR *)IDI_HAND, "res_str.Buffer = %p\n", res_str.Buffer );
|
|
|
|
DeleteObject( info.hbmColor );
|
|
|
|
DeleteObject( info.hbmMask );
|
|
|
|
|
|
|
|
module[module_str.Length] = 0;
|
|
|
|
ok( GetModuleHandleW(module) == GetModuleHandleW(L"user32.dll"),
|
|
|
|
"GetIconInfoEx wrong module %s\n", wine_dbgstr_w(module) );
|
|
|
|
|
2022-02-23 12:39:56 +00:00
|
|
|
ret = DestroyIcon(handle);
|
|
|
|
ok(ret, "Destroy icon failed, error %lu.\n", GetLastError());
|
|
|
|
}
|
|
|
|
|
2022-04-04 14:57:23 +00:00
|
|
|
static LRESULT WINAPI test_message_call_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
|
|
|
|
{
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_SETTEXT:
|
|
|
|
ok( !wcscmp( (const WCHAR *)lparam, L"test" ),
|
|
|
|
"lparam = %s\n", wine_dbgstr_w( (const WCHAR *)lparam ));
|
|
|
|
return 6;
|
|
|
|
case WM_USER:
|
|
|
|
ok( wparam == 1, "wparam = %Iu\n", wparam );
|
|
|
|
ok( lparam == 2, "lparam = %Iu\n", lparam );
|
|
|
|
return 3;
|
|
|
|
case WM_USER + 1:
|
|
|
|
return lparam;
|
|
|
|
}
|
|
|
|
|
|
|
|
return DefWindowProcW( hwnd, msg, wparam, lparam );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void WINAPI test_message_callback( HWND hwnd, UINT msg, ULONG_PTR data, LRESULT result )
|
|
|
|
{
|
|
|
|
ok( msg == WM_USER, "msg = %u\n", msg );
|
|
|
|
ok( data == 10, "data = %Iu\n", data );
|
|
|
|
ok( result == 3, "result = %Iu\n", result );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_message_call(void)
|
|
|
|
{
|
|
|
|
const LPARAM large_lparam = (LPARAM)(3 + ((ULONGLONG)1 << 60));
|
|
|
|
struct send_message_callback_params callback_params = {
|
|
|
|
.callback = test_message_callback,
|
|
|
|
.data = 10,
|
|
|
|
};
|
|
|
|
struct send_message_timeout_params smp;
|
|
|
|
WNDCLASSW cls = { 0 };
|
|
|
|
LRESULT res;
|
|
|
|
HWND hwnd;
|
|
|
|
|
|
|
|
cls.lpfnWndProc = test_message_call_proc;
|
|
|
|
cls.lpszClassName = L"TestClass";
|
|
|
|
RegisterClassW( &cls );
|
|
|
|
|
|
|
|
hwnd = CreateWindowExW( 0, L"TestClass", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL );
|
|
|
|
|
2022-07-19 17:19:56 +00:00
|
|
|
res = NtUserMessageCall( hwnd, WM_USER, 1, 2, NULL, NtUserSendMessage, FALSE );
|
2022-04-04 14:57:23 +00:00
|
|
|
ok( res == 3, "res = %Iu\n", res );
|
|
|
|
|
2022-07-19 17:19:56 +00:00
|
|
|
res = NtUserMessageCall( hwnd, WM_USER, 1, 2, NULL, NtUserSendMessage, TRUE );
|
2022-04-04 14:57:23 +00:00
|
|
|
ok( res == 3, "res = %Iu\n", res );
|
|
|
|
|
2022-04-08 11:30:22 +00:00
|
|
|
res = NtUserMessageCall( hwnd, WM_SETTEXT, 0, (LPARAM)L"test", NULL, NtUserSendMessage, FALSE );
|
2022-04-04 14:57:23 +00:00
|
|
|
ok( res == 6, "res = %Iu\n", res );
|
|
|
|
|
2022-04-08 11:30:22 +00:00
|
|
|
res = NtUserMessageCall( hwnd, WM_SETTEXT, 0, (LPARAM)"test", NULL, NtUserSendMessage, TRUE );
|
2022-04-04 14:57:23 +00:00
|
|
|
ok( res == 6, "res = %Iu\n", res );
|
|
|
|
|
|
|
|
SetLastError( 0xdeadbeef );
|
2022-04-08 11:30:22 +00:00
|
|
|
res = NtUserMessageCall( UlongToHandle(0xdeadbeef), WM_USER, 1, 2, 0, NtUserSendMessage, TRUE );
|
2022-04-04 14:57:23 +00:00
|
|
|
ok( !res, "res = %Iu\n", res );
|
|
|
|
ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "GetLastError() = %lu\n", GetLastError());
|
|
|
|
|
2022-04-08 11:30:22 +00:00
|
|
|
res = NtUserMessageCall( hwnd, WM_USER + 1, 0, large_lparam, 0, NtUserSendMessage, FALSE );
|
2022-04-04 14:57:23 +00:00
|
|
|
ok( res == large_lparam, "res = %Iu\n", res );
|
|
|
|
|
|
|
|
smp.flags = 0;
|
|
|
|
smp.timeout = 10;
|
|
|
|
smp.result = 0xdeadbeef;
|
2022-04-08 11:30:22 +00:00
|
|
|
res = NtUserMessageCall( hwnd, WM_USER, 1, 2, &smp, NtUserSendMessageTimeout, FALSE );
|
2022-04-04 14:57:23 +00:00
|
|
|
ok( res == 3, "res = %Iu\n", res );
|
|
|
|
ok( smp.result == 1, "smp.result = %Iu\n", smp.result );
|
|
|
|
|
|
|
|
smp.flags = 0;
|
|
|
|
smp.timeout = 10;
|
|
|
|
smp.result = 0xdeadbeef;
|
|
|
|
res = NtUserMessageCall( hwnd, WM_USER + 1, 0, large_lparam,
|
2022-04-08 11:30:22 +00:00
|
|
|
&smp, NtUserSendMessageTimeout, FALSE );
|
2022-04-04 14:57:23 +00:00
|
|
|
ok( res == large_lparam, "res = %Iu\n", res );
|
|
|
|
ok( smp.result == 1, "smp.result = %Iu\n", smp.result );
|
|
|
|
|
|
|
|
res = NtUserMessageCall( hwnd, WM_USER, 1, 2, (void *)0xdeadbeef,
|
2022-04-08 11:30:22 +00:00
|
|
|
NtUserSendNotifyMessage, FALSE );
|
2022-04-04 14:57:23 +00:00
|
|
|
ok( res == 1, "res = %Iu\n", res );
|
|
|
|
|
|
|
|
res = NtUserMessageCall( hwnd, WM_USER, 1, 2, &callback_params,
|
2022-04-08 11:30:22 +00:00
|
|
|
NtUserSendMessageCallback, FALSE );
|
2022-04-04 14:57:23 +00:00
|
|
|
ok( res == 1, "res = %Iu\n", res );
|
|
|
|
|
|
|
|
DestroyWindow( hwnd );
|
|
|
|
UnregisterClassW( L"TestClass", NULL );
|
|
|
|
}
|
|
|
|
|
2022-04-07 13:24:55 +00:00
|
|
|
static void test_window_text(void)
|
|
|
|
{
|
|
|
|
WCHAR buf[512];
|
|
|
|
LRESULT res;
|
|
|
|
int len;
|
|
|
|
HWND hwnd;
|
|
|
|
|
|
|
|
hwnd = CreateWindowExW( 0, L"static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL );
|
|
|
|
|
|
|
|
memset( buf, 0xcc, sizeof(buf) );
|
|
|
|
len = NtUserInternalGetWindowText( hwnd, buf, ARRAYSIZE(buf) );
|
|
|
|
ok( len == 0, "len = %d\n", len );
|
|
|
|
ok( !buf[0], "buf = %s\n", wine_dbgstr_w(buf) );
|
|
|
|
|
2022-04-08 11:30:22 +00:00
|
|
|
res = NtUserMessageCall( hwnd, WM_SETTEXT, 0, (LPARAM)L"test", 0, NtUserDefWindowProc, FALSE );
|
2022-04-07 13:24:55 +00:00
|
|
|
ok( res == 1, "res = %Id\n", res );
|
|
|
|
|
|
|
|
memset( buf, 0xcc, sizeof(buf) );
|
|
|
|
len = NtUserInternalGetWindowText( hwnd, buf, ARRAYSIZE(buf) );
|
|
|
|
ok( len == 4, "len = %d\n", len );
|
|
|
|
ok( !lstrcmpW( buf, L"test" ), "buf = %s\n", wine_dbgstr_w(buf) );
|
|
|
|
|
2022-06-20 15:58:21 +00:00
|
|
|
res = NtUserMessageCall( hwnd, WM_GETTEXTLENGTH, 0, 0, 0, NtUserDefWindowProc, TRUE );
|
|
|
|
ok( res == 4, "res = %Id\n", res );
|
|
|
|
|
|
|
|
res = NtUserMessageCall( hwnd, WM_GETTEXTLENGTH, 0, 0, 0, NtUserDefWindowProc, FALSE );
|
|
|
|
ok( res == 4, "res = %Id\n", res );
|
|
|
|
|
2022-04-08 11:30:22 +00:00
|
|
|
res = NtUserMessageCall( hwnd, WM_SETTEXT, 0, (LPARAM)"TestA", 0, NtUserDefWindowProc, TRUE );
|
2022-04-07 13:24:55 +00:00
|
|
|
ok( res == 1, "res = %Id\n", res );
|
|
|
|
|
|
|
|
memset( buf, 0xcc, sizeof(buf) );
|
|
|
|
len = NtUserInternalGetWindowText( hwnd, buf, ARRAYSIZE(buf) );
|
|
|
|
ok( len == 5, "len = %d\n", len );
|
|
|
|
ok( !lstrcmpW( buf, L"TestA" ), "buf = %s\n", wine_dbgstr_w(buf) );
|
|
|
|
|
2022-06-20 15:58:21 +00:00
|
|
|
res = NtUserMessageCall( hwnd, WM_GETTEXTLENGTH, 0, 0, 0, NtUserDefWindowProc, TRUE );
|
|
|
|
ok( res == 5, "res = %Id\n", res );
|
|
|
|
|
2022-04-07 13:24:55 +00:00
|
|
|
DestroyWindow( hwnd );
|
|
|
|
}
|
|
|
|
|
2022-04-30 23:10:44 +00:00
|
|
|
#define test_menu_item_id(a, b, c) test_menu_item_id_(a, b, c, __LINE__)
|
|
|
|
static void test_menu_item_id_( HMENU menu, int pos, int expect, int line )
|
|
|
|
{
|
|
|
|
MENUITEMINFOW item;
|
|
|
|
BOOL ret;
|
|
|
|
|
|
|
|
item.cbSize = sizeof(item);
|
|
|
|
item.fMask = MIIM_ID;
|
|
|
|
ret = GetMenuItemInfoW( menu, pos, TRUE, &item );
|
|
|
|
ok_(__FILE__,line)( ret, "GetMenuItemInfoW failed: %lu\n", GetLastError() );
|
|
|
|
ok_(__FILE__,line)( item.wID == expect, "got if %d, expected %d\n", item.wID, expect );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_menu(void)
|
|
|
|
{
|
|
|
|
MENUITEMINFOW item;
|
|
|
|
HMENU menu;
|
|
|
|
int count;
|
|
|
|
BOOL ret;
|
|
|
|
|
|
|
|
menu = CreateMenu();
|
|
|
|
|
|
|
|
memset( &item, 0, sizeof(item) );
|
|
|
|
item.cbSize = sizeof(item);
|
|
|
|
item.fMask = MIIM_ID;
|
|
|
|
item.wID = 10;
|
|
|
|
ret = NtUserThunkedMenuItemInfo( menu, 0, MF_BYPOSITION, NtUserInsertMenuItem, &item, NULL );
|
|
|
|
ok( ret, "InsertMenuItemW failed: %lu\n", GetLastError() );
|
|
|
|
|
|
|
|
count = GetMenuItemCount( menu );
|
|
|
|
ok( count == 1, "count = %d\n", count );
|
|
|
|
|
|
|
|
item.wID = 20;
|
|
|
|
ret = NtUserThunkedMenuItemInfo( menu, 1, MF_BYPOSITION, NtUserInsertMenuItem, &item, NULL );
|
|
|
|
ok( ret, "InsertMenuItemW failed: %lu\n", GetLastError() );
|
|
|
|
|
|
|
|
count = GetMenuItemCount( menu );
|
|
|
|
ok( count == 2, "count = %d\n", count );
|
|
|
|
test_menu_item_id( menu, 0, 10 );
|
|
|
|
test_menu_item_id( menu, 1, 20 );
|
|
|
|
|
|
|
|
item.wID = 30;
|
|
|
|
ret = NtUserThunkedMenuItemInfo( menu, 1, MF_BYPOSITION, NtUserInsertMenuItem, &item, NULL );
|
|
|
|
ok( ret, "InsertMenuItemW failed: %lu\n", GetLastError() );
|
|
|
|
|
|
|
|
count = GetMenuItemCount( menu );
|
|
|
|
ok( count == 3, "count = %d\n", count );
|
|
|
|
test_menu_item_id( menu, 0, 10 );
|
|
|
|
test_menu_item_id( menu, 1, 30 );
|
|
|
|
test_menu_item_id( menu, 2, 20 );
|
|
|
|
|
|
|
|
item.wID = 50;
|
|
|
|
ret = NtUserThunkedMenuItemInfo( menu, 10, 0, NtUserInsertMenuItem, &item, NULL );
|
|
|
|
ok( ret, "InsertMenuItemW failed: %lu\n", GetLastError() );
|
|
|
|
|
|
|
|
count = GetMenuItemCount( menu );
|
|
|
|
ok( count == 4, "count = %d\n", count );
|
|
|
|
test_menu_item_id( menu, 0, 50 );
|
|
|
|
test_menu_item_id( menu, 1, 10 );
|
|
|
|
test_menu_item_id( menu, 2, 30 );
|
|
|
|
test_menu_item_id( menu, 3, 20 );
|
|
|
|
|
|
|
|
item.wID = 60;
|
|
|
|
ret = NtUserThunkedMenuItemInfo( menu, 1, MF_BYPOSITION, NtUserSetMenuItemInfo, &item, NULL );
|
|
|
|
ok( ret, "InsertMenuItemW failed: %lu\n", GetLastError() );
|
|
|
|
|
|
|
|
count = GetMenuItemCount( menu );
|
|
|
|
ok( count == 4, "count = %d\n", count );
|
|
|
|
test_menu_item_id( menu, 1, 60 );
|
|
|
|
|
|
|
|
ret = NtUserDestroyMenu( menu );
|
|
|
|
ok( ret, "NtUserDestroyMenu failed: %lu\n", GetLastError() );
|
|
|
|
}
|
|
|
|
|
2022-04-15 15:25:57 +00:00
|
|
|
static MSG *msg_ptr;
|
|
|
|
|
|
|
|
static LRESULT WINAPI hook_proc( INT code, WPARAM wparam, LPARAM lparam )
|
|
|
|
{
|
|
|
|
msg_ptr = (MSG *)lparam;
|
|
|
|
ok( code == 100, "code = %d\n", code );
|
|
|
|
ok( msg_ptr->time == 1, "time = %lx\n", msg_ptr->time );
|
|
|
|
ok( msg_ptr->wParam == 10, "wParam = %Ix\n", msg_ptr->wParam );
|
|
|
|
ok( msg_ptr->lParam == 20, "lParam = %Ix\n", msg_ptr->lParam );
|
|
|
|
msg_ptr->time = 3;
|
|
|
|
msg_ptr->wParam = 1;
|
|
|
|
msg_ptr->lParam = 2;
|
|
|
|
return CallNextHookEx( NULL, code, wparam, lparam );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_message_filter(void)
|
|
|
|
{
|
|
|
|
HHOOK hook;
|
|
|
|
MSG msg;
|
|
|
|
BOOL ret;
|
|
|
|
|
|
|
|
hook = SetWindowsHookExW( WH_MSGFILTER, hook_proc, NULL, GetCurrentThreadId() );
|
|
|
|
ok( hook != NULL, "SetWindowsHookExW failed\n");
|
|
|
|
|
|
|
|
memset( &msg, 0, sizeof(msg) );
|
|
|
|
msg.time = 1;
|
|
|
|
msg.wParam = 10;
|
|
|
|
msg.lParam = 20;
|
|
|
|
ret = NtUserCallMsgFilter( &msg, 100 );
|
|
|
|
ok( !ret, "CallMsgFilterW returned: %x\n", ret );
|
|
|
|
ok( msg_ptr != &msg, "our ptr was passed directly to hook\n" );
|
|
|
|
|
|
|
|
if (sizeof(void *) == 8) /* on some Windows versions, msg is not modified on wow64 */
|
|
|
|
{
|
|
|
|
ok( msg.time == 3, "time = %lx\n", msg.time );
|
|
|
|
ok( msg.wParam == 1, "wParam = %Ix\n", msg.wParam );
|
|
|
|
ok( msg.lParam == 2, "lParam = %Ix\n", msg.lParam );
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = NtUserUnhookWindowsHookEx( hook );
|
|
|
|
ok( ret, "NtUserUnhookWindowsHook failed: %lu\n", GetLastError() );
|
|
|
|
}
|
|
|
|
|
2022-07-19 17:51:53 +00:00
|
|
|
static char calls[128];
|
|
|
|
|
|
|
|
static void WINAPI timer_func( HWND hwnd, UINT msg, UINT_PTR id, DWORD time )
|
|
|
|
{
|
|
|
|
sprintf( calls + strlen( calls ), "timer%Iu,", id );
|
|
|
|
NtUserKillTimer( hwnd, id );
|
|
|
|
|
|
|
|
if (!id)
|
|
|
|
{
|
|
|
|
MSG msg;
|
|
|
|
NtUserSetTimer( hwnd, 1, 1, timer_func, TIMERV_DEFAULT_COALESCING );
|
|
|
|
while (GetMessageW( &msg, NULL, 0, 0 ))
|
|
|
|
{
|
|
|
|
TranslateMessage( &msg );
|
|
|
|
NtUserDispatchMessage( &msg );
|
|
|
|
if (msg.message == WM_TIMER) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
strcat( calls, "crash," );
|
|
|
|
*(volatile int *)0 = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_timer(void)
|
|
|
|
{
|
|
|
|
HWND hwnd;
|
|
|
|
MSG msg;
|
|
|
|
|
|
|
|
hwnd = CreateWindowExA( 0, "static", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL );
|
|
|
|
|
|
|
|
NtUserSetTimer( hwnd, 0, 1, timer_func, TIMERV_DEFAULT_COALESCING );
|
|
|
|
|
|
|
|
calls[0] = 0;
|
|
|
|
while (GetMessageW( &msg, NULL, 0, 0 ))
|
|
|
|
{
|
|
|
|
TranslateMessage( &msg );
|
|
|
|
NtUserDispatchMessage( &msg );
|
|
|
|
if (msg.message == WM_TIMER) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ok( !strcmp( calls, "timer0,timer1,crash,crash," ), "calls = %s\n", calls );
|
|
|
|
DestroyWindow( hwnd );
|
|
|
|
}
|
|
|
|
|
2022-10-24 22:27:16 +00:00
|
|
|
static void test_NtUserDisplayConfigGetDeviceInfo(void)
|
|
|
|
{
|
|
|
|
DISPLAYCONFIG_SOURCE_DEVICE_NAME source_name;
|
|
|
|
NTSTATUS status;
|
|
|
|
|
|
|
|
source_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
|
|
|
|
source_name.header.size = sizeof(source_name.header);
|
|
|
|
status = NtUserDisplayConfigGetDeviceInfo(&source_name.header);
|
|
|
|
ok(status == STATUS_INVALID_PARAMETER, "got %#lx.\n", status);
|
|
|
|
|
|
|
|
source_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
|
|
|
|
source_name.header.size = sizeof(source_name);
|
|
|
|
source_name.header.adapterId.LowPart = 0xFFFF;
|
|
|
|
source_name.header.adapterId.HighPart = 0xFFFF;
|
|
|
|
source_name.header.id = 0;
|
|
|
|
status = NtUserDisplayConfigGetDeviceInfo(&source_name.header);
|
|
|
|
ok(status == STATUS_UNSUCCESSFUL || status == STATUS_NOT_SUPPORTED, "got %#lx.\n", status);
|
|
|
|
}
|
|
|
|
|
2022-12-20 12:52:26 +00:00
|
|
|
static LRESULT WINAPI test_ipc_message_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
|
|
|
|
{
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case WM_SETTEXT:
|
|
|
|
case CB_FINDSTRING:
|
|
|
|
ok( !wcscmp( (const WCHAR *)lparam, L"test" ),
|
|
|
|
"lparam = %s\n", wine_dbgstr_w( (const WCHAR *)lparam ));
|
|
|
|
return 6;
|
|
|
|
|
|
|
|
case WM_GETTEXT:
|
|
|
|
case EM_GETLINE:
|
|
|
|
ok( wparam == 100, "wparam = %Iu\n", wparam );
|
|
|
|
wcscpy( (void *)lparam, L"Test" );
|
|
|
|
return 4;
|
|
|
|
|
2023-07-20 22:42:30 +00:00
|
|
|
case CB_GETLBTEXT:
|
|
|
|
ok( wparam == 100, "wparam = %Iu\n", wparam );
|
|
|
|
wcscpy( (void *)lparam, L"Te" );
|
|
|
|
return 4;
|
|
|
|
|
2022-12-20 12:52:26 +00:00
|
|
|
case WM_GETTEXTLENGTH:
|
|
|
|
return 99;
|
|
|
|
|
|
|
|
case WM_MDICREATE:
|
|
|
|
{
|
|
|
|
MDICREATESTRUCTW *mdi = (MDICREATESTRUCTW *)lparam;
|
|
|
|
ok( !wcscmp( mdi->szClass, L"TestClass" ), "szClass = %s\n", wine_dbgstr_w( mdi->szClass ));
|
|
|
|
ok( !wcscmp( mdi->szTitle, L"TestTitle" ), "szTitle = %s\n", wine_dbgstr_w( mdi->szTitle ));
|
|
|
|
return 0xdeadbeef;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return DefWindowProcW( hwnd, msg, wparam, lparam );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_inter_process_messages( const char *argv0 )
|
|
|
|
{
|
|
|
|
WNDCLASSW cls = { 0 };
|
|
|
|
char path[MAX_PATH];
|
|
|
|
PROCESS_INFORMATION pi;
|
|
|
|
STARTUPINFOA startup;
|
|
|
|
MSG msg;
|
|
|
|
HWND hwnd;
|
|
|
|
BOOL ret;
|
|
|
|
|
|
|
|
cls.lpfnWndProc = test_ipc_message_proc;
|
|
|
|
cls.lpszClassName = L"TestIPCClass";
|
|
|
|
RegisterClassW( &cls );
|
|
|
|
|
|
|
|
hwnd = CreateWindowExW( 0, L"TestIPCClass", NULL, WS_POPUP | CBS_HASSTRINGS, 0,0,0,0,0,0,0, NULL );
|
|
|
|
|
|
|
|
memset( &startup, 0, sizeof(startup) );
|
|
|
|
startup.cb = sizeof(startup);
|
|
|
|
startup.dwFlags = STARTF_USESHOWWINDOW;
|
|
|
|
startup.wShowWindow = SW_SHOWNORMAL;
|
|
|
|
sprintf( path, "%s win32u ipcmsg %Ix", argv0, (INT_PTR)hwnd );
|
|
|
|
ret = CreateProcessA( NULL, path, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &pi );
|
|
|
|
ok( ret, "CreateProcess '%s' failed err %lu.\n", path, GetLastError() );
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
GetMessageW( &msg, NULL, 0, 0 );
|
|
|
|
TranslateMessage( &msg );
|
|
|
|
DispatchMessageW( &msg );
|
|
|
|
} while (msg.message != WM_USER);
|
|
|
|
|
|
|
|
wait_child_process( pi.hProcess );
|
|
|
|
|
|
|
|
CloseHandle( pi.hThread );
|
|
|
|
CloseHandle( pi.hProcess );
|
|
|
|
|
|
|
|
DestroyWindow( hwnd );
|
|
|
|
UnregisterClassW( L"TestIPCClass", NULL );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_inter_process_child( HWND hwnd )
|
|
|
|
{
|
|
|
|
MDICREATESTRUCTA mdi;
|
|
|
|
WCHAR bufW[100];
|
|
|
|
char buf[100];
|
|
|
|
int res;
|
|
|
|
|
|
|
|
res = SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)"test" );
|
|
|
|
ok( res == 6, "WM_SETTEXT returned %d\n", res );
|
|
|
|
|
|
|
|
res = NtUserMessageCall( hwnd, WM_SETTEXT, 0, (LPARAM)"test", NULL, NtUserSendMessage, TRUE );
|
|
|
|
ok( res == 6, "res = %d\n", res );
|
|
|
|
|
|
|
|
res = NtUserMessageCall( hwnd, CB_FINDSTRING, 0, (LPARAM)"test", NULL, NtUserSendMessage, TRUE );
|
|
|
|
ok( res == 6, "res = %d\n", res );
|
|
|
|
|
|
|
|
memset( buf, 0xcc, sizeof(buf) );
|
|
|
|
res = NtUserMessageCall( hwnd, WM_GETTEXT, sizeof(buf), (LPARAM)buf, NULL, NtUserSendMessage, TRUE );
|
|
|
|
ok( res == 4, "res = %d\n", res );
|
|
|
|
ok( !strcmp( buf, "Test" ), "buf = %s\n", buf );
|
|
|
|
|
|
|
|
memset( bufW, 0xcc, sizeof(bufW) );
|
|
|
|
res = NtUserMessageCall( hwnd, WM_GETTEXT, ARRAYSIZE(bufW), (LPARAM)bufW, NULL, NtUserSendMessage, FALSE );
|
|
|
|
ok( res == 4, "res = %d\n", res );
|
|
|
|
ok( !wcscmp( bufW, L"Test" ), "buf = %s\n", buf );
|
|
|
|
|
|
|
|
memset( buf, 0xcc, sizeof(buf) );
|
|
|
|
res = NtUserMessageCall( hwnd, CB_GETLBTEXT, 100, (LPARAM)buf, NULL, NtUserSendMessage, TRUE );
|
|
|
|
todo_wine
|
|
|
|
ok( res == 1, "res = %d\n", res );
|
|
|
|
ok( buf[0] == 'T', "buf[0] = %c\n", buf[0] );
|
|
|
|
todo_wine
|
|
|
|
ok( buf[1] == (char)0xcc, "buf[1] = %x\n", buf[1] );
|
|
|
|
|
2023-07-20 22:42:30 +00:00
|
|
|
memset( bufW, 0xcc, sizeof(bufW) );
|
|
|
|
res = NtUserMessageCall( hwnd, CB_GETLBTEXT, 100, (LPARAM)bufW, NULL, NtUserSendMessage, FALSE );
|
|
|
|
todo_wine
|
|
|
|
ok( res == 1, "res = %d\n", res );
|
|
|
|
ok( bufW[0] == 'T', "bufW[0] = %c\n", buf[0] );
|
|
|
|
ok( bufW[1] && buf[1] != 'e', "bufW[1] = %x\n", buf[1] );
|
|
|
|
|
2022-12-20 12:52:26 +00:00
|
|
|
memset( buf, 0xcc, sizeof(buf) );
|
|
|
|
*(DWORD *)buf = ARRAYSIZE(buf);
|
|
|
|
res = NtUserMessageCall( hwnd, EM_GETLINE, sizeof(buf), (LPARAM)buf, NULL, NtUserSendMessage, TRUE );
|
|
|
|
ok( res == 4, "res = %d\n", res );
|
|
|
|
ok( !strcmp( buf, "Test" ), "buf = %s\n", buf );
|
|
|
|
|
|
|
|
res = NtUserMessageCall( hwnd, WM_GETTEXTLENGTH, 0, 0, NULL, NtUserSendMessage, TRUE );
|
|
|
|
ok( res == 4, "res = %d\n", res );
|
|
|
|
|
|
|
|
mdi.szClass = "TestClass";
|
|
|
|
mdi.szTitle = "TestTitle";
|
|
|
|
mdi.hOwner = 0;
|
|
|
|
mdi.x = mdi.y = 10;
|
|
|
|
mdi.cx = mdi.cy = 100;
|
|
|
|
mdi.style = 0;
|
|
|
|
mdi.lParam = 0xdeadbeef;
|
|
|
|
res = NtUserMessageCall( hwnd, WM_MDICREATE, 0, (LPARAM)&mdi, NULL, NtUserSendMessage, TRUE );
|
|
|
|
ok( res == 0xdeadbeef, "res = %d\n", res );
|
|
|
|
|
|
|
|
PostMessageA( hwnd, WM_USER, 0, 0 );
|
|
|
|
}
|
|
|
|
|
2023-01-28 09:35:54 +00:00
|
|
|
static DWORD CALLBACK test_NtUserGetPointerInfoList_thread( void *arg )
|
|
|
|
{
|
|
|
|
POINTER_INFO pointer_info[4] = {0};
|
|
|
|
UINT32 entry_count, pointer_count;
|
|
|
|
HWND hwnd;
|
|
|
|
BOOL ret;
|
|
|
|
|
|
|
|
hwnd = CreateWindowW( L"test", L"test name", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
|
|
|
|
100, 100, 200, 200, 0, 0, NULL, 0 );
|
|
|
|
flush_events();
|
|
|
|
|
|
|
|
memset( &pointer_info, 0xcd, sizeof(pointer_info) );
|
|
|
|
entry_count = pointer_count = 2;
|
|
|
|
ret = NtUserGetPointerInfoList( 1, PT_POINTER, 0, 0, sizeof(POINTER_INFO), &entry_count, &pointer_count, pointer_info );
|
|
|
|
ok( !ret, "NtUserGetPointerInfoList succeeded\n" );
|
|
|
|
ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
|
|
|
|
ok( pointer_count == 2, "got pointer_count %u\n", pointer_count );
|
|
|
|
ok( entry_count == 2, "got entry_count %u\n", entry_count );
|
|
|
|
|
|
|
|
DestroyWindow( hwnd );
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define check_pointer_info( a, b ) check_pointer_info_( __LINE__, a, b )
|
|
|
|
static void check_pointer_info_( int line, const POINTER_INFO *actual, const POINTER_INFO *expected )
|
|
|
|
{
|
|
|
|
check_member( *actual, *expected, "%#lx", pointerType );
|
|
|
|
check_member( *actual, *expected, "%#x", pointerId );
|
|
|
|
check_member( *actual, *expected, "%#x", frameId );
|
|
|
|
check_member( *actual, *expected, "%#x", pointerFlags );
|
|
|
|
check_member( *actual, *expected, "%p", sourceDevice );
|
|
|
|
check_member( *actual, *expected, "%p", hwndTarget );
|
|
|
|
check_member( *actual, *expected, "%+ld", ptPixelLocation.x );
|
|
|
|
check_member( *actual, *expected, "%+ld", ptPixelLocation.y );
|
|
|
|
check_member( *actual, *expected, "%+ld", ptHimetricLocation.x );
|
|
|
|
check_member( *actual, *expected, "%+ld", ptHimetricLocation.y );
|
|
|
|
check_member( *actual, *expected, "%+ld", ptPixelLocationRaw.x );
|
|
|
|
check_member( *actual, *expected, "%+ld", ptPixelLocationRaw.y );
|
|
|
|
check_member( *actual, *expected, "%+ld", ptHimetricLocationRaw.x );
|
|
|
|
check_member( *actual, *expected, "%+ld", ptHimetricLocationRaw.y );
|
|
|
|
check_member( *actual, *expected, "%lu", dwTime );
|
|
|
|
check_member( *actual, *expected, "%u", historyCount );
|
|
|
|
check_member( *actual, *expected, "%#x", InputData );
|
|
|
|
check_member( *actual, *expected, "%#lx", dwKeyStates );
|
|
|
|
check_member( *actual, *expected, "%I64u", PerformanceCount );
|
|
|
|
check_member( *actual, *expected, "%#x", ButtonChangeType );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_NtUserGetPointerInfoList( BOOL mouse_in_pointer_enabled )
|
|
|
|
{
|
|
|
|
void *invalid_ptr = (void *)0xdeadbeef;
|
|
|
|
POINTER_TOUCH_INFO touch_info[4] = {0};
|
|
|
|
POINTER_PEN_INFO pen_info[4] = {0};
|
|
|
|
POINTER_INFO pointer_info[4] = {0};
|
|
|
|
UINT32 entry_count, pointer_count;
|
|
|
|
WNDCLASSW cls =
|
|
|
|
{
|
|
|
|
.lpfnWndProc = DefWindowProcW,
|
|
|
|
.hInstance = GetModuleHandleW( NULL ),
|
|
|
|
.hbrBackground = GetStockObject( WHITE_BRUSH ),
|
|
|
|
.lpszClassName = L"test",
|
|
|
|
};
|
|
|
|
HANDLE thread;
|
|
|
|
SIZE_T size;
|
|
|
|
ATOM class;
|
|
|
|
DWORD res;
|
|
|
|
HWND hwnd;
|
|
|
|
BOOL ret;
|
|
|
|
|
|
|
|
class = RegisterClassW( &cls );
|
|
|
|
ok( class, "RegisterClassW failed: %lu\n", GetLastError() );
|
|
|
|
|
|
|
|
entry_count = pointer_count = 2;
|
|
|
|
ret = NtUserGetPointerInfoList( 1, PT_POINTER, 0, 0, sizeof(POINTER_INFO), invalid_ptr, &pointer_count, pointer_info );
|
|
|
|
ok( !ret, "NtUserGetPointerInfoList succeeded\n" );
|
|
|
|
todo_wine
|
|
|
|
ok( GetLastError() == ERROR_NOACCESS, "got error %lu\n", GetLastError() );
|
|
|
|
entry_count = pointer_count = 2;
|
|
|
|
ret = NtUserGetPointerInfoList( 1, PT_POINTER, 0, 0, sizeof(POINTER_INFO), &entry_count, invalid_ptr, pointer_info );
|
|
|
|
ok( !ret, "NtUserGetPointerInfoList succeeded\n" );
|
|
|
|
todo_wine
|
|
|
|
ok( GetLastError() == ERROR_NOACCESS, "got error %lu\n", GetLastError() );
|
|
|
|
entry_count = pointer_count = 2;
|
|
|
|
ret = NtUserGetPointerInfoList( 1, PT_POINTER, 0, 0, sizeof(POINTER_INFO), &entry_count, &pointer_count, invalid_ptr );
|
|
|
|
ok( !ret, "NtUserGetPointerInfoList succeeded\n" );
|
|
|
|
todo_wine
|
|
|
|
ok( GetLastError() == ERROR_NOACCESS || broken(GetLastError() == ERROR_INVALID_PARAMETER) /* w10 32bit */, "got error %lu\n", GetLastError() );
|
|
|
|
|
|
|
|
memset( pointer_info, 0xcd, sizeof(pointer_info) );
|
|
|
|
entry_count = pointer_count = 2;
|
|
|
|
ret = NtUserGetPointerInfoList( 1, PT_POINTER, 0, 0, sizeof(POINTER_INFO), &entry_count, &pointer_count, pointer_info );
|
|
|
|
ok( !ret, "NtUserGetPointerInfoList succeeded\n" );
|
|
|
|
todo_wine
|
|
|
|
ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
|
|
|
|
ok( pointer_count == 2, "got pointer_count %u\n", pointer_count );
|
|
|
|
ok( entry_count == 2, "got entry_count %u\n", entry_count );
|
|
|
|
|
|
|
|
SetCursorPos( 500, 500 ); /* avoid generating mouse message on window creation */
|
|
|
|
|
|
|
|
hwnd = CreateWindowW( L"test", L"test name", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
|
|
|
|
100, 100, 200, 200, 0, 0, NULL, 0 );
|
|
|
|
flush_events();
|
|
|
|
|
|
|
|
memset( pointer_info, 0xcd, sizeof(pointer_info) );
|
|
|
|
entry_count = pointer_count = 2;
|
|
|
|
ret = NtUserGetPointerInfoList( 1, PT_POINTER, 0, 0, sizeof(POINTER_INFO), &entry_count, &pointer_count, pointer_info );
|
|
|
|
ok( !ret, "NtUserGetPointerInfoList succeeded\n" );
|
|
|
|
todo_wine
|
|
|
|
ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
|
|
|
|
ok( pointer_count == 2, "got pointer_count %u\n", pointer_count );
|
|
|
|
ok( entry_count == 2, "got entry_count %u\n", entry_count );
|
|
|
|
|
|
|
|
SetCursorPos( 200, 200 );
|
|
|
|
flush_events();
|
|
|
|
mouse_event( MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 );
|
|
|
|
flush_events();
|
|
|
|
mouse_event( MOUSEEVENTF_LEFTUP, 0, 0, 0, 0 );
|
|
|
|
flush_events();
|
|
|
|
mouse_event( MOUSEEVENTF_MOVE, 10, 10, 0, 0 );
|
|
|
|
flush_events();
|
|
|
|
|
|
|
|
memset( pointer_info, 0xcd, sizeof(pointer_info) );
|
|
|
|
entry_count = pointer_count = 2;
|
|
|
|
ret = NtUserGetPointerInfoList( 1, PT_POINTER, 0, 0, sizeof(POINTER_INFO), &entry_count, &pointer_count, pointer_info );
|
|
|
|
todo_wine_if(mouse_in_pointer_enabled)
|
|
|
|
ok( ret == mouse_in_pointer_enabled, "NtUserGetPointerInfoList failed, error %lu\n", GetLastError() );
|
|
|
|
if (!ret)
|
|
|
|
{
|
|
|
|
todo_wine
|
|
|
|
ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
ok( pointer_count == 1, "got pointer_count %u\n", pointer_count );
|
|
|
|
ok( entry_count == 1, "got entry_count %u\n", entry_count );
|
|
|
|
ok( pointer_info[0].pointerType == PT_MOUSE, "got pointerType %lu\n", pointer_info[0].pointerType );
|
|
|
|
ok( pointer_info[0].pointerId == 1, "got pointerId %u\n", pointer_info[0].pointerId );
|
|
|
|
ok( !!pointer_info[0].frameId, "got frameId %u\n", pointer_info[0].frameId );
|
|
|
|
ok( pointer_info[0].pointerFlags == (0x20000 | POINTER_MESSAGE_FLAG_INRANGE | POINTER_MESSAGE_FLAG_PRIMARY),
|
|
|
|
"got pointerFlags %#x\n", pointer_info[0].pointerFlags );
|
|
|
|
ok( pointer_info[0].sourceDevice == INVALID_HANDLE_VALUE || broken(!!pointer_info[0].sourceDevice) /* w1064v1809 32bit */,
|
|
|
|
"got sourceDevice %p\n", pointer_info[0].sourceDevice );
|
|
|
|
ok( pointer_info[0].hwndTarget == hwnd, "got hwndTarget %p\n", pointer_info[0].hwndTarget );
|
|
|
|
ok( !!pointer_info[0].ptPixelLocation.x, "got ptPixelLocation %s\n", wine_dbgstr_point( &pointer_info[0].ptPixelLocation ) );
|
|
|
|
ok( !!pointer_info[0].ptPixelLocation.y, "got ptPixelLocation %s\n", wine_dbgstr_point( &pointer_info[0].ptPixelLocation ) );
|
|
|
|
ok( !!pointer_info[0].ptHimetricLocation.x, "got ptHimetricLocation %s\n", wine_dbgstr_point( &pointer_info[0].ptHimetricLocation ) );
|
|
|
|
ok( !!pointer_info[0].ptHimetricLocation.y, "got ptHimetricLocation %s\n", wine_dbgstr_point( &pointer_info[0].ptHimetricLocation ) );
|
|
|
|
ok( !!pointer_info[0].ptPixelLocationRaw.x, "got ptPixelLocationRaw %s\n", wine_dbgstr_point( &pointer_info[0].ptPixelLocationRaw ) );
|
|
|
|
ok( !!pointer_info[0].ptPixelLocationRaw.y, "got ptPixelLocationRaw %s\n", wine_dbgstr_point( &pointer_info[0].ptPixelLocationRaw ) );
|
|
|
|
ok( !!pointer_info[0].ptHimetricLocationRaw.x, "got ptHimetricLocationRaw %s\n", wine_dbgstr_point( &pointer_info[0].ptHimetricLocationRaw ) );
|
|
|
|
ok( !!pointer_info[0].ptHimetricLocationRaw.y, "got ptHimetricLocationRaw %s\n", wine_dbgstr_point( &pointer_info[0].ptHimetricLocationRaw ) );
|
|
|
|
ok( !!pointer_info[0].dwTime, "got dwTime %lu\n", pointer_info[0].dwTime );
|
|
|
|
ok( pointer_info[0].historyCount == 1, "got historyCount %u\n", pointer_info[0].historyCount );
|
|
|
|
ok( pointer_info[0].InputData == 0, "got InputData %u\n", pointer_info[0].InputData );
|
|
|
|
ok( pointer_info[0].dwKeyStates == 0, "got dwKeyStates %lu\n", pointer_info[0].dwKeyStates );
|
|
|
|
ok( !!pointer_info[0].PerformanceCount, "got PerformanceCount %I64u\n", pointer_info[0].PerformanceCount );
|
|
|
|
ok( pointer_info[0].ButtonChangeType == 0, "got ButtonChangeType %u\n", pointer_info[0].ButtonChangeType );
|
|
|
|
|
|
|
|
thread = CreateThread( NULL, 0, test_NtUserGetPointerInfoList_thread, NULL, 0, NULL );
|
|
|
|
res = WaitForSingleObject( thread, 5000 );
|
|
|
|
ok( !res, "WaitForSingleObject returned %#lx, error %lu\n", res, GetLastError() );
|
|
|
|
|
|
|
|
memset( pen_info, 0xa5, sizeof(pen_info) );
|
|
|
|
entry_count = pointer_count = 2;
|
|
|
|
ret = NtUserGetPointerInfoList( 1, PT_PEN, 0, 0, sizeof(POINTER_PEN_INFO), &entry_count, &pointer_count, pen_info );
|
|
|
|
ok( ret, "NtUserGetPointerInfoList failed, error %lu\n", GetLastError() );
|
|
|
|
ok( pointer_count == 1, "got pointer_count %u\n", pointer_count );
|
|
|
|
ok( entry_count == 1, "got entry_count %u\n", entry_count );
|
|
|
|
check_pointer_info( &pen_info[0].pointerInfo, &pointer_info[0] );
|
|
|
|
memset( touch_info, 0xa5, sizeof(touch_info) );
|
|
|
|
entry_count = pointer_count = 2;
|
|
|
|
ret = NtUserGetPointerInfoList( 1, PT_TOUCH, 0, 0, sizeof(POINTER_TOUCH_INFO), &entry_count, &pointer_count, touch_info );
|
|
|
|
ok( ret, "NtUserGetPointerInfoList failed, error %lu\n", GetLastError() );
|
|
|
|
ok( pointer_count == 1, "got pointer_count %u\n", pointer_count );
|
|
|
|
ok( entry_count == 1, "got entry_count %u\n", entry_count );
|
|
|
|
check_pointer_info( &touch_info[0].pointerInfo, &pointer_info[0] );
|
|
|
|
|
|
|
|
entry_count = pointer_count = 2;
|
|
|
|
ret = NtUserGetPointerInfoList( 1, PT_POINTER, 0, 0, sizeof(POINTER_INFO) - 1, &entry_count, &pointer_count, pointer_info );
|
|
|
|
ok( !ret, "NtUserGetPointerInfoList succeeded\n" );
|
|
|
|
ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
|
|
|
|
entry_count = pointer_count = 2;
|
|
|
|
ret = NtUserGetPointerInfoList( 1, PT_PEN, 0, 0, sizeof(POINTER_PEN_INFO) - 1, &entry_count, &pointer_count, pointer_info );
|
|
|
|
ok( !ret, "NtUserGetPointerInfoList succeeded\n" );
|
|
|
|
ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
|
|
|
|
entry_count = pointer_count = 2;
|
|
|
|
ret = NtUserGetPointerInfoList( 1, PT_TOUCH, 0, 0, sizeof(POINTER_TOUCH_INFO) - 1, &entry_count, &pointer_count, pointer_info );
|
|
|
|
ok( !ret, "NtUserGetPointerInfoList succeeded\n" );
|
|
|
|
ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
|
|
|
|
entry_count = pointer_count = 2;
|
|
|
|
ret = NtUserGetPointerInfoList( 1, PT_TOUCHPAD, 0, 0, sizeof(POINTER_TOUCH_INFO) - 1, &entry_count, &pointer_count, pointer_info );
|
|
|
|
ok( !ret, "NtUserGetPointerInfoList succeeded\n" );
|
|
|
|
ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
|
|
|
|
entry_count = pointer_count = 2;
|
|
|
|
ret = NtUserGetPointerInfoList( 1, PT_POINTER, 0, 0, sizeof(POINTER_INFO) + 1, &entry_count, &pointer_count, pointer_info );
|
|
|
|
ok( !ret, "NtUserGetPointerInfoList succeeded\n" );
|
|
|
|
ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
|
|
|
|
entry_count = pointer_count = 2;
|
|
|
|
ret = NtUserGetPointerInfoList( 1, PT_PEN, 0, 0, sizeof(POINTER_PEN_INFO) + 1, &entry_count, &pointer_count, pointer_info );
|
|
|
|
ok( !ret, "NtUserGetPointerInfoList succeeded\n" );
|
|
|
|
ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
|
|
|
|
entry_count = pointer_count = 2;
|
|
|
|
ret = NtUserGetPointerInfoList( 1, PT_TOUCH, 0, 0, sizeof(POINTER_TOUCH_INFO) + 1, &entry_count, &pointer_count, pointer_info );
|
|
|
|
ok( !ret, "NtUserGetPointerInfoList succeeded\n" );
|
|
|
|
ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
|
|
|
|
entry_count = pointer_count = 2;
|
|
|
|
ret = NtUserGetPointerInfoList( 1, PT_TOUCHPAD, 0, 0, sizeof(POINTER_TOUCH_INFO) + 1, &entry_count, &pointer_count, pointer_info );
|
|
|
|
ok( !ret, "NtUserGetPointerInfoList succeeded\n" );
|
|
|
|
ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
|
|
|
|
|
|
|
|
for (size = 0; size < 0xfff; ++size)
|
|
|
|
{
|
|
|
|
char buffer[0x1000];
|
|
|
|
entry_count = pointer_count = 2;
|
|
|
|
ret = NtUserGetPointerInfoList( 1, PT_MOUSE, 0, 0, size, &entry_count, &pointer_count, buffer );
|
|
|
|
ok( !ret, "NtUserGetPointerInfoList succeeded\n" );
|
|
|
|
ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %lu\n", GetLastError() );
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
DestroyWindow( hwnd );
|
|
|
|
|
|
|
|
ret = UnregisterClassW( L"test", GetModuleHandleW(NULL) );
|
|
|
|
ok( ret, "UnregisterClassW failed: %lu\n", GetLastError() );
|
|
|
|
}
|
|
|
|
|
2022-12-19 10:39:38 +00:00
|
|
|
static void test_NtUserEnableMouseInPointer_process( const char *arg )
|
|
|
|
{
|
|
|
|
DWORD enable = strtoul( arg, 0, 10 );
|
|
|
|
BOOL ret;
|
|
|
|
|
2023-01-28 09:35:31 +00:00
|
|
|
ret = NtUserIsMouseInPointerEnabled();
|
|
|
|
ok( !ret, "NtUserIsMouseInPointerEnabled returned %u, error %lu\n", ret, GetLastError() );
|
|
|
|
|
2022-12-19 10:39:38 +00:00
|
|
|
ret = NtUserEnableMouseInPointer( enable );
|
|
|
|
todo_wine
|
|
|
|
ok( ret, "NtUserEnableMouseInPointer failed, error %lu\n", GetLastError() );
|
2023-01-28 09:35:31 +00:00
|
|
|
ret = NtUserIsMouseInPointerEnabled();
|
|
|
|
todo_wine_if(enable)
|
|
|
|
ok( ret == enable, "NtUserIsMouseInPointerEnabled returned %u, error %lu\n", ret, GetLastError() );
|
2022-12-19 10:39:38 +00:00
|
|
|
|
|
|
|
SetLastError( 0xdeadbeef );
|
|
|
|
ret = NtUserEnableMouseInPointer( !enable );
|
|
|
|
ok( !ret, "NtUserEnableMouseInPointer succeeded\n" );
|
|
|
|
todo_wine
|
|
|
|
ok( GetLastError() == ERROR_ACCESS_DENIED, "got error %lu\n", GetLastError() );
|
2023-01-28 09:35:31 +00:00
|
|
|
ret = NtUserIsMouseInPointerEnabled();
|
|
|
|
todo_wine_if(enable)
|
|
|
|
ok( ret == enable, "NtUserIsMouseInPointerEnabled returned %u, error %lu\n", ret, GetLastError() );
|
2022-12-19 10:39:38 +00:00
|
|
|
|
|
|
|
ret = NtUserEnableMouseInPointer( enable );
|
|
|
|
todo_wine
|
|
|
|
ok( ret, "NtUserEnableMouseInPointer failed, error %lu\n", GetLastError() );
|
2023-01-28 09:35:31 +00:00
|
|
|
ret = NtUserIsMouseInPointerEnabled();
|
|
|
|
todo_wine_if(enable)
|
|
|
|
ok( ret == enable, "NtUserIsMouseInPointerEnabled returned %u, error %lu\n", ret, GetLastError() );
|
2023-01-28 09:35:54 +00:00
|
|
|
|
|
|
|
test_NtUserGetPointerInfoList( enable );
|
2022-12-19 10:39:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void test_NtUserEnableMouseInPointer( char **argv, BOOL enable )
|
|
|
|
{
|
|
|
|
STARTUPINFOA startup = {.cb = sizeof(STARTUPINFOA)};
|
|
|
|
PROCESS_INFORMATION info = {0};
|
|
|
|
char cmdline[MAX_PATH * 2];
|
|
|
|
BOOL ret;
|
|
|
|
|
|
|
|
sprintf( cmdline, "%s %s NtUserEnableMouseInPointer %u", argv[0], argv[1], enable );
|
|
|
|
ret = CreateProcessA( NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info );
|
|
|
|
ok( ret, "CreateProcessA failed, error %lu\n", GetLastError() );
|
|
|
|
if (!ret) return;
|
|
|
|
|
|
|
|
wait_child_process( info.hProcess );
|
|
|
|
CloseHandle( info.hThread );
|
|
|
|
CloseHandle( info.hProcess );
|
|
|
|
}
|
|
|
|
|
2023-07-20 22:42:30 +00:00
|
|
|
struct lparam_hook_test
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
UINT message;
|
|
|
|
WPARAM wparam;
|
2023-07-18 11:58:02 +00:00
|
|
|
BOOL no_wparam_check;
|
2023-07-20 22:42:30 +00:00
|
|
|
LRESULT msg_result;
|
|
|
|
LRESULT check_result;
|
|
|
|
BOOL todo_result;
|
|
|
|
const void *lparam;
|
|
|
|
const void *change_lparam;
|
|
|
|
const void *check_lparam;
|
2023-08-04 11:11:50 +00:00
|
|
|
const void *in_lparam;
|
2023-07-20 22:42:30 +00:00
|
|
|
size_t lparam_size;
|
2023-07-17 21:43:19 +00:00
|
|
|
size_t lparam_init_size;
|
2023-07-20 22:42:30 +00:00
|
|
|
size_t check_size;
|
|
|
|
BOOL poison_lparam;
|
2023-07-17 22:28:55 +00:00
|
|
|
BOOL not_allowed;
|
2023-07-20 22:42:30 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const struct lparam_hook_test *current_hook_test;
|
|
|
|
|
|
|
|
static LPARAM callwnd_hook_lparam, callwnd_hook_lparam2, retwnd_hook_lparam, retwnd_hook_lparam2;
|
|
|
|
static LPARAM wndproc_lparam;
|
|
|
|
static char lparam_buffer[521];
|
|
|
|
|
|
|
|
static void check_params( const struct lparam_hook_test *test, UINT message,
|
|
|
|
WPARAM wparam, LPARAM lparam, BOOL is_ret )
|
|
|
|
{
|
2023-07-18 11:58:02 +00:00
|
|
|
if (!test->no_wparam_check)
|
2023-07-20 22:42:30 +00:00
|
|
|
ok( wparam == test->wparam, "got wparam %Ix, expected %Ix\n", wparam, test->wparam );
|
|
|
|
if (lparam == (LPARAM)lparam_buffer)
|
|
|
|
return;
|
|
|
|
|
2023-07-18 18:23:34 +00:00
|
|
|
if (sizeof(void *) != 4 || (test->message != EM_SETTABSTOPS && test->message != LB_SETTABSTOPS))
|
|
|
|
ok( (LPARAM)&message < lparam && lparam < (LPARAM)NtCurrentTeb()->Tib.StackBase,
|
|
|
|
"lparam is not on the stack\n");
|
2023-07-20 22:42:30 +00:00
|
|
|
|
2023-07-18 10:24:04 +00:00
|
|
|
switch (test->message)
|
|
|
|
{
|
|
|
|
case WM_COPYDATA:
|
|
|
|
{
|
|
|
|
const COPYDATASTRUCT *cds = (const COPYDATASTRUCT *)lparam;
|
|
|
|
const COPYDATASTRUCT *cds_in = (const COPYDATASTRUCT *)lparam_buffer;
|
|
|
|
ok( cds->dwData == cds_in->dwData, "cds->dwData != cds_in->dwData\n");
|
|
|
|
ok( cds->cbData == cds_in->cbData, "cds->dwData != cds_in->dwData\n");
|
|
|
|
if (cds_in->lpData)
|
|
|
|
{
|
|
|
|
ok( cds->lpData != cds_in->lpData, "cds->lpData == cds_in->lpData\n" );
|
|
|
|
if (cds->cbData)
|
|
|
|
ok( !memcmp( cds->lpData, cds_in->lpData, cds->cbData ), "unexpected pvData %s\n",
|
|
|
|
wine_dbgstr_an( cds->lpData, cds->cbData ));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ok( !cds->lpData, "cds->lpData = %p\n", cds->lpData );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2023-07-18 11:58:02 +00:00
|
|
|
case EM_GETSEL:
|
|
|
|
case SBM_GETRANGE:
|
|
|
|
case CB_GETEDITSEL:
|
|
|
|
ok( wparam, "wparam = 0\n" );
|
|
|
|
break;
|
|
|
|
|
2023-07-18 18:17:36 +00:00
|
|
|
case EM_GETLINE:
|
|
|
|
if (!is_ret)
|
|
|
|
{
|
|
|
|
WCHAR *buf = (WCHAR *)lparam;
|
|
|
|
ok(buf[0] == 8, "buf[0] = %x\n", buf[0]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2023-07-18 10:24:04 +00:00
|
|
|
default:
|
|
|
|
if (test->check_size) {
|
2023-07-18 22:14:31 +00:00
|
|
|
const void *expected;
|
2023-08-04 11:11:50 +00:00
|
|
|
if (is_ret && test->check_lparam)
|
|
|
|
expected = test->check_lparam;
|
|
|
|
else if (is_ret && test->change_lparam)
|
2023-07-18 22:14:31 +00:00
|
|
|
expected = test->change_lparam;
|
2023-08-04 11:11:50 +00:00
|
|
|
else if (test->in_lparam)
|
|
|
|
expected = test->in_lparam;
|
2023-07-18 22:14:31 +00:00
|
|
|
else
|
|
|
|
expected = test->lparam;
|
2023-07-18 10:24:04 +00:00
|
|
|
ok( !memcmp( (const void *)lparam, expected, test->check_size ), "unexpected lparam content\n" );
|
|
|
|
}
|
2023-07-20 22:42:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void poison_lparam( const struct lparam_hook_test *test, LPARAM lparam )
|
|
|
|
{
|
2023-07-26 09:42:42 +00:00
|
|
|
/* message copy is never transferred back in hooks */
|
2023-07-20 22:42:30 +00:00
|
|
|
if (test->lparam_size && lparam != (LPARAM)lparam_buffer)
|
|
|
|
memset( (void *)lparam, 0xc0, test->lparam_size );
|
|
|
|
}
|
|
|
|
|
|
|
|
static LRESULT WINAPI callwnd_hook_proc( INT code, WPARAM wparam, LPARAM lparam )
|
|
|
|
{
|
|
|
|
const struct lparam_hook_test *test = current_hook_test;
|
|
|
|
CWPSTRUCT *cwp = (CWPSTRUCT *)lparam;
|
|
|
|
LRESULT result;
|
|
|
|
|
|
|
|
if (cwp->message != test->message) return CallNextHookEx( NULL, code, wparam, lparam );
|
|
|
|
|
|
|
|
callwnd_hook_lparam = cwp->lParam;
|
|
|
|
winetest_push_context( "call_hook" );
|
|
|
|
check_params( test, cwp->message, cwp->wParam, cwp->lParam, FALSE );
|
|
|
|
winetest_pop_context();
|
|
|
|
|
|
|
|
result = CallNextHookEx( NULL, code, wparam, lparam );
|
|
|
|
|
|
|
|
poison_lparam( test, cwp->lParam );
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static LRESULT WINAPI callwnd_hook_proc2( INT code, WPARAM wparam, LPARAM lparam )
|
|
|
|
{
|
|
|
|
const struct lparam_hook_test *test = current_hook_test;
|
|
|
|
CWPSTRUCT *cwp = (CWPSTRUCT *)lparam;
|
|
|
|
LRESULT result;
|
|
|
|
|
|
|
|
if (cwp->message != test->message) return CallNextHookEx( NULL, code, wparam, lparam );
|
|
|
|
|
|
|
|
callwnd_hook_lparam2 = cwp->lParam;
|
|
|
|
winetest_push_context( "call_hook2" );
|
|
|
|
check_params( test, cwp->message, cwp->wParam, cwp->lParam, FALSE );
|
|
|
|
winetest_pop_context();
|
|
|
|
|
|
|
|
result = CallNextHookEx( NULL, code, wparam, lparam );
|
|
|
|
|
|
|
|
poison_lparam( test, cwp->lParam );
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static LRESULT WINAPI retwnd_hook_proc( INT code, WPARAM wparam, LPARAM lparam )
|
|
|
|
{
|
|
|
|
const struct lparam_hook_test *test = current_hook_test;
|
|
|
|
CWPRETSTRUCT *cwpret = (CWPRETSTRUCT *)lparam;
|
|
|
|
LRESULT result;
|
|
|
|
|
|
|
|
if (cwpret->message != test->message) return CallNextHookEx( NULL, code, wparam, lparam );
|
|
|
|
|
|
|
|
retwnd_hook_lparam = cwpret->lParam;
|
|
|
|
winetest_push_context( "ret_hook" );
|
|
|
|
check_params( test, cwpret->message, cwpret->wParam, cwpret->lParam, TRUE );
|
|
|
|
winetest_pop_context();
|
|
|
|
|
|
|
|
result = CallNextHookEx( NULL, code, wparam, lparam );
|
|
|
|
|
|
|
|
poison_lparam( test, cwpret->lParam );
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static LRESULT WINAPI retwnd_hook_proc2( INT code, WPARAM wparam, LPARAM lparam )
|
|
|
|
{
|
|
|
|
const struct lparam_hook_test *test = current_hook_test;
|
|
|
|
CWPRETSTRUCT *cwpret = (CWPRETSTRUCT *)lparam;
|
|
|
|
LRESULT result;
|
|
|
|
|
|
|
|
if (cwpret->message != test->message) return CallNextHookEx( NULL, code, wparam, lparam );
|
|
|
|
|
|
|
|
retwnd_hook_lparam2 = cwpret->lParam;
|
|
|
|
winetest_push_context( "ret_hook2" );
|
|
|
|
check_params( test, cwpret->message, cwpret->wParam, cwpret->lParam, TRUE );
|
|
|
|
winetest_pop_context();
|
|
|
|
|
|
|
|
result = CallNextHookEx( NULL, code, wparam, lparam );
|
|
|
|
|
|
|
|
poison_lparam( test, cwpret->lParam );
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static LRESULT WINAPI lparam_test_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
|
|
|
|
{
|
|
|
|
const struct lparam_hook_test *test = current_hook_test;
|
|
|
|
|
|
|
|
if (test && msg == test->message)
|
|
|
|
{
|
|
|
|
wndproc_lparam = lparam;
|
|
|
|
|
|
|
|
winetest_push_context( "wndproc" );
|
|
|
|
check_params( test, msg, wparam, lparam, FALSE );
|
|
|
|
winetest_pop_context();
|
|
|
|
|
|
|
|
if (test->change_lparam) memcpy( (void *)lparam, test->change_lparam, test->lparam_size );
|
|
|
|
else if(test->poison_lparam) memset( (void *)lparam, 0xcc, test->lparam_size );
|
|
|
|
return test->msg_result;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (msg)
|
|
|
|
{
|
|
|
|
case CB_GETLBTEXTLEN:
|
|
|
|
case LB_GETTEXTLEN:
|
|
|
|
return 7;
|
|
|
|
}
|
|
|
|
|
|
|
|
return DefWindowProcW( hwnd, msg, wparam, lparam );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void test_msg_output( const struct lparam_hook_test *test, LRESULT result, BOOL hooks_called )
|
|
|
|
{
|
|
|
|
const LPARAM orig = (LPARAM)lparam_buffer;
|
|
|
|
const void *expected;
|
|
|
|
|
2023-07-17 22:28:55 +00:00
|
|
|
/* Some messages are not allowed with NtUserMessageCall, they seem to be reserved
|
|
|
|
* for system. Unhooked SendMessage still works for them. */
|
|
|
|
if (test->not_allowed)
|
|
|
|
{
|
|
|
|
todo_wine ok( !wndproc_lparam, "wndproc_lparam called\n" );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ok( wndproc_lparam, "wndproc_lparam not called\n" );
|
|
|
|
|
2023-07-20 22:42:30 +00:00
|
|
|
if (test->check_result)
|
|
|
|
todo_wine_if(test->todo_result)
|
|
|
|
ok( result == test->check_result, "unexpected result %Ix\n", result );
|
|
|
|
else
|
|
|
|
todo_wine_if(test->todo_result)
|
|
|
|
ok( result == test->msg_result, "unexpected result %Ix\n", result );
|
|
|
|
|
|
|
|
if (!test->lparam_size)
|
|
|
|
{
|
|
|
|
ok( wndproc_lparam == orig, "wndproc_lparam modified\n" );
|
|
|
|
if (hooks_called)
|
|
|
|
{
|
|
|
|
ok( callwnd_hook_lparam == orig, "callwnd_hook_lparam modified\n" );
|
|
|
|
ok( callwnd_hook_lparam2 == orig, "callwnd_hook_lparam2 modified\n" );
|
|
|
|
ok( retwnd_hook_lparam == orig, "retwnd_hook_lparam modified\n" );
|
|
|
|
ok( retwnd_hook_lparam2 == orig, "retwnd_hook_lparam2 modified\n" );
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
expected = test->change_lparam ? test->change_lparam : test->lparam;
|
|
|
|
if (test->check_lparam)
|
|
|
|
expected = test->check_lparam;
|
|
|
|
else if(test->change_lparam)
|
|
|
|
expected = test->change_lparam;
|
|
|
|
else
|
|
|
|
expected = test->lparam;
|
|
|
|
if (expected)
|
2023-07-22 00:27:39 +00:00
|
|
|
todo_wine_if((test->message == CB_GETLBTEXT && test->msg_result == 7) ||
|
|
|
|
(test->message == LB_GETTEXT && test->msg_result == 7))
|
2023-07-20 22:42:30 +00:00
|
|
|
ok( !memcmp( lparam_buffer, expected, test->lparam_size ), "unexpected lparam content\n" );
|
|
|
|
|
|
|
|
ok( wndproc_lparam != orig, "wndproc_lparam unmodified\n" );
|
|
|
|
if (!hooks_called)
|
|
|
|
return;
|
|
|
|
|
|
|
|
ok( callwnd_hook_lparam, "callwnd_hook_lparam not called\n" );
|
|
|
|
ok( callwnd_hook_lparam2, "callwnd_hook_lparam2 not called\n" );
|
|
|
|
ok( retwnd_hook_lparam, "retwnd_hook_lparam not called\n" );
|
|
|
|
ok( retwnd_hook_lparam2, "retwnd_hook_lparam2 not called\n" );
|
|
|
|
|
|
|
|
ok( orig != callwnd_hook_lparam, "callwnd_hook_lparam not modified\n" );
|
|
|
|
ok( orig != callwnd_hook_lparam2, "callwnd_hook_lparam2 not modified\n" );
|
|
|
|
ok( orig != retwnd_hook_lparam, "retwnd_hook_lparam not modified\n" );
|
|
|
|
ok( orig != retwnd_hook_lparam2, "retwnd_hook_lparam2 not modified\n" );
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Only the first hook's lparam matches window proc, following hook
|
|
|
|
* calls copy the message again. Even when lparam values match, they
|
|
|
|
* are copied separatelly for each proc invocation. Poisoning their
|
|
|
|
* content in hook procs has no effect on other calls.
|
|
|
|
*/
|
|
|
|
ok( wndproc_lparam == callwnd_hook_lparam, "wndproc_lparam %Ix != callwnd_hook_lparam %Ix\n",
|
|
|
|
wndproc_lparam, callwnd_hook_lparam);
|
|
|
|
todo_wine
|
|
|
|
ok( callwnd_hook_lparam != callwnd_hook_lparam2, "wndproc_lparam == callwnd_hook_lparam2\n" );
|
|
|
|
ok( wndproc_lparam == retwnd_hook_lparam, "wndproc_lparam %Ix != retwnd_hook_lparam %Ix\n",
|
|
|
|
wndproc_lparam, retwnd_hook_lparam);
|
|
|
|
todo_wine
|
|
|
|
ok( retwnd_hook_lparam != retwnd_hook_lparam2, "wndproc_lparam == retwnd_hook_lparam2\n" );
|
|
|
|
}
|
|
|
|
|
|
|
|
static void init_hook_test( const struct lparam_hook_test *test )
|
|
|
|
{
|
|
|
|
wndproc_lparam = 0;
|
|
|
|
callwnd_hook_lparam = 0;
|
|
|
|
callwnd_hook_lparam2 = 0;
|
|
|
|
retwnd_hook_lparam = 0;
|
|
|
|
retwnd_hook_lparam2 = 0;
|
|
|
|
|
2023-07-22 00:27:39 +00:00
|
|
|
if (test->lparam_size)
|
|
|
|
{
|
2023-07-17 21:43:19 +00:00
|
|
|
if (test->lparam_init_size)
|
|
|
|
memcpy( lparam_buffer, test->lparam, test->lparam_init_size );
|
|
|
|
else if (test->lparam)
|
2023-07-22 00:27:39 +00:00
|
|
|
memcpy( lparam_buffer, test->lparam, test->lparam_size );
|
|
|
|
else
|
|
|
|
memset( lparam_buffer, 0xcc, test->lparam_size );
|
|
|
|
}
|
2023-07-20 22:42:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void test_wndproc_hook(void)
|
|
|
|
{
|
|
|
|
const struct lparam_hook_test *test;
|
|
|
|
HHOOK call_hook, call_hook2, ret_hook, ret_hook2;
|
|
|
|
WNDCLASSW cls = { 0 };
|
|
|
|
LRESULT res;
|
|
|
|
HWND hwnd;
|
|
|
|
BOOL ret;
|
|
|
|
|
|
|
|
static const BOOL false_lparam = FALSE;
|
|
|
|
static const WCHAR strbufW[8] = L"abc\0defg";
|
2023-07-22 00:27:39 +00:00
|
|
|
static const WCHAR strbuf2W[8] = L"\0\xcccc\xcccc\xcccc\xcccc\xcccc\xcccc\xcccc";
|
2023-07-20 22:42:30 +00:00
|
|
|
static const WCHAR strbuf3W[8] = L"abcdefgh";
|
2023-07-22 00:27:39 +00:00
|
|
|
static const WCHAR strbuf4W[8] = L"abc\0\xcccc\xcccc\xcccc\xcccc";
|
2023-07-20 22:42:30 +00:00
|
|
|
static const RECT rect_in = { 1, 2, 100, 200 };
|
|
|
|
static const RECT rect_out = { 3, 4, 110, 220 };
|
2023-07-17 22:06:13 +00:00
|
|
|
static const MINMAXINFO minmax_in = { .ptMinTrackSize.x = 1 };
|
|
|
|
static const MINMAXINFO minmax_out = { .ptMinTrackSize.x = 2 };
|
2023-07-17 22:28:55 +00:00
|
|
|
static const DRAWITEMSTRUCT drawitem_in = { .itemID = 1 };
|
2023-07-17 22:32:48 +00:00
|
|
|
static const MEASUREITEMSTRUCT mis_in = { .itemID = 1 };
|
|
|
|
static const MEASUREITEMSTRUCT mis_out = { .itemID = 2, .CtlType = 3, .CtlID = 4, .itemData = 5 };
|
2023-07-18 08:29:07 +00:00
|
|
|
static const DELETEITEMSTRUCT dis_in = { .itemID = 1 };
|
2023-07-18 08:46:09 +00:00
|
|
|
static const COMPAREITEMSTRUCT cis_in = { .itemID1 = 1 };
|
2023-07-18 10:12:59 +00:00
|
|
|
static const WINDOWPOS winpos_in = { .x = 1, .cy = 2 };
|
|
|
|
static const WINDOWPOS winpos_out = { .x = 10, .cy = 22 };
|
2023-07-18 10:24:04 +00:00
|
|
|
static const COPYDATASTRUCT cds_in = { .dwData = 1 };
|
|
|
|
static WORD data_word = 3;
|
|
|
|
static const COPYDATASTRUCT cds2_in = { .cbData = 2, .lpData = &data_word };
|
|
|
|
static const COPYDATASTRUCT cds3_in = { .dwData = 2, .lpData = (void *)0xdeadbeef };
|
|
|
|
static const COPYDATASTRUCT cds4_in = { .cbData = 2 };
|
|
|
|
static const COPYDATASTRUCT cds5_in = { .lpData = (void *)0xdeadbeef };
|
2023-07-18 10:47:45 +00:00
|
|
|
static const STYLESTRUCT style_in = { .styleOld = 1, .styleNew = 2 };
|
|
|
|
static const STYLESTRUCT style_out = { .styleOld = 10, .styleNew = 20 };
|
2023-07-18 11:39:04 +00:00
|
|
|
static const MSG msg_in = { .wParam = 1, .lParam = 2 };
|
2023-07-18 11:43:25 +00:00
|
|
|
static const SCROLLINFO si_in = { .cbSize = sizeof(si_in), .nPos = 6 };
|
|
|
|
static const SCROLLINFO si_out = { .cbSize = sizeof(si_in), .nPos = 60 };
|
|
|
|
static const SCROLLBARINFO sbi_in = { .xyThumbTop = 6 };
|
|
|
|
static const SCROLLBARINFO sbi_out = { .xyThumbTop = 60 };
|
2023-07-18 11:58:02 +00:00
|
|
|
static const DWORD dw_in = 1, dw_out = 2;
|
2023-07-18 18:23:34 +00:00
|
|
|
static const UINT32 tabstops_in[2] = { 3, 4 };
|
2023-07-18 20:07:07 +00:00
|
|
|
static const UINT32 items_out[2] = { 1, 2 };
|
2023-07-18 20:25:58 +00:00
|
|
|
static const MDINEXTMENU nm_in = { .hmenuIn = (HMENU)0xdeadbeef };
|
|
|
|
static const MDINEXTMENU nm_out = { .hmenuIn = (HMENU)1 };
|
2023-07-18 20:54:23 +00:00
|
|
|
static const MDICREATESTRUCTW mcs_in = { .x = 1, .y = 2 };
|
2023-08-04 11:11:50 +00:00
|
|
|
static const COMBOBOXINFO cbi_in = { .cbSize = 1, .hwndList = HWND_MESSAGE };
|
|
|
|
static const COMBOBOXINFO cbi_check =
|
|
|
|
{ .cbSize = sizeof(void *) == 4 ? sizeof(cbi_in) : 1, .hwndList = HWND_MESSAGE };
|
2023-07-18 22:14:31 +00:00
|
|
|
static const COMBOBOXINFO cbi_out = { .hwndList = (HWND)2 };
|
|
|
|
static const COMBOBOXINFO cbi_ret = { .hwndList = (HWND)2,
|
|
|
|
.cbSize = sizeof(void *) == 4 ? sizeof(cbi_in) : 0 };
|
2023-07-20 22:42:30 +00:00
|
|
|
|
|
|
|
static const struct lparam_hook_test lparam_hook_tests[] =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
"WM_NCCALCSIZE", WM_NCCALCSIZE,
|
|
|
|
.lparam = &rect_in, .lparam_size = sizeof(RECT), .change_lparam = &rect_out,
|
|
|
|
.check_size = sizeof(RECT),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"WM_MOVING", WM_MOVING,
|
2023-07-18 20:30:08 +00:00
|
|
|
.lparam = &rect_in, .lparam_size = sizeof(RECT), .change_lparam = &rect_out,
|
|
|
|
.check_size = sizeof(RECT),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"WM_SIZING", WM_SIZING,
|
|
|
|
.lparam = &rect_in, .lparam_size = sizeof(RECT), .change_lparam = &rect_out,
|
2023-07-20 22:42:30 +00:00
|
|
|
.check_size = sizeof(RECT),
|
|
|
|
},
|
2023-07-18 12:23:46 +00:00
|
|
|
{
|
|
|
|
"EM_GETRECT", EM_GETRECT,
|
|
|
|
.lparam = &rect_in, .lparam_size = sizeof(RECT), .change_lparam = &rect_out,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"EM_SETRECT", EM_SETRECT,
|
|
|
|
.lparam = &rect_in, .lparam_size = sizeof(RECT), .change_lparam = &rect_out,
|
|
|
|
.check_size = sizeof(RECT),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"EM_SETRECTNP", EM_SETRECTNP,
|
|
|
|
.lparam = &rect_in, .lparam_size = sizeof(RECT), .change_lparam = &rect_out,
|
|
|
|
.check_size = sizeof(RECT),
|
|
|
|
},
|
2023-07-20 22:42:30 +00:00
|
|
|
{
|
|
|
|
"LB_GETITEMRECT", LB_GETITEMRECT,
|
|
|
|
.lparam = &rect_in, .lparam_size = sizeof(RECT), .change_lparam = &rect_out,
|
|
|
|
.check_size = sizeof(RECT),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"CB_GETDROPPEDCONTROLRECT", CB_GETDROPPEDCONTROLRECT,
|
2023-07-18 11:19:43 +00:00
|
|
|
.lparam = &rect_in, .lparam_size = sizeof(RECT), .change_lparam = &rect_out,
|
2023-07-20 22:42:30 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"WM_GETTEXT", WM_GETTEXT, .wparam = 8,
|
|
|
|
.lparam_size = sizeof(strbufW), .change_lparam = strbufW, .check_lparam = strbuf2W,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"WM_GETTEXT2", WM_GETTEXT, .wparam = 8, .msg_result = 1,
|
2023-07-22 00:27:39 +00:00
|
|
|
.lparam_size = sizeof(strbufW), .change_lparam = strbufW, .check_lparam = strbuf4W,
|
2023-07-20 22:42:30 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"WM_GETTEXT3", WM_GETTEXT, .wparam = 8, .msg_result = 9,
|
2023-07-22 00:27:39 +00:00
|
|
|
.lparam_size = sizeof(strbufW), .change_lparam = strbufW, .check_lparam = strbuf4W,
|
2023-07-20 22:42:30 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"WM_ASKCBFORMATNAME", WM_ASKCBFORMATNAME, .wparam = 8,
|
2023-07-22 00:27:39 +00:00
|
|
|
.lparam_size = sizeof(strbufW), .change_lparam = strbufW, .check_lparam = strbuf4W,
|
2023-07-20 22:42:30 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"WM_ASKCBFORMATNAME2", WM_ASKCBFORMATNAME, .wparam = 8, .msg_result = 1,
|
2023-07-22 00:27:39 +00:00
|
|
|
.lparam_size = sizeof(strbufW), .change_lparam = strbufW, .check_lparam = strbuf4W,
|
2023-07-20 22:42:30 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"WM_ASKCBFORMATNAME3", WM_ASKCBFORMATNAME, .wparam = 8, .msg_result = 9,
|
2023-07-22 00:27:39 +00:00
|
|
|
.lparam_size = sizeof(strbufW), .change_lparam = strbufW, .check_lparam = strbuf4W,
|
2023-07-20 22:42:30 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"CB_GETLBTEXT", CB_GETLBTEXT, .msg_result = 7, .check_result = 4, .todo_result = TRUE,
|
2023-07-22 00:27:39 +00:00
|
|
|
.lparam_size = sizeof(strbufW), .change_lparam = strbufW, .check_lparam = strbuf4W,
|
2023-07-20 22:42:30 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"CB_GETLBTEXT2", CB_GETLBTEXT, .msg_result = 9, .check_result = 8, .todo_result = TRUE,
|
|
|
|
.lparam_size = sizeof(strbufW), .change_lparam = strbuf3W, .check_lparam = strbuf3W,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"CB_GETLBTEXT3", CB_GETLBTEXT,
|
|
|
|
.lparam_size = sizeof(strbufW), .change_lparam = strbuf3W, .check_lparam = strbuf3W,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"LB_GETTEXT", LB_GETTEXT, .msg_result = 7, .check_result = 4, .todo_result = TRUE,
|
2023-07-22 00:27:39 +00:00
|
|
|
.lparam_size = sizeof(strbufW), .change_lparam = strbufW, .check_lparam = strbuf4W,
|
2023-07-20 22:42:30 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"LB_GETTEXT2", LB_GETTEXT, .msg_result = 9, .check_result = 8, .todo_result = TRUE,
|
|
|
|
.lparam_size = sizeof(strbufW), .change_lparam = strbuf3W, .check_lparam = strbuf3W,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"LB_GETTEXT3", LB_GETTEXT,
|
|
|
|
.lparam_size = sizeof(strbufW), .change_lparam = strbuf3W, .check_lparam = strbuf3W,
|
|
|
|
},
|
|
|
|
{
|
2023-07-18 11:58:02 +00:00
|
|
|
"WM_MDIGETACTIVE", WM_MDIGETACTIVE, .no_wparam_check = TRUE,
|
2023-07-20 22:42:30 +00:00
|
|
|
.lparam_size = sizeof(BOOL), .change_lparam = &false_lparam,
|
|
|
|
},
|
2023-07-17 22:06:13 +00:00
|
|
|
{
|
|
|
|
"WM_GETMINMAXINFO", WM_GETMINMAXINFO,
|
|
|
|
.lparam_size = sizeof(minmax_in), .lparam = &minmax_in, .change_lparam = &minmax_out,
|
|
|
|
.check_size = sizeof(minmax_in)
|
|
|
|
},
|
2023-07-17 22:32:48 +00:00
|
|
|
{
|
|
|
|
"WM_MEASUREITEM", WM_MEASUREITEM, .wparam = 10,
|
|
|
|
.lparam_size = sizeof(mis_in), .lparam = &mis_in, .change_lparam = &mis_out,
|
|
|
|
.check_size = sizeof(mis_in),
|
|
|
|
},
|
2023-07-18 08:29:07 +00:00
|
|
|
{
|
|
|
|
"WM_DELETEITEM", WM_DELETEITEM, .wparam = 10,
|
|
|
|
.lparam_size = sizeof(dis_in), .lparam = &dis_in, .poison_lparam = TRUE,
|
|
|
|
.check_size = sizeof(dis_in),
|
|
|
|
},
|
2023-07-18 08:46:09 +00:00
|
|
|
{
|
|
|
|
"WM_COMPAREITEM", WM_COMPAREITEM, .wparam = 10,
|
|
|
|
.lparam_size = sizeof(cis_in), .lparam = &cis_in, .poison_lparam = TRUE,
|
|
|
|
.check_size = sizeof(cis_in),
|
|
|
|
},
|
2023-07-18 10:12:59 +00:00
|
|
|
{
|
|
|
|
"WM_WINDOWPOSCHANGING", WM_WINDOWPOSCHANGING,
|
|
|
|
.lparam_size = sizeof(WINDOWPOS), .lparam = &winpos_in, .change_lparam = &winpos_out,
|
|
|
|
.check_size = sizeof(WINDOWPOS)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"WM_WINDOWPOSCHANGED", WM_WINDOWPOSCHANGED,
|
|
|
|
.lparam_size = sizeof(WINDOWPOS), .lparam = &winpos_in, .poison_lparam = TRUE,
|
|
|
|
.check_size = sizeof(WINDOWPOS),
|
|
|
|
},
|
2023-07-18 10:24:04 +00:00
|
|
|
{
|
|
|
|
"WM_COPYDATA", WM_COPYDATA, .wparam = 0xdeadbeef,
|
|
|
|
.lparam_size = sizeof(cds_in), .lparam = &cds_in, .poison_lparam = TRUE,
|
|
|
|
.check_size = sizeof(cds_in),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"WM_COPYDATA-2", WM_COPYDATA, .wparam = 0xdeadbeef,
|
|
|
|
.lparam_size = sizeof(cds2_in), .lparam = &cds2_in, .poison_lparam = TRUE,
|
|
|
|
.check_size = sizeof(cds2_in),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"WM_COPYDATA-3", WM_COPYDATA, .wparam = 0xdeadbeef,
|
|
|
|
.lparam_size = sizeof(cds3_in), .lparam = &cds3_in, .poison_lparam = TRUE,
|
|
|
|
.check_size = sizeof(cds3_in),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"WM_COPYDATA-4", WM_COPYDATA, .wparam = 0xdeadbeef,
|
|
|
|
.lparam_size = sizeof(cds4_in), .lparam = &cds4_in, .poison_lparam = TRUE,
|
|
|
|
.check_size = sizeof(cds4_in),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"WM_COPYDATA-5", WM_COPYDATA, .wparam = 0xdeadbeef,
|
|
|
|
.lparam_size = sizeof(cds5_in), .lparam = &cds5_in, .poison_lparam = TRUE,
|
|
|
|
.check_size = sizeof(cds5_in),
|
|
|
|
},
|
2023-07-18 10:47:45 +00:00
|
|
|
{
|
|
|
|
"WM_STYLECHANGING", WM_STYLECHANGING,
|
|
|
|
.lparam_size = sizeof(style_in), .lparam = &style_in, .change_lparam = &style_out,
|
|
|
|
.check_size = sizeof(style_in)
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"WM_STYLECHANGED", WM_STYLECHANGED,
|
|
|
|
.lparam_size = sizeof(style_in), .lparam = &style_in, .poison_lparam = TRUE,
|
|
|
|
.check_size = sizeof(style_in),
|
|
|
|
},
|
2023-07-18 11:39:04 +00:00
|
|
|
{
|
|
|
|
"WM_GETDLGCODE", WM_GETDLGCODE,
|
|
|
|
.lparam_size = sizeof(msg_in), .lparam = &msg_in, .poison_lparam = TRUE,
|
|
|
|
.check_size = sizeof(msg_in),
|
|
|
|
},
|
2023-07-18 11:43:25 +00:00
|
|
|
{
|
|
|
|
"SBM_SETSCROLLINFO", SBM_SETSCROLLINFO,
|
|
|
|
.lparam_size = sizeof(si_in), .lparam = &si_in, .change_lparam = &si_out,
|
|
|
|
.check_size = sizeof(si_in),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"SBM_GETSCROLLINFO", SBM_GETSCROLLINFO,
|
|
|
|
.lparam_size = sizeof(si_in), .lparam = &si_in, .change_lparam = &si_out,
|
|
|
|
.check_size = sizeof(si_in),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"SBM_GETSCROLLBARINFO", SBM_GETSCROLLBARINFO,
|
|
|
|
.lparam_size = sizeof(sbi_in), .lparam = &sbi_in, .change_lparam = &sbi_out,
|
|
|
|
.check_size = sizeof(sbi_in),
|
|
|
|
},
|
2023-07-18 11:58:02 +00:00
|
|
|
{
|
|
|
|
"EM_GETSEL", EM_GETSEL, .no_wparam_check = TRUE,
|
|
|
|
.lparam_size = sizeof(DWORD), .lparam = &dw_in, .change_lparam = &dw_out,
|
|
|
|
.check_size = sizeof(DWORD),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"SBM_GETRANGE", SBM_GETRANGE, .no_wparam_check = TRUE,
|
|
|
|
.lparam_size = sizeof(DWORD), .lparam = &dw_in, .change_lparam = &dw_out,
|
|
|
|
.check_size = sizeof(DWORD),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"CB_GETEDITSEL", CB_GETEDITSEL, .no_wparam_check = TRUE,
|
|
|
|
.lparam_size = sizeof(DWORD), .lparam = &dw_in, .change_lparam = &dw_out,
|
|
|
|
.check_size = sizeof(DWORD),
|
|
|
|
},
|
2023-07-18 18:17:36 +00:00
|
|
|
{
|
|
|
|
"EM_GETLINE", EM_GETLINE, .msg_result = 5,
|
|
|
|
.lparam = L"\x8""2345678", .lparam_size = sizeof(strbufW), .change_lparam = L"abc\0defg",
|
|
|
|
.check_size = sizeof(WCHAR), .check_lparam = L"abc\0""5678",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"EM_GETLINE-2", EM_GETLINE, .msg_result = 1,
|
|
|
|
.lparam = L"\x8""2345678", .lparam_size = sizeof(strbufW), .change_lparam = L"abc\0defg",
|
|
|
|
.check_size = sizeof(WCHAR), .check_lparam = L"abc\0""5678",
|
|
|
|
},
|
2023-07-18 18:23:34 +00:00
|
|
|
{
|
|
|
|
"EM_SETTABSTOPS", EM_SETTABSTOPS, .wparam = ARRAYSIZE(tabstops_in),
|
|
|
|
.lparam_size = sizeof(tabstops_in), .lparam = &tabstops_in, .poison_lparam = TRUE,
|
|
|
|
.check_size = sizeof(tabstops_in),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"LB_SETTABSTOPS", LB_SETTABSTOPS, .wparam = ARRAYSIZE(tabstops_in),
|
|
|
|
.lparam_size = sizeof(tabstops_in), .lparam = &tabstops_in, .poison_lparam = TRUE,
|
|
|
|
.check_size = sizeof(tabstops_in),
|
|
|
|
},
|
2023-07-18 20:07:07 +00:00
|
|
|
{
|
|
|
|
"LB_GETSELITEMS", LB_GETSELITEMS,
|
|
|
|
.wparam = ARRAYSIZE(items_out), .msg_result = ARRAYSIZE(items_out),
|
|
|
|
.lparam_size = sizeof(items_out), .change_lparam = items_out,
|
|
|
|
},
|
2023-07-18 20:25:58 +00:00
|
|
|
{
|
|
|
|
"WM_NEXTMENU", WM_NEXTMENU,
|
|
|
|
.lparam_size = sizeof(nm_in), .lparam = &nm_in, .change_lparam = &nm_out,
|
|
|
|
.check_size = sizeof(nm_in)
|
|
|
|
},
|
2023-07-18 20:54:23 +00:00
|
|
|
{
|
|
|
|
"WM_MDICREATE", WM_MDICREATE,
|
|
|
|
.lparam_size = sizeof(mcs_in), .lparam = &mcs_in, .poison_lparam = TRUE,
|
|
|
|
.check_size = sizeof(mcs_in),
|
|
|
|
},
|
2023-07-18 22:14:31 +00:00
|
|
|
{
|
|
|
|
"CB_GETCOMBOBOXINFO", CB_GETCOMBOBOXINFO,
|
2023-08-04 11:11:50 +00:00
|
|
|
.lparam_size = sizeof(cbi_in), .change_lparam = &cbi_out, .lparam = &cbi_in,
|
|
|
|
.check_lparam = &cbi_ret, .check_size = sizeof(cbi_in), .in_lparam = &cbi_check,
|
2023-07-18 22:14:31 +00:00
|
|
|
},
|
2023-07-17 21:43:19 +00:00
|
|
|
/* messages that don't change lparam */
|
2023-07-20 22:42:30 +00:00
|
|
|
{ "WM_USER", WM_USER },
|
|
|
|
{ "WM_NOTIFY", WM_NOTIFY },
|
2023-07-17 21:43:19 +00:00
|
|
|
{ "WM_SETTEXT", WM_SETTEXT, .lparam = strbufW, .lparam_init_size = sizeof(strbufW) },
|
|
|
|
{ "WM_DEVMODECHANGE", WM_DEVMODECHANGE, .lparam = strbufW, .lparam_init_size = sizeof(strbufW) },
|
|
|
|
{ "CB_DIR", CB_DIR, .lparam = strbufW, .lparam_init_size = sizeof(strbufW) },
|
|
|
|
{ "LB_DIR", LB_DIR, .lparam = strbufW, .lparam_init_size = sizeof(strbufW) },
|
|
|
|
{ "LB_ADDFILE", LB_ADDFILE, .lparam = strbufW, .lparam_init_size = sizeof(strbufW) },
|
|
|
|
{ "EM_REPLACESEL", EM_REPLACESEL, .lparam = strbufW, .lparam_init_size = sizeof(strbufW) },
|
|
|
|
{ "WM_WININICHANGE", WM_WININICHANGE, .lparam = strbufW, .lparam_init_size = sizeof(strbufW) },
|
2023-07-18 18:34:57 +00:00
|
|
|
{ "CB_ADDSTRING", CB_ADDSTRING },
|
|
|
|
{ "CB_INSERTSTRING", CB_INSERTSTRING },
|
|
|
|
{ "LB_ADDSTRING", LB_ADDSTRING },
|
2023-07-17 22:28:55 +00:00
|
|
|
/* messages not allowed to be sent by NtUserMessageCall */
|
|
|
|
{
|
|
|
|
"WM_DRAWITEM", WM_DRAWITEM, .wparam = 10,
|
|
|
|
.lparam_size = sizeof(drawitem_in), .lparam = &drawitem_in, .not_allowed = TRUE,
|
|
|
|
},
|
2023-07-20 22:42:30 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
cls.lpfnWndProc = lparam_test_proc;
|
|
|
|
cls.lpszClassName = L"TestLParamClass";
|
|
|
|
RegisterClassW( &cls );
|
|
|
|
|
|
|
|
hwnd = CreateWindowExA( 0, "TestLParamClass", NULL, WS_POPUP, 0,0,0,0,0,0,0, NULL );
|
|
|
|
|
|
|
|
for (test = lparam_hook_tests; test < lparam_hook_tests + ARRAYSIZE(lparam_hook_tests); test++)
|
|
|
|
{
|
|
|
|
current_hook_test = test;
|
|
|
|
winetest_push_context("%s", test->name);
|
|
|
|
|
|
|
|
/* Simple unhooked SendMessage just passes unmodified lparam. */
|
|
|
|
winetest_push_context( "sendmsg" );
|
|
|
|
init_hook_test( test );
|
|
|
|
res = SendMessageW( hwnd, test->message, test->wparam, (LPARAM)lparam_buffer );
|
|
|
|
ok( res == test->msg_result, "NtUserMessageCall returned %Ix\n", res );
|
|
|
|
ok( wndproc_lparam == (LPARAM)lparam_buffer, "unexpected wndproc_lparam %Ix, expected %p\n",
|
|
|
|
wndproc_lparam, lparam_buffer );
|
|
|
|
winetest_pop_context();
|
|
|
|
|
|
|
|
/* NtUserMessageCall uses a copy of lparam even when not hooked. */
|
|
|
|
wndproc_lparam = 0;
|
|
|
|
winetest_push_context( "ntsendmsg" );
|
|
|
|
init_hook_test( test );
|
|
|
|
res = NtUserMessageCall( hwnd, test->message, test->wparam, (LPARAM)lparam_buffer, NULL,
|
|
|
|
NtUserSendMessage, FALSE );
|
|
|
|
test_msg_output( test, res, FALSE );
|
|
|
|
winetest_pop_context();
|
|
|
|
|
|
|
|
call_hook2 = SetWindowsHookExW( WH_CALLWNDPROC, callwnd_hook_proc2, NULL, GetCurrentThreadId() );
|
|
|
|
ok( call_hook2 != NULL, "SetWindowsHookExW failed\n");
|
|
|
|
call_hook = SetWindowsHookExW( WH_CALLWNDPROC, callwnd_hook_proc, NULL, GetCurrentThreadId() );
|
|
|
|
ok( call_hook != NULL, "SetWindowsHookExW failed\n");
|
|
|
|
ret_hook2 = SetWindowsHookExW( WH_CALLWNDPROCRET, retwnd_hook_proc2,
|
|
|
|
NULL, GetCurrentThreadId() );
|
|
|
|
ok( ret_hook2 != NULL, "SetWindowsHookExW failed\n");
|
|
|
|
ret_hook = SetWindowsHookExW( WH_CALLWNDPROCRET, retwnd_hook_proc,
|
|
|
|
NULL, GetCurrentThreadId() );
|
|
|
|
ok( ret_hook != NULL, "SetWindowsHookExW failed\n");
|
|
|
|
|
|
|
|
/* Hooked SendMessage behaves just like NtUserMessageCall. */
|
|
|
|
winetest_push_context( "hooked_sendmsg" );
|
|
|
|
init_hook_test( test );
|
|
|
|
res = SendMessageW( hwnd, test->message, test->wparam, (LPARAM)lparam_buffer );
|
|
|
|
test_msg_output( test, res, TRUE );
|
|
|
|
winetest_pop_context();
|
|
|
|
|
|
|
|
winetest_push_context( "hooked_ntsendmsg" );
|
|
|
|
init_hook_test( test );
|
|
|
|
res = NtUserMessageCall( hwnd, test->message, test->wparam, (LPARAM)lparam_buffer,
|
|
|
|
NULL, NtUserSendMessage, FALSE );
|
|
|
|
test_msg_output( test, res, TRUE );
|
|
|
|
winetest_pop_context();
|
|
|
|
|
|
|
|
ret = NtUserUnhookWindowsHookEx( call_hook );
|
|
|
|
ok( ret, "NtUserUnhookWindowsHook failed: %lu\n", GetLastError() );
|
|
|
|
ret = NtUserUnhookWindowsHookEx( call_hook2 );
|
|
|
|
ok( ret, "NtUserUnhookWindowsHook failed: %lu\n", GetLastError() );
|
|
|
|
ret = NtUserUnhookWindowsHookEx( ret_hook );
|
|
|
|
ok( ret, "NtUserUnhookWindowsHook failed: %lu\n", GetLastError() );
|
|
|
|
ret = NtUserUnhookWindowsHookEx( ret_hook2 );
|
|
|
|
ok( ret, "NtUserUnhookWindowsHook failed: %lu\n", GetLastError() );
|
|
|
|
|
|
|
|
winetest_pop_context();
|
|
|
|
}
|
|
|
|
|
|
|
|
DestroyWindow( hwnd );
|
|
|
|
UnregisterClassW( L"TestLParamClass", NULL );
|
|
|
|
}
|
|
|
|
|
2021-10-12 13:33:30 +00:00
|
|
|
START_TEST(win32u)
|
|
|
|
{
|
2022-12-20 12:52:26 +00:00
|
|
|
char **argv;
|
|
|
|
int argc;
|
|
|
|
|
2021-10-12 13:33:30 +00:00
|
|
|
/* native win32u.dll fails if user32 is not loaded, so make sure it's fully initialized */
|
|
|
|
GetDesktopWindow();
|
|
|
|
|
2022-12-20 12:52:26 +00:00
|
|
|
argc = winetest_get_mainargs( &argv );
|
|
|
|
if (argc > 3 && !strcmp( argv[2], "ipcmsg" ))
|
|
|
|
{
|
|
|
|
test_inter_process_child( LongToHandle( strtol( argv[3], NULL, 16 )));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-12-19 10:39:38 +00:00
|
|
|
if (argc > 3 && !strcmp( argv[2], "NtUserEnableMouseInPointer" ))
|
|
|
|
{
|
|
|
|
winetest_push_context( "enable %s", argv[3] );
|
|
|
|
test_NtUserEnableMouseInPointer_process( argv[3] );
|
|
|
|
winetest_pop_context();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-12-21 19:31:29 +00:00
|
|
|
test_NtUserEnumDisplayDevices();
|
2021-11-08 13:48:37 +00:00
|
|
|
test_window_props();
|
2022-03-04 13:28:16 +00:00
|
|
|
test_class();
|
2023-03-11 07:53:29 +00:00
|
|
|
test_NtUserCreateInputContext();
|
2023-03-11 07:58:33 +00:00
|
|
|
test_NtUserBuildHimcList();
|
2021-12-21 19:31:29 +00:00
|
|
|
test_NtUserBuildHwndList();
|
2022-02-23 12:39:56 +00:00
|
|
|
test_cursoricon();
|
2022-04-04 14:57:23 +00:00
|
|
|
test_message_call();
|
2022-04-07 13:24:55 +00:00
|
|
|
test_window_text();
|
2022-04-30 23:10:44 +00:00
|
|
|
test_menu();
|
2022-04-15 15:25:57 +00:00
|
|
|
test_message_filter();
|
2022-07-19 17:51:53 +00:00
|
|
|
test_timer();
|
2022-12-20 12:52:26 +00:00
|
|
|
test_inter_process_messages( argv[0] );
|
2023-07-20 22:42:30 +00:00
|
|
|
test_wndproc_hook();
|
2021-12-21 19:31:29 +00:00
|
|
|
|
|
|
|
test_NtUserCloseWindowStation();
|
2022-10-24 22:27:16 +00:00
|
|
|
test_NtUserDisplayConfigGetDeviceInfo();
|
2022-12-19 10:39:38 +00:00
|
|
|
|
|
|
|
test_NtUserEnableMouseInPointer( argv, FALSE );
|
|
|
|
test_NtUserEnableMouseInPointer( argv, TRUE );
|
2021-10-12 13:33:30 +00:00
|
|
|
}
|