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