Assorted spelling fixes.
[wine.git] / dlls / kernel32 / tests / path.c
blob0f07ea6fb01f770a06b14653a3afbf86ba595186
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 <assert.h>
25 #include "wine/test.h"
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winuser.h"
29 #include "winerror.h"
30 #include "winnls.h"
32 #define HAS_TRAIL_SLASH_A(string) (string[lstrlenA(string)-1]=='\\')
34 #define LONGFILE "Long File test.path"
35 #define SHORTFILE "pathtest.pth"
36 #define SHORTDIR "shortdir"
37 #define LONGDIR "Long Directory"
38 #define NONFILE_SHORT "noexist.pth"
39 #define NONFILE_LONG "NonExistent File"
40 #define NONDIR_SHORT "notadir"
41 #define NONDIR_LONG "NonExistent Directory"
43 #define NOT_A_VALID_DRIVE '@'
45 #ifdef __i386__
46 #define ARCH "x86"
47 #elif defined __x86_64__
48 #define ARCH "amd64"
49 #else
50 #define ARCH "none"
51 #endif
53 /* the following characters don't work well with GetFullPathNameA
54 in Win98. I don't know if this is a FAT thing, or if it is an OS thing
55 but I don't test these characters now.
56 NOTE: Win2k allows GetFullPathNameA to work with them though
57 |<>"
59 static const CHAR funny_chars[]="!@#$%^&*()=+{}[],?'`";
60 static const CHAR is_char_ok[] ="11111110111111111011";
62 static DWORD (WINAPI *pGetLongPathNameA)(LPCSTR,LPSTR,DWORD);
63 static DWORD (WINAPI *pGetLongPathNameW)(LPWSTR,LPWSTR,DWORD);
65 /* Present in Win2003+ */
66 static BOOL (WINAPI *pNeedCurrentDirectoryForExePathA)(LPCSTR);
67 static BOOL (WINAPI *pNeedCurrentDirectoryForExePathW)(LPCWSTR);
69 static DWORD (WINAPI *pSearchPathA)(LPCSTR,LPCSTR,LPCSTR,DWORD,LPSTR,LPSTR*);
70 static DWORD (WINAPI *pSearchPathW)(LPCWSTR,LPCWSTR,LPCWSTR,DWORD,LPWSTR,LPWSTR*);
72 static BOOL (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*);
73 static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW);
74 static BOOL (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);
75 static BOOL (WINAPI *pGetCurrentActCtx)(HANDLE *);
76 static void (WINAPI *pReleaseActCtx)(HANDLE);
78 /* a structure to deal with wine todos somewhat cleanly */
79 typedef struct {
80 DWORD shortlen;
81 DWORD shorterror;
82 DWORD s2llen;
83 DWORD s2lerror;
84 DWORD longlen;
85 DWORD longerror;
86 } SLpassfail;
88 /* function that tests GetFullPathNameA, GetShortPathNameA,GetLongPathNameA */
89 /* NOTE: the passfail structure is used to allow customizable todo checking
90 for wine. It is not very pretty, but it sure beats duplicating this
91 function lots of times
93 static void test_ValidPathA(const CHAR *curdir, const CHAR *subdir, const CHAR *filename,
94 CHAR *shortstr, SLpassfail *passfail, const CHAR *errstr)
96 CHAR tmpstr[MAX_PATH],
97 fullpath[MAX_PATH], /*full path to the file (not short/long) */
98 subpath[MAX_PATH], /*relative path to the file */
99 fullpathshort[MAX_PATH], /*absolute path to the file (short format) */
100 fullpathlong[MAX_PATH], /*absolute path to the file (long format) */
101 curdirshort[MAX_PATH], /*absolute path to the current dir (short) */
102 curdirlong[MAX_PATH]; /*absolute path to the current dir (long) */
103 LPSTR strptr; /*ptr to the filename portion of the path */
104 DWORD len;
105 /* if passfail is NULL, we can perform all checks within this function,
106 otherwise, we will return the relevant data in the passfail struct, so
107 we must initialize it first
109 if(passfail!=NULL) {
110 passfail->shortlen=-1;passfail->s2llen=-1;passfail->longlen=-1;
111 passfail->shorterror=0;passfail->s2lerror=0;passfail->longerror=0;
113 /* GetLongPathNameA is only supported on Win2k+ and Win98+ */
114 if(pGetLongPathNameA) {
115 ok((len=pGetLongPathNameA(curdir,curdirlong,MAX_PATH)),
116 "%s: GetLongPathNameA failed\n",errstr);
117 /*GetLongPathNameA can return a trailing '\\' but shouldn't do so here */
118 ok(! HAS_TRAIL_SLASH_A(curdirlong),
119 "%s: GetLongPathNameA should not have a trailing \\\n",errstr);
121 ok((len=GetShortPathNameA(curdir,curdirshort,MAX_PATH)),
122 "%s: GetShortPathNameA failed\n",errstr);
123 /*GetShortPathNameA can return a trailing '\\' but shouldn't do so here */
124 ok(! HAS_TRAIL_SLASH_A(curdirshort),
125 "%s: GetShortPathNameA should not have a trailing \\\n",errstr);
126 /* build relative and absolute paths from inputs */
127 if(lstrlenA(subdir)) {
128 sprintf(subpath,"%s\\%s",subdir,filename);
129 } else {
130 lstrcpyA(subpath,filename);
132 sprintf(fullpath,"%s\\%s",curdir,subpath);
133 sprintf(fullpathshort,"%s\\%s",curdirshort,subpath);
134 sprintf(fullpathlong,"%s\\%s",curdirlong,subpath);
135 /* Test GetFullPathNameA functionality */
136 len=GetFullPathNameA(subpath,MAX_PATH,tmpstr,&strptr);
137 ok(len, "GetFullPathNameA failed for: '%s'\n",subpath);
138 if(HAS_TRAIL_SLASH_A(subpath)) {
139 ok(strptr==NULL,
140 "%s: GetFullPathNameA should not return a filename ptr\n",errstr);
141 ok(lstrcmpiA(fullpath,tmpstr)==0,
142 "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
143 errstr,tmpstr,fullpath);
144 } else {
145 ok(lstrcmpiA(strptr,filename)==0,
146 "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
147 errstr,strptr,filename);
148 ok(lstrcmpiA(fullpath,tmpstr)==0,
149 "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
150 errstr,tmpstr,fullpath);
152 /* Test GetShortPathNameA functionality */
153 SetLastError(0);
154 len=GetShortPathNameA(fullpathshort,shortstr,MAX_PATH);
155 if(passfail==NULL) {
156 ok(len, "%s: GetShortPathNameA failed\n",errstr);
157 } else {
158 passfail->shortlen=len;
159 passfail->shorterror=GetLastError();
161 /* Test GetLongPathNameA functionality
162 We test both conversion from GetFullPathNameA and from GetShortPathNameA
164 if(pGetLongPathNameA) {
165 if(len!=0) {
166 SetLastError(0);
167 len=pGetLongPathNameA(shortstr,tmpstr,MAX_PATH);
168 if(passfail==NULL) {
169 ok(len,
170 "%s: GetLongPathNameA failed during Short->Long conversion\n", errstr);
171 ok(lstrcmpiA(fullpathlong,tmpstr)==0,
172 "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
173 errstr,tmpstr,fullpathlong);
174 } else {
175 passfail->s2llen=len;
176 passfail->s2lerror=GetLastError();
179 SetLastError(0);
180 len=pGetLongPathNameA(fullpath,tmpstr,MAX_PATH);
181 if(passfail==NULL) {
182 ok(len, "%s: GetLongPathNameA failed\n",errstr);
183 if(HAS_TRAIL_SLASH_A(fullpath)) {
184 ok(lstrcmpiA(fullpathlong,tmpstr)==0,
185 "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
186 errstr,tmpstr,fullpathlong);
187 } else {
188 ok(lstrcmpiA(fullpathlong,tmpstr)==0,
189 "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
190 errstr,tmpstr,fullpathlong);
192 } else {
193 passfail->longlen=len;
194 passfail->longerror=GetLastError();
199 /* split path into leading directory, and 8.3 filename */
200 static void test_SplitShortPathA(CHAR *path,CHAR *dir,CHAR *eight,CHAR *three) {
201 BOOL done = FALSE, error = FALSE;
202 int ext,fil;
203 int len,i;
204 len=lstrlenA(path);
205 ext=len;
206 fil=len;
207 /* walk backwards over path looking for '.' or '\\' separators */
208 for(i=len-1;(i>=0) && (!done);i--) {
209 if(path[i]=='.')
210 if(ext!=len) error=TRUE; else ext=i;
211 else if(path[i]=='\\') {
212 if(i==len-1) {
213 error=TRUE;
214 } else {
215 fil=i;
216 done=TRUE;
220 /* Check that we didn't find a trailing '\\' or multiple '.' */
221 ok(!error,"Illegal file found in 8.3 path '%s'\n",path);
222 /* Separate dir, root, and extension */
223 if(ext!=len) lstrcpyA(three,path+ext+1); else lstrcpyA(three,"");
224 if(fil!=len) {
225 lstrcpynA(eight,path+fil+1,ext-fil);
226 lstrcpynA(dir,path,fil+1);
227 } else {
228 lstrcpynA(eight,path,ext+1);
229 lstrcpyA(dir,"");
231 /* Validate that root and extension really are 8.3 */
232 ok(lstrlenA(eight)<=8 && lstrlenA(three)<=3,
233 "GetShortPathNAmeA did not return an 8.3 path\n");
236 /* Check that GetShortPathNameA returns a valid 8.3 path */
237 static void test_LongtoShortA(CHAR *teststr,const CHAR *goodstr,
238 const CHAR *ext,const CHAR *errstr) {
239 CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
241 test_SplitShortPathA(teststr,dir,eight,three);
242 ok(lstrcmpiA(dir,goodstr)==0,
243 "GetShortPathNameA returned '%s' instead of '%s'\n",dir,goodstr);
244 ok(lstrcmpiA(three,ext)==0,
245 "GetShortPathNameA returned '%s' with incorrect extension\n",three);
248 /* Test that Get(Short|Long|Full)PathNameA work correctly with interesting
249 characters in the filename.
250 'valid' indicates whether this would be an allowed filename
251 'todo' indicates that wine doesn't get this right yet.
252 NOTE: We always call this routine with a nonexistent filename, so
253 Get(Short|Long)PathNameA should never pass, but GetFullPathNameA
254 should.
256 static void test_FunnyChars(CHAR *curdir,CHAR *curdir_short,CHAR *filename, INT valid,CHAR *errstr)
258 CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
259 SLpassfail passfail;
261 test_ValidPathA(curdir,"",filename,tmpstr,&passfail,errstr);
262 if(valid) {
263 sprintf(tmpstr1,"%s\\%s",curdir_short,filename);
264 ok((passfail.shortlen==0 &&
265 (passfail.shorterror==ERROR_FILE_NOT_FOUND || passfail.shorterror==ERROR_PATH_NOT_FOUND || !passfail.shorterror)) ||
266 (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
267 "%s: GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
268 errstr,passfail.shortlen,passfail.shorterror,tmpstr);
269 } else {
270 ok(passfail.shortlen==0 &&
271 (passfail.shorterror==ERROR_INVALID_NAME || passfail.shorterror==ERROR_FILE_NOT_FOUND || !passfail.shorterror),
272 "%s: GetShortPathA should have failed len=%d, error=%d\n",
273 errstr,passfail.shortlen,passfail.shorterror);
275 if(pGetLongPathNameA) {
276 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
277 if(valid) {
278 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
279 "%s: GetLongPathA returned %d and not %d\n",
280 errstr,passfail.longerror,ERROR_FILE_NOT_FOUND);
281 } else {
282 ok(passfail.longerror==ERROR_INVALID_NAME ||
283 passfail.longerror==ERROR_FILE_NOT_FOUND,
284 "%s: GetLongPathA returned %d and not %d or %d'\n",
285 errstr, passfail.longerror,ERROR_INVALID_NAME,ERROR_FILE_NOT_FOUND);
290 /* Routine to test that SetCurrentDirectory behaves as expected. */
291 static void test_setdir(CHAR *olddir,CHAR *newdir,
292 CHAR *cmprstr, INT pass, const CHAR *errstr)
294 CHAR tmppath[MAX_PATH], *dirptr;
295 DWORD val,len,chklen;
297 val=SetCurrentDirectoryA(newdir);
298 len=GetCurrentDirectoryA(MAX_PATH,tmppath);
299 /* if 'pass' then the SetDirectoryA was supposed to pass */
300 if(pass) {
301 dirptr=(cmprstr==NULL) ? newdir : cmprstr;
302 chklen=lstrlenA(dirptr);
303 ok(val,"%s: SetCurrentDirectoryA failed\n",errstr);
304 ok(len==chklen,
305 "%s: SetCurrentDirectory did not change the directory, though it passed\n",
306 errstr);
307 ok(lstrcmpiA(dirptr,tmppath)==0,
308 "%s: SetCurrentDirectory did not change the directory, though it passed\n",
309 errstr);
310 ok(SetCurrentDirectoryA(olddir),
311 "%s: Couldn't set directory to its original value\n",errstr);
312 } else {
313 /* else thest that it fails correctly */
314 chklen=lstrlenA(olddir);
315 ok(val==0,
316 "%s: SetCurrentDirectoryA passed when it should have failed\n",errstr);
317 ok(len==chklen,
318 "%s: SetCurrentDirectory changed the directory, though it failed\n",
319 errstr);
320 ok(lstrcmpiA(olddir,tmppath)==0,
321 "%s: SetCurrentDirectory changed the directory, though it failed\n",
322 errstr);
325 static void test_InitPathA(CHAR *newdir, CHAR *curDrive, CHAR *otherDrive)
327 CHAR tmppath[MAX_PATH], /*path to TEMP */
328 tmpstr[MAX_PATH],
329 tmpstr1[MAX_PATH],
330 invalid_dir[MAX_PATH];
332 DWORD len,len1,drives;
333 INT id;
334 HANDLE hndl;
335 BOOL bRes;
336 UINT unique;
338 *curDrive = *otherDrive = NOT_A_VALID_DRIVE;
340 /* Get the current drive letter */
341 if( GetCurrentDirectoryA( MAX_PATH, tmpstr))
342 *curDrive = tmpstr[0];
343 else
344 trace( "Unable to discover current drive, some tests will not be conducted.\n");
346 /* Test GetTempPathA */
347 len=GetTempPathA(MAX_PATH,tmppath);
348 ok(len!=0 && len < MAX_PATH,"GetTempPathA failed\n");
349 ok(HAS_TRAIL_SLASH_A(tmppath),
350 "GetTempPathA returned a path that did not end in '\\'\n");
351 lstrcpyA(tmpstr,"aaaaaaaa");
352 len1=GetTempPathA(len,tmpstr);
353 ok(len1==len+1 || broken(len1 == len), /* WinME */
354 "GetTempPathA should return string length %d instead of %d\n",len+1,len1);
356 /* Test GetTmpFileNameA */
357 ok((id=GetTempFileNameA(tmppath,"path",0,newdir)),"GetTempFileNameA failed\n");
358 sprintf(tmpstr,"pat%.4x.tmp",id & 0xffff);
359 sprintf(tmpstr1,"pat%x.tmp",id & 0xffff);
360 ok(lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr)==0 ||
361 lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr1)==0,
362 "GetTempFileNameA returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
363 newdir,tmpstr,tmpstr1,id);
364 ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
366 id=GetTempFileNameA(tmppath,NULL,0,newdir);
367 /* Windows 95, 98 return 0==id, while Windows 2000, XP return 0!=id */
368 if (id)
370 sprintf(tmpstr,"%.4x.tmp",id & 0xffff);
371 sprintf(tmpstr1,"%x.tmp",id & 0xffff);
372 ok(lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr)==0 ||
373 lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr1)==0,
374 "GetTempFileNameA returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
375 newdir,tmpstr,tmpstr1,id);
376 ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
379 for(unique=0;unique<3;unique++) {
380 /* Nonexistent path */
381 sprintf(invalid_dir, "%s\\%s",tmppath,"non_existent_dir_1jwj3y32nb3");
382 SetLastError(0xdeadbeef);
383 ok(!GetTempFileNameA(invalid_dir,"tfn",unique,newdir),"GetTempFileNameA should have failed\n");
384 ok(GetLastError()==ERROR_DIRECTORY || broken(GetLastError()==ERROR_PATH_NOT_FOUND)/*win98*/,
385 "got %d, expected ERROR_DIRECTORY\n", GetLastError());
387 /* Check return value for unique !=0 */
388 if(unique) {
389 ok((GetTempFileNameA(tmppath,"tfn",unique,newdir) == unique),"GetTempFileNameA unexpectedly failed\n");
390 /* if unique != 0, the actual temp files are not created: */
391 ok(!DeleteFileA(newdir) && GetLastError() == ERROR_FILE_NOT_FOUND,"Deleted a file that shouldn't exist!\n");
395 /* Find first valid drive letter that is neither newdir[0] nor curDrive */
396 drives = GetLogicalDrives() & ~(1<<(newdir[0]-'A'));
397 if( *curDrive != NOT_A_VALID_DRIVE)
398 drives &= ~(1<<(*curDrive-'A'));
399 if( drives)
400 for( *otherDrive='A'; (drives & 1) == 0; drives>>=1, (*otherDrive)++);
401 else
402 trace( "Could not find alternative drive, some tests will not be conducted.\n");
404 /* Do some CreateDirectoryA tests */
405 /* It would be nice to do test the SECURITY_ATTRIBUTES, but I don't
406 really understand how they work.
407 More formal tests should be done along with CreateFile tests
409 ok((id=GetTempFileNameA(tmppath,"path",0,newdir)),"GetTempFileNameA failed\n");
410 ok(CreateDirectoryA(newdir,NULL)==0,
411 "CreateDirectoryA succeeded even though a file of the same name exists\n");
412 ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
413 ok(CreateDirectoryA(newdir,NULL),"CreateDirectoryA failed\n");
414 /* Create some files to test other functions. Note, we will test CreateFileA
415 at some later point
417 sprintf(tmpstr,"%s\\%s",newdir,SHORTDIR);
418 ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed\n");
419 sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
420 ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed\n");
421 sprintf(tmpstr,"%c:", *curDrive);
422 bRes = CreateDirectoryA(tmpstr,NULL);
423 ok(!bRes && (GetLastError() == ERROR_ACCESS_DENIED ||
424 GetLastError() == ERROR_ALREADY_EXISTS),
425 "CreateDirectoryA(\"%s\" should have failed (%d)\n", tmpstr, GetLastError());
426 sprintf(tmpstr,"%c:\\", *curDrive);
427 bRes = CreateDirectoryA(tmpstr,NULL);
428 ok(!bRes && (GetLastError() == ERROR_ACCESS_DENIED ||
429 GetLastError() == ERROR_ALREADY_EXISTS),
430 "CreateDirectoryA(\"%s\" should have failed (%d)\n", tmpstr, GetLastError());
431 sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,SHORTFILE);
432 hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
433 CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
434 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
435 ok(CloseHandle(hndl),"CloseHandle failed\n");
436 sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,LONGFILE);
437 hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
438 CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
439 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
440 ok(CloseHandle(hndl),"CloseHandle failed\n");
441 sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,SHORTFILE);
442 hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
443 CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
444 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
445 ok(CloseHandle(hndl),"CloseHandle failed\n");
446 sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,LONGFILE);
447 hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
448 CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
449 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
450 ok(CloseHandle(hndl),"CloseHandle failed\n");
453 /* Test GetCurrentDirectory & SetCurrentDirectory */
454 static void test_CurrentDirectoryA(CHAR *origdir, CHAR *newdir)
456 CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
457 char *buffer;
458 DWORD len,len1;
459 /* Save the original directory, so that we can return to it at the end
460 of the test
462 len=GetCurrentDirectoryA(MAX_PATH,origdir);
463 ok(len!=0 && len < MAX_PATH,"GetCurrentDirectoryA failed\n");
464 /* Make sure that CetCurrentDirectoryA doesn't overwrite the buffer when the
465 buffer size is too small to hold the current directory
467 lstrcpyA(tmpstr,"aaaaaaa");
468 len1=GetCurrentDirectoryA(len,tmpstr);
469 ok(len1==len+1, "GetCurrentDirectoryA returned %d instead of %d\n",len1,len+1);
470 ok(lstrcmpiA(tmpstr,"aaaaaaa")==0,
471 "GetCurrentDirectoryA should not have modified the buffer\n");
473 buffer = HeapAlloc( GetProcessHeap(), 0, 2 * 65536 );
474 SetLastError( 0xdeadbeef );
475 strcpy( buffer, "foo" );
476 len = GetCurrentDirectoryA( 32767, buffer );
477 ok( len != 0 && len < MAX_PATH, "GetCurrentDirectoryA failed %u err %u\n", len, GetLastError() );
478 if (len) ok( !strcmp( buffer, origdir ), "wrong result %s\n", buffer );
479 SetLastError( 0xdeadbeef );
480 strcpy( buffer, "foo" );
481 len = GetCurrentDirectoryA( 32768, buffer );
482 ok( len != 0 && len < MAX_PATH, "GetCurrentDirectoryA failed %u err %u\n", len, GetLastError() );
483 if (len) ok( !strcmp( buffer, origdir ), "wrong result %s\n", buffer );
484 SetLastError( 0xdeadbeef );
485 strcpy( buffer, "foo" );
486 len = GetCurrentDirectoryA( 65535, buffer );
487 ok( (len != 0 && len < MAX_PATH) || broken(!len), /* nt4, win2k, xp */ "GetCurrentDirectoryA failed %u err %u\n", len, GetLastError() );
488 if (len) ok( !strcmp( buffer, origdir ), "wrong result %s\n", buffer );
489 SetLastError( 0xdeadbeef );
490 strcpy( buffer, "foo" );
491 len = GetCurrentDirectoryA( 65536, buffer );
492 ok( (len != 0 && len < MAX_PATH) || broken(!len), /* nt4 */ "GetCurrentDirectoryA failed %u err %u\n", len, GetLastError() );
493 if (len) ok( !strcmp( buffer, origdir ), "wrong result %s\n", buffer );
494 SetLastError( 0xdeadbeef );
495 strcpy( buffer, "foo" );
496 len = GetCurrentDirectoryA( 2 * 65536, buffer );
497 ok( (len != 0 && len < MAX_PATH) || broken(!len), /* nt4 */ "GetCurrentDirectoryA failed %u err %u\n", len, GetLastError() );
498 if (len) ok( !strcmp( buffer, origdir ), "wrong result %s\n", buffer );
499 HeapFree( GetProcessHeap(), 0, buffer );
501 /* Check for crash prevention on swapped args. Crashes all but Win9x.
503 if (0)
505 GetCurrentDirectoryA( 42, (LPSTR)(MAX_PATH + 42) );
508 /* SetCurrentDirectoryA shouldn't care whether the string has a
509 trailing '\\' or not
511 sprintf(tmpstr,"%s\\",newdir);
512 test_setdir(origdir,tmpstr,newdir,1,"check 1");
513 test_setdir(origdir,newdir,NULL,1,"check 2");
514 /* Set the directory to the working area. We just tested that this works,
515 so why check it again.
517 SetCurrentDirectoryA(newdir);
518 /* Check that SetCurrentDirectory fails when a nonexistent dir is specified */
519 sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_SHORT);
520 test_setdir(newdir,tmpstr,NULL,0,"check 3");
521 /* Check that SetCurrentDirectory fails for a nonexistent lond directory */
522 sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_LONG);
523 test_setdir(newdir,tmpstr,NULL,0,"check 4");
524 /* Check that SetCurrentDirectory passes with a long directory */
525 sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
526 test_setdir(newdir,tmpstr,NULL,1,"check 5");
527 /* Check that SetCurrentDirectory passes with a short relative directory */
528 sprintf(tmpstr,"%s",SHORTDIR);
529 sprintf(tmpstr1,"%s\\%s",newdir,SHORTDIR);
530 test_setdir(newdir,tmpstr,tmpstr1,1,"check 6");
531 /* starting with a '.' */
532 sprintf(tmpstr,".\\%s",SHORTDIR);
533 test_setdir(newdir,tmpstr,tmpstr1,1,"check 7");
534 /* Check that SetCurrentDirectory passes with a short relative directory */
535 sprintf(tmpstr,"%s",LONGDIR);
536 sprintf(tmpstr1,"%s\\%s",newdir,LONGDIR);
537 test_setdir(newdir,tmpstr,tmpstr1,1,"check 8");
538 /* starting with a '.' */
539 sprintf(tmpstr,".\\%s",LONGDIR);
540 test_setdir(newdir,tmpstr,tmpstr1,1,"check 9");
541 /* change to root without a trailing backslash. The function call succeeds
542 but the directory is not changed.
544 sprintf(tmpstr, "%c:", newdir[0]);
545 test_setdir(newdir,tmpstr,newdir,1,"check 10");
546 /* works however with a trailing backslash */
547 sprintf(tmpstr, "%c:\\", newdir[0]);
548 test_setdir(newdir,tmpstr,NULL,1,"check 11");
551 /* Cleanup the mess we made while executing these tests */
552 static void test_CleanupPathA(CHAR *origdir, CHAR *curdir)
554 CHAR tmpstr[MAX_PATH];
555 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
556 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
557 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,LONGFILE);
558 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
559 sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,SHORTFILE);
560 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
561 sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
562 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
563 sprintf(tmpstr,"%s\\%s",curdir,SHORTDIR);
564 ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
565 sprintf(tmpstr,"%s\\%s",curdir,LONGDIR);
566 ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
567 ok(SetCurrentDirectoryA(origdir),"SetCurrentDirectoryA failed\n");
568 ok(RemoveDirectoryA(curdir),"RemoveDirectoryA failed\n");
571 /* test that short path name functions work regardless of case */
572 static void test_ShortPathCase(const char *tmpdir, const char *dirname,
573 const char *filename)
575 char buf[MAX_PATH], shortbuf[MAX_PATH];
576 HANDLE hndl;
577 size_t i;
579 assert(strlen(tmpdir) + strlen(dirname) + strlen(filename) + 2 < sizeof(buf));
580 sprintf(buf,"%s\\%s\\%s",tmpdir,dirname,filename);
581 GetShortPathNameA(buf,shortbuf,sizeof(shortbuf));
582 hndl = CreateFileA(shortbuf,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
583 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed (%d)\n",GetLastError());
584 CloseHandle(hndl);
585 /* Now for the real test */
586 for(i=0;i<strlen(shortbuf);i++)
587 if (i % 2)
588 shortbuf[i] = tolower(shortbuf[i]);
589 hndl = CreateFileA(shortbuf,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
590 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed (%d)\n",GetLastError());
591 CloseHandle(hndl);
594 /* This routine will test Get(Full|Short|Long)PathNameA */
595 static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive)
597 CHAR curdir_short[MAX_PATH],
598 longdir_short[MAX_PATH];
599 CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH],tmpstr2[MAX_PATH];
600 LPSTR strptr; /*ptr to the filename portion of the path */
601 DWORD len;
602 INT i;
603 CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
604 SLpassfail passfail;
606 /* Get the short form of the current directory */
607 ok((len=GetShortPathNameA(curdir,curdir_short,MAX_PATH)),
608 "GetShortPathNameA failed\n");
609 ok(!HAS_TRAIL_SLASH_A(curdir_short),
610 "GetShortPathNameA should not have a trailing \\\n");
611 /* Get the short form of the absolute-path to LONGDIR */
612 sprintf(tmpstr,"%s\\%s",curdir_short,LONGDIR);
613 ok((len=GetShortPathNameA(tmpstr,longdir_short,MAX_PATH)),
614 "GetShortPathNameA failed\n");
615 ok(lstrcmpiA(longdir_short+(len-1),"\\")!=0,
616 "GetShortPathNameA should not have a trailing \\\n");
618 if (pGetLongPathNameA) {
619 DWORD rc1,rc2;
620 sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
621 rc1=(*pGetLongPathNameA)(tmpstr,NULL,0);
622 rc2=(*pGetLongPathNameA)(curdir,NULL,0);
623 ok((rc1-strlen(tmpstr))==(rc2-strlen(curdir)),
624 "GetLongPathNameA: wrong return code, %d instead of %d\n",
625 rc1, lstrlenA(tmpstr)+1);
627 sprintf(dir,"%c:",curDrive);
628 rc1=(*pGetLongPathNameA)(dir,tmpstr,sizeof(tmpstr));
629 ok(strcmp(dir,tmpstr)==0,
630 "GetLongPathNameA: returned '%s' instead of '%s' (rc=%d)\n",
631 tmpstr,dir,rc1);
634 /* Check the cases where both file and directory exist first */
635 /* Start with a 8.3 directory, 8.3 filename */
636 test_ValidPathA(curdir,SHORTDIR,SHORTFILE,tmpstr,NULL,"test1");
637 sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,SHORTFILE);
638 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
639 "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
640 /* Now try a 8.3 directory, long file name */
641 test_ValidPathA(curdir,SHORTDIR,LONGFILE,tmpstr,NULL,"test2");
642 sprintf(tmpstr1,"%s\\%s",curdir_short,SHORTDIR);
643 test_LongtoShortA(tmpstr,tmpstr1,"PAT","test2");
644 /* Next is a long directory, 8.3 file */
645 test_ValidPathA(curdir,LONGDIR,SHORTFILE,tmpstr,NULL,"test3");
646 sprintf(tmpstr1,"%s\\%s",longdir_short,SHORTFILE);
647 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
648 "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
649 /*Lastly a long directory, long file */
650 test_ValidPathA(curdir,LONGDIR,LONGFILE,tmpstr,NULL,"test4");
651 test_LongtoShortA(tmpstr,longdir_short,"PAT","test4");
653 /* Now check all of the invalid file w/ valid directory combinations */
654 /* Start with a 8.3 directory, 8.3 filename */
655 test_ValidPathA(curdir,SHORTDIR,NONFILE_SHORT,tmpstr,&passfail,"test5");
656 sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,NONFILE_SHORT);
657 ok((passfail.shortlen==0 &&
658 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
659 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
660 (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
661 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
662 passfail.shortlen,passfail.shorterror,tmpstr);
663 if(pGetLongPathNameA) {
664 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
665 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
666 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
668 /* Now try a 8.3 directory, long file name */
669 test_ValidPathA(curdir,SHORTDIR,NONFILE_LONG,tmpstr,&passfail,"test6");
670 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
671 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
672 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
673 !passfail.shorterror,
674 "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
675 if(pGetLongPathNameA) {
676 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
677 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
678 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
680 /* Next is a long directory, 8.3 file */
681 test_ValidPathA(curdir,LONGDIR,NONFILE_SHORT,tmpstr,&passfail,"test7");
682 sprintf(tmpstr2,"%s\\%s",curdir_short,LONGDIR);
683 GetShortPathNameA(tmpstr2,tmpstr1,MAX_PATH);
684 strcat(tmpstr1,"\\" NONFILE_SHORT);
685 ok((passfail.shortlen==0 &&
686 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
687 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
688 (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
689 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
690 passfail.shortlen,passfail.shorterror,tmpstr);
691 if(pGetLongPathNameA) {
692 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
693 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
694 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
696 /*Lastly a long directory, long file */
697 test_ValidPathA(curdir,LONGDIR,NONFILE_LONG,tmpstr,&passfail,"test8");
698 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
699 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
700 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
701 !passfail.shorterror,
702 "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
703 if(pGetLongPathNameA) {
704 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
705 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
706 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
708 /* Now try again with directories that don't exist */
709 /* 8.3 directory, 8.3 filename */
710 test_ValidPathA(curdir,NONDIR_SHORT,SHORTFILE,tmpstr,&passfail,"test9");
711 sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,NONDIR_SHORT,SHORTFILE);
712 ok((passfail.shortlen==0 &&
713 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
714 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
715 (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
716 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
717 passfail.shortlen,passfail.shorterror,tmpstr);
718 if(pGetLongPathNameA) {
719 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
720 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
721 passfail.longerror==ERROR_FILE_NOT_FOUND,
722 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
723 passfail.longerror);
725 /* Now try a 8.3 directory, long file name */
726 test_ValidPathA(curdir,NONDIR_SHORT,LONGFILE,tmpstr,&passfail,"test10");
727 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
728 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
729 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
730 !passfail.shorterror,
731 "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
732 passfail.shorterror);
733 if(pGetLongPathNameA) {
734 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
735 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
736 passfail.longerror==ERROR_FILE_NOT_FOUND,
737 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
738 passfail.longerror);
740 /* Next is a long directory, 8.3 file */
741 test_ValidPathA(curdir,NONDIR_LONG,SHORTFILE,tmpstr,&passfail,"test11");
742 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
743 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
744 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
745 !passfail.shorterror,
746 "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
747 passfail.shorterror);
748 if(pGetLongPathNameA) {
749 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
750 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
751 passfail.longerror==ERROR_FILE_NOT_FOUND,
752 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
753 passfail.longerror);
755 /*Lastly a long directory, long file */
756 test_ValidPathA(curdir,NONDIR_LONG,LONGFILE,tmpstr,&passfail,"test12");
757 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
758 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
759 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
760 !passfail.shorterror,
761 "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
762 passfail.shorterror);
763 if(pGetLongPathNameA) {
764 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
765 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
766 passfail.longerror==ERROR_FILE_NOT_FOUND,
767 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
768 passfail.longerror);
770 /* Next try directories ending with '\\' */
771 /* Existing Directories */
772 sprintf(tmpstr,"%s\\",SHORTDIR);
773 test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test13");
774 sprintf(tmpstr,"%s\\",LONGDIR);
775 test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test14");
776 /* Nonexistent directories */
777 sprintf(tmpstr,"%s\\",NONDIR_SHORT);
778 test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test15");
779 sprintf(tmpstr2,"%s\\%s",curdir_short,tmpstr);
780 ok((passfail.shortlen==0 &&
781 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
782 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
783 (passfail.shortlen==strlen(tmpstr2) && lstrcmpiA(tmpstr1,tmpstr2)==0),
784 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
785 passfail.shortlen,passfail.shorterror,tmpstr);
786 if(pGetLongPathNameA) {
787 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
788 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
789 "GetLongPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
790 passfail.longerror);
792 sprintf(tmpstr,"%s\\",NONDIR_LONG);
793 test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test16");
794 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
795 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
796 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
797 !passfail.shorterror,
798 "GetShortPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
799 passfail.shorterror);
800 if(pGetLongPathNameA) {
801 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
802 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
803 "GetLongPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
804 passfail.longerror);
806 /* Test GetFullPathNameA with drive letters */
807 if( curDrive != NOT_A_VALID_DRIVE) {
808 sprintf(tmpstr,"%c:",curdir[0]);
809 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr2,&strptr),
810 "GetFullPathNameA(%c:) failed\n", curdir[0]);
811 GetCurrentDirectoryA(MAX_PATH,tmpstr);
812 sprintf(tmpstr1,"%s\\",tmpstr);
813 ok(lstrcmpiA(tmpstr,tmpstr2)==0 || lstrcmpiA(tmpstr1,tmpstr2)==0,
814 "GetFullPathNameA(%c:) returned '%s' instead of '%s' or '%s'\n",
815 curdir[0],tmpstr2,tmpstr,tmpstr1);
817 sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
818 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
819 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
820 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
821 ok(lstrcmpiA(SHORTFILE,strptr)==0,
822 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
824 /* Without a leading slash, insert the current directory if on the current drive */
825 sprintf(tmpstr,"%c:%s\\%s",curdir[0],SHORTDIR,SHORTFILE);
826 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
827 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
828 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
829 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
830 ok(lstrcmpiA(SHORTFILE,strptr)==0,
831 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
832 /* Otherwise insert the missing leading slash */
833 if( otherDrive != NOT_A_VALID_DRIVE) {
834 /* FIXME: this test assumes that current directory on other drive is root */
835 sprintf(tmpstr,"%c:%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
836 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed for %s\n", tmpstr);
837 sprintf(tmpstr,"%c:\\%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
838 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
839 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
840 ok(lstrcmpiA(SHORTFILE,strptr)==0,
841 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
843 /* Xilinx tools like to mix Unix and DOS formats, which Windows handles fine.
844 So test for them. */
845 if( curDrive != NOT_A_VALID_DRIVE) {
846 sprintf(tmpstr,"%c:/%s\\%s",curDrive,SHORTDIR,SHORTFILE);
847 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
848 sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
849 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
850 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
851 ok(lstrcmpiA(SHORTFILE,strptr)==0,
852 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
854 /**/
855 sprintf(tmpstr,"%c:%s/%s",curdir[0],SHORTDIR,SHORTFILE);
856 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
857 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
858 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
859 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
860 ok(lstrcmpiA(SHORTFILE,strptr)==0,
861 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
862 /* Windows will insert a drive letter in front of an absolute UNIX path */
863 sprintf(tmpstr,"/%s/%s",SHORTDIR,SHORTFILE);
864 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
865 sprintf(tmpstr,"%c:\\%s\\%s",*tmpstr1,SHORTDIR,SHORTFILE);
866 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
867 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
868 /* This passes in Wine because it still contains the pointer from the previous test */
869 ok(lstrcmpiA(SHORTFILE,strptr)==0,
870 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
872 /* Now try some relative paths */
873 ok(GetShortPathNameA(LONGDIR,tmpstr,MAX_PATH),"GetShortPathNameA failed\n");
874 test_SplitShortPathA(tmpstr,dir,eight,three);
875 if(pGetLongPathNameA) {
876 ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
877 ok(lstrcmpiA(tmpstr1,LONGDIR)==0,
878 "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,LONGDIR);
880 sprintf(tmpstr,".\\%s",LONGDIR);
881 ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed\n");
882 test_SplitShortPathA(tmpstr1,dir,eight,three);
883 ok(lstrcmpiA(dir,".")==0 || dir[0]=='\0',
884 "GetShortPathNameA did not keep relative directory [%s]\n",tmpstr1);
885 if(pGetLongPathNameA) {
886 ok(pGetLongPathNameA(tmpstr1,tmpstr1,MAX_PATH),"GetLongPathNameA failed %s\n",
887 tmpstr);
888 ok(lstrcmpiA(tmpstr1,tmpstr)==0,
889 "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
891 /* Check out Get*PathNameA on some funny characters */
892 for(i=0;i<lstrlenA(funny_chars);i++) {
893 INT valid;
894 valid=(is_char_ok[i]=='0') ? 0 : 1;
895 sprintf(tmpstr1,"check%d-1",i);
896 sprintf(tmpstr,"file%c000.ext",funny_chars[i]);
897 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
898 sprintf(tmpstr1,"check%d-2",i);
899 sprintf(tmpstr,"file000.e%ct",funny_chars[i]);
900 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
901 sprintf(tmpstr1,"check%d-3",i);
902 sprintf(tmpstr,"%cfile000.ext",funny_chars[i]);
903 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
904 sprintf(tmpstr1,"check%d-4",i);
905 sprintf(tmpstr,"file000%c.ext",funny_chars[i]);
906 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
907 sprintf(tmpstr1,"check%d-5",i);
908 sprintf(tmpstr,"Long %c File",funny_chars[i]);
909 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
910 sprintf(tmpstr1,"check%d-6",i);
911 sprintf(tmpstr,"%c Long File",funny_chars[i]);
912 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
913 sprintf(tmpstr1,"check%d-7",i);
914 sprintf(tmpstr,"Long File %c",funny_chars[i]);
915 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
917 /* Now try it on mixed case short names */
918 test_ShortPathCase(curdir,SHORTDIR,LONGFILE);
919 test_ShortPathCase(curdir,LONGDIR,SHORTFILE);
920 test_ShortPathCase(curdir,LONGDIR,LONGFILE);
923 static void test_GetTempPathA(char* tmp_dir)
925 DWORD len, len_with_null;
926 char buf[MAX_PATH];
928 len_with_null = strlen(tmp_dir) + 1;
930 lstrcpyA(buf, "foo");
931 len = GetTempPathA(MAX_PATH, buf);
932 ok(len <= MAX_PATH, "should fit into MAX_PATH\n");
933 ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
934 ok(len == strlen(buf), "returned length should be equal to the length of string\n");
936 /* Some versions of Windows touch the buffer, some don't so we don't
937 * test that. Also, NT sometimes exaggerates the required buffer size
938 * so we cannot test for an exact match. Finally, the
939 * 'len_with_null - 1' case is so buggy on Windows it's not testable.
940 * For instance in some cases Win98 returns len_with_null - 1 instead
941 * of len_with_null.
943 len = GetTempPathA(1, buf);
944 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
946 len = GetTempPathA(0, NULL);
947 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
949 /* The call above gave us the buffer size that Windows thinks is needed
950 * so the next call should work
952 lstrcpyA(buf, "foo");
953 len = GetTempPathA(len, buf);
954 ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
955 ok(len == strlen(buf), "returned length should be equal to the length of string\n");
958 static void test_GetTempPathW(char* tmp_dir)
960 DWORD len, len_with_null;
961 WCHAR buf[MAX_PATH];
962 WCHAR tmp_dirW[MAX_PATH];
963 static const WCHAR fooW[] = {'f','o','o',0};
965 MultiByteToWideChar(CP_ACP,0,tmp_dir,-1,tmp_dirW,sizeof(tmp_dirW)/sizeof(*tmp_dirW));
966 len_with_null = lstrlenW(tmp_dirW) + 1;
968 /* This one is different from ANSI version: ANSI version doesn't
969 * touch the buffer, unicode version usually truncates the buffer
970 * to zero size. NT still exaggerates the required buffer size
971 * sometimes so we cannot test for an exact match. Finally, the
972 * 'len_with_null - 1' case is so buggy on Windows it's not testable.
973 * For instance on NT4 it will sometimes return a path without the
974 * trailing '\\' and sometimes return an error.
977 lstrcpyW(buf, fooW);
978 len = GetTempPathW(MAX_PATH, buf);
979 if (len == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
981 win_skip("GetTempPathW is not available\n");
982 return;
984 ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
985 ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
987 lstrcpyW(buf, fooW);
988 len = GetTempPathW(1, buf);
989 ok(buf[0] == 0, "unicode version should truncate the buffer to zero size\n");
990 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
992 len = GetTempPathW(0, NULL);
993 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
995 lstrcpyW(buf, fooW);
996 len = GetTempPathW(len, buf);
997 ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
998 ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
1001 static void test_GetTempPath(void)
1003 char save_TMP[MAX_PATH];
1004 char windir[MAX_PATH];
1005 char buf[MAX_PATH];
1007 if (!GetEnvironmentVariableA("TMP", save_TMP, sizeof(save_TMP))) save_TMP[0] = 0;
1009 /* test default configuration */
1010 trace("TMP=%s\n", save_TMP);
1011 if (save_TMP[0])
1013 strcpy(buf,save_TMP);
1014 if (buf[strlen(buf)-1]!='\\')
1015 strcat(buf,"\\");
1016 test_GetTempPathA(buf);
1017 test_GetTempPathW(buf);
1020 /* TMP=C:\WINDOWS */
1021 GetWindowsDirectoryA(windir, sizeof(windir));
1022 SetEnvironmentVariableA("TMP", windir);
1023 GetEnvironmentVariableA("TMP", buf, sizeof(buf));
1024 trace("TMP=%s\n", buf);
1025 strcat(windir,"\\");
1026 test_GetTempPathA(windir);
1027 test_GetTempPathW(windir);
1029 /* TMP=C:\ */
1030 GetWindowsDirectoryA(windir, sizeof(windir));
1031 windir[3] = 0;
1032 SetEnvironmentVariableA("TMP", windir);
1033 GetEnvironmentVariableA("TMP", buf, sizeof(buf));
1034 trace("TMP=%s\n", buf);
1035 test_GetTempPathA(windir);
1036 test_GetTempPathW(windir);
1038 /* TMP=C: i.e. use current working directory of the specified drive */
1039 GetWindowsDirectoryA(windir, sizeof(windir));
1040 SetCurrentDirectoryA(windir);
1041 windir[2] = 0;
1042 SetEnvironmentVariableA("TMP", windir);
1043 GetEnvironmentVariableA("TMP", buf, sizeof(buf));
1044 trace("TMP=%s\n", buf);
1045 GetWindowsDirectoryA(windir, sizeof(windir));
1046 strcat(windir,"\\");
1047 test_GetTempPathA(windir);
1048 test_GetTempPathW(windir);
1050 SetEnvironmentVariableA("TMP", save_TMP);
1053 static void test_GetLongPathNameA(void)
1055 DWORD length, explength, hostsize;
1056 char tempfile[MAX_PATH];
1057 char longpath[MAX_PATH];
1058 char unc_prefix[MAX_PATH];
1059 char unc_short[MAX_PATH], unc_long[MAX_PATH];
1060 char temppath[MAX_PATH], temppath2[MAX_PATH];
1061 HANDLE file;
1063 if (!pGetLongPathNameA)
1064 return;
1066 GetTempPathA(MAX_PATH, tempfile);
1067 lstrcatA(tempfile, "longfilename.longext");
1069 file = CreateFileA(tempfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1070 CloseHandle(file);
1072 /* Test a normal path with a small buffer size */
1073 memset(temppath, 0, MAX_PATH);
1074 length = pGetLongPathNameA(tempfile, temppath, 4);
1075 /* We have a failure so length should be the minimum plus the terminating '0' */
1076 ok(length >= strlen(tempfile) + 1, "Wrong length\n");
1077 ok(temppath[0] == 0, "Buffer should not have been touched\n");
1079 /* Some UNC syntax tests */
1081 memset(temppath, 0, MAX_PATH);
1082 memset(temppath2, 0, MAX_PATH);
1083 lstrcpyA(temppath2, "\\\\?\\");
1084 lstrcatA(temppath2, tempfile);
1085 explength = length + 4;
1087 SetLastError(0xdeadbeef);
1088 length = pGetLongPathNameA(temppath2, NULL, 0);
1089 if (length == 0 && GetLastError() == ERROR_BAD_NET_NAME)
1091 win_skip("UNC syntax tests don't work on Win98/WinMe\n");
1092 DeleteFileA(tempfile);
1093 return;
1095 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1097 length = pGetLongPathNameA(temppath2, NULL, MAX_PATH);
1098 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1100 length = pGetLongPathNameA(temppath2, temppath, 4);
1101 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1102 ok(temppath[0] == 0, "Buffer should not have been touched\n");
1104 /* Now an UNC path with the computername */
1105 lstrcpyA(unc_prefix, "\\\\");
1106 hostsize = sizeof(unc_prefix) - 2;
1107 GetComputerNameA(unc_prefix + 2, &hostsize);
1108 lstrcatA(unc_prefix, "\\");
1110 /* Create a short syntax for the whole unc path */
1111 memset(unc_short, 0, MAX_PATH);
1112 GetShortPathNameA(tempfile, temppath, MAX_PATH);
1113 lstrcpyA(unc_short, unc_prefix);
1114 unc_short[lstrlenA(unc_short)] = temppath[0];
1115 lstrcatA(unc_short, "$\\");
1116 lstrcatA(unc_short, strchr(temppath, '\\') + 1);
1118 /* Create a long syntax for reference */
1119 memset(longpath, 0, MAX_PATH);
1120 pGetLongPathNameA(tempfile, temppath, MAX_PATH);
1121 lstrcpyA(longpath, unc_prefix);
1122 longpath[lstrlenA(longpath)] = temppath[0];
1123 lstrcatA(longpath, "$\\");
1124 lstrcatA(longpath, strchr(temppath, '\\') + 1);
1126 /* NULL test */
1127 SetLastError(0xdeadbeef);
1128 length = pGetLongPathNameA(unc_short, NULL, 0);
1129 if (length == 0 && GetLastError() == ERROR_BAD_NETPATH)
1131 /* Seen on Window XP Home */
1132 win_skip("UNC with computername is not supported\n");
1133 DeleteFileA(tempfile);
1134 return;
1136 explength = lstrlenA(longpath) + 1;
1137 todo_wine
1138 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1140 length = pGetLongPathNameA(unc_short, NULL, MAX_PATH);
1141 todo_wine
1142 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1144 memset(unc_long, 0, MAX_PATH);
1145 length = pGetLongPathNameA(unc_short, unc_long, lstrlenA(unc_short));
1146 /* length will include terminating '0' on failure */
1147 todo_wine
1148 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1149 ok(unc_long[0] == 0, "Buffer should not have been touched\n");
1151 memset(unc_long, 0, MAX_PATH);
1152 length = pGetLongPathNameA(unc_short, unc_long, length);
1153 /* length doesn't include terminating '0' on success */
1154 explength--;
1155 todo_wine
1157 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1158 ok(!lstrcmpiA(unc_long, longpath), "Expected (%s), got (%s)\n", longpath, unc_long);
1161 DeleteFileA(tempfile);
1164 static void test_GetLongPathNameW(void)
1166 DWORD length, expanded;
1167 BOOL ret;
1168 HANDLE file;
1169 WCHAR empty[MAX_PATH];
1170 WCHAR tempdir[MAX_PATH], name[200];
1171 WCHAR dirpath[4 + MAX_PATH + 200]; /* To ease removal */
1172 WCHAR shortpath[4 + MAX_PATH + 200 + 1 + 200];
1173 static const WCHAR prefix[] = { '\\','\\','?','\\', 0};
1174 static const WCHAR backslash[] = { '\\', 0};
1175 static const WCHAR letterX[] = { 'X', 0};
1177 if (!pGetLongPathNameW)
1178 return;
1180 SetLastError(0xdeadbeef);
1181 length = pGetLongPathNameW(NULL,NULL,0);
1182 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1184 win_skip("GetLongPathNameW is not implemented\n");
1185 return;
1187 ok(0==length,"GetLongPathNameW returned %d but expected 0\n",length);
1188 ok(GetLastError()==ERROR_INVALID_PARAMETER,"GetLastError returned %d but expected ERROR_INVALID_PARAMETER\n",GetLastError());
1190 SetLastError(0xdeadbeef);
1191 empty[0]=0;
1192 length = pGetLongPathNameW(empty,NULL,0);
1193 ok(0==length,"GetLongPathNameW returned %d but expected 0\n",length);
1194 ok(GetLastError()==ERROR_PATH_NOT_FOUND,"GetLastError returned %d but expected ERROR_PATH_NOT_FOUND\n",GetLastError());
1196 /* Create a long path name. The path needs to exist for these tests to
1197 * succeed so we need the "\\?\" prefix when creating directories and
1198 * files.
1200 name[0] = 0;
1201 while (lstrlenW(name) < (sizeof(name)/sizeof(WCHAR) - 1))
1202 lstrcatW(name, letterX);
1204 GetTempPathW(MAX_PATH, tempdir);
1206 lstrcpyW(shortpath, prefix);
1207 lstrcatW(shortpath, tempdir);
1208 lstrcatW(shortpath, name);
1209 lstrcpyW(dirpath, shortpath);
1210 ret = CreateDirectoryW(shortpath, NULL);
1211 ok(ret, "Could not create the temporary directory : %d\n", GetLastError());
1212 lstrcatW(shortpath, backslash);
1213 lstrcatW(shortpath, name);
1215 /* Path does not exist yet and we know it overruns MAX_PATH */
1217 /* No prefix */
1218 SetLastError(0xdeadbeef);
1219 length = pGetLongPathNameW(shortpath + 4, NULL, 0);
1220 ok(length == 0, "Expected 0, got %d\n", length);
1221 todo_wine
1222 ok(GetLastError() == ERROR_PATH_NOT_FOUND,
1223 "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
1224 /* With prefix */
1225 SetLastError(0xdeadbeef);
1226 length = pGetLongPathNameW(shortpath, NULL, 0);
1227 todo_wine
1229 ok(length == 0, "Expected 0, got %d\n", length);
1230 ok(GetLastError() == ERROR_FILE_NOT_FOUND,
1231 "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
1234 file = CreateFileW(shortpath, GENERIC_READ|GENERIC_WRITE, 0, NULL,
1235 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1236 ok(file != INVALID_HANDLE_VALUE,
1237 "Could not create the temporary file : %d.\n", GetLastError());
1238 CloseHandle(file);
1240 /* Path exists */
1242 /* No prefix */
1243 SetLastError(0xdeadbeef);
1244 length = pGetLongPathNameW(shortpath + 4, NULL, 0);
1245 todo_wine
1247 ok(length == 0, "Expected 0, got %d\n", length);
1248 ok(GetLastError() == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
1250 /* With prefix */
1251 expanded = 4 + (pGetLongPathNameW(tempdir, NULL, 0) - 1) + lstrlenW(name) + 1 + lstrlenW(name) + 1;
1252 SetLastError(0xdeadbeef);
1253 length = pGetLongPathNameW(shortpath, NULL, 0);
1254 ok(length == expanded, "Expected %d, got %d\n", expanded, length);
1256 /* NULL buffer with length crashes on Windows */
1257 if (0)
1258 pGetLongPathNameW(shortpath, NULL, 20);
1260 ok(DeleteFileW(shortpath), "Could not delete temporary file\n");
1261 ok(RemoveDirectoryW(dirpath), "Could not delete temporary directory\n");
1264 static void test_GetShortPathNameW(void)
1266 WCHAR test_path[] = { 'L', 'o', 'n', 'g', 'D', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 'N', 'a', 'm', 'e', 0 };
1267 WCHAR path[MAX_PATH];
1268 WCHAR short_path[MAX_PATH];
1269 DWORD length;
1270 HANDLE file;
1271 int ret;
1272 WCHAR name[] = { 't', 'e', 's', 't', 0 };
1273 WCHAR backSlash[] = { '\\', 0 };
1275 SetLastError(0xdeadbeef);
1276 GetTempPathW( MAX_PATH, path );
1277 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1279 win_skip("GetTempPathW is not implemented\n");
1280 return;
1283 lstrcatW( path, test_path );
1284 lstrcatW( path, backSlash );
1285 ret = CreateDirectoryW( path, NULL );
1286 ok( ret, "Directory was not created. LastError = %d\n", GetLastError() );
1288 /* Starting a main part of test */
1289 length = GetShortPathNameW( path, short_path, 0 );
1290 ok( length, "GetShortPathNameW returned 0.\n" );
1291 ret = GetShortPathNameW( path, short_path, length );
1292 ok( ret, "GetShortPathNameW returned 0.\n" );
1294 lstrcatW( short_path, name );
1296 /* GetShortPathName for a non-existent short file name should fail */
1297 SetLastError(0xdeadbeef);
1298 length = GetShortPathNameW( short_path, path, 0 );
1299 ok(!length, "GetShortPathNameW should fail\n");
1300 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
1302 file = CreateFileW( short_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1303 ok( file != INVALID_HANDLE_VALUE, "File was not created.\n" );
1305 /* End test */
1306 CloseHandle( file );
1307 ret = DeleteFileW( short_path );
1308 ok( ret, "Cannot delete file.\n" );
1309 ret = RemoveDirectoryW( path );
1310 ok( ret, "Cannot delete directory.\n" );
1313 static void test_GetSystemDirectory(void)
1315 CHAR buffer[MAX_PATH + 4];
1316 DWORD res;
1317 DWORD total;
1319 SetLastError(0xdeadbeef);
1320 res = GetSystemDirectoryA(NULL, 0);
1321 /* res includes the terminating Zero */
1322 ok(res > 0, "returned %d with %d (expected '>0')\n", res, GetLastError());
1324 total = res;
1326 /* this crashes on XP */
1327 if (0)
1328 GetSystemDirectoryA(NULL, total);
1330 SetLastError(0xdeadbeef);
1331 res = GetSystemDirectoryA(NULL, total-1);
1332 /* 95+NT: total (includes the terminating Zero)
1333 98+ME: 0 with ERROR_INVALID_PARAMETER */
1334 ok( (res == total) || (!res && (GetLastError() == ERROR_INVALID_PARAMETER)),
1335 "returned %d with %d (expected '%d' or: '0' with "
1336 "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), total);
1338 if (total > MAX_PATH) return;
1340 buffer[0] = '\0';
1341 SetLastError(0xdeadbeef);
1342 res = GetSystemDirectoryA(buffer, total);
1343 /* res does not include the terminating Zero */
1344 ok( (res == (total-1)) && (buffer[0]),
1345 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1346 res, GetLastError(), buffer, total-1);
1348 buffer[0] = '\0';
1349 SetLastError(0xdeadbeef);
1350 res = GetSystemDirectoryA(buffer, total + 1);
1351 /* res does not include the terminating Zero */
1352 ok( (res == (total-1)) && (buffer[0]),
1353 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1354 res, GetLastError(), buffer, total-1);
1356 memset(buffer, '#', total + 1);
1357 buffer[total + 2] = '\0';
1358 SetLastError(0xdeadbeef);
1359 res = GetSystemDirectoryA(buffer, total-1);
1360 /* res includes the terminating Zero) */
1361 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1362 res, GetLastError(), buffer, total);
1364 memset(buffer, '#', total + 1);
1365 buffer[total + 2] = '\0';
1366 SetLastError(0xdeadbeef);
1367 res = GetSystemDirectoryA(buffer, total-2);
1368 /* res includes the terminating Zero) */
1369 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1370 res, GetLastError(), buffer, total);
1373 static void test_GetWindowsDirectory(void)
1375 CHAR buffer[MAX_PATH + 4];
1376 DWORD res;
1377 DWORD total;
1379 SetLastError(0xdeadbeef);
1380 res = GetWindowsDirectoryA(NULL, 0);
1381 /* res includes the terminating Zero */
1382 ok(res > 0, "returned %d with %d (expected '>0')\n", res, GetLastError());
1384 total = res;
1385 /* this crashes on XP */
1386 if (0)
1387 GetWindowsDirectoryA(NULL, total);
1389 SetLastError(0xdeadbeef);
1390 res = GetWindowsDirectoryA(NULL, total-1);
1391 /* 95+NT: total (includes the terminating Zero)
1392 98+ME: 0 with ERROR_INVALID_PARAMETER */
1393 ok( (res == total) || (!res && (GetLastError() == ERROR_INVALID_PARAMETER)),
1394 "returned %d with %d (expected '%d' or: '0' with "
1395 "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), total);
1397 if (total > MAX_PATH) return;
1399 buffer[0] = '\0';
1400 SetLastError(0xdeadbeef);
1401 res = GetWindowsDirectoryA(buffer, total);
1402 /* res does not include the terminating Zero */
1403 ok( (res == (total-1)) && (buffer[0]),
1404 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1405 res, GetLastError(), buffer, total-1);
1407 buffer[0] = '\0';
1408 SetLastError(0xdeadbeef);
1409 res = GetWindowsDirectoryA(buffer, total + 1);
1410 /* res does not include the terminating Zero */
1411 ok( (res == (total-1)) && (buffer[0]),
1412 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1413 res, GetLastError(), buffer, total-1);
1415 memset(buffer, '#', total + 1);
1416 buffer[total + 2] = '\0';
1417 SetLastError(0xdeadbeef);
1418 res = GetWindowsDirectoryA(buffer, total-1);
1419 /* res includes the terminating Zero) */
1420 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1421 res, GetLastError(), buffer, total);
1423 memset(buffer, '#', total + 1);
1424 buffer[total + 2] = '\0';
1425 SetLastError(0xdeadbeef);
1426 res = GetWindowsDirectoryA(buffer, total-2);
1427 /* res includes the terminating Zero) */
1428 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1429 res, GetLastError(), buffer, total);
1432 static void test_NeedCurrentDirectoryForExePathA(void)
1434 if (!pNeedCurrentDirectoryForExePathA)
1436 win_skip("NeedCurrentDirectoryForExePathA is not available\n");
1437 return;
1440 /* Crashes in Windows */
1441 if (0)
1442 pNeedCurrentDirectoryForExePathA(NULL);
1444 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", NULL);
1445 ok(pNeedCurrentDirectoryForExePathA("."), "returned FALSE for \".\"\n");
1446 ok(pNeedCurrentDirectoryForExePathA("c:\\"), "returned FALSE for \"c:\\\"\n");
1447 ok(pNeedCurrentDirectoryForExePathA("cmd.exe"), "returned FALSE for \"cmd.exe\"\n");
1449 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", "nya");
1450 ok(!pNeedCurrentDirectoryForExePathA("."), "returned TRUE for \".\"\n");
1451 ok(pNeedCurrentDirectoryForExePathA("c:\\"), "returned FALSE for \"c:\\\"\n");
1452 ok(!pNeedCurrentDirectoryForExePathA("cmd.exe"), "returned TRUE for \"cmd.exe\"\n");
1455 static void test_NeedCurrentDirectoryForExePathW(void)
1457 const WCHAR thispath[] = {'.', 0};
1458 const WCHAR fullpath[] = {'c', ':', '\\', 0};
1459 const WCHAR cmdname[] = {'c', 'm', 'd', '.', 'e', 'x', 'e', 0};
1461 if (!pNeedCurrentDirectoryForExePathW)
1463 win_skip("NeedCurrentDirectoryForExePathW is not available\n");
1464 return;
1467 /* Crashes in Windows */
1468 if (0)
1469 pNeedCurrentDirectoryForExePathW(NULL);
1471 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", NULL);
1472 ok(pNeedCurrentDirectoryForExePathW(thispath), "returned FALSE for \".\"\n");
1473 ok(pNeedCurrentDirectoryForExePathW(fullpath), "returned FALSE for \"c:\\\"\n");
1474 ok(pNeedCurrentDirectoryForExePathW(cmdname), "returned FALSE for \"cmd.exe\"\n");
1476 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", "nya");
1477 ok(!pNeedCurrentDirectoryForExePathW(thispath), "returned TRUE for \".\"\n");
1478 ok(pNeedCurrentDirectoryForExePathW(fullpath), "returned FALSE for \"c:\\\"\n");
1479 ok(!pNeedCurrentDirectoryForExePathW(cmdname), "returned TRUE for \"cmd.exe\"\n");
1482 /* Call various path/file name retrieving APIs and check the case of
1483 * the returned drive letter. Some apps (for instance Adobe Photoshop CS3
1484 * installer) depend on the drive letter being in upper case.
1486 static void test_drive_letter_case(void)
1488 UINT ret;
1489 char buf[MAX_PATH];
1491 #define is_upper_case_letter(a) ((a) >= 'A' && (a) <= 'Z')
1493 memset(buf, 0, sizeof(buf));
1494 SetLastError(0xdeadbeef);
1495 ret = GetWindowsDirectoryA(buf, sizeof(buf));
1496 ok(ret, "GetWindowsDirectory 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 /* re-use the buffer returned by GetFullPathName */
1502 buf[2] = '/';
1503 SetLastError(0xdeadbeef);
1504 ret = GetFullPathNameA(buf + 2, sizeof(buf), buf, NULL);
1505 ok(ret, "GetFullPathName error %u\n", GetLastError());
1506 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1507 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1508 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1510 memset(buf, 0, sizeof(buf));
1511 SetLastError(0xdeadbeef);
1512 ret = GetSystemDirectoryA(buf, sizeof(buf));
1513 ok(ret, "GetSystemDirectory error %u\n", GetLastError());
1514 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1515 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1516 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1518 memset(buf, 0, sizeof(buf));
1519 SetLastError(0xdeadbeef);
1520 ret = GetCurrentDirectoryA(sizeof(buf), buf);
1521 ok(ret, "GetCurrentDirectory error %u\n", GetLastError());
1522 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1523 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1524 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1526 /* TEMP is an environment variable, so it can't be tested for case-sensitivity */
1527 memset(buf, 0, sizeof(buf));
1528 SetLastError(0xdeadbeef);
1529 ret = GetTempPathA(sizeof(buf), buf);
1530 ok(ret, "GetTempPath error %u\n", GetLastError());
1531 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1532 if (buf[0])
1534 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1535 ok(buf[strlen(buf)-1] == '\\', "Temporary path (%s) doesn't end in a slash\n", buf);
1538 memset(buf, 0, sizeof(buf));
1539 SetLastError(0xdeadbeef);
1540 ret = GetFullPathNameA(".", sizeof(buf), buf, NULL);
1541 ok(ret, "GetFullPathName error %u\n", GetLastError());
1542 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1543 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1544 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1546 /* re-use the buffer returned by GetFullPathName */
1547 SetLastError(0xdeadbeef);
1548 ret = GetShortPathNameA(buf, buf, sizeof(buf));
1549 ok(ret, "GetShortPathName error %u\n", GetLastError());
1550 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1551 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1552 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1554 if (pGetLongPathNameA)
1556 /* re-use the buffer returned by GetShortPathName */
1557 SetLastError(0xdeadbeef);
1558 ret = pGetLongPathNameA(buf, buf, sizeof(buf));
1559 ok(ret, "GetLongPathNameA error %u\n", GetLastError());
1560 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1561 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1562 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1564 #undef is_upper_case_letter
1567 static const char manifest_dep[] =
1568 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
1569 "<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH "\"/>"
1570 " <file name=\"testdep.dll\" />"
1571 " <file name=\"ole32\" />"
1572 " <file name=\"kernel32.dll\" />"
1573 "</assembly>";
1575 static const char manifest_main[] =
1576 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
1577 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
1578 "<dependency>"
1579 " <dependentAssembly>"
1580 " <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH "\" />"
1581 " </dependentAssembly>"
1582 "</dependency>"
1583 "</assembly>";
1585 static void create_manifest_file(const char *filename, const char *manifest)
1587 WCHAR path[MAX_PATH], manifest_path[MAX_PATH];
1588 HANDLE file;
1589 DWORD size;
1591 MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH );
1593 GetTempPathW(sizeof(manifest_path)/sizeof(WCHAR), manifest_path);
1594 lstrcatW(manifest_path, path);
1596 file = CreateFileW(manifest_path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1597 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
1598 WriteFile(file, manifest, strlen(manifest), &size, NULL);
1599 CloseHandle(file);
1602 static void delete_manifest_file(const char *filename)
1604 CHAR path[MAX_PATH];
1606 GetTempPathA(sizeof(path), path);
1607 strcat(path, filename);
1608 DeleteFileA(path);
1611 static HANDLE test_create(const char *file)
1613 WCHAR path[MAX_PATH], manifest_path[MAX_PATH];
1614 ACTCTXW actctx;
1615 HANDLE handle;
1617 MultiByteToWideChar(CP_ACP, 0, file, -1, path, MAX_PATH);
1618 GetTempPathW(sizeof(manifest_path)/sizeof(WCHAR), manifest_path);
1619 lstrcatW(manifest_path, path);
1621 memset(&actctx, 0, sizeof(ACTCTXW));
1622 actctx.cbSize = sizeof(ACTCTXW);
1623 actctx.lpSource = manifest_path;
1625 handle = pCreateActCtxW(&actctx);
1626 ok(handle != INVALID_HANDLE_VALUE, "failed to create context, error %u\n", GetLastError());
1628 ok(actctx.cbSize == sizeof(actctx), "cbSize=%d\n", actctx.cbSize);
1629 ok(actctx.dwFlags == 0, "dwFlags=%d\n", actctx.dwFlags);
1630 ok(actctx.lpSource == manifest_path, "lpSource=%p\n", actctx.lpSource);
1631 ok(actctx.wProcessorArchitecture == 0, "wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture);
1632 ok(actctx.wLangId == 0, "wLangId=%d\n", actctx.wLangId);
1633 ok(actctx.lpAssemblyDirectory == NULL, "lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory);
1634 ok(actctx.lpResourceName == NULL, "lpResourceName=%p\n", actctx.lpResourceName);
1635 ok(actctx.lpApplicationName == NULL, "lpApplicationName=%p\n", actctx.lpApplicationName);
1636 ok(actctx.hModule == NULL, "hModule=%p\n", actctx.hModule);
1638 return handle;
1641 static void test_SearchPathA(void)
1643 static const CHAR testdepA[] = "testdep.dll";
1644 static const CHAR testdeprelA[] = "./testdep.dll";
1645 static const CHAR kernel32A[] = "kernel32.dll";
1646 static const CHAR fileA[] = "";
1647 CHAR pathA[MAX_PATH], buffA[MAX_PATH], path2A[MAX_PATH];
1648 CHAR *ptrA = NULL;
1649 ULONG_PTR cookie;
1650 HANDLE handle;
1651 DWORD ret;
1653 if (!pSearchPathA)
1655 win_skip("SearchPathA isn't available\n");
1656 return;
1659 GetWindowsDirectoryA(pathA, sizeof(pathA)/sizeof(CHAR));
1661 /* NULL filename */
1662 SetLastError(0xdeadbeef);
1663 ret = pSearchPathA(pathA, NULL, NULL, sizeof(buffA)/sizeof(CHAR), buffA, &ptrA);
1664 ok(ret == 0, "Expected failure, got %d\n", ret);
1665 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1666 "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
1668 /* empty filename */
1669 SetLastError(0xdeadbeef);
1670 ret = pSearchPathA(pathA, fileA, NULL, sizeof(buffA)/sizeof(CHAR), buffA, &ptrA);
1671 ok(ret == 0, "Expected failure, got %d\n", ret);
1672 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1673 "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
1675 if (!pActivateActCtx)
1676 return;
1678 create_manifest_file("testdep1.manifest", manifest_dep);
1679 create_manifest_file("main.manifest", manifest_main);
1681 handle = test_create("main.manifest");
1682 delete_manifest_file("testdep1.manifest");
1683 delete_manifest_file("main.manifest");
1685 /* search fails without active context */
1686 ret = pSearchPathA(NULL, testdepA, NULL, sizeof(buffA)/sizeof(CHAR), buffA, NULL);
1687 ok(ret == 0, "got %d\n", ret);
1689 ret = pSearchPathA(NULL, kernel32A, NULL, sizeof(path2A)/sizeof(CHAR), path2A, NULL);
1690 ok(ret && ret == strlen(path2A), "got %d\n", ret);
1692 ret = pActivateActCtx(handle, &cookie);
1693 ok(ret, "failed to activate context, %u\n", GetLastError());
1695 /* works when activated */
1696 ret = pSearchPathA(NULL, testdepA, NULL, sizeof(buffA)/sizeof(CHAR), buffA, NULL);
1697 ok(ret && ret == strlen(buffA), "got %d\n", ret);
1699 ret = pSearchPathA(NULL, "testdep.dll", ".ext", sizeof(buffA)/sizeof(CHAR), buffA, NULL);
1700 ok(ret && ret == strlen(buffA), "got %d\n", ret);
1702 ret = pSearchPathA(NULL, "testdep", ".dll", sizeof(buffA)/sizeof(CHAR), buffA, NULL);
1703 ok(ret && ret == strlen(buffA), "got %d\n", ret);
1705 ret = pSearchPathA(NULL, "testdep", ".ext", sizeof(buffA)/sizeof(CHAR), buffA, NULL);
1706 ok(!ret, "got %d\n", ret);
1708 /* name contains path */
1709 ret = pSearchPathA(NULL, testdeprelA, NULL, sizeof(buffA)/sizeof(CHAR), buffA, NULL);
1710 ok(!ret, "got %d\n", ret);
1712 /* fails with specified path that doesn't contain this file */
1713 ret = pSearchPathA(pathA, testdepA, NULL, sizeof(buffA)/sizeof(CHAR), buffA, NULL);
1714 ok(!ret, "got %d\n", ret);
1716 /* path is redirected for wellknown names too */
1717 ret = pSearchPathA(NULL, kernel32A, NULL, sizeof(buffA)/sizeof(CHAR), buffA, NULL);
1718 ok(ret && ret == strlen(buffA), "got %d\n", ret);
1719 ok(strcmp(buffA, path2A), "got wrong path %s, %s\n", buffA, path2A);
1721 ret = pDeactivateActCtx(0, cookie);
1722 ok(ret, "failed to deactivate context, %u\n", GetLastError());
1723 pReleaseActCtx(handle);
1726 static void test_SearchPathW(void)
1728 static const WCHAR testdeprelW[] = {'.','/','t','e','s','t','d','e','p','.','d','l','l',0};
1729 static const WCHAR testdepW[] = {'t','e','s','t','d','e','p','.','d','l','l',0};
1730 static const WCHAR testdep1W[] = {'t','e','s','t','d','e','p',0};
1731 static const WCHAR kernel32dllW[] = {'k','e','r','n','e','l','3','2','.','d','l','l',0};
1732 static const WCHAR kernel32W[] = {'k','e','r','n','e','l','3','2',0};
1733 static const WCHAR ole32W[] = {'o','l','e','3','2',0};
1734 static const WCHAR extW[] = {'.','e','x','t',0};
1735 static const WCHAR dllW[] = {'.','d','l','l',0};
1736 static const WCHAR fileW[] = { 0 };
1737 WCHAR pathW[MAX_PATH], buffW[MAX_PATH], path2W[MAX_PATH];
1738 WCHAR *ptrW = NULL;
1739 ULONG_PTR cookie;
1740 HANDLE handle;
1741 DWORD ret;
1743 if (!pSearchPathW)
1745 win_skip("SearchPathW isn't available\n");
1746 return;
1749 if (0)
1751 /* NULL filename, crashes on nt4 */
1752 pSearchPathW(pathW, NULL, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, &ptrW);
1755 GetWindowsDirectoryW(pathW, sizeof(pathW)/sizeof(WCHAR));
1757 /* empty filename */
1758 SetLastError(0xdeadbeef);
1759 ret = pSearchPathW(pathW, fileW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, &ptrW);
1760 ok(ret == 0, "Expected failure, got %d\n", ret);
1761 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1762 "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
1764 if (!pActivateActCtx)
1765 return;
1767 create_manifest_file("testdep1.manifest", manifest_dep);
1768 create_manifest_file("main.manifest", manifest_main);
1770 handle = test_create("main.manifest");
1771 delete_manifest_file("testdep1.manifest");
1772 delete_manifest_file("main.manifest");
1774 /* search fails without active context */
1775 ret = pSearchPathW(NULL, testdepW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
1776 ok(ret == 0, "got %d\n", ret);
1778 ret = pSearchPathW(NULL, kernel32dllW, NULL, sizeof(path2W)/sizeof(WCHAR), path2W, NULL);
1779 ok(ret && ret == lstrlenW(path2W), "got %d\n", ret);
1781 /* full path, name without 'dll' extension */
1782 GetSystemDirectoryW(pathW, sizeof(pathW)/sizeof(WCHAR));
1783 ret = pSearchPathW(pathW, kernel32W, NULL, sizeof(path2W)/sizeof(WCHAR), path2W, NULL);
1784 ok(ret == 0, "got %d\n", ret);
1786 GetWindowsDirectoryW(pathW, sizeof(pathW)/sizeof(WCHAR));
1788 ret = pActivateActCtx(handle, &cookie);
1789 ok(ret, "failed to activate context, %u\n", GetLastError());
1791 /* works when activated */
1792 ret = pSearchPathW(NULL, testdepW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
1793 ok(ret && ret == lstrlenW(buffW), "got %d\n", ret);
1795 ret = pSearchPathW(NULL, testdepW, extW, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
1796 ok(ret && ret == lstrlenW(buffW), "got %d\n", ret);
1798 ret = pSearchPathW(NULL, testdep1W, dllW, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
1799 ok(ret && ret == lstrlenW(buffW), "got %d\n", ret);
1801 ret = pSearchPathW(NULL, testdep1W, extW, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
1802 ok(!ret, "got %d\n", ret);
1804 /* name contains path */
1805 ret = pSearchPathW(NULL, testdeprelW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
1806 ok(!ret, "got %d\n", ret);
1808 /* fails with specified path that doesn't contain this file */
1809 ret = pSearchPathW(pathW, testdepW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
1810 ok(!ret, "got %d\n", ret);
1812 /* path is redirected for wellknown names too, meaning it takes precedence over normal search order */
1813 ret = pSearchPathW(NULL, kernel32dllW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
1814 ok(ret && ret == lstrlenW(buffW), "got %d\n", ret);
1815 ok(lstrcmpW(buffW, path2W), "got wrong path %s, %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(path2W));
1817 /* path is built using on manifest file name */
1818 ret = pSearchPathW(NULL, ole32W, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL);
1819 ok(ret && ret == lstrlenW(buffW), "got %d\n", ret);
1821 ret = pDeactivateActCtx(0, cookie);
1822 ok(ret, "failed to deactivate context, %u\n", GetLastError());
1823 pReleaseActCtx(handle);
1826 static void test_GetFullPathNameA(void)
1828 char output[MAX_PATH], *filepart;
1829 DWORD ret;
1830 int i;
1832 const struct
1834 LPCSTR name;
1835 DWORD len;
1836 LPSTR buffer;
1837 LPSTR *lastpart;
1838 } invalid_parameters[] =
1840 {NULL, 0, NULL, NULL},
1841 {NULL, MAX_PATH, NULL, NULL},
1842 {NULL, MAX_PATH, output, NULL},
1843 {NULL, MAX_PATH, output, &filepart},
1844 {"", 0, NULL, NULL},
1845 {"", MAX_PATH, NULL, NULL},
1846 {"", MAX_PATH, output, NULL},
1847 {"", MAX_PATH, output, &filepart},
1850 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
1852 SetLastError(0xdeadbeef);
1853 strcpy(output, "deadbeef");
1854 filepart = (char *)0xdeadbeef;
1855 ret = GetFullPathNameA(invalid_parameters[i].name,
1856 invalid_parameters[i].len,
1857 invalid_parameters[i].buffer,
1858 invalid_parameters[i].lastpart);
1859 ok(!ret, "[%d] Expected GetFullPathNameA to return 0, got %u\n", i, ret);
1860 ok(!strcmp(output, "deadbeef"), "[%d] Expected the output buffer to be unchanged, got \"%s\"\n", i, output);
1861 ok(filepart == (char *)0xdeadbeef, "[%d] Expected output file part pointer to be untouched, got %p\n", i, filepart);
1862 ok(GetLastError() == 0xdeadbeef ||
1863 GetLastError() == ERROR_INVALID_NAME, /* Win7 */
1864 "[%d] Expected GetLastError() to return 0xdeadbeef, got %u\n",
1865 i, GetLastError());
1869 static void test_GetFullPathNameW(void)
1871 static const WCHAR emptyW[] = {0};
1872 static const WCHAR deadbeefW[] = {'d','e','a','d','b','e','e','f',0};
1874 WCHAR output[MAX_PATH], *filepart;
1875 DWORD ret;
1876 int i;
1878 const struct
1880 LPCWSTR name;
1881 DWORD len;
1882 LPWSTR buffer;
1883 LPWSTR *lastpart;
1884 int win7_expect;
1885 } invalid_parameters[] =
1887 {NULL, 0, NULL, NULL},
1888 {NULL, 0, NULL, &filepart, 1},
1889 {NULL, MAX_PATH, NULL, NULL},
1890 {NULL, MAX_PATH, output, NULL},
1891 {NULL, MAX_PATH, output, &filepart, 1},
1892 {emptyW, 0, NULL, NULL},
1893 {emptyW, 0, NULL, &filepart, 1},
1894 {emptyW, MAX_PATH, NULL, NULL},
1895 {emptyW, MAX_PATH, output, NULL},
1896 {emptyW, MAX_PATH, output, &filepart, 1},
1899 SetLastError(0xdeadbeef);
1900 ret = GetFullPathNameW(NULL, 0, NULL, NULL);
1901 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1903 win_skip("GetFullPathNameW is not available\n");
1904 return;
1907 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
1909 SetLastError(0xdeadbeef);
1910 lstrcpyW(output, deadbeefW);
1911 filepart = (WCHAR *)0xdeadbeef;
1912 ret = GetFullPathNameW(invalid_parameters[i].name,
1913 invalid_parameters[i].len,
1914 invalid_parameters[i].buffer,
1915 invalid_parameters[i].lastpart);
1916 ok(!ret, "[%d] Expected GetFullPathNameW to return 0, got %u\n", i, ret);
1917 ok(!lstrcmpW(output, deadbeefW), "[%d] Expected the output buffer to be unchanged, got %s\n", i, wine_dbgstr_w(output));
1918 ok(filepart == (WCHAR *)0xdeadbeef ||
1919 (invalid_parameters[i].win7_expect && filepart == NULL),
1920 "[%d] Expected output file part pointer to be untouched, got %p\n", i, filepart);
1921 ok(GetLastError() == 0xdeadbeef ||
1922 GetLastError() == ERROR_INVALID_NAME, /* Win7 */
1923 "[%d] Expected GetLastError() to return 0xdeadbeef, got %u\n",
1924 i, GetLastError());
1928 static void init_pointers(void)
1930 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
1932 #define MAKEFUNC(f) (p##f = (void*)GetProcAddress(hKernel32, #f))
1933 MAKEFUNC(GetLongPathNameA);
1934 MAKEFUNC(GetLongPathNameW);
1935 MAKEFUNC(NeedCurrentDirectoryForExePathA);
1936 MAKEFUNC(NeedCurrentDirectoryForExePathW);
1937 MAKEFUNC(SearchPathA);
1938 MAKEFUNC(SearchPathW);
1939 MAKEFUNC(ActivateActCtx);
1940 MAKEFUNC(CreateActCtxW);
1941 MAKEFUNC(DeactivateActCtx);
1942 MAKEFUNC(GetCurrentActCtx);
1943 MAKEFUNC(ReleaseActCtx);
1944 #undef MAKEFUNC
1947 static void test_relative_path(void)
1949 char path[MAX_PATH], buf[MAX_PATH];
1950 HANDLE file;
1951 int ret;
1953 if (!pGetLongPathNameA) return;
1955 GetTempPathA(MAX_PATH, path);
1956 ret = SetCurrentDirectoryA(path);
1957 ok(ret, "SetCurrentDirectory error %d\n", GetLastError());
1959 ret = CreateDirectoryA("foo", NULL);
1960 ok(ret, "CreateDirectory error %d\n", GetLastError());
1961 file = CreateFileA("foo\\file", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
1962 ok(file != INVALID_HANDLE_VALUE, "failed to create temp file\n");
1963 CloseHandle(file);
1964 ret = CreateDirectoryA("bar", NULL);
1965 ok(ret, "CreateDirectory error %d\n", GetLastError());
1966 ret = SetCurrentDirectoryA("bar");
1967 ok(ret, "SetCurrentDirectory error %d\n", GetLastError());
1969 ret = GetFileAttributesA("..\\foo\\file");
1970 ok(ret != INVALID_FILE_ATTRIBUTES, "GetFileAttributes error %d\n", GetLastError());
1972 strcpy(buf, "deadbeef");
1973 ret = pGetLongPathNameA(".", buf, MAX_PATH);
1974 ok(ret, "GetLongPathName error %d\n", GetLastError());
1975 ok(!strcmp(buf, "."), "expected ., got %s\n", buf);
1976 strcpy(buf, "deadbeef");
1977 ret = GetShortPathNameA(".", buf, MAX_PATH);
1978 ok(ret, "GetShortPathName error %d\n", GetLastError());
1979 ok(!strcmp(buf, "."), "expected ., got %s\n", buf);
1981 strcpy(buf, "deadbeef");
1982 ret = pGetLongPathNameA("..", buf, MAX_PATH);
1983 ok(ret, "GetLongPathName error %d\n", GetLastError());
1984 ok(!strcmp(buf, ".."), "expected .., got %s\n", buf);
1985 strcpy(buf, "deadbeef");
1986 ret = GetShortPathNameA("..", buf, MAX_PATH);
1987 ok(ret, "GetShortPathName error %d\n", GetLastError());
1988 ok(!strcmp(buf, ".."), "expected .., got %s\n", buf);
1990 strcpy(buf, "deadbeef");
1991 ret = pGetLongPathNameA("..\\foo\\file", buf, MAX_PATH);
1992 ok(ret, "GetLongPathName error %d\n", GetLastError());
1993 ok(!strcmp(buf, "..\\foo\\file"), "expected ..\\foo\\file, got %s\n", buf);
1994 strcpy(buf, "deadbeef");
1995 ret = GetShortPathNameA("..\\foo\\file", buf, MAX_PATH);
1996 ok(ret, "GetShortPathName error %d\n", GetLastError());
1997 ok(!strcmp(buf, "..\\foo\\file"), "expected ..\\foo\\file, got %s\n", buf);
1999 SetCurrentDirectoryA("..");
2000 DeleteFileA("foo\\file");
2001 RemoveDirectoryA("foo");
2002 RemoveDirectoryA("bar");
2005 START_TEST(path)
2007 CHAR origdir[MAX_PATH],curdir[MAX_PATH], curDrive, otherDrive;
2009 init_pointers();
2011 /* Report only once */
2012 if (!pGetLongPathNameA)
2013 win_skip("GetLongPathNameA is not available\n");
2014 if (!pGetLongPathNameW)
2015 win_skip("GetLongPathNameW is not available\n");
2016 if (!pActivateActCtx)
2017 win_skip("Activation contexts not supported, some tests will be skipped\n");
2019 test_relative_path();
2020 test_InitPathA(curdir, &curDrive, &otherDrive);
2021 test_CurrentDirectoryA(origdir,curdir);
2022 test_PathNameA(curdir, curDrive, otherDrive);
2023 test_CleanupPathA(origdir,curdir);
2024 test_GetTempPath();
2025 test_GetLongPathNameA();
2026 test_GetLongPathNameW();
2027 test_GetShortPathNameW();
2028 test_GetSystemDirectory();
2029 test_GetWindowsDirectory();
2030 test_NeedCurrentDirectoryForExePathA();
2031 test_NeedCurrentDirectoryForExePathW();
2032 test_drive_letter_case();
2033 test_SearchPathA();
2034 test_SearchPathW();
2035 test_GetFullPathNameA();
2036 test_GetFullPathNameW();