Stub implementation for MsiGetFileHashA/W.
[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      "GetTempPath returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
339      newdir,tmpstr,tmpstr1,id);
340
341 /* Find first valid drive letter that is neither newdir[0] nor curDrive */
342   drives = GetLogicalDrives() & ~(1<<(newdir[0]-'A'));
343   if( *curDrive != NOT_A_VALID_DRIVE)
344     drives &= ~(1<<(*curDrive-'A'));
345   if( drives)
346     for( *otherDrive='A'; (drives & 1) == 0; drives>>=1, (*otherDrive)++);
347   else
348     trace( "Could not find alternative drive, some tests will not be conducted.\n");
349
350 /* Do some CreateDirectoryA tests */
351 /* It would be nice to do test the SECURITY_ATTRIBUTES, but I don't
352    really understand how they work.
353    More formal tests should be done along with CreateFile tests
354 */
355   ok(CreateDirectoryA(newdir,NULL)==0,
356      "CreateDirectoryA succeeded even though a file of the same name exists\n");
357   ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
358   ok(CreateDirectoryA(newdir,NULL),"CreateDirectoryA failed\n");
359 /* Create some files to test other functions.  Note, we will test CreateFileA
360    at some later point
361 */
362   sprintf(tmpstr,"%s\\%s",newdir,SHORTDIR);
363   ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed\n");
364   sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
365   ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed\n");
366   bRes = CreateDirectoryA("c:",NULL);
367   ok(!bRes && GetLastError() == ERROR_ACCESS_DENIED,
368      "CreateDirectoryA(\"c:\" should have failed (%ld)\n", GetLastError());
369   bRes = CreateDirectoryA("c:\\",NULL);
370   ok(!bRes && GetLastError() == ERROR_ACCESS_DENIED,
371      "CreateDirectoryA(\"c:\\\" should have failed (%ld)\n", GetLastError());
372   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,SHORTFILE);
373   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
374                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
375   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
376   ok(CloseHandle(hndl),"CloseHandle failed\n");
377   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,LONGFILE);
378   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
379                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
380   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
381   ok(CloseHandle(hndl),"CloseHandle failed\n");
382   sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,SHORTFILE);
383   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
384                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
385   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
386   ok(CloseHandle(hndl),"CloseHandle failed\n");
387   sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,LONGFILE);
388   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
389                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
390   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
391   ok(CloseHandle(hndl),"CloseHandle failed\n");
392 }
393
394 /* Test GetCurrentDirectory & SetCurrentDirectory */
395 static void test_CurrentDirectoryA(CHAR *origdir, CHAR *newdir)
396 {
397   CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
398   DWORD len,len1;
399 /* Save the original directory, so that we can return to it at the end
400    of the test
401 */
402   len=GetCurrentDirectoryA(MAX_PATH,origdir);
403   ok(len!=0 && len < MAX_PATH,"GetCurrentDirectoryA failed\n");
404 /* Make sure that CetCurrentDirectoryA doesn't overwrite the buffer when the
405    buffer size is too small to hold the current directory
406 */
407   lstrcpyA(tmpstr,"aaaaaaa");
408   len1=GetCurrentDirectoryA(len,tmpstr);
409   ok(len1==len+1, "GetCurrentDirectoryA returned %ld instead of %ld\n",len1,len+1);
410   ok(lstrcmpiA(tmpstr,"aaaaaaa")==0,
411      "GetCurrentDirectoryA should not have modified the buffer\n");
412 /* SetCurrentDirectoryA shouldn't care whether the string has a
413    trailing '\\' or not
414 */
415   sprintf(tmpstr,"%s\\",newdir);
416   test_setdir(origdir,tmpstr,newdir,1,"check 1");
417   test_setdir(origdir,newdir,NULL,1,"check 2");
418 /* Set the directory to the working area.  We just tested that this works,
419    so why check it again.
420 */
421   SetCurrentDirectoryA(newdir);
422 /* Check that SetCurrentDirectory fails when a nonexistent dir is specified */
423   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_SHORT);
424   test_setdir(newdir,tmpstr,NULL,0,"check 3");
425 /* Check that SetCurrentDirectory fails for a nonexistent lond directory */
426   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_LONG);
427   test_setdir(newdir,tmpstr,NULL,0,"check 4");
428 /* Check that SetCurrentDirectory passes with a long directory */
429   sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
430   test_setdir(newdir,tmpstr,NULL,1,"check 5");
431 /* Check that SetCurrentDirectory passes with a short relative directory */
432   sprintf(tmpstr,"%s",SHORTDIR);
433   sprintf(tmpstr1,"%s\\%s",newdir,SHORTDIR);
434   test_setdir(newdir,tmpstr,tmpstr1,1,"check 6");
435 /* starting with a '.' */
436   sprintf(tmpstr,".\\%s",SHORTDIR);
437   test_setdir(newdir,tmpstr,tmpstr1,1,"check 7");
438 /* Check that SetCurrentDirectory passes with a short relative directory */
439   sprintf(tmpstr,"%s",LONGDIR);
440   sprintf(tmpstr1,"%s\\%s",newdir,LONGDIR);
441   test_setdir(newdir,tmpstr,tmpstr1,1,"check 8");
442 /* starting with a '.' */
443   sprintf(tmpstr,".\\%s",LONGDIR);
444   test_setdir(newdir,tmpstr,tmpstr1,1,"check 9");
445 }
446
447 /* Cleanup the mess we made while executing these tests */
448 static void test_CleanupPathA(CHAR *origdir, CHAR *curdir)
449 {
450   CHAR tmpstr[MAX_PATH];
451   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
452   ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
453   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,LONGFILE);
454   ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
455   sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,SHORTFILE);
456   ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
457   sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
458   ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
459   sprintf(tmpstr,"%s\\%s",curdir,SHORTDIR);
460   ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
461   sprintf(tmpstr,"%s\\%s",curdir,LONGDIR);
462   ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
463   ok(SetCurrentDirectoryA(origdir),"SetCurrentDirectoryA failed\n");
464   ok(RemoveDirectoryA(curdir),"RemoveDirectoryA failed\n");
465 }
466
467 /* This routine will test Get(Full|Short|Long)PathNameA */
468 static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive)
469 {
470   CHAR curdir_short[MAX_PATH],
471        longdir_short[MAX_PATH];
472   CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH],tmpstr2[MAX_PATH];
473   LPSTR strptr;                 /*ptr to the filename portion of the path */
474   DWORD len;
475   INT i;
476   CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
477   SLpassfail passfail;
478
479 /* Get the short form of the current directory */
480   ok((len=GetShortPathNameA(curdir,curdir_short,MAX_PATH)),
481      "GetShortPathNameA failed\n");
482   ok(!HAS_TRAIL_SLASH_A(curdir_short),
483      "GetShortPathNameA should not have a trailing \\\n");
484 /* Get the short form of the absolute-path to LONGDIR */
485   sprintf(tmpstr,"%s\\%s",curdir_short,LONGDIR);
486   ok((len=GetShortPathNameA(tmpstr,longdir_short,MAX_PATH)),
487      "GetShortPathNameA failed\n");
488   ok(lstrcmpiA(longdir_short+(len-1),"\\")!=0,
489      "GetShortPathNameA should not have a trailing \\\n");
490
491   if (pGetLongPathNameA) {
492     DWORD rc1,rc2;
493     sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
494     rc1=(*pGetLongPathNameA)(tmpstr,NULL,0);
495     rc2=(*pGetLongPathNameA)(curdir,NULL,0);
496     ok((rc1-strlen(tmpstr))==(rc2-strlen(curdir)),
497        "GetLongPathNameA: wrong return code, %ld instead of %d\n",
498        rc1, strlen(tmpstr)+1);
499
500     sprintf(dir,"%c:",curDrive);
501     rc1=(*pGetLongPathNameA)(dir,tmpstr,sizeof(tmpstr));
502     ok(strcmp(dir,tmpstr)==0,
503        "GetLongPathNameA: returned '%s' instead of '%s' (rc=%ld)\n",
504        tmpstr,dir,rc1);
505   }
506
507 /* Check the cases where both file and directory exist first */
508 /* Start with a 8.3 directory, 8.3 filename */
509   test_ValidPathA(curdir,SHORTDIR,SHORTFILE,tmpstr,NULL,"test1");
510   sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,SHORTFILE);
511   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
512      "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
513 /* Now try a 8.3 directory, long file name */
514   test_ValidPathA(curdir,SHORTDIR,LONGFILE,tmpstr,NULL,"test2");
515   sprintf(tmpstr1,"%s\\%s",curdir_short,SHORTDIR);
516   test_LongtoShortA(tmpstr,tmpstr1,"PAT","test2");
517 /* Next is a long directory, 8.3 file */
518   test_ValidPathA(curdir,LONGDIR,SHORTFILE,tmpstr,NULL,"test3");
519   sprintf(tmpstr1,"%s\\%s",longdir_short,SHORTFILE);
520   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
521      "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
522 /*Lastly a long directory, long file */
523   test_ValidPathA(curdir,LONGDIR,LONGFILE,tmpstr,NULL,"test4");
524   test_LongtoShortA(tmpstr,longdir_short,"PAT","test4");
525
526 /* Now check all of the invalid file w/ valid directory combinations */
527 /* Start with a 8.3 directory, 8.3 filename */
528   test_ValidPathA(curdir,SHORTDIR,NONFILE_SHORT,tmpstr,&passfail,"test5");
529   sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,NONFILE_SHORT);
530   ok((passfail.shortlen==0 &&
531       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
532        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
533      (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
534      "GetShortPathNameA error: len=%ld error=%ld tmpstr=[%s]\n",
535      passfail.shortlen,passfail.shorterror,tmpstr);
536   if(pGetLongPathNameA) {
537     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
538     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
539        "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
540   }
541 /* Now try a 8.3 directory, long file name */
542   test_ValidPathA(curdir,SHORTDIR,NONFILE_LONG,tmpstr,&passfail,"test6");
543   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
544   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
545      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
546      !passfail.shorterror,
547      "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
548   if(pGetLongPathNameA) {
549     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
550     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
551        "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
552   }
553 /* Next is a long directory, 8.3 file */
554   test_ValidPathA(curdir,LONGDIR,NONFILE_SHORT,tmpstr,&passfail,"test7");
555   sprintf(tmpstr2,"%s\\%s",curdir_short,LONGDIR);
556   GetShortPathNameA(tmpstr2,tmpstr1,MAX_PATH);
557   strcat(tmpstr1,"\\" NONFILE_SHORT);
558   ok((passfail.shortlen==0 &&
559       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
560        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
561      (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
562      "GetShortPathNameA error: len=%ld error=%ld tmpstr=[%s]\n",
563      passfail.shortlen,passfail.shorterror,tmpstr);
564   if(pGetLongPathNameA) {
565     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
566     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
567       "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
568   }
569 /*Lastly a long directory, long file */
570   test_ValidPathA(curdir,LONGDIR,NONFILE_LONG,tmpstr,&passfail,"test8");
571   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
572   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
573      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
574      !passfail.shorterror,
575      "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
576   if(pGetLongPathNameA) {
577     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
578     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
579        "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
580   }
581 /* Now try again with directories that don't exist */
582 /* 8.3 directory, 8.3 filename */
583   test_ValidPathA(curdir,NONDIR_SHORT,SHORTFILE,tmpstr,&passfail,"test9");
584   sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,NONDIR_SHORT,SHORTFILE);
585   ok((passfail.shortlen==0 &&
586       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
587        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
588      (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
589      "GetShortPathNameA error: len=%ld error=%ld tmpstr=[%s]\n",
590      passfail.shortlen,passfail.shorterror,tmpstr);
591   if(pGetLongPathNameA) {
592     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
593     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
594        passfail.longerror==ERROR_FILE_NOT_FOUND,
595        "GetLongPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'\n",
596        passfail.longerror);
597   }
598 /* Now try a 8.3 directory, long file name */
599   test_ValidPathA(curdir,NONDIR_SHORT,LONGFILE,tmpstr,&passfail,"test10");
600   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
601   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
602      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
603      !passfail.shorterror,
604      "GetShortPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'\n",
605       passfail.shorterror);
606   if(pGetLongPathNameA) {
607     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
608     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
609        passfail.longerror==ERROR_FILE_NOT_FOUND,
610        "GetLongPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'\n",
611        passfail.longerror);
612   }
613 /* Next is a long directory, 8.3 file */
614   test_ValidPathA(curdir,NONDIR_LONG,SHORTFILE,tmpstr,&passfail,"test11");
615   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
616   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
617      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
618      !passfail.shorterror,
619      "GetShortPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'\n",
620       passfail.shorterror);
621   if(pGetLongPathNameA) {
622     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
623     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
624        passfail.longerror==ERROR_FILE_NOT_FOUND,
625        "GetLongPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'\n",
626        passfail.longerror);
627   }
628 /*Lastly a long directory, long file */
629   test_ValidPathA(curdir,NONDIR_LONG,LONGFILE,tmpstr,&passfail,"test12");
630   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
631   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
632      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
633      !passfail.shorterror,
634      "GetShortPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'\n",
635       passfail.shorterror);
636   if(pGetLongPathNameA) {
637     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
638     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
639        passfail.longerror==ERROR_FILE_NOT_FOUND,
640        "GetLongPathA returned %ld and not 'ERROR_PATH_NOT_FOUND'\n",
641        passfail.longerror);
642   }
643 /* Next try directories ending with '\\' */
644 /* Existing Directories */
645   sprintf(tmpstr,"%s\\",SHORTDIR);
646   test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test13");
647   sprintf(tmpstr,"%s\\",LONGDIR);
648   test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test14");
649 /* Nonexistent directories */
650   sprintf(tmpstr,"%s\\",NONDIR_SHORT);
651   test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test15");
652   sprintf(tmpstr2,"%s\\%s",curdir_short,tmpstr);
653   ok((passfail.shortlen==0 &&
654       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
655        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
656      (passfail.shortlen==strlen(tmpstr2) && lstrcmpiA(tmpstr1,tmpstr2)==0),
657      "GetShortPathNameA error: len=%ld error=%ld tmpstr=[%s]\n",
658      passfail.shortlen,passfail.shorterror,tmpstr);
659   if(pGetLongPathNameA) {
660     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
661     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
662        "GetLongPathA returned %ld and not 'ERROR_FILE_NOT_FOUND'\n",
663        passfail.longerror);
664   }
665   sprintf(tmpstr,"%s\\",NONDIR_LONG);
666   test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test16");
667   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
668   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
669      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
670      !passfail.shorterror,
671      "GetShortPathA returned %ld and not 'ERROR_FILE_NOT_FOUND'\n",
672       passfail.shorterror);
673   if(pGetLongPathNameA) {
674     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
675     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
676        "GetLongPathA returned %ld and not 'ERROR_FILE_NOT_FOUND'\n",
677        passfail.longerror);
678   }
679 /* Test GetFullPathNameA with drive letters */
680   if( curDrive != NOT_A_VALID_DRIVE) {
681     sprintf(tmpstr,"%c:",curdir[0]);
682     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr2,&strptr),
683        "GetFullPathNameA(%c:) failed\n", curdir[0]);
684     GetCurrentDirectoryA(MAX_PATH,tmpstr);
685     sprintf(tmpstr1,"%s\\",tmpstr);
686     ok(lstrcmpiA(tmpstr,tmpstr2)==0 || lstrcmpiA(tmpstr1,tmpstr2)==0,
687        "GetFullPathNameA(%c:) returned '%s' instead of '%s' or '%s'\n",
688        curdir[0],tmpstr2,tmpstr,tmpstr1);
689
690     sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
691     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
692     ok(lstrcmpiA(tmpstr,tmpstr1)==0,
693        "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
694     ok(lstrcmpiA(SHORTFILE,strptr)==0,
695        "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
696   }
697 /* Without a leading slash, insert the current directory if on the current drive */
698   sprintf(tmpstr,"%c:%s\\%s",curdir[0],SHORTDIR,SHORTFILE);
699   ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
700   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
701   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
702       "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
703   ok(lstrcmpiA(SHORTFILE,strptr)==0,
704       "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
705 /* Otherwise insert the missing leading slash */
706   if( otherDrive != NOT_A_VALID_DRIVE) {
707     sprintf(tmpstr,"%c:%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
708     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed for %s\n", tmpstr);
709     sprintf(tmpstr,"%c:\\%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
710     ok(lstrcmpiA(tmpstr,tmpstr1)==0,
711        "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
712     ok(lstrcmpiA(SHORTFILE,strptr)==0,
713        "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
714   }
715 /* Xilinx tools like to mix Unix and DOS formats, which Windows handles fine.
716    So test for them. */
717   if( curDrive != NOT_A_VALID_DRIVE) {
718     sprintf(tmpstr,"%c:/%s\\%s",curDrive,SHORTDIR,SHORTFILE);
719     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
720     sprintf(tmpstr,"%c:\\%s\\%s",curDrive,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 /**/
727   sprintf(tmpstr,"%c:%s/%s",curdir[0],SHORTDIR,SHORTFILE);
728   ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
729   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
730   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
731       "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
732   ok(lstrcmpiA(SHORTFILE,strptr)==0,
733       "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
734 /* Windows will insert a drive letter in front of an absolute UNIX path */
735   sprintf(tmpstr,"/%s/%s",SHORTDIR,SHORTFILE);
736   ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
737   sprintf(tmpstr,"%c:\\%s\\%s",*tmpstr1,SHORTDIR,SHORTFILE);
738   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
739      "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
740 /* This passes in Wine because it still contains the pointer from the previous test */
741   ok(lstrcmpiA(SHORTFILE,strptr)==0,
742       "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
743
744 /* Now try some relative paths */
745   ok(GetShortPathNameA(LONGDIR,tmpstr,MAX_PATH),"GetShortPathNameA failed\n");
746   test_SplitShortPathA(tmpstr,dir,eight,three);
747   if(pGetLongPathNameA) {
748     ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
749     ok(lstrcmpiA(tmpstr1,LONGDIR)==0,
750        "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,LONGDIR);
751   }
752   sprintf(tmpstr,".\\%s",LONGDIR);
753   ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed\n");
754   test_SplitShortPathA(tmpstr1,dir,eight,three);
755   ok(lstrcmpiA(dir,".")==0 || dir[0]=='\0',
756      "GetShortPathNameA did not keep relative directory [%s]\n",tmpstr1);
757   if(pGetLongPathNameA) {
758     ok(pGetLongPathNameA(tmpstr1,tmpstr1,MAX_PATH),"GetLongPathNameA failed %s\n",
759        tmpstr);
760     ok(lstrcmpiA(tmpstr1,tmpstr)==0,
761        "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
762   }
763 /* Check out Get*PathNameA on some funny characters */
764   for(i=0;i<lstrlenA(funny_chars);i++) {
765     INT valid;
766     valid=(is_char_ok[i]=='0') ? 0 : 1;
767     sprintf(tmpstr1,"check%d-1",i);
768     sprintf(tmpstr,"file%c000.ext",funny_chars[i]);
769     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
770     sprintf(tmpstr1,"check%d-2",i);
771     sprintf(tmpstr,"file000.e%ct",funny_chars[i]);
772     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
773     sprintf(tmpstr1,"check%d-3",i);
774     sprintf(tmpstr,"%cfile000.ext",funny_chars[i]);
775     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
776     sprintf(tmpstr1,"check%d-4",i);
777     sprintf(tmpstr,"file000%c.ext",funny_chars[i]);
778     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
779     sprintf(tmpstr1,"check%d-5",i);
780     sprintf(tmpstr,"Long %c File",funny_chars[i]);
781     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
782     sprintf(tmpstr1,"check%d-6",i);
783     sprintf(tmpstr,"%c Long File",funny_chars[i]);
784     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
785     sprintf(tmpstr1,"check%d-7",i);
786     sprintf(tmpstr,"Long File %c",funny_chars[i]);
787     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
788   }
789 }
790
791 static void test_GetTempPathA(char* tmp_dir)
792 {
793     DWORD len, len_with_null;
794     char buf[MAX_PATH];
795
796     len_with_null = strlen(tmp_dir) + 1;
797
798     lstrcpyA(buf, "foo");
799     len = GetTempPathA(MAX_PATH, buf);
800     ok(len <= MAX_PATH, "should fit into MAX_PATH\n");
801     ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
802     ok(len == strlen(buf), "returned length should be equal to the length of string\n");
803
804     /* Some versions of Windows touch the buffer, some don't so we don't
805      * test that. Also, NT sometimes exagerates the required buffer size
806      * so we cannot test for an exact match. Finally, the
807      * 'len_with_null - 1' case is so buggy on Windows it's not testable.
808      * For instance in some cases Win98 returns len_with_null - 1 instead
809      * of len_with_null.
810      */
811     len = GetTempPathA(1, buf);
812     ok(len >= len_with_null, "Expected >= %lu, got %lu\n", len_with_null, len);
813
814     len = GetTempPathA(0, NULL);
815     ok(len >= len_with_null, "Expected >= %lu, got %lu\n", len_with_null, len);
816
817     /* The call above gave us the buffer size that Windows thinks is needed
818      * so the next call should work
819      */
820     lstrcpyA(buf, "foo");
821     len = GetTempPathA(len, buf);
822     ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
823     ok(len == strlen(buf), "returned length should be equal to the length of string\n");
824 }
825
826 static void test_GetTempPathW(char* tmp_dir)
827 {
828     DWORD len, len_with_null;
829     WCHAR buf[MAX_PATH];
830     WCHAR tmp_dirW[MAX_PATH];
831     static const WCHAR fooW[] = {'f','o','o',0};
832
833     MultiByteToWideChar(CP_ACP,0,tmp_dir,-1,tmp_dirW,sizeof(tmp_dirW)/sizeof(*tmp_dirW));
834     len_with_null = lstrlenW(tmp_dirW) + 1;
835
836     /* This one is different from ANSI version: ANSI version doesn't
837      * touch the buffer, unicode version usually truncates the buffer
838      * to zero size. NT still exagerates the required buffer size
839      * sometimes so we cannot test for an exact match. Finally, the
840      * 'len_with_null - 1' case is so buggy on Windows it's not testable.
841      * For instance on NT4 it will sometimes return a path without the
842      * trailing '\\' and sometimes return an error.
843      */
844
845     lstrcpyW(buf, fooW);
846     len = GetTempPathW(MAX_PATH, buf);
847     if (len==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED)
848         return;
849     ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
850     ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
851
852     lstrcpyW(buf, fooW);
853     len = GetTempPathW(1, buf);
854     ok(buf[0] == 0, "unicode version should truncate the buffer to zero size\n");
855     ok(len >= len_with_null, "Expected >= %lu, got %lu\n", len_with_null, len);
856
857     len = GetTempPathW(0, NULL);
858     ok(len >= len_with_null, "Expected >= %lu, got %lu\n", len_with_null, len);
859
860     lstrcpyW(buf, fooW);
861     len = GetTempPathW(len, buf);
862     ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
863     ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
864 }
865
866 static void test_GetTempPath(void)
867 {
868     char save_TMP[MAX_PATH];
869     char windir[MAX_PATH];
870     char buf[MAX_PATH];
871
872     GetEnvironmentVariableA("TMP", save_TMP, sizeof(save_TMP));
873
874     /* test default configuration */
875     trace("TMP=%s\n", save_TMP);
876     strcpy(buf,save_TMP);
877     if (buf[strlen(buf)-1]!='\\')
878         strcat(buf,"\\");
879     test_GetTempPathA(buf);
880     test_GetTempPathW(buf);
881
882     /* TMP=C:\WINDOWS */
883     GetWindowsDirectoryA(windir, sizeof(windir));
884     SetEnvironmentVariableA("TMP", windir);
885     GetEnvironmentVariableA("TMP", buf, sizeof(buf));
886     trace("TMP=%s\n", buf);
887     strcat(windir,"\\");
888     test_GetTempPathA(windir);
889     test_GetTempPathW(windir);
890
891     /* TMP=C:\ */
892     GetWindowsDirectoryA(windir, sizeof(windir));
893     windir[3] = 0;
894     SetEnvironmentVariableA("TMP", windir);
895     GetEnvironmentVariableA("TMP", buf, sizeof(buf));
896     trace("TMP=%s\n", buf);
897     test_GetTempPathA(windir);
898     test_GetTempPathW(windir);
899
900     /* TMP=C: i.e. use current working directory of the specified drive */
901     GetWindowsDirectoryA(windir, sizeof(windir));
902     SetCurrentDirectoryA(windir);
903     windir[2] = 0;
904     SetEnvironmentVariableA("TMP", windir);
905     GetEnvironmentVariableA("TMP", buf, sizeof(buf));
906     trace("TMP=%s\n", buf);
907     GetWindowsDirectoryA(windir, sizeof(windir));
908     strcat(windir,"\\");
909     test_GetTempPathA(windir);
910     test_GetTempPathW(windir);
911
912     SetEnvironmentVariableA("TMP", save_TMP);
913 }
914
915 START_TEST(path)
916 {
917     CHAR origdir[MAX_PATH],curdir[MAX_PATH], curDrive, otherDrive;
918     pGetLongPathNameA = (void*)GetProcAddress( GetModuleHandleA("kernel32.dll"),
919                                                "GetLongPathNameA" );
920     test_InitPathA(curdir, &curDrive, &otherDrive);
921     test_CurrentDirectoryA(origdir,curdir);
922     test_PathNameA(curdir, curDrive, otherDrive);
923     test_CleanupPathA(origdir,curdir);
924     test_GetTempPath();
925 }