ole32: Fix memory leaks in the storage test.
[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 || broken(len1 == len), /* WinME */
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   sprintf(tmpstr,"%c:", *curDrive);
388   bRes = CreateDirectoryA(tmpstr,NULL);
389   ok(!bRes && (GetLastError() == ERROR_ACCESS_DENIED  ||
390                GetLastError() == ERROR_ALREADY_EXISTS),
391      "CreateDirectoryA(\"%s\" should have failed (%d)\n", tmpstr, GetLastError());
392   sprintf(tmpstr,"%c:\\", *curDrive);
393   bRes = CreateDirectoryA(tmpstr,NULL);
394   ok(!bRes && (GetLastError() == ERROR_ACCESS_DENIED  ||
395                GetLastError() == ERROR_ALREADY_EXISTS),
396      "CreateDirectoryA(\"%s\" should have failed (%d)\n", tmpstr, GetLastError());
397   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,SHORTFILE);
398   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
399                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
400   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
401   ok(CloseHandle(hndl),"CloseHandle failed\n");
402   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,LONGFILE);
403   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
404                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
405   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
406   ok(CloseHandle(hndl),"CloseHandle failed\n");
407   sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,SHORTFILE);
408   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
409                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
410   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
411   ok(CloseHandle(hndl),"CloseHandle failed\n");
412   sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,LONGFILE);
413   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
414                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
415   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
416   ok(CloseHandle(hndl),"CloseHandle failed\n");
417 }
418
419 /* Test GetCurrentDirectory & SetCurrentDirectory */
420 static void test_CurrentDirectoryA(CHAR *origdir, CHAR *newdir)
421 {
422   CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
423   DWORD len,len1;
424 /* Save the original directory, so that we can return to it at the end
425    of the test
426 */
427   len=GetCurrentDirectoryA(MAX_PATH,origdir);
428   ok(len!=0 && len < MAX_PATH,"GetCurrentDirectoryA failed\n");
429 /* Make sure that CetCurrentDirectoryA doesn't overwrite the buffer when the
430    buffer size is too small to hold the current directory
431 */
432   lstrcpyA(tmpstr,"aaaaaaa");
433   len1=GetCurrentDirectoryA(len,tmpstr);
434   ok(len1==len+1, "GetCurrentDirectoryA returned %d instead of %d\n",len1,len+1);
435   ok(lstrcmpiA(tmpstr,"aaaaaaa")==0,
436      "GetCurrentDirectoryA should not have modified the buffer\n");
437 /* SetCurrentDirectoryA shouldn't care whether the string has a
438    trailing '\\' or not
439 */
440   sprintf(tmpstr,"%s\\",newdir);
441   test_setdir(origdir,tmpstr,newdir,1,"check 1");
442   test_setdir(origdir,newdir,NULL,1,"check 2");
443 /* Set the directory to the working area.  We just tested that this works,
444    so why check it again.
445 */
446   SetCurrentDirectoryA(newdir);
447 /* Check that SetCurrentDirectory fails when a nonexistent dir is specified */
448   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_SHORT);
449   test_setdir(newdir,tmpstr,NULL,0,"check 3");
450 /* Check that SetCurrentDirectory fails for a nonexistent lond directory */
451   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_LONG);
452   test_setdir(newdir,tmpstr,NULL,0,"check 4");
453 /* Check that SetCurrentDirectory passes with a long directory */
454   sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
455   test_setdir(newdir,tmpstr,NULL,1,"check 5");
456 /* Check that SetCurrentDirectory passes with a short relative directory */
457   sprintf(tmpstr,"%s",SHORTDIR);
458   sprintf(tmpstr1,"%s\\%s",newdir,SHORTDIR);
459   test_setdir(newdir,tmpstr,tmpstr1,1,"check 6");
460 /* starting with a '.' */
461   sprintf(tmpstr,".\\%s",SHORTDIR);
462   test_setdir(newdir,tmpstr,tmpstr1,1,"check 7");
463 /* Check that SetCurrentDirectory passes with a short relative directory */
464   sprintf(tmpstr,"%s",LONGDIR);
465   sprintf(tmpstr1,"%s\\%s",newdir,LONGDIR);
466   test_setdir(newdir,tmpstr,tmpstr1,1,"check 8");
467 /* starting with a '.' */
468   sprintf(tmpstr,".\\%s",LONGDIR);
469   test_setdir(newdir,tmpstr,tmpstr1,1,"check 9");
470 /* change to root without a trailing backslash. The function call succeeds
471    but the directory is not changed.
472 */
473   sprintf(tmpstr, "%c:", newdir[0]);
474   test_setdir(newdir,tmpstr,newdir,1,"check 10");
475 /* works however with a trailing backslash */
476   sprintf(tmpstr, "%c:\\", newdir[0]);
477   test_setdir(newdir,tmpstr,NULL,1,"check 11");
478 }
479
480 /* Cleanup the mess we made while executing these tests */
481 static void test_CleanupPathA(CHAR *origdir, CHAR *curdir)
482 {
483   CHAR tmpstr[MAX_PATH];
484   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
485   ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
486   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,LONGFILE);
487   ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
488   sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,SHORTFILE);
489   ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
490   sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
491   ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
492   sprintf(tmpstr,"%s\\%s",curdir,SHORTDIR);
493   ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
494   sprintf(tmpstr,"%s\\%s",curdir,LONGDIR);
495   ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
496   ok(SetCurrentDirectoryA(origdir),"SetCurrentDirectoryA failed\n");
497   ok(RemoveDirectoryA(curdir),"RemoveDirectoryA failed\n");
498 }
499
500 /* This routine will test Get(Full|Short|Long)PathNameA */
501 static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive)
502 {
503   CHAR curdir_short[MAX_PATH],
504        longdir_short[MAX_PATH];
505   CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH],tmpstr2[MAX_PATH];
506   LPSTR strptr;                 /*ptr to the filename portion of the path */
507   DWORD len;
508   INT i;
509   CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
510   SLpassfail passfail;
511
512 /* Get the short form of the current directory */
513   ok((len=GetShortPathNameA(curdir,curdir_short,MAX_PATH)),
514      "GetShortPathNameA failed\n");
515   ok(!HAS_TRAIL_SLASH_A(curdir_short),
516      "GetShortPathNameA should not have a trailing \\\n");
517 /* Get the short form of the absolute-path to LONGDIR */
518   sprintf(tmpstr,"%s\\%s",curdir_short,LONGDIR);
519   ok((len=GetShortPathNameA(tmpstr,longdir_short,MAX_PATH)),
520      "GetShortPathNameA failed\n");
521   ok(lstrcmpiA(longdir_short+(len-1),"\\")!=0,
522      "GetShortPathNameA should not have a trailing \\\n");
523
524   if (pGetLongPathNameA) {
525     DWORD rc1,rc2;
526     sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
527     rc1=(*pGetLongPathNameA)(tmpstr,NULL,0);
528     rc2=(*pGetLongPathNameA)(curdir,NULL,0);
529     ok((rc1-strlen(tmpstr))==(rc2-strlen(curdir)),
530        "GetLongPathNameA: wrong return code, %d instead of %d\n",
531        rc1, lstrlenA(tmpstr)+1);
532
533     sprintf(dir,"%c:",curDrive);
534     rc1=(*pGetLongPathNameA)(dir,tmpstr,sizeof(tmpstr));
535     ok(strcmp(dir,tmpstr)==0,
536        "GetLongPathNameA: returned '%s' instead of '%s' (rc=%d)\n",
537        tmpstr,dir,rc1);
538   }
539
540 /* Check the cases where both file and directory exist first */
541 /* Start with a 8.3 directory, 8.3 filename */
542   test_ValidPathA(curdir,SHORTDIR,SHORTFILE,tmpstr,NULL,"test1");
543   sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,SHORTFILE);
544   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
545      "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
546 /* Now try a 8.3 directory, long file name */
547   test_ValidPathA(curdir,SHORTDIR,LONGFILE,tmpstr,NULL,"test2");
548   sprintf(tmpstr1,"%s\\%s",curdir_short,SHORTDIR);
549   test_LongtoShortA(tmpstr,tmpstr1,"PAT","test2");
550 /* Next is a long directory, 8.3 file */
551   test_ValidPathA(curdir,LONGDIR,SHORTFILE,tmpstr,NULL,"test3");
552   sprintf(tmpstr1,"%s\\%s",longdir_short,SHORTFILE);
553   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
554      "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
555 /*Lastly a long directory, long file */
556   test_ValidPathA(curdir,LONGDIR,LONGFILE,tmpstr,NULL,"test4");
557   test_LongtoShortA(tmpstr,longdir_short,"PAT","test4");
558
559 /* Now check all of the invalid file w/ valid directory combinations */
560 /* Start with a 8.3 directory, 8.3 filename */
561   test_ValidPathA(curdir,SHORTDIR,NONFILE_SHORT,tmpstr,&passfail,"test5");
562   sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,NONFILE_SHORT);
563   ok((passfail.shortlen==0 &&
564       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
565        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
566      (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
567      "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
568      passfail.shortlen,passfail.shorterror,tmpstr);
569   if(pGetLongPathNameA) {
570     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
571     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
572        "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
573   }
574 /* Now try a 8.3 directory, long file name */
575   test_ValidPathA(curdir,SHORTDIR,NONFILE_LONG,tmpstr,&passfail,"test6");
576   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
577   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
578      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
579      !passfail.shorterror,
580      "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
581   if(pGetLongPathNameA) {
582     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
583     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
584        "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
585   }
586 /* Next is a long directory, 8.3 file */
587   test_ValidPathA(curdir,LONGDIR,NONFILE_SHORT,tmpstr,&passfail,"test7");
588   sprintf(tmpstr2,"%s\\%s",curdir_short,LONGDIR);
589   GetShortPathNameA(tmpstr2,tmpstr1,MAX_PATH);
590   strcat(tmpstr1,"\\" NONFILE_SHORT);
591   ok((passfail.shortlen==0 &&
592       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
593        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
594      (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
595      "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
596      passfail.shortlen,passfail.shorterror,tmpstr);
597   if(pGetLongPathNameA) {
598     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
599     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
600       "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
601   }
602 /*Lastly a long directory, long file */
603   test_ValidPathA(curdir,LONGDIR,NONFILE_LONG,tmpstr,&passfail,"test8");
604   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
605   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
606      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
607      !passfail.shorterror,
608      "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
609   if(pGetLongPathNameA) {
610     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
611     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
612        "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
613   }
614 /* Now try again with directories that don't exist */
615 /* 8.3 directory, 8.3 filename */
616   test_ValidPathA(curdir,NONDIR_SHORT,SHORTFILE,tmpstr,&passfail,"test9");
617   sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,NONDIR_SHORT,SHORTFILE);
618   ok((passfail.shortlen==0 &&
619       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
620        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
621      (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
622      "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
623      passfail.shortlen,passfail.shorterror,tmpstr);
624   if(pGetLongPathNameA) {
625     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
626     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
627        passfail.longerror==ERROR_FILE_NOT_FOUND,
628        "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
629        passfail.longerror);
630   }
631 /* Now try a 8.3 directory, long file name */
632   test_ValidPathA(curdir,NONDIR_SHORT,LONGFILE,tmpstr,&passfail,"test10");
633   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
634   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
635      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
636      !passfail.shorterror,
637      "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
638       passfail.shorterror);
639   if(pGetLongPathNameA) {
640     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
641     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
642        passfail.longerror==ERROR_FILE_NOT_FOUND,
643        "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
644        passfail.longerror);
645   }
646 /* Next is a long directory, 8.3 file */
647   test_ValidPathA(curdir,NONDIR_LONG,SHORTFILE,tmpstr,&passfail,"test11");
648   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
649   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
650      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
651      !passfail.shorterror,
652      "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
653       passfail.shorterror);
654   if(pGetLongPathNameA) {
655     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
656     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
657        passfail.longerror==ERROR_FILE_NOT_FOUND,
658        "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
659        passfail.longerror);
660   }
661 /*Lastly a long directory, long file */
662   test_ValidPathA(curdir,NONDIR_LONG,LONGFILE,tmpstr,&passfail,"test12");
663   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
664   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
665      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
666      !passfail.shorterror,
667      "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
668       passfail.shorterror);
669   if(pGetLongPathNameA) {
670     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
671     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
672        passfail.longerror==ERROR_FILE_NOT_FOUND,
673        "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
674        passfail.longerror);
675   }
676 /* Next try directories ending with '\\' */
677 /* Existing Directories */
678   sprintf(tmpstr,"%s\\",SHORTDIR);
679   test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test13");
680   sprintf(tmpstr,"%s\\",LONGDIR);
681   test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test14");
682 /* Nonexistent directories */
683   sprintf(tmpstr,"%s\\",NONDIR_SHORT);
684   test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test15");
685   sprintf(tmpstr2,"%s\\%s",curdir_short,tmpstr);
686   ok((passfail.shortlen==0 &&
687       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
688        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
689      (passfail.shortlen==strlen(tmpstr2) && lstrcmpiA(tmpstr1,tmpstr2)==0),
690      "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
691      passfail.shortlen,passfail.shorterror,tmpstr);
692   if(pGetLongPathNameA) {
693     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
694     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
695        "GetLongPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
696        passfail.longerror);
697   }
698   sprintf(tmpstr,"%s\\",NONDIR_LONG);
699   test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test16");
700   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
701   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
702      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
703      !passfail.shorterror,
704      "GetShortPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
705       passfail.shorterror);
706   if(pGetLongPathNameA) {
707     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
708     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
709        "GetLongPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
710        passfail.longerror);
711   }
712 /* Test GetFullPathNameA with drive letters */
713   if( curDrive != NOT_A_VALID_DRIVE) {
714     sprintf(tmpstr,"%c:",curdir[0]);
715     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr2,&strptr),
716        "GetFullPathNameA(%c:) failed\n", curdir[0]);
717     GetCurrentDirectoryA(MAX_PATH,tmpstr);
718     sprintf(tmpstr1,"%s\\",tmpstr);
719     ok(lstrcmpiA(tmpstr,tmpstr2)==0 || lstrcmpiA(tmpstr1,tmpstr2)==0,
720        "GetFullPathNameA(%c:) returned '%s' instead of '%s' or '%s'\n",
721        curdir[0],tmpstr2,tmpstr,tmpstr1);
722
723     sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
724     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
725     ok(lstrcmpiA(tmpstr,tmpstr1)==0,
726        "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
727     ok(lstrcmpiA(SHORTFILE,strptr)==0,
728        "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
729   }
730 /* Without a leading slash, insert the current directory if on the current drive */
731   sprintf(tmpstr,"%c:%s\\%s",curdir[0],SHORTDIR,SHORTFILE);
732   ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
733   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
734   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
735       "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
736   ok(lstrcmpiA(SHORTFILE,strptr)==0,
737       "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
738 /* Otherwise insert the missing leading slash */
739   if( otherDrive != NOT_A_VALID_DRIVE) {
740     /* FIXME: this test assumes that current directory on other drive is root */
741     sprintf(tmpstr,"%c:%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
742     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed for %s\n", tmpstr);
743     sprintf(tmpstr,"%c:\\%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
744     ok(lstrcmpiA(tmpstr,tmpstr1)==0,
745        "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
746     ok(lstrcmpiA(SHORTFILE,strptr)==0,
747        "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
748   }
749 /* Xilinx tools like to mix Unix and DOS formats, which Windows handles fine.
750    So test for them. */
751   if( curDrive != NOT_A_VALID_DRIVE) {
752     sprintf(tmpstr,"%c:/%s\\%s",curDrive,SHORTDIR,SHORTFILE);
753     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
754     sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
755     ok(lstrcmpiA(tmpstr,tmpstr1)==0,
756        "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
757     ok(lstrcmpiA(SHORTFILE,strptr)==0,
758        "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
759   }
760 /**/
761   sprintf(tmpstr,"%c:%s/%s",curdir[0],SHORTDIR,SHORTFILE);
762   ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
763   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
764   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
765       "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
766   ok(lstrcmpiA(SHORTFILE,strptr)==0,
767       "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
768 /* Windows will insert a drive letter in front of an absolute UNIX path */
769   sprintf(tmpstr,"/%s/%s",SHORTDIR,SHORTFILE);
770   ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
771   sprintf(tmpstr,"%c:\\%s\\%s",*tmpstr1,SHORTDIR,SHORTFILE);
772   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
773      "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
774 /* This passes in Wine because it still contains the pointer from the previous test */
775   ok(lstrcmpiA(SHORTFILE,strptr)==0,
776       "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
777
778 /* Now try some relative paths */
779   ok(GetShortPathNameA(LONGDIR,tmpstr,MAX_PATH),"GetShortPathNameA failed\n");
780   test_SplitShortPathA(tmpstr,dir,eight,three);
781   if(pGetLongPathNameA) {
782     ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
783     ok(lstrcmpiA(tmpstr1,LONGDIR)==0,
784        "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,LONGDIR);
785   }
786   sprintf(tmpstr,".\\%s",LONGDIR);
787   ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed\n");
788   test_SplitShortPathA(tmpstr1,dir,eight,three);
789   ok(lstrcmpiA(dir,".")==0 || dir[0]=='\0',
790      "GetShortPathNameA did not keep relative directory [%s]\n",tmpstr1);
791   if(pGetLongPathNameA) {
792     ok(pGetLongPathNameA(tmpstr1,tmpstr1,MAX_PATH),"GetLongPathNameA failed %s\n",
793        tmpstr);
794     ok(lstrcmpiA(tmpstr1,tmpstr)==0,
795        "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
796   }
797 /* Check out Get*PathNameA on some funny characters */
798   for(i=0;i<lstrlenA(funny_chars);i++) {
799     INT valid;
800     valid=(is_char_ok[i]=='0') ? 0 : 1;
801     sprintf(tmpstr1,"check%d-1",i);
802     sprintf(tmpstr,"file%c000.ext",funny_chars[i]);
803     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
804     sprintf(tmpstr1,"check%d-2",i);
805     sprintf(tmpstr,"file000.e%ct",funny_chars[i]);
806     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
807     sprintf(tmpstr1,"check%d-3",i);
808     sprintf(tmpstr,"%cfile000.ext",funny_chars[i]);
809     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
810     sprintf(tmpstr1,"check%d-4",i);
811     sprintf(tmpstr,"file000%c.ext",funny_chars[i]);
812     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
813     sprintf(tmpstr1,"check%d-5",i);
814     sprintf(tmpstr,"Long %c File",funny_chars[i]);
815     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
816     sprintf(tmpstr1,"check%d-6",i);
817     sprintf(tmpstr,"%c Long File",funny_chars[i]);
818     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
819     sprintf(tmpstr1,"check%d-7",i);
820     sprintf(tmpstr,"Long File %c",funny_chars[i]);
821     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
822   }
823 }
824
825 static void test_GetTempPathA(char* tmp_dir)
826 {
827     DWORD len, len_with_null;
828     char buf[MAX_PATH];
829
830     len_with_null = strlen(tmp_dir) + 1;
831
832     lstrcpyA(buf, "foo");
833     len = GetTempPathA(MAX_PATH, buf);
834     ok(len <= MAX_PATH, "should fit into MAX_PATH\n");
835     ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
836     ok(len == strlen(buf), "returned length should be equal to the length of string\n");
837
838     /* Some versions of Windows touch the buffer, some don't so we don't
839      * test that. Also, NT sometimes exaggerates the required buffer size
840      * so we cannot test for an exact match. Finally, the
841      * 'len_with_null - 1' case is so buggy on Windows it's not testable.
842      * For instance in some cases Win98 returns len_with_null - 1 instead
843      * of len_with_null.
844      */
845     len = GetTempPathA(1, buf);
846     ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
847
848     len = GetTempPathA(0, NULL);
849     ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
850
851     /* The call above gave us the buffer size that Windows thinks is needed
852      * so the next call should work
853      */
854     lstrcpyA(buf, "foo");
855     len = GetTempPathA(len, buf);
856     ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
857     ok(len == strlen(buf), "returned length should be equal to the length of string\n");
858 }
859
860 static void test_GetTempPathW(char* tmp_dir)
861 {
862     DWORD len, len_with_null;
863     WCHAR buf[MAX_PATH];
864     WCHAR tmp_dirW[MAX_PATH];
865     static const WCHAR fooW[] = {'f','o','o',0};
866
867     MultiByteToWideChar(CP_ACP,0,tmp_dir,-1,tmp_dirW,sizeof(tmp_dirW)/sizeof(*tmp_dirW));
868     len_with_null = lstrlenW(tmp_dirW) + 1;
869
870     /* This one is different from ANSI version: ANSI version doesn't
871      * touch the buffer, unicode version usually truncates the buffer
872      * to zero size. NT still exaggerates the required buffer size
873      * sometimes so we cannot test for an exact match. Finally, the
874      * 'len_with_null - 1' case is so buggy on Windows it's not testable.
875      * For instance on NT4 it will sometimes return a path without the
876      * trailing '\\' and sometimes return an error.
877      */
878
879     lstrcpyW(buf, fooW);
880     len = GetTempPathW(MAX_PATH, buf);
881     if (len == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
882     {
883         win_skip("GetTempPathW is not available\n");
884         return;
885     }
886     ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
887     ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
888
889     lstrcpyW(buf, fooW);
890     len = GetTempPathW(1, buf);
891     ok(buf[0] == 0, "unicode version should truncate the buffer to zero size\n");
892     ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
893
894     len = GetTempPathW(0, NULL);
895     ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
896
897     lstrcpyW(buf, fooW);
898     len = GetTempPathW(len, buf);
899     ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
900     ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
901 }
902
903 static void test_GetTempPath(void)
904 {
905     char save_TMP[MAX_PATH];
906     char windir[MAX_PATH];
907     char buf[MAX_PATH];
908
909     if (!GetEnvironmentVariableA("TMP", save_TMP, sizeof(save_TMP))) save_TMP[0] = 0;
910
911     /* test default configuration */
912     trace("TMP=%s\n", save_TMP);
913     if (save_TMP[0])
914     {
915         strcpy(buf,save_TMP);
916         if (buf[strlen(buf)-1]!='\\')
917             strcat(buf,"\\");
918         test_GetTempPathA(buf);
919         test_GetTempPathW(buf);
920     }
921
922     /* TMP=C:\WINDOWS */
923     GetWindowsDirectoryA(windir, sizeof(windir));
924     SetEnvironmentVariableA("TMP", windir);
925     GetEnvironmentVariableA("TMP", buf, sizeof(buf));
926     trace("TMP=%s\n", buf);
927     strcat(windir,"\\");
928     test_GetTempPathA(windir);
929     test_GetTempPathW(windir);
930
931     /* TMP=C:\ */
932     GetWindowsDirectoryA(windir, sizeof(windir));
933     windir[3] = 0;
934     SetEnvironmentVariableA("TMP", windir);
935     GetEnvironmentVariableA("TMP", buf, sizeof(buf));
936     trace("TMP=%s\n", buf);
937     test_GetTempPathA(windir);
938     test_GetTempPathW(windir);
939
940     /* TMP=C: i.e. use current working directory of the specified drive */
941     GetWindowsDirectoryA(windir, sizeof(windir));
942     SetCurrentDirectoryA(windir);
943     windir[2] = 0;
944     SetEnvironmentVariableA("TMP", windir);
945     GetEnvironmentVariableA("TMP", buf, sizeof(buf));
946     trace("TMP=%s\n", buf);
947     GetWindowsDirectoryA(windir, sizeof(windir));
948     strcat(windir,"\\");
949     test_GetTempPathA(windir);
950     test_GetTempPathW(windir);
951
952     SetEnvironmentVariableA("TMP", save_TMP);
953 }
954
955 static void test_GetLongPathNameA(void)
956 {
957     DWORD length, explength, hostsize;
958     char tempfile[MAX_PATH];
959     char longpath[MAX_PATH];
960     char unc_prefix[MAX_PATH];
961     char unc_short[MAX_PATH], unc_long[MAX_PATH];
962     char temppath[MAX_PATH], temppath2[MAX_PATH];
963     HANDLE file;
964
965     if (!pGetLongPathNameA)
966         return;
967
968     GetTempPathA(MAX_PATH, tempfile);
969     lstrcatA(tempfile, "longfilename.longext");
970
971     file = CreateFileA(tempfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
972     CloseHandle(file);
973
974     /* Test a normal path with a small buffer size */
975     memset(temppath, 0, MAX_PATH);
976     length = pGetLongPathNameA(tempfile, temppath, 4);
977     /* We have a failure so length should be the minumum plus the terminating '0'  */
978     ok(length >= lstrlen(tempfile) + 1, "Wrong length\n");
979     ok(temppath[0] == 0, "Buffer should not have been touched\n");
980
981     /* Some UNC syntax tests */
982
983     memset(temppath, 0, MAX_PATH);
984     memset(temppath2, 0, MAX_PATH);
985     lstrcpyA(temppath2, "\\\\?\\");
986     lstrcatA(temppath2, tempfile);
987     explength = length + 4;
988
989     SetLastError(0xdeadbeef);
990     length = pGetLongPathNameA(temppath2, NULL, 0);
991     if (length == 0 && GetLastError() == ERROR_BAD_NET_NAME)
992     {
993         win_skip("UNC syntax tests don't work on Win98/WinMe\n");
994         DeleteFileA(tempfile);
995         return;
996     }
997     ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
998
999     length = pGetLongPathNameA(temppath2, NULL, MAX_PATH);
1000     ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1001
1002     length = pGetLongPathNameA(temppath2, temppath, 4);
1003     ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1004     ok(temppath[0] == 0, "Buffer should not have been touched\n");
1005
1006     /* Now an UNC path with the computername */
1007     lstrcpyA(unc_prefix, "\\\\");
1008     hostsize = sizeof(unc_prefix) - 2;
1009     GetComputerName(unc_prefix + 2, &hostsize);
1010     lstrcatA(unc_prefix, "\\");
1011
1012     /* Create a short syntax for the whole unc path */
1013     memset(unc_short, 0, MAX_PATH);
1014     GetShortPathNameA(tempfile, temppath, MAX_PATH);
1015     lstrcpyA(unc_short, unc_prefix);
1016     unc_short[lstrlenA(unc_short)] = temppath[0];
1017     lstrcatA(unc_short, "$\\");
1018     lstrcatA(unc_short, strchr(temppath, '\\') + 1);
1019
1020     /* Create a long syntax for reference */
1021     memset(longpath, 0, MAX_PATH);
1022     pGetLongPathNameA(tempfile, temppath, MAX_PATH);
1023     lstrcpyA(longpath, unc_prefix);
1024     longpath[lstrlenA(longpath)] = temppath[0];
1025     lstrcatA(longpath, "$\\");
1026     lstrcatA(longpath, strchr(temppath, '\\') + 1);
1027
1028     /* NULL test */
1029     SetLastError(0xdeadbeef);
1030     length = pGetLongPathNameA(unc_short, NULL, 0);
1031     if (length == 0 && GetLastError() == ERROR_BAD_NETPATH)
1032     {
1033         /* Seen on Window XP Home */
1034         win_skip("UNC with computername is not supported\n");
1035         DeleteFileA(tempfile);
1036         return;
1037     }
1038     explength = lstrlenA(longpath) + 1;
1039     todo_wine
1040     ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1041
1042     length = pGetLongPathNameA(unc_short, NULL, MAX_PATH);
1043     todo_wine
1044     ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1045
1046     memset(unc_long, 0, MAX_PATH);
1047     length = pGetLongPathNameA(unc_short, unc_long, lstrlenA(unc_short));
1048     /* length will include terminating '0' on failure */
1049     todo_wine
1050     ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1051     ok(unc_long[0] == 0, "Buffer should not have been touched\n");
1052
1053     memset(unc_long, 0, MAX_PATH);
1054     length = pGetLongPathNameA(unc_short, unc_long, length);
1055     /* length doesn't include terminating '0' on success */
1056     explength--;
1057     todo_wine
1058     {
1059     ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1060     ok(!lstrcmpiA(unc_long, longpath), "Expected (%s), got (%s)\n", longpath, unc_long);
1061     }
1062
1063     DeleteFileA(tempfile);
1064 }
1065
1066 static void test_GetLongPathNameW(void)
1067 {
1068     DWORD length, expanded;
1069     BOOL ret;
1070     HANDLE file;
1071     WCHAR empty[MAX_PATH];
1072     WCHAR tempdir[MAX_PATH], name[200];
1073     WCHAR dirpath[4 + MAX_PATH + 200]; /* To ease removal */
1074     WCHAR shortpath[4 + MAX_PATH + 200 + 1 + 200];
1075     static const WCHAR prefix[] = { '\\','\\','?','\\', 0};
1076     static const WCHAR backslash[] = { '\\', 0};
1077     static const WCHAR letterX[] = { 'X', 0};
1078
1079     if (!pGetLongPathNameW)
1080         return;
1081
1082     SetLastError(0xdeadbeef); 
1083     length = pGetLongPathNameW(NULL,NULL,0);
1084     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1085     {
1086         win_skip("GetLongPathNameW is not implemented\n");
1087         return;
1088     }
1089     ok(0==length,"GetLongPathNameW returned %d but expected 0\n",length);
1090     ok(GetLastError()==ERROR_INVALID_PARAMETER,"GetLastError returned %d but expected ERROR_INVALID_PARAMETER\n",GetLastError());
1091
1092     SetLastError(0xdeadbeef); 
1093     empty[0]=0;
1094     length = pGetLongPathNameW(empty,NULL,0);
1095     ok(0==length,"GetLongPathNameW returned %d but expected 0\n",length);
1096     ok(GetLastError()==ERROR_PATH_NOT_FOUND,"GetLastError returned %d but expected ERROR_PATH_NOT_FOUND\n",GetLastError());
1097
1098     /* Create a long path name. The path needs to exist for these tests to
1099      * succeed so we need the "\\?\" prefix when creating directories and
1100      * files.
1101      */
1102     name[0] = 0;
1103     while (lstrlenW(name) < (sizeof(name)/sizeof(WCHAR) - 1))
1104         lstrcatW(name, letterX);
1105
1106     GetTempPathW(MAX_PATH, tempdir);
1107
1108     lstrcpyW(shortpath, prefix);
1109     lstrcatW(shortpath, tempdir);
1110     lstrcatW(shortpath, name);
1111     lstrcpyW(dirpath, shortpath);
1112     ret = CreateDirectoryW(shortpath, NULL);
1113     ok(ret, "Could not create the temporary directory : %d\n", GetLastError());
1114     lstrcatW(shortpath, backslash);
1115     lstrcatW(shortpath, name);
1116
1117     /* Path does not exist yet and we know it overruns MAX_PATH */
1118
1119     /* No prefix */
1120     SetLastError(0xdeadbeef);
1121     length = pGetLongPathNameW(shortpath + 4, NULL, 0);
1122     ok(length == 0, "Expected 0, got %d\n", length);
1123     todo_wine
1124     ok(GetLastError() == ERROR_PATH_NOT_FOUND,
1125        "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
1126     /* With prefix */
1127     SetLastError(0xdeadbeef);
1128     length = pGetLongPathNameW(shortpath, NULL, 0);
1129     todo_wine
1130     {
1131     ok(length == 0, "Expected 0, got %d\n", length);
1132     ok(GetLastError() == ERROR_FILE_NOT_FOUND,
1133        "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
1134     }
1135
1136     file = CreateFileW(shortpath, GENERIC_READ|GENERIC_WRITE, 0, NULL,
1137                        CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1138     ok(file != INVALID_HANDLE_VALUE,
1139        "Could not create the temporary file : %d.\n", GetLastError());
1140     CloseHandle(file);
1141
1142     /* Path exists */
1143
1144     /* No prefix */
1145     SetLastError(0xdeadbeef);
1146     length = pGetLongPathNameW(shortpath + 4, NULL, 0);
1147     todo_wine
1148     {
1149     ok(length == 0, "Expected 0, got %d\n", length);
1150     ok(GetLastError() == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
1151     }
1152     /* With prefix */
1153     expanded = 4 + (pGetLongPathNameW(tempdir, NULL, 0) - 1) + lstrlenW(name) + 1 + lstrlenW(name) + 1;
1154     SetLastError(0xdeadbeef);
1155     length = pGetLongPathNameW(shortpath, NULL, 0);
1156     ok(length == expanded, "Expected %d, got %d\n", expanded, length);
1157
1158     /* NULL buffer with length crashes on Windows */
1159     if (0)
1160     length = pGetLongPathNameW(shortpath, NULL, 20);
1161
1162     ok(DeleteFileW(shortpath), "Could not delete temporary file\n");
1163     ok(RemoveDirectoryW(dirpath), "Could not delete temporary directory\n");
1164 }
1165
1166 static void test_GetShortPathNameW(void)
1167 {
1168     WCHAR test_path[] = { 'L', 'o', 'n', 'g', 'D', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 'N', 'a', 'm', 'e',  0 };
1169     WCHAR path[MAX_PATH];
1170     WCHAR short_path[MAX_PATH];
1171     DWORD length;
1172     HANDLE file;
1173     int ret;
1174     WCHAR name[] = { 't', 'e', 's', 't', 0 };
1175     WCHAR backSlash[] = { '\\', 0 };
1176
1177     SetLastError(0xdeadbeef);
1178     GetTempPathW( MAX_PATH, path );
1179     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1180     {
1181         win_skip("GetTempPathW is not implemented\n");
1182         return;
1183     }
1184
1185     lstrcatW( path, test_path );
1186     lstrcatW( path, backSlash );
1187     ret = CreateDirectoryW( path, NULL );
1188     ok( ret, "Directory was not created. LastError = %d\n", GetLastError() );
1189
1190     /* Starting a main part of test */
1191     length = GetShortPathNameW( path, short_path, 0 );
1192     ok( length, "GetShortPathNameW returned 0.\n" );
1193     ret = GetShortPathNameW( path, short_path, length );
1194     ok( ret, "GetShortPathNameW returned 0.\n" );
1195     lstrcatW( short_path, name );
1196     file = CreateFileW( short_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1197     ok( file != INVALID_HANDLE_VALUE, "File was not created.\n" );
1198
1199     /* End test */
1200     CloseHandle( file );
1201     ret = DeleteFileW( short_path );
1202     ok( ret, "Cannot delete file.\n" );
1203     ret = RemoveDirectoryW( path );
1204     ok( ret, "Cannot delete directory.\n" );
1205 }
1206
1207 static void test_GetSystemDirectory(void)
1208 {
1209     CHAR    buffer[MAX_PATH + 4];
1210     DWORD   res;
1211     DWORD   total;
1212
1213     SetLastError(0xdeadbeef);
1214     res = GetSystemDirectory(NULL, 0);
1215     /* res includes the terminating Zero */
1216     ok(res > 0, "returned %d with %d (expected '>0')\n", res, GetLastError());
1217
1218     total = res;
1219
1220     /* this crashes on XP */
1221     if (0) res = GetSystemDirectory(NULL, total);
1222
1223     SetLastError(0xdeadbeef);
1224     res = GetSystemDirectory(NULL, total-1);
1225     /* 95+NT: total (includes the terminating Zero)
1226        98+ME: 0 with ERROR_INVALID_PARAMETER */
1227     ok( (res == total) || (!res && (GetLastError() == ERROR_INVALID_PARAMETER)),
1228         "returned %d with %d (expected '%d' or: '0' with "
1229         "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), total);
1230
1231     if (total > MAX_PATH) return;
1232
1233     buffer[0] = '\0';
1234     SetLastError(0xdeadbeef);
1235     res = GetSystemDirectory(buffer, total);
1236     /* res does not include the terminating Zero */
1237     ok( (res == (total-1)) && (buffer[0]),
1238         "returned %d with %d and '%s' (expected '%d' and a string)\n",
1239         res, GetLastError(), buffer, total-1);
1240
1241     buffer[0] = '\0';
1242     SetLastError(0xdeadbeef);
1243     res = GetSystemDirectory(buffer, total + 1);
1244     /* res does not include the terminating Zero */
1245     ok( (res == (total-1)) && (buffer[0]),
1246         "returned %d with %d and '%s' (expected '%d' and a string)\n",
1247         res, GetLastError(), buffer, total-1);
1248
1249     memset(buffer, '#', total + 1);
1250     buffer[total + 2] = '\0';
1251     SetLastError(0xdeadbeef);
1252     res = GetSystemDirectory(buffer, total-1);
1253     /* res includes the terminating Zero) */
1254     ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1255         res, GetLastError(), buffer, total);
1256
1257     memset(buffer, '#', total + 1);
1258     buffer[total + 2] = '\0';
1259     SetLastError(0xdeadbeef);
1260     res = GetSystemDirectory(buffer, total-2);
1261     /* res includes the terminating Zero) */
1262     ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1263         res, GetLastError(), buffer, total);
1264 }
1265
1266 static void test_GetWindowsDirectory(void)
1267 {
1268     CHAR    buffer[MAX_PATH + 4];
1269     DWORD   res;
1270     DWORD   total;
1271
1272     SetLastError(0xdeadbeef);
1273     res = GetWindowsDirectory(NULL, 0);
1274     /* res includes the terminating Zero */
1275     ok(res > 0, "returned %d with %d (expected '>0')\n", res, GetLastError());
1276
1277     total = res;
1278     /* this crashes on XP */
1279     if (0) res = GetWindowsDirectory(NULL, total);
1280
1281     SetLastError(0xdeadbeef);
1282     res = GetWindowsDirectory(NULL, total-1);
1283     /* 95+NT: total (includes the terminating Zero)
1284        98+ME: 0 with ERROR_INVALID_PARAMETER */
1285     ok( (res == total) || (!res && (GetLastError() == ERROR_INVALID_PARAMETER)),
1286         "returned %d with %d (expected '%d' or: '0' with "
1287         "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), total);
1288
1289     if (total > MAX_PATH) return;
1290
1291     buffer[0] = '\0';
1292     SetLastError(0xdeadbeef);
1293     res = GetWindowsDirectory(buffer, total);
1294     /* res does not include the terminating Zero */
1295     ok( (res == (total-1)) && (buffer[0]),
1296         "returned %d with %d and '%s' (expected '%d' and a string)\n",
1297         res, GetLastError(), buffer, total-1);
1298
1299     buffer[0] = '\0';
1300     SetLastError(0xdeadbeef);
1301     res = GetWindowsDirectory(buffer, total + 1);
1302     /* res does not include the terminating Zero */
1303     ok( (res == (total-1)) && (buffer[0]),
1304         "returned %d with %d and '%s' (expected '%d' and a string)\n",
1305         res, GetLastError(), buffer, total-1);
1306
1307     memset(buffer, '#', total + 1);
1308     buffer[total + 2] = '\0';
1309     SetLastError(0xdeadbeef);
1310     res = GetWindowsDirectory(buffer, total-1);
1311     /* res includes the terminating Zero) */
1312     ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1313         res, GetLastError(), buffer, total);
1314
1315     memset(buffer, '#', total + 1);
1316     buffer[total + 2] = '\0';
1317     SetLastError(0xdeadbeef);
1318     res = GetWindowsDirectory(buffer, total-2);
1319     /* res includes the terminating Zero) */
1320     ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1321         res, GetLastError(), buffer, total);
1322 }
1323
1324 static void test_NeedCurrentDirectoryForExePathA(void)
1325 {
1326     /* Crashes in Windows */
1327     if (0)
1328         ok(pNeedCurrentDirectoryForExePathA(NULL), "returned FALSE for NULL\n");
1329
1330     SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", NULL);
1331     ok(pNeedCurrentDirectoryForExePathA("."), "returned FALSE for \".\"\n");
1332     ok(pNeedCurrentDirectoryForExePathA("c:\\"), "returned FALSE for \"c:\\\"\n");
1333     ok(pNeedCurrentDirectoryForExePathA("cmd.exe"), "returned FALSE for \"cmd.exe\"\n");
1334
1335     SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", "nya");
1336     ok(!pNeedCurrentDirectoryForExePathA("."), "returned TRUE for \".\"\n");
1337     ok(pNeedCurrentDirectoryForExePathA("c:\\"), "returned FALSE for \"c:\\\"\n");
1338     ok(!pNeedCurrentDirectoryForExePathA("cmd.exe"), "returned TRUE for \"cmd.exe\"\n");
1339 }
1340
1341 static void test_NeedCurrentDirectoryForExePathW(void)
1342 {
1343     const WCHAR thispath[] = {'.', 0};
1344     const WCHAR fullpath[] = {'c', ':', '\\', 0};
1345     const WCHAR cmdname[] = {'c', 'm', 'd', '.', 'e', 'x', 'e', 0};
1346
1347     /* Crashes in Windows */
1348     if (0)
1349         ok(pNeedCurrentDirectoryForExePathW(NULL), "returned FALSE for NULL\n");
1350
1351     SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", NULL);
1352     ok(pNeedCurrentDirectoryForExePathW(thispath), "returned FALSE for \".\"\n");
1353     ok(pNeedCurrentDirectoryForExePathW(fullpath), "returned FALSE for \"c:\\\"\n");
1354     ok(pNeedCurrentDirectoryForExePathW(cmdname), "returned FALSE for \"cmd.exe\"\n");
1355
1356     SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", "nya");
1357     ok(!pNeedCurrentDirectoryForExePathW(thispath), "returned TRUE for \".\"\n");
1358     ok(pNeedCurrentDirectoryForExePathW(fullpath), "returned FALSE for \"c:\\\"\n");
1359     ok(!pNeedCurrentDirectoryForExePathW(cmdname), "returned TRUE for \"cmd.exe\"\n");
1360 }
1361
1362 /* Call various path/file name retrieving APIs and check the case of
1363  * the returned drive letter. Some apps (for instance Adobe Photoshop CS3
1364  * installer) depend on the drive letter being in upper case.
1365  */
1366 static void test_drive_letter_case(void)
1367 {
1368     UINT ret;
1369     char buf[MAX_PATH];
1370
1371 #define is_upper_case_letter(a) ((a) >= 'A' && (a) <= 'Z')
1372
1373     memset(buf, 0, sizeof(buf));
1374     SetLastError(0xdeadbeef);
1375     ret = GetWindowsDirectory(buf, sizeof(buf));
1376     ok(ret, "GetWindowsDirectory error %u\n", GetLastError());
1377     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1378     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1379     ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1380
1381     /* re-use the buffer returned by GetFullPathName */
1382     buf[2] = '/';
1383     SetLastError(0xdeadbeef);
1384     ret = GetFullPathName(buf + 2, sizeof(buf), buf, NULL);
1385     ok(ret, "GetFullPathName error %u\n", GetLastError());
1386     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1387     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1388     ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1389
1390     memset(buf, 0, sizeof(buf));
1391     SetLastError(0xdeadbeef);
1392     ret = GetSystemDirectory(buf, sizeof(buf));
1393     ok(ret, "GetSystemDirectory error %u\n", GetLastError());
1394     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1395     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1396     ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1397
1398     memset(buf, 0, sizeof(buf));
1399     SetLastError(0xdeadbeef);
1400     ret = GetCurrentDirectory(sizeof(buf), buf);
1401     ok(ret, "GetCurrentDirectory error %u\n", GetLastError());
1402     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1403     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1404     ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1405
1406     /* TEMP is an environment variable, so it can't be tested for case-sensitivity */
1407     memset(buf, 0, sizeof(buf));
1408     SetLastError(0xdeadbeef);
1409     ret = GetTempPath(sizeof(buf), buf);
1410     ok(ret, "GetTempPath error %u\n", GetLastError());
1411     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1412     if (buf[0])
1413     {
1414         ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1415         ok(buf[strlen(buf)-1] == '\\', "Temporary path (%s) doesn't end in a slash\n", buf);
1416     }
1417
1418     memset(buf, 0, sizeof(buf));
1419     SetLastError(0xdeadbeef);
1420     ret = GetFullPathName(".", sizeof(buf), buf, NULL);
1421     ok(ret, "GetFullPathName error %u\n", GetLastError());
1422     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1423     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1424     ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1425
1426     /* re-use the buffer returned by GetFullPathName */
1427     SetLastError(0xdeadbeef);
1428     ret = GetShortPathName(buf, buf, sizeof(buf));
1429     ok(ret, "GetShortPathName error %u\n", GetLastError());
1430     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1431     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1432     ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1433
1434     if (pGetLongPathNameA)
1435     {
1436         /* re-use the buffer returned by GetShortPathName */
1437         SetLastError(0xdeadbeef);
1438         ret = pGetLongPathNameA(buf, buf, sizeof(buf));
1439         ok(ret, "GetLongPathNameA error %u\n", GetLastError());
1440         ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1441         ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1442         ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1443     }
1444 #undef is_upper_case_letter
1445 }
1446
1447 START_TEST(path)
1448 {
1449     CHAR origdir[MAX_PATH],curdir[MAX_PATH], curDrive, otherDrive;
1450     pGetLongPathNameA = (void*)GetProcAddress( GetModuleHandleA("kernel32.dll"),
1451                                                "GetLongPathNameA" );
1452     pGetLongPathNameW = (void*)GetProcAddress(GetModuleHandleA("kernel32.dll") ,
1453                                                "GetLongPathNameW" );
1454     pNeedCurrentDirectoryForExePathA =
1455         (void*)GetProcAddress( GetModuleHandleA("kernel32.dll"),
1456                                "NeedCurrentDirectoryForExePathA" );
1457     pNeedCurrentDirectoryForExePathW =
1458         (void*)GetProcAddress( GetModuleHandleA("kernel32.dll"),
1459                                "NeedCurrentDirectoryForExePathW" );
1460
1461     /* Report only once */
1462     if (!pGetLongPathNameA)
1463         win_skip("GetLongPathNameA is not available\n");
1464     if (!pGetLongPathNameW)
1465         win_skip("GetLongPathNameW is not available\n");
1466
1467     test_InitPathA(curdir, &curDrive, &otherDrive);
1468     test_CurrentDirectoryA(origdir,curdir);
1469     test_PathNameA(curdir, curDrive, otherDrive);
1470     test_CleanupPathA(origdir,curdir);
1471     test_GetTempPath();
1472     test_GetLongPathNameA();
1473     test_GetLongPathNameW();
1474     test_GetShortPathNameW();
1475     test_GetSystemDirectory();
1476     test_GetWindowsDirectory();
1477     if (pNeedCurrentDirectoryForExePathA)
1478     {
1479         test_NeedCurrentDirectoryForExePathA();
1480     }
1481     if (pNeedCurrentDirectoryForExePathW)
1482     {
1483         test_NeedCurrentDirectoryForExePathW();
1484     }
1485     test_drive_letter_case();
1486 }