1 /* vdir.h 2 * 3 * (c) 1999 Microsoft Corporation. All rights reserved. 4 * Portions (c) 1999 ActiveState Tool Corp, http://www.ActiveState.com/ 5 * 6 * You may distribute under the terms of either the GNU General Public 7 * License or the Artistic License, as specified in the README file. 8 */ 9 10 #ifndef ___VDir_H___ 11 #define ___VDir_H___ 12 13 /* 14 * Allow one slot for each possible drive letter 15 * and one additional slot for a UNC name 16 */ 17 const int driveCount = ('Z'-'A')+1+1; 18 const int driveLetterCount = ('Z'-'A')+1; 19 20 class VDir 21 { 22 public: 23 VDir(int bManageDir = 1); 24 ~VDir() {}; 25 26 void Init(VDir* pDir, VMem *pMem); 27 void SetDefaultA(char const *pDefault); 28 void SetDefaultW(WCHAR const *pDefault); 29 char* MapPathA(const char *pInName); 30 WCHAR* MapPathW(const WCHAR *pInName); 31 int SetCurrentDirectoryA(char *lpBuffer); 32 int SetCurrentDirectoryW(WCHAR *lpBuffer); 33 inline int GetDefault(void) { return nDefault; }; 34 35 inline char* GetCurrentDirectoryA(int dwBufSize, char *lpBuffer) 36 { 37 char* ptr = dirTableA[nDefault]; 38 while (--dwBufSize) 39 { 40 if ((*lpBuffer++ = *ptr++) == '\0') 41 break; 42 } 43 *lpBuffer = '\0'; 44 return /* unused */ NULL; 45 }; 46 inline WCHAR* GetCurrentDirectoryW(int dwBufSize, WCHAR *lpBuffer) 47 { 48 WCHAR* ptr = dirTableW[nDefault]; 49 while (--dwBufSize) 50 { 51 if ((*lpBuffer++ = *ptr++) == '\0') 52 break; 53 } 54 *lpBuffer = '\0'; 55 return /* unused */ NULL; 56 }; 57 58 DWORD CalculateEnvironmentSpace(void); 59 LPSTR BuildEnvironmentSpace(LPSTR lpStr); 60 61 protected: 62 int SetDirA(char const *pPath, int index); 63 int SetDirW(WCHAR const *pPath, int index); 64 void FromEnvA(char *pEnv, int index); 65 void FromEnvW(WCHAR *pEnv, int index); 66 67 inline const char *GetDefaultDirA(void) 68 { 69 return dirTableA[nDefault]; 70 }; 71 inline void SetDefaultDirA(char const *pPath, int index) 72 { 73 SetDirA(pPath, index); 74 nDefault = index; 75 }; 76 inline const WCHAR *GetDefaultDirW(void) 77 { 78 return dirTableW[nDefault]; 79 }; 80 inline void SetDefaultDirW(WCHAR const *pPath, int index) 81 { 82 SetDirW(pPath, index); 83 nDefault = index; 84 }; 85 inline const char *GetDirA(int index) 86 { 87 char *ptr = dirTableA[index]; 88 if (!ptr) { 89 /* simulate the existence of this drive */ 90 ptr = szLocalBufferA; 91 ptr[0] = 'A' + index; 92 ptr[1] = ':'; 93 ptr[2] = '\\'; 94 ptr[3] = 0; 95 } 96 return ptr; 97 }; 98 inline const WCHAR *GetDirW(int index) 99 { 100 WCHAR *ptr = dirTableW[index]; 101 if (!ptr) { 102 /* simulate the existence of this drive */ 103 ptr = szLocalBufferW; 104 ptr[0] = 'A' + index; 105 ptr[1] = ':'; 106 ptr[2] = '\\'; 107 ptr[3] = 0; 108 } 109 return ptr; 110 }; 111 112 inline int DriveIndex(char chr) 113 { 114 if (chr == '\\' || chr == '/') 115 return ('Z'-'A')+1; 116 return (chr | 0x20)-'a'; 117 }; 118 119 VMem *pMem; 120 int nDefault, bManageDirectory; 121 char *dirTableA[driveCount]; 122 char szLocalBufferA[MAX_PATH+1]; 123 WCHAR *dirTableW[driveCount]; 124 WCHAR szLocalBufferW[MAX_PATH+1]; 125 }; 126 127 128 VDir::VDir(int bManageDir /* = 1 */) 129 { 130 nDefault = 0; 131 bManageDirectory = bManageDir; 132 memset(dirTableA, 0, sizeof(dirTableA)); 133 memset(dirTableW, 0, sizeof(dirTableW)); 134 } 135 136 void VDir::Init(VDir* pDir, VMem *p) 137 { 138 int index; 139 140 pMem = p; 141 if (pDir) { 142 for (index = 0; index < driveCount; ++index) { 143 SetDirW(pDir->GetDirW(index), index); 144 } 145 nDefault = pDir->GetDefault(); 146 } 147 else { 148 int bSave = bManageDirectory; 149 DWORD driveBits = GetLogicalDrives(); 150 151 bManageDirectory = 0; 152 WCHAR szBuffer[MAX_PATH*driveCount]; 153 if (GetLogicalDriveStringsW(sizeof(szBuffer), szBuffer)) { 154 WCHAR* pEnv = GetEnvironmentStringsW(); 155 WCHAR* ptr = szBuffer; 156 for (index = 0; index < driveCount; ++index) { 157 if (driveBits & (1<<index)) { 158 ptr += SetDirW(ptr, index) + 1; 159 FromEnvW(pEnv, index); 160 } 161 } 162 FreeEnvironmentStringsW(pEnv); 163 } 164 SetDefaultW(L"."); 165 bManageDirectory = bSave; 166 } 167 } 168 169 int VDir::SetDirA(char const *pPath, int index) 170 { 171 char chr, *ptr; 172 int length = 0; 173 WCHAR wBuffer[MAX_PATH+1]; 174 if (index < driveCount && pPath != NULL) { 175 length = strlen(pPath); 176 pMem->Free(dirTableA[index]); 177 ptr = dirTableA[index] = (char*)pMem->Malloc(length+2); 178 if (ptr != NULL) { 179 strcpy(ptr, pPath); 180 ptr += length-1; 181 chr = *ptr++; 182 if (chr != '\\' && chr != '/') { 183 *ptr++ = '\\'; 184 *ptr = '\0'; 185 } 186 MultiByteToWideChar(CP_ACP, 0, dirTableA[index], -1, 187 wBuffer, (sizeof(wBuffer)/sizeof(WCHAR))); 188 length = wcslen(wBuffer); 189 pMem->Free(dirTableW[index]); 190 dirTableW[index] = (WCHAR*)pMem->Malloc((length+1)*2); 191 if (dirTableW[index] != NULL) { 192 wcscpy(dirTableW[index], wBuffer); 193 } 194 } 195 } 196 197 if(bManageDirectory) 198 ::SetCurrentDirectoryA(pPath); 199 200 return length; 201 } 202 203 void VDir::FromEnvA(char *pEnv, int index) 204 { /* gets the directory for index from the environment variable. */ 205 while (*pEnv != '\0') { 206 if ((pEnv[0] == '=') && (DriveIndex(pEnv[1]) == index) 207 && pEnv[2] == ':' && pEnv[3] == '=') { 208 SetDirA(&pEnv[4], index); 209 break; 210 } 211 else 212 pEnv += strlen(pEnv)+1; 213 } 214 } 215 216 void VDir::FromEnvW(WCHAR *pEnv, int index) 217 { /* gets the directory for index from the environment variable. */ 218 while (*pEnv != '\0') { 219 if ((pEnv[0] == '=') && (DriveIndex((char)pEnv[1]) == index) 220 && pEnv[2] == ':' && pEnv[3] == '=') { 221 SetDirW(&pEnv[4], index); 222 break; 223 } 224 else 225 pEnv += wcslen(pEnv)+1; 226 } 227 } 228 229 void VDir::SetDefaultA(char const *pDefault) 230 { 231 char szBuffer[MAX_PATH+1]; 232 char *pPtr; 233 234 if (GetFullPathNameA(pDefault, sizeof(szBuffer), szBuffer, &pPtr)) { 235 if (*pDefault != '.' && pPtr != NULL) 236 *pPtr = '\0'; 237 238 SetDefaultDirA(szBuffer, DriveIndex(szBuffer[0])); 239 } 240 } 241 242 int VDir::SetDirW(WCHAR const *pPath, int index) 243 { 244 WCHAR chr, *ptr; 245 int length = 0; 246 if (index < driveCount && pPath != NULL) { 247 length = wcslen(pPath); 248 pMem->Free(dirTableW[index]); 249 ptr = dirTableW[index] = (WCHAR*)pMem->Malloc((length+2)*2); 250 if (ptr != NULL) { 251 char *ansi; 252 wcscpy(ptr, pPath); 253 ptr += length-1; 254 chr = *ptr++; 255 if (chr != '\\' && chr != '/') { 256 *ptr++ = '\\'; 257 *ptr = '\0'; 258 } 259 ansi = win32_ansipath(dirTableW[index]); 260 length = strlen(ansi); 261 pMem->Free(dirTableA[index]); 262 dirTableA[index] = (char*)pMem->Malloc(length+1); 263 if (dirTableA[index] != NULL) { 264 strcpy(dirTableA[index], ansi); 265 } 266 win32_free(ansi); 267 } 268 } 269 270 if(bManageDirectory) 271 ::SetCurrentDirectoryW(pPath); 272 273 return length; 274 } 275 276 void VDir::SetDefaultW(WCHAR const *pDefault) 277 { 278 WCHAR szBuffer[MAX_PATH+1]; 279 WCHAR *pPtr; 280 281 if (GetFullPathNameW(pDefault, (sizeof(szBuffer)/sizeof(WCHAR)), szBuffer, &pPtr)) { 282 if (*pDefault != '.' && pPtr != NULL) 283 *pPtr = '\0'; 284 285 SetDefaultDirW(szBuffer, DriveIndex((char)szBuffer[0])); 286 } 287 } 288 289 inline BOOL IsPathSep(char ch) 290 { 291 return (ch == '\\' || ch == '/'); 292 } 293 294 inline void DoGetFullPathNameA(char* lpBuffer, DWORD dwSize, char* Dest) 295 { 296 char *pPtr; 297 298 /* 299 * On WinNT GetFullPathName does not fail, (or at least always 300 * succeeds when the drive is valid) WinNT does set *Dest to NULL 301 * On Win98 GetFullPathName will set last error if it fails, but 302 * does not touch *Dest 303 */ 304 *Dest = '\0'; 305 GetFullPathNameA(lpBuffer, dwSize, Dest, &pPtr); 306 } 307 308 inline bool IsSpecialFileName(const char* pName) 309 { 310 /* specical file names are devices that the system can open 311 * these include AUX, CON, NUL, PRN, COMx, LPTx, CLOCK$, CONIN$, CONOUT$ 312 * (x is a single digit, and names are case-insensitive) 313 */ 314 char ch = (pName[0] & ~0x20); 315 switch (ch) 316 { 317 case 'A': /* AUX */ 318 if (((pName[1] & ~0x20) == 'U') 319 && ((pName[2] & ~0x20) == 'X') 320 && !pName[3]) 321 return true; 322 break; 323 case 'C': /* CLOCK$, COMx, CON, CONIN$ CONOUT$ */ 324 ch = (pName[1] & ~0x20); 325 switch (ch) 326 { 327 case 'L': /* CLOCK$ */ 328 if (((pName[2] & ~0x20) == 'O') 329 && ((pName[3] & ~0x20) == 'C') 330 && ((pName[4] & ~0x20) == 'K') 331 && (pName[5] == '$') 332 && !pName[6]) 333 return true; 334 break; 335 case 'O': /* COMx, CON, CONIN$ CONOUT$ */ 336 if ((pName[2] & ~0x20) == 'M') { 337 if ( inRANGE(pName[3], '1', '9') 338 && !pName[4]) 339 return true; 340 } 341 else if ((pName[2] & ~0x20) == 'N') { 342 if (!pName[3]) 343 return true; 344 else if ((pName[3] & ~0x20) == 'I') { 345 if (((pName[4] & ~0x20) == 'N') 346 && (pName[5] == '$') 347 && !pName[6]) 348 return true; 349 } 350 else if ((pName[3] & ~0x20) == 'O') { 351 if (((pName[4] & ~0x20) == 'U') 352 && ((pName[5] & ~0x20) == 'T') 353 && (pName[6] == '$') 354 && !pName[7]) 355 return true; 356 } 357 } 358 break; 359 } 360 break; 361 case 'L': /* LPTx */ 362 if (((pName[1] & ~0x20) == 'U') 363 && ((pName[2] & ~0x20) == 'X') 364 && inRANGE(pName[3], '1', '9') 365 && !pName[4]) 366 return true; 367 break; 368 case 'N': /* NUL */ 369 if (((pName[1] & ~0x20) == 'U') 370 && ((pName[2] & ~0x20) == 'L') 371 && !pName[3]) 372 return true; 373 break; 374 case 'P': /* PRN */ 375 if (((pName[1] & ~0x20) == 'R') 376 && ((pName[2] & ~0x20) == 'N') 377 && !pName[3]) 378 return true; 379 break; 380 } 381 return false; 382 } 383 384 char *VDir::MapPathA(const char *pInName) 385 { /* 386 * possiblities -- relative path or absolute path with or without drive letter 387 * OR UNC name 388 */ 389 int driveIndex; 390 char szBuffer[(MAX_PATH+1)*2]; 391 char szlBuf[MAX_PATH+1]; 392 int length = strlen(pInName); 393 394 if (!length) 395 return (char*)pInName; 396 397 if (length > MAX_PATH) { 398 strncpy(szlBuf, pInName, MAX_PATH); 399 if (IsPathSep(pInName[0]) && !IsPathSep(pInName[1])) { 400 /* absolute path - reduce length by 2 for drive specifier */ 401 szlBuf[MAX_PATH-2] = '\0'; 402 } 403 else 404 szlBuf[MAX_PATH] = '\0'; 405 pInName = szlBuf; 406 } 407 /* strlen(pInName) is now <= MAX_PATH */ 408 409 if (length > 1 && pInName[1] == ':') { 410 /* has drive letter */ 411 if (length > 2 && IsPathSep(pInName[2])) { 412 /* absolute with drive letter */ 413 DoGetFullPathNameA((char*)pInName, sizeof(szLocalBufferA), szLocalBufferA); 414 } 415 else { 416 /* relative path with drive letter */ 417 driveIndex = DriveIndex(*pInName); 418 if (driveIndex < 0 || driveIndex >= driveLetterCount) 419 return (char *)pInName; 420 strcpy(szBuffer, GetDirA(driveIndex)); 421 strcat(szBuffer, &pInName[2]); 422 if(strlen(szBuffer) > MAX_PATH) 423 szBuffer[MAX_PATH] = '\0'; 424 425 DoGetFullPathNameA(szBuffer, sizeof(szLocalBufferA), szLocalBufferA); 426 } 427 } 428 else { 429 /* no drive letter */ 430 if (length > 1 && IsPathSep(pInName[1]) && IsPathSep(pInName[0])) { 431 /* UNC name */ 432 DoGetFullPathNameA((char*)pInName, sizeof(szLocalBufferA), szLocalBufferA); 433 } 434 else { 435 strcpy(szBuffer, GetDefaultDirA()); 436 if (IsPathSep(pInName[0])) { 437 /* absolute path */ 438 strcpy(&szBuffer[2], pInName); 439 DoGetFullPathNameA(szBuffer, sizeof(szLocalBufferA), szLocalBufferA); 440 } 441 else { 442 /* relative path */ 443 if (IsSpecialFileName(pInName)) { 444 return (char*)pInName; 445 } 446 else { 447 strcat(szBuffer, pInName); 448 if (strlen(szBuffer) > MAX_PATH) 449 szBuffer[MAX_PATH] = '\0'; 450 451 DoGetFullPathNameA(szBuffer, sizeof(szLocalBufferA), szLocalBufferA); 452 } 453 } 454 } 455 } 456 457 return szLocalBufferA; 458 } 459 460 int VDir::SetCurrentDirectoryA(char *lpBuffer) 461 { 462 char *pPtr; 463 int length, nRet = -1; 464 465 pPtr = MapPathA(lpBuffer); 466 length = strlen(pPtr); 467 if(length > 3 && IsPathSep(pPtr[length-1])) { 468 /* don't remove the trailing slash from 'x:\' */ 469 pPtr[length-1] = '\0'; 470 } 471 472 DWORD r = GetFileAttributesA(pPtr); 473 if ((r != 0xffffffff) && (r & FILE_ATTRIBUTE_DIRECTORY)) 474 { 475 char szBuffer[(MAX_PATH+1)*2]; 476 DoGetFullPathNameA(pPtr, sizeof(szBuffer), szBuffer); 477 SetDefaultDirA(szBuffer, DriveIndex(szBuffer[0])); 478 nRet = 0; 479 } 480 481 return nRet; 482 } 483 484 DWORD VDir::CalculateEnvironmentSpace(void) 485 { /* the current directory environment strings are stored as '=D:=d:\path' */ 486 int index; 487 DWORD dwSize = 0; 488 for (index = 0; index < driveCount; ++index) { 489 if (dirTableA[index] != NULL) { 490 dwSize += strlen(dirTableA[index]) + 5; /* add 1 for trailing NULL and 4 for '=D:=' */ 491 } 492 } 493 return dwSize; 494 } 495 496 LPSTR VDir::BuildEnvironmentSpace(LPSTR lpStr) 497 { /* store the current directory environment strings as '=D:=d:\path' */ 498 int index, length; 499 LPSTR lpDirStr; 500 for (index = 0; index < driveCount; ++index) { 501 lpDirStr = dirTableA[index]; 502 if (lpDirStr != NULL) { 503 lpStr[0] = '='; 504 lpStr[1] = lpDirStr[0]; 505 lpStr[2] = '\0'; 506 CharUpper(&lpStr[1]); 507 lpStr[2] = ':'; 508 lpStr[3] = '='; 509 strcpy(&lpStr[4], lpDirStr); 510 length = strlen(lpDirStr); 511 lpStr += length + 5; /* add 1 for trailing NULL and 4 for '=D:=' */ 512 if (length > 3 && IsPathSep(lpStr[-2])) { 513 lpStr[-2] = '\0'; /* remove the trailing path separator */ 514 --lpStr; 515 } 516 } 517 } 518 return lpStr; 519 } 520 521 inline BOOL IsPathSep(WCHAR ch) 522 { 523 return (ch == '\\' || ch == '/'); 524 } 525 526 inline void DoGetFullPathNameW(WCHAR* lpBuffer, DWORD dwSize, WCHAR* Dest) 527 { 528 WCHAR *pPtr; 529 530 /* 531 * On WinNT GetFullPathName does not fail, (or at least always 532 * succeeds when the drive is valid) WinNT does set *Dest to NULL 533 * On Win98 GetFullPathName will set last error if it fails, but 534 * does not touch *Dest 535 */ 536 *Dest = '\0'; 537 GetFullPathNameW(lpBuffer, dwSize, Dest, &pPtr); 538 } 539 540 inline bool IsSpecialFileName(const WCHAR* pName) 541 { 542 /* specical file names are devices that the system can open 543 * these include AUX, CON, NUL, PRN, COMx, LPTx, CLOCK$, CONIN$, CONOUT$ 544 * (x is a single digit, and names are case-insensitive) 545 */ 546 WCHAR ch = (pName[0] & ~0x20); 547 switch (ch) 548 { 549 case 'A': /* AUX */ 550 if (((pName[1] & ~0x20) == 'U') 551 && ((pName[2] & ~0x20) == 'X') 552 && !pName[3]) 553 return true; 554 break; 555 case 'C': /* CLOCK$, COMx, CON, CONIN$ CONOUT$ */ 556 ch = (pName[1] & ~0x20); 557 switch (ch) 558 { 559 case 'L': /* CLOCK$ */ 560 if (((pName[2] & ~0x20) == 'O') 561 && ((pName[3] & ~0x20) == 'C') 562 && ((pName[4] & ~0x20) == 'K') 563 && (pName[5] == '$') 564 && !pName[6]) 565 return true; 566 break; 567 case 'O': /* COMx, CON, CONIN$ CONOUT$ */ 568 if ((pName[2] & ~0x20) == 'M') { 569 if ( inRANGE(pName[3], '1', '9') 570 && !pName[4]) 571 return true; 572 } 573 else if ((pName[2] & ~0x20) == 'N') { 574 if (!pName[3]) 575 return true; 576 else if ((pName[3] & ~0x20) == 'I') { 577 if (((pName[4] & ~0x20) == 'N') 578 && (pName[5] == '$') 579 && !pName[6]) 580 return true; 581 } 582 else if ((pName[3] & ~0x20) == 'O') { 583 if (((pName[4] & ~0x20) == 'U') 584 && ((pName[5] & ~0x20) == 'T') 585 && (pName[6] == '$') 586 && !pName[7]) 587 return true; 588 } 589 } 590 break; 591 } 592 break; 593 case 'L': /* LPTx */ 594 if (((pName[1] & ~0x20) == 'U') 595 && ((pName[2] & ~0x20) == 'X') 596 && inRANGE(pName[3], '1', '9') 597 && !pName[4]) 598 return true; 599 break; 600 case 'N': /* NUL */ 601 if (((pName[1] & ~0x20) == 'U') 602 && ((pName[2] & ~0x20) == 'L') 603 && !pName[3]) 604 return true; 605 break; 606 case 'P': /* PRN */ 607 if (((pName[1] & ~0x20) == 'R') 608 && ((pName[2] & ~0x20) == 'N') 609 && !pName[3]) 610 return true; 611 break; 612 } 613 return false; 614 } 615 616 WCHAR* VDir::MapPathW(const WCHAR *pInName) 617 { /* 618 * possiblities -- relative path or absolute path with or without drive letter 619 * OR UNC name 620 */ 621 int driveIndex; 622 WCHAR szBuffer[(MAX_PATH+1)*2]; 623 WCHAR szlBuf[MAX_PATH+1]; 624 int length = wcslen(pInName); 625 626 if (!length) 627 return (WCHAR*)pInName; 628 629 if (length > MAX_PATH) { 630 wcsncpy(szlBuf, pInName, MAX_PATH); 631 if (IsPathSep(pInName[0]) && !IsPathSep(pInName[1])) { 632 /* absolute path - reduce length by 2 for drive specifier */ 633 szlBuf[MAX_PATH-2] = '\0'; 634 } 635 else 636 szlBuf[MAX_PATH] = '\0'; 637 pInName = szlBuf; 638 } 639 /* strlen(pInName) is now <= MAX_PATH */ 640 641 if (length > 1 && pInName[1] == ':') { 642 /* has drive letter */ 643 if (IsPathSep(pInName[2])) { 644 /* absolute with drive letter */ 645 DoGetFullPathNameW((WCHAR*)pInName, (sizeof(szLocalBufferW)/sizeof(WCHAR)), szLocalBufferW); 646 } 647 else { 648 /* relative path with drive letter */ 649 driveIndex = DriveIndex(*pInName); 650 if (driveIndex < 0 || driveIndex >= driveLetterCount) 651 return (WCHAR *)pInName; 652 wcscpy(szBuffer, GetDirW(driveIndex)); 653 wcscat(szBuffer, &pInName[2]); 654 if(wcslen(szBuffer) > MAX_PATH) 655 szBuffer[MAX_PATH] = '\0'; 656 657 DoGetFullPathNameW(szBuffer, (sizeof(szLocalBufferW)/sizeof(WCHAR)), szLocalBufferW); 658 } 659 } 660 else { 661 /* no drive letter */ 662 if (length > 1 && IsPathSep(pInName[1]) && IsPathSep(pInName[0])) { 663 /* UNC name */ 664 DoGetFullPathNameW((WCHAR*)pInName, (sizeof(szLocalBufferW)/sizeof(WCHAR)), szLocalBufferW); 665 } 666 else { 667 wcscpy(szBuffer, GetDefaultDirW()); 668 if (IsPathSep(pInName[0])) { 669 /* absolute path */ 670 wcscpy(&szBuffer[2], pInName); 671 DoGetFullPathNameW(szBuffer, (sizeof(szLocalBufferW)/sizeof(WCHAR)), szLocalBufferW); 672 } 673 else { 674 /* relative path */ 675 if (IsSpecialFileName(pInName)) { 676 return (WCHAR*)pInName; 677 } 678 else { 679 wcscat(szBuffer, pInName); 680 if (wcslen(szBuffer) > MAX_PATH) 681 szBuffer[MAX_PATH] = '\0'; 682 683 DoGetFullPathNameW(szBuffer, (sizeof(szLocalBufferW)/sizeof(WCHAR)), szLocalBufferW); 684 } 685 } 686 } 687 } 688 return szLocalBufferW; 689 } 690 691 int VDir::SetCurrentDirectoryW(WCHAR *lpBuffer) 692 { 693 WCHAR *pPtr; 694 int length, nRet = -1; 695 696 pPtr = MapPathW(lpBuffer); 697 length = wcslen(pPtr); 698 if(length > 3 && IsPathSep(pPtr[length-1])) { 699 /* don't remove the trailing slash from 'x:\' */ 700 pPtr[length-1] = '\0'; 701 } 702 703 DWORD r = GetFileAttributesW(pPtr); 704 if ((r != 0xffffffff) && (r & FILE_ATTRIBUTE_DIRECTORY)) 705 { 706 WCHAR wBuffer[(MAX_PATH+1)*2]; 707 DoGetFullPathNameW(pPtr, (sizeof(wBuffer)/sizeof(WCHAR)), wBuffer); 708 SetDefaultDirW(wBuffer, DriveIndex((char)wBuffer[0])); 709 nRet = 0; 710 } 711 712 return nRet; 713 } 714 715 #endif /* ___VDir_H___ */ 716