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 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 DWORD s_dwFlags = 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     DWORD dwFlags;
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 
40 #define EXSTYLE_0  0
41 #define EXSTYLE_1  WS_EX_APPWINDOW
42 #define EXSTYLE_2  WS_EX_TOOLWINDOW
43 #define EXSTYLE_3  (WS_EX_APPWINDOW | WS_EX_TOOLWINDOW)
44 
45 #define TYPE_0 FALSE, FALSE
46 #define TYPE_1 FALSE, TRUE
47 #define TYPE_2 TRUE, TRUE
48 
49 static const TEST_ENTRY s_entries[] =
50 {
51     // STYLE_0, EXSTYLE_0
52     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_0 },
53     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_0, STYLE_0, EXSTYLE_0 },
54     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_0, STYLE_0, EXSTYLE_0 },
55 
56     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_0 },
57     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_0, STYLE_1, EXSTYLE_0 },
58     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_0, STYLE_1, EXSTYLE_0 },
59 
60     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_0 },
61     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_0, STYLE_0, EXSTYLE_1 },
62     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_0, STYLE_0, EXSTYLE_1 },
63 
64     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_0 },
65     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_0, STYLE_1, EXSTYLE_1 },
66     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_0, STYLE_1, EXSTYLE_1 },
67 
68     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_0 },
69     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_0, STYLE_0, EXSTYLE_2 },
70     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_0, STYLE_0, EXSTYLE_2 },
71 
72     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_0 },
73     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_0, STYLE_1, EXSTYLE_2 },
74     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_0, STYLE_1, EXSTYLE_2 },
75 
76     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_0 },
77     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_0, STYLE_0, EXSTYLE_3 },
78     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_0, STYLE_0, EXSTYLE_3 },
79 
80     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_0 },
81     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_0, STYLE_1, EXSTYLE_3 },
82     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_0, STYLE_1, EXSTYLE_3 },
83 
84     // STYLE_1, EXSTYLE_0
85     { __LINE__, 3, TYPE_0, STYLE_1, EXSTYLE_0 },
86     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_0, STYLE_0, EXSTYLE_0 },
87     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_0, STYLE_0, EXSTYLE_0 },
88 
89     { __LINE__, 3, TYPE_0, STYLE_1, EXSTYLE_0 },
90     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_0, STYLE_1, EXSTYLE_0 },
91     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_0, STYLE_1, EXSTYLE_0 },
92 
93     { __LINE__, 3, TYPE_0, STYLE_1, EXSTYLE_0 },
94     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_0, STYLE_0, EXSTYLE_1 },
95     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_0, STYLE_0, EXSTYLE_1 },
96 
97     { __LINE__, 3, TYPE_0, STYLE_1, EXSTYLE_0 },
98     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_0, STYLE_1, EXSTYLE_1 },
99     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_0, STYLE_1, EXSTYLE_1 },
100 
101     { __LINE__, 3, TYPE_0, STYLE_1, EXSTYLE_0 },
102     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_0, STYLE_0, EXSTYLE_2 },
103     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_0, STYLE_0, EXSTYLE_2 },
104 
105     { __LINE__, 3, TYPE_0, STYLE_1, EXSTYLE_0 },
106     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_0, STYLE_1, EXSTYLE_2 },
107     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_0, STYLE_1, EXSTYLE_2 },
108 
109     { __LINE__, 3, TYPE_0, STYLE_1, EXSTYLE_0 },
110     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_0, STYLE_0, EXSTYLE_3 },
111     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_0, STYLE_0, EXSTYLE_3 },
112 
113     { __LINE__, 3, TYPE_0, STYLE_1, EXSTYLE_0 },
114     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_0, STYLE_1, EXSTYLE_3 },
115     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_0, STYLE_1, EXSTYLE_3 },
116 
117     // STYLE_0, EXSTYLE_1
118     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_1 },
119     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_1, STYLE_0, EXSTYLE_0 },
120     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_1, STYLE_0, EXSTYLE_0 },
121 
122     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_1 },
123     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_1, STYLE_1, EXSTYLE_0 },
124     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_1, STYLE_1, EXSTYLE_0 },
125 
126     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_1 },
127     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_1, STYLE_0, EXSTYLE_1 },
128     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_1, STYLE_0, EXSTYLE_1 },
129 
130     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_1 },
131     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_1, STYLE_1, EXSTYLE_1 },
132     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_1, STYLE_1, EXSTYLE_1 },
133 
134     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_1 },
135     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_1, STYLE_0, EXSTYLE_2 },
136     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_1, STYLE_0, EXSTYLE_2 },
137 
138     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_1 },
139     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_1, STYLE_1, EXSTYLE_2 },
140     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_1, STYLE_1, EXSTYLE_2 },
141 
142     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_1 },
143     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_1, STYLE_0, EXSTYLE_3 },
144     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_1, STYLE_0, EXSTYLE_3 },
145 
146     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_1 },
147     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_1, STYLE_1, EXSTYLE_3 },
148     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_1, STYLE_1, EXSTYLE_3 },
149 
150     // STYLE_1, EXSTYLE_1
151     { __LINE__, 0xB, TYPE_0, STYLE_1, EXSTYLE_1 },
152     { __LINE__, 0xB, TYPE_1, STYLE_1, EXSTYLE_1, STYLE_0, EXSTYLE_0 },
153     { __LINE__, 0xB, TYPE_2, STYLE_1, EXSTYLE_1, STYLE_0, EXSTYLE_0 },
154 
155     { __LINE__, 0xB, TYPE_0, STYLE_1, EXSTYLE_1 },
156     { __LINE__, 0x1B, TYPE_1, STYLE_1, EXSTYLE_1, STYLE_1, EXSTYLE_0 },
157     { __LINE__, 0x1B, TYPE_2, STYLE_1, EXSTYLE_1, STYLE_1, EXSTYLE_0 },
158 
159     { __LINE__, 0xB, TYPE_0, STYLE_1, EXSTYLE_1 },
160     { __LINE__, 0x4B, TYPE_1, STYLE_1, EXSTYLE_1, STYLE_0, EXSTYLE_1 },
161     { __LINE__, 0x4B, TYPE_2, STYLE_1, EXSTYLE_1, STYLE_0, EXSTYLE_1 },
162 
163     { __LINE__, 0xB, TYPE_0, STYLE_1, EXSTYLE_1 },
164     { __LINE__, 0x5B, TYPE_1, STYLE_1, EXSTYLE_1, STYLE_1, EXSTYLE_1 },
165     { __LINE__, 0x5B, TYPE_2, STYLE_1, EXSTYLE_1, STYLE_1, EXSTYLE_1 },
166 
167     { __LINE__, 0xB, TYPE_0, STYLE_1, EXSTYLE_1 },
168     { __LINE__, 0x2B, TYPE_1, STYLE_1, EXSTYLE_1, STYLE_0, EXSTYLE_2 },
169     { __LINE__, 0x2B, TYPE_2, STYLE_1, EXSTYLE_1, STYLE_0, EXSTYLE_2 },
170 
171     { __LINE__, 0xB, TYPE_0, STYLE_1, EXSTYLE_1 },
172     { __LINE__, 0x3B, TYPE_1, STYLE_1, EXSTYLE_1, STYLE_1, EXSTYLE_2 },
173     { __LINE__, 0x3B, TYPE_2, STYLE_1, EXSTYLE_1, STYLE_1, EXSTYLE_2 },
174 
175     { __LINE__, 0xB, TYPE_0, STYLE_1, EXSTYLE_1 },
176     { __LINE__, 0x6B, TYPE_1, STYLE_1, EXSTYLE_1, STYLE_0, EXSTYLE_3 },
177     { __LINE__, 0x6B, TYPE_2, STYLE_1, EXSTYLE_1, STYLE_0, EXSTYLE_3 },
178 
179     { __LINE__, 0xB, TYPE_0, STYLE_1, EXSTYLE_1 },
180     { __LINE__, 0x7B, TYPE_1, STYLE_1, EXSTYLE_1, STYLE_1, EXSTYLE_3 },
181     { __LINE__, 0x7B, TYPE_2, STYLE_1, EXSTYLE_1, STYLE_1, EXSTYLE_3 },
182 
183     // STYLE_0, EXSTYLE_2
184     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_2 },
185     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_2, STYLE_0, EXSTYLE_0 },
186     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_2, STYLE_0, EXSTYLE_0 },
187 
188     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_2 },
189     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_2, STYLE_1, EXSTYLE_0 },
190     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_2, STYLE_1, EXSTYLE_0 },
191 
192     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_2 },
193     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_2, STYLE_0, EXSTYLE_2 },
194     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_2, STYLE_0, EXSTYLE_2 },
195 
196     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_2 },
197     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_2, STYLE_1, EXSTYLE_2 },
198     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_2, STYLE_1, EXSTYLE_2 },
199 
200     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_2 },
201     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_2, STYLE_0, EXSTYLE_2 },
202     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_2, STYLE_0, EXSTYLE_2 },
203 
204     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_2 },
205     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_2, STYLE_1, EXSTYLE_2 },
206     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_2, STYLE_1, EXSTYLE_2 },
207 
208     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_2 },
209     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_2, STYLE_0, EXSTYLE_3 },
210     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_2, STYLE_0, EXSTYLE_3 },
211 
212     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_2 },
213     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_2, STYLE_1, EXSTYLE_3 },
214     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_2, STYLE_1, EXSTYLE_3 },
215 
216     // STYLE_1, EXSTYLE_2
217     { __LINE__, 0, TYPE_0, STYLE_1, EXSTYLE_2 },
218     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_2, STYLE_0, EXSTYLE_0 },
219     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_2, STYLE_0, EXSTYLE_0 },
220 
221     { __LINE__, 0, TYPE_0, STYLE_1, EXSTYLE_2 },
222     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_2, STYLE_1, EXSTYLE_0 },
223     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_2, STYLE_1, EXSTYLE_0 },
224 
225     { __LINE__, 0, TYPE_0, STYLE_1, EXSTYLE_2 },
226     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_2, STYLE_0, EXSTYLE_1 },
227     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_2, STYLE_0, EXSTYLE_1 },
228 
229     { __LINE__, 0, TYPE_0, STYLE_1, EXSTYLE_2 },
230     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_2, STYLE_1, EXSTYLE_1 },
231     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_2, STYLE_1, EXSTYLE_1 },
232 
233     { __LINE__, 0, TYPE_0, STYLE_1, EXSTYLE_2 },
234     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_2, STYLE_0, EXSTYLE_2 },
235     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_2, STYLE_0, EXSTYLE_2 },
236 
237     { __LINE__, 0, TYPE_0, STYLE_1, EXSTYLE_2 },
238     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_2, STYLE_1, EXSTYLE_2 },
239     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_2, STYLE_1, EXSTYLE_2 },
240 
241     { __LINE__, 0, TYPE_0, STYLE_1, EXSTYLE_2 },
242     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_2, STYLE_0, EXSTYLE_3 },
243     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_2, STYLE_0, EXSTYLE_3 },
244 
245     { __LINE__, 0, TYPE_0, STYLE_1, EXSTYLE_2 },
246     { __LINE__, 0, TYPE_1, STYLE_1, EXSTYLE_2, STYLE_1, EXSTYLE_3 },
247     { __LINE__, 0, TYPE_2, STYLE_1, EXSTYLE_2, STYLE_1, EXSTYLE_3 },
248 
249     // STYLE_0, EXSTYLE_3
250     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_3 },
251     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_3, STYLE_0, EXSTYLE_0 },
252     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_3, STYLE_0, EXSTYLE_0 },
253 
254     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_3 },
255     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_3, STYLE_1, EXSTYLE_0 },
256     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_3, STYLE_1, EXSTYLE_0 },
257 
258     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_3 },
259     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_3, STYLE_0, EXSTYLE_2 },
260     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_3, STYLE_0, EXSTYLE_2 },
261 
262     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_3 },
263     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_3, STYLE_1, EXSTYLE_2 },
264     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_3, STYLE_1, EXSTYLE_2 },
265 
266     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_3 },
267     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_3, STYLE_0, EXSTYLE_2 },
268     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_3, STYLE_0, EXSTYLE_2 },
269 
270     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_3 },
271     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_3, STYLE_1, EXSTYLE_2 },
272     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_3, STYLE_1, EXSTYLE_2 },
273 
274     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_3 },
275     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_3, STYLE_0, EXSTYLE_3 },
276     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_3, STYLE_0, EXSTYLE_3 },
277 
278     { __LINE__, 0, TYPE_0, STYLE_0, EXSTYLE_3 },
279     { __LINE__, 0, TYPE_1, STYLE_0, EXSTYLE_3, STYLE_1, EXSTYLE_3 },
280     { __LINE__, 0, TYPE_2, STYLE_0, EXSTYLE_3, STYLE_1, EXSTYLE_3 },
281 
282     // STYLE_1, EXSTYLE_3
283     { __LINE__, 0xF, TYPE_0, STYLE_1, EXSTYLE_3 },
284     { __LINE__, 0xF, TYPE_1, STYLE_1, EXSTYLE_3, STYLE_0, EXSTYLE_0 },
285     { __LINE__, 0xF, TYPE_2, STYLE_1, EXSTYLE_3, STYLE_0, EXSTYLE_0 },
286 
287     { __LINE__, 0xF, TYPE_0, STYLE_1, EXSTYLE_3 },
288     { __LINE__, 0x1F, TYPE_1, STYLE_1, EXSTYLE_3, STYLE_1, EXSTYLE_0 },
289     { __LINE__, 0x1F, TYPE_2, STYLE_1, EXSTYLE_3, STYLE_1, EXSTYLE_0 },
290 
291     { __LINE__, 0xF, TYPE_0, STYLE_1, EXSTYLE_3 },
292     { __LINE__, 0x4F, TYPE_1, STYLE_1, EXSTYLE_3, STYLE_0, EXSTYLE_1 },
293     { __LINE__, 0x4F, TYPE_2, STYLE_1, EXSTYLE_3, STYLE_0, EXSTYLE_1 },
294 
295     { __LINE__, 0xF, TYPE_0, STYLE_1, EXSTYLE_3 },
296     { __LINE__, 0x5F, TYPE_1, STYLE_1, EXSTYLE_3, STYLE_1, EXSTYLE_1 },
297     { __LINE__, 0x5F, TYPE_2, STYLE_1, EXSTYLE_3, STYLE_1, EXSTYLE_1 },
298 
299     { __LINE__, 0xF, TYPE_0, STYLE_1, EXSTYLE_3 },
300     { __LINE__, 0x2F, TYPE_1, STYLE_1, EXSTYLE_3, STYLE_0, EXSTYLE_2 },
301     { __LINE__, 0x2F, TYPE_2, STYLE_1, EXSTYLE_3, STYLE_0, EXSTYLE_2 },
302 
303     { __LINE__, 0xF, TYPE_0, STYLE_1, EXSTYLE_3 },
304     { __LINE__, 0x3F, TYPE_1, STYLE_1, EXSTYLE_3, STYLE_1, EXSTYLE_2 },
305     { __LINE__, 0x3F, TYPE_2, STYLE_1, EXSTYLE_3, STYLE_1, EXSTYLE_2 },
306 
307     { __LINE__, 0xF, TYPE_0, STYLE_1, EXSTYLE_3 },
308     { __LINE__, 0x6F, TYPE_1, STYLE_1, EXSTYLE_3, STYLE_0, EXSTYLE_3 },
309     { __LINE__, 0x6F, TYPE_2, STYLE_1, EXSTYLE_3, STYLE_0, EXSTYLE_3 },
310 
311     { __LINE__, 0xF, TYPE_0, STYLE_1, EXSTYLE_3 },
312     { __LINE__, 0x7F, TYPE_1, STYLE_1, EXSTYLE_3, STYLE_1, EXSTYLE_3 },
313     { __LINE__, 0x7F, TYPE_2, STYLE_1, EXSTYLE_3, STYLE_1, EXSTYLE_3 },
314 };
315 
316 static const size_t s_num_entries = sizeof(s_entries) / sizeof(s_entries[0]);
317 
318 static void DoTestEntryPart1(const TEST_ENTRY *pEntry)
319 {
320     ok(!pEntry->bIsChild || pEntry->bHasOwner,
321        "Line %d: bIsChild && !bHasOwner\n", pEntry->lineno);
322 
323     s_hwndParent = NULL;
324     if (pEntry->bIsChild || pEntry->bHasOwner)
325     {
326         s_hwndParent = DoCreateWindow(NULL, pEntry->owner_style, pEntry->owner_exstyle);
327     }
328 
329     DWORD style = pEntry->style;
330     DWORD exstyle = pEntry->exstyle;
331     if (pEntry->bIsChild)
332         style |= WS_CHILD;
333     else
334         style &= ~WS_CHILD;
335 
336     s_dwFlags = 0;
337     s_hwndTarget = DoCreateWindow(s_hwndParent, style, exstyle);
338 }
339 
340 static void DoTestEntryPart2(const TEST_ENTRY *pEntry)
341 {
342     ok(s_dwFlags == pEntry->dwFlags, "Line %d: s_dwFlags expected 0x%lX but was 0x%lX\n",
343        pEntry->lineno, pEntry->dwFlags, s_dwFlags);
344 
345     PostMessageW(s_hwndTarget, WM_CLOSE, 0, 0);
346     s_hwndTarget = NULL;
347 
348     if (pEntry->bIsChild || pEntry->bHasOwner)
349     {
350         PostMessageW(s_hwndParent, WM_CLOSE, 0, 0);
351         s_hwndParent = NULL;
352     }
353 }
354 
355 static LRESULT CALLBACK
356 WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
357 {
358     if (uMsg == s_uShellHookMsg && uMsg != 0)
359     {
360         DWORD style, exstyle, owner_style, owner_exstyle;
361         HWND hwndOwner;
362         DWORD dwFlags;
363         switch (wParam)
364         {
365             case HSHELL_WINDOWCREATED:
366                 if ((HWND)lParam != s_hwndTarget)
367                     break;
368                 style = (LONG)GetWindowLongPtrW(s_hwndTarget, GWL_STYLE);
369                 exstyle = (LONG)GetWindowLongPtrW(s_hwndTarget, GWL_EXSTYLE);
370                 if (style & WS_CHILD)
371                     hwndOwner = GetParent(s_hwndTarget);
372                 else
373                     hwndOwner = GetWindow(s_hwndTarget, GW_OWNER);
374                 owner_style = (LONG)GetWindowLongPtrW(hwndOwner, GWL_STYLE);
375                 owner_exstyle = (LONG)GetWindowLongPtrW(hwndOwner, GWL_EXSTYLE);
376                 dwFlags = (1 << 0);
377                 if (style & WS_VISIBLE)
378                     dwFlags |= (1 << 1);
379                 if (exstyle & WS_EX_TOOLWINDOW)
380                     dwFlags |= (1 << 2);
381                 if (exstyle & WS_EX_APPWINDOW)
382                     dwFlags |= (1 << 3);
383                 if (owner_style & WS_VISIBLE)
384                     dwFlags |= (1 << 4);
385                 if (owner_exstyle & WS_EX_TOOLWINDOW)
386                     dwFlags |= (1 << 5);
387                 if (owner_exstyle & WS_EX_APPWINDOW)
388                     dwFlags |= (1 << 6);
389                 s_dwFlags = dwFlags;
390                 break;
391         }
392     }
393     switch (uMsg)
394     {
395         case WM_CREATE:
396             PostMessageW(hwnd, WM_COMMAND, 1000, 0);
397             return DefWindowProcW(hwnd, uMsg, wParam, lParam);
398         case WM_COMMAND:
399             if (hwnd == s_hwndHookViewer)
400             {
401                 if (1000 <= wParam && wParam < 2000)
402                 {
403                     INT i = (INT)wParam - 1000;
404                     DoTestEntryPart1(&s_entries[i]);
405                     PostMessageW(hwnd, WM_COMMAND, 2000 + i, 0);
406                 }
407                 else if (2000 <= wParam && wParam < 3000)
408                 {
409                     INT i = (INT)wParam - 2000;
410                     DoTestEntryPart2(&s_entries[i]);
411                     ++i;
412                     if (i == s_num_entries)
413                     {
414                         PostQuitMessage(0);
415                         break;
416                     }
417                     PostMessageW(hwnd, WM_COMMAND, 1000 + i, 0);
418                 }
419             }
420             break;
421         default:
422             return DefWindowProcW(hwnd, uMsg, wParam, lParam);
423     }
424     return 0;
425 }
426 
427 START_TEST(ShellHook)
428 {
429     WNDCLASSW wc;
430 
431     ZeroMemory(&wc, sizeof(wc));
432     wc.lpfnWndProc = WindowProc;
433     wc.hInstance = GetModuleHandleW(NULL);
434     wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
435     wc.hCursor = LoadCursor(NULL, IDC_ARROW);
436     wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1);
437     wc.lpszClassName = s_szName;
438     if (!RegisterClassW(&wc))
439     {
440         skip("RegisterClassW failed\n");
441         return;
442     }
443 
444     s_hwndHookViewer = DoCreateWindow(NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0);
445     if (s_hwndHookViewer == NULL)
446     {
447         skip("CreateWindowExW failed\n");
448         return;
449     }
450 
451     s_uShellHookMsg = RegisterWindowMessageW(L"SHELLHOOK");
452     RegisterShellHookWindow(s_hwndHookViewer);
453 
454     MSG msg;
455     while (GetMessageW(&msg, NULL, 0, 0))
456     {
457         TranslateMessage(&msg);
458         DispatchMessageW(&msg);
459     }
460 
461     DeregisterShellHookWindow(s_hwndHookViewer);
462     DestroyWindow(s_hwndHookViewer);
463     s_hwndHookViewer = NULL;
464 }
465