Implement A->W call for GetNamedSecurityInfo.
[wine] / dlls / user / tests / msg.c
1 /*
2  * Unit tests for window message handling
3  *
4  * Copyright 1999 Ove Kaaven
5  * Copyright 2003 Dimitrie O. Paun
6  * Copyright 2004 Dmitry Timoshkov
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include <assert.h>
24 #include <stdarg.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30
31 #include "wine/test.h"
32
33 #define MDI_FIRST_CHILD_ID 2004
34
35 /*
36 FIXME: add tests for these
37 Window Edge Styles (Win31/Win95/98 look), in order of precedence:
38  WS_EX_DLGMODALFRAME: double border, WS_CAPTION allowed
39  WS_THICKFRAME: thick border
40  WS_DLGFRAME: double border, WS_CAPTION not allowed (but possibly shown anyway)
41  WS_BORDER (default for overlapped windows): single black border
42  none (default for child (and popup?) windows): no border
43 */
44
45 typedef enum { 
46     sent=0x1, posted=0x2, parent=0x4, wparam=0x8, lparam=0x10,
47     defwinproc=0x20, optional=0x40, hook=0x80
48 } msg_flags_t;
49
50 struct message {
51     UINT message;          /* the WM_* code */
52     msg_flags_t flags;     /* message props */
53     WPARAM wParam;         /* expected value of wParam */
54     LPARAM lParam;         /* expected value of lParam */
55 };
56
57 /* Empty message sequence */
58 static const struct message WmEmptySeq[] =
59 {
60     { 0 }
61 };
62 /* CreateWindow (for overlapped window, not initially visible) (16/32) */
63 static const struct message WmCreateOverlappedSeq[] = {
64     { HCBT_CREATEWND, hook },
65     { WM_GETMINMAXINFO, sent },
66     { WM_NCCREATE, sent },
67     { WM_NCCALCSIZE, sent|wparam, 0 },
68     { WM_CREATE, sent },
69     { 0 }
70 };
71 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
72  * for a not visible overlapped window.
73  */
74 static const struct message WmSWP_ShowOverlappedSeq[] = {
75     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
76     { WM_NCPAINT, sent|wparam|optional, 1 },
77     { WM_GETTEXT, sent|defwinproc|optional },
78     { WM_ERASEBKGND, sent|optional },
79     { HCBT_ACTIVATE, hook },
80     { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
81     { WM_WINDOWPOSCHANGING, sent|wparam|optional, 0 }, /* Win9x: SWP_NOSENDCHANGING */
82     { WM_ACTIVATEAPP, sent|wparam, 1 },
83     { WM_NCACTIVATE, sent|wparam, 1 },
84     { WM_GETTEXT, sent|defwinproc|optional },
85     { WM_ACTIVATE, sent|wparam, 1 },
86     { HCBT_SETFOCUS, hook },
87     { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
88     { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
89     { WM_NCPAINT, sent|wparam|optional, 1 },
90     { WM_GETTEXT, sent|defwinproc|optional },
91     { WM_ERASEBKGND, sent|optional },
92     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
93     { WM_NCCALCSIZE, sent|wparam|optional, 1 },
94     { WM_NCPAINT, sent|wparam|optional, 1 },
95     { WM_ERASEBKGND, sent|optional },
96     { 0 }
97 };
98 /* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE)
99  * for a visible overlapped window.
100  */
101 static const struct message WmSWP_HideOverlappedSeq[] = {
102     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
103     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
104     { 0 }
105 };
106 /* ShowWindow(SW_SHOW) for a not visible overlapped window */
107 static const struct message WmShowOverlappedSeq[] = {
108     { WM_SHOWWINDOW, sent|wparam, 1 },
109     { WM_NCPAINT, sent|wparam|optional, 1 },
110     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
111     { WM_NCPAINT, sent|wparam|optional, 1 },
112     { WM_GETTEXT, sent|defwinproc|optional },
113     { WM_ERASEBKGND, sent|optional },
114     { HCBT_ACTIVATE, hook },
115     { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
116     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
117     { WM_ACTIVATEAPP, sent|wparam, 1 },
118     { WM_NCACTIVATE, sent|wparam, 1 },
119     { WM_GETTEXT, sent|defwinproc|optional },
120     { WM_ACTIVATE, sent|wparam, 1 },
121     { HCBT_SETFOCUS, hook },
122     { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
123     { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
124     { WM_NCPAINT, sent|wparam|optional, 1 },
125     { WM_GETTEXT, sent|defwinproc|optional },
126     { WM_ERASEBKGND, sent|optional },
127     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
128     { WM_NCCALCSIZE, sent|optional },
129     { WM_NCPAINT, sent|optional },
130     { WM_ERASEBKGND, sent|optional },
131 #if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE
132        * messages. Does that mean that CreateWindow doesn't set initial
133        * window dimensions for overlapped windows?
134        */
135     { WM_SIZE, sent },
136     { WM_MOVE, sent },
137 #endif
138     { 0 }
139 };
140 /* ShowWindow(SW_HIDE) for a visible overlapped window */
141 static const struct message WmHideOverlappedSeq[] = {
142     { WM_SHOWWINDOW, sent|wparam, 0 },
143     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
144     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
145     { WM_SIZE, sent },
146     { WM_MOVE, sent },
147     { WM_NCACTIVATE, sent|wparam, 0 },
148     { WM_ACTIVATE, sent|wparam, 0 },
149     { WM_ACTIVATEAPP, sent|wparam, 0 },
150     { WM_KILLFOCUS, sent|wparam, 0 },
151     { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
152     { 0 }
153 };
154 /* ShowWindow(SW_HIDE) for an invisible overlapped window */
155 static const struct message WmHideInvisibleOverlappedSeq[] = {
156     { 0 }
157 };
158 /* DestroyWindow for a visible overlapped window */
159 static const struct message WmDestroyOverlappedSeq[] = {
160     { HCBT_DESTROYWND, hook },
161     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
162     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
163     { WM_NCACTIVATE, sent|wparam, 0 },
164     { WM_ACTIVATE, sent|wparam, 0 },
165     { WM_ACTIVATEAPP, sent|wparam, 0 },
166     { WM_KILLFOCUS, sent|wparam, 0 },
167     { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
168     { WM_DESTROY, sent },
169     { WM_NCDESTROY, sent },
170     { 0 }
171 };
172 /* CreateWindow (for a child popup window, not initially visible) */
173 static const struct message WmCreateChildPopupSeq[] = {
174     { HCBT_CREATEWND, hook },
175     { WM_NCCREATE, sent }, 
176     { WM_NCCALCSIZE, sent|wparam, 0 },
177     { WM_CREATE, sent },
178     { WM_SIZE, sent },
179     { WM_MOVE, sent },
180     { 0 }
181 };
182 /* CreateWindow (for a popup window, not initially visible,
183  * which sets WS_VISIBLE in WM_CREATE handler)
184  */
185 static const struct message WmCreateInvisiblePopupSeq[] = {
186     { HCBT_CREATEWND, hook },
187     { WM_NCCREATE, sent }, 
188     { WM_NCCALCSIZE, sent|wparam, 0 },
189     { WM_CREATE, sent },
190     { WM_STYLECHANGING, sent },
191     { WM_STYLECHANGED, sent },
192     { WM_SIZE, sent },
193     { WM_MOVE, sent },
194     { 0 }
195 };
196 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER)
197  * for a popup window with WS_VISIBLE style set
198  */
199 static const struct message WmShowVisiblePopupSeq_2[] = {
200     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
201     { 0 }
202 };
203 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
204  * for a popup window with WS_VISIBLE style set
205  */
206 static const struct message WmShowVisiblePopupSeq_3[] = {
207     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
208     { HCBT_ACTIVATE, hook },
209     { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
210     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
211     { WM_NCACTIVATE, sent|wparam, 1 },
212     { WM_ACTIVATE, sent|wparam, 1 },
213     { HCBT_SETFOCUS, hook },
214     { WM_KILLFOCUS, sent|parent },
215     { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
216     { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
217     { WM_SETFOCUS, sent|defwinproc },
218     { 0 }
219 };
220 /* CreateWindow (for child window, not initially visible) */
221 static const struct message WmCreateChildSeq[] = {
222     { HCBT_CREATEWND, hook },
223     { WM_NCCREATE, sent }, 
224     /* child is inserted into parent's child list after WM_NCCREATE returns */
225     { WM_NCCALCSIZE, sent|wparam, 0 },
226     { WM_CREATE, sent },
227     { WM_SIZE, sent },
228     { WM_MOVE, sent },
229     { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
230     { 0 }
231 };
232 /* CreateWindow (for maximized child window, not initially visible) */
233 static const struct message WmCreateMaximizedChildSeq[] = {
234     { HCBT_CREATEWND, hook },
235     { WM_NCCREATE, sent }, 
236     { WM_NCCALCSIZE, sent|wparam, 0 },
237     { WM_CREATE, sent },
238     { WM_SIZE, sent },
239     { WM_MOVE, sent },
240     { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE },
241     { WM_GETMINMAXINFO, sent },
242     { WM_WINDOWPOSCHANGING, sent },
243     { WM_NCCALCSIZE, sent|wparam, 1 },
244     { WM_WINDOWPOSCHANGED, sent },
245     { WM_SIZE, sent|defwinproc },
246     { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
247     { 0 }
248 };
249 /* CreateWindow (for a child window, initially visible) */
250 static const struct message WmCreateVisibleChildSeq[] = {
251     { HCBT_CREATEWND, hook },
252     { WM_NCCREATE, sent }, 
253     /* child is inserted into parent's child list after WM_NCCREATE returns */
254     { WM_NCCALCSIZE, sent|wparam, 0 },
255     { WM_CREATE, sent },
256     { WM_SIZE, sent },
257     { WM_MOVE, sent },
258     { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE },
259     { WM_SHOWWINDOW, sent|wparam, 1 },
260     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
261     { WM_ERASEBKGND, sent|parent|optional },
262     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
263     { 0 }
264 };
265 /* ShowWindow(SW_SHOW) for a not visible child window */
266 static const struct message WmShowChildSeq[] = {
267     { WM_SHOWWINDOW, sent|wparam, 1 },
268     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
269     { WM_ERASEBKGND, sent|parent|optional },
270     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
271     { 0 }
272 };
273 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE)
274  * for a not visible child window
275  */
276 static const struct message WmShowChildSeq_2[] = {
277     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
278     { WM_CHILDACTIVATE, sent },
279     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
280     { 0 }
281 };
282 /* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE)
283  * for a not visible child window
284  */
285 static const struct message WmShowChildSeq_3[] = {
286     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
287     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
288     { 0 }
289 };
290 /* DestroyWindow for a visible child window */
291 static const struct message WmDestroyChildSeq[] = {
292     { HCBT_DESTROYWND, hook },
293     { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY },
294     { WM_SHOWWINDOW, sent|wparam, 0 },
295     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
296     { WM_ERASEBKGND, sent|parent|optional },
297     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
298     { HCBT_SETFOCUS, hook }, /* set focus to a parent */
299     { WM_KILLFOCUS, sent },
300     { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
301     { WM_IME_SETCONTEXT, sent|wparam|parent|optional, 1 },
302     { WM_SETFOCUS, sent|parent },
303     { WM_DESTROY, sent },
304     { WM_DESTROY, sent|optional }, /* a bug in win2k sp4 ? */
305     { WM_NCDESTROY, sent },
306     { WM_NCDESTROY, sent|optional }, /* a bug in win2k sp4 ? */
307     { 0 }
308 };
309 /* Moving the mouse in nonclient area */
310 static const struct message WmMouseMoveInNonClientAreaSeq[] = { /* FIXME: add */
311     { WM_NCHITTEST, sent },
312     { WM_SETCURSOR, sent },
313     { WM_NCMOUSEMOVE, posted },
314     { 0 }
315 };
316 /* Moving the mouse in client area */
317 static const struct message WmMouseMoveInClientAreaSeq[] = { /* FIXME: add */
318     { WM_NCHITTEST, sent },
319     { WM_SETCURSOR, sent },
320     { WM_MOUSEMOVE, posted },
321     { 0 }
322 };
323 /* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
324 static const struct message WmDragTitleBarSeq[] = { /* FIXME: add */
325     { WM_NCLBUTTONDOWN, sent|wparam, HTCAPTION },
326     { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_MOVE+2 },
327     { WM_GETMINMAXINFO, sent|defwinproc },
328     { WM_ENTERSIZEMOVE, sent|defwinproc },
329     { WM_WINDOWPOSCHANGING, sent|defwinproc },
330     { WM_WINDOWPOSCHANGED, sent|defwinproc },
331     { WM_MOVE, sent|defwinproc },
332     { WM_EXITSIZEMOVE, sent|defwinproc },
333     { 0 }
334 };
335 /* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
336 static const struct message WmDragThickBordersBarSeq[] = { /* FIXME: add */
337     { WM_NCLBUTTONDOWN, sent|wparam, 0xd },
338     { WM_SYSCOMMAND, sent|defwinproc|wparam, 0xf004 },
339     { WM_GETMINMAXINFO, sent|defwinproc },
340     { WM_ENTERSIZEMOVE, sent|defwinproc },
341     { WM_SIZING, sent|defwinproc|wparam, 4}, /* one for each mouse movement */
342     { WM_WINDOWPOSCHANGING, sent|defwinproc },
343     { WM_GETMINMAXINFO, sent|defwinproc },
344     { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
345     { WM_NCPAINT, sent|defwinproc|wparam, 1 },
346     { WM_GETTEXT, sent|defwinproc },
347     { WM_ERASEBKGND, sent|defwinproc },
348     { WM_WINDOWPOSCHANGED, sent|defwinproc },
349     { WM_MOVE, sent|defwinproc },
350     { WM_SIZE, sent|defwinproc },
351     { WM_EXITSIZEMOVE, sent|defwinproc },
352     { 0 }
353 };
354 /* Resizing child window with MoveWindow (32) */
355 static const struct message WmResizingChildWithMoveWindowSeq[] = {
356     { WM_WINDOWPOSCHANGING, sent },
357     { WM_NCCALCSIZE, sent|wparam, 1 },
358     { WM_ERASEBKGND, sent|optional },
359     { WM_WINDOWPOSCHANGED, sent },
360     { WM_MOVE, sent|defwinproc },
361     { WM_SIZE, sent|defwinproc },
362     { 0 }
363 };
364 /* Clicking on inactive button */
365 static const struct message WmClickInactiveButtonSeq[] = { /* FIXME: add */
366     { WM_NCHITTEST, sent },
367     { WM_PARENTNOTIFY, sent|parent|wparam, WM_LBUTTONDOWN },
368     { WM_MOUSEACTIVATE, sent },
369     { WM_MOUSEACTIVATE, sent|parent|defwinproc },
370     { WM_SETCURSOR, sent },
371     { WM_SETCURSOR, sent|parent|defwinproc },
372     { WM_LBUTTONDOWN, posted },
373     { WM_KILLFOCUS, posted|parent },
374     { WM_SETFOCUS, posted },
375     { WM_CTLCOLORBTN, posted|parent },
376     { BM_SETSTATE, posted },
377     { WM_CTLCOLORBTN, posted|parent },
378     { WM_LBUTTONUP, posted },
379     { BM_SETSTATE, posted },
380     { WM_CTLCOLORBTN, posted|parent },
381     { WM_COMMAND, posted|parent },
382     { 0 }
383 };
384 /* Reparenting a button (16/32) */
385 /* The last child (button) reparented gets topmost for its new parent. */
386 static const struct message WmReparentButtonSeq[] = { /* FIXME: add */
387     { WM_SHOWWINDOW, sent|wparam, 0 },
388     { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
389     { WM_ERASEBKGND, sent|parent },
390     { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER },
391     { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE|SWP_NOZORDER },
392     { WM_CHILDACTIVATE, sent },
393     { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOREDRAW|SWP_NOZORDER },
394     { WM_MOVE, sent|defwinproc },
395     { WM_SHOWWINDOW, sent|wparam, 1 },
396     { 0 }
397 };
398 /* Creation of a custom dialog (32) */
399 static const struct message WmCreateCustomDialogSeq[] = {
400     { HCBT_CREATEWND, hook },
401     { WM_GETMINMAXINFO, sent },
402     { WM_NCCREATE, sent },
403     { WM_NCCALCSIZE, sent|wparam, 0 },
404     { WM_CREATE, sent },
405     { WM_SHOWWINDOW, sent|wparam, 1 },
406     { HCBT_ACTIVATE, hook },
407     { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
408     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
409     { WM_NCACTIVATE, sent|wparam, 1 },
410     { WM_GETTEXT, sent|optional|defwinproc },
411     { WM_GETICON, sent|optional|defwinproc },
412     { WM_GETICON, sent|optional|defwinproc },
413     { WM_GETICON, sent|optional|defwinproc },
414     { WM_GETTEXT, sent|optional|defwinproc },
415     { WM_ACTIVATE, sent|wparam, 1 },
416     { WM_KILLFOCUS, sent|parent },
417     { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
418     { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
419     { WM_SETFOCUS, sent },
420     { WM_GETDLGCODE, sent|defwinproc|wparam, 0 },
421     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
422     { WM_NCPAINT, sent|wparam, 1 },
423     { WM_GETTEXT, sent|optional|defwinproc },
424     { WM_GETICON, sent|optional|defwinproc },
425     { WM_GETICON, sent|optional|defwinproc },
426     { WM_GETICON, sent|optional|defwinproc },
427     { WM_GETTEXT, sent|optional|defwinproc },
428     { WM_ERASEBKGND, sent },
429     { WM_CTLCOLORDLG, sent|defwinproc },
430     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
431     { WM_GETTEXT, sent|optional },
432     { WM_GETICON, sent|optional },
433     { WM_GETICON, sent|optional },
434     { WM_GETICON, sent|optional },
435     { WM_GETTEXT, sent|optional },
436     { WM_NCCALCSIZE, sent|optional },
437     { WM_NCPAINT, sent|optional },
438     { WM_GETTEXT, sent|optional|defwinproc },
439     { WM_GETICON, sent|optional|defwinproc },
440     { WM_GETICON, sent|optional|defwinproc },
441     { WM_GETICON, sent|optional|defwinproc },
442     { WM_GETTEXT, sent|optional|defwinproc },
443     { WM_ERASEBKGND, sent|optional },
444     { WM_CTLCOLORDLG, sent|optional|defwinproc },
445     { WM_SIZE, sent },
446     { WM_MOVE, sent },
447     { 0 }
448 };
449 /* Calling EndDialog for a custom dialog (32) */
450 static const struct message WmEndCustomDialogSeq[] = {
451     { WM_WINDOWPOSCHANGING, sent },
452     { WM_WINDOWPOSCHANGED, sent },
453     { WM_GETTEXT, sent|optional },
454     { WM_GETICON, sent|optional },
455     { WM_GETICON, sent|optional },
456     { WM_GETICON, sent|optional },
457     { HCBT_ACTIVATE, hook },
458     { WM_NCACTIVATE, sent|wparam, 0 },
459     { WM_GETTEXT, sent|optional|defwinproc },
460     { WM_GETICON, sent|optional|defwinproc },
461     { WM_GETICON, sent|optional|defwinproc },
462     { WM_GETICON, sent|optional|defwinproc },
463     { WM_GETTEXT, sent|optional|defwinproc },
464     { WM_ACTIVATE, sent|wparam, 0 },
465     { WM_WINDOWPOSCHANGING, sent|optional },
466     { HCBT_SETFOCUS, hook },
467     { WM_KILLFOCUS, sent },
468     { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
469     { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 },
470     { WM_SETFOCUS, sent|parent|defwinproc },
471     { 0 }
472 };
473 /* Creation and destruction of a modal dialog (32) */
474 static const struct message WmModalDialogSeq[] = {
475     { WM_CANCELMODE, sent|parent },
476     { WM_KILLFOCUS, sent|parent },
477     { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 },
478     { WM_ENABLE, sent|parent|wparam, 0 },
479     { HCBT_CREATEWND, hook },
480     { WM_SETFONT, sent },
481     { WM_INITDIALOG, sent },
482     { WM_CHANGEUISTATE, sent|optional },
483     { WM_SHOWWINDOW, sent },
484     { HCBT_ACTIVATE, hook },
485     { WM_WINDOWPOSCHANGING, sent },
486     { WM_NCACTIVATE, sent|wparam, 1 },
487     { WM_GETICON, sent|optional },
488     { WM_GETICON, sent|optional },
489     { WM_GETICON, sent|optional },
490     { WM_GETTEXT, sent|optional },
491     { WM_ACTIVATE, sent|wparam, 1 },
492     { WM_WINDOWPOSCHANGING, sent },
493     { WM_NCPAINT, sent },
494     { WM_GETICON, sent|optional },
495     { WM_GETICON, sent|optional },
496     { WM_GETICON, sent|optional },
497     { WM_GETTEXT, sent|optional },
498     { WM_ERASEBKGND, sent },
499     { WM_CTLCOLORDLG, sent },
500     { WM_WINDOWPOSCHANGED, sent },
501     { WM_GETICON, sent|optional },
502     { WM_GETICON, sent|optional },
503     { WM_GETICON, sent|optional },
504     { WM_GETTEXT, sent|optional },
505     { WM_NCCALCSIZE, sent|optional },
506     { WM_NCPAINT, sent|optional },
507     { WM_GETICON, sent|optional },
508     { WM_GETICON, sent|optional },
509     { WM_GETICON, sent|optional },
510     { WM_GETTEXT, sent|optional },
511     { WM_ERASEBKGND, sent|optional },
512     { WM_CTLCOLORDLG, sent|optional },
513     { WM_PAINT, sent|optional },
514     { WM_CTLCOLORBTN, sent },
515     { WM_ENTERIDLE, sent|parent },
516     { WM_TIMER, sent },
517     { WM_ENABLE, sent|parent|wparam, 1 },
518     { WM_WINDOWPOSCHANGING, sent },
519     { WM_WINDOWPOSCHANGED, sent },
520     { WM_GETICON, sent|optional },
521     { WM_GETICON, sent|optional },
522     { WM_GETICON, sent|optional },
523     { WM_GETTEXT, sent|optional },
524     { HCBT_ACTIVATE, hook },
525     { WM_NCACTIVATE, sent|wparam, 0 },
526     { WM_GETICON, sent|optional },
527     { WM_GETICON, sent|optional },
528     { WM_GETICON, sent|optional },
529     { WM_GETTEXT, sent|optional },
530     { WM_ACTIVATE, sent|wparam, 0 },
531     { WM_WINDOWPOSCHANGING, sent|optional },
532     { HCBT_SETFOCUS, hook },
533     { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 },
534     { WM_SETFOCUS, sent|parent|defwinproc },
535     { HCBT_DESTROYWND, hook },
536     { WM_DESTROY, sent },
537     { WM_NCDESTROY, sent },
538     { 0 }
539 };
540 /* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */
541 static const struct message WmCreateModalDialogResizeSeq[] = { /* FIXME: add */
542     /* (inside dialog proc, handling WM_INITDIALOG) */
543     { WM_WINDOWPOSCHANGING, sent },
544     { WM_NCCALCSIZE, sent },
545     { WM_NCACTIVATE, sent|parent|wparam, 0 },
546     { WM_GETTEXT, sent|defwinproc },
547     { WM_ACTIVATE, sent|parent|wparam, 0 },
548     { WM_WINDOWPOSCHANGING, sent },
549     { WM_WINDOWPOSCHANGING, sent|parent },
550     { WM_NCACTIVATE, sent|wparam, 1 },
551     { WM_ACTIVATE, sent|wparam, 1 },
552     { WM_WINDOWPOSCHANGED, sent },
553     { WM_SIZE, sent|defwinproc },
554     /* (setting focus) */
555     { WM_SHOWWINDOW, sent|wparam, 1 },
556     { WM_WINDOWPOSCHANGING, sent },
557     { WM_NCPAINT, sent },
558     { WM_GETTEXT, sent|defwinproc },
559     { WM_ERASEBKGND, sent },
560     { WM_CTLCOLORDLG, sent|defwinproc },
561     { WM_WINDOWPOSCHANGED, sent },
562     { WM_PAINT, sent },
563     /* (bunch of WM_CTLCOLOR* for each control) */
564     { WM_PAINT, sent|parent },
565     { WM_ENTERIDLE, sent|parent|wparam, 0 },
566     { WM_SETCURSOR, sent|parent },
567     { 0 }
568 };
569 /* SetMenu for NonVisible windows with size change*/
570 static const struct message WmSetMenuNonVisibleSizeChangeSeq[] = {
571     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
572     { WM_NCCALCSIZE, sent|wparam, 1 },
573     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
574     { WM_MOVE, sent|defwinproc },
575     { WM_SIZE, sent|defwinproc },
576     { WM_GETICON, sent|optional },
577     { WM_GETICON, sent|optional },
578     { WM_GETICON, sent|optional },
579     { WM_GETTEXT, sent|optional },
580     { WM_NCCALCSIZE, sent|wparam|optional, 1 },
581     { 0 }
582 };
583 /* SetMenu for NonVisible windows with no size change */
584 static const struct message WmSetMenuNonVisibleNoSizeChangeSeq[] = {
585     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
586     { WM_NCCALCSIZE, sent|wparam, 1 },
587     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
588     { 0 }
589 };
590 /* SetMenu for Visible windows with size change */
591 static const struct message WmSetMenuVisibleSizeChangeSeq[] = {
592     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
593     { WM_NCCALCSIZE, sent|wparam, 1 },
594     { WM_NCPAINT, sent|wparam, 1 },
595     { WM_GETTEXT, sent|defwinproc|optional },
596     { WM_ERASEBKGND, sent|optional },
597     { WM_ACTIVATE, sent|optional },
598     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
599     { WM_MOVE, sent|defwinproc },
600     { WM_SIZE, sent|defwinproc },
601     { WM_NCCALCSIZE, sent|wparam|optional, 1 },
602     { WM_NCPAINT, sent|wparam|optional, 1 },
603     { WM_ERASEBKGND, sent|optional },
604     { 0 }
605 };
606 /* SetMenu for Visible windows with no size change */
607 static const struct message WmSetMenuVisibleNoSizeChangeSeq[] = {
608     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
609     { WM_NCCALCSIZE, sent|wparam, 1 },
610     { WM_NCPAINT, sent|wparam, 1 },
611     { WM_GETTEXT, sent|defwinproc|optional },
612     { WM_ERASEBKGND, sent|optional },
613     { WM_ACTIVATE, sent|optional },
614     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
615     { 0 }
616 };
617 /* DrawMenuBar for a visible window */
618 static const struct message WmDrawMenuBarSeq[] =
619 {
620     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
621     { WM_NCCALCSIZE, sent|wparam, 1 },
622     { WM_NCPAINT, sent|wparam, 1 },
623     { WM_GETTEXT, sent|defwinproc|optional },
624     { WM_ERASEBKGND, sent|optional },
625     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
626     { 0 }
627 };
628
629 static const struct message WmSetRedrawFalseSeq[] =
630 {
631     { WM_SETREDRAW, sent|wparam, 0 },
632     { 0 }
633 };
634
635 static const struct message WmSetRedrawTrueSeq[] =
636 {
637     { WM_SETREDRAW, sent|wparam, 1 },
638     { 0 }
639 };
640
641 static const struct message WmEnableWindowSeq[] =
642 {
643     { WM_CANCELMODE, sent },
644     { WM_ENABLE, sent },
645     { 0 }
646 };
647
648 static const struct message WmGetScrollRangeSeq[] =
649 {
650     { SBM_GETRANGE, sent },
651     { 0 }
652 };
653 static const struct message WmGetScrollInfoSeq[] =
654 {
655     { SBM_GETSCROLLINFO, sent },
656     { 0 }
657 };
658 static const struct message WmSetScrollRangeSeq[] =
659 {
660     /* MSDN claims that Windows sends SBM_SETRANGE message, but win2k SP4
661        sends SBM_SETSCROLLINFO.
662      */
663     { SBM_SETSCROLLINFO, sent },
664     { 0 }
665 };
666 /* SetScrollRange for a window without a non-client area */
667 static const struct message WmSetScrollRangeHVSeq[] =
668 {
669     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
670     { WM_NCCALCSIZE, sent|wparam, 1 },
671     { WM_GETTEXT, sent|defwinproc|optional },
672     { WM_ERASEBKGND, sent|optional },
673     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
674     { 0 }
675 };
676 /* SetScrollRange for a window with a non-client area */
677 static const struct message WmSetScrollRangeHV_NC_Seq[] =
678 {
679     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
680     { WM_NCCALCSIZE, sent|wparam, 1 },
681     { WM_NCPAINT, sent|optional },
682     { WM_GETTEXT, sent|defwinproc|optional },
683     { WM_ERASEBKGND, sent|optional },
684     { WM_CTLCOLORDLG, sent|defwinproc|optional }, /* sent to a parent of the dialog */
685     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
686     { WM_SIZE, sent|defwinproc },
687     { 0 }
688 };
689
690 static int after_end_dialog;
691 static int sequence_cnt, sequence_size;
692 static struct message* sequence;
693
694 static void add_message(const struct message *msg)
695 {
696     if (!sequence) 
697     {
698         sequence_size = 10;
699         sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof (struct message) );
700     }
701     if (sequence_cnt == sequence_size) 
702     {
703         sequence_size *= 2;
704         sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof (struct message) );
705     }
706     assert(sequence);
707
708     sequence[sequence_cnt].message = msg->message;
709     sequence[sequence_cnt].flags = msg->flags;
710     sequence[sequence_cnt].wParam = msg->wParam;
711     sequence[sequence_cnt].lParam = msg->lParam;
712
713     sequence_cnt++;
714 }
715
716 static void flush_sequence()
717 {
718     HeapFree(GetProcessHeap(), 0, sequence);
719     sequence = 0;
720     sequence_cnt = sequence_size = 0;
721 }
722
723 static void ok_sequence(const struct message *expected, const char *context)
724 {
725     static const struct message end_of_sequence = { 0, 0, 0, 0 };
726     const struct message *actual;
727     
728     add_message(&end_of_sequence);
729
730     actual = sequence;
731
732     while (expected->message && actual->message)
733     {
734         trace("expected %04x - actual %04x\n", expected->message, actual->message);
735
736         if (expected->message == actual->message)
737         {
738             if (expected->flags & wparam)
739                  ok (expected->wParam == actual->wParam,
740                      "%s: in msg 0x%04x expecting wParam 0x%x got 0x%x\n",
741                      context, expected->message, expected->wParam, actual->wParam);
742             if (expected->flags & lparam)
743                  ok (expected->lParam == actual->lParam,
744                      "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n",
745                      context, expected->message, expected->lParam, actual->lParam);
746             ok ((expected->flags & defwinproc) == (actual->flags & defwinproc),
747                 "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n",
748                 context, expected->message, (expected->flags & defwinproc) ? "" : "NOT ");
749             ok ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)),
750                 "%s: the msg 0x%04x should have been %s\n",
751                 context, expected->message, (expected->flags & posted) ? "posted" : "sent");
752             ok ((expected->flags & parent) == (actual->flags & parent),
753                 "%s: the msg 0x%04x was expected in %s\n",
754                 context, expected->message, (expected->flags & parent) ? "parent" : "child");
755             ok ((expected->flags & hook) == (actual->flags & hook),
756                 "%s: the msg 0x%04x should have been sent by a hook\n",
757                 context, expected->message);
758             expected++;
759             actual++;
760         }
761         else if (expected->flags & optional)
762             expected++;
763         else
764         {
765           todo_wine {
766             ok (FALSE, "%s: the msg 0x%04x was expected, but got msg 0x%04x instead\n",
767                 context, expected->message, actual->message);
768             expected++;
769             actual++;
770           }
771         }
772     }
773
774     /* skip all optional trailing messages */
775     while (expected->message && (expected->flags & optional))
776         expected++;
777
778   todo_wine {
779     if (expected->message || actual->message)
780         ok (FALSE, "%s: the msg sequence is not complete: expected %04x - actual %04x\n",
781             context, expected->message, actual->message);
782   }
783
784     flush_sequence();
785 }
786
787 /******************************** MDI test **********************************/
788
789 /* CreateWindow for MDI frame window, initially visible */
790 static const struct message WmCreateMDIframeSeq[] = {
791     { HCBT_CREATEWND, hook },
792     { WM_GETMINMAXINFO, sent },
793     { WM_NCCREATE, sent },
794     { WM_NCCALCSIZE, sent|wparam, 0 },
795     { WM_CREATE, sent },
796     { WM_SHOWWINDOW, sent|wparam, 1 },
797     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
798     { HCBT_ACTIVATE, hook },
799     { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
800     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
801     { WM_WINDOWPOSCHANGED, sent|wparam|optional, 0 }, /* Win9x */
802     { WM_ACTIVATEAPP, sent|wparam, 1 },
803     { WM_NCACTIVATE, sent|wparam, 1 },
804     { WM_ACTIVATE, sent|wparam, 1 },
805     { HCBT_SETFOCUS, hook },
806     { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
807     { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
808     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
809     { WM_SIZE, sent },
810     { WM_MOVE, sent },
811     { 0 }
812 };
813 /* DestroyWindow for MDI frame window, initially visible */
814 static const struct message WmDestroyMDIframeSeq[] = {
815     { HCBT_DESTROYWND, hook },
816     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
817     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
818     { WM_NCACTIVATE, sent|wparam, 0 },
819     { WM_ACTIVATE, sent|wparam|optional, 0 }, /* Win9x */
820     { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, /* Win9x */
821     { WM_DESTROY, sent },
822     { WM_NCDESTROY, sent },
823     { 0 }
824 };
825 /* CreateWindow for MDI client window, initially visible */
826 static const struct message WmCreateMDIclientSeq[] = {
827     { HCBT_CREATEWND, hook },
828     { WM_NCCREATE, sent },
829     { WM_NCCALCSIZE, sent|wparam, 0 },
830     { WM_CREATE, sent },
831     { WM_SIZE, sent },
832     { WM_MOVE, sent },
833     { WM_PARENTNOTIFY, sent|wparam, WM_CREATE }, /* in MDI frame */
834     { WM_SHOWWINDOW, sent|wparam, 1 },
835     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
836     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
837     { 0 }
838 };
839 /* DestroyWindow for MDI client window, initially visible */
840 static const struct message WmDestroyMDIclientSeq[] = {
841     { HCBT_DESTROYWND, hook },
842     { WM_PARENTNOTIFY, sent|wparam, WM_DESTROY }, /* in MDI frame */
843     { WM_SHOWWINDOW, sent|wparam, 0 },
844     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
845     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
846     { WM_DESTROY, sent },
847     { WM_NCDESTROY, sent },
848     { 0 }
849 };
850 /* CreateWindow for MDI child window, initially visible */
851 static const struct message WmCreateMDIchildVisibleSeq[] = {
852     { HCBT_CREATEWND, hook },
853     { WM_NCCREATE, sent }, 
854     { WM_NCCALCSIZE, sent|wparam, 0 },
855     { WM_CREATE, sent },
856     { WM_SIZE, sent },
857     { WM_MOVE, sent },
858     /* Win2k sends wparam set to
859      * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
860      * while Win9x doesn't bother to set child window id according to
861      * CLIENTCREATESTRUCT.idFirstChild
862      */
863     { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
864     { WM_SHOWWINDOW, sent|wparam, 1 },
865     { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, /*SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER*/
866     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
867     { WM_MDIREFRESHMENU, sent/*|wparam|lparam, 0, 0*/ },
868     { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, /*SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE*/
869     { WM_CHILDACTIVATE, sent|wparam|lparam, 0, 0 },
870     { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, 0 }, /*SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE*/
871
872     /* Win9x: message sequence terminates here. */
873
874     { WM_NCACTIVATE, sent|wparam|defwinproc, 1 },
875     { HCBT_SETFOCUS, hook }, /* in MDI client */
876     { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
877     { WM_SETFOCUS, sent }, /* in MDI client */
878     { HCBT_SETFOCUS, hook },
879     { WM_KILLFOCUS, sent }, /* in MDI client */
880     { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
881     { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
882     { WM_SETFOCUS, sent|defwinproc },
883     { WM_MDIACTIVATE, sent|defwinproc },
884     { 0 }
885 };
886 /* DestroyWindow for MDI child window, initially visible */
887 static const struct message WmDestroyMDIchildVisibleSeq[] = {
888     { HCBT_DESTROYWND, hook },
889     /* Win2k sends wparam set to
890      * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
891      * while Win9x doesn't bother to set child window id according to
892      * CLIENTCREATESTRUCT.idFirstChild
893      */
894     { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
895     { WM_SHOWWINDOW, sent|wparam, 0 },
896     { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, /*SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE|SWP_NOZORDER*/
897     { WM_ERASEBKGND, sent|parent|optional },
898     { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
899
900     /* { WM_DESTROY, sent }
901      * Win9x: message sequence terminates here.
902      */
903
904     { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
905     { WM_KILLFOCUS, sent },
906     { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
907     { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
908     { WM_SETFOCUS, sent }, /* in MDI client */
909
910     { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
911     { WM_KILLFOCUS, sent }, /* in MDI client */
912     { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
913     { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
914     { WM_SETFOCUS, sent }, /* in MDI client */
915
916     { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
917     { WM_KILLFOCUS, sent },
918     { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
919     { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
920     { WM_SETFOCUS, sent }, /* in MDI client */
921
922     { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
923     { WM_KILLFOCUS, sent }, /* in MDI client */
924     { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
925     { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
926     { WM_SETFOCUS, sent }, /* in MDI client */
927
928     { WM_DESTROY, sent },
929
930     { HCBT_SETFOCUS, hook }, /* set focus to MDI client */
931     { WM_KILLFOCUS, sent },
932     { WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
933     { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, /* in MDI client */
934     { WM_SETFOCUS, sent }, /* in MDI client */
935
936     { HCBT_SETFOCUS, hook }, /* MDI client sets focus back to MDI child */
937     { WM_KILLFOCUS, sent }, /* in MDI client */
938     { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, /* in MDI client */
939     { WM_IME_SETCONTEXT, sent|wparam|optional, 1 },
940     { WM_SETFOCUS, sent }, /* in MDI client */
941
942     { WM_NCDESTROY, sent },
943     { 0 }
944 };
945 /* CreateWindow for MDI child window, initially invisible */
946 static const struct message WmCreateMDIchildInvisibleSeq[] = {
947     { HCBT_CREATEWND, hook },
948     { WM_NCCREATE, sent }, 
949     { WM_NCCALCSIZE, sent|wparam, 0 },
950     { WM_CREATE, sent },
951     { WM_SIZE, sent },
952     { WM_MOVE, sent },
953     /* Win2k sends wparam set to
954      * MAKEWPARAM(WM_CREATE, MDI_FIRST_CHILD_ID + nTotalCreated),
955      * while Win9x doesn't bother to set child window id according to
956      * CLIENTCREATESTRUCT.idFirstChild
957      */
958     { WM_PARENTNOTIFY, sent /*|wparam, WM_CREATE*/ }, /* in MDI client */
959     { 0 }
960 };
961 /* DestroyWindow for MDI child window, initially invisible */
962 static const struct message WmDestroyMDIchildInvisibleSeq[] = {
963     { HCBT_DESTROYWND, hook },
964     /* Win2k sends wparam set to
965      * MAKEWPARAM(WM_DESTROY, MDI_FIRST_CHILD_ID + nTotalCreated),
966      * while Win9x doesn't bother to set child window id according to
967      * CLIENTCREATESTRUCT.idFirstChild
968      */
969     { WM_PARENTNOTIFY, sent /*|wparam, WM_DESTROY*/ }, /* in MDI client */
970     { WM_DESTROY, sent },
971     { WM_NCDESTROY, sent },
972     { 0 }
973 };
974
975 static HWND mdi_client;
976 static WNDPROC old_mdi_client_proc;
977
978 static LRESULT WINAPI mdi_client_hook_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
979 {
980     struct message msg;
981
982     /* do not log painting messages */
983     if (message != WM_PAINT &&
984         message != WM_ERASEBKGND &&
985         message != WM_NCPAINT &&
986         message != WM_GETTEXT)
987     {
988         trace("mdi client: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
989
990         msg.message = message;
991         msg.flags = sent|wparam|lparam;
992         msg.wParam = wParam;
993         msg.lParam = lParam;
994         add_message(&msg);
995     }
996
997     return CallWindowProcA(old_mdi_client_proc, hwnd, message, wParam, lParam);
998 }
999
1000 static LRESULT WINAPI mdi_child_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1001 {
1002     static long defwndproc_counter = 0;
1003     LRESULT ret;
1004     struct message msg;
1005
1006     /* do not log painting messages */
1007     if (message != WM_PAINT &&
1008         message != WM_ERASEBKGND &&
1009         message != WM_NCPAINT &&
1010         message != WM_GETTEXT)
1011     {
1012         trace("mdi child: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1013
1014         switch (message)
1015         {
1016             case WM_WINDOWPOSCHANGING:
1017             case WM_WINDOWPOSCHANGED:
1018             {
1019                 WINDOWPOS *winpos = (WINDOWPOS *)lParam;
1020
1021                 trace("%s\n", (message == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1022                 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1023                       winpos->hwnd, winpos->hwndInsertAfter,
1024                       winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1025                 break;
1026             }
1027         }
1028
1029         msg.message = message;
1030         msg.flags = sent|wparam|lparam;
1031         if (defwndproc_counter) msg.flags |= defwinproc;
1032         msg.wParam = wParam;
1033         msg.lParam = lParam;
1034         add_message(&msg);
1035     }
1036
1037     defwndproc_counter++;
1038     ret = DefMDIChildProcA(hwnd, message, wParam, lParam);
1039     defwndproc_counter--;
1040
1041     return ret;
1042 }
1043
1044 static LRESULT WINAPI mdi_frame_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1045 {
1046     static long defwndproc_counter = 0;
1047     LRESULT ret;
1048     struct message msg;
1049
1050     /* do not log painting messages */
1051     if (message != WM_PAINT &&
1052         message != WM_ERASEBKGND &&
1053         message != WM_NCPAINT &&
1054         message != WM_GETTEXT)
1055     {
1056         trace("mdi frame: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1057
1058         msg.message = message;
1059         msg.flags = sent|wparam|lparam;
1060         if (defwndproc_counter) msg.flags |= defwinproc;
1061         msg.wParam = wParam;
1062         msg.lParam = lParam;
1063         add_message(&msg);
1064     }
1065
1066     defwndproc_counter++;
1067     ret = DefFrameProcA(hwnd, mdi_client, message, wParam, lParam);
1068     defwndproc_counter--;
1069
1070     return ret;
1071 }
1072
1073 static BOOL mdi_RegisterWindowClasses(void)
1074 {
1075     WNDCLASSA cls;
1076
1077     cls.style = 0;
1078     cls.lpfnWndProc = mdi_frame_wnd_proc;
1079     cls.cbClsExtra = 0;
1080     cls.cbWndExtra = 0;
1081     cls.hInstance = GetModuleHandleA(0);
1082     cls.hIcon = 0;
1083     cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
1084     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
1085     cls.lpszMenuName = NULL;
1086     cls.lpszClassName = "MDI_frame_class";
1087     if (!RegisterClassA(&cls)) return FALSE;
1088
1089     cls.lpfnWndProc = mdi_child_wnd_proc;
1090     cls.lpszClassName = "MDI_child_class";
1091     if (!RegisterClassA(&cls)) return FALSE;
1092
1093     if (!GetClassInfoA(0, "MDIClient", &cls)) assert(0);
1094     old_mdi_client_proc = cls.lpfnWndProc;
1095     cls.hInstance = GetModuleHandleA(0);
1096     cls.lpfnWndProc = mdi_client_hook_proc;
1097     cls.lpszClassName = "MDI_client_class";
1098     if (!RegisterClassA(&cls)) assert(0);
1099
1100     return TRUE;
1101 }
1102
1103 static void test_mdi_messages(void)
1104 {
1105     CLIENTCREATESTRUCT client_cs;
1106     HWND mdi_frame, mdi_child;
1107
1108     assert(mdi_RegisterWindowClasses());
1109
1110     flush_sequence();
1111
1112     trace("creating MDI frame window\n");
1113     mdi_frame = CreateWindowExA(0, "MDI_frame_class", "MDI frame window",
1114                                 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
1115                                 WS_MAXIMIZEBOX | WS_VISIBLE,
1116                                 100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
1117                                 GetDesktopWindow(), 0,
1118                                 GetModuleHandleA(0), NULL);
1119     assert(mdi_frame);
1120     ok_sequence(WmCreateMDIframeSeq, "Create MDI frame window");
1121
1122     trace("creating MDI client window\n");
1123     client_cs.hWindowMenu = 0;
1124     client_cs.idFirstChild = MDI_FIRST_CHILD_ID;
1125     mdi_client = CreateWindowExA(0, "MDI_client_class",
1126                                  NULL,
1127                                  WS_CHILD | WS_VISIBLE | MDIS_ALLCHILDSTYLES,
1128                                  0, 0, 0, 0,
1129                                  mdi_frame, 0, GetModuleHandleA(0), &client_cs);
1130     assert(mdi_client);
1131     ok_sequence(WmCreateMDIclientSeq, "Create visible MDI client window");
1132
1133     ok(GetFocus() == mdi_frame, "input focus should be on MDI frame not on %p\n", GetFocus());
1134
1135     SetFocus(0);
1136     flush_sequence();
1137
1138     trace("creating visible MDI child window\n");
1139     mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1140                                 WS_CHILD | WS_VISIBLE,
1141                                 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1142                                 mdi_client, 0, GetModuleHandleA(0), NULL);
1143     assert(mdi_child);
1144     ok_sequence(WmCreateMDIchildVisibleSeq, "Create visible MDI child window");
1145
1146     ok(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE, "MDI child should be visible\n");
1147     ok(IsWindowVisible(mdi_child), "MDI child should be visible\n");
1148
1149     DestroyWindow(mdi_child);
1150     ok_sequence(WmDestroyMDIchildVisibleSeq, "Destroy visible MDI child window");
1151
1152     SetFocus(0);
1153     flush_sequence();
1154
1155     trace("creating invisible MDI child window\n");
1156     mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_class", "MDI child",
1157                                 WS_CHILD,
1158                                 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
1159                                 mdi_client, 0, GetModuleHandleA(0), NULL);
1160     assert(mdi_child);
1161     ok_sequence(WmCreateMDIchildInvisibleSeq, "Create invisible MDI child window");
1162
1163     ok(!(GetWindowLongA(mdi_child, GWL_STYLE) & WS_VISIBLE), "MDI child should not be visible\n");
1164     ok(!IsWindowVisible(mdi_child), "MDI child should not be visible\n");
1165
1166     DestroyWindow(mdi_child);
1167     ok_sequence(WmDestroyMDIchildInvisibleSeq, "Destroy invisible MDI child window");
1168
1169     DestroyWindow(mdi_client);
1170     ok_sequence(WmDestroyMDIclientSeq, "Destroy MDI client window");
1171
1172     DestroyWindow(mdi_frame);
1173     ok_sequence(WmDestroyMDIframeSeq, "Destroy MDI frame window");
1174 }
1175 /************************* End of MDI test **********************************/
1176
1177 static void test_WM_SETREDRAW(HWND hwnd)
1178 {
1179     DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
1180
1181     flush_sequence();
1182
1183     SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0);
1184     ok_sequence(WmSetRedrawFalseSeq, "SetRedraw:FALSE");
1185
1186     ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should NOT be set\n");
1187     ok(!IsWindowVisible(hwnd), "IsWindowVisible() should return FALSE\n");
1188
1189     flush_sequence();
1190     SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0);
1191     ok_sequence(WmSetRedrawTrueSeq, "SetRedraw:TRUE");
1192
1193     ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
1194     ok(IsWindowVisible(hwnd), "IsWindowVisible() should return TRUE\n");
1195
1196     /* restore original WS_VISIBLE state */
1197     SetWindowLongA(hwnd, GWL_STYLE, style);
1198
1199     flush_sequence();
1200 }
1201
1202 static INT_PTR CALLBACK TestModalDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1203 {
1204     struct message msg;
1205
1206     trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1207
1208     msg.message = message;
1209     msg.flags = sent|wparam|lparam;
1210     msg.wParam = wParam;
1211     msg.lParam = lParam;
1212     add_message(&msg);
1213
1214     if (message == WM_INITDIALOG) SetTimer( hwnd, 1, 100, NULL );
1215     if (message == WM_TIMER) EndDialog( hwnd, 0 );
1216     return 0;
1217 }
1218
1219 static void test_hv_scroll_1(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
1220 {
1221     DWORD style, exstyle;
1222     INT xmin, xmax;
1223
1224     exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1225     style = GetWindowLongA(hwnd, GWL_STYLE);
1226     /* do not be confused by WS_DLGFRAME set */
1227     if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
1228
1229     if (clear) ok(style & clear, "style %08lx should be set\n", clear);
1230     if (set) ok(!(style & set), "style %08lx should not be set\n", set);
1231
1232     ok(SetScrollRange(hwnd, ctl, min, max, FALSE), "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
1233     if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
1234         ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollRange(SB_HORZ/SB_VERT) NC");
1235     else
1236         ok_sequence(WmSetScrollRangeHVSeq, "SetScrollRange(SB_HORZ/SB_VERT)");
1237
1238     style = GetWindowLongA(hwnd, GWL_STYLE);
1239     if (set) ok(style & set, "style %08lx should be set\n", set);
1240     if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
1241
1242     /* a subsequent call should do nothing */
1243     ok(SetScrollRange(hwnd, ctl, min, max, FALSE), "SetScrollRange(%d) error %ld\n", ctl, GetLastError());
1244     ok_sequence(WmEmptySeq, "SetScrollRange(SB_HORZ/SB_VERT)");
1245
1246     xmin = 0xdeadbeef;
1247     xmax = 0xdeadbeef;
1248     trace("Ignore GetScrollRange error below if you are on Win9x\n");
1249     ok(GetScrollRange(hwnd, ctl, &xmin, &xmax), "GetScrollRange(%d) error %ld\n", ctl, GetLastError());
1250     ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT)");
1251     ok(xmin == min, "unexpected min scroll value %d\n", xmin);
1252     ok(xmax == max, "unexpected max scroll value %d\n", xmax);
1253 }
1254
1255 static void test_hv_scroll_2(HWND hwnd, INT ctl, DWORD clear, DWORD set, INT min, INT max)
1256 {
1257     DWORD style, exstyle;
1258     SCROLLINFO si;
1259
1260     exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1261     style = GetWindowLongA(hwnd, GWL_STYLE);
1262     /* do not be confused by WS_DLGFRAME set */
1263     if ((style & WS_CAPTION) == WS_CAPTION) style &= ~WS_CAPTION;
1264
1265     if (clear) ok(style & clear, "style %08lx should be set\n", clear);
1266     if (set) ok(!(style & set), "style %08lx should not be set\n", set);
1267
1268     si.cbSize = sizeof(si);
1269     si.fMask = SIF_RANGE;
1270     si.nMin = min;
1271     si.nMax = max;
1272     SetScrollInfo(hwnd, ctl, &si, TRUE);
1273     if ((style & (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME)) || (exstyle & WS_EX_DLGMODALFRAME))
1274         ok_sequence(WmSetScrollRangeHV_NC_Seq, "SetScrollInfo(SB_HORZ/SB_VERT) NC");
1275     else
1276         ok_sequence(WmSetScrollRangeHVSeq, "SetScrollInfo(SB_HORZ/SB_VERT)");
1277
1278     style = GetWindowLongA(hwnd, GWL_STYLE);
1279     if (set) ok(style & set, "style %08lx should be set\n", set);
1280     if (clear) ok(!(style & clear), "style %08lx should not be set\n", clear);
1281
1282     /* a subsequent call should do nothing */
1283     SetScrollInfo(hwnd, ctl, &si, TRUE);
1284     ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT)");
1285
1286     si.fMask = SIF_PAGE;
1287     si.nPage = 5;
1288     SetScrollInfo(hwnd, ctl, &si, FALSE);
1289     ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT)");
1290
1291     si.fMask = SIF_POS;
1292     si.nPos = max - 1;
1293     SetScrollInfo(hwnd, ctl, &si, FALSE);
1294     ok_sequence(WmEmptySeq, "SetScrollInfo(SB_HORZ/SB_VERT)");
1295
1296     si.fMask = SIF_RANGE;
1297     si.nMin = 0xdeadbeef;
1298     si.nMax = 0xdeadbeef;
1299     ok(GetScrollInfo(hwnd, ctl, &si), "GetScrollInfo error %ld\n", GetLastError());
1300     ok_sequence(WmEmptySeq, "GetScrollRange(SB_HORZ/SB_VERT)");
1301     ok(si.nMin == min, "unexpected min scroll value %d\n", si.nMin);
1302     ok(si.nMax == max, "unexpected max scroll value %d\n", si.nMax);
1303 }
1304
1305 /* Win9x sends WM_USER+xxx while and NT versions send SBM_xxx messages */
1306 static void test_scroll_messages(HWND hwnd)
1307 {
1308     SCROLLINFO si;
1309     INT min, max;
1310
1311     min = 0xdeadbeef;
1312     max = 0xdeadbeef;
1313     ok(GetScrollRange(hwnd, SB_CTL, &min, &max), "GetScrollRange error %ld\n", GetLastError());
1314     if (sequence->message != WmGetScrollRangeSeq[0].message)
1315         trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
1316     /* values of min and max are undefined */
1317     flush_sequence();
1318
1319     ok(SetScrollRange(hwnd, SB_CTL, 10, 150, FALSE), "SetScrollRange error %ld\n", GetLastError());
1320     if (sequence->message != WmSetScrollRangeSeq[0].message)
1321         trace("SetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
1322     flush_sequence();
1323
1324     min = 0xdeadbeef;
1325     max = 0xdeadbeef;
1326     ok(GetScrollRange(hwnd, SB_CTL, &min, &max), "GetScrollRange error %ld\n", GetLastError());
1327     if (sequence->message != WmGetScrollRangeSeq[0].message)
1328         trace("GetScrollRange(SB_CTL) generated unknown message %04x\n", sequence->message);
1329     /* values of min and max are undefined */
1330     flush_sequence();
1331
1332     si.cbSize = sizeof(si);
1333     si.fMask = SIF_RANGE;
1334     si.nMin = 20;
1335     si.nMax = 160;
1336     SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
1337     if (sequence->message != WmSetScrollRangeSeq[0].message)
1338         trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
1339     flush_sequence();
1340
1341     si.fMask = SIF_PAGE;
1342     si.nPage = 10;
1343     SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
1344     if (sequence->message != WmSetScrollRangeSeq[0].message)
1345         trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
1346     flush_sequence();
1347
1348     si.fMask = SIF_POS;
1349     si.nPos = 20;
1350     SetScrollInfo(hwnd, SB_CTL, &si, FALSE);
1351     if (sequence->message != WmSetScrollRangeSeq[0].message)
1352         trace("SetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
1353     flush_sequence();
1354
1355     si.fMask = SIF_RANGE;
1356     si.nMin = 0xdeadbeef;
1357     si.nMax = 0xdeadbeef;
1358     ok(GetScrollInfo(hwnd, SB_CTL, &si), "GetScrollInfo error %ld\n", GetLastError());
1359     if (sequence->message != WmGetScrollInfoSeq[0].message)
1360         trace("GetScrollInfo(SB_CTL) generated unknown message %04x\n", sequence->message);
1361     /* values of min and max are undefined */
1362     flush_sequence();
1363
1364     /* set WS_HSCROLL */
1365     test_hv_scroll_1(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
1366     /* clear WS_HSCROLL */
1367     test_hv_scroll_1(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
1368
1369     /* set WS_HSCROLL */
1370     test_hv_scroll_2(hwnd, SB_HORZ, 0, WS_HSCROLL, 10, 150);
1371     /* clear WS_HSCROLL */
1372     test_hv_scroll_2(hwnd, SB_HORZ, WS_HSCROLL, 0, 0, 0);
1373
1374     /* set WS_VSCROLL */
1375     test_hv_scroll_1(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
1376     /* clear WS_VSCROLL */
1377     test_hv_scroll_1(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
1378
1379     /* set WS_VSCROLL */
1380     test_hv_scroll_2(hwnd, SB_VERT, 0, WS_VSCROLL, 10, 150);
1381     /* clear WS_VSCROLL */
1382     test_hv_scroll_2(hwnd, SB_VERT, WS_VSCROLL, 0, 0, 0);
1383 }
1384
1385 /* test if we receive the right sequence of messages */
1386 static void test_messages(void)
1387 {
1388     HWND hwnd, hparent, hchild;
1389     HWND hchild2, hbutton;
1390     HMENU hmenu;
1391
1392     hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
1393                            100, 100, 200, 200, 0, 0, 0, NULL);
1394     ok (hwnd != 0, "Failed to create overlapped window\n");
1395     ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped");
1396
1397     /* test ShowWindow(SW_HIDE) on a newly created invisible window */
1398     ok( ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow: window was visible\n" );
1399     ok_sequence(WmHideInvisibleOverlappedSeq, "ShowWindow(SW_HIDE):overlapped, invisible");
1400
1401     /* test WM_SETREDRAW on a not visible top level window */
1402     test_WM_SETREDRAW(hwnd);
1403
1404     SetWindowPos(hwnd, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
1405     ok_sequence(WmSWP_ShowOverlappedSeq, "SetWindowPos:SWP_SHOWWINDOW:overlapped");
1406     ok(IsWindowVisible(hwnd), "window should be visible at this point\n");
1407
1408     ok(GetActiveWindow() == hwnd, "window should be active\n");
1409     ok(GetFocus() == hwnd, "window should have input focus\n");
1410     ShowWindow(hwnd, SW_HIDE);
1411     ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped");
1412     
1413     ShowWindow(hwnd, SW_SHOW);
1414     ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped");
1415
1416     ok(GetActiveWindow() == hwnd, "window should be active\n");
1417     ok(GetFocus() == hwnd, "window should have input focus\n");
1418     SetWindowPos(hwnd, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE);
1419     ok_sequence(WmSWP_HideOverlappedSeq, "SetWindowPos:SWP_HIDEWINDOW:overlapped");
1420     ok(!IsWindowVisible(hwnd), "window should not be visible at this point\n");
1421
1422     /* test WM_SETREDRAW on a visible top level window */
1423     ShowWindow(hwnd, SW_SHOW);
1424     test_WM_SETREDRAW(hwnd);
1425
1426     trace("testing scroll APIs on a visible top level window %p\n", hwnd);
1427     test_scroll_messages(hwnd);
1428
1429     DestroyWindow(hwnd);
1430     ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped");
1431
1432     hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1433                               100, 100, 200, 200, 0, 0, 0, NULL);
1434     ok (hparent != 0, "Failed to create parent window\n");
1435     flush_sequence();
1436
1437     hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_MAXIMIZE,
1438                              0, 0, 10, 10, hparent, 0, 0, NULL);
1439     ok (hchild != 0, "Failed to create child window\n");
1440     ok_sequence(WmCreateMaximizedChildSeq, "CreateWindow:maximized child");
1441     DestroyWindow(hchild);
1442     flush_sequence();
1443
1444     hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
1445                              0, 0, 10, 10, hparent, 0, 0, NULL);
1446     ok (hchild != 0, "Failed to create child window\n");
1447     ok_sequence(WmCreateVisibleChildSeq, "CreateWindow:visible child");
1448
1449     trace("testing scroll APIs on a visible child window %p\n", hchild);
1450     test_scroll_messages(hchild);
1451
1452     DestroyWindow(hchild);
1453     flush_sequence();
1454
1455     hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD,
1456                              0, 0, 10, 10, hparent, 0, 0, NULL);
1457     ok (hchild != 0, "Failed to create child window\n");
1458     ok_sequence(WmCreateChildSeq, "CreateWindow:child");
1459     
1460     hchild2 = CreateWindowExA(0, "SimpleWindowClass", "Test child2", WS_CHILD,
1461                                100, 100, 50, 50, hparent, 0, 0, NULL);
1462     ok (hchild2 != 0, "Failed to create child2 window\n");
1463     flush_sequence();
1464
1465     hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILD,
1466                               0, 100, 50, 50, hchild, 0, 0, NULL);
1467     ok (hbutton != 0, "Failed to create button window\n");
1468
1469     /* test WM_SETREDRAW on a not visible child window */
1470     test_WM_SETREDRAW(hchild);
1471
1472     ShowWindow(hchild, SW_SHOW);
1473     ok_sequence(WmShowChildSeq, "ShowWindow:child");
1474
1475     /* test WM_SETREDRAW on a visible child window */
1476     test_WM_SETREDRAW(hchild);
1477
1478     MoveWindow(hchild, 10, 10, 20, 20, TRUE);
1479     ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child");
1480
1481     ShowWindow(hchild, SW_HIDE);
1482     flush_sequence();
1483     SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
1484     ok_sequence(WmShowChildSeq_2, "SetWindowPos:show_child_2");
1485
1486     ShowWindow(hchild, SW_HIDE);
1487     flush_sequence();
1488     SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
1489     ok_sequence(WmShowChildSeq_3, "SetWindowPos:show_child_3");
1490
1491     /* DestroyWindow sequence below expects that a child has focus */
1492     SetFocus(hchild);
1493     flush_sequence();
1494
1495     DestroyWindow(hchild);
1496     ok_sequence(WmDestroyChildSeq, "DestroyWindow:child");
1497     DestroyWindow(hchild2);
1498     DestroyWindow(hbutton);
1499
1500     flush_sequence();
1501     hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP,
1502                              0, 0, 100, 100, hparent, 0, 0, NULL);
1503     ok (hchild != 0, "Failed to create child popup window\n");
1504     ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup");
1505     DestroyWindow(hchild);
1506
1507     /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */
1508     flush_sequence();
1509     hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP,
1510                              0, 0, 100, 100, hparent, 0, 0, NULL);
1511     ok (hchild != 0, "Failed to create popup window\n");
1512     ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup");
1513     ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
1514     ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
1515     flush_sequence();
1516     ShowWindow(hchild, SW_SHOW);
1517     ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup");
1518     flush_sequence();
1519     SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
1520     ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2");
1521     flush_sequence();
1522     SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
1523     ok_sequence(WmShowVisiblePopupSeq_3, "SetWindowPos:show_visible_popup_3");
1524     DestroyWindow(hchild);
1525
1526     /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually
1527      * changes nothing in message sequences.
1528      */
1529     flush_sequence();
1530     hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE,
1531                              0, 0, 100, 100, hparent, 0, 0, NULL);
1532     ok (hchild != 0, "Failed to create popup window\n");
1533     ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup");
1534     ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n");
1535     ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n");
1536     flush_sequence();
1537     ShowWindow(hchild, SW_SHOW);
1538     ok_sequence(WmEmptySeq, "ShowWindow:show_visible_popup");
1539     flush_sequence();
1540     SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER);
1541     ok_sequence(WmShowVisiblePopupSeq_2, "SetWindowPos:show_visible_popup_2");
1542     DestroyWindow(hchild);
1543
1544     flush_sequence();
1545     hwnd = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME,
1546                            0, 0, 100, 100, hparent, 0, 0, NULL);
1547     ok(hwnd != 0, "Failed to create custom dialog window\n");
1548     ok_sequence(WmCreateCustomDialogSeq, "CreateCustomDialog");
1549
1550     trace("testing scroll APIs on a visible dialog %p\n", hwnd);
1551     test_scroll_messages(hwnd);
1552
1553     flush_sequence();
1554     after_end_dialog = 1;
1555     EndDialog( hwnd, 0 );
1556     ok_sequence(WmEndCustomDialogSeq, "EndCustomDialog");
1557
1558     DestroyWindow(hwnd);
1559     after_end_dialog = 0;
1560
1561     flush_sequence();
1562     DialogBoxA( 0, "TEST_DIALOG", hparent, TestModalDlgProcA );
1563     ok_sequence(WmModalDialogSeq, "ModalDialog");
1564
1565     DestroyWindow(hparent);
1566     flush_sequence();
1567
1568     /* Message sequence for SetMenu */
1569     hmenu = CreateMenu();
1570     ok (hmenu != 0, "Failed to create menu\n");
1571     ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n");
1572     hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW,
1573                            100, 100, 200, 200, 0, hmenu, 0, NULL);
1574     ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped");
1575     ok (SetMenu(hwnd, 0), "SetMenu\n");
1576     ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange");
1577     ok (SetMenu(hwnd, 0), "SetMenu\n");
1578     ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange");
1579     ShowWindow(hwnd, SW_SHOW);
1580     flush_sequence();
1581     ok (SetMenu(hwnd, 0), "SetMenu\n");
1582     ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange");
1583     ok (SetMenu(hwnd, hmenu), "SetMenu\n");
1584     ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange");
1585
1586     ok(DrawMenuBar(hwnd), "DrawMenuBar\n");
1587     ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar");
1588
1589     DestroyWindow(hwnd);
1590     flush_sequence();
1591
1592     /* Message sequence for EnableWindow */
1593     hparent = CreateWindowExA(0, "TestWindowClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
1594                               100, 100, 200, 200, 0, 0, 0, NULL);
1595     ok (hparent != 0, "Failed to create parent window\n");
1596     hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_VISIBLE,
1597                              0, 0, 10, 10, hparent, 0, 0, NULL);
1598     ok (hchild != 0, "Failed to create child window\n");
1599
1600     SetFocus(hchild);
1601     flush_sequence();
1602
1603     EnableWindow(hparent, FALSE);
1604     ok_sequence(WmEnableWindowSeq, "EnableWindow");
1605
1606     DestroyWindow(hparent);
1607     flush_sequence();
1608 }
1609
1610 static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1611 {
1612     static long defwndproc_counter = 0;
1613     LRESULT ret;
1614     struct message msg;
1615
1616     trace("%p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1617
1618     msg.message = message;
1619     msg.flags = sent|wparam|lparam;
1620     if (defwndproc_counter) msg.flags |= defwinproc;
1621     msg.wParam = wParam;
1622     msg.lParam = lParam;
1623     add_message(&msg);
1624
1625     if (message == WM_GETMINMAXINFO && (GetWindowLongA(hwnd, GWL_STYLE) & WS_CHILD))
1626     {
1627         HWND parent = GetParent(hwnd);
1628         RECT rc;
1629         MINMAXINFO *minmax = (MINMAXINFO *)lParam;
1630
1631         GetClientRect(parent, &rc);
1632         trace("parent %p client size = (%ld x %ld)\n", parent, rc.right, rc.bottom);
1633
1634         trace("ptReserved = (%ld,%ld)\n"
1635               "ptMaxSize = (%ld,%ld)\n"
1636               "ptMaxPosition = (%ld,%ld)\n"
1637               "ptMinTrackSize = (%ld,%ld)\n"
1638               "ptMaxTrackSize = (%ld,%ld)\n",
1639               minmax->ptReserved.x, minmax->ptReserved.y,
1640               minmax->ptMaxSize.x, minmax->ptMaxSize.y,
1641               minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
1642               minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
1643               minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
1644
1645         ok(minmax->ptMaxSize.x == rc.right, "default width of maximized child %ld != %ld\n",
1646            minmax->ptMaxSize.x, rc.right);
1647         ok(minmax->ptMaxSize.y == rc.bottom, "default height of maximized child %ld != %ld\n",
1648            minmax->ptMaxSize.y, rc.bottom);
1649     }
1650
1651     defwndproc_counter++;
1652     ret = DefWindowProcA(hwnd, message, wParam, lParam);
1653     defwndproc_counter--;
1654
1655     return ret;
1656 }
1657
1658 static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1659 {
1660     static long defwndproc_counter = 0;
1661     LRESULT ret;
1662     struct message msg;
1663
1664     trace("popup: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1665
1666     msg.message = message;
1667     msg.flags = sent|wparam|lparam;
1668     if (defwndproc_counter) msg.flags |= defwinproc;
1669     msg.wParam = wParam;
1670     msg.lParam = lParam;
1671     add_message(&msg);
1672
1673     if (message == WM_CREATE)
1674     {
1675         DWORD style = GetWindowLongA(hwnd, GWL_STYLE) | WS_VISIBLE;
1676         SetWindowLongA(hwnd, GWL_STYLE, style);
1677     }
1678
1679     defwndproc_counter++;
1680     ret = DefWindowProcA(hwnd, message, wParam, lParam);
1681     defwndproc_counter--;
1682
1683     return ret;
1684 }
1685
1686 static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1687 {
1688     static long defwndproc_counter = 0;
1689     LRESULT ret;
1690     struct message msg;
1691
1692     trace("parent: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1693
1694     if (message == WM_PARENTNOTIFY || message == WM_CANCELMODE ||
1695         message == WM_SETFOCUS || message == WM_KILLFOCUS ||
1696         message == WM_ENABLE || message == WM_ENTERIDLE ||
1697         message == WM_IME_SETCONTEXT)
1698     {
1699         msg.message = message;
1700         msg.flags = sent|parent|wparam|lparam;
1701         if (defwndproc_counter) msg.flags |= defwinproc;
1702         msg.wParam = wParam;
1703         msg.lParam = lParam;
1704         add_message(&msg);
1705     }
1706
1707     defwndproc_counter++;
1708     ret = DefWindowProcA(hwnd, message, wParam, lParam);
1709     defwndproc_counter--;
1710
1711     return ret;
1712 }
1713
1714 static LRESULT WINAPI TestDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1715 {
1716     static long defwndproc_counter = 0;
1717     LRESULT ret;
1718     struct message msg;
1719
1720     trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam);
1721
1722     DefDlgProcA(hwnd, DM_SETDEFID, 1, 0);
1723     ret = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0);
1724     if (after_end_dialog)
1725         ok( ret == 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret );
1726     else
1727         ok(HIWORD(ret) == DC_HASDEFID, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret);
1728
1729     msg.message = message;
1730     msg.flags = sent|wparam|lparam;
1731     if (defwndproc_counter) msg.flags |= defwinproc;
1732     msg.wParam = wParam;
1733     msg.lParam = lParam;
1734     add_message(&msg);
1735
1736     defwndproc_counter++;
1737     ret = DefDlgProcA(hwnd, message, wParam, lParam);
1738     defwndproc_counter--;
1739
1740     return ret;
1741 }
1742
1743 static BOOL RegisterWindowClasses(void)
1744 {
1745     WNDCLASSA cls;
1746
1747     cls.style = 0;
1748     cls.lpfnWndProc = MsgCheckProcA;
1749     cls.cbClsExtra = 0;
1750     cls.cbWndExtra = 0;
1751     cls.hInstance = GetModuleHandleA(0);
1752     cls.hIcon = 0;
1753     cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
1754     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
1755     cls.lpszMenuName = NULL;
1756     cls.lpszClassName = "TestWindowClass";
1757     if(!RegisterClassA(&cls)) return FALSE;
1758
1759     cls.lpfnWndProc = PopupMsgCheckProcA;
1760     cls.lpszClassName = "TestPopupClass";
1761     if(!RegisterClassA(&cls)) return FALSE;
1762
1763     cls.lpfnWndProc = ParentMsgCheckProcA;
1764     cls.lpszClassName = "TestParentClass";
1765     if(!RegisterClassA(&cls)) return FALSE;
1766
1767     cls.lpfnWndProc = DefWindowProcA;
1768     cls.lpszClassName = "SimpleWindowClass";
1769     if(!RegisterClassA(&cls)) return FALSE;
1770
1771     ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n");
1772     cls.lpfnWndProc = TestDlgProcA;
1773     cls.lpszClassName = "TestDialogClass";
1774     if(!RegisterClassA(&cls)) return FALSE;
1775
1776     return TRUE;
1777 }
1778
1779 static HHOOK hCBT_hook;
1780
1781 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) 
1782
1783     char buf[256];
1784
1785     trace("CBT: %d, %08x, %08lx\n", nCode, wParam, lParam);
1786
1787     if (GetClassNameA((HWND)wParam, buf, sizeof(buf)))
1788     {
1789         if (!strcmp(buf, "TestWindowClass") ||
1790             !strcmp(buf, "TestParentClass") ||
1791             !strcmp(buf, "TestPopupClass") ||
1792             !strcmp(buf, "SimpleWindowClass") ||
1793             !strcmp(buf, "TestDialogClass") ||
1794             !strcmp(buf, "MDI_frame_class") ||
1795             !strcmp(buf, "MDI_client_class") ||
1796             !strcmp(buf, "MDI_child_class") ||
1797             !strcmp(buf, "#32770"))
1798         {
1799             struct message msg;
1800
1801             msg.message = nCode;
1802             msg.flags = hook;
1803             msg.wParam = wParam;
1804             msg.lParam = lParam;
1805             add_message(&msg);
1806         }
1807     }
1808     return CallNextHookEx(hCBT_hook, nCode, wParam, lParam);
1809 }
1810
1811 START_TEST(msg)
1812 {
1813     if (!RegisterWindowClasses()) assert(0);
1814
1815     hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
1816     assert(hCBT_hook);
1817
1818     test_messages();
1819     test_mdi_messages();
1820
1821     UnhookWindowsHookEx(hCBT_hook);
1822 }