[USER32_WINETEST] Sync with Wine Staging 4.18 except win.c (PR #1980). CORE-16441
[reactos.git] / modules / rostests / winetests / user32 / dialog.c
index 679a762..3360b68 100644 (file)
@@ -42,6 +42,7 @@
 #include "winbase.h"
 #include "wingdi.h"
 #include "winuser.h"
 #include "winbase.h"
 #include "wingdi.h"
 #include "winuser.h"
+#include "winnls.h"
 
 #define MAXHWNDS 1024
 static HWND hwnd [MAXHWNDS];
 
 #define MAXHWNDS 1024
 static HWND hwnd [MAXHWNDS];
@@ -57,6 +58,7 @@ static LONG g_styleInitialFocusT1, g_styleInitialFocusT2;
 static BOOL g_bInitialFocusInitDlgResult, g_bReceivedCommand;
 
 static BOOL g_terminated;
 static BOOL g_bInitialFocusInitDlgResult, g_bReceivedCommand;
 
 static BOOL g_terminated;
+static BOOL g_button1Clicked;
 
 typedef struct {
     INT_PTR id;
 
 typedef struct {
     INT_PTR id;
@@ -149,6 +151,11 @@ static const h_entry hierarchy [] = {
     {0, 0, 0, 0}
 };
 
     {0, 0, 0, 0}
 };
 
+static DWORD get_button_style(HWND button)
+{
+    return GetWindowLongW(button, GWL_STYLE) & BS_TYPEMASK;
+}
+
 static BOOL CreateWindows (HINSTANCE hinst)
 {
     const h_entry *p = hierarchy;
 static BOOL CreateWindows (HINSTANCE hinst)
 {
     const h_entry *p = hierarchy;
@@ -156,14 +163,14 @@ static BOOL CreateWindows (HINSTANCE hinst)
     while (p->id != 0)
     {
         DWORD style, exstyle;
     while (p->id != 0)
     {
         DWORD style, exstyle;
-        char ctrlname[9];
+        char ctrlname[16];
 
         /* Basically assert that the hierarchy is valid and track the
          * maximum control number
          */
         if (p->id >= numwnds)
         {
 
         /* Basically assert that the hierarchy is valid and track the
          * maximum control number
          */
         if (p->id >= numwnds)
         {
-            if (p->id >=  sizeof(hwnd)/sizeof(hwnd[0]))
+            if (p->id >=  ARRAY_SIZE(hwnd))
             {
                 trace ("Control %ld is out of range\n", p->id);
                 return FALSE;
             {
                 trace ("Control %ld is out of range\n", p->id);
                 return FALSE;
@@ -476,6 +483,10 @@ static LRESULT CALLBACK main_window_procA (HWND hwnd, UINT uiMsg, WPARAM wParam,
                 g_terminated = TRUE;
                 return 0;
             }
                 g_terminated = TRUE;
                 return 0;
             }
+            else if ((wParam == 100 || wParam == 0xFFFF) && lParam)
+            {
+                g_button1Clicked = TRUE;
+            }
             break;
     }
 
             break;
     }
 
@@ -630,76 +641,47 @@ static void test_WM_NEXTDLGCTL(void)
      * BS_DEFPUSHBUTTON with out making it default.
      */
 
      * BS_DEFPUSHBUTTON with out making it default.
      */
 
-    /*
-     * Keep the focus on Edit control.
-     */
+    /* Keep the focus on Edit control. */
+    SetFocus(g_hwndTestDlgEdit);
+    ok((GetFocus() == g_hwndTestDlgEdit), "Focus didn't set on Edit control\n");
 
 
-    if ( SetFocus( g_hwndTestDlgEdit ) )
-    {
-         ok ((GetFocus() == g_hwndTestDlgEdit), "Focus didn't set on Edit control\n");
-
-        /*
-         * Test message WM_NEXTDLGCTL
-         */
-        DefDlgProcA( g_hwndTestDlg, WM_NEXTDLGCTL, 0, 0 );
-        ok ((GetFocus() == g_hwndTestDlgBut1), "Focus didn't move to first button\n");
+    /* Test message WM_NEXTDLGCTL */
+    DefDlgProcA(g_hwndTestDlg, WM_NEXTDLGCTL, 0, 0);
+    ok((GetFocus() == g_hwndTestDlgBut1), "Focus didn't move to first button\n");
 
 
-        /*
-         * Check whether the default button ID got changed by sending message "WM_NEXTDLGCTL"
-         */
-        dwVal = DefDlgProcA(g_hwndTestDlg, DM_GETDEFID, 0, 0);
-        ok ( IDCANCEL == (LOWORD(dwVal)), "WM_NEXTDLGCTL changed default button\n");
-
-        /*
-         * Check whether the style of the button which got the focus, changed to BS_DEFPUSHBUTTON and
-         * the style of default button changed to BS_PUSHBUTTON.
-         */
-        if ( IDCANCEL == (LOWORD(dwVal)) )
-        {
-                ok ( ((GetWindowLongA( g_hwndTestDlgBut1, GWL_STYLE)) & BS_DEFPUSHBUTTON),
-                        "Button1 style not set to BS_DEFPUSHBUTTON\n" );
-
-                ok ( !((GetWindowLongA( g_hwndTestDlgBut2, GWL_STYLE)) & BS_DEFPUSHBUTTON),
-                        "Button2's style not changed to BS_PUSHBUTTON\n" );
-        }
+    /* Check whether the default button ID got changed by sending message "WM_NEXTDLGCTL" */
+    dwVal = DefDlgProcA(g_hwndTestDlg, DM_GETDEFID, 0, 0);
+    ok(IDCANCEL == (LOWORD(dwVal)), "WM_NEXTDLGCTL changed default button\n");
 
 
-        /*
-         * Move focus to Button2 using "WM_NEXTDLGCTL"
-         */
-        DefDlgProcA( g_hwndTestDlg, WM_NEXTDLGCTL, 0, 0 );
-        ok ((GetFocus() == g_hwndTestDlgBut2), "Focus didn't move to second button\n");
+    /*
+     * Check whether the style of the button which got the focus, changed to BS_DEFPUSHBUTTON and
+     * the style of default button changed to BS_PUSHBUTTON.
+     */
+    ok(get_button_style(g_hwndTestDlgBut1) == BS_DEFPUSHBUTTON, "Button1's style not set to BS_DEFPUSHBUTTON");
+    ok(get_button_style(g_hwndTestDlgBut2) == BS_PUSHBUTTON, "Button2's style not set to BS_PUSHBUTTON");
 
 
-        /*
-         * Check whether the default button ID got changed by sending message "WM_NEXTDLGCTL"
-         */
-        dwVal = DefDlgProcA(g_hwndTestDlg, DM_GETDEFID, 0, 0);
-        ok ( IDCANCEL == (LOWORD(dwVal)), "WM_NEXTDLGCTL changed default button\n");
+    /* Move focus to Button2 using "WM_NEXTDLGCTL" */
+    DefDlgProcA(g_hwndTestDlg, WM_NEXTDLGCTL, 0, 0);
+    ok((GetFocus() == g_hwndTestDlgBut2), "Focus didn't move to second button\n");
 
 
-        /*
-         * Check whether the style of the button which got the focus, changed to BS_DEFPUSHBUTTON and
-         * the style of button which lost the focus changed to BS_PUSHBUTTON.
-         */
-        if ( IDCANCEL == (LOWORD(dwVal)) )
-        {
-                ok ( ((GetWindowLongA( g_hwndTestDlgBut2, GWL_STYLE)) & BS_DEFPUSHBUTTON),
-                        "Button2 style not set to BS_DEFPUSHBUTTON\n" );
+    /* Check whether the default button ID got changed by sending message "WM_NEXTDLGCTL" */
+    dwVal = DefDlgProcA(g_hwndTestDlg, DM_GETDEFID, 0, 0);
+    ok(IDCANCEL == (LOWORD(dwVal)), "WM_NEXTDLGCTL changed default button\n");
 
 
-                ok ( !((GetWindowLongA( g_hwndTestDlgBut1, GWL_STYLE)) & BS_DEFPUSHBUTTON),
-                        "Button1's style not changed to BS_PUSHBUTTON\n" );
-        }
+    /*
+     * Check whether the style of the button which got the focus, changed to BS_DEFPUSHBUTTON and
+     * the style of button which lost the focus changed to BS_PUSHBUTTON.
+     */
+    ok(get_button_style(g_hwndTestDlgBut1) == BS_PUSHBUTTON, "Button1's style not set to BS_PUSHBUTTON");
+    ok(get_button_style(g_hwndTestDlgBut2) == BS_DEFPUSHBUTTON, "Button2's style not set to BS_DEFPUSHBUTTON");
 
 
-        /*
-         * Move focus to Edit control using "WM_NEXTDLGCTL"
-         */
-        DefDlgProcA( g_hwndTestDlg, WM_NEXTDLGCTL, 0, 0 );
-        ok ((GetFocus() == g_hwndTestDlgEdit), "Focus didn't move to Edit control\n");
+    /* Move focus to Edit control using "WM_NEXTDLGCTL" */
+    DefDlgProcA(g_hwndTestDlg, WM_NEXTDLGCTL, 0, 0);
+    ok((GetFocus() == g_hwndTestDlgEdit), "Focus didn't move to Edit control\n");
 
 
-        /*
-         * Check whether the default button ID got changed by sending message "WM_NEXTDLGCTL"
-         */
-        dwVal = DefDlgProcA(g_hwndTestDlg, DM_GETDEFID, 0, 0);
-        ok ( IDCANCEL == (LOWORD(dwVal)), "WM_NEXTDLGCTL changed default button\n");
-    }
+    /* Check whether the default button ID got changed by sending message "WM_NEXTDLGCTL" */
+    dwVal = DefDlgProcA(g_hwndTestDlg, DM_GETDEFID, 0, 0);
+    ok(IDCANCEL == (LOWORD(dwVal)), "WM_NEXTDLGCTL changed default button\n");
 
     /* test nested default buttons */
 
 
     /* test nested default buttons */
 
@@ -812,6 +794,34 @@ static void test_IsDialogMessage(void)
     ok (!IsDialogMessageA(msg.hwnd, &msg), "expected failure\n");
 
     UnhookWindowsHookEx(hook);
     ok (!IsDialogMessageA(msg.hwnd, &msg), "expected failure\n");
 
     UnhookWindowsHookEx(hook);
+    DestroyWindow(g_hwndMain);
+
+    g_hwndMain = CreateWindowA("IsDialogMessageWindowClass", "IsDialogMessageWindowClass", WS_OVERLAPPEDWINDOW,
+                               CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, g_hinst, 0);
+    SetFocus(g_hwndButton1);
+    g_button1Clicked = FALSE;
+    FormEnterMsg(&msg, g_hwndButton1);
+    ok(IsDialogMessageA(g_hwndMain, &msg), "Did not handle the ENTER\n");
+    ok(g_button1Clicked, "Did not receive button 1 click notification\n");
+
+    g_button1Clicked = FALSE;
+    FormEnterMsg(&msg, g_hwndMain);
+    ok(IsDialogMessageA(g_hwndMain, &msg), "Did not handle the ENTER\n");
+    ok(g_button1Clicked, "Did not receive button 1 click notification\n");
+
+    g_button1Clicked = FALSE;
+    FormEnterMsg(&msg, g_hwndButton2);
+    ok(IsDialogMessageA(g_hwndMain, &msg), "Did not handle the ENTER\n");
+    ok(g_button1Clicked, "Did not receive button 1 click notification\n");
+
+    /* Button with id larger than 0xFFFF should also work */
+    g_button1Clicked = FALSE;
+    FormEnterMsg(&msg, g_hwndMain);
+    SetWindowLongPtrW(g_hwndButton1, GWLP_ID, 0x1FFFF);
+    ok(IsDialogMessageA(g_hwndMain, &msg), "Did not handle the ENTER\n");
+    ok(g_button1Clicked, "Did not receive button 1 click notification\n");
+
+    DestroyWindow(g_hwndMain);
 }
 
 
 }
 
 
@@ -876,6 +886,56 @@ static INT_PTR CALLBACK focusDlgWinProc (HWND hDlg, UINT uiMsg, WPARAM wParam,
     return FALSE;
 }
 
     return FALSE;
 }
 
+static INT_PTR CALLBACK EmptyProcUserTemplate(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    switch(uMsg) {
+    case WM_INITDIALOG:
+        return TRUE;
+    }
+    return FALSE;
+}
+
+static INT_PTR CALLBACK focusChildDlgWinProc (HWND hwnd, UINT uiMsg, WPARAM wParam,
+        LPARAM lParam)
+{
+    static HWND hChildDlg;
+
+    switch (uiMsg)
+    {
+    case WM_INITDIALOG:
+    {
+        RECT rectHwnd;
+        struct  {
+            DLGTEMPLATE tmplate;
+            WORD menu,class,title;
+        } temp;
+
+        SetFocus( GetDlgItem(hwnd, 200) );
+
+        GetClientRect(hwnd,&rectHwnd);
+        temp.tmplate.style = WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | DS_CONTROL | DS_3DLOOK;
+        temp.tmplate.dwExtendedStyle = 0;
+        temp.tmplate.cdit = 0;
+        temp.tmplate.x = 0;
+        temp.tmplate.y = 0;
+        temp.tmplate.cx = 0;
+        temp.tmplate.cy = 0;
+        temp.menu = temp.class = temp.title = 0;
+
+        hChildDlg = CreateDialogIndirectParamA(g_hinst, &temp.tmplate,
+                  hwnd, (DLGPROC)EmptyProcUserTemplate, 0);
+        ok(hChildDlg != 0, "Failed to create test dialog.\n");
+
+        return FALSE;
+    }
+    case WM_CLOSE:
+        DestroyWindow(hChildDlg);
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
 /* Helper for InitialFocusTest */
 static const char * GetHwndString(HWND hw)
 {
 /* Helper for InitialFocusTest */
 static const char * GetHwndString(HWND hw)
 {
@@ -1062,6 +1122,29 @@ static void test_focus(void)
 
         DestroyWindow(hDlg);
     }
 
         DestroyWindow(hDlg);
     }
+
+    /* Test 6:
+     * Select textbox's text on creation when WM_INITDIALOG creates a child dialog. */
+    {
+        HWND hDlg;
+        HRSRC hResource;
+        HANDLE hTemplate;
+        DLGTEMPLATE* pTemplate;
+        HWND edit;
+
+        hResource = FindResourceA(g_hinst,"FOCUS_TEST_DIALOG_3", (LPCSTR)RT_DIALOG);
+        hTemplate = LoadResource(g_hinst, hResource);
+        pTemplate = LockResource(hTemplate);
+
+        hDlg = CreateDialogIndirectParamA(g_hinst, pTemplate, NULL, focusChildDlgWinProc, 0);
+        ok(hDlg != 0, "Failed to create test dialog.\n");
+        edit = GetDlgItem(hDlg, 200);
+
+        ok(GetFocus() == edit, "Focus not set to edit, focus=%p, dialog=%p, edit=%p\n",
+                GetFocus(), hDlg, edit);
+
+        DestroyWindow(hDlg);
+    }
 }
 
 static void test_GetDlgItemText(void)
 }
 
 static void test_GetDlgItemText(void)
@@ -1070,16 +1153,54 @@ static void test_GetDlgItemText(void)
     BOOL ret;
 
     strcpy(string, "Overwrite Me");
     BOOL ret;
 
     strcpy(string, "Overwrite Me");
-    ret = GetDlgItemTextA(NULL, 0, string, sizeof(string)/sizeof(string[0]));
+    ret = GetDlgItemTextA(NULL, 0, string, ARRAY_SIZE(string));
     ok(!ret, "GetDlgItemText(NULL) shouldn't have succeeded\n");
 
     ok(string[0] == '\0' || broken(!strcmp(string, "Overwrite Me")),
        "string retrieved using GetDlgItemText should have been NULL terminated\n");
 }
 
     ok(!ret, "GetDlgItemText(NULL) shouldn't have succeeded\n");
 
     ok(string[0] == '\0' || broken(!strcmp(string, "Overwrite Me")),
        "string retrieved using GetDlgItemText should have been NULL terminated\n");
 }
 
+static INT_PTR CALLBACK getdlgitem_test_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+    if (msg == WM_INITDIALOG)
+    {
+        char text[64];
+        LONG_PTR val;
+        HWND hwnd;
+        BOOL ret;
+
+        hwnd = GetDlgItem(hdlg, -1);
+        ok(hwnd != NULL, "Expected dialog item.\n");
+
+        *text = 0;
+        ret = GetDlgItemTextA(hdlg, -1, text, ARRAY_SIZE(text));
+        ok(ret && !strcmp(text, "Text1"), "Unexpected item text.\n");
+
+        val = GetWindowLongA(hwnd, GWLP_ID);
+        ok(val == -1, "Unexpected id.\n");
+
+        val = GetWindowLongPtrA(hwnd, GWLP_ID);
+        ok(val == -1, "Unexpected id %ld.\n", val);
+
+        hwnd = GetDlgItem(hdlg, -2);
+        ok(hwnd != NULL, "Expected dialog item.\n");
+
+        val = GetWindowLongA(hwnd, GWLP_ID);
+        ok(val == -2, "Unexpected id.\n");
+
+        val = GetWindowLongPtrA(hwnd, GWLP_ID);
+        ok(val == -2, "Unexpected id %ld.\n", val);
+
+        EndDialog(hdlg, 0xdead);
+    }
+
+    return FALSE;
+}
+
 static void test_GetDlgItem(void)
 {
     HWND hwnd, child1, child2, hwnd2;
 static void test_GetDlgItem(void)
 {
     HWND hwnd, child1, child2, hwnd2;
+    INT_PTR retval;
     BOOL ret;
 
     hwnd = CreateWindowA("button", "parent", WS_VISIBLE, 0, 0, 100, 100, NULL, 0, g_hinst, NULL);
     BOOL ret;
 
     hwnd = CreateWindowA("button", "parent", WS_VISIBLE, 0, 0, 100, 100, NULL, 0, g_hinst, NULL);
@@ -1126,6 +1247,9 @@ static void test_GetDlgItem(void)
     DestroyWindow(child1);
     DestroyWindow(child2);
     DestroyWindow(hwnd);
     DestroyWindow(child1);
     DestroyWindow(child2);
     DestroyWindow(hwnd);
+
+    retval = DialogBoxParamA(g_hinst, "GETDLGITEM_TEST_DIALOG", NULL, getdlgitem_test_dialog_proc, 0);
+    ok(retval == 0xdead, "Unexpected return value.\n");
 }
 
 static INT_PTR CALLBACK DestroyDlgWinProc (HWND hDlg, UINT uiMsg,
 }
 
 static INT_PTR CALLBACK DestroyDlgWinProc (HWND hDlg, UINT uiMsg,
@@ -1486,7 +1610,7 @@ static INT_PTR CALLBACK test_aw_conversion_dlgproc(HWND hdlg, UINT msg, WPARAM w
            (BYTE)buff[0], (BYTE)buff[1], len);
 
         memset(buffW, 0xff, sizeof(buffW));
            (BYTE)buff[0], (BYTE)buff[1], len);
 
         memset(buffW, 0xff, sizeof(buffW));
-        len = GetWindowTextW(hdlg, buffW, sizeof(buffW)/sizeof(buffW[0]));
+        len = GetWindowTextW(hdlg, buffW, ARRAY_SIZE(buffW));
         ok(buffW[0] == 'W' && buffW[1] == 0xffff && len == 0, "Unexpected window text %#x, %#x, len %d\n",
             buffW[0], buffW[1], len);
 
         ok(buffW[0] == 'W' && buffW[1] == 0xffff && len == 0, "Unexpected window text %#x, %#x, len %d\n",
             buffW[0], buffW[1], len);
 
@@ -1592,7 +1716,7 @@ static INT_PTR CALLBACK test_aw_conversion_dlgproc2(HWND hdlg, UINT msg, WPARAM
         ok(!strcmp(buff, testtext) && len == 0, "Unexpected window text %s, len %d\n", buff, len);
 
         memset(buffW, 0xff, sizeof(buffW));
         ok(!strcmp(buff, testtext) && len == 0, "Unexpected window text %s, len %d\n", buff, len);
 
         memset(buffW, 0xff, sizeof(buffW));
-        len = GetWindowTextW(hdlg, buffW, sizeof(buffW)/sizeof(buffW[0]));
+        len = GetWindowTextW(hdlg, buffW, ARRAY_SIZE(buffW));
         ok(buffW[0] == 0 && buffW[1] == 0xffff && len == 0, "Unexpected window text %#x, %#x, len %d\n",
             buffW[0], buffW[1], len);
 
         ok(buffW[0] == 0 && buffW[1] == 0xffff && len == 0, "Unexpected window text %#x, %#x, len %d\n",
             buffW[0], buffW[1], len);
 
@@ -1869,6 +1993,187 @@ static void test_MessageBoxFontTest(void)
     DestroyWindow(hDlg);
 }
 
     DestroyWindow(hDlg);
 }
 
+static const char msgbox_title[] = "%5!z9ZXw*ia;57n/FGl.bCH,Su\"mfKN;foCqAU\'j6AmoJgAc_D:Z0A\'E6PF_O/w";
+static WCHAR expectedOK[] =
+{
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f',
+'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P',
+'F','_','O','/','w','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'M','e','s','s','a','g','e','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'O','K',' ',' ',' ','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0
+};
+static WCHAR expectedOkCancel[] =
+{
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f',
+'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P',
+'F','_','O','/','w','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'M','e','s','s','a','g','e','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'O','K',' ',' ',' ','C','a','n','c','e','l',' ',' ',' ','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0
+};
+static WCHAR expectedAbortRetryIgnore[] =
+{
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f',
+'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P',
+'F','_','O','/','w','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'M','e','s','s','a','g','e','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'A','b','o','r','t',' ',' ',' ','R','e','t','r','y',' ',' ',' ','I','g','n','o','r','e',' ',' ',' ','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0
+};
+
+static WCHAR expectedYesNo[] =
+{
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f',
+'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P',
+'F','_','O','/','w','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'M','e','s','s','a','g','e','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'Y','e','s',' ',' ',' ','N','o',' ',' ',' ','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0
+};
+static WCHAR expectedYesNoCancel[] =
+{
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f',
+'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P',
+'F','_','O','/','w','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'M','e','s','s','a','g','e','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'Y','e','s',' ',' ',' ','N','o',' ',' ',' ','C','a','n','c','e','l',' ',' ',' ','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0
+};
+static WCHAR expectedRetryCancel[] =
+{
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f',
+'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P',
+'F','_','O','/','w','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'M','e','s','s','a','g','e','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'R','e','t','r','y',' ',' ',' ','C','a','n','c','e','l',' ',' ',' ','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0
+};
+static WCHAR expectedCancelTryContinue[] =
+{
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f',
+'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P',
+'F','_','O','/','w','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'M','e','s','s','a','g','e','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
+'C','a','n','c','e','l',' ',' ',' ','T','r','y',' ','A','g','a','i','n',' ',' ',' ','C','o','n','t','i','n','u','e',' ',' ',' ','\r','\n',
+'-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0
+};
+
+BOOL non_english = FALSE;
+
+DWORD WINAPI WorkerThread(void *param)
+{
+    WCHAR *expected = param;
+    char windowTitle[sizeof(msgbox_title)];
+    HWND hwndMbox;
+    BOOL succeeded = FALSE;
+
+    Sleep(200);
+
+    hwndMbox = GetForegroundWindow();
+
+    /* Find the Window, if it doesn't have focus */
+    if (!(IsWindow(hwndMbox) &&
+        GetWindowTextA(hwndMbox, windowTitle, sizeof(msgbox_title)) &&
+        lstrcmpA(msgbox_title, windowTitle) == 0))
+    {
+        hwndMbox = FindWindowA(NULL, msgbox_title);
+
+        if (!IsWindow(hwndMbox))
+            goto cleanup;
+    }
+
+    SendMessageA(hwndMbox, WM_COPY, 0, 0);
+
+    if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL))
+    {
+        HANDLE textHandle = GetClipboardData(CF_UNICODETEXT);
+        WCHAR *text = GlobalLock(textHandle);
+
+        if (text != NULL)
+        {
+            if(non_english)
+                ok(lstrlenW(text) > 0, "Empty string on clipboard\n");
+            else
+            {
+                succeeded = lstrcmpW(expected, text) == 0;
+                if(!succeeded)
+                {
+                    ok(0, "%s\n", wine_dbgstr_w(text));
+                    ok(0, "%s\n", wine_dbgstr_w(expected));
+                }
+            }
+
+            GlobalUnlock(textHandle);
+        }
+        else
+            ok(0, "No text on clipboard.\n");
+
+        CloseClipboard();
+
+    }
+    else
+        trace("Clipboard error\n");
+
+    PostMessageA(hwndMbox, WM_COMMAND, IDIGNORE, 0); /* For MB_ABORTRETRYIGNORE dialog. */
+    PostMessageA(hwndMbox, WM_CLOSE, 0, 0);
+
+cleanup:
+    ok(succeeded || non_english, "Failed to get string.\n");
+
+    return 0;
+}
+
+static void test_MessageBox_WM_COPY_Test(void)
+{
+    DWORD tid = 0;
+
+    non_english = (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH);
+    trace("non_english %d\n", non_english);
+
+    CreateThread(NULL, 0, WorkerThread, &expectedOK, 0, &tid);
+    MessageBoxA(NULL, "Message", msgbox_title, MB_OK);
+
+    CreateThread(NULL, 0, WorkerThread, &expectedOkCancel, 0, &tid);
+    MessageBoxA(NULL, "Message", msgbox_title, MB_OKCANCEL);
+
+    CreateThread(NULL, 0, WorkerThread, &expectedAbortRetryIgnore, 0, &tid);
+    MessageBoxA(NULL, "Message", msgbox_title, MB_ABORTRETRYIGNORE);
+
+    CreateThread(NULL, 0, WorkerThread, &expectedYesNo, 0, &tid);
+    MessageBoxA(NULL, "Message", msgbox_title, MB_YESNO);
+
+    CreateThread(NULL, 0, WorkerThread, &expectedYesNoCancel, 0, &tid);
+    MessageBoxA(NULL, "Message", msgbox_title, MB_YESNOCANCEL);
+
+    CreateThread(NULL, 0, WorkerThread, &expectedRetryCancel, 0, &tid);
+    MessageBoxA(NULL, "Message", msgbox_title, MB_RETRYCANCEL);
+
+    CreateThread(NULL, 0, WorkerThread, &expectedCancelTryContinue, 0, &tid);
+    MessageBoxA(NULL, "Message", msgbox_title, MB_CANCELTRYCONTINUE);
+}
+
 static void test_SaveRestoreFocus(void)
 {
     HWND hDlg;
 static void test_SaveRestoreFocus(void)
 {
     HWND hDlg;
@@ -2178,4 +2483,5 @@ START_TEST(dialog)
     test_SaveRestoreFocus();
     test_timer_message();
     test_MessageBox();
     test_SaveRestoreFocus();
     test_timer_message();
     test_MessageBox();
+    test_MessageBox_WM_COPY_Test();
 }
 }