kernel32/tests: Get rid of unneeded function typedefs.
[wine/multimedia.git] / dlls / kernel32 / tests / path.c
blobba47910f8e37836a6985e93dbadb7a6e035e8423
1 /*
2 * Unit test suite for various Path and Directory Functions
4 * Copyright 2002 Geoffrey Hausheer
5 * Copyright 2006 Detlef Riekenberg
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.
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.
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
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"
31 #define HAS_TRAIL_SLASH_A(string) (string[lstrlenA(string)-1]=='\\')
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"
42 #define NOT_A_VALID_DRIVE '@'
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 |<>"
50 static const CHAR funny_chars[]="!@#$%^&*()=+{}[],?'`";
51 static const CHAR is_char_ok[] ="11111110111111111011";
53 static DWORD (WINAPI *pGetLongPathNameA)(LPCSTR,LPSTR,DWORD);
54 static DWORD (WINAPI *pGetLongPathNameW)(LPWSTR,LPWSTR,DWORD);
56 /* Present in Win2003+ */
57 static BOOL (WINAPI *pNeedCurrentDirectoryForExePathA)(LPCSTR);
58 static BOOL (WINAPI *pNeedCurrentDirectoryForExePathW)(LPCWSTR);
60 static DWORD (WINAPI *pSearchPathA)(LPCSTR,LPCSTR,LPCSTR,DWORD,LPSTR,LPSTR*);
61 static DWORD (WINAPI *pSearchPathW)(LPCWSTR,LPCWSTR,LPCWSTR,DWORD,LPWSTR,LPWSTR*);
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;
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
78 static void test_ValidPathA(const CHAR *curdir, const CHAR *subdir, const CHAR *filename,
79 CHAR *shortstr, SLpassfail *passfail, const CHAR *errstr)
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
94 if(passfail!=NULL) {
95 passfail->shortlen=-1;passfail->s2llen=-1;passfail->longlen=-1;
96 passfail->shorterror=0;passfail->s2lerror=0;passfail->longerror=0;
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);
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);
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);
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();
146 /* Test GetLongPathNameA functionality
147 We test both conversion from GetFullPathNameA and from GetShortPathNameA
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();
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);
177 } else {
178 passfail->longlen=len;
179 passfail->longerror=GetLastError();
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;
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,"");
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");
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];
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);
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.
240 static void test_FunnyChars(CHAR *curdir,CHAR *curdir_short,CHAR *filename, INT valid,CHAR *errstr)
242 CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
243 SLpassfail passfail;
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);
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);
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)
278 CHAR tmppath[MAX_PATH], *dirptr;
279 DWORD val,len,chklen;
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);
309 static void test_InitPathA(CHAR *newdir, CHAR *curDrive, CHAR *otherDrive)
311 CHAR tmppath[MAX_PATH], /*path to TEMP */
312 tmpstr[MAX_PATH],
313 tmpstr1[MAX_PATH],
314 invalid_dir[MAX_PATH];
316 DWORD len,len1,drives;
317 INT id;
318 HANDLE hndl;
319 BOOL bRes;
320 UINT unique;
322 *curDrive = *otherDrive = NOT_A_VALID_DRIVE;
324 /* Get the current drive letter */
325 if( GetCurrentDirectoryA( MAX_PATH, tmpstr))
326 *curDrive = tmpstr[0];
327 else
328 trace( "Unable to discover current drive, some tests will not be conducted.\n");
330 /* Test GetTempPathA */
331 len=GetTempPathA(MAX_PATH,tmppath);
332 ok(len!=0 && len < MAX_PATH,"GetTempPathA failed\n");
333 ok(HAS_TRAIL_SLASH_A(tmppath),
334 "GetTempPathA returned a path that did not end in '\\'\n");
335 lstrcpyA(tmpstr,"aaaaaaaa");
336 len1=GetTempPathA(len,tmpstr);
337 ok(len1==len+1 || broken(len1 == len), /* WinME */
338 "GetTempPathA should return string length %d instead of %d\n",len+1,len1);
340 /* Test GetTmpFileNameA */
341 ok((id=GetTempFileNameA(tmppath,"path",0,newdir)),"GetTempFileNameA failed\n");
342 sprintf(tmpstr,"pat%.4x.tmp",id & 0xffff);
343 sprintf(tmpstr1,"pat%x.tmp",id & 0xffff);
344 ok(lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr)==0 ||
345 lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr1)==0,
346 "GetTempFileNameA returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
347 newdir,tmpstr,tmpstr1,id);
348 ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
350 id=GetTempFileNameA(tmppath,NULL,0,newdir);
351 /* Windows 95, 98 return 0==id, while Windows 2000, XP return 0!=id */
352 if (id)
354 sprintf(tmpstr,"%.4x.tmp",id & 0xffff);
355 sprintf(tmpstr1,"%x.tmp",id & 0xffff);
356 ok(lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr)==0 ||
357 lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr1)==0,
358 "GetTempFileNameA returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
359 newdir,tmpstr,tmpstr1,id);
360 ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
363 for(unique=0;unique<3;unique++) {
364 /* Nonexistent path */
365 sprintf(invalid_dir, "%s\\%s",tmppath,"non_existent_dir_1jwj3y32nb3");
366 SetLastError(0xdeadbeef);
367 ok(!GetTempFileNameA(invalid_dir,"tfn",unique,newdir),"GetTempFileNameA should have failed\n");
368 ok(GetLastError()==ERROR_DIRECTORY || broken(GetLastError()==ERROR_PATH_NOT_FOUND)/*win98*/,
369 "got %d, expected ERROR_DIRECTORY\n", GetLastError());
371 /* Check return value for unique !=0 */
372 if(unique) {
373 ok((GetTempFileNameA(tmppath,"tfn",unique,newdir) == unique),"GetTempFileNameA unexpectedly failed\n");
374 /* if unique != 0, the actual temp files are not created: */
375 ok(!DeleteFileA(newdir) && GetLastError() == ERROR_FILE_NOT_FOUND,"Deleted a file that shouldn't exist!\n");
379 /* Find first valid drive letter that is neither newdir[0] nor curDrive */
380 drives = GetLogicalDrives() & ~(1<<(newdir[0]-'A'));
381 if( *curDrive != NOT_A_VALID_DRIVE)
382 drives &= ~(1<<(*curDrive-'A'));
383 if( drives)
384 for( *otherDrive='A'; (drives & 1) == 0; drives>>=1, (*otherDrive)++);
385 else
386 trace( "Could not find alternative drive, some tests will not be conducted.\n");
388 /* Do some CreateDirectoryA tests */
389 /* It would be nice to do test the SECURITY_ATTRIBUTES, but I don't
390 really understand how they work.
391 More formal tests should be done along with CreateFile tests
393 ok((id=GetTempFileNameA(tmppath,"path",0,newdir)),"GetTempFileNameA failed\n");
394 ok(CreateDirectoryA(newdir,NULL)==0,
395 "CreateDirectoryA succeeded even though a file of the same name exists\n");
396 ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
397 ok(CreateDirectoryA(newdir,NULL),"CreateDirectoryA failed\n");
398 /* Create some files to test other functions. Note, we will test CreateFileA
399 at some later point
401 sprintf(tmpstr,"%s\\%s",newdir,SHORTDIR);
402 ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed\n");
403 sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
404 ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed\n");
405 sprintf(tmpstr,"%c:", *curDrive);
406 bRes = CreateDirectoryA(tmpstr,NULL);
407 ok(!bRes && (GetLastError() == ERROR_ACCESS_DENIED ||
408 GetLastError() == ERROR_ALREADY_EXISTS),
409 "CreateDirectoryA(\"%s\" should have failed (%d)\n", tmpstr, GetLastError());
410 sprintf(tmpstr,"%c:\\", *curDrive);
411 bRes = CreateDirectoryA(tmpstr,NULL);
412 ok(!bRes && (GetLastError() == ERROR_ACCESS_DENIED ||
413 GetLastError() == ERROR_ALREADY_EXISTS),
414 "CreateDirectoryA(\"%s\" should have failed (%d)\n", tmpstr, GetLastError());
415 sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,SHORTFILE);
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 sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,LONGFILE);
421 hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
422 CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
423 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
424 ok(CloseHandle(hndl),"CloseHandle failed\n");
425 sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,SHORTFILE);
426 hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
427 CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
428 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
429 ok(CloseHandle(hndl),"CloseHandle failed\n");
430 sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,LONGFILE);
431 hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
432 CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
433 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
434 ok(CloseHandle(hndl),"CloseHandle failed\n");
437 /* Test GetCurrentDirectory & SetCurrentDirectory */
438 static void test_CurrentDirectoryA(CHAR *origdir, CHAR *newdir)
440 CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
441 char *buffer;
442 DWORD len,len1;
443 /* Save the original directory, so that we can return to it at the end
444 of the test
446 len=GetCurrentDirectoryA(MAX_PATH,origdir);
447 ok(len!=0 && len < MAX_PATH,"GetCurrentDirectoryA failed\n");
448 /* Make sure that CetCurrentDirectoryA doesn't overwrite the buffer when the
449 buffer size is too small to hold the current directory
451 lstrcpyA(tmpstr,"aaaaaaa");
452 len1=GetCurrentDirectoryA(len,tmpstr);
453 ok(len1==len+1, "GetCurrentDirectoryA returned %d instead of %d\n",len1,len+1);
454 ok(lstrcmpiA(tmpstr,"aaaaaaa")==0,
455 "GetCurrentDirectoryA should not have modified the buffer\n");
457 buffer = HeapAlloc( GetProcessHeap(), 0, 2 * 65536 );
458 SetLastError( 0xdeadbeef );
459 strcpy( buffer, "foo" );
460 len = GetCurrentDirectoryA( 32767, buffer );
461 ok( len != 0 && len < MAX_PATH, "GetCurrentDirectoryA failed %u err %u\n", len, GetLastError() );
462 if (len) ok( !strcmp( buffer, origdir ), "wrong result %s\n", buffer );
463 SetLastError( 0xdeadbeef );
464 strcpy( buffer, "foo" );
465 len = GetCurrentDirectoryA( 32768, buffer );
466 ok( len != 0 && len < MAX_PATH, "GetCurrentDirectoryA failed %u err %u\n", len, GetLastError() );
467 if (len) ok( !strcmp( buffer, origdir ), "wrong result %s\n", buffer );
468 SetLastError( 0xdeadbeef );
469 strcpy( buffer, "foo" );
470 len = GetCurrentDirectoryA( 65535, buffer );
471 ok( (len != 0 && len < MAX_PATH) || broken(!len), /* nt4, win2k, xp */ "GetCurrentDirectoryA failed %u err %u\n", len, GetLastError() );
472 if (len) ok( !strcmp( buffer, origdir ), "wrong result %s\n", buffer );
473 SetLastError( 0xdeadbeef );
474 strcpy( buffer, "foo" );
475 len = GetCurrentDirectoryA( 65536, buffer );
476 ok( (len != 0 && len < MAX_PATH) || broken(!len), /* nt4 */ "GetCurrentDirectoryA failed %u err %u\n", len, GetLastError() );
477 if (len) ok( !strcmp( buffer, origdir ), "wrong result %s\n", buffer );
478 SetLastError( 0xdeadbeef );
479 strcpy( buffer, "foo" );
480 len = GetCurrentDirectoryA( 2 * 65536, buffer );
481 ok( (len != 0 && len < MAX_PATH) || broken(!len), /* nt4 */ "GetCurrentDirectoryA failed %u err %u\n", len, GetLastError() );
482 if (len) ok( !strcmp( buffer, origdir ), "wrong result %s\n", buffer );
483 HeapFree( GetProcessHeap(), 0, buffer );
485 /* Check for crash prevention on swapped args. Crashes all but Win9x.
487 if (0)
489 GetCurrentDirectoryA( 42, (LPSTR)(MAX_PATH + 42) );
492 /* SetCurrentDirectoryA shouldn't care whether the string has a
493 trailing '\\' or not
495 sprintf(tmpstr,"%s\\",newdir);
496 test_setdir(origdir,tmpstr,newdir,1,"check 1");
497 test_setdir(origdir,newdir,NULL,1,"check 2");
498 /* Set the directory to the working area. We just tested that this works,
499 so why check it again.
501 SetCurrentDirectoryA(newdir);
502 /* Check that SetCurrentDirectory fails when a nonexistent dir is specified */
503 sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_SHORT);
504 test_setdir(newdir,tmpstr,NULL,0,"check 3");
505 /* Check that SetCurrentDirectory fails for a nonexistent lond directory */
506 sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_LONG);
507 test_setdir(newdir,tmpstr,NULL,0,"check 4");
508 /* Check that SetCurrentDirectory passes with a long directory */
509 sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
510 test_setdir(newdir,tmpstr,NULL,1,"check 5");
511 /* Check that SetCurrentDirectory passes with a short relative directory */
512 sprintf(tmpstr,"%s",SHORTDIR);
513 sprintf(tmpstr1,"%s\\%s",newdir,SHORTDIR);
514 test_setdir(newdir,tmpstr,tmpstr1,1,"check 6");
515 /* starting with a '.' */
516 sprintf(tmpstr,".\\%s",SHORTDIR);
517 test_setdir(newdir,tmpstr,tmpstr1,1,"check 7");
518 /* Check that SetCurrentDirectory passes with a short relative directory */
519 sprintf(tmpstr,"%s",LONGDIR);
520 sprintf(tmpstr1,"%s\\%s",newdir,LONGDIR);
521 test_setdir(newdir,tmpstr,tmpstr1,1,"check 8");
522 /* starting with a '.' */
523 sprintf(tmpstr,".\\%s",LONGDIR);
524 test_setdir(newdir,tmpstr,tmpstr1,1,"check 9");
525 /* change to root without a trailing backslash. The function call succeeds
526 but the directory is not changed.
528 sprintf(tmpstr, "%c:", newdir[0]);
529 test_setdir(newdir,tmpstr,newdir,1,"check 10");
530 /* works however with a trailing backslash */
531 sprintf(tmpstr, "%c:\\", newdir[0]);
532 test_setdir(newdir,tmpstr,NULL,1,"check 11");
535 /* Cleanup the mess we made while executing these tests */
536 static void test_CleanupPathA(CHAR *origdir, CHAR *curdir)
538 CHAR tmpstr[MAX_PATH];
539 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
540 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
541 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,LONGFILE);
542 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
543 sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,SHORTFILE);
544 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
545 sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
546 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
547 sprintf(tmpstr,"%s\\%s",curdir,SHORTDIR);
548 ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
549 sprintf(tmpstr,"%s\\%s",curdir,LONGDIR);
550 ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
551 ok(SetCurrentDirectoryA(origdir),"SetCurrentDirectoryA failed\n");
552 ok(RemoveDirectoryA(curdir),"RemoveDirectoryA failed\n");
555 /* test that short path name functions work regardless of case */
556 static void test_ShortPathCase(const char *tmpdir, const char *dirname,
557 const char *filename)
559 char buf[MAX_PATH], shortbuf[MAX_PATH];
560 HANDLE hndl;
561 int i;
563 snprintf(buf,sizeof(buf),"%s\\%s\\%s",tmpdir,dirname,filename);
564 GetShortPathNameA(buf,shortbuf,sizeof(shortbuf));
565 hndl = CreateFileA(shortbuf,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
566 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed (%d)\n",GetLastError());
567 CloseHandle(hndl);
568 /* Now for the real test */
569 for(i=0;i<strlen(shortbuf);i++)
570 if (i % 2)
571 shortbuf[i] = tolower(shortbuf[i]);
572 hndl = CreateFileA(shortbuf,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
573 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed (%d)\n",GetLastError());
574 CloseHandle(hndl);
577 /* This routine will test Get(Full|Short|Long)PathNameA */
578 static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive)
580 CHAR curdir_short[MAX_PATH],
581 longdir_short[MAX_PATH];
582 CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH],tmpstr2[MAX_PATH];
583 LPSTR strptr; /*ptr to the filename portion of the path */
584 DWORD len;
585 INT i;
586 CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
587 SLpassfail passfail;
589 /* Get the short form of the current directory */
590 ok((len=GetShortPathNameA(curdir,curdir_short,MAX_PATH)),
591 "GetShortPathNameA failed\n");
592 ok(!HAS_TRAIL_SLASH_A(curdir_short),
593 "GetShortPathNameA should not have a trailing \\\n");
594 /* Get the short form of the absolute-path to LONGDIR */
595 sprintf(tmpstr,"%s\\%s",curdir_short,LONGDIR);
596 ok((len=GetShortPathNameA(tmpstr,longdir_short,MAX_PATH)),
597 "GetShortPathNameA failed\n");
598 ok(lstrcmpiA(longdir_short+(len-1),"\\")!=0,
599 "GetShortPathNameA should not have a trailing \\\n");
601 if (pGetLongPathNameA) {
602 DWORD rc1,rc2;
603 sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
604 rc1=(*pGetLongPathNameA)(tmpstr,NULL,0);
605 rc2=(*pGetLongPathNameA)(curdir,NULL,0);
606 ok((rc1-strlen(tmpstr))==(rc2-strlen(curdir)),
607 "GetLongPathNameA: wrong return code, %d instead of %d\n",
608 rc1, lstrlenA(tmpstr)+1);
610 sprintf(dir,"%c:",curDrive);
611 rc1=(*pGetLongPathNameA)(dir,tmpstr,sizeof(tmpstr));
612 ok(strcmp(dir,tmpstr)==0,
613 "GetLongPathNameA: returned '%s' instead of '%s' (rc=%d)\n",
614 tmpstr,dir,rc1);
617 /* Check the cases where both file and directory exist first */
618 /* Start with a 8.3 directory, 8.3 filename */
619 test_ValidPathA(curdir,SHORTDIR,SHORTFILE,tmpstr,NULL,"test1");
620 sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,SHORTFILE);
621 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
622 "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
623 /* Now try a 8.3 directory, long file name */
624 test_ValidPathA(curdir,SHORTDIR,LONGFILE,tmpstr,NULL,"test2");
625 sprintf(tmpstr1,"%s\\%s",curdir_short,SHORTDIR);
626 test_LongtoShortA(tmpstr,tmpstr1,"PAT","test2");
627 /* Next is a long directory, 8.3 file */
628 test_ValidPathA(curdir,LONGDIR,SHORTFILE,tmpstr,NULL,"test3");
629 sprintf(tmpstr1,"%s\\%s",longdir_short,SHORTFILE);
630 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
631 "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
632 /*Lastly a long directory, long file */
633 test_ValidPathA(curdir,LONGDIR,LONGFILE,tmpstr,NULL,"test4");
634 test_LongtoShortA(tmpstr,longdir_short,"PAT","test4");
636 /* Now check all of the invalid file w/ valid directory combinations */
637 /* Start with a 8.3 directory, 8.3 filename */
638 test_ValidPathA(curdir,SHORTDIR,NONFILE_SHORT,tmpstr,&passfail,"test5");
639 sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,NONFILE_SHORT);
640 ok((passfail.shortlen==0 &&
641 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
642 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
643 (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
644 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
645 passfail.shortlen,passfail.shorterror,tmpstr);
646 if(pGetLongPathNameA) {
647 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
648 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
649 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
651 /* Now try a 8.3 directory, long file name */
652 test_ValidPathA(curdir,SHORTDIR,NONFILE_LONG,tmpstr,&passfail,"test6");
653 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
654 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
655 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
656 !passfail.shorterror,
657 "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
658 if(pGetLongPathNameA) {
659 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
660 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
661 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
663 /* Next is a long directory, 8.3 file */
664 test_ValidPathA(curdir,LONGDIR,NONFILE_SHORT,tmpstr,&passfail,"test7");
665 sprintf(tmpstr2,"%s\\%s",curdir_short,LONGDIR);
666 GetShortPathNameA(tmpstr2,tmpstr1,MAX_PATH);
667 strcat(tmpstr1,"\\" NONFILE_SHORT);
668 ok((passfail.shortlen==0 &&
669 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
670 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
671 (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
672 "GetShortPathNameA error: len=%d error=%d 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 should have returned 'ERROR_FILE_NOT_FOUND'\n");
679 /*Lastly a long directory, long file */
680 test_ValidPathA(curdir,LONGDIR,NONFILE_LONG,tmpstr,&passfail,"test8");
681 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
682 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
683 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
684 !passfail.shorterror,
685 "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
686 if(pGetLongPathNameA) {
687 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
688 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
689 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
691 /* Now try again with directories that don't exist */
692 /* 8.3 directory, 8.3 filename */
693 test_ValidPathA(curdir,NONDIR_SHORT,SHORTFILE,tmpstr,&passfail,"test9");
694 sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,NONDIR_SHORT,SHORTFILE);
695 ok((passfail.shortlen==0 &&
696 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
697 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
698 (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
699 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
700 passfail.shortlen,passfail.shorterror,tmpstr);
701 if(pGetLongPathNameA) {
702 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
703 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
704 passfail.longerror==ERROR_FILE_NOT_FOUND,
705 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
706 passfail.longerror);
708 /* Now try a 8.3 directory, long file name */
709 test_ValidPathA(curdir,NONDIR_SHORT,LONGFILE,tmpstr,&passfail,"test10");
710 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
711 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
712 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
713 !passfail.shorterror,
714 "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
715 passfail.shorterror);
716 if(pGetLongPathNameA) {
717 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
718 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
719 passfail.longerror==ERROR_FILE_NOT_FOUND,
720 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
721 passfail.longerror);
723 /* Next is a long directory, 8.3 file */
724 test_ValidPathA(curdir,NONDIR_LONG,SHORTFILE,tmpstr,&passfail,"test11");
725 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
726 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
727 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
728 !passfail.shorterror,
729 "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
730 passfail.shorterror);
731 if(pGetLongPathNameA) {
732 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
733 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
734 passfail.longerror==ERROR_FILE_NOT_FOUND,
735 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
736 passfail.longerror);
738 /*Lastly a long directory, long file */
739 test_ValidPathA(curdir,NONDIR_LONG,LONGFILE,tmpstr,&passfail,"test12");
740 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
741 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
742 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
743 !passfail.shorterror,
744 "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
745 passfail.shorterror);
746 if(pGetLongPathNameA) {
747 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
748 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
749 passfail.longerror==ERROR_FILE_NOT_FOUND,
750 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
751 passfail.longerror);
753 /* Next try directories ending with '\\' */
754 /* Existing Directories */
755 sprintf(tmpstr,"%s\\",SHORTDIR);
756 test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test13");
757 sprintf(tmpstr,"%s\\",LONGDIR);
758 test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test14");
759 /* Nonexistent directories */
760 sprintf(tmpstr,"%s\\",NONDIR_SHORT);
761 test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test15");
762 sprintf(tmpstr2,"%s\\%s",curdir_short,tmpstr);
763 ok((passfail.shortlen==0 &&
764 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
765 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
766 (passfail.shortlen==strlen(tmpstr2) && lstrcmpiA(tmpstr1,tmpstr2)==0),
767 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
768 passfail.shortlen,passfail.shorterror,tmpstr);
769 if(pGetLongPathNameA) {
770 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
771 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
772 "GetLongPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
773 passfail.longerror);
775 sprintf(tmpstr,"%s\\",NONDIR_LONG);
776 test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test16");
777 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
778 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
779 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
780 !passfail.shorterror,
781 "GetShortPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
782 passfail.shorterror);
783 if(pGetLongPathNameA) {
784 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
785 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
786 "GetLongPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
787 passfail.longerror);
789 /* Test GetFullPathNameA with drive letters */
790 if( curDrive != NOT_A_VALID_DRIVE) {
791 sprintf(tmpstr,"%c:",curdir[0]);
792 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr2,&strptr),
793 "GetFullPathNameA(%c:) failed\n", curdir[0]);
794 GetCurrentDirectoryA(MAX_PATH,tmpstr);
795 sprintf(tmpstr1,"%s\\",tmpstr);
796 ok(lstrcmpiA(tmpstr,tmpstr2)==0 || lstrcmpiA(tmpstr1,tmpstr2)==0,
797 "GetFullPathNameA(%c:) returned '%s' instead of '%s' or '%s'\n",
798 curdir[0],tmpstr2,tmpstr,tmpstr1);
800 sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
801 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
802 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
803 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
804 ok(lstrcmpiA(SHORTFILE,strptr)==0,
805 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
807 /* Without a leading slash, insert the current directory if on the current drive */
808 sprintf(tmpstr,"%c:%s\\%s",curdir[0],SHORTDIR,SHORTFILE);
809 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
810 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
811 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
812 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
813 ok(lstrcmpiA(SHORTFILE,strptr)==0,
814 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
815 /* Otherwise insert the missing leading slash */
816 if( otherDrive != NOT_A_VALID_DRIVE) {
817 /* FIXME: this test assumes that current directory on other drive is root */
818 sprintf(tmpstr,"%c:%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
819 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed for %s\n", tmpstr);
820 sprintf(tmpstr,"%c:\\%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
821 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
822 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
823 ok(lstrcmpiA(SHORTFILE,strptr)==0,
824 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
826 /* Xilinx tools like to mix Unix and DOS formats, which Windows handles fine.
827 So test for them. */
828 if( curDrive != NOT_A_VALID_DRIVE) {
829 sprintf(tmpstr,"%c:/%s\\%s",curDrive,SHORTDIR,SHORTFILE);
830 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
831 sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
832 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
833 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
834 ok(lstrcmpiA(SHORTFILE,strptr)==0,
835 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
837 /**/
838 sprintf(tmpstr,"%c:%s/%s",curdir[0],SHORTDIR,SHORTFILE);
839 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
840 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
841 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
842 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
843 ok(lstrcmpiA(SHORTFILE,strptr)==0,
844 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
845 /* Windows will insert a drive letter in front of an absolute UNIX path */
846 sprintf(tmpstr,"/%s/%s",SHORTDIR,SHORTFILE);
847 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
848 sprintf(tmpstr,"%c:\\%s\\%s",*tmpstr1,SHORTDIR,SHORTFILE);
849 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
850 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
851 /* This passes in Wine because it still contains the pointer from the previous test */
852 ok(lstrcmpiA(SHORTFILE,strptr)==0,
853 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
855 /* Now try some relative paths */
856 ok(GetShortPathNameA(LONGDIR,tmpstr,MAX_PATH),"GetShortPathNameA failed\n");
857 test_SplitShortPathA(tmpstr,dir,eight,three);
858 if(pGetLongPathNameA) {
859 ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
860 ok(lstrcmpiA(tmpstr1,LONGDIR)==0,
861 "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,LONGDIR);
863 sprintf(tmpstr,".\\%s",LONGDIR);
864 ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed\n");
865 test_SplitShortPathA(tmpstr1,dir,eight,three);
866 ok(lstrcmpiA(dir,".")==0 || dir[0]=='\0',
867 "GetShortPathNameA did not keep relative directory [%s]\n",tmpstr1);
868 if(pGetLongPathNameA) {
869 ok(pGetLongPathNameA(tmpstr1,tmpstr1,MAX_PATH),"GetLongPathNameA failed %s\n",
870 tmpstr);
871 ok(lstrcmpiA(tmpstr1,tmpstr)==0,
872 "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
874 /* Check out Get*PathNameA on some funny characters */
875 for(i=0;i<lstrlenA(funny_chars);i++) {
876 INT valid;
877 valid=(is_char_ok[i]=='0') ? 0 : 1;
878 sprintf(tmpstr1,"check%d-1",i);
879 sprintf(tmpstr,"file%c000.ext",funny_chars[i]);
880 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
881 sprintf(tmpstr1,"check%d-2",i);
882 sprintf(tmpstr,"file000.e%ct",funny_chars[i]);
883 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
884 sprintf(tmpstr1,"check%d-3",i);
885 sprintf(tmpstr,"%cfile000.ext",funny_chars[i]);
886 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
887 sprintf(tmpstr1,"check%d-4",i);
888 sprintf(tmpstr,"file000%c.ext",funny_chars[i]);
889 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
890 sprintf(tmpstr1,"check%d-5",i);
891 sprintf(tmpstr,"Long %c File",funny_chars[i]);
892 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
893 sprintf(tmpstr1,"check%d-6",i);
894 sprintf(tmpstr,"%c Long File",funny_chars[i]);
895 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
896 sprintf(tmpstr1,"check%d-7",i);
897 sprintf(tmpstr,"Long File %c",funny_chars[i]);
898 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
900 /* Now try it on mixed case short names */
901 test_ShortPathCase(curdir,SHORTDIR,LONGFILE);
902 test_ShortPathCase(curdir,LONGDIR,SHORTFILE);
903 test_ShortPathCase(curdir,LONGDIR,LONGFILE);
906 static void test_GetTempPathA(char* tmp_dir)
908 DWORD len, len_with_null;
909 char buf[MAX_PATH];
911 len_with_null = strlen(tmp_dir) + 1;
913 lstrcpyA(buf, "foo");
914 len = GetTempPathA(MAX_PATH, buf);
915 ok(len <= MAX_PATH, "should fit into MAX_PATH\n");
916 ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
917 ok(len == strlen(buf), "returned length should be equal to the length of string\n");
919 /* Some versions of Windows touch the buffer, some don't so we don't
920 * test that. Also, NT sometimes exaggerates the required buffer size
921 * so we cannot test for an exact match. Finally, the
922 * 'len_with_null - 1' case is so buggy on Windows it's not testable.
923 * For instance in some cases Win98 returns len_with_null - 1 instead
924 * of len_with_null.
926 len = GetTempPathA(1, buf);
927 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
929 len = GetTempPathA(0, NULL);
930 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
932 /* The call above gave us the buffer size that Windows thinks is needed
933 * so the next call should work
935 lstrcpyA(buf, "foo");
936 len = GetTempPathA(len, buf);
937 ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
938 ok(len == strlen(buf), "returned length should be equal to the length of string\n");
941 static void test_GetTempPathW(char* tmp_dir)
943 DWORD len, len_with_null;
944 WCHAR buf[MAX_PATH];
945 WCHAR tmp_dirW[MAX_PATH];
946 static const WCHAR fooW[] = {'f','o','o',0};
948 MultiByteToWideChar(CP_ACP,0,tmp_dir,-1,tmp_dirW,sizeof(tmp_dirW)/sizeof(*tmp_dirW));
949 len_with_null = lstrlenW(tmp_dirW) + 1;
951 /* This one is different from ANSI version: ANSI version doesn't
952 * touch the buffer, unicode version usually truncates the buffer
953 * to zero size. NT still exaggerates the required buffer size
954 * sometimes so we cannot test for an exact match. Finally, the
955 * 'len_with_null - 1' case is so buggy on Windows it's not testable.
956 * For instance on NT4 it will sometimes return a path without the
957 * trailing '\\' and sometimes return an error.
960 lstrcpyW(buf, fooW);
961 len = GetTempPathW(MAX_PATH, buf);
962 if (len == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
964 win_skip("GetTempPathW is not available\n");
965 return;
967 ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
968 ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
970 lstrcpyW(buf, fooW);
971 len = GetTempPathW(1, buf);
972 ok(buf[0] == 0, "unicode version should truncate the buffer to zero size\n");
973 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
975 len = GetTempPathW(0, NULL);
976 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
978 lstrcpyW(buf, fooW);
979 len = GetTempPathW(len, buf);
980 ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
981 ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
984 static void test_GetTempPath(void)
986 char save_TMP[MAX_PATH];
987 char windir[MAX_PATH];
988 char buf[MAX_PATH];
990 if (!GetEnvironmentVariableA("TMP", save_TMP, sizeof(save_TMP))) save_TMP[0] = 0;
992 /* test default configuration */
993 trace("TMP=%s\n", save_TMP);
994 if (save_TMP[0])
996 strcpy(buf,save_TMP);
997 if (buf[strlen(buf)-1]!='\\')
998 strcat(buf,"\\");
999 test_GetTempPathA(buf);
1000 test_GetTempPathW(buf);
1003 /* TMP=C:\WINDOWS */
1004 GetWindowsDirectoryA(windir, sizeof(windir));
1005 SetEnvironmentVariableA("TMP", windir);
1006 GetEnvironmentVariableA("TMP", buf, sizeof(buf));
1007 trace("TMP=%s\n", buf);
1008 strcat(windir,"\\");
1009 test_GetTempPathA(windir);
1010 test_GetTempPathW(windir);
1012 /* TMP=C:\ */
1013 GetWindowsDirectoryA(windir, sizeof(windir));
1014 windir[3] = 0;
1015 SetEnvironmentVariableA("TMP", windir);
1016 GetEnvironmentVariableA("TMP", buf, sizeof(buf));
1017 trace("TMP=%s\n", buf);
1018 test_GetTempPathA(windir);
1019 test_GetTempPathW(windir);
1021 /* TMP=C: i.e. use current working directory of the specified drive */
1022 GetWindowsDirectoryA(windir, sizeof(windir));
1023 SetCurrentDirectoryA(windir);
1024 windir[2] = 0;
1025 SetEnvironmentVariableA("TMP", windir);
1026 GetEnvironmentVariableA("TMP", buf, sizeof(buf));
1027 trace("TMP=%s\n", buf);
1028 GetWindowsDirectoryA(windir, sizeof(windir));
1029 strcat(windir,"\\");
1030 test_GetTempPathA(windir);
1031 test_GetTempPathW(windir);
1033 SetEnvironmentVariableA("TMP", save_TMP);
1036 static void test_GetLongPathNameA(void)
1038 DWORD length, explength, hostsize;
1039 char tempfile[MAX_PATH];
1040 char longpath[MAX_PATH];
1041 char unc_prefix[MAX_PATH];
1042 char unc_short[MAX_PATH], unc_long[MAX_PATH];
1043 char temppath[MAX_PATH], temppath2[MAX_PATH];
1044 HANDLE file;
1046 if (!pGetLongPathNameA)
1047 return;
1049 GetTempPathA(MAX_PATH, tempfile);
1050 lstrcatA(tempfile, "longfilename.longext");
1052 file = CreateFileA(tempfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1053 CloseHandle(file);
1055 /* Test a normal path with a small buffer size */
1056 memset(temppath, 0, MAX_PATH);
1057 length = pGetLongPathNameA(tempfile, temppath, 4);
1058 /* We have a failure so length should be the minimum plus the terminating '0' */
1059 ok(length >= lstrlen(tempfile) + 1, "Wrong length\n");
1060 ok(temppath[0] == 0, "Buffer should not have been touched\n");
1062 /* Some UNC syntax tests */
1064 memset(temppath, 0, MAX_PATH);
1065 memset(temppath2, 0, MAX_PATH);
1066 lstrcpyA(temppath2, "\\\\?\\");
1067 lstrcatA(temppath2, tempfile);
1068 explength = length + 4;
1070 SetLastError(0xdeadbeef);
1071 length = pGetLongPathNameA(temppath2, NULL, 0);
1072 if (length == 0 && GetLastError() == ERROR_BAD_NET_NAME)
1074 win_skip("UNC syntax tests don't work on Win98/WinMe\n");
1075 DeleteFileA(tempfile);
1076 return;
1078 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1080 length = pGetLongPathNameA(temppath2, NULL, MAX_PATH);
1081 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1083 length = pGetLongPathNameA(temppath2, temppath, 4);
1084 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1085 ok(temppath[0] == 0, "Buffer should not have been touched\n");
1087 /* Now an UNC path with the computername */
1088 lstrcpyA(unc_prefix, "\\\\");
1089 hostsize = sizeof(unc_prefix) - 2;
1090 GetComputerName(unc_prefix + 2, &hostsize);
1091 lstrcatA(unc_prefix, "\\");
1093 /* Create a short syntax for the whole unc path */
1094 memset(unc_short, 0, MAX_PATH);
1095 GetShortPathNameA(tempfile, temppath, MAX_PATH);
1096 lstrcpyA(unc_short, unc_prefix);
1097 unc_short[lstrlenA(unc_short)] = temppath[0];
1098 lstrcatA(unc_short, "$\\");
1099 lstrcatA(unc_short, strchr(temppath, '\\') + 1);
1101 /* Create a long syntax for reference */
1102 memset(longpath, 0, MAX_PATH);
1103 pGetLongPathNameA(tempfile, temppath, MAX_PATH);
1104 lstrcpyA(longpath, unc_prefix);
1105 longpath[lstrlenA(longpath)] = temppath[0];
1106 lstrcatA(longpath, "$\\");
1107 lstrcatA(longpath, strchr(temppath, '\\') + 1);
1109 /* NULL test */
1110 SetLastError(0xdeadbeef);
1111 length = pGetLongPathNameA(unc_short, NULL, 0);
1112 if (length == 0 && GetLastError() == ERROR_BAD_NETPATH)
1114 /* Seen on Window XP Home */
1115 win_skip("UNC with computername is not supported\n");
1116 DeleteFileA(tempfile);
1117 return;
1119 explength = lstrlenA(longpath) + 1;
1120 todo_wine
1121 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1123 length = pGetLongPathNameA(unc_short, NULL, MAX_PATH);
1124 todo_wine
1125 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1127 memset(unc_long, 0, MAX_PATH);
1128 length = pGetLongPathNameA(unc_short, unc_long, lstrlenA(unc_short));
1129 /* length will include terminating '0' on failure */
1130 todo_wine
1131 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1132 ok(unc_long[0] == 0, "Buffer should not have been touched\n");
1134 memset(unc_long, 0, MAX_PATH);
1135 length = pGetLongPathNameA(unc_short, unc_long, length);
1136 /* length doesn't include terminating '0' on success */
1137 explength--;
1138 todo_wine
1140 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1141 ok(!lstrcmpiA(unc_long, longpath), "Expected (%s), got (%s)\n", longpath, unc_long);
1144 DeleteFileA(tempfile);
1147 static void test_GetLongPathNameW(void)
1149 DWORD length, expanded;
1150 BOOL ret;
1151 HANDLE file;
1152 WCHAR empty[MAX_PATH];
1153 WCHAR tempdir[MAX_PATH], name[200];
1154 WCHAR dirpath[4 + MAX_PATH + 200]; /* To ease removal */
1155 WCHAR shortpath[4 + MAX_PATH + 200 + 1 + 200];
1156 static const WCHAR prefix[] = { '\\','\\','?','\\', 0};
1157 static const WCHAR backslash[] = { '\\', 0};
1158 static const WCHAR letterX[] = { 'X', 0};
1160 if (!pGetLongPathNameW)
1161 return;
1163 SetLastError(0xdeadbeef);
1164 length = pGetLongPathNameW(NULL,NULL,0);
1165 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1167 win_skip("GetLongPathNameW is not implemented\n");
1168 return;
1170 ok(0==length,"GetLongPathNameW returned %d but expected 0\n",length);
1171 ok(GetLastError()==ERROR_INVALID_PARAMETER,"GetLastError returned %d but expected ERROR_INVALID_PARAMETER\n",GetLastError());
1173 SetLastError(0xdeadbeef);
1174 empty[0]=0;
1175 length = pGetLongPathNameW(empty,NULL,0);
1176 ok(0==length,"GetLongPathNameW returned %d but expected 0\n",length);
1177 ok(GetLastError()==ERROR_PATH_NOT_FOUND,"GetLastError returned %d but expected ERROR_PATH_NOT_FOUND\n",GetLastError());
1179 /* Create a long path name. The path needs to exist for these tests to
1180 * succeed so we need the "\\?\" prefix when creating directories and
1181 * files.
1183 name[0] = 0;
1184 while (lstrlenW(name) < (sizeof(name)/sizeof(WCHAR) - 1))
1185 lstrcatW(name, letterX);
1187 GetTempPathW(MAX_PATH, tempdir);
1189 lstrcpyW(shortpath, prefix);
1190 lstrcatW(shortpath, tempdir);
1191 lstrcatW(shortpath, name);
1192 lstrcpyW(dirpath, shortpath);
1193 ret = CreateDirectoryW(shortpath, NULL);
1194 ok(ret, "Could not create the temporary directory : %d\n", GetLastError());
1195 lstrcatW(shortpath, backslash);
1196 lstrcatW(shortpath, name);
1198 /* Path does not exist yet and we know it overruns MAX_PATH */
1200 /* No prefix */
1201 SetLastError(0xdeadbeef);
1202 length = pGetLongPathNameW(shortpath + 4, NULL, 0);
1203 ok(length == 0, "Expected 0, got %d\n", length);
1204 todo_wine
1205 ok(GetLastError() == ERROR_PATH_NOT_FOUND,
1206 "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
1207 /* With prefix */
1208 SetLastError(0xdeadbeef);
1209 length = pGetLongPathNameW(shortpath, NULL, 0);
1210 todo_wine
1212 ok(length == 0, "Expected 0, got %d\n", length);
1213 ok(GetLastError() == ERROR_FILE_NOT_FOUND,
1214 "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
1217 file = CreateFileW(shortpath, GENERIC_READ|GENERIC_WRITE, 0, NULL,
1218 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1219 ok(file != INVALID_HANDLE_VALUE,
1220 "Could not create the temporary file : %d.\n", GetLastError());
1221 CloseHandle(file);
1223 /* Path exists */
1225 /* No prefix */
1226 SetLastError(0xdeadbeef);
1227 length = pGetLongPathNameW(shortpath + 4, NULL, 0);
1228 todo_wine
1230 ok(length == 0, "Expected 0, got %d\n", length);
1231 ok(GetLastError() == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
1233 /* With prefix */
1234 expanded = 4 + (pGetLongPathNameW(tempdir, NULL, 0) - 1) + lstrlenW(name) + 1 + lstrlenW(name) + 1;
1235 SetLastError(0xdeadbeef);
1236 length = pGetLongPathNameW(shortpath, NULL, 0);
1237 ok(length == expanded, "Expected %d, got %d\n", expanded, length);
1239 /* NULL buffer with length crashes on Windows */
1240 if (0)
1241 pGetLongPathNameW(shortpath, NULL, 20);
1243 ok(DeleteFileW(shortpath), "Could not delete temporary file\n");
1244 ok(RemoveDirectoryW(dirpath), "Could not delete temporary directory\n");
1247 static void test_GetShortPathNameW(void)
1249 WCHAR test_path[] = { 'L', 'o', 'n', 'g', 'D', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 'N', 'a', 'm', 'e', 0 };
1250 WCHAR path[MAX_PATH];
1251 WCHAR short_path[MAX_PATH];
1252 DWORD length;
1253 HANDLE file;
1254 int ret;
1255 WCHAR name[] = { 't', 'e', 's', 't', 0 };
1256 WCHAR backSlash[] = { '\\', 0 };
1258 SetLastError(0xdeadbeef);
1259 GetTempPathW( MAX_PATH, path );
1260 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1262 win_skip("GetTempPathW is not implemented\n");
1263 return;
1266 lstrcatW( path, test_path );
1267 lstrcatW( path, backSlash );
1268 ret = CreateDirectoryW( path, NULL );
1269 ok( ret, "Directory was not created. LastError = %d\n", GetLastError() );
1271 /* Starting a main part of test */
1272 length = GetShortPathNameW( path, short_path, 0 );
1273 ok( length, "GetShortPathNameW returned 0.\n" );
1274 ret = GetShortPathNameW( path, short_path, length );
1275 ok( ret, "GetShortPathNameW returned 0.\n" );
1276 lstrcatW( short_path, name );
1277 file = CreateFileW( short_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1278 ok( file != INVALID_HANDLE_VALUE, "File was not created.\n" );
1280 /* End test */
1281 CloseHandle( file );
1282 ret = DeleteFileW( short_path );
1283 ok( ret, "Cannot delete file.\n" );
1284 ret = RemoveDirectoryW( path );
1285 ok( ret, "Cannot delete directory.\n" );
1288 static void test_GetSystemDirectory(void)
1290 CHAR buffer[MAX_PATH + 4];
1291 DWORD res;
1292 DWORD total;
1294 SetLastError(0xdeadbeef);
1295 res = GetSystemDirectory(NULL, 0);
1296 /* res includes the terminating Zero */
1297 ok(res > 0, "returned %d with %d (expected '>0')\n", res, GetLastError());
1299 total = res;
1301 /* this crashes on XP */
1302 if (0)
1303 GetSystemDirectory(NULL, total);
1305 SetLastError(0xdeadbeef);
1306 res = GetSystemDirectory(NULL, total-1);
1307 /* 95+NT: total (includes the terminating Zero)
1308 98+ME: 0 with ERROR_INVALID_PARAMETER */
1309 ok( (res == total) || (!res && (GetLastError() == ERROR_INVALID_PARAMETER)),
1310 "returned %d with %d (expected '%d' or: '0' with "
1311 "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), total);
1313 if (total > MAX_PATH) return;
1315 buffer[0] = '\0';
1316 SetLastError(0xdeadbeef);
1317 res = GetSystemDirectory(buffer, total);
1318 /* res does not include the terminating Zero */
1319 ok( (res == (total-1)) && (buffer[0]),
1320 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1321 res, GetLastError(), buffer, total-1);
1323 buffer[0] = '\0';
1324 SetLastError(0xdeadbeef);
1325 res = GetSystemDirectory(buffer, total + 1);
1326 /* res does not include the terminating Zero */
1327 ok( (res == (total-1)) && (buffer[0]),
1328 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1329 res, GetLastError(), buffer, total-1);
1331 memset(buffer, '#', total + 1);
1332 buffer[total + 2] = '\0';
1333 SetLastError(0xdeadbeef);
1334 res = GetSystemDirectory(buffer, total-1);
1335 /* res includes the terminating Zero) */
1336 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1337 res, GetLastError(), buffer, total);
1339 memset(buffer, '#', total + 1);
1340 buffer[total + 2] = '\0';
1341 SetLastError(0xdeadbeef);
1342 res = GetSystemDirectory(buffer, total-2);
1343 /* res includes the terminating Zero) */
1344 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1345 res, GetLastError(), buffer, total);
1348 static void test_GetWindowsDirectory(void)
1350 CHAR buffer[MAX_PATH + 4];
1351 DWORD res;
1352 DWORD total;
1354 SetLastError(0xdeadbeef);
1355 res = GetWindowsDirectory(NULL, 0);
1356 /* res includes the terminating Zero */
1357 ok(res > 0, "returned %d with %d (expected '>0')\n", res, GetLastError());
1359 total = res;
1360 /* this crashes on XP */
1361 if (0)
1362 GetWindowsDirectory(NULL, total);
1364 SetLastError(0xdeadbeef);
1365 res = GetWindowsDirectory(NULL, total-1);
1366 /* 95+NT: total (includes the terminating Zero)
1367 98+ME: 0 with ERROR_INVALID_PARAMETER */
1368 ok( (res == total) || (!res && (GetLastError() == ERROR_INVALID_PARAMETER)),
1369 "returned %d with %d (expected '%d' or: '0' with "
1370 "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), total);
1372 if (total > MAX_PATH) return;
1374 buffer[0] = '\0';
1375 SetLastError(0xdeadbeef);
1376 res = GetWindowsDirectory(buffer, total);
1377 /* res does not include the terminating Zero */
1378 ok( (res == (total-1)) && (buffer[0]),
1379 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1380 res, GetLastError(), buffer, total-1);
1382 buffer[0] = '\0';
1383 SetLastError(0xdeadbeef);
1384 res = GetWindowsDirectory(buffer, total + 1);
1385 /* res does not include the terminating Zero */
1386 ok( (res == (total-1)) && (buffer[0]),
1387 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1388 res, GetLastError(), buffer, total-1);
1390 memset(buffer, '#', total + 1);
1391 buffer[total + 2] = '\0';
1392 SetLastError(0xdeadbeef);
1393 res = GetWindowsDirectory(buffer, total-1);
1394 /* res includes the terminating Zero) */
1395 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1396 res, GetLastError(), buffer, total);
1398 memset(buffer, '#', total + 1);
1399 buffer[total + 2] = '\0';
1400 SetLastError(0xdeadbeef);
1401 res = GetWindowsDirectory(buffer, total-2);
1402 /* res includes the terminating Zero) */
1403 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1404 res, GetLastError(), buffer, total);
1407 static void test_NeedCurrentDirectoryForExePathA(void)
1409 if (!pNeedCurrentDirectoryForExePathA)
1411 win_skip("NeedCurrentDirectoryForExePathA is not available\n");
1412 return;
1415 /* Crashes in Windows */
1416 if (0)
1417 pNeedCurrentDirectoryForExePathA(NULL);
1419 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", NULL);
1420 ok(pNeedCurrentDirectoryForExePathA("."), "returned FALSE for \".\"\n");
1421 ok(pNeedCurrentDirectoryForExePathA("c:\\"), "returned FALSE for \"c:\\\"\n");
1422 ok(pNeedCurrentDirectoryForExePathA("cmd.exe"), "returned FALSE for \"cmd.exe\"\n");
1424 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", "nya");
1425 ok(!pNeedCurrentDirectoryForExePathA("."), "returned TRUE for \".\"\n");
1426 ok(pNeedCurrentDirectoryForExePathA("c:\\"), "returned FALSE for \"c:\\\"\n");
1427 ok(!pNeedCurrentDirectoryForExePathA("cmd.exe"), "returned TRUE for \"cmd.exe\"\n");
1430 static void test_NeedCurrentDirectoryForExePathW(void)
1432 const WCHAR thispath[] = {'.', 0};
1433 const WCHAR fullpath[] = {'c', ':', '\\', 0};
1434 const WCHAR cmdname[] = {'c', 'm', 'd', '.', 'e', 'x', 'e', 0};
1436 if (!pNeedCurrentDirectoryForExePathW)
1438 win_skip("NeedCurrentDirectoryForExePathW is not available\n");
1439 return;
1442 /* Crashes in Windows */
1443 if (0)
1444 pNeedCurrentDirectoryForExePathW(NULL);
1446 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", NULL);
1447 ok(pNeedCurrentDirectoryForExePathW(thispath), "returned FALSE for \".\"\n");
1448 ok(pNeedCurrentDirectoryForExePathW(fullpath), "returned FALSE for \"c:\\\"\n");
1449 ok(pNeedCurrentDirectoryForExePathW(cmdname), "returned FALSE for \"cmd.exe\"\n");
1451 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", "nya");
1452 ok(!pNeedCurrentDirectoryForExePathW(thispath), "returned TRUE for \".\"\n");
1453 ok(pNeedCurrentDirectoryForExePathW(fullpath), "returned FALSE for \"c:\\\"\n");
1454 ok(!pNeedCurrentDirectoryForExePathW(cmdname), "returned TRUE for \"cmd.exe\"\n");
1457 /* Call various path/file name retrieving APIs and check the case of
1458 * the returned drive letter. Some apps (for instance Adobe Photoshop CS3
1459 * installer) depend on the drive letter being in upper case.
1461 static void test_drive_letter_case(void)
1463 UINT ret;
1464 char buf[MAX_PATH];
1466 #define is_upper_case_letter(a) ((a) >= 'A' && (a) <= 'Z')
1468 memset(buf, 0, sizeof(buf));
1469 SetLastError(0xdeadbeef);
1470 ret = GetWindowsDirectory(buf, sizeof(buf));
1471 ok(ret, "GetWindowsDirectory error %u\n", GetLastError());
1472 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1473 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1474 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1476 /* re-use the buffer returned by GetFullPathName */
1477 buf[2] = '/';
1478 SetLastError(0xdeadbeef);
1479 ret = GetFullPathName(buf + 2, sizeof(buf), buf, NULL);
1480 ok(ret, "GetFullPathName error %u\n", GetLastError());
1481 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1482 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1483 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1485 memset(buf, 0, sizeof(buf));
1486 SetLastError(0xdeadbeef);
1487 ret = GetSystemDirectory(buf, sizeof(buf));
1488 ok(ret, "GetSystemDirectory error %u\n", GetLastError());
1489 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1490 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1491 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1493 memset(buf, 0, sizeof(buf));
1494 SetLastError(0xdeadbeef);
1495 ret = GetCurrentDirectory(sizeof(buf), buf);
1496 ok(ret, "GetCurrentDirectory error %u\n", GetLastError());
1497 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1498 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1499 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1501 /* TEMP is an environment variable, so it can't be tested for case-sensitivity */
1502 memset(buf, 0, sizeof(buf));
1503 SetLastError(0xdeadbeef);
1504 ret = GetTempPath(sizeof(buf), buf);
1505 ok(ret, "GetTempPath error %u\n", GetLastError());
1506 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1507 if (buf[0])
1509 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1510 ok(buf[strlen(buf)-1] == '\\', "Temporary path (%s) doesn't end in a slash\n", buf);
1513 memset(buf, 0, sizeof(buf));
1514 SetLastError(0xdeadbeef);
1515 ret = GetFullPathName(".", sizeof(buf), buf, NULL);
1516 ok(ret, "GetFullPathName error %u\n", GetLastError());
1517 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1518 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1519 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1521 /* re-use the buffer returned by GetFullPathName */
1522 SetLastError(0xdeadbeef);
1523 ret = GetShortPathName(buf, buf, sizeof(buf));
1524 ok(ret, "GetShortPathName error %u\n", GetLastError());
1525 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1526 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1527 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1529 if (pGetLongPathNameA)
1531 /* re-use the buffer returned by GetShortPathName */
1532 SetLastError(0xdeadbeef);
1533 ret = pGetLongPathNameA(buf, buf, sizeof(buf));
1534 ok(ret, "GetLongPathNameA error %u\n", GetLastError());
1535 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1536 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1537 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1539 #undef is_upper_case_letter
1542 static void test_SearchPathA(void)
1544 CHAR pathA[MAX_PATH], fileA[] = "", buffA[MAX_PATH];
1545 CHAR *ptrA = NULL;
1546 DWORD ret;
1548 if (!pSearchPathA)
1550 win_skip("SearchPathA isn't available\n");
1551 return;
1554 GetWindowsDirectoryA(pathA, sizeof(pathA)/sizeof(CHAR));
1556 /* NULL filename */
1557 SetLastError(0xdeadbeef);
1558 ret = pSearchPathA(pathA, NULL, NULL, sizeof(buffA)/sizeof(CHAR), buffA, &ptrA);
1559 ok(ret == 0, "Expected failure, got %d\n", ret);
1560 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1561 "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
1563 /* empty filename */
1564 SetLastError(0xdeadbeef);
1565 ret = pSearchPathA(pathA, fileA, NULL, sizeof(buffA)/sizeof(CHAR), buffA, &ptrA);
1566 ok(ret == 0, "Expected failure, got %d\n", ret);
1567 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1568 "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
1571 static void test_SearchPathW(void)
1573 WCHAR pathW[MAX_PATH], fileW[] = { 0 }, buffW[MAX_PATH];
1574 WCHAR *ptrW = NULL;
1575 DWORD ret;
1577 if (!pSearchPathW)
1579 win_skip("SearchPathW isn't available\n");
1580 return;
1583 if (0)
1585 /* NULL filename, crashes on nt4 */
1586 pSearchPathW(pathW, NULL, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, &ptrW);
1589 /* empty filename */
1590 SetLastError(0xdeadbeef);
1591 ret = pSearchPathW(pathW, fileW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, &ptrW);
1592 ok(ret == 0, "Expected failure, got %d\n", ret);
1593 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1594 "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
1597 static void test_GetFullPathNameA(void)
1599 char output[MAX_PATH], *filepart;
1600 DWORD ret;
1601 int i;
1603 const struct
1605 LPCSTR name;
1606 DWORD len;
1607 LPSTR buffer;
1608 LPSTR *lastpart;
1609 } invalid_parameters[] =
1611 {NULL, 0, NULL, NULL},
1612 {NULL, MAX_PATH, NULL, NULL},
1613 {NULL, MAX_PATH, output, NULL},
1614 {NULL, MAX_PATH, output, &filepart},
1615 {"", 0, NULL, NULL},
1616 {"", MAX_PATH, NULL, NULL},
1617 {"", MAX_PATH, output, NULL},
1618 {"", MAX_PATH, output, &filepart},
1621 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
1623 SetLastError(0xdeadbeef);
1624 strcpy(output, "deadbeef");
1625 filepart = (char *)0xdeadbeef;
1626 ret = GetFullPathNameA(invalid_parameters[i].name,
1627 invalid_parameters[i].len,
1628 invalid_parameters[i].buffer,
1629 invalid_parameters[i].lastpart);
1630 ok(!ret, "[%d] Expected GetFullPathNameA to return 0, got %u\n", i, ret);
1631 ok(!strcmp(output, "deadbeef"), "[%d] Expected the output buffer to be unchanged, got \"%s\"\n", i, output);
1632 ok(filepart == (char *)0xdeadbeef, "[%d] Expected output file part pointer to be untouched, got %p\n", i, filepart);
1633 ok(GetLastError() == 0xdeadbeef ||
1634 GetLastError() == ERROR_INVALID_NAME, /* Win7 */
1635 "[%d] Expected GetLastError() to return 0xdeadbeef, got %u\n",
1636 i, GetLastError());
1640 static void test_GetFullPathNameW(void)
1642 static const WCHAR emptyW[] = {0};
1643 static const WCHAR deadbeefW[] = {'d','e','a','d','b','e','e','f',0};
1645 WCHAR output[MAX_PATH], *filepart;
1646 DWORD ret;
1647 int i;
1649 const struct
1651 LPCWSTR name;
1652 DWORD len;
1653 LPWSTR buffer;
1654 LPWSTR *lastpart;
1655 int win7_expect;
1656 } invalid_parameters[] =
1658 {NULL, 0, NULL, NULL},
1659 {NULL, 0, NULL, &filepart, 1},
1660 {NULL, MAX_PATH, NULL, NULL},
1661 {NULL, MAX_PATH, output, NULL},
1662 {NULL, MAX_PATH, output, &filepart, 1},
1663 {emptyW, 0, NULL, NULL},
1664 {emptyW, 0, NULL, &filepart, 1},
1665 {emptyW, MAX_PATH, NULL, NULL},
1666 {emptyW, MAX_PATH, output, NULL},
1667 {emptyW, MAX_PATH, output, &filepart, 1},
1670 SetLastError(0xdeadbeef);
1671 ret = GetFullPathNameW(NULL, 0, NULL, NULL);
1672 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1674 win_skip("GetFullPathNameW is not available\n");
1675 return;
1678 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
1680 SetLastError(0xdeadbeef);
1681 lstrcpyW(output, deadbeefW);
1682 filepart = (WCHAR *)0xdeadbeef;
1683 ret = GetFullPathNameW(invalid_parameters[i].name,
1684 invalid_parameters[i].len,
1685 invalid_parameters[i].buffer,
1686 invalid_parameters[i].lastpart);
1687 ok(!ret, "[%d] Expected GetFullPathNameW to return 0, got %u\n", i, ret);
1688 ok(!lstrcmpW(output, deadbeefW), "[%d] Expected the output buffer to be unchanged, got %s\n", i, wine_dbgstr_w(output));
1689 ok(filepart == (WCHAR *)0xdeadbeef ||
1690 (invalid_parameters[i].win7_expect && filepart == NULL),
1691 "[%d] Expected output file part pointer to be untouched, got %p\n", i, filepart);
1692 ok(GetLastError() == 0xdeadbeef ||
1693 GetLastError() == ERROR_INVALID_NAME, /* Win7 */
1694 "[%d] Expected GetLastError() to return 0xdeadbeef, got %u\n",
1695 i, GetLastError());
1699 static void init_pointers(void)
1701 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
1703 #define MAKEFUNC(f) (p##f = (void*)GetProcAddress(hKernel32, #f))
1704 MAKEFUNC(GetLongPathNameA);
1705 MAKEFUNC(GetLongPathNameW);
1706 MAKEFUNC(NeedCurrentDirectoryForExePathA);
1707 MAKEFUNC(NeedCurrentDirectoryForExePathW);
1708 MAKEFUNC(SearchPathA);
1709 MAKEFUNC(SearchPathW);
1710 #undef MAKEFUNC
1713 START_TEST(path)
1715 CHAR origdir[MAX_PATH],curdir[MAX_PATH], curDrive, otherDrive;
1717 init_pointers();
1719 /* Report only once */
1720 if (!pGetLongPathNameA)
1721 win_skip("GetLongPathNameA is not available\n");
1722 if (!pGetLongPathNameW)
1723 win_skip("GetLongPathNameW is not available\n");
1725 test_InitPathA(curdir, &curDrive, &otherDrive);
1726 test_CurrentDirectoryA(origdir,curdir);
1727 test_PathNameA(curdir, curDrive, otherDrive);
1728 test_CleanupPathA(origdir,curdir);
1729 test_GetTempPath();
1730 test_GetLongPathNameA();
1731 test_GetLongPathNameW();
1732 test_GetShortPathNameW();
1733 test_GetSystemDirectory();
1734 test_GetWindowsDirectory();
1735 test_NeedCurrentDirectoryForExePathA();
1736 test_NeedCurrentDirectoryForExePathW();
1737 test_drive_letter_case();
1738 test_SearchPathA();
1739 test_SearchPathW();
1740 test_GetFullPathNameA();
1741 test_GetFullPathNameW();