kernel32/tests: Add tests for GetSystemDirectory.
[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 /* a structure to deal with wine todos somewhat cleanly */
57 typedef struct {
58   DWORD shortlen;
59   DWORD shorterror;
60   DWORD s2llen;
61   DWORD s2lerror;
62   DWORD longlen;
63   DWORD longerror;
64 } SLpassfail;
65
66 /* function that tests GetFullPathNameA, GetShortPathNameA,GetLongPathNameA */
67 /* NOTE: the passfail structure is used to allow cutomizeable todo checking
68          for wine.  It is not very pretty, but it sure beats duplicating this
69          function lots of times
70 */
71 static void test_ValidPathA(const CHAR *curdir, const CHAR *subdir, const CHAR *filename,
72                          CHAR *shortstr, SLpassfail *passfail, const CHAR *errstr)
73 {
74   CHAR tmpstr[MAX_PATH],
75        fullpath[MAX_PATH],      /*full path to the file (not short/long) */
76        subpath[MAX_PATH],       /*relative path to the file */
77        fullpathshort[MAX_PATH], /*absolue path to the file (short format) */
78        fullpathlong[MAX_PATH],  /*absolute path to the file (long format) */
79        curdirshort[MAX_PATH],   /*absolute path to the current dir (short) */
80        curdirlong[MAX_PATH];    /*absolute path to the current dir (long) */
81   LPSTR strptr;                 /*ptr to the filename portion of the path */
82   DWORD len;
83 /* if passfail is NULL, we can perform all checks within this function,
84    otherwise, we will return the relevant data in the passfail struct, so
85    we must initialize it first
86 */
87   if(passfail!=NULL) {
88     passfail->shortlen=-1;passfail->s2llen=-1;passfail->longlen=-1;
89     passfail->shorterror=0;passfail->s2lerror=0;passfail->longerror=0;
90   }
91 /* GetLongPathNameA is only supported on Win2k+ and Win98+ */
92   if(pGetLongPathNameA) {
93     ok((len=pGetLongPathNameA(curdir,curdirlong,MAX_PATH)),
94        "%s: GetLongPathNameA failed\n",errstr);
95 /*GetLongPathNameA can return a trailing '\\' but shouldn't do so here */
96     ok(! HAS_TRAIL_SLASH_A(curdirlong),
97        "%s: GetLongPathNameA should not have a trailing \\\n",errstr);
98   }
99   ok((len=GetShortPathNameA(curdir,curdirshort,MAX_PATH)),
100      "%s: GetShortPathNameA failed\n",errstr);
101 /*GetShortPathNameA can return a trailing '\\' but shouldn't do so here */
102   ok(! HAS_TRAIL_SLASH_A(curdirshort),
103      "%s: GetShortPathNameA should not have a trailing \\\n",errstr);
104 /* build relative and absolute paths from inputs */
105   if(lstrlenA(subdir)) {
106     sprintf(subpath,"%s\\%s",subdir,filename);
107   } else {
108     lstrcpyA(subpath,filename);
109   }
110   sprintf(fullpath,"%s\\%s",curdir,subpath);
111   sprintf(fullpathshort,"%s\\%s",curdirshort,subpath);
112   sprintf(fullpathlong,"%s\\%s",curdirlong,subpath);
113 /* Test GetFullPathNameA functionality */
114   len=GetFullPathNameA(subpath,MAX_PATH,tmpstr,&strptr);
115   ok(len, "GetFullPathNameA failed for: '%s'\n",subpath);
116   if(HAS_TRAIL_SLASH_A(subpath)) {
117     ok(strptr==NULL,
118        "%s: GetFullPathNameA should not return a filename ptr\n",errstr);
119     ok(lstrcmpiA(fullpath,tmpstr)==0,
120        "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
121        errstr,tmpstr,fullpath);
122   } else {
123     ok(lstrcmpiA(strptr,filename)==0,
124        "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
125        errstr,strptr,filename);
126     ok(lstrcmpiA(fullpath,tmpstr)==0,
127        "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
128        errstr,tmpstr,fullpath);
129   }
130 /* Test GetShortPathNameA functionality */
131   SetLastError(0);
132   len=GetShortPathNameA(fullpathshort,shortstr,MAX_PATH);
133   if(passfail==NULL) {
134     ok(len, "%s: GetShortPathNameA failed\n",errstr);
135   } else {
136     passfail->shortlen=len;
137     passfail->shorterror=GetLastError();
138   }
139 /* Test GetLongPathNameA functionality
140    We test both conversion from GetFullPathNameA and from GetShortPathNameA
141 */
142   if(pGetLongPathNameA) {
143     if(len!=0) {
144       SetLastError(0);
145       len=pGetLongPathNameA(shortstr,tmpstr,MAX_PATH);
146       if(passfail==NULL) {
147         ok(len,
148           "%s: GetLongPathNameA failed during Short->Long conversion\n", errstr);
149         ok(lstrcmpiA(fullpathlong,tmpstr)==0,
150            "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
151            errstr,tmpstr,fullpathlong);
152       } else {
153         passfail->s2llen=len;
154         passfail->s2lerror=GetLastError();
155       }
156     }
157     SetLastError(0);
158     len=pGetLongPathNameA(fullpath,tmpstr,MAX_PATH);
159     if(passfail==NULL) {
160       ok(len, "%s: GetLongPathNameA failed\n",errstr);
161       if(HAS_TRAIL_SLASH_A(fullpath)) {
162         ok(lstrcmpiA(fullpathlong,tmpstr)==0,
163            "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
164            errstr,tmpstr,fullpathlong);
165       } else {
166         ok(lstrcmpiA(fullpathlong,tmpstr)==0,
167           "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
168           errstr,tmpstr,fullpathlong);
169       }
170     } else {
171       passfail->longlen=len;
172       passfail->longerror=GetLastError();
173     }
174   }
175 }
176
177 /* split path into leading directory, and 8.3 filename */
178 static void test_SplitShortPathA(CHAR *path,CHAR *dir,CHAR *eight,CHAR *three) {
179   int done,error;
180   int ext,fil;
181   int len,i;
182   len=lstrlenA(path);
183   ext=len; fil=len; done=0; error=0;
184 /* walk backwards over path looking for '.' or '\\' separators */
185   for(i=len-1;(i>=0) && (!done);i--) {
186     if(path[i]=='.')
187       if(ext!=len) error=1; else ext=i;
188     else if(path[i]=='\\') {
189       if(i==len-1) {
190         error=1;
191       } else {
192         fil=i;
193         done=1;
194       }
195     }
196   }
197 /* Check that we didn't find a trailing '\\' or multiple '.' */
198   ok(!error,"Illegal file found in 8.3 path '%s'\n",path);
199 /* Separate dir, root, and extension */
200   if(ext!=len) lstrcpyA(three,path+ext+1); else lstrcpyA(three,"");
201   if(fil!=len) {
202     lstrcpynA(eight,path+fil+1,ext-fil);
203     lstrcpynA(dir,path,fil+1);
204   } else {
205     lstrcpynA(eight,path,ext+1);
206     lstrcpyA(dir,"");
207   }
208 /* Validate that root and extension really are 8.3 */
209   ok(lstrlenA(eight)<=8 && lstrlenA(three)<=3,
210      "GetShortPathNAmeA did not return an 8.3 path\n");
211 }
212
213 /* Check that GetShortPathNameA returns a valid 8.3 path */
214 static void test_LongtoShortA(CHAR *teststr,const CHAR *goodstr,
215                               const CHAR *ext,const CHAR *errstr) {
216   CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
217
218   test_SplitShortPathA(teststr,dir,eight,three);
219   ok(lstrcmpiA(dir,goodstr)==0,
220      "GetShortPathNameA returned '%s' instead of '%s'\n",dir,goodstr);
221   ok(lstrcmpiA(three,ext)==0,
222      "GetShortPathNameA returned '%s' with incorrect extension\n",three);
223 }
224
225 /* Test that Get(Short|Long|Full)PathNameA work correctly with interesting
226    characters in the filename.
227      'valid' indicates whether this would be an allowed filename
228      'todo' indicates that wine doesn't get this right yet.
229    NOTE: We always call this routine with a nonexistent filename, so
230          Get(Short|Long)PathNameA should never pass, but GetFullPathNameA
231          should.
232 */
233 static void test_FunnyChars(CHAR *curdir,CHAR *curdir_short,CHAR *filename, INT valid,CHAR *errstr)
234 {
235   CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
236   SLpassfail passfail;
237
238   test_ValidPathA(curdir,"",filename,tmpstr,&passfail,errstr);
239   if(valid) {
240     sprintf(tmpstr1,"%s\\%s",curdir_short,filename);
241       ok((passfail.shortlen==0 &&
242           (passfail.shorterror==ERROR_FILE_NOT_FOUND || passfail.shorterror==ERROR_PATH_NOT_FOUND || !passfail.shorterror)) ||
243          (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
244          "%s: GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
245          errstr,passfail.shortlen,passfail.shorterror,tmpstr);
246   } else {
247       ok(passfail.shortlen==0 &&
248          (passfail.shorterror==ERROR_INVALID_NAME || passfail.shorterror==ERROR_FILE_NOT_FOUND || !passfail.shorterror),
249          "%s: GetShortPathA should have failed len=%d, error=%d\n",
250          errstr,passfail.shortlen,passfail.shorterror);
251   }
252   if(pGetLongPathNameA) {
253     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
254     if(valid) {
255       ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
256          "%s: GetLongPathA returned %d and not %d\n",
257          errstr,passfail.longerror,ERROR_FILE_NOT_FOUND);
258     } else {
259       ok(passfail.longerror==ERROR_INVALID_NAME ||
260          passfail.longerror==ERROR_FILE_NOT_FOUND,
261          "%s: GetLongPathA returned %d and not %d or %d'\n",
262          errstr, passfail.longerror,ERROR_INVALID_NAME,ERROR_FILE_NOT_FOUND);
263     }
264   }
265 }
266
267 /* Routine to test that SetCurrentDirectory behaves as expected. */
268 static void test_setdir(CHAR *olddir,CHAR *newdir,
269                         CHAR *cmprstr, INT pass, const CHAR *errstr)
270 {
271   CHAR tmppath[MAX_PATH], *dirptr;
272   DWORD val,len,chklen;
273
274   val=SetCurrentDirectoryA(newdir);
275   len=GetCurrentDirectoryA(MAX_PATH,tmppath);
276 /* if 'pass' then the SetDirectoryA was supposed to pass */
277   if(pass) {
278     dirptr=(cmprstr==NULL) ? newdir : cmprstr;
279     chklen=lstrlenA(dirptr);
280     ok(val,"%s: SetCurrentDirectoryA failed\n",errstr);
281     ok(len==chklen,
282        "%s: SetCurrentDirectory did not change the directory, though it passed\n",
283        errstr);
284     ok(lstrcmpiA(dirptr,tmppath)==0,
285        "%s: SetCurrentDirectory did not change the directory, though it passed\n",
286        errstr);
287     ok(SetCurrentDirectoryA(olddir),
288        "%s: Couldn't set directory to it's original value\n",errstr);
289   } else {
290 /* else thest that it fails correctly */
291     chklen=lstrlenA(olddir);
292     ok(val==0,
293        "%s: SetCurrentDirectoryA passed when it should have failed\n",errstr);
294     ok(len==chklen,
295        "%s: SetCurrentDirectory changed the directory, though it failed\n",
296        errstr);
297     ok(lstrcmpiA(olddir,tmppath)==0,
298        "%s: SetCurrentDirectory changed the directory, though it failed\n",
299        errstr);
300   }
301 }
302 static void test_InitPathA(CHAR *newdir, CHAR *curDrive, CHAR *otherDrive)
303 {
304   CHAR tmppath[MAX_PATH], /*path to TEMP */
305        tmpstr[MAX_PATH],
306        tmpstr1[MAX_PATH];
307   DWORD len,len1,drives;
308   INT id;
309   HANDLE hndl;
310   BOOL bRes;
311
312   *curDrive = *otherDrive = NOT_A_VALID_DRIVE;
313
314 /* Get the current drive letter */
315   if( GetCurrentDirectoryA( MAX_PATH, tmpstr))
316     *curDrive = tmpstr[0];
317   else
318     trace( "Unable to discover current drive, some tests will not be conducted.\n");
319
320 /* Test GetTempPathA */
321   len=GetTempPathA(MAX_PATH,tmppath);
322   ok(len!=0 && len < MAX_PATH,"GetTempPathA failed\n");
323   ok(HAS_TRAIL_SLASH_A(tmppath),
324      "GetTempPathA returned a path that did not end in '\\'\n");
325   lstrcpyA(tmpstr,"aaaaaaaa");
326   len1=GetTempPathA(len,tmpstr);
327   ok(len1==len+1,
328      "GetTempPathA should return string length %d instead of %d\n",len+1,len1);
329
330 /* Test GetTmpFileNameA
331    The only test we do here is whether GetTempFileNameA passes or not.
332    We do not thoroughly test this function yet (specifically, whether
333    it behaves correctly when 'unique' is non zero)
334 */
335   ok((id=GetTempFileNameA(tmppath,"path",0,newdir)),"GetTempFileNameA failed\n");
336   sprintf(tmpstr,"pat%.4x.tmp",id & 0xffff);
337   sprintf(tmpstr1,"pat%x.tmp",id & 0xffff);
338   ok(lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr)==0 ||
339      lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr1)==0,
340      "GetTempFileNameA returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
341      newdir,tmpstr,tmpstr1,id);
342   ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");     
343
344   id=GetTempFileNameA(tmppath,NULL,0,newdir);
345 /* Windows 95, 98 return 0==id, while Windows 2000, XP return 0!=id */
346   if (id)
347   {
348     sprintf(tmpstr,"%.4x.tmp",id & 0xffff);
349     sprintf(tmpstr1,"%x.tmp",id & 0xffff);
350     ok(lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr)==0 ||
351        lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr1)==0,
352        "GetTempFileNameA returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
353        newdir,tmpstr,tmpstr1,id);
354     ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
355   }
356
357 /* Find first valid drive letter that is neither newdir[0] nor curDrive */
358   drives = GetLogicalDrives() & ~(1<<(newdir[0]-'A'));
359   if( *curDrive != NOT_A_VALID_DRIVE)
360     drives &= ~(1<<(*curDrive-'A'));
361   if( drives)
362     for( *otherDrive='A'; (drives & 1) == 0; drives>>=1, (*otherDrive)++);
363   else
364     trace( "Could not find alternative drive, some tests will not be conducted.\n");
365
366 /* Do some CreateDirectoryA tests */
367 /* It would be nice to do test the SECURITY_ATTRIBUTES, but I don't
368    really understand how they work.
369    More formal tests should be done along with CreateFile tests
370 */
371   ok((id=GetTempFileNameA(tmppath,"path",0,newdir)),"GetTempFileNameA failed\n");
372   ok(CreateDirectoryA(newdir,NULL)==0,
373      "CreateDirectoryA succeeded even though a file of the same name exists\n");
374   ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
375   ok(CreateDirectoryA(newdir,NULL),"CreateDirectoryA failed\n");
376 /* Create some files to test other functions.  Note, we will test CreateFileA
377    at some later point
378 */
379   sprintf(tmpstr,"%s\\%s",newdir,SHORTDIR);
380   ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed\n");
381   sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
382   ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed\n");
383   bRes = CreateDirectoryA("c:",NULL);
384   ok(!bRes && (GetLastError() == ERROR_ACCESS_DENIED  || 
385                GetLastError() == ERROR_ALREADY_EXISTS),
386      "CreateDirectoryA(\"c:\" should have failed (%d)\n", GetLastError());
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   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,SHORTFILE);
392   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
393                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
394   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
395   ok(CloseHandle(hndl),"CloseHandle failed\n");
396   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,LONGFILE);
397   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
398                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
399   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
400   ok(CloseHandle(hndl),"CloseHandle failed\n");
401   sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,SHORTFILE);
402   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
403                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
404   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
405   ok(CloseHandle(hndl),"CloseHandle failed\n");
406   sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,LONGFILE);
407   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
408                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
409   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
410   ok(CloseHandle(hndl),"CloseHandle failed\n");
411 }
412
413 /* Test GetCurrentDirectory & SetCurrentDirectory */
414 static void test_CurrentDirectoryA(CHAR *origdir, CHAR *newdir)
415 {
416   CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
417   DWORD len,len1;
418 /* Save the original directory, so that we can return to it at the end
419    of the test
420 */
421   len=GetCurrentDirectoryA(MAX_PATH,origdir);
422   ok(len!=0 && len < MAX_PATH,"GetCurrentDirectoryA failed\n");
423 /* Make sure that CetCurrentDirectoryA doesn't overwrite the buffer when the
424    buffer size is too small to hold the current directory
425 */
426   lstrcpyA(tmpstr,"aaaaaaa");
427   len1=GetCurrentDirectoryA(len,tmpstr);
428   ok(len1==len+1, "GetCurrentDirectoryA returned %d instead of %d\n",len1,len+1);
429   ok(lstrcmpiA(tmpstr,"aaaaaaa")==0,
430      "GetCurrentDirectoryA should not have modified the buffer\n");
431 /* SetCurrentDirectoryA shouldn't care whether the string has a
432    trailing '\\' or not
433 */
434   sprintf(tmpstr,"%s\\",newdir);
435   test_setdir(origdir,tmpstr,newdir,1,"check 1");
436   test_setdir(origdir,newdir,NULL,1,"check 2");
437 /* Set the directory to the working area.  We just tested that this works,
438    so why check it again.
439 */
440   SetCurrentDirectoryA(newdir);
441 /* Check that SetCurrentDirectory fails when a nonexistent dir is specified */
442   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_SHORT);
443   test_setdir(newdir,tmpstr,NULL,0,"check 3");
444 /* Check that SetCurrentDirectory fails for a nonexistent lond directory */
445   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_LONG);
446   test_setdir(newdir,tmpstr,NULL,0,"check 4");
447 /* Check that SetCurrentDirectory passes with a long directory */
448   sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
449   test_setdir(newdir,tmpstr,NULL,1,"check 5");
450 /* Check that SetCurrentDirectory passes with a short relative directory */
451   sprintf(tmpstr,"%s",SHORTDIR);
452   sprintf(tmpstr1,"%s\\%s",newdir,SHORTDIR);
453   test_setdir(newdir,tmpstr,tmpstr1,1,"check 6");
454 /* starting with a '.' */
455   sprintf(tmpstr,".\\%s",SHORTDIR);
456   test_setdir(newdir,tmpstr,tmpstr1,1,"check 7");
457 /* Check that SetCurrentDirectory passes with a short relative directory */
458   sprintf(tmpstr,"%s",LONGDIR);
459   sprintf(tmpstr1,"%s\\%s",newdir,LONGDIR);
460   test_setdir(newdir,tmpstr,tmpstr1,1,"check 8");
461 /* starting with a '.' */
462   sprintf(tmpstr,".\\%s",LONGDIR);
463   test_setdir(newdir,tmpstr,tmpstr1,1,"check 9");
464 }
465
466 /* Cleanup the mess we made while executing these tests */
467 static void test_CleanupPathA(CHAR *origdir, CHAR *curdir)
468 {
469   CHAR tmpstr[MAX_PATH];
470   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
471   ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
472   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,LONGFILE);
473   ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
474   sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,SHORTFILE);
475   ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
476   sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
477   ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
478   sprintf(tmpstr,"%s\\%s",curdir,SHORTDIR);
479   ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
480   sprintf(tmpstr,"%s\\%s",curdir,LONGDIR);
481   ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
482   ok(SetCurrentDirectoryA(origdir),"SetCurrentDirectoryA failed\n");
483   ok(RemoveDirectoryA(curdir),"RemoveDirectoryA failed\n");
484 }
485
486 /* This routine will test Get(Full|Short|Long)PathNameA */
487 static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive)
488 {
489   CHAR curdir_short[MAX_PATH],
490        longdir_short[MAX_PATH];
491   CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH],tmpstr2[MAX_PATH];
492   LPSTR strptr;                 /*ptr to the filename portion of the path */
493   DWORD len;
494   INT i;
495   CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
496   SLpassfail passfail;
497
498 /* Get the short form of the current directory */
499   ok((len=GetShortPathNameA(curdir,curdir_short,MAX_PATH)),
500      "GetShortPathNameA failed\n");
501   ok(!HAS_TRAIL_SLASH_A(curdir_short),
502      "GetShortPathNameA should not have a trailing \\\n");
503 /* Get the short form of the absolute-path to LONGDIR */
504   sprintf(tmpstr,"%s\\%s",curdir_short,LONGDIR);
505   ok((len=GetShortPathNameA(tmpstr,longdir_short,MAX_PATH)),
506      "GetShortPathNameA failed\n");
507   ok(lstrcmpiA(longdir_short+(len-1),"\\")!=0,
508      "GetShortPathNameA should not have a trailing \\\n");
509
510   if (pGetLongPathNameA) {
511     DWORD rc1,rc2;
512     sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
513     rc1=(*pGetLongPathNameA)(tmpstr,NULL,0);
514     rc2=(*pGetLongPathNameA)(curdir,NULL,0);
515     ok((rc1-strlen(tmpstr))==(rc2-strlen(curdir)),
516        "GetLongPathNameA: wrong return code, %d instead of %d\n",
517        rc1, lstrlenA(tmpstr)+1);
518
519     sprintf(dir,"%c:",curDrive);
520     rc1=(*pGetLongPathNameA)(dir,tmpstr,sizeof(tmpstr));
521     ok(strcmp(dir,tmpstr)==0,
522        "GetLongPathNameA: returned '%s' instead of '%s' (rc=%d)\n",
523        tmpstr,dir,rc1);
524   }
525
526 /* Check the cases where both file and directory exist first */
527 /* Start with a 8.3 directory, 8.3 filename */
528   test_ValidPathA(curdir,SHORTDIR,SHORTFILE,tmpstr,NULL,"test1");
529   sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,SHORTFILE);
530   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
531      "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
532 /* Now try a 8.3 directory, long file name */
533   test_ValidPathA(curdir,SHORTDIR,LONGFILE,tmpstr,NULL,"test2");
534   sprintf(tmpstr1,"%s\\%s",curdir_short,SHORTDIR);
535   test_LongtoShortA(tmpstr,tmpstr1,"PAT","test2");
536 /* Next is a long directory, 8.3 file */
537   test_ValidPathA(curdir,LONGDIR,SHORTFILE,tmpstr,NULL,"test3");
538   sprintf(tmpstr1,"%s\\%s",longdir_short,SHORTFILE);
539   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
540      "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
541 /*Lastly a long directory, long file */
542   test_ValidPathA(curdir,LONGDIR,LONGFILE,tmpstr,NULL,"test4");
543   test_LongtoShortA(tmpstr,longdir_short,"PAT","test4");
544
545 /* Now check all of the invalid file w/ valid directory combinations */
546 /* Start with a 8.3 directory, 8.3 filename */
547   test_ValidPathA(curdir,SHORTDIR,NONFILE_SHORT,tmpstr,&passfail,"test5");
548   sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,NONFILE_SHORT);
549   ok((passfail.shortlen==0 &&
550       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
551        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
552      (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
553      "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
554      passfail.shortlen,passfail.shorterror,tmpstr);
555   if(pGetLongPathNameA) {
556     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
557     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
558        "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
559   }
560 /* Now try a 8.3 directory, long file name */
561   test_ValidPathA(curdir,SHORTDIR,NONFILE_LONG,tmpstr,&passfail,"test6");
562   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
563   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
564      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
565      !passfail.shorterror,
566      "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
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 /* Next is a long directory, 8.3 file */
573   test_ValidPathA(curdir,LONGDIR,NONFILE_SHORT,tmpstr,&passfail,"test7");
574   sprintf(tmpstr2,"%s\\%s",curdir_short,LONGDIR);
575   GetShortPathNameA(tmpstr2,tmpstr1,MAX_PATH);
576   strcat(tmpstr1,"\\" NONFILE_SHORT);
577   ok((passfail.shortlen==0 &&
578       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
579        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
580      (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
581      "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
582      passfail.shortlen,passfail.shorterror,tmpstr);
583   if(pGetLongPathNameA) {
584     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
585     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
586       "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
587   }
588 /*Lastly a long directory, long file */
589   test_ValidPathA(curdir,LONGDIR,NONFILE_LONG,tmpstr,&passfail,"test8");
590   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
591   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
592      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
593      !passfail.shorterror,
594      "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
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 /* Now try again with directories that don't exist */
601 /* 8.3 directory, 8.3 filename */
602   test_ValidPathA(curdir,NONDIR_SHORT,SHORTFILE,tmpstr,&passfail,"test9");
603   sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,NONDIR_SHORT,SHORTFILE);
604   ok((passfail.shortlen==0 &&
605       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
606        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
607      (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
608      "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
609      passfail.shortlen,passfail.shorterror,tmpstr);
610   if(pGetLongPathNameA) {
611     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
612     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
613        passfail.longerror==ERROR_FILE_NOT_FOUND,
614        "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
615        passfail.longerror);
616   }
617 /* Now try a 8.3 directory, long file name */
618   test_ValidPathA(curdir,NONDIR_SHORT,LONGFILE,tmpstr,&passfail,"test10");
619   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
620   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
621      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
622      !passfail.shorterror,
623      "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
624       passfail.shorterror);
625   if(pGetLongPathNameA) {
626     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
627     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
628        passfail.longerror==ERROR_FILE_NOT_FOUND,
629        "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
630        passfail.longerror);
631   }
632 /* Next is a long directory, 8.3 file */
633   test_ValidPathA(curdir,NONDIR_LONG,SHORTFILE,tmpstr,&passfail,"test11");
634   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
635   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
636      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
637      !passfail.shorterror,
638      "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
639       passfail.shorterror);
640   if(pGetLongPathNameA) {
641     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
642     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
643        passfail.longerror==ERROR_FILE_NOT_FOUND,
644        "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
645        passfail.longerror);
646   }
647 /*Lastly a long directory, long file */
648   test_ValidPathA(curdir,NONDIR_LONG,LONGFILE,tmpstr,&passfail,"test12");
649   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
650   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
651      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
652      !passfail.shorterror,
653      "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
654       passfail.shorterror);
655   if(pGetLongPathNameA) {
656     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
657     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
658        passfail.longerror==ERROR_FILE_NOT_FOUND,
659        "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
660        passfail.longerror);
661   }
662 /* Next try directories ending with '\\' */
663 /* Existing Directories */
664   sprintf(tmpstr,"%s\\",SHORTDIR);
665   test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test13");
666   sprintf(tmpstr,"%s\\",LONGDIR);
667   test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test14");
668 /* Nonexistent directories */
669   sprintf(tmpstr,"%s\\",NONDIR_SHORT);
670   test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test15");
671   sprintf(tmpstr2,"%s\\%s",curdir_short,tmpstr);
672   ok((passfail.shortlen==0 &&
673       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
674        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
675      (passfail.shortlen==strlen(tmpstr2) && lstrcmpiA(tmpstr1,tmpstr2)==0),
676      "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
677      passfail.shortlen,passfail.shorterror,tmpstr);
678   if(pGetLongPathNameA) {
679     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
680     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
681        "GetLongPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
682        passfail.longerror);
683   }
684   sprintf(tmpstr,"%s\\",NONDIR_LONG);
685   test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test16");
686   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
687   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
688      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
689      !passfail.shorterror,
690      "GetShortPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
691       passfail.shorterror);
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 /* Test GetFullPathNameA with drive letters */
699   if( curDrive != NOT_A_VALID_DRIVE) {
700     sprintf(tmpstr,"%c:",curdir[0]);
701     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr2,&strptr),
702        "GetFullPathNameA(%c:) failed\n", curdir[0]);
703     GetCurrentDirectoryA(MAX_PATH,tmpstr);
704     sprintf(tmpstr1,"%s\\",tmpstr);
705     ok(lstrcmpiA(tmpstr,tmpstr2)==0 || lstrcmpiA(tmpstr1,tmpstr2)==0,
706        "GetFullPathNameA(%c:) returned '%s' instead of '%s' or '%s'\n",
707        curdir[0],tmpstr2,tmpstr,tmpstr1);
708
709     sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
710     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
711     ok(lstrcmpiA(tmpstr,tmpstr1)==0,
712        "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
713     ok(lstrcmpiA(SHORTFILE,strptr)==0,
714        "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
715   }
716 /* Without a leading slash, insert the current directory if on the current drive */
717   sprintf(tmpstr,"%c:%s\\%s",curdir[0],SHORTDIR,SHORTFILE);
718   ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
719   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
720   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
721       "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
722   ok(lstrcmpiA(SHORTFILE,strptr)==0,
723       "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
724 /* Otherwise insert the missing leading slash */
725   if( otherDrive != NOT_A_VALID_DRIVE) {
726     sprintf(tmpstr,"%c:%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
727     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed for %s\n", tmpstr);
728     sprintf(tmpstr,"%c:\\%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
729     ok(lstrcmpiA(tmpstr,tmpstr1)==0,
730        "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
731     ok(lstrcmpiA(SHORTFILE,strptr)==0,
732        "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
733   }
734 /* Xilinx tools like to mix Unix and DOS formats, which Windows handles fine.
735    So test for them. */
736   if( curDrive != NOT_A_VALID_DRIVE) {
737     sprintf(tmpstr,"%c:/%s\\%s",curDrive,SHORTDIR,SHORTFILE);
738     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
739     sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
740     ok(lstrcmpiA(tmpstr,tmpstr1)==0,
741        "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
742     ok(lstrcmpiA(SHORTFILE,strptr)==0,
743        "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
744   }
745 /**/
746   sprintf(tmpstr,"%c:%s/%s",curdir[0],SHORTDIR,SHORTFILE);
747   ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
748   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
749   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
750       "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
751   ok(lstrcmpiA(SHORTFILE,strptr)==0,
752       "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
753 /* Windows will insert a drive letter in front of an absolute UNIX path */
754   sprintf(tmpstr,"/%s/%s",SHORTDIR,SHORTFILE);
755   ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
756   sprintf(tmpstr,"%c:\\%s\\%s",*tmpstr1,SHORTDIR,SHORTFILE);
757   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
758      "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
759 /* This passes in Wine because it still contains the pointer from the previous test */
760   ok(lstrcmpiA(SHORTFILE,strptr)==0,
761       "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
762
763 /* Now try some relative paths */
764   ok(GetShortPathNameA(LONGDIR,tmpstr,MAX_PATH),"GetShortPathNameA failed\n");
765   test_SplitShortPathA(tmpstr,dir,eight,three);
766   if(pGetLongPathNameA) {
767     ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
768     ok(lstrcmpiA(tmpstr1,LONGDIR)==0,
769        "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,LONGDIR);
770   }
771   sprintf(tmpstr,".\\%s",LONGDIR);
772   ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed\n");
773   test_SplitShortPathA(tmpstr1,dir,eight,three);
774   ok(lstrcmpiA(dir,".")==0 || dir[0]=='\0',
775      "GetShortPathNameA did not keep relative directory [%s]\n",tmpstr1);
776   if(pGetLongPathNameA) {
777     ok(pGetLongPathNameA(tmpstr1,tmpstr1,MAX_PATH),"GetLongPathNameA failed %s\n",
778        tmpstr);
779     ok(lstrcmpiA(tmpstr1,tmpstr)==0,
780        "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
781   }
782 /* Check out Get*PathNameA on some funny characters */
783   for(i=0;i<lstrlenA(funny_chars);i++) {
784     INT valid;
785     valid=(is_char_ok[i]=='0') ? 0 : 1;
786     sprintf(tmpstr1,"check%d-1",i);
787     sprintf(tmpstr,"file%c000.ext",funny_chars[i]);
788     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
789     sprintf(tmpstr1,"check%d-2",i);
790     sprintf(tmpstr,"file000.e%ct",funny_chars[i]);
791     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
792     sprintf(tmpstr1,"check%d-3",i);
793     sprintf(tmpstr,"%cfile000.ext",funny_chars[i]);
794     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
795     sprintf(tmpstr1,"check%d-4",i);
796     sprintf(tmpstr,"file000%c.ext",funny_chars[i]);
797     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
798     sprintf(tmpstr1,"check%d-5",i);
799     sprintf(tmpstr,"Long %c File",funny_chars[i]);
800     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
801     sprintf(tmpstr1,"check%d-6",i);
802     sprintf(tmpstr,"%c Long File",funny_chars[i]);
803     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
804     sprintf(tmpstr1,"check%d-7",i);
805     sprintf(tmpstr,"Long File %c",funny_chars[i]);
806     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
807   }
808 }
809
810 static void test_GetTempPathA(char* tmp_dir)
811 {
812     DWORD len, len_with_null;
813     char buf[MAX_PATH];
814
815     len_with_null = strlen(tmp_dir) + 1;
816
817     lstrcpyA(buf, "foo");
818     len = GetTempPathA(MAX_PATH, buf);
819     ok(len <= MAX_PATH, "should fit into MAX_PATH\n");
820     ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
821     ok(len == strlen(buf), "returned length should be equal to the length of string\n");
822
823     /* Some versions of Windows touch the buffer, some don't so we don't
824      * test that. Also, NT sometimes exagerates the required buffer size
825      * so we cannot test for an exact match. Finally, the
826      * 'len_with_null - 1' case is so buggy on Windows it's not testable.
827      * For instance in some cases Win98 returns len_with_null - 1 instead
828      * of len_with_null.
829      */
830     len = GetTempPathA(1, buf);
831     ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
832
833     len = GetTempPathA(0, NULL);
834     ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
835
836     /* The call above gave us the buffer size that Windows thinks is needed
837      * so the next call should work
838      */
839     lstrcpyA(buf, "foo");
840     len = GetTempPathA(len, buf);
841     ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
842     ok(len == strlen(buf), "returned length should be equal to the length of string\n");
843 }
844
845 static void test_GetTempPathW(char* tmp_dir)
846 {
847     DWORD len, len_with_null;
848     WCHAR buf[MAX_PATH];
849     WCHAR tmp_dirW[MAX_PATH];
850     static const WCHAR fooW[] = {'f','o','o',0};
851
852     MultiByteToWideChar(CP_ACP,0,tmp_dir,-1,tmp_dirW,sizeof(tmp_dirW)/sizeof(*tmp_dirW));
853     len_with_null = lstrlenW(tmp_dirW) + 1;
854
855     /* This one is different from ANSI version: ANSI version doesn't
856      * touch the buffer, unicode version usually truncates the buffer
857      * to zero size. NT still exagerates the required buffer size
858      * sometimes so we cannot test for an exact match. Finally, the
859      * 'len_with_null - 1' case is so buggy on Windows it's not testable.
860      * For instance on NT4 it will sometimes return a path without the
861      * trailing '\\' and sometimes return an error.
862      */
863
864     lstrcpyW(buf, fooW);
865     len = GetTempPathW(MAX_PATH, buf);
866     if (len==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
867         return;
868     ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
869     ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
870
871     lstrcpyW(buf, fooW);
872     len = GetTempPathW(1, buf);
873     ok(buf[0] == 0, "unicode version should truncate the buffer to zero size\n");
874     ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
875
876     len = GetTempPathW(0, NULL);
877     ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
878
879     lstrcpyW(buf, fooW);
880     len = GetTempPathW(len, buf);
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
885 static void test_GetTempPath(void)
886 {
887     char save_TMP[MAX_PATH];
888     char windir[MAX_PATH];
889     char buf[MAX_PATH];
890
891     GetEnvironmentVariableA("TMP", save_TMP, sizeof(save_TMP));
892
893     /* test default configuration */
894     trace("TMP=%s\n", save_TMP);
895     strcpy(buf,save_TMP);
896     if (buf[strlen(buf)-1]!='\\')
897         strcat(buf,"\\");
898     test_GetTempPathA(buf);
899     test_GetTempPathW(buf);
900
901     /* TMP=C:\WINDOWS */
902     GetWindowsDirectoryA(windir, sizeof(windir));
903     SetEnvironmentVariableA("TMP", windir);
904     GetEnvironmentVariableA("TMP", buf, sizeof(buf));
905     trace("TMP=%s\n", buf);
906     strcat(windir,"\\");
907     test_GetTempPathA(windir);
908     test_GetTempPathW(windir);
909
910     /* TMP=C:\ */
911     GetWindowsDirectoryA(windir, sizeof(windir));
912     windir[3] = 0;
913     SetEnvironmentVariableA("TMP", windir);
914     GetEnvironmentVariableA("TMP", buf, sizeof(buf));
915     trace("TMP=%s\n", buf);
916     test_GetTempPathA(windir);
917     test_GetTempPathW(windir);
918
919     /* TMP=C: i.e. use current working directory of the specified drive */
920     GetWindowsDirectoryA(windir, sizeof(windir));
921     SetCurrentDirectoryA(windir);
922     windir[2] = 0;
923     SetEnvironmentVariableA("TMP", windir);
924     GetEnvironmentVariableA("TMP", buf, sizeof(buf));
925     trace("TMP=%s\n", buf);
926     GetWindowsDirectoryA(windir, sizeof(windir));
927     strcat(windir,"\\");
928     test_GetTempPathA(windir);
929     test_GetTempPathW(windir);
930
931     SetEnvironmentVariableA("TMP", save_TMP);
932 }
933
934 static void test_GetLongPathNameW(void)
935 {
936     DWORD length; 
937     WCHAR empty[MAX_PATH];
938
939     /* Not present in all windows versions */
940     if(pGetLongPathNameW) 
941     {
942     SetLastError(0xdeadbeef); 
943     length = pGetLongPathNameW(NULL,NULL,0);
944     ok(0==length,"GetLongPathNameW returned %d but expected 0\n",length);
945     ok(GetLastError()==ERROR_INVALID_PARAMETER,"GetLastError returned %x but expected ERROR_INVALID_PARAMETER\n",GetLastError());
946
947     SetLastError(0xdeadbeef); 
948     empty[0]=0;
949     length = pGetLongPathNameW(empty,NULL,0);
950     ok(0==length,"GetLongPathNameW returned %d but expected 0\n",length);
951     ok(GetLastError()==ERROR_PATH_NOT_FOUND,"GetLastError returned %x but expected ERROR_PATH_NOT_FOUND\n",GetLastError());
952     }
953 }
954
955 static void test_GetSystemDirectory(void)
956 {
957     CHAR    buffer[MAX_PATH + 4];
958     DWORD   res;
959     DWORD   total;
960
961     SetLastError(0xdeadbeef);
962     res = GetSystemDirectory(NULL, 0);
963     /* res includes the terminating Zero */
964     ok(res > 0, "returned %d with 0x%x (expected '>0')\n", res, GetLastError());
965
966     total = res;
967 #if 0
968     /* this test crash on XP */
969     res = GetSystemDirectory(NULL, total);
970 #endif
971
972     SetLastError(0xdeadbeef);
973     res = GetSystemDirectory(NULL, total-1);
974     /* 95+NT: total (includes the terminating Zero)
975        98+ME: 0 with ERROR_INVALID_PARAMETER */
976     ok( (res == total) || (!res && (GetLastError() == ERROR_INVALID_PARAMETER)),
977         "returned %d with 0x%x (expected '%d' or: '0' with " \
978         "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), total);
979
980     if (total > MAX_PATH) return;
981
982     buffer[0] = '\0';
983     SetLastError(0xdeadbeef);
984     res = GetSystemDirectory(buffer, total);
985     /* res does not include the terminating Zero */
986     ok( (res == (total-1)) && (buffer[0]),
987         "returned %d with 0x%x and '%s' (expected '%d' and a string)\n",
988         res, GetLastError(), buffer, total-1);
989
990     buffer[0] = '\0';
991     SetLastError(0xdeadbeef);
992     res = GetSystemDirectory(buffer, total + 1);
993     /* res does not include the terminating Zero */
994     ok( (res == (total-1)) && (buffer[0]),
995         "returned %d with 0x%x and '%s' (expected '%d' and a string)\n",
996         res, GetLastError(), buffer, total-1);
997
998     memset(buffer, '#', total + 1);
999     buffer[total + 2] = '\0';
1000     SetLastError(0xdeadbeef);
1001     res = GetSystemDirectory(buffer, total-1);
1002     /* res includes the terminating Zero) */
1003     ok( res == total, "returned %d with 0x%x and '%s' (expected '%d')\n",
1004         res, GetLastError(), buffer, total);
1005
1006     memset(buffer, '#', total + 1);
1007     buffer[total + 2] = '\0';
1008     SetLastError(0xdeadbeef);
1009     res = GetSystemDirectory(buffer, total-2);
1010     /* res includes the terminating Zero) */
1011     ok( res == total, "returned %d with 0x%x and '%s' (expected '%d')\n",
1012         res, GetLastError(), buffer, total);
1013 }
1014
1015 START_TEST(path)
1016 {
1017     CHAR origdir[MAX_PATH],curdir[MAX_PATH], curDrive, otherDrive;
1018     pGetLongPathNameA = (void*)GetProcAddress( GetModuleHandleA("kernel32.dll"),
1019                                                "GetLongPathNameA" );
1020     pGetLongPathNameW = (void*)GetProcAddress(GetModuleHandleA("kernel32.dll") ,
1021                                                "GetLongPathNameW" );
1022     test_InitPathA(curdir, &curDrive, &otherDrive);
1023     test_CurrentDirectoryA(origdir,curdir);
1024     test_PathNameA(curdir, curDrive, otherDrive);
1025     test_CleanupPathA(origdir,curdir);
1026     test_GetTempPath();
1027     test_GetLongPathNameW();
1028     test_GetSystemDirectory();
1029 }