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