INT21_GetFreeDiskSpace(): The drive parameter is found in the DL
[wine] / dlls / kernel / tests / path.c
1 /*
2  * Unit test suite for Get*PathNamesA and (Get|Set)CurrentDirectoryA.
3  *
4  * Copyright 2002 Geoffrey Hausheer
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include "wine/test.h"
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "winerror.h"
28 #include "winnls.h"
29
30 #define HAS_TRAIL_SLASH_A(string) (string[lstrlenA(string)-1]=='\\')
31
32 #define LONGFILE "Long File test.path"
33 #define SHORTFILE "pathtest.pth"
34 #define SHORTDIR "shortdir"
35 #define LONGDIR "Long Directory"
36 #define NONFILE_SHORT "noexist.pth"
37 #define NONFILE_LONG "Non Existent File"
38 #define NONDIR_SHORT "notadir"
39 #define NONDIR_LONG "Non Existent Directory"
40
41 #define NOT_A_VALID_DRIVE '@'
42
43 /* the following characters don't work well with GetFullPathNameA
44    in Win98.  I don't know if this is a FAT thing, or if it is an OS thing
45    but I don't test these characters now.
46    NOTE: Win2k allows GetFullPathNameA to work with them though
47       |<>"
48 */
49 static const CHAR funny_chars[]="!@#$%^&*()=+{}[],?'`";
50 static const CHAR is_char_ok[] ="11111110111111111011";
51 static const CHAR wine_todo[]  ="00000000000000000000";
52
53 static DWORD (WINAPI *pGetLongPathNameA)(LPCSTR,LPSTR,DWORD);
54
55 /* a structure to deal with wine todos somewhat cleanly */
56 typedef struct {
57   DWORD shortlen;
58   DWORD shorterror;
59   DWORD s2llen;
60   DWORD s2lerror;
61   DWORD longlen;
62   DWORD longerror;
63 } SLpassfail;
64
65 /* function that tests GetFullPathNameA, GetShortPathNameA,GetLongPathNameA */
66 /* NOTE: the passfail structure is used to allow cutomizeable todo checking
67          for wine.  It is not very pretty, but it sure beats duplicating this
68          function lots of times
69 */
70 static void test_ValidPathA(CHAR *curdir, CHAR *subdir, CHAR *filename,
71                          CHAR *shortstr, SLpassfail *passfail, CHAR *errstr) {
72   CHAR tmpstr[MAX_PATH],
73        fullpath[MAX_PATH],      /*full path to the file (not short/long) */
74        subpath[MAX_PATH],       /*relative path to the file */
75        fullpathshort[MAX_PATH], /*absolue path to the file (short format) */
76        fullpathlong[MAX_PATH],  /*absolute path to the file (long format) */
77        curdirshort[MAX_PATH],   /*absolute path to the current dir (short) */
78        curdirlong[MAX_PATH];    /*absolute path to the current dir (long) */
79   LPSTR strptr;                 /*ptr to the filename portion of the path */
80   DWORD len;
81 /* if passfail is NULL, we can perform all checks within this function,
82    otherwise, we will return the relevant data in the passfail struct, so
83    we must initialize it first
84 */
85   if(passfail!=NULL) {
86     passfail->shortlen=-1;passfail->s2llen=-1;passfail->longlen=-1;
87     passfail->shorterror=0;passfail->s2lerror=0;passfail->longerror=0;
88   }
89 /* GetLongPathNameA is only supported on Win2k+ and Win98+ */
90   if(pGetLongPathNameA) {
91     ok((len=pGetLongPathNameA(curdir,curdirlong,MAX_PATH)),
92        "%s: GetLongPathNameA failed",errstr);
93 /*GetLongPathNameA can return a trailing '\\' but shouldn't do so here */
94     ok(! HAS_TRAIL_SLASH_A(curdirlong),
95        "%s: GetLongPathNameA should not have a trailing \\",errstr);
96   }
97   ok((len=GetShortPathNameA(curdir,curdirshort,MAX_PATH)),
98      "%s: GetShortPathNameA failed",errstr);
99 /*GetShortPathNameA can return a trailing '\\' but shouldn't do so here */
100   ok(! HAS_TRAIL_SLASH_A(curdirshort),
101      "%s: GetShortPathNameA should not have a trailing \\",errstr);
102 /* build relative and absolute paths from inputs */
103   if(lstrlenA(subdir)) {
104     sprintf(subpath,"%s\\%s",subdir,filename);
105   } else {
106     lstrcpyA(subpath,filename);
107   }
108   sprintf(fullpath,"%s\\%s",curdir,subpath);
109   sprintf(fullpathshort,"%s\\%s",curdirshort,subpath);
110   sprintf(fullpathlong,"%s\\%s",curdirlong,subpath);
111 /* Test GetFullPathNameA functionality */
112   len=GetFullPathNameA(subpath,MAX_PATH,tmpstr,&strptr);
113   ok(len, "GetFullPathNameA failed for: '%s'",subpath);
114   if(HAS_TRAIL_SLASH_A(subpath)) {
115 /* Wine strips off the trailing '\\'. Neither Win98 nor Win2k do this. */
116     todo_wine {
117       ok(strptr==NULL,
118          "%s: GetFullPathNameA should not return a filename ptr",errstr);
119       ok(lstrcmpiA(fullpath,tmpstr)==0,
120          "%s: GetFullPathNameA returned '%s' instead of '%s'",
121          errstr,tmpstr,fullpath);
122     }
123   } else {
124     ok(lstrcmpiA(strptr,filename)==0,
125        "%s: GetFullPathNameA returned '%s' instead of '%s'",
126        errstr,strptr,filename);
127     ok(lstrcmpiA(fullpath,tmpstr)==0,
128        "%s: GetFullPathNameA returned '%s' instead of '%s'",
129        errstr,tmpstr,fullpath);
130   }
131 /* Test GetShortPathNameA functionality */
132   SetLastError(0);
133   len=GetShortPathNameA(fullpathshort,shortstr,MAX_PATH);
134   if(passfail==NULL) {
135     ok(len, "%s: GetShortPathNameA failed",errstr);
136   } else {
137     passfail->shortlen=len;
138     passfail->shorterror=GetLastError();
139   }
140 /* Test GetLongPathNameA functionality
141    We test both conversion from GetFullPathNameA and from GetShortPathNameA
142 */
143   if(pGetLongPathNameA) {
144     if(len==0) {
145       SetLastError(0);
146       len=pGetLongPathNameA(shortstr,tmpstr,MAX_PATH);
147       if(passfail==NULL) {
148         ok(len,
149           "%s: GetLongPathNameA failed during Short->Long conversion", errstr);
150         ok(lstrcmpiA(fullpathlong,tmpstr)==0,
151            "%s: GetLongPathNameA returned '%s' instead of '%s'",
152            errstr,tmpstr,fullpathlong);
153       } else {
154         passfail->s2llen=len;
155         passfail->s2lerror=GetLastError();
156       }
157     }
158     SetLastError(0);
159     len=pGetLongPathNameA(fullpath,tmpstr,MAX_PATH);
160     if(passfail==NULL) {
161       ok(len, "%s: GetLongPathNameA failed",errstr);
162       if(HAS_TRAIL_SLASH_A(fullpath)) {
163 /* Wine strips off the trailing '\\'  Neither Win98 nor Win2k do this */
164         todo_wine {
165           ok(lstrcmpiA(fullpathlong,tmpstr)==0,
166            "%s: GetLongPathNameA returned '%s' instead of '%s'",
167            errstr,tmpstr,fullpathlong);
168         }
169       } else {
170         ok(lstrcmpiA(fullpathlong,tmpstr)==0,
171           "%s: GetLongPathNameA returned '%s' instead of '%s'",
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'",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");
215 }
216
217 /* Check that GetShortPathNameA returns a valid 8.3 path */
218 static void test_LongtoShortA(CHAR *teststr,CHAR *goodstr,
219                               CHAR *ext,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'",dir,goodstr);
225   ok(lstrcmpiA(three,ext)==0,
226      "GetShortPathNameA returned '%s' with incorrect extension",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' indictaes that wine doesn't get this right yet.
233    NOTE: We always call this routine with a non-existent filename, so
234          Get(Short|Long)PathNameA should never pass, but GetFullPathNameA
235          should.
236 */
237 static void test_FunnyChars(CHAR *curdir,CHAR *filename,
238                              INT valid,INT todo,CHAR *errstr) {
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,filename);
245     if(todo) {
246       todo_wine {
247         ok((passfail.shortlen==0 &&
248             (passfail.shorterror==ERROR_FILE_NOT_FOUND || passfail.shorterror==ERROR_PATH_NOT_FOUND || !passfail.shorterror)) ||
249            (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
250            "%s: GetShortPathNameA error: len=%ld error=%ld tmpstr=[%s]",
251            errstr,passfail.shortlen,passfail.shorterror,tmpstr);
252       }
253     } else {
254       ok((passfail.shortlen==0 &&
255           (passfail.shorterror==ERROR_FILE_NOT_FOUND || passfail.shorterror==ERROR_PATH_NOT_FOUND || !passfail.shorterror)) ||
256          (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
257          "%s: GetShortPathNameA error: len=%ld error=%ld tmpstr=[%s]",
258          errstr,passfail.shortlen,passfail.shorterror,tmpstr);
259     }
260   } else {
261     if(todo) {
262       todo_wine {
263 /* Win2k returns ERROR_INVALID_NAME, Win98, wine return ERROR_FILE_NOT_FOUND, NT4 doesn't set last error */
264         ok(passfail.shortlen==0 &&
265            (passfail.shorterror==ERROR_INVALID_NAME || passfail.shorterror==ERROR_FILE_NOT_FOUND || !passfail.shorterror),
266            "%s: GetShortPathA should have failed len=%ld, error=%ld",
267            errstr,passfail.shortlen,passfail.shorterror);
268       }
269     } else {
270       ok(passfail.shortlen==0 &&
271          (passfail.shorterror==ERROR_INVALID_NAME || passfail.shorterror==ERROR_FILE_NOT_FOUND || !passfail.shorterror),
272          "%s: GetShortPathA should have failed len=%ld, error=%ld",
273          errstr,passfail.shortlen,passfail.shorterror);
274     }
275   }
276   if(pGetLongPathNameA) {
277     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have");
278     if(valid) {
279       ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
280          "%s: GetLongPathA returned %ld and not %d",
281          errstr,passfail.longerror,ERROR_FILE_NOT_FOUND);
282     } else {
283       ok(passfail.longerror==ERROR_INVALID_NAME ||
284          passfail.longerror==ERROR_FILE_NOT_FOUND,
285          "%s: GetLongPathA returned %ld and not %d or %d'",
286          errstr, passfail.longerror,ERROR_INVALID_NAME,ERROR_FILE_NOT_FOUND);
287     }
288   }
289 }
290
291 /* Routine to test that SetCurrentDirectory behaves as expected. */
292 static void test_setdir(CHAR *olddir,CHAR *newdir,
293                         CHAR *cmprstr, INT pass,CHAR *errstr)
294 {
295   CHAR tmppath[MAX_PATH], *dirptr;
296   DWORD val,len,chklen;
297
298   val=SetCurrentDirectoryA(newdir);
299   len=GetCurrentDirectoryA(MAX_PATH,tmppath);
300 /* if 'pass' then the SetDirectoryA was supposed to pass */
301   if(pass) {
302     dirptr=(cmprstr==NULL) ? newdir : cmprstr;
303     chklen=lstrlenA(dirptr);
304     ok(val,"%s: SetCurrentDirectoryA failed",errstr);
305     ok(len==chklen,
306        "%s: SetCurrentDirectory did not change the directory, though it passed",
307        errstr);
308     ok(lstrcmpiA(dirptr,tmppath)==0,
309        "%s: SetCurrentDirectory did not change the directory, though it passed",
310        errstr);
311     ok(SetCurrentDirectoryA(olddir),
312        "%s: Couldn't set directory to it's original value",errstr);
313   } else {
314 /* else thest that it fails correctly */
315     chklen=lstrlenA(olddir);
316     ok(val==0,
317        "%s: SetCurrentDirectoryA passed when it should have failed",errstr);
318     ok(len==chklen,
319        "%s: SetCurrentDirectory changed the directory, though it failed",
320        errstr);
321     ok(lstrcmpiA(olddir,tmppath)==0,
322        "%s: SetCurrentDirectory changed the directory, though it failed",
323        errstr);
324   }
325 }
326 static void test_InitPathA(CHAR *newdir, CHAR *curDrive, CHAR *otherDrive)
327 {
328   CHAR tmppath[MAX_PATH], /*path to TEMP */
329        tmpstr[MAX_PATH],
330        tmpstr1[MAX_PATH];
331   DWORD len,len1,drives;
332   INT id;
333   HANDLE hndl;
334
335   *curDrive = *otherDrive = NOT_A_VALID_DRIVE;
336
337 /* Get the current drive letter */
338   if( GetCurrentDirectoryA( MAX_PATH, tmpstr))
339     *curDrive = tmpstr[0];
340   else
341     trace( "Unable to discover current drive, some tests will not be conducted.\n");
342
343 /* Test GetTempPathA */
344   len=GetTempPathA(MAX_PATH,tmppath);
345   ok(len!=0 && len < MAX_PATH,"GetTempPathA failed");
346   ok(HAS_TRAIL_SLASH_A(tmppath),
347      "GetTempPathA returned a path that did not end in '\\'");
348   lstrcpyA(tmpstr,"aaaaaaaa");
349   len1=GetTempPathA(len,tmpstr);
350   ok(len1==len+1,
351      "GetTempPathA should return string length %ld instead of %ld",len+1,len1);
352
353 /* Test GetTmpFileNameA
354    The only test we do here is whether GetTempFileNameA passes or not.
355    We do not thoroughly test this function yet (specifically, whether
356    it behaves correctly when 'unique' is non zero)
357 */
358   ok((id=GetTempFileNameA(tmppath,"path",0,newdir)),"GetTempFileNameA failed");
359   sprintf(tmpstr,"pat%.4x.tmp",id & 0xffff);
360   sprintf(tmpstr1,"pat%x.tmp",id & 0xffff);
361   ok(lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr)==0 ||
362      lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr1)==0,
363      "GetTempPath returned '%s' which doesn't match '%s' or '%s'. id=%x",
364      newdir,tmpstr,tmpstr1,id);
365
366 /* Find first valid drive letter that is neither newdir[0] nor curDrive */
367   drives = GetLogicalDrives() & ~(1<<(newdir[0]-'A'));
368   if( *curDrive != NOT_A_VALID_DRIVE)
369     drives &= ~(1<<(*curDrive-'A'));
370   if( drives)
371     for( *otherDrive='A'; (drives & 1) == 0; drives>>=1, (*otherDrive)++);
372   else
373     trace( "Could not find alternative drive, some tests will not be conducted.\n");
374
375 /* Do some CreateDirectoryA tests */
376 /* It would be nice to do test the SECURITY_ATTRIBUTES, but I don't
377    really understand how they work.
378    More formal tests should be done along with CreateFile tests
379 */
380   ok(CreateDirectoryA(newdir,NULL)==0,
381      "CreateDirectoryA succeeded even though a file of the same name exists");
382   ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created");
383   ok(CreateDirectoryA(newdir,NULL),"CreateDirectoryA failed");
384 /* Create some files to test other functions.  Note, we will test CreateFileA
385    at some later point
386 */
387   sprintf(tmpstr,"%s\\%s",newdir,SHORTDIR);
388   ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed");
389   sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
390   ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed");
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");
395   ok(CloseHandle(hndl),"CloseHandle failed");
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");
400   ok(CloseHandle(hndl),"CloseHandle failed");
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");
405   ok(CloseHandle(hndl),"CloseHandle failed");
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");
410   ok(CloseHandle(hndl),"CloseHandle failed");
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");
423   ok(lstrcmpiA(origdir+(len-1),"\\")!=0,
424      "GetCurrentDirectoryA should not have a trailing \\");
425 /* Make sure that CetCurrentDirectoryA doesn't overwrite the buffer when the
426    buffer size is too small to hold the current directory
427 */
428   lstrcpyA(tmpstr,"aaaaaaa");
429   len1=GetCurrentDirectoryA(len,tmpstr);
430   ok(len1==len+1, "GetCurrentDirectoryA returned %ld instead of %ld",len1,len+1);
431   ok(lstrcmpiA(tmpstr,"aaaaaaa")==0,
432      "GetCurrentDirectoryA should not have modified the buffer");
433 /* SetCurrentDirectoryA shouldn't care whether the string has a
434    trailing '\\' or not
435 */
436   sprintf(tmpstr,"%s\\",newdir);
437   test_setdir(origdir,tmpstr,newdir,1,"check 1");
438   test_setdir(origdir,newdir,NULL,1,"check 2");
439 /* Set the directory to the working area.  We just tested that this works,
440    so why check it again.
441 */
442   SetCurrentDirectoryA(newdir);
443 /* Check that SetCurrentDirectory fails when a non-existent dir is specified */
444   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_SHORT);
445   test_setdir(newdir,tmpstr,NULL,0,"check 3");
446 /* Check that SetCurrentDirectory fails for a non-existent lond directory */
447   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_LONG);
448   test_setdir(newdir,tmpstr,NULL,0,"check 4");
449 /* Check that SetCurrentDirectory passes with a long directory */
450   sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
451   test_setdir(newdir,tmpstr,NULL,1,"check 5");
452 /* Check that SetCurrentDirectory passes with a short relative directory */
453   sprintf(tmpstr,"%s",SHORTDIR);
454   sprintf(tmpstr1,"%s\\%s",newdir,SHORTDIR);
455   test_setdir(newdir,tmpstr,tmpstr1,1,"check 6");
456 /* starting with a '.' */
457   sprintf(tmpstr,".\\%s",SHORTDIR);
458   test_setdir(newdir,tmpstr,tmpstr1,1,"check 7");
459 /* Check that SetCurrentDirectory passes with a short relative directory */
460   sprintf(tmpstr,"%s",LONGDIR);
461   sprintf(tmpstr1,"%s\\%s",newdir,LONGDIR);
462   test_setdir(newdir,tmpstr,tmpstr1,1,"check 8");
463 /* starting with a '.' */
464   sprintf(tmpstr,".\\%s",LONGDIR);
465   test_setdir(newdir,tmpstr,tmpstr1,1,"check 9");
466 }
467
468 /* Cleanup the mess we made while executing these tests */
469 static void test_CleanupPathA(CHAR *origdir, CHAR *curdir)
470 {
471   CHAR tmpstr[MAX_PATH];
472   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
473   ok(DeleteFileA(tmpstr),"DeleteFileA failed");
474   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,LONGFILE);
475   ok(DeleteFileA(tmpstr),"DeleteFileA failed");
476   sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,SHORTFILE);
477   ok(DeleteFileA(tmpstr),"DeleteFileA failed");
478   sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
479   ok(DeleteFileA(tmpstr),"DeleteFileA failed");
480   sprintf(tmpstr,"%s\\%s",curdir,SHORTDIR);
481   ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed");
482   sprintf(tmpstr,"%s\\%s",curdir,LONGDIR);
483   ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed");
484   ok(SetCurrentDirectoryA(origdir),"SetCurrentDirectoryA failed");
485   ok(RemoveDirectoryA(curdir),"RemoveDirectoryA failed");
486 }
487
488 /* This routine will test Get(Full|Short|Long)PathNameA */
489 static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive)
490 {
491   CHAR curdir_short[MAX_PATH],
492        longdir_short[MAX_PATH];
493   CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH],tmpstr2[MAX_PATH];
494   LPSTR strptr;                 /*ptr to the filename portion of the path */
495   DWORD len;
496   INT i;
497   CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
498   SLpassfail passfail;
499
500 /* Get the short form of the current directory */
501   ok((len=GetShortPathNameA(curdir,curdir_short,MAX_PATH)),
502      "GetShortPathNameA failed");
503   ok(!HAS_TRAIL_SLASH_A(curdir_short),
504      "GetShortPathNameA should not have a trailing \\");
505 /* Get the short form of the absolute-path to LONGDIR */
506   sprintf(tmpstr,"%s\\%s",curdir_short,LONGDIR);
507   ok((len=GetShortPathNameA(tmpstr,longdir_short,MAX_PATH)),
508      "GetShortPathNameA failed");
509   ok(lstrcmpiA(longdir_short+(len-1),"\\")!=0,
510      "GetShortPathNameA should not have a trailing \\");
511
512   if (pGetLongPathNameA) {
513     DWORD rc1,rc2;
514     sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
515     rc1=(*pGetLongPathNameA)(tmpstr,NULL,0);
516     rc2=(*pGetLongPathNameA)(curdir,NULL,0);
517     ok((rc1-strlen(tmpstr))==(rc2-strlen(curdir)),
518        "GetLongPathNameA: wrong return code, %ld instead of %d",
519        rc1, strlen(tmpstr)+1);
520
521     todo_wine {
522         sprintf(dir,"%c:",curDrive);
523         rc1=(*pGetLongPathNameA)(dir,tmpstr,sizeof(tmpstr));
524         ok(strcmp(dir,tmpstr)==0,
525            "GetLongPathNameA: returned '%s' instead of '%s' (rc=%ld)",
526            tmpstr,dir,rc1);
527     }
528   }
529
530 /* Check the cases where both file and directory exist first */
531 /* Start with a 8.3 directory, 8.3 filename */
532   test_ValidPathA(curdir,SHORTDIR,SHORTFILE,tmpstr,NULL,"test1");
533   sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,SHORTFILE);
534   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
535      "GetShortPathNameA returned '%s' instead of '%s'",tmpstr,tmpstr1);
536 /* Now try a 8.3 directory, long file name */
537   test_ValidPathA(curdir,SHORTDIR,LONGFILE,tmpstr,NULL,"test2");
538   sprintf(tmpstr1,"%s\\%s",curdir_short,SHORTDIR);
539   test_LongtoShortA(tmpstr,tmpstr1,"PAT","test2");
540 /* Next is a long directory, 8.3 file */
541   test_ValidPathA(curdir,LONGDIR,SHORTFILE,tmpstr,NULL,"test3");
542   sprintf(tmpstr1,"%s\\%s",longdir_short,SHORTFILE);
543   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
544      "GetShortPathNameA returned '%s' instead of '%s'",tmpstr,tmpstr1);
545 /*Lastly a long directory, long file */
546   test_ValidPathA(curdir,LONGDIR,LONGFILE,tmpstr,NULL,"test4");
547   test_LongtoShortA(tmpstr,longdir_short,"PAT","test4");
548
549 /* Now check all of the invalid file w/ valid directory combinations */
550 /* Start with a 8.3 directory, 8.3 filename */
551   test_ValidPathA(curdir,SHORTDIR,NONFILE_SHORT,tmpstr,&passfail,"test5");
552   sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,NONFILE_SHORT);
553   ok((passfail.shortlen==0 &&
554       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
555        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
556      (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
557      "GetShortPathNameA error: len=%ld error=%ld tmpstr=[%s]",
558      passfail.shortlen,passfail.shorterror,tmpstr);
559   if(pGetLongPathNameA) {
560     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have");
561     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
562        "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'");
563   }
564 /* Now try a 8.3 directory, long file name */
565   test_ValidPathA(curdir,SHORTDIR,NONFILE_LONG,tmpstr,&passfail,"test6");
566   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have");
567   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
568      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
569      !passfail.shorterror,
570      "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'");
571   if(pGetLongPathNameA) {
572     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have");
573     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
574        "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'");
575   }
576 /* Next is a long directory, 8.3 file */
577   test_ValidPathA(curdir,LONGDIR,NONFILE_SHORT,tmpstr,&passfail,"test7");
578   sprintf(tmpstr2,"%s\\%s",curdir_short,LONGDIR);
579   GetShortPathNameA(tmpstr2,tmpstr1,MAX_PATH);
580   strcat(tmpstr1,"\\" NONFILE_SHORT);
581   ok((passfail.shortlen==0 &&
582       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
583        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
584      (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
585      "GetShortPathNameA error: len=%ld error=%ld tmpstr=[%s]",
586      passfail.shortlen,passfail.shorterror,tmpstr);
587   if(pGetLongPathNameA) {
588     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have");
589     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
590       "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'");
591   }
592 /*Lastly a long directory, long file */
593   test_ValidPathA(curdir,LONGDIR,NONFILE_LONG,tmpstr,&passfail,"test8");
594   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have");
595   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
596      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
597      !passfail.shorterror,
598      "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'");
599   if(pGetLongPathNameA) {
600     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have");
601     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
602        "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'");
603   }
604 /* Now try again with directories that don't exist */
605 /* 8.3 directory, 8.3 filename */
606   test_ValidPathA(curdir,NONDIR_SHORT,SHORTFILE,tmpstr,&passfail,"test9");
607   sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,NONDIR_SHORT,SHORTFILE);
608   ok((passfail.shortlen==0 &&
609       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
610        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
611      (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
612      "GetShortPathNameA error: len=%ld error=%ld tmpstr=[%s]",
613      passfail.shortlen,passfail.shorterror,tmpstr);
614   if(pGetLongPathNameA) {
615     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have");
616     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
617        passfail.longerror==ERROR_FILE_NOT_FOUND,
618        "GetLongPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'",
619        passfail.longerror);
620   }
621 /* Now try a 8.3 directory, long file name */
622   test_ValidPathA(curdir,NONDIR_SHORT,LONGFILE,tmpstr,&passfail,"test10");
623   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have");
624   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
625      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
626      !passfail.shorterror,
627      "GetShortPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'",
628       passfail.shorterror);
629   if(pGetLongPathNameA) {
630     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have");
631     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
632        passfail.longerror==ERROR_FILE_NOT_FOUND,
633        "GetLongPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'",
634        passfail.longerror);
635   }
636 /* Next is a long directory, 8.3 file */
637   test_ValidPathA(curdir,NONDIR_LONG,SHORTFILE,tmpstr,&passfail,"test11");
638   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have");
639   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
640      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
641      !passfail.shorterror,
642      "GetShortPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'",
643       passfail.shorterror);
644   if(pGetLongPathNameA) {
645     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have");
646     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
647        passfail.longerror==ERROR_FILE_NOT_FOUND,
648        "GetLongPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'",
649        passfail.longerror);
650   }
651 /*Lastly a long directory, long file */
652   test_ValidPathA(curdir,NONDIR_LONG,LONGFILE,tmpstr,&passfail,"test12");
653   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have");
654   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
655      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
656      !passfail.shorterror,
657      "GetShortPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'",
658       passfail.shorterror);
659   if(pGetLongPathNameA) {
660     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have");
661     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
662        passfail.longerror==ERROR_FILE_NOT_FOUND,
663        "GetLongPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'",
664        passfail.longerror);
665   }
666 /* Next try directories ending with '\\' */
667 /* Existing Directories */
668   sprintf(tmpstr,"%s\\",SHORTDIR);
669   test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test13");
670   sprintf(tmpstr,"%s\\",LONGDIR);
671   test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test14");
672 /* Non-existent directories */
673   sprintf(tmpstr,"%s\\",NONDIR_SHORT);
674   test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test15");
675   sprintf(tmpstr2,"%s\\%s",curdir,tmpstr);
676   ok((passfail.shortlen==0 &&
677       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
678        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
679      (passfail.shortlen==strlen(tmpstr2) && lstrcmpiA(tmpstr1,tmpstr2)==0),
680      "GetShortPathNameA error: len=%ld error=%ld tmpstr=[%s]",
681      passfail.shortlen,passfail.shorterror,tmpstr);
682   if(pGetLongPathNameA) {
683     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have");
684     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
685        "GetLongPathA returned %ld and not 'ERROR_FILE_NOT_FOUND'",
686        passfail.longerror);
687   }
688   sprintf(tmpstr,"%s\\",NONDIR_LONG);
689   test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test16");
690   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have");
691   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
692      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
693      !passfail.shorterror,
694      "GetShortPathA returned %ld and not 'ERROR_FILE_NOT_FOUND'",
695       passfail.shorterror);
696   if(pGetLongPathNameA) {
697     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have");
698     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
699        "GetLongPathA returned %ld and not 'ERROR_FILE_NOT_FOUND'",
700        passfail.longerror);
701   }
702 /* Test GetFullPathNameA with drive letters */
703   if( curDrive != NOT_A_VALID_DRIVE) {
704     sprintf(tmpstr,"%c:",curdir[0]);
705     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr2,&strptr),
706        "GetFullPathNameA(%c:) failed", curdir[0]);
707     GetCurrentDirectoryA(MAX_PATH,tmpstr);
708     sprintf(tmpstr1,"%s\\",tmpstr);
709     ok(lstrcmpiA(tmpstr,tmpstr2)==0 || lstrcmpiA(tmpstr1,tmpstr2)==0,
710        "GetFullPathNameA(%c:) returned '%s' instead of '%s' or '%s'",
711        curdir[0],tmpstr2,tmpstr,tmpstr1);
712
713     sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
714     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed");
715     ok(lstrcmpiA(tmpstr,tmpstr1)==0,
716        "GetFullPathNameA returned '%s' instead of '%s'",tmpstr1,tmpstr);
717     ok(lstrcmpiA(SHORTFILE,strptr)==0,
718        "GetFullPathNameA returned part '%s' instead of '%s'",strptr,SHORTFILE);
719   }
720 /* Without a leading slash, insert the current directory if on the current drive */
721   sprintf(tmpstr,"%c:%s\\%s",curdir[0],SHORTDIR,SHORTFILE);
722   ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed");
723   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
724   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
725       "GetFullPathNameA returned '%s' instead of '%s'",tmpstr1,tmpstr);
726   ok(lstrcmpiA(SHORTFILE,strptr)==0,
727       "GetFullPathNameA returned part '%s' instead of '%s'",strptr,SHORTFILE);
728 /* Otherwise insert the missing leading slash */
729   if( otherDrive != NOT_A_VALID_DRIVE) {
730     sprintf(tmpstr,"%c:%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
731     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed for %s", tmpstr);
732     sprintf(tmpstr,"%c:\\%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
733     ok(lstrcmpiA(tmpstr,tmpstr1)==0,
734        "GetFullPathNameA returned '%s' instead of '%s'",tmpstr1,tmpstr);
735     ok(lstrcmpiA(SHORTFILE,strptr)==0,
736        "GetFullPathNameA returned part '%s' instead of '%s'",strptr,SHORTFILE);
737   }
738 /* Xilinx tools like to mix Unix and DOS formats, which Windows handles fine.
739    So test for them. */
740   if( curDrive != NOT_A_VALID_DRIVE) {
741     sprintf(tmpstr,"%c:/%s\\%s",curDrive,SHORTDIR,SHORTFILE);
742     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed");
743     sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
744     ok(lstrcmpiA(tmpstr,tmpstr1)==0,
745        "GetFullPathNameA returned '%s' instead of '%s'",tmpstr1,tmpstr);
746     ok(lstrcmpiA(SHORTFILE,strptr)==0,
747        "GetFullPathNameA returned part '%s' instead of '%s'",strptr,SHORTFILE);
748   }
749 /**/
750   sprintf(tmpstr,"%c:%s/%s",curdir[0],SHORTDIR,SHORTFILE);
751   ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed");
752   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
753   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
754       "GetFullPathNameA returned '%s' instead of '%s'",tmpstr1,tmpstr);
755   ok(lstrcmpiA(SHORTFILE,strptr)==0,
756       "GetFullPathNameA returned part '%s' instead of '%s'",strptr,SHORTFILE);
757 /* Windows will insert a drive letter in front of an absolute UNIX path, but
758     Wine probably shouldn't. */
759   sprintf(tmpstr,"/%s/%s",SHORTDIR,SHORTFILE);
760   ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed");
761   todo_wine {
762     if( curDrive != NOT_A_VALID_DRIVE) {
763       sprintf(tmpstr,"C:\\%s\\%s",SHORTDIR,SHORTFILE);
764       ok(lstrcmpiA(tmpstr,tmpstr1)==0,
765          "GetFullPathNameA returned '%s' instead of '%s'",tmpstr1,tmpstr);
766     }
767   }
768 /* This passes in Wine because it still contains the pointer from the previous test */
769   ok(lstrcmpiA(SHORTFILE,strptr)==0,
770       "GetFullPathNameA returned part '%s' instead of '%s'",strptr,SHORTFILE);
771
772 /* Now try some relative paths */
773   ok(GetShortPathNameA(LONGDIR,tmpstr,MAX_PATH),"GetShortPathNameA failed");
774   test_SplitShortPathA(tmpstr,dir,eight,three);
775   if(pGetLongPathNameA) {
776     ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed");
777     todo_wine {
778       ok(lstrcmpiA(tmpstr1,LONGDIR)==0,
779          "GetLongPathNameA returned '%s' instead of '%s'",tmpstr1,LONGDIR);
780     }
781   }
782   sprintf(tmpstr,".\\%s",LONGDIR);
783   ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed");
784   test_SplitShortPathA(tmpstr1,dir,eight,three);
785   ok(lstrcmpiA(dir,".")==0 || dir[0]=='\0',
786      "GetShortPathNameA did not keep relative directory [%s]",tmpstr1);
787   if(pGetLongPathNameA) {
788     ok(pGetLongPathNameA(tmpstr1,tmpstr1,MAX_PATH),"GetShortPathNameA failed");
789     todo_wine {
790       ok(lstrcmpiA(tmpstr1,tmpstr)==0,
791          "GetLongPathNameA returned '%s' instead of '%s'",tmpstr1,tmpstr);
792     }
793   }
794 /* Check out Get*PathNameA on some funny characters */
795   for(i=0;i<lstrlenA(funny_chars);i++) {
796     INT valid,todo;
797     valid=(is_char_ok[i]=='0') ? 0 : 1;
798     todo=(wine_todo[i]=='0') ? 0 : 1;
799     sprintf(tmpstr1,"check%d-1",i);
800     sprintf(tmpstr,"file%c000.ext",funny_chars[i]);
801     test_FunnyChars(curdir,tmpstr,valid,todo,tmpstr1);
802     sprintf(tmpstr1,"check%d-2",i);
803     sprintf(tmpstr,"file000.e%ct",funny_chars[i]);
804     test_FunnyChars(curdir,tmpstr,valid,todo,tmpstr1);
805     sprintf(tmpstr1,"check%d-3",i);
806     sprintf(tmpstr,"%cfile000.ext",funny_chars[i]);
807     test_FunnyChars(curdir,tmpstr,valid,todo,tmpstr1);
808     sprintf(tmpstr1,"check%d-4",i);
809     sprintf(tmpstr,"file000%c.ext",funny_chars[i]);
810     test_FunnyChars(curdir,tmpstr,valid,todo,tmpstr1);
811     sprintf(tmpstr1,"check%d-5",i);
812     sprintf(tmpstr,"Long %c File",funny_chars[i]);
813     test_FunnyChars(curdir,tmpstr,valid,0,tmpstr1);
814     sprintf(tmpstr1,"check%d-6",i);
815     sprintf(tmpstr,"%c Long File",funny_chars[i]);
816     test_FunnyChars(curdir,tmpstr,valid,0,tmpstr1);
817     sprintf(tmpstr1,"check%d-7",i);
818     sprintf(tmpstr,"Long File %c",funny_chars[i]);
819     test_FunnyChars(curdir,tmpstr,valid,0,tmpstr1);
820   }
821 }
822
823 static void test_GetTempPathA(char* tmp_dir)
824 {
825     DWORD len, len_with_null;
826     char buf[MAX_PATH];
827
828     len_with_null = strlen(tmp_dir) + 1;
829
830     lstrcpyA(buf, "foo");
831     len = GetTempPathA(MAX_PATH, buf);
832     ok(len <= MAX_PATH, "should fit into MAX_PATH");
833     ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]",tmp_dir,buf);
834     ok(len == strlen(buf), "returned length should be equal to the length of string");
835
836     /* Some versions of Windows touch the buffer, some don't so we don't
837      * test that. Also, NT sometimes exagerates the required buffer size
838      * so we cannot test for an exact match. Finally, the
839      * 'len_with_null - 1' case is so buggy on Windows it's not testable.
840      * For instance in some cases Win98 returns len_with_null - 1 instead
841      * of len_with_null.
842      */
843     len = GetTempPathA(1, buf);
844     ok(len >= len_with_null, "Expected >= %lu, got %lu", len_with_null, len);
845
846     len = GetTempPathA(0, NULL);
847     ok(len >= len_with_null, "Expected >= %lu, got %lu", len_with_null, len);
848
849     /* The call above gave us the buffer size that Windows thinks is needed
850      * so the next call should work
851      */
852     lstrcpyA(buf, "foo");
853     len = GetTempPathA(len, buf);
854     ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]",tmp_dir,buf);
855     ok(len == strlen(buf), "returned length should be equal to the length of string");
856 }
857
858 static void test_GetTempPathW(char* tmp_dir)
859 {
860     DWORD len, len_with_null;
861     WCHAR buf[MAX_PATH];
862     WCHAR tmp_dirW[MAX_PATH];
863     static const WCHAR fooW[] = {'f','o','o',0};
864
865     MultiByteToWideChar(CP_ACP,0,tmp_dir,-1,tmp_dirW,sizeof(tmp_dirW)/sizeof(*tmp_dirW));
866     len_with_null = lstrlenW(tmp_dirW) + 1;
867
868     /* This one is different from ANSI version: ANSI version doesn't
869      * touch the buffer, unicode version usually truncates the buffer
870      * to zero size. NT still exagerates the required buffer size
871      * sometimes so we cannot test for an exact match. Finally, the
872      * 'len_with_null - 1' case is so buggy on Windows it's not testable.
873      * For instance on NT4 it will sometimes return a path without the
874      * trailing '\\' and sometimes return an error.
875      */
876
877     lstrcpyW(buf, fooW);
878     len = GetTempPathW(MAX_PATH, buf);
879     if (len==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
880         return;
881     ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path");
882     ok(len == lstrlenW(buf), "returned length should be equal to the length of string");
883
884     lstrcpyW(buf, fooW);
885     len = GetTempPathW(1, buf);
886     ok(buf[0] == 0, "unicode version should truncate the buffer to zero size");
887     ok(len >= len_with_null, "Expected >= %lu, got %lu", len_with_null, len);
888
889     len = GetTempPathW(0, NULL);
890     ok(len >= len_with_null, "Expected >= %lu, got %lu", len_with_null, len);
891
892     lstrcpyW(buf, fooW);
893     len = GetTempPathW(len, buf);
894     ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path");
895     ok(len == lstrlenW(buf), "returned length should be equal to the length of string");
896 }
897
898 static void test_GetTempPath(void)
899 {
900     char save_TMP[MAX_PATH];
901     char windir[MAX_PATH];
902     char buf[MAX_PATH];
903
904     GetEnvironmentVariableA("TMP", save_TMP, sizeof(save_TMP));
905
906     /* test default configuration */
907     trace("TMP=%s\n", save_TMP);
908     strcpy(buf,save_TMP);
909     if (buf[strlen(buf)-1]!='\\')
910         strcat(buf,"\\");
911     test_GetTempPathA(buf);
912     test_GetTempPathW(buf);
913
914     /* TMP=C:\WINDOWS */
915     GetWindowsDirectoryA(windir, sizeof(windir));
916     SetEnvironmentVariableA("TMP", windir);
917     GetEnvironmentVariableA("TMP", buf, sizeof(buf));
918     trace("TMP=%s\n", buf);
919     strcat(windir,"\\");
920     test_GetTempPathA(windir);
921     test_GetTempPathW(windir);
922
923     /* TMP=C:\ */
924     GetWindowsDirectoryA(windir, sizeof(windir));
925     windir[3] = 0;
926     SetEnvironmentVariableA("TMP", windir);
927     GetEnvironmentVariableA("TMP", buf, sizeof(buf));
928     trace("TMP=%s\n", buf);
929     test_GetTempPathA(windir);
930     test_GetTempPathW(windir);
931
932     /* TMP=C: i.e. use current working directory of the specified drive */
933     GetWindowsDirectoryA(windir, sizeof(windir));
934     SetCurrentDirectoryA(windir);
935     windir[2] = 0;
936     SetEnvironmentVariableA("TMP", windir);
937     GetEnvironmentVariableA("TMP", buf, sizeof(buf));
938     trace("TMP=%s\n", buf);
939     GetWindowsDirectoryA(windir, sizeof(windir));
940     strcat(windir,"\\");
941     test_GetTempPathA(windir);
942     test_GetTempPathW(windir);
943
944     SetEnvironmentVariableA("TMP", save_TMP);
945 }
946
947 START_TEST(path)
948 {
949     CHAR origdir[MAX_PATH],curdir[MAX_PATH], curDrive, otherDrive;
950     pGetLongPathNameA = (void*)GetProcAddress( GetModuleHandleA("kernel32.dll"),
951                                                "GetLongPathNameA" );
952     test_InitPathA(curdir, &curDrive, &otherDrive);
953     test_CurrentDirectoryA(origdir,curdir);
954     test_PathNameA(curdir, curDrive, otherDrive);
955     test_CleanupPathA(origdir,curdir);
956     test_GetTempPath();
957 }