diff options
Diffstat (limited to '')
| -rw-r--r-- | src/libs/dutil/WixToolset.DUtil/pathutil.cpp | 404 |
1 files changed, 340 insertions, 64 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/pathutil.cpp b/src/libs/dutil/WixToolset.DUtil/pathutil.cpp index 0e2a5dec..dd5385fc 100644 --- a/src/libs/dutil/WixToolset.DUtil/pathutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/pathutil.cpp | |||
| @@ -20,6 +20,11 @@ | |||
| 20 | 20 | ||
| 21 | #define PATH_GOOD_ENOUGH 64 | 21 | #define PATH_GOOD_ENOUGH 64 |
| 22 | 22 | ||
| 23 | typedef DWORD(APIENTRY* PFN_GETTEMPPATH2W)( | ||
| 24 | __in DWORD BufferLength, | ||
| 25 | __out LPWSTR Buffer | ||
| 26 | ); | ||
| 27 | |||
| 23 | static BOOL IsPathSeparatorChar( | 28 | static BOOL IsPathSeparatorChar( |
| 24 | __in WCHAR wc | 29 | __in WCHAR wc |
| 25 | ); | 30 | ); |
| @@ -527,28 +532,55 @@ DAPI_(HRESULT) PathForCurrentProcess( | |||
| 527 | ) | 532 | ) |
| 528 | { | 533 | { |
| 529 | HRESULT hr = S_OK; | 534 | HRESULT hr = S_OK; |
| 530 | DWORD cch = MAX_PATH; | 535 | WCHAR smallBuffer[1] = { }; |
| 536 | SIZE_T cchMax = 0; | ||
| 537 | DWORD cchBuffer = 0; | ||
| 538 | DWORD cch = 0; | ||
| 539 | DWORD dwMaxAttempts = 20; | ||
| 531 | 540 | ||
| 532 | do | 541 | // GetModuleFileNameW didn't originally set the last error when the buffer was too small. |
| 542 | ::SetLastError(ERROR_SUCCESS); | ||
| 543 | |||
| 544 | cch = ::GetModuleFileNameW(hModule, smallBuffer, countof(smallBuffer)); | ||
| 545 | PathExitOnNullWithLastError(cch, hr, "Failed to get size of path for executing process."); | ||
| 546 | |||
| 547 | if (*psczFullPath && ERROR_INSUFFICIENT_BUFFER == ::GetLastError()) | ||
| 533 | { | 548 | { |
| 534 | hr = StrAlloc(psczFullPath, cch); | 549 | hr = StrMaxLength(*psczFullPath, &cchMax); |
| 535 | PathExitOnFailure(hr, "Failed to allocate string for module path."); | 550 | PathExitOnFailure(hr, "Failed to get max length of input buffer."); |
| 551 | |||
| 552 | cchBuffer = (DWORD)min(DWORD_MAX, cchMax); | ||
| 553 | } | ||
| 554 | else | ||
| 555 | { | ||
| 556 | cchBuffer = MAX_PATH + 1; | ||
| 557 | |||
| 558 | hr = StrAlloc(psczFullPath, cchBuffer); | ||
| 559 | PathExitOnFailure(hr, "Failed to allocate space for module path."); | ||
| 560 | } | ||
| 561 | |||
| 562 | ::SetLastError(ERROR_SUCCESS); | ||
| 536 | 563 | ||
| 537 | DWORD cchRequired = ::GetModuleFileNameW(hModule, *psczFullPath, cch); | 564 | for (DWORD i = 0; i < dwMaxAttempts; ++i) |
| 538 | if (0 == cchRequired) | 565 | { |
| 566 | cch = ::GetModuleFileNameW(hModule, *psczFullPath, cchBuffer); | ||
| 567 | PathExitOnNullWithLastError(cch, hr, "Failed to get path for executing process."); | ||
| 568 | |||
| 569 | if (ERROR_INSUFFICIENT_BUFFER != ::GetLastError()) | ||
| 539 | { | 570 | { |
| 540 | PathExitWithLastError(hr, "Failed to get path for executing process."); | 571 | break; |
| 541 | } | 572 | } |
| 542 | else if (cchRequired == cch) | 573 | |
| 574 | if ((dwMaxAttempts - 1) == i) | ||
| 543 | { | 575 | { |
| 544 | cch = cchRequired + 1; | 576 | PathExitWithRootFailure(hr, E_FAIL, "Unexpected failure getting path for executing process."); |
| 545 | hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); | ||
| 546 | } | 577 | } |
| 547 | else | 578 | |
| 548 | { | 579 | cchBuffer *= 2; |
| 549 | hr = S_OK; | 580 | |
| 550 | } | 581 | hr = StrAlloc(psczFullPath, cchBuffer); |
| 551 | } while (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr); | 582 | PathExitOnFailure(hr, "Failed to re-allocate more space for module path."); |
| 583 | } | ||
| 552 | 584 | ||
| 553 | LExit: | 585 | LExit: |
| 554 | return hr; | 586 | return hr; |
| @@ -582,17 +614,18 @@ DAPI_(HRESULT) PathCreateTempFile( | |||
| 582 | __in_opt LPCWSTR wzDirectory, | 614 | __in_opt LPCWSTR wzDirectory, |
| 583 | __in_opt __format_string LPCWSTR wzFileNameTemplate, | 615 | __in_opt __format_string LPCWSTR wzFileNameTemplate, |
| 584 | __in DWORD dwUniqueCount, | 616 | __in DWORD dwUniqueCount, |
| 617 | __in_z LPCWSTR wzPrefix, | ||
| 585 | __in DWORD dwFileAttributes, | 618 | __in DWORD dwFileAttributes, |
| 586 | __out_opt LPWSTR* psczTempFile, | 619 | __out_opt LPWSTR* psczTempFile, |
| 587 | __out_opt HANDLE* phTempFile | 620 | __out_opt HANDLE* phTempFile |
| 588 | ) | 621 | ) |
| 589 | { | 622 | { |
| 590 | AssertSz(0 < dwUniqueCount, "Must specify a non-zero unique count."); | 623 | Assert(wzPrefix); |
| 624 | AssertSz(!wzFileNameTemplate || !*wzFileNameTemplate || 0 < dwUniqueCount, "Must specify a non-zero unique count."); | ||
| 591 | 625 | ||
| 592 | HRESULT hr = S_OK; | 626 | HRESULT hr = S_OK; |
| 593 | 627 | ||
| 594 | LPWSTR sczTempPath = NULL; | 628 | LPWSTR sczTempPath = NULL; |
| 595 | DWORD cchTempPath = MAX_PATH; | ||
| 596 | 629 | ||
| 597 | HANDLE hTempFile = INVALID_HANDLE_VALUE; | 630 | HANDLE hTempFile = INVALID_HANDLE_VALUE; |
| 598 | LPWSTR scz = NULL; | 631 | LPWSTR scz = NULL; |
| @@ -605,13 +638,8 @@ DAPI_(HRESULT) PathCreateTempFile( | |||
| 605 | } | 638 | } |
| 606 | else | 639 | else |
| 607 | { | 640 | { |
| 608 | hr = StrAlloc(&sczTempPath, cchTempPath); | 641 | hr = PathGetTempPath(&sczTempPath, NULL); |
| 609 | PathExitOnFailure(hr, "Failed to allocate memory for the temp path."); | 642 | PathExitOnFailure(hr, "Failed to get temp path."); |
| 610 | |||
| 611 | if (!::GetTempPathW(cchTempPath, sczTempPath)) | ||
| 612 | { | ||
| 613 | PathExitWithLastError(hr, "Failed to get temp path."); | ||
| 614 | } | ||
| 615 | } | 643 | } |
| 616 | 644 | ||
| 617 | if (wzFileNameTemplate && *wzFileNameTemplate) | 645 | if (wzFileNameTemplate && *wzFileNameTemplate) |
| @@ -621,7 +649,7 @@ DAPI_(HRESULT) PathCreateTempFile( | |||
| 621 | hr = StrAllocFormatted(&scz, wzFileNameTemplate, i); | 649 | hr = StrAllocFormatted(&scz, wzFileNameTemplate, i); |
| 622 | PathExitOnFailure(hr, "Failed to allocate memory for file template."); | 650 | PathExitOnFailure(hr, "Failed to allocate memory for file template."); |
| 623 | 651 | ||
| 624 | hr = StrAllocFormatted(&sczTempFile, L"%s%s", sczTempPath, scz); | 652 | hr = StrAllocFormatted(&sczTempFile, L"%ls%ls", sczTempPath, scz); |
| 625 | PathExitOnFailure(hr, "Failed to allocate temp file name."); | 653 | PathExitOnFailure(hr, "Failed to allocate temp file name."); |
| 626 | 654 | ||
| 627 | hTempFile = ::CreateFileW(sczTempFile, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, CREATE_NEW, dwFileAttributes, NULL); | 655 | hTempFile = ::CreateFileW(sczTempFile, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, CREATE_NEW, dwFileAttributes, NULL); |
| @@ -642,13 +670,8 @@ DAPI_(HRESULT) PathCreateTempFile( | |||
| 642 | // the system to provide us a temp file using its built-in mechanism. | 670 | // the system to provide us a temp file using its built-in mechanism. |
| 643 | if (INVALID_HANDLE_VALUE == hTempFile) | 671 | if (INVALID_HANDLE_VALUE == hTempFile) |
| 644 | { | 672 | { |
| 645 | hr = StrAlloc(&sczTempFile, MAX_PATH); | 673 | hr = PathGetTempFileName(sczTempPath, wzPrefix, 0, &sczTempFile); |
| 646 | PathExitOnFailure(hr, "Failed to allocate memory for the temp path"); | 674 | PathExitOnFailure(hr, "Failed to create new temp file name."); |
| 647 | |||
| 648 | if (!::GetTempFileNameW(sczTempPath, L"TMP", 0, sczTempFile)) | ||
| 649 | { | ||
| 650 | PathExitWithLastError(hr, "Failed to create new temp file name."); | ||
| 651 | } | ||
| 652 | 675 | ||
| 653 | hTempFile = ::CreateFileW(sczTempFile, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, dwFileAttributes, NULL); | 676 | hTempFile = ::CreateFileW(sczTempFile, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, dwFileAttributes, NULL); |
| 654 | if (INVALID_HANDLE_VALUE == hTempFile) | 677 | if (INVALID_HANDLE_VALUE == hTempFile) |
| @@ -684,6 +707,82 @@ LExit: | |||
| 684 | } | 707 | } |
| 685 | 708 | ||
| 686 | 709 | ||
| 710 | DAPI_(HRESULT) PathGetTempFileName( | ||
| 711 | __in LPCWSTR wzPathName, | ||
| 712 | __in LPCWSTR wzPrefixString, | ||
| 713 | __in UINT uUnique, | ||
| 714 | __out LPWSTR* psczTempFileName | ||
| 715 | ) | ||
| 716 | { | ||
| 717 | HRESULT hr = S_OK; | ||
| 718 | size_t cchFullPath = 0; | ||
| 719 | WORD wValue = (WORD)(0xffff & uUnique); | ||
| 720 | LPWSTR scz = NULL; | ||
| 721 | LPWSTR sczTempFile = NULL; | ||
| 722 | HANDLE hTempFile = INVALID_HANDLE_VALUE; | ||
| 723 | |||
| 724 | hr = ::StringCchLengthW(wzPathName, STRSAFE_MAX_CCH, &cchFullPath); | ||
| 725 | PathExitOnFailure(hr, "Failed to get length of path to prefix."); | ||
| 726 | |||
| 727 | if (MAX_PATH - 14 >= cchFullPath) | ||
| 728 | { | ||
| 729 | hr = StrAlloc(psczTempFileName, MAX_PATH); | ||
| 730 | PathExitOnFailure(hr, "Failed to allocate buffer for GetTempFileNameW."); | ||
| 731 | |||
| 732 | if (!::GetTempFileNameW(wzPathName, wzPrefixString, uUnique, *psczTempFileName)) | ||
| 733 | { | ||
| 734 | PathExitWithLastError(hr, "Failed to create new temp file name."); | ||
| 735 | } | ||
| 736 | |||
| 737 | ExitFunction(); | ||
| 738 | } | ||
| 739 | |||
| 740 | // TODO: when uUnique is 0, consider not always starting at 0 to avoid collisions if this is called repeatedly. | ||
| 741 | // Purposely let it wrap around. | ||
| 742 | for (WORD w = 0; w < WORD_MAX && INVALID_HANDLE_VALUE == hTempFile; ++wValue) | ||
| 743 | { | ||
| 744 | hr = StrAllocFormatted(&scz, L"%ls%x.TMP", wzPrefixString, w); | ||
| 745 | PathExitOnFailure(hr, "Failed to allocate memory for file template."); | ||
| 746 | |||
| 747 | hr = PathConcat(wzPathName, scz, &sczTempFile); | ||
| 748 | PathExitOnFailure(hr, "Failed to allocate temp file name."); | ||
| 749 | |||
| 750 | hTempFile = ::CreateFileW(sczTempFile, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, CREATE_NEW, 0, NULL); | ||
| 751 | if (INVALID_HANDLE_VALUE == hTempFile) | ||
| 752 | { | ||
| 753 | // if the file already exists, try next one. | ||
| 754 | hr = HRESULT_FROM_WIN32(::GetLastError()); | ||
| 755 | if (HRESULT_FROM_WIN32(ERROR_FILE_EXISTS) == hr) | ||
| 756 | { | ||
| 757 | hr = S_OK; | ||
| 758 | } | ||
| 759 | PathExitOnFailure(hr, "Failed to create file: %ls", sczTempFile); | ||
| 760 | } | ||
| 761 | |||
| 762 | ++w; | ||
| 763 | } | ||
| 764 | |||
| 765 | if (INVALID_HANDLE_VALUE == hTempFile) | ||
| 766 | { | ||
| 767 | PathExitWithRootFailure(hr, HRESULT_FROM_WIN32(ERROR_FILE_EXISTS), "Failed to create temp file."); | ||
| 768 | } | ||
| 769 | |||
| 770 | hr = StrAllocString(psczTempFileName, sczTempFile, 0); | ||
| 771 | PathExitOnFailure(hr, "Failed to copy temp file string."); | ||
| 772 | |||
| 773 | LExit: | ||
| 774 | if (INVALID_HANDLE_VALUE != hTempFile) | ||
| 775 | { | ||
| 776 | ::CloseHandle(hTempFile); | ||
| 777 | } | ||
| 778 | |||
| 779 | ReleaseStr(scz); | ||
| 780 | ReleaseStr(sczTempFile); | ||
| 781 | |||
| 782 | return hr; | ||
| 783 | } | ||
| 784 | |||
| 785 | |||
| 687 | DAPI_(HRESULT) PathCreateTimeBasedTempFile( | 786 | DAPI_(HRESULT) PathCreateTimeBasedTempFile( |
| 688 | __in_z_opt LPCWSTR wzDirectory, | 787 | __in_z_opt LPCWSTR wzDirectory, |
| 689 | __in_z LPCWSTR wzPrefix, | 788 | __in_z LPCWSTR wzPrefix, |
| @@ -695,7 +794,7 @@ DAPI_(HRESULT) PathCreateTimeBasedTempFile( | |||
| 695 | { | 794 | { |
| 696 | HRESULT hr = S_OK; | 795 | HRESULT hr = S_OK; |
| 697 | BOOL fRetry = FALSE; | 796 | BOOL fRetry = FALSE; |
| 698 | WCHAR wzTempPath[MAX_PATH] = { }; | 797 | LPWSTR sczTempParentPath = NULL; |
| 699 | LPWSTR sczPrefix = NULL; | 798 | LPWSTR sczPrefix = NULL; |
| 700 | LPWSTR sczPrefixFolder = NULL; | 799 | LPWSTR sczPrefixFolder = NULL; |
| 701 | SYSTEMTIME time = { }; | 800 | SYSTEMTIME time = { }; |
| @@ -711,12 +810,10 @@ DAPI_(HRESULT) PathCreateTimeBasedTempFile( | |||
| 711 | } | 810 | } |
| 712 | else | 811 | else |
| 713 | { | 812 | { |
| 714 | if (!::GetTempPathW(countof(wzTempPath), wzTempPath)) | 813 | hr = PathGetTempPath(&sczTempParentPath, NULL); |
| 715 | { | 814 | PathExitOnFailure(hr, "Failed to get temp folder."); |
| 716 | PathExitWithLastError(hr, "Failed to get temp folder."); | ||
| 717 | } | ||
| 718 | 815 | ||
| 719 | hr = PathConcat(wzTempPath, wzPrefix, &sczPrefix); | 816 | hr = PathConcat(sczTempParentPath, wzPrefix, &sczPrefix); |
| 720 | PathExitOnFailure(hr, "Failed to concatenate the temp folder and log prefix."); | 817 | PathExitOnFailure(hr, "Failed to concatenate the temp folder and log prefix."); |
| 721 | } | 818 | } |
| 722 | 819 | ||
| @@ -778,6 +875,7 @@ DAPI_(HRESULT) PathCreateTimeBasedTempFile( | |||
| 778 | 875 | ||
| 779 | LExit: | 876 | LExit: |
| 780 | ReleaseFile(hTempFile); | 877 | ReleaseFile(hTempFile); |
| 878 | ReleaseStr(sczTempParentPath); | ||
| 781 | ReleaseStr(sczTempPath); | 879 | ReleaseStr(sczTempPath); |
| 782 | ReleaseStr(sczPrefixFolder); | 880 | ReleaseStr(sczPrefixFolder); |
| 783 | ReleaseStr(sczPrefix); | 881 | ReleaseStr(sczPrefix); |
| @@ -799,7 +897,6 @@ DAPI_(HRESULT) PathCreateTempDirectory( | |||
| 799 | HRESULT hr = S_OK; | 897 | HRESULT hr = S_OK; |
| 800 | 898 | ||
| 801 | LPWSTR sczTempPath = NULL; | 899 | LPWSTR sczTempPath = NULL; |
| 802 | DWORD cchTempPath = MAX_PATH; | ||
| 803 | 900 | ||
| 804 | LPWSTR scz = NULL; | 901 | LPWSTR scz = NULL; |
| 805 | 902 | ||
| @@ -813,13 +910,8 @@ DAPI_(HRESULT) PathCreateTempDirectory( | |||
| 813 | } | 910 | } |
| 814 | else | 911 | else |
| 815 | { | 912 | { |
| 816 | hr = StrAlloc(&sczTempPath, cchTempPath); | 913 | hr = PathGetTempPath(&sczTempPath, NULL); |
| 817 | PathExitOnFailure(hr, "Failed to allocate memory for the temp path."); | 914 | PathExitOnFailure(hr, "Failed to get temp path."); |
| 818 | |||
| 819 | if (!::GetTempPathW(cchTempPath, sczTempPath)) | ||
| 820 | { | ||
| 821 | PathExitWithLastError(hr, "Failed to get temp path."); | ||
| 822 | } | ||
| 823 | } | 915 | } |
| 824 | 916 | ||
| 825 | for (DWORD i = 1; i <= dwUniqueCount; ++i) | 917 | for (DWORD i = 1; i <= dwUniqueCount; ++i) |
| @@ -869,46 +961,230 @@ LExit: | |||
| 869 | 961 | ||
| 870 | 962 | ||
| 871 | DAPI_(HRESULT) PathGetTempPath( | 963 | DAPI_(HRESULT) PathGetTempPath( |
| 872 | __out_z LPWSTR* psczTempPath | 964 | __out_z LPWSTR* psczTempPath, |
| 965 | __out_opt SIZE_T* pcch | ||
| 966 | ) | ||
| 967 | { | ||
| 968 | |||
| 969 | HRESULT hr = S_OK; | ||
| 970 | SIZE_T cchMax = 0; | ||
| 971 | DWORD cchBuffer = 0; | ||
| 972 | DWORD cch = 0; | ||
| 973 | DWORD dwAttempts = 0; | ||
| 974 | HMODULE hModule = NULL; | ||
| 975 | PFN_GETTEMPPATH2W pfnGetTempPath = NULL; | ||
| 976 | const DWORD dwMaxAttempts = 10; | ||
| 977 | |||
| 978 | if (*psczTempPath) | ||
| 979 | { | ||
| 980 | hr = StrMaxLength(*psczTempPath, &cchMax); | ||
| 981 | PathExitOnFailure(hr, "Failed to get max length of input buffer."); | ||
| 982 | |||
| 983 | cchBuffer = (DWORD)min(DWORD_MAX, cchMax); | ||
| 984 | } | ||
| 985 | else | ||
| 986 | { | ||
| 987 | cchBuffer = MAX_PATH + 1; | ||
| 988 | |||
| 989 | hr = StrAlloc(psczTempPath, cchBuffer); | ||
| 990 | PathExitOnFailure(hr, "Failed to allocate space for temp path."); | ||
| 991 | } | ||
| 992 | |||
| 993 | hr = LoadSystemLibrary(L"kernel32.dll", &hModule); | ||
| 994 | PathExitOnFailure(hr, "Failed to load kernel32.dll"); | ||
| 995 | |||
| 996 | pfnGetTempPath = reinterpret_cast<PFN_GETTEMPPATH2W>(::GetProcAddress(hModule, "GetTempPath2W")); | ||
| 997 | if (!pfnGetTempPath) | ||
| 998 | { | ||
| 999 | pfnGetTempPath = ::GetTempPathW; | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | for (; dwAttempts < dwMaxAttempts; ++dwAttempts) | ||
| 1003 | { | ||
| 1004 | cch = pfnGetTempPath(cchBuffer, *psczTempPath); | ||
| 1005 | PathExitOnNullWithLastError(cch, hr, "Failed to get temp path."); | ||
| 1006 | |||
| 1007 | cch += 1; // add one for null terminator. | ||
| 1008 | |||
| 1009 | if (cch <= cchBuffer) | ||
| 1010 | { | ||
| 1011 | break; | ||
| 1012 | } | ||
| 1013 | |||
| 1014 | hr = StrAlloc(psczTempPath, cch); | ||
| 1015 | PathExitOnFailure(hr, "Failed to reallocate space for temp path."); | ||
| 1016 | |||
| 1017 | cchBuffer = cch; | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | if (dwMaxAttempts == dwAttempts) | ||
| 1021 | { | ||
| 1022 | PathExitWithRootFailure(hr, E_INSUFFICIENT_BUFFER, "GetTempPathW results never converged."); | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | if (pcch) | ||
| 1026 | { | ||
| 1027 | *pcch = cch - 1; // remove one for null terminator. | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | LExit: | ||
| 1031 | return hr; | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | |||
| 1035 | DAPI_(HRESULT) PathGetSystemDirectory( | ||
| 1036 | __out_z LPWSTR* psczSystemPath | ||
| 1037 | ) | ||
| 1038 | { | ||
| 1039 | HRESULT hr = S_OK; | ||
| 1040 | SIZE_T cchMax = 0; | ||
| 1041 | DWORD cchBuffer = 0; | ||
| 1042 | DWORD cch = 0; | ||
| 1043 | |||
| 1044 | if (*psczSystemPath) | ||
| 1045 | { | ||
| 1046 | hr = StrMaxLength(*psczSystemPath, &cchMax); | ||
| 1047 | PathExitOnFailure(hr, "Failed to get max length of input buffer."); | ||
| 1048 | |||
| 1049 | cchBuffer = (DWORD)min(DWORD_MAX, cchMax); | ||
| 1050 | } | ||
| 1051 | else | ||
| 1052 | { | ||
| 1053 | cchBuffer = MAX_PATH + 1; | ||
| 1054 | |||
| 1055 | hr = StrAlloc(psczSystemPath, cchBuffer); | ||
| 1056 | PathExitOnFailure(hr, "Failed to allocate space for system directory."); | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | cch = ::GetSystemDirectoryW(*psczSystemPath, cchBuffer); | ||
| 1060 | PathExitOnNullWithLastError(cch, hr, "Failed to get system directory path with default size."); | ||
| 1061 | |||
| 1062 | if (cch > cchBuffer) | ||
| 1063 | { | ||
| 1064 | hr = StrAlloc(psczSystemPath, cch); | ||
| 1065 | PathExitOnFailure(hr, "Failed to realloc system directory path."); | ||
| 1066 | |||
| 1067 | cchBuffer = cch; | ||
| 1068 | |||
| 1069 | cch = ::GetSystemDirectoryW(*psczSystemPath, cchBuffer); | ||
| 1070 | PathExitOnNullWithLastError(cch, hr, "Failed to get system directory path with returned size."); | ||
| 1071 | |||
| 1072 | if (cch > cchBuffer) | ||
| 1073 | { | ||
| 1074 | PathExitWithRootFailure(hr, E_INSUFFICIENT_BUFFER, "Failed to get system directory path with returned size."); | ||
| 1075 | } | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | hr = PathBackslashTerminate(psczSystemPath); | ||
| 1079 | PathExitOnFailure(hr, "Failed to terminate system directory path with backslash."); | ||
| 1080 | |||
| 1081 | LExit: | ||
| 1082 | return hr; | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | |||
| 1086 | DAPI_(HRESULT) PathGetSystemWow64Directory( | ||
| 1087 | __out_z LPWSTR* psczSystemPath | ||
| 873 | ) | 1088 | ) |
| 874 | { | 1089 | { |
| 875 | HRESULT hr = S_OK; | 1090 | HRESULT hr = S_OK; |
| 876 | WCHAR wzTempPath[MAX_PATH + 1] = { }; | 1091 | SIZE_T cchMax = 0; |
| 1092 | DWORD cchBuffer = 0; | ||
| 877 | DWORD cch = 0; | 1093 | DWORD cch = 0; |
| 878 | 1094 | ||
| 879 | cch = ::GetTempPathW(countof(wzTempPath), wzTempPath); | 1095 | if (*psczSystemPath) |
| 880 | if (!cch) | ||
| 881 | { | 1096 | { |
| 882 | PathExitWithLastError(hr, "Failed to GetTempPath."); | 1097 | hr = StrMaxLength(*psczSystemPath, &cchMax); |
| 1098 | PathExitOnFailure(hr, "Failed to get max length of input buffer."); | ||
| 1099 | |||
| 1100 | cchBuffer = (DWORD)min(DWORD_MAX, cchMax); | ||
| 883 | } | 1101 | } |
| 884 | else if (cch >= countof(wzTempPath)) | 1102 | else |
| 885 | { | 1103 | { |
| 886 | PathExitWithRootFailure(hr, E_INSUFFICIENT_BUFFER, "TEMP directory path too long."); | 1104 | cchBuffer = MAX_PATH + 1; |
| 1105 | |||
| 1106 | hr = StrAlloc(psczSystemPath, cchBuffer); | ||
| 1107 | PathExitOnFailure(hr, "Failed to allocate space for system wow64 directory."); | ||
| 887 | } | 1108 | } |
| 888 | 1109 | ||
| 889 | hr = StrAllocString(psczTempPath, wzTempPath, cch); | 1110 | cch = ::GetSystemWow64DirectoryW(*psczSystemPath, cchBuffer); |
| 890 | PathExitOnFailure(hr, "Failed to copy TEMP directory path."); | 1111 | PathExitOnNullWithLastError(cch, hr, "Failed to get system wow64 directory path with default size."); |
| 1112 | |||
| 1113 | cch += 1; // add one for the null terminator. | ||
| 1114 | |||
| 1115 | if (cch > cchBuffer) | ||
| 1116 | { | ||
| 1117 | hr = StrAlloc(psczSystemPath, cch); | ||
| 1118 | PathExitOnFailure(hr, "Failed to realloc system wow64 directory path."); | ||
| 1119 | |||
| 1120 | cchBuffer = cch; | ||
| 1121 | |||
| 1122 | cch = ::GetSystemWow64DirectoryW(*psczSystemPath, cchBuffer); | ||
| 1123 | PathExitOnNullWithLastError(cch, hr, "Failed to get system wow64 directory path with returned size."); | ||
| 1124 | |||
| 1125 | cch += 1; // add one for the null terminator. | ||
| 1126 | |||
| 1127 | if (cch > cchBuffer) | ||
| 1128 | { | ||
| 1129 | PathExitWithRootFailure(hr, E_INSUFFICIENT_BUFFER, "Failed to get system wow64 directory path with returned size."); | ||
| 1130 | } | ||
| 1131 | } | ||
| 1132 | |||
| 1133 | hr = PathBackslashTerminate(psczSystemPath); | ||
| 1134 | PathExitOnFailure(hr, "Failed to terminate system wow64 directory path with backslash."); | ||
| 891 | 1135 | ||
| 892 | LExit: | 1136 | LExit: |
| 893 | return hr; | 1137 | return hr; |
| 894 | } | 1138 | } |
| 895 | 1139 | ||
| 896 | 1140 | ||
| 897 | DAPI_(HRESULT) PathGetKnownFolder( | 1141 | DAPI_(HRESULT) PathGetVolumePathName( |
| 898 | __in int csidl, | 1142 | __in_z LPCWSTR wzFileName, |
| 899 | __out LPWSTR* psczKnownFolder | 1143 | __out_z LPWSTR* psczVolumePathName |
| 900 | ) | 1144 | ) |
| 901 | { | 1145 | { |
| 902 | HRESULT hr = S_OK; | 1146 | HRESULT hr = S_OK; |
| 1147 | DWORD cchBuffer = 0; | ||
| 1148 | SIZE_T cchMax = 0; | ||
| 1149 | const DWORD dwMaxAttempts = 20; | ||
| 903 | 1150 | ||
| 904 | hr = StrAlloc(psczKnownFolder, MAX_PATH); | 1151 | if (*psczVolumePathName) |
| 905 | PathExitOnFailure(hr, "Failed to allocate memory for known folder."); | 1152 | { |
| 1153 | hr = StrMaxLength(*psczVolumePathName, &cchMax); | ||
| 1154 | PathExitOnFailure(hr, "Failed to get max length of input buffer."); | ||
| 906 | 1155 | ||
| 907 | hr = ::SHGetFolderPathW(NULL, csidl, NULL, SHGFP_TYPE_CURRENT, *psczKnownFolder); | 1156 | cchBuffer = (DWORD)min(DWORD_MAX, cchMax); |
| 908 | PathExitOnFailure(hr, "Failed to get known folder path."); | 1157 | } |
| 1158 | else | ||
| 1159 | { | ||
| 1160 | cchBuffer = MAX_PATH + 1; | ||
| 1161 | |||
| 1162 | hr = StrAlloc(psczVolumePathName, cchBuffer); | ||
| 1163 | PathExitOnFailure(hr, "Failed to allocate space for volume path name."); | ||
| 1164 | } | ||
| 1165 | |||
| 1166 | for (DWORD i = 0; i < dwMaxAttempts; ++i) | ||
| 1167 | { | ||
| 1168 | if (::GetVolumePathNameW(wzFileName, *psczVolumePathName, cchBuffer)) | ||
| 1169 | { | ||
| 1170 | break; | ||
| 1171 | } | ||
| 1172 | |||
| 1173 | hr = HRESULT_FROM_WIN32(::GetLastError()); | ||
| 1174 | if (HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE) != hr && E_INSUFFICIENT_BUFFER != hr || | ||
| 1175 | (dwMaxAttempts - 1) == i) | ||
| 1176 | { | ||
| 1177 | PathExitWithRootFailure(hr, hr, "Failed to get volume path name of: %ls", wzFileName); | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | cchBuffer *= 2; | ||
| 1181 | |||
| 1182 | hr = StrAlloc(psczVolumePathName, cchBuffer); | ||
| 1183 | PathExitOnFailure(hr, "Failed to re-allocate more space for volume path name."); | ||
| 1184 | } | ||
| 909 | 1185 | ||
| 910 | hr = PathBackslashTerminate(psczKnownFolder); | 1186 | hr = PathBackslashTerminate(psczVolumePathName); |
| 911 | PathExitOnFailure(hr, "Failed to ensure known folder path is backslash terminated."); | 1187 | PathExitOnFailure(hr, "Failed to terminate volume path name with backslash."); |
| 912 | 1188 | ||
| 913 | LExit: | 1189 | LExit: |
| 914 | return hr; | 1190 | return hr; |
