1 // Windows/FileDir.cpp 2 3 #include "StdAfx.h" 4 5 #ifndef _UNICODE 6 #include "../Common/StringConvert.h" 7 #endif 8 9 #include "FileDir.h" 10 #include "FileFind.h" 11 #include "FileName.h" 12 13 #ifndef _UNICODE 14 extern bool g_IsNT; 15 #endif 16 17 namespace NWindows { 18 namespace NFile { 19 20 #if defined(WIN_LONG_PATH) && defined(_UNICODE) 21 #define WIN_LONG_PATH2 22 #endif 23 24 // SetCurrentDirectory doesn't support \\?\ prefix 25 26 #ifdef WIN_LONG_PATH 27 bool GetLongPathBase(LPCWSTR fileName, UString &res); 28 bool GetLongPath(LPCWSTR fileName, UString &res); 29 #endif 30 31 namespace NDirectory { 32 33 #ifndef _UNICODE 34 static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; } 35 static UString GetUnicodePath(const CSysString &sysPath) 36 { return MultiByteToUnicodeString(sysPath, GetCurrentCodePage()); } 37 static CSysString GetSysPath(LPCWSTR sysPath) 38 { return UnicodeStringToMultiByte(sysPath, GetCurrentCodePage()); } 39 #endif 40 41 #ifndef UNDER_CE 42 43 bool MyGetWindowsDirectory(CSysString &path) 44 { 45 UINT needLength = ::GetWindowsDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); 46 path.ReleaseBuffer(); 47 return (needLength > 0 && needLength <= MAX_PATH); 48 } 49 50 bool MyGetSystemDirectory(CSysString &path) 51 { 52 UINT needLength = ::GetSystemDirectory(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); 53 path.ReleaseBuffer(); 54 return (needLength > 0 && needLength <= MAX_PATH); 55 } 56 57 #endif 58 59 #ifndef _UNICODE 60 bool MyGetWindowsDirectory(UString &path) 61 { 62 if (g_IsNT) 63 { 64 UINT needLength = ::GetWindowsDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); 65 path.ReleaseBuffer(); 66 return (needLength > 0 && needLength <= MAX_PATH); 67 } 68 CSysString sysPath; 69 if (!MyGetWindowsDirectory(sysPath)) 70 return false; 71 path = GetUnicodePath(sysPath); 72 return true; 73 } 74 75 bool MyGetSystemDirectory(UString &path) 76 { 77 if (g_IsNT) 78 { 79 UINT needLength = ::GetSystemDirectoryW(path.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); 80 path.ReleaseBuffer(); 81 return (needLength > 0 && needLength <= MAX_PATH); 82 } 83 CSysString sysPath; 84 if (!MyGetSystemDirectory(sysPath)) 85 return false; 86 path = GetUnicodePath(sysPath); 87 return true; 88 } 89 #endif 90 91 bool SetDirTime(LPCWSTR fileName, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime) 92 { 93 #ifndef _UNICODE 94 if (!g_IsNT) 95 { 96 ::SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 97 return false; 98 } 99 #endif 100 HANDLE hDir = ::CreateFileW(fileName, GENERIC_WRITE, 101 FILE_SHARE_READ | FILE_SHARE_WRITE, 102 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); 103 #ifdef WIN_LONG_PATH 104 if (hDir == INVALID_HANDLE_VALUE) 105 { 106 UString longPath; 107 if (GetLongPath(fileName, longPath)) 108 hDir = ::CreateFileW(longPath, GENERIC_WRITE, 109 FILE_SHARE_READ | FILE_SHARE_WRITE, 110 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); 111 } 112 #endif 113 114 bool res = false; 115 if (hDir != INVALID_HANDLE_VALUE) 116 { 117 res = BOOLToBool(::SetFileTime(hDir, cTime, aTime, mTime)); 118 ::CloseHandle(hDir); 119 } 120 return res; 121 } 122 123 bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes) 124 { 125 if (::SetFileAttributes(fileName, fileAttributes)) 126 return true; 127 #ifdef WIN_LONG_PATH2 128 UString longPath; 129 if (GetLongPath(fileName, longPath)) 130 return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); 131 #endif 132 return false; 133 } 134 135 bool MyRemoveDirectory(LPCTSTR pathName) 136 { 137 if (::RemoveDirectory(pathName)) 138 return true; 139 #ifdef WIN_LONG_PATH2 140 UString longPath; 141 if (GetLongPath(pathName, longPath)) 142 return BOOLToBool(::RemoveDirectoryW(longPath)); 143 #endif 144 return false; 145 } 146 147 #ifdef WIN_LONG_PATH 148 bool GetLongPaths(LPCWSTR s1, LPCWSTR s2, UString &d1, UString &d2) 149 { 150 if (!GetLongPathBase(s1, d1) || !GetLongPathBase(s2, d2)) 151 return false; 152 if (d1.IsEmpty() && d2.IsEmpty()) return false; 153 if (d1.IsEmpty()) d1 = s1; 154 if (d2.IsEmpty()) d2 = s2; 155 return true; 156 } 157 #endif 158 159 bool MyMoveFile(LPCTSTR existFileName, LPCTSTR newFileName) 160 { 161 if (::MoveFile(existFileName, newFileName)) 162 return true; 163 #ifdef WIN_LONG_PATH2 164 UString d1, d2; 165 if (GetLongPaths(existFileName, newFileName, d1, d2)) 166 return BOOLToBool(::MoveFileW(d1, d2)); 167 #endif 168 return false; 169 } 170 171 #ifndef _UNICODE 172 bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes) 173 { 174 if (!g_IsNT) 175 return MySetFileAttributes(GetSysPath(fileName), fileAttributes); 176 if (::SetFileAttributesW(fileName, fileAttributes)) 177 return true; 178 #ifdef WIN_LONG_PATH 179 UString longPath; 180 if (GetLongPath(fileName, longPath)) 181 return BOOLToBool(::SetFileAttributesW(longPath, fileAttributes)); 182 #endif 183 return false; 184 } 185 186 187 bool MyRemoveDirectory(LPCWSTR pathName) 188 { 189 if (!g_IsNT) 190 return MyRemoveDirectory(GetSysPath(pathName)); 191 if (::RemoveDirectoryW(pathName)) 192 return true; 193 #ifdef WIN_LONG_PATH 194 UString longPath; 195 if (GetLongPath(pathName, longPath)) 196 return BOOLToBool(::RemoveDirectoryW(longPath)); 197 #endif 198 return false; 199 } 200 201 bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName) 202 { 203 if (!g_IsNT) 204 return MyMoveFile(GetSysPath(existFileName), GetSysPath(newFileName)); 205 if (::MoveFileW(existFileName, newFileName)) 206 return true; 207 #ifdef WIN_LONG_PATH 208 UString d1, d2; 209 if (GetLongPaths(existFileName, newFileName, d1, d2)) 210 return BOOLToBool(::MoveFileW(d1, d2)); 211 #endif 212 return false; 213 } 214 #endif 215 216 bool MyCreateDirectory(LPCTSTR pathName) 217 { 218 if (::CreateDirectory(pathName, NULL)) 219 return true; 220 #ifdef WIN_LONG_PATH2 221 if (::GetLastError() != ERROR_ALREADY_EXISTS) 222 { 223 UString longPath; 224 if (GetLongPath(pathName, longPath)) 225 return BOOLToBool(::CreateDirectoryW(longPath, NULL)); 226 } 227 #endif 228 return false; 229 } 230 231 #ifndef _UNICODE 232 bool MyCreateDirectory(LPCWSTR pathName) 233 { 234 if (!g_IsNT) 235 return MyCreateDirectory(GetSysPath(pathName)); 236 if (::CreateDirectoryW(pathName, NULL)) 237 return true; 238 #ifdef WIN_LONG_PATH 239 if (::GetLastError() != ERROR_ALREADY_EXISTS) 240 { 241 UString longPath; 242 if (GetLongPath(pathName, longPath)) 243 return BOOLToBool(::CreateDirectoryW(longPath, NULL)); 244 } 245 #endif 246 return false; 247 } 248 #endif 249 250 /* 251 bool CreateComplexDirectory(LPCTSTR pathName) 252 { 253 NName::CParsedPath path; 254 path.ParsePath(pathName); 255 CSysString fullPath = path.Prefix; 256 DWORD errorCode = ERROR_SUCCESS; 257 for (int i = 0; i < path.PathParts.Size(); i++) 258 { 259 const CSysString &string = path.PathParts[i]; 260 if (string.IsEmpty()) 261 { 262 if (i != path.PathParts.Size() - 1) 263 return false; 264 return true; 265 } 266 fullPath += path.PathParts[i]; 267 if (!MyCreateDirectory(fullPath)) 268 { 269 DWORD errorCode = GetLastError(); 270 if (errorCode != ERROR_ALREADY_EXISTS) 271 return false; 272 } 273 fullPath += NName::kDirDelimiter; 274 } 275 return true; 276 } 277 */ 278 279 bool CreateComplexDirectory(LPCTSTR _aPathName) 280 { 281 CSysString pathName = _aPathName; 282 int pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); 283 if (pos > 0 && pos == pathName.Length() - 1) 284 { 285 if (pathName.Length() == 3 && pathName[1] == ':') 286 return true; // Disk folder; 287 pathName.Delete(pos); 288 } 289 CSysString pathName2 = pathName; 290 pos = pathName.Length(); 291 for (;;) 292 { 293 if (MyCreateDirectory(pathName)) 294 break; 295 if (::GetLastError() == ERROR_ALREADY_EXISTS) 296 { 297 NFind::CFileInfo fileInfo; 298 if (!fileInfo.Find(pathName)) // For network folders 299 return true; 300 if (!fileInfo.IsDir()) 301 return false; 302 break; 303 } 304 pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR)); 305 if (pos < 0 || pos == 0) 306 return false; 307 if (pathName[pos - 1] == ':') 308 return false; 309 pathName = pathName.Left(pos); 310 } 311 pathName = pathName2; 312 while (pos < pathName.Length()) 313 { 314 pos = pathName.Find(TEXT(CHAR_PATH_SEPARATOR), pos + 1); 315 if (pos < 0) 316 pos = pathName.Length(); 317 if (!MyCreateDirectory(pathName.Left(pos))) 318 return false; 319 } 320 return true; 321 } 322 323 #ifndef _UNICODE 324 325 bool CreateComplexDirectory(LPCWSTR _aPathName) 326 { 327 UString pathName = _aPathName; 328 int pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); 329 if (pos > 0 && pos == pathName.Length() - 1) 330 { 331 if (pathName.Length() == 3 && pathName[1] == L':') 332 return true; // Disk folder; 333 pathName.Delete(pos); 334 } 335 UString pathName2 = pathName; 336 pos = pathName.Length(); 337 for (;;) 338 { 339 if (MyCreateDirectory(pathName)) 340 break; 341 if (::GetLastError() == ERROR_ALREADY_EXISTS) 342 { 343 NFind::CFileInfoW fileInfo; 344 if (!fileInfo.Find(pathName)) // For network folders 345 return true; 346 if (!fileInfo.IsDir()) 347 return false; 348 break; 349 } 350 pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); 351 if (pos < 0 || pos == 0) 352 return false; 353 if (pathName[pos - 1] == L':') 354 return false; 355 pathName = pathName.Left(pos); 356 } 357 pathName = pathName2; 358 while (pos < pathName.Length()) 359 { 360 pos = pathName.Find(WCHAR_PATH_SEPARATOR, pos + 1); 361 if (pos < 0) 362 pos = pathName.Length(); 363 if (!MyCreateDirectory(pathName.Left(pos))) 364 return false; 365 } 366 return true; 367 } 368 369 #endif 370 371 bool DeleteFileAlways(LPCTSTR name) 372 { 373 if (!MySetFileAttributes(name, 0)) 374 return false; 375 if (::DeleteFile(name)) 376 return true; 377 #ifdef WIN_LONG_PATH2 378 UString longPath; 379 if (GetLongPath(name, longPath)) 380 return BOOLToBool(::DeleteFileW(longPath)); 381 #endif 382 return false; 383 } 384 385 #ifndef _UNICODE 386 bool DeleteFileAlways(LPCWSTR name) 387 { 388 if (!g_IsNT) 389 return DeleteFileAlways(GetSysPath(name)); 390 if (!MySetFileAttributes(name, 0)) 391 return false; 392 if (::DeleteFileW(name)) 393 return true; 394 #ifdef WIN_LONG_PATH 395 UString longPath; 396 if (GetLongPath(name, longPath)) 397 return BOOLToBool(::DeleteFileW(longPath)); 398 #endif 399 return false; 400 } 401 #endif 402 403 static bool RemoveDirectorySubItems2(const CSysString pathPrefix, const NFind::CFileInfo &fileInfo) 404 { 405 if (fileInfo.IsDir()) 406 return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); 407 return DeleteFileAlways(pathPrefix + fileInfo.Name); 408 } 409 410 bool RemoveDirectoryWithSubItems(const CSysString &path) 411 { 412 NFind::CFileInfo fileInfo; 413 CSysString pathPrefix = path + NName::kDirDelimiter; 414 { 415 NFind::CEnumerator enumerator(pathPrefix + TCHAR(NName::kAnyStringWildcard)); 416 while (enumerator.Next(fileInfo)) 417 if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) 418 return false; 419 } 420 if (!MySetFileAttributes(path, 0)) 421 return false; 422 return MyRemoveDirectory(path); 423 } 424 425 #ifndef _UNICODE 426 static bool RemoveDirectorySubItems2(const UString pathPrefix, const NFind::CFileInfoW &fileInfo) 427 { 428 if (fileInfo.IsDir()) 429 return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); 430 return DeleteFileAlways(pathPrefix + fileInfo.Name); 431 } 432 bool RemoveDirectoryWithSubItems(const UString &path) 433 { 434 NFind::CFileInfoW fileInfo; 435 UString pathPrefix = path + UString(NName::kDirDelimiter); 436 { 437 NFind::CEnumeratorW enumerator(pathPrefix + UString(NName::kAnyStringWildcard)); 438 while (enumerator.Next(fileInfo)) 439 if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) 440 return false; 441 } 442 if (!MySetFileAttributes(path, 0)) 443 return false; 444 return MyRemoveDirectory(path); 445 } 446 #endif 447 448 bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName) 449 { 450 int index; 451 if (!MyGetFullPathName(fileName, resultName, index)) 452 return false; 453 resultName = resultName.Left(index); 454 return true; 455 } 456 457 bool GetOnlyName(LPCTSTR fileName, CSysString &resultName) 458 { 459 int index; 460 if (!MyGetFullPathName(fileName, resultName, index)) 461 return false; 462 resultName = resultName.Mid(index); 463 return true; 464 } 465 466 #ifdef UNDER_CE 467 bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath) 468 { 469 resultPath = fileName; 470 return true; 471 } 472 473 bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex) 474 { 475 resultPath = fileName; 476 // change it 477 fileNamePartStartIndex = resultPath.ReverseFind(WCHAR_PATH_SEPARATOR); 478 fileNamePartStartIndex++; 479 return true; 480 } 481 482 #else 483 484 bool MyGetShortPathName(LPCTSTR longPath, CSysString &shortPath) 485 { 486 DWORD needLength = ::GetShortPathName(longPath, shortPath.GetBuffer(MAX_PATH + 1), MAX_PATH + 1); 487 shortPath.ReleaseBuffer(); 488 return (needLength > 0 && needLength < MAX_PATH); 489 } 490 491 #ifdef WIN_LONG_PATH 492 493 static UString GetLastPart(LPCWSTR path) 494 { 495 int i = (int)wcslen(path); 496 for (; i > 0; i--) 497 { 498 WCHAR c = path[i - 1]; 499 if (c == WCHAR_PATH_SEPARATOR || c == '/') 500 break; 501 } 502 return path + i; 503 } 504 505 static void AddTrailingDots(LPCWSTR oldPath, UString &newPath) 506 { 507 int len = (int)wcslen(oldPath); 508 int i; 509 for (i = len; i > 0 && oldPath[i - 1] == '.'; i--); 510 if (i == 0 || i == len) 511 return; 512 UString oldName = GetLastPart(oldPath); 513 UString newName = GetLastPart(newPath); 514 int nonDotsLen = oldName.Length() - (len - i); 515 if (nonDotsLen == 0 || newName.CompareNoCase(oldName.Left(nonDotsLen)) != 0) 516 return; 517 for (; i != len; i++) 518 newPath += '.'; 519 } 520 521 #endif 522 523 bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, int &fileNamePartStartIndex) 524 { 525 resultPath.Empty(); 526 LPTSTR fileNamePointer = 0; 527 LPTSTR buffer = resultPath.GetBuffer(MAX_PATH); 528 DWORD needLength = ::GetFullPathName(fileName, MAX_PATH + 1, buffer, &fileNamePointer); 529 resultPath.ReleaseBuffer(); 530 if (needLength == 0) 531 return false; 532 if (needLength >= MAX_PATH) 533 { 534 #ifdef WIN_LONG_PATH2 535 needLength++; 536 buffer = resultPath.GetBuffer(needLength + 1); 537 DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); 538 resultPath.ReleaseBuffer(); 539 if (needLength2 == 0 || needLength2 > needLength) 540 #endif 541 return false; 542 } 543 if (fileNamePointer == 0) 544 fileNamePartStartIndex = lstrlen(fileName); 545 else 546 fileNamePartStartIndex = (int)(fileNamePointer - buffer); 547 #ifdef _UNICODE 548 #ifdef WIN_LONG_PATH 549 AddTrailingDots(fileName, resultPath); 550 #endif 551 #endif 552 return true; 553 } 554 555 #ifndef _UNICODE 556 bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath, int &fileNamePartStartIndex) 557 { 558 resultPath.Empty(); 559 if (g_IsNT) 560 { 561 LPWSTR fileNamePointer = 0; 562 LPWSTR buffer = resultPath.GetBuffer(MAX_PATH); 563 DWORD needLength = ::GetFullPathNameW(fileName, MAX_PATH + 1, buffer, &fileNamePointer); 564 resultPath.ReleaseBuffer(); 565 if (needLength == 0) 566 return false; 567 if (needLength >= MAX_PATH) 568 { 569 #ifdef WIN_LONG_PATH 570 needLength++; 571 buffer = resultPath.GetBuffer(needLength + 1); 572 DWORD needLength2 = ::GetFullPathNameW(fileName, needLength, buffer, &fileNamePointer); 573 resultPath.ReleaseBuffer(); 574 if (needLength2 == 0 || needLength2 > needLength) 575 #endif 576 return false; 577 } 578 if (fileNamePointer == 0) 579 fileNamePartStartIndex = MyStringLen(fileName); 580 else 581 fileNamePartStartIndex = (int)(fileNamePointer - buffer); 582 #ifdef WIN_LONG_PATH 583 AddTrailingDots(fileName, resultPath); 584 #endif 585 } 586 else 587 { 588 CSysString sysPath; 589 if (!MyGetFullPathName(GetSysPath(fileName), sysPath, fileNamePartStartIndex)) 590 return false; 591 UString resultPath1 = GetUnicodePath(sysPath.Left(fileNamePartStartIndex)); 592 UString resultPath2 = GetUnicodePath(sysPath.Mid(fileNamePartStartIndex)); 593 fileNamePartStartIndex = resultPath1.Length(); 594 resultPath = resultPath1 + resultPath2; 595 } 596 return true; 597 } 598 #endif 599 600 601 bool MyGetFullPathName(LPCTSTR fileName, CSysString &path) 602 { 603 int index; 604 return MyGetFullPathName(fileName, path, index); 605 } 606 607 #ifndef _UNICODE 608 bool MyGetFullPathName(LPCWSTR fileName, UString &path) 609 { 610 int index; 611 return MyGetFullPathName(fileName, path, index); 612 } 613 #endif 614 615 #ifndef _UNICODE 616 bool GetOnlyName(LPCWSTR fileName, UString &resultName) 617 { 618 int index; 619 if (!MyGetFullPathName(fileName, resultName, index)) 620 return false; 621 resultName = resultName.Mid(index); 622 return true; 623 } 624 #endif 625 626 #ifndef _UNICODE 627 bool GetOnlyDirPrefix(LPCWSTR fileName, UString &resultName) 628 { 629 int index; 630 if (!MyGetFullPathName(fileName, resultName, index)) 631 return false; 632 resultName = resultName.Left(index); 633 return true; 634 } 635 #endif 636 637 bool MyGetCurrentDirectory(CSysString &path) 638 { 639 DWORD needLength = ::GetCurrentDirectory(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); 640 path.ReleaseBuffer(); 641 return (needLength > 0 && needLength <= MAX_PATH); 642 } 643 644 #ifndef _UNICODE 645 bool MySetCurrentDirectory(LPCWSTR path) 646 { 647 if (g_IsNT) 648 return BOOLToBool(::SetCurrentDirectoryW(path)); 649 return MySetCurrentDirectory(GetSysPath(path)); 650 } 651 bool MyGetCurrentDirectory(UString &path) 652 { 653 if (g_IsNT) 654 { 655 DWORD needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); 656 path.ReleaseBuffer(); 657 return (needLength > 0 && needLength <= MAX_PATH); 658 } 659 CSysString sysPath; 660 if (!MyGetCurrentDirectory(sysPath)) 661 return false; 662 path = GetUnicodePath(sysPath); 663 return true; 664 } 665 #endif 666 667 bool MySearchPath(LPCTSTR path, LPCTSTR fileName, LPCTSTR extension, 668 CSysString &resultPath, UINT32 &filePart) 669 { 670 LPTSTR filePartPointer; 671 DWORD value = ::SearchPath(path, fileName, extension, 672 MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); 673 filePart = (UINT32)(filePartPointer - (LPCTSTR)resultPath); 674 resultPath.ReleaseBuffer(); 675 return (value > 0 && value <= MAX_PATH); 676 } 677 #endif 678 679 #ifndef _UNICODE 680 bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, 681 UString &resultPath, UINT32 &filePart) 682 { 683 if (g_IsNT) 684 { 685 LPWSTR filePartPointer = 0; 686 DWORD value = ::SearchPathW(path, fileName, extension, 687 MAX_PATH, resultPath.GetBuffer(MAX_PATH + 1), &filePartPointer); 688 filePart = (UINT32)(filePartPointer - (LPCWSTR)resultPath); 689 resultPath.ReleaseBuffer(); 690 return (value > 0 && value <= MAX_PATH); 691 } 692 693 CSysString sysPath; 694 if (!MySearchPath( 695 path != 0 ? (LPCTSTR)GetSysPath(path): 0, 696 fileName != 0 ? (LPCTSTR)GetSysPath(fileName): 0, 697 extension != 0 ? (LPCTSTR)GetSysPath(extension): 0, 698 sysPath, filePart)) 699 return false; 700 UString resultPath1 = GetUnicodePath(sysPath.Left(filePart)); 701 UString resultPath2 = GetUnicodePath(sysPath.Mid(filePart)); 702 filePart = resultPath1.Length(); 703 resultPath = resultPath1 + resultPath2; 704 return true; 705 } 706 #endif 707 708 bool MyGetTempPath(CSysString &path) 709 { 710 DWORD needLength = ::GetTempPath(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); 711 path.ReleaseBuffer(); 712 return (needLength > 0 && needLength <= MAX_PATH); 713 } 714 715 #ifndef _UNICODE 716 bool MyGetTempPath(UString &path) 717 { 718 path.Empty(); 719 if (g_IsNT) 720 { 721 DWORD needLength = ::GetTempPathW(MAX_PATH + 1, path.GetBuffer(MAX_PATH + 1)); 722 path.ReleaseBuffer(); 723 return (needLength > 0 && needLength <= MAX_PATH); 724 } 725 CSysString sysPath; 726 if (!MyGetTempPath(sysPath)) 727 return false; 728 path = GetUnicodePath(sysPath); 729 return true; 730 } 731 #endif 732 733 UINT MyGetTempFileName(LPCTSTR dirPath, LPCTSTR prefix, CSysString &path) 734 { 735 UINT number = ::GetTempFileName(dirPath, prefix, 0, path.GetBuffer(MAX_PATH + 1)); 736 path.ReleaseBuffer(); 737 return number; 738 } 739 740 #ifndef _UNICODE 741 UINT MyGetTempFileName(LPCWSTR dirPath, LPCWSTR prefix, UString &path) 742 { 743 if (g_IsNT) 744 { 745 UINT number = ::GetTempFileNameW(dirPath, prefix, 0, path.GetBuffer(MAX_PATH)); 746 path.ReleaseBuffer(); 747 return number; 748 } 749 CSysString sysPath; 750 UINT number = MyGetTempFileName( 751 dirPath ? (LPCTSTR)GetSysPath(dirPath): 0, 752 prefix ? (LPCTSTR)GetSysPath(prefix): 0, 753 sysPath); 754 path = GetUnicodePath(sysPath); 755 return number; 756 } 757 #endif 758 759 UINT CTempFile::Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath) 760 { 761 Remove(); 762 UINT number = MyGetTempFileName(dirPath, prefix, resultPath); 763 if (number != 0) 764 { 765 _fileName = resultPath; 766 _mustBeDeleted = true; 767 } 768 return number; 769 } 770 771 bool CTempFile::Create(LPCTSTR prefix, CSysString &resultPath) 772 { 773 CSysString tempPath; 774 if (!MyGetTempPath(tempPath)) 775 return false; 776 if (Create(tempPath, prefix, resultPath) != 0) 777 return true; 778 #ifdef UNDER_CE 779 return false; 780 #else 781 if (!MyGetWindowsDirectory(tempPath)) 782 return false; 783 return (Create(tempPath, prefix, resultPath) != 0); 784 #endif 785 } 786 787 bool CTempFile::Remove() 788 { 789 if (!_mustBeDeleted) 790 return true; 791 _mustBeDeleted = !DeleteFileAlways(_fileName); 792 return !_mustBeDeleted; 793 } 794 795 #ifndef _UNICODE 796 797 UINT CTempFileW::Create(LPCWSTR dirPath, LPCWSTR prefix, UString &resultPath) 798 { 799 Remove(); 800 UINT number = MyGetTempFileName(dirPath, prefix, resultPath); 801 if (number != 0) 802 { 803 _fileName = resultPath; 804 _mustBeDeleted = true; 805 } 806 return number; 807 } 808 809 bool CTempFileW::Create(LPCWSTR prefix, UString &resultPath) 810 { 811 UString tempPath; 812 if (!MyGetTempPath(tempPath)) 813 return false; 814 if (Create(tempPath, prefix, resultPath) != 0) 815 return true; 816 if (!MyGetWindowsDirectory(tempPath)) 817 return false; 818 return (Create(tempPath, prefix, resultPath) != 0); 819 } 820 821 bool CTempFileW::Remove() 822 { 823 if (!_mustBeDeleted) 824 return true; 825 _mustBeDeleted = !DeleteFileAlways(_fileName); 826 return !_mustBeDeleted; 827 } 828 829 #endif 830 831 bool CreateTempDirectory(LPCTSTR prefix, CSysString &dirName) 832 { 833 /* 834 CSysString prefix = tempPath + prefixChars; 835 CRandom random; 836 random.Init(); 837 */ 838 for (;;) 839 { 840 { 841 CTempFile tempFile; 842 if (!tempFile.Create(prefix, dirName)) 843 return false; 844 if (!tempFile.Remove()) 845 return false; 846 } 847 /* 848 UINT32 randomNumber = random.Generate(); 849 TCHAR randomNumberString[32]; 850 _stprintf(randomNumberString, _T("%04X"), randomNumber); 851 dirName = prefix + randomNumberString; 852 */ 853 if (NFind::DoesFileOrDirExist(dirName)) 854 continue; 855 if (MyCreateDirectory(dirName)) 856 return true; 857 if (::GetLastError() != ERROR_ALREADY_EXISTS) 858 return false; 859 } 860 } 861 862 bool CTempDirectory::Create(LPCTSTR prefix) 863 { 864 Remove(); 865 return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); 866 } 867 868 #ifndef _UNICODE 869 870 bool CreateTempDirectory(LPCWSTR prefix, UString &dirName) 871 { 872 /* 873 CSysString prefix = tempPath + prefixChars; 874 CRandom random; 875 random.Init(); 876 */ 877 for (;;) 878 { 879 { 880 CTempFileW tempFile; 881 if (!tempFile.Create(prefix, dirName)) 882 return false; 883 if (!tempFile.Remove()) 884 return false; 885 } 886 /* 887 UINT32 randomNumber = random.Generate(); 888 TCHAR randomNumberString[32]; 889 _stprintf(randomNumberString, _T("%04X"), randomNumber); 890 dirName = prefix + randomNumberString; 891 */ 892 if (NFind::DoesFileOrDirExist(dirName)) 893 continue; 894 if (MyCreateDirectory(dirName)) 895 return true; 896 if (::GetLastError() != ERROR_ALREADY_EXISTS) 897 return false; 898 } 899 } 900 901 bool CTempDirectoryW::Create(LPCWSTR prefix) 902 { 903 Remove(); 904 return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); 905 } 906 907 #endif 908 909 }}} 910