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