Sync trunk r40500
[reactos.git] / rostests / winetests / kernel32 / path.c
1 /*
2 * Unit test suite for various Path and Directory Functions
3 *
4 * Copyright 2002 Geoffrey Hausheer
5 * Copyright 2006 Detlef Riekenberg
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include "wine/test.h"
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "winerror.h"
29 #include "winnls.h"
30
31 #define HAS_TRAIL_SLASH_A(string) (string[lstrlenA(string)-1]=='\\')
32
33 #define LONGFILE "Long File test.path"
34 #define SHORTFILE "pathtest.pth"
35 #define SHORTDIR "shortdir"
36 #define LONGDIR "Long Directory"
37 #define NONFILE_SHORT "noexist.pth"
38 #define NONFILE_LONG "NonExistent File"
39 #define NONDIR_SHORT "notadir"
40 #define NONDIR_LONG "NonExistent Directory"
41
42 #define NOT_A_VALID_DRIVE '@'
43
44 /* the following characters don't work well with GetFullPathNameA
45 in Win98. I don't know if this is a FAT thing, or if it is an OS thing
46 but I don't test these characters now.
47 NOTE: Win2k allows GetFullPathNameA to work with them though
48 |<>"
49 */
50 static const CHAR funny_chars[]="!@#$%^&*()=+{}[],?'`";
51 static const CHAR is_char_ok[] ="11111110111111111011";
52
53 static DWORD (WINAPI *pGetLongPathNameA)(LPCSTR,LPSTR,DWORD);
54 static DWORD (WINAPI *pGetLongPathNameW)(LPWSTR,LPWSTR,DWORD);
55
56 /* Present in Win2003+ */
57 static BOOL (WINAPI *pNeedCurrentDirectoryForExePathA)(LPCSTR);
58 static BOOL (WINAPI *pNeedCurrentDirectoryForExePathW)(LPCWSTR);
59
60 /* a structure to deal with wine todos somewhat cleanly */
61 typedef struct {
62 DWORD shortlen;
63 DWORD shorterror;
64 DWORD s2llen;
65 DWORD s2lerror;
66 DWORD longlen;
67 DWORD longerror;
68 } SLpassfail;
69
70 /* function that tests GetFullPathNameA, GetShortPathNameA,GetLongPathNameA */
71 /* NOTE: the passfail structure is used to allow customizable todo checking
72 for wine. It is not very pretty, but it sure beats duplicating this
73 function lots of times
74 */
75 static void test_ValidPathA(const CHAR *curdir, const CHAR *subdir, const CHAR *filename,
76 CHAR *shortstr, SLpassfail *passfail, const CHAR *errstr)
77 {
78 CHAR tmpstr[MAX_PATH],
79 fullpath[MAX_PATH], /*full path to the file (not short/long) */
80 subpath[MAX_PATH], /*relative path to the file */
81 fullpathshort[MAX_PATH], /*absolute path to the file (short format) */
82 fullpathlong[MAX_PATH], /*absolute path to the file (long format) */
83 curdirshort[MAX_PATH], /*absolute path to the current dir (short) */
84 curdirlong[MAX_PATH]; /*absolute path to the current dir (long) */
85 LPSTR strptr; /*ptr to the filename portion of the path */
86 DWORD len;
87 /* if passfail is NULL, we can perform all checks within this function,
88 otherwise, we will return the relevant data in the passfail struct, so
89 we must initialize it first
90 */
91 if(passfail!=NULL) {
92 passfail->shortlen=-1;passfail->s2llen=-1;passfail->longlen=-1;
93 passfail->shorterror=0;passfail->s2lerror=0;passfail->longerror=0;
94 }
95 /* GetLongPathNameA is only supported on Win2k+ and Win98+ */
96 if(pGetLongPathNameA) {
97 ok((len=pGetLongPathNameA(curdir,curdirlong,MAX_PATH)),
98 "%s: GetLongPathNameA failed\n",errstr);
99 /*GetLongPathNameA can return a trailing '\\' but shouldn't do so here */
100 ok(! HAS_TRAIL_SLASH_A(curdirlong),
101 "%s: GetLongPathNameA should not have a trailing \\\n",errstr);
102 }
103 ok((len=GetShortPathNameA(curdir,curdirshort,MAX_PATH)),
104 "%s: GetShortPathNameA failed\n",errstr);
105 /*GetShortPathNameA can return a trailing '\\' but shouldn't do so here */
106 ok(! HAS_TRAIL_SLASH_A(curdirshort),
107 "%s: GetShortPathNameA should not have a trailing \\\n",errstr);
108 /* build relative and absolute paths from inputs */
109 if(lstrlenA(subdir)) {
110 sprintf(subpath,"%s\\%s",subdir,filename);
111 } else {
112 lstrcpyA(subpath,filename);
113 }
114 sprintf(fullpath,"%s\\%s",curdir,subpath);
115 sprintf(fullpathshort,"%s\\%s",curdirshort,subpath);
116 sprintf(fullpathlong,"%s\\%s",curdirlong,subpath);
117 /* Test GetFullPathNameA functionality */
118 len=GetFullPathNameA(subpath,MAX_PATH,tmpstr,&strptr);
119 ok(len, "GetFullPathNameA failed for: '%s'\n",subpath);
120 if(HAS_TRAIL_SLASH_A(subpath)) {
121 ok(strptr==NULL,
122 "%s: GetFullPathNameA should not return a filename ptr\n",errstr);
123 ok(lstrcmpiA(fullpath,tmpstr)==0,
124 "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
125 errstr,tmpstr,fullpath);
126 } else {
127 ok(lstrcmpiA(strptr,filename)==0,
128 "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
129 errstr,strptr,filename);
130 ok(lstrcmpiA(fullpath,tmpstr)==0,
131 "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
132 errstr,tmpstr,fullpath);
133 }
134 /* Test GetShortPathNameA functionality */
135 SetLastError(0);
136 len=GetShortPathNameA(fullpathshort,shortstr,MAX_PATH);
137 if(passfail==NULL) {
138 ok(len, "%s: GetShortPathNameA failed\n",errstr);
139 } else {
140 passfail->shortlen=len;
141 passfail->shorterror=GetLastError();
142 }
143 /* Test GetLongPathNameA functionality
144 We test both conversion from GetFullPathNameA and from GetShortPathNameA
145 */
146 if(pGetLongPathNameA) {
147 if(len!=0) {
148 SetLastError(0);
149 len=pGetLongPathNameA(shortstr,tmpstr,MAX_PATH);
150 if(passfail==NULL) {
151 ok(len,
152 "%s: GetLongPathNameA failed during Short->Long conversion\n", errstr);
153 ok(lstrcmpiA(fullpathlong,tmpstr)==0,
154 "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
155 errstr,tmpstr,fullpathlong);
156 } else {
157 passfail->s2llen=len;
158 passfail->s2lerror=GetLastError();
159 }
160 }
161 SetLastError(0);
162 len=pGetLongPathNameA(fullpath,tmpstr,MAX_PATH);
163 if(passfail==NULL) {
164 ok(len, "%s: GetLongPathNameA failed\n",errstr);
165 if(HAS_TRAIL_SLASH_A(fullpath)) {
166 ok(lstrcmpiA(fullpathlong,tmpstr)==0,
167 "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
168 errstr,tmpstr,fullpathlong);
169 } else {
170 ok(lstrcmpiA(fullpathlong,tmpstr)==0,
171 "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
172 errstr,tmpstr,fullpathlong);
173 }
174 } else {
175 passfail->longlen=len;
176 passfail->longerror=GetLastError();
177 }
178 }
179 }
180
181 /* split path into leading directory, and 8.3 filename */
182 static void test_SplitShortPathA(CHAR *path,CHAR *dir,CHAR *eight,CHAR *three) {
183 int done,error;
184 int ext,fil;
185 int len,i;
186 len=lstrlenA(path);
187 ext=len; fil=len; done=0; error=0;
188 /* walk backwards over path looking for '.' or '\\' separators */
189 for(i=len-1;(i>=0) && (!done);i--) {
190 if(path[i]=='.')
191 if(ext!=len) error=1; else ext=i;
192 else if(path[i]=='\\') {
193 if(i==len-1) {
194 error=1;
195 } else {
196 fil=i;
197 done=1;
198 }
199 }
200 }
201 /* Check that we didn't find a trailing '\\' or multiple '.' */
202 ok(!error,"Illegal file found in 8.3 path '%s'\n",path);
203 /* Separate dir, root, and extension */
204 if(ext!=len) lstrcpyA(three,path+ext+1); else lstrcpyA(three,"");
205 if(fil!=len) {
206 lstrcpynA(eight,path+fil+1,ext-fil);
207 lstrcpynA(dir,path,fil+1);
208 } else {
209 lstrcpynA(eight,path,ext+1);
210 lstrcpyA(dir,"");
211 }
212 /* Validate that root and extension really are 8.3 */
213 ok(lstrlenA(eight)<=8 && lstrlenA(three)<=3,
214 "GetShortPathNAmeA did not return an 8.3 path\n");
215 }
216
217 /* Check that GetShortPathNameA returns a valid 8.3 path */
218 static void test_LongtoShortA(CHAR *teststr,const CHAR *goodstr,
219 const CHAR *ext,const CHAR *errstr) {
220 CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
221
222 test_SplitShortPathA(teststr,dir,eight,three);
223 ok(lstrcmpiA(dir,goodstr)==0,
224 "GetShortPathNameA returned '%s' instead of '%s'\n",dir,goodstr);
225 ok(lstrcmpiA(three,ext)==0,
226 "GetShortPathNameA returned '%s' with incorrect extension\n",three);
227 }
228
229 /* Test that Get(Short|Long|Full)PathNameA work correctly with interesting
230 characters in the filename.
231 'valid' indicates whether this would be an allowed filename
232 'todo' indicates that wine doesn't get this right yet.
233 NOTE: We always call this routine with a nonexistent filename, so
234 Get(Short|Long)PathNameA should never pass, but GetFullPathNameA
235 should.
236 */
237 static void test_FunnyChars(CHAR *curdir,CHAR *curdir_short,CHAR *filename, INT valid,CHAR *errstr)
238 {
239 CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
240 SLpassfail passfail;
241
242 test_ValidPathA(curdir,"",filename,tmpstr,&passfail,errstr);
243 if(valid) {
244 sprintf(tmpstr1,"%s\\%s",curdir_short,filename);
245 ok((passfail.shortlen==0 &&
246 (passfail.shorterror==ERROR_FILE_NOT_FOUND || passfail.shorterror==ERROR_PATH_NOT_FOUND || !passfail.shorterror)) ||
247 (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
248 "%s: GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
249 errstr,passfail.shortlen,passfail.shorterror,tmpstr);
250 } else {
251 ok(passfail.shortlen==0 &&
252 (passfail.shorterror==ERROR_INVALID_NAME || passfail.shorterror==ERROR_FILE_NOT_FOUND || !passfail.shorterror),
253 "%s: GetShortPathA should have failed len=%d, error=%d\n",
254 errstr,passfail.shortlen,passfail.shorterror);
255 }
256 if(pGetLongPathNameA) {
257 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
258 if(valid) {
259 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
260 "%s: GetLongPathA returned %d and not %d\n",
261 errstr,passfail.longerror,ERROR_FILE_NOT_FOUND);
262 } else {
263 ok(passfail.longerror==ERROR_INVALID_NAME ||
264 passfail.longerror==ERROR_FILE_NOT_FOUND,
265 "%s: GetLongPathA returned %d and not %d or %d'\n",
266 errstr, passfail.longerror,ERROR_INVALID_NAME,ERROR_FILE_NOT_FOUND);
267 }
268 }
269 }
270
271 /* Routine to test that SetCurrentDirectory behaves as expected. */
272 static void test_setdir(CHAR *olddir,CHAR *newdir,
273 CHAR *cmprstr, INT pass, const CHAR *errstr)
274 {
275 CHAR tmppath[MAX_PATH], *dirptr;
276 DWORD val,len,chklen;
277
278 val=SetCurrentDirectoryA(newdir);
279 len=GetCurrentDirectoryA(MAX_PATH,tmppath);
280 /* if 'pass' then the SetDirectoryA was supposed to pass */
281 if(pass) {
282 dirptr=(cmprstr==NULL) ? newdir : cmprstr;
283 chklen=lstrlenA(dirptr);
284 ok(val,"%s: SetCurrentDirectoryA failed\n",errstr);
285 ok(len==chklen,
286 "%s: SetCurrentDirectory did not change the directory, though it passed\n",
287 errstr);
288 ok(lstrcmpiA(dirptr,tmppath)==0,
289 "%s: SetCurrentDirectory did not change the directory, though it passed\n",
290 errstr);
291 ok(SetCurrentDirectoryA(olddir),
292 "%s: Couldn't set directory to it's original value\n",errstr);
293 } else {
294 /* else thest that it fails correctly */
295 chklen=lstrlenA(olddir);
296 ok(val==0,
297 "%s: SetCurrentDirectoryA passed when it should have failed\n",errstr);
298 ok(len==chklen,
299 "%s: SetCurrentDirectory changed the directory, though it failed\n",
300 errstr);
301 ok(lstrcmpiA(olddir,tmppath)==0,
302 "%s: SetCurrentDirectory changed the directory, though it failed\n",
303 errstr);
304 }
305 }
306 static void test_InitPathA(CHAR *newdir, CHAR *curDrive, CHAR *otherDrive)
307 {
308 CHAR tmppath[MAX_PATH], /*path to TEMP */
309 tmpstr[MAX_PATH],
310 tmpstr1[MAX_PATH];
311 DWORD len,len1,drives;
312 INT id;
313 HANDLE hndl;
314 BOOL bRes;
315
316 *curDrive = *otherDrive = NOT_A_VALID_DRIVE;
317
318 /* Get the current drive letter */
319 if( GetCurrentDirectoryA( MAX_PATH, tmpstr))
320 *curDrive = tmpstr[0];
321 else
322 trace( "Unable to discover current drive, some tests will not be conducted.\n");
323
324 /* Test GetTempPathA */
325 len=GetTempPathA(MAX_PATH,tmppath);
326 ok(len!=0 && len < MAX_PATH,"GetTempPathA failed\n");
327 ok(HAS_TRAIL_SLASH_A(tmppath),
328 "GetTempPathA returned a path that did not end in '\\'\n");
329 lstrcpyA(tmpstr,"aaaaaaaa");
330 len1=GetTempPathA(len,tmpstr);
331 ok(len1==len+1,
332 "GetTempPathA should return string length %d instead of %d\n",len+1,len1);
333
334 /* Test GetTmpFileNameA
335 The only test we do here is whether GetTempFileNameA passes or not.
336 We do not thoroughly test this function yet (specifically, whether
337 it behaves correctly when 'unique' is non zero)
338 */
339 ok((id=GetTempFileNameA(tmppath,"path",0,newdir)),"GetTempFileNameA failed\n");
340 sprintf(tmpstr,"pat%.4x.tmp",id & 0xffff);
341 sprintf(tmpstr1,"pat%x.tmp",id & 0xffff);
342 ok(lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr)==0 ||
343 lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr1)==0,
344 "GetTempFileNameA returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
345 newdir,tmpstr,tmpstr1,id);
346 ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
347
348 id=GetTempFileNameA(tmppath,NULL,0,newdir);
349 /* Windows 95, 98 return 0==id, while Windows 2000, XP return 0!=id */
350 if (id)
351 {
352 sprintf(tmpstr,"%.4x.tmp",id & 0xffff);
353 sprintf(tmpstr1,"%x.tmp",id & 0xffff);
354 ok(lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr)==0 ||
355 lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr1)==0,
356 "GetTempFileNameA returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
357 newdir,tmpstr,tmpstr1,id);
358 ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
359 }
360
361 /* Find first valid drive letter that is neither newdir[0] nor curDrive */
362 drives = GetLogicalDrives() & ~(1<<(newdir[0]-'A'));
363 if( *curDrive != NOT_A_VALID_DRIVE)
364 drives &= ~(1<<(*curDrive-'A'));
365 if( drives)
366 for( *otherDrive='A'; (drives & 1) == 0; drives>>=1, (*otherDrive)++);
367 else
368 trace( "Could not find alternative drive, some tests will not be conducted.\n");
369
370 /* Do some CreateDirectoryA tests */
371 /* It would be nice to do test the SECURITY_ATTRIBUTES, but I don't
372 really understand how they work.
373 More formal tests should be done along with CreateFile tests
374 */
375 ok((id=GetTempFileNameA(tmppath,"path",0,newdir)),"GetTempFileNameA failed\n");
376 ok(CreateDirectoryA(newdir,NULL)==0,
377 "CreateDirectoryA succeeded even though a file of the same name exists\n");
378 ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
379 ok(CreateDirectoryA(newdir,NULL),"CreateDirectoryA failed\n");
380 /* Create some files to test other functions. Note, we will test CreateFileA
381 at some later point
382 */
383 sprintf(tmpstr,"%s\\%s",newdir,SHORTDIR);
384 ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed\n");
385 sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
386 ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed\n");
387 bRes = CreateDirectoryA("c:",NULL);
388 ok(!bRes && (GetLastError() == ERROR_ACCESS_DENIED ||
389 GetLastError() == ERROR_ALREADY_EXISTS),
390 "CreateDirectoryA(\"c:\" should have failed (%d)\n", GetLastError());
391 bRes = CreateDirectoryA("c:\\",NULL);
392 ok(!bRes && (GetLastError() == ERROR_ACCESS_DENIED ||
393 GetLastError() == ERROR_ALREADY_EXISTS),
394 "CreateDirectoryA(\"c:\\\" should have failed (%d)\n", GetLastError());
395 sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,SHORTFILE);
396 hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
397 CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
398 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
399 ok(CloseHandle(hndl),"CloseHandle failed\n");
400 sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,LONGFILE);
401 hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
402 CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
403 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
404 ok(CloseHandle(hndl),"CloseHandle failed\n");
405 sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,SHORTFILE);
406 hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
407 CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
408 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
409 ok(CloseHandle(hndl),"CloseHandle failed\n");
410 sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,LONGFILE);
411 hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
412 CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
413 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
414 ok(CloseHandle(hndl),"CloseHandle failed\n");
415 }
416
417 /* Test GetCurrentDirectory & SetCurrentDirectory */
418 static void test_CurrentDirectoryA(CHAR *origdir, CHAR *newdir)
419 {
420 CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
421 DWORD len,len1;
422 /* Save the original directory, so that we can return to it at the end
423 of the test
424 */
425 len=GetCurrentDirectoryA(MAX_PATH,origdir);
426 ok(len!=0 && len < MAX_PATH,"GetCurrentDirectoryA failed\n");
427 /* Make sure that CetCurrentDirectoryA doesn't overwrite the buffer when the
428 buffer size is too small to hold the current directory
429 */
430 lstrcpyA(tmpstr,"aaaaaaa");
431 len1=GetCurrentDirectoryA(len,tmpstr);
432 ok(len1==len+1, "GetCurrentDirectoryA returned %d instead of %d\n",len1,len+1);
433 ok(lstrcmpiA(tmpstr,"aaaaaaa")==0,
434 "GetCurrentDirectoryA should not have modified the buffer\n");
435 /* SetCurrentDirectoryA shouldn't care whether the string has a
436 trailing '\\' or not
437 */
438 sprintf(tmpstr,"%s\\",newdir);
439 test_setdir(origdir,tmpstr,newdir,1,"check 1");
440 test_setdir(origdir,newdir,NULL,1,"check 2");
441 /* Set the directory to the working area. We just tested that this works,
442 so why check it again.
443 */
444 SetCurrentDirectoryA(newdir);
445 /* Check that SetCurrentDirectory fails when a nonexistent dir is specified */
446 sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_SHORT);
447 test_setdir(newdir,tmpstr,NULL,0,"check 3");
448 /* Check that SetCurrentDirectory fails for a nonexistent lond directory */
449 sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_LONG);
450 test_setdir(newdir,tmpstr,NULL,0,"check 4");
451 /* Check that SetCurrentDirectory passes with a long directory */
452 sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
453 test_setdir(newdir,tmpstr,NULL,1,"check 5");
454 /* Check that SetCurrentDirectory passes with a short relative directory */
455 sprintf(tmpstr,"%s",SHORTDIR);
456 sprintf(tmpstr1,"%s\\%s",newdir,SHORTDIR);
457 test_setdir(newdir,tmpstr,tmpstr1,1,"check 6");
458 /* starting with a '.' */
459 sprintf(tmpstr,".\\%s",SHORTDIR);
460 test_setdir(newdir,tmpstr,tmpstr1,1,"check 7");
461 /* Check that SetCurrentDirectory passes with a short relative directory */
462 sprintf(tmpstr,"%s",LONGDIR);
463 sprintf(tmpstr1,"%s\\%s",newdir,LONGDIR);
464 test_setdir(newdir,tmpstr,tmpstr1,1,"check 8");
465 /* starting with a '.' */
466 sprintf(tmpstr,".\\%s",LONGDIR);
467 test_setdir(newdir,tmpstr,tmpstr1,1,"check 9");
468 }
469
470 /* Cleanup the mess we made while executing these tests */
471 static void test_CleanupPathA(CHAR *origdir, CHAR *curdir)
472 {
473 CHAR tmpstr[MAX_PATH];
474 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
475 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
476 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,LONGFILE);
477 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
478 sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,SHORTFILE);
479 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
480 sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
481 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
482 sprintf(tmpstr,"%s\\%s",curdir,SHORTDIR);
483 ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
484 sprintf(tmpstr,"%s\\%s",curdir,LONGDIR);
485 ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
486 ok(SetCurrentDirectoryA(origdir),"SetCurrentDirectoryA failed\n");
487 ok(RemoveDirectoryA(curdir),"RemoveDirectoryA failed\n");
488 }
489
490 /* This routine will test Get(Full|Short|Long)PathNameA */
491 static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive)
492 {
493 CHAR curdir_short[MAX_PATH],
494 longdir_short[MAX_PATH];
495 CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH],tmpstr2[MAX_PATH];
496 LPSTR strptr; /*ptr to the filename portion of the path */
497 DWORD len;
498 INT i;
499 CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
500 SLpassfail passfail;
501
502 /* Get the short form of the current directory */
503 ok((len=GetShortPathNameA(curdir,curdir_short,MAX_PATH)),
504 "GetShortPathNameA failed\n");
505 ok(!HAS_TRAIL_SLASH_A(curdir_short),
506 "GetShortPathNameA should not have a trailing \\\n");
507 /* Get the short form of the absolute-path to LONGDIR */
508 sprintf(tmpstr,"%s\\%s",curdir_short,LONGDIR);
509 ok((len=GetShortPathNameA(tmpstr,longdir_short,MAX_PATH)),
510 "GetShortPathNameA failed\n");
511 ok(lstrcmpiA(longdir_short+(len-1),"\\")!=0,
512 "GetShortPathNameA should not have a trailing \\\n");
513
514 if (pGetLongPathNameA) {
515 DWORD rc1,rc2;
516 sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
517 rc1=(*pGetLongPathNameA)(tmpstr,NULL,0);
518 rc2=(*pGetLongPathNameA)(curdir,NULL,0);
519 ok((rc1-strlen(tmpstr))==(rc2-strlen(curdir)),
520 "GetLongPathNameA: wrong return code, %d instead of %d\n",
521 rc1, lstrlenA(tmpstr)+1);
522
523 sprintf(dir,"%c:",curDrive);
524 rc1=(*pGetLongPathNameA)(dir,tmpstr,sizeof(tmpstr));
525 ok(strcmp(dir,tmpstr)==0,
526 "GetLongPathNameA: returned '%s' instead of '%s' (rc=%d)\n",
527 tmpstr,dir,rc1);
528 }
529
530 /* Check the cases where both file and directory exist first */
531 /* Start with a 8.3 directory, 8.3 filename */
532 test_ValidPathA(curdir,SHORTDIR,SHORTFILE,tmpstr,NULL,"test1");
533 sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,SHORTFILE);
534 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
535 "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
536 /* Now try a 8.3 directory, long file name */
537 test_ValidPathA(curdir,SHORTDIR,LONGFILE,tmpstr,NULL,"test2");
538 sprintf(tmpstr1,"%s\\%s",curdir_short,SHORTDIR);
539 test_LongtoShortA(tmpstr,tmpstr1,"PAT","test2");
540 /* Next is a long directory, 8.3 file */
541 test_ValidPathA(curdir,LONGDIR,SHORTFILE,tmpstr,NULL,"test3");
542 sprintf(tmpstr1,"%s\\%s",longdir_short,SHORTFILE);
543 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
544 "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
545 /*Lastly a long directory, long file */
546 test_ValidPathA(curdir,LONGDIR,LONGFILE,tmpstr,NULL,"test4");
547 test_LongtoShortA(tmpstr,longdir_short,"PAT","test4");
548
549 /* Now check all of the invalid file w/ valid directory combinations */
550 /* Start with a 8.3 directory, 8.3 filename */
551 test_ValidPathA(curdir,SHORTDIR,NONFILE_SHORT,tmpstr,&passfail,"test5");
552 sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,NONFILE_SHORT);
553 ok((passfail.shortlen==0 &&
554 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
555 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
556 (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
557 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
558 passfail.shortlen,passfail.shorterror,tmpstr);
559 if(pGetLongPathNameA) {
560 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
561 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
562 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
563 }
564 /* Now try a 8.3 directory, long file name */
565 test_ValidPathA(curdir,SHORTDIR,NONFILE_LONG,tmpstr,&passfail,"test6");
566 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
567 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
568 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
569 !passfail.shorterror,
570 "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
571 if(pGetLongPathNameA) {
572 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
573 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
574 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
575 }
576 /* Next is a long directory, 8.3 file */
577 test_ValidPathA(curdir,LONGDIR,NONFILE_SHORT,tmpstr,&passfail,"test7");
578 sprintf(tmpstr2,"%s\\%s",curdir_short,LONGDIR);
579 GetShortPathNameA(tmpstr2,tmpstr1,MAX_PATH);
580 strcat(tmpstr1,"\\" NONFILE_SHORT);
581 ok((passfail.shortlen==0 &&
582 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
583 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
584 (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
585 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
586 passfail.shortlen,passfail.shorterror,tmpstr);
587 if(pGetLongPathNameA) {
588 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
589 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
590 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
591 }
592 /*Lastly a long directory, long file */
593 test_ValidPathA(curdir,LONGDIR,NONFILE_LONG,tmpstr,&passfail,"test8");
594 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
595 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
596 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
597 !passfail.shorterror,
598 "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
599 if(pGetLongPathNameA) {
600 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
601 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
602 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
603 }
604 /* Now try again with directories that don't exist */
605 /* 8.3 directory, 8.3 filename */
606 test_ValidPathA(curdir,NONDIR_SHORT,SHORTFILE,tmpstr,&passfail,"test9");
607 sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,NONDIR_SHORT,SHORTFILE);
608 ok((passfail.shortlen==0 &&
609 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
610 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
611 (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
612 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
613 passfail.shortlen,passfail.shorterror,tmpstr);
614 if(pGetLongPathNameA) {
615 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
616 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
617 passfail.longerror==ERROR_FILE_NOT_FOUND,
618 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
619 passfail.longerror);
620 }
621 /* Now try a 8.3 directory, long file name */
622 test_ValidPathA(curdir,NONDIR_SHORT,LONGFILE,tmpstr,&passfail,"test10");
623 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
624 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
625 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
626 !passfail.shorterror,
627 "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
628 passfail.shorterror);
629 if(pGetLongPathNameA) {
630 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
631 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
632 passfail.longerror==ERROR_FILE_NOT_FOUND,
633 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
634 passfail.longerror);
635 }
636 /* Next is a long directory, 8.3 file */
637 test_ValidPathA(curdir,NONDIR_LONG,SHORTFILE,tmpstr,&passfail,"test11");
638 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
639 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
640 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
641 !passfail.shorterror,
642 "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
643 passfail.shorterror);
644 if(pGetLongPathNameA) {
645 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
646 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
647 passfail.longerror==ERROR_FILE_NOT_FOUND,
648 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
649 passfail.longerror);
650 }
651 /*Lastly a long directory, long file */
652 test_ValidPathA(curdir,NONDIR_LONG,LONGFILE,tmpstr,&passfail,"test12");
653 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
654 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
655 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
656 !passfail.shorterror,
657 "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
658 passfail.shorterror);
659 if(pGetLongPathNameA) {
660 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
661 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
662 passfail.longerror==ERROR_FILE_NOT_FOUND,
663 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
664 passfail.longerror);
665 }
666 /* Next try directories ending with '\\' */
667 /* Existing Directories */
668 sprintf(tmpstr,"%s\\",SHORTDIR);
669 test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test13");
670 sprintf(tmpstr,"%s\\",LONGDIR);
671 test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test14");
672 /* Nonexistent directories */
673 sprintf(tmpstr,"%s\\",NONDIR_SHORT);
674 test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test15");
675 sprintf(tmpstr2,"%s\\%s",curdir_short,tmpstr);
676 ok((passfail.shortlen==0 &&
677 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
678 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
679 (passfail.shortlen==strlen(tmpstr2) && lstrcmpiA(tmpstr1,tmpstr2)==0),
680 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
681 passfail.shortlen,passfail.shorterror,tmpstr);
682 if(pGetLongPathNameA) {
683 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
684 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
685 "GetLongPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
686 passfail.longerror);
687 }
688 sprintf(tmpstr,"%s\\",NONDIR_LONG);
689 test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test16");
690 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
691 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
692 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
693 !passfail.shorterror,
694 "GetShortPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
695 passfail.shorterror);
696 if(pGetLongPathNameA) {
697 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
698 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
699 "GetLongPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
700 passfail.longerror);
701 }
702 /* Test GetFullPathNameA with drive letters */
703 if( curDrive != NOT_A_VALID_DRIVE) {
704 sprintf(tmpstr,"%c:",curdir[0]);
705 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr2,&strptr),
706 "GetFullPathNameA(%c:) failed\n", curdir[0]);
707 GetCurrentDirectoryA(MAX_PATH,tmpstr);
708 sprintf(tmpstr1,"%s\\",tmpstr);
709 ok(lstrcmpiA(tmpstr,tmpstr2)==0 || lstrcmpiA(tmpstr1,tmpstr2)==0,
710 "GetFullPathNameA(%c:) returned '%s' instead of '%s' or '%s'\n",
711 curdir[0],tmpstr2,tmpstr,tmpstr1);
712
713 sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
714 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
715 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
716 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
717 ok(lstrcmpiA(SHORTFILE,strptr)==0,
718 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
719 }
720 /* Without a leading slash, insert the current directory if on the current drive */
721 sprintf(tmpstr,"%c:%s\\%s",curdir[0],SHORTDIR,SHORTFILE);
722 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
723 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
724 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
725 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
726 ok(lstrcmpiA(SHORTFILE,strptr)==0,
727 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
728 /* Otherwise insert the missing leading slash */
729 if( otherDrive != NOT_A_VALID_DRIVE) {
730 /* FIXME: this test assumes that current directory on other drive is root */
731 sprintf(tmpstr,"%c:%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
732 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed for %s\n", tmpstr);
733 sprintf(tmpstr,"%c:\\%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
734 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
735 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
736 ok(lstrcmpiA(SHORTFILE,strptr)==0,
737 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
738 }
739 /* Xilinx tools like to mix Unix and DOS formats, which Windows handles fine.
740 So test for them. */
741 if( curDrive != NOT_A_VALID_DRIVE) {
742 sprintf(tmpstr,"%c:/%s\\%s",curDrive,SHORTDIR,SHORTFILE);
743 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
744 sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
745 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
746 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
747 ok(lstrcmpiA(SHORTFILE,strptr)==0,
748 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
749 }
750 /**/
751 sprintf(tmpstr,"%c:%s/%s",curdir[0],SHORTDIR,SHORTFILE);
752 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
753 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
754 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
755 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
756 ok(lstrcmpiA(SHORTFILE,strptr)==0,
757 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
758 /* Windows will insert a drive letter in front of an absolute UNIX path */
759 sprintf(tmpstr,"/%s/%s",SHORTDIR,SHORTFILE);
760 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
761 sprintf(tmpstr,"%c:\\%s\\%s",*tmpstr1,SHORTDIR,SHORTFILE);
762 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
763 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
764 /* This passes in Wine because it still contains the pointer from the previous test */
765 ok(lstrcmpiA(SHORTFILE,strptr)==0,
766 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
767
768 /* Now try some relative paths */
769 ok(GetShortPathNameA(LONGDIR,tmpstr,MAX_PATH),"GetShortPathNameA failed\n");
770 test_SplitShortPathA(tmpstr,dir,eight,three);
771 if(pGetLongPathNameA) {
772 ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
773 ok(lstrcmpiA(tmpstr1,LONGDIR)==0,
774 "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,LONGDIR);
775 }
776 sprintf(tmpstr,".\\%s",LONGDIR);
777 ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed\n");
778 test_SplitShortPathA(tmpstr1,dir,eight,three);
779 ok(lstrcmpiA(dir,".")==0 || dir[0]=='\0',
780 "GetShortPathNameA did not keep relative directory [%s]\n",tmpstr1);
781 if(pGetLongPathNameA) {
782 ok(pGetLongPathNameA(tmpstr1,tmpstr1,MAX_PATH),"GetLongPathNameA failed %s\n",
783 tmpstr);
784 ok(lstrcmpiA(tmpstr1,tmpstr)==0,
785 "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
786 }
787 /* Check out Get*PathNameA on some funny characters */
788 for(i=0;i<lstrlenA(funny_chars);i++) {
789 INT valid;
790 valid=(is_char_ok[i]=='0') ? 0 : 1;
791 sprintf(tmpstr1,"check%d-1",i);
792 sprintf(tmpstr,"file%c000.ext",funny_chars[i]);
793 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
794 sprintf(tmpstr1,"check%d-2",i);
795 sprintf(tmpstr,"file000.e%ct",funny_chars[i]);
796 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
797 sprintf(tmpstr1,"check%d-3",i);
798 sprintf(tmpstr,"%cfile000.ext",funny_chars[i]);
799 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
800 sprintf(tmpstr1,"check%d-4",i);
801 sprintf(tmpstr,"file000%c.ext",funny_chars[i]);
802 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
803 sprintf(tmpstr1,"check%d-5",i);
804 sprintf(tmpstr,"Long %c File",funny_chars[i]);
805 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
806 sprintf(tmpstr1,"check%d-6",i);
807 sprintf(tmpstr,"%c Long File",funny_chars[i]);
808 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
809 sprintf(tmpstr1,"check%d-7",i);
810 sprintf(tmpstr,"Long File %c",funny_chars[i]);
811 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
812 }
813 }
814
815 static void test_GetTempPathA(char* tmp_dir)
816 {
817 DWORD len, len_with_null;
818 char buf[MAX_PATH];
819
820 len_with_null = strlen(tmp_dir) + 1;
821
822 lstrcpyA(buf, "foo");
823 len = GetTempPathA(MAX_PATH, buf);
824 ok(len <= MAX_PATH, "should fit into MAX_PATH\n");
825 ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
826 ok(len == strlen(buf), "returned length should be equal to the length of string\n");
827
828 /* Some versions of Windows touch the buffer, some don't so we don't
829 * test that. Also, NT sometimes exaggerates the required buffer size
830 * so we cannot test for an exact match. Finally, the
831 * 'len_with_null - 1' case is so buggy on Windows it's not testable.
832 * For instance in some cases Win98 returns len_with_null - 1 instead
833 * of len_with_null.
834 */
835 len = GetTempPathA(1, buf);
836 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
837
838 len = GetTempPathA(0, NULL);
839 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
840
841 /* The call above gave us the buffer size that Windows thinks is needed
842 * so the next call should work
843 */
844 lstrcpyA(buf, "foo");
845 len = GetTempPathA(len, buf);
846 ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
847 ok(len == strlen(buf), "returned length should be equal to the length of string\n");
848 }
849
850 static void test_GetTempPathW(char* tmp_dir)
851 {
852 DWORD len, len_with_null;
853 WCHAR buf[MAX_PATH];
854 WCHAR tmp_dirW[MAX_PATH];
855 static const WCHAR fooW[] = {'f','o','o',0};
856
857 MultiByteToWideChar(CP_ACP,0,tmp_dir,-1,tmp_dirW,sizeof(tmp_dirW)/sizeof(*tmp_dirW));
858 len_with_null = lstrlenW(tmp_dirW) + 1;
859
860 /* This one is different from ANSI version: ANSI version doesn't
861 * touch the buffer, unicode version usually truncates the buffer
862 * to zero size. NT still exaggerates the required buffer size
863 * sometimes so we cannot test for an exact match. Finally, the
864 * 'len_with_null - 1' case is so buggy on Windows it's not testable.
865 * For instance on NT4 it will sometimes return a path without the
866 * trailing '\\' and sometimes return an error.
867 */
868
869 lstrcpyW(buf, fooW);
870 len = GetTempPathW(MAX_PATH, buf);
871 if (len==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
872 return;
873 ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
874 ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
875
876 lstrcpyW(buf, fooW);
877 len = GetTempPathW(1, buf);
878 ok(buf[0] == 0, "unicode version should truncate the buffer to zero size\n");
879 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
880
881 len = GetTempPathW(0, NULL);
882 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
883
884 lstrcpyW(buf, fooW);
885 len = GetTempPathW(len, buf);
886 ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
887 ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
888 }
889
890 static void test_GetTempPath(void)
891 {
892 char save_TMP[MAX_PATH];
893 char windir[MAX_PATH];
894 char buf[MAX_PATH];
895
896 GetEnvironmentVariableA("TMP", save_TMP, sizeof(save_TMP));
897
898 /* test default configuration */
899 trace("TMP=%s\n", save_TMP);
900 strcpy(buf,save_TMP);
901 if (buf[strlen(buf)-1]!='\\')
902 strcat(buf,"\\");
903 test_GetTempPathA(buf);
904 test_GetTempPathW(buf);
905
906 /* TMP=C:\WINDOWS */
907 GetWindowsDirectoryA(windir, sizeof(windir));
908 SetEnvironmentVariableA("TMP", windir);
909 GetEnvironmentVariableA("TMP", buf, sizeof(buf));
910 trace("TMP=%s\n", buf);
911 strcat(windir,"\\");
912 test_GetTempPathA(windir);
913 test_GetTempPathW(windir);
914
915 /* TMP=C:\ */
916 GetWindowsDirectoryA(windir, sizeof(windir));
917 windir[3] = 0;
918 SetEnvironmentVariableA("TMP", windir);
919 GetEnvironmentVariableA("TMP", buf, sizeof(buf));
920 trace("TMP=%s\n", buf);
921 test_GetTempPathA(windir);
922 test_GetTempPathW(windir);
923
924 /* TMP=C: i.e. use current working directory of the specified drive */
925 GetWindowsDirectoryA(windir, sizeof(windir));
926 SetCurrentDirectoryA(windir);
927 windir[2] = 0;
928 SetEnvironmentVariableA("TMP", windir);
929 GetEnvironmentVariableA("TMP", buf, sizeof(buf));
930 trace("TMP=%s\n", buf);
931 GetWindowsDirectoryA(windir, sizeof(windir));
932 strcat(windir,"\\");
933 test_GetTempPathA(windir);
934 test_GetTempPathW(windir);
935
936 SetEnvironmentVariableA("TMP", save_TMP);
937 }
938
939 static void test_GetLongPathNameW(void)
940 {
941 DWORD length;
942 WCHAR empty[MAX_PATH];
943
944 /* Not present in all windows versions */
945 if(pGetLongPathNameW)
946 {
947 SetLastError(0xdeadbeef);
948 length = pGetLongPathNameW(NULL,NULL,0);
949 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
950 {
951 skip("GetLongPathNameW is not implemented\n");
952 return;
953 }
954 ok(0==length,"GetLongPathNameW returned %d but expected 0\n",length);
955 ok(GetLastError()==ERROR_INVALID_PARAMETER,"GetLastError returned %d but expected ERROR_INVALID_PARAMETER\n",GetLastError());
956
957 SetLastError(0xdeadbeef);
958 empty[0]=0;
959 length = pGetLongPathNameW(empty,NULL,0);
960 ok(0==length,"GetLongPathNameW returned %d but expected 0\n",length);
961 ok(GetLastError()==ERROR_PATH_NOT_FOUND,"GetLastError returned %d but expected ERROR_PATH_NOT_FOUND\n",GetLastError());
962 }
963 }
964
965 static void test_GetShortPathNameW(void)
966 {
967 WCHAR test_path[] = { 'L', 'o', 'n', 'g', 'D', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 'N', 'a', 'm', 'e', 0 };
968 WCHAR path[MAX_PATH];
969 WCHAR short_path[MAX_PATH];
970 DWORD length;
971 HANDLE file;
972 int ret;
973 WCHAR name[] = { 't', 'e', 's', 't', 0 };
974 WCHAR backSlash[] = { '\\', 0 };
975
976 SetLastError(0xdeadbeef);
977 GetTempPathW( MAX_PATH, path );
978 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
979 {
980 skip("GetTempPathW is not implemented\n");
981 return;
982 }
983
984 lstrcatW( path, test_path );
985 lstrcatW( path, backSlash );
986 ret = CreateDirectoryW( path, NULL );
987 ok( ret, "Directory was not created. LastError = %d\n", GetLastError() );
988
989 /* Starting a main part of test */
990 length = GetShortPathNameW( path, short_path, 0 );
991 ok( length, "GetShortPathNameW returned 0.\n" );
992 ret = GetShortPathNameW( path, short_path, length );
993 ok( ret, "GetShortPathNameW returned 0.\n" );
994 lstrcatW( short_path, name );
995 file = CreateFileW( short_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
996 ok( file != INVALID_HANDLE_VALUE, "File was not created.\n" );
997
998 /* End test */
999 CloseHandle( file );
1000 ret = DeleteFileW( short_path );
1001 ok( ret, "Cannot delete file.\n" );
1002 ret = RemoveDirectoryW( path );
1003 ok( ret, "Cannot delete directory.\n" );
1004 }
1005
1006 static void test_GetSystemDirectory(void)
1007 {
1008 CHAR buffer[MAX_PATH + 4];
1009 DWORD res;
1010 DWORD total;
1011
1012 SetLastError(0xdeadbeef);
1013 res = GetSystemDirectory(NULL, 0);
1014 /* res includes the terminating Zero */
1015 ok(res > 0, "returned %d with %d (expected '>0')\n", res, GetLastError());
1016
1017 total = res;
1018
1019 /* this crashes on XP */
1020 if (0) res = GetSystemDirectory(NULL, total);
1021
1022 SetLastError(0xdeadbeef);
1023 res = GetSystemDirectory(NULL, total-1);
1024 /* 95+NT: total (includes the terminating Zero)
1025 98+ME: 0 with ERROR_INVALID_PARAMETER */
1026 ok( (res == total) || (!res && (GetLastError() == ERROR_INVALID_PARAMETER)),
1027 "returned %d with %d (expected '%d' or: '0' with "
1028 "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), total);
1029
1030 if (total > MAX_PATH) return;
1031
1032 buffer[0] = '\0';
1033 SetLastError(0xdeadbeef);
1034 res = GetSystemDirectory(buffer, total);
1035 /* res does not include the terminating Zero */
1036 ok( (res == (total-1)) && (buffer[0]),
1037 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1038 res, GetLastError(), buffer, total-1);
1039
1040 buffer[0] = '\0';
1041 SetLastError(0xdeadbeef);
1042 res = GetSystemDirectory(buffer, total + 1);
1043 /* res does not include the terminating Zero */
1044 ok( (res == (total-1)) && (buffer[0]),
1045 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1046 res, GetLastError(), buffer, total-1);
1047
1048 memset(buffer, '#', total + 1);
1049 buffer[total + 2] = '\0';
1050 SetLastError(0xdeadbeef);
1051 res = GetSystemDirectory(buffer, total-1);
1052 /* res includes the terminating Zero) */
1053 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1054 res, GetLastError(), buffer, total);
1055
1056 memset(buffer, '#', total + 1);
1057 buffer[total + 2] = '\0';
1058 SetLastError(0xdeadbeef);
1059 res = GetSystemDirectory(buffer, total-2);
1060 /* res includes the terminating Zero) */
1061 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1062 res, GetLastError(), buffer, total);
1063 }
1064
1065 static void test_GetWindowsDirectory(void)
1066 {
1067 CHAR buffer[MAX_PATH + 4];
1068 DWORD res;
1069 DWORD total;
1070
1071 SetLastError(0xdeadbeef);
1072 res = GetWindowsDirectory(NULL, 0);
1073 /* res includes the terminating Zero */
1074 ok(res > 0, "returned %d with %d (expected '>0')\n", res, GetLastError());
1075
1076 total = res;
1077 /* this crashes on XP */
1078 if (0) res = GetWindowsDirectory(NULL, total);
1079
1080 SetLastError(0xdeadbeef);
1081 res = GetWindowsDirectory(NULL, total-1);
1082 /* 95+NT: total (includes the terminating Zero)
1083 98+ME: 0 with ERROR_INVALID_PARAMETER */
1084 ok( (res == total) || (!res && (GetLastError() == ERROR_INVALID_PARAMETER)),
1085 "returned %d with %d (expected '%d' or: '0' with "
1086 "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), total);
1087
1088 if (total > MAX_PATH) return;
1089
1090 buffer[0] = '\0';
1091 SetLastError(0xdeadbeef);
1092 res = GetWindowsDirectory(buffer, total);
1093 /* res does not include the terminating Zero */
1094 ok( (res == (total-1)) && (buffer[0]),
1095 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1096 res, GetLastError(), buffer, total-1);
1097
1098 buffer[0] = '\0';
1099 SetLastError(0xdeadbeef);
1100 res = GetWindowsDirectory(buffer, total + 1);
1101 /* res does not include the terminating Zero */
1102 ok( (res == (total-1)) && (buffer[0]),
1103 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1104 res, GetLastError(), buffer, total-1);
1105
1106 memset(buffer, '#', total + 1);
1107 buffer[total + 2] = '\0';
1108 SetLastError(0xdeadbeef);
1109 res = GetWindowsDirectory(buffer, total-1);
1110 /* res includes the terminating Zero) */
1111 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1112 res, GetLastError(), buffer, total);
1113
1114 memset(buffer, '#', total + 1);
1115 buffer[total + 2] = '\0';
1116 SetLastError(0xdeadbeef);
1117 res = GetWindowsDirectory(buffer, total-2);
1118 /* res includes the terminating Zero) */
1119 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1120 res, GetLastError(), buffer, total);
1121 }
1122
1123 static void test_NeedCurrentDirectoryForExePathA(void)
1124 {
1125 /* Crashes in Windows */
1126 if (0)
1127 ok(pNeedCurrentDirectoryForExePathA(NULL), "returned FALSE for NULL\n");
1128
1129 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", NULL);
1130 ok(pNeedCurrentDirectoryForExePathA("."), "returned FALSE for \".\"\n");
1131 ok(pNeedCurrentDirectoryForExePathA("c:\\"), "returned FALSE for \"c:\\\"\n");
1132 ok(pNeedCurrentDirectoryForExePathA("cmd.exe"), "returned FALSE for \"cmd.exe\"\n");
1133
1134 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", "nya");
1135 ok(!pNeedCurrentDirectoryForExePathA("."), "returned TRUE for \".\"\n");
1136 ok(pNeedCurrentDirectoryForExePathA("c:\\"), "returned FALSE for \"c:\\\"\n");
1137 ok(!pNeedCurrentDirectoryForExePathA("cmd.exe"), "returned TRUE for \"cmd.exe\"\n");
1138 }
1139
1140 static void test_NeedCurrentDirectoryForExePathW(void)
1141 {
1142 const WCHAR thispath[] = {'.', 0};
1143 const WCHAR fullpath[] = {'c', ':', '\\', 0};
1144 const WCHAR cmdname[] = {'c', 'm', 'd', '.', 'e', 'x', 'e', 0};
1145
1146 /* Crashes in Windows */
1147 if (0)
1148 ok(pNeedCurrentDirectoryForExePathW(NULL), "returned FALSE for NULL\n");
1149
1150 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", NULL);
1151 ok(pNeedCurrentDirectoryForExePathW(thispath), "returned FALSE for \".\"\n");
1152 ok(pNeedCurrentDirectoryForExePathW(fullpath), "returned FALSE for \"c:\\\"\n");
1153 ok(pNeedCurrentDirectoryForExePathW(cmdname), "returned FALSE for \"cmd.exe\"\n");
1154
1155 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", "nya");
1156 ok(!pNeedCurrentDirectoryForExePathW(thispath), "returned TRUE for \".\"\n");
1157 ok(pNeedCurrentDirectoryForExePathW(fullpath), "returned FALSE for \"c:\\\"\n");
1158 ok(!pNeedCurrentDirectoryForExePathW(cmdname), "returned TRUE for \"cmd.exe\"\n");
1159 }
1160
1161 /* Call various path/file name retrieving APIs and check the case of
1162 * the returned drive letter. Some apps (for instance Adobe Photoshop CS3
1163 * installer) depend on the drive letter being in upper case.
1164 */
1165 static void test_drive_letter_case(void)
1166 {
1167 UINT ret;
1168 char buf[MAX_PATH];
1169
1170 #define is_upper_case_letter(a) ((a) >= 'A' && (a) <= 'Z')
1171
1172 memset(buf, 0, sizeof(buf));
1173 SetLastError(0xdeadbeef);
1174 ret = GetWindowsDirectory(buf, sizeof(buf));
1175 ok(ret, "GetWindowsDirectory error %u\n", GetLastError());
1176 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1177 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1178 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1179
1180 /* re-use the buffer returned by GetFullPathName */
1181 buf[2] = '/';
1182 SetLastError(0xdeadbeef);
1183 ret = GetFullPathName(buf + 2, sizeof(buf), buf, NULL);
1184 ok(ret, "GetFullPathName error %u\n", GetLastError());
1185 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1186 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1187 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1188
1189 memset(buf, 0, sizeof(buf));
1190 SetLastError(0xdeadbeef);
1191 ret = GetSystemDirectory(buf, sizeof(buf));
1192 ok(ret, "GetSystemDirectory error %u\n", GetLastError());
1193 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1194 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1195 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1196
1197 memset(buf, 0, sizeof(buf));
1198 SetLastError(0xdeadbeef);
1199 ret = GetCurrentDirectory(sizeof(buf), buf);
1200 ok(ret, "GetCurrentDirectory error %u\n", GetLastError());
1201 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1202 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1203 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1204
1205 /* TEMP is an environment variable, so it can't be tested for case-sensitivity */
1206 memset(buf, 0, sizeof(buf));
1207 SetLastError(0xdeadbeef);
1208 ret = GetTempPath(sizeof(buf), buf);
1209 ok(ret, "GetTempPath error %u\n", GetLastError());
1210 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1211 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1212 ok(buf[strlen(buf)-1] == '\\', "Temporary path (%s) doesn't end in a slash\n", buf);
1213
1214 memset(buf, 0, sizeof(buf));
1215 SetLastError(0xdeadbeef);
1216 ret = GetFullPathName(".", sizeof(buf), buf, NULL);
1217 ok(ret, "GetFullPathName error %u\n", GetLastError());
1218 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1219 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1220 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1221
1222 /* re-use the buffer returned by GetFullPathName */
1223 SetLastError(0xdeadbeef);
1224 ret = GetShortPathName(buf, buf, sizeof(buf));
1225 ok(ret, "GetShortPathName error %u\n", GetLastError());
1226 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1227 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1228 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1229
1230 if (pGetLongPathNameA)
1231 {
1232 /* re-use the buffer returned by GetShortPathName */
1233 SetLastError(0xdeadbeef);
1234 ret = pGetLongPathNameA(buf, buf, sizeof(buf));
1235 ok(ret, "GetLongPathNameA error %u\n", GetLastError());
1236 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1237 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1238 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1239 }
1240 #undef is_upper_case_letter
1241 }
1242
1243 START_TEST(path)
1244 {
1245 CHAR origdir[MAX_PATH],curdir[MAX_PATH], curDrive, otherDrive;
1246 pGetLongPathNameA = (void*)GetProcAddress( GetModuleHandleA("kernel32.dll"),
1247 "GetLongPathNameA" );
1248 pGetLongPathNameW = (void*)GetProcAddress(GetModuleHandleA("kernel32.dll") ,
1249 "GetLongPathNameW" );
1250 pNeedCurrentDirectoryForExePathA =
1251 (void*)GetProcAddress( GetModuleHandleA("kernel32.dll"),
1252 "NeedCurrentDirectoryForExePathA" );
1253 pNeedCurrentDirectoryForExePathW =
1254 (void*)GetProcAddress( GetModuleHandleA("kernel32.dll"),
1255 "NeedCurrentDirectoryForExePathW" );
1256
1257 test_InitPathA(curdir, &curDrive, &otherDrive);
1258 test_CurrentDirectoryA(origdir,curdir);
1259 test_PathNameA(curdir, curDrive, otherDrive);
1260 test_CleanupPathA(origdir,curdir);
1261 test_GetTempPath();
1262 test_GetLongPathNameW();
1263 test_GetShortPathNameW();
1264 test_GetSystemDirectory();
1265 test_GetWindowsDirectory();
1266 if (pNeedCurrentDirectoryForExePathA)
1267 {
1268 test_NeedCurrentDirectoryForExePathA();
1269 }
1270 if (pNeedCurrentDirectoryForExePathW)
1271 {
1272 test_NeedCurrentDirectoryForExePathW();
1273 }
1274 test_drive_letter_case();
1275 }