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