kernel32: GetLongPathName should fail when called with a wildcard.
[wine.git] / dlls / kernel32 / tests / path.c
blobdf91b316ce611f0f4154f67bee2745673b810aca
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 #elif defined __arm__
50 #define ARCH "arm"
51 #elif defined __aarch64__
52 #define ARCH "arm64"
53 #else
54 #define ARCH "none"
55 #endif
57 /* the following characters don't work well with GetFullPathNameA
58 in Win98. I don't know if this is a FAT thing, or if it is an OS thing
59 but I don't test these characters now.
60 NOTE: Win2k allows GetFullPathNameA to work with them though
61 |<>"
63 static const CHAR funny_chars[]="!@#$%^&*()=+{}[],?'`";
64 static const CHAR is_char_ok[] ="11111110111111111011";
66 static DWORD (WINAPI *pGetLongPathNameA)(LPCSTR,LPSTR,DWORD);
67 static DWORD (WINAPI *pGetLongPathNameW)(LPWSTR,LPWSTR,DWORD);
69 /* Present in Win2003+ */
70 static BOOL (WINAPI *pNeedCurrentDirectoryForExePathA)(LPCSTR);
71 static BOOL (WINAPI *pNeedCurrentDirectoryForExePathW)(LPCWSTR);
73 static DWORD (WINAPI *pSearchPathA)(LPCSTR,LPCSTR,LPCSTR,DWORD,LPSTR,LPSTR*);
74 static DWORD (WINAPI *pSearchPathW)(LPCWSTR,LPCWSTR,LPCWSTR,DWORD,LPWSTR,LPWSTR*);
75 static BOOL (WINAPI *pSetSearchPathMode)(DWORD);
77 static BOOL (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*);
78 static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW);
79 static BOOL (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);
80 static BOOL (WINAPI *pGetCurrentActCtx)(HANDLE *);
81 static void (WINAPI *pReleaseActCtx)(HANDLE);
83 static BOOL (WINAPI *pCheckNameLegalDOS8Dot3W)(const WCHAR *, char *, DWORD, BOOL *, BOOL *);
84 static BOOL (WINAPI *pCheckNameLegalDOS8Dot3A)(const char *, char *, DWORD, BOOL *, BOOL *);
86 /* a structure to deal with wine todos somewhat cleanly */
87 typedef struct {
88 DWORD shortlen;
89 DWORD shorterror;
90 DWORD s2llen;
91 DWORD s2lerror;
92 DWORD longlen;
93 DWORD longerror;
94 } SLpassfail;
96 /* function that tests GetFullPathNameA, GetShortPathNameA,GetLongPathNameA */
97 /* NOTE: the passfail structure is used to allow customizable todo checking
98 for wine. It is not very pretty, but it sure beats duplicating this
99 function lots of times
101 static void test_ValidPathA(const CHAR *curdir, const CHAR *subdir, const CHAR *filename,
102 CHAR *shortstr, SLpassfail *passfail, const CHAR *errstr)
104 CHAR tmpstr[MAX_PATH],
105 fullpath[MAX_PATH], /*full path to the file (not short/long) */
106 subpath[MAX_PATH], /*relative path to the file */
107 fullpathshort[MAX_PATH], /*absolute path to the file (short format) */
108 fullpathlong[MAX_PATH], /*absolute path to the file (long format) */
109 curdirshort[MAX_PATH], /*absolute path to the current dir (short) */
110 curdirlong[MAX_PATH]; /*absolute path to the current dir (long) */
111 LPSTR strptr; /*ptr to the filename portion of the path */
112 DWORD len;
113 /* if passfail is NULL, we can perform all checks within this function,
114 otherwise, we will return the relevant data in the passfail struct, so
115 we must initialize it first
117 if(passfail!=NULL) {
118 passfail->shortlen=-1;passfail->s2llen=-1;passfail->longlen=-1;
119 passfail->shorterror=0;passfail->s2lerror=0;passfail->longerror=0;
121 /* GetLongPathNameA is only supported on Win2k+ and Win98+ */
122 if(pGetLongPathNameA) {
123 ok((len=pGetLongPathNameA(curdir,curdirlong,MAX_PATH)),
124 "%s: GetLongPathNameA failed\n",errstr);
125 /*GetLongPathNameA can return a trailing '\\' but shouldn't do so here */
126 ok(! HAS_TRAIL_SLASH_A(curdirlong),
127 "%s: GetLongPathNameA should not have a trailing \\\n",errstr);
129 ok((len=GetShortPathNameA(curdir,curdirshort,MAX_PATH)),
130 "%s: GetShortPathNameA failed\n",errstr);
131 /*GetShortPathNameA can return a trailing '\\' but shouldn't do so here */
132 ok(! HAS_TRAIL_SLASH_A(curdirshort),
133 "%s: GetShortPathNameA should not have a trailing \\\n",errstr);
134 /* build relative and absolute paths from inputs */
135 if(lstrlenA(subdir)) {
136 sprintf(subpath,"%s\\%s",subdir,filename);
137 } else {
138 lstrcpyA(subpath,filename);
140 sprintf(fullpath,"%s\\%s",curdir,subpath);
141 sprintf(fullpathshort,"%s\\%s",curdirshort,subpath);
142 sprintf(fullpathlong,"%s\\%s",curdirlong,subpath);
143 /* Test GetFullPathNameA functionality */
144 len=GetFullPathNameA(subpath,MAX_PATH,tmpstr,&strptr);
145 ok(len, "GetFullPathNameA failed for: '%s'\n",subpath);
146 if(HAS_TRAIL_SLASH_A(subpath)) {
147 ok(strptr==NULL,
148 "%s: GetFullPathNameA should not return a filename ptr\n",errstr);
149 ok(lstrcmpiA(fullpath,tmpstr)==0,
150 "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
151 errstr,tmpstr,fullpath);
152 } else {
153 ok(lstrcmpiA(strptr,filename)==0,
154 "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
155 errstr,strptr,filename);
156 ok(lstrcmpiA(fullpath,tmpstr)==0,
157 "%s: GetFullPathNameA returned '%s' instead of '%s'\n",
158 errstr,tmpstr,fullpath);
160 /* Test GetShortPathNameA functionality */
161 SetLastError(0);
162 len=GetShortPathNameA(fullpathshort,shortstr,MAX_PATH);
163 if(passfail==NULL) {
164 ok(len, "%s: GetShortPathNameA failed\n",errstr);
165 } else {
166 passfail->shortlen=len;
167 passfail->shorterror=GetLastError();
169 /* Test GetLongPathNameA functionality
170 We test both conversion from GetFullPathNameA and from GetShortPathNameA
172 if(pGetLongPathNameA) {
173 if(len!=0) {
174 SetLastError(0);
175 len=pGetLongPathNameA(shortstr,tmpstr,MAX_PATH);
176 if(passfail==NULL) {
177 ok(len,
178 "%s: GetLongPathNameA failed during Short->Long conversion\n", errstr);
179 ok(lstrcmpiA(fullpathlong,tmpstr)==0,
180 "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
181 errstr,tmpstr,fullpathlong);
182 } else {
183 passfail->s2llen=len;
184 passfail->s2lerror=GetLastError();
187 SetLastError(0);
188 len=pGetLongPathNameA(fullpath,tmpstr,MAX_PATH);
189 if(passfail==NULL) {
190 ok(len, "%s: GetLongPathNameA failed\n",errstr);
191 ok(!lstrcmpiA(fullpathlong, tmpstr), "%s: GetLongPathNameA returned '%s' instead of '%s'\n",
192 errstr, tmpstr, fullpathlong);
193 } else {
194 passfail->longlen=len;
195 passfail->longerror=GetLastError();
200 /* split path into leading directory, and 8.3 filename */
201 static void test_SplitShortPathA(CHAR *path,CHAR *dir,CHAR *eight,CHAR *three) {
202 BOOL done = FALSE, error = FALSE;
203 int ext,fil;
204 int len,i;
205 len=lstrlenA(path);
206 ext=len;
207 fil=len;
208 /* walk backwards over path looking for '.' or '\\' separators */
209 for(i=len-1;(i>=0) && (!done);i--) {
210 if(path[i]=='.')
211 if(ext!=len) error=TRUE; else ext=i;
212 else if(path[i]=='\\') {
213 if(i==len-1) {
214 error=TRUE;
215 } else {
216 fil=i;
217 done=TRUE;
221 /* Check that we didn't find a trailing '\\' or multiple '.' */
222 ok(!error,"Illegal file found in 8.3 path '%s'\n",path);
223 /* Separate dir, root, and extension */
224 if(ext!=len) lstrcpyA(three,path+ext+1); else lstrcpyA(three,"");
225 if(fil!=len) {
226 lstrcpynA(eight,path+fil+1,ext-fil);
227 lstrcpynA(dir,path,fil+1);
228 } else {
229 lstrcpynA(eight,path,ext+1);
230 lstrcpyA(dir,"");
232 /* Validate that root and extension really are 8.3 */
233 ok(lstrlenA(eight)<=8 && lstrlenA(three)<=3,
234 "GetShortPathNAmeA did not return an 8.3 path\n");
237 /* Check that GetShortPathNameA returns a valid 8.3 path */
238 static void test_LongtoShortA(CHAR *teststr,const CHAR *goodstr,
239 const CHAR *ext,const CHAR *errstr) {
240 CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
242 test_SplitShortPathA(teststr,dir,eight,three);
243 ok(lstrcmpiA(dir,goodstr)==0,
244 "GetShortPathNameA returned '%s' instead of '%s'\n",dir,goodstr);
245 ok(lstrcmpiA(three,ext)==0,
246 "GetShortPathNameA returned '%s' with incorrect extension\n",three);
249 /* Test that Get(Short|Long|Full)PathNameA work correctly with interesting
250 characters in the filename.
251 'valid' indicates whether this would be an allowed filename
252 'todo' indicates that wine doesn't get this right yet.
253 NOTE: We always call this routine with a nonexistent filename, so
254 Get(Short|Long)PathNameA should never pass, but GetFullPathNameA
255 should.
257 static void test_FunnyChars(CHAR *curdir,CHAR *curdir_short,CHAR *filename, INT valid,CHAR *errstr)
259 CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
260 SLpassfail passfail;
262 test_ValidPathA(curdir,"",filename,tmpstr,&passfail,errstr);
263 if(valid) {
264 sprintf(tmpstr1,"%s\\%s",curdir_short,filename);
265 ok((passfail.shortlen==0 &&
266 (passfail.shorterror==ERROR_FILE_NOT_FOUND || passfail.shorterror==ERROR_PATH_NOT_FOUND || !passfail.shorterror)) ||
267 (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
268 "%s: GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
269 errstr,passfail.shortlen,passfail.shorterror,tmpstr);
270 } else {
271 ok(passfail.shortlen==0 &&
272 (passfail.shorterror==ERROR_INVALID_NAME || passfail.shorterror==ERROR_FILE_NOT_FOUND || !passfail.shorterror),
273 "%s: GetShortPathA should have failed len=%d, error=%d\n",
274 errstr,passfail.shortlen,passfail.shorterror);
276 if(pGetLongPathNameA) {
277 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
278 if(valid) {
279 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
280 "%s: GetLongPathA returned %d and not %d\n",
281 errstr,passfail.longerror,ERROR_FILE_NOT_FOUND);
282 } else {
283 ok(passfail.longerror==ERROR_INVALID_NAME ||
284 passfail.longerror==ERROR_FILE_NOT_FOUND,
285 "%s: GetLongPathA returned %d and not %d or %d'\n",
286 errstr, passfail.longerror,ERROR_INVALID_NAME,ERROR_FILE_NOT_FOUND);
291 /* Routine to test that SetCurrentDirectory behaves as expected. */
292 static void test_setdir(CHAR *olddir,CHAR *newdir,
293 CHAR *cmprstr, INT pass, const CHAR *errstr)
295 CHAR tmppath[MAX_PATH], *dirptr;
296 DWORD val,len,chklen;
298 val=SetCurrentDirectoryA(newdir);
299 len=GetCurrentDirectoryA(MAX_PATH,tmppath);
300 /* if 'pass' then the SetDirectoryA was supposed to pass */
301 if(pass) {
302 dirptr=(cmprstr==NULL) ? newdir : cmprstr;
303 chklen=lstrlenA(dirptr);
304 ok(val,"%s: SetCurrentDirectoryA failed\n",errstr);
305 ok(len==chklen,
306 "%s: SetCurrentDirectory did not change the directory, though it passed\n",
307 errstr);
308 ok(lstrcmpiA(dirptr,tmppath)==0,
309 "%s: SetCurrentDirectory did not change the directory, though it passed\n",
310 errstr);
311 ok(SetCurrentDirectoryA(olddir),
312 "%s: Couldn't set directory to its original value\n",errstr);
313 } else {
314 /* else thest that it fails correctly */
315 chklen=lstrlenA(olddir);
316 ok(val==0,
317 "%s: SetCurrentDirectoryA passed when it should have failed\n",errstr);
318 ok(len==chklen,
319 "%s: SetCurrentDirectory changed the directory, though it failed\n",
320 errstr);
321 ok(lstrcmpiA(olddir,tmppath)==0,
322 "%s: SetCurrentDirectory changed the directory, though it failed\n",
323 errstr);
326 static void test_InitPathA(CHAR *newdir, CHAR *curDrive, CHAR *otherDrive)
328 CHAR tmppath[MAX_PATH], /*path to TEMP */
329 tmpstr[MAX_PATH],
330 tmpstr1[MAX_PATH],
331 invalid_dir[MAX_PATH];
333 DWORD len,len1,drives;
334 INT id;
335 HANDLE hndl;
336 BOOL bRes;
337 UINT unique;
339 *curDrive = *otherDrive = NOT_A_VALID_DRIVE;
341 /* Get the current drive letter */
342 if( GetCurrentDirectoryA( MAX_PATH, tmpstr))
343 *curDrive = tmpstr[0];
344 else
345 trace( "Unable to discover current drive, some tests will not be conducted.\n");
347 /* Test GetTempPathA */
348 len=GetTempPathA(MAX_PATH,tmppath);
349 ok(len!=0 && len < MAX_PATH,"GetTempPathA failed\n");
350 ok(HAS_TRAIL_SLASH_A(tmppath),
351 "GetTempPathA returned a path that did not end in '\\'\n");
352 lstrcpyA(tmpstr,"aaaaaaaa");
353 len1=GetTempPathA(len,tmpstr);
354 ok(len1==len+1 || broken(len1 == len), /* WinME */
355 "GetTempPathA should return string length %d instead of %d\n",len+1,len1);
357 /* Test GetTmpFileNameA */
358 ok((id=GetTempFileNameA(tmppath,"path",0,newdir)),"GetTempFileNameA failed\n");
359 sprintf(tmpstr,"pat%.4x.tmp",id & 0xffff);
360 sprintf(tmpstr1,"pat%x.tmp",id & 0xffff);
361 ok(lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr)==0 ||
362 lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr1)==0,
363 "GetTempFileNameA returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
364 newdir,tmpstr,tmpstr1,id);
365 ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
367 id=GetTempFileNameA(tmppath,NULL,0,newdir);
368 /* Windows 95, 98 return 0==id, while Windows 2000, XP return 0!=id */
369 if (id)
371 sprintf(tmpstr,"%.4x.tmp",id & 0xffff);
372 sprintf(tmpstr1,"%x.tmp",id & 0xffff);
373 ok(lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr)==0 ||
374 lstrcmpiA(newdir+lstrlenA(tmppath),tmpstr1)==0,
375 "GetTempFileNameA returned '%s' which doesn't match '%s' or '%s'. id=%x\n",
376 newdir,tmpstr,tmpstr1,id);
377 ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
380 for(unique=0;unique<3;unique++) {
381 /* Nonexistent path */
382 sprintf(invalid_dir, "%s\\%s",tmppath,"non_existent_dir_1jwj3y32nb3");
383 SetLastError(0xdeadbeef);
384 ok(!GetTempFileNameA(invalid_dir,"tfn",unique,newdir),"GetTempFileNameA should have failed\n");
385 ok(GetLastError()==ERROR_DIRECTORY || broken(GetLastError()==ERROR_PATH_NOT_FOUND)/*win98*/,
386 "got %d, expected ERROR_DIRECTORY\n", GetLastError());
388 /* Check return value for unique !=0 */
389 if(unique) {
390 ok((GetTempFileNameA(tmppath,"tfn",unique,newdir) == unique),"GetTempFileNameA unexpectedly failed\n");
391 /* if unique != 0, the actual temp files are not created: */
392 ok(!DeleteFileA(newdir) && GetLastError() == ERROR_FILE_NOT_FOUND,"Deleted a file that shouldn't exist!\n");
396 /* Find first valid drive letter that is neither newdir[0] nor curDrive */
397 drives = GetLogicalDrives() & ~(1<<(newdir[0]-'A'));
398 if( *curDrive != NOT_A_VALID_DRIVE)
399 drives &= ~(1<<(*curDrive-'A'));
400 if( drives)
401 for( *otherDrive='A'; (drives & 1) == 0; drives>>=1, (*otherDrive)++);
402 else
403 trace( "Could not find alternative drive, some tests will not be conducted.\n");
405 /* Do some CreateDirectoryA tests */
406 /* It would be nice to do test the SECURITY_ATTRIBUTES, but I don't
407 really understand how they work.
408 More formal tests should be done along with CreateFile tests
410 ok((id=GetTempFileNameA(tmppath,"path",0,newdir)),"GetTempFileNameA failed\n");
411 ok(CreateDirectoryA(newdir,NULL)==0,
412 "CreateDirectoryA succeeded even though a file of the same name exists\n");
413 ok(DeleteFileA(newdir),"Couldn't delete the temporary file we just created\n");
414 ok(CreateDirectoryA(newdir,NULL),"CreateDirectoryA failed\n");
415 /* Create some files to test other functions. Note, we will test CreateFileA
416 at some later point
418 sprintf(tmpstr,"%s\\%s",newdir,SHORTDIR);
419 ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed\n");
420 sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
421 ok(CreateDirectoryA(tmpstr,NULL),"CreateDirectoryA failed\n");
422 sprintf(tmpstr,"%c:", *curDrive);
423 bRes = CreateDirectoryA(tmpstr,NULL);
424 ok(!bRes && (GetLastError() == ERROR_ACCESS_DENIED ||
425 GetLastError() == ERROR_ALREADY_EXISTS),
426 "CreateDirectoryA(\"%s\" should have failed (%d)\n", tmpstr, GetLastError());
427 sprintf(tmpstr,"%c:\\", *curDrive);
428 bRes = CreateDirectoryA(tmpstr,NULL);
429 ok(!bRes && (GetLastError() == ERROR_ACCESS_DENIED ||
430 GetLastError() == ERROR_ALREADY_EXISTS),
431 "CreateDirectoryA(\"%s\" should have failed (%d)\n", tmpstr, GetLastError());
432 sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,SHORTFILE);
433 hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
434 CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
435 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
436 ok(CloseHandle(hndl),"CloseHandle failed\n");
437 sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,LONGFILE);
438 hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
439 CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
440 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
441 ok(CloseHandle(hndl),"CloseHandle failed\n");
442 sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,SHORTFILE);
443 hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
444 CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
445 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
446 ok(CloseHandle(hndl),"CloseHandle failed\n");
447 sprintf(tmpstr,"%s\\%s\\%s",newdir,LONGDIR,LONGFILE);
448 hndl=CreateFileA(tmpstr,GENERIC_WRITE,0,NULL,
449 CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
450 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed\n");
451 ok(CloseHandle(hndl),"CloseHandle failed\n");
454 /* Test GetCurrentDirectory & SetCurrentDirectory */
455 static void test_CurrentDirectoryA(CHAR *origdir, CHAR *newdir)
457 CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH];
458 char *buffer;
459 DWORD len,len1;
460 /* Save the original directory, so that we can return to it at the end
461 of the test
463 len=GetCurrentDirectoryA(MAX_PATH,origdir);
464 ok(len!=0 && len < MAX_PATH,"GetCurrentDirectoryA failed\n");
465 /* Make sure that CetCurrentDirectoryA doesn't overwrite the buffer when the
466 buffer size is too small to hold the current directory
468 lstrcpyA(tmpstr,"aaaaaaa");
469 len1=GetCurrentDirectoryA(len,tmpstr);
470 ok(len1==len+1, "GetCurrentDirectoryA returned %d instead of %d\n",len1,len+1);
471 ok(lstrcmpiA(tmpstr,"aaaaaaa")==0,
472 "GetCurrentDirectoryA should not have modified the buffer\n");
474 buffer = HeapAlloc( GetProcessHeap(), 0, 2 * 65536 );
475 SetLastError( 0xdeadbeef );
476 strcpy( buffer, "foo" );
477 len = GetCurrentDirectoryA( 32767, buffer );
478 ok( len != 0 && len < MAX_PATH, "GetCurrentDirectoryA failed %u err %u\n", len, GetLastError() );
479 if (len) ok( !strcmp( buffer, origdir ), "wrong result %s\n", buffer );
480 SetLastError( 0xdeadbeef );
481 strcpy( buffer, "foo" );
482 len = GetCurrentDirectoryA( 32768, buffer );
483 ok( len != 0 && len < MAX_PATH, "GetCurrentDirectoryA failed %u err %u\n", len, GetLastError() );
484 if (len) ok( !strcmp( buffer, origdir ), "wrong result %s\n", buffer );
485 SetLastError( 0xdeadbeef );
486 strcpy( buffer, "foo" );
487 len = GetCurrentDirectoryA( 65535, buffer );
488 ok( (len != 0 && len < MAX_PATH) || broken(!len), /* nt4, win2k, xp */ "GetCurrentDirectoryA failed %u err %u\n", len, GetLastError() );
489 if (len) ok( !strcmp( buffer, origdir ), "wrong result %s\n", buffer );
490 SetLastError( 0xdeadbeef );
491 strcpy( buffer, "foo" );
492 len = GetCurrentDirectoryA( 65536, buffer );
493 ok( (len != 0 && len < MAX_PATH) || broken(!len), /* nt4 */ "GetCurrentDirectoryA failed %u err %u\n", len, GetLastError() );
494 if (len) ok( !strcmp( buffer, origdir ), "wrong result %s\n", buffer );
495 SetLastError( 0xdeadbeef );
496 strcpy( buffer, "foo" );
497 len = GetCurrentDirectoryA( 2 * 65536, buffer );
498 ok( (len != 0 && len < MAX_PATH) || broken(!len), /* nt4 */ "GetCurrentDirectoryA failed %u err %u\n", len, GetLastError() );
499 if (len) ok( !strcmp( buffer, origdir ), "wrong result %s\n", buffer );
500 HeapFree( GetProcessHeap(), 0, buffer );
502 /* Check for crash prevention on swapped args. Crashes all but Win9x.
504 if (0)
506 GetCurrentDirectoryA( 42, (LPSTR)(MAX_PATH + 42) );
509 /* SetCurrentDirectoryA shouldn't care whether the string has a
510 trailing '\\' or not
512 sprintf(tmpstr,"%s\\",newdir);
513 test_setdir(origdir,tmpstr,newdir,1,"check 1");
514 test_setdir(origdir,newdir,NULL,1,"check 2");
515 /* Set the directory to the working area. We just tested that this works,
516 so why check it again.
518 SetCurrentDirectoryA(newdir);
519 /* Check that SetCurrentDirectory fails when a nonexistent dir is specified */
520 sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_SHORT);
521 test_setdir(newdir,tmpstr,NULL,0,"check 3");
522 /* Check that SetCurrentDirectory fails for a nonexistent lond directory */
523 sprintf(tmpstr,"%s\\%s\\%s",newdir,SHORTDIR,NONDIR_LONG);
524 test_setdir(newdir,tmpstr,NULL,0,"check 4");
525 /* Check that SetCurrentDirectory passes with a long directory */
526 sprintf(tmpstr,"%s\\%s",newdir,LONGDIR);
527 test_setdir(newdir,tmpstr,NULL,1,"check 5");
528 /* Check that SetCurrentDirectory passes with a short relative directory */
529 sprintf(tmpstr,"%s",SHORTDIR);
530 sprintf(tmpstr1,"%s\\%s",newdir,SHORTDIR);
531 test_setdir(newdir,tmpstr,tmpstr1,1,"check 6");
532 /* starting with a '.' */
533 sprintf(tmpstr,".\\%s",SHORTDIR);
534 test_setdir(newdir,tmpstr,tmpstr1,1,"check 7");
535 /* Check that SetCurrentDirectory passes with a short relative directory */
536 sprintf(tmpstr,"%s",LONGDIR);
537 sprintf(tmpstr1,"%s\\%s",newdir,LONGDIR);
538 test_setdir(newdir,tmpstr,tmpstr1,1,"check 8");
539 /* starting with a '.' */
540 sprintf(tmpstr,".\\%s",LONGDIR);
541 test_setdir(newdir,tmpstr,tmpstr1,1,"check 9");
542 /* change to root without a trailing backslash. The function call succeeds
543 but the directory is not changed.
545 sprintf(tmpstr, "%c:", newdir[0]);
546 test_setdir(newdir,tmpstr,newdir,1,"check 10");
547 /* works however with a trailing backslash */
548 sprintf(tmpstr, "%c:\\", newdir[0]);
549 test_setdir(newdir,tmpstr,NULL,1,"check 11");
552 /* Cleanup the mess we made while executing these tests */
553 static void test_CleanupPathA(CHAR *origdir, CHAR *curdir)
555 CHAR tmpstr[MAX_PATH];
556 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
557 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
558 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,LONGFILE);
559 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
560 sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,SHORTFILE);
561 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
562 sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
563 ok(DeleteFileA(tmpstr),"DeleteFileA failed\n");
564 sprintf(tmpstr,"%s\\%s",curdir,SHORTDIR);
565 ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
566 sprintf(tmpstr,"%s\\%s",curdir,LONGDIR);
567 ok(RemoveDirectoryA(tmpstr),"RemoveDirectoryA failed\n");
568 ok(SetCurrentDirectoryA(origdir),"SetCurrentDirectoryA failed\n");
569 ok(RemoveDirectoryA(curdir),"RemoveDirectoryA failed\n");
572 /* test that short path name functions work regardless of case */
573 static void test_ShortPathCase(const char *tmpdir, const char *dirname,
574 const char *filename)
576 char buf[MAX_PATH], shortbuf[MAX_PATH];
577 HANDLE hndl;
578 size_t i;
580 assert(strlen(tmpdir) + strlen(dirname) + strlen(filename) + 2 < sizeof(buf));
581 sprintf(buf,"%s\\%s\\%s",tmpdir,dirname,filename);
582 GetShortPathNameA(buf,shortbuf,sizeof(shortbuf));
583 hndl = CreateFileA(shortbuf,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
584 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed (%d)\n",GetLastError());
585 CloseHandle(hndl);
586 /* Now for the real test */
587 for(i=0;i<strlen(shortbuf);i++)
588 if (i % 2)
589 shortbuf[i] = tolower(shortbuf[i]);
590 hndl = CreateFileA(shortbuf,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
591 ok(hndl!=INVALID_HANDLE_VALUE,"CreateFileA failed (%d)\n",GetLastError());
592 CloseHandle(hndl);
595 /* This routine will test Get(Full|Short|Long)PathNameA */
596 static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive)
598 CHAR curdir_short[MAX_PATH],
599 longdir_short[MAX_PATH];
600 CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH],tmpstr2[MAX_PATH];
601 LPSTR strptr; /*ptr to the filename portion of the path */
602 DWORD len;
603 INT i;
604 CHAR dir[MAX_PATH],eight[MAX_PATH],three[MAX_PATH];
605 SLpassfail passfail;
607 /* Get the short form of the current directory */
608 ok((len=GetShortPathNameA(curdir,curdir_short,MAX_PATH)),
609 "GetShortPathNameA failed\n");
610 ok(!HAS_TRAIL_SLASH_A(curdir_short),
611 "GetShortPathNameA should not have a trailing \\\n");
612 /* Get the short form of the absolute-path to LONGDIR */
613 sprintf(tmpstr,"%s\\%s",curdir_short,LONGDIR);
614 ok((len=GetShortPathNameA(tmpstr,longdir_short,MAX_PATH)),
615 "GetShortPathNameA failed\n");
616 ok(lstrcmpiA(longdir_short+(len-1),"\\")!=0,
617 "GetShortPathNameA should not have a trailing \\\n");
619 if (pGetLongPathNameA) {
620 DWORD rc1,rc2;
621 sprintf(tmpstr,"%s\\%s\\%s",curdir,LONGDIR,LONGFILE);
622 rc1=(*pGetLongPathNameA)(tmpstr,NULL,0);
623 rc2=(*pGetLongPathNameA)(curdir,NULL,0);
624 ok((rc1-strlen(tmpstr))==(rc2-strlen(curdir)),
625 "GetLongPathNameA: wrong return code, %d instead of %d\n",
626 rc1, lstrlenA(tmpstr)+1);
628 sprintf(dir,"%c:",curDrive);
629 rc1=(*pGetLongPathNameA)(dir,tmpstr,sizeof(tmpstr));
630 ok(strcmp(dir,tmpstr)==0,
631 "GetLongPathNameA: returned '%s' instead of '%s' (rc=%d)\n",
632 tmpstr,dir,rc1);
635 /* Check the cases where both file and directory exist first */
636 /* Start with a 8.3 directory, 8.3 filename */
637 test_ValidPathA(curdir,SHORTDIR,SHORTFILE,tmpstr,NULL,"test1");
638 sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,SHORTFILE);
639 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
640 "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
641 /* Now try a 8.3 directory, long file name */
642 test_ValidPathA(curdir,SHORTDIR,LONGFILE,tmpstr,NULL,"test2");
643 sprintf(tmpstr1,"%s\\%s",curdir_short,SHORTDIR);
644 test_LongtoShortA(tmpstr,tmpstr1,"PAT","test2");
645 /* Next is a long directory, 8.3 file */
646 test_ValidPathA(curdir,LONGDIR,SHORTFILE,tmpstr,NULL,"test3");
647 sprintf(tmpstr1,"%s\\%s",longdir_short,SHORTFILE);
648 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
649 "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr,tmpstr1);
650 /*Lastly a long directory, long file */
651 test_ValidPathA(curdir,LONGDIR,LONGFILE,tmpstr,NULL,"test4");
652 test_LongtoShortA(tmpstr,longdir_short,"PAT","test4");
654 /* Now check all of the invalid file w/ valid directory combinations */
655 /* Start with a 8.3 directory, 8.3 filename */
656 test_ValidPathA(curdir,SHORTDIR,NONFILE_SHORT,tmpstr,&passfail,"test5");
657 sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,SHORTDIR,NONFILE_SHORT);
658 ok((passfail.shortlen==0 &&
659 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
660 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
661 (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
662 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
663 passfail.shortlen,passfail.shorterror,tmpstr);
664 if(pGetLongPathNameA) {
665 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
666 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
667 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
669 /* Now try a 8.3 directory, long file name */
670 test_ValidPathA(curdir,SHORTDIR,NONFILE_LONG,tmpstr,&passfail,"test6");
671 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
672 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
673 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
674 !passfail.shorterror,
675 "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
676 if(pGetLongPathNameA) {
677 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
678 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
679 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
681 /* Next is a long directory, 8.3 file */
682 test_ValidPathA(curdir,LONGDIR,NONFILE_SHORT,tmpstr,&passfail,"test7");
683 sprintf(tmpstr2,"%s\\%s",curdir_short,LONGDIR);
684 GetShortPathNameA(tmpstr2,tmpstr1,MAX_PATH);
685 strcat(tmpstr1,"\\" NONFILE_SHORT);
686 ok((passfail.shortlen==0 &&
687 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
688 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
689 (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
690 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
691 passfail.shortlen,passfail.shorterror,tmpstr);
692 if(pGetLongPathNameA) {
693 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
694 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
695 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
697 /*Lastly a long directory, long file */
698 test_ValidPathA(curdir,LONGDIR,NONFILE_LONG,tmpstr,&passfail,"test8");
699 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
700 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
701 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
702 !passfail.shorterror,
703 "GetShortPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
704 if(pGetLongPathNameA) {
705 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
706 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
707 "GetlongPathA should have returned 'ERROR_FILE_NOT_FOUND'\n");
709 /* Now try again with directories that don't exist */
710 /* 8.3 directory, 8.3 filename */
711 test_ValidPathA(curdir,NONDIR_SHORT,SHORTFILE,tmpstr,&passfail,"test9");
712 sprintf(tmpstr1,"%s\\%s\\%s",curdir_short,NONDIR_SHORT,SHORTFILE);
713 ok((passfail.shortlen==0 &&
714 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
715 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
716 (passfail.shortlen==strlen(tmpstr1) && lstrcmpiA(tmpstr,tmpstr1)==0),
717 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
718 passfail.shortlen,passfail.shorterror,tmpstr);
719 if(pGetLongPathNameA) {
720 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
721 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
722 passfail.longerror==ERROR_FILE_NOT_FOUND,
723 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
724 passfail.longerror);
726 /* Now try a 8.3 directory, long file name */
727 test_ValidPathA(curdir,NONDIR_SHORT,LONGFILE,tmpstr,&passfail,"test10");
728 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
729 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
730 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
731 !passfail.shorterror,
732 "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
733 passfail.shorterror);
734 if(pGetLongPathNameA) {
735 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
736 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
737 passfail.longerror==ERROR_FILE_NOT_FOUND,
738 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
739 passfail.longerror);
741 /* Next is a long directory, 8.3 file */
742 test_ValidPathA(curdir,NONDIR_LONG,SHORTFILE,tmpstr,&passfail,"test11");
743 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
744 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
745 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
746 !passfail.shorterror,
747 "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
748 passfail.shorterror);
749 if(pGetLongPathNameA) {
750 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
751 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
752 passfail.longerror==ERROR_FILE_NOT_FOUND,
753 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
754 passfail.longerror);
756 /*Lastly a long directory, long file */
757 test_ValidPathA(curdir,NONDIR_LONG,LONGFILE,tmpstr,&passfail,"test12");
758 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
759 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
760 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
761 !passfail.shorterror,
762 "GetShortPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
763 passfail.shorterror);
764 if(pGetLongPathNameA) {
765 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
766 ok(passfail.longerror==ERROR_PATH_NOT_FOUND ||
767 passfail.longerror==ERROR_FILE_NOT_FOUND,
768 "GetLongPathA returned %d and not 'ERROR_PATH_NOT_FOUND'\n",
769 passfail.longerror);
771 /* Next try directories ending with '\\' */
772 /* Existing Directories */
773 sprintf(tmpstr,"%s\\",SHORTDIR);
774 test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test13");
775 sprintf(tmpstr,"%s\\",LONGDIR);
776 test_ValidPathA(curdir,"",tmpstr,tmpstr1,NULL,"test14");
777 /* Nonexistent directories */
778 sprintf(tmpstr,"%s\\",NONDIR_SHORT);
779 test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test15");
780 sprintf(tmpstr2,"%s\\%s",curdir_short,tmpstr);
781 ok((passfail.shortlen==0 &&
782 (passfail.shorterror==ERROR_PATH_NOT_FOUND ||
783 passfail.shorterror==ERROR_FILE_NOT_FOUND)) ||
784 (passfail.shortlen==strlen(tmpstr2) && lstrcmpiA(tmpstr1,tmpstr2)==0),
785 "GetShortPathNameA error: len=%d error=%d tmpstr=[%s]\n",
786 passfail.shortlen,passfail.shorterror,tmpstr);
787 if(pGetLongPathNameA) {
788 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
789 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
790 "GetLongPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
791 passfail.longerror);
793 sprintf(tmpstr,"%s\\",NONDIR_LONG);
794 test_ValidPathA(curdir,"",tmpstr,tmpstr1,&passfail,"test16");
795 ok(passfail.shortlen==0,"GetShortPathNameA passed when it shouldn't have\n");
796 ok(passfail.shorterror==ERROR_PATH_NOT_FOUND ||
797 passfail.shorterror==ERROR_FILE_NOT_FOUND ||
798 !passfail.shorterror,
799 "GetShortPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
800 passfail.shorterror);
801 if(pGetLongPathNameA) {
802 ok(passfail.longlen==0,"GetLongPathNameA passed when it shouldn't have\n");
803 ok(passfail.longerror==ERROR_FILE_NOT_FOUND,
804 "GetLongPathA returned %d and not 'ERROR_FILE_NOT_FOUND'\n",
805 passfail.longerror);
807 /* Test GetFullPathNameA with drive letters */
808 if( curDrive != NOT_A_VALID_DRIVE) {
809 sprintf(tmpstr,"%c:",curdir[0]);
810 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr2,&strptr),
811 "GetFullPathNameA(%c:) failed\n", curdir[0]);
812 GetCurrentDirectoryA(MAX_PATH,tmpstr);
813 sprintf(tmpstr1,"%s\\",tmpstr);
814 ok(lstrcmpiA(tmpstr,tmpstr2)==0 || lstrcmpiA(tmpstr1,tmpstr2)==0,
815 "GetFullPathNameA(%c:) returned '%s' instead of '%s' or '%s'\n",
816 curdir[0],tmpstr2,tmpstr,tmpstr1);
818 sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
819 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
820 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
821 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
822 ok(lstrcmpiA(SHORTFILE,strptr)==0,
823 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
825 /* Without a leading slash, insert the current directory if on the current drive */
826 sprintf(tmpstr,"%c:%s\\%s",curdir[0],SHORTDIR,SHORTFILE);
827 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
828 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
829 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
830 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
831 ok(lstrcmpiA(SHORTFILE,strptr)==0,
832 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
833 /* Otherwise insert the missing leading slash */
834 if( otherDrive != NOT_A_VALID_DRIVE) {
835 /* FIXME: this test assumes that current directory on other drive is root */
836 sprintf(tmpstr,"%c:%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
837 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed for %s\n", tmpstr);
838 sprintf(tmpstr,"%c:\\%s\\%s",otherDrive,SHORTDIR,SHORTFILE);
839 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
840 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
841 ok(lstrcmpiA(SHORTFILE,strptr)==0,
842 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
844 /* Xilinx tools like to mix Unix and DOS formats, which Windows handles fine.
845 So test for them. */
846 if( curDrive != NOT_A_VALID_DRIVE) {
847 sprintf(tmpstr,"%c:/%s\\%s",curDrive,SHORTDIR,SHORTFILE);
848 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
849 sprintf(tmpstr,"%c:\\%s\\%s",curDrive,SHORTDIR,SHORTFILE);
850 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
851 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
852 ok(lstrcmpiA(SHORTFILE,strptr)==0,
853 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
855 /* Don't Starve relies on GetLongPathName returning the passed in filename,
856 even if the actual file on disk has a different case or separator */
857 if (pGetLongPathNameA) {
858 int len = lstrlenA(LONGDIR) + 1;
859 sprintf(tmpstr,"%s/%s",LONGDIR,LONGFILE);
860 ok(GetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
861 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
862 "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
863 tmpstr[len] = tolower(tmpstr[len]);
864 ok(GetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
865 ok(lstrcmpA(tmpstr,tmpstr1)==0,
866 "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
867 sprintf(tmpstr,"%s/%s",SHORTDIR,SHORTFILE);
868 ok(GetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
869 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
870 "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
871 len = lstrlenA(SHORTDIR) + 1;
872 tmpstr[len] = toupper(tmpstr[len]);
873 ok(GetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
874 ok(lstrcmpiA(tmpstr,tmpstr1)==0 && lstrcmpA(tmpstr,tmpstr1) != 0,
875 "GetLongPathNameA returned '%s' instead of '%s/%s'\n",tmpstr1,SHORTDIR,SHORTFILE);
877 sprintf(tmpstr,"%s/%s",SHORTDIR,SHORTFILE);
878 ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed\n");
879 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
880 "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
882 /**/
883 sprintf(tmpstr,"%c:%s/%s",curdir[0],SHORTDIR,SHORTFILE);
884 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
885 sprintf(tmpstr,"%s\\%s\\%s",curdir,SHORTDIR,SHORTFILE);
886 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
887 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
888 ok(lstrcmpiA(SHORTFILE,strptr)==0,
889 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
890 /* Windows will insert a drive letter in front of an absolute UNIX path */
891 sprintf(tmpstr,"/%s/%s",SHORTDIR,SHORTFILE);
892 ok(GetFullPathNameA(tmpstr,MAX_PATH,tmpstr1,&strptr),"GetFullPathNameA failed\n");
893 sprintf(tmpstr,"%c:\\%s\\%s",*tmpstr1,SHORTDIR,SHORTFILE);
894 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
895 "GetFullPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
896 /* This passes in Wine because it still contains the pointer from the previous test */
897 ok(lstrcmpiA(SHORTFILE,strptr)==0,
898 "GetFullPathNameA returned part '%s' instead of '%s'\n",strptr,SHORTFILE);
900 /* Now try some relative paths */
901 ok(GetShortPathNameA(LONGDIR,tmpstr,MAX_PATH),"GetShortPathNameA failed\n");
902 test_SplitShortPathA(tmpstr,dir,eight,three);
903 if(pGetLongPathNameA) {
904 ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
905 ok(lstrcmpiA(tmpstr1,LONGDIR)==0,
906 "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,LONGDIR);
908 sprintf(tmpstr,".\\%s",LONGDIR);
909 ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed\n");
910 test_SplitShortPathA(tmpstr1,dir,eight,three);
911 ok(lstrcmpiA(dir,".")==0 || dir[0]=='\0',
912 "GetShortPathNameA did not keep relative directory [%s]\n",tmpstr1);
913 if(pGetLongPathNameA) {
914 ok(pGetLongPathNameA(tmpstr1,tmpstr1,MAX_PATH),"GetLongPathNameA failed %s\n",
915 tmpstr);
916 ok(lstrcmpiA(tmpstr1,tmpstr)==0,
917 "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
919 /* Check out Get*PathNameA on some funny characters */
920 for(i=0;i<lstrlenA(funny_chars);i++) {
921 INT valid;
922 valid=(is_char_ok[i]=='0') ? 0 : 1;
923 sprintf(tmpstr1,"check%d-1",i);
924 sprintf(tmpstr,"file%c000.ext",funny_chars[i]);
925 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
926 sprintf(tmpstr1,"check%d-2",i);
927 sprintf(tmpstr,"file000.e%ct",funny_chars[i]);
928 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
929 sprintf(tmpstr1,"check%d-3",i);
930 sprintf(tmpstr,"%cfile000.ext",funny_chars[i]);
931 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
932 sprintf(tmpstr1,"check%d-4",i);
933 sprintf(tmpstr,"file000%c.ext",funny_chars[i]);
934 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
935 sprintf(tmpstr1,"check%d-5",i);
936 sprintf(tmpstr,"Long %c File",funny_chars[i]);
937 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
938 sprintf(tmpstr1,"check%d-6",i);
939 sprintf(tmpstr,"%c Long File",funny_chars[i]);
940 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
941 sprintf(tmpstr1,"check%d-7",i);
942 sprintf(tmpstr,"Long File %c",funny_chars[i]);
943 test_FunnyChars(curdir,curdir_short,tmpstr,valid,tmpstr1);
945 /* Now try it on mixed case short names */
946 test_ShortPathCase(curdir,SHORTDIR,LONGFILE);
947 test_ShortPathCase(curdir,LONGDIR,SHORTFILE);
948 test_ShortPathCase(curdir,LONGDIR,LONGFILE);
950 /* test double delimiters */
951 sprintf(tmpstr,"%s\\\\%s", SHORTDIR,SHORTFILE);
952 ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed\n");
953 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
954 "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
955 sprintf(tmpstr,".\\\\%s\\\\%s", SHORTDIR,SHORTFILE);
956 ok(GetShortPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetShortPathNameA failed\n");
957 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
958 "GetShortPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
960 if (pGetLongPathNameA) {
961 sprintf(tmpstr,"%s\\\\%s",LONGDIR,LONGFILE);
962 ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
963 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
964 "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
966 sprintf(tmpstr,".\\\\%s\\\\%s",LONGDIR,LONGFILE);
967 ok(pGetLongPathNameA(tmpstr,tmpstr1,MAX_PATH),"GetLongPathNameA failed\n");
968 ok(lstrcmpiA(tmpstr,tmpstr1)==0,
969 "GetLongPathNameA returned '%s' instead of '%s'\n",tmpstr1,tmpstr);
973 static void test_GetTempPathA(char* tmp_dir)
975 DWORD len, slen, len_with_null;
976 char buf[MAX_PATH];
978 len_with_null = strlen(tmp_dir) + 1;
980 lstrcpyA(buf, "foo");
981 len = GetTempPathA(MAX_PATH, buf);
982 ok(len <= MAX_PATH, "should fit into MAX_PATH\n");
983 ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
984 ok(len == strlen(buf), "returned length should be equal to the length of string\n");
986 /* Some versions of Windows touch the buffer, some don't so we don't
987 * test that. Also, NT sometimes exaggerates the required buffer size
988 * so we cannot test for an exact match. Finally, the
989 * 'len_with_null - 1' case is so buggy on Windows it's not testable.
990 * For instance in some cases Win98 returns len_with_null - 1 instead
991 * of len_with_null.
993 len = GetTempPathA(1, buf);
994 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
996 len = GetTempPathA(0, NULL);
997 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
999 /* The call above gave us the buffer size that Windows thinks is needed
1000 * so the next call should work
1002 lstrcpyA(buf, "foo");
1003 len = GetTempPathA(len, buf);
1004 ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
1005 ok(len == strlen(buf), "returned length should be equal to the length of string\n");
1007 memset(buf, 'a', sizeof(buf));
1008 len = GetTempPathA(sizeof(buf), buf);
1009 ok(lstrcmpiA(buf, tmp_dir) == 0, "expected [%s], got [%s]\n",tmp_dir,buf);
1010 ok(len == strlen(buf), "returned length should be equal to the length of string\n");
1011 /* The rest of the buffer remains untouched */
1012 slen = len + 1;
1013 for(len++; len < sizeof(buf); len++)
1014 ok(buf[len] == 'a', "expected 'a' at [%d], got 0x%x\n", len, buf[len]);
1016 /* When the buffer is not long enough it remains untouched */
1017 memset(buf, 'a', sizeof(buf));
1018 len = GetTempPathA(slen / 2, buf);
1019 ok(len == slen || broken(len == slen + 1) /* read the big comment above */ ,
1020 "expected %d, got %d\n", slen, len);
1021 for(len = 0; len < ARRAY_SIZE(buf); len++)
1022 ok(buf[len] == 'a', "expected 'a' at [%d], got 0x%x\n", len, buf[len]);
1025 static void test_GetTempPathW(char* tmp_dir)
1027 DWORD len, slen, len_with_null;
1028 WCHAR buf[MAX_PATH], *long_buf;
1029 WCHAR tmp_dirW[MAX_PATH];
1030 static const WCHAR fooW[] = {'f','o','o',0};
1032 MultiByteToWideChar(CP_ACP, 0, tmp_dir, -1, tmp_dirW, ARRAY_SIZE(tmp_dirW));
1033 len_with_null = lstrlenW(tmp_dirW) + 1;
1035 /* This one is different from ANSI version: ANSI version doesn't
1036 * touch the buffer, unicode version usually truncates the buffer
1037 * to zero size. NT still exaggerates the required buffer size
1038 * sometimes so we cannot test for an exact match. Finally, the
1039 * 'len_with_null - 1' case is so buggy on Windows it's not testable.
1040 * For instance on NT4 it will sometimes return a path without the
1041 * trailing '\\' and sometimes return an error.
1044 lstrcpyW(buf, fooW);
1045 len = GetTempPathW(MAX_PATH, buf);
1046 if (len == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1048 win_skip("GetTempPathW is not available\n");
1049 return;
1051 ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
1052 ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
1054 lstrcpyW(buf, fooW);
1055 len = GetTempPathW(1, buf);
1056 ok(buf[0] == 0, "unicode version should truncate the buffer to zero size\n");
1057 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
1059 len = GetTempPathW(0, NULL);
1060 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len);
1062 lstrcpyW(buf, fooW);
1063 len = GetTempPathW(len, buf);
1064 ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
1065 ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
1067 for(len = 0; len < ARRAY_SIZE(buf); len++)
1068 buf[len] = 'a';
1069 len = GetTempPathW(len, buf);
1070 ok(lstrcmpiW(buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
1071 ok(len == lstrlenW(buf), "returned length should be equal to the length of string\n");
1072 /* The rest of the buffer must be zeroed */
1073 slen = len + 1;
1074 for(len++; len < ARRAY_SIZE(buf); len++)
1075 ok(buf[len] == '\0', "expected NULL at [%d], got 0x%x\n", len, buf[len]);
1077 /* When the buffer is not long enough the length passed is zeroed */
1078 for(len = 0; len < ARRAY_SIZE(buf); len++)
1079 buf[len] = 'a';
1080 len = GetTempPathW(slen / 2, buf);
1081 ok(len == slen || broken(len == slen + 1) /* read the big comment above */ ,
1082 "expected %d, got %d\n", slen, len);
1085 /* In Windows 8 when TMP var points to a drive only (like C:) instead of a
1086 * full directory the behavior changes. It will start filling the path but
1087 * will later truncate the buffer before returning. So the generic test
1088 * below will fail for this Windows 8 corner case.
1090 char tmp_var[64];
1091 DWORD version = GetVersion();
1092 GetEnvironmentVariableA("TMP", tmp_var, sizeof(tmp_var));
1093 if (strlen(tmp_var) == 2 && version >= 0x00060002)
1094 return;
1097 for(len = 0; len < slen / 2; len++)
1098 ok(buf[len] == '\0', "expected NULL at [%d], got 0x%x\n", len, buf[len]);
1099 for(; len < ARRAY_SIZE(buf); len++)
1100 ok(buf[len] == 'a', "expected 'a' at [%d], got 0x%x\n", len, buf[len]);
1102 /* bogus application from bug 38220 passes the count value in sizeof(buffer)
1103 * instead the correct count of WCHAR, this test catches this case. */
1104 slen = 65534;
1105 long_buf = HeapAlloc(GetProcessHeap(), 0, slen * sizeof(WCHAR));
1106 if (!long_buf)
1108 skip("Could not allocate memory for the test\n");
1109 return;
1111 for(len = 0; len < slen; len++)
1112 long_buf[len] = 0xCC;
1113 len = GetTempPathW(slen, long_buf);
1114 ok(lstrcmpiW(long_buf, tmp_dirW) == 0, "GetTempPathW returned an incorrect temporary path\n");
1115 ok(len == lstrlenW(long_buf), "returned length should be equal to the length of string\n");
1116 /* the remaining buffer must be zeroed up to different values in different OS versions.
1117 * <= XP - 32766
1118 * > XP - 32767
1119 * to simplify testing we will test only until XP.
1121 for(; len < 32767; len++)
1122 ok(long_buf[len] == '\0', "expected NULL at [%d], got 0x%x\n", len, long_buf[len]);
1123 /* we will know skip the test that is in the middle of the OS difference by
1124 * incrementing len and then resume the test for the untouched part. */
1125 for(len++; len < slen; len++)
1126 ok(long_buf[len] == 0xcc, "expected 0xcc at [%d], got 0x%x\n", len, long_buf[len]);
1128 HeapFree(GetProcessHeap(), 0, long_buf);
1131 static void test_GetTempPath(void)
1133 char save_TMP[MAX_PATH];
1134 char windir[MAX_PATH];
1135 char buf[MAX_PATH];
1136 WCHAR curdir[MAX_PATH];
1138 if (!GetEnvironmentVariableA("TMP", save_TMP, sizeof(save_TMP))) save_TMP[0] = 0;
1140 /* test default configuration */
1141 trace("TMP=%s\n", save_TMP);
1142 if (save_TMP[0])
1144 strcpy(buf,save_TMP);
1145 if (buf[strlen(buf)-1]!='\\')
1146 strcat(buf,"\\");
1147 test_GetTempPathA(buf);
1148 test_GetTempPathW(buf);
1151 /* TMP=C:\WINDOWS */
1152 GetWindowsDirectoryA(windir, sizeof(windir));
1153 SetEnvironmentVariableA("TMP", windir);
1154 GetEnvironmentVariableA("TMP", buf, sizeof(buf));
1155 trace("TMP=%s\n", buf);
1156 strcat(windir,"\\");
1157 test_GetTempPathA(windir);
1158 test_GetTempPathW(windir);
1160 /* TMP=C:\ */
1161 GetWindowsDirectoryA(windir, sizeof(windir));
1162 windir[3] = 0;
1163 SetEnvironmentVariableA("TMP", windir);
1164 GetEnvironmentVariableA("TMP", buf, sizeof(buf));
1165 trace("TMP=%s\n", buf);
1166 test_GetTempPathA(windir);
1167 test_GetTempPathW(windir);
1169 GetCurrentDirectoryW(MAX_PATH, curdir);
1170 /* TMP=C: i.e. use current working directory of the specified drive */
1171 GetWindowsDirectoryA(windir, sizeof(windir));
1172 SetCurrentDirectoryA(windir);
1173 windir[2] = 0;
1174 SetEnvironmentVariableA("TMP", windir);
1175 GetEnvironmentVariableA("TMP", buf, sizeof(buf));
1176 trace("TMP=%s\n", buf);
1177 GetWindowsDirectoryA(windir, sizeof(windir));
1178 strcat(windir,"\\");
1179 test_GetTempPathA(windir);
1180 test_GetTempPathW(windir);
1182 SetEnvironmentVariableA("TMP", save_TMP);
1183 SetCurrentDirectoryW(curdir);
1186 static void test_GetLongPathNameA(void)
1188 DWORD length, explength, hostsize;
1189 char tempfile[MAX_PATH], *name;
1190 char longpath[MAX_PATH];
1191 char unc_prefix[MAX_PATH];
1192 char unc_short[MAX_PATH], unc_long[MAX_PATH];
1193 char temppath[MAX_PATH], temppath2[MAX_PATH];
1194 HANDLE file;
1196 if (!pGetLongPathNameA)
1197 return;
1199 GetTempPathA(MAX_PATH, tempfile);
1200 name = tempfile + strlen(tempfile);
1202 strcpy(name, "*");
1203 SetLastError(0xdeadbeef);
1204 length = pGetLongPathNameA(tempfile, temppath, MAX_PATH);
1205 ok(!length, "GetLongPathNameA should fail\n");
1206 ok(GetLastError() == ERROR_INVALID_NAME, "wrong error %d\n", GetLastError());
1208 strcpy(name, "longfilename.longext");
1210 file = CreateFileA(tempfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1211 CloseHandle(file);
1213 /* Test a normal path with a small buffer size */
1214 memset(temppath, 0, MAX_PATH);
1215 length = pGetLongPathNameA(tempfile, temppath, 4);
1216 /* We have a failure so length should be the minimum plus the terminating '0' */
1217 ok(length >= strlen(tempfile) + 1, "Wrong length\n");
1218 ok(temppath[0] == 0, "Buffer should not have been touched\n");
1220 /* Some UNC syntax tests */
1222 memset(temppath, 0, MAX_PATH);
1223 memset(temppath2, 0, MAX_PATH);
1224 lstrcpyA(temppath2, "\\\\?\\");
1225 lstrcatA(temppath2, tempfile);
1226 explength = length + 4;
1228 SetLastError(0xdeadbeef);
1229 length = pGetLongPathNameA(temppath2, NULL, 0);
1230 if (length == 0 && GetLastError() == ERROR_BAD_NET_NAME)
1232 win_skip("UNC syntax tests don't work on Win98/WinMe\n");
1233 DeleteFileA(tempfile);
1234 return;
1236 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1238 length = pGetLongPathNameA(temppath2, NULL, MAX_PATH);
1239 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1241 length = pGetLongPathNameA(temppath2, temppath, 4);
1242 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1243 ok(temppath[0] == 0, "Buffer should not have been touched\n");
1245 /* Now an UNC path with the computername */
1246 lstrcpyA(unc_prefix, "\\\\");
1247 hostsize = sizeof(unc_prefix) - 2;
1248 GetComputerNameA(unc_prefix + 2, &hostsize);
1249 lstrcatA(unc_prefix, "\\");
1251 /* Create a short syntax for the whole unc path */
1252 memset(unc_short, 0, MAX_PATH);
1253 GetShortPathNameA(tempfile, temppath, MAX_PATH);
1254 lstrcpyA(unc_short, unc_prefix);
1255 unc_short[lstrlenA(unc_short)] = temppath[0];
1256 lstrcatA(unc_short, "$\\");
1257 lstrcatA(unc_short, strchr(temppath, '\\') + 1);
1259 /* Create a long syntax for reference */
1260 memset(longpath, 0, MAX_PATH);
1261 pGetLongPathNameA(tempfile, temppath, MAX_PATH);
1262 lstrcpyA(longpath, unc_prefix);
1263 longpath[lstrlenA(longpath)] = temppath[0];
1264 lstrcatA(longpath, "$\\");
1265 lstrcatA(longpath, strchr(temppath, '\\') + 1);
1267 /* NULL test */
1268 SetLastError(0xdeadbeef);
1269 length = pGetLongPathNameA(unc_short, NULL, 0);
1270 if (length == 0 && GetLastError() == ERROR_BAD_NETPATH)
1272 /* Seen on Window XP Home */
1273 win_skip("UNC with computername is not supported\n");
1274 DeleteFileA(tempfile);
1275 return;
1277 explength = lstrlenA(longpath) + 1;
1278 todo_wine
1279 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1281 length = pGetLongPathNameA(unc_short, NULL, MAX_PATH);
1282 todo_wine
1283 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1285 memset(unc_long, 0, MAX_PATH);
1286 length = pGetLongPathNameA(unc_short, unc_long, lstrlenA(unc_short));
1287 /* length will include terminating '0' on failure */
1288 todo_wine
1289 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1290 ok(unc_long[0] == 0, "Buffer should not have been touched\n");
1292 memset(unc_long, 0, MAX_PATH);
1293 length = pGetLongPathNameA(unc_short, unc_long, length);
1294 /* length doesn't include terminating '0' on success */
1295 explength--;
1296 todo_wine
1298 ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
1299 ok(!lstrcmpiA(unc_long, longpath), "Expected (%s), got (%s)\n", longpath, unc_long);
1302 DeleteFileA(tempfile);
1305 static void test_GetLongPathNameW(void)
1307 DWORD length, expanded;
1308 BOOL ret;
1309 HANDLE file;
1310 WCHAR empty[MAX_PATH];
1311 WCHAR tempdir[MAX_PATH], name[200];
1312 WCHAR dirpath[4 + MAX_PATH + 200]; /* To ease removal */
1313 WCHAR shortpath[4 + MAX_PATH + 200 + 1 + 200];
1314 static const WCHAR prefix[] = { '\\','\\','?','\\', 0};
1315 static const WCHAR backslash[] = { '\\', 0};
1316 static const WCHAR letterX[] = { 'X', 0};
1318 if (!pGetLongPathNameW)
1319 return;
1321 SetLastError(0xdeadbeef);
1322 length = pGetLongPathNameW(NULL,NULL,0);
1323 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1325 win_skip("GetLongPathNameW is not implemented\n");
1326 return;
1328 ok(0==length,"GetLongPathNameW returned %d but expected 0\n",length);
1329 ok(GetLastError()==ERROR_INVALID_PARAMETER,"GetLastError returned %d but expected ERROR_INVALID_PARAMETER\n",GetLastError());
1331 SetLastError(0xdeadbeef);
1332 empty[0]=0;
1333 length = pGetLongPathNameW(empty,NULL,0);
1334 ok(0==length,"GetLongPathNameW returned %d but expected 0\n",length);
1335 ok(GetLastError()==ERROR_PATH_NOT_FOUND,"GetLastError returned %d but expected ERROR_PATH_NOT_FOUND\n",GetLastError());
1337 /* Create a long path name. The path needs to exist for these tests to
1338 * succeed so we need the "\\?\" prefix when creating directories and
1339 * files.
1341 name[0] = 0;
1342 while (lstrlenW(name) < (ARRAY_SIZE(name) - 1))
1343 lstrcatW(name, letterX);
1345 GetTempPathW(MAX_PATH, tempdir);
1347 lstrcpyW(shortpath, prefix);
1348 lstrcatW(shortpath, tempdir);
1349 lstrcatW(shortpath, name);
1350 lstrcpyW(dirpath, shortpath);
1351 ret = CreateDirectoryW(shortpath, NULL);
1352 ok(ret, "Could not create the temporary directory : %d\n", GetLastError());
1353 lstrcatW(shortpath, backslash);
1354 lstrcatW(shortpath, name);
1356 /* Path does not exist yet and we know it overruns MAX_PATH */
1358 /* No prefix */
1359 SetLastError(0xdeadbeef);
1360 length = pGetLongPathNameW(shortpath + 4, NULL, 0);
1361 ok(length == 0, "Expected 0, got %d\n", length);
1362 todo_wine
1363 ok(GetLastError() == ERROR_PATH_NOT_FOUND,
1364 "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
1365 /* With prefix */
1366 SetLastError(0xdeadbeef);
1367 length = pGetLongPathNameW(shortpath, NULL, 0);
1368 todo_wine
1370 ok(length == 0, "Expected 0, got %d\n", length);
1371 ok(GetLastError() == ERROR_FILE_NOT_FOUND,
1372 "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
1375 file = CreateFileW(shortpath, GENERIC_READ|GENERIC_WRITE, 0, NULL,
1376 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1377 ok(file != INVALID_HANDLE_VALUE,
1378 "Could not create the temporary file : %d.\n", GetLastError());
1379 CloseHandle(file);
1381 /* Path exists */
1383 /* No prefix */
1384 SetLastError(0xdeadbeef);
1385 length = pGetLongPathNameW(shortpath + 4, NULL, 0);
1386 todo_wine
1388 ok(length == 0, "Expected 0, got %d\n", length);
1389 ok(GetLastError() == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
1391 /* With prefix */
1392 expanded = 4 + (pGetLongPathNameW(tempdir, NULL, 0) - 1) + lstrlenW(name) + 1 + lstrlenW(name) + 1;
1393 SetLastError(0xdeadbeef);
1394 length = pGetLongPathNameW(shortpath, NULL, 0);
1395 ok(length == expanded, "Expected %d, got %d\n", expanded, length);
1397 /* NULL buffer with length crashes on Windows */
1398 if (0)
1399 pGetLongPathNameW(shortpath, NULL, 20);
1401 ok(DeleteFileW(shortpath), "Could not delete temporary file\n");
1402 ok(RemoveDirectoryW(dirpath), "Could not delete temporary directory\n");
1405 static void test_GetShortPathNameW(void)
1407 static const WCHAR extended_prefix[] = {'\\','\\','?','\\',0};
1408 static const WCHAR test_path[] = { 'L', 'o', 'n', 'g', 'D', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 'N', 'a', 'm', 'e', 0 };
1409 static const WCHAR name[] = { 't', 'e', 's', 't', 0 };
1410 static const WCHAR backSlash[] = { '\\', 0 };
1411 static const WCHAR a_bcdeW[] = {'a','.','b','c','d','e',0};
1412 static const WCHAR wildW[] = { '*',0 };
1413 WCHAR path[MAX_PATH], tmppath[MAX_PATH], *ptr;
1414 WCHAR short_path[MAX_PATH];
1415 DWORD length;
1416 HANDLE file;
1417 int ret;
1419 SetLastError(0xdeadbeef);
1420 GetTempPathW( MAX_PATH, tmppath );
1421 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1423 win_skip("GetTempPathW is not implemented\n");
1424 return;
1427 lstrcpyW( path, tmppath );
1428 lstrcatW( path, test_path );
1429 lstrcatW( path, backSlash );
1430 ret = CreateDirectoryW( path, NULL );
1431 ok( ret, "Directory was not created. LastError = %d\n", GetLastError() );
1433 /* Starting a main part of test */
1435 /* extended path \\?\C:\path\ */
1436 lstrcpyW( path, extended_prefix );
1437 lstrcatW( path, tmppath );
1438 lstrcatW( path, test_path );
1439 lstrcatW( path, backSlash );
1440 short_path[0] = 0;
1441 length = GetShortPathNameW( path, short_path, ARRAY_SIZE( short_path ));
1442 ok( length, "GetShortPathNameW returned 0.\n" );
1444 lstrcpyW( path, tmppath );
1445 lstrcatW( path, test_path );
1446 lstrcatW( path, backSlash );
1447 length = GetShortPathNameW( path, short_path, 0 );
1448 ok( length, "GetShortPathNameW returned 0.\n" );
1449 ret = GetShortPathNameW( path, short_path, length );
1450 ok( ret && ret == length-1, "GetShortPathNameW returned 0.\n" );
1452 lstrcatW( short_path, name );
1454 /* GetShortPathName for a non-existent short file name should fail */
1455 SetLastError(0xdeadbeef);
1456 length = GetShortPathNameW( short_path, path, 0 );
1457 ok(!length, "GetShortPathNameW should fail\n");
1458 ok(GetLastError() == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
1460 file = CreateFileW( short_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1461 ok( file != INVALID_HANDLE_VALUE, "File was not created.\n" );
1462 CloseHandle( file );
1463 ret = DeleteFileW( short_path );
1464 ok( ret, "Cannot delete file.\n" );
1466 ptr = path + lstrlenW(path);
1467 lstrcpyW( ptr, a_bcdeW);
1468 file = CreateFileW( path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
1469 ok( file != INVALID_HANDLE_VALUE, "File was not created.\n" );
1470 CloseHandle( file );
1472 length = GetShortPathNameW( path, short_path, ARRAY_SIZE( short_path ));
1473 ok( length, "GetShortPathNameW failed: %u.\n", GetLastError() );
1475 lstrcpyW(ptr, wildW);
1476 SetLastError(0xdeadbeef);
1477 length = GetShortPathNameW( path, short_path, ARRAY_SIZE( short_path ) );
1478 ok(!length, "GetShortPathNameW should fail\n");
1479 ok(GetLastError() == ERROR_INVALID_NAME, "wrong error %d\n", GetLastError());
1481 lstrcpyW(ptr, a_bcdeW);
1482 ret = DeleteFileW( path );
1483 ok( ret, "Cannot delete file.\n" );
1484 *ptr = 0;
1486 /* End test */
1487 ret = RemoveDirectoryW( path );
1488 ok( ret, "Cannot delete directory.\n" );
1491 static void test_GetSystemDirectory(void)
1493 CHAR buffer[MAX_PATH + 4];
1494 DWORD res;
1495 DWORD total;
1497 SetLastError(0xdeadbeef);
1498 res = GetSystemDirectoryA(NULL, 0);
1499 /* res includes the terminating Zero */
1500 ok(res > 0, "returned %d with %d (expected '>0')\n", res, GetLastError());
1502 total = res;
1504 /* this crashes on XP */
1505 if (0)
1506 GetSystemDirectoryA(NULL, total);
1508 SetLastError(0xdeadbeef);
1509 res = GetSystemDirectoryA(NULL, total-1);
1510 /* 95+NT: total (includes the terminating Zero)
1511 98+ME: 0 with ERROR_INVALID_PARAMETER */
1512 ok( (res == total) || (!res && (GetLastError() == ERROR_INVALID_PARAMETER)),
1513 "returned %d with %d (expected '%d' or: '0' with "
1514 "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), total);
1516 if (total > MAX_PATH) return;
1518 buffer[0] = '\0';
1519 SetLastError(0xdeadbeef);
1520 res = GetSystemDirectoryA(buffer, total);
1521 /* res does not include the terminating Zero */
1522 ok( (res == (total-1)) && (buffer[0]),
1523 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1524 res, GetLastError(), buffer, total-1);
1526 buffer[0] = '\0';
1527 SetLastError(0xdeadbeef);
1528 res = GetSystemDirectoryA(buffer, total + 1);
1529 /* res does not include the terminating Zero */
1530 ok( (res == (total-1)) && (buffer[0]),
1531 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1532 res, GetLastError(), buffer, total-1);
1534 memset(buffer, '#', total + 1);
1535 buffer[total + 2] = '\0';
1536 SetLastError(0xdeadbeef);
1537 res = GetSystemDirectoryA(buffer, total-1);
1538 /* res includes the terminating Zero) */
1539 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1540 res, GetLastError(), buffer, total);
1542 memset(buffer, '#', total + 1);
1543 buffer[total + 2] = '\0';
1544 SetLastError(0xdeadbeef);
1545 res = GetSystemDirectoryA(buffer, total-2);
1546 /* res includes the terminating Zero) */
1547 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1548 res, GetLastError(), buffer, total);
1551 static void test_GetWindowsDirectory(void)
1553 CHAR buffer[MAX_PATH + 4];
1554 DWORD res;
1555 DWORD total;
1557 SetLastError(0xdeadbeef);
1558 res = GetWindowsDirectoryA(NULL, 0);
1559 /* res includes the terminating Zero */
1560 ok(res > 0, "returned %d with %d (expected '>0')\n", res, GetLastError());
1562 total = res;
1563 /* this crashes on XP */
1564 if (0)
1565 GetWindowsDirectoryA(NULL, total);
1567 SetLastError(0xdeadbeef);
1568 res = GetWindowsDirectoryA(NULL, total-1);
1569 /* 95+NT: total (includes the terminating Zero)
1570 98+ME: 0 with ERROR_INVALID_PARAMETER */
1571 ok( (res == total) || (!res && (GetLastError() == ERROR_INVALID_PARAMETER)),
1572 "returned %d with %d (expected '%d' or: '0' with "
1573 "ERROR_INVALID_PARAMETER)\n", res, GetLastError(), total);
1575 if (total > MAX_PATH) return;
1577 buffer[0] = '\0';
1578 SetLastError(0xdeadbeef);
1579 res = GetWindowsDirectoryA(buffer, total);
1580 /* res does not include the terminating Zero */
1581 ok( (res == (total-1)) && (buffer[0]),
1582 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1583 res, GetLastError(), buffer, total-1);
1585 buffer[0] = '\0';
1586 SetLastError(0xdeadbeef);
1587 res = GetWindowsDirectoryA(buffer, total + 1);
1588 /* res does not include the terminating Zero */
1589 ok( (res == (total-1)) && (buffer[0]),
1590 "returned %d with %d and '%s' (expected '%d' and a string)\n",
1591 res, GetLastError(), buffer, total-1);
1593 memset(buffer, '#', total + 1);
1594 buffer[total + 2] = '\0';
1595 SetLastError(0xdeadbeef);
1596 res = GetWindowsDirectoryA(buffer, total-1);
1597 /* res includes the terminating Zero) */
1598 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1599 res, GetLastError(), buffer, total);
1601 memset(buffer, '#', total + 1);
1602 buffer[total + 2] = '\0';
1603 SetLastError(0xdeadbeef);
1604 res = GetWindowsDirectoryA(buffer, total-2);
1605 /* res includes the terminating Zero) */
1606 ok( res == total, "returned %d with %d and '%s' (expected '%d')\n",
1607 res, GetLastError(), buffer, total);
1610 static void test_NeedCurrentDirectoryForExePathA(void)
1612 if (!pNeedCurrentDirectoryForExePathA)
1614 win_skip("NeedCurrentDirectoryForExePathA is not available\n");
1615 return;
1618 /* Crashes in Windows */
1619 if (0)
1620 pNeedCurrentDirectoryForExePathA(NULL);
1622 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", NULL);
1623 ok(pNeedCurrentDirectoryForExePathA("."), "returned FALSE for \".\"\n");
1624 ok(pNeedCurrentDirectoryForExePathA("c:\\"), "returned FALSE for \"c:\\\"\n");
1625 ok(pNeedCurrentDirectoryForExePathA("cmd.exe"), "returned FALSE for \"cmd.exe\"\n");
1627 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", "nya");
1628 ok(!pNeedCurrentDirectoryForExePathA("."), "returned TRUE for \".\"\n");
1629 ok(pNeedCurrentDirectoryForExePathA("c:\\"), "returned FALSE for \"c:\\\"\n");
1630 ok(!pNeedCurrentDirectoryForExePathA("cmd.exe"), "returned TRUE for \"cmd.exe\"\n");
1633 static void test_NeedCurrentDirectoryForExePathW(void)
1635 const WCHAR thispath[] = {'.', 0};
1636 const WCHAR fullpath[] = {'c', ':', '\\', 0};
1637 const WCHAR cmdname[] = {'c', 'm', 'd', '.', 'e', 'x', 'e', 0};
1639 if (!pNeedCurrentDirectoryForExePathW)
1641 win_skip("NeedCurrentDirectoryForExePathW is not available\n");
1642 return;
1645 /* Crashes in Windows */
1646 if (0)
1647 pNeedCurrentDirectoryForExePathW(NULL);
1649 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", NULL);
1650 ok(pNeedCurrentDirectoryForExePathW(thispath), "returned FALSE for \".\"\n");
1651 ok(pNeedCurrentDirectoryForExePathW(fullpath), "returned FALSE for \"c:\\\"\n");
1652 ok(pNeedCurrentDirectoryForExePathW(cmdname), "returned FALSE for \"cmd.exe\"\n");
1654 SetEnvironmentVariableA("NoDefaultCurrentDirectoryInExePath", "nya");
1655 ok(!pNeedCurrentDirectoryForExePathW(thispath), "returned TRUE for \".\"\n");
1656 ok(pNeedCurrentDirectoryForExePathW(fullpath), "returned FALSE for \"c:\\\"\n");
1657 ok(!pNeedCurrentDirectoryForExePathW(cmdname), "returned TRUE for \"cmd.exe\"\n");
1660 /* Call various path/file name retrieving APIs and check the case of
1661 * the returned drive letter. Some apps (for instance Adobe Photoshop CS3
1662 * installer) depend on the drive letter being in upper case.
1664 static void test_drive_letter_case(void)
1666 UINT ret;
1667 char buf[MAX_PATH];
1669 #define is_upper_case_letter(a) ((a) >= 'A' && (a) <= 'Z')
1671 memset(buf, 0, sizeof(buf));
1672 SetLastError(0xdeadbeef);
1673 ret = GetWindowsDirectoryA(buf, sizeof(buf));
1674 ok(ret, "GetWindowsDirectory error %u\n", GetLastError());
1675 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1676 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1677 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1679 /* re-use the buffer returned by GetFullPathName */
1680 buf[2] = '/';
1681 SetLastError(0xdeadbeef);
1682 ret = GetFullPathNameA(buf + 2, sizeof(buf), buf, NULL);
1683 ok(ret, "GetFullPathName error %u\n", GetLastError());
1684 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1685 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1686 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1688 memset(buf, 0, sizeof(buf));
1689 SetLastError(0xdeadbeef);
1690 ret = GetSystemDirectoryA(buf, sizeof(buf));
1691 ok(ret, "GetSystemDirectory error %u\n", GetLastError());
1692 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1693 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1694 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1696 memset(buf, 0, sizeof(buf));
1697 SetLastError(0xdeadbeef);
1698 ret = GetCurrentDirectoryA(sizeof(buf), buf);
1699 ok(ret, "GetCurrentDirectory error %u\n", GetLastError());
1700 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1701 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1702 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1704 /* TEMP is an environment variable, so it can't be tested for case-sensitivity */
1705 memset(buf, 0, sizeof(buf));
1706 SetLastError(0xdeadbeef);
1707 ret = GetTempPathA(sizeof(buf), buf);
1708 ok(ret, "GetTempPath error %u\n", GetLastError());
1709 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1710 if (buf[0])
1712 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1713 ok(buf[strlen(buf)-1] == '\\', "Temporary path (%s) doesn't end in a slash\n", buf);
1716 memset(buf, 0, sizeof(buf));
1717 SetLastError(0xdeadbeef);
1718 ret = GetFullPathNameA(".", sizeof(buf), buf, NULL);
1719 ok(ret, "GetFullPathName error %u\n", GetLastError());
1720 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1721 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1722 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1724 /* re-use the buffer returned by GetFullPathName */
1725 SetLastError(0xdeadbeef);
1726 ret = GetShortPathNameA(buf, buf, sizeof(buf));
1727 ok(ret, "GetShortPathName error %u\n", GetLastError());
1728 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1729 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1730 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1732 if (pGetLongPathNameA)
1734 /* re-use the buffer returned by GetShortPathName */
1735 SetLastError(0xdeadbeef);
1736 ret = pGetLongPathNameA(buf, buf, sizeof(buf));
1737 ok(ret, "GetLongPathNameA error %u\n", GetLastError());
1738 ok(ret < sizeof(buf), "buffer should be %u bytes\n", ret);
1739 ok(buf[1] == ':', "expected buf[1] == ':' got %c\n", buf[1]);
1740 ok(is_upper_case_letter(buf[0]), "expected buf[0] upper case letter got %c\n", buf[0]);
1742 #undef is_upper_case_letter
1745 static const char manifest_dep[] =
1746 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
1747 "<assemblyIdentity version=\"1.2.3.4\" name=\"testdep1\" type=\"win32\" processorArchitecture=\"" ARCH "\"/>"
1748 " <file name=\"testdep.dll\" />"
1749 " <file name=\"ole32\" />"
1750 " <file name=\"kernel32.dll\" />"
1751 "</assembly>";
1753 static const char manifest_main[] =
1754 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
1755 "<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
1756 "<dependency>"
1757 " <dependentAssembly>"
1758 " <assemblyIdentity type=\"win32\" name=\"testdep1\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH "\" />"
1759 " </dependentAssembly>"
1760 "</dependency>"
1761 "</assembly>";
1763 static void create_manifest_file(const char *filename, const char *manifest)
1765 WCHAR path[MAX_PATH], manifest_path[MAX_PATH];
1766 HANDLE file;
1767 DWORD size;
1769 MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH );
1771 GetTempPathW(ARRAY_SIZE(manifest_path), manifest_path);
1772 lstrcatW(manifest_path, path);
1774 file = CreateFileW(manifest_path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1775 ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
1776 WriteFile(file, manifest, strlen(manifest), &size, NULL);
1777 CloseHandle(file);
1780 static void delete_manifest_file(const char *filename)
1782 CHAR path[MAX_PATH];
1784 GetTempPathA(sizeof(path), path);
1785 strcat(path, filename);
1786 DeleteFileA(path);
1789 static HANDLE test_create(const char *file)
1791 WCHAR path[MAX_PATH], manifest_path[MAX_PATH];
1792 ACTCTXW actctx;
1793 HANDLE handle;
1795 MultiByteToWideChar(CP_ACP, 0, file, -1, path, MAX_PATH);
1796 GetTempPathW(ARRAY_SIZE(manifest_path), manifest_path);
1797 lstrcatW(manifest_path, path);
1799 memset(&actctx, 0, sizeof(ACTCTXW));
1800 actctx.cbSize = sizeof(ACTCTXW);
1801 actctx.lpSource = manifest_path;
1803 handle = pCreateActCtxW(&actctx);
1804 ok(handle != INVALID_HANDLE_VALUE, "failed to create context, error %u\n", GetLastError());
1806 ok(actctx.cbSize == sizeof(actctx), "cbSize=%d\n", actctx.cbSize);
1807 ok(actctx.dwFlags == 0, "dwFlags=%d\n", actctx.dwFlags);
1808 ok(actctx.lpSource == manifest_path, "lpSource=%p\n", actctx.lpSource);
1809 ok(actctx.wProcessorArchitecture == 0, "wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture);
1810 ok(actctx.wLangId == 0, "wLangId=%d\n", actctx.wLangId);
1811 ok(actctx.lpAssemblyDirectory == NULL, "lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory);
1812 ok(actctx.lpResourceName == NULL, "lpResourceName=%p\n", actctx.lpResourceName);
1813 ok(actctx.lpApplicationName == NULL, "lpApplicationName=%p\n", actctx.lpApplicationName);
1814 ok(actctx.hModule == NULL, "hModule=%p\n", actctx.hModule);
1816 return handle;
1819 static void test_SearchPathA(void)
1821 static const CHAR testdepA[] = "testdep.dll";
1822 static const CHAR testdeprelA[] = "./testdep.dll";
1823 static const CHAR kernel32A[] = "kernel32.dll";
1824 static const CHAR fileA[] = "";
1825 CHAR pathA[MAX_PATH], buffA[MAX_PATH], path2A[MAX_PATH];
1826 CHAR *ptrA = NULL;
1827 ULONG_PTR cookie;
1828 HANDLE handle;
1829 DWORD ret;
1831 if (!pSearchPathA)
1833 win_skip("SearchPathA isn't available\n");
1834 return;
1837 GetWindowsDirectoryA(pathA, ARRAY_SIZE(pathA));
1839 /* NULL filename */
1840 SetLastError(0xdeadbeef);
1841 ret = pSearchPathA(pathA, NULL, NULL, ARRAY_SIZE(buffA), buffA, &ptrA);
1842 ok(ret == 0, "Expected failure, got %d\n", ret);
1843 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1844 "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
1846 /* empty filename */
1847 SetLastError(0xdeadbeef);
1848 ret = pSearchPathA(pathA, fileA, NULL, ARRAY_SIZE(buffA), buffA, &ptrA);
1849 ok(ret == 0, "Expected failure, got %d\n", ret);
1850 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1851 "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
1853 if (!pActivateActCtx)
1854 return;
1856 create_manifest_file("testdep1.manifest", manifest_dep);
1857 create_manifest_file("main.manifest", manifest_main);
1859 handle = test_create("main.manifest");
1860 delete_manifest_file("testdep1.manifest");
1861 delete_manifest_file("main.manifest");
1863 /* search fails without active context */
1864 ret = pSearchPathA(NULL, testdepA, NULL, ARRAY_SIZE(buffA), buffA, NULL);
1865 ok(ret == 0, "got %d\n", ret);
1867 ret = pSearchPathA(NULL, kernel32A, NULL, ARRAY_SIZE(path2A), path2A, NULL);
1868 ok(ret && ret == strlen(path2A), "got %d\n", ret);
1870 ret = pActivateActCtx(handle, &cookie);
1871 ok(ret, "failed to activate context, %u\n", GetLastError());
1873 /* works when activated */
1874 ret = pSearchPathA(NULL, testdepA, NULL, ARRAY_SIZE(buffA), buffA, NULL);
1875 ok(ret && ret == strlen(buffA), "got %d\n", ret);
1877 ret = pSearchPathA(NULL, "testdep.dll", ".ext", ARRAY_SIZE(buffA), buffA, NULL);
1878 ok(ret && ret == strlen(buffA), "got %d\n", ret);
1880 ret = pSearchPathA(NULL, "testdep", ".dll", ARRAY_SIZE(buffA), buffA, NULL);
1881 ok(ret && ret == strlen(buffA), "got %d\n", ret);
1883 ret = pSearchPathA(NULL, "testdep", ".ext", ARRAY_SIZE(buffA), buffA, NULL);
1884 ok(!ret, "got %d\n", ret);
1886 /* name contains path */
1887 ret = pSearchPathA(NULL, testdeprelA, NULL, ARRAY_SIZE(buffA), buffA, NULL);
1888 ok(!ret, "got %d\n", ret);
1890 /* fails with specified path that doesn't contain this file */
1891 ret = pSearchPathA(pathA, testdepA, NULL, ARRAY_SIZE(buffA), buffA, NULL);
1892 ok(!ret, "got %d\n", ret);
1894 /* path is redirected for wellknown names too */
1895 ret = pSearchPathA(NULL, kernel32A, NULL, ARRAY_SIZE(buffA), buffA, NULL);
1896 ok(ret && ret == strlen(buffA), "got %d\n", ret);
1897 ok(strcmp(buffA, path2A), "got wrong path %s, %s\n", buffA, path2A);
1899 ret = pDeactivateActCtx(0, cookie);
1900 ok(ret, "failed to deactivate context, %u\n", GetLastError());
1901 pReleaseActCtx(handle);
1904 static void test_SearchPathW(void)
1906 static const WCHAR testdeprelW[] = {'.','/','t','e','s','t','d','e','p','.','d','l','l',0};
1907 static const WCHAR testdepW[] = {'t','e','s','t','d','e','p','.','d','l','l',0};
1908 static const WCHAR testdep1W[] = {'t','e','s','t','d','e','p',0};
1909 static const WCHAR kernel32dllW[] = {'k','e','r','n','e','l','3','2','.','d','l','l',0};
1910 static const WCHAR kernel32W[] = {'k','e','r','n','e','l','3','2',0};
1911 static const WCHAR ole32W[] = {'o','l','e','3','2',0};
1912 static const WCHAR extW[] = {'.','e','x','t',0};
1913 static const WCHAR dllW[] = {'.','d','l','l',0};
1914 static const WCHAR fileW[] = { 0 };
1915 WCHAR pathW[MAX_PATH], buffW[MAX_PATH], path2W[MAX_PATH];
1916 WCHAR *ptrW = NULL;
1917 ULONG_PTR cookie;
1918 HANDLE handle;
1919 DWORD ret;
1921 if (!pSearchPathW)
1923 win_skip("SearchPathW isn't available\n");
1924 return;
1927 if (0)
1929 /* NULL filename, crashes on nt4 */
1930 pSearchPathW(pathW, NULL, NULL, ARRAY_SIZE(buffW), buffW, &ptrW);
1933 GetWindowsDirectoryW(pathW, ARRAY_SIZE(pathW));
1935 /* empty filename */
1936 SetLastError(0xdeadbeef);
1937 ret = pSearchPathW(pathW, fileW, NULL, ARRAY_SIZE(buffW), buffW, &ptrW);
1938 ok(ret == 0, "Expected failure, got %d\n", ret);
1939 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1940 "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError());
1942 if (!pActivateActCtx)
1943 return;
1945 create_manifest_file("testdep1.manifest", manifest_dep);
1946 create_manifest_file("main.manifest", manifest_main);
1948 handle = test_create("main.manifest");
1949 delete_manifest_file("testdep1.manifest");
1950 delete_manifest_file("main.manifest");
1952 /* search fails without active context */
1953 ret = pSearchPathW(NULL, testdepW, NULL, ARRAY_SIZE(buffW), buffW, NULL);
1954 ok(ret == 0, "got %d\n", ret);
1956 ret = pSearchPathW(NULL, kernel32dllW, NULL, ARRAY_SIZE(path2W), path2W, NULL);
1957 ok(ret && ret == lstrlenW(path2W), "got %d\n", ret);
1959 /* full path, name without 'dll' extension */
1960 GetSystemDirectoryW(pathW, ARRAY_SIZE(pathW));
1961 ret = pSearchPathW(pathW, kernel32W, NULL, ARRAY_SIZE(path2W), path2W, NULL);
1962 ok(ret == 0, "got %d\n", ret);
1964 GetWindowsDirectoryW(pathW, ARRAY_SIZE(pathW));
1966 ret = pActivateActCtx(handle, &cookie);
1967 ok(ret, "failed to activate context, %u\n", GetLastError());
1969 /* works when activated */
1970 ret = pSearchPathW(NULL, testdepW, NULL, ARRAY_SIZE(buffW), buffW, NULL);
1971 ok(ret && ret == lstrlenW(buffW), "got %d\n", ret);
1973 ret = pSearchPathW(NULL, testdepW, extW, ARRAY_SIZE(buffW), buffW, NULL);
1974 ok(ret && ret == lstrlenW(buffW), "got %d\n", ret);
1976 ret = pSearchPathW(NULL, testdep1W, dllW, ARRAY_SIZE(buffW), buffW, NULL);
1977 ok(ret && ret == lstrlenW(buffW), "got %d\n", ret);
1979 ret = pSearchPathW(NULL, testdep1W, extW, ARRAY_SIZE(buffW), buffW, NULL);
1980 ok(!ret, "got %d\n", ret);
1982 /* name contains path */
1983 ret = pSearchPathW(NULL, testdeprelW, NULL, ARRAY_SIZE(buffW), buffW, NULL);
1984 ok(!ret, "got %d\n", ret);
1986 /* fails with specified path that doesn't contain this file */
1987 ret = pSearchPathW(pathW, testdepW, NULL, ARRAY_SIZE(buffW), buffW, NULL);
1988 ok(!ret, "got %d\n", ret);
1990 /* path is redirected for wellknown names too, meaning it takes precedence over normal search order */
1991 ret = pSearchPathW(NULL, kernel32dllW, NULL, ARRAY_SIZE(buffW), buffW, NULL);
1992 ok(ret && ret == lstrlenW(buffW), "got %d\n", ret);
1993 ok(lstrcmpW(buffW, path2W), "got wrong path %s, %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(path2W));
1995 /* path is built using on manifest file name */
1996 ret = pSearchPathW(NULL, ole32W, NULL, ARRAY_SIZE(buffW), buffW, NULL);
1997 ok(ret && ret == lstrlenW(buffW), "got %d\n", ret);
1999 ret = pDeactivateActCtx(0, cookie);
2000 ok(ret, "failed to deactivate context, %u\n", GetLastError());
2001 pReleaseActCtx(handle);
2004 static void test_GetFullPathNameA(void)
2006 char output[MAX_PATH], *filepart;
2007 DWORD ret;
2008 int i;
2009 UINT acp;
2011 const struct
2013 LPCSTR name;
2014 DWORD len;
2015 LPSTR buffer;
2016 LPSTR *lastpart;
2017 } invalid_parameters[] =
2019 {NULL, 0, NULL, NULL},
2020 {NULL, MAX_PATH, NULL, NULL},
2021 {NULL, MAX_PATH, output, NULL},
2022 {NULL, MAX_PATH, output, &filepart},
2023 {"", 0, NULL, NULL},
2024 {"", MAX_PATH, NULL, NULL},
2025 {"", MAX_PATH, output, NULL},
2026 {"", MAX_PATH, output, &filepart},
2029 for (i = 0; i < ARRAY_SIZE(invalid_parameters); i++)
2031 SetLastError(0xdeadbeef);
2032 strcpy(output, "deadbeef");
2033 filepart = (char *)0xdeadbeef;
2034 ret = GetFullPathNameA(invalid_parameters[i].name,
2035 invalid_parameters[i].len,
2036 invalid_parameters[i].buffer,
2037 invalid_parameters[i].lastpart);
2038 ok(!ret, "[%d] Expected GetFullPathNameA to return 0, got %u\n", i, ret);
2039 ok(!strcmp(output, "deadbeef"), "[%d] Expected the output buffer to be unchanged, got \"%s\"\n", i, output);
2040 ok(filepart == (char *)0xdeadbeef, "[%d] Expected output file part pointer to be untouched, got %p\n", i, filepart);
2041 ok(GetLastError() == 0xdeadbeef ||
2042 GetLastError() == ERROR_INVALID_NAME, /* Win7 */
2043 "[%d] Expected GetLastError() to return 0xdeadbeef, got %u\n",
2044 i, GetLastError());
2047 acp = GetACP();
2048 if (acp != 932)
2049 skip("Skipping DBCS(Japanese) GetFullPathNameA test in this codepage (%d)\n", acp);
2050 else {
2051 const struct dbcs_case {
2052 const char *input;
2053 const char *expected;
2054 } testset[] = {
2055 { "c:\\a\\\x95\x5c\x97\xa0.txt", "\x95\x5c\x97\xa0.txt" },
2056 { "c:\\\x83\x8f\x83\x43\x83\x93\\wine.c", "wine.c" },
2057 { "c:\\demo\\\x97\xa0\x95\x5c", "\x97\xa0\x95\x5c" }
2059 for (i = 0; i < ARRAY_SIZE(testset); i++) {
2060 ret = GetFullPathNameA(testset[i].input, sizeof(output),
2061 output, &filepart);
2062 ok(ret, "[%d] GetFullPathName error %u\n", i, GetLastError());
2063 ok(!lstrcmpA(filepart, testset[i].expected),
2064 "[%d] expected %s got %s\n", i, testset[i].expected, filepart);
2069 static void test_GetFullPathNameW(void)
2071 static const WCHAR emptyW[] = {0};
2072 static const WCHAR deadbeefW[] = {'d','e','a','d','b','e','e','f',0};
2074 WCHAR output[MAX_PATH], *filepart;
2075 DWORD ret;
2076 int i;
2078 const struct
2080 LPCWSTR name;
2081 DWORD len;
2082 LPWSTR buffer;
2083 LPWSTR *lastpart;
2084 int win7_expect;
2085 } invalid_parameters[] =
2087 {NULL, 0, NULL, NULL},
2088 {NULL, 0, NULL, &filepart, 1},
2089 {NULL, MAX_PATH, NULL, NULL},
2090 {NULL, MAX_PATH, output, NULL},
2091 {NULL, MAX_PATH, output, &filepart, 1},
2092 {emptyW, 0, NULL, NULL},
2093 {emptyW, 0, NULL, &filepart, 1},
2094 {emptyW, MAX_PATH, NULL, NULL},
2095 {emptyW, MAX_PATH, output, NULL},
2096 {emptyW, MAX_PATH, output, &filepart, 1},
2099 SetLastError(0xdeadbeef);
2100 ret = GetFullPathNameW(NULL, 0, NULL, NULL);
2101 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
2103 win_skip("GetFullPathNameW is not available\n");
2104 return;
2107 for (i = 0; i < ARRAY_SIZE(invalid_parameters); i++)
2109 SetLastError(0xdeadbeef);
2110 lstrcpyW(output, deadbeefW);
2111 filepart = (WCHAR *)0xdeadbeef;
2112 ret = GetFullPathNameW(invalid_parameters[i].name,
2113 invalid_parameters[i].len,
2114 invalid_parameters[i].buffer,
2115 invalid_parameters[i].lastpart);
2116 ok(!ret, "[%d] Expected GetFullPathNameW to return 0, got %u\n", i, ret);
2117 ok(!lstrcmpW(output, deadbeefW), "[%d] Expected the output buffer to be unchanged, got %s\n", i, wine_dbgstr_w(output));
2118 ok(filepart == (WCHAR *)0xdeadbeef ||
2119 (invalid_parameters[i].win7_expect && filepart == NULL),
2120 "[%d] Expected output file part pointer to be untouched, got %p\n", i, filepart);
2121 ok(GetLastError() == 0xdeadbeef ||
2122 GetLastError() == ERROR_INVALID_NAME, /* Win7 */
2123 "[%d] Expected GetLastError() to return 0xdeadbeef, got %u\n",
2124 i, GetLastError());
2128 static void init_pointers(void)
2130 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
2132 #define MAKEFUNC(f) (p##f = (void*)GetProcAddress(hKernel32, #f))
2133 MAKEFUNC(GetLongPathNameA);
2134 MAKEFUNC(GetLongPathNameW);
2135 MAKEFUNC(NeedCurrentDirectoryForExePathA);
2136 MAKEFUNC(NeedCurrentDirectoryForExePathW);
2137 MAKEFUNC(SearchPathA);
2138 MAKEFUNC(SearchPathW);
2139 MAKEFUNC(SetSearchPathMode);
2140 MAKEFUNC(ActivateActCtx);
2141 MAKEFUNC(CreateActCtxW);
2142 MAKEFUNC(DeactivateActCtx);
2143 MAKEFUNC(GetCurrentActCtx);
2144 MAKEFUNC(ReleaseActCtx);
2145 MAKEFUNC(CheckNameLegalDOS8Dot3W);
2146 MAKEFUNC(CheckNameLegalDOS8Dot3A);
2147 #undef MAKEFUNC
2150 static void test_relative_path(void)
2152 char path[MAX_PATH], buf[MAX_PATH];
2153 HANDLE file;
2154 int ret;
2155 WCHAR curdir[MAX_PATH];
2157 if (!pGetLongPathNameA) return;
2159 GetCurrentDirectoryW(MAX_PATH, curdir);
2160 GetTempPathA(MAX_PATH, path);
2161 ret = SetCurrentDirectoryA(path);
2162 ok(ret, "SetCurrentDirectory error %d\n", GetLastError());
2164 ret = CreateDirectoryA("foo", NULL);
2165 ok(ret, "CreateDirectory error %d\n", GetLastError());
2166 file = CreateFileA("foo\\file", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
2167 ok(file != INVALID_HANDLE_VALUE, "failed to create temp file\n");
2168 CloseHandle(file);
2169 ret = CreateDirectoryA("bar", NULL);
2170 ok(ret, "CreateDirectory error %d\n", GetLastError());
2171 ret = SetCurrentDirectoryA("bar");
2172 ok(ret, "SetCurrentDirectory error %d\n", GetLastError());
2174 ret = GetFileAttributesA("..\\foo\\file");
2175 ok(ret != INVALID_FILE_ATTRIBUTES, "GetFileAttributes error %d\n", GetLastError());
2177 strcpy(buf, "deadbeef");
2178 ret = pGetLongPathNameA(".", buf, MAX_PATH);
2179 ok(ret, "GetLongPathName error %d\n", GetLastError());
2180 ok(!strcmp(buf, "."), "expected ., got %s\n", buf);
2181 strcpy(buf, "deadbeef");
2182 ret = GetShortPathNameA(".", buf, MAX_PATH);
2183 ok(ret, "GetShortPathName error %d\n", GetLastError());
2184 ok(!strcmp(buf, "."), "expected ., got %s\n", buf);
2186 strcpy(buf, "deadbeef");
2187 ret = pGetLongPathNameA("..", buf, MAX_PATH);
2188 ok(ret, "GetLongPathName error %d\n", GetLastError());
2189 ok(!strcmp(buf, ".."), "expected .., got %s\n", buf);
2190 strcpy(buf, "deadbeef");
2191 ret = GetShortPathNameA("..", buf, MAX_PATH);
2192 ok(ret, "GetShortPathName error %d\n", GetLastError());
2193 ok(!strcmp(buf, ".."), "expected .., got %s\n", buf);
2195 strcpy(buf, "deadbeef");
2196 ret = pGetLongPathNameA("..\\foo\\file", buf, MAX_PATH);
2197 ok(ret, "GetLongPathName error %d\n", GetLastError());
2198 ok(!strcmp(buf, "..\\foo\\file"), "expected ..\\foo\\file, got %s\n", buf);
2199 strcpy(buf, "deadbeef");
2200 ret = GetShortPathNameA("..\\foo\\file", buf, MAX_PATH);
2201 ok(ret, "GetShortPathName error %d\n", GetLastError());
2202 ok(!strcmp(buf, "..\\foo\\file"), "expected ..\\foo\\file, got %s\n", buf);
2204 strcpy(buf, "deadbeef");
2205 ret = pGetLongPathNameA(".\\..\\foo\\file", buf, MAX_PATH);
2206 ok(ret, "GetLongPathName error %d\n", GetLastError());
2207 ok(!strcmp(buf, ".\\..\\foo\\file"), "expected .\\..\\foo\\file, got %s\n", buf);
2208 strcpy(buf, "deadbeef");
2209 ret = GetShortPathNameA(".\\..\\foo\\file", buf, MAX_PATH);
2210 ok(ret, "GetShortPathName error %d\n", GetLastError());
2211 ok(!strcmp(buf, ".\\..\\foo\\file"), "expected .\\..\\foo\\file, got %s\n", buf);
2213 /* test double delimiters */
2214 strcpy(buf, "deadbeef");
2215 ret = pGetLongPathNameA("..\\\\foo\\file", buf, MAX_PATH);
2216 ok(ret, "GetLongPathName error %d\n", GetLastError());
2217 ok(!strcmp(buf, "..\\\\foo\\file"), "expected ..\\\\foo\\file, got %s\n", buf);
2218 strcpy(buf, "deadbeef");
2219 ret = GetShortPathNameA("..\\\\foo\\file", buf, MAX_PATH);
2220 ok(ret, "GetShortPathName error %d\n", GetLastError());
2221 ok(!strcmp(buf, "..\\\\foo\\file"), "expected ..\\\\foo\\file, got %s\n", buf);
2223 SetCurrentDirectoryA("..");
2224 DeleteFileA("foo\\file");
2225 RemoveDirectoryA("foo");
2226 RemoveDirectoryA("bar");
2227 SetCurrentDirectoryW(curdir);
2230 static void test_CheckNameLegalDOS8Dot3(void)
2232 static const WCHAR has_driveW[] = {'C',':','\\','a','.','t','x','t',0};
2233 static const WCHAR has_pathW[] = {'b','\\','a','.','t','x','t',0};
2234 static const WCHAR too_longW[] = {'a','l','o','n','g','f','i','l','e','n','a','m','e','.','t','x','t',0};
2235 static const WCHAR twodotsW[] = {'t','e','s','t','.','e','s','t','.','t','x','t',0};
2236 static const WCHAR longextW[] = {'t','e','s','t','.','t','x','t','t','x','t',0};
2237 static const WCHAR emptyW[] = {0};
2238 static const WCHAR funnycharsW[] = {'!','#','$','%','&','\'','(',')','.','-','@','^',0};
2239 static const WCHAR length8W[] = {'t','e','s','t','t','e','s','t','.','t','x','t',0};
2240 static const WCHAR length1W[] = {'t',0};
2241 static const WCHAR withspaceW[] = {'t','e','s','t',' ','e','s','t','.','t','x','t',0};
2243 static const struct {
2244 const WCHAR *name;
2245 BOOL should_be_legal, has_space;
2246 } cases[] = {
2247 {has_driveW, FALSE, FALSE},
2248 {has_pathW, FALSE, FALSE},
2249 {too_longW, FALSE, FALSE},
2250 {twodotsW, FALSE, FALSE},
2251 {longextW, FALSE, FALSE},
2252 {emptyW, TRUE /* ! */, FALSE},
2253 {funnycharsW, TRUE, FALSE},
2254 {length8W, TRUE, FALSE},
2255 {length1W, TRUE, FALSE},
2256 {withspaceW, TRUE, TRUE},
2259 BOOL br, is_legal, has_space;
2260 char astr[64];
2261 DWORD i;
2263 if(!pCheckNameLegalDOS8Dot3W){
2264 win_skip("Missing CheckNameLegalDOS8Dot3, skipping tests\n");
2265 return;
2268 br = pCheckNameLegalDOS8Dot3W(NULL, NULL, 0, NULL, &is_legal);
2269 ok(br == FALSE, "CheckNameLegalDOS8Dot3W should have failed\n");
2271 br = pCheckNameLegalDOS8Dot3A(NULL, NULL, 0, NULL, &is_legal);
2272 ok(br == FALSE, "CheckNameLegalDOS8Dot3A should have failed\n");
2274 br = pCheckNameLegalDOS8Dot3W(length8W, NULL, 0, NULL, NULL);
2275 ok(br == FALSE, "CheckNameLegalDOS8Dot3W should have failed\n");
2277 br = pCheckNameLegalDOS8Dot3A("testtest.txt", NULL, 0, NULL, NULL);
2278 ok(br == FALSE, "CheckNameLegalDOS8Dot3A should have failed\n");
2280 for(i = 0; i < ARRAY_SIZE(cases); ++i){
2281 br = pCheckNameLegalDOS8Dot3W(cases[i].name, NULL, 0, &has_space, &is_legal);
2282 ok(br == TRUE, "CheckNameLegalDOS8Dot3W failed for %s\n", wine_dbgstr_w(cases[i].name));
2283 ok(is_legal == cases[i].should_be_legal, "Got wrong legality for %s\n", wine_dbgstr_w(cases[i].name));
2284 if(is_legal)
2285 ok(has_space == cases[i].has_space, "Got wrong space for %s\n", wine_dbgstr_w(cases[i].name));
2287 WideCharToMultiByte(CP_ACP, 0, cases[i].name, -1, astr, sizeof(astr), NULL, NULL);
2289 br = pCheckNameLegalDOS8Dot3A(astr, NULL, 0, &has_space, &is_legal);
2290 ok(br == TRUE, "CheckNameLegalDOS8Dot3W failed for %s\n", astr);
2291 ok(is_legal == cases[i].should_be_legal, "Got wrong legality for %s\n", astr);
2292 if(is_legal)
2293 ok(has_space == cases[i].has_space, "Got wrong space for %s\n", wine_dbgstr_w(cases[i].name));
2297 static void test_SetSearchPathMode(void)
2299 BOOL ret;
2300 char orig[MAX_PATH], buf[MAX_PATH], dir[MAX_PATH], expect[MAX_PATH];
2301 HANDLE handle;
2303 if (!pSetSearchPathMode)
2305 win_skip( "SetSearchPathMode isn't available\n" );
2306 return;
2308 GetCurrentDirectoryA( MAX_PATH, orig );
2309 GetTempPathA( MAX_PATH, buf );
2310 GetTempFileNameA( buf, "path", 0, dir );
2311 DeleteFileA( dir );
2312 CreateDirectoryA( dir, NULL );
2313 ret = SetCurrentDirectoryA( dir );
2314 ok( ret, "failed to switch to %s\n", dir );
2315 if (!ret)
2317 RemoveDirectoryA( dir );
2318 return;
2321 handle = CreateFileA( "kernel32.dll", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
2322 CloseHandle( handle );
2324 SetLastError( 0xdeadbeef );
2325 ret = pSetSearchPathMode( 0 );
2326 ok( !ret, "SetSearchPathMode succeeded\n" );
2327 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
2329 SetLastError( 0xdeadbeef );
2330 ret = pSetSearchPathMode( 0x80 );
2331 ok( !ret, "SetSearchPathMode succeeded\n" );
2332 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
2334 SetLastError( 0xdeadbeef );
2335 ret = pSetSearchPathMode( BASE_SEARCH_PATH_PERMANENT );
2336 ok( !ret, "SetSearchPathMode succeeded\n" );
2337 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
2339 SetLastError( 0xdeadbeef );
2340 ret = SearchPathA( NULL, "kernel32.dll", NULL, MAX_PATH, buf, NULL );
2341 ok( ret, "SearchPathA failed err %u\n", GetLastError() );
2342 GetCurrentDirectoryA( MAX_PATH, expect );
2343 strcat( expect, "\\kernel32.dll" );
2344 ok( !lstrcmpiA( buf, expect ), "found %s expected %s\n", buf, expect );
2346 SetLastError( 0xdeadbeef );
2347 ret = pSetSearchPathMode( BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE );
2348 ok( ret, "SetSearchPathMode failed err %u\n", GetLastError() );
2350 SetLastError( 0xdeadbeef );
2351 ret = SearchPathA( NULL, "kernel32.dll", NULL, MAX_PATH, buf, NULL );
2352 ok( ret, "SearchPathA failed err %u\n", GetLastError() );
2353 GetSystemDirectoryA( expect, MAX_PATH );
2354 strcat( expect, "\\kernel32.dll" );
2355 ok( !lstrcmpiA( buf, expect ), "found %s expected %s\n", buf, expect );
2357 SetLastError( 0xdeadbeef );
2358 ret = pSetSearchPathMode( BASE_SEARCH_PATH_DISABLE_SAFE_SEARCHMODE );
2359 ok( ret, "SetSearchPathMode failed err %u\n", GetLastError() );
2361 SetLastError( 0xdeadbeef );
2362 ret = SearchPathA( NULL, "kernel32.dll", NULL, MAX_PATH, buf, NULL );
2363 ok( ret, "SearchPathA failed err %u\n", GetLastError() );
2364 GetCurrentDirectoryA( MAX_PATH, expect );
2365 strcat( expect, "\\kernel32.dll" );
2366 ok( !lstrcmpiA( buf, expect ), "found %s expected %s\n", buf, expect );
2368 SetLastError( 0xdeadbeef );
2369 ret = pSetSearchPathMode( BASE_SEARCH_PATH_DISABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT );
2370 ok( !ret, "SetSearchPathMode succeeded\n" );
2371 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
2373 SetLastError( 0xdeadbeef );
2374 ret = pSetSearchPathMode( BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT );
2375 ok( ret, "SetSearchPathMode failed err %u\n", GetLastError() );
2377 SetLastError( 0xdeadbeef );
2378 ret = pSetSearchPathMode( BASE_SEARCH_PATH_DISABLE_SAFE_SEARCHMODE );
2379 ok( !ret, "SetSearchPathMode succeeded\n" );
2380 ok( GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError() );
2382 SetLastError( 0xdeadbeef );
2383 ret = pSetSearchPathMode( BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE );
2384 ok( !ret, "SetSearchPathMode succeeded\n" );
2385 ok( GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError() );
2387 SetLastError( 0xdeadbeef );
2388 ret = pSetSearchPathMode( BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT );
2389 ok( ret, "SetSearchPathMode failed err %u\n", GetLastError() );
2391 SetLastError( 0xdeadbeef );
2392 ret = SearchPathA( NULL, "kernel32.dll", NULL, MAX_PATH, buf, NULL );
2393 ok( ret, "SearchPathA failed err %u\n", GetLastError() );
2394 GetSystemDirectoryA( expect, MAX_PATH );
2395 strcat( expect, "\\kernel32.dll" );
2396 ok( !lstrcmpiA( buf, expect ), "found %s expected %s\n", buf, expect );
2398 DeleteFileA( "kernel32.dll" );
2399 SetCurrentDirectoryA( orig );
2400 RemoveDirectoryA( dir );
2403 START_TEST(path)
2405 CHAR origdir[MAX_PATH],curdir[MAX_PATH], curDrive, otherDrive;
2407 init_pointers();
2409 /* Report only once */
2410 if (!pGetLongPathNameA)
2411 win_skip("GetLongPathNameA is not available\n");
2412 if (!pGetLongPathNameW)
2413 win_skip("GetLongPathNameW is not available\n");
2414 if (!pActivateActCtx)
2415 win_skip("Activation contexts not supported, some tests will be skipped\n");
2417 test_relative_path();
2418 test_InitPathA(curdir, &curDrive, &otherDrive);
2419 test_CurrentDirectoryA(origdir,curdir);
2420 test_PathNameA(curdir, curDrive, otherDrive);
2421 test_CleanupPathA(origdir,curdir);
2422 test_GetTempPath();
2423 test_GetLongPathNameA();
2424 test_GetLongPathNameW();
2425 test_GetShortPathNameW();
2426 test_GetSystemDirectory();
2427 test_GetWindowsDirectory();
2428 test_NeedCurrentDirectoryForExePathA();
2429 test_NeedCurrentDirectoryForExePathW();
2430 test_drive_letter_case();
2431 test_SearchPathA();
2432 test_SearchPathW();
2433 test_GetFullPathNameA();
2434 test_GetFullPathNameW();
2435 test_CheckNameLegalDOS8Dot3();
2436 test_SetSearchPathMode();