quartz: Remove superfluous pointer casts.
[wine] / dlls / kernel32 / tests / 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 /* change to root without a trailing backslash. The function call succeeds
469    but the directory is not changed.
470 */
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");
476 }
477
478 /* Cleanup the mess we made while executing these tests */
479 static void test_CleanupPathA(CHAR *origdir, CHAR *curdir)
480 {
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");
496 }
497
498 /* This routine will test Get(Full|Short|Long)PathNameA */
499 static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive)
500 {
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;
509
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");
521
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);
530
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);
536   }
537
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");
556
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");
571   }
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");
583   }
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");
599   }
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");
611   }
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);
628   }
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);
643   }
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);
658   }
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);
673   }
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);
695   }
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);
709   }
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);
720
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);
727   }
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);
746   }
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);
757   }
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);
775
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);
783   }
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);
794   }
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);
820   }
821 }
822
823 static void test_GetTempPathA(char* tmp_dir)
824 {
825     DWORD len, len_with_null;
826     char buf[MAX_PATH];
827
828     len_with_null = strlen(tmp_dir) + 1;
829
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");
835
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.
842      */
843     len = GetTempPathA(1, buf);
844     ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
845
846     len = GetTempPathA(0, NULL);
847     ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
848
849     /* The call above gave us the buffer size that Windows thinks is needed
850      * so the next call should work
851      */
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");
856 }
857
858 static void test_GetTempPathW(char* tmp_dir)
859 {
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};
864
865     MultiByteToWideChar(CP_ACP,0,tmp_dir,-1,tmp_dirW,sizeof(tmp_dirW)/sizeof(*tmp_dirW));
866     len_with_null = lstrlenW(tmp_dirW) + 1;
867
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.
875      */
876
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");
883
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);
888
889     len = GetTempPathW(0, NULL);
890     ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
891
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");
896 }
897
898 static void test_GetTempPath(void)
899 {
900     char save_TMP[MAX_PATH];
901     char windir[MAX_PATH];
902     char buf[MAX_PATH];
903
904     if (!GetEnvironmentVariableA("TMP", save_TMP, sizeof(save_TMP))) save_TMP[0] = 0;
905
906     /* test default configuration */
907     trace("TMP=%s\n", save_TMP);
908     if (save_TMP[0])
909     {
910         strcpy(buf,save_TMP);
911         if (buf[strlen(buf)-1]!='\\')
912             strcat(buf,"\\");
913         test_GetTempPathA(buf);
914         test_GetTempPathW(buf);
915     }
916
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);
925
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);
934
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);
946
947     SetEnvironmentVariableA("TMP", save_TMP);
948 }
949
950 static void test_GetLongPathNameW(void)
951 {
952     DWORD length; 
953     WCHAR empty[MAX_PATH];
954
955     /* Not present in all windows versions */
956     if(pGetLongPathNameW) 
957     {
958     SetLastError(0xdeadbeef); 
959     length = pGetLongPathNameW(NULL,NULL,0);
960     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
961     {
962         skip("GetLongPathNameW is not implemented\n");
963         return;
964     }
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());
967
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());
973     }
974 }
975
976 static void test_GetShortPathNameW(void)
977 {
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 };
986
987     SetLastError(0xdeadbeef);
988     GetTempPathW( MAX_PATH, path );
989     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
990     {
991         skip("GetTempPathW is not implemented\n");
992         return;
993     }
994
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() );
999
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" );
1008
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" );
1015 }
1016
1017 static void test_GetSystemDirectory(void)
1018 {
1019     CHAR    buffer[MAX_PATH + 4];
1020     DWORD   res;
1021     DWORD   total;
1022
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());
1027
1028     total = res;
1029
1030     /* this crashes on XP */
1031     if (0) res = GetSystemDirectory(NULL, total);
1032
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);
1040
1041     if (total > MAX_PATH) return;
1042
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);
1050
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);
1058
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);
1066
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);
1074 }
1075
1076 static void test_GetWindowsDirectory(void)
1077 {
1078     CHAR    buffer[MAX_PATH + 4];
1079     DWORD   res;
1080     DWORD   total;
1081
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());
1086
1087     total = res;
1088     /* this crashes on XP */
1089     if (0) res = GetWindowsDirectory(NULL, total);
1090
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);
1098
1099     if (total > MAX_PATH) return;
1100
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);
1108
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);
1116
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);
1124
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);
1132 }
1133
1134 static void test_NeedCurrentDirectoryForExePathA(void)
1135 {
1136     /* Crashes in Windows */
1137     if (0)
1138         ok(pNeedCurrentDirectoryForExePathA(NULL), "returned FALSE for NULL\n");
1139
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");
1144
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");
1149 }
1150
1151 static void test_NeedCurrentDirectoryForExePathW(void)
1152 {
1153     const WCHAR thispath[] = {'.', 0};
1154     const WCHAR fullpath[] = {'c', ':', '\\', 0};
1155     const WCHAR cmdname[] = {'c', 'm', 'd', '.', 'e', 'x', 'e', 0};
1156
1157     /* Crashes in Windows */
1158     if (0)
1159         ok(pNeedCurrentDirectoryForExePathW(NULL), "returned FALSE for NULL\n");
1160
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");
1165
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");
1170 }
1171
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.
1175  */
1176 static void test_drive_letter_case(void)
1177 {
1178     UINT ret;
1179     char buf[MAX_PATH];
1180
1181 #define is_upper_case_letter(a) ((a) >= 'A' && (a) <= 'Z')
1182
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]);
1190
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]);
1199
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]);
1207
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]);
1215
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])
1223     {
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);
1226     }
1227
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]);
1235
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]);
1243
1244     if (pGetLongPathNameA)
1245     {
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]);
1253     }
1254 #undef is_upper_case_letter
1255 }
1256
1257 START_TEST(path)
1258 {
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" );
1270
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)
1281     {
1282         test_NeedCurrentDirectoryForExePathA();
1283     }
1284     if (pNeedCurrentDirectoryForExePathW)
1285     {
1286         test_NeedCurrentDirectoryForExePathW();
1287     }
1288     test_drive_letter_case();
1289 }