summaryrefslogtreecommitdiff
path: root/src/libs/dutil/WixToolset.DUtil/pathutil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/pathutil.cpp')
-rw-r--r--src/libs/dutil/WixToolset.DUtil/pathutil.cpp404
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
23typedef DWORD(APIENTRY* PFN_GETTEMPPATH2W)(
24 __in DWORD BufferLength,
25 __out LPWSTR Buffer
26 );
27
23static BOOL IsPathSeparatorChar( 28static 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
553LExit: 585LExit:
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
710DAPI_(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
773LExit:
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
687DAPI_(HRESULT) PathCreateTimeBasedTempFile( 786DAPI_(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
779LExit: 876LExit:
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
871DAPI_(HRESULT) PathGetTempPath( 963DAPI_(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
1030LExit:
1031 return hr;
1032}
1033
1034
1035DAPI_(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
1081LExit:
1082 return hr;
1083}
1084
1085
1086DAPI_(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
892LExit: 1136LExit:
893 return hr; 1137 return hr;
894} 1138}
895 1139
896 1140
897DAPI_(HRESULT) PathGetKnownFolder( 1141DAPI_(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
913LExit: 1189LExit:
914 return hr; 1190 return hr;