1 /* Unit test suite for the dialog functions.
2  *
3  * Copyright 2004 Bill Medland
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  *
19  *
20  *
21  * This test suite currently works by building a quite complex hierarchy of
22  * objects in a variety of styles and then performs a limited number of tests
23  * for the previous and next dialog group or tab items.
24  *
25  * The test specifically does not test all possibilities at this time since
26  * there are several cases where the Windows behaviour is rather strange and
27  * significant work would be required to get the Wine code to duplicate the
28  * strangeness, especially since most are in situations that would not
29  * normally be met.
30  */
31 
32 #ifndef __REACTOS__
33 #define WINVER 0x0600 /* For NONCLIENTMETRICS with padding */
34 #endif
35 
36 #include <assert.h>
37 #include <stdio.h>
38 #include <stdarg.h>
39 
40 #include "wine/test.h"
41 #include "windef.h"
42 #include "winbase.h"
43 #include "wingdi.h"
44 #include "winuser.h"
45 #include "winnls.h"
46 
47 #define MAXHWNDS 1024
48 static HWND hwnd [MAXHWNDS];
49 static unsigned int numwnds=1; /* 0 is reserved for null */
50 
51 /* Global handles */
52 static HINSTANCE g_hinst;                          /* This application's HINSTANCE */
53 static HWND g_hwndMain, g_hwndButton1, g_hwndButton2, g_hwndButtonCancel;
54 static HWND g_hwndTestDlg, g_hwndTestDlgBut1, g_hwndTestDlgBut2, g_hwndTestDlgEdit;
55 static HWND g_hwndInitialFocusT1, g_hwndInitialFocusT2, g_hwndInitialFocusGroupBox;
56 
57 static LONG g_styleInitialFocusT1, g_styleInitialFocusT2;
58 static BOOL g_bInitialFocusInitDlgResult, g_bReceivedCommand;
59 
60 static BOOL g_terminated;
61 static BOOL g_button1Clicked;
62 
63 typedef struct {
64     INT_PTR id;
65     int parent;
66     DWORD style;
67     DWORD exstyle;
68 } h_entry;
69 
70 static const h_entry hierarchy [] = {
71     /* 0 is reserved for the null window */
72     {  1,  0, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE},
73     { 20,  1,  WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
74     {  2,  1,  WS_CHILD | WS_VISIBLE, WS_EX_CONTROLPARENT},
75     { 60,  2,  WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0},
76     /* What happens with groups when the parent is disabled */
77     {  8,  2,  WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, WS_EX_CONTROLPARENT},
78     { 85,  8,  WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_GROUP, 0},
79     {  9,  8,  WS_CHILD, WS_EX_CONTROLPARENT},
80     { 86,  9,  WS_CHILD | WS_VISIBLE, 0},
81     { 87,  9,  WS_CHILD | WS_VISIBLE, 0},
82     { 31,  8,  WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
83     { 10,  2,  WS_CHILD | WS_VISIBLE, WS_EX_CONTROLPARENT},
84     { 88, 10,  WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
85     { 11, 10,  WS_CHILD, WS_EX_CONTROLPARENT},
86     { 89, 11,  WS_CHILD | WS_VISIBLE, 0},
87     { 32, 11,  WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
88     { 90, 11,  WS_CHILD | WS_VISIBLE, 0},
89     { 33, 10,  WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
90     { 21,  2,  WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
91     { 61,  2,  WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0},
92     {  3,  1,  WS_CHILD | WS_VISIBLE | DS_CONTROL, 0},
93     { 22,  3,  WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
94     { 62,  3,  WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0},
95     {  7,  3,  WS_CHILD | WS_VISIBLE, WS_EX_CONTROLPARENT},
96     {  4,  7,  WS_CHILD | WS_VISIBLE | DS_CONTROL, 0},
97     { 83,  4,  WS_CHILD | WS_VISIBLE, 0},
98     {  5,  4,  WS_CHILD | WS_VISIBLE | DS_CONTROL, 0},
99     /* A couple of controls around the main dialog */
100     { 29,  5,  WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
101     { 81,  5,  WS_CHILD | WS_VISIBLE, 0},
102     /* The main dialog with lots of controls */
103     {  6,  5,  WS_CHILD | WS_VISIBLE, WS_EX_CONTROLPARENT},
104         /* At the start of a dialog */
105         /* Disabled controls are skipped */
106     { 63,  6,  WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, 0},
107         /* Invisible controls are skipped */
108     { 64,  6,  WS_CHILD | WS_TABSTOP, 0},
109         /* Invisible disabled controls are skipped */
110     { 65,  6,  WS_CHILD | WS_DISABLED | WS_TABSTOP, 0},
111         /* Non-tabstop controls are skipped for tabs but not for groups */
112     { 66,  6,  WS_CHILD | WS_VISIBLE, 0},
113         /* End of first group, with no tabstops in it */
114     { 23,  6,  WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
115         /* At last a tabstop */
116     { 67,  6,  WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0},
117     /* A group that is totally disabled or invisible */
118     { 24,  6,  WS_CHILD | WS_DISABLED | WS_GROUP, 0},
119     { 68,  6,  WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, 0},
120     { 69,  6,  WS_CHILD | WS_TABSTOP, 0},
121     /* A valid group in the middle of the dialog (not the first nor last group*/
122     { 25,  6,  WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
123         /* A non-tabstop item will be skipped for tabs */
124     { 70,  6,  WS_CHILD | WS_VISIBLE, 0},
125         /* A disabled item will be skipped for tabs and groups */
126     { 71,  6,  WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, 0},
127         /* A valid item will be found for tabs and groups */
128     { 72,  6,  WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0},
129         /* A disabled item to skip when looking for the next group item */
130     { 73,  6,  WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, 0},
131     /* The next group begins with an enabled visible label */
132     { 26,  6,  WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
133     { 74,  6,  WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0},
134     { 75,  6,  WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0},
135     /* That group is terminated by a disabled label */
136     { 27,  6,  WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_GROUP, 0},
137     { 76,  6,  WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0},
138     { 77,  6,  WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0},
139     /* That group is terminated by an invisible label */
140     { 28,  6,  WS_CHILD | WS_GROUP, 0},
141     /* The end of the dialog with item for loop and recursion testing */
142     { 78,  6,  WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0},
143     /* No tabstop so skipped for prev tab, but found for prev group */
144     { 79,  6,  WS_CHILD | WS_VISIBLE, 0},
145     { 80,  6,  WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_TABSTOP, 0},
146     /* A couple of controls after the main dialog */
147     { 82,  5,  WS_CHILD | WS_VISIBLE, 0},
148     { 30,  5,  WS_CHILD | WS_VISIBLE | WS_GROUP, 0},
149     /* And around them */
150     { 84,  4,  WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0},
151     {0, 0, 0, 0}
152 };
153 
154 static DWORD get_button_style(HWND button)
155 {
156     return GetWindowLongW(button, GWL_STYLE) & BS_TYPEMASK;
157 }
158 
159 static BOOL CreateWindows (HINSTANCE hinst)
160 {
161     const h_entry *p = hierarchy;
162 
163     while (p->id != 0)
164     {
165         DWORD style, exstyle;
166         char ctrlname[16];
167 
168         /* Basically assert that the hierarchy is valid and track the
169          * maximum control number
170          */
171         if (p->id >= numwnds)
172         {
173             if (p->id >=  ARRAY_SIZE(hwnd))
174             {
175                 trace ("Control %ld is out of range\n", p->id);
176                 return FALSE;
177             }
178             else
179                 numwnds = p->id+1;
180         }
181         if (p->id <= 0)
182         {
183             trace ("Control %ld is out of range\n", p->id);
184             return FALSE;
185         }
186         if (hwnd[p->id] != 0)
187         {
188             trace ("Control %ld is used more than once\n", p->id);
189             return FALSE;
190         }
191 
192         /* Create the control */
193         sprintf (ctrlname, "ctrl%4.4ld", p->id);
194         hwnd[p->id] = CreateWindowExA(p->exstyle, p->parent ? "static" : "GetNextDlgItemWindowClass", ctrlname, p->style, 10, 10, 10, 10, hwnd[p->parent], p->parent ? (HMENU) (2000 + p->id) : 0, hinst, 0);
195         if (!hwnd[p->id])
196         {
197             trace ("Failed to create control %ld\n", p->id);
198             return FALSE;
199         }
200 
201         /* Check that the styles are as we specified (except the main one
202          * which is quite frequently messed up).  If this keeps breaking then
203          * we could mask out the bits that don't concern us.
204          */
205         if (p->parent)
206         {
207             style = GetWindowLongA(hwnd[p->id], GWL_STYLE);
208             exstyle = GetWindowLongA(hwnd[p->id], GWL_EXSTYLE);
209             if (style != p->style || exstyle != p->exstyle)
210             {
211                 trace ("Style mismatch at %ld: %8.8x %8.8x cf %8.8x %8.8x\n", p->id, style, exstyle, p->style, p->exstyle);
212             }
213         }
214         p++;
215     }
216 
217     return TRUE;
218 }
219 
220 /* Form the lParam of a WM_KEYDOWN message */
221 static DWORD KeyDownData (int repeat, int scancode, int extended, int wasdown)
222 {
223     return ((repeat & 0x0000FFFF) | ((scancode & 0x00FF) << 16) |
224             (extended ? 0x01000000 : 0) | (wasdown ? 0x40000000 : 0));
225 }
226 
227 /* Form a WM_KEYDOWN VK_TAB message to the specified window */
228 static void FormTabMsg (MSG *pMsg, HWND hwnd)
229 {
230     pMsg->hwnd = hwnd;
231     pMsg->message = WM_KEYDOWN;
232     pMsg->wParam = VK_TAB;
233     pMsg->lParam = KeyDownData (1, 0x0F, 0, 0);
234     /* pMsg->time is not set.  It shouldn't be needed */
235     /* pMsg->pt is ignored */
236 }
237 
238 /* Form a WM_KEYDOWN VK_RETURN message to the specified window */
239 static void FormEnterMsg (MSG *pMsg, HWND hwnd)
240 {
241     pMsg->hwnd = hwnd;
242     pMsg->message = WM_KEYDOWN;
243     pMsg->wParam = VK_RETURN;
244     pMsg->lParam = KeyDownData (1, 0x1C, 0, 0);
245     /* pMsg->time is not set.  It shouldn't be needed */
246     /* pMsg->pt is ignored */
247 }
248 
249 /***********************************************************************
250  *
251  * The actual tests
252  */
253 
254 typedef struct
255 {
256     int isok; /* or is it todo */
257     int test;
258     int dlg;
259     int ctl;
260     int tab;
261     int prev;
262     int res;
263 } test_record;
264 
265 static int id (HWND h)
266 {
267     unsigned int i;
268     for (i = 0; i < numwnds; i++)
269         if (hwnd[i] == h)
270             return i;
271     return -1;
272 }
273 
274 /* Tests
275  *
276  * Tests 1-8 test the hCtl argument of null or the dialog itself.
277  *
278  *   1. Prev Group of null is null
279  *   2. Prev Tab of null is null
280  *   3. Prev Group of hDlg in hDlg is null
281  *   4. Prev Tab of hDlg in hDlg is null
282  *   5. Next Group of null is first visible enabled child
283  *      Check it skips invisible, disabled and both.
284  *   6. Next Tab of null is first visible enabled tabstop
285  *      Check it skips invisible, disabled, nontabstop, and in combination.
286  *   7. Next Group of hDlg in hDlg is as of null
287  *   8. Next Tab of hDlg in hDlg is as of null
288  *
289  * Tests 9-14 test descent
290  *
291  *   9. DS_CONTROL does not result in descending the hierarchy for Tab Next
292  *  10. DS_CONTROL does not result in descending the hierarchy for Group Next
293  *  11. WS_EX_CONTROLPARENT results in descending the hierarchy for Tab Next
294  *  12. WS_EX_CONTROLPARENT results in descending the hierarchy for Group Next
295  *  13. WS_EX_CONTROLPARENT results in descending the hierarchy for Tab Prev
296  *  14. WS_EX_CONTROLPARENT results in descending the hierarchy for Group Prev
297  *
298  * Tests 15-24 are the basic Prev/Next Group tests
299  *
300  *  15. Next Group of a visible enabled non-group control is the next visible
301  *      enabled non-group control, if there is one before the next group
302  *  16. Next Group of a visible enabled non-group control wraps around to the
303  *      beginning of the group on finding a control that starts another group.
304  *      Note that the group is in the middle of the dialog.
305  *  17. As 16 except note that the next group is started with a disabled
306  *      visible control.
307  *  18. As 16 except note that the next group is started with an invisible
308  *      enabled control.
309  *  19. Next Group wraps around the controls of the dialog
310  *  20. Next Group is the same even if the initial control is disabled.
311  *  21. Next Group is the same even if the initial control is invisible.
312  *  22. Next Group is the same even if the initial control has the group style
313  *  23. Next Group returns the initial control if there is no visible enabled
314  *      control in the group. (Initial control disabled and not group style).
315  *  24. Prev version of test 16.
316  *      Prev Group of a visible enabled non-group control wraps around to the
317  *      beginning of the group on finding a control that starts the group.
318  *      Note that the group is in the middle of the dialog.
319  *
320  * In tests 25 to 28 the control is sitting under dialogs which do not have
321  * the WS_EX_CONTROLPARENT style and so cannot be reached from the top of
322  * the dialog.
323  *
324  *  25. Next Group of an inaccessible control is as if it were accessible
325  *  26. Prev Group of an inaccessible control begins searching at the highest
326  *      level ancestor that did not permit recursion down the hierarchy
327  *  27. Next Tab of an inaccessible control is as if it were accessible
328  *  28. Prev Tab of an inaccessible control begins searching at the highest
329  *      level ancestor that did not permit recursion down the hierarchy.
330  *
331  * Tests 29- are the basic Tab tests
332  *
333  *  29. Next Tab of a control is the next visible enabled control with the
334  *      Tabstop style (N.B. skips disabled, invisible and non-tabstop)
335  *  30. Prev Tab of a control is the previous visible enabled control with the
336  *      Tabstop style (N.B. skips disabled, invisible and non-tabstop)
337  *  31. Next Tab test with at least two layers of descent and finding the
338  *      result not at the first control.
339  *  32. Next Tab test with at least two layers of descent with the descent and
340  *      control at the start of each level.
341  *  33. Prev Tab test with at least two layers of descent and finding the
342  *      result not at the last control.
343  *  34. Prev Tab test with at least two layers of descent with the descent and
344  *      control at the end of each level.
345  *
346  *  35. Passing NULL may result in the first child being the one returned.
347  *      (group test)
348  *  36. Passing NULL may result in the first child being the one returned.
349  *      (tab test)
350  */
351 
352 static void test_GetNextDlgItem(void)
353 {
354     static test_record test [] =
355     {
356         /* isok test dlg  ctl  tab  prev res  */
357 
358         {   1,   1,    6,   0,   0,   1,   0},
359         {   1,   2,    6,   0,   1,   1,   0},
360         {   1,   3,    6,   6,   0,   1,   0},
361         {   1,   4,    6,   6,   1,   1,   0},
362         {   1,   5,    6,   0,   0,   0,  66},
363         {   1,   6,    6,   0,   1,   0,  67},
364         {   1,   7,    6,   6,   0,   0,  66},
365         {   1,   8,    6,   6,   1,   0,  67},
366 
367         {   1,   9,    4,  83,   1,   0,  84},
368         {   1,  10,    4,  83,   0,   0,   5},
369         {   1,  11,    5,  81,   1,   0,  67},
370         {   1,  12,    5,  81,   0,   0,  66},
371         {   1,  13,    5,  82,   1,   1,  78},
372 
373         {   1,  14,    5,  82,   0,   1,  79},
374         {   1,  15,    6,  70,   0,   0,  72},
375         {   1,  16,    6,  72,   0,   0,  25},
376         {   1,  17,    6,  75,   0,   0,  26},
377         {   1,  18,    6,  77,   0,   0,  76},
378         {   1,  19,    6,  79,   0,   0,  66},
379         {   1,  20,    6,  71,   0,   0,  72},
380         {   1,  21,    6,  64,   0,   0,  66},
381 
382         {   1,  22,    6,  25,   0,   0,  70},
383         {   1,  23,    6,  68,   0,   0,  68},
384         {   1,  24,    6,  25,   0,   1,  72},
385         {   1,  25,    1,  70,   0,   0,  72},
386         /*{   0,  26,    1,  70,   0,   1,   3}, Crashes Win95*/
387         {   1,  27,    1,  70,   1,   0,  72},
388         /*{   0,  28,    1,  70,   1,   1,  61}, Crashes Win95*/
389 
390         {   1,  29,    6,  67,   1,   0,  72},
391         {   1,  30,    6,  72,   1,   1,  67},
392 
393         {   1,  35,    2,   0,   0,   0,  60},
394         {   1,  36,    2,   0,   1,   0,  60},
395 
396         {   0,   0,    0,   0,   0,   0,   0}  /* End of test */
397     };
398     const test_record *p = test;
399 
400     ok (CreateWindows (g_hinst), "Could not create test windows\n");
401 
402     while (p->dlg)
403     {
404         HWND a;
405         a = (p->tab ? GetNextDlgTabItem : GetNextDlgGroupItem) (hwnd[p->dlg], hwnd[p->ctl], p->prev);
406         todo_wine_if (!p->isok)
407             ok (a == hwnd[p->res], "Test %d: %s %s item of %d in %d was %d instead of %d\n", p->test, p->prev ? "Prev" : "Next", p->tab ? "Tab" : "Group", p->ctl, p->dlg, id(a), p->res);
408         p++;
409     }
410 }
411 
412 /*
413  *  OnMainWindowCreate
414  */
415 static BOOL OnMainWindowCreate(HWND hwnd, LPCREATESTRUCTA lpcs)
416 {
417     g_hwndButton1 = CreateWindowA("button", "Button &1",
418             WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON | BS_TEXT,
419             10, 10, 80, 80, hwnd, (HMENU)100, g_hinst, 0);
420     if (!g_hwndButton1) return FALSE;
421 
422     g_hwndButton2 = CreateWindowA("button", "Button &2",
423             WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_TEXT,
424             110, 10, 80, 80, hwnd, (HMENU)200, g_hinst, 0);
425     if (!g_hwndButton2) return FALSE;
426 
427     g_hwndButtonCancel = CreateWindowA("button", "Cancel",
428             WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | BS_TEXT,
429             210, 10, 80, 80, hwnd, (HMENU)IDCANCEL, g_hinst, 0);
430     if (!g_hwndButtonCancel) return FALSE;
431 
432     return TRUE;
433 }
434 
435 
436 /*
437  *  OnTestDlgCreate
438  */
439 
440 static BOOL OnTestDlgCreate (HWND hwnd, LPCREATESTRUCTA lpcs)
441 {
442     g_hwndTestDlgEdit = CreateWindowExA( WS_EX_LEFT | WS_EX_LTRREADING |
443             WS_EX_RIGHTSCROLLBAR | WS_EX_NOPARENTNOTIFY | WS_EX_CLIENTEDGE,
444             "Edit", "Edit",
445             WS_CHILDWINDOW | WS_VISIBLE | WS_TABSTOP | ES_LEFT | ES_AUTOHSCROLL,
446             16,33,184,24, hwnd, (HMENU)101, g_hinst, 0);
447     if (!g_hwndTestDlgEdit) return FALSE;
448 
449     g_hwndTestDlgBut1 = CreateWindowExA( WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR
450             | WS_EX_NOPARENTNOTIFY,
451             "button", "Button &1",
452             WS_CHILDWINDOW | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | BS_TEXT,
453             204,33,30,24, hwnd, (HMENU)201, g_hinst, 0);
454     if (!g_hwndTestDlgBut1) return FALSE;
455 
456     g_hwndTestDlgBut2 = CreateWindowExA( WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR
457             | WS_EX_NOPARENTNOTIFY, "button",
458             "Button &2",
459             WS_CHILDWINDOW | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON | BS_TEXT,
460             90,102,80,24, hwnd, (HMENU)IDCANCEL, g_hinst, 0);
461     if (!g_hwndTestDlgBut2) return FALSE;
462 
463     return TRUE;
464 }
465 
466 static LRESULT CALLBACK main_window_procA (HWND hwnd, UINT uiMsg, WPARAM wParam,
467         LPARAM lParam)
468 {
469     switch (uiMsg)
470     {
471         /* Add blank case statements for these to ensure we don't use them
472          * by mistake.
473          */
474         case DM_GETDEFID: break;
475         case DM_SETDEFID: break;
476 
477         case WM_CREATE:
478             return (OnMainWindowCreate (hwnd,
479                     (LPCREATESTRUCTA) lParam) ? 0 : (LRESULT) -1);
480         case WM_COMMAND:
481             if (wParam == IDCANCEL)
482             {
483                 g_terminated = TRUE;
484                 return 0;
485             }
486             else if ((wParam == 100 || wParam == 0xFFFF) && lParam)
487             {
488                 g_button1Clicked = TRUE;
489             }
490             break;
491     }
492 
493     return DefWindowProcA (hwnd, uiMsg, wParam, lParam);
494 }
495 
496 static LRESULT CALLBACK disabled_test_proc (HWND hwnd, UINT uiMsg,
497         WPARAM wParam, LPARAM lParam)
498 {
499     switch (uiMsg)
500     {
501         case WM_INITDIALOG:
502         {
503             DWORD dw;
504             HWND hwndOk;
505 
506             dw = SendMessageA(hwnd, DM_GETDEFID, 0, 0);
507             assert(DC_HASDEFID == HIWORD(dw));
508             hwndOk = GetDlgItem(hwnd, LOWORD(dw));
509             assert(hwndOk);
510             EnableWindow(hwndOk, FALSE);
511 
512             PostMessageA(hwnd, WM_KEYDOWN, VK_RETURN, 0);
513             PostMessageA(hwnd, WM_COMMAND, IDCANCEL, 0);
514             break;
515         }
516         case WM_COMMAND:
517             if (wParam == IDOK)
518             {
519                 g_terminated = TRUE;
520                 EndDialog(hwnd, 0);
521                 return 0;
522             }
523             else if (wParam == IDCANCEL)
524             {
525                 EndDialog(hwnd, 0);
526                 return 0;
527             }
528             break;
529     }
530 
531     return DefWindowProcA (hwnd, uiMsg, wParam, lParam);
532 }
533 
534 static LRESULT CALLBACK testDlgWinProc (HWND hwnd, UINT uiMsg, WPARAM wParam,
535         LPARAM lParam)
536 {
537     switch (uiMsg)
538     {
539         /* Add blank case statements for these to ensure we don't use them
540          * by mistake.
541          */
542         case DM_GETDEFID: break;
543         case DM_SETDEFID: break;
544 
545         case WM_CREATE:
546             return (OnTestDlgCreate (hwnd,
547                     (LPCREATESTRUCTA) lParam) ? 0 : (LRESULT) -1);
548         case WM_COMMAND:
549             if(LOWORD(wParam) == 300) g_bReceivedCommand = TRUE;
550     }
551 
552     return DefDlgProcA (hwnd, uiMsg, wParam, lParam);
553 }
554 
555 static LRESULT CALLBACK test_control_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
556 {
557     switch(msg)
558     {
559         case WM_CREATE:
560         {
561             static const short sample[] = { 10,1,2,3,4,5 };
562             CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
563             short *data = cs->lpCreateParams;
564             ok(!memcmp(data, sample, sizeof(sample)), "data mismatch: %d,%d,%d,%d,%d\n", data[0], data[1], data[2], data[3], data[4]);
565         }
566         return 0;
567 
568     default:
569         break;
570     }
571 
572     return DefWindowProcA(hwnd, msg, wparam, lparam);
573 }
574 
575 static BOOL RegisterWindowClasses (void)
576 {
577     WNDCLASSA cls;
578 
579     cls.style = 0;
580     cls.lpfnWndProc = DefWindowProcA;
581     cls.cbClsExtra = 0;
582     cls.cbWndExtra = 0;
583     cls.hInstance = g_hinst;
584     cls.hIcon = NULL;
585     cls.hCursor = LoadCursorA (NULL, (LPCSTR)IDC_ARROW);
586     cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
587     cls.lpszMenuName = NULL;
588     cls.lpszClassName = "GetNextDlgItemWindowClass";
589 
590     if (!RegisterClassA (&cls)) return FALSE;
591 
592     cls.lpfnWndProc = main_window_procA;
593     cls.lpszClassName = "IsDialogMessageWindowClass";
594     if (!RegisterClassA (&cls)) return FALSE;
595 
596     cls.lpfnWndProc = test_control_procA;
597     cls.lpszClassName = "TESTCONTROL";
598     if (!RegisterClassA (&cls)) return FALSE;
599 
600     GetClassInfoA(0, "#32770", &cls);
601     cls.lpfnWndProc = testDlgWinProc;
602     cls.lpszClassName = "WM_NEXTDLGCTLWndClass";
603     if (!RegisterClassA (&cls)) return FALSE;
604 
605     return TRUE;
606 }
607 
608 static void test_WM_NEXTDLGCTL(void)
609 {
610     HWND child1, child2, child3;
611     MSG msg;
612     DWORD dwVal;
613 
614     g_hwndTestDlg = CreateWindowExA( WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR
615               | WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CONTROLPARENT | WS_EX_APPWINDOW,
616               "WM_NEXTDLGCTLWndClass",
617               "WM_NEXTDLGCTL Message test window",
618               WS_POPUPWINDOW | WS_CLIPSIBLINGS | WS_DLGFRAME | WS_OVERLAPPED |
619               WS_MINIMIZEBOX | WS_MAXIMIZEBOX | DS_3DLOOK | DS_SETFONT | DS_MODALFRAME,
620               0, 0, 235, 135,
621               NULL, NULL, g_hinst, 0);
622 
623     assert (g_hwndTestDlg);
624     assert (g_hwndTestDlgBut1);
625     assert (g_hwndTestDlgBut2);
626     assert (g_hwndTestDlgEdit);
627 
628     /*
629      * Test message DM_SETDEFID
630      */
631 
632     DefDlgProcA( g_hwndTestDlg, DM_SETDEFID, IDCANCEL, 0 );
633     DefDlgProcA( g_hwndTestDlgBut1, BM_SETSTYLE, BS_DEFPUSHBUTTON, FALSE );
634     dwVal = DefDlgProcA(g_hwndTestDlg, DM_GETDEFID, 0, 0);
635 
636     ok ( IDCANCEL == (LOWORD(dwVal)), "Did not set default ID\n" );
637 
638     /*
639      * Check whether message WM_NEXTDLGCTL is changing the focus to next control and if
640      * the destination control is a button, style of the button should be changed to
641      * BS_DEFPUSHBUTTON with out making it default.
642      */
643 
644     /* Keep the focus on Edit control. */
645     SetFocus(g_hwndTestDlgEdit);
646     ok((GetFocus() == g_hwndTestDlgEdit), "Focus didn't set on Edit control\n");
647 
648     /* Test message WM_NEXTDLGCTL */
649     DefDlgProcA(g_hwndTestDlg, WM_NEXTDLGCTL, 0, 0);
650     ok((GetFocus() == g_hwndTestDlgBut1), "Focus didn't move to first button\n");
651 
652     /* Check whether the default button ID got changed by sending message "WM_NEXTDLGCTL" */
653     dwVal = DefDlgProcA(g_hwndTestDlg, DM_GETDEFID, 0, 0);
654     ok(IDCANCEL == (LOWORD(dwVal)), "WM_NEXTDLGCTL changed default button\n");
655 
656     /*
657      * Check whether the style of the button which got the focus, changed to BS_DEFPUSHBUTTON and
658      * the style of default button changed to BS_PUSHBUTTON.
659      */
660     ok(get_button_style(g_hwndTestDlgBut1) == BS_DEFPUSHBUTTON, "Button1's style not set to BS_DEFPUSHBUTTON");
661     ok(get_button_style(g_hwndTestDlgBut2) == BS_PUSHBUTTON, "Button2's style not set to BS_PUSHBUTTON");
662 
663     /* Move focus to Button2 using "WM_NEXTDLGCTL" */
664     DefDlgProcA(g_hwndTestDlg, WM_NEXTDLGCTL, 0, 0);
665     ok((GetFocus() == g_hwndTestDlgBut2), "Focus didn't move to second button\n");
666 
667     /* Check whether the default button ID got changed by sending message "WM_NEXTDLGCTL" */
668     dwVal = DefDlgProcA(g_hwndTestDlg, DM_GETDEFID, 0, 0);
669     ok(IDCANCEL == (LOWORD(dwVal)), "WM_NEXTDLGCTL changed default button\n");
670 
671     /*
672      * Check whether the style of the button which got the focus, changed to BS_DEFPUSHBUTTON and
673      * the style of button which lost the focus changed to BS_PUSHBUTTON.
674      */
675     ok(get_button_style(g_hwndTestDlgBut1) == BS_PUSHBUTTON, "Button1's style not set to BS_PUSHBUTTON");
676     ok(get_button_style(g_hwndTestDlgBut2) == BS_DEFPUSHBUTTON, "Button2's style not set to BS_DEFPUSHBUTTON");
677 
678     /* Move focus to Edit control using "WM_NEXTDLGCTL" */
679     DefDlgProcA(g_hwndTestDlg, WM_NEXTDLGCTL, 0, 0);
680     ok((GetFocus() == g_hwndTestDlgEdit), "Focus didn't move to Edit control\n");
681 
682     /* Check whether the default button ID got changed by sending message "WM_NEXTDLGCTL" */
683     dwVal = DefDlgProcA(g_hwndTestDlg, DM_GETDEFID, 0, 0);
684     ok(IDCANCEL == (LOWORD(dwVal)), "WM_NEXTDLGCTL changed default button\n");
685 
686     /* test nested default buttons */
687 
688     child1 = CreateWindowA("button", "child1", WS_VISIBLE|WS_CHILD, 0, 0, 50, 50,
689                            g_hwndTestDlg, (HMENU)100, g_hinst, NULL);
690     ok(child1 != NULL, "failed to create first child\n");
691     child2 = CreateWindowA("button", "child2", WS_VISIBLE|WS_CHILD, 60, 60, 30, 30,
692                            g_hwndTestDlg, (HMENU)200, g_hinst, NULL);
693     ok(child2 != NULL, "failed to create second child\n");
694     /* create nested child */
695     child3 = CreateWindowA("button", "child3", WS_VISIBLE|WS_CHILD, 10, 10, 10, 10,
696                            child1, (HMENU)300, g_hinst, NULL);
697     ok(child3 != NULL, "failed to create subchild\n");
698 
699     DefDlgProcA( g_hwndTestDlg, DM_SETDEFID, 200, 0);
700     dwVal = DefDlgProcA( g_hwndTestDlg, DM_GETDEFID, 0, 0);
701     ok(LOWORD(dwVal) == 200, "expected 200, got %x\n", dwVal);
702 
703     DefDlgProcA( g_hwndTestDlg, DM_SETDEFID, 300, 0);
704     dwVal = DefDlgProcA( g_hwndTestDlg, DM_GETDEFID, 0, 0);
705     ok(LOWORD(dwVal) == 300, "expected 300, got %x\n", dwVal);
706     ok(SendMessageW( child3, WM_GETDLGCODE, 0, 0) != DLGC_DEFPUSHBUTTON,
707        "expected child3 not to be marked as DLGC_DEFPUSHBUTTON\n");
708 
709     g_bReceivedCommand = FALSE;
710     FormEnterMsg (&msg, child3);
711     ok(IsDialogMessageA(g_hwndTestDlg, &msg), "Did not handle the ENTER\n");
712     ok(g_bReceivedCommand, "Did not trigger the default Button action\n");
713 
714     DestroyWindow(child3);
715     DestroyWindow(child2);
716     DestroyWindow(child1);
717     DestroyWindow(g_hwndTestDlg);
718 }
719 
720 static LRESULT CALLBACK hook_proc(INT code, WPARAM wParam, LPARAM lParam)
721 {
722     ok(0, "unexpected hook called, code %d\n", code);
723     return CallNextHookEx(NULL, code, wParam, lParam);
724 }
725 
726 static BOOL g_MSGF_DIALOGBOX;
727 static LRESULT CALLBACK hook_proc2(INT code, WPARAM wParam, LPARAM lParam)
728 {
729     ok(code == MSGF_DIALOGBOX, "unexpected hook called, code %d\n", code);
730     g_MSGF_DIALOGBOX = code == MSGF_DIALOGBOX;
731     return CallNextHookEx(NULL, code, wParam, lParam);
732 }
733 
734 static void test_IsDialogMessage(void)
735 {
736     HHOOK hook;
737     MSG msg;
738 
739     g_hwndMain = CreateWindowA("IsDialogMessageWindowClass", "IsDialogMessageWindowClass",
740             WS_OVERLAPPEDWINDOW,
741             CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
742             NULL, NULL, g_hinst, 0);
743 
744     assert (g_hwndMain);
745     assert (g_hwndButton1);
746     assert (g_hwndButtonCancel);
747 
748     if (0)
749     {
750         /* crashes on Windows */
751         IsDialogMessageA(NULL, NULL);
752         IsDialogMessageA(g_hwndMain, NULL);
753     }
754 
755     /* The focus should initially be nowhere.  The first TAB should take it
756      * to the first button.  The second TAB should take it to the Cancel
757      * button.
758      */
759 
760     /* valid window, invalid message window */
761     hook = SetWindowsHookExA(WH_MSGFILTER, hook_proc2, NULL, GetCurrentThreadId());
762     FormTabMsg (&msg, (HWND)0xbeefbeef);
763     ok (!IsDialogMessageA(g_hwndMain, &msg), "expected failure\n");
764     ok(g_MSGF_DIALOGBOX, "hook wasn't called\n");
765     g_MSGF_DIALOGBOX = FALSE;
766     UnhookWindowsHookEx(hook);
767 
768     hook = SetWindowsHookExA(WH_MSGFILTER, hook_proc, NULL, GetCurrentThreadId());
769     FormTabMsg (&msg, g_hwndMain);
770 
771     ok (!IsDialogMessageA(NULL, &msg), "expected failure\n");
772     ok (!IsDialogMessageA((HWND)0xbeefbeef, &msg), "expected failure\n");
773 
774     UnhookWindowsHookEx(hook);
775 
776     ok (IsDialogMessageA(g_hwndMain, &msg), "Did not handle first TAB\n");
777     ok ((GetFocus() == g_hwndButton1), "Focus did not move to first button\n");
778     FormTabMsg (&msg, g_hwndButton1);
779     ok (IsDialogMessageA(g_hwndMain, &msg), "Did not handle second TAB\n");
780     ok ((GetFocus() == g_hwndButtonCancel),
781             "Focus did not move to cancel button\n");
782     FormEnterMsg (&msg, g_hwndButtonCancel);
783     ok (IsDialogMessageA(g_hwndMain, &msg), "Did not handle the ENTER\n");
784     ok (g_terminated, "ENTER did not terminate\n");
785 
786     /* matching but invalid window handles, NULL */
787     hook = SetWindowsHookExA(WH_MSGFILTER, hook_proc, NULL, GetCurrentThreadId());
788 
789     FormTabMsg (&msg, NULL);
790     ok (!IsDialogMessageA(msg.hwnd, &msg), "expected failure\n");
791 
792     /* matching but invalid window handles, not NULL */
793     FormTabMsg (&msg, (HWND)0xbeefbeef);
794     ok (!IsDialogMessageA(msg.hwnd, &msg), "expected failure\n");
795 
796     UnhookWindowsHookEx(hook);
797     DestroyWindow(g_hwndMain);
798 
799     g_hwndMain = CreateWindowA("IsDialogMessageWindowClass", "IsDialogMessageWindowClass", WS_OVERLAPPEDWINDOW,
800                                CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, g_hinst, 0);
801     SetFocus(g_hwndButton1);
802     g_button1Clicked = FALSE;
803     FormEnterMsg(&msg, g_hwndButton1);
804     ok(IsDialogMessageA(g_hwndMain, &msg), "Did not handle the ENTER\n");
805     ok(g_button1Clicked, "Did not receive button 1 click notification\n");
806 
807     g_button1Clicked = FALSE;
808     FormEnterMsg(&msg, g_hwndMain);
809     ok(IsDialogMessageA(g_hwndMain, &msg), "Did not handle the ENTER\n");
810     ok(g_button1Clicked, "Did not receive button 1 click notification\n");
811 
812     g_button1Clicked = FALSE;
813     FormEnterMsg(&msg, g_hwndButton2);
814     ok(IsDialogMessageA(g_hwndMain, &msg), "Did not handle the ENTER\n");
815     ok(g_button1Clicked, "Did not receive button 1 click notification\n");
816 
817     /* Button with id larger than 0xFFFF should also work */
818     g_button1Clicked = FALSE;
819     FormEnterMsg(&msg, g_hwndMain);
820     SetWindowLongPtrW(g_hwndButton1, GWLP_ID, 0x1FFFF);
821     ok(IsDialogMessageA(g_hwndMain, &msg), "Did not handle the ENTER\n");
822     ok(g_button1Clicked, "Did not receive button 1 click notification\n");
823 
824     DestroyWindow(g_hwndMain);
825 }
826 
827 
828 static INT_PTR CALLBACK delayFocusDlgWinProc (HWND hDlg, UINT uiMsg, WPARAM wParam,
829         LPARAM lParam)
830 {
831     switch (uiMsg)
832     {
833     case WM_INITDIALOG:
834         g_hwndMain = hDlg;
835        g_hwndInitialFocusGroupBox = GetDlgItem(hDlg,100);
836        g_hwndButton1 = GetDlgItem(hDlg,200);
837        g_hwndButton2 = GetDlgItem(hDlg,201);
838        g_hwndButtonCancel = GetDlgItem(hDlg,IDCANCEL);
839        g_styleInitialFocusT1 = GetWindowLongA(g_hwndInitialFocusGroupBox, GWL_STYLE);
840 
841        /* Initially check the second radio button */
842        SendMessageA(g_hwndButton1, BM_SETCHECK, BST_UNCHECKED, 0);
843        SendMessageA(g_hwndButton2, BM_SETCHECK, BST_CHECKED  , 0);
844        /* Continue testing after dialog initialization */
845        PostMessageA(hDlg, WM_USER, 0, 0);
846        return g_bInitialFocusInitDlgResult;
847 
848     case WM_COMMAND:
849         if (LOWORD(wParam) == IDCANCEL)
850        {
851            EndDialog(hDlg, LOWORD(wParam));
852            return TRUE;
853        }
854        return FALSE;
855 
856     case WM_USER:
857        g_styleInitialFocusT2 = GetWindowLongA(hDlg, GWL_STYLE);
858         g_hwndInitialFocusT1 = GetFocus();
859        SetFocus(hDlg);
860         g_hwndInitialFocusT2 = GetFocus();
861        PostMessageA(hDlg, WM_COMMAND, IDCANCEL, 0);
862        return TRUE;
863     }
864 
865     return FALSE;
866 }
867 
868 static INT_PTR CALLBACK focusDlgWinProc (HWND hDlg, UINT uiMsg, WPARAM wParam,
869         LPARAM lParam)
870 {
871     switch (uiMsg)
872     {
873     case WM_INITDIALOG:
874         SetWindowTextA(GetDlgItem(hDlg, 200), "new caption");
875         return TRUE;
876 
877     case WM_COMMAND:
878        if (LOWORD(wParam) == 200)
879        {
880            if (HIWORD(wParam) == EN_SETFOCUS)
881                g_hwndInitialFocusT1 = (HWND)lParam;
882        }
883        return FALSE;
884     }
885 
886     return FALSE;
887 }
888 
889 static INT_PTR CALLBACK EmptyProcUserTemplate(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
890 {
891     switch(uMsg) {
892     case WM_INITDIALOG:
893         return TRUE;
894     }
895     return FALSE;
896 }
897 
898 static INT_PTR CALLBACK focusChildDlgWinProc (HWND hwnd, UINT uiMsg, WPARAM wParam,
899         LPARAM lParam)
900 {
901     static HWND hChildDlg;
902 
903     switch (uiMsg)
904     {
905     case WM_INITDIALOG:
906     {
907         RECT rectHwnd;
908         struct  {
909             DLGTEMPLATE tmplate;
910             WORD menu,class,title;
911         } temp;
912 
913         SetFocus( GetDlgItem(hwnd, 200) );
914 
915         GetClientRect(hwnd,&rectHwnd);
916         temp.tmplate.style = WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | DS_CONTROL | DS_3DLOOK;
917         temp.tmplate.dwExtendedStyle = 0;
918         temp.tmplate.cdit = 0;
919         temp.tmplate.x = 0;
920         temp.tmplate.y = 0;
921         temp.tmplate.cx = 0;
922         temp.tmplate.cy = 0;
923         temp.menu = temp.class = temp.title = 0;
924 
925         hChildDlg = CreateDialogIndirectParamA(g_hinst, &temp.tmplate,
926                   hwnd, (DLGPROC)EmptyProcUserTemplate, 0);
927         ok(hChildDlg != 0, "Failed to create test dialog.\n");
928 
929         return FALSE;
930     }
931     case WM_CLOSE:
932         DestroyWindow(hChildDlg);
933         return TRUE;
934     }
935 
936     return FALSE;
937 }
938 
939 /* Helper for InitialFocusTest */
940 static const char * GetHwndString(HWND hw)
941 {
942   if (hw == NULL)
943     return "a null handle";
944   if (hw == g_hwndMain)
945     return "the dialog handle";
946   if (hw == g_hwndInitialFocusGroupBox)
947     return "the group box control";
948   if (hw == g_hwndButton1)
949     return "the first button";
950   if (hw == g_hwndButton2)
951     return "the second button";
952   if (hw == g_hwndButtonCancel)
953     return "the cancel button";
954 
955   return "unknown handle";
956 }
957 
958 static void test_focus(void)
959 {
960     /* Test 1:
961      * This test intentionally returns FALSE in response to WM_INITDIALOG
962      * without setting focus to a control. This is what MFC's CFormView does.
963      *
964      * Since the WM_INITDIALOG handler returns FALSE without setting the focus,
965      * the focus should initially be NULL. Later, when we manually set focus to
966      * the dialog, the default handler should set focus to the first control that
967      * is "visible, not disabled, and has the WS_TABSTOP style" (MSDN). Because the
968      * second radio button has been checked, it should be the first control
969      * that meets these criteria and should receive the focus.
970      */
971 
972     g_bInitialFocusInitDlgResult = FALSE;
973     g_hwndInitialFocusT1 = (HWND) -1;
974     g_hwndInitialFocusT2 = (HWND) -1;
975     g_styleInitialFocusT1 = -1;
976     g_styleInitialFocusT2 = -1;
977 
978     DialogBoxA(g_hinst, "RADIO_TEST_DIALOG", NULL, delayFocusDlgWinProc);
979 
980     ok (((g_styleInitialFocusT1 & WS_TABSTOP) == 0),
981        "Error in wrc - Detected WS_TABSTOP as default style for GROUPBOX\n");
982 
983     ok (((g_styleInitialFocusT2 & WS_VISIBLE) == 0),
984        "Modal dialogs should not be shown until the message queue first goes empty\n");
985 
986     ok ((g_hwndInitialFocusT1 == NULL),
987         "Error in initial focus when WM_INITDIALOG returned FALSE: "
988         "Expected NULL focus, got %s (%p).\n",
989         GetHwndString(g_hwndInitialFocusT1), g_hwndInitialFocusT1);
990 
991     ok ((g_hwndInitialFocusT2 == g_hwndButton2),
992         "Error after first SetFocus() when WM_INITDIALOG returned FALSE: "
993         "Expected the second button (%p), got %s (%p).\n",
994         g_hwndButton2, GetHwndString(g_hwndInitialFocusT2),
995         g_hwndInitialFocusT2);
996 
997     /* Test 2:
998      * This is the same as above, except WM_INITDIALOG is made to return TRUE.
999      * This should cause the focus to go to the second radio button right away
1000      * and stay there (until the user indicates otherwise).
1001      */
1002 
1003     g_bInitialFocusInitDlgResult = TRUE;
1004     g_hwndInitialFocusT1 = (HWND) -1;
1005     g_hwndInitialFocusT2 = (HWND) -1;
1006     g_styleInitialFocusT1 = -1;
1007     g_styleInitialFocusT2 = -1;
1008 
1009     DialogBoxA(g_hinst, "RADIO_TEST_DIALOG", NULL, delayFocusDlgWinProc);
1010 
1011     ok ((g_hwndInitialFocusT1 == g_hwndButton2),
1012        "Error in initial focus when WM_INITDIALOG returned TRUE: "
1013        "Expected the second button (%p), got %s (%p).\n",
1014        g_hwndButton2, GetHwndString(g_hwndInitialFocusT1),
1015        g_hwndInitialFocusT1);
1016 
1017     ok ((g_hwndInitialFocusT2 == g_hwndButton2),
1018        "Error after first SetFocus() when WM_INITDIALOG returned TRUE: "
1019        "Expected the second button (%p), got %s (%p).\n",
1020        g_hwndButton2, GetHwndString(g_hwndInitialFocusT2),
1021        g_hwndInitialFocusT2);
1022 
1023     /* Test 3:
1024      * If the dialog has DS_CONTROL and it's not visible then we shouldn't change focus */
1025     {
1026         HWND hDlg;
1027         HRSRC hResource;
1028         HANDLE hTemplate;
1029         DLGTEMPLATE* pTemplate;
1030         HWND hTextbox;
1031         DWORD selectionStart = 0xdead, selectionEnd = 0xbeef;
1032 
1033         hResource = FindResourceA(g_hinst,"FOCUS_TEST_DIALOG", (LPCSTR)RT_DIALOG);
1034         hTemplate = LoadResource(g_hinst, hResource);
1035         pTemplate = LockResource(hTemplate);
1036 
1037         g_hwndInitialFocusT1 = 0;
1038         hDlg = CreateDialogIndirectParamA(g_hinst, pTemplate, NULL, focusDlgWinProc, 0);
1039         ok (hDlg != 0, "Failed to create test dialog.\n");
1040 
1041         ok ((g_hwndInitialFocusT1 == 0),
1042             "Focus should not be set for an invisible DS_CONTROL dialog %p.\n", g_hwndInitialFocusT1);
1043 
1044         /* Also make sure that WM_SETFOCUS selects the textbox's text */
1045         hTextbox = GetDlgItem(hDlg, 200);
1046         SendMessageA(hTextbox, WM_SETTEXT, 0, (LPARAM)"Hello world");
1047 
1048         SendMessageA(hDlg, WM_SETFOCUS, 0, 0);
1049         SendMessageA(hTextbox, EM_GETSEL, (WPARAM)&selectionStart, (LPARAM)&selectionEnd);
1050         ok(selectionStart == 0 && selectionEnd == 11, "Text selection after WM_SETFOCUS is [%i, %i) expected [0, 11)\n", selectionStart, selectionEnd);
1051 
1052         /* but WM_ACTIVATE does not */
1053         SendMessageA(hTextbox, EM_SETSEL, 0, 0);
1054         SendMessageA(hDlg, WM_ACTIVATE, WA_ACTIVE, 0);
1055         SendMessageA(hTextbox, EM_GETSEL, (WPARAM)&selectionStart, (LPARAM)&selectionEnd);
1056         ok(selectionStart == 0 && selectionEnd == 0, "Text selection after WM_ACTIVATE is [%i, %i) expected [0, 0)\n", selectionStart, selectionEnd);
1057 
1058         DestroyWindow(hDlg);
1059     }
1060 
1061     /* Test 4:
1062      * If the dialog has no tab-accessible controls, set focus to first control */
1063     {
1064         HWND hDlg;
1065         HRSRC hResource;
1066         HANDLE hTemplate;
1067         DLGTEMPLATE* pTemplate;
1068         HWND hLabel;
1069 
1070         hResource = FindResourceA(g_hinst,"FOCUS_TEST_DIALOG_2", (LPCSTR)RT_DIALOG);
1071         hTemplate = LoadResource(g_hinst, hResource);
1072         pTemplate = LockResource(hTemplate);
1073 
1074         hDlg = CreateDialogIndirectParamA(g_hinst, pTemplate, NULL, focusDlgWinProc, 0);
1075         ok(hDlg != 0, "Failed to create test dialog.\n");
1076         hLabel = GetDlgItem(hDlg, 200);
1077 
1078         ok(GetFocus() == hLabel, "Focus not set to label, focus=%p dialog=%p label=%p\n", GetFocus(), hDlg, hLabel);
1079 
1080         DestroyWindow(hDlg);
1081 
1082         /* Also check focus after WM_ACTIVATE and WM_SETFOCUS */
1083         hDlg = CreateDialogIndirectParamA(g_hinst, pTemplate, NULL, NULL, 0);
1084         ok(hDlg != 0, "Failed to create test dialog.\n");
1085         hLabel = GetDlgItem(hDlg, 200);
1086 
1087         SetFocus(NULL);
1088         SendMessageA(hDlg, WM_ACTIVATE, WA_ACTIVE, 0);
1089         ok(GetFocus() == NULL, "Focus set on WM_ACTIVATE, focus=%p dialog=%p label=%p\n", GetFocus(), hDlg, hLabel);
1090 
1091         SetFocus(NULL);
1092         SendMessageA(hDlg, WM_SETFOCUS, 0, 0);
1093         ok(GetFocus() == hLabel, "Focus not set to label on WM_SETFOCUS, focus=%p dialog=%p label=%p\n", GetFocus(), hDlg, hLabel);
1094 
1095         DestroyWindow(hDlg);
1096     }
1097 
1098     /* Test 5:
1099      * Select textbox's text on creation */
1100     {
1101         HWND hDlg;
1102         HRSRC hResource;
1103         HANDLE hTemplate;
1104         DLGTEMPLATE* pTemplate;
1105         HWND edit;
1106         DWORD selectionStart = 0xdead, selectionEnd = 0xbeef;
1107 
1108         hResource = FindResourceA(g_hinst,"FOCUS_TEST_DIALOG_3", (LPCSTR)RT_DIALOG);
1109         hTemplate = LoadResource(g_hinst, hResource);
1110         pTemplate = LockResource(hTemplate);
1111 
1112         hDlg = CreateDialogIndirectParamA(g_hinst, pTemplate, NULL, focusDlgWinProc, 0);
1113         ok(hDlg != 0, "Failed to create test dialog.\n");
1114         edit = GetDlgItem(hDlg, 200);
1115 
1116         ok(GetFocus() == edit, "Focus not set to edit, focus=%p, dialog=%p, edit=%p\n",
1117                 GetFocus(), hDlg, edit);
1118         SendMessageA(edit, EM_GETSEL, (WPARAM)&selectionStart, (LPARAM)&selectionEnd);
1119         ok(selectionStart == 0 && selectionEnd == 11,
1120                 "Text selection after WM_SETFOCUS is [%i, %i) expected [0, 11)\n",
1121                 selectionStart, selectionEnd);
1122 
1123         DestroyWindow(hDlg);
1124     }
1125 
1126     /* Test 6:
1127      * Select textbox's text on creation when WM_INITDIALOG creates a child dialog. */
1128     {
1129         HWND hDlg;
1130         HRSRC hResource;
1131         HANDLE hTemplate;
1132         DLGTEMPLATE* pTemplate;
1133         HWND edit;
1134 
1135         hResource = FindResourceA(g_hinst,"FOCUS_TEST_DIALOG_3", (LPCSTR)RT_DIALOG);
1136         hTemplate = LoadResource(g_hinst, hResource);
1137         pTemplate = LockResource(hTemplate);
1138 
1139         hDlg = CreateDialogIndirectParamA(g_hinst, pTemplate, NULL, focusChildDlgWinProc, 0);
1140         ok(hDlg != 0, "Failed to create test dialog.\n");
1141         edit = GetDlgItem(hDlg, 200);
1142 
1143         ok(GetFocus() == edit, "Focus not set to edit, focus=%p, dialog=%p, edit=%p\n",
1144                 GetFocus(), hDlg, edit);
1145 
1146         DestroyWindow(hDlg);
1147     }
1148 }
1149 
1150 static void test_GetDlgItemText(void)
1151 {
1152     char string[64];
1153     BOOL ret;
1154 
1155     strcpy(string, "Overwrite Me");
1156     ret = GetDlgItemTextA(NULL, 0, string, ARRAY_SIZE(string));
1157     ok(!ret, "GetDlgItemText(NULL) shouldn't have succeeded\n");
1158 
1159     ok(string[0] == '\0' || broken(!strcmp(string, "Overwrite Me")),
1160        "string retrieved using GetDlgItemText should have been NULL terminated\n");
1161 }
1162 
1163 static INT_PTR CALLBACK getdlgitem_test_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
1164 {
1165     if (msg == WM_INITDIALOG)
1166     {
1167         char text[64];
1168         LONG_PTR val;
1169         HWND hwnd;
1170         BOOL ret;
1171 
1172         hwnd = GetDlgItem(hdlg, -1);
1173         ok(hwnd != NULL, "Expected dialog item.\n");
1174 
1175         *text = 0;
1176         ret = GetDlgItemTextA(hdlg, -1, text, ARRAY_SIZE(text));
1177         ok(ret && !strcmp(text, "Text1"), "Unexpected item text.\n");
1178 
1179         val = GetWindowLongA(hwnd, GWLP_ID);
1180         ok(val == -1, "Unexpected id.\n");
1181 
1182         val = GetWindowLongPtrA(hwnd, GWLP_ID);
1183         ok(val == -1, "Unexpected id %ld.\n", val);
1184 
1185         hwnd = GetDlgItem(hdlg, -2);
1186         ok(hwnd != NULL, "Expected dialog item.\n");
1187 
1188         val = GetWindowLongA(hwnd, GWLP_ID);
1189         ok(val == -2, "Unexpected id.\n");
1190 
1191         val = GetWindowLongPtrA(hwnd, GWLP_ID);
1192         ok(val == -2, "Unexpected id %ld.\n", val);
1193 
1194         EndDialog(hdlg, 0xdead);
1195     }
1196 
1197     return FALSE;
1198 }
1199 
1200 static void test_GetDlgItem(void)
1201 {
1202     HWND hwnd, child1, child2, hwnd2;
1203     INT_PTR retval;
1204     BOOL ret;
1205 
1206     hwnd = CreateWindowA("button", "parent", WS_VISIBLE, 0, 0, 100, 100, NULL, 0, g_hinst, NULL);
1207     ok(hwnd != NULL, "failed to created window\n");
1208 
1209     /* created with the same ID */
1210     child1 = CreateWindowA("button", "child1", WS_VISIBLE|WS_CHILD, 0, 0, 10, 10, hwnd, 0, g_hinst, NULL);
1211     ok(child1 != NULL, "failed to create first child\n");
1212     child2 = CreateWindowA("button", "child2", WS_VISIBLE|WS_CHILD, 0, 0, 10, 10, hwnd, 0, g_hinst, NULL);
1213     ok(child2 != NULL, "failed to create second child\n");
1214 
1215     hwnd2 = GetDlgItem(hwnd, 0);
1216     ok(hwnd2 == child1, "expected first child, got %p\n", hwnd2);
1217 
1218     hwnd2 = GetTopWindow(hwnd);
1219     ok(hwnd2 == child1, "expected first child to be top, got %p\n", hwnd2);
1220 
1221     ret = SetWindowPos(child1, child2, 0, 0, 0, 0, SWP_NOMOVE);
1222     ok(ret, "got %d\n", ret);
1223     hwnd2 = GetTopWindow(hwnd);
1224     ok(hwnd2 == child2, "expected second child to be top, got %p\n", hwnd2);
1225 
1226     /* top window from child list is picked */
1227     hwnd2 = GetDlgItem(hwnd, 0);
1228     ok(hwnd2 == child2, "expected second child, got %p\n", hwnd2);
1229 
1230     /* Now test how GetDlgItem searches */
1231     DestroyWindow(child2);
1232     child2 = CreateWindowA("button", "child2", WS_VISIBLE|WS_CHILD, 0, 0, 10, 10, child1, 0, g_hinst, NULL);
1233     ok(child2 != NULL, "failed to create second child\n");
1234 
1235     /* give child2 an ID */
1236     SetWindowLongA(child2, GWLP_ID, 100);
1237 
1238     hwnd2 = GetDlgItem(hwnd, 100);
1239     ok(!hwnd2, "expected child to not be found, got %p\n", hwnd2);
1240 
1241     /* make the ID of child2 public with a WS_EX_CONTROLPARENT parent */
1242     SetWindowLongA(child1, GWL_EXSTYLE, WS_EX_CONTROLPARENT);
1243 
1244     hwnd2 = GetDlgItem(hwnd, 100);
1245     ok(!hwnd2, "expected child to not be found, got %p\n", hwnd2);
1246 
1247     DestroyWindow(child1);
1248     DestroyWindow(child2);
1249     DestroyWindow(hwnd);
1250 
1251     retval = DialogBoxParamA(g_hinst, "GETDLGITEM_TEST_DIALOG", NULL, getdlgitem_test_dialog_proc, 0);
1252     ok(retval == 0xdead, "Unexpected return value.\n");
1253 }
1254 
1255 static INT_PTR CALLBACK DestroyDlgWinProc (HWND hDlg, UINT uiMsg,
1256         WPARAM wParam, LPARAM lParam)
1257 {
1258     if (uiMsg == WM_INITDIALOG)
1259     {
1260         DestroyWindow(hDlg);
1261         return TRUE;
1262     }
1263     return FALSE;
1264 }
1265 
1266 static INT_PTR CALLBACK DestroyOnCloseDlgWinProc (HWND hDlg, UINT uiMsg,
1267         WPARAM wParam, LPARAM lParam)
1268 {
1269     switch (uiMsg)
1270     {
1271     case WM_INITDIALOG:
1272         PostMessageA(hDlg, WM_CLOSE, 0, 0);
1273         return TRUE;
1274     case WM_CLOSE:
1275         DestroyWindow(hDlg);
1276         return TRUE;
1277     case WM_DESTROY:
1278         PostQuitMessage(0);
1279         return TRUE;
1280     }
1281     return FALSE;
1282 }
1283 
1284 static INT_PTR CALLBACK TestInitDialogHandleProc (HWND hDlg, UINT uiMsg,
1285         WPARAM wParam, LPARAM lParam)
1286 {
1287     if (uiMsg == WM_INITDIALOG)
1288     {
1289         HWND expected = GetNextDlgTabItem(hDlg, NULL, FALSE);
1290         ok(expected == (HWND)wParam,
1291            "Expected wParam to be the handle to the first tabstop control (%p), got %p\n",
1292            expected, (HWND)wParam);
1293 
1294         EndDialog(hDlg, LOWORD(SendMessageA(hDlg, DM_GETDEFID, 0, 0)));
1295         return TRUE;
1296     }
1297     return FALSE;
1298 }
1299 
1300 static INT_PTR CALLBACK TestDefButtonDlgProc (HWND hDlg, UINT uiMsg,
1301                                               WPARAM wParam, LPARAM lParam)
1302 {
1303     switch (uiMsg)
1304     {
1305     case WM_INITDIALOG:
1306         EndDialog(hDlg, LOWORD(SendMessageA(hDlg, DM_GETDEFID, 0, 0)));
1307         return TRUE;
1308     }
1309     return FALSE;
1310 }
1311 
1312 static INT_PTR CALLBACK TestReturnKeyDlgProc (HWND hDlg, UINT uiMsg,
1313         WPARAM wParam, LPARAM lParam)
1314 {
1315     static int received_idok;
1316 
1317     switch (uiMsg)
1318     {
1319     case WM_INITDIALOG:
1320     {
1321         MSG msg = {hDlg, WM_KEYDOWN, VK_RETURN, 0x011c0001};
1322 
1323         received_idok = -1;
1324         IsDialogMessageA(hDlg, &msg);
1325         ok(received_idok == 0xdead, "WM_COMMAND/0xdead not received\n");
1326 
1327         received_idok = -2;
1328         IsDialogMessageA(hDlg, &msg);
1329         ok(received_idok == IDOK, "WM_COMMAND/IDOK not received\n");
1330 
1331         EndDialog(hDlg, 0);
1332         return TRUE;
1333     }
1334 
1335     case DM_GETDEFID:
1336         if (received_idok == -1)
1337         {
1338             HWND hwnd = GetDlgItem(hDlg, 0xdead);
1339             ok(!hwnd, "dialog item with ID 0xdead should not exist\n");
1340             SetWindowLongA(hDlg, DWLP_MSGRESULT, MAKELRESULT(0xdead, DC_HASDEFID));
1341             return TRUE;
1342         }
1343         return FALSE;
1344 
1345     case WM_COMMAND:
1346         received_idok = wParam;
1347         return TRUE;
1348     }
1349     return FALSE;
1350 }
1351 
1352 static INT_PTR CALLBACK TestControlStyleDlgProc(HWND hdlg, UINT msg,
1353                                                 WPARAM wparam, LPARAM lparam)
1354 {
1355     HWND control;
1356     DWORD style, exstyle;
1357     char buf[256];
1358 
1359     switch (msg)
1360     {
1361     case WM_INITDIALOG:
1362         control = GetDlgItem(hdlg, 7);
1363         ok(control != 0, "dialog control with id 7 not found\n");
1364         style = GetWindowLongA(control, GWL_STYLE);
1365         ok(style == (WS_CHILD|WS_VISIBLE), "expected WS_CHILD|WS_VISIBLE, got %#x\n", style);
1366         exstyle = GetWindowLongA(control, GWL_EXSTYLE);
1367         ok(exstyle == (WS_EX_NOPARENTNOTIFY|WS_EX_TRANSPARENT|WS_EX_CLIENTEDGE), "expected WS_EX_NOPARENTNOTIFY|WS_EX_TRANSPARENT|WS_EX_CLIENTEDGE, got %#x\n", exstyle);
1368         buf[0] = 0;
1369         GetWindowTextA(control, buf, sizeof(buf));
1370         ok(strcmp(buf, "bump7") == 0,  "expected bump7, got %s\n", buf);
1371 
1372         control = GetDlgItem(hdlg, 8);
1373         ok(control != 0, "dialog control with id 8 not found\n");
1374         style = GetWindowLongA(control, GWL_STYLE);
1375         ok(style == (WS_CHILD|WS_VISIBLE), "expected WS_CHILD|WS_VISIBLE, got %#x\n", style);
1376         exstyle = GetWindowLongA(control, GWL_EXSTYLE);
1377         ok(exstyle == (WS_EX_NOPARENTNOTIFY|WS_EX_TRANSPARENT), "expected WS_EX_NOPARENTNOTIFY|WS_EX_TRANSPARENT, got %#x\n", exstyle);
1378         buf[0] = 0;
1379         GetWindowTextA(control, buf, sizeof(buf));
1380         ok(strcmp(buf, "bump8") == 0,  "expected bump8, got %s\n", buf);
1381 
1382         EndDialog(hdlg, -7);
1383         return TRUE;
1384     }
1385     return FALSE;
1386 }
1387 
1388 static const WCHAR testtextW[] = {'W','n','d','T','e','x','t',0};
1389 static const char *testtext = "WndText";
1390 
1391 enum defdlgproc_text
1392 {
1393     DLGPROCTEXT_SNDMSGA = 0,
1394     DLGPROCTEXT_SNDMSGW,
1395     DLGPROCTEXT_DLGPROCA,
1396     DLGPROCTEXT_DLGPROCW,
1397     DLGPROCTEXT_SETTEXTA,
1398     DLGPROCTEXT_SETTEXTW,
1399 };
1400 
1401 static const char *testmodes[] =
1402 {
1403     "SNDMSGA",
1404     "SNDMSGW",
1405     "DLGPROCA",
1406     "DLGPROCW",
1407     "SETTEXTA",
1408     "SETTEXTW",
1409 };
1410 
1411 static INT_PTR CALLBACK test_aw_conversion_dlgprocA(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
1412 {
1413     int mode = HandleToULong(GetPropA(hdlg, "test_mode"));
1414     WCHAR *text = (WCHAR *)lparam;
1415     char *textA = (char *)lparam;
1416 
1417     switch (msg)
1418     {
1419     case WM_SETTEXT:
1420     case WM_WININICHANGE:
1421     case WM_DEVMODECHANGE:
1422     case CB_DIR:
1423     case LB_DIR:
1424     case LB_ADDFILE:
1425     case EM_REPLACESEL:
1426         switch (mode)
1427         {
1428         case DLGPROCTEXT_DLGPROCA:
1429             ok(textA == testtext, "%s: %s, unexpected text %s.\n", IsWindowUnicode(hdlg) ? "U" : "A",
1430                 testmodes[mode], textA);
1431             break;
1432         case DLGPROCTEXT_DLGPROCW:
1433             ok(text == testtextW, "%s: %s, unexpected text %s.\n", IsWindowUnicode(hdlg) ? "U" : "A", testmodes[mode],
1434                 wine_dbgstr_w(text));
1435             break;
1436         case DLGPROCTEXT_SNDMSGA:
1437         case DLGPROCTEXT_SETTEXTA:
1438             if (IsWindowUnicode(hdlg))
1439             {
1440                 ok(text != testtextW && !lstrcmpW(text, testtextW),
1441                     "U: %s, unexpected text %s.\n", testmodes[mode], wine_dbgstr_w(text));
1442             }
1443             else
1444                 ok(textA == testtext, "A: %s, unexpected text %s.\n", testmodes[mode], textA);
1445             break;
1446         case DLGPROCTEXT_SNDMSGW:
1447         case DLGPROCTEXT_SETTEXTW:
1448             if (IsWindowUnicode(hdlg))
1449                 ok(text == testtextW, "U: %s, unexpected text %s.\n", testmodes[mode], wine_dbgstr_w(text));
1450             else
1451                 ok(textA != testtext && !strcmp(textA, testtext), "A: %s, unexpected text %s.\n",
1452                     testmodes[mode], textA);
1453             break;
1454         }
1455         break;
1456     };
1457 
1458     return DefWindowProcW(hdlg, msg, wparam, lparam);
1459 }
1460 
1461 static INT_PTR CALLBACK test_aw_conversion_dlgprocW(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
1462 {
1463     int mode = HandleToULong(GetPropA(hdlg, "test_mode"));
1464     WCHAR *text = (WCHAR *)lparam;
1465     char *textA = (char *)lparam;
1466 
1467     switch (msg)
1468     {
1469     case WM_SETTEXT:
1470     case WM_WININICHANGE:
1471     case WM_DEVMODECHANGE:
1472     case CB_DIR:
1473     case LB_DIR:
1474     case LB_ADDFILE:
1475     case EM_REPLACESEL:
1476         switch (mode)
1477         {
1478         case DLGPROCTEXT_DLGPROCA:
1479             ok(textA == testtext, "%s: %s, unexpected text %s.\n", IsWindowUnicode(hdlg) ? "U" : "A",
1480                 testmodes[mode], textA);
1481             break;
1482         case DLGPROCTEXT_DLGPROCW:
1483             ok(text == testtextW, "%s: %s, unexpected text %s.\n", IsWindowUnicode(hdlg) ? "U" : "A", testmodes[mode],
1484                 wine_dbgstr_w(text));
1485             break;
1486         case DLGPROCTEXT_SNDMSGA:
1487         case DLGPROCTEXT_SETTEXTA:
1488             if (IsWindowUnicode(hdlg))
1489                 ok(text != testtextW && !lstrcmpW(text, testtextW),
1490                     "U: %s, unexpected text %s.\n", testmodes[mode], wine_dbgstr_w(text));
1491             else
1492                 ok(textA == testtext, "A: %s, unexpected text %s.\n", testmodes[mode], textA);
1493             break;
1494         case DLGPROCTEXT_SNDMSGW:
1495         case DLGPROCTEXT_SETTEXTW:
1496             if (IsWindowUnicode(hdlg))
1497                 ok(text == testtextW, "U: %s, unexpected text %s.\n", testmodes[mode], wine_dbgstr_w(text));
1498             else
1499                 ok(textA != testtext && !strcmp(textA, testtext), "A: %s, unexpected text %s.\n",
1500                     testmodes[mode], textA);
1501             break;
1502         }
1503         break;
1504     }
1505 
1506     return DefWindowProcA(hdlg, msg, wparam, lparam);
1507 }
1508 
1509 static void dlg_test_aw_message(HWND hdlg, UINT msg)
1510 {
1511     SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_SNDMSGA));
1512     SendMessageA(hdlg, msg, 0, (LPARAM)testtext);
1513 
1514     SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_SNDMSGW));
1515     SendMessageW(hdlg, msg, 0, (LPARAM)testtextW);
1516 
1517     SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_DLGPROCA));
1518     DefDlgProcA(hdlg, msg, 0, (LPARAM)testtext);
1519 
1520     SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_DLGPROCW));
1521     DefDlgProcW(hdlg, msg, 0, (LPARAM)testtextW);
1522 }
1523 
1524 static INT_PTR CALLBACK test_aw_conversion_dlgproc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
1525 {
1526     ULONG_PTR dlgproc, originalproc;
1527     WCHAR buffW[64];
1528     char buff[64];
1529     BOOL ret;
1530     INT len;
1531 
1532     switch (msg)
1533     {
1534     case WM_INITDIALOG:
1535         ok(IsWindowUnicode(hdlg), "Expected unicode window.\n");
1536 
1537         dlg_test_aw_message(hdlg, WM_WININICHANGE);
1538         dlg_test_aw_message(hdlg, WM_DEVMODECHANGE);
1539         dlg_test_aw_message(hdlg, CB_DIR);
1540         dlg_test_aw_message(hdlg, LB_DIR);
1541         dlg_test_aw_message(hdlg, LB_ADDFILE);
1542         dlg_test_aw_message(hdlg, EM_REPLACESEL);
1543         dlg_test_aw_message(hdlg, WM_SETTEXT);
1544 
1545         /* WM_SETTEXT/WM_GETTEXT */
1546         originalproc = GetWindowLongPtrW(hdlg, DWLP_DLGPROC);
1547         ok(originalproc == (ULONG_PTR)test_aw_conversion_dlgproc, "Unexpected dlg proc %#lx.\n", originalproc);
1548 
1549         dlgproc = GetWindowLongPtrA(hdlg, DWLP_DLGPROC);
1550         ok(dlgproc != (ULONG_PTR)test_aw_conversion_dlgproc, "Unexpected dlg proc %#lx.\n", dlgproc);
1551 
1552         dlgproc = SetWindowLongPtrA(hdlg, DWLP_DLGPROC, (UINT_PTR)test_aw_conversion_dlgprocA);
1553         ok(IsWindowUnicode(hdlg), "Expected unicode window.\n");
1554 
1555         dlgproc = GetWindowLongPtrW(hdlg, DWLP_DLGPROC);
1556         ok(dlgproc != (ULONG_PTR)test_aw_conversion_dlgprocA, "Unexpected dlg proc %#lx.\n", dlgproc);
1557 
1558         dlgproc = GetWindowLongPtrA(hdlg, DWLP_DLGPROC);
1559         ok(dlgproc == (ULONG_PTR)test_aw_conversion_dlgprocA, "Unexpected dlg proc %#lx.\n", dlgproc);
1560 
1561         SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_SETTEXTA));
1562         ret = SetWindowTextA(hdlg, testtext);
1563     todo_wine
1564         ok(ret, "Failed to set window text.\n");
1565 
1566         SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_SETTEXTW));
1567         ret = SetWindowTextW(hdlg, testtextW);
1568     todo_wine
1569         ok(ret, "Failed to set window text.\n");
1570 
1571         memset(buff, 'A', sizeof(buff));
1572         len = GetWindowTextA(hdlg, buff, sizeof(buff));
1573         ok(buff[0] == 0 && buff[1] == 'A' && len == 0, "Unexpected window text %#x, %#x, len %d\n",
1574            (BYTE)buff[0], (BYTE)buff[1], len);
1575 
1576         memset(buffW, 0xff, sizeof(buffW));
1577         len = GetWindowTextW(hdlg, buffW, 64);
1578         ok(!lstrcmpW(buffW, testtextW) && len == 0, "Unexpected window text %s, len %d\n", wine_dbgstr_w(buffW), len);
1579 
1580         dlg_test_aw_message(hdlg, WM_WININICHANGE);
1581         dlg_test_aw_message(hdlg, WM_DEVMODECHANGE);
1582         dlg_test_aw_message(hdlg, CB_DIR);
1583         dlg_test_aw_message(hdlg, LB_DIR);
1584         dlg_test_aw_message(hdlg, LB_ADDFILE);
1585         dlg_test_aw_message(hdlg, EM_REPLACESEL);
1586         dlg_test_aw_message(hdlg, WM_SETTEXT);
1587 
1588         dlgproc = SetWindowLongPtrW(hdlg, DWLP_DLGPROC, (UINT_PTR)test_aw_conversion_dlgprocW);
1589         ok(IsWindowUnicode(hdlg), "Expected unicode window.\n");
1590 
1591         dlgproc = GetWindowLongPtrW(hdlg, DWLP_DLGPROC);
1592         ok(dlgproc == (ULONG_PTR)test_aw_conversion_dlgprocW, "Unexpected dlg proc %#lx.\n", dlgproc);
1593 
1594         dlgproc = GetWindowLongPtrA(hdlg, DWLP_DLGPROC);
1595         ok(dlgproc != (ULONG_PTR)test_aw_conversion_dlgprocW, "Unexpected dlg proc %#lx.\n", dlgproc);
1596 
1597         SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_SETTEXTA));
1598         ret = SetWindowTextA(hdlg, testtext);
1599     todo_wine
1600         ok(ret, "Failed to set window text.\n");
1601 
1602         SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_SETTEXTW));
1603         ret = SetWindowTextW(hdlg, testtextW);
1604     todo_wine
1605         ok(ret, "Failed to set window text.\n");
1606 
1607         memset(buff, 'A', sizeof(buff));
1608         len = GetWindowTextA(hdlg, buff, sizeof(buff));
1609         ok(buff[0] == 0 && buff[1] == 'A' && len == 0, "Unexpected window text %#x, %#x, len %d\n",
1610            (BYTE)buff[0], (BYTE)buff[1], len);
1611 
1612         memset(buffW, 0xff, sizeof(buffW));
1613         len = GetWindowTextW(hdlg, buffW, ARRAY_SIZE(buffW));
1614         ok(buffW[0] == 'W' && buffW[1] == 0xffff && len == 0, "Unexpected window text %#x, %#x, len %d\n",
1615             buffW[0], buffW[1], len);
1616 
1617         dlg_test_aw_message(hdlg, WM_WININICHANGE);
1618         dlg_test_aw_message(hdlg, WM_DEVMODECHANGE);
1619         dlg_test_aw_message(hdlg, CB_DIR);
1620         dlg_test_aw_message(hdlg, LB_DIR);
1621         dlg_test_aw_message(hdlg, LB_ADDFILE);
1622         dlg_test_aw_message(hdlg, EM_REPLACESEL);
1623         dlg_test_aw_message(hdlg, WM_SETTEXT);
1624 
1625         SetWindowLongPtrA(hdlg, DWLP_DLGPROC, originalproc);
1626         EndDialog(hdlg, -123);
1627         return TRUE;
1628     }
1629     return FALSE;
1630 }
1631 
1632 static INT_PTR CALLBACK test_aw_conversion_dlgproc2(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
1633 {
1634     ULONG_PTR dlgproc, originalproc;
1635     WCHAR buffW[64];
1636     char buff[64];
1637     BOOL ret;
1638     INT len;
1639 
1640     switch (msg)
1641     {
1642     case WM_INITDIALOG:
1643         ok(!IsWindowUnicode(hdlg), "Unexpected unicode window.\n");
1644 
1645         dlg_test_aw_message(hdlg, WM_WININICHANGE);
1646         dlg_test_aw_message(hdlg, WM_DEVMODECHANGE);
1647         dlg_test_aw_message(hdlg, CB_DIR);
1648         dlg_test_aw_message(hdlg, LB_DIR);
1649         dlg_test_aw_message(hdlg, LB_ADDFILE);
1650         dlg_test_aw_message(hdlg, EM_REPLACESEL);
1651         dlg_test_aw_message(hdlg, WM_SETTEXT);
1652 
1653         originalproc = GetWindowLongPtrW(hdlg, DWLP_DLGPROC);
1654         ok(originalproc != (ULONG_PTR)test_aw_conversion_dlgproc2, "Unexpected dlg proc %#lx.\n", originalproc);
1655 
1656         dlgproc = GetWindowLongPtrA(hdlg, DWLP_DLGPROC);
1657         ok(dlgproc == (ULONG_PTR)test_aw_conversion_dlgproc2, "Unexpected dlg proc %#lx.\n", dlgproc);
1658 
1659         dlgproc = SetWindowLongPtrA(hdlg, DWLP_DLGPROC, (UINT_PTR)test_aw_conversion_dlgprocW);
1660         ok(!IsWindowUnicode(hdlg), "Unexpected unicode window.\n");
1661 
1662         dlgproc = GetWindowLongPtrW(hdlg, DWLP_DLGPROC);
1663         ok(dlgproc != (ULONG_PTR)test_aw_conversion_dlgprocW, "Unexpected dlg proc %#lx.\n", dlgproc);
1664 
1665         dlgproc = GetWindowLongPtrA(hdlg, DWLP_DLGPROC);
1666         ok(dlgproc == (ULONG_PTR)test_aw_conversion_dlgprocW, "Unexpected dlg proc %#lx.\n", dlgproc);
1667 
1668         SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_SETTEXTA));
1669         ret = SetWindowTextA(hdlg, testtext);
1670     todo_wine
1671         ok(ret, "Failed to set window text.\n");
1672 
1673         SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_SETTEXTW));
1674         ret = SetWindowTextW(hdlg, testtextW);
1675     todo_wine
1676         ok(ret, "Failed to set window text.\n");
1677 
1678         memset(buff, 'A', sizeof(buff));
1679         len = GetWindowTextA(hdlg, buff, sizeof(buff));
1680         ok(!strcmp(buff, testtext) && len == 0, "Unexpected window text %s, len %d\n", buff, len);
1681 
1682         memset(buffW, 0xff, sizeof(buffW));
1683         len = GetWindowTextW(hdlg, buffW, 64);
1684         ok(buffW[0] == 0 && buffW[1] == 0xffff && len == 0, "Unexpected window text %s, len %d\n",
1685             wine_dbgstr_w(buffW), len);
1686 
1687         dlg_test_aw_message(hdlg, WM_WININICHANGE);
1688         dlg_test_aw_message(hdlg, WM_DEVMODECHANGE);
1689         dlg_test_aw_message(hdlg, CB_DIR);
1690         dlg_test_aw_message(hdlg, LB_DIR);
1691         dlg_test_aw_message(hdlg, LB_ADDFILE);
1692         dlg_test_aw_message(hdlg, EM_REPLACESEL);
1693         dlg_test_aw_message(hdlg, WM_SETTEXT);
1694 
1695         dlgproc = SetWindowLongPtrW(hdlg, DWLP_DLGPROC, (UINT_PTR)test_aw_conversion_dlgprocA);
1696         ok(!IsWindowUnicode(hdlg), "Unexpected unicode window.\n");
1697 
1698         dlgproc = GetWindowLongPtrW(hdlg, DWLP_DLGPROC);
1699         ok(dlgproc == (ULONG_PTR)test_aw_conversion_dlgprocA, "Unexpected dlg proc %#lx.\n", dlgproc);
1700 
1701         dlgproc = GetWindowLongPtrA(hdlg, DWLP_DLGPROC);
1702         ok(dlgproc != (ULONG_PTR)test_aw_conversion_dlgprocA, "Unexpected dlg proc %#lx.\n", dlgproc);
1703 
1704         SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_SETTEXTA));
1705         ret = SetWindowTextA(hdlg, testtext);
1706     todo_wine
1707         ok(ret, "Failed to set window text.\n");
1708 
1709         SetPropA(hdlg, "test_mode", ULongToHandle(DLGPROCTEXT_SETTEXTW));
1710         ret = SetWindowTextW(hdlg, testtextW);
1711     todo_wine
1712         ok(ret, "Failed to set window text.\n");
1713 
1714         memset(buff, 'A', sizeof(buff));
1715         len = GetWindowTextA(hdlg, buff, sizeof(buff));
1716         ok(!strcmp(buff, testtext) && len == 0, "Unexpected window text %s, len %d\n", buff, len);
1717 
1718         memset(buffW, 0xff, sizeof(buffW));
1719         len = GetWindowTextW(hdlg, buffW, ARRAY_SIZE(buffW));
1720         ok(buffW[0] == 0 && buffW[1] == 0xffff && len == 0, "Unexpected window text %#x, %#x, len %d\n",
1721             buffW[0], buffW[1], len);
1722 
1723         dlg_test_aw_message(hdlg, WM_WININICHANGE);
1724         dlg_test_aw_message(hdlg, WM_DEVMODECHANGE);
1725         dlg_test_aw_message(hdlg, CB_DIR);
1726         dlg_test_aw_message(hdlg, LB_DIR);
1727         dlg_test_aw_message(hdlg, LB_ADDFILE);
1728         dlg_test_aw_message(hdlg, EM_REPLACESEL);
1729         dlg_test_aw_message(hdlg, WM_SETTEXT);
1730 
1731         SetWindowLongPtrA(hdlg, DWLP_DLGPROC, originalproc);
1732         EndDialog(hdlg, -123);
1733         return TRUE;
1734     }
1735     return FALSE;
1736 }
1737 
1738 static LRESULT CALLBACK test_aw_conversion_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1739 {
1740     WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
1741     int mode = HandleToULong(GetPropA(hwnd, "test_mode"));
1742     WCHAR *text = (WCHAR *)lparam;
1743     char *textA = (char *)lparam;
1744 
1745     switch (msg)
1746     {
1747     case WM_SETTEXT:
1748     case WM_WININICHANGE:
1749     case WM_DEVMODECHANGE:
1750     case CB_DIR:
1751     case LB_DIR:
1752     case LB_ADDFILE:
1753     case EM_REPLACESEL:
1754         switch (mode)
1755         {
1756         case DLGPROCTEXT_SNDMSGA:
1757             if (IsWindowUnicode(hwnd))
1758                 ok(text != testtextW && !lstrcmpW(text, testtextW),
1759                     "U: %s, unexpected text %s.\n", testmodes[mode], wine_dbgstr_w(text));
1760             else
1761                 ok(textA == testtext, "A: %s, unexpected text %s.\n", testmodes[mode], textA);
1762             break;
1763         case DLGPROCTEXT_SNDMSGW:
1764             if (IsWindowUnicode(hwnd))
1765                 ok(text == testtextW, "U: %s, unexpected text %s.\n", testmodes[mode], wine_dbgstr_w(text));
1766             else
1767                 ok(textA != testtext && !strcmp(textA, testtext), "A: %s, unexpected text %s.\n",
1768                     testmodes[mode], textA);
1769             break;
1770         default:
1771             ok(0, "Unexpected test mode %d.\n", mode);
1772         }
1773         break;
1774     }
1775 
1776     return IsWindowUnicode(hwnd) ? CallWindowProcW(oldproc, hwnd, msg, wparam, lparam) :
1777         CallWindowProcA(oldproc, hwnd, msg, wparam, lparam);
1778 }
1779 
1780 static INT_PTR CALLBACK test_aw_conversion_dlgproc3(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
1781 {
1782     BOOL is_unicode = !!lparam;
1783     LONG_PTR oldproc;
1784 
1785     switch (msg)
1786     {
1787     case WM_INITDIALOG:
1788         ok(is_unicode == IsWindowUnicode(hdlg), "Unexpected unicode window property.\n");
1789 
1790         oldproc = SetWindowLongPtrA(hdlg, GWLP_WNDPROC, (LONG_PTR)test_aw_conversion_wndproc);
1791         SetWindowLongPtrA(hdlg, GWLP_USERDATA, oldproc);
1792         ok(!IsWindowUnicode(hdlg), "Unexpected unicode window.\n");
1793 
1794         dlg_test_aw_message(hdlg, WM_WININICHANGE);
1795         dlg_test_aw_message(hdlg, WM_DEVMODECHANGE);
1796         dlg_test_aw_message(hdlg, CB_DIR);
1797         dlg_test_aw_message(hdlg, LB_DIR);
1798         dlg_test_aw_message(hdlg, LB_ADDFILE);
1799         dlg_test_aw_message(hdlg, EM_REPLACESEL);
1800         dlg_test_aw_message(hdlg, WM_SETTEXT);
1801 
1802         SetWindowLongPtrW(hdlg, GWLP_WNDPROC, (LONG_PTR)test_aw_conversion_wndproc);
1803         ok(IsWindowUnicode(hdlg), "Expected unicode window.\n");
1804 
1805         dlg_test_aw_message(hdlg, WM_WININICHANGE);
1806         dlg_test_aw_message(hdlg, WM_DEVMODECHANGE);
1807         dlg_test_aw_message(hdlg, CB_DIR);
1808         dlg_test_aw_message(hdlg, LB_DIR);
1809         dlg_test_aw_message(hdlg, LB_ADDFILE);
1810         dlg_test_aw_message(hdlg, EM_REPLACESEL);
1811         dlg_test_aw_message(hdlg, WM_SETTEXT);
1812 
1813         SetWindowLongPtrA(hdlg, GWLP_WNDPROC, oldproc);
1814         EndDialog(hdlg, -123);
1815         return TRUE;
1816     }
1817     return FALSE;
1818 }
1819 
1820 static void test_DialogBoxParam(void)
1821 {
1822     static const WCHAR nameW[] = {'T','E','S','T','_','E','M','P','T','Y','_','D','I','A','L','O','G',0};
1823     INT_PTR ret;
1824     HWND hwnd_invalid = (HWND)0x4444;
1825 
1826     ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_DLG_CHILD_POPUP", 0, TestControlStyleDlgProc, 0);
1827     ok(ret == -7, "expected -7, got %ld\n", ret);
1828 
1829     SetLastError(0xdeadbeef);
1830     ret = DialogBoxParamA(GetModuleHandleA(NULL), "IDD_DIALOG" , hwnd_invalid, 0 , 0);
1831     ok(0 == ret || broken(ret == -1), "DialogBoxParamA returned %ld, expected 0\n", ret);
1832     ok(ERROR_INVALID_WINDOW_HANDLE == GetLastError() ||
1833        broken(GetLastError() == 0xdeadbeef),
1834        "got %d, expected ERROR_INVALID_WINDOW_HANDLE\n",GetLastError());
1835 
1836     /* Test a dialog which destroys itself on WM_INITDIALOG. */
1837     SetLastError(0xdeadbeef);
1838     ret = DialogBoxParamA(GetModuleHandleA(NULL), "IDD_DIALOG", 0, DestroyDlgWinProc, 0);
1839     ok(-1 == ret, "DialogBoxParamA returned %ld, expected -1\n", ret);
1840     ok(ERROR_INVALID_WINDOW_HANDLE == GetLastError() ||
1841        GetLastError() == ERROR_SUCCESS ||
1842        broken(GetLastError() == 0xdeadbeef),
1843        "got %d, expected ERROR_INVALID_WINDOW_HANDLE\n",GetLastError());
1844 
1845     /* Test a dialog which destroys itself on WM_CLOSE. */
1846     ret = DialogBoxParamA(GetModuleHandleA(NULL), "IDD_DIALOG", 0, DestroyOnCloseDlgWinProc, 0);
1847     ok(0 == ret, "DialogBoxParamA returned %ld, expected 0\n", ret);
1848 
1849     SetLastError(0xdeadbeef);
1850     ret = DialogBoxParamA(GetModuleHandleA(NULL), "RESOURCE_INVALID" , 0, 0, 0);
1851     ok(-1 == ret, "DialogBoxParamA returned %ld, expected -1\n", ret);
1852     ok(ERROR_RESOURCE_NAME_NOT_FOUND == GetLastError() ||
1853        broken(GetLastError() == 0xdeadbeef),
1854        "got %d, expected ERROR_RESOURCE_NAME_NOT_FOUND\n",GetLastError());
1855 
1856     SetLastError(0xdeadbeef);
1857     ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_DIALOG_INVALID_CLASS", 0, DestroyDlgWinProc, 0);
1858     ok(ret == -1, "DialogBoxParamA returned %ld, expected -1\n", ret);
1859     ok(GetLastError() == 0, "got %d\n", GetLastError());
1860 
1861     SetLastError(0xdeadbeef);
1862     ret = DefDlgProcA(0, WM_ERASEBKGND, 0, 0);
1863     ok(ret == 0, "DefDlgProcA returned %ld, expected 0\n", ret);
1864     ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE ||
1865        broken(GetLastError() == 0xdeadbeef),
1866        "got %d, expected ERROR_INVALID_WINDOW_HANDLE\n", GetLastError());
1867 
1868     ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_EMPTY_DIALOG", 0, TestInitDialogHandleProc, 0);
1869     ok(ret == IDOK, "Expected IDOK\n");
1870 
1871     ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_EMPTY_DIALOG", 0, TestDefButtonDlgProc, 0);
1872     ok(ret == IDOK, "Expected IDOK\n");
1873 
1874     ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_EMPTY_DIALOG", 0, TestReturnKeyDlgProc, 0);
1875     ok(ret == 0, "Unexpected ret value %ld.\n", ret);
1876 
1877     /* WM_SETTEXT handling in case of A/W dialog procedures vs A/W dialog window.  */
1878     ret = DialogBoxParamW(GetModuleHandleA(NULL), nameW, 0, test_aw_conversion_dlgproc, 0);
1879     ok(ret == -123, "Unexpected ret value %ld.\n", ret);
1880 
1881     ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_EMPTY_DIALOG", 0, test_aw_conversion_dlgproc2, 0);
1882     ok(ret == -123, "Unexpected ret value %ld.\n", ret);
1883 
1884     ret = DialogBoxParamW(GetModuleHandleA(NULL), nameW, 0, test_aw_conversion_dlgproc3, 1);
1885     ok(ret == -123, "Unexpected ret value %ld.\n", ret);
1886 
1887     ret = DialogBoxParamA(GetModuleHandleA(NULL), "TEST_EMPTY_DIALOG", 0, test_aw_conversion_dlgproc3, 0);
1888     ok(ret == -123, "Unexpected ret value %ld.\n", ret);
1889 }
1890 
1891 static void test_DisabledDialogTest(void)
1892 {
1893     g_terminated = FALSE;
1894     DialogBoxParamA(g_hinst, "IDD_DIALOG", NULL, disabled_test_proc, 0);
1895     ok(FALSE == g_terminated, "dialog with disabled ok button has been terminated\n");
1896 }
1897 
1898 static INT_PTR CALLBACK messageBoxFontDlgWinProc (HWND hDlg, UINT uiMsg, WPARAM wParam,
1899         LPARAM lParam)
1900 {
1901     if (uiMsg == WM_INITDIALOG) {
1902         SetFocus(hDlg);
1903         return 1;
1904     }
1905 
1906     return 0;
1907 }
1908 
1909 static void test_MessageBoxFontTest(void)
1910 {
1911     /* This dialog template defines a dialog template which got 0x7fff as its
1912      * font size and omits the other font members. On WinNT, passing such a
1913      * dialog template to CreateDialogIndirectParamW will result in a dialog
1914      * being created which uses the message box font. We test that here.
1915      */
1916 
1917     static unsigned char dlgTemplate[] =
1918     {
1919         /* Dialog header */
1920         0x01,0x00,              /* Version */
1921         0xff,0xff,              /* Extended template marker */
1922         0x00,0x00,0x00,0x00,    /* Context Help ID */
1923         0x00,0x00,0x00,0x00,    /* Extended style */
1924         0xc0,0x00,0xc8,0x80,    /* Style (WS_SYSMENU|WS_CAPTION|WS_POPUP|DS_SETFONT|DS_MODALFRAME) */
1925         0x01,0x00,              /* Control count */
1926         0x00,0x00,              /* X */
1927         0x00,0x00,              /* Y */
1928         0x80,0x00,              /* Width */
1929         0x80,0x00,              /* Height */
1930         0x00,0x00,              /* Menu name */
1931         0x00,0x00,              /* Class name */
1932         'T',0x00,'e',0x00,      /* Caption (unicode) */
1933         's',0x00,'t',0x00,
1934         0x00,0x00,
1935         0xff,0x7f,              /* Font height (0x7fff = message box font) */
1936 
1937         /* Control #1 */
1938         0x00,0x00,              /* Align to DWORD (header is 42 bytes) */
1939         0x00,0x00,0x00,0x00,    /* Context Help ID */
1940         0x00,0x00,0x00,0x00,    /* Extended style */
1941         0x00,0x00,0x00,0x50,    /* Style (WS_CHILD|WS_VISIBLE) */
1942         0x00,0x00,              /* X */
1943         0x00,0x00,              /* Y */
1944         0x80,0x00,              /* Width */
1945         0x80,0x00,              /* Height */
1946         0x00,0x01,0x00,0x00,    /* Control ID (256) */
1947         0xff,0xff,0x82,0x00,    /* Class (Static) */
1948         'W',0x00,'I',0x00,      /* Caption (unicode) */
1949         'N',0x00,'E',0x00,
1950         ' ',0x00,'d',0x00,
1951         'i',0x00,'a',0x00,
1952         'l',0x00,'o',0x00,
1953         'g',0x00,' ',0x00,
1954         't',0x00,'e',0x00,
1955         's',0x00,'t',0x00,
1956         '.',0x00,0x00,0x00,
1957         0x00,0x00,              /* Size of extended data */
1958 
1959         0x00,0x00               /* Align to DWORD */
1960     };
1961 
1962     HWND hDlg;
1963     HFONT hFont;
1964     LOGFONTW lfStaticFont;
1965     NONCLIENTMETRICSW ncMetrics;
1966 
1967     /* Check if the dialog can be created from the template. On Win9x, this should fail
1968      * because we are calling the W function which is not implemented, but that's what
1969      * we want, because passing such a template to CreateDialogIndirectParamA would crash
1970      * anyway.
1971      */
1972     hDlg = CreateDialogIndirectParamW(g_hinst, (LPCDLGTEMPLATEW)dlgTemplate, NULL, messageBoxFontDlgWinProc, 0);
1973     if (!hDlg)
1974     {
1975         win_skip("dialog wasn't created\n");
1976         return;
1977     }
1978 
1979     hFont = (HFONT) SendDlgItemMessageW(hDlg, 256, WM_GETFONT, 0, 0);
1980     if (!hFont)
1981     {
1982         skip("dialog uses system font\n");
1983         DestroyWindow(hDlg);
1984         return;
1985     }
1986     GetObjectW(hFont, sizeof(LOGFONTW), &lfStaticFont);
1987 
1988     ncMetrics.cbSize = FIELD_OFFSET(NONCLIENTMETRICSW, iPaddedBorderWidth);
1989     SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 0, &ncMetrics, 0);
1990     ok( !memcmp(&lfStaticFont, &ncMetrics.lfMessageFont, FIELD_OFFSET(LOGFONTW, lfFaceName)) &&
1991         !lstrcmpW(lfStaticFont.lfFaceName, ncMetrics.lfMessageFont.lfFaceName),
1992         "dialog doesn't use message box font\n");
1993     DestroyWindow(hDlg);
1994 }
1995 
1996 static const char msgbox_title[] = "%5!z9ZXw*ia;57n/FGl.bCH,Su\"mfKN;foCqAU\'j6AmoJgAc_D:Z0A\'E6PF_O/w";
1997 static WCHAR expectedOK[] =
1998 {
1999 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
2000 '%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f',
2001 'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P',
2002 'F','_','O','/','w','\r','\n',
2003 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
2004 'M','e','s','s','a','g','e','\r','\n',
2005 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
2006 'O','K',' ',' ',' ','\r','\n',
2007 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0
2008 };
2009 static WCHAR expectedOkCancel[] =
2010 {
2011 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
2012 '%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f',
2013 'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P',
2014 'F','_','O','/','w','\r','\n',
2015 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
2016 'M','e','s','s','a','g','e','\r','\n',
2017 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
2018 'O','K',' ',' ',' ','C','a','n','c','e','l',' ',' ',' ','\r','\n',
2019 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0
2020 };
2021 static WCHAR expectedAbortRetryIgnore[] =
2022 {
2023 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
2024 '%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f',
2025 'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P',
2026 'F','_','O','/','w','\r','\n',
2027 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
2028 'M','e','s','s','a','g','e','\r','\n',
2029 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
2030 'A','b','o','r','t',' ',' ',' ','R','e','t','r','y',' ',' ',' ','I','g','n','o','r','e',' ',' ',' ','\r','\n',
2031 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0
2032 };
2033 
2034 static WCHAR expectedYesNo[] =
2035 {
2036 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
2037 '%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f',
2038 'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P',
2039 'F','_','O','/','w','\r','\n',
2040 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
2041 'M','e','s','s','a','g','e','\r','\n',
2042 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
2043 'Y','e','s',' ',' ',' ','N','o',' ',' ',' ','\r','\n',
2044 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0
2045 };
2046 static WCHAR expectedYesNoCancel[] =
2047 {
2048 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
2049 '%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f',
2050 'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P',
2051 'F','_','O','/','w','\r','\n',
2052 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
2053 'M','e','s','s','a','g','e','\r','\n',
2054 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
2055 'Y','e','s',' ',' ',' ','N','o',' ',' ',' ','C','a','n','c','e','l',' ',' ',' ','\r','\n',
2056 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0
2057 };
2058 static WCHAR expectedRetryCancel[] =
2059 {
2060 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
2061 '%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f',
2062 'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P',
2063 'F','_','O','/','w','\r','\n',
2064 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
2065 'M','e','s','s','a','g','e','\r','\n',
2066 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
2067 'R','e','t','r','y',' ',' ',' ','C','a','n','c','e','l',' ',' ',' ','\r','\n',
2068 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0
2069 };
2070 static WCHAR expectedCancelTryContinue[] =
2071 {
2072 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
2073 '%','5','!','z','9','Z','X','w','*','i','a',';','5','7','n','/','F','G','l','.','b','C','H',',','S','u','"','m','f',
2074 'K','N',';','f','o','C','q','A','U','\'','j','6','A','m','o','J','g','A','c','_','D',':','Z','0','A','\'','E','6','P',
2075 'F','_','O','/','w','\r','\n',
2076 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
2077 'M','e','s','s','a','g','e','\r','\n',
2078 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n',
2079 'C','a','n','c','e','l',' ',' ',' ','T','r','y',' ','A','g','a','i','n',' ',' ',' ','C','o','n','t','i','n','u','e',' ',' ',' ','\r','\n',
2080 '-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\r','\n', 0
2081 };
2082 
2083 BOOL non_english = FALSE;
2084 
2085 DWORD WINAPI WorkerThread(void *param)
2086 {
2087     WCHAR *expected = param;
2088     char windowTitle[sizeof(msgbox_title)];
2089     HWND hwndMbox;
2090     BOOL succeeded = FALSE;
2091 
2092     Sleep(200);
2093 
2094     hwndMbox = GetForegroundWindow();
2095 
2096     /* Find the Window, if it doesn't have focus */
2097     if (!(IsWindow(hwndMbox) &&
2098         GetWindowTextA(hwndMbox, windowTitle, sizeof(msgbox_title)) &&
2099         lstrcmpA(msgbox_title, windowTitle) == 0))
2100     {
2101         hwndMbox = FindWindowA(NULL, msgbox_title);
2102 
2103         if (!IsWindow(hwndMbox))
2104             goto cleanup;
2105     }
2106 
2107     SendMessageA(hwndMbox, WM_COPY, 0, 0);
2108 
2109     if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL))
2110     {
2111         HANDLE textHandle = GetClipboardData(CF_UNICODETEXT);
2112         WCHAR *text = GlobalLock(textHandle);
2113 
2114         if (text != NULL)
2115         {
2116             if(non_english)
2117                 ok(lstrlenW(text) > 0, "Empty string on clipboard\n");
2118             else
2119             {
2120                 succeeded = lstrcmpW(expected, text) == 0;
2121                 if(!succeeded)
2122                 {
2123                     ok(0, "%s\n", wine_dbgstr_w(text));
2124                     ok(0, "%s\n", wine_dbgstr_w(expected));
2125                 }
2126             }
2127 
2128             GlobalUnlock(textHandle);
2129         }
2130         else
2131             ok(0, "No text on clipboard.\n");
2132 
2133         CloseClipboard();
2134 
2135     }
2136     else
2137         trace("Clipboard error\n");
2138 
2139     PostMessageA(hwndMbox, WM_COMMAND, IDIGNORE, 0); /* For MB_ABORTRETRYIGNORE dialog. */
2140     PostMessageA(hwndMbox, WM_CLOSE, 0, 0);
2141 
2142 cleanup:
2143     ok(succeeded || non_english, "Failed to get string.\n");
2144 
2145     return 0;
2146 }
2147 
2148 static void test_MessageBox_WM_COPY_Test(void)
2149 {
2150     DWORD tid = 0;
2151 
2152     non_english = (PRIMARYLANGID(GetUserDefaultLangID()) != LANG_ENGLISH);
2153     trace("non_english %d\n", non_english);
2154 
2155     CreateThread(NULL, 0, WorkerThread, &expectedOK, 0, &tid);
2156     MessageBoxA(NULL, "Message", msgbox_title, MB_OK);
2157 
2158     CreateThread(NULL, 0, WorkerThread, &expectedOkCancel, 0, &tid);
2159     MessageBoxA(NULL, "Message", msgbox_title, MB_OKCANCEL);
2160 
2161     CreateThread(NULL, 0, WorkerThread, &expectedAbortRetryIgnore, 0, &tid);
2162     MessageBoxA(NULL, "Message", msgbox_title, MB_ABORTRETRYIGNORE);
2163 
2164     CreateThread(NULL, 0, WorkerThread, &expectedYesNo, 0, &tid);
2165     MessageBoxA(NULL, "Message", msgbox_title, MB_YESNO);
2166 
2167     CreateThread(NULL, 0, WorkerThread, &expectedYesNoCancel, 0, &tid);
2168     MessageBoxA(NULL, "Message", msgbox_title, MB_YESNOCANCEL);
2169 
2170     CreateThread(NULL, 0, WorkerThread, &expectedRetryCancel, 0, &tid);
2171     MessageBoxA(NULL, "Message", msgbox_title, MB_RETRYCANCEL);
2172 
2173     CreateThread(NULL, 0, WorkerThread, &expectedCancelTryContinue, 0, &tid);
2174     MessageBoxA(NULL, "Message", msgbox_title, MB_CANCELTRYCONTINUE);
2175 }
2176 
2177 static void test_SaveRestoreFocus(void)
2178 {
2179     HWND hDlg;
2180     HRSRC hResource;
2181     HANDLE hTemplate;
2182     DLGTEMPLATE* pTemplate;
2183     LONG_PTR foundId;
2184     HWND foundHwnd;
2185 
2186     /* create the dialog */
2187     hResource = FindResourceA(g_hinst, "MULTI_EDIT_DIALOG", (LPCSTR)RT_DIALOG);
2188     hTemplate = LoadResource(g_hinst, hResource);
2189     pTemplate = LockResource(hTemplate);
2190 
2191     hDlg = CreateDialogIndirectParamA(g_hinst, pTemplate, NULL, messageBoxFontDlgWinProc, 0);
2192     ok (hDlg != 0, "Failed to create test dialog.\n");
2193 
2194     foundId = GetWindowLongPtrA(GetFocus(), GWLP_ID);
2195     ok (foundId == 1000, "First edit box should have gained focus on dialog creation. Expected: %d, Found: %ld\n", 1000, foundId);
2196 
2197     SetFocus(GetNextDlgTabItem(hDlg, GetFocus(), FALSE));
2198     SendMessageA(hDlg, WM_ACTIVATE, MAKEWPARAM(WA_ACTIVE, 0), 0);
2199     foundId = GetWindowLongPtrA(GetFocus(), GWLP_ID);
2200     ok (foundId == 1001, "First edit box should have regained focus after dialog reactivation. Expected: %d, Found: %ld\n", 1001, foundId);
2201     SetFocus(GetNextDlgTabItem(hDlg, NULL, FALSE));
2202 
2203     /* de- then reactivate the dialog */
2204     SendMessageA(hDlg, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE, 0), 0);
2205     SendMessageA(hDlg, WM_ACTIVATE, MAKEWPARAM(WA_ACTIVE, 0), 0);
2206 
2207     foundId = GetWindowLongPtrA(GetFocus(), GWLP_ID);
2208     ok (foundId == 1000, "First edit box should have regained focus after dialog reactivation. Expected: %d, Found: %ld\n", 1000, foundId);
2209 
2210     /* select the next tabbable item */
2211     SetFocus(GetNextDlgTabItem(hDlg, GetFocus(), FALSE));
2212 
2213     foundId = GetWindowLongPtrA(GetFocus(), GWLP_ID);
2214     ok (foundId == 1001, "Second edit box should have gained focus. Expected: %d, Found: %ld\n", 1001, foundId);
2215 
2216     /* de- then reactivate the dialog */
2217     SendMessageA(hDlg, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE, 0), 0);
2218     SendMessageA(hDlg, WM_ACTIVATE, MAKEWPARAM(WA_ACTIVE, 0), 0);
2219 
2220     foundId = GetWindowLongPtrA(GetFocus(), GWLP_ID);
2221     ok (foundId == 1001, "Second edit box should have gained focus after dialog reactivation. Expected: %d, Found: %ld\n", 1001, foundId);
2222 
2223     /* set focus to the dialog */
2224     SetFocus(hDlg);
2225 
2226     foundId = GetWindowLongPtrA(GetFocus(), GWLP_ID);
2227     ok (foundId == 1000, "First edit box should have gained focus on dialog focus. Expected: %d, Found: %ld\n", 1000, foundId);
2228 
2229     /* select second tabbable item */
2230     SetFocus(GetNextDlgTabItem(hDlg, GetNextDlgTabItem(hDlg, NULL, FALSE), FALSE));
2231 
2232     foundId = GetWindowLongPtrA(GetFocus(), GWLP_ID);
2233     ok (foundId == 1001, "Second edit box should have gained focus. Expected: %d, Found: %ld\n", 1001, foundId);
2234 
2235     /* send WM_ACTIVATE message to already active dialog */
2236     SendMessageA(hDlg, WM_ACTIVATE, MAKEWPARAM(WA_ACTIVE, 0), 0);
2237 
2238     foundId = GetWindowLongPtrA(GetFocus(), GWLP_ID);
2239     ok (foundId == 1001, "Second edit box should have gained focus. Expected: %d, Found: %ld\n", 1001, foundId);
2240 
2241     /* disable the 2nd box */
2242     EnableWindow(GetFocus(), FALSE);
2243 
2244     foundHwnd = GetFocus();
2245     ok (foundHwnd == NULL, "Second edit box should have lost focus after being disabled. Expected: %p, Found: %p\n", NULL, foundHwnd);
2246 
2247     /* de- then reactivate the dialog */
2248     SendMessageA(hDlg, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE, 0), 0);
2249     SendMessageA(hDlg, WM_ACTIVATE, MAKEWPARAM(WA_ACTIVE, 0), 0);
2250 
2251     foundHwnd = GetFocus();
2252     ok (foundHwnd == NULL, "No controls should have gained focus after dialog reactivation. Expected: %p, Found: %p\n", NULL, foundHwnd);
2253 
2254     /* clean up */
2255     DestroyWindow(hDlg);
2256 }
2257 
2258 static INT_PTR CALLBACK timer_message_dlg_proc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
2259 {
2260     static int count;
2261     BOOL visible;
2262 
2263     switch (msg)
2264     {
2265         case WM_INITDIALOG:
2266             visible = GetWindowLongA(wnd, GWL_STYLE) & WS_VISIBLE;
2267             ok(!visible, "Dialog should not be visible.\n");
2268             SetTimer(wnd, 1, 100, NULL);
2269             Sleep(200);
2270             return FALSE;
2271 
2272         case WM_COMMAND:
2273             if (LOWORD(wparam) != IDCANCEL) return FALSE;
2274             EndDialog(wnd, LOWORD(wparam));
2275             return TRUE;
2276 
2277         case WM_TIMER:
2278             if (wparam != 1) return FALSE;
2279             visible = GetWindowLongA(wnd, GWL_STYLE) & WS_VISIBLE;
2280             if (!count++)
2281             {
2282                 ok(!visible, "Dialog should not be visible.\n");
2283                 PostMessageA(wnd, WM_USER, 0, 0);
2284             }
2285             else
2286             {
2287                 ok(visible, "Dialog should be visible.\n");
2288                 PostMessageA(wnd, WM_COMMAND, IDCANCEL, 0);
2289             }
2290             return TRUE;
2291 
2292         case WM_USER:
2293             visible = GetWindowLongA(wnd, GWL_STYLE) & WS_VISIBLE;
2294             ok(visible, "Dialog should be visible.\n");
2295             return TRUE;
2296 
2297         default:
2298             return FALSE;
2299     }
2300 }
2301 
2302 static void test_timer_message(void)
2303 {
2304     DialogBoxA(g_hinst, "RADIO_TEST_DIALOG", NULL, timer_message_dlg_proc);
2305 }
2306 
2307 static LRESULT CALLBACK msgbox_hook_proc(INT code, WPARAM wParam, LPARAM lParam)
2308 {
2309     if (code == HCBT_ACTIVATE)
2310     {
2311         HWND msgbox = (HWND)wParam, msghwnd;
2312         char text[64];
2313 
2314         if (msgbox)
2315         {
2316             text[0] = 0;
2317             GetWindowTextA(msgbox, text, sizeof(text));
2318             ok(!strcmp(text, "MSGBOX caption"), "Unexpected window text \"%s\"\n", text);
2319 
2320             msghwnd = GetDlgItem(msgbox, 0xffff);
2321             ok(msghwnd != NULL, "Expected static control\n");
2322 
2323             text[0] = 0;
2324             GetWindowTextA(msghwnd, text, sizeof(text));
2325             ok(!strcmp(text, "Text"), "Unexpected window text \"%s\"\n", text);
2326 
2327             SendDlgItemMessageA(msgbox, IDCANCEL, WM_LBUTTONDOWN, 0, 0);
2328             SendDlgItemMessageA(msgbox, IDCANCEL, WM_LBUTTONUP, 0, 0);
2329         }
2330     }
2331 
2332     return CallNextHookEx(NULL, code, wParam, lParam);
2333 }
2334 
2335 struct create_window_params
2336 {
2337     BOOL owner;
2338     char caption[64];
2339     DWORD style;
2340 };
2341 
2342 static DWORD WINAPI create_window_thread(void *param)
2343 {
2344     struct create_window_params *p = param;
2345     HWND owner = 0;
2346 
2347     if (p->owner)
2348     {
2349         owner = CreateWindowExA(0, "Static", NULL, WS_POPUP, 10, 10, 10, 10, 0, 0, 0, NULL);
2350         ok(owner != 0, "failed to create owner window\n");
2351     }
2352 
2353     MessageBoxA(owner, NULL, p->caption, p->style);
2354 
2355     if (owner) DestroyWindow(owner);
2356 
2357     return 0;
2358 }
2359 
2360 static HWND wait_for_window(const char *caption)
2361 {
2362     HWND hwnd;
2363     DWORD timeout = 0;
2364 
2365     for (;;)
2366     {
2367         hwnd = FindWindowA(NULL, caption);
2368         if (hwnd) break;
2369 
2370         Sleep(50);
2371         timeout += 50;
2372         if (timeout > 3000)
2373         {
2374             ok(0, "failed to wait for a window %s\n", caption);
2375             break;
2376         }
2377     }
2378 
2379     Sleep(50);
2380     return hwnd;
2381 }
2382 
2383 static void test_MessageBox(void)
2384 {
2385     static const struct
2386     {
2387         DWORD mb_style;
2388         DWORD ex_style;
2389     } test[] =
2390     {
2391         { MB_OK, 0 },
2392         { MB_OK | MB_TASKMODAL, 0 },
2393         { MB_OK | MB_SYSTEMMODAL, WS_EX_TOPMOST },
2394     };
2395     struct create_window_params params;
2396     HANDLE thread;
2397     DWORD tid, i;
2398     HHOOK hook;
2399     int ret;
2400 
2401     hook = SetWindowsHookExA(WH_CBT, msgbox_hook_proc, NULL, GetCurrentThreadId());
2402 
2403     ret = MessageBoxA(NULL, "Text", "MSGBOX caption", MB_OKCANCEL);
2404     ok(ret == IDCANCEL, "got %d\n", ret);
2405 
2406     UnhookWindowsHookEx(hook);
2407 
2408     sprintf(params.caption, "pid %08x, tid %08x, time %08x",
2409             GetCurrentProcessId(), GetCurrentThreadId(), GetCurrentTime());
2410 
2411     params.owner = FALSE;
2412 
2413     for (i = 0; i < sizeof(test)/sizeof(test[0]); i++)
2414     {
2415         HWND hwnd;
2416         DWORD ex_style;
2417 
2418         params.style = test[i].mb_style;
2419 
2420         thread = CreateThread(NULL, 0, create_window_thread, &params, 0, &tid);
2421 
2422         hwnd = wait_for_window(params.caption);
2423         ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE);
2424         ok((ex_style & WS_EX_TOPMOST) == test[i].ex_style, "%d: got window ex_style %#x\n", i, ex_style);
2425 
2426         PostMessageA(hwnd, WM_COMMAND, IDCANCEL, 0);
2427 
2428         ok(WaitForSingleObject(thread, 5000) != WAIT_TIMEOUT, "thread failed to terminate\n");
2429         CloseHandle(thread);
2430     }
2431 
2432     params.owner = TRUE;
2433 
2434     for (i = 0; i < sizeof(test)/sizeof(test[0]); i++)
2435     {
2436         HWND hwnd;
2437         DWORD ex_style;
2438 
2439         params.style = test[i].mb_style;
2440 
2441         thread = CreateThread(NULL, 0, create_window_thread, &params, 0, &tid);
2442 
2443         hwnd = wait_for_window(params.caption);
2444         ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE);
2445         ok((ex_style & WS_EX_TOPMOST) == test[i].ex_style, "%d: got window ex_style %#x\n", i, ex_style);
2446 
2447         PostMessageA(hwnd, WM_COMMAND, IDCANCEL, 0);
2448 
2449         ok(WaitForSingleObject(thread, 5000) != WAIT_TIMEOUT, "thread failed to terminate\n");
2450         CloseHandle(thread);
2451     }
2452 }
2453 
2454 static INT_PTR CALLBACK custom_test_dialog_proc(HWND hdlg, UINT msg, WPARAM wparam, LPARAM lparam)
2455 {
2456     if (msg == WM_INITDIALOG)
2457         EndDialog(hdlg, 0);
2458 
2459     return FALSE;
2460 }
2461 
2462 static void test_dialog_custom_data(void)
2463 {
2464     DialogBoxA(g_hinst, "CUSTOM_TEST_DIALOG", NULL, custom_test_dialog_proc);
2465 }
2466 
2467 START_TEST(dialog)
2468 {
2469     g_hinst = GetModuleHandleA (0);
2470 
2471     if (!RegisterWindowClasses()) assert(0);
2472 
2473     test_dialog_custom_data();
2474     test_GetNextDlgItem();
2475     test_IsDialogMessage();
2476     test_WM_NEXTDLGCTL();
2477     test_focus();
2478     test_GetDlgItem();
2479     test_GetDlgItemText();
2480     test_DialogBoxParam();
2481     test_DisabledDialogTest();
2482     test_MessageBoxFontTest();
2483     test_SaveRestoreFocus();
2484     test_timer_message();
2485     test_MessageBox();
2486     test_MessageBox_WM_COPY_Test();
2487 }
2488