1 /*
2  * PROJECT:         ReactOS api tests
3  * LICENSE:         GPLv2+ - See COPYING in the top level directory
4  * PURPOSE:         Tests for PathResolve
5  * PROGRAMMER:      Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6  */
7 
8 #include "shelltest.h"
9 
10 #include <stdio.h>
11 #include <assert.h>
12 
13 /*
14  * NOTE: "App Paths" registry key and PATHEXT environment variable
15  *       have no effect for PathResolve.
16  */
17 
18 /* PathResolve */
19 typedef int (WINAPI *PATHRESOLVE)(LPWSTR, LPWSTR*, UINT);
20 
21 /* IsLFNDriveW */
22 typedef BOOL (WINAPI *ISLFNDRIVEW)(LPCWSTR);
23 
24 static HINSTANCE    s_hShell32 = NULL;
25 static PATHRESOLVE  s_pPathResolve = NULL;
26 static ISLFNDRIVEW  s_pIsLFNDriveW = NULL;
27 static WCHAR        s_TestDir[MAX_PATH];
28 static WCHAR        s_ShortcutLongName[MAX_PATH];
29 static WCHAR        s_ShortcutShortName[MAX_PATH];
30 static WCHAR        s_LinkTarget[MAX_PATH];
31 static LPWSTR       s_Dirs[2] = { s_TestDir, NULL };
32 
33 /* PathResolve flags */
34 #ifndef PRF_VERIFYEXISTS
35     #define PRF_VERIFYEXISTS         0x01
36     #define PRF_EXECUTABLE           0x02
37     #define PRF_TRYPROGRAMEXTENSIONS (PRF_EXECUTABLE | PRF_VERIFYEXISTS)
38     #define PRF_FIRSTDIRDEF          0x04
39     #define PRF_DONTFINDLNK          0x08
40 #endif
41 #ifndef PRF_REQUIREABSOLUTE
42     #define PRF_REQUIREABSOLUTE      0x10
43 #endif
44 
45 /* Abstraction of PathResolve flags to manage the test entries */
46 #define FLAGS0      0
47 #define FLAGS1      PRF_VERIFYEXISTS
48 #define FLAGS2      PRF_EXECUTABLE
49 #define FLAGS3      PRF_TRYPROGRAMEXTENSIONS
50 #define FLAGS4      (PRF_FIRSTDIRDEF | PRF_VERIFYEXISTS)
51 #define FLAGS5      (PRF_FIRSTDIRDEF | PRF_EXECUTABLE)
52 #define FLAGS6      (PRF_FIRSTDIRDEF | PRF_TRYPROGRAMEXTENSIONS)
53 #define FLAGS7      (PRF_REQUIREABSOLUTE | PRF_VERIFYEXISTS)
54 #define FLAGS8      (PRF_REQUIREABSOLUTE | PRF_EXECUTABLE)
55 #define FLAGS9      (PRF_REQUIREABSOLUTE | PRF_TRYPROGRAMEXTENSIONS)
56 #define FLAGS10     (PRF_REQUIREABSOLUTE | PRF_FIRSTDIRDEF | PRF_VERIFYEXISTS)
57 #define FLAGS11     (PRF_REQUIREABSOLUTE | PRF_FIRSTDIRDEF | PRF_EXECUTABLE)
58 #define FLAGS12     (PRF_REQUIREABSOLUTE | PRF_FIRSTDIRDEF | PRF_TRYPROGRAMEXTENSIONS)
59 #define FLAGS13     0xFFFFFFFF
60 
61 /* The test entry structure */
62 typedef struct tagTEST_ENTRY
63 {
64     INT         LineNumber;    /* # */
65     INT         Ret;
66     DWORD       Error;
67     UINT        EF_;
68     LPCWSTR     NameBefore;
69     LPCWSTR     NameExpected;
70     UINT        Flags;
71     LPWSTR     *Dirs;
72 } TEST_ENTRY, *PTEST_ENTRY;
73 
74 /* Flags for TEST_ENTRY */
75 #define EF_FULLPATH     0x01
76 #define EF_TESTDATA     0x02
77 #define EF_TYPE_MASK    0x0F
78 #define EF_NAME_ONLY    0x10
79 #define EF_APP_PATH     0x20
80 
81 /* Special error codes */
82 #define ERR_NO_CHANGE 0xBEEF      /* Error Code 48879 */
83 #define ERR_DEAD      0xDEAD      /* Error Code 57005 */
84 #define ERR_IGNORE    0x7F7F7F7F  /* Ignore Error Code */
85 #define RAISED        9999        /* exception raised */
86 
87 /* The test entries for long file name (LFN) */
88 static const TEST_ENTRY s_LFNEntries[] =
89 {
90     /* null path */
91     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, NULL, NULL, FLAGS0 },
92     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, NULL, NULL, FLAGS1 },
93     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, NULL, NULL, FLAGS2 },
94     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, NULL, NULL, FLAGS3 },
95     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, NULL, NULL, FLAGS4 },
96     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, NULL, NULL, FLAGS5 },
97     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, NULL, NULL, FLAGS6 },
98     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, NULL, NULL, FLAGS7 },
99     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, NULL, NULL, FLAGS8 },
100     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, NULL, NULL, FLAGS9 },
101     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, NULL, NULL, FLAGS10 },
102     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, NULL, NULL, FLAGS11 },
103     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, NULL, NULL, FLAGS12 },
104     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, NULL, NULL, FLAGS13 },
105     /* empty path */
106     { __LINE__, 1, ERR_NO_CHANGE, EF_FULLPATH, L"", NULL, FLAGS0 },
107     { __LINE__, 1, ERROR_NO_MORE_FILES, EF_FULLPATH, L"", NULL, FLAGS1 },
108     { __LINE__, 1, ERROR_NO_MORE_FILES, EF_FULLPATH, L"", NULL, FLAGS2 },
109     { __LINE__, 1, ERROR_NO_MORE_FILES, EF_FULLPATH, L"", NULL, FLAGS3 },
110     { __LINE__, 1, ERROR_NO_MORE_FILES, EF_FULLPATH, L"", NULL, FLAGS4 },
111     { __LINE__, 1, ERROR_NO_MORE_FILES, EF_FULLPATH, L"", NULL, FLAGS5 },
112     { __LINE__, 1, ERROR_NO_MORE_FILES, EF_FULLPATH, L"", NULL, FLAGS6 },
113     { __LINE__, 1, ERROR_NO_MORE_FILES, EF_FULLPATH, L"", NULL, FLAGS7 },
114     { __LINE__, 1, ERROR_NO_MORE_FILES, EF_FULLPATH, L"", NULL, FLAGS8 },
115     { __LINE__, 1, ERROR_NO_MORE_FILES, EF_FULLPATH, L"", NULL, FLAGS9 },
116     { __LINE__, 1, ERROR_NO_MORE_FILES, EF_FULLPATH, L"", NULL, FLAGS10 },
117     { __LINE__, 1, ERROR_NO_MORE_FILES, EF_FULLPATH, L"", NULL, FLAGS11 },
118     { __LINE__, 1, ERROR_NO_MORE_FILES, EF_FULLPATH, L"", NULL, FLAGS12 },
119     { __LINE__, 1, ERROR_NO_MORE_FILES, EF_FULLPATH, L"", NULL, FLAGS13 },
120     /* invalid name */
121     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_FULLPATH, L"invalid name", L"invalid name", FLAGS0 },
122     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_FULLPATH, L"invalid name", L"invalid name", FLAGS1 },
123     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_FULLPATH, L"invalid name", L"invalid name", FLAGS2 },
124     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_FULLPATH, L"invalid name", L"invalid name", FLAGS3 },
125     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_FULLPATH, L"invalid name", L"invalid name", FLAGS4 },
126     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_FULLPATH, L"invalid name", L"invalid name", FLAGS5 },
127     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_FULLPATH, L"invalid name", L"invalid name", FLAGS6 },
128     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_FULLPATH, L"invalid name", L"invalid name", FLAGS7 },
129     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_FULLPATH, L"invalid name", L"invalid name", FLAGS8 },
130     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_FULLPATH, L"invalid name", L"invalid name", FLAGS9 },
131     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_FULLPATH, L"invalid name", L"invalid name", FLAGS10 },
132     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_FULLPATH, L"invalid name", L"invalid name", FLAGS11 },
133     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_FULLPATH, L"invalid name", L"invalid name", FLAGS12 },
134     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_FULLPATH, L"invalid name", L"invalid name", FLAGS13 },
135     /* testdata/2PRONG (path) */
136     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA, L"2PRONG", L"2PRONG", FLAGS0 },
137     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"2PRONG", L"2PRONG", FLAGS1 },
138     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA, L"2PRONG", L"2PRONG", FLAGS2 },
139     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"2PRONG", L"2PRONG", FLAGS3 },
140     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"2PRONG", L"2PRONG", FLAGS4 },
141     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"2PRONG", L"2PRONG", FLAGS5 },
142     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"2PRONG", L"2PRONG", FLAGS6 },
143     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"2PRONG", L"2PRONG", FLAGS7 },
144     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA, L"2PRONG", L"2PRONG", FLAGS8 },
145     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"2PRONG", L"2PRONG", FLAGS9 },
146     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"2PRONG", L"2PRONG", FLAGS10 },
147     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"2PRONG", L"2PRONG", FLAGS11 },
148     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"2PRONG", L"2PRONG", FLAGS12 },
149     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"2PRONG", L"2PRONG", FLAGS13 },
150     /* testdata/2PRONG (name only) */
151     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS0 },
152     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS1 },
153     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS2 },
154     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS3 },
155     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS4 },
156     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS5 },
157     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS6 },
158     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS7 },
159     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS8 },
160     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS9 },
161     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS10 },
162     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS11 },
163     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS12 },
164     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS13 },
165     /* testdata/2PRONG with dirs (name only) */
166     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS0, s_Dirs },
167     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS1, s_Dirs },
168     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS2, s_Dirs },
169     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS3, s_Dirs },
170     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS4, s_Dirs },
171     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS5, s_Dirs },
172     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS6, s_Dirs },
173     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS7, s_Dirs },
174     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS8, s_Dirs },
175     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS9, s_Dirs },
176     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS10, s_Dirs },
177     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS11, s_Dirs },
178     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS12, s_Dirs },
179     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG", NULL, FLAGS13, s_Dirs },
180     /* testdata/2PRONG (name only, app path) */
181     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"2PRONG", L"2PRONG", FLAGS0 },
182     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"2PRONG", L"2PRONG", FLAGS1 },
183     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"2PRONG", L"2PRONG", FLAGS2 },
184     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"2PRONG", L"2PRONG", FLAGS3 },
185     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"2PRONG", L"2PRONG", FLAGS4 },
186     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"2PRONG", L"2PRONG", FLAGS5 },
187     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"2PRONG", L"2PRONG", FLAGS6 },
188     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"2PRONG", L"2PRONG", FLAGS7 },
189     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"2PRONG", L"2PRONG", FLAGS8 },
190     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"2PRONG", L"2PRONG", FLAGS9 },
191     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"2PRONG", L"2PRONG", FLAGS10 },
192     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"2PRONG", L"2PRONG", FLAGS11 },
193     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"2PRONG", L"2PRONG", FLAGS12 },
194     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"2PRONG", L"2PRONG", FLAGS13 },
195     /* 2PRONG.txt */
196     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS0 },
197     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS1 },
198     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS2 },
199     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS3 },
200     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS4 },
201     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS5 },
202     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS6 },
203     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS7 },
204     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS8 },
205     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS9 },
206     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS10 },
207     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS11 },
208     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS12 },
209     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS13 },
210     /* 2PRONG.txt with dirs */
211     { __LINE__, 1, ERR_IGNORE, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS0, s_Dirs },
212     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS1, s_Dirs },
213     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS2, s_Dirs },
214     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS3, s_Dirs },
215     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS4, s_Dirs },
216     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS5, s_Dirs },
217     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS6, s_Dirs },
218     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS7, s_Dirs },
219     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS8, s_Dirs },
220     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS9, s_Dirs },
221     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS10, s_Dirs },
222     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS11, s_Dirs },
223     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS12, s_Dirs },
224     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"2PRONG.txt", L"2PRONG.txt", FLAGS13, s_Dirs },
225     /* 2PRONG.txt (name only) */
226     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", NULL, FLAGS0 },
227     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", NULL, FLAGS1 },
228     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", NULL, FLAGS2 },
229     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", NULL, FLAGS3 },
230     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", NULL, FLAGS4 },
231     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", NULL, FLAGS5 },
232     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", NULL, FLAGS6 },
233     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", NULL, FLAGS7 },
234     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", NULL, FLAGS8 },
235     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", NULL, FLAGS9 },
236     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", NULL, FLAGS10 },
237     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", NULL, FLAGS11 },
238     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", NULL, FLAGS12 },
239     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", NULL, FLAGS13 },
240     /* 2PRONG.txt with dirs (name only) */
241     { __LINE__, 1, ERR_IGNORE, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", L"2PRONG.txt", FLAGS0, s_Dirs },
242     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", L"2PRONG.txt", FLAGS1, s_Dirs },
243     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", L"2PRONG.txt", FLAGS2, s_Dirs },
244     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", L"2PRONG.txt", FLAGS3, s_Dirs },
245     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", L"2PRONG.txt", FLAGS4, s_Dirs },
246     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", L"2PRONG.txt", FLAGS5, s_Dirs },
247     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", L"2PRONG.txt", FLAGS6, s_Dirs },
248     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", L"2PRONG.txt", FLAGS7, s_Dirs },
249     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", L"2PRONG.txt", FLAGS8, s_Dirs },
250     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", L"2PRONG.txt", FLAGS9, s_Dirs },
251     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", L"2PRONG.txt", FLAGS10, s_Dirs },
252     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", L"2PRONG.txt", FLAGS11, s_Dirs },
253     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", L"2PRONG.txt", FLAGS12, s_Dirs },
254     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"2PRONG.txt", L"2PRONG.txt", FLAGS13, s_Dirs },
255     /* testdata/CmdLineUtils (path) */
256     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS0 },
257     { __LINE__, 1, ERROR_NO_MORE_FILES, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils.lnk", FLAGS1 },
258     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS2 },
259     { __LINE__, 1, ERROR_NO_MORE_FILES, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils.lnk", FLAGS3 },
260     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS4 },
261     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS5 },
262     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS6 },
263     { __LINE__, 1, ERROR_NO_MORE_FILES, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils.lnk", FLAGS7 },
264     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS8 },
265     { __LINE__, 1, ERROR_NO_MORE_FILES, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils.lnk", FLAGS9 },
266     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS10 },
267     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS11 },
268     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS12 },
269     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS13 },
270     /* testdata/CmdLineUtils with PRF_DONTFINDLNK (path) */
271     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS0 | PRF_DONTFINDLNK },
272     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS1 | PRF_DONTFINDLNK },
273     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS2 | PRF_DONTFINDLNK },
274     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS3 | PRF_DONTFINDLNK },
275     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS4 | PRF_DONTFINDLNK },
276     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS5 | PRF_DONTFINDLNK },
277     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS6 | PRF_DONTFINDLNK },
278     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS7 | PRF_DONTFINDLNK },
279     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS8 | PRF_DONTFINDLNK },
280     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS9 | PRF_DONTFINDLNK },
281     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS10 | PRF_DONTFINDLNK },
282     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS11 | PRF_DONTFINDLNK },
283     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS12 | PRF_DONTFINDLNK },
284     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"CmdLineUtils", L"CmdLineUtils", FLAGS13 | PRF_DONTFINDLNK },
285     /* testdata/CmdLineUtils (name only) */
286     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils", NULL, FLAGS0 },
287     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils", NULL, FLAGS1 },
288     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils", NULL, FLAGS2 },
289     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils", NULL, FLAGS3 },
290     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils", NULL, FLAGS4 },
291     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils", NULL, FLAGS5 },
292     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils", NULL, FLAGS6 },
293     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils", NULL, FLAGS7 },
294     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils", NULL, FLAGS8 },
295     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils", NULL, FLAGS9 },
296     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils", NULL, FLAGS10 },
297     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils", NULL, FLAGS11 },
298     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils", NULL, FLAGS12 },
299     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils", NULL, FLAGS13 },
300     /* testdata/CmdLineUtils.exe (path) */
301     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA, L"CmdLineUtils.exe", L"CmdLineUtils.exe", FLAGS0 },
302     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"CmdLineUtils.exe", L"CmdLineUtils.exe", FLAGS1 },
303     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA, L"CmdLineUtils.exe", L"CmdLineUtils.exe", FLAGS2 },
304     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"CmdLineUtils.exe", L"CmdLineUtils.exe", FLAGS3 },
305     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"CmdLineUtils.exe", L"CmdLineUtils.exe", FLAGS4 },
306     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"CmdLineUtils.exe", L"CmdLineUtils.exe", FLAGS5 },
307     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"CmdLineUtils.exe", L"CmdLineUtils.exe", FLAGS6 },
308     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"CmdLineUtils.exe", L"CmdLineUtils.exe", FLAGS7 },
309     { __LINE__, 1, ERR_NO_CHANGE, EF_TESTDATA, L"CmdLineUtils.exe", L"CmdLineUtils.exe", FLAGS8 },
310     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA, L"CmdLineUtils.exe", L"CmdLineUtils.exe", FLAGS9 },
311     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"CmdLineUtils.exe", L"CmdLineUtils.exe", FLAGS10 },
312     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"CmdLineUtils.exe", L"CmdLineUtils.exe", FLAGS11 },
313     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"CmdLineUtils.exe", L"CmdLineUtils.exe", FLAGS12 },
314     { __LINE__, RAISED, ERR_DEAD, EF_TESTDATA, L"CmdLineUtils.exe", L"CmdLineUtils.exe", FLAGS13 },
315     /* testdata/CmdLineUtils.exe (name only) */
316     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS0 },
317     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS1 },
318     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS2 },
319     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS3 },
320     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS4 },
321     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS5 },
322     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS6 },
323     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS7 },
324     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS8 },
325     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS9 },
326     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS10 },
327     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS11 },
328     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS12 },
329     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS13 },
330     /* testdata/CmdLineUtils.exe with dirs (name only) */
331     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS0, s_Dirs },
332     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS1, s_Dirs },
333     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS2, s_Dirs },
334     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS3, s_Dirs },
335     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS4, s_Dirs },
336     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS5, s_Dirs },
337     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS6, s_Dirs },
338     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS7, s_Dirs },
339     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS8, s_Dirs },
340     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS9, s_Dirs },
341     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS10, s_Dirs },
342     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS11, s_Dirs },
343     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS12, s_Dirs },
344     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS13, s_Dirs },
345     /* testdata/CmdLineUtils.exe with dirs (name only) */
346     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS0, s_Dirs },
347     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS1, s_Dirs },
348     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS2, s_Dirs },
349     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS3, s_Dirs },
350     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS4, s_Dirs },
351     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS5, s_Dirs },
352     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS6, s_Dirs },
353     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS7, s_Dirs },
354     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS8, s_Dirs },
355     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS9, s_Dirs },
356     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS10, s_Dirs },
357     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS11, s_Dirs },
358     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS12, s_Dirs },
359     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY, L"CmdLineUtils.exe", NULL, FLAGS13, s_Dirs },
360     /* GhostProgram.exe -> testdata/CmdLineUtils.exe (name only, app path) */
361     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"GhostProgram.exe", L"CmdLineUtils.exe", FLAGS0 },
362     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"GhostProgram.exe", L"CmdLineUtils.exe", FLAGS1 },
363     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"GhostProgram.exe", L"CmdLineUtils.exe", FLAGS2 },
364     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"GhostProgram.exe", L"CmdLineUtils.exe", FLAGS3 },
365     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"GhostProgram.exe", L"CmdLineUtils.exe", FLAGS4 },
366     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"GhostProgram.exe", L"CmdLineUtils.exe", FLAGS5 },
367     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"GhostProgram.exe", L"CmdLineUtils.exe", FLAGS6 },
368     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"GhostProgram.exe", L"CmdLineUtils.exe", FLAGS7 },
369     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"GhostProgram.exe", L"CmdLineUtils.exe", FLAGS8 },
370     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"GhostProgram.exe", L"CmdLineUtils.exe", FLAGS9 },
371     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"GhostProgram.exe", L"CmdLineUtils.exe", FLAGS10 },
372     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"GhostProgram.exe", L"CmdLineUtils.exe", FLAGS11 },
373     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"GhostProgram.exe", L"CmdLineUtils.exe", FLAGS12 },
374     { __LINE__, 0, ERROR_FILE_NOT_FOUND, EF_TESTDATA | EF_NAME_ONLY | EF_APP_PATH, L"GhostProgram.exe", L"CmdLineUtils.exe", FLAGS13 },
375     /* CmdLineUtils.lnk */
376     { __LINE__, 1, ERR_NO_CHANGE, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS0 },
377     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS1 },
378     { __LINE__, 1, ERR_NO_CHANGE, EF_FULLPATH, s_ShortcutLongName, NULL, FLAGS2 },
379     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS3 },
380     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS4 },
381     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS5 },
382     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS6 },
383     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS7 },
384     { __LINE__, 1, ERR_NO_CHANGE, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS8 },
385     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS9 },
386     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS10 },
387     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS11 },
388     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS12 },
389     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS13 },
390     /* CmdLineUtils.lnk (with PRF_DONTFINDLNK) */
391     { __LINE__, 1, ERR_NO_CHANGE, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS0 | PRF_DONTFINDLNK },
392     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS1 | PRF_DONTFINDLNK },
393     { __LINE__, 1, ERR_NO_CHANGE, EF_FULLPATH, s_ShortcutLongName, NULL, FLAGS2 | PRF_DONTFINDLNK },
394     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS3 | PRF_DONTFINDLNK },
395     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS4 | PRF_DONTFINDLNK },
396     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS5 | PRF_DONTFINDLNK },
397     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS6 | PRF_DONTFINDLNK },
398     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS7 | PRF_DONTFINDLNK },
399     { __LINE__, 1, ERR_NO_CHANGE, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS8 | PRF_DONTFINDLNK },
400     { __LINE__, 1, ERROR_FILE_NOT_FOUND, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS9 | PRF_DONTFINDLNK },
401     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS10 | PRF_DONTFINDLNK },
402     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS11 | PRF_DONTFINDLNK },
403     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS12 | PRF_DONTFINDLNK },
404     { __LINE__, RAISED, ERR_DEAD, EF_FULLPATH, s_ShortcutLongName, s_ShortcutLongName, FLAGS13 | PRF_DONTFINDLNK },
405 };
406 
407 static BOOL
408 CreateShortcut(LPCWSTR pszLnkFileName,
409                LPCWSTR pszTargetPathName)
410 {
411     IPersistFile *ppf;
412     IShellLinkW* psl;
413     HRESULT hres;
414 
415     hres = CoInitialize(NULL);
416     if (SUCCEEDED(hres))
417     {
418         hres = CoCreateInstance(CLSID_ShellLink, NULL,
419             CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID*)&psl);
420         if (SUCCEEDED(hres))
421         {
422             psl->SetPath(pszTargetPathName);
423             hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
424             if (SUCCEEDED(hres))
425             {
426                 hres = ppf->Save(pszLnkFileName, TRUE);
427                 ppf->Release();
428             }
429             psl->Release();
430         }
431         CoUninitialize();
432     }
433     SetLastError(hres);
434 
435     return SUCCEEDED(hres);
436 }
437 
438 static BOOL
439 CreateRegAppPath(INT LineNumber, const WCHAR* Name, const WCHAR* Value)
440 {
441     HKEY RegistryKey;
442     LONG Result;
443     WCHAR Buffer[1024];
444     DWORD Disposition;
445 
446     wcscpy(Buffer, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\");
447     wcscat(Buffer, Name);
448     Result = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Buffer, 0, NULL,
449         0, KEY_WRITE, NULL, &RegistryKey, &Disposition);
450     if (Result != ERROR_SUCCESS)
451     {
452         trace("#%d: Could not create test key. Status: %lu\n", LineNumber, Result);
453         return FALSE;
454     }
455     Result = RegSetValueW(RegistryKey, NULL, REG_SZ, Value, 0);
456     if (Result != ERROR_SUCCESS)
457     {
458         trace("#%d: Could not set value of the test key. Status: %lu\n", LineNumber, Result);
459         RegCloseKey(RegistryKey);
460         return FALSE;
461     }
462     RegCloseKey(RegistryKey);
463     return TRUE;
464 }
465 
466 static BOOL
467 DeleteRegAppPath(INT LineNumber, const WCHAR* Name)
468 {
469     LONG Result;
470     WCHAR Buffer[1024];
471     wcscpy(Buffer, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\");
472     wcscat(Buffer, Name);
473     Result = RegDeleteKeyW(HKEY_LOCAL_MACHINE, Buffer);
474     if (Result != ERROR_SUCCESS)
475     {
476         trace("#%d: Could not remove the test key. Status: %lu\n", LineNumber, Result);
477         return FALSE;
478     }
479     return TRUE;
480 }
481 
482 static void DoEntry(INT SectionNumber, INT LineNumber, const TEST_ENTRY *pEntry)
483 {
484     WCHAR Path[MAX_PATH], PathExpected[MAX_PATH];
485     INT Ret;
486     DWORD Error;
487 
488     if (pEntry->NameBefore == NULL)
489     {
490         assert(pEntry->NameExpected == NULL);
491     }
492 
493     switch (pEntry->EF_ & EF_TYPE_MASK)
494     {
495     case EF_FULLPATH:
496         if (pEntry->NameBefore)
497         {
498             lstrcpyW(Path, pEntry->NameBefore);
499         }
500         if (pEntry->NameExpected)
501         {
502             lstrcpyW(PathExpected, pEntry->NameExpected);
503         }
504         break;
505 
506     case EF_TESTDATA:
507         if (pEntry->EF_ & EF_NAME_ONLY)
508         {
509             lstrcpyW(Path, pEntry->NameBefore);
510         }
511         else
512         {
513             lstrcpyW(Path, s_TestDir);
514             lstrcatW(Path, L"\\");
515             lstrcatW(Path, pEntry->NameBefore);
516         }
517 
518         if (pEntry->NameExpected)
519         {
520             lstrcpyW(PathExpected, s_TestDir);
521             lstrcatW(PathExpected, L"\\");
522             lstrcatW(PathExpected, pEntry->NameExpected);
523         }
524         break;
525     }
526 
527     if (pEntry->EF_ & EF_APP_PATH)
528     {
529         if (!CreateRegAppPath(LineNumber, pEntry->NameBefore, PathExpected))
530         {
531             skip("Section %d, Line %d: CreateRegAppPath failure\n", SectionNumber, LineNumber);
532             return;
533         }
534     }
535 
536     _SEH2_TRY
537     {
538         SetLastError(ERR_NO_CHANGE);
539         if (pEntry->NameBefore)
540         {
541             Ret = (*s_pPathResolve)(Path, pEntry->Dirs, pEntry->Flags);
542         }
543         else
544         {
545             Ret = (*s_pPathResolve)(NULL, pEntry->Dirs, pEntry->Flags);
546         }
547         Error = GetLastError();
548     }
549     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
550     {
551         Ret = RAISED;
552         Error = ERR_DEAD;
553     }
554     _SEH2_END;
555 
556     if (pEntry->EF_ & EF_APP_PATH)
557     {
558         ok(DeleteRegAppPath(LineNumber, pEntry->NameBefore),
559            "Section %d, Line %d: DeleteRegAppPath failed\n", SectionNumber, LineNumber);
560     }
561 
562     ok(Ret == pEntry->Ret, "Section %d, Line %d: Ret expected %d, was %d.\n",
563        SectionNumber, LineNumber, pEntry->Ret, Ret);
564     if (pEntry->Error != ERR_IGNORE)
565     {
566         ok(Error == pEntry->Error, "Section %d, Line %d: last error expected %ld, was %ld.\n",
567            SectionNumber, LineNumber, pEntry->Error, Error);
568     }
569 
570     if (pEntry->NameExpected && !(pEntry->EF_ & EF_APP_PATH))
571     {
572         ok(lstrcmpW(Path, PathExpected) == 0, "Section %d, Line%d: Path expected %s, was %s.\n",
573            SectionNumber, LineNumber, wine_dbgstr_w(PathExpected), wine_dbgstr_w(Path));
574     }
575 }
576 
577 static void TestMain_PathResolve(void)
578 {
579     UINT i, cEntries;
580     const TEST_ENTRY *pEntries;
581     WCHAR Saved[128], *pPathExtSaved;
582 
583     pEntries = s_LFNEntries;
584     cEntries = _countof(s_LFNEntries);
585 
586     /* save PATHEXT */
587     if (GetEnvironmentVariableW(L"PATHEXT", Saved, _countof(Saved)))
588         pPathExtSaved = Saved;
589     else
590         pPathExtSaved = NULL;
591 
592     /* Section 1 */
593     for (i = 0; i < cEntries; ++i)
594     {
595         DoEntry(1, pEntries[i].LineNumber, &pEntries[i]);
596     }
597 
598     /* Section 2: reset PATHEXT */
599     if (SetEnvironmentVariableW(L"PATHEXT", NULL))
600     {
601         for (i = 0; i < cEntries; ++i)
602             DoEntry(2, pEntries[i].LineNumber, &pEntries[i]);
603     }
604     else
605     {
606         skip("SetEnvironmentVariableW failed\n");
607     }
608 
609     /* Section 3: set PATHEXT to ".COM;.EXE;.BAT" */
610     if (SetEnvironmentVariableW(L"PATHEXT", L".COM;.EXE;.BAT"))
611     {
612         for (i = 0; i < cEntries; ++i)
613             DoEntry(3, pEntries[i].LineNumber, &pEntries[i]);
614     }
615     else
616     {
617         skip("SetEnvironmentVariableW failed\n");
618     }
619 
620     /* Section 4: set PATHEXT to ".TXT" */
621     if (SetEnvironmentVariableW(L"PATHEXT", L".TXT"))
622     {
623         for (i = 0; i < cEntries; ++i)
624             DoEntry(4, pEntries[i].LineNumber, &pEntries[i]);
625     }
626     else
627     {
628         skip("SetEnvironmentVariableW failed\n");
629     }
630 
631     /* restore PATHEXT */
632     SetEnvironmentVariableW(L"PATHEXT", pPathExtSaved);
633 }
634 
635 START_TEST(PathResolve)
636 {
637     LPWSTR pch;
638     WCHAR szRoot[MAX_PATH];
639 
640     /* Get this program's path */
641     GetModuleFileNameW(NULL, s_TestDir, _countof(s_TestDir));
642 
643     /* Add '\testdata' to the path */
644     pch = wcsrchr(s_TestDir, L'\\');
645     if (pch == NULL)
646     {
647         skip("GetModuleFileName and/or wcsrchr are insane.\n");
648         return;
649     }
650     lstrcpyW(pch, L"\\testdata");
651 
652     /* Create the testdata directory */
653     CreateDirectoryW(s_TestDir, NULL);
654     if (GetFileAttributesW(s_TestDir) == INVALID_FILE_ATTRIBUTES)
655     {
656         skip("testdata is not found.\n");
657         return;
658     }
659 
660     /* Build s_LinkTarget path */
661     lstrcpyW(s_LinkTarget, s_TestDir);
662     lstrcatW(s_LinkTarget, L"\\");
663     lstrcatW(s_LinkTarget, L"2PRONG.txt");
664 
665     /* Create the file */
666     fclose(_wfopen(s_LinkTarget, L"wb"));
667     ok(GetFileAttributesW(s_LinkTarget) != INVALID_FILE_ATTRIBUTES, "s_LinkTarget not found\n");
668 
669     /* Build s_ShortcutLongName path */
670     lstrcpyW(s_ShortcutLongName, s_TestDir);
671     lstrcatW(s_ShortcutLongName, L"\\");
672     lstrcatW(s_ShortcutLongName, L"CmdLineUtils.lnk"); /* in Long File Name */
673 
674     /* Create s_ShortcutLongName shortcut file */
675     ok(CreateShortcut(s_ShortcutLongName, s_LinkTarget),
676        "CreateShortcut(%s, %s) failed.\n",
677        wine_dbgstr_w(s_ShortcutLongName), wine_dbgstr_w(s_LinkTarget));
678 
679     /* Build s_ShortcutShortName path */
680     lstrcpyW(s_ShortcutShortName, s_TestDir);
681     lstrcatW(s_ShortcutShortName, L"\\");
682     GetShortPathNameW(s_ShortcutShortName, s_ShortcutShortName, _countof(s_ShortcutShortName));
683     lstrcatW(s_ShortcutShortName, L"CmdLineU.lnk"); /* in Short File Name */
684 
685     /* Create s_ShortcutShortName shortcut file */
686     ok(CreateShortcut(s_ShortcutShortName, s_LinkTarget),
687        "CreateShortcut(%s, %s) failed.\n",
688        wine_dbgstr_w(s_ShortcutShortName), wine_dbgstr_w(s_LinkTarget));
689 
690     /* Load shell32.dll */
691     s_hShell32 = LoadLibraryA("shell32");
692     if (s_hShell32 == NULL)
693     {
694         skip("Unable to load shell32.\n");
695         goto Cleanup;
696     }
697 
698     /* Get PathResolve procedure */
699     s_pPathResolve = (PATHRESOLVE)GetProcAddress(s_hShell32, "PathResolve");
700     if (s_pPathResolve == NULL)
701     {
702         skip("Unable to get PathResolve address.\n");
703         goto Cleanup;
704     }
705 
706     /* Get IsLFNDriveW procedure */
707     s_pIsLFNDriveW = (ISLFNDRIVEW)GetProcAddress(s_hShell32, (LPCSTR)(INT_PTR)42);
708     if (s_pIsLFNDriveW == NULL)
709     {
710         skip("Unable to get IsLFNDriveW address.\n");
711         goto Cleanup;
712     }
713 
714     /* Is LFN supported? */
715     lstrcpyW(szRoot, s_TestDir);
716     PathStripToRootW(szRoot);
717     if (!s_pIsLFNDriveW(szRoot))
718     {
719         skip("LFN is not supported in this drive %s.\n", wine_dbgstr_w(szRoot));
720         goto Cleanup;
721     }
722 
723     /* Do tests */
724     TestMain_PathResolve();
725 
726     /* Clean up */
727 Cleanup:
728     DeleteFileW(s_LinkTarget);
729     DeleteFileW(s_ShortcutLongName);
730     DeleteFileW(s_ShortcutShortName);
731     RemoveDirectoryW(s_TestDir);
732     FreeLibrary(s_hShell32);
733 }
734