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