Fixes a regression introduced by 8d7de32cd646f3d1f118836e643e6146c9837278.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=59034
-- v5: win32u: Clear STARTF_USESHOWWINDOW in MessageBoxIndirectW(). user32/tests: Add tests showing that MessageBox() resets STARTF_USESHOWWINDOW. win32u: Implement NtUserModifyUserStartupInfoFlags(). win32u: Fetch startup info flags during initialization. win32u: Ignore statup cmd show mode for owned windows.
From: Paul Gofman pgofman@codeweavers.com
Fixes a regression introduced by 8d7de32cd646f3d1f118836e643e6146c9837278.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=59034 --- dlls/user32/tests/win.c | 36 ++++++++++++++++++++++-------------- dlls/win32u/window.c | 1 + 2 files changed, 23 insertions(+), 14 deletions(-)
diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c index 354d6ed5ca3..6073e087cb4 100644 --- a/dlls/user32/tests/win.c +++ b/dlls/user32/tests/win.c @@ -13677,20 +13677,27 @@ static const struct test_startupinfo_showwindow_test test_startupinfo_showwindow static void test_startupinfo_showwindow_proc( int test_id ) { const struct test_startupinfo_showwindow_test *test = &test_startupinfo_showwindow_tests[test_id]; - static const DWORD ignored_window_styles[] = - { - WS_CHILD, - WS_POPUP, /* WS_POPUP windows are not ignored when used with WS_CAPTION (which is WS_BORDER | WS_DLGFRAME) */ - WS_CHILD | WS_POPUP, - WS_POPUP | WS_BORDER, - WS_POPUP | WS_DLGFRAME, - WS_POPUP | WS_SYSMENU | WS_THICKFRAME| WS_MINIMIZEBOX | WS_MAXIMIZEBOX, + static const struct + { + DWORD style; + BOOL parent; + } + ignored_window_styles[] = + { + { WS_CHILD, TRUE }, + { WS_POPUP }, /* Unowned WS_POPUP windows are not ignored when used with WS_CAPTION (which is WS_BORDER | WS_DLGFRAME) */ + { WS_CHILD | WS_POPUP, TRUE }, + { WS_POPUP | WS_BORDER }, + { WS_POPUP | WS_DLGFRAME }, + { WS_POPUP | WS_SYSMENU | WS_THICKFRAME| WS_MINIMIZEBOX | WS_MAXIMIZEBOX }, + { WS_OVERLAPPED, TRUE }, /* owned window */ + { WS_POPUP | WS_CAPTION, TRUE }, /* owned window */ }; BOOL bval, expected; STARTUPINFOW sa; unsigned int i; DWORD style; - HWND hwnd; + HWND parent, hwnd;
GetStartupInfoW( &sa );
@@ -13705,26 +13712,27 @@ static void test_startupinfo_showwindow_proc( int test_id ) * SW_ variants for ShowWindow() which are not altered by startup info still consume startup info usage so can * only be tested once per process. */
- hwnd = CreateWindowA( "static", "parent", WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL, + parent = CreateWindowA( "static", "parent", WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL, GetModuleHandleW( NULL ), NULL ); pump_messages(); for (i = 0; i < ARRAY_SIZE(ignored_window_styles); ++i) { winetest_push_context( "%u", i ); - hwnd = CreateWindowA( "static", "overlapped", ignored_window_styles[i], 0, 0, 0, 0, - ignored_window_styles[i] & WS_CHILD ? hwnd : NULL, NULL, + hwnd = CreateWindowA( "static", "overlapped", ignored_window_styles[i].style, 0, 0, 0, 0, + ignored_window_styles[i].parent ? parent : NULL, NULL, GetModuleHandleW( NULL ), NULL ); ok( !!hwnd, "got NULL.\n" ); ShowWindow( hwnd, SW_SHOW ); bval = IsWindowVisible( hwnd ); - if ((ignored_window_styles[i] & (WS_CHILD | WS_POPUP)) == WS_CHILD) + if ((ignored_window_styles[i].style & (WS_CHILD | WS_POPUP)) == WS_CHILD) ok( !bval, "unexpectedly visible.\n" ); else ok( bval, "unexpectedly invisible.\n" ); pump_messages(); + DestroyWindow( hwnd ); winetest_pop_context(); } - DestroyWindow( hwnd ); + DestroyWindow( parent ); pump_messages();
style = test->style; diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 340ab31e857..e053adf0112 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -4739,6 +4739,7 @@ static BOOL show_window( HWND hwnd, INT cmd )
if ((!(style & (WS_POPUP | WS_CHILD)) || ((style & (WS_POPUP | WS_CHILD | WS_CAPTION)) == (WS_POPUP | WS_CAPTION))) + && !get_window_relative( hwnd, GW_OWNER ) && InterlockedExchange( &first_window, 0 )) { RTL_USER_PROCESS_PARAMETERS *params = NtCurrentTeb()->Peb->ProcessParameters;
From: Paul Gofman pgofman@codeweavers.com
And use those to track first use instead of first_window parameter. --- dlls/user32/tests/win.c | 14 +++++++++----- dlls/win32u/class.c | 1 + dlls/win32u/win32u_private.h | 1 + dlls/win32u/window.c | 32 ++++++++++++++++++++++++++------ 4 files changed, 37 insertions(+), 11 deletions(-)
diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c index 6073e087cb4..693a95f3d72 100644 --- a/dlls/user32/tests/win.c +++ b/dlls/user32/tests/win.c @@ -31,6 +31,7 @@ #include "wingdi.h" #include "winuser.h" #include "winreg.h" +#include "winternl.h"
#include "wine/test.h"
@@ -13693,18 +13694,21 @@ static void test_startupinfo_showwindow_proc( int test_id ) { WS_OVERLAPPED, TRUE }, /* owned window */ { WS_POPUP | WS_CAPTION, TRUE }, /* owned window */ }; + + RTL_USER_PROCESS_PARAMETERS *up = NtCurrentTeb()->Peb->ProcessParameters; BOOL bval, expected; - STARTUPINFOW sa; unsigned int i; DWORD style; HWND parent, hwnd;
- GetStartupInfoW( &sa ); + winetest_push_context( "test %d", test_id );
- winetest_push_context( "show %u, test %d", sa.wShowWindow, test_id ); + ok( up->dwFlags & STARTF_USESHOWWINDOW, "got %#lx.\n", up->dwFlags ); + ok( up->wShowWindow == SW_HIDE, "got %lu.\n.", up->wShowWindow );
- ok( sa.dwFlags & STARTF_USESHOWWINDOW, "got %#lx.\n", sa.dwFlags ); - ok( sa.wShowWindow == SW_HIDE, "got %u.\n.", sa.wShowWindow ); + /* Startup window parameters are fetched early and current values don't affect behaviour. */ + up->dwFlags = 0; + up->wShowWindow = SW_SHOW;
/* First test windows which are not affected by startup info. ShowWindow() called for those doesn't count as * consuming startup info, it is still used with the next applicable window. diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c index 9cc5b6402aa..dc1a42b381d 100644 --- a/dlls/win32u/class.c +++ b/dlls/win32u/class.c @@ -249,6 +249,7 @@ static void init_user(void) { NtQuerySystemInformation( SystemBasicInformation, &system_info, sizeof(system_info), NULL );
+ init_startup_info(); shared_session_init(); gdi_init(); sysparams_init(); diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index ee76854c7e4..983e097187b 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -301,6 +301,7 @@ extern HWND get_progman_window(void); extern HWND get_taskman_window(void); extern BOOL is_client_surface_window( struct client_surface *surface, HWND hwnd ); extern HICON get_window_icon_info( HWND hwnd, UINT type, HICON icon, ICONINFO *ret ); +extern void init_startup_info(void);
/* to release pointers retrieved by win_get_ptr */ static inline void release_win_ptr( struct tagWND *ptr ) diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index e053adf0112..9d2a8efe381 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -53,6 +53,29 @@ static void *client_objects[MAX_USER_HANDLES]; #define PLACE_MAX 0x0002 #define PLACE_RECT 0x0004
+static volatile unsigned int startup_info_flags; +static unsigned int startup_show_window; + +static unsigned int set_startup_info_flags( unsigned int mask, unsigned int flags ) +{ + unsigned int prev, new; + + do + { + prev = startup_info_flags; + new = (prev & ~mask) | flags; + } while (InterlockedCompareExchange( (LONG volatile *)&startup_info_flags, new, prev ) != prev ); + return prev; +} + +void init_startup_info(void) +{ + RTL_USER_PROCESS_PARAMETERS *p = NtCurrentTeb()->Peb->ProcessParameters; + + startup_show_window = p->wShowWindow; + set_startup_info_flags( ~0u, p->dwFlags ); +} + /*********************************************************************** * alloc_user_handle */ @@ -4724,7 +4747,6 @@ void update_window_state( HWND hwnd ) */ static BOOL show_window( HWND hwnd, INT cmd ) { - static volatile LONG first_window = 1; WND *win; HWND parent; DWORD style = get_window_long( hwnd, GWL_STYLE ), new_style; @@ -4740,13 +4762,11 @@ static BOOL show_window( HWND hwnd, INT cmd ) if ((!(style & (WS_POPUP | WS_CHILD)) || ((style & (WS_POPUP | WS_CHILD | WS_CAPTION)) == (WS_POPUP | WS_CAPTION))) && !get_window_relative( hwnd, GW_OWNER ) - && InterlockedExchange( &first_window, 0 )) + && set_startup_info_flags( STARTF_USESHOWWINDOW, 0 ) & STARTF_USESHOWWINDOW) { - RTL_USER_PROCESS_PARAMETERS *params = NtCurrentTeb()->Peb->ProcessParameters; - - if (params->dwFlags & STARTF_USESHOWWINDOW && (cmd == SW_SHOW || cmd == SW_SHOWNORMAL || cmd == SW_SHOWDEFAULT)) + if (cmd == SW_SHOW || cmd == SW_SHOWNORMAL || cmd == SW_SHOWDEFAULT) { - cmd = params->wShowWindow; + cmd = startup_show_window; TRACE( "hwnd=%p, using cmd %d from startup info.\n", hwnd, cmd ); } }
From: Paul Gofman pgofman@codeweavers.com
--- dlls/user32/tests/win.c | 75 +++++++++++++++++++++++++++++++++++++ dlls/win32u/main.c | 5 +++ dlls/win32u/win32syscalls.h | 5 +-- dlls/win32u/win32u.spec | 2 +- dlls/win32u/window.c | 11 ++++++ dlls/wow64win/user.c | 8 ++++ include/ntuser.h | 1 + 7 files changed, 103 insertions(+), 4 deletions(-)
diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c index 693a95f3d72..13dff9d672d 100644 --- a/dlls/user32/tests/win.c +++ b/dlls/user32/tests/win.c @@ -64,6 +64,8 @@ static BOOL (WINAPI *pSystemParametersInfoForDpi)(UINT,UINT,void*,UINT,UINT); static HICON (WINAPI *pInternalGetWindowIcon)(HWND window, UINT type); static BOOL (WINAPI *pSetProcessLaunchForegroundPolicy)(DWORD,DWORD);
+static BOOL (WINAPI *pNtUserModifyUserStartupInfoFlags)(DWORD,DWORD); + static BOOL test_lbuttondown_flag; static DWORD num_gettext_msgs; static DWORD num_settext_msgs; @@ -13777,6 +13779,65 @@ static void test_startupinfo_showwindow_proc( int test_id ) winetest_pop_context(); }
+static void test_showwindow_proc_modify_flags(void) +{ + RTL_USER_PROCESS_PARAMETERS *up = NtCurrentTeb()->Peb->ProcessParameters; + HWND hwnd; + BOOL ret; + + if (!pNtUserModifyUserStartupInfoFlags) + { + win_skip( "NtUserModifyUserStartupInfoFlags is not available.\n" ); + return; + } + + ok( up->dwFlags & STARTF_USESHOWWINDOW, "got %#lx.\n", up->dwFlags ); + ok( up->wShowWindow == SW_HIDE, "got %lu.\n.", up->wShowWindow ); + + /* Startup window parameters are fetched early and current values don't affect behaviour. */ + up->dwFlags = 0; + up->wShowWindow = SW_SHOW; + + pNtUserModifyUserStartupInfoFlags( STARTF_USESHOWWINDOW, 0 ); + hwnd = CreateWindowA( "static", "overlapped2", WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL, GetModuleHandleW(NULL), NULL ); + ok( !!hwnd, "got NULL.\n" ); + pump_messages(); + ShowWindow( hwnd, SW_SHOWDEFAULT ); + ret = IsWindowVisible( hwnd ); + ok( ret, "got %d.\n", ret ); + DestroyWindow( hwnd ); + pump_messages(); + + pNtUserModifyUserStartupInfoFlags( STARTF_USESHOWWINDOW, STARTF_USESHOWWINDOW ); + hwnd = CreateWindowA( "static", "overlapped2", WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL, GetModuleHandleW(NULL), NULL ); + ok( !!hwnd, "got NULL.\n" ); + pump_messages(); + ShowWindow( hwnd, SW_SHOWDEFAULT ); + ret = IsWindowVisible( hwnd ); + ok( !ret, "got %d.\n", ret ); + DestroyWindow( hwnd ); + pump_messages(); + + hwnd = CreateWindowA( "static", "overlapped2", WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL, GetModuleHandleW(NULL), NULL ); + ok( !!hwnd, "got NULL.\n" ); + pump_messages(); + ShowWindow( hwnd, SW_SHOWDEFAULT ); + ret = IsWindowVisible( hwnd ); + ok( ret, "got %d.\n", ret ); + DestroyWindow( hwnd ); + pump_messages(); + + pNtUserModifyUserStartupInfoFlags( STARTF_USESHOWWINDOW, STARTF_USESHOWWINDOW ); + hwnd = CreateWindowA( "static", "overlapped2", WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL, GetModuleHandleW(NULL), NULL ); + ok( !!hwnd, "got NULL.\n" ); + pump_messages(); + ShowWindow( hwnd, SW_SHOWDEFAULT ); + ret = IsWindowVisible( hwnd ); + ok( !ret, "got %d.\n", ret ); + DestroyWindow( hwnd ); + pump_messages(); +} + static void test_startupinfo_showwindow( char **argv ) { STARTUPINFOA sa = {.cb = sizeof(STARTUPINFOA)}; @@ -13795,6 +13856,11 @@ static void test_startupinfo_showwindow( char **argv ) ok( ret, "got error %lu\n", GetLastError() ); wait_child_process( &info ); } + + sprintf( cmdline, "%s %s showwindow_proc_modify_flags", argv[0], argv[1] ); + ret = CreateProcessA( NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &sa, &info ); + ok( ret, "got error %lu\n", GetLastError() ); + wait_child_process( &info ); }
static void test_cascade_windows(void) @@ -14273,6 +14339,7 @@ START_TEST(win) int argc = winetest_get_mainargs( &argv ); HMODULE user32 = GetModuleHandleA( "user32.dll" ); HMODULE gdi32 = GetModuleHandleA("gdi32.dll"); + HMODULE win32u = GetModuleHandleA("win32u.dll"); pGetWindowInfo = (void *)GetProcAddress( user32, "GetWindowInfo" ); pGetWindowModuleFileNameA = (void *)GetProcAddress( user32, "GetWindowModuleFileNameA" ); pGetLayeredWindowAttributes = (void *)GetProcAddress( user32, "GetLayeredWindowAttributes" ); @@ -14293,6 +14360,8 @@ START_TEST(win) pInternalGetWindowIcon = (void *)GetProcAddress( user32, "InternalGetWindowIcon" ); pSetProcessLaunchForegroundPolicy = (void*)GetProcAddress( user32, "SetProcessLaunchForegroundPolicy" );
+ pNtUserModifyUserStartupInfoFlags = (void*)GetProcAddress( win32u, "NtUserModifyUserStartupInfoFlags" ); + if (argc == 4) { HWND hwnd; @@ -14328,6 +14397,12 @@ START_TEST(win) return; }
+ if (argc == 3 && !strcmp(argv[2], "showwindow_proc_modify_flags")) + { + test_showwindow_proc_modify_flags(); + return; + } + if (!RegisterWindowClasses()) assert(0);
hwndMain = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window", diff --git a/dlls/win32u/main.c b/dlls/win32u/main.c index 193c2c048bf..c0482ba059f 100644 --- a/dlls/win32u/main.c +++ b/dlls/win32u/main.c @@ -1962,6 +1962,11 @@ LRESULT SYSCALL_API NtUserMessageCall( HWND hwnd, UINT msg, WPARAM wparam, LPARA SYSCALL_FUNC( NtUserMessageCall ); }
+BOOL SYSCALL_API NtUserModifyUserStartupInfoFlags( DWORD mask, DWORD flags ) +{ + SYSCALL_FUNC( NtUserModifyUserStartupInfoFlags ); +} + BOOL SYSCALL_API NtUserMoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy, BOOL repaint ) { SYSCALL_FUNC( NtUserMoveWindow ); diff --git a/dlls/win32u/win32syscalls.h b/dlls/win32u/win32syscalls.h index 69982b52833..7826afd3fc3 100644 --- a/dlls/win32u/win32syscalls.h +++ b/dlls/win32u/win32syscalls.h @@ -1209,7 +1209,7 @@ SYSCALL_ENTRY( 0x14b5, NtUserMessageCall, 28 ) \ SYSCALL_ENTRY( 0x14b6, NtUserMinInitialize, 0 ) \ SYSCALL_ENTRY( 0x14b7, NtUserMinMaximize, 0 ) \ - SYSCALL_ENTRY( 0x14b8, NtUserModifyUserStartupInfoFlags, 0 ) \ + SYSCALL_ENTRY( 0x14b8, NtUserModifyUserStartupInfoFlags, 8 ) \ SYSCALL_ENTRY( 0x14b9, NtUserModifyWindowTouchCapability, 0 ) \ SYSCALL_ENTRY( 0x14ba, NtUserMoveWindow, 24 ) \ SYSCALL_ENTRY( 0x14bb, NtUserMsgWaitForMultipleObjectsEx, 20 ) \ @@ -2751,7 +2751,7 @@ SYSCALL_ENTRY( 0x14b5, NtUserMessageCall, 56 ) \ SYSCALL_ENTRY( 0x14b6, NtUserMinInitialize, 0 ) \ SYSCALL_ENTRY( 0x14b7, NtUserMinMaximize, 0 ) \ - SYSCALL_ENTRY( 0x14b8, NtUserModifyUserStartupInfoFlags, 0 ) \ + SYSCALL_ENTRY( 0x14b8, NtUserModifyUserStartupInfoFlags, 16 ) \ SYSCALL_ENTRY( 0x14b9, NtUserModifyWindowTouchCapability, 0 ) \ SYSCALL_ENTRY( 0x14ba, NtUserMoveWindow, 48 ) \ SYSCALL_ENTRY( 0x14bb, NtUserMsgWaitForMultipleObjectsEx, 40 ) \ @@ -3929,7 +3929,6 @@ SYSCALL_STUB( NtUserMarkWindowForRawMouse ) \ SYSCALL_STUB( NtUserMinInitialize ) \ SYSCALL_STUB( NtUserMinMaximize ) \ - SYSCALL_STUB( NtUserModifyUserStartupInfoFlags ) \ SYSCALL_STUB( NtUserModifyWindowTouchCapability ) \ SYSCALL_STUB( NtUserNavigateFocus ) \ SYSCALL_STUB( NtUserNlsKbdSendIMENotification ) \ diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index f0ccfba35cb..e3e80a05d0c 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -1207,7 +1207,7 @@ @ stdcall -syscall NtUserMessageCall(long long long long long long long) @ stub -syscall NtUserMinInitialize @ stub -syscall NtUserMinMaximize -@ stub -syscall NtUserModifyUserStartupInfoFlags +@ stdcall -syscall NtUserModifyUserStartupInfoFlags(long long) @ stub -syscall NtUserModifyWindowTouchCapability @ stdcall -syscall NtUserMoveWindow(long long long long long long) @ stdcall -syscall NtUserMsgWaitForMultipleObjectsEx(long ptr long long long) diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 9d2a8efe381..560fd62d8ce 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -6452,3 +6452,14 @@ BOOL WINAPI NtUserGetWindowDisplayAffinity( HWND hwnd, DWORD *affinity ) *affinity = WDA_NONE; return TRUE; } + +/***************************************************************** + * NtUserModifyUserStartupInfoFlags (win32u.@) + */ +BOOL WINAPI NtUserModifyUserStartupInfoFlags( DWORD mask, DWORD flags ) +{ + TRACE( "%#x, %#x.\n", (int)mask, (int)flags ); + + set_startup_info_flags( mask, flags ); + return TRUE; +} diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index 398f0fa2f6f..b728e7c01d7 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -3807,6 +3807,14 @@ NTSTATUS WINAPI wow64_NtUserMessageCall( UINT *args ) return message_call_32to64( hwnd, msg, wparam, lparam, result_info, type, ansi ); }
+NTSTATUS WINAPI wow64_NtUserModifyUserStartupInfoFlags( UINT *args ) +{ + DWORD mask = get_ulong( &args ); + DWORD flags = get_ulong( &args ); + + return NtUserModifyUserStartupInfoFlags( mask, flags ); +} + NTSTATUS WINAPI wow64_NtUserMoveWindow( UINT *args ) { HWND hwnd = get_handle( &args ); diff --git a/include/ntuser.h b/include/ntuser.h index 664bcfe459d..8b9d177419b 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -933,6 +933,7 @@ W32KAPI INT WINAPI NtUserMenuItemFromPoint( HWND hwnd, HMENU handle, int x, W32KAPI BOOL WINAPI NtUserMessageBeep( UINT type ); W32KAPI LRESULT WINAPI NtUserMessageCall( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam, void *result_info, DWORD type, BOOL ansi ); +W32KAPI BOOL WINAPI NtUserModifyUserStartupInfoFlags( DWORD mask, DWORD flags ); W32KAPI BOOL WINAPI NtUserMoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy, BOOL repaint ); W32KAPI DWORD WINAPI NtUserMsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles, DWORD timeout, DWORD mask, DWORD flags );
From: Paul Gofman pgofman@codeweavers.com
--- dlls/user32/tests/dialog.c | 100 ++++++++++++++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 2 deletions(-)
diff --git a/dlls/user32/tests/dialog.c b/dlls/user32/tests/dialog.c index 49b8f1968a0..a8c366cc7df 100644 --- a/dlls/user32/tests/dialog.c +++ b/dlls/user32/tests/dialog.c @@ -40,6 +40,8 @@ #include "winuser.h" #include "winnls.h"
+static BOOL (WINAPI *pNtUserModifyUserStartupInfoFlags)(DWORD,DWORD); + #define MAXHWNDS 1024 static HWND hwnd [MAXHWNDS]; static unsigned int numwnds=1; /* 0 is reserved for null */ @@ -147,6 +149,17 @@ static const h_entry hierarchy [] = { {0, 0, 0, 0} };
+static void pump_messages(void) +{ + MSG msg; + + while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) + { + TranslateMessage( &msg ); + DispatchMessageA( &msg ); + } +} + static DWORD get_button_style(HWND button) { return GetWindowLongW(button, GWL_STYLE) & BS_TYPEMASK; @@ -2248,7 +2261,63 @@ static LRESULT CALLBACK msgbox_hook_proc(INT code, WPARAM wParam, LPARAM lParam) return CallNextHookEx(NULL, code, wParam, lParam); }
-static void test_MessageBox(void) +static LRESULT CALLBACK msgbox_hook_proc2(INT code, WPARAM wParam, LPARAM lParam) +{ + return 1; /* prevent message box or dialog window creation. */ +} + +static void test_message_box_startup_info(void) +{ + HHOOK hook; + HWND hwnd; + int ret; + + hook = SetWindowsHookExA( WH_CBT, msgbox_hook_proc2, NULL, GetCurrentThreadId() ); + ret = DialogBoxParamA( GetModuleHandleA( NULL ), "TEST_EMPTY_DIALOG", 0, NULL, 0 ); + ok(ret == -1, "got %d\n", ret); + UnhookWindowsHookEx( hook ); + + hwnd = CreateWindowA( "static", "overlapped2", WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL, GetModuleHandleW(NULL), NULL ); + ok( !!hwnd, "got NULL.\n" ); + pump_messages(); + ShowWindow( hwnd, SW_SHOWDEFAULT ); + /* startup info window show flags are in effect. */ + ret = IsWindowVisible( hwnd ); + ok( !ret, "got %d.\n", ret ); + DestroyWindow( hwnd ); + pump_messages(); + + /* set startup info flags once again. */ + pNtUserModifyUserStartupInfoFlags( STARTF_USESHOWWINDOW, STARTF_USESHOWWINDOW ); + hook = SetWindowsHookExA( WH_CBT, msgbox_hook_proc2, NULL, GetCurrentThreadId() ); + ret = MessageBoxA(NULL, "Text", "MSGBOX caption", msgbox_type); + todo_wine ok(!ret, "got %d\n", ret); /* Wine returns -1 here. */ + UnhookWindowsHookEx( hook ); + + hwnd = CreateWindowA( "static", "overlapped2", WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL, GetModuleHandleW(NULL), NULL ); + ok( !!hwnd, "got NULL.\n" ); + pump_messages(); + ShowWindow( hwnd, SW_SHOWDEFAULT ); + ret = IsWindowVisible( hwnd ); + /* startup info flags have no effect, while the message box window wasn't even created. */ + todo_wine ok( ret, "got %d.\n", ret ); + DestroyWindow( hwnd ); + pump_messages(); + + /* sanity check, set startup flags once againg and check that it works */ + pNtUserModifyUserStartupInfoFlags( STARTF_USESHOWWINDOW, STARTF_USESHOWWINDOW ); + hwnd = CreateWindowA( "static", "overlapped2", WS_OVERLAPPED, 0, 0, 0, 0, NULL, NULL, GetModuleHandleW(NULL), NULL ); + ok( !!hwnd, "got NULL.\n" ); + pump_messages(); + ShowWindow( hwnd, SW_SHOWDEFAULT ); + ret = IsWindowVisible( hwnd ); + /* startup info flags have no effect, while the message box window wasn't even created. */ + ok( !ret, "got %d.\n", ret ); + DestroyWindow( hwnd ); + pump_messages(); +} + +static void test_MessageBox(char **argv) { static const UINT tests[] = { @@ -2260,6 +2329,9 @@ static void test_MessageBox(void) MB_OKCANCEL | MB_TASKMODAL | MB_TOPMOST, MB_OKCANCEL | MB_TASKMODAL | MB_SYSTEMMODAL | MB_TOPMOST, }; + STARTUPINFOA sa = {.cb = sizeof(STARTUPINFOA)}; + PROCESS_INFORMATION info; + char cmdline[MAX_PATH]; unsigned int i; HHOOK hook; int ret; @@ -2278,6 +2350,18 @@ static void test_MessageBox(void) }
UnhookWindowsHookEx(hook); + + if (!pNtUserModifyUserStartupInfoFlags) + { + win_skip("NtUserModifyUserStartupInfoFlags is not available.\n"); + return; + } + sa.dwFlags = STARTF_USESHOWWINDOW; + sa.wShowWindow = SW_HIDE; + sprintf(cmdline, "%s %s message_box_startup_info", argv[0], argv[1]); + ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &sa, &info); + ok(ret, "got error %lu\n", GetLastError()); + wait_child_process(&info); }
static INT_PTR CALLBACK custom_test_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam) @@ -2436,10 +2520,22 @@ static void test_create_controls(void)
START_TEST(dialog) { + char **argv; + int argc = winetest_get_mainargs( &argv ); + HMODULE win32u = GetModuleHandleA("win32u.dll"); + + pNtUserModifyUserStartupInfoFlags = (void*)GetProcAddress(win32u, "NtUserModifyUserStartupInfoFlags"); + g_hinst = GetModuleHandleA (0);
if (!RegisterWindowClasses()) assert(0);
+ if (argc == 3 && !strcmp(argv[2], "message_box_startup_info")) + { + test_message_box_startup_info(); + return; + } + test_dialog_custom_data(); test_GetNextDlgItem(); test_IsDialogMessage(); @@ -2453,6 +2549,6 @@ START_TEST(dialog) test_MessageBoxFontTest(); test_SaveRestoreFocus(); test_timer_message(); - test_MessageBox(); + test_MessageBox(argv); test_capture_release(); }
From: Paul Gofman pgofman@codeweavers.com
Fixes a regression introduced by 8d7de32cd646f3d1f118836e643e6146c9837278. --- dlls/user32/msgbox.c | 1 + dlls/user32/tests/dialog.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/dlls/user32/msgbox.c b/dlls/user32/msgbox.c index 12eea8e92d7..009f3858c60 100644 --- a/dlls/user32/msgbox.c +++ b/dlls/user32/msgbox.c @@ -540,6 +540,7 @@ INT WINAPI MessageBoxIndirectW( LPMSGBOXPARAMSW msgbox ) EnumThreadWindows(GetCurrentThreadId(), MSGBOX_EnumProc, (LPARAM)&threadWindows); }
+ NtUserModifyUserStartupInfoFlags( STARTF_USESHOWWINDOW, 0 ); ret=DialogBoxIndirectParamW(msgbox->hInstance, tmplate, msgbox->hwndOwner, MSGBOX_DlgProc, (LPARAM)msgbox);
diff --git a/dlls/user32/tests/dialog.c b/dlls/user32/tests/dialog.c index a8c366cc7df..20e21bea0bc 100644 --- a/dlls/user32/tests/dialog.c +++ b/dlls/user32/tests/dialog.c @@ -2300,7 +2300,7 @@ static void test_message_box_startup_info(void) ShowWindow( hwnd, SW_SHOWDEFAULT ); ret = IsWindowVisible( hwnd ); /* startup info flags have no effect, while the message box window wasn't even created. */ - todo_wine ok( ret, "got %d.\n", ret ); + ok( ret, "got %d.\n", ret ); DestroyWindow( hwnd ); pump_messages();
v5: - align `&& !get_window_relative( hwnd, GW_OWNER )`.