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