1 /*
2  * PROJECT:     ReactOS api tests
3  * LICENSE:     LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4  * PURPOSE:     Test for Shell Hook
5  * COPYRIGHT:   Copyright 2020-2021 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
6  */
7 #include "shelltest.h"
8 #include "undocshell.h"
9 
10 static UINT s_uShellHookMsg = 0;
11 static HWND s_hwndHookViewer = NULL;
12 static HWND s_hwndParent = NULL;
13 static HWND s_hwndTarget = NULL;
14 static UINT s_nWindowCreatedCount = 0;
15 static WCHAR s_szName[] = L"ReactOS ShellHook testcase";
16 
17 static HWND
18 DoCreateWindow(HWND hwndParent, DWORD style, DWORD exstyle)
19 {
20     return CreateWindowExW(exstyle, s_szName, s_szName, style,
21                            CW_USEDEFAULT, CW_USEDEFAULT, 100, 100,
22                            hwndParent, NULL, GetModuleHandleW(NULL), NULL);
23 }
24 
25 struct TEST_ENTRY
26 {
27     INT lineno;
28     UINT nCount;
29     BOOL bIsChild;
30     BOOL bHasOwner;
31     DWORD style;
32     DWORD exstyle;
33     DWORD owner_style;
34     DWORD owner_exstyle;
35 };
36 
37 #define STYLE_0  WS_POPUP
38 #define STYLE_1  (WS_POPUP | WS_VISIBLE)
39 #define STYLE_2  (WS_OVERLAPPED | WS_VISIBLE)
40 
41 #define EXSTYLE_0  0
42 #define EXSTYLE_1  WS_EX_APPWINDOW
43 #define EXSTYLE_2  WS_EX_TOOLWINDOW
44 #define EXSTYLE_3  (WS_EX_APPWINDOW | WS_EX_TOOLWINDOW)
45 
46 #define TYPE_0 FALSE, FALSE
47 #define TYPE_1 FALSE, TRUE
48 #define TYPE_2 TRUE, TRUE
49 
50 static const TEST_ENTRY s_entries[] =
51 {
52     // TYPE_0
53     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_0 },
54     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_1 },
55     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_2 },
56     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_3 },
57     { __LINE__, 1, TYPE_0, STYLE_1, EXSTYLE_0 },
58     { __LINE__, 1, TYPE_0, STYLE_1, EXSTYLE_1 },
59     { __LINE__, 0, TYPE_0, STYLE_1, EXSTYLE_2 },
60     { __LINE__, 1, TYPE_0, STYLE_1, EXSTYLE_3 },
61     { __LINE__, 1, TYPE_0, STYLE_2, EXSTYLE_0 },
62     { __LINE__, 1, TYPE_0, STYLE_2, EXSTYLE_1 },
63     { __LINE__, 0, TYPE_0, STYLE_2, EXSTYLE_2 },
64     { __LINE__, 1, TYPE_0, STYLE_2, EXSTYLE_3 },
65 
66     // TYPE_1
67     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_0, STYLE_0, EXSTYLE_0 },
68     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_0, STYLE_0, EXSTYLE_1 },
69     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_0, STYLE_0, EXSTYLE_2 },
70     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_0, STYLE_0, EXSTYLE_3 },
71     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_0, STYLE_1, EXSTYLE_0 },
72     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_0, STYLE_1, EXSTYLE_1 },
73     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_0, STYLE_1, EXSTYLE_2 },
74     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_0, STYLE_1, EXSTYLE_3 },
75     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_0, STYLE_2, EXSTYLE_0 },
76     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_0, STYLE_2, EXSTYLE_1 },
77     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_0, STYLE_2, EXSTYLE_2 },
78     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_0, STYLE_2, EXSTYLE_3 },
79     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_1, STYLE_0, EXSTYLE_0 },
80     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_1, STYLE_0, EXSTYLE_1 },
81     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_1, STYLE_0, EXSTYLE_2 },
82     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_1, STYLE_0, EXSTYLE_3 },
83     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_1, STYLE_1, EXSTYLE_0 },
84     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_1, STYLE_1, EXSTYLE_1 },
85     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_1, STYLE_1, EXSTYLE_2 },
86     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_1, STYLE_1, EXSTYLE_3 },
87     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_1, STYLE_2, EXSTYLE_0 },
88     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_1, STYLE_2, EXSTYLE_1 },
89     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_1, STYLE_2, EXSTYLE_2 },
90     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_1, STYLE_2, EXSTYLE_3 },
91     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_2, STYLE_0, EXSTYLE_0 },
92     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_2, STYLE_0, EXSTYLE_1 },
93     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_2, STYLE_0, EXSTYLE_2 },
94     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_2, STYLE_0, EXSTYLE_3 },
95     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_2, STYLE_1, EXSTYLE_0 },
96     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_2, STYLE_1, EXSTYLE_1 },
97     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_2, STYLE_1, EXSTYLE_2 },
98     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_2, STYLE_1, EXSTYLE_3 },
99     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_2, STYLE_2, EXSTYLE_0 },
100     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_2, STYLE_2, EXSTYLE_1 },
101     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_2, STYLE_2, EXSTYLE_2 },
102     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_2, STYLE_2, EXSTYLE_3 },
103     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_3, STYLE_0, EXSTYLE_0 },
104     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_3, STYLE_0, EXSTYLE_1 },
105     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_3, STYLE_0, EXSTYLE_2 },
106     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_3, STYLE_0, EXSTYLE_3 },
107     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_3, STYLE_1, EXSTYLE_0 },
108     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_3, STYLE_1, EXSTYLE_1 },
109     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_3, STYLE_1, EXSTYLE_2 },
110     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_3, STYLE_1, EXSTYLE_3 },
111     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_3, STYLE_2, EXSTYLE_0 },
112     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_3, STYLE_2, EXSTYLE_1 },
113     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_3, STYLE_2, EXSTYLE_2 },
114     { __LINE__, 1, TYPE_1, STYLE_1, EXSTYLE_3, STYLE_2, EXSTYLE_3 },
115     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_0, STYLE_0, EXSTYLE_0 },
116     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_0, STYLE_0, EXSTYLE_1 },
117     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_0, STYLE_0, EXSTYLE_2 },
118     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_0, STYLE_0, EXSTYLE_3 },
119     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_0, STYLE_1, EXSTYLE_0 },
120     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_0, STYLE_1, EXSTYLE_1 },
121     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_0, STYLE_1, EXSTYLE_2 },
122     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_0, STYLE_1, EXSTYLE_3 },
123     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_0, STYLE_2, EXSTYLE_0 },
124     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_0, STYLE_2, EXSTYLE_1 },
125     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_0, STYLE_2, EXSTYLE_2 },
126     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_0, STYLE_2, EXSTYLE_3 },
127     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_1, STYLE_0, EXSTYLE_0 },
128     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_1, STYLE_0, EXSTYLE_1 },
129     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_1, STYLE_0, EXSTYLE_2 },
130     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_1, STYLE_0, EXSTYLE_3 },
131     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_1, STYLE_1, EXSTYLE_0 },
132     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_1, STYLE_1, EXSTYLE_1 },
133     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_1, STYLE_1, EXSTYLE_2 },
134     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_1, STYLE_1, EXSTYLE_3 },
135     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_1, STYLE_2, EXSTYLE_0 },
136     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_1, STYLE_2, EXSTYLE_1 },
137     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_1, STYLE_2, EXSTYLE_2 },
138     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_1, STYLE_2, EXSTYLE_3 },
139     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_2, STYLE_0, EXSTYLE_0 },
140     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_2, STYLE_0, EXSTYLE_1 },
141     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_2, STYLE_0, EXSTYLE_2 },
142     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_2, STYLE_0, EXSTYLE_3 },
143     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_2, STYLE_1, EXSTYLE_0 },
144     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_2, STYLE_1, EXSTYLE_1 },
145     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_2, STYLE_1, EXSTYLE_2 },
146     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_2, STYLE_1, EXSTYLE_3 },
147     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_2, STYLE_2, EXSTYLE_0 },
148     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_2, STYLE_2, EXSTYLE_1 },
149     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_2, STYLE_2, EXSTYLE_2 },
150     { __LINE__, 0, TYPE_1, STYLE_2, EXSTYLE_2, STYLE_2, EXSTYLE_3 },
151     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_3, STYLE_0, EXSTYLE_0 },
152     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_3, STYLE_0, EXSTYLE_1 },
153     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_3, STYLE_0, EXSTYLE_2 },
154     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_3, STYLE_0, EXSTYLE_3 },
155     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_3, STYLE_1, EXSTYLE_0 },
156     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_3, STYLE_1, EXSTYLE_1 },
157     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_3, STYLE_1, EXSTYLE_2 },
158     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_3, STYLE_1, EXSTYLE_3 },
159     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_3, STYLE_2, EXSTYLE_0 },
160     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_3, STYLE_2, EXSTYLE_1 },
161     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_3, STYLE_2, EXSTYLE_2 },
162     { __LINE__, 1, TYPE_1, STYLE_2, EXSTYLE_3, STYLE_2, EXSTYLE_3 },
163 
164     // TYPE_2
165     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_0, STYLE_0, EXSTYLE_0 },
166     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_0, STYLE_0, EXSTYLE_1 },
167     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_0, STYLE_0, EXSTYLE_2 },
168     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_0, STYLE_0, EXSTYLE_3 },
169     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_0, STYLE_1, EXSTYLE_0 },
170     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_0, STYLE_1, EXSTYLE_1 },
171     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_0, STYLE_1, EXSTYLE_2 },
172     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_0, STYLE_1, EXSTYLE_3 },
173     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_0, STYLE_2, EXSTYLE_0 },
174     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_0, STYLE_2, EXSTYLE_1 },
175     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_0, STYLE_2, EXSTYLE_2 },
176     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_0, STYLE_2, EXSTYLE_3 },
177     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_1, STYLE_0, EXSTYLE_0 },
178     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_1, STYLE_0, EXSTYLE_1 },
179     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_1, STYLE_0, EXSTYLE_2 },
180     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_1, STYLE_0, EXSTYLE_3 },
181     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_1, STYLE_1, EXSTYLE_0 },
182     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_1, STYLE_1, EXSTYLE_1 },
183     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_1, STYLE_1, EXSTYLE_2 },
184     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_1, STYLE_1, EXSTYLE_3 },
185     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_1, STYLE_2, EXSTYLE_0 },
186     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_1, STYLE_2, EXSTYLE_1 },
187     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_1, STYLE_2, EXSTYLE_2 },
188     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_1, STYLE_2, EXSTYLE_3 },
189     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_2, STYLE_0, EXSTYLE_0 },
190     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_2, STYLE_0, EXSTYLE_1 },
191     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_2, STYLE_0, EXSTYLE_2 },
192     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_2, STYLE_0, EXSTYLE_3 },
193     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_2, STYLE_1, EXSTYLE_0 },
194     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_2, STYLE_1, EXSTYLE_1 },
195     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_2, STYLE_1, EXSTYLE_2 },
196     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_2, STYLE_1, EXSTYLE_3 },
197     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_2, STYLE_2, EXSTYLE_0 },
198     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_2, STYLE_2, EXSTYLE_1 },
199     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_2, STYLE_2, EXSTYLE_2 },
200     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_2, STYLE_2, EXSTYLE_3 },
201     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_3, STYLE_0, EXSTYLE_0 },
202     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_3, STYLE_0, EXSTYLE_1 },
203     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_3, STYLE_0, EXSTYLE_2 },
204     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_3, STYLE_0, EXSTYLE_3 },
205     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_3, STYLE_1, EXSTYLE_0 },
206     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_3, STYLE_1, EXSTYLE_1 },
207     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_3, STYLE_1, EXSTYLE_2 },
208     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_3, STYLE_1, EXSTYLE_3 },
209     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_3, STYLE_2, EXSTYLE_0 },
210     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_3, STYLE_2, EXSTYLE_1 },
211     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_3, STYLE_2, EXSTYLE_2 },
212     { __LINE__, 1, TYPE_2, STYLE_1, EXSTYLE_3, STYLE_2, EXSTYLE_3 },
213     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_0, STYLE_0, EXSTYLE_0 },
214     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_0, STYLE_0, EXSTYLE_1 },
215     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_0, STYLE_0, EXSTYLE_2 },
216     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_0, STYLE_0, EXSTYLE_3 },
217     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_0, STYLE_1, EXSTYLE_0 },
218     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_0, STYLE_1, EXSTYLE_1 },
219     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_0, STYLE_1, EXSTYLE_2 },
220     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_0, STYLE_1, EXSTYLE_3 },
221     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_0, STYLE_2, EXSTYLE_0 },
222     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_0, STYLE_2, EXSTYLE_1 },
223     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_0, STYLE_2, EXSTYLE_2 },
224     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_0, STYLE_2, EXSTYLE_3 },
225     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_1, STYLE_0, EXSTYLE_0 },
226     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_1, STYLE_0, EXSTYLE_1 },
227     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_1, STYLE_0, EXSTYLE_2 },
228     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_1, STYLE_0, EXSTYLE_3 },
229     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_1, STYLE_1, EXSTYLE_0 },
230     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_1, STYLE_1, EXSTYLE_1 },
231     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_1, STYLE_1, EXSTYLE_2 },
232     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_1, STYLE_1, EXSTYLE_3 },
233     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_1, STYLE_2, EXSTYLE_0 },
234     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_1, STYLE_2, EXSTYLE_1 },
235     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_1, STYLE_2, EXSTYLE_2 },
236     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_1, STYLE_2, EXSTYLE_3 },
237     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_2, STYLE_0, EXSTYLE_0 },
238     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_2, STYLE_0, EXSTYLE_1 },
239     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_2, STYLE_0, EXSTYLE_2 },
240     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_2, STYLE_0, EXSTYLE_3 },
241     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_2, STYLE_1, EXSTYLE_0 },
242     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_2, STYLE_1, EXSTYLE_1 },
243     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_2, STYLE_1, EXSTYLE_2 },
244     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_2, STYLE_1, EXSTYLE_3 },
245     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_2, STYLE_2, EXSTYLE_0 },
246     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_2, STYLE_2, EXSTYLE_1 },
247     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_2, STYLE_2, EXSTYLE_2 },
248     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_2, STYLE_2, EXSTYLE_3 },
249     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_3, STYLE_0, EXSTYLE_0 },
250     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_3, STYLE_0, EXSTYLE_1 },
251     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_3, STYLE_0, EXSTYLE_2 },
252     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_3, STYLE_0, EXSTYLE_3 },
253     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_3, STYLE_1, EXSTYLE_0 },
254     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_3, STYLE_1, EXSTYLE_1 },
255     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_3, STYLE_1, EXSTYLE_2 },
256     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_3, STYLE_1, EXSTYLE_3 },
257     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_3, STYLE_2, EXSTYLE_0 },
258     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_3, STYLE_2, EXSTYLE_1 },
259     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_3, STYLE_2, EXSTYLE_2 },
260     { __LINE__, 0, TYPE_2, STYLE_2, EXSTYLE_3, STYLE_2, EXSTYLE_3 },
261 };
262 
263 static const size_t s_num_entries = sizeof(s_entries) / sizeof(s_entries[0]);
264 
265 static void DoTestEntryPart1(const TEST_ENTRY *pEntry)
266 {
267     ok(!pEntry->bIsChild || pEntry->bHasOwner,
268        "Line %d: bIsChild && !bHasOwner\n", pEntry->lineno);
269 
270     s_hwndParent = NULL;
271     if (pEntry->bIsChild || pEntry->bHasOwner)
272     {
273         s_hwndParent = DoCreateWindow(NULL, pEntry->owner_style, pEntry->owner_exstyle);
274     }
275 
276     DWORD style = pEntry->style;
277     DWORD exstyle = pEntry->exstyle;
278     if (pEntry->bIsChild)
279         style |= WS_CHILD;
280     else
281         style &= ~WS_CHILD;
282 
283     s_nWindowCreatedCount = 0;
284     s_hwndTarget = DoCreateWindow(s_hwndParent, style, exstyle);
285 }
286 
287 static void DoTestEntryPart2(const TEST_ENTRY *pEntry)
288 {
289     ok(s_nWindowCreatedCount == pEntry->nCount,
290        "Line %d: s_nWindowCreatedCount expected %u but was %u\n",
291        pEntry->lineno, pEntry->nCount, s_nWindowCreatedCount);
292 
293     PostMessageW(s_hwndTarget, WM_CLOSE, 0, 0);
294     s_hwndTarget = NULL;
295 
296     if (pEntry->bIsChild || pEntry->bHasOwner)
297     {
298         PostMessageW(s_hwndParent, WM_CLOSE, 0, 0);
299         s_hwndParent = NULL;
300     }
301 }
302 
303 static LRESULT CALLBACK
304 WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
305 {
306     if (uMsg == s_uShellHookMsg && uMsg != 0)
307     {
308         switch (wParam)
309         {
310             case HSHELL_WINDOWCREATED:
311                 if ((HWND)lParam != s_hwndTarget)
312                     break;
313                 ++s_nWindowCreatedCount;
314                 break;
315         }
316     }
317 #define ID_IGNITION 1000
318 #define ID_BURNING 2000
319     switch (uMsg)
320     {
321         case WM_CREATE:
322             PostMessageW(hwnd, WM_COMMAND, ID_IGNITION, 0);
323             return DefWindowProcW(hwnd, uMsg, wParam, lParam);
324         case WM_COMMAND:
325             if (hwnd != s_hwndHookViewer)
326                 break;
327 
328             if (ID_IGNITION <= wParam && wParam < ID_BURNING)
329             {
330                 INT i = (INT)wParam - ID_IGNITION;
331                 DoTestEntryPart1(&s_entries[i]);
332                 PostMessageW(hwnd, WM_COMMAND, ID_BURNING + i, 0);
333             }
334             else if (ID_BURNING <= wParam)
335             {
336                 INT i = (INT)wParam - ID_BURNING;
337                 DoTestEntryPart2(&s_entries[i]);
338                 ++i;
339                 if (i == (INT)s_num_entries)
340                 {
341                     PostQuitMessage(0);
342                     break;
343                 }
344                 PostMessageW(hwnd, WM_COMMAND, ID_IGNITION + i, 0);
345             }
346             break;
347         default:
348             return DefWindowProcW(hwnd, uMsg, wParam, lParam);
349     }
350     return 0;
351 }
352 
353 START_TEST(ShellHook)
354 {
355     WNDCLASSW wc;
356 
357     ZeroMemory(&wc, sizeof(wc));
358     wc.lpfnWndProc = WindowProc;
359     wc.hInstance = GetModuleHandleW(NULL);
360     wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
361     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
362     wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
363     wc.lpszClassName = s_szName;
364     if (!RegisterClassW(&wc))
365     {
366         skip("RegisterClassW failed\n");
367         return;
368     }
369 
370     s_hwndHookViewer = DoCreateWindow(NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0);
371     if (s_hwndHookViewer == NULL)
372     {
373         skip("CreateWindowExW failed\n");
374         return;
375     }
376 
377     s_uShellHookMsg = RegisterWindowMessageW(L"SHELLHOOK");
378     RegisterShellHookWindow(s_hwndHookViewer);
379 
380     MSG msg;
381     while (GetMessageW(&msg, NULL, 0, 0))
382     {
383         TranslateMessage(&msg);
384         DispatchMessageW(&msg);
385     }
386 
387     DeregisterShellHookWindow(s_hwndHookViewer);
388     DestroyWindow(s_hwndHookViewer);
389     s_hwndHookViewer = NULL;
390 }
391