push 378fe7a60681a28e8b22f62dcfe122d585b92570
[wine/hacks.git] / dlls / kernel32 / tests / path.c
bloba272b567ec5f8edd2ca19026ef3b76cac1aa6367
1 /*
2 * Unit test suite for various Path and Directory Functions
4 * Copyright 2002 Geoffrey Hausheer
5 * Copyright 2006 Detlef Riekenberg
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.
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.
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
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"
31 #define HAS_TRAIL_SLASH_A(string) (string[lstrlenA(string)-1]=='\\')
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"
42 #define NOT_A_VALID_DRIVE '@'
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 |<>"
50 static const CHAR funny_chars[]="!@#$%^&*()=+{}[],?'`";
51 static const CHAR is_char_ok[] ="11111110111111111011";
53 static DWORD (WINAPI *pGetLongPathNameA)(LPCSTR,LPSTR,DWORD);
54 static DWORD (WINAPI *pGetLongPathNameW)(LPWSTR,LPWSTR,DWORD);
56 /* Present in Win2003+ */
57 static BOOL (WINAPI *pNeedCurrentDirectoryForExePathA)(LPCSTR);
58 static BOOL (WINAPI *pNeedCurrentDirectoryForExePathW)(LPCWSTR);
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;
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
75 static void test_ValidPathA(const CHAR *curdir, const CHAR *subdir, const CHAR *filename,
76 CHAR *shortstr, SLpassfail *passfail, const CHAR *errstr)
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
91 if(passfail!=NULL) {
92 passfail->shortlen=-1;passfail->s2llen=-1;passfail->longlen=-1;
93 passfail->shorterror=0;passfail->s2lerror=0;passfail->longerror=0;
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);
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);
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);
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();
143 /* Test GetLongPathNameA functionality
144 We test both conversion from GetFullPathNameA and from GetShortPathNameA
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();
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);
174 } else {
175 passfail->longlen=len;
176 passfail->longerror=GetLastError();
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;
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,"");
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");
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];
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);
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.
237 static void test_FunnyChars(CHAR *curdir,CHAR *curdir_short,CHAR *filename, INT valid,CHAR *errstr)
239 CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
240 SLpassfail passfail;
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);
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);
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)
275 CHAR tmppath[MAX_PATH], *dirptr;
276 DWORD val,len,chklen;
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);
306 static void test_InitPathA(CHAR *newdir, CHAR *curDrive, CHAR *otherDrive)
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;
316 *curDrive = *otherDrive = NOT_A_VALID_DRIVE;
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");
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 || broken(len1 == len), /* WinME */
332 "GetTempPathA should return string length %d instead of %d\n",len+1,len1);
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)
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");
348 id=GetTempFileNameA(tmppath,NULL,0,newdir);
349 /* Windows 95, 98 return 0==id, while Windows 2000, XP return 0!=id */
350 if (id)
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");
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");
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
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
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");
417 /* Test GetCurrentDirectory & SetCurrentDirectory */
418 static void test_CurrentDirectoryA(CHAR *origdir, CHAR *newdir)
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
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
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
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.
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 /* change to root without a trailing backslash. The function call succeeds
469 but the directory is not changed.
471 sprintf(tmpstr, "%c:", newdir[0]);
472 test_setdir(newdir,tmpstr,newdir,1,"check 10");
473 /* works however with a trailing backslash */
474 sprintf(tmpstr, "%c:\\", newdir[0]);
475 test_setdir(newdir,tmpstr,NULL,1,"check 11");
478 /* Cleanup the mess we made while executing these tests */
479 static void test_CleanupPathA(CHAR *origdir, CHAR *curdir)
481 CHAR tmpstr[MAX_PATH];
482 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
483 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
484 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,LONGFILE);
485 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
486 sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,SHORTFILE);
487 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
488 sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
489 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
490 sprintf(tmpstr,"%s\\%s",curdir,SHORTDIR);
491 ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
492 sprintf(tmpstr,"%s\\%s",curdir,LONGDIR);
493 ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
494 ok(SetCurrentDirectoryA(origdir),"SetCurrentDirectoryA failed\n");
495 ok(RemoveDirectoryA(curdir),"RemoveDirectoryA failed\n");
498 /* This routine will test Get(Full|Short|Long)PathNameA */
499 static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive)
501 CHAR curdir_short[MAX_PATH],
502 longdir_short[MAX_PATH];
503 CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH],tmpstr2[MAX_PATH];
504 LPSTR strptr; /*ptr to the filename portion of the path */
505 DWORD len;
506 INT i;
507 CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
508 SLpassfail passfail;
510 /* Get the short form of the current directory */
511 ok((len=GetShortPathNameA(curdir,curdir_short,MAX_PATH)),
512 "GetShortPathNameA failed\n");
513 ok(!HAS_TRAIL_SLASH_A(curdir_short),
514 "GetShortPathNameA should not have a trailing \\\n");
515 /* Get the short form of the absolute-path to LONGDIR */
516 sprintf(tmpstr,"%s\\%s",curdir_short,LONGDIR);
517 ok((len=GetShortPathNameA(tmpstr,longdir_short,MAX_PATH)),
518 "GetShortPathNameA failed\n");
519 ok(lstrcmpiA(longdir_short+(len-1),"\\")!=0,
520 "GetShortPathNameA should not have a trailing \\\n");
522 if (pGetLongPathNameA) {
523 DWORD rc1,rc2;
524 sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
525 rc1=(*pGetLongPathNameA)(tmpstr,NULL,0);
526 rc2=(*pGetLongPathNameA)(curdir,NULL,0);
527 ok((rc1-strlen(tmpstr))==(rc2-strlen(curdir)),
528 "GetLongPathNameA: wrong return code, %d instead of %d\n",
529 rc1, lstrlenA(tmpstr)+1);
531 sprintf(dir,"%c:",curDrive);
532 rc1=(*pGetLongPathNameA)(dir,tmpstr,sizeof(tmpstr));
533 ok(strcmp(dir,tmpstr)==0,
534 "GetLongPathNameA: returned '%s' instead of '%s' (rc=%d)\n",
535 tmpstr,dir,rc1);
538 /* Check the cases where both file and directory exist first */
539 /* Start with a 8.3 directory, 8.3 filename */
540 test_ValidPathA(curdir,SHORTDIR,SHORTFILE,tmpstr,NULL,"test1");
541 sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,SHORTFILE);
542 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
543 "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
544 /* Now try a 8.3 directory, long file name */
545 test_ValidPathA(curdir,SHORTDIR,LONGFILE,tmpstr,NULL,"test2");
546 sprintf(tmpstr1,"%s\\%s",curdir_short,SHORTDIR);
547 test_LongtoShortA(tmpstr,tmpstr1,"PAT","test2");
548 /* Next is a long directory, 8.3 file */
549 test_ValidPathA(curdir,LONGDIR,SHORTFILE,tmpstr,NULL,"test3");
550 sprintf(tmpstr1,"%s\\%s",longdir_short,SHORTFILE);
551 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
552 "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
553 /*Lastly a long directory, long file */
554 test_ValidPathA(curdir,LONGDIR,LONGFILE,tmpstr,NULL,"test4");
555 test_LongtoShortA(tmpstr,longdir_short,"PAT","test4");
557 /* Now check all of the invalid file w/ valid directory combinations */
558 /* Start with a 8.3 directory, 8.3 filename */
559 test_ValidPathA(curdir,SHORTDIR,NONFILE_SHORT,tmpstr,&passfail,"test5");
560 sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,NONFILE_SHORT);
561 ok((passfail.shortlen==0 &&
562 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
563 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
564 (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
565 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
566 passfail.shortlen,passfail.shorterror,tmpstr);
567 if(pGetLongPathNameA) {
568 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
569 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
570 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
572 /* Now try a 8.3 directory, long file name */
573 test_ValidPathA(curdir,SHORTDIR,NONFILE_LONG,tmpstr,&passfail,"test6");
574 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
575 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
576 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
577 !passfail.shorterror,
578 "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
579 if(pGetLongPathNameA) {
580 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
581 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
582 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
584 /* Next is a long directory, 8.3 file */
585 test_ValidPathA(curdir,LONGDIR,NONFILE_SHORT,tmpstr,&passfail,"test7");
586 sprintf(tmpstr2,"%s\\%s",curdir_short,LONGDIR);
587 GetShortPathNameA(tmpstr2,tmpstr1,MAX_PATH);
588 strcat(tmpstr1,"\\" NONFILE_SHORT);
589 ok((passfail.shortlen==0 &&
590 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
591 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
592 (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
593 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
594 passfail.shortlen,passfail.shorterror,tmpstr);
595 if(pGetLongPathNameA) {
596 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
597 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
598 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
600 /*Lastly a long directory, long file */
601 test_ValidPathA(curdir,LONGDIR,NONFILE_LONG,tmpstr,&passfail,"test8");
602 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
603 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
604 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
605 !passfail.shorterror,
606 "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
607 if(pGetLongPathNameA) {
608 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
609 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
610 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
612 /* Now try again with directories that don't exist */
613 /* 8.3 directory, 8.3 filename */
614 test_ValidPathA(curdir,NONDIR_SHORT,SHORTFILE,tmpstr,&passfail,"test9");
615 sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,NONDIR_SHORT,SHORTFILE);
616 ok((passfail.shortlen==0 &&
617 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
618 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
619 (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
620 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
621 passfail.shortlen,passfail.shorterror,tmpstr);
622 if(pGetLongPathNameA) {
623 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
624 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
625 passfail.longerror==ERROR_FILE_NOT_FOUND,
626 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
627 passfail.longerror);
629 /* Now try a 8.3 directory, long file name */
630 test_ValidPathA(curdir,NONDIR_SHORT,LONGFILE,tmpstr,&passfail,"test10");
631 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
632 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
633 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
634 !passfail.shorterror,
635 "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
636 passfail.shorterror);
637 if(pGetLongPathNameA) {
638 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
639 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
640 passfail.longerror==ERROR_FILE_NOT_FOUND,
641 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
642 passfail.longerror);
644 /* Next is a long directory, 8.3 file */
645 test_ValidPathA(curdir,NONDIR_LONG,SHORTFILE,tmpstr,&passfail,"test11");
646 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
647 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
648 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
649 !passfail.shorterror,
650 "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
651 passfail.shorterror);
652 if(pGetLongPathNameA) {
653 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
654 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
655 passfail.longerror==ERROR_FILE_NOT_FOUND,
656 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
657 passfail.longerror);
659 /*Lastly a long directory, long file */
660 test_ValidPathA(curdir,NONDIR_LONG,LONGFILE,tmpstr,&passfail,"test12");
661 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
662 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
663 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
664 !passfail.shorterror,
665 "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
666 passfail.shorterror);
667 if(pGetLongPathNameA) {
668 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
669 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
670 passfail.longerror==ERROR_FILE_NOT_FOUND,
671 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
672 passfail.longerror);
674 /* Next try directories ending with '\\' */
675 /* Existing Directories */
676 sprintf(tmpstr,"%s\\",SHORTDIR);
677 test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test13");
678 sprintf(tmpstr,"%s\\",LONGDIR);
679 test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test14");
680 /* Nonexistent directories */
681 sprintf(tmpstr,"%s\\",NONDIR_SHORT);
682 test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test15");
683 sprintf(tmpstr2,"%s\\%s",curdir_short,tmpstr);
684 ok((passfail.shortlen==0 &&
685 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
686 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
687 (passfail.shortlen==strlen(tmpstr2) && lstrcmpiA(tmpstr1,tmpstr2)==0),
688 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
689 passfail.shortlen,passfail.shorterror,tmpstr);
690 if(pGetLongPathNameA) {
691 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
692 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
693 "GetLongPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
694 passfail.longerror);
696 sprintf(tmpstr,"%s\\",NONDIR_LONG);
697 test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test16");
698 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
699 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
700 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
701 !passfail.shorterror,
702 "GetShortPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
703 passfail.shorterror);
704 if(pGetLongPathNameA) {
705 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
706 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
707 "GetLongPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
708 passfail.longerror);
710 /* Test GetFullPathNameA with drive letters */
711 if( curDrive != NOT_A_VALID_DRIVE) {
712 sprintf(tmpstr,"%c:",curdir[0]);
713 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr2,&strptr),
714 "GetFullPathNameA(%c:) failed\n", curdir[0]);
715 GetCurrentDirectoryA(MAX_PATH,tmpstr);
716 sprintf(tmpstr1,"%s\\",tmpstr);
717 ok(lstrcmpiA(tmpstr,tmpstr2)==0 || lstrcmpiA(tmpstr1,tmpstr2)==0,
718 "GetFullPathNameA(%c:) returned '%s' instead of '%s' or '%s'\n",
719 curdir[0],tmpstr2,tmpstr,tmpstr1);
721 sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
722 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
723 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
724 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
725 ok(lstrcmpiA(SHORTFILE,strptr)==0,
726 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
728 /* Without a leading slash, insert the current directory if on the current drive */
729 sprintf(tmpstr,"%c:%s\\%s",curdir[0],SHORTDIR,SHORTFILE);
730 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
731 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
732 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
733 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
734 ok(lstrcmpiA(SHORTFILE,strptr)==0,
735 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
736 /* Otherwise insert the missing leading slash */
737 if( otherDrive != NOT_A_VALID_DRIVE) {
738 /* FIXME: this test assumes that current directory on other drive is root */
739 sprintf(tmpstr,"%c:%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
740 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed for %s\n", tmpstr);
741 sprintf(tmpstr,"%c:\\%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
742 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
743 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
744 ok(lstrcmpiA(SHORTFILE,strptr)==0,
745 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
747 /* Xilinx tools like to mix Unix and DOS formats, which Windows handles fine.
748 So test for them. */
749 if( curDrive != NOT_A_VALID_DRIVE) {
750 sprintf(tmpstr,"%c:/%s\\%s",curDrive,SHORTDIR,SHORTFILE);
751 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
752 sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
753 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
754 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
755 ok(lstrcmpiA(SHORTFILE,strptr)==0,
756 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
758 /**/
759 sprintf(tmpstr,"%c:%s/%s",curdir[0],SHORTDIR,SHORTFILE);
760 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
761 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
762 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
763 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
764 ok(lstrcmpiA(SHORTFILE,strptr)==0,
765 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
766 /* Windows will insert a drive letter in front of an absolute UNIX path */
767 sprintf(tmpstr,"/%s/%s",SHORTDIR,SHORTFILE);
768 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
769 sprintf(tmpstr,"%c:\\%s\\%s",*tmpstr1,SHORTDIR,SHORTFILE);
770 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
771 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
772 /* This passes in Wine because it still contains the pointer from the previous test */
773 ok(lstrcmpiA(SHORTFILE,strptr)==0,
774 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
776 /* Now try some relative paths */
777 ok(GetShortPathNameA(LONGDIR,tmpstr,MAX_PATH),"GetShortPathNameA failed\n");
778 test_SplitShortPathA(tmpstr,dir,eight,three);
779 if(pGetLongPathNameA) {
780 ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
781 ok(lstrcmpiA(tmpstr1,LONGDIR)==0,
782 "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,LONGDIR);
784 sprintf(tmpstr,".\\%s",LONGDIR);
785 ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed\n");
786 test_SplitShortPathA(tmpstr1,dir,eight,three);
787 ok(lstrcmpiA(dir,".")==0 || dir[0]=='\0',
788 "GetShortPathNameA did not keep relative directory [%s]\n",tmpstr1);
789 if(pGetLongPathNameA) {
790 ok(pGetLongPathNameA(tmpstr1,tmpstr1,MAX_PATH),"GetLongPathNameA failed %s\n",
791 tmpstr);
792 ok(lstrcmpiA(tmpstr1,tmpstr)==0,
793 "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
795 /* Check out Get*PathNameA on some funny characters */
796 for(i=0;i<lstrlenA(funny_chars);i++) {
797 INT valid;
798 valid=(is_char_ok[i]=='0') ? 0 : 1;
799 sprintf(tmpstr1,"check%d-1",i);
800 sprintf(tmpstr,"file%c000.ext",funny_chars[i]);
801 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
802 sprintf(tmpstr1,"check%d-2",i);
803 sprintf(tmpstr,"file000.e%ct",funny_chars[i]);
804 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
805 sprintf(tmpstr1,"check%d-3",i);
806 sprintf(tmpstr,"%cfile000.ext",funny_chars[i]);
807 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
808 sprintf(tmpstr1,"check%d-4",i);
809 sprintf(tmpstr,"file000%c.ext",funny_chars[i]);
810 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
811 sprintf(tmpstr1,"check%d-5",i);
812 sprintf(tmpstr,"Long %c File",funny_chars[i]);
813 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
814 sprintf(tmpstr1,"check%d-6",i);
815 sprintf(tmpstr,"%c Long File",funny_chars[i]);
816 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
817 sprintf(tmpstr1,"check%d-7",i);
818 sprintf(tmpstr,"Long File %c",funny_chars[i]);
819 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
823 static void test_GetTempPathA(char* tmp_dir)
825 DWORD len, len_with_null;
826 char buf[MAX_PATH];
828 len_with_null = strlen(tmp_dir) + 1;
830 lstrcpyA(buf, "foo");
831 len = GetTempPathA(MAX_PATH, buf);
832 ok(len <= MAX_PATH, "should fit into MAX_PATH\n");
833 ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
834 ok(len == strlen(buf), "returned length should be equal to the length of string\n");
836 /* Some versions of Windows touch the buffer, some don't so we don't
837 * test that. Also, NT sometimes exaggerates the required buffer size
838 * so we cannot test for an exact match. Finally, the
839 * 'len_with_null - 1' case is so buggy on Windows it's not testable.
840 * For instance in some cases Win98 returns len_with_null - 1 instead
841 * of len_with_null.
843 len = GetTempPathA(1, buf);
844 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
846 len = GetTempPathA(0, NULL);
847 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
849 /* The call above gave us the buffer size that Windows thinks is needed
850 * so the next call should work
852 lstrcpyA(buf, "foo");
853 len = GetTempPathA(len, buf);
854 ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
855 ok(len == strlen(buf), "returned length should be equal to the length of string\n");
858 static void test_GetTempPathW(char* tmp_dir)
860 DWORD len, len_with_null;
861 WCHAR buf[MAX_PATH];
862 WCHAR tmp_dirW[MAX_PATH];
863 static const WCHAR fooW[] = {'f','o','o',0};
865 MultiByteToWideChar(CP_ACP,0,tmp_dir,-1,tmp_dirW,sizeof(tmp_dirW)/sizeof(*tmp_dirW));
866 len_with_null = lstrlenW(tmp_dirW) + 1;
868 /* This one is different from ANSI version: ANSI version doesn't
869 * touch the buffer, unicode version usually truncates the buffer
870 * to zero size. NT still exaggerates the required buffer size
871 * sometimes so we cannot test for an exact match. Finally, the
872 * 'len_with_null - 1' case is so buggy on Windows it's not testable.
873 * For instance on NT4 it will sometimes return a path without the
874 * trailing '\\' and sometimes return an error.
877 lstrcpyW(buf, fooW);
878 len = GetTempPathW(MAX_PATH, buf);
879 if (len==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
880 return;
881 ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
882 ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
884 lstrcpyW(buf, fooW);
885 len = GetTempPathW(1, buf);
886 ok(buf[0] == 0, "unicode version should truncate the buffer to zero size\n");
887 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
889 len = GetTempPathW(0, NULL);
890 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
892 lstrcpyW(buf, fooW);
893 len = GetTempPathW(len, buf);
894 ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
895 ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
898 static void test_GetTempPath(void)
900 char save_TMP[MAX_PATH];
901 char windir[MAX_PATH];
902 char buf[MAX_PATH];
904 if (!GetEnvironmentVariableA("TMP", save_TMP, sizeof(save_TMP))) save_TMP[0] = 0;
906 /* test default configuration */
907 trace("TMP=%s\n", save_TMP);
908 if (save_TMP[0])
910 strcpy(buf,save_TMP);
911 if (buf[strlen(buf)-1]!='\\')
912 strcat(buf,"\\");
913 test_GetTempPathA(buf);
914 test_GetTempPathW(buf);
917 /* TMP=C:\WINDOWS */
918 GetWindowsDirectoryA(windir, sizeof(windir));
919 SetEnvironmentVariableA("TMP", windir);
920 GetEnvironmentVariableA("TMP", buf, sizeof(buf));
921 trace("TMP=%s\n", buf);
922 strcat(windir,"\\");
923 test_GetTempPathA(windir);
924 test_GetTempPathW(windir);
926 /* TMP=C:\ */
927 GetWindowsDirectoryA(windir, sizeof(windir));
928 windir[3] = 0;
929 SetEnvironmentVariableA("TMP", windir);
930 GetEnvironmentVariableA("TMP", buf, sizeof(buf));
931 trace("TMP=%s\n", buf);
932 test_GetTempPathA(windir);
933 test_GetTempPathW(windir);
935 /* TMP=C: i.e. use current working directory of the specified drive */
936 GetWindowsDirectoryA(windir, sizeof(windir));
937 SetCurrentDirectoryA(windir);
938 windir[2] = 0;
939 SetEnvironmentVariableA("TMP", windir);
940 GetEnvironmentVariableA("TMP", buf, sizeof(buf));
941 trace("TMP=%s\n", buf);
942 GetWindowsDirectoryA(windir, sizeof(windir));
943 strcat(windir,"\\");
944 test_GetTempPathA(windir);
945 test_GetTempPathW(windir);
947 SetEnvironmentVariableA("TMP", save_TMP);
950 static void test_GetLongPathNameW(void)
952 DWORD length;
953 WCHAR empty[MAX_PATH];
955 /* Not present in all windows versions */
956 if(pGetLongPathNameW)
958 SetLastError(0xdeadbeef);
959 length = pGetLongPathNameW(NULL,NULL,0);
960 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
962 skip("GetLongPathNameW is not implemented\n");
963 return;
965 ok(0==length,"GetLongPathNameW returned %d but expected 0\n",length);
966 ok(GetLastError()==ERROR_INVALID_PARAMETER,"GetLastError returned %d but expected ERROR_INVALID_PARAMETER\n",GetLastError());
968 SetLastError(0xdeadbeef);
969 empty[0]=0;
970 length = pGetLongPathNameW(empty,NULL,0);
971 ok(0==length,"GetLongPathNameW returned %d but expected 0\n",length);
972 ok(GetLastError()==ERROR_PATH_NOT_FOUND,"GetLastError returned %d but expected ERROR_PATH_NOT_FOUND\n",GetLastError());
976 static void test_GetShortPathNameW(void)
978 WCHAR test_path[] = { 'L', 'o', 'n', 'g', 'D', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 'N', 'a', 'm', 'e', 0 };
979 WCHAR path[MAX_PATH];
980 WCHAR short_path[MAX_PATH];
981 DWORD length;
982 HANDLE file;
983 int ret;
984 WCHAR name[] = { 't', 'e', 's', 't', 0 };
985 WCHAR backSlash[] = { '\\', 0 };
987 SetLastError(0xdeadbeef);
988 GetTempPathW( MAX_PATH, path );
989 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
991 skip("GetTempPathW is not implemented\n");
992 return;
995 lstrcatW( path, test_path );
996 lstrcatW( path, backSlash );
997 ret = CreateDirectoryW( path, NULL );
998 ok( ret, "Directory was not created. LastError = %d\n", GetLastError() );
1000 /* Starting a main part of test */
1001 length = GetShortPathNameW( path, short_path, 0 );
1002 ok( length, "GetShortPathNameW returned 0.\n" );
1003 ret = GetShortPathNameW( path, short_path, length );
1004 ok( ret, "GetShortPathNameW returned 0.\n" );
1005 lstrcatW( short_path, name );
1006 file = CreateFileW( short_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1007 ok( file != INVALID_HANDLE_VALUE, "File was not created.\n" );
1009 /* End test */
1010 CloseHandle( file );
1011 ret = DeleteFileW( short_path );
1012 ok( ret, "Cannot delete file.\n" );
1013 ret = RemoveDirectoryW( path );
1014 ok( ret, "Cannot delete directory.\n" );
1017 static void test_GetSystemDirectory(void)
1019 CHAR buffer[MAX_PATH + 4];
1020 DWORD res;
1021 DWORD total;
1023 SetLastError(0xdeadbeef);
1024 res = GetSystemDirectory(NULL, 0);
1025 /* res includes the terminating Zero */
1026 ok(res > 0, "returned %d with %d (expected '>0')\n", res, GetLastError());
1028 total = res;
1030 /* this crashes on XP */
1031 if (0) res = GetSystemDirectory(NULL, total);
1033 SetLastError(0xdeadbeef);
1034 res = GetSystemDirectory(NULL, total-1);
1035 /* 95+NT: total (includes the terminating Zero)
1036 98+ME: 0 with ERROR_INVALID_PARAMETER */
1037 ok( (res == total) || (!res && (GetLastError() == ERROR_INVALID_PARAMETER)),
1038 "returned %d with %d (expected '%d' or: '0' with "
1039 "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), total);
1041 if (total > MAX_PATH) return;
1043 buffer[0] = '\0';
1044 SetLastError(0xdeadbeef);
1045 res = GetSystemDirectory(buffer, total);
1046 /* res does not include the terminating Zero */
1047 ok( (res == (total-1)) && (buffer[0]),
1048 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1049 res, GetLastError(), buffer, total-1);
1051 buffer[0] = '\0';
1052 SetLastError(0xdeadbeef);
1053 res = GetSystemDirectory(buffer, total + 1);
1054 /* res does not include the terminating Zero */
1055 ok( (res == (total-1)) && (buffer[0]),
1056 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1057 res, GetLastError(), buffer, total-1);
1059 memset(buffer, '#', total + 1);
1060 buffer[total + 2] = '\0';
1061 SetLastError(0xdeadbeef);
1062 res = GetSystemDirectory(buffer, total-1);
1063 /* res includes the terminating Zero) */
1064 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1065 res, GetLastError(), buffer, total);
1067 memset(buffer, '#', total + 1);
1068 buffer[total + 2] = '\0';
1069 SetLastError(0xdeadbeef);
1070 res = GetSystemDirectory(buffer, total-2);
1071 /* res includes the terminating Zero) */
1072 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1073 res, GetLastError(), buffer, total);
1076 static void test_GetWindowsDirectory(void)
1078 CHAR buffer[MAX_PATH + 4];
1079 DWORD res;
1080 DWORD total;
1082 SetLastError(0xdeadbeef);
1083 res = GetWindowsDirectory(NULL, 0);
1084 /* res includes the terminating Zero */
1085 ok(res > 0, "returned %d with %d (expected '>0')\n", res, GetLastError());
1087 total = res;
1088 /* this crashes on XP */
1089 if (0) res = GetWindowsDirectory(NULL, total);
1091 SetLastError(0xdeadbeef);
1092 res = GetWindowsDirectory(NULL, total-1);
1093 /* 95+NT: total (includes the terminating Zero)
1094 98+ME: 0 with ERROR_INVALID_PARAMETER */
1095 ok( (res == total) || (!res && (GetLastError() == ERROR_INVALID_PARAMETER)),
1096 "returned %d with %d (expected '%d' or: '0' with "
1097 "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), total);
1099 if (total > MAX_PATH) return;
1101 buffer[0] = '\0';
1102 SetLastError(0xdeadbeef);
1103 res = GetWindowsDirectory(buffer, total);
1104 /* res does not include the terminating Zero */
1105 ok( (res == (total-1)) && (buffer[0]),
1106 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1107 res, GetLastError(), buffer, total-1);
1109 buffer[0] = '\0';
1110 SetLastError(0xdeadbeef);
1111 res = GetWindowsDirectory(buffer, total + 1);
1112 /* res does not include the terminating Zero */
1113 ok( (res == (total-1)) && (buffer[0]),
1114 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1115 res, GetLastError(), buffer, total-1);
1117 memset(buffer, '#', total + 1);
1118 buffer[total + 2] = '\0';
1119 SetLastError(0xdeadbeef);
1120 res = GetWindowsDirectory(buffer, total-1);
1121 /* res includes the terminating Zero) */
1122 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1123 res, GetLastError(), buffer, total);
1125 memset(buffer, '#', total + 1);
1126 buffer[total + 2] = '\0';
1127 SetLastError(0xdeadbeef);
1128 res = GetWindowsDirectory(buffer, total-2);
1129 /* res includes the terminating Zero) */
1130 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1131 res, GetLastError(), buffer, total);
1134 static void test_NeedCurrentDirectoryForExePathA(void)
1136 /* Crashes in Windows */
1137 if (0)
1138 ok(pNeedCurrentDirectoryForExePathA(NULL), "returned FALSE for NULL\n");
1140 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", NULL);
1141 ok(pNeedCurrentDirectoryForExePathA("."), "returned FALSE for \".\"\n");
1142 ok(pNeedCurrentDirectoryForExePathA("c:\\"), "returned FALSE for \"c:\\\"\n");
1143 ok(pNeedCurrentDirectoryForExePathA("cmd.exe"), "returned FALSE for \"cmd.exe\"\n");
1145 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", "nya");
1146 ok(!pNeedCurrentDirectoryForExePathA("."), "returned TRUE for \".\"\n");
1147 ok(pNeedCurrentDirectoryForExePathA("c:\\"), "returned FALSE for \"c:\\\"\n");
1148 ok(!pNeedCurrentDirectoryForExePathA("cmd.exe"), "returned TRUE for \"cmd.exe\"\n");
1151 static void test_NeedCurrentDirectoryForExePathW(void)
1153 const WCHAR thispath[] = {'.', 0};
1154 const WCHAR fullpath[] = {'c', ':', '\\', 0};
1155 const WCHAR cmdname[] = {'c', 'm', 'd', '.', 'e', 'x', 'e', 0};
1157 /* Crashes in Windows */
1158 if (0)
1159 ok(pNeedCurrentDirectoryForExePathW(NULL), "returned FALSE for NULL\n");
1161 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", NULL);
1162 ok(pNeedCurrentDirectoryForExePathW(thispath), "returned FALSE for \".\"\n");
1163 ok(pNeedCurrentDirectoryForExePathW(fullpath), "returned FALSE for \"c:\\\"\n");
1164 ok(pNeedCurrentDirectoryForExePathW(cmdname), "returned FALSE for \"cmd.exe\"\n");
1166 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", "nya");
1167 ok(!pNeedCurrentDirectoryForExePathW(thispath), "returned TRUE for \".\"\n");
1168 ok(pNeedCurrentDirectoryForExePathW(fullpath), "returned FALSE for \"c:\\\"\n");
1169 ok(!pNeedCurrentDirectoryForExePathW(cmdname), "returned TRUE for \"cmd.exe\"\n");
1172 /* Call various path/file name retrieving APIs and check the case of
1173 * the returned drive letter. Some apps (for instance Adobe Photoshop CS3
1174 * installer) depend on the drive letter being in upper case.
1176 static void test_drive_letter_case(void)
1178 UINT ret;
1179 char buf[MAX_PATH];
1181 #define is_upper_case_letter(a) ((a) >= 'A' && (a) <= 'Z')
1183 memset(buf, 0, sizeof(buf));
1184 SetLastError(0xdeadbeef);
1185 ret = GetWindowsDirectory(buf, sizeof(buf));
1186 ok(ret, "GetWindowsDirectory error %u\n", GetLastError());
1187 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1188 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1189 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1191 /* re-use the buffer returned by GetFullPathName */
1192 buf[2] = '/';
1193 SetLastError(0xdeadbeef);
1194 ret = GetFullPathName(buf + 2, sizeof(buf), buf, NULL);
1195 ok(ret, "GetFullPathName error %u\n", GetLastError());
1196 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1197 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1198 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1200 memset(buf, 0, sizeof(buf));
1201 SetLastError(0xdeadbeef);
1202 ret = GetSystemDirectory(buf, sizeof(buf));
1203 ok(ret, "GetSystemDirectory error %u\n", GetLastError());
1204 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1205 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1206 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1208 memset(buf, 0, sizeof(buf));
1209 SetLastError(0xdeadbeef);
1210 ret = GetCurrentDirectory(sizeof(buf), buf);
1211 ok(ret, "GetCurrentDirectory error %u\n", GetLastError());
1212 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1213 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1214 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1216 /* TEMP is an environment variable, so it can't be tested for case-sensitivity */
1217 memset(buf, 0, sizeof(buf));
1218 SetLastError(0xdeadbeef);
1219 ret = GetTempPath(sizeof(buf), buf);
1220 ok(ret, "GetTempPath error %u\n", GetLastError());
1221 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1222 if (buf[0])
1224 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1225 ok(buf[strlen(buf)-1] == '\\', "Temporary path (%s) doesn't end in a slash\n", buf);
1228 memset(buf, 0, sizeof(buf));
1229 SetLastError(0xdeadbeef);
1230 ret = GetFullPathName(".", sizeof(buf), buf, NULL);
1231 ok(ret, "GetFullPathName error %u\n", GetLastError());
1232 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1233 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1234 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1236 /* re-use the buffer returned by GetFullPathName */
1237 SetLastError(0xdeadbeef);
1238 ret = GetShortPathName(buf, buf, sizeof(buf));
1239 ok(ret, "GetShortPathName error %u\n", GetLastError());
1240 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1241 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1242 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1244 if (pGetLongPathNameA)
1246 /* re-use the buffer returned by GetShortPathName */
1247 SetLastError(0xdeadbeef);
1248 ret = pGetLongPathNameA(buf, buf, sizeof(buf));
1249 ok(ret, "GetLongPathNameA error %u\n", GetLastError());
1250 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1251 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1252 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1254 #undef is_upper_case_letter
1257 START_TEST(path)
1259 CHAR origdir[MAX_PATH],curdir[MAX_PATH], curDrive, otherDrive;
1260 pGetLongPathNameA = (void*)GetProcAddress( GetModuleHandleA("kernel32.dll"),
1261 "GetLongPathNameA" );
1262 pGetLongPathNameW = (void*)GetProcAddress(GetModuleHandleA("kernel32.dll") ,
1263 "GetLongPathNameW" );
1264 pNeedCurrentDirectoryForExePathA =
1265 (void*)GetProcAddress( GetModuleHandleA("kernel32.dll"),
1266 "NeedCurrentDirectoryForExePathA" );
1267 pNeedCurrentDirectoryForExePathW =
1268 (void*)GetProcAddress( GetModuleHandleA("kernel32.dll"),
1269 "NeedCurrentDirectoryForExePathW" );
1271 test_InitPathA(curdir, &curDrive, &otherDrive);
1272 test_CurrentDirectoryA(origdir,curdir);
1273 test_PathNameA(curdir, curDrive, otherDrive);
1274 test_CleanupPathA(origdir,curdir);
1275 test_GetTempPath();
1276 test_GetLongPathNameW();
1277 test_GetShortPathNameW();
1278 test_GetSystemDirectory();
1279 test_GetWindowsDirectory();
1280 if (pNeedCurrentDirectoryForExePathA)
1282 test_NeedCurrentDirectoryForExePathA();
1284 if (pNeedCurrentDirectoryForExePathW)
1286 test_NeedCurrentDirectoryForExePathW();
1288 test_drive_letter_case();