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