1 /* 2 * Unit test suite for various Path and Directory Functions 3 * 4 * Copyright 2002 Geoffrey Hausheer 5 * Copyright 2006 Detlef Riekenberg 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include <stdarg.h> 23 #include <stdio.h> 24 #include <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" 31 32 #define HAS_TRAIL_SLASH_A(string) (string[lstrlenA(string)-1]=='\\') 33 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" 42 43 #define NOT_A_VALID_DRIVE '@' 44 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 56 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 |<>" 62 */ 63 static const CHAR funny_chars[]="!@#$%^&*()=+{}[],?'`"; 64 static const CHAR is_char_ok[] ="11111110111111111011"; 65 66 static DWORD (WINAPI *pGetLongPathNameA)(LPCSTR,LPSTR,DWORD); 67 static DWORD (WINAPI *pGetLongPathNameW)(LPWSTR,LPWSTR,DWORD); 68 69 /* Present in Win2003+ */ 70 static BOOL (WINAPI *pNeedCurrentDirectoryForExePathA)(LPCSTR); 71 static BOOL (WINAPI *pNeedCurrentDirectoryForExePathW)(LPCWSTR); 72 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); 76 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); 82 83 static BOOL (WINAPI *pCheckNameLegalDOS8Dot3W)(const WCHAR *, char *, DWORD, BOOL *, BOOL *); 84 static BOOL (WINAPI *pCheckNameLegalDOS8Dot3A)(const char *, char *, DWORD, BOOL *, BOOL *); 85 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; 95 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 100 */ 101 static void test_ValidPathA(const CHAR *curdir, const CHAR *subdir, const CHAR *filename, 102 CHAR *shortstr, SLpassfail *passfail, const CHAR *errstr) 103 { 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 116 */ 117 if(passfail!=NULL) { 118 passfail->shortlen=-1;passfail->s2llen=-1;passfail->longlen=-1; 119 passfail->shorterror=0;passfail->s2lerror=0;passfail->longerror=0; 120 } 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); 128 } 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); 139 } 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); 159 } 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(); 168 } 169 /* Test GetLongPathNameA functionality 170 We test both conversion from GetFullPathNameA and from GetShortPathNameA 171 */ 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(); 185 } 186 } 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(); 196 } 197 } 198 } 199 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; 218 } 219 } 220 } 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,""); 231 } 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"); 235 } 236 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]; 241 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); 247 } 248 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. 256 */ 257 static void test_FunnyChars(CHAR *curdir,CHAR *curdir_short,CHAR *filename, INT valid,CHAR *errstr) 258 { 259 CHAR tmpstr[MAX_PATH],tmpstr1[MAX_PATH]; 260 SLpassfail passfail; 261 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); 275 } 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); 287 } 288 } 289 } 290 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) 294 { 295 CHAR tmppath[MAX_PATH], *dirptr; 296 DWORD val,len,chklen; 297 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); 324 } 325 } 326 static void test_InitPathA(CHAR *newdir, CHAR *curDrive, CHAR *otherDrive) 327 { 328 CHAR tmppath[MAX_PATH], /*path to TEMP */ 329 tmpstr[MAX_PATH], 330 tmpstr1[MAX_PATH], 331 invalid_dir[MAX_PATH]; 332 333 DWORD len,len1,drives; 334 INT id; 335 HANDLE hndl; 336 BOOL bRes; 337 UINT unique; 338 339 *curDrive = *otherDrive = NOT_A_VALID_DRIVE; 340 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"); 346 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); 356 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"); 366 367 id=GetTempFileNameA(tmppath,NULL,0,newdir); 368 /* Windows 95, 98 return 0==id, while Windows 2000, XP return 0!=id */ 369 if (id) 370 { 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"); 378 } 379 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()); 387 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"); 393 } 394 } 395 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"); 404 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 409 */ 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 417 */ 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"); 452 } 453 454 /* Test GetCurrentDirectory & SetCurrentDirectory */ 455 static void test_CurrentDirectoryA(CHAR *origdir, CHAR *newdir) 456 { 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 462 */ 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 467 */ 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"); 473 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 ); 501 502 /* Check for crash prevention on swapped args. Crashes all but Win9x. 503 */ 504 if (0) 505 { 506 GetCurrentDirectoryA( 42, (LPSTR)(MAX_PATH + 42) ); 507 } 508 509 /* SetCurrentDirectoryA shouldn't care whether the string has a 510 trailing '\\' or not 511 */ 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. 517 */ 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. 544 */ 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"); 550 } 551 552 /* Cleanup the mess we made while executing these tests */ 553 static void test_CleanupPathA(CHAR *origdir, CHAR *curdir) 554 { 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"); 570 } 571 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) 575 { 576 char buf[MAX_PATH], shortbuf[MAX_PATH]; 577 HANDLE hndl; 578 size_t i; 579 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); 593 } 594 595 /* This routine will test Get(Full|Short|Long)PathNameA */ 596 static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive) 597 { 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; 606 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"); 618 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); 627 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); 633 } 634 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"); 653 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"); 668 } 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"); 680 } 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"); 696 } 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"); 708 } 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); 725 } 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); 740 } 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); 755 } 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); 770 } 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); 792 } 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); 806 } 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); 817 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); 824 } 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); 843 } 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); 854 } 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); 876 } 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); 881 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); 899 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); 907 } 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); 918 } 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); 944 } 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); 949 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); 959 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); 965 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); 970 } 971 } 972 973 static void test_GetTempPathA(char* tmp_dir) 974 { 975 DWORD len, slen, len_with_null; 976 char buf[MAX_PATH]; 977 978 len_with_null = strlen(tmp_dir) + 1; 979 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"); 985 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. 992 */ 993 len = GetTempPathA(1, buf); 994 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len); 995 996 len = GetTempPathA(0, NULL); 997 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len); 998 999 /* The call above gave us the buffer size that Windows thinks is needed 1000 * so the next call should work 1001 */ 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"); 1006 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]); 1015 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 < sizeof(buf) / sizeof(buf[0]); len++) 1022 ok(buf[len] == 'a', "expected 'a' at [%d], got 0x%x\n", len, buf[len]); 1023 } 1024 1025 static void test_GetTempPathW(char* tmp_dir) 1026 { 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}; 1031 1032 MultiByteToWideChar(CP_ACP,0,tmp_dir,-1,tmp_dirW,sizeof(tmp_dirW)/sizeof(*tmp_dirW)); 1033 len_with_null = lstrlenW(tmp_dirW) + 1; 1034 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. 1042 */ 1043 1044 lstrcpyW(buf, fooW); 1045 len = GetTempPathW(MAX_PATH, buf); 1046 if (len == 0 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 1047 { 1048 win_skip("GetTempPathW is not available\n"); 1049 return; 1050 } 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"); 1053 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); 1058 1059 len = GetTempPathW(0, NULL); 1060 ok(len >= len_with_null, "Expected >= %u, got %u\n", len_with_null, len); 1061 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"); 1066 1067 for(len = 0; len < sizeof(buf) / sizeof(buf[0]); 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 < sizeof(buf) / sizeof(buf[0]); len++) 1075 ok(buf[len] == '\0', "expected NULL at [%d], got 0x%x\n", len, buf[len]); 1076 1077 /* When the buffer is not long enough the length passed is zeroed */ 1078 for(len = 0; len < sizeof(buf) / sizeof(buf[0]); 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); 1083 1084 { 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. 1089 */ 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; 1095 } 1096 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 < sizeof(buf) / sizeof(buf[0]); len++) 1100 ok(buf[len] == 'a', "expected 'a' at [%d], got 0x%x\n", len, buf[len]); 1101 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) 1107 { 1108 skip("Could not allocate memory for the test\n"); 1109 return; 1110 } 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. 1120 */ 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]); 1127 1128 HeapFree(GetProcessHeap(), 0, long_buf); 1129 } 1130 1131 static void test_GetTempPath(void) 1132 { 1133 char save_TMP[MAX_PATH]; 1134 char windir[MAX_PATH]; 1135 char buf[MAX_PATH]; 1136 WCHAR curdir[MAX_PATH]; 1137 1138 if (!GetEnvironmentVariableA("TMP", save_TMP, sizeof(save_TMP))) save_TMP[0] = 0; 1139 1140 /* test default configuration */ 1141 trace("TMP=%s\n", save_TMP); 1142 if (save_TMP[0]) 1143 { 1144 strcpy(buf,save_TMP); 1145 if (buf[strlen(buf)-1]!='\\') 1146 strcat(buf,"\\"); 1147 test_GetTempPathA(buf); 1148 test_GetTempPathW(buf); 1149 } 1150 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); 1159 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); 1168 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); 1181 1182 SetEnvironmentVariableA("TMP", save_TMP); 1183 SetCurrentDirectoryW(curdir); 1184 } 1185 1186 static void test_GetLongPathNameA(void) 1187 { 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; 1195 1196 if (!pGetLongPathNameA) 1197 return; 1198 1199 GetTempPathA(MAX_PATH, tempfile); 1200 name = tempfile + strlen(tempfile); 1201 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()); 1207 1208 strcpy(name, "longfilename.longext"); 1209 1210 file = CreateFileA(tempfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 1211 CloseHandle(file); 1212 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"); 1219 1220 /* Some UNC syntax tests */ 1221 1222 memset(temppath, 0, MAX_PATH); 1223 memset(temppath2, 0, MAX_PATH); 1224 lstrcpyA(temppath2, "\\\\?\\"); 1225 lstrcatA(temppath2, tempfile); 1226 explength = length + 4; 1227 1228 SetLastError(0xdeadbeef); 1229 length = pGetLongPathNameA(temppath2, NULL, 0); 1230 if (length == 0 && GetLastError() == ERROR_BAD_NET_NAME) 1231 { 1232 win_skip("UNC syntax tests don't work on Win98/WinMe\n"); 1233 DeleteFileA(tempfile); 1234 return; 1235 } 1236 ok(length == explength, "Wrong length %d, expected %d\n", length, explength); 1237 1238 length = pGetLongPathNameA(temppath2, NULL, MAX_PATH); 1239 ok(length == explength, "Wrong length %d, expected %d\n", length, explength); 1240 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"); 1244 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, "\\"); 1250 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); 1258 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); 1266 1267 /* NULL test */ 1268 SetLastError(0xdeadbeef); 1269 length = pGetLongPathNameA(unc_short, NULL, 0); 1270 if (length == 0 && GetLastError() == ERROR_BAD_NETPATH) 1271 { 1272 /* Seen on Window XP Home */ 1273 win_skip("UNC with computername is not supported\n"); 1274 DeleteFileA(tempfile); 1275 return; 1276 } 1277 explength = lstrlenA(longpath) + 1; 1278 todo_wine 1279 ok(length == explength, "Wrong length %d, expected %d\n", length, explength); 1280 1281 length = pGetLongPathNameA(unc_short, NULL, MAX_PATH); 1282 todo_wine 1283 ok(length == explength, "Wrong length %d, expected %d\n", length, explength); 1284 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"); 1291 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 1297 { 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); 1300 } 1301 1302 DeleteFileA(tempfile); 1303 } 1304 1305 static void test_GetLongPathNameW(void) 1306 { 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}; 1317 1318 if (!pGetLongPathNameW) 1319 return; 1320 1321 SetLastError(0xdeadbeef); 1322 length = pGetLongPathNameW(NULL,NULL,0); 1323 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 1324 { 1325 win_skip("GetLongPathNameW is not implemented\n"); 1326 return; 1327 } 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()); 1330 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()); 1336 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. 1340 */ 1341 name[0] = 0; 1342 while (lstrlenW(name) < (sizeof(name)/sizeof(WCHAR) - 1)) 1343 lstrcatW(name, letterX); 1344 1345 GetTempPathW(MAX_PATH, tempdir); 1346 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); 1355 1356 /* Path does not exist yet and we know it overruns MAX_PATH */ 1357 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 1369 { 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()); 1373 } 1374 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); 1380 1381 /* Path exists */ 1382 1383 /* No prefix */ 1384 SetLastError(0xdeadbeef); 1385 length = pGetLongPathNameW(shortpath + 4, NULL, 0); 1386 todo_wine 1387 { 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()); 1390 } 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); 1396 1397 /* NULL buffer with length crashes on Windows */ 1398 if (0) 1399 pGetLongPathNameW(shortpath, NULL, 20); 1400 1401 ok(DeleteFileW(shortpath), "Could not delete temporary file\n"); 1402 ok(RemoveDirectoryW(dirpath), "Could not delete temporary directory\n"); 1403 } 1404 1405 static void test_GetShortPathNameW(void) 1406 { 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; 1418 1419 SetLastError(0xdeadbeef); 1420 GetTempPathW( MAX_PATH, tmppath ); 1421 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 1422 { 1423 win_skip("GetTempPathW is not implemented\n"); 1424 return; 1425 } 1426 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() ); 1432 1433 /* Starting a main part of test */ 1434 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, sizeof(short_path) / sizeof(*short_path) ); 1442 ok( length, "GetShortPathNameW returned 0.\n" ); 1443 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" ); 1451 1452 lstrcatW( short_path, name ); 1453 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()); 1459 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" ); 1465 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 ); 1471 1472 length = GetShortPathNameW( path, short_path, sizeof(short_path)/sizeof(*short_path) ); 1473 ok( length, "GetShortPathNameW failed: %u.\n", GetLastError() ); 1474 1475 lstrcpyW(ptr, wildW); 1476 SetLastError(0xdeadbeef); 1477 length = GetShortPathNameW( path, short_path, sizeof(short_path)/sizeof(*short_path) ); 1478 ok(!length, "GetShortPathNameW should fail\n"); 1479 ok(GetLastError() == ERROR_INVALID_NAME, "wrong error %d\n", GetLastError()); 1480 1481 lstrcpyW(ptr, a_bcdeW); 1482 ret = DeleteFileW( path ); 1483 ok( ret, "Cannot delete file.\n" ); 1484 *ptr = 0; 1485 1486 /* End test */ 1487 ret = RemoveDirectoryW( path ); 1488 ok( ret, "Cannot delete directory.\n" ); 1489 } 1490 1491 static void test_GetSystemDirectory(void) 1492 { 1493 CHAR buffer[MAX_PATH + 4]; 1494 DWORD res; 1495 DWORD total; 1496 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()); 1501 1502 total = res; 1503 1504 /* this crashes on XP */ 1505 if (0) 1506 GetSystemDirectoryA(NULL, total); 1507 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); 1515 1516 if (total > MAX_PATH) return; 1517 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); 1525 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); 1533 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); 1541 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); 1549 } 1550 1551 static void test_GetWindowsDirectory(void) 1552 { 1553 CHAR buffer[MAX_PATH + 4]; 1554 DWORD res; 1555 DWORD total; 1556 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()); 1561 1562 total = res; 1563 /* this crashes on XP */ 1564 if (0) 1565 GetWindowsDirectoryA(NULL, total); 1566 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); 1574 1575 if (total > MAX_PATH) return; 1576 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); 1584 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); 1592 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); 1600 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); 1608 } 1609 1610 static void test_NeedCurrentDirectoryForExePathA(void) 1611 { 1612 if (!pNeedCurrentDirectoryForExePathA) 1613 { 1614 win_skip("NeedCurrentDirectoryForExePathA is not available\n"); 1615 return; 1616 } 1617 1618 /* Crashes in Windows */ 1619 if (0) 1620 pNeedCurrentDirectoryForExePathA(NULL); 1621 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"); 1626 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"); 1631 } 1632 1633 static void test_NeedCurrentDirectoryForExePathW(void) 1634 { 1635 const WCHAR thispath[] = {'.', 0}; 1636 const WCHAR fullpath[] = {'c', ':', '\\', 0}; 1637 const WCHAR cmdname[] = {'c', 'm', 'd', '.', 'e', 'x', 'e', 0}; 1638 1639 if (!pNeedCurrentDirectoryForExePathW) 1640 { 1641 win_skip("NeedCurrentDirectoryForExePathW is not available\n"); 1642 return; 1643 } 1644 1645 /* Crashes in Windows */ 1646 if (0) 1647 pNeedCurrentDirectoryForExePathW(NULL); 1648 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"); 1653 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"); 1658 } 1659 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. 1663 */ 1664 static void test_drive_letter_case(void) 1665 { 1666 UINT ret; 1667 char buf[MAX_PATH]; 1668 1669 #define is_upper_case_letter(a) ((a) >= 'A' && (a) <= 'Z') 1670 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]); 1678 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]); 1687 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]); 1695 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]); 1703 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]) 1711 { 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); 1714 } 1715 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]); 1723 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]); 1731 1732 if (pGetLongPathNameA) 1733 { 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]); 1741 } 1742 #undef is_upper_case_letter 1743 } 1744 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>"; 1752 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>"; 1762 1763 static void create_manifest_file(const char *filename, const char *manifest) 1764 { 1765 WCHAR path[MAX_PATH], manifest_path[MAX_PATH]; 1766 HANDLE file; 1767 DWORD size; 1768 1769 MultiByteToWideChar( CP_ACP, 0, filename, -1, path, MAX_PATH ); 1770 1771 GetTempPathW(sizeof(manifest_path)/sizeof(WCHAR), manifest_path); 1772 lstrcatW(manifest_path, path); 1773 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); 1778 } 1779 1780 static void delete_manifest_file(const char *filename) 1781 { 1782 CHAR path[MAX_PATH]; 1783 1784 GetTempPathA(sizeof(path), path); 1785 strcat(path, filename); 1786 DeleteFileA(path); 1787 } 1788 1789 static HANDLE test_create(const char *file) 1790 { 1791 WCHAR path[MAX_PATH], manifest_path[MAX_PATH]; 1792 ACTCTXW actctx; 1793 HANDLE handle; 1794 1795 MultiByteToWideChar(CP_ACP, 0, file, -1, path, MAX_PATH); 1796 GetTempPathW(sizeof(manifest_path)/sizeof(WCHAR), manifest_path); 1797 lstrcatW(manifest_path, path); 1798 1799 memset(&actctx, 0, sizeof(ACTCTXW)); 1800 actctx.cbSize = sizeof(ACTCTXW); 1801 actctx.lpSource = manifest_path; 1802 1803 handle = pCreateActCtxW(&actctx); 1804 ok(handle != INVALID_HANDLE_VALUE, "failed to create context, error %u\n", GetLastError()); 1805 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); 1815 1816 return handle; 1817 } 1818 1819 static void test_SearchPathA(void) 1820 { 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], path3A[MAX_PATH], curdirA[MAX_PATH]; 1826 CHAR tmpdirA[MAX_PATH], *ptrA = NULL; 1827 ULONG_PTR cookie; 1828 HANDLE handle; 1829 BOOL bret; 1830 DWORD ret; 1831 1832 if (!pSearchPathA) 1833 { 1834 win_skip("SearchPathA isn't available\n"); 1835 return; 1836 } 1837 1838 GetWindowsDirectoryA(pathA, sizeof(pathA)/sizeof(CHAR)); 1839 1840 /* NULL filename */ 1841 SetLastError(0xdeadbeef); 1842 ret = pSearchPathA(pathA, NULL, NULL, sizeof(buffA)/sizeof(CHAR), buffA, &ptrA); 1843 ok(ret == 0, "Expected failure, got %d\n", ret); 1844 ok(GetLastError() == ERROR_INVALID_PARAMETER, 1845 "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError()); 1846 1847 /* empty filename */ 1848 SetLastError(0xdeadbeef); 1849 ret = pSearchPathA(pathA, fileA, NULL, sizeof(buffA)/sizeof(CHAR), buffA, &ptrA); 1850 ok(ret == 0, "Expected failure, got %d\n", ret); 1851 ok(GetLastError() == ERROR_INVALID_PARAMETER, 1852 "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError()); 1853 1854 if (!pActivateActCtx) 1855 return; 1856 1857 create_manifest_file("testdep1.manifest", manifest_dep); 1858 create_manifest_file("main.manifest", manifest_main); 1859 1860 handle = test_create("main.manifest"); 1861 delete_manifest_file("testdep1.manifest"); 1862 delete_manifest_file("main.manifest"); 1863 1864 /* search fails without active context */ 1865 ret = pSearchPathA(NULL, testdepA, NULL, sizeof(buffA)/sizeof(CHAR), buffA, NULL); 1866 ok(ret == 0, "got %d\n", ret); 1867 1868 ret = pSearchPathA(NULL, kernel32A, NULL, sizeof(path2A)/sizeof(CHAR), path2A, NULL); 1869 ok(ret && ret == strlen(path2A), "got %d\n", ret); 1870 1871 ret = pActivateActCtx(handle, &cookie); 1872 ok(ret, "failed to activate context, %u\n", GetLastError()); 1873 1874 /* works when activated */ 1875 ret = pSearchPathA(NULL, testdepA, NULL, sizeof(buffA)/sizeof(CHAR), buffA, NULL); 1876 ok(ret && ret == strlen(buffA), "got %d\n", ret); 1877 1878 ret = pSearchPathA(NULL, "testdep.dll", ".ext", sizeof(buffA)/sizeof(CHAR), buffA, NULL); 1879 ok(ret && ret == strlen(buffA), "got %d\n", ret); 1880 1881 ret = pSearchPathA(NULL, "testdep", ".dll", sizeof(buffA)/sizeof(CHAR), buffA, NULL); 1882 ok(ret && ret == strlen(buffA), "got %d\n", ret); 1883 1884 ret = pSearchPathA(NULL, "testdep", ".ext", sizeof(buffA)/sizeof(CHAR), buffA, NULL); 1885 ok(!ret, "got %d\n", ret); 1886 1887 /* name contains path */ 1888 ret = pSearchPathA(NULL, testdeprelA, NULL, sizeof(buffA)/sizeof(CHAR), buffA, NULL); 1889 ok(!ret, "got %d\n", ret); 1890 1891 /* fails with specified path that doesn't contain this file */ 1892 ret = pSearchPathA(pathA, testdepA, NULL, sizeof(buffA)/sizeof(CHAR), buffA, NULL); 1893 ok(!ret, "got %d\n", ret); 1894 1895 /* path is redirected for wellknown names too */ 1896 ret = pSearchPathA(NULL, kernel32A, NULL, sizeof(buffA)/sizeof(CHAR), buffA, NULL); 1897 ok(ret && ret == strlen(buffA), "got %d\n", ret); 1898 ok(strcmp(buffA, path2A), "got wrong path %s, %s\n", buffA, path2A); 1899 1900 ret = pDeactivateActCtx(0, cookie); 1901 ok(ret, "failed to deactivate context, %u\n", GetLastError()); 1902 pReleaseActCtx(handle); 1903 1904 /* test the search path priority of the working directory */ 1905 GetTempPathA(sizeof(tmpdirA), tmpdirA); 1906 ret = GetCurrentDirectoryA(MAX_PATH, curdirA); 1907 ok(ret, "failed to obtain working directory.\n"); 1908 sprintf(pathA, "%s\\%s", tmpdirA, kernel32A); 1909 ret = pSearchPathA(NULL, kernel32A, NULL, sizeof(path2A)/sizeof(CHAR), path2A, NULL); 1910 ok(ret && ret == strlen(path2A), "got %d\n", ret); 1911 bret = CopyFileA(path2A, pathA, FALSE); 1912 ok(bret != 0, "failed to copy test executable to temp directory, %u\n", GetLastError()); 1913 sprintf(path3A, "%s%s%s", curdirA, curdirA[strlen(curdirA)-1] != '\\' ? "\\" : "", kernel32A); 1914 bret = CopyFileA(path2A, path3A, FALSE); 1915 ok(bret != 0, "failed to copy test executable to launch directory, %u\n", GetLastError()); 1916 bret = SetCurrentDirectoryA(tmpdirA); 1917 ok(bret, "failed to change working directory\n"); 1918 ret = pSearchPathA(NULL, kernel32A, ".exe", sizeof(buffA), buffA, NULL); 1919 ok(ret && ret == strlen(buffA), "got %d\n", ret); 1920 ok(strcmp(buffA, path3A) == 0, "expected %s, got %s\n", path3A, buffA); 1921 bret = SetCurrentDirectoryA(curdirA); 1922 ok(bret, "failed to reset working directory\n"); 1923 DeleteFileA(path3A); 1924 DeleteFileA(pathA); 1925 } 1926 1927 static void test_SearchPathW(void) 1928 { 1929 static const WCHAR testdeprelW[] = {'.','/','t','e','s','t','d','e','p','.','d','l','l',0}; 1930 static const WCHAR testdepW[] = {'t','e','s','t','d','e','p','.','d','l','l',0}; 1931 static const WCHAR testdep1W[] = {'t','e','s','t','d','e','p',0}; 1932 static const WCHAR kernel32dllW[] = {'k','e','r','n','e','l','3','2','.','d','l','l',0}; 1933 static const WCHAR kernel32W[] = {'k','e','r','n','e','l','3','2',0}; 1934 static const WCHAR ole32W[] = {'o','l','e','3','2',0}; 1935 static const WCHAR extW[] = {'.','e','x','t',0}; 1936 static const WCHAR dllW[] = {'.','d','l','l',0}; 1937 static const WCHAR fileW[] = { 0 }; 1938 WCHAR pathW[MAX_PATH], buffW[MAX_PATH], path2W[MAX_PATH]; 1939 WCHAR *ptrW = NULL; 1940 ULONG_PTR cookie; 1941 HANDLE handle; 1942 DWORD ret; 1943 1944 if (!pSearchPathW) 1945 { 1946 win_skip("SearchPathW isn't available\n"); 1947 return; 1948 } 1949 1950 if (0) 1951 { 1952 /* NULL filename, crashes on nt4 */ 1953 pSearchPathW(pathW, NULL, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, &ptrW); 1954 } 1955 1956 GetWindowsDirectoryW(pathW, sizeof(pathW)/sizeof(WCHAR)); 1957 1958 /* empty filename */ 1959 SetLastError(0xdeadbeef); 1960 ret = pSearchPathW(pathW, fileW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, &ptrW); 1961 ok(ret == 0, "Expected failure, got %d\n", ret); 1962 ok(GetLastError() == ERROR_INVALID_PARAMETER, 1963 "Expected ERROR_INVALID_PARAMETER, got %x\n", GetLastError()); 1964 1965 if (!pActivateActCtx) 1966 return; 1967 1968 create_manifest_file("testdep1.manifest", manifest_dep); 1969 create_manifest_file("main.manifest", manifest_main); 1970 1971 handle = test_create("main.manifest"); 1972 delete_manifest_file("testdep1.manifest"); 1973 delete_manifest_file("main.manifest"); 1974 1975 /* search fails without active context */ 1976 ret = pSearchPathW(NULL, testdepW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL); 1977 ok(ret == 0, "got %d\n", ret); 1978 1979 ret = pSearchPathW(NULL, kernel32dllW, NULL, sizeof(path2W)/sizeof(WCHAR), path2W, NULL); 1980 ok(ret && ret == lstrlenW(path2W), "got %d\n", ret); 1981 1982 /* full path, name without 'dll' extension */ 1983 GetSystemDirectoryW(pathW, sizeof(pathW)/sizeof(WCHAR)); 1984 ret = pSearchPathW(pathW, kernel32W, NULL, sizeof(path2W)/sizeof(WCHAR), path2W, NULL); 1985 ok(ret == 0, "got %d\n", ret); 1986 1987 GetWindowsDirectoryW(pathW, sizeof(pathW)/sizeof(WCHAR)); 1988 1989 ret = pActivateActCtx(handle, &cookie); 1990 ok(ret, "failed to activate context, %u\n", GetLastError()); 1991 1992 /* works when activated */ 1993 ret = pSearchPathW(NULL, testdepW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL); 1994 ok(ret && ret == lstrlenW(buffW), "got %d\n", ret); 1995 1996 ret = pSearchPathW(NULL, testdepW, extW, sizeof(buffW)/sizeof(WCHAR), buffW, NULL); 1997 ok(ret && ret == lstrlenW(buffW), "got %d\n", ret); 1998 1999 ret = pSearchPathW(NULL, testdep1W, dllW, sizeof(buffW)/sizeof(WCHAR), buffW, NULL); 2000 ok(ret && ret == lstrlenW(buffW), "got %d\n", ret); 2001 2002 ret = pSearchPathW(NULL, testdep1W, extW, sizeof(buffW)/sizeof(WCHAR), buffW, NULL); 2003 ok(!ret, "got %d\n", ret); 2004 2005 /* name contains path */ 2006 ret = pSearchPathW(NULL, testdeprelW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL); 2007 ok(!ret, "got %d\n", ret); 2008 2009 /* fails with specified path that doesn't contain this file */ 2010 ret = pSearchPathW(pathW, testdepW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL); 2011 ok(!ret, "got %d\n", ret); 2012 2013 /* path is redirected for wellknown names too, meaning it takes precedence over normal search order */ 2014 ret = pSearchPathW(NULL, kernel32dllW, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL); 2015 ok(ret && ret == lstrlenW(buffW), "got %d\n", ret); 2016 ok(lstrcmpW(buffW, path2W), "got wrong path %s, %s\n", wine_dbgstr_w(buffW), wine_dbgstr_w(path2W)); 2017 2018 /* path is built using on manifest file name */ 2019 ret = pSearchPathW(NULL, ole32W, NULL, sizeof(buffW)/sizeof(WCHAR), buffW, NULL); 2020 ok(ret && ret == lstrlenW(buffW), "got %d\n", ret); 2021 2022 ret = pDeactivateActCtx(0, cookie); 2023 ok(ret, "failed to deactivate context, %u\n", GetLastError()); 2024 pReleaseActCtx(handle); 2025 } 2026 2027 static void test_GetFullPathNameA(void) 2028 { 2029 char output[MAX_PATH], *filepart; 2030 DWORD ret; 2031 int i; 2032 UINT acp; 2033 2034 const struct 2035 { 2036 LPCSTR name; 2037 DWORD len; 2038 LPSTR buffer; 2039 LPSTR *lastpart; 2040 } invalid_parameters[] = 2041 { 2042 {NULL, 0, NULL, NULL}, 2043 {NULL, MAX_PATH, NULL, NULL}, 2044 {NULL, MAX_PATH, output, NULL}, 2045 {NULL, MAX_PATH, output, &filepart}, 2046 {"", 0, NULL, NULL}, 2047 {"", MAX_PATH, NULL, NULL}, 2048 {"", MAX_PATH, output, NULL}, 2049 {"", MAX_PATH, output, &filepart}, 2050 }; 2051 2052 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++) 2053 { 2054 SetLastError(0xdeadbeef); 2055 strcpy(output, "deadbeef"); 2056 filepart = (char *)0xdeadbeef; 2057 ret = GetFullPathNameA(invalid_parameters[i].name, 2058 invalid_parameters[i].len, 2059 invalid_parameters[i].buffer, 2060 invalid_parameters[i].lastpart); 2061 ok(!ret, "[%d] Expected GetFullPathNameA to return 0, got %u\n", i, ret); 2062 ok(!strcmp(output, "deadbeef"), "[%d] Expected the output buffer to be unchanged, got \"%s\"\n", i, output); 2063 ok(filepart == (char *)0xdeadbeef, "[%d] Expected output file part pointer to be untouched, got %p\n", i, filepart); 2064 ok(GetLastError() == 0xdeadbeef || 2065 GetLastError() == ERROR_INVALID_NAME, /* Win7 */ 2066 "[%d] Expected GetLastError() to return 0xdeadbeef, got %u\n", 2067 i, GetLastError()); 2068 } 2069 2070 acp = GetACP(); 2071 if (acp != 932) 2072 skip("Skipping DBCS(Japanese) GetFullPathNameA test in this codepage (%d)\n", acp); 2073 else { 2074 const struct dbcs_case { 2075 const char *input; 2076 const char *expected; 2077 } testset[] = { 2078 { "c:\\a\\\x95\x5c\x97\xa0.txt", "\x95\x5c\x97\xa0.txt" }, 2079 { "c:\\\x83\x8f\x83\x43\x83\x93\\wine.c", "wine.c" }, 2080 { "c:\\demo\\\x97\xa0\x95\x5c", "\x97\xa0\x95\x5c" } 2081 }; 2082 for (i = 0; i < sizeof(testset)/sizeof(testset[0]); i++) { 2083 ret = GetFullPathNameA(testset[i].input, sizeof(output), 2084 output, &filepart); 2085 ok(ret, "[%d] GetFullPathName error %u\n", i, GetLastError()); 2086 ok(!lstrcmpA(filepart, testset[i].expected), 2087 "[%d] expected %s got %s\n", i, testset[i].expected, filepart); 2088 } 2089 } 2090 } 2091 2092 static void test_GetFullPathNameW(void) 2093 { 2094 static const WCHAR emptyW[] = {0}; 2095 static const WCHAR deadbeefW[] = {'d','e','a','d','b','e','e','f',0}; 2096 2097 WCHAR output[MAX_PATH], *filepart; 2098 DWORD ret; 2099 int i; 2100 2101 const struct 2102 { 2103 LPCWSTR name; 2104 DWORD len; 2105 LPWSTR buffer; 2106 LPWSTR *lastpart; 2107 int win7_expect; 2108 } invalid_parameters[] = 2109 { 2110 {NULL, 0, NULL, NULL}, 2111 {NULL, 0, NULL, &filepart, 1}, 2112 {NULL, MAX_PATH, NULL, NULL}, 2113 {NULL, MAX_PATH, output, NULL}, 2114 {NULL, MAX_PATH, output, &filepart, 1}, 2115 {emptyW, 0, NULL, NULL}, 2116 {emptyW, 0, NULL, &filepart, 1}, 2117 {emptyW, MAX_PATH, NULL, NULL}, 2118 {emptyW, MAX_PATH, output, NULL}, 2119 {emptyW, MAX_PATH, output, &filepart, 1}, 2120 }; 2121 2122 SetLastError(0xdeadbeef); 2123 ret = GetFullPathNameW(NULL, 0, NULL, NULL); 2124 if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 2125 { 2126 win_skip("GetFullPathNameW is not available\n"); 2127 return; 2128 } 2129 2130 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++) 2131 { 2132 SetLastError(0xdeadbeef); 2133 lstrcpyW(output, deadbeefW); 2134 filepart = (WCHAR *)0xdeadbeef; 2135 ret = GetFullPathNameW(invalid_parameters[i].name, 2136 invalid_parameters[i].len, 2137 invalid_parameters[i].buffer, 2138 invalid_parameters[i].lastpart); 2139 ok(!ret, "[%d] Expected GetFullPathNameW to return 0, got %u\n", i, ret); 2140 ok(!lstrcmpW(output, deadbeefW), "[%d] Expected the output buffer to be unchanged, got %s\n", i, wine_dbgstr_w(output)); 2141 ok(filepart == (WCHAR *)0xdeadbeef || 2142 (invalid_parameters[i].win7_expect && filepart == NULL), 2143 "[%d] Expected output file part pointer to be untouched, got %p\n", i, filepart); 2144 ok(GetLastError() == 0xdeadbeef || 2145 GetLastError() == ERROR_INVALID_NAME, /* Win7 */ 2146 "[%d] Expected GetLastError() to return 0xdeadbeef, got %u\n", 2147 i, GetLastError()); 2148 } 2149 } 2150 2151 static void init_pointers(void) 2152 { 2153 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); 2154 2155 #define MAKEFUNC(f) (p##f = (void*)GetProcAddress(hKernel32, #f)) 2156 MAKEFUNC(GetLongPathNameA); 2157 MAKEFUNC(GetLongPathNameW); 2158 MAKEFUNC(NeedCurrentDirectoryForExePathA); 2159 MAKEFUNC(NeedCurrentDirectoryForExePathW); 2160 MAKEFUNC(SearchPathA); 2161 MAKEFUNC(SearchPathW); 2162 MAKEFUNC(SetSearchPathMode); 2163 MAKEFUNC(ActivateActCtx); 2164 MAKEFUNC(CreateActCtxW); 2165 MAKEFUNC(DeactivateActCtx); 2166 MAKEFUNC(GetCurrentActCtx); 2167 MAKEFUNC(ReleaseActCtx); 2168 MAKEFUNC(CheckNameLegalDOS8Dot3W); 2169 MAKEFUNC(CheckNameLegalDOS8Dot3A); 2170 #undef MAKEFUNC 2171 } 2172 2173 static void test_relative_path(void) 2174 { 2175 char path[MAX_PATH], buf[MAX_PATH]; 2176 HANDLE file; 2177 int ret; 2178 WCHAR curdir[MAX_PATH]; 2179 2180 if (!pGetLongPathNameA) return; 2181 2182 GetCurrentDirectoryW(MAX_PATH, curdir); 2183 GetTempPathA(MAX_PATH, path); 2184 ret = SetCurrentDirectoryA(path); 2185 ok(ret, "SetCurrentDirectory error %d\n", GetLastError()); 2186 2187 ret = CreateDirectoryA("foo", NULL); 2188 ok(ret, "CreateDirectory error %d\n", GetLastError()); 2189 file = CreateFileA("foo\\file", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); 2190 ok(file != INVALID_HANDLE_VALUE, "failed to create temp file\n"); 2191 CloseHandle(file); 2192 ret = CreateDirectoryA("bar", NULL); 2193 ok(ret, "CreateDirectory error %d\n", GetLastError()); 2194 ret = SetCurrentDirectoryA("bar"); 2195 ok(ret, "SetCurrentDirectory error %d\n", GetLastError()); 2196 2197 ret = GetFileAttributesA("..\\foo\\file"); 2198 ok(ret != INVALID_FILE_ATTRIBUTES, "GetFileAttributes error %d\n", GetLastError()); 2199 2200 strcpy(buf, "deadbeef"); 2201 ret = pGetLongPathNameA(".", buf, MAX_PATH); 2202 ok(ret, "GetLongPathName error %d\n", GetLastError()); 2203 ok(!strcmp(buf, "."), "expected ., got %s\n", buf); 2204 strcpy(buf, "deadbeef"); 2205 ret = GetShortPathNameA(".", buf, MAX_PATH); 2206 ok(ret, "GetShortPathName error %d\n", GetLastError()); 2207 ok(!strcmp(buf, "."), "expected ., got %s\n", buf); 2208 2209 strcpy(buf, "deadbeef"); 2210 ret = pGetLongPathNameA("..", buf, MAX_PATH); 2211 ok(ret, "GetLongPathName error %d\n", GetLastError()); 2212 ok(!strcmp(buf, ".."), "expected .., got %s\n", buf); 2213 strcpy(buf, "deadbeef"); 2214 ret = GetShortPathNameA("..", buf, MAX_PATH); 2215 ok(ret, "GetShortPathName error %d\n", GetLastError()); 2216 ok(!strcmp(buf, ".."), "expected .., got %s\n", buf); 2217 2218 strcpy(buf, "deadbeef"); 2219 ret = pGetLongPathNameA("..\\foo\\file", buf, MAX_PATH); 2220 ok(ret, "GetLongPathName error %d\n", GetLastError()); 2221 ok(!strcmp(buf, "..\\foo\\file"), "expected ..\\foo\\file, got %s\n", buf); 2222 strcpy(buf, "deadbeef"); 2223 ret = GetShortPathNameA("..\\foo\\file", buf, MAX_PATH); 2224 ok(ret, "GetShortPathName error %d\n", GetLastError()); 2225 ok(!strcmp(buf, "..\\foo\\file"), "expected ..\\foo\\file, got %s\n", buf); 2226 2227 strcpy(buf, "deadbeef"); 2228 ret = pGetLongPathNameA(".\\..\\foo\\file", buf, MAX_PATH); 2229 ok(ret, "GetLongPathName error %d\n", GetLastError()); 2230 ok(!strcmp(buf, ".\\..\\foo\\file"), "expected .\\..\\foo\\file, got %s\n", buf); 2231 strcpy(buf, "deadbeef"); 2232 ret = GetShortPathNameA(".\\..\\foo\\file", buf, MAX_PATH); 2233 ok(ret, "GetShortPathName error %d\n", GetLastError()); 2234 ok(!strcmp(buf, ".\\..\\foo\\file"), "expected .\\..\\foo\\file, got %s\n", buf); 2235 2236 /* test double delimiters */ 2237 strcpy(buf, "deadbeef"); 2238 ret = pGetLongPathNameA("..\\\\foo\\file", buf, MAX_PATH); 2239 ok(ret, "GetLongPathName error %d\n", GetLastError()); 2240 ok(!strcmp(buf, "..\\\\foo\\file"), "expected ..\\\\foo\\file, got %s\n", buf); 2241 strcpy(buf, "deadbeef"); 2242 ret = GetShortPathNameA("..\\\\foo\\file", buf, MAX_PATH); 2243 ok(ret, "GetShortPathName error %d\n", GetLastError()); 2244 ok(!strcmp(buf, "..\\\\foo\\file"), "expected ..\\\\foo\\file, got %s\n", buf); 2245 2246 SetCurrentDirectoryA(".."); 2247 DeleteFileA("foo\\file"); 2248 RemoveDirectoryA("foo"); 2249 RemoveDirectoryA("bar"); 2250 SetCurrentDirectoryW(curdir); 2251 } 2252 2253 static void test_CheckNameLegalDOS8Dot3(void) 2254 { 2255 static const WCHAR has_driveW[] = {'C',':','\\','a','.','t','x','t',0}; 2256 static const WCHAR has_pathW[] = {'b','\\','a','.','t','x','t',0}; 2257 static const WCHAR too_longW[] = {'a','l','o','n','g','f','i','l','e','n','a','m','e','.','t','x','t',0}; 2258 static const WCHAR twodotsW[] = {'t','e','s','t','.','e','s','t','.','t','x','t',0}; 2259 static const WCHAR longextW[] = {'t','e','s','t','.','t','x','t','t','x','t',0}; 2260 static const WCHAR emptyW[] = {0}; 2261 static const WCHAR funnycharsW[] = {'!','#','$','%','&','\'','(',')','.','-','@','^',0}; 2262 static const WCHAR length8W[] = {'t','e','s','t','t','e','s','t','.','t','x','t',0}; 2263 static const WCHAR length1W[] = {'t',0}; 2264 static const WCHAR withspaceW[] = {'t','e','s','t',' ','e','s','t','.','t','x','t',0}; 2265 2266 static const struct { 2267 const WCHAR *name; 2268 BOOL should_be_legal, has_space; 2269 } cases[] = { 2270 {has_driveW, FALSE, FALSE}, 2271 {has_pathW, FALSE, FALSE}, 2272 {too_longW, FALSE, FALSE}, 2273 {twodotsW, FALSE, FALSE}, 2274 {longextW, FALSE, FALSE}, 2275 {emptyW, TRUE /* ! */, FALSE}, 2276 {funnycharsW, TRUE, FALSE}, 2277 {length8W, TRUE, FALSE}, 2278 {length1W, TRUE, FALSE}, 2279 {withspaceW, TRUE, TRUE}, 2280 }; 2281 2282 BOOL br, is_legal, has_space; 2283 char astr[64]; 2284 DWORD i; 2285 2286 if(!pCheckNameLegalDOS8Dot3W){ 2287 win_skip("Missing CheckNameLegalDOS8Dot3, skipping tests\n"); 2288 return; 2289 } 2290 2291 br = pCheckNameLegalDOS8Dot3W(NULL, NULL, 0, NULL, &is_legal); 2292 ok(br == FALSE, "CheckNameLegalDOS8Dot3W should have failed\n"); 2293 2294 br = pCheckNameLegalDOS8Dot3A(NULL, NULL, 0, NULL, &is_legal); 2295 ok(br == FALSE, "CheckNameLegalDOS8Dot3A should have failed\n"); 2296 2297 br = pCheckNameLegalDOS8Dot3W(length8W, NULL, 0, NULL, NULL); 2298 ok(br == FALSE, "CheckNameLegalDOS8Dot3W should have failed\n"); 2299 2300 br = pCheckNameLegalDOS8Dot3A("testtest.txt", NULL, 0, NULL, NULL); 2301 ok(br == FALSE, "CheckNameLegalDOS8Dot3A should have failed\n"); 2302 2303 for(i = 0; i < sizeof(cases)/sizeof(*cases); ++i){ 2304 br = pCheckNameLegalDOS8Dot3W(cases[i].name, NULL, 0, &has_space, &is_legal); 2305 ok(br == TRUE, "CheckNameLegalDOS8Dot3W failed for %s\n", wine_dbgstr_w(cases[i].name)); 2306 ok(is_legal == cases[i].should_be_legal, "Got wrong legality for %s\n", wine_dbgstr_w(cases[i].name)); 2307 if(is_legal) 2308 ok(has_space == cases[i].has_space, "Got wrong space for %s\n", wine_dbgstr_w(cases[i].name)); 2309 2310 WideCharToMultiByte(CP_ACP, 0, cases[i].name, -1, astr, sizeof(astr), NULL, NULL); 2311 2312 br = pCheckNameLegalDOS8Dot3A(astr, NULL, 0, &has_space, &is_legal); 2313 ok(br == TRUE, "CheckNameLegalDOS8Dot3W failed for %s\n", astr); 2314 ok(is_legal == cases[i].should_be_legal, "Got wrong legality for %s\n", astr); 2315 if(is_legal) 2316 ok(has_space == cases[i].has_space, "Got wrong space for %s\n", wine_dbgstr_w(cases[i].name)); 2317 } 2318 } 2319 2320 static void test_SetSearchPathMode(void) 2321 { 2322 BOOL ret; 2323 char orig[MAX_PATH], buf[MAX_PATH], dir[MAX_PATH], expect[MAX_PATH]; 2324 HANDLE handle; 2325 2326 if (!pSetSearchPathMode) 2327 { 2328 win_skip( "SetSearchPathMode isn't available\n" ); 2329 return; 2330 } 2331 GetCurrentDirectoryA( MAX_PATH, orig ); 2332 GetTempPathA( MAX_PATH, buf ); 2333 GetTempFileNameA( buf, "path", 0, dir ); 2334 DeleteFileA( dir ); 2335 CreateDirectoryA( dir, NULL ); 2336 ret = SetCurrentDirectoryA( dir ); 2337 ok( ret, "failed to switch to %s\n", dir ); 2338 if (!ret) 2339 { 2340 RemoveDirectoryA( dir ); 2341 return; 2342 } 2343 2344 handle = CreateFileA( "kernel32.dll", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 ); 2345 CloseHandle( handle ); 2346 2347 SetLastError( 0xdeadbeef ); 2348 ret = pSetSearchPathMode( 0 ); 2349 ok( !ret, "SetSearchPathMode succeeded\n" ); 2350 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); 2351 2352 SetLastError( 0xdeadbeef ); 2353 ret = pSetSearchPathMode( 0x80 ); 2354 ok( !ret, "SetSearchPathMode succeeded\n" ); 2355 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); 2356 2357 SetLastError( 0xdeadbeef ); 2358 ret = pSetSearchPathMode( BASE_SEARCH_PATH_PERMANENT ); 2359 ok( !ret, "SetSearchPathMode succeeded\n" ); 2360 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); 2361 2362 SetLastError( 0xdeadbeef ); 2363 ret = SearchPathA( NULL, "kernel32.dll", NULL, MAX_PATH, buf, NULL ); 2364 ok( ret, "SearchPathA failed err %u\n", GetLastError() ); 2365 GetCurrentDirectoryA( MAX_PATH, expect ); 2366 strcat( expect, "\\kernel32.dll" ); 2367 ok( !lstrcmpiA( buf, expect ), "found %s expected %s\n", buf, expect ); 2368 2369 SetLastError( 0xdeadbeef ); 2370 ret = pSetSearchPathMode( BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE ); 2371 ok( ret, "SetSearchPathMode failed err %u\n", GetLastError() ); 2372 2373 SetLastError( 0xdeadbeef ); 2374 ret = SearchPathA( NULL, "kernel32.dll", NULL, MAX_PATH, buf, NULL ); 2375 ok( ret, "SearchPathA failed err %u\n", GetLastError() ); 2376 GetSystemDirectoryA( expect, MAX_PATH ); 2377 strcat( expect, "\\kernel32.dll" ); 2378 ok( !lstrcmpiA( buf, expect ), "found %s expected %s\n", buf, expect ); 2379 2380 SetLastError( 0xdeadbeef ); 2381 ret = pSetSearchPathMode( BASE_SEARCH_PATH_DISABLE_SAFE_SEARCHMODE ); 2382 ok( ret, "SetSearchPathMode failed err %u\n", GetLastError() ); 2383 2384 SetLastError( 0xdeadbeef ); 2385 ret = SearchPathA( NULL, "kernel32.dll", NULL, MAX_PATH, buf, NULL ); 2386 ok( ret, "SearchPathA failed err %u\n", GetLastError() ); 2387 GetCurrentDirectoryA( MAX_PATH, expect ); 2388 strcat( expect, "\\kernel32.dll" ); 2389 ok( !lstrcmpiA( buf, expect ), "found %s expected %s\n", buf, expect ); 2390 2391 SetLastError( 0xdeadbeef ); 2392 ret = pSetSearchPathMode( BASE_SEARCH_PATH_DISABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT ); 2393 ok( !ret, "SetSearchPathMode succeeded\n" ); 2394 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); 2395 2396 SetLastError( 0xdeadbeef ); 2397 ret = pSetSearchPathMode( BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT ); 2398 ok( ret, "SetSearchPathMode failed err %u\n", GetLastError() ); 2399 2400 SetLastError( 0xdeadbeef ); 2401 ret = pSetSearchPathMode( BASE_SEARCH_PATH_DISABLE_SAFE_SEARCHMODE ); 2402 ok( !ret, "SetSearchPathMode succeeded\n" ); 2403 ok( GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError() ); 2404 2405 SetLastError( 0xdeadbeef ); 2406 ret = pSetSearchPathMode( BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE ); 2407 ok( !ret, "SetSearchPathMode succeeded\n" ); 2408 ok( GetLastError() == ERROR_ACCESS_DENIED, "wrong error %u\n", GetLastError() ); 2409 2410 SetLastError( 0xdeadbeef ); 2411 ret = pSetSearchPathMode( BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT ); 2412 ok( ret, "SetSearchPathMode failed err %u\n", GetLastError() ); 2413 2414 SetLastError( 0xdeadbeef ); 2415 ret = SearchPathA( NULL, "kernel32.dll", NULL, MAX_PATH, buf, NULL ); 2416 ok( ret, "SearchPathA failed err %u\n", GetLastError() ); 2417 GetSystemDirectoryA( expect, MAX_PATH ); 2418 strcat( expect, "\\kernel32.dll" ); 2419 ok( !lstrcmpiA( buf, expect ), "found %s expected %s\n", buf, expect ); 2420 2421 DeleteFileA( "kernel32.dll" ); 2422 SetCurrentDirectoryA( orig ); 2423 RemoveDirectoryA( dir ); 2424 } 2425 2426 START_TEST(path) 2427 { 2428 CHAR origdir[MAX_PATH],curdir[MAX_PATH], curDrive, otherDrive; 2429 2430 init_pointers(); 2431 2432 /* Report only once */ 2433 if (!pGetLongPathNameA) 2434 win_skip("GetLongPathNameA is not available\n"); 2435 if (!pGetLongPathNameW) 2436 win_skip("GetLongPathNameW is not available\n"); 2437 if (!pActivateActCtx) 2438 win_skip("Activation contexts not supported, some tests will be skipped\n"); 2439 2440 test_relative_path(); 2441 test_InitPathA(curdir, &curDrive, &otherDrive); 2442 test_CurrentDirectoryA(origdir,curdir); 2443 test_PathNameA(curdir, curDrive, otherDrive); 2444 test_CleanupPathA(origdir,curdir); 2445 test_GetTempPath(); 2446 test_GetLongPathNameA(); 2447 test_GetLongPathNameW(); 2448 test_GetShortPathNameW(); 2449 test_GetSystemDirectory(); 2450 test_GetWindowsDirectory(); 2451 test_NeedCurrentDirectoryForExePathA(); 2452 test_NeedCurrentDirectoryForExePathW(); 2453 test_drive_letter_case(); 2454 test_SearchPathA(); 2455 test_SearchPathW(); 2456 test_GetFullPathNameA(); 2457 test_GetFullPathNameW(); 2458 test_CheckNameLegalDOS8Dot3(); 2459 test_SetSearchPathMode(); 2460 } 2461