[SHELL32_APITEST] Strengthen SHChangeNotify testcase more and more (#4174)
[reactos.git] / modules / rostests / apitests / shell32 / SHChangeNotify.cpp
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 SHChangeNotify
5 * COPYRIGHT: Copyright 2020-2021 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
6 */
7
8 // NOTE: This test program closes the Explorer windows before tests.
9
10 #include "shelltest.h"
11 #include "SHChangeNotify.h"
12 #include <time.h>
13 #include <process.h>
14 #include <versionhelpers.h>
15
16 // --- The selection of tests ---
17 //#define DISABLE_THIS_TESTCASE
18 #define NO_TRIVIAL
19 //#define NO_INTERRUPT_LEVEL
20 //#define NO_SHELL_LEVEL
21 #define NEW_DELIVERY_ONLY
22 //#define RANDOM_HALF
23 #define RANDOM_QUARTER
24
25 // --- Show the elapsed time by GetTickCount() ---
26 //#define ENTRY_TICK
27 #define GROUP_TICK
28 #define TOTAL_TICK
29
30 static HWND s_hwnd = NULL;
31 static WCHAR s_szSubProgram[MAX_PATH];
32 static HANDLE s_hThread = NULL;
33 static HANDLE s_hEvent = NULL;
34
35 static HWND DoWaitForWindow(LPCWSTR clsname, LPCWSTR text, BOOL bClosing, BOOL bForce)
36 {
37 HWND hwnd = NULL;
38 for (INT i = 0; i < 50; ++i)
39 {
40 hwnd = FindWindowW(clsname, text);
41 if (bClosing)
42 {
43 if (!hwnd)
44 break;
45
46 if (bForce)
47 PostMessage(hwnd, WM_CLOSE, 0, 0);
48 }
49 else
50 {
51 if (hwnd)
52 break;
53 }
54
55 Sleep(1);
56 }
57 return hwnd;
58 }
59
60 static BOOL DoCreateEmptyFile(LPCWSTR pszFileName)
61 {
62 FILE *fp = _wfopen(pszFileName, L"wb");
63 if (fp)
64 fclose(fp);
65 return fp != NULL;
66 }
67
68 struct TEST_ENTRY;
69
70 typedef BOOL (*ACTION)(const struct TEST_ENTRY *entry);
71
72 typedef struct TEST_ENTRY
73 {
74 INT line;
75 DIRTYPE iWriteDir;
76 LPCSTR pattern;
77 LPCWSTR path1;
78 LPCWSTR path2;
79 ACTION action;
80 } TEST_ENTRY;
81
82 #define TEST_FILE L"_TEST_.txt"
83 #define TEST_FILE_KAI L"_TEST_KAI_.txt"
84 #define TEST_DIR L"_TESTDIR_"
85 #define TEST_DIR_KAI L"_TESTDIR_KAI_"
86 #define MOVE_FILE(from, to) MoveFileW((from), (to))
87
88 static BOOL DoAction1(const TEST_ENTRY *entry)
89 {
90 LPWSTR pszPath = DoGetDir(entry->iWriteDir);
91 PathAppendW(pszPath, TEST_FILE);
92 ok(DoCreateEmptyFile(pszPath), "Line %d: DoCreateEmptyFile failed\n", entry->line);
93 return TRUE;
94 }
95
96 static BOOL DoAction2(const TEST_ENTRY *entry)
97 {
98 LPWSTR pszPath1 = DoGetDir(entry->iWriteDir), pszPath2 = DoGetDir(entry->iWriteDir);
99 PathAppendW(pszPath1, TEST_FILE);
100 PathAppendW(pszPath2, TEST_FILE_KAI);
101 ok(MOVE_FILE(pszPath1, pszPath2), "Line %d: MOVE_FILE(%ls, %ls) failed (%ld)\n",
102 entry->line, pszPath1, pszPath2, GetLastError());
103 return TRUE;
104 }
105
106 static BOOL DoAction3(const TEST_ENTRY *entry)
107 {
108 LPWSTR pszPath1 = DoGetDir(entry->iWriteDir), pszPath2 = DoGetDir(entry->iWriteDir);
109 PathAppendW(pszPath1, TEST_FILE_KAI);
110 PathAppendW(pszPath2, TEST_FILE);
111 ok(MOVE_FILE(pszPath1, pszPath2), "Line %d: MOVE_FILE(%ls, %ls) failed (%ld)\n",
112 entry->line, pszPath1, pszPath2, GetLastError());
113 return TRUE;
114 }
115
116 static BOOL DoAction4(const TEST_ENTRY *entry)
117 {
118 LPWSTR pszPath = DoGetDir(entry->iWriteDir);
119 PathAppendW(pszPath, TEST_FILE);
120 ok(DeleteFileW(pszPath), "Line %d: DeleteFileW(%ls) failed (%ld)\n",
121 entry->line, pszPath, GetLastError());
122 return TRUE;
123 }
124
125 static BOOL DoAction5(const TEST_ENTRY *entry)
126 {
127 LPWSTR pszPath = DoGetDir(entry->iWriteDir);
128 PathAppendW(pszPath, TEST_DIR);
129 ok(CreateDirectoryW(pszPath, NULL), "Line %d: CreateDirectoryW(%ls) failed (%ld)\n",
130 entry->line, pszPath, GetLastError());
131 return TRUE;
132 }
133
134 static BOOL DoAction6(const TEST_ENTRY *entry)
135 {
136 LPWSTR pszPath1 = DoGetDir(entry->iWriteDir), pszPath2 = DoGetDir(entry->iWriteDir);
137 PathAppendW(pszPath1, TEST_DIR);
138 PathAppendW(pszPath2, TEST_DIR_KAI);
139 ok(MOVE_FILE(pszPath1, pszPath2), "Line %d: MOVE_FILE(%ls, %ls) failed (%ld)\n",
140 entry->line, pszPath1, pszPath2, GetLastError());
141 return TRUE;
142 }
143
144 static BOOL DoAction7(const TEST_ENTRY *entry)
145 {
146 LPWSTR pszPath1 = DoGetDir(entry->iWriteDir), pszPath2 = DoGetDir(entry->iWriteDir);
147 PathAppendW(pszPath1, TEST_DIR_KAI);
148 PathAppendW(pszPath2, TEST_DIR);
149 ok(MOVE_FILE(pszPath1, pszPath2), "Line %d: MOVE_FILE(%ls, %ls) failed (%ld)\n",
150 entry->line, pszPath1, pszPath2, GetLastError());
151 return TRUE;
152 }
153
154 static BOOL DoAction8(const TEST_ENTRY *entry)
155 {
156 LPWSTR pszPath = DoGetDir(entry->iWriteDir);
157 PathAppendW(pszPath, TEST_DIR);
158 ok(RemoveDirectoryW(pszPath), "Line %d: RemoveDirectoryW(%ls) failed (%ld)\n",
159 entry->line, pszPath, GetLastError());
160 return TRUE;
161 }
162
163 static BOOL DoAction9(const TEST_ENTRY *entry)
164 {
165 LPWSTR pszPath = DoGetDir(entry->iWriteDir);
166 PathAppendW(pszPath, TEST_FILE);
167 SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW | SHCNF_FLUSH, pszPath, NULL);
168 return FALSE;
169 }
170
171 static BOOL DoAction10(const TEST_ENTRY *entry)
172 {
173 LPWSTR pszPath = DoGetDir(entry->iWriteDir);
174 PathAppendW(pszPath, TEST_FILE);
175 SHChangeNotify(SHCNE_DELETE, SHCNF_PATHW | SHCNF_FLUSH, pszPath, NULL);
176 return FALSE;
177 }
178
179 static BOOL DoAction11(const TEST_ENTRY *entry)
180 {
181 LPWSTR pszPath = DoGetDir(entry->iWriteDir);
182 PathAppendW(pszPath, TEST_DIR);
183 SHChangeNotify(SHCNE_MKDIR, SHCNF_PATHW | SHCNF_FLUSH, pszPath, NULL);
184 return FALSE;
185 }
186
187 static BOOL DoAction12(const TEST_ENTRY *entry)
188 {
189 LPWSTR pszPath = DoGetDir(entry->iWriteDir);
190 PathAppendW(pszPath, TEST_DIR);
191 SHChangeNotify(SHCNE_RMDIR, SHCNF_PATHW | SHCNF_FLUSH, pszPath, NULL);
192 return FALSE;
193 }
194
195 #define WRITEDIR_0 DIRTYPE_DESKTOP
196 static WCHAR s_szDesktop[MAX_PATH];
197 static WCHAR s_szTestFile0[MAX_PATH];
198 static WCHAR s_szTestFile0Kai[MAX_PATH];
199 static WCHAR s_szTestDir0[MAX_PATH];
200 static WCHAR s_szTestDir0Kai[MAX_PATH];
201
202 #define WRITEDIR_1 DIRTYPE_MYDOCUMENTS
203 static WCHAR s_szDocuments[MAX_PATH];
204 static WCHAR s_szTestFile1[MAX_PATH];
205 static WCHAR s_szTestFile1Kai[MAX_PATH];
206 static WCHAR s_szTestDir1[MAX_PATH];
207 static WCHAR s_szTestDir1Kai[MAX_PATH];
208
209 static void DoDeleteFilesAndDirs(void)
210 {
211 DeleteFileW(TEMP_FILE);
212 DeleteFileW(s_szTestFile0);
213 DeleteFileW(s_szTestFile0Kai);
214 DeleteFileW(s_szTestFile1);
215 DeleteFileW(s_szTestFile1Kai);
216 RemoveDirectoryW(s_szTestDir0);
217 RemoveDirectoryW(s_szTestDir0Kai);
218 RemoveDirectoryW(s_szTestDir1);
219 RemoveDirectoryW(s_szTestDir1Kai);
220 }
221
222 static const TEST_ENTRY s_group_00[] =
223 {
224 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction1 },
225 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction2 },
226 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction3 },
227 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction4 },
228 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction5 },
229 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction6 },
230 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction7 },
231 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction8 },
232 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction9 },
233 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction10 },
234 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction11 },
235 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction12 },
236
237 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction1 },
238 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction2 },
239 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction3 },
240 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction4 },
241 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction5 },
242 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction6 },
243 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction7 },
244 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction8 },
245 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction9 },
246 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction10 },
247 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction11 },
248 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction12 },
249 };
250
251 static const TEST_ENTRY s_group_01[] =
252 {
253 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction1 },
254 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction2 },
255 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction3 },
256 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction4 },
257 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction5 },
258 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction6 },
259 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction7 },
260 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction8 },
261 { __LINE__, WRITEDIR_0, "0100000", s_szTestFile0, L"", DoAction9 },
262 { __LINE__, WRITEDIR_0, "0010000", s_szTestFile0, L"", DoAction10 },
263 { __LINE__, WRITEDIR_0, "0001000", s_szTestDir0, L"", DoAction11 },
264 { __LINE__, WRITEDIR_0, "0000100", s_szTestDir0, L"", DoAction12 },
265
266 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction1 },
267 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction2 },
268 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction3 },
269 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction4 },
270 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction5 },
271 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction6 },
272 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction7 },
273 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction8 },
274 { __LINE__, WRITEDIR_1, "0100000", s_szTestFile1, L"", DoAction9 },
275 { __LINE__, WRITEDIR_1, "0010000", s_szTestFile1, L"", DoAction10 },
276 { __LINE__, WRITEDIR_1, "0001000", s_szTestDir1, L"", DoAction11 },
277 { __LINE__, WRITEDIR_1, "0000100", s_szTestDir1, L"", DoAction12 },
278 };
279
280 static const TEST_ENTRY s_group_02[] =
281 {
282 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction1 },
283 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction2 },
284 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction3 },
285 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction4 },
286 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction5 },
287 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction6 },
288 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction7 },
289 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction8 },
290 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction9 },
291 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction10 },
292 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction11 },
293 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction12 },
294
295 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction1 },
296 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction2 },
297 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction3 },
298 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction4 },
299 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction5 },
300 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction6 },
301 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction7 },
302 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction8 },
303 { __LINE__, WRITEDIR_1, "0100000", s_szTestFile1, L"", DoAction9 },
304 { __LINE__, WRITEDIR_1, "0010000", s_szTestFile1, L"", DoAction10 },
305 { __LINE__, WRITEDIR_1, "0001000", s_szTestDir1, L"", DoAction11 },
306 { __LINE__, WRITEDIR_1, "0000100", s_szTestDir1, L"", DoAction12 },
307 };
308
309 static const TEST_ENTRY s_group_03[] =
310 {
311 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction1 },
312 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction2 },
313 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction3 },
314 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction4 },
315 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction5 },
316 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction6 },
317 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction7 },
318 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction8 },
319 { __LINE__, WRITEDIR_0, "0100000", s_szTestFile0, L"", DoAction9 },
320 { __LINE__, WRITEDIR_0, "0010000", s_szTestFile0, L"", DoAction10 },
321 { __LINE__, WRITEDIR_0, "0001000", s_szTestDir0, L"", DoAction11 },
322 { __LINE__, WRITEDIR_0, "0000100", s_szTestDir0, L"", DoAction12 },
323
324 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction1 },
325 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction2 },
326 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction3 },
327 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction4 },
328 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction5 },
329 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction6 },
330 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction7 },
331 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction8 },
332 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction9 },
333 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction10 },
334 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction11 },
335 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction12 },
336 };
337
338 static const TEST_ENTRY s_group_04[] =
339 {
340 { __LINE__, WRITEDIR_0, "0100000", s_szTestFile0, L"", DoAction1 },
341 { __LINE__, WRITEDIR_0, "1000000", s_szTestFile0, s_szTestFile0Kai, DoAction2 },
342 { __LINE__, WRITEDIR_0, "1000000", s_szTestFile0Kai, s_szTestFile0, DoAction3 },
343 { __LINE__, WRITEDIR_0, "0010000", s_szTestFile0, L"", DoAction4 },
344 { __LINE__, WRITEDIR_0, "0001000", s_szTestDir0, L"", DoAction5 },
345 { __LINE__, WRITEDIR_0, "0000010", s_szTestDir0, s_szTestDir0Kai, DoAction6 },
346 { __LINE__, WRITEDIR_0, "0000010", s_szTestDir0Kai, s_szTestDir0, DoAction7 },
347 { __LINE__, WRITEDIR_0, "0000100", s_szTestDir0, L"", DoAction8 },
348 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction9 },
349 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction10 },
350 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction11 },
351 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction12 },
352
353 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction1 },
354 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction2 },
355 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction3 },
356 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction4 },
357 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction5 },
358 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction6 },
359 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction7 },
360 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction8 },
361 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction9 },
362 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction10 },
363 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction11 },
364 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction12 },
365 };
366
367 static const TEST_ENTRY s_group_05[] =
368 {
369 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction1 },
370 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction2 },
371 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction3 },
372 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction4 },
373 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction5 },
374 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction6 },
375 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction7 },
376 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction8 },
377 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction9 },
378 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction10 },
379 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction11 },
380 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction12 },
381
382 { __LINE__, WRITEDIR_1, "0100000", s_szTestFile1, L"", DoAction1 },
383 { __LINE__, WRITEDIR_1, "1000000", s_szTestFile1, s_szTestFile1Kai, DoAction2 },
384 { __LINE__, WRITEDIR_1, "1000000", s_szTestFile1Kai, s_szTestFile1, DoAction3 },
385 { __LINE__, WRITEDIR_1, "0010000", s_szTestFile1, L"", DoAction4 },
386 { __LINE__, WRITEDIR_1, "0001000", s_szTestDir1, L"", DoAction5 },
387 { __LINE__, WRITEDIR_1, "0000010", s_szTestDir1, s_szTestDir1Kai, DoAction6 },
388 { __LINE__, WRITEDIR_1, "0000010", s_szTestDir1Kai, s_szTestDir1, DoAction7 },
389 { __LINE__, WRITEDIR_1, "0000100", s_szTestDir1, L"", DoAction8 },
390 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction9 },
391 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction10 },
392 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction11 },
393 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction12 },
394 };
395
396 static const TEST_ENTRY s_group_06[] =
397 {
398 { __LINE__, WRITEDIR_0, "0100000", s_szTestFile0, L"", DoAction1 },
399 { __LINE__, WRITEDIR_0, "1000000", s_szTestFile0, s_szTestFile0Kai, DoAction2 },
400 { __LINE__, WRITEDIR_0, "1000000", s_szTestFile0Kai, s_szTestFile0, DoAction3 },
401 { __LINE__, WRITEDIR_0, "0010000", s_szTestFile0, L"", DoAction4 },
402 { __LINE__, WRITEDIR_0, "0001000", s_szTestDir0, L"", DoAction5 },
403 { __LINE__, WRITEDIR_0, "0000010", s_szTestDir0, s_szTestDir0Kai, DoAction6 },
404 { __LINE__, WRITEDIR_0, "0000010", s_szTestDir0Kai, s_szTestDir0, DoAction7 },
405 { __LINE__, WRITEDIR_0, "0000100", s_szTestDir0, L"", DoAction8 },
406 { __LINE__, WRITEDIR_0, "0100000", s_szTestFile0, L"", DoAction9 },
407 { __LINE__, WRITEDIR_0, "0010000", s_szTestFile0, L"", DoAction10 },
408 { __LINE__, WRITEDIR_0, "0001000", s_szTestDir0, L"", DoAction11 },
409 { __LINE__, WRITEDIR_0, "0000100", s_szTestDir0, L"", DoAction12 },
410
411 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction1 },
412 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction2 },
413 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction3 },
414 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction4 },
415 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction5 },
416 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction6 },
417 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction7 },
418 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction8 },
419 { __LINE__, WRITEDIR_1, "0100000", s_szTestFile1, L"", DoAction9 },
420 { __LINE__, WRITEDIR_1, "0010000", s_szTestFile1, L"", DoAction10 },
421 { __LINE__, WRITEDIR_1, "0001000", s_szTestDir1, L"", DoAction11 },
422 { __LINE__, WRITEDIR_1, "0000100", s_szTestDir1, L"", DoAction12 },
423 };
424
425 static const TEST_ENTRY s_group_07[] =
426 {
427 { __LINE__, WRITEDIR_0, "0100000", s_szTestFile0, L"", DoAction1 },
428 { __LINE__, WRITEDIR_0, "1000000", s_szTestFile0, s_szTestFile0Kai, DoAction2 },
429 { __LINE__, WRITEDIR_0, "1000000", s_szTestFile0Kai, s_szTestFile0, DoAction3 },
430 { __LINE__, WRITEDIR_0, "0010000", s_szTestFile0, L"", DoAction4 },
431 { __LINE__, WRITEDIR_0, "0001000", s_szTestDir0, L"", DoAction5 },
432 { __LINE__, WRITEDIR_0, "0000010", s_szTestDir0, s_szTestDir0Kai, DoAction6 },
433 { __LINE__, WRITEDIR_0, "0000010", s_szTestDir0Kai, s_szTestDir0, DoAction7 },
434 { __LINE__, WRITEDIR_0, "0000100", s_szTestDir0, L"", DoAction8 },
435 { __LINE__, WRITEDIR_0, "0100000", s_szTestFile0, L"", DoAction9 },
436 { __LINE__, WRITEDIR_0, "0010000", s_szTestFile0, L"", DoAction10 },
437 { __LINE__, WRITEDIR_0, "0001000", s_szTestDir0, L"", DoAction11 },
438 { __LINE__, WRITEDIR_0, "0000100", s_szTestDir0, L"", DoAction12 },
439
440 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction1 },
441 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction2 },
442 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction3 },
443 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction4 },
444 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction5 },
445 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction6 },
446 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction7 },
447 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction8 },
448 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction9 },
449 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction10 },
450 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction11 },
451 { __LINE__, WRITEDIR_1, "0000000", L"", L"", DoAction12 },
452 };
453
454 static const TEST_ENTRY s_group_08[] =
455 {
456 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction1 },
457 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction2 },
458 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction3 },
459 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction4 },
460 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction5 },
461 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction6 },
462 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction7 },
463 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction8 },
464 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction9 },
465 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction10 },
466 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction11 },
467 { __LINE__, WRITEDIR_0, "0000000", L"", L"", DoAction12 },
468
469 { __LINE__, WRITEDIR_1, "0100000", s_szTestFile1, L"", DoAction1 },
470 { __LINE__, WRITEDIR_1, "1000000", s_szTestFile1, s_szTestFile1Kai, DoAction2 },
471 { __LINE__, WRITEDIR_1, "1000000", s_szTestFile1Kai, s_szTestFile1, DoAction3 },
472 { __LINE__, WRITEDIR_1, "0010000", s_szTestFile1, L"", DoAction4 },
473 { __LINE__, WRITEDIR_1, "0001000", s_szTestDir1, L"", DoAction5 },
474 { __LINE__, WRITEDIR_1, "0000010", s_szTestDir1, s_szTestDir1Kai, DoAction6 },
475 { __LINE__, WRITEDIR_1, "0000010", s_szTestDir1Kai, s_szTestDir1, DoAction7 },
476 { __LINE__, WRITEDIR_1, "0000100", s_szTestDir1, L"", DoAction8 },
477 { __LINE__, WRITEDIR_1, "0100000", s_szTestFile1, L"", DoAction9 },
478 { __LINE__, WRITEDIR_1, "0010000", s_szTestFile1, L"", DoAction10 },
479 { __LINE__, WRITEDIR_1, "0001000", s_szTestDir1, L"", DoAction11 },
480 { __LINE__, WRITEDIR_1, "0000100", s_szTestDir1, L"", DoAction12 },
481 };
482
483 static LPCSTR PatternFromFlags(DWORD flags)
484 {
485 static CHAR s_buf[(TYPE_MAX + 1) + 1];
486 for (INT i = 0; i < (TYPE_MAX + 1); ++i)
487 s_buf[i] = (char)('0' + !!(flags & (1 << i)));
488
489 s_buf[TYPE_MAX + 1] = 0;
490 return s_buf;
491 }
492
493 static BOOL DoGetPaths(LPWSTR pszPath1, LPWSTR pszPath2)
494 {
495 pszPath1[0] = pszPath2[0] = 0;
496
497 WCHAR szText[MAX_PATH * 2];
498 szText[0] = 0;
499 FILE *fp = _wfopen(TEMP_FILE, L"rb");
500 if (fp)
501 {
502 fread(szText, 1, sizeof(szText), fp);
503 fclose(fp);
504 }
505
506 LPWSTR pch = wcschr(szText, L'|');
507 if (pch == NULL)
508 return FALSE;
509
510 *pch = 0;
511 StringCchCopyW(pszPath1, MAX_PATH, szText);
512 StringCchCopyW(pszPath2, MAX_PATH, pch + 1);
513 return TRUE;
514 }
515
516 static void DoTestEntry(INT iEntry, const TEST_ENTRY *entry, INT nSources)
517 {
518 #ifdef ENTRY_TICK
519 DWORD dwOldTick = GetTickCount();
520 #endif
521
522 BOOL bInterrupting = FALSE;
523 if (entry->action)
524 bInterrupting = entry->action(entry);
525
526 DWORD flags;
527 LPCSTR pattern;
528 if ((nSources & SHCNRF_InterruptLevel) && bInterrupting)
529 {
530 // The event won't work at here. Manually waiting...
531 UINT cTry = ((iEntry == 0) ? 100 : 60);
532 for (UINT iTry = 0; iTry < cTry; ++iTry)
533 {
534 flags = SendMessageW(s_hwnd, WM_GET_NOTIFY_FLAGS, 0, 0);
535 pattern = PatternFromFlags(flags);
536 if (strcmp(pattern, "0000000") != 0)
537 break;
538
539 Sleep(1);
540 }
541 }
542 else
543 {
544 if (WaitForSingleObject(s_hEvent, 100) == WAIT_OBJECT_0)
545 Sleep(1);
546
547 flags = SendMessageW(s_hwnd, WM_GET_NOTIFY_FLAGS, 0, 0);
548 pattern = PatternFromFlags(flags);
549 }
550
551 SendMessageW(s_hwnd, WM_SET_PATHS, 0, 0);
552
553 WCHAR szPath1[MAX_PATH], szPath2[MAX_PATH];
554 szPath1[0] = szPath2[0] = 0;
555 BOOL bOK = DoGetPaths(szPath1, szPath2);
556
557 static UINT s_cCalmDown = 0;
558
559 if (pattern[TYPE_UPDATEDIR] == '1')
560 {
561 trace("Line %d: SHCNE_UPDATEDIR: Calm down (%u)...\n", entry->line, s_cCalmDown);
562
563 if (++s_cCalmDown < 3)
564 Sleep(3000);
565
566 if (entry->pattern)
567 ok(TRUE, "Line %d:\n", entry->line);
568 if (entry->path1)
569 ok(TRUE, "Line %d:\n", entry->line);
570 if (entry->path2)
571 ok(TRUE, "Line %d:\n", entry->line);
572 }
573 else
574 {
575 s_cCalmDown = 0;
576 if (entry->pattern)
577 {
578 ok(strcmp(pattern, entry->pattern) == 0,
579 "Line %d: pattern mismatch '%s', tick=0x%08lX\n",
580 entry->line, pattern, GetTickCount());
581 }
582 if (entry->path1)
583 ok(bOK && lstrcmpiW(entry->path1, szPath1) == 0,
584 "Line %d: path1 mismatch '%S' (%d)\n", entry->line, szPath1, bOK);
585 if (entry->path2)
586 ok(bOK && lstrcmpiW(entry->path2, szPath2) == 0,
587 "Line %d: path2 mismatch '%S' (%d)\n", entry->line, szPath2, bOK);
588 }
589
590 SendMessageW(s_hwnd, WM_CLEAR_FLAGS, 0, 0);
591 ResetEvent(s_hEvent);
592
593 #ifdef ENTRY_TICK
594 DWORD dwNewTick = GetTickCount();
595 DWORD dwTick = dwNewTick - dwOldTick;
596 trace("DoTestEntry: Line %d: tick=%lu.%lu sec\n", entry->line,
597 (dwTick / 1000), (dwTick / 100 % 10));
598 #endif
599 }
600
601 static void DoQuitTest(BOOL bForce)
602 {
603 PostMessageW(s_hwnd, WM_COMMAND, IDOK, 0);
604
605 DoWaitForWindow(CLASSNAME, CLASSNAME, TRUE, bForce);
606 s_hwnd = NULL;
607
608 if (s_hEvent)
609 {
610 CloseHandle(s_hEvent);
611 s_hEvent = NULL;
612 }
613
614 DoDeleteFilesAndDirs();
615 }
616
617 static void DoAbortThread(void)
618 {
619 skip("Aborting the thread...\n");
620 if (s_hThread)
621 {
622 TerminateThread(s_hThread, -1);
623 s_hThread = NULL;
624 }
625 }
626
627 static BOOL CALLBACK HandlerRoutine(DWORD dwCtrlType)
628 {
629 switch (dwCtrlType)
630 {
631 case CTRL_C_EVENT:
632 case CTRL_BREAK_EVENT:
633 DoAbortThread();
634 DoQuitTest(TRUE);
635 return TRUE;
636 }
637 return FALSE;
638 }
639
640 static BOOL DoInitTest(void)
641 {
642 // DIRTYPE_DESKTOP
643 LPWSTR psz = DoGetDir(DIRTYPE_DESKTOP);
644 StringCchCopyW(s_szDesktop, _countof(s_szDesktop), psz);
645
646 PathAppendW(psz, TEST_FILE);
647 StringCchCopyW(s_szTestFile0, _countof(s_szTestFile0), psz);
648
649 PathRemoveFileSpecW(psz);
650 PathAppendW(psz, TEST_FILE_KAI);
651 StringCchCopyW(s_szTestFile0Kai, _countof(s_szTestFile0Kai), psz);
652
653 PathRemoveFileSpecW(psz);
654 PathAppendW(psz, TEST_DIR);
655 StringCchCopyW(s_szTestDir0, _countof(s_szTestDir0), psz);
656
657 PathRemoveFileSpecW(psz);
658 PathAppendW(psz, TEST_DIR_KAI);
659 StringCchCopyW(s_szTestDir0Kai, _countof(s_szTestDir0Kai), psz);
660
661 // DIRTYPE_MYDOCUMENTS
662 psz = DoGetDir(DIRTYPE_MYDOCUMENTS);
663 StringCchCopyW(s_szDocuments, _countof(s_szDocuments), psz);
664
665 PathAppendW(psz, TEST_FILE);
666 StringCchCopyW(s_szTestFile1, _countof(s_szTestFile1), psz);
667
668 PathRemoveFileSpecW(psz);
669 PathAppendW(psz, TEST_FILE_KAI);
670 StringCchCopyW(s_szTestFile1Kai, _countof(s_szTestFile1Kai), psz);
671
672 PathRemoveFileSpecW(psz);
673 PathAppendW(psz, TEST_DIR);
674 StringCchCopyW(s_szTestDir1, _countof(s_szTestDir1), psz);
675
676 PathRemoveFileSpecW(psz);
677 PathAppendW(psz, TEST_DIR_KAI);
678 StringCchCopyW(s_szTestDir1Kai, _countof(s_szTestDir1Kai), psz);
679
680 // prepare for files and dirs
681 DoDeleteFilesAndDirs();
682 DoCreateEmptyFile(TEMP_FILE);
683
684 // Ctrl+C
685 SetConsoleCtrlHandler(HandlerRoutine, TRUE);
686
687 // close Explorer windows
688 trace("Closing Explorer windows...\n");
689 DoWaitForWindow(L"CabinetWClass", NULL, TRUE, TRUE);
690
691 // close the CLASSNAME windows
692 return DoWaitForWindow(CLASSNAME, CLASSNAME, TRUE, TRUE) == NULL;
693 }
694
695 static BOOL
696 GetSubProgramPath(void)
697 {
698 GetModuleFileNameW(NULL, s_szSubProgram, _countof(s_szSubProgram));
699 PathRemoveFileSpecW(s_szSubProgram);
700 PathAppendW(s_szSubProgram, L"shell32_apitest_sub.exe");
701
702 if (!PathFileExistsW(s_szSubProgram))
703 {
704 PathRemoveFileSpecW(s_szSubProgram);
705 PathAppendW(s_szSubProgram, L"testdata\\shell32_apitest_sub.exe");
706
707 if (!PathFileExistsW(s_szSubProgram))
708 return FALSE;
709 }
710
711 return TRUE;
712 }
713
714 #define SRC_00 0
715 #define SRC_01 SHCNRF_ShellLevel
716 #define SRC_02 (SHCNRF_NewDelivery)
717 #define SRC_03 (SHCNRF_NewDelivery | SHCNRF_ShellLevel)
718 #define SRC_04 SHCNRF_InterruptLevel
719 #define SRC_05 (SHCNRF_InterruptLevel | SHCNRF_ShellLevel)
720 #define SRC_06 (SHCNRF_InterruptLevel | SHCNRF_NewDelivery)
721 #define SRC_07 (SHCNRF_InterruptLevel | SHCNRF_NewDelivery | SHCNRF_ShellLevel)
722 #define SRC_08 (SHCNRF_RecursiveInterrupt | SHCNRF_InterruptLevel)
723 #define SRC_09 (SHCNRF_RecursiveInterrupt | SHCNRF_InterruptLevel | SHCNRF_ShellLevel)
724 #define SRC_10 (SHCNRF_RecursiveInterrupt | SHCNRF_InterruptLevel | SHCNRF_NewDelivery)
725 #define SRC_11 (SHCNRF_RecursiveInterrupt | SHCNRF_InterruptLevel | SHCNRF_NewDelivery | SHCNRF_ShellLevel)
726
727 #define WATCHDIR_0 DIRTYPE_NULL
728 #define WATCHDIR_1 DIRTYPE_DESKTOP
729 #define WATCHDIR_2 DIRTYPE_MYCOMPUTER
730 #define WATCHDIR_3 DIRTYPE_MYDOCUMENTS
731
732 static void
733 DoTestGroup(INT line, UINT cEntries, const TEST_ENTRY *pEntries, BOOL fRecursive,
734 INT nSources, DIRTYPE iWatchDir)
735 {
736 #ifdef NO_INTERRUPT_LEVEL
737 if (nSources & SHCNRF_InterruptLevel)
738 return;
739 #endif
740 #ifdef NO_SHELL_LEVEL
741 if (nSources & SHCNRF_ShellLevel)
742 return;
743 #endif
744 #ifdef NEW_DELIVERY_ONLY
745 if (!(nSources & SHCNRF_NewDelivery))
746 return;
747 #endif
748 #ifdef GROUP_TICK
749 DWORD dwOldTick = GetTickCount();
750 #endif
751 #ifdef RANDOM_QUARTER
752 if ((rand() & 3) == 0)
753 return;
754 #elif defined(RANDOM_HALF)
755 if (rand() & 1)
756 return;
757 #endif
758
759 trace("DoTestGroup: Line %d: fRecursive:%u, iWatchDir:%u, nSources:0x%X\n",
760 line, fRecursive, iWatchDir, nSources);
761
762 if (s_hEvent)
763 {
764 CloseHandle(s_hEvent);
765 s_hEvent = NULL;
766 }
767 s_hEvent = CreateEventW(NULL, TRUE, FALSE, EVENT_NAME);
768
769 WCHAR szParams[64];
770 StringCchPrintfW(szParams, _countof(szParams), L"%u,%u,%u", fRecursive, iWatchDir, nSources);
771
772 HINSTANCE hinst = ShellExecuteW(NULL, NULL, s_szSubProgram, szParams, NULL, SW_SHOWNORMAL);
773 if ((INT_PTR)hinst <= 32)
774 {
775 skip("Unable to run shell32_apitest_sub.exe.\n");
776 return;
777 }
778
779 s_hwnd = DoWaitForWindow(CLASSNAME, CLASSNAME, FALSE, FALSE);
780 if (!s_hwnd)
781 {
782 skip("Unable to find window.\n");
783 return;
784 }
785
786 for (UINT i = 0; i < cEntries; ++i)
787 {
788 if (!IsWindow(s_hwnd))
789 {
790 DoAbortThread();
791 DoQuitTest(TRUE);
792 break;
793 }
794
795 DoTestEntry(i, &pEntries[i], nSources);
796 }
797
798 DoQuitTest(FALSE);
799
800 #ifdef GROUP_TICK
801 DWORD dwNewTick = GetTickCount();
802 DWORD dwTick = dwNewTick - dwOldTick;
803 trace("DoTestGroup: Line %d: %lu.%lu sec\n", line, (dwTick / 1000), (dwTick / 100 % 10));
804 #endif
805 }
806
807 static unsigned __stdcall TestThreadProc(void *)
808 {
809 srand(time(NULL));
810 #ifdef RANDOM_QUARTER
811 skip("RANDOM_QUARTER\n");
812 #elif defined(RANDOM_HALF)
813 skip("RANDOM_HALF\n");
814 #endif
815
816 // fRecursive == FALSE.
817 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, FALSE, SRC_00, WATCHDIR_0);
818 DoTestGroup(__LINE__, _countof(s_group_01), s_group_01, FALSE, SRC_01, WATCHDIR_0);
819 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, FALSE, SRC_02, WATCHDIR_0);
820 DoTestGroup(__LINE__, _countof(s_group_01), s_group_01, FALSE, SRC_03, WATCHDIR_0);
821 DoTestGroup(__LINE__, _countof(s_group_04), s_group_04, FALSE, SRC_04, WATCHDIR_0);
822 DoTestGroup(__LINE__, _countof(s_group_06), s_group_06, FALSE, SRC_05, WATCHDIR_0);
823 DoTestGroup(__LINE__, _countof(s_group_04), s_group_04, FALSE, SRC_06, WATCHDIR_0);
824 DoTestGroup(__LINE__, _countof(s_group_06), s_group_06, FALSE, SRC_07, WATCHDIR_0);
825 DoTestGroup(__LINE__, _countof(s_group_04), s_group_04, FALSE, SRC_08, WATCHDIR_0);
826 DoTestGroup(__LINE__, _countof(s_group_06), s_group_06, FALSE, SRC_09, WATCHDIR_0);
827 DoTestGroup(__LINE__, _countof(s_group_04), s_group_04, FALSE, SRC_10, WATCHDIR_0);
828 DoTestGroup(__LINE__, _countof(s_group_06), s_group_06, FALSE, SRC_11, WATCHDIR_0);
829
830 BOOL bTarget = IsWindowsXPOrGreater() && !IsWindowsVistaOrGreater();
831
832 #define SWITCH(x, y) (bTarget ? (x) : (y))
833 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, FALSE, SRC_00, WATCHDIR_1);
834 DoTestGroup(__LINE__, _countof(s_group_03), s_group_03, FALSE, SRC_01, WATCHDIR_1);
835 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, FALSE, SRC_02, WATCHDIR_1);
836 DoTestGroup(__LINE__, _countof(s_group_03), s_group_03, FALSE, SRC_03, WATCHDIR_1);
837 DoTestGroup(__LINE__, SWITCH(_countof(s_group_00), _countof(s_group_04)), SWITCH(s_group_00, s_group_04), FALSE, SRC_04, WATCHDIR_1);
838 DoTestGroup(__LINE__, _countof(s_group_07), s_group_07, FALSE, SRC_05, WATCHDIR_1);
839 DoTestGroup(__LINE__, SWITCH(_countof(s_group_00), _countof(s_group_04)), SWITCH(s_group_00, s_group_04), FALSE, SRC_06, WATCHDIR_1);
840 DoTestGroup(__LINE__, _countof(s_group_07), s_group_07, FALSE, SRC_07, WATCHDIR_1);
841 DoTestGroup(__LINE__, _countof(s_group_04), s_group_04, FALSE, SRC_08, WATCHDIR_1);
842 DoTestGroup(__LINE__, _countof(s_group_07), s_group_07, FALSE, SRC_09, WATCHDIR_1);
843 DoTestGroup(__LINE__, SWITCH(_countof(s_group_00), _countof(s_group_04)), SWITCH(s_group_00, s_group_04), FALSE, SRC_06, WATCHDIR_1);
844 DoTestGroup(__LINE__, _countof(s_group_07), s_group_07, FALSE, SRC_11, WATCHDIR_1);
845 #undef SWITCH
846
847 #ifndef NO_TRIVIAL
848 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, FALSE, SRC_00, WATCHDIR_2);
849 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, FALSE, SRC_01, WATCHDIR_2);
850 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, FALSE, SRC_02, WATCHDIR_2);
851 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, FALSE, SRC_03, WATCHDIR_2);
852 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, FALSE, SRC_04, WATCHDIR_2);
853 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, FALSE, SRC_05, WATCHDIR_2);
854 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, FALSE, SRC_06, WATCHDIR_2);
855 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, FALSE, SRC_07, WATCHDIR_2);
856 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, FALSE, SRC_08, WATCHDIR_2);
857 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, FALSE, SRC_09, WATCHDIR_2);
858 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, FALSE, SRC_10, WATCHDIR_2);
859 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, FALSE, SRC_11, WATCHDIR_2);
860 #endif
861
862 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, FALSE, SRC_00, WATCHDIR_3);
863 DoTestGroup(__LINE__, _countof(s_group_02), s_group_02, FALSE, SRC_01, WATCHDIR_3);
864 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, FALSE, SRC_02, WATCHDIR_3);
865 DoTestGroup(__LINE__, _countof(s_group_02), s_group_02, FALSE, SRC_03, WATCHDIR_3);
866 DoTestGroup(__LINE__, _countof(s_group_05), s_group_05, FALSE, SRC_04, WATCHDIR_3);
867 DoTestGroup(__LINE__, _countof(s_group_08), s_group_08, FALSE, SRC_05, WATCHDIR_3);
868 DoTestGroup(__LINE__, _countof(s_group_05), s_group_05, FALSE, SRC_06, WATCHDIR_3);
869 DoTestGroup(__LINE__, _countof(s_group_08), s_group_08, FALSE, SRC_07, WATCHDIR_3);
870 DoTestGroup(__LINE__, _countof(s_group_05), s_group_05, FALSE, SRC_08, WATCHDIR_3);
871 DoTestGroup(__LINE__, _countof(s_group_08), s_group_08, FALSE, SRC_09, WATCHDIR_3);
872 DoTestGroup(__LINE__, _countof(s_group_05), s_group_05, FALSE, SRC_10, WATCHDIR_3);
873 DoTestGroup(__LINE__, _countof(s_group_08), s_group_08, FALSE, SRC_11, WATCHDIR_3);
874
875 // fRecursive == TRUE.
876 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, TRUE, SRC_00, WATCHDIR_0);
877 DoTestGroup(__LINE__, _countof(s_group_01), s_group_01, TRUE, SRC_01, WATCHDIR_0);
878 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, TRUE, SRC_02, WATCHDIR_0);
879 DoTestGroup(__LINE__, _countof(s_group_01), s_group_01, TRUE, SRC_03, WATCHDIR_0);
880 DoTestGroup(__LINE__, _countof(s_group_04), s_group_04, TRUE, SRC_04, WATCHDIR_0);
881 DoTestGroup(__LINE__, _countof(s_group_06), s_group_06, TRUE, SRC_05, WATCHDIR_0);
882 DoTestGroup(__LINE__, _countof(s_group_04), s_group_04, TRUE, SRC_06, WATCHDIR_0);
883 DoTestGroup(__LINE__, _countof(s_group_06), s_group_06, TRUE, SRC_07, WATCHDIR_0);
884 DoTestGroup(__LINE__, _countof(s_group_04), s_group_04, TRUE, SRC_08, WATCHDIR_0);
885 DoTestGroup(__LINE__, _countof(s_group_06), s_group_06, TRUE, SRC_09, WATCHDIR_0);
886 DoTestGroup(__LINE__, _countof(s_group_04), s_group_04, TRUE, SRC_10, WATCHDIR_0);
887 DoTestGroup(__LINE__, _countof(s_group_06), s_group_06, TRUE, SRC_11, WATCHDIR_0);
888
889 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, TRUE, SRC_00, WATCHDIR_1);
890 DoTestGroup(__LINE__, _countof(s_group_01), s_group_01, TRUE, SRC_01, WATCHDIR_1);
891 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, TRUE, SRC_02, WATCHDIR_1);
892 DoTestGroup(__LINE__, _countof(s_group_01), s_group_01, TRUE, SRC_03, WATCHDIR_1);
893 DoTestGroup(__LINE__, _countof(s_group_04), s_group_04, TRUE, SRC_04, WATCHDIR_1);
894 DoTestGroup(__LINE__, _countof(s_group_06), s_group_06, TRUE, SRC_05, WATCHDIR_1);
895 DoTestGroup(__LINE__, _countof(s_group_04), s_group_04, TRUE, SRC_06, WATCHDIR_1);
896 DoTestGroup(__LINE__, _countof(s_group_06), s_group_06, TRUE, SRC_07, WATCHDIR_1);
897 DoTestGroup(__LINE__, _countof(s_group_04), s_group_04, TRUE, SRC_08, WATCHDIR_1);
898 DoTestGroup(__LINE__, _countof(s_group_06), s_group_06, TRUE, SRC_09, WATCHDIR_1);
899 DoTestGroup(__LINE__, _countof(s_group_04), s_group_04, TRUE, SRC_10, WATCHDIR_1);
900 DoTestGroup(__LINE__, _countof(s_group_06), s_group_06, TRUE, SRC_11, WATCHDIR_1);
901
902 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, TRUE, SRC_00, WATCHDIR_2);
903 DoTestGroup(__LINE__, _countof(s_group_01), s_group_01, TRUE, SRC_01, WATCHDIR_2);
904 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, TRUE, SRC_02, WATCHDIR_2);
905 DoTestGroup(__LINE__, _countof(s_group_01), s_group_01, TRUE, SRC_03, WATCHDIR_2);
906 DoTestGroup(__LINE__, _countof(s_group_04), s_group_04, TRUE, SRC_04, WATCHDIR_2);
907 DoTestGroup(__LINE__, _countof(s_group_06), s_group_06, TRUE, SRC_05, WATCHDIR_2);
908 DoTestGroup(__LINE__, _countof(s_group_04), s_group_04, TRUE, SRC_06, WATCHDIR_2);
909 DoTestGroup(__LINE__, _countof(s_group_06), s_group_06, TRUE, SRC_07, WATCHDIR_2);
910 DoTestGroup(__LINE__, _countof(s_group_04), s_group_04, TRUE, SRC_08, WATCHDIR_2);
911 DoTestGroup(__LINE__, _countof(s_group_06), s_group_06, TRUE, SRC_09, WATCHDIR_2);
912 DoTestGroup(__LINE__, _countof(s_group_04), s_group_04, TRUE, SRC_10, WATCHDIR_2);
913 DoTestGroup(__LINE__, _countof(s_group_06), s_group_06, TRUE, SRC_11, WATCHDIR_2);
914
915 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, TRUE, SRC_00, WATCHDIR_3);
916 DoTestGroup(__LINE__, _countof(s_group_02), s_group_02, TRUE, SRC_01, WATCHDIR_3);
917 DoTestGroup(__LINE__, _countof(s_group_00), s_group_00, TRUE, SRC_02, WATCHDIR_3);
918 DoTestGroup(__LINE__, _countof(s_group_02), s_group_02, TRUE, SRC_03, WATCHDIR_3);
919 DoTestGroup(__LINE__, _countof(s_group_05), s_group_05, TRUE, SRC_04, WATCHDIR_3);
920 DoTestGroup(__LINE__, _countof(s_group_08), s_group_08, TRUE, SRC_05, WATCHDIR_3);
921 DoTestGroup(__LINE__, _countof(s_group_05), s_group_05, TRUE, SRC_06, WATCHDIR_3);
922 DoTestGroup(__LINE__, _countof(s_group_08), s_group_08, TRUE, SRC_07, WATCHDIR_3);
923 DoTestGroup(__LINE__, _countof(s_group_05), s_group_05, TRUE, SRC_08, WATCHDIR_3);
924 DoTestGroup(__LINE__, _countof(s_group_08), s_group_08, TRUE, SRC_09, WATCHDIR_3);
925 DoTestGroup(__LINE__, _countof(s_group_05), s_group_05, TRUE, SRC_10, WATCHDIR_3);
926 DoTestGroup(__LINE__, _countof(s_group_08), s_group_08, TRUE, SRC_11, WATCHDIR_3);
927
928 return 0;
929 }
930
931 START_TEST(SHChangeNotify)
932 {
933 #ifdef DISABLE_THIS_TESTCASE
934 skip("This testcase is disabled by DISABLE_THIS_TESTCASE macro.\n");
935 #endif
936 #ifdef TOTAL_TICK
937 DWORD dwOldTick = GetTickCount();
938 #endif
939
940 trace("Please don't operate your PC while testing...\n");
941
942 if (!GetSubProgramPath())
943 {
944 skip("shell32_apitest_sub.exe not found\n");
945 return;
946 }
947
948 if (!DoInitTest())
949 {
950 skip("Unable to initialize.\n");
951 DoQuitTest(TRUE);
952 return;
953 }
954
955 s_hThread = (HANDLE)_beginthreadex(NULL, 0, TestThreadProc, NULL, 0, NULL);
956 WaitForSingleObject(s_hThread, INFINITE);
957 CloseHandle(s_hThread);
958
959 #ifdef TOTAL_TICK
960 DWORD dwNewTick = GetTickCount();
961 DWORD dwTick = dwNewTick - dwOldTick;
962 trace("SHChangeNotify: Total %lu.%lu sec\n", (dwTick / 1000), (dwTick / 100 % 10));
963 #endif
964 }