diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 92e00cc2..9db4ec3a 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -326,6 +326,7 @@ patch_enable_all () enable_user_exe16_CONTAINING_RECORD="$1" enable_user_exe16_DlgDirList="$1" enable_user32_CharToOem="$1" + enable_user32_DM_SETDEFID="$1" enable_user32_DeferWindowPos="$1" enable_user32_DialogBoxParam="$1" enable_user32_Dialog_Paint_Event="$1" @@ -1159,6 +1160,9 @@ patch_enable () user32-CharToOem) enable_user32_CharToOem="$2" ;; + user32-DM_SETDEFID) + enable_user32_DM_SETDEFID="$2" + ;; user32-DeferWindowPos) enable_user32_DeferWindowPos="$2" ;; @@ -6736,6 +6740,25 @@ if test "$enable_user32_CharToOem" -eq 1; then ) >> "$patchlist" fi +# Patchset user32-DM_SETDEFID +# | +# | This patchset fixes the following Wine bugs: +# | * [#22764] Use root dialog for DM_SETDEFID/DM_GETDEFID in DefDlgProc +# | +# | Modified files: +# | * dlls/user32/defdlg.c, dlls/user32/dialog.c, dlls/user32/tests/win.c +# | +if test "$enable_user32_DM_SETDEFID" -eq 1; then + patch_apply user32-DM_SETDEFID/0001-user32-Do-not-initialize-dialog-info-for-every-windo.patch + patch_apply user32-DM_SETDEFID/0002-user32-Use-root-dialog-for-DM_SETDEFID-DM_GETDEFID-i.patch + patch_apply user32-DM_SETDEFID/0003-user32-tests-Add-a-bunch-of-tests-for-DM_SETDEFID-DM.patch + ( + echo '+ { "Dmitry Timoshkov", "user32: Do not initialize dialog info for every window passed to DefDlgProc.", 1 },'; + echo '+ { "Dmitry Timoshkov", "user32: Use root dialog for DM_SETDEFID/DM_GETDEFID in DefDlgProc.", 1 },'; + echo '+ { "Dmitry Timoshkov", "user32/tests: Add a bunch of tests for DM_SETDEFID/DM_GETDEFID handling by a DefDlgProc.", 1 },'; + ) >> "$patchlist" +fi + # Patchset user32-DeferWindowPos # | # | This patchset fixes the following Wine bugs: diff --git a/patches/user32-DM_SETDEFID/0001-user32-Do-not-initialize-dialog-info-for-every-windo.patch b/patches/user32-DM_SETDEFID/0001-user32-Do-not-initialize-dialog-info-for-every-windo.patch new file mode 100644 index 00000000..8f97fe07 --- /dev/null +++ b/patches/user32-DM_SETDEFID/0001-user32-Do-not-initialize-dialog-info-for-every-windo.patch @@ -0,0 +1,57 @@ +From c40265799ed2dd422b06cce9560b7b855304cbf1 Mon Sep 17 00:00:00 2001 +From: Dmitry Timoshkov +Date: Wed, 15 Jun 2016 14:57:10 +0800 +Subject: user32: Do not initialize dialog info for every window passed to + DefDlgProc. + +The tests in the last patch in the series use +DefDlgProcA(parent, DM_GETDEFID, 0, 0); +as a simple dialog detector, and that call leads to dialog info being +created for a not dialog window, which later makes this window being +treated as a dialog. + +DIALOG_CreateControls32() gets called after the dialog info creation +has been forced, so passing TRUE to DIALOG_get_info() is redundant there. +--- + dlls/user32/defdlg.c | 4 ++-- + dlls/user32/dialog.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/dlls/user32/defdlg.c b/dlls/user32/defdlg.c +index 00a73c6..258c3a9 100644 +--- a/dlls/user32/defdlg.c ++++ b/dlls/user32/defdlg.c +@@ -364,7 +364,7 @@ LRESULT WINAPI DefDlgProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) + LRESULT result = 0; + + /* Perform DIALOGINFO initialization if not done */ +- if(!(dlgInfo = DIALOG_get_info( hwnd, TRUE ))) return 0; ++ if (!(dlgInfo = DIALOG_get_info( hwnd, msg == WM_NCCREATE ))) return 0; + + SetWindowLongPtrW( hwnd, DWLP_MSGRESULT, 0 ); + +@@ -422,7 +422,7 @@ LRESULT WINAPI DefDlgProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) + LRESULT result = 0; + + /* Perform DIALOGINFO initialization if not done */ +- if(!(dlgInfo = DIALOG_get_info( hwnd, TRUE ))) return 0; ++ if (!(dlgInfo = DIALOG_get_info( hwnd, msg == WM_NCCREATE ))) return 0; + + SetWindowLongPtrW( hwnd, DWLP_MSGRESULT, 0 ); + +diff --git a/dlls/user32/dialog.c b/dlls/user32/dialog.c +index 9cb4b8d..b84784f 100644 +--- a/dlls/user32/dialog.c ++++ b/dlls/user32/dialog.c +@@ -216,7 +216,7 @@ static const WORD *DIALOG_GetControl32( const WORD *p, DLG_CONTROL_INFO *info, + static BOOL DIALOG_CreateControls32( HWND hwnd, LPCSTR template, const DLG_TEMPLATE *dlgTemplate, + HINSTANCE hInst, BOOL unicode ) + { +- DIALOGINFO *dlgInfo = DIALOG_get_info( hwnd, TRUE ); ++ DIALOGINFO *dlgInfo = DIALOG_get_info( hwnd, FALSE ); + DLG_CONTROL_INFO info; + HWND hwndCtrl, hwndDefButton = 0; + INT items = dlgTemplate->nbItems; +-- +2.8.0 + diff --git a/patches/user32-DM_SETDEFID/0002-user32-Use-root-dialog-for-DM_SETDEFID-DM_GETDEFID-i.patch b/patches/user32-DM_SETDEFID/0002-user32-Use-root-dialog-for-DM_SETDEFID-DM_GETDEFID-i.patch new file mode 100644 index 00000000..f7f78ef1 --- /dev/null +++ b/patches/user32-DM_SETDEFID/0002-user32-Use-root-dialog-for-DM_SETDEFID-DM_GETDEFID-i.patch @@ -0,0 +1,62 @@ +From d068cb5331e7dee5ceb0c14a3eff9ef2c273865d Mon Sep 17 00:00:00 2001 +From: Dmitry Timoshkov +Date: Wed, 15 Jun 2016 15:07:39 +0800 +Subject: user32: Use root dialog for DM_SETDEFID/DM_GETDEFID in DefDlgProc. + +This patch fixes DM_SETDEFID/DM_GETDEFID handling in complex dialog +structures such as a property sheet. +--- + dlls/user32/defdlg.c | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/dlls/user32/defdlg.c b/dlls/user32/defdlg.c +index 258c3a9..6765a51 100644 +--- a/dlls/user32/defdlg.c ++++ b/dlls/user32/defdlg.c +@@ -209,6 +209,25 @@ static BOOL DEFDLG_SetDefButton( HWND hwndDlg, DIALOGINFO *dlgInfo, HWND hwndNew + } + + ++static HWND root_dialog(HWND hwnd) ++{ ++ while ((GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_CONTROLPARENT) && ++ (GetWindowLongA(hwnd, GWL_STYLE) & (WS_CHILD|WS_POPUP)) == WS_CHILD) ++ { ++ HWND parent = GetParent(hwnd); ++ ++ if (!DIALOG_get_info(parent, FALSE)) ++ break; ++ ++ hwnd = parent; ++ ++ if (!(GetWindowLongA(hwnd, GWL_STYLE) & DS_CONTROL)) ++ break; ++ } ++ ++ return hwnd; ++} ++ + /*********************************************************************** + * DEFDLG_Proc + * +@@ -264,11 +283,17 @@ static LRESULT DEFDLG_Proc( HWND hwnd, UINT msg, WPARAM wParam, + return 0; + + case DM_SETDEFID: ++ hwnd = root_dialog( hwnd ); ++ dlgInfo = DIALOG_get_info( hwnd, FALSE ); ++ + if (dlgInfo && !(dlgInfo->flags & DF_END)) + DEFDLG_SetDefId( hwnd, dlgInfo, wParam ); + return 1; + + case DM_GETDEFID: ++ hwnd = root_dialog( hwnd ); ++ dlgInfo = DIALOG_get_info( hwnd, FALSE ); ++ + if (dlgInfo && !(dlgInfo->flags & DF_END)) + { + HWND hwndDefId; +-- +2.8.0 + diff --git a/patches/user32-DM_SETDEFID/0003-user32-tests-Add-a-bunch-of-tests-for-DM_SETDEFID-DM.patch b/patches/user32-DM_SETDEFID/0003-user32-tests-Add-a-bunch-of-tests-for-DM_SETDEFID-DM.patch new file mode 100644 index 00000000..4233ba02 --- /dev/null +++ b/patches/user32-DM_SETDEFID/0003-user32-tests-Add-a-bunch-of-tests-for-DM_SETDEFID-DM.patch @@ -0,0 +1,148 @@ +From 44670a4e2f5d3434d8546ed32724b58a24b4399e Mon Sep 17 00:00:00 2001 +From: Dmitry Timoshkov +Date: Wed, 15 Jun 2016 15:09:46 +0800 +Subject: user32/tests: Add a bunch of tests for DM_SETDEFID/DM_GETDEFID + handling by a DefDlgProc. + +--- + dlls/user32/tests/win.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 87 insertions(+) + +diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c +index c135fdf..23e98e0 100644 +--- a/dlls/user32/tests/win.c ++++ b/dlls/user32/tests/win.c +@@ -4228,15 +4228,65 @@ static void test_window_styles(void) + } + } + ++static HWND root_dialog(HWND hwnd) ++{ ++ while ((GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_CONTROLPARENT) && ++ (GetWindowLongA(hwnd, GWL_STYLE) & (WS_CHILD|WS_POPUP)) == WS_CHILD) ++ { ++ HWND parent = GetParent(hwnd); ++ ++ /* simple detector for a window being a dialog */ ++ if (!DefDlgProcA(parent, DM_GETDEFID, 0, 0)) ++ break; ++ ++ hwnd = parent; ++ ++ if (!(GetWindowLongA(hwnd, GWL_STYLE) & DS_CONTROL)) ++ break; ++ } ++ ++ return hwnd; ++} ++ + static INT_PTR WINAPI empty_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) + { + return 0; + } + ++static LRESULT expected_id; ++ + static INT_PTR WINAPI empty_dlg_proc3(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) + { + if (msg == WM_INITDIALOG) ++ { ++ HWND parent = GetParent(hwnd); ++ LRESULT id, ret; ++ ++ id = DefDlgProcA(parent, DM_GETDEFID, 0, 0); ++ if (!id || root_dialog(hwnd) == hwnd) ++ parent = 0; ++ ++ id = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0); ++ if (!parent) ++ ok(id == MAKELONG(IDOK,DC_HASDEFID), "expected (IDOK,DC_HASDEFID), got %08lx\n", id); ++ else ++ ok(id == expected_id, "expected %08lx, got %08lx\n", expected_id, id); ++ ++ ret = DefDlgProcA(hwnd, DM_SETDEFID, 0x3333, 0); ++ ok(ret, "DefDlgProc(DM_SETDEFID) failed\n"); ++ id = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0); ++ ok(id == MAKELONG(0x3333,DC_HASDEFID), "expected (0x3333,DC_HASDEFID), got %08lx\n", id); ++ ++ if (parent) ++ { ++ id = DefDlgProcA(parent, DM_GETDEFID, 0, 0); ++ ok(id == MAKELONG(0x3333,DC_HASDEFID), "expected (0x3333,DC_HASDEFID), got %08lx\n", id); ++ ++ expected_id = MAKELONG(0x3333,DC_HASDEFID); ++ } ++ + EndDialog(hwnd, 0); ++ } + + return 0; + } +@@ -4255,6 +4305,16 @@ static INT_PTR WINAPI empty_dlg_proc2(HWND hwnd, UINT msg, WPARAM wparam, LPARAM + struct dialog_param *param = (struct dialog_param *)lparam; + BOOL parent_is_child; + HWND disabled_hwnd; ++ LRESULT id, ret; ++ ++ id = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0); ++ ok(id == MAKELONG(IDOK,DC_HASDEFID), "expected (IDOK,DC_HASDEFID), got %08lx\n", id); ++ ret = DefDlgProcA(hwnd, DM_SETDEFID, 0x2222, 0); ++ ok(ret, "DefDlgProc(DM_SETDEFID) failed\n"); ++ id = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0); ++ ok(id == MAKELONG(0x2222,DC_HASDEFID), "expected (0x2222,DC_HASDEFID), got %08lx\n", id); ++ ++ expected_id = MAKELONG(0x2222,DC_HASDEFID); + + parent_is_child = (GetWindowLongA(param->parent, GWL_STYLE) & (WS_POPUP | WS_CHILD)) == WS_CHILD; + +@@ -4296,6 +4356,25 @@ static INT_PTR WINAPI empty_dlg_proc2(HWND hwnd, UINT msg, WPARAM wparam, LPARAM + DialogBoxIndirectParamA(GetModuleHandleA(NULL), param->dlg_data, hwnd, empty_dlg_proc3, 0); + ok(IsWindowEnabled(hwnd), "wrong state for %p (%08x)\n", hwnd, style); + ++ param->dlg_data->style |= DS_CONTROL; ++ DialogBoxIndirectParamA(GetModuleHandleA(NULL), param->dlg_data, hwnd, empty_dlg_proc3, 0); ++ ok(IsWindowEnabled(hwnd), "wrong state for %p (%08x)\n", hwnd, style); ++ ++ param->dlg_data->dwExtendedStyle |= WS_EX_CONTROLPARENT; ++ SetWindowLongA(hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_CONTROLPARENT); ++ SetWindowLongA(hwnd, GWL_STYLE, style & ~DS_CONTROL); ++ param->dlg_data->style &= ~DS_CONTROL; ++ DialogBoxIndirectParamA(GetModuleHandleA(NULL), param->dlg_data, hwnd, empty_dlg_proc3, 0); ++ ok(IsWindowEnabled(hwnd), "wrong state for %p (%08x)\n", hwnd, style); ++ ++ SetWindowLongA(hwnd, GWL_STYLE, style | DS_CONTROL); ++ DialogBoxIndirectParamA(GetModuleHandleA(NULL), param->dlg_data, hwnd, empty_dlg_proc3, 0); ++ ok(IsWindowEnabled(hwnd), "wrong state for %p (%08x)\n", hwnd, style); ++ ++ param->dlg_data->style |= DS_CONTROL; ++ DialogBoxIndirectParamA(GetModuleHandleA(NULL), param->dlg_data, hwnd, empty_dlg_proc3, 0); ++ ok(IsWindowEnabled(hwnd), "wrong state for %p (%08x)\n", hwnd, style); ++ + EndDialog(hwnd, 0); + } + return 0; +@@ -4314,6 +4393,7 @@ static void check_dialog_style(DWORD style_in, DWORD ex_style_in, DWORD style_ou + DWORD style, ex_style; + HWND hwnd, grand_parent = 0, parent = 0; + struct dialog_param param; ++ LRESULT id, ret; + + if (style_in & WS_CHILD) + { +@@ -4341,6 +4421,13 @@ static void check_dialog_style(DWORD style_in, DWORD ex_style_in, DWORD style_ou + hwnd = CreateDialogIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, parent, empty_dlg_proc, 0); + ok(hwnd != 0, "dialog creation failed, style %#x, exstyle %#x\n", style_in, ex_style_in); + ++ id = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0); ++ ok(id == MAKELONG(IDOK,DC_HASDEFID), "expected (IDOK,DC_HASDEFID), got %08lx\n", id); ++ ret = DefDlgProcA(hwnd, DM_SETDEFID, 0x1111, 0); ++ ok(ret, "DefDlgProc(DM_SETDEFID) failed\n"); ++ id = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0); ++ ok(id == MAKELONG(0x1111,DC_HASDEFID), "expected (0x1111,DC_HASDEFID), got %08lx\n", id); ++ + flush_events( TRUE ); + + style = GetWindowLongA(hwnd, GWL_STYLE); +-- +2.8.0 + diff --git a/patches/user32-DM_SETDEFID/definition b/patches/user32-DM_SETDEFID/definition new file mode 100644 index 00000000..26018a07 --- /dev/null +++ b/patches/user32-DM_SETDEFID/definition @@ -0,0 +1 @@ +Fixes: [22764] Use root dialog for DM_SETDEFID/DM_GETDEFID in DefDlgProc