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 } 965