user32: F10 key deactivates menu.
[wine] / dlls / kernel32 / tests / path.c
1 /*
2  * Unit test suite for various Path and Directory Functions
3  *
4  * Copyright 2002 Geoffrey Hausheer
5  * Copyright 2006 Detlef Riekenberg
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include "wine/test.h"
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "winerror.h"
29 #include "winnls.h"
30
31 #define HAS_TRAIL_SLASH_A(string) (string[lstrlenA(string)-1]=='\\')
32
33 #define LONGFILE "Long File test.path"
34 #define SHORTFILE "pathtest.pth"
35 #define SHORTDIR "shortdir"
36 #define LONGDIR "Long Directory"
37 #define NONFILE_SHORT "noexist.pth"
38 #define NONFILE_LONG "NonExistent File"
39 #define NONDIR_SHORT "notadir"
40 #define NONDIR_LONG "NonExistent Directory"
41
42 #define NOT_A_VALID_DRIVE '@'
43
44 /* the following characters don't work well with GetFullPathNameA
45    in Win98.  I don't know if this is a FAT thing, or if it is an OS thing
46    but I don't test these characters now.
47    NOTE: Win2k allows GetFullPathNameA to work with them though
48       |<>"
49 */
50 static const CHAR funny_chars[]="!@#$%^&*()=+{}[],?'`";
51 static const CHAR is_char_ok[] ="11111110111111111011";
52
53 static DWORD (WINAPI *pGetLongPathNameA)(LPCSTR,LPSTR,DWORD);
54 static DWORD (WINAPI *pGetLongPathNameW)(LPWSTR,LPWSTR,DWORD);
55
56 /* Present in Win2003+ */
57 static BOOL  (WINAPI *pNeedCurrentDirectoryForExePathA)(LPCSTR);
58 static BOOL  (WINAPI *pNeedCurrentDirectoryForExePathW)(LPCWSTR);
59
60 static DWORD (WINAPI *pSearchPathA)(LPCSTR,LPCSTR,LPCSTR,DWORD,LPSTR,LPSTR*);
61 static DWORD (WINAPI *pSearchPathW)(LPCWSTR,LPCWSTR,LPCWSTR,DWORD,LPWSTR,LPWSTR*);
62
63 /* a structure to deal with wine todos somewhat cleanly */
64 typedef struct {
65   DWORD shortlen;
66   DWORD shorterror;
67   DWORD s2llen;
68   DWORD s2lerror;
69   DWORD longlen;
70   DWORD longerror;
71 } SLpassfail;
72
73 /* function that tests GetFullPathNameA, GetShortPathNameA,GetLongPathNameA */
74 /* NOTE: the passfail structure is used to allow customizable todo checking
75          for wine.  It is not very pretty, but it sure beats duplicating this
76          function lots of times
77 */
78 static void test_ValidPathA(const CHAR *curdir, const CHAR *subdir, const CHAR *filename,
79                          CHAR *shortstr, SLpassfail *passfail, const CHAR *errstr)
80 {
81   CHAR tmpstr[MAX_PATH],
82        fullpath[MAX_PATH],      /*full path to the file (not short/long) */
83        subpath[MAX_PATH],       /*relative path to the file */
84        fullpathshort[MAX_PATH], /*absolute path to the file (short format) */
85        fullpathlong[MAX_PATH],  /*absolute path to the file (long format) */
86        curdirshort[MAX_PATH],   /*absolute path to the current dir (short) */
87        curdirlong[MAX_PATH];    /*absolute path to the current dir (long) */
88   LPSTR strptr;                 /*ptr to the filename portion of the path */
89   DWORD len;
90 /* if passfail is NULL, we can perform all checks within this function,
91    otherwise, we will return the relevant data in the passfail struct, so
92    we must initialize it first
93 */
94   if(passfail!=NULL) {
95     passfail->shortlen=-1;passfail->s2llen=-1;passfail->longlen=-1;
96     passfail->shorterror=0;passfail->s2lerror=0;passfail->longerror=0;
97   }
98 /* GetLongPathNameA is only supported on Win2k+ and Win98+ */
99   if(pGetLongPathNameA) {
100     ok((len=pGetLongPathNameA(curdir,curdirlong,MAX_PATH)),
101        "%s: GetLongPathNameA failed\n",errstr);
102 /*GetLongPathNameA can return a trailing '\\' but shouldn't do so here */
103     ok(! HAS_TRAIL_SLASH_A(curdirlong),
104        "%s: GetLongPathNameA should not have a trailing \\\n",errstr);
105   }
106   ok((len=GetShortPathNameA(curdir,curdirshort,MAX_PATH)),
107      "%s: GetShortPathNameA failed\n",errstr);
108 /*GetShortPathNameA can return a trailing '\\' but shouldn't do so here */
109   ok(! HAS_TRAIL_SLASH_A(curdirshort),
110      "%s: GetShortPathNameA should not have a trailing \\\n",errstr);
111 /* build relative and absolute paths from inputs */
112   if(lstrlenA(subdir)) {
113     sprintf(subpath,"%s\\%s",subdir,filename);
114   } else {
115     lstrcpyA(subpath,filename);
116   }
117   sprintf(fullpath,"%s\\%s",curdir,subpath);
118   sprintf(fullpathshort,"%s\\%s",curdirshort,subpath);
119   sprintf(fullpathlong,"%s\\%s",curdirlong,subpath);
120 /* Test GetFullPathNameA functionality */
121   len=GetFullPathNameA(subpath,MAX_PATH,tmpstr,&strptr);
122   ok(len, "GetFullPathNameA failed for: '%s'\n",subpath);
123   if(HAS_TRAIL_SLASH_A(subpath)) {
124     ok(strptr==NULL,
125        "%s: GetFullPathNameA should not return a filename ptr\n",errstr);
126     ok(lstrcmpiA(fullpath,tmpstr)==0,
127        "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
128        errstr,tmpstr,fullpath);
129   } else {
130     ok(lstrcmpiA(strptr,filename)==0,
131        "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
132        errstr,strptr,filename);
133     ok(lstrcmpiA(fullpath,tmpstr)==0,
134        "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
135        errstr,tmpstr,fullpath);
136   }
137 /* Test GetShortPathNameA functionality */
138   SetLastError(0);
139   len=GetShortPathNameA(fullpathshort,shortstr,MAX_PATH);
140   if(passfail==NULL) {
141     ok(len, "%s: GetShortPathNameA failed\n",errstr);
142   } else {
143     passfail->shortlen=len;
144     passfail->shorterror=GetLastError();
145   }
146 /* Test GetLongPathNameA functionality
147    We test both conversion from GetFullPathNameA and from GetShortPathNameA
148 */
149   if(pGetLongPathNameA) {
150     if(len!=0) {
151       SetLastError(0);
152       len=pGetLongPathNameA(shortstr,tmpstr,MAX_PATH);
153       if(passfail==NULL) {
154         ok(len,
155           "%s: GetLongPathNameA failed during Short->Long conversion\n", errstr);
156         ok(lstrcmpiA(fullpathlong,tmpstr)==0,
157            "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
158            errstr,tmpstr,fullpathlong);
159       } else {
160         passfail->s2llen=len;
161         passfail->s2lerror=GetLastError();
162       }
163     }
164     SetLastError(0);
165     len=pGetLongPathNameA(fullpath,tmpstr,MAX_PATH);
166     if(passfail==NULL) {
167       ok(len, "%s: GetLongPathNameA failed\n",errstr);
168       if(HAS_TRAIL_SLASH_A(fullpath)) {
169         ok(lstrcmpiA(fullpathlong,tmpstr)==0,
170            "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
171            errstr,tmpstr,fullpathlong);
172       } else {
173         ok(lstrcmpiA(fullpathlong,tmpstr)==0,
174           "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
175           errstr,tmpstr,fullpathlong);
176       }
177     } else {
178       passfail->longlen=len;
179       passfail->longerror=GetLastError();
180     }
181   }
182 }
183
184 /* split path into leading directory, and 8.3 filename */
185 static void test_SplitShortPathA(CHAR *path,CHAR *dir,CHAR *eight,CHAR *three) {
186   int done,error;
187   int ext,fil;
188   int len,i;
189   len=lstrlenA(path);
190   ext=len; fil=len; done=0; error=0;
191 /* walk backwards over path looking for '.' or '\\' separators */
192   for(i=len-1;(i>=0) && (!done);i--) {
193     if(path[i]=='.')
194       if(ext!=len) error=1; else ext=i;
195     else if(path[i]=='\\') {
196       if(i==len-1) {
197         error=1;
198       } else {
199         fil=i;
200         done=1;
201       }
202     }
203   }
204 /* Check that we didn't find a trailing '\\' or multiple '.' */
205   ok(!error,"Illegal file found in 8.3 path '%s'\n",path);
206 /* Separate dir, root, and extension */
207   if(ext!=len) lstrcpyA(three,path+ext+1); else lstrcpyA(three,"");
208   if(fil!=len) {
209     lstrcpynA(eight,path+fil+1,ext-fil);
210     lstrcpynA(dir,path,fil+1);
211   } else {
212     lstrcpynA(eight,path,ext+1);
213     lstrcpyA(dir,"");
214   }
215 /* Validate that root and extension really are 8.3 */
216   ok(lstrlenA(eight)<=8 && lstrlenA(three)<=3,
217      "GetShortPathNAmeA did not return an 8.3 path\n");
218 }
219
220 /* Check that GetShortPathNameA returns a valid 8.3 path */
221 static void test_LongtoShortA(CHAR *teststr,const CHAR *goodstr,
222                               const CHAR *ext,const CHAR *errstr) {
223   CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
224
225   test_SplitShortPathA(teststr,dir,eight,three);
226   ok(lstrcmpiA(dir,goodstr)==0,
227      "GetShortPathNameA returned '%s' instead of '%s'\n",dir,goodstr);
228   ok(lstrcmpiA(three,ext)==0,
229      "GetShortPathNameA returned '%s' with incorrect extension\n",three);
230 }
231
232 /* Test that Get(Short|Long|Full)PathNameA work correctly with interesting
233    characters in the filename.
234      'valid' indicates whether this would be an allowed filename
235      'todo' indicates that wine doesn't get this right yet.
236    NOTE: We always call this routine with a nonexistent filename, so
237          Get(Short|Long)PathNameA should never pass, but GetFullPathNameA
238          should.
239 */
240 static void test_FunnyChars(CHAR *curdir,CHAR *curdir_short,CHAR *filename, INT valid,CHAR *errstr)
241 {
242   CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
243   SLpassfail passfail;
244
245   test_ValidPathA(curdir,"",filename,tmpstr,&passfail,errstr);
246   if(valid) {
247     sprintf(tmpstr1,"%s\\%s",curdir_short,filename);
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=%d error=%d tmpstr=[%s]\n",
252          errstr,passfail.shortlen,passfail.shorterror,tmpstr);
253   } else {
254       ok(passfail.shortlen==0 &&
255          (passfail.shorterror==ERROR_INVALID_NAME || passfail.shorterror==ERROR_FILE_NOT_FOUND || !passfail.shorterror),
256          "%s: GetShortPathA should have failed len=%d, error=%d\n",
257          errstr,passfail.shortlen,passfail.shorterror);
258   }
259   if(pGetLongPathNameA) {
260     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
261     if(valid) {
262       ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
263          "%s: GetLongPathA returned %d and not %d\n",
264          errstr,passfail.longerror,ERROR_FILE_NOT_FOUND);
265     } else {
266       ok(passfail.longerror==ERROR_INVALID_NAME ||
267          passfail.longerror==ERROR_FILE_NOT_FOUND,
268          "%s: GetLongPathA returned %d and not %d or %d'\n",
269          errstr, passfail.longerror,ERROR_INVALID_NAME,ERROR_FILE_NOT_FOUND);
270     }
271   }
272 }
273
274 /* Routine to test that SetCurrentDirectory behaves as expected. */
275 static void test_setdir(CHAR *olddir,CHAR *newdir,
276                         CHAR *cmprstr, INT pass, const CHAR *errstr)
277 {
278   CHAR tmppath[MAX_PATH], *dirptr;
279   DWORD val,len,chklen;
280
281   val=SetCurrentDirectoryA(newdir);
282   len=GetCurrentDirectoryA(MAX_PATH,tmppath);
283 /* if 'pass' then the SetDirectoryA was supposed to pass */
284   if(pass) {
285     dirptr=(cmprstr==NULL) ? newdir : cmprstr;
286     chklen=lstrlenA(dirptr);
287     ok(val,"%s: SetCurrentDirectoryA failed\n",errstr);
288     ok(len==chklen,
289        "%s: SetCurrentDirectory did not change the directory, though it passed\n",
290        errstr);
291     ok(lstrcmpiA(dirptr,tmppath)==0,
292        "%s: SetCurrentDirectory did not change the directory, though it passed\n",
293        errstr);
294     ok(SetCurrentDirectoryA(olddir),
295        "%s: Couldn't set directory to it's original value\n",errstr);
296   } else {
297 /* else thest that it fails correctly */
298     chklen=lstrlenA(olddir);
299     ok(val==0,
300        "%s: SetCurrentDirectoryA passed when it should have failed\n",errstr);
301     ok(len==chklen,
302        "%s: SetCurrentDirectory changed the directory, though it failed\n",
303        errstr);
304     ok(lstrcmpiA(olddir,tmppath)==0,
305        "%s: SetCurrentDirectory changed the directory, though it failed\n",
306        errstr);
307   }
308 }
309 static void test_InitPathA(CHAR *newdir, CHAR *curDrive, CHAR *otherDrive)
310 {
311   CHAR tmppath[MAX_PATH], /*path to TEMP */
312        tmpstr[MAX_PATH],
313        tmpstr1[MAX_PATH];
314   DWORD len,len1,drives;
315   INT id;
316   HANDLE hndl;
317   BOOL bRes;
318
319   *curDrive = *otherDrive = NOT_A_VALID_DRIVE;
320
321 /* Get the current drive letter */
322   if( GetCurrentDirectoryA( MAX_PATH, tmpstr))
323     *curDrive = tmpstr[0];
324   else
325     trace( "Unable to discover current drive, some tests will not be conducted.\n");
326
327 /* Test GetTempPathA */
328   len=GetTempPathA(MAX_PATH,tmppath);
329   ok(len!=0 && len < MAX_PATH,"GetTempPathA failed\n");
330   ok(HAS_TRAIL_SLASH_A(tmppath),
331      "GetTempPathA returned a path that did not end in '\\'\n");
332   lstrcpyA(tmpstr,"aaaaaaaa");
333   len1=GetTempPathA(len,tmpstr);
334   ok(len1==len+1 || broken(len1 == len), /* WinME */
335      "GetTempPathA should return string length %d instead of %d\n",len+1,len1);
336
337 /* Test GetTmpFileNameA
338    The only test we do here is whether GetTempFileNameA passes or not.
339    We do not thoroughly test this function yet (specifically, whether
340    it behaves correctly when 'unique' is non zero)
341 */
342   ok((id=GetTempFileNameA(tmppath,"path",0,newdir)),"GetTempFileNameA failed\n");
343   sprintf(tmpstr,"pat%.4x.tmp",id & 0xffff);
344   sprintf(tmpstr1,"pat%x.tmp",id & 0xffff);
345   ok(lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr)==0 ||
346      lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr1)==0,
347      "GetTempFileNameA returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
348      newdir,tmpstr,tmpstr1,id);
349   ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");     
350
351   id=GetTempFileNameA(tmppath,NULL,0,newdir);
352 /* Windows 95, 98 return 0==id, while Windows 2000, XP return 0!=id */
353   if (id)
354   {
355     sprintf(tmpstr,"%.4x.tmp",id & 0xffff);
356     sprintf(tmpstr1,"%x.tmp",id & 0xffff);
357     ok(lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr)==0 ||
358        lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr1)==0,
359        "GetTempFileNameA returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
360        newdir,tmpstr,tmpstr1,id);
361     ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
362   }
363
364 /* Find first valid drive letter that is neither newdir[0] nor curDrive */
365   drives = GetLogicalDrives() & ~(1<<(newdir[0]-'A'));
366   if( *curDrive != NOT_A_VALID_DRIVE)
367     drives &= ~(1<<(*curDrive-'A'));
368   if( drives)
369     for( *otherDrive='A'; (drives & 1) == 0; drives>>=1, (*otherDrive)++);
370   else
371     trace( "Could not find alternative drive, some tests will not be conducted.\n");
372
373 /* Do some CreateDirectoryA tests */
374 /* It would be nice to do test the SECURITY_ATTRIBUTES, but I don't
375    really understand how they work.
376    More formal tests should be done along with CreateFile tests
377 */
378   ok((id=GetTempFileNameA(tmppath,"path",0,newdir)),"GetTempFileNameA failed\n");
379   ok(CreateDirectoryA(newdir,NULL)==0,
380      "CreateDirectoryA succeeded even though a file of the same name exists\n");
381   ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
382   ok(CreateDirectoryA(newdir,NULL),"CreateDirectoryA failed\n");
383 /* Create some files to test other functions.  Note, we will test CreateFileA
384    at some later point
385 */
386   sprintf(tmpstr,"%s\\%s",newdir,SHORTDIR);
387   ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed\n");
388   sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
389   ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed\n");
390   sprintf(tmpstr,"%c:", *curDrive);
391   bRes = CreateDirectoryA(tmpstr,NULL);
392   ok(!bRes && (GetLastError() == ERROR_ACCESS_DENIED  ||
393                GetLastError() == ERROR_ALREADY_EXISTS),
394      "CreateDirectoryA(\"%s\" should have failed (%d)\n", tmpstr, GetLastError());
395   sprintf(tmpstr,"%c:\\", *curDrive);
396   bRes = CreateDirectoryA(tmpstr,NULL);
397   ok(!bRes && (GetLastError() == ERROR_ACCESS_DENIED  ||
398                GetLastError() == ERROR_ALREADY_EXISTS),
399      "CreateDirectoryA(\"%s\" should have failed (%d)\n", tmpstr, GetLastError());
400   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,SHORTFILE);
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   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,LONGFILE);
406   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
407                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
408   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
409   ok(CloseHandle(hndl),"CloseHandle failed\n");
410   sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,SHORTFILE);
411   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
412                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
413   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
414   ok(CloseHandle(hndl),"CloseHandle failed\n");
415   sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,LONGFILE);
416   hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
417                    CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
418   ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
419   ok(CloseHandle(hndl),"CloseHandle failed\n");
420 }
421
422 /* Test GetCurrentDirectory & SetCurrentDirectory */
423 static void test_CurrentDirectoryA(CHAR *origdir, CHAR *newdir)
424 {
425   CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
426   DWORD len,len1;
427 /* Save the original directory, so that we can return to it at the end
428    of the test
429 */
430   len=GetCurrentDirectoryA(MAX_PATH,origdir);
431   ok(len!=0 && len < MAX_PATH,"GetCurrentDirectoryA failed\n");
432 /* Make sure that CetCurrentDirectoryA doesn't overwrite the buffer when the
433    buffer size is too small to hold the current directory
434 */
435   lstrcpyA(tmpstr,"aaaaaaa");
436   len1=GetCurrentDirectoryA(len,tmpstr);
437   ok(len1==len+1, "GetCurrentDirectoryA returned %d instead of %d\n",len1,len+1);
438   ok(lstrcmpiA(tmpstr,"aaaaaaa")==0,
439      "GetCurrentDirectoryA should not have modified the buffer\n");
440 /* SetCurrentDirectoryA shouldn't care whether the string has a
441    trailing '\\' or not
442 */
443   sprintf(tmpstr,"%s\\",newdir);
444   test_setdir(origdir,tmpstr,newdir,1,"check 1");
445   test_setdir(origdir,newdir,NULL,1,"check 2");
446 /* Set the directory to the working area.  We just tested that this works,
447    so why check it again.
448 */
449   SetCurrentDirectoryA(newdir);
450 /* Check that SetCurrentDirectory fails when a nonexistent dir is specified */
451   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_SHORT);
452   test_setdir(newdir,tmpstr,NULL,0,"check 3");
453 /* Check that SetCurrentDirectory fails for a nonexistent lond directory */
454   sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_LONG);
455   test_setdir(newdir,tmpstr,NULL,0,"check 4");
456 /* Check that SetCurrentDirectory passes with a long directory */
457   sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
458   test_setdir(newdir,tmpstr,NULL,1,"check 5");
459 /* Check that SetCurrentDirectory passes with a short relative directory */
460   sprintf(tmpstr,"%s",SHORTDIR);
461   sprintf(tmpstr1,"%s\\%s",newdir,SHORTDIR);
462   test_setdir(newdir,tmpstr,tmpstr1,1,"check 6");
463 /* starting with a '.' */
464   sprintf(tmpstr,".\\%s",SHORTDIR);
465   test_setdir(newdir,tmpstr,tmpstr1,1,"check 7");
466 /* Check that SetCurrentDirectory passes with a short relative directory */
467   sprintf(tmpstr,"%s",LONGDIR);
468   sprintf(tmpstr1,"%s\\%s",newdir,LONGDIR);
469   test_setdir(newdir,tmpstr,tmpstr1,1,"check 8");
470 /* starting with a '.' */
471   sprintf(tmpstr,".\\%s",LONGDIR);
472   test_setdir(newdir,tmpstr,tmpstr1,1,"check 9");
473 /* change to root without a trailing backslash. The function call succeeds
474    but the directory is not changed.
475 */
476   sprintf(tmpstr, "%c:", newdir[0]);
477   test_setdir(newdir,tmpstr,newdir,1,"check 10");
478 /* works however with a trailing backslash */
479   sprintf(tmpstr, "%c:\\", newdir[0]);
480   test_setdir(newdir,tmpstr,NULL,1,"check 11");
481 }
482
483 /* Cleanup the mess we made while executing these tests */
484 static void test_CleanupPathA(CHAR *origdir, CHAR *curdir)
485 {
486   CHAR tmpstr[MAX_PATH];
487   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
488   ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
489   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,LONGFILE);
490   ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
491   sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,SHORTFILE);
492   ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
493   sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
494   ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
495   sprintf(tmpstr,"%s\\%s",curdir,SHORTDIR);
496   ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
497   sprintf(tmpstr,"%s\\%s",curdir,LONGDIR);
498   ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
499   ok(SetCurrentDirectoryA(origdir),"SetCurrentDirectoryA failed\n");
500   ok(RemoveDirectoryA(curdir),"RemoveDirectoryA failed\n");
501 }
502
503 /* This routine will test Get(Full|Short|Long)PathNameA */
504 static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive)
505 {
506   CHAR curdir_short[MAX_PATH],
507        longdir_short[MAX_PATH];
508   CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH],tmpstr2[MAX_PATH];
509   LPSTR strptr;                 /*ptr to the filename portion of the path */
510   DWORD len;
511   INT i;
512   CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
513   SLpassfail passfail;
514
515 /* Get the short form of the current directory */
516   ok((len=GetShortPathNameA(curdir,curdir_short,MAX_PATH)),
517      "GetShortPathNameA failed\n");
518   ok(!HAS_TRAIL_SLASH_A(curdir_short),
519      "GetShortPathNameA should not have a trailing \\\n");
520 /* Get the short form of the absolute-path to LONGDIR */
521   sprintf(tmpstr,"%s\\%s",curdir_short,LONGDIR);
522   ok((len=GetShortPathNameA(tmpstr,longdir_short,MAX_PATH)),
523      "GetShortPathNameA failed\n");
524   ok(lstrcmpiA(longdir_short+(len-1),"\\")!=0,
525      "GetShortPathNameA should not have a trailing \\\n");
526
527   if (pGetLongPathNameA) {
528     DWORD rc1,rc2;
529     sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
530     rc1=(*pGetLongPathNameA)(tmpstr,NULL,0);
531     rc2=(*pGetLongPathNameA)(curdir,NULL,0);
532     ok((rc1-strlen(tmpstr))==(rc2-strlen(curdir)),
533        "GetLongPathNameA: wrong return code, %d instead of %d\n",
534        rc1, lstrlenA(tmpstr)+1);
535
536     sprintf(dir,"%c:",curDrive);
537     rc1=(*pGetLongPathNameA)(dir,tmpstr,sizeof(tmpstr));
538     ok(strcmp(dir,tmpstr)==0,
539        "GetLongPathNameA: returned '%s' instead of '%s' (rc=%d)\n",
540        tmpstr,dir,rc1);
541   }
542
543 /* Check the cases where both file and directory exist first */
544 /* Start with a 8.3 directory, 8.3 filename */
545   test_ValidPathA(curdir,SHORTDIR,SHORTFILE,tmpstr,NULL,"test1");
546   sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,SHORTFILE);
547   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
548      "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
549 /* Now try a 8.3 directory, long file name */
550   test_ValidPathA(curdir,SHORTDIR,LONGFILE,tmpstr,NULL,"test2");
551   sprintf(tmpstr1,"%s\\%s",curdir_short,SHORTDIR);
552   test_LongtoShortA(tmpstr,tmpstr1,"PAT","test2");
553 /* Next is a long directory, 8.3 file */
554   test_ValidPathA(curdir,LONGDIR,SHORTFILE,tmpstr,NULL,"test3");
555   sprintf(tmpstr1,"%s\\%s",longdir_short,SHORTFILE);
556   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
557      "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
558 /*Lastly a long directory, long file */
559   test_ValidPathA(curdir,LONGDIR,LONGFILE,tmpstr,NULL,"test4");
560   test_LongtoShortA(tmpstr,longdir_short,"PAT","test4");
561
562 /* Now check all of the invalid file w/ valid directory combinations */
563 /* Start with a 8.3 directory, 8.3 filename */
564   test_ValidPathA(curdir,SHORTDIR,NONFILE_SHORT,tmpstr,&passfail,"test5");
565   sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,NONFILE_SHORT);
566   ok((passfail.shortlen==0 &&
567       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
568        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
569      (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
570      "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
571      passfail.shortlen,passfail.shorterror,tmpstr);
572   if(pGetLongPathNameA) {
573     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
574     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
575        "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
576   }
577 /* Now try a 8.3 directory, long file name */
578   test_ValidPathA(curdir,SHORTDIR,NONFILE_LONG,tmpstr,&passfail,"test6");
579   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
580   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
581      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
582      !passfail.shorterror,
583      "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
584   if(pGetLongPathNameA) {
585     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
586     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
587        "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
588   }
589 /* Next is a long directory, 8.3 file */
590   test_ValidPathA(curdir,LONGDIR,NONFILE_SHORT,tmpstr,&passfail,"test7");
591   sprintf(tmpstr2,"%s\\%s",curdir_short,LONGDIR);
592   GetShortPathNameA(tmpstr2,tmpstr1,MAX_PATH);
593   strcat(tmpstr1,"\\" NONFILE_SHORT);
594   ok((passfail.shortlen==0 &&
595       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
596        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
597      (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
598      "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
599      passfail.shortlen,passfail.shorterror,tmpstr);
600   if(pGetLongPathNameA) {
601     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
602     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
603       "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
604   }
605 /*Lastly a long directory, long file */
606   test_ValidPathA(curdir,LONGDIR,NONFILE_LONG,tmpstr,&passfail,"test8");
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 should have returned 'ERROR_FILE_NOT_FOUND'\n");
612   if(pGetLongPathNameA) {
613     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
614     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
615        "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
616   }
617 /* Now try again with directories that don't exist */
618 /* 8.3 directory, 8.3 filename */
619   test_ValidPathA(curdir,NONDIR_SHORT,SHORTFILE,tmpstr,&passfail,"test9");
620   sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,NONDIR_SHORT,SHORTFILE);
621   ok((passfail.shortlen==0 &&
622       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
623        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
624      (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
625      "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
626      passfail.shortlen,passfail.shorterror,tmpstr);
627   if(pGetLongPathNameA) {
628     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
629     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
630        passfail.longerror==ERROR_FILE_NOT_FOUND,
631        "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
632        passfail.longerror);
633   }
634 /* Now try a 8.3 directory, long file name */
635   test_ValidPathA(curdir,NONDIR_SHORT,LONGFILE,tmpstr,&passfail,"test10");
636   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
637   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
638      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
639      !passfail.shorterror,
640      "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
641       passfail.shorterror);
642   if(pGetLongPathNameA) {
643     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
644     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
645        passfail.longerror==ERROR_FILE_NOT_FOUND,
646        "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
647        passfail.longerror);
648   }
649 /* Next is a long directory, 8.3 file */
650   test_ValidPathA(curdir,NONDIR_LONG,SHORTFILE,tmpstr,&passfail,"test11");
651   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
652   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
653      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
654      !passfail.shorterror,
655      "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
656       passfail.shorterror);
657   if(pGetLongPathNameA) {
658     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
659     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
660        passfail.longerror==ERROR_FILE_NOT_FOUND,
661        "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
662        passfail.longerror);
663   }
664 /*Lastly a long directory, long file */
665   test_ValidPathA(curdir,NONDIR_LONG,LONGFILE,tmpstr,&passfail,"test12");
666   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
667   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
668      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
669      !passfail.shorterror,
670      "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
671       passfail.shorterror);
672   if(pGetLongPathNameA) {
673     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
674     ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
675        passfail.longerror==ERROR_FILE_NOT_FOUND,
676        "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
677        passfail.longerror);
678   }
679 /* Next try directories ending with '\\' */
680 /* Existing Directories */
681   sprintf(tmpstr,"%s\\",SHORTDIR);
682   test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test13");
683   sprintf(tmpstr,"%s\\",LONGDIR);
684   test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test14");
685 /* Nonexistent directories */
686   sprintf(tmpstr,"%s\\",NONDIR_SHORT);
687   test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test15");
688   sprintf(tmpstr2,"%s\\%s",curdir_short,tmpstr);
689   ok((passfail.shortlen==0 &&
690       (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
691        passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
692      (passfail.shortlen==strlen(tmpstr2) && lstrcmpiA(tmpstr1,tmpstr2)==0),
693      "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
694      passfail.shortlen,passfail.shorterror,tmpstr);
695   if(pGetLongPathNameA) {
696     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
697     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
698        "GetLongPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
699        passfail.longerror);
700   }
701   sprintf(tmpstr,"%s\\",NONDIR_LONG);
702   test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test16");
703   ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
704   ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
705      passfail.shorterror==ERROR_FILE_NOT_FOUND ||
706      !passfail.shorterror,
707      "GetShortPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
708       passfail.shorterror);
709   if(pGetLongPathNameA) {
710     ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
711     ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
712        "GetLongPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
713        passfail.longerror);
714   }
715 /* Test GetFullPathNameA with drive letters */
716   if( curDrive != NOT_A_VALID_DRIVE) {
717     sprintf(tmpstr,"%c:",curdir[0]);
718     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr2,&strptr),
719        "GetFullPathNameA(%c:) failed\n", curdir[0]);
720     GetCurrentDirectoryA(MAX_PATH,tmpstr);
721     sprintf(tmpstr1,"%s\\",tmpstr);
722     ok(lstrcmpiA(tmpstr,tmpstr2)==0 || lstrcmpiA(tmpstr1,tmpstr2)==0,
723        "GetFullPathNameA(%c:) returned '%s' instead of '%s' or '%s'\n",
724        curdir[0],tmpstr2,tmpstr,tmpstr1);
725
726     sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
727     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
728     ok(lstrcmpiA(tmpstr,tmpstr1)==0,
729        "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
730     ok(lstrcmpiA(SHORTFILE,strptr)==0,
731        "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
732   }
733 /* Without a leading slash, insert the current directory if on the current drive */
734   sprintf(tmpstr,"%c:%s\\%s",curdir[0],SHORTDIR,SHORTFILE);
735   ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
736   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
737   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
738       "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
739   ok(lstrcmpiA(SHORTFILE,strptr)==0,
740       "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
741 /* Otherwise insert the missing leading slash */
742   if( otherDrive != NOT_A_VALID_DRIVE) {
743     /* FIXME: this test assumes that current directory on other drive is root */
744     sprintf(tmpstr,"%c:%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
745     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed for %s\n", tmpstr);
746     sprintf(tmpstr,"%c:\\%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
747     ok(lstrcmpiA(tmpstr,tmpstr1)==0,
748        "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
749     ok(lstrcmpiA(SHORTFILE,strptr)==0,
750        "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
751   }
752 /* Xilinx tools like to mix Unix and DOS formats, which Windows handles fine.
753    So test for them. */
754   if( curDrive != NOT_A_VALID_DRIVE) {
755     sprintf(tmpstr,"%c:/%s\\%s",curDrive,SHORTDIR,SHORTFILE);
756     ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
757     sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
758     ok(lstrcmpiA(tmpstr,tmpstr1)==0,
759        "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
760     ok(lstrcmpiA(SHORTFILE,strptr)==0,
761        "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
762   }
763 /**/
764   sprintf(tmpstr,"%c:%s/%s",curdir[0],SHORTDIR,SHORTFILE);
765   ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
766   sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
767   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
768       "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
769   ok(lstrcmpiA(SHORTFILE,strptr)==0,
770       "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
771 /* Windows will insert a drive letter in front of an absolute UNIX path */
772   sprintf(tmpstr,"/%s/%s",SHORTDIR,SHORTFILE);
773   ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
774   sprintf(tmpstr,"%c:\\%s\\%s",*tmpstr1,SHORTDIR,SHORTFILE);
775   ok(lstrcmpiA(tmpstr,tmpstr1)==0,
776      "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
777 /* This passes in Wine because it still contains the pointer from the previous test */
778   ok(lstrcmpiA(SHORTFILE,strptr)==0,
779       "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
780
781 /* Now try some relative paths */
782   ok(GetShortPathNameA(LONGDIR,tmpstr,MAX_PATH),"GetShortPathNameA failed\n");
783   test_SplitShortPathA(tmpstr,dir,eight,three);
784   if(pGetLongPathNameA) {
785     ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
786     ok(lstrcmpiA(tmpstr1,LONGDIR)==0,
787        "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,LONGDIR);
788   }
789   sprintf(tmpstr,".\\%s",LONGDIR);
790   ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed\n");
791   test_SplitShortPathA(tmpstr1,dir,eight,three);
792   ok(lstrcmpiA(dir,".")==0 || dir[0]=='\0',
793      "GetShortPathNameA did not keep relative directory [%s]\n",tmpstr1);
794   if(pGetLongPathNameA) {
795     ok(pGetLongPathNameA(tmpstr1,tmpstr1,MAX_PATH),"GetLongPathNameA failed %s\n",
796        tmpstr);
797     ok(lstrcmpiA(tmpstr1,tmpstr)==0,
798        "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
799   }
800 /* Check out Get*PathNameA on some funny characters */
801   for(i=0;i<lstrlenA(funny_chars);i++) {
802     INT valid;
803     valid=(is_char_ok[i]=='0') ? 0 : 1;
804     sprintf(tmpstr1,"check%d-1",i);
805     sprintf(tmpstr,"file%c000.ext",funny_chars[i]);
806     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
807     sprintf(tmpstr1,"check%d-2",i);
808     sprintf(tmpstr,"file000.e%ct",funny_chars[i]);
809     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
810     sprintf(tmpstr1,"check%d-3",i);
811     sprintf(tmpstr,"%cfile000.ext",funny_chars[i]);
812     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
813     sprintf(tmpstr1,"check%d-4",i);
814     sprintf(tmpstr,"file000%c.ext",funny_chars[i]);
815     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
816     sprintf(tmpstr1,"check%d-5",i);
817     sprintf(tmpstr,"Long %c File",funny_chars[i]);
818     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
819     sprintf(tmpstr1,"check%d-6",i);
820     sprintf(tmpstr,"%c Long File",funny_chars[i]);
821     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
822     sprintf(tmpstr1,"check%d-7",i);
823     sprintf(tmpstr,"Long File %c",funny_chars[i]);
824     test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
825   }
826 }
827
828 static void test_GetTempPathA(char* tmp_dir)
829 {
830     DWORD len, len_with_null;
831     char buf[MAX_PATH];
832
833     len_with_null = strlen(tmp_dir) + 1;
834
835     lstrcpyA(buf, "foo");
836     len = GetTempPathA(MAX_PATH, buf);
837     ok(len <= MAX_PATH, "should fit into MAX_PATH\n");
838     ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
839     ok(len == strlen(buf), "returned length should be equal to the length of string\n");
840
841     /* Some versions of Windows touch the buffer, some don't so we don't
842      * test that. Also, NT sometimes exaggerates the required buffer size
843      * so we cannot test for an exact match. Finally, the
844      * 'len_with_null - 1' case is so buggy on Windows it's not testable.
845      * For instance in some cases Win98 returns len_with_null - 1 instead
846      * of len_with_null.
847      */
848     len = GetTempPathA(1, buf);
849     ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
850
851     len = GetTempPathA(0, NULL);
852     ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
853
854     /* The call above gave us the buffer size that Windows thinks is needed
855      * so the next call should work
856      */
857     lstrcpyA(buf, "foo");
858     len = GetTempPathA(len, buf);
859     ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
860     ok(len == strlen(buf), "returned length should be equal to the length of string\n");
861 }
862
863 static void test_GetTempPathW(char* tmp_dir)
864 {
865     DWORD len, len_with_null;
866     WCHAR buf[MAX_PATH];
867     WCHAR tmp_dirW[MAX_PATH];
868     static const WCHAR fooW[] = {'f','o','o',0};
869
870     MultiByteToWideChar(CP_ACP,0,tmp_dir,-1,tmp_dirW,sizeof(tmp_dirW)/sizeof(*tmp_dirW));
871     len_with_null = lstrlenW(tmp_dirW) + 1;
872
873     /* This one is different from ANSI version: ANSI version doesn't
874      * touch the buffer, unicode version usually truncates the buffer
875      * to zero size. NT still exaggerates the required buffer size
876      * sometimes so we cannot test for an exact match. Finally, the
877      * 'len_with_null - 1' case is so buggy on Windows it's not testable.
878      * For instance on NT4 it will sometimes return a path without the
879      * trailing '\\' and sometimes return an error.
880      */
881
882     lstrcpyW(buf, fooW);
883     len = GetTempPathW(MAX_PATH, buf);
884     if (len == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
885     {
886         win_skip("GetTempPathW is not available\n");
887         return;
888     }
889     ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
890     ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
891
892     lstrcpyW(buf, fooW);
893     len = GetTempPathW(1, buf);
894     ok(buf[0] == 0, "unicode version should truncate the buffer to zero size\n");
895     ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
896
897     len = GetTempPathW(0, NULL);
898     ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
899
900     lstrcpyW(buf, fooW);
901     len = GetTempPathW(len, buf);
902     ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
903     ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
904 }
905
906 static void test_GetTempPath(void)
907 {
908     char save_TMP[MAX_PATH];
909     char windir[MAX_PATH];
910     char buf[MAX_PATH];
911
912     if (!GetEnvironmentVariableA("TMP", save_TMP, sizeof(save_TMP))) save_TMP[0] = 0;
913
914     /* test default configuration */
915     trace("TMP=%s\n", save_TMP);
916     if (save_TMP[0])
917     {
918         strcpy(buf,save_TMP);
919         if (buf[strlen(buf)-1]!='\\')
920             strcat(buf,"\\");
921         test_GetTempPathA(buf);
922         test_GetTempPathW(buf);
923     }
924
925     /* TMP=C:\WINDOWS */
926     GetWindowsDirectoryA(windir, sizeof(windir));
927     SetEnvironmentVariableA("TMP", windir);
928     GetEnvironmentVariableA("TMP", buf, sizeof(buf));
929     trace("TMP=%s\n", buf);
930     strcat(windir,"\\");
931     test_GetTempPathA(windir);
932     test_GetTempPathW(windir);
933
934     /* TMP=C:\ */
935     GetWindowsDirectoryA(windir, sizeof(windir));
936     windir[3] = 0;
937     SetEnvironmentVariableA("TMP", windir);
938     GetEnvironmentVariableA("TMP", buf, sizeof(buf));
939     trace("TMP=%s\n", buf);
940     test_GetTempPathA(windir);
941     test_GetTempPathW(windir);
942
943     /* TMP=C: i.e. use current working directory of the specified drive */
944     GetWindowsDirectoryA(windir, sizeof(windir));
945     SetCurrentDirectoryA(windir);
946     windir[2] = 0;
947     SetEnvironmentVariableA("TMP", windir);
948     GetEnvironmentVariableA("TMP", buf, sizeof(buf));
949     trace("TMP=%s\n", buf);
950     GetWindowsDirectoryA(windir, sizeof(windir));
951     strcat(windir,"\\");
952     test_GetTempPathA(windir);
953     test_GetTempPathW(windir);
954
955     SetEnvironmentVariableA("TMP", save_TMP);
956 }
957
958 static void test_GetLongPathNameA(void)
959 {
960     DWORD length, explength, hostsize;
961     char tempfile[MAX_PATH];
962     char longpath[MAX_PATH];
963     char unc_prefix[MAX_PATH];
964     char unc_short[MAX_PATH], unc_long[MAX_PATH];
965     char temppath[MAX_PATH], temppath2[MAX_PATH];
966     HANDLE file;
967
968     if (!pGetLongPathNameA)
969         return;
970
971     GetTempPathA(MAX_PATH, tempfile);
972     lstrcatA(tempfile, "longfilename.longext");
973
974     file = CreateFileA(tempfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
975     CloseHandle(file);
976
977     /* Test a normal path with a small buffer size */
978     memset(temppath, 0, MAX_PATH);
979     length = pGetLongPathNameA(tempfile, temppath, 4);
980     /* We have a failure so length should be the minumum plus the terminating '0'  */
981     ok(length >= lstrlen(tempfile) + 1, "Wrong length\n");
982     ok(temppath[0] == 0, "Buffer should not have been touched\n");
983
984     /* Some UNC syntax tests */
985
986     memset(temppath, 0, MAX_PATH);
987     memset(temppath2, 0, MAX_PATH);
988     lstrcpyA(temppath2, "\\\\?\\");
989     lstrcatA(temppath2, tempfile);
990     explength = length + 4;
991
992     SetLastError(0xdeadbeef);
993     length = pGetLongPathNameA(temppath2, NULL, 0);
994     if (length == 0 && GetLastError() == ERROR_BAD_NET_NAME)
995     {
996         win_skip("UNC syntax tests don't work on Win98/WinMe\n");
997         DeleteFileA(tempfile);
998         return;
999     }
1000     ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1001
1002     length = pGetLongPathNameA(temppath2, NULL, MAX_PATH);
1003     ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1004
1005     length = pGetLongPathNameA(temppath2, temppath, 4);
1006     ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1007     ok(temppath[0] == 0, "Buffer should not have been touched\n");
1008
1009     /* Now an UNC path with the computername */
1010     lstrcpyA(unc_prefix, "\\\\");
1011     hostsize = sizeof(unc_prefix) - 2;
1012     GetComputerName(unc_prefix + 2, &hostsize);
1013     lstrcatA(unc_prefix, "\\");
1014
1015     /* Create a short syntax for the whole unc path */
1016     memset(unc_short, 0, MAX_PATH);
1017     GetShortPathNameA(tempfile, temppath, MAX_PATH);
1018     lstrcpyA(unc_short, unc_prefix);
1019     unc_short[lstrlenA(unc_short)] = temppath[0];
1020     lstrcatA(unc_short, "$\\");
1021     lstrcatA(unc_short, strchr(temppath, '\\') + 1);
1022
1023     /* Create a long syntax for reference */
1024     memset(longpath, 0, MAX_PATH);
1025     pGetLongPathNameA(tempfile, temppath, MAX_PATH);
1026     lstrcpyA(longpath, unc_prefix);
1027     longpath[lstrlenA(longpath)] = temppath[0];
1028     lstrcatA(longpath, "$\\");
1029     lstrcatA(longpath, strchr(temppath, '\\') + 1);
1030
1031     /* NULL test */
1032     SetLastError(0xdeadbeef);
1033     length = pGetLongPathNameA(unc_short, NULL, 0);
1034     if (length == 0 && GetLastError() == ERROR_BAD_NETPATH)
1035     {
1036         /* Seen on Window XP Home */
1037         win_skip("UNC with computername is not supported\n");
1038         DeleteFileA(tempfile);
1039         return;
1040     }
1041     explength = lstrlenA(longpath) + 1;
1042     todo_wine
1043     ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1044
1045     length = pGetLongPathNameA(unc_short, NULL, MAX_PATH);
1046     todo_wine
1047     ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1048
1049     memset(unc_long, 0, MAX_PATH);
1050     length = pGetLongPathNameA(unc_short, unc_long, lstrlenA(unc_short));
1051     /* length will include terminating '0' on failure */
1052     todo_wine
1053     ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1054     ok(unc_long[0] == 0, "Buffer should not have been touched\n");
1055
1056     memset(unc_long, 0, MAX_PATH);
1057     length = pGetLongPathNameA(unc_short, unc_long, length);
1058     /* length doesn't include terminating '0' on success */
1059     explength--;
1060     todo_wine
1061     {
1062     ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1063     ok(!lstrcmpiA(unc_long, longpath), "Expected (%s), got (%s)\n", longpath, unc_long);
1064     }
1065
1066     DeleteFileA(tempfile);
1067 }
1068
1069 static void test_GetLongPathNameW(void)
1070 {
1071     DWORD length, expanded;
1072     BOOL ret;
1073     HANDLE file;
1074     WCHAR empty[MAX_PATH];
1075     WCHAR tempdir[MAX_PATH], name[200];
1076     WCHAR dirpath[4 + MAX_PATH + 200]; /* To ease removal */
1077     WCHAR shortpath[4 + MAX_PATH + 200 + 1 + 200];
1078     static const WCHAR prefix[] = { '\\','\\','?','\\', 0};
1079     static const WCHAR backslash[] = { '\\', 0};
1080     static const WCHAR letterX[] = { 'X', 0};
1081
1082     if (!pGetLongPathNameW)
1083         return;
1084
1085     SetLastError(0xdeadbeef); 
1086     length = pGetLongPathNameW(NULL,NULL,0);
1087     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1088     {
1089         win_skip("GetLongPathNameW is not implemented\n");
1090         return;
1091     }
1092     ok(0==length,"GetLongPathNameW returned %d but expected 0\n",length);
1093     ok(GetLastError()==ERROR_INVALID_PARAMETER,"GetLastError returned %d but expected ERROR_INVALID_PARAMETER\n",GetLastError());
1094
1095     SetLastError(0xdeadbeef); 
1096     empty[0]=0;
1097     length = pGetLongPathNameW(empty,NULL,0);
1098     ok(0==length,"GetLongPathNameW returned %d but expected 0\n",length);
1099     ok(GetLastError()==ERROR_PATH_NOT_FOUND,"GetLastError returned %d but expected ERROR_PATH_NOT_FOUND\n",GetLastError());
1100
1101     /* Create a long path name. The path needs to exist for these tests to
1102      * succeed so we need the "\\?\" prefix when creating directories and
1103      * files.
1104      */
1105     name[0] = 0;
1106     while (lstrlenW(name) < (sizeof(name)/sizeof(WCHAR) - 1))
1107         lstrcatW(name, letterX);
1108
1109     GetTempPathW(MAX_PATH, tempdir);
1110
1111     lstrcpyW(shortpath, prefix);
1112     lstrcatW(shortpath, tempdir);
1113     lstrcatW(shortpath, name);
1114     lstrcpyW(dirpath, shortpath);
1115     ret = CreateDirectoryW(shortpath, NULL);
1116     ok(ret, "Could not create the temporary directory : %d\n", GetLastError());
1117     lstrcatW(shortpath, backslash);
1118     lstrcatW(shortpath, name);
1119
1120     /* Path does not exist yet and we know it overruns MAX_PATH */
1121
1122     /* No prefix */
1123     SetLastError(0xdeadbeef);
1124     length = pGetLongPathNameW(shortpath + 4, NULL, 0);
1125     ok(length == 0, "Expected 0, got %d\n", length);
1126     todo_wine
1127     ok(GetLastError() == ERROR_PATH_NOT_FOUND,
1128        "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
1129     /* With prefix */
1130     SetLastError(0xdeadbeef);
1131     length = pGetLongPathNameW(shortpath, NULL, 0);
1132     todo_wine
1133     {
1134     ok(length == 0, "Expected 0, got %d\n", length);
1135     ok(GetLastError() == ERROR_FILE_NOT_FOUND,
1136        "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
1137     }
1138
1139     file = CreateFileW(shortpath, GENERIC_READ|GENERIC_WRITE, 0, NULL,
1140                        CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1141     ok(file != INVALID_HANDLE_VALUE,
1142        "Could not create the temporary file : %d.\n", GetLastError());
1143     CloseHandle(file);
1144
1145     /* Path exists */
1146
1147     /* No prefix */
1148     SetLastError(0xdeadbeef);
1149     length = pGetLongPathNameW(shortpath + 4, NULL, 0);
1150     todo_wine
1151     {
1152     ok(length == 0, "Expected 0, got %d\n", length);
1153     ok(GetLastError() == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
1154     }
1155     /* With prefix */
1156     expanded = 4 + (pGetLongPathNameW(tempdir, NULL, 0) - 1) + lstrlenW(name) + 1 + lstrlenW(name) + 1;
1157     SetLastError(0xdeadbeef);
1158     length = pGetLongPathNameW(shortpath, NULL, 0);
1159     ok(length == expanded, "Expected %d, got %d\n", expanded, length);
1160
1161     /* NULL buffer with length crashes on Windows */
1162     if (0)
1163     length = pGetLongPathNameW(shortpath, NULL, 20);
1164
1165     ok(DeleteFileW(shortpath), "Could not delete temporary file\n");
1166     ok(RemoveDirectoryW(dirpath), "Could not delete temporary directory\n");
1167 }
1168
1169 static void test_GetShortPathNameW(void)
1170 {
1171     WCHAR test_path[] = { 'L', 'o', 'n', 'g', 'D', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 'N', 'a', 'm', 'e',  0 };
1172     WCHAR path[MAX_PATH];
1173     WCHAR short_path[MAX_PATH];
1174     DWORD length;
1175     HANDLE file;
1176     int ret;
1177     WCHAR name[] = { 't', 'e', 's', 't', 0 };
1178     WCHAR backSlash[] = { '\\', 0 };
1179
1180     SetLastError(0xdeadbeef);
1181     GetTempPathW( MAX_PATH, path );
1182     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1183     {
1184         win_skip("GetTempPathW is not implemented\n");
1185         return;
1186     }
1187
1188     lstrcatW( path, test_path );
1189     lstrcatW( path, backSlash );
1190     ret = CreateDirectoryW( path, NULL );
1191     ok( ret, "Directory was not created. LastError = %d\n", GetLastError() );
1192
1193     /* Starting a main part of test */
1194     length = GetShortPathNameW( path, short_path, 0 );
1195     ok( length, "GetShortPathNameW returned 0.\n" );
1196     ret = GetShortPathNameW( path, short_path, length );
1197     ok( ret, "GetShortPathNameW returned 0.\n" );
1198     lstrcatW( short_path, name );
1199     file = CreateFileW( short_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1200     ok( file != INVALID_HANDLE_VALUE, "File was not created.\n" );
1201
1202     /* End test */
1203     CloseHandle( file );
1204     ret = DeleteFileW( short_path );
1205     ok( ret, "Cannot delete file.\n" );
1206     ret = RemoveDirectoryW( path );
1207     ok( ret, "Cannot delete directory.\n" );
1208 }
1209
1210 static void test_GetSystemDirectory(void)
1211 {
1212     CHAR    buffer[MAX_PATH + 4];
1213     DWORD   res;
1214     DWORD   total;
1215
1216     SetLastError(0xdeadbeef);
1217     res = GetSystemDirectory(NULL, 0);
1218     /* res includes the terminating Zero */
1219     ok(res > 0, "returned %d with %d (expected '>0')\n", res, GetLastError());
1220
1221     total = res;
1222
1223     /* this crashes on XP */
1224     if (0) res = GetSystemDirectory(NULL, total);
1225
1226     SetLastError(0xdeadbeef);
1227     res = GetSystemDirectory(NULL, total-1);
1228     /* 95+NT: total (includes the terminating Zero)
1229        98+ME: 0 with ERROR_INVALID_PARAMETER */
1230     ok( (res == total) || (!res && (GetLastError() == ERROR_INVALID_PARAMETER)),
1231         "returned %d with %d (expected '%d' or: '0' with "
1232         "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), total);
1233
1234     if (total > MAX_PATH) return;
1235
1236     buffer[0] = '\0';
1237     SetLastError(0xdeadbeef);
1238     res = GetSystemDirectory(buffer, total);
1239     /* res does not include the terminating Zero */
1240     ok( (res == (total-1)) && (buffer[0]),
1241         "returned %d with %d and '%s' (expected '%d' and a string)\n",
1242         res, GetLastError(), buffer, total-1);
1243
1244     buffer[0] = '\0';
1245     SetLastError(0xdeadbeef);
1246     res = GetSystemDirectory(buffer, total + 1);
1247     /* res does not include the terminating Zero */
1248     ok( (res == (total-1)) && (buffer[0]),
1249         "returned %d with %d and '%s' (expected '%d' and a string)\n",
1250         res, GetLastError(), buffer, total-1);
1251
1252     memset(buffer, '#', total + 1);
1253     buffer[total + 2] = '\0';
1254     SetLastError(0xdeadbeef);
1255     res = GetSystemDirectory(buffer, total-1);
1256     /* res includes the terminating Zero) */
1257     ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1258         res, GetLastError(), buffer, total);
1259
1260     memset(buffer, '#', total + 1);
1261     buffer[total + 2] = '\0';
1262     SetLastError(0xdeadbeef);
1263     res = GetSystemDirectory(buffer, total-2);
1264     /* res includes the terminating Zero) */
1265     ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1266         res, GetLastError(), buffer, total);
1267 }
1268
1269 static void test_GetWindowsDirectory(void)
1270 {
1271     CHAR    buffer[MAX_PATH + 4];
1272     DWORD   res;
1273     DWORD   total;
1274
1275     SetLastError(0xdeadbeef);
1276     res = GetWindowsDirectory(NULL, 0);
1277     /* res includes the terminating Zero */
1278     ok(res > 0, "returned %d with %d (expected '>0')\n", res, GetLastError());
1279
1280     total = res;
1281     /* this crashes on XP */
1282     if (0) res = GetWindowsDirectory(NULL, total);
1283
1284     SetLastError(0xdeadbeef);
1285     res = GetWindowsDirectory(NULL, total-1);
1286     /* 95+NT: total (includes the terminating Zero)
1287        98+ME: 0 with ERROR_INVALID_PARAMETER */
1288     ok( (res == total) || (!res && (GetLastError() == ERROR_INVALID_PARAMETER)),
1289         "returned %d with %d (expected '%d' or: '0' with "
1290         "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), total);
1291
1292     if (total > MAX_PATH) return;
1293
1294     buffer[0] = '\0';
1295     SetLastError(0xdeadbeef);
1296     res = GetWindowsDirectory(buffer, total);
1297     /* res does not include the terminating Zero */
1298     ok( (res == (total-1)) && (buffer[0]),
1299         "returned %d with %d and '%s' (expected '%d' and a string)\n",
1300         res, GetLastError(), buffer, total-1);
1301
1302     buffer[0] = '\0';
1303     SetLastError(0xdeadbeef);
1304     res = GetWindowsDirectory(buffer, total + 1);
1305     /* res does not include the terminating Zero */
1306     ok( (res == (total-1)) && (buffer[0]),
1307         "returned %d with %d and '%s' (expected '%d' and a string)\n",
1308         res, GetLastError(), buffer, total-1);
1309
1310     memset(buffer, '#', total + 1);
1311     buffer[total + 2] = '\0';
1312     SetLastError(0xdeadbeef);
1313     res = GetWindowsDirectory(buffer, total-1);
1314     /* res includes the terminating Zero) */
1315     ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1316         res, GetLastError(), buffer, total);
1317
1318     memset(buffer, '#', total + 1);
1319     buffer[total + 2] = '\0';
1320     SetLastError(0xdeadbeef);
1321     res = GetWindowsDirectory(buffer, total-2);
1322     /* res includes the terminating Zero) */
1323     ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1324         res, GetLastError(), buffer, total);
1325 }
1326
1327 static void test_NeedCurrentDirectoryForExePathA(void)
1328 {
1329     if (!pNeedCurrentDirectoryForExePathA)
1330     {
1331         win_skip("NeedCurrentDirectoryForExePathA is not available\n");
1332         return;
1333     }
1334
1335     /* Crashes in Windows */
1336     if (0)
1337         ok(pNeedCurrentDirectoryForExePathA(NULL), "returned FALSE for NULL\n");
1338
1339     SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", NULL);
1340     ok(pNeedCurrentDirectoryForExePathA("."), "returned FALSE for \".\"\n");
1341     ok(pNeedCurrentDirectoryForExePathA("c:\\"), "returned FALSE for \"c:\\\"\n");
1342     ok(pNeedCurrentDirectoryForExePathA("cmd.exe"), "returned FALSE for \"cmd.exe\"\n");
1343
1344     SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", "nya");
1345     ok(!pNeedCurrentDirectoryForExePathA("."), "returned TRUE for \".\"\n");
1346     ok(pNeedCurrentDirectoryForExePathA("c:\\"), "returned FALSE for \"c:\\\"\n");
1347     ok(!pNeedCurrentDirectoryForExePathA("cmd.exe"), "returned TRUE for \"cmd.exe\"\n");
1348 }
1349
1350 static void test_NeedCurrentDirectoryForExePathW(void)
1351 {
1352     const WCHAR thispath[] = {'.', 0};
1353     const WCHAR fullpath[] = {'c', ':', '\\', 0};
1354     const WCHAR cmdname[] = {'c', 'm', 'd', '.', 'e', 'x', 'e', 0};
1355
1356     if (!pNeedCurrentDirectoryForExePathW)
1357     {
1358         win_skip("NeedCurrentDirectoryForExePathW is not available\n");
1359         return;
1360     }
1361
1362     /* Crashes in Windows */
1363     if (0)
1364         ok(pNeedCurrentDirectoryForExePathW(NULL), "returned FALSE for NULL\n");
1365
1366     SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", NULL);
1367     ok(pNeedCurrentDirectoryForExePathW(thispath), "returned FALSE for \".\"\n");
1368     ok(pNeedCurrentDirectoryForExePathW(fullpath), "returned FALSE for \"c:\\\"\n");
1369     ok(pNeedCurrentDirectoryForExePathW(cmdname), "returned FALSE for \"cmd.exe\"\n");
1370
1371     SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", "nya");
1372     ok(!pNeedCurrentDirectoryForExePathW(thispath), "returned TRUE for \".\"\n");
1373     ok(pNeedCurrentDirectoryForExePathW(fullpath), "returned FALSE for \"c:\\\"\n");
1374     ok(!pNeedCurrentDirectoryForExePathW(cmdname), "returned TRUE for \"cmd.exe\"\n");
1375 }
1376
1377 /* Call various path/file name retrieving APIs and check the case of
1378  * the returned drive letter. Some apps (for instance Adobe Photoshop CS3
1379  * installer) depend on the drive letter being in upper case.
1380  */
1381 static void test_drive_letter_case(void)
1382 {
1383     UINT ret;
1384     char buf[MAX_PATH];
1385
1386 #define is_upper_case_letter(a) ((a) >= 'A' && (a) <= 'Z')
1387
1388     memset(buf, 0, sizeof(buf));
1389     SetLastError(0xdeadbeef);
1390     ret = GetWindowsDirectory(buf, sizeof(buf));
1391     ok(ret, "GetWindowsDirectory error %u\n", GetLastError());
1392     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1393     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1394     ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1395
1396     /* re-use the buffer returned by GetFullPathName */
1397     buf[2] = '/';
1398     SetLastError(0xdeadbeef);
1399     ret = GetFullPathName(buf + 2, sizeof(buf), buf, NULL);
1400     ok(ret, "GetFullPathName error %u\n", GetLastError());
1401     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1402     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1403     ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1404
1405     memset(buf, 0, sizeof(buf));
1406     SetLastError(0xdeadbeef);
1407     ret = GetSystemDirectory(buf, sizeof(buf));
1408     ok(ret, "GetSystemDirectory error %u\n", GetLastError());
1409     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1410     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1411     ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1412
1413     memset(buf, 0, sizeof(buf));
1414     SetLastError(0xdeadbeef);
1415     ret = GetCurrentDirectory(sizeof(buf), buf);
1416     ok(ret, "GetCurrentDirectory error %u\n", GetLastError());
1417     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1418     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1419     ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1420
1421     /* TEMP is an environment variable, so it can't be tested for case-sensitivity */
1422     memset(buf, 0, sizeof(buf));
1423     SetLastError(0xdeadbeef);
1424     ret = GetTempPath(sizeof(buf), buf);
1425     ok(ret, "GetTempPath error %u\n", GetLastError());
1426     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1427     if (buf[0])
1428     {
1429         ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1430         ok(buf[strlen(buf)-1] == '\\', "Temporary path (%s) doesn't end in a slash\n", buf);
1431     }
1432
1433     memset(buf, 0, sizeof(buf));
1434     SetLastError(0xdeadbeef);
1435     ret = GetFullPathName(".", sizeof(buf), buf, NULL);
1436     ok(ret, "GetFullPathName error %u\n", GetLastError());
1437     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1438     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1439     ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1440
1441     /* re-use the buffer returned by GetFullPathName */
1442     SetLastError(0xdeadbeef);
1443     ret = GetShortPathName(buf, buf, sizeof(buf));
1444     ok(ret, "GetShortPathName error %u\n", GetLastError());
1445     ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1446     ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1447     ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1448
1449     if (pGetLongPathNameA)
1450     {
1451         /* re-use the buffer returned by GetShortPathName */
1452         SetLastError(0xdeadbeef);
1453         ret = pGetLongPathNameA(buf, buf, sizeof(buf));
1454         ok(ret, "GetLongPathNameA error %u\n", GetLastError());
1455         ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1456         ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1457         ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1458     }
1459 #undef is_upper_case_letter
1460 }
1461
1462 static void test_SearchPathA(void)
1463 {
1464     CHAR pathA[MAX_PATH], fileA[] = "", buffA[MAX_PATH];
1465     CHAR *ptrA = NULL;
1466     DWORD ret;
1467
1468     if (!pSearchPathA)
1469     {
1470         win_skip("SearchPathA isn't available\n");
1471         return;
1472     }
1473
1474     GetWindowsDirectoryA(pathA, sizeof(pathA)/sizeof(CHAR));
1475
1476     /* NULL filename */
1477     SetLastError(0xdeadbeef);
1478     ret = pSearchPathA(pathA, NULL, NULL, sizeof(buffA)/sizeof(CHAR), buffA, &ptrA);
1479     ok(ret == 0, "Expected failure, got %d\n", ret);
1480     ok(GetLastError() == ERROR_INVALID_PARAMETER,
1481       "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
1482
1483     /* empty filename */
1484     SetLastError(0xdeadbeef);
1485     ret = pSearchPathA(pathA, fileA, NULL, sizeof(buffA)/sizeof(CHAR), buffA, &ptrA);
1486     ok(ret == 0, "Expected failure, got %d\n", ret);
1487     ok(GetLastError() == ERROR_INVALID_PARAMETER ||
1488        broken(GetLastError() == ERROR_FILE_NOT_FOUND) /* win9x */,
1489       "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
1490 }
1491
1492 static void test_SearchPathW(void)
1493 {
1494     WCHAR pathW[MAX_PATH], fileW[] = { 0 }, buffW[MAX_PATH];
1495     WCHAR *ptrW = NULL;
1496     DWORD ret;
1497
1498     if (!pSearchPathW)
1499     {
1500         win_skip("SearchPathW isn't available\n");
1501         return;
1502     }
1503
1504     /* SearchPathW is a stub on win9x and doesn't return sane error,
1505        so quess if it's implemented indirectly */
1506     SetLastError(0xdeadbeef);
1507     GetWindowsDirectoryW(pathW, sizeof(pathW)/sizeof(WCHAR));
1508     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1509     {
1510         win_skip("SearchPathW not implemented\n");
1511         return;
1512     }
1513
1514 if (0)
1515 {
1516     /* NULL filename, crashes on nt4 */
1517     SetLastError(0xdeadbeef);
1518     ret = pSearchPathW(pathW, NULL, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, &ptrW);
1519     ok(ret == 0, "Expected failure, got %d\n", ret);
1520     ok(GetLastError() == ERROR_INVALID_PARAMETER,
1521        "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
1522 }
1523
1524     /* empty filename */
1525     SetLastError(0xdeadbeef);
1526     ret = pSearchPathW(pathW, fileW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, &ptrW);
1527     ok(ret == 0, "Expected failure, got %d\n", ret);
1528     ok(GetLastError() == ERROR_INVALID_PARAMETER,
1529       "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
1530 }
1531
1532 static void init_pointers(void)
1533 {
1534     HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
1535
1536 #define MAKEFUNC(f) (p##f = (void*)GetProcAddress(hKernel32, #f))
1537     MAKEFUNC(GetLongPathNameA);
1538     MAKEFUNC(GetLongPathNameW);
1539     MAKEFUNC(NeedCurrentDirectoryForExePathA);
1540     MAKEFUNC(NeedCurrentDirectoryForExePathW);
1541     MAKEFUNC(SearchPathA);
1542     MAKEFUNC(SearchPathW);
1543 #undef MAKEFUNC
1544 }
1545
1546 START_TEST(path)
1547 {
1548     CHAR origdir[MAX_PATH],curdir[MAX_PATH], curDrive, otherDrive;
1549
1550     init_pointers();
1551
1552     /* Report only once */
1553     if (!pGetLongPathNameA)
1554         win_skip("GetLongPathNameA is not available\n");
1555     if (!pGetLongPathNameW)
1556         win_skip("GetLongPathNameW is not available\n");
1557
1558     test_InitPathA(curdir, &curDrive, &otherDrive);
1559     test_CurrentDirectoryA(origdir,curdir);
1560     test_PathNameA(curdir, curDrive, otherDrive);
1561     test_CleanupPathA(origdir,curdir);
1562     test_GetTempPath();
1563     test_GetLongPathNameA();
1564     test_GetLongPathNameW();
1565     test_GetShortPathNameW();
1566     test_GetSystemDirectory();
1567     test_GetWindowsDirectory();
1568     test_NeedCurrentDirectoryForExePathA();
1569     test_NeedCurrentDirectoryForExePathW();
1570     test_drive_letter_case();
1571     test_SearchPathA();
1572     test_SearchPathW();
1573 }