1 /*
2  * PROJECT:     ReactOS API tests
3  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:     Test for advpack.dll DelNode function
5  * COPYRIGHT:   Copyright 2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6  */
7 #include <apitest.h>
8 
9 #include <windef.h>
10 #include <stdio.h>
11 
12 /* Flags for DelNode */
13 #define ADN_DEL_IF_EMPTY            0x00000001
14 #define ADN_DONT_DEL_SUBDIRS        0x00000002
15 #define ADN_DONT_DEL_DIR            0x00000004
16 #define ADN_DEL_UNC_PATHS           0x00000008
17 
18 /* DelNodeA and DelNodeW in advpack.dll */
19 typedef HRESULT (WINAPI *DELNODEA)(LPCSTR, DWORD);
20 typedef HRESULT (WINAPI *DELNODEW)(LPCWSTR, DWORD);
21 
22 static HINSTANCE s_hAdvPack = NULL;
23 static DELNODEA s_pDelNodeA = NULL;
24 static DELNODEW s_pDelNodeW = NULL;
25 
26 typedef struct
27 {
28     const char *item;
29     BOOL is_dir;
30 } NODEA;
31 
32 static const NODEA s_nodesA[] =
33 {
34     { "dir1", TRUE },               /* 0 */
35     { "dir1\\dir2", TRUE },         /* 1 */
36     { "dir1\\dir2\\file1", FALSE }, /* 2 */
37 };
38 
39 typedef struct
40 {
41     const WCHAR *item;
42     BOOL is_dir;
43 } NODEW;
44 
45 static const NODEW s_nodesW[] =
46 {
47     { L"dir1", TRUE },               /* 0 */
48     { L"dir1\\dir2", TRUE },         /* 1 */
49     { L"dir1\\dir2\\file1", FALSE }, /* 2 */
50 };
51 
52 typedef enum
53 {
54     EAT_CREATE,
55     EAT_DELETE,
56     EAT_CHECK_EXIST,
57     EAT_CHECK_NON_EXIST,
58     EAT_CALL
59 } ENTRY_ACTION_TYPE;
60 
61 typedef struct
62 {
63     INT lineno;
64     INT node;
65     ENTRY_ACTION_TYPE action_type;
66     DWORD flags;
67     HRESULT ret;
68 } ENTRY;
69 
70 /* TODO: ADN_DEL_UNC_PATHS */
71 #define FLAGS0  0
72 #define FLAGS1  ADN_DEL_IF_EMPTY
73 #define FLAGS2  ADN_DONT_DEL_DIR
74 #define FLAGS3  ADN_DONT_DEL_SUBDIRS
75 #define FLAGS4  (ADN_DONT_DEL_DIR | ADN_DONT_DEL_SUBDIRS)
76 #define FLAGS5  (ADN_DEL_IF_EMPTY | ADN_DONT_DEL_DIR)
77 #define FLAGS6  (ADN_DEL_IF_EMPTY | ADN_DONT_DEL_SUBDIRS)
78 #define FLAGS7  (ADN_DEL_IF_EMPTY | ADN_DONT_DEL_DIR | ADN_DONT_DEL_SUBDIRS)
79 #define FLAGS8  0xFFFFFFFF
80 
81 /* The test entries */
82 static const ENTRY s_entries[] =
83 {
84     { __LINE__, 0, EAT_CREATE },
85     { __LINE__, 1, EAT_CREATE },
86     { __LINE__, 1, EAT_DELETE },
87     { __LINE__, 0, EAT_DELETE },
88 
89     { __LINE__, 0, EAT_CREATE },
90     { __LINE__, 1, EAT_CREATE },
91     { __LINE__, 0, EAT_CALL, FLAGS0, S_OK },
92     { __LINE__, 0, EAT_CHECK_NON_EXIST },
93 
94     { __LINE__, 0, EAT_CREATE },
95     { __LINE__, 1, EAT_CREATE },
96     { __LINE__, 0, EAT_CALL, FLAGS1, E_FAIL },
97     { __LINE__, 0, EAT_CHECK_EXIST },
98 
99     { __LINE__, 0, EAT_CREATE },
100     { __LINE__, 1, EAT_CREATE },
101     { __LINE__, 0, EAT_CALL, FLAGS2, S_OK },
102     { __LINE__, 0, EAT_CHECK_EXIST },
103 
104     { __LINE__, 0, EAT_CREATE },
105     { __LINE__, 1, EAT_CREATE },
106     { __LINE__, 0, EAT_CALL, FLAGS3, S_OK },
107     { __LINE__, 0, EAT_CHECK_EXIST },
108 
109     { __LINE__, 0, EAT_CREATE },
110     { __LINE__, 1, EAT_CREATE },
111     { __LINE__, 0, EAT_CALL, FLAGS4, S_OK },
112     { __LINE__, 0, EAT_CHECK_EXIST },
113 
114     { __LINE__, 0, EAT_CREATE },
115     { __LINE__, 1, EAT_CREATE },
116     { __LINE__, 0, EAT_CALL, FLAGS5, E_FAIL },
117     { __LINE__, 0, EAT_CHECK_EXIST },
118 
119     { __LINE__, 0, EAT_CREATE },
120     { __LINE__, 1, EAT_CREATE },
121     { __LINE__, 0, EAT_CALL, FLAGS6, E_FAIL },
122     { __LINE__, 0, EAT_CHECK_EXIST },
123 
124     { __LINE__, 0, EAT_CREATE },
125     { __LINE__, 1, EAT_CREATE },
126     { __LINE__, 0, EAT_CALL, FLAGS7, E_FAIL },
127     { __LINE__, 0, EAT_CHECK_EXIST },
128 
129     { __LINE__, 0, EAT_CREATE },
130     { __LINE__, 1, EAT_CREATE },
131     { __LINE__, 0, EAT_CALL, FLAGS8, E_FAIL },
132     { __LINE__, 0, EAT_CHECK_EXIST },
133 
134     { __LINE__, 0, EAT_CREATE },
135     { __LINE__, 1, EAT_CREATE },
136     { __LINE__, 2, EAT_CREATE },
137     { __LINE__, 0, EAT_CALL, FLAGS0, S_OK },
138     { __LINE__, 0, EAT_CHECK_NON_EXIST },
139 
140     { __LINE__, 0, EAT_CREATE },
141     { __LINE__, 1, EAT_CREATE },
142     { __LINE__, 2, EAT_CREATE },
143     { __LINE__, 0, EAT_CALL, FLAGS1, E_FAIL },
144     { __LINE__, 0, EAT_CHECK_EXIST },
145     { __LINE__, 1, EAT_CHECK_EXIST },
146     { __LINE__, 2, EAT_CHECK_EXIST },
147 
148     { __LINE__, 0, EAT_CREATE },
149     { __LINE__, 1, EAT_CREATE },
150     { __LINE__, 2, EAT_CREATE },
151     { __LINE__, 0, EAT_CALL, FLAGS2, S_OK },
152     { __LINE__, 0, EAT_CHECK_EXIST },
153     { __LINE__, 1, EAT_CHECK_NON_EXIST },
154     { __LINE__, 2, EAT_CHECK_NON_EXIST },
155 
156     { __LINE__, 0, EAT_CREATE },
157     { __LINE__, 1, EAT_CREATE },
158     { __LINE__, 2, EAT_CREATE },
159     { __LINE__, 0, EAT_CALL, FLAGS3, S_OK },
160     { __LINE__, 0, EAT_CHECK_EXIST },
161     { __LINE__, 1, EAT_CHECK_EXIST },
162     { __LINE__, 2, EAT_CHECK_EXIST },
163 
164     { __LINE__, 0, EAT_CREATE },
165     { __LINE__, 1, EAT_CREATE },
166     { __LINE__, 2, EAT_CREATE },
167     { __LINE__, 0, EAT_CALL, FLAGS4, S_OK },
168     { __LINE__, 0, EAT_CHECK_EXIST },
169     { __LINE__, 1, EAT_CHECK_EXIST },
170     { __LINE__, 2, EAT_CHECK_EXIST },
171 
172     { __LINE__, 0, EAT_CREATE },
173     { __LINE__, 1, EAT_CREATE },
174     { __LINE__, 2, EAT_CREATE },
175     { __LINE__, 0, EAT_CALL, FLAGS5, E_FAIL },
176     { __LINE__, 0, EAT_CHECK_EXIST },
177     { __LINE__, 1, EAT_CHECK_EXIST },
178     { __LINE__, 2, EAT_CHECK_EXIST },
179 
180     { __LINE__, 0, EAT_CREATE },
181     { __LINE__, 1, EAT_CREATE },
182     { __LINE__, 2, EAT_CREATE },
183     { __LINE__, 0, EAT_CALL, FLAGS6, E_FAIL },
184     { __LINE__, 0, EAT_CHECK_EXIST },
185     { __LINE__, 1, EAT_CHECK_EXIST },
186     { __LINE__, 2, EAT_CHECK_EXIST },
187 
188     { __LINE__, 0, EAT_CREATE },
189     { __LINE__, 1, EAT_CREATE },
190     { __LINE__, 2, EAT_CREATE },
191     { __LINE__, 0, EAT_CALL, FLAGS7, E_FAIL },
192     { __LINE__, 0, EAT_CHECK_EXIST },
193     { __LINE__, 1, EAT_CHECK_EXIST },
194     { __LINE__, 2, EAT_CHECK_EXIST },
195 
196     { __LINE__, 0, EAT_CREATE },
197     { __LINE__, 1, EAT_CREATE },
198     { __LINE__, 2, EAT_CREATE },
199     { __LINE__, 0, EAT_CALL, FLAGS8, E_FAIL },
200     { __LINE__, 0, EAT_CHECK_EXIST },
201     { __LINE__, 1, EAT_CHECK_EXIST },
202     { __LINE__, 2, EAT_CHECK_EXIST },
203 
204     { __LINE__, 1, EAT_CREATE },
205     { __LINE__, 2, EAT_CREATE },
206     { __LINE__, 1, EAT_CALL, FLAGS0, S_OK },
207     { __LINE__, 1, EAT_CHECK_NON_EXIST },
208 
209     { __LINE__, 1, EAT_CREATE },
210     { __LINE__, 2, EAT_CREATE },
211     { __LINE__, 1, EAT_CALL, FLAGS1, E_FAIL },
212     { __LINE__, 1, EAT_CHECK_EXIST },
213     { __LINE__, 2, EAT_CHECK_EXIST },
214 
215     { __LINE__, 1, EAT_CREATE },
216     { __LINE__, 2, EAT_CREATE },
217     { __LINE__, 1, EAT_CALL, FLAGS2, S_OK },
218     { __LINE__, 1, EAT_CHECK_EXIST },
219     { __LINE__, 2, EAT_CHECK_NON_EXIST },
220 
221     { __LINE__, 1, EAT_CREATE },
222     { __LINE__, 2, EAT_CREATE },
223     { __LINE__, 1, EAT_CALL, FLAGS3, S_OK },
224     { __LINE__, 1, EAT_CHECK_NON_EXIST },
225 
226     { __LINE__, 1, EAT_CREATE },
227     { __LINE__, 2, EAT_CREATE },
228     { __LINE__, 1, EAT_CALL, FLAGS4, S_OK },
229     { __LINE__, 1, EAT_CHECK_EXIST },
230     { __LINE__, 2, EAT_CHECK_NON_EXIST },
231 
232     { __LINE__, 1, EAT_CREATE },
233     { __LINE__, 2, EAT_CREATE },
234     { __LINE__, 1, EAT_CALL, FLAGS5, E_FAIL },
235     { __LINE__, 1, EAT_CHECK_EXIST },
236     { __LINE__, 2, EAT_CHECK_EXIST },
237 
238     { __LINE__, 1, EAT_CREATE },
239     { __LINE__, 2, EAT_CREATE },
240     { __LINE__, 1, EAT_CALL, FLAGS6, E_FAIL },
241     { __LINE__, 1, EAT_CHECK_EXIST },
242     { __LINE__, 2, EAT_CHECK_EXIST },
243 
244     { __LINE__, 1, EAT_CREATE },
245     { __LINE__, 2, EAT_CREATE },
246     { __LINE__, 1, EAT_CALL, FLAGS7, E_FAIL },
247     { __LINE__, 1, EAT_CHECK_EXIST },
248     { __LINE__, 2, EAT_CHECK_EXIST },
249 
250     { __LINE__, 1, EAT_CREATE },
251     { __LINE__, 2, EAT_CREATE },
252     { __LINE__, 1, EAT_CALL, FLAGS8, E_FAIL },
253     { __LINE__, 1, EAT_CHECK_EXIST },
254     { __LINE__, 2, EAT_CHECK_EXIST },
255 
256     { __LINE__, 2, EAT_DELETE },
257 
258     { __LINE__, 1, EAT_CREATE },
259     { __LINE__, 1, EAT_CALL, FLAGS0, S_OK },
260     { __LINE__, 1, EAT_CHECK_NON_EXIST },
261 
262     { __LINE__, 1, EAT_CREATE },
263     { __LINE__, 1, EAT_CALL, FLAGS1, S_OK },
264     { __LINE__, 1, EAT_CHECK_NON_EXIST },
265 
266     { __LINE__, 1, EAT_CREATE },
267     { __LINE__, 1, EAT_CALL, FLAGS2, S_OK },
268     { __LINE__, 1, EAT_CHECK_EXIST },
269 
270     { __LINE__, 1, EAT_CREATE },
271     { __LINE__, 1, EAT_CALL, FLAGS3, S_OK },
272     { __LINE__, 1, EAT_CHECK_NON_EXIST },
273 
274     { __LINE__, 1, EAT_CREATE },
275     { __LINE__, 1, EAT_CALL, FLAGS4, S_OK },
276     { __LINE__, 1, EAT_CHECK_EXIST },
277 
278     { __LINE__, 1, EAT_CREATE },
279     { __LINE__, 1, EAT_CALL, FLAGS5, S_OK },
280     { __LINE__, 1, EAT_CHECK_NON_EXIST },
281 
282     { __LINE__, 1, EAT_CREATE },
283     { __LINE__, 1, EAT_CALL, FLAGS6, S_OK },
284     { __LINE__, 1, EAT_CHECK_NON_EXIST },
285 
286     { __LINE__, 1, EAT_CREATE },
287     { __LINE__, 1, EAT_CALL, FLAGS7, S_OK },
288     { __LINE__, 1, EAT_CHECK_NON_EXIST },
289 
290     { __LINE__, 1, EAT_CREATE },
291     { __LINE__, 1, EAT_CALL, FLAGS8, S_OK },
292     { __LINE__, 1, EAT_CHECK_NON_EXIST },
293 
294     { __LINE__, 1, EAT_CREATE },
295 
296     { __LINE__, 2, EAT_CREATE },
297     { __LINE__, 2, EAT_CALL, FLAGS0, S_OK },
298     { __LINE__, 2, EAT_CHECK_NON_EXIST },
299 
300     { __LINE__, 2, EAT_CREATE },
301     { __LINE__, 2, EAT_CALL, FLAGS1, S_OK },
302     { __LINE__, 2, EAT_CHECK_NON_EXIST },
303 
304     { __LINE__, 2, EAT_CREATE },
305     { __LINE__, 2, EAT_CALL, FLAGS2, S_OK },
306     { __LINE__, 2, EAT_CHECK_NON_EXIST },
307 
308     { __LINE__, 2, EAT_CREATE },
309     { __LINE__, 2, EAT_CALL, FLAGS3, S_OK },
310     { __LINE__, 2, EAT_CHECK_NON_EXIST },
311 
312     { __LINE__, 2, EAT_CREATE },
313     { __LINE__, 2, EAT_CALL, FLAGS4, S_OK },
314     { __LINE__, 2, EAT_CHECK_NON_EXIST },
315 
316     { __LINE__, 2, EAT_CREATE },
317     { __LINE__, 2, EAT_CALL, FLAGS5, S_OK },
318     { __LINE__, 2, EAT_CHECK_NON_EXIST },
319 
320     { __LINE__, 2, EAT_CREATE },
321     { __LINE__, 2, EAT_CALL, FLAGS6, S_OK },
322     { __LINE__, 2, EAT_CHECK_NON_EXIST },
323 
324     { __LINE__, 2, EAT_CREATE },
325     { __LINE__, 2, EAT_CALL, FLAGS7, S_OK },
326     { __LINE__, 2, EAT_CHECK_NON_EXIST },
327 
328     { __LINE__, 2, EAT_CREATE },
329     { __LINE__, 2, EAT_CALL, FLAGS8, S_OK },
330     { __LINE__, 2, EAT_CHECK_NON_EXIST },
331 
332     { __LINE__, 2, EAT_DELETE },
333     { __LINE__, 1, EAT_DELETE },
334     { __LINE__, 0, EAT_DELETE },
335 
336     { __LINE__, 2, EAT_CALL, FLAGS0, E_FAIL },
337     { __LINE__, 2, EAT_CALL, FLAGS1, E_FAIL },
338     { __LINE__, 2, EAT_CALL, FLAGS2, E_FAIL },
339     { __LINE__, 2, EAT_CALL, FLAGS3, E_FAIL },
340     { __LINE__, 2, EAT_CALL, FLAGS4, E_FAIL },
341     { __LINE__, 2, EAT_CALL, FLAGS5, E_FAIL },
342     { __LINE__, 2, EAT_CALL, FLAGS6, E_FAIL },
343     { __LINE__, 2, EAT_CALL, FLAGS7, E_FAIL },
344     { __LINE__, 2, EAT_CALL, FLAGS8, E_FAIL },
345 
346     { __LINE__, 1, EAT_CALL, FLAGS0, E_FAIL },
347     { __LINE__, 1, EAT_CALL, FLAGS1, E_FAIL },
348     { __LINE__, 1, EAT_CALL, FLAGS2, E_FAIL },
349     { __LINE__, 1, EAT_CALL, FLAGS3, E_FAIL },
350     { __LINE__, 1, EAT_CALL, FLAGS4, E_FAIL },
351     { __LINE__, 1, EAT_CALL, FLAGS5, E_FAIL },
352     { __LINE__, 1, EAT_CALL, FLAGS6, E_FAIL },
353     { __LINE__, 1, EAT_CALL, FLAGS7, E_FAIL },
354     { __LINE__, 1, EAT_CALL, FLAGS8, E_FAIL },
355 };
356 
357 static char  s_cur_dir_A[MAX_PATH] = "";
358 static WCHAR s_cur_dir_W[MAX_PATH] = L"";
359 
360 static char *GetPathA(const char *item)
361 {
362     static char s_path[MAX_PATH];
363     lstrcpyA(s_path, s_cur_dir_A);
364     lstrcatA(s_path, "\\");
365     lstrcatA(s_path, item);
366     return s_path;
367 }
368 
369 static WCHAR *GetPathW(const WCHAR *item)
370 {
371     static WCHAR s_path[MAX_PATH];
372     lstrcpyW(s_path, s_cur_dir_W);
373     lstrcatW(s_path, L"\\");
374     lstrcatW(s_path, item);
375     return s_path;
376 }
377 
378 static void cleanupA(void)
379 {
380     size_t i, k;
381     for (k = 0; k < 4; ++k)
382     {
383         for (i = 0; i < _countof(s_nodesA); ++i)
384         {
385             const NODEA *node = &s_nodesA[i];
386             char *path = GetPathA(node->item);
387 
388             DeleteFileA(path);
389             RemoveDirectoryA(path);
390         }
391     }
392 }
393 
394 static void Test_DelNodeA(void)
395 {
396     DWORD attr;
397     size_t i;
398 
399     if (!GetCurrentDirectoryA(_countof(s_cur_dir_A), s_cur_dir_A))
400     {
401         skip("GetCurrentDirectoryA failed\n");
402         return;
403     }
404 
405     cleanupA();
406 
407     for (i = 0; i < _countof(s_entries); ++i)
408     {
409         const ENTRY *entry = &s_entries[i];
410         INT lineno = entry->lineno;
411         const NODEA *node = &s_nodesA[entry->node];
412         char *path = GetPathA(node->item);
413         INT ret;
414 
415         switch (entry->action_type)
416         {
417             case EAT_CREATE:
418                 if (node->is_dir)
419                 {
420                     CreateDirectoryA(path, NULL);
421 
422                     attr = GetFileAttributesA(path);
423                     ok(attr != INVALID_FILE_ATTRIBUTES, "Line %d: path:%s, attr:0x%08lX\n", lineno, path, attr);
424                     ok((attr & FILE_ATTRIBUTE_DIRECTORY), "Line %d: path:%s, attr:0x%08lX\n", lineno, path, attr);
425                 }
426                 else
427                 {
428                     fclose(fopen(path, "w"));
429 
430                     attr = GetFileAttributesA(path);
431                     ok(attr != INVALID_FILE_ATTRIBUTES, "Line %d: attr was 0x%08lX\n", lineno, attr);
432                     ok(!(attr & FILE_ATTRIBUTE_DIRECTORY), "Line %d: attr was 0x%08lX\n", lineno, attr);
433                 }
434                 break;
435             case EAT_DELETE:
436                 if (node->is_dir)
437                 {
438                     RemoveDirectoryA(path);
439                 }
440                 else
441                 {
442                     DeleteFileA(path);
443                 }
444                 attr = GetFileAttributesA(path);
445                 ok(attr == INVALID_FILE_ATTRIBUTES, "Line %d: cannot delete\n", lineno);
446                 break;
447             case EAT_CHECK_EXIST:
448                 attr = GetFileAttributesA(path);
449                 ok(attr != INVALID_FILE_ATTRIBUTES, "Line %d: attr was 0x%08lX\n", lineno, attr);
450                 break;
451             case EAT_CHECK_NON_EXIST:
452                 attr = GetFileAttributesA(path);
453                 ok(attr == INVALID_FILE_ATTRIBUTES, "Line %d: attr was 0x%08lX\n", lineno, attr);
454                 break;
455             case EAT_CALL:
456                 ret = (*s_pDelNodeA)(path, entry->flags);
457                 ok(ret == entry->ret, "Line %d: ret:%d, path:%s, flags:0x%08lX\n",
458                    lineno, ret, path, entry->flags);
459                 break;
460         }
461     }
462 
463     cleanupA();
464 }
465 
466 static void cleanupW(void)
467 {
468     size_t i, k;
469     for (k = 0; k < 4; ++k)
470     {
471         for (i = 0; i < _countof(s_nodesW); ++i)
472         {
473             const NODEW *node = &s_nodesW[i];
474             WCHAR *path = GetPathW(node->item);
475 
476             DeleteFileW(path);
477             RemoveDirectoryW(path);
478         }
479     }
480 }
481 
482 static void Test_DelNodeW(void)
483 {
484     DWORD attr;
485     size_t i;
486 
487     if (!GetCurrentDirectoryW(_countof(s_cur_dir_W), s_cur_dir_W))
488     {
489         skip("GetCurrentDirectoryA failed\n");
490         return;
491     }
492 
493     cleanupW();
494 
495     for (i = 0; i < _countof(s_entries); ++i)
496     {
497         const ENTRY *entry = &s_entries[i];
498         INT lineno = entry->lineno;
499         const NODEW *node = &s_nodesW[entry->node];
500         WCHAR *path = GetPathW(node->item);
501         INT ret;
502 
503         switch (entry->action_type)
504         {
505             case EAT_CREATE:
506                 if (node->is_dir)
507                 {
508                     CreateDirectoryW(path, NULL);
509 
510                     attr = GetFileAttributesW(path);
511                     ok(attr != INVALID_FILE_ATTRIBUTES, "Line %d: path:%S, attr:0x%08lX\n", lineno, path, attr);
512                     ok((attr & FILE_ATTRIBUTE_DIRECTORY), "Line %d: path:%S, attr:0x%08lX\n", lineno, path, attr);
513                 }
514                 else
515                 {
516                     fclose(_wfopen(path, L"w"));
517 
518                     attr = GetFileAttributesW(path);
519                     ok(attr != INVALID_FILE_ATTRIBUTES, "Line %d: attr was 0x%08lX\n", lineno, attr);
520                     ok(!(attr & FILE_ATTRIBUTE_DIRECTORY), "Line %d: attr was 0x%08lX\n", lineno, attr);
521                 }
522                 break;
523             case EAT_DELETE:
524                 if (node->is_dir)
525                 {
526                     RemoveDirectoryW(path);
527                 }
528                 else
529                 {
530                     DeleteFileW(path);
531                 }
532                 attr = GetFileAttributesW(path);
533                 ok(attr == INVALID_FILE_ATTRIBUTES, "Line %d: cannot delete\n", lineno);
534                 break;
535             case EAT_CHECK_EXIST:
536                 attr = GetFileAttributesW(path);
537                 ok(attr != INVALID_FILE_ATTRIBUTES, "Line %d: attr was 0x%08lX\n", lineno, attr);
538                 break;
539             case EAT_CHECK_NON_EXIST:
540                 attr = GetFileAttributesW(path);
541                 ok(attr == INVALID_FILE_ATTRIBUTES, "Line %d: attr was 0x%08lX\n", lineno, attr);
542                 break;
543             case EAT_CALL:
544                 ret = (*s_pDelNodeW)(path, entry->flags);
545                 ok(ret == entry->ret, "Line %d: ret:%d, path:%S, flags:0x%08lX\n",
546                    lineno, ret, path, entry->flags);
547                 break;
548         }
549     }
550 
551     cleanupW();
552 }
553 
554 START_TEST(DelNode)
555 {
556     s_hAdvPack = LoadLibraryA("advpack.dll");
557     if (s_hAdvPack == NULL)
558     {
559         skip("unable to load advpack.dll\n");
560         return;
561     }
562 
563     /* DelNodeA */
564     s_pDelNodeA = (DELNODEA)GetProcAddress(s_hAdvPack, "DelNodeA");
565     if (s_pDelNodeA)
566     {
567         Test_DelNodeA();
568     }
569     else
570     {
571         skip("DelNodeA not found in advpack.dll\n");
572     }
573 
574     /* DelNodeW */
575     s_pDelNodeW = (DELNODEW)GetProcAddress(s_hAdvPack, "DelNodeW");
576     if (s_pDelNodeW)
577     {
578         Test_DelNodeW();
579     }
580     else
581     {
582         skip("DelNodeW not found in advpack.dll\n");
583     }
584 
585     FreeLibrary(s_hAdvPack);
586     s_hAdvPack = NULL;
587 }
588