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