diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2022-06-24 12:28:27 -0500 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2022-06-27 11:14:21 -0500 |
commit | eb53852d7ae6838e54525eb57df1d8ce8a722f9b (patch) | |
tree | 7fa05bd6df1bce2e20d87c5fbacc1c658dc000aa /src/libs | |
parent | 6ee12a64cb75097a238e60d4fd0ea542e8312214 (diff) | |
download | wix-eb53852d7ae6838e54525eb57df1d8ce8a722f9b.tar.gz wix-eb53852d7ae6838e54525eb57df1d8ce8a722f9b.tar.bz2 wix-eb53852d7ae6838e54525eb57df1d8ce8a722f9b.zip |
Add longPathAware to Burn manifest to support long paths.
Fixes 3455
Diffstat (limited to 'src/libs')
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/apputil.cpp | 28 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/cabcutil.cpp | 86 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/cabutil.cpp | 68 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/dirutil.cpp | 64 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/fileutil.cpp | 12 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/inc/dirutil.h | 3 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/inc/pathutil.h | 67 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/inc/shelutil.h | 15 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/logutil.cpp | 19 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/path2utl.cpp | 145 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/pathutil.cpp | 404 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/rexutil.cpp | 77 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/sceutil.cpp | 11 | ||||
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/shelutil.cpp | 210 | ||||
-rw-r--r-- | src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp | 182 |
15 files changed, 1083 insertions, 308 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/apputil.cpp b/src/libs/dutil/WixToolset.DUtil/apputil.cpp index b70c8cfb..9e75082a 100644 --- a/src/libs/dutil/WixToolset.DUtil/apputil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/apputil.cpp | |||
@@ -87,31 +87,27 @@ DAPI_(HRESULT) LoadSystemLibraryWithPath( | |||
87 | ) | 87 | ) |
88 | { | 88 | { |
89 | HRESULT hr = S_OK; | 89 | HRESULT hr = S_OK; |
90 | DWORD cch = 0; | 90 | LPWSTR sczDirectory = NULL; |
91 | WCHAR wzPath[MAX_PATH] = { }; | 91 | LPWSTR sczPath = NULL; |
92 | 92 | ||
93 | cch = ::GetSystemDirectoryW(wzPath, MAX_PATH); | 93 | hr = PathGetSystemDirectory(&sczDirectory); |
94 | AppExitOnNullWithLastError(cch, hr, "Failed to get the Windows system directory."); | 94 | AppExitOnFailure(hr, "Failed to get the Windows system directory."); |
95 | 95 | ||
96 | if (L'\\' != wzPath[cch - 1]) | 96 | hr = StrAllocFormatted(&sczPath, L"%ls%ls", sczDirectory, wzModuleName); |
97 | { | 97 | AppExitOnFailure(hr, "Failed to create the fully-qualified path to %ls.", wzModuleName); |
98 | hr = ::StringCchCatNW(wzPath, MAX_PATH, L"\\", 1); | ||
99 | AppExitOnRootFailure(hr, "Failed to terminate the string with a backslash."); | ||
100 | } | ||
101 | 98 | ||
102 | hr = ::StringCchCatW(wzPath, MAX_PATH, wzModuleName); | 99 | *phModule = ::LoadLibraryExW(sczPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); |
103 | AppExitOnRootFailure(hr, "Failed to create the fully-qualified path to %ls.", wzModuleName); | 100 | AppExitOnNullWithLastError(*phModule, hr, "Failed to load the library %ls.", sczPath); |
104 | |||
105 | *phModule = ::LoadLibraryExW(wzPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); | ||
106 | AppExitOnNullWithLastError(*phModule, hr, "Failed to load the library %ls.", wzModuleName); | ||
107 | 101 | ||
108 | if (psczPath) | 102 | if (psczPath) |
109 | { | 103 | { |
110 | hr = StrAllocString(psczPath, wzPath, MAX_PATH); | 104 | *psczPath = sczPath; |
111 | AppExitOnFailure(hr, "Failed to copy the path to library."); | 105 | sczPath = NULL; |
112 | } | 106 | } |
113 | 107 | ||
114 | LExit: | 108 | LExit: |
109 | ReleaseStr(sczDirectory); | ||
110 | |||
115 | return hr; | 111 | return hr; |
116 | } | 112 | } |
117 | 113 | ||
diff --git a/src/libs/dutil/WixToolset.DUtil/cabcutil.cpp b/src/libs/dutil/WixToolset.DUtil/cabcutil.cpp index d1edc54d..294669af 100644 --- a/src/libs/dutil/WixToolset.DUtil/cabcutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/cabcutil.cpp | |||
@@ -89,8 +89,8 @@ struct CABC_DATA | |||
89 | 89 | ||
90 | STRINGDICT_HANDLE shDictHandle; | 90 | STRINGDICT_HANDLE shDictHandle; |
91 | 91 | ||
92 | WCHAR wzCabinetPath[MAX_PATH]; | 92 | LPWSTR sczCabinetPath; |
93 | WCHAR wzEmptyFile[MAX_PATH]; | 93 | LPWSTR sczEmptyFile; |
94 | HANDLE hEmptyFile; | 94 | HANDLE hEmptyFile; |
95 | DWORD dwLastFileIndex; | 95 | DWORD dwLastFileIndex; |
96 | 96 | ||
@@ -197,33 +197,17 @@ extern "C" HRESULT DAPI CabCBegin( | |||
197 | 197 | ||
198 | HRESULT hr = S_OK; | 198 | HRESULT hr = S_OK; |
199 | CABC_DATA *pcd = NULL; | 199 | CABC_DATA *pcd = NULL; |
200 | WCHAR wzTempPath[MAX_PATH] = { }; | ||
201 | 200 | ||
202 | C_ASSERT(sizeof(MSIFILEHASHINFO) == 20); | 201 | C_ASSERT(sizeof(MSIFILEHASHINFO) == 20); |
203 | 202 | ||
204 | WCHAR wzPathBuffer [MAX_PATH] = L""; | 203 | LPWSTR pwzPathBuffer = NULL; |
205 | size_t cchPathBuffer; | ||
206 | if (wzCabDir) | 204 | if (wzCabDir) |
207 | { | 205 | { |
208 | hr = ::StringCchLengthW(wzCabDir, MAX_PATH, &cchPathBuffer); | 206 | hr = StrAllocString(&pwzPathBuffer, wzCabDir, 0); |
209 | CabcExitOnFailure(hr, "Failed to get length of cab directory"); | ||
210 | |||
211 | // Need room to terminate with L'\\' and L'\0' | ||
212 | if((MAX_PATH - 1) <= cchPathBuffer || 0 == cchPathBuffer) | ||
213 | { | ||
214 | hr = E_INVALIDARG; | ||
215 | CabcExitOnFailure(hr, "Cab directory had invalid length: %u", cchPathBuffer); | ||
216 | } | ||
217 | |||
218 | hr = ::StringCchCopyW(wzPathBuffer, countof(wzPathBuffer), wzCabDir); | ||
219 | CabcExitOnFailure(hr, "Failed to copy cab directory to buffer"); | 207 | CabcExitOnFailure(hr, "Failed to copy cab directory to buffer"); |
220 | 208 | ||
221 | if (L'\\' != wzPathBuffer[cchPathBuffer - 1]) | 209 | hr = PathBackslashTerminate(&pwzPathBuffer); |
222 | { | 210 | CabcExitOnFailure(hr, "Failed to cat \\ to end of buffer"); |
223 | hr = ::StringCchCatW(wzPathBuffer, countof(wzPathBuffer), L"\\"); | ||
224 | CabcExitOnFailure(hr, "Failed to cat \\ to end of buffer"); | ||
225 | ++cchPathBuffer; | ||
226 | } | ||
227 | } | 211 | } |
228 | 212 | ||
229 | pcd = static_cast<CABC_DATA*>(MemAlloc(sizeof(CABC_DATA), TRUE)); | 213 | pcd = static_cast<CABC_DATA*>(MemAlloc(sizeof(CABC_DATA), TRUE)); |
@@ -290,33 +274,23 @@ extern "C" HRESULT DAPI CabCBegin( | |||
290 | CabcExitWithLastError(hr, "failed to convert cab name to multi-byte"); | 274 | CabcExitWithLastError(hr, "failed to convert cab name to multi-byte"); |
291 | } | 275 | } |
292 | 276 | ||
293 | if (0 == ::WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, wzPathBuffer, -1, pcd->ccab.szCabPath, sizeof(pcd->ccab.szCab), NULL, NULL)) | 277 | if (0 == ::WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, pwzPathBuffer, -1, pcd->ccab.szCabPath, sizeof(pcd->ccab.szCab), NULL, NULL)) |
294 | { | 278 | { |
295 | CabcExitWithLastError(hr, "failed to convert cab dir to multi-byte"); | 279 | CabcExitWithLastError(hr, "failed to convert cab dir to multi-byte"); |
296 | } | 280 | } |
297 | 281 | ||
298 | // Remember the path to the cabinet. | 282 | // Remember the path to the cabinet. |
299 | hr= ::StringCchCopyW(pcd->wzCabinetPath, countof(pcd->wzCabinetPath), wzPathBuffer); | 283 | hr = PathConcat(pwzPathBuffer, wzCab, &pcd->sczCabinetPath); |
300 | CabcExitOnFailure(hr, "Failed to copy cabinet path from path: %ls", wzPathBuffer); | ||
301 | |||
302 | hr = ::StringCchCatW(pcd->wzCabinetPath, countof(pcd->wzCabinetPath), wzCab); | ||
303 | CabcExitOnFailure(hr, "Failed to concat to cabinet path cabinet name: %ls", wzCab); | 284 | CabcExitOnFailure(hr, "Failed to concat to cabinet path cabinet name: %ls", wzCab); |
304 | 285 | ||
305 | // Get the empty file to use as the blank marker for duplicates. | 286 | // Get the empty file to use as the blank marker for duplicates. |
306 | if (!::GetTempPathW(countof(wzTempPath), wzTempPath)) | 287 | hr = DirCreateTempPath(L"WSC", &pcd->sczEmptyFile); |
307 | { | 288 | CabcExitOnFailure(hr, "Failed to create a temp file name."); |
308 | CabcExitWithLastError(hr, "Failed to get temp path."); | ||
309 | } | ||
310 | |||
311 | if (!::GetTempFileNameW(wzTempPath, L"WSC", 0, pcd->wzEmptyFile)) | ||
312 | { | ||
313 | CabcExitWithLastError(hr, "Failed to create a temp file name."); | ||
314 | } | ||
315 | 289 | ||
316 | // Try to open the newly created empty file (remember, GetTempFileName() is kind enough to create a file for us) | 290 | // Try to open the newly created empty file (remember, GetTempFileName() is kind enough to create a file for us) |
317 | // with a handle to automatically delete the file on close. Ignore any failure that might happen, since the worst | 291 | // with a handle to automatically delete the file on close. Ignore any failure that might happen, since the worst |
318 | // case is we'll leave a zero byte file behind in the temp folder. | 292 | // case is we'll leave a zero byte file behind in the temp folder. |
319 | pcd->hEmptyFile = ::CreateFileW(pcd->wzEmptyFile, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL); | 293 | pcd->hEmptyFile = ::CreateFileW(pcd->sczEmptyFile, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL); |
320 | 294 | ||
321 | hr = DictCreateWithEmbeddedKey(&pcd->shDictHandle, dwMaxFiles, reinterpret_cast<void **>(&pcd->prgFiles), offsetof(CABC_FILE, pwzSourcePath), DICT_FLAG_CASEINSENSITIVE); | 295 | hr = DictCreateWithEmbeddedKey(&pcd->shDictHandle, dwMaxFiles, reinterpret_cast<void **>(&pcd->prgFiles), offsetof(CABC_FILE, pwzSourcePath), DICT_FLAG_CASEINSENSITIVE); |
322 | CabcExitOnFailure(hr, "Failed to create dictionary to keep track of duplicate files"); | 296 | CabcExitOnFailure(hr, "Failed to create dictionary to keep track of duplicate files"); |
@@ -358,6 +332,8 @@ extern "C" HRESULT DAPI CabCBegin( | |||
358 | *phContext = pcd; | 332 | *phContext = pcd; |
359 | 333 | ||
360 | LExit: | 334 | LExit: |
335 | ReleaseStr(pwzPathBuffer); | ||
336 | |||
361 | if (FAILED(hr) && pcd && pcd->hfci) | 337 | if (FAILED(hr) && pcd && pcd->hfci) |
362 | { | 338 | { |
363 | ::FCIDestroy(pcd->hfci); | 339 | ::FCIDestroy(pcd->hfci); |
@@ -527,7 +503,7 @@ extern "C" HRESULT DAPI CabCFinish( | |||
527 | // files point at the same path (the empty file) so there is no point in tracking them with | 503 | // files point at the same path (the empty file) so there is no point in tracking them with |
528 | // their path. | 504 | // their path. |
529 | fileInfo.wzSourcePath = pcd->prgDuplicates[dwDupeArrayFileIndex].pwzSourcePath; | 505 | fileInfo.wzSourcePath = pcd->prgDuplicates[dwDupeArrayFileIndex].pwzSourcePath; |
530 | fileInfo.wzEmptyPath = pcd->wzEmptyFile; | 506 | fileInfo.wzEmptyPath = pcd->sczEmptyFile; |
531 | 507 | ||
532 | // Use the provided token, otherwise default to the source file name. | 508 | // Use the provided token, otherwise default to the source file name. |
533 | if (pcd->prgDuplicates[dwDupeArrayFileIndex].pwzToken) | 509 | if (pcd->prgDuplicates[dwDupeArrayFileIndex].pwzToken) |
@@ -643,7 +619,7 @@ extern "C" HRESULT DAPI CabCFinish( | |||
643 | if (pcd->fGoodCab && pcd->cDuplicates) | 619 | if (pcd->fGoodCab && pcd->cDuplicates) |
644 | { | 620 | { |
645 | hr = UpdateDuplicateFiles(pcd); | 621 | hr = UpdateDuplicateFiles(pcd); |
646 | CabcExitOnFailure(hr, "Failed to update duplicates in cabinet: %ls", pcd->wzCabinetPath); | 622 | CabcExitOnFailure(hr, "Failed to update duplicates in cabinet: %ls", pcd->sczCabinetPath); |
647 | } | 623 | } |
648 | 624 | ||
649 | LExit: | 625 | LExit: |
@@ -692,6 +668,9 @@ static void FreeCabCData( | |||
692 | ReleaseMem(pcd->prgFiles); | 668 | ReleaseMem(pcd->prgFiles); |
693 | ReleaseMem(pcd->prgDuplicates); | 669 | ReleaseMem(pcd->prgDuplicates); |
694 | 670 | ||
671 | ReleaseStr(pcd->sczCabinetPath); | ||
672 | ReleaseStr(pcd->sczEmptyFile); | ||
673 | |||
695 | ReleaseMem(pcd); | 674 | ReleaseMem(pcd); |
696 | } | 675 | } |
697 | } | 676 | } |
@@ -709,7 +688,7 @@ static HRESULT CheckForDuplicateFile( | |||
709 | __in LONGLONG llFileSize | 688 | __in LONGLONG llFileSize |
710 | ) | 689 | ) |
711 | { | 690 | { |
712 | DWORD i; | 691 | DWORD i = 0; |
713 | HRESULT hr = S_OK; | 692 | HRESULT hr = S_OK; |
714 | UINT er = ERROR_SUCCESS; | 693 | UINT er = ERROR_SUCCESS; |
715 | 694 | ||
@@ -916,17 +895,17 @@ static HRESULT UpdateDuplicateFiles( | |||
916 | LPVOID pv = NULL; | 895 | LPVOID pv = NULL; |
917 | MS_CABINET_HEADER *pCabinetHeader = NULL; | 896 | MS_CABINET_HEADER *pCabinetHeader = NULL; |
918 | 897 | ||
919 | hCabinet = ::CreateFileW(pcd->wzCabinetPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | 898 | hCabinet = ::CreateFileW(pcd->sczCabinetPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); |
920 | if (INVALID_HANDLE_VALUE == hCabinet) | 899 | if (INVALID_HANDLE_VALUE == hCabinet) |
921 | { | 900 | { |
922 | CabcExitWithLastError(hr, "Failed to open cabinet: %ls", pcd->wzCabinetPath); | 901 | CabcExitWithLastError(hr, "Failed to open cabinet: %ls", pcd->sczCabinetPath); |
923 | } | 902 | } |
924 | 903 | ||
925 | // Shouldn't need more than 16 MB to get the whole cabinet header into memory so use that as | 904 | // Shouldn't need more than 16 MB to get the whole cabinet header into memory so use that as |
926 | // the upper bound for the memory map. | 905 | // the upper bound for the memory map. |
927 | if (!::GetFileSizeEx(hCabinet, &liCabinetSize)) | 906 | if (!::GetFileSizeEx(hCabinet, &liCabinetSize)) |
928 | { | 907 | { |
929 | CabcExitWithLastError(hr, "Failed to get size of cabinet: %ls", pcd->wzCabinetPath); | 908 | CabcExitWithLastError(hr, "Failed to get size of cabinet: %ls", pcd->sczCabinetPath); |
930 | } | 909 | } |
931 | 910 | ||
932 | if (0 == liCabinetSize.HighPart && liCabinetSize.LowPart < MAX_CABINET_HEADER_SIZE) | 911 | if (0 == liCabinetSize.HighPart && liCabinetSize.LowPart < MAX_CABINET_HEADER_SIZE) |
@@ -942,11 +921,11 @@ static HRESULT UpdateDuplicateFiles( | |||
942 | hCabinetMapping = ::CreateFileMappingW(hCabinet, NULL, PAGE_READWRITE | SEC_COMMIT, 0, cbCabinet, NULL); | 921 | hCabinetMapping = ::CreateFileMappingW(hCabinet, NULL, PAGE_READWRITE | SEC_COMMIT, 0, cbCabinet, NULL); |
943 | if (NULL == hCabinetMapping || INVALID_HANDLE_VALUE == hCabinetMapping) | 922 | if (NULL == hCabinetMapping || INVALID_HANDLE_VALUE == hCabinetMapping) |
944 | { | 923 | { |
945 | CabcExitWithLastError(hr, "Failed to memory map cabinet file: %ls", pcd->wzCabinetPath); | 924 | CabcExitWithLastError(hr, "Failed to memory map cabinet file: %ls", pcd->sczCabinetPath); |
946 | } | 925 | } |
947 | 926 | ||
948 | pv = ::MapViewOfFile(hCabinetMapping, FILE_MAP_WRITE, 0, 0, 0); | 927 | pv = ::MapViewOfFile(hCabinetMapping, FILE_MAP_WRITE, 0, 0, 0); |
949 | CabcExitOnNullWithLastError(pv, hr, "Failed to map view of cabinet file: %ls", pcd->wzCabinetPath); | 928 | CabcExitOnNullWithLastError(pv, hr, "Failed to map view of cabinet file: %ls", pcd->sczCabinetPath); |
950 | 929 | ||
951 | pCabinetHeader = static_cast<MS_CABINET_HEADER*>(pv); | 930 | pCabinetHeader = static_cast<MS_CABINET_HEADER*>(pv); |
952 | 931 | ||
@@ -1155,7 +1134,7 @@ static __callback INT_PTR DIAMONDAPI CabCOpen( | |||
1155 | 1134 | ||
1156 | if (INVALID_HANDLE_VALUE == reinterpret_cast<HANDLE>(pFile)) | 1135 | if (INVALID_HANDLE_VALUE == reinterpret_cast<HANDLE>(pFile)) |
1157 | { | 1136 | { |
1158 | CabcExitOnLastError(hr, "failed to open file: %s", pszFile); | 1137 | CabcExitOnLastError(hr, "failed to open file: %hs", pszFile); |
1159 | } | 1138 | } |
1160 | 1139 | ||
1161 | LExit: | 1140 | LExit: |
@@ -1326,11 +1305,12 @@ static __callback BOOL DIAMONDAPI CabCGetTempFile( | |||
1326 | 1305 | ||
1327 | HRESULT hr = S_OK; | 1306 | HRESULT hr = S_OK; |
1328 | char szTempPath[MAX_PATH] = { }; | 1307 | char szTempPath[MAX_PATH] = { }; |
1329 | DWORD cchTempPath = MAX_PATH; | ||
1330 | DWORD dwProcessId = ::GetCurrentProcessId(); | 1308 | DWORD dwProcessId = ::GetCurrentProcessId(); |
1331 | HANDLE hTempFile = INVALID_HANDLE_VALUE; | 1309 | HANDLE hTempFile = INVALID_HANDLE_VALUE; |
1332 | 1310 | ||
1333 | if (MAX_PATH < ::GetTempPathA(cchTempPath, szTempPath)) | 1311 | // TODO: Allow user to pass in different temp path in case the default is too long, |
1312 | // and/or see if magic similar to CABC_MAGIC_UNICODE_STRING_MARKER can be used to pass ourselves a path longer than MAX_PATH. | ||
1313 | if (MAX_PATH < ::GetTempPathA(countof(szTempPath), szTempPath)) | ||
1334 | { | 1314 | { |
1335 | CabcExitWithLastError(hr, "Failed to get temp path during cabinet creation."); | 1315 | CabcExitWithLastError(hr, "Failed to get temp path during cabinet creation."); |
1336 | } | 1316 | } |
@@ -1339,7 +1319,7 @@ static __callback BOOL DIAMONDAPI CabCGetTempFile( | |||
1339 | { | 1319 | { |
1340 | LONG dwTempIndex = ::InterlockedIncrement(reinterpret_cast<volatile LONG*>(&dwIndex)); | 1320 | LONG dwTempIndex = ::InterlockedIncrement(reinterpret_cast<volatile LONG*>(&dwIndex)); |
1341 | 1321 | ||
1342 | hr = ::StringCbPrintfA(szFile, cbFile, "%s\\%08x.%03x", szTempPath, dwTempIndex, dwProcessId); | 1322 | hr = ::StringCbPrintfA(szFile, cbFile, "%hs\\%08x.%03x", szTempPath, dwTempIndex, dwProcessId); |
1343 | CabcExitOnFailure(hr, "failed to format log file path."); | 1323 | CabcExitOnFailure(hr, "failed to format log file path."); |
1344 | 1324 | ||
1345 | hTempFile = ::CreateFileA(szFile, 0, FILE_SHARE_DELETE, NULL, CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL); | 1325 | hTempFile = ::CreateFileA(szFile, 0, FILE_SHARE_DELETE, NULL, CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, NULL); |
@@ -1351,7 +1331,11 @@ static __callback BOOL DIAMONDAPI CabCGetTempFile( | |||
1351 | } | 1331 | } |
1352 | else | 1332 | else |
1353 | { | 1333 | { |
1354 | hr = E_FAIL; // this file was taken so be pessimistic and assume we're not going to find one. | 1334 | hr = HRESULT_FROM_WIN32(::GetLastError()); // this file was taken so be pessimistic and assume we're not going to find one. |
1335 | if (SUCCEEDED(hr)) | ||
1336 | { | ||
1337 | hr = E_FAIL; | ||
1338 | } | ||
1355 | } | 1339 | } |
1356 | } | 1340 | } |
1357 | CabcExitOnFailure(hr, "failed to find temporary file."); | 1341 | CabcExitOnFailure(hr, "failed to find temporary file."); |
@@ -1386,7 +1370,7 @@ static __callback BOOL DIAMONDAPI CabCGetNextCabinet( | |||
1386 | if (pccab->iCab == 1) | 1370 | if (pccab->iCab == 1) |
1387 | { | 1371 | { |
1388 | pcd->wzFirstCabinetName[0] = '\0'; | 1372 | pcd->wzFirstCabinetName[0] = '\0'; |
1389 | LPCWSTR pwzCabinetName = PathFile(pcd->wzCabinetPath); | 1373 | LPCWSTR pwzCabinetName = PathFile(pcd->sczCabinetPath); |
1390 | size_t len = wcsnlen(pwzCabinetName, sizeof(pwzCabinetName)); | 1374 | size_t len = wcsnlen(pwzCabinetName, sizeof(pwzCabinetName)); |
1391 | if (len > 4) | 1375 | if (len > 4) |
1392 | { | 1376 | { |
diff --git a/src/libs/dutil/WixToolset.DUtil/cabutil.cpp b/src/libs/dutil/WixToolset.DUtil/cabutil.cpp index f3629d57..57463e1a 100644 --- a/src/libs/dutil/WixToolset.DUtil/cabutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/cabutil.cpp | |||
@@ -261,15 +261,15 @@ static HRESULT DAPI CabOperation( | |||
261 | ) | 261 | ) |
262 | { | 262 | { |
263 | HRESULT hr = S_OK; | 263 | HRESULT hr = S_OK; |
264 | BOOL fResult; | 264 | BOOL fResult = FALSE; |
265 | 265 | ||
266 | LPWSTR sczCabinet = NULL; | 266 | LPWSTR sczCabinet = NULL; |
267 | LPWSTR pwz = NULL; | 267 | LPWSTR pwz = NULL; |
268 | CHAR szCabDirectory[MAX_PATH * 4]; // Make sure these are big enough for UTF-8 strings | 268 | LPSTR pszCabDirectory = NULL; |
269 | CHAR szCabFile[MAX_PATH * 4]; | 269 | CHAR szCabFile[MAX_PATH * 4] = { }; // Make sure this is big enough for UTF-8 strings |
270 | 270 | ||
271 | CAB_CALLBACK_STRUCT ccs; | 271 | CAB_CALLBACK_STRUCT ccs = { }; |
272 | PFNFDINOTIFY pfnFdiNotify; | 272 | PFNFDINOTIFY pfnFdiNotify = NULL; |
273 | 273 | ||
274 | // | 274 | // |
275 | // ensure the cabinet.dll is loaded | 275 | // ensure the cabinet.dll is loaded |
@@ -299,15 +299,13 @@ static HRESULT DAPI CabOperation( | |||
299 | // If a full path was not provided, use the relative current directory. | 299 | // If a full path was not provided, use the relative current directory. |
300 | if (wzCabinet == pwz) | 300 | if (wzCabinet == pwz) |
301 | { | 301 | { |
302 | hr = ::StringCchCopyA(szCabDirectory, countof(szCabDirectory), ".\\"); | 302 | hr = StrAnsiAllocStringAnsi(&pszCabDirectory, ".\\", 0); |
303 | CabExitOnFailure(hr, "Failed to copy relative current directory as cabinet directory."); | 303 | CabExitOnFailure(hr, "Failed to copy relative current directory as cabinet directory."); |
304 | } | 304 | } |
305 | else | 305 | else |
306 | { | 306 | { |
307 | if (!::WideCharToMultiByte(CP_UTF8, 0, sczCabinet, -1, szCabDirectory, countof(szCabDirectory), NULL, NULL)) | 307 | hr = StrAnsiAllocString(&pszCabDirectory, sczCabinet, 0, CP_UTF8); |
308 | { | 308 | CabExitOnFailure(hr, "failed to convert cabinet directory to ASCII: %ls", sczCabinet); |
309 | CabExitWithLastError(hr, "failed to convert cabinet directory to ASCII: %ls", sczCabinet); | ||
310 | } | ||
311 | } | 309 | } |
312 | 310 | ||
313 | // | 311 | // |
@@ -331,7 +329,7 @@ static HRESULT DAPI CabOperation( | |||
331 | v_pfnNetFx11Notify = pfnNotify; | 329 | v_pfnNetFx11Notify = pfnNotify; |
332 | pfnFdiNotify = FDINotify; | 330 | pfnFdiNotify = FDINotify; |
333 | } | 331 | } |
334 | fResult = vpfnFDICopy(vhfdi, szCabFile, szCabDirectory, 0, pfnFdiNotify, NULL, static_cast<void*>(&ccs)); | 332 | fResult = vpfnFDICopy(vhfdi, szCabFile, pszCabDirectory, 0, pfnFdiNotify, NULL, static_cast<void*>(&ccs)); |
335 | if (!fResult && !ccs.fStopExtracting) // if something went wrong and it wasn't us just stopping the extraction, then return a failure | 333 | if (!fResult && !ccs.fStopExtracting) // if something went wrong and it wasn't us just stopping the extraction, then return a failure |
336 | { | 334 | { |
337 | CabExitWithLastError(hr, "failed to extract cabinet file: %ls", sczCabinet); | 335 | CabExitWithLastError(hr, "failed to extract cabinet file: %ls", sczCabinet); |
@@ -339,6 +337,7 @@ static HRESULT DAPI CabOperation( | |||
339 | 337 | ||
340 | LExit: | 338 | LExit: |
341 | ReleaseStr(sczCabinet); | 339 | ReleaseStr(sczCabinet); |
340 | ReleaseStr(pszCabDirectory); | ||
342 | v_pfnNetFx11Notify = NULL; | 341 | v_pfnNetFx11Notify = NULL; |
343 | 342 | ||
344 | return hr; | 343 | return hr; |
@@ -493,14 +492,15 @@ static __callback INT_PTR DIAMONDAPI CabExtractCallback(__in FDINOTIFICATIONTYPE | |||
493 | INT_PTR ipResult = 0; // result to return on success | 492 | INT_PTR ipResult = 0; // result to return on success |
494 | 493 | ||
495 | CAB_CALLBACK_STRUCT* pccs = static_cast<CAB_CALLBACK_STRUCT*>(pFDINotify->pv); | 494 | CAB_CALLBACK_STRUCT* pccs = static_cast<CAB_CALLBACK_STRUCT*>(pFDINotify->pv); |
496 | LPCSTR sz; | 495 | LPCSTR sz = NULL; |
497 | WCHAR wz[MAX_PATH]; | 496 | LPWSTR pwz = NULL; |
498 | FILETIME ft; | 497 | LPWSTR pwzPath = NULL; |
498 | FILETIME ft = { }; | ||
499 | 499 | ||
500 | switch (iNotification) | 500 | switch (iNotification) |
501 | { | 501 | { |
502 | case fdintCOPY_FILE: // begin extracting a resource from cabinet | 502 | case fdintCOPY_FILE: // begin extracting a resource from cabinet |
503 | CabExitOnNull(pFDINotify->psz1, hr, E_INVALIDARG, "No cabinet file ID given to convert"); | 503 | Assert(pccs && pFDINotify->psz1); |
504 | CabExitOnNull(pccs, hr, E_INVALIDARG, "Failed to call cabextract callback, because no callback struct was provided"); | 504 | CabExitOnNull(pccs, hr, E_INVALIDARG, "Failed to call cabextract callback, because no callback struct was provided"); |
505 | 505 | ||
506 | if (pccs->fStopExtracting) | 506 | if (pccs->fStopExtracting) |
@@ -510,40 +510,37 @@ static __callback INT_PTR DIAMONDAPI CabExtractCallback(__in FDINOTIFICATIONTYPE | |||
510 | 510 | ||
511 | // convert params to useful variables | 511 | // convert params to useful variables |
512 | sz = static_cast<LPCSTR>(pFDINotify->psz1); | 512 | sz = static_cast<LPCSTR>(pFDINotify->psz1); |
513 | if (!::MultiByteToWideChar(CP_ACP, 0, sz, -1, wz, countof(wz))) | 513 | CabExitOnNull(sz, hr, E_INVALIDARG, "No cabinet file ID given to convert"); |
514 | { | 514 | |
515 | CabExitWithLastError(hr, "failed to convert cabinet file id to unicode: %s", sz); | 515 | hr = StrAllocStringAnsi(&pwz, sz, 0, CP_ACP); |
516 | } | 516 | CabExitOnFailure(hr, "failed to convert cabinet file id to unicode: %hs", sz); |
517 | 517 | ||
518 | if (pccs->pfnProgress) | 518 | if (pccs->pfnProgress) |
519 | { | 519 | { |
520 | hr = pccs->pfnProgress(TRUE, wz, pccs->pvContext); | 520 | hr = pccs->pfnProgress(TRUE, pwz, pccs->pvContext); |
521 | if (S_OK != hr) | 521 | if (S_OK != hr) |
522 | { | 522 | { |
523 | ExitFunction(); | 523 | ExitFunction(); |
524 | } | 524 | } |
525 | } | 525 | } |
526 | 526 | ||
527 | if (L'*' == *pccs->pwzExtract || 0 == lstrcmpW(pccs->pwzExtract, wz)) | 527 | if (L'*' == *pccs->pwzExtract || 0 == lstrcmpW(pccs->pwzExtract, pwz)) |
528 | { | 528 | { |
529 | // get the created date for the resource in the cabinet | 529 | // get the created date for the resource in the cabinet |
530 | FILETIME ftLocal; | 530 | FILETIME ftLocal; |
531 | if (!::DosDateTimeToFileTime(pFDINotify->date, pFDINotify->time, &ftLocal)) | 531 | if (!::DosDateTimeToFileTime(pFDINotify->date, pFDINotify->time, &ftLocal)) |
532 | { | 532 | { |
533 | CabExitWithLastError(hr, "failed to get time for resource: %ls", wz); | 533 | CabExitWithLastError(hr, "failed to get time for resource: %ls", pwz); |
534 | } | 534 | } |
535 | ::LocalFileTimeToFileTime(&ftLocal, &ft); | 535 | ::LocalFileTimeToFileTime(&ftLocal, &ft); |
536 | 536 | ||
537 | WCHAR wzPath[MAX_PATH]; | 537 | hr = PathConcat(pccs->pwzExtractDir, pwz, &pwzPath); |
538 | hr = ::StringCchCopyW(wzPath, countof(wzPath), pccs->pwzExtractDir); | 538 | CabExitOnFailure(hr, "failed to concat onto path: %ls file: %ls", pccs->pwzExtractDir, pwz); |
539 | CabExitOnFailure(hr, "failed to copy in extract directory: %ls for file: %ls", pccs->pwzExtractDir, wz); | ||
540 | hr = ::StringCchCatW(wzPath, countof(wzPath), wz); | ||
541 | CabExitOnFailure(hr, "failed to concat onto path: %ls file: %ls", wzPath, wz); | ||
542 | 539 | ||
543 | hFile = OpenFileWithRetry(wzPath, GENERIC_WRITE, CREATE_ALWAYS); | 540 | hFile = OpenFileWithRetry(pwzPath, GENERIC_WRITE, CREATE_ALWAYS); |
544 | if (INVALID_HANDLE_VALUE == hFile) | 541 | if (INVALID_HANDLE_VALUE == hFile) |
545 | { | 542 | { |
546 | CabExitWithLastError(hr, "failed to create file: %ls", wzPath); | 543 | CabExitWithLastError(hr, "failed to create file: %ls", pwzPath); |
547 | } | 544 | } |
548 | 545 | ||
549 | ::SetFileTime(hFile, &ft, &ft, &ft); // try to set the file time (who cares if it fails) | 546 | ::SetFileTime(hFile, &ft, &ft, &ft); // try to set the file time (who cares if it fails) |
@@ -567,17 +564,15 @@ static __callback INT_PTR DIAMONDAPI CabExtractCallback(__in FDINOTIFICATIONTYPE | |||
567 | 564 | ||
568 | break; | 565 | break; |
569 | case fdintCLOSE_FILE_INFO: // resource extraction complete | 566 | case fdintCLOSE_FILE_INFO: // resource extraction complete |
570 | Assert(pFDINotify->hf && pFDINotify->psz1); | 567 | Assert(pFDINotify->hf && pccs && pFDINotify->psz1); |
571 | CabExitOnNull(pccs, hr, E_INVALIDARG, "Failed to call cabextract callback, because no callback struct was provided"); | 568 | CabExitOnNull(pccs, hr, E_INVALIDARG, "Failed to call cabextract callback, because no callback struct was provided"); |
572 | 569 | ||
573 | // convert params to useful variables | 570 | // convert params to useful variables |
574 | sz = static_cast<LPCSTR>(pFDINotify->psz1); | 571 | sz = static_cast<LPCSTR>(pFDINotify->psz1); |
575 | CabExitOnNull(sz, hr, E_INVALIDARG, "Failed to convert cabinet file id, because no cabinet file id was provided"); | 572 | CabExitOnNull(sz, hr, E_INVALIDARG, "Failed to convert cabinet file id, because no cabinet file id was provided"); |
576 | 573 | ||
577 | if (!::MultiByteToWideChar(CP_ACP, 0, sz, -1, wz, countof(wz))) | 574 | hr = StrAllocStringAnsi(&pwz, sz, 0, CP_ACP); |
578 | { | 575 | CabExitOnFailure(hr, "failed to convert cabinet file id to unicode: %hs", sz); |
579 | CabExitWithLastError(hr, "failed to convert cabinet file id to unicode: %s", sz); | ||
580 | } | ||
581 | 576 | ||
582 | if (NULL != pFDINotify->hf) // just close the file | 577 | if (NULL != pFDINotify->hf) // just close the file |
583 | { | 578 | { |
@@ -586,7 +581,7 @@ static __callback INT_PTR DIAMONDAPI CabExtractCallback(__in FDINOTIFICATIONTYPE | |||
586 | 581 | ||
587 | if (pccs->pfnProgress) | 582 | if (pccs->pfnProgress) |
588 | { | 583 | { |
589 | hr = pccs->pfnProgress(FALSE, wz, pccs->pvContext); | 584 | hr = pccs->pfnProgress(FALSE, pwz, pccs->pvContext); |
590 | } | 585 | } |
591 | 586 | ||
592 | if (S_OK == hr && L'*' == *pccs->pwzExtract) // if everything is okay and we're extracting all files, keep going | 587 | if (S_OK == hr && L'*' == *pccs->pwzExtract) // if everything is okay and we're extracting all files, keep going |
@@ -613,5 +608,8 @@ static __callback INT_PTR DIAMONDAPI CabExtractCallback(__in FDINOTIFICATIONTYPE | |||
613 | LExit: | 608 | LExit: |
614 | ReleaseFileHandle(hFile); | 609 | ReleaseFileHandle(hFile); |
615 | 610 | ||
611 | ReleaseStr(pwz); | ||
612 | ReleaseStr(pwzPath); | ||
613 | |||
616 | return (S_OK == hr) ? ipResult : -1; | 614 | return (S_OK == hr) ? ipResult : -1; |
617 | } | 615 | } |
diff --git a/src/libs/dutil/WixToolset.DUtil/dirutil.cpp b/src/libs/dutil/WixToolset.DUtil/dirutil.cpp index 94eab9e7..2c02225d 100644 --- a/src/libs/dutil/WixToolset.DUtil/dirutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/dirutil.cpp | |||
@@ -59,34 +59,10 @@ LExit: | |||
59 | *******************************************************************/ | 59 | *******************************************************************/ |
60 | extern "C" HRESULT DAPI DirCreateTempPath( | 60 | extern "C" HRESULT DAPI DirCreateTempPath( |
61 | __in_z LPCWSTR wzPrefix, | 61 | __in_z LPCWSTR wzPrefix, |
62 | __out_ecount_z(cchPath) LPWSTR wzPath, | 62 | __out_opt LPWSTR* psczTempFile |
63 | __in DWORD cchPath | ||
64 | ) | 63 | ) |
65 | { | 64 | { |
66 | Assert(wzPrefix); | 65 | return PathCreateTempFile(NULL, NULL, 0, wzPrefix, 0, psczTempFile, NULL); |
67 | Assert(wzPath); | ||
68 | |||
69 | HRESULT hr = S_OK; | ||
70 | |||
71 | WCHAR wzDir[MAX_PATH]; | ||
72 | WCHAR wzFile[MAX_PATH]; | ||
73 | DWORD cch = 0; | ||
74 | |||
75 | cch = ::GetTempPathW(countof(wzDir), wzDir); | ||
76 | if (!cch || cch >= countof(wzDir)) | ||
77 | { | ||
78 | DirExitWithLastError(hr, "Failed to GetTempPath."); | ||
79 | } | ||
80 | |||
81 | if (!::GetTempFileNameW(wzDir, wzPrefix, 0, wzFile)) | ||
82 | { | ||
83 | DirExitWithLastError(hr, "Failed to GetTempFileName."); | ||
84 | } | ||
85 | |||
86 | hr = ::StringCchCopyW(wzPath, cchPath, wzFile); | ||
87 | |||
88 | LExit: | ||
89 | return hr; | ||
90 | } | 66 | } |
91 | 67 | ||
92 | 68 | ||
@@ -192,18 +168,19 @@ extern "C" HRESULT DAPI DirEnsureDeleteEx( | |||
192 | Assert(wzPath && *wzPath); | 168 | Assert(wzPath && *wzPath); |
193 | 169 | ||
194 | HRESULT hr = S_OK; | 170 | HRESULT hr = S_OK; |
195 | DWORD er; | 171 | DWORD er = ERROR_SUCCESS; |
196 | 172 | ||
197 | DWORD dwAttrib; | 173 | DWORD dwAttrib = 0; |
198 | HANDLE hFind = INVALID_HANDLE_VALUE; | 174 | HANDLE hFind = INVALID_HANDLE_VALUE; |
199 | LPWSTR sczDelete = NULL; | 175 | LPWSTR sczDelete = NULL; |
200 | WIN32_FIND_DATAW wfd; | 176 | WIN32_FIND_DATAW wfd = { }; |
201 | 177 | ||
202 | BOOL fDeleteFiles = (DIR_DELETE_FILES == (dwFlags & DIR_DELETE_FILES)); | 178 | BOOL fDeleteFiles = (DIR_DELETE_FILES == (dwFlags & DIR_DELETE_FILES)); |
203 | BOOL fRecurse = (DIR_DELETE_RECURSE == (dwFlags & DIR_DELETE_RECURSE)); | 179 | BOOL fRecurse = (DIR_DELETE_RECURSE == (dwFlags & DIR_DELETE_RECURSE)); |
204 | BOOL fScheduleDelete = (DIR_DELETE_SCHEDULE == (dwFlags & DIR_DELETE_SCHEDULE)); | 180 | BOOL fScheduleDelete = (DIR_DELETE_SCHEDULE == (dwFlags & DIR_DELETE_SCHEDULE)); |
205 | WCHAR wzTempDirectory[MAX_PATH] = { }; | 181 | WCHAR wzSafeFileName[MAX_PATH + 1] = { }; |
206 | WCHAR wzTempPath[MAX_PATH] = { }; | 182 | LPWSTR sczTempDirectory = NULL; |
183 | LPWSTR sczTempPath = NULL; | ||
207 | 184 | ||
208 | if (-1 == (dwAttrib = ::GetFileAttributesW(wzPath))) | 185 | if (-1 == (dwAttrib = ::GetFileAttributesW(wzPath))) |
209 | { | 186 | { |
@@ -231,10 +208,8 @@ extern "C" HRESULT DAPI DirEnsureDeleteEx( | |||
231 | { | 208 | { |
232 | if (fScheduleDelete) | 209 | if (fScheduleDelete) |
233 | { | 210 | { |
234 | if (!::GetTempPathW(countof(wzTempDirectory), wzTempDirectory)) | 211 | hr = PathGetTempPath(&sczTempDirectory, NULL); |
235 | { | 212 | DirExitOnFailure(hr, "Failed to get temp directory."); |
236 | DirExitWithLastError(hr, "Failed to get temp directory."); | ||
237 | } | ||
238 | } | 213 | } |
239 | 214 | ||
240 | // Delete everything in this directory. | 215 | // Delete everything in this directory. |
@@ -256,10 +231,11 @@ extern "C" HRESULT DAPI DirEnsureDeleteEx( | |||
256 | } | 231 | } |
257 | 232 | ||
258 | // For extra safety and to silence OACR. | 233 | // For extra safety and to silence OACR. |
259 | wfd.cFileName[MAX_PATH - 1] = L'\0'; | 234 | hr = ::StringCchCopyNExW(wzSafeFileName, countof(wzSafeFileName), wfd.cFileName, countof(wfd.cFileName), NULL, NULL, STRSAFE_FILL_BEHIND_NULL | STRSAFE_NULL_ON_FAILURE); |
235 | DirExitOnFailure(hr, "Failed to ensure file name was null terminated."); | ||
260 | 236 | ||
261 | hr = PathConcat(wzPath, wfd.cFileName, &sczDelete); | 237 | hr = PathConcat(wzPath, wzSafeFileName, &sczDelete); |
262 | DirExitOnFailure(hr, "Failed to concat filename '%ls' to directory: %ls", wfd.cFileName, wzPath); | 238 | DirExitOnFailure(hr, "Failed to concat filename '%ls' to directory: %ls", wzSafeFileName, wzPath); |
263 | 239 | ||
264 | if (fRecurse && wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) | 240 | if (fRecurse && wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) |
265 | { | 241 | { |
@@ -288,16 +264,14 @@ extern "C" HRESULT DAPI DirEnsureDeleteEx( | |||
288 | { | 264 | { |
289 | if (fScheduleDelete) | 265 | if (fScheduleDelete) |
290 | { | 266 | { |
291 | if (!::GetTempFileNameW(wzTempDirectory, L"DEL", 0, wzTempPath)) | 267 | hr = PathGetTempFileName(sczTempDirectory, L"DEL", 0, &sczTempPath); |
292 | { | 268 | DirExitOnFailure(hr, "Failed to get temp file to move to."); |
293 | DirExitWithLastError(hr, "Failed to get temp file to move to."); | ||
294 | } | ||
295 | 269 | ||
296 | // Try to move the file to the temp directory then schedule for delete, | 270 | // Try to move the file to the temp directory then schedule for delete, |
297 | // otherwise just schedule for delete. | 271 | // otherwise just schedule for delete. |
298 | if (::MoveFileExW(sczDelete, wzTempPath, MOVEFILE_REPLACE_EXISTING)) | 272 | if (::MoveFileExW(sczDelete, sczTempPath, MOVEFILE_REPLACE_EXISTING)) |
299 | { | 273 | { |
300 | ::MoveFileExW(wzTempPath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); | 274 | ::MoveFileExW(sczTempPath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); |
301 | } | 275 | } |
302 | else | 276 | else |
303 | { | 277 | { |
@@ -348,6 +322,8 @@ extern "C" HRESULT DAPI DirEnsureDeleteEx( | |||
348 | LExit: | 322 | LExit: |
349 | ReleaseFileFindHandle(hFind); | 323 | ReleaseFileFindHandle(hFind); |
350 | ReleaseStr(sczDelete); | 324 | ReleaseStr(sczDelete); |
325 | ReleaseStr(sczTempDirectory); | ||
326 | ReleaseStr(sczTempPath); | ||
351 | 327 | ||
352 | return hr; | 328 | return hr; |
353 | } | 329 | } |
diff --git a/src/libs/dutil/WixToolset.DUtil/fileutil.cpp b/src/libs/dutil/WixToolset.DUtil/fileutil.cpp index 9f68ee52..ac407916 100644 --- a/src/libs/dutil/WixToolset.DUtil/fileutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/fileutil.cpp | |||
@@ -1284,21 +1284,18 @@ extern "C" HRESULT DAPI FileCreateTempW( | |||
1284 | Assert(wzPrefix && *wzPrefix); | 1284 | Assert(wzPrefix && *wzPrefix); |
1285 | HRESULT hr = E_FAIL; | 1285 | HRESULT hr = E_FAIL; |
1286 | 1286 | ||
1287 | WCHAR wzTempPath[MAX_PATH]; | 1287 | LPWSTR pwzTempPath = NULL; |
1288 | DWORD cchTempPath = countof(wzTempPath); | ||
1289 | LPWSTR pwzTempFile = NULL; | 1288 | LPWSTR pwzTempFile = NULL; |
1290 | 1289 | ||
1291 | HANDLE hTempFile = INVALID_HANDLE_VALUE; | 1290 | HANDLE hTempFile = INVALID_HANDLE_VALUE; |
1292 | int i = 0; | 1291 | int i = 0; |
1293 | 1292 | ||
1294 | if (!::GetTempPathW(cchTempPath, wzTempPath)) | 1293 | hr = PathGetTempPath(&pwzTempPath, NULL); |
1295 | { | 1294 | FileExitOnFailure(hr, "failed to get temp path"); |
1296 | FileExitOnLastError(hr, "failed to get temp path"); | ||
1297 | } | ||
1298 | 1295 | ||
1299 | for (i = 0; i < 1000 && INVALID_HANDLE_VALUE == hTempFile; ++i) | 1296 | for (i = 0; i < 1000 && INVALID_HANDLE_VALUE == hTempFile; ++i) |
1300 | { | 1297 | { |
1301 | hr = StrAllocFormatted(&pwzTempFile, L"%s%s%05d.%s", wzTempPath, wzPrefix, i, wzExtension); | 1298 | hr = StrAllocFormatted(&pwzTempFile, L"%s%s%05d.%s", pwzTempPath, wzPrefix, i, wzExtension); |
1302 | FileExitOnFailure(hr, "failed to allocate memory for temp filename"); | 1299 | FileExitOnFailure(hr, "failed to allocate memory for temp filename"); |
1303 | 1300 | ||
1304 | hTempFile = ::CreateFileW(pwzTempFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); | 1301 | hTempFile = ::CreateFileW(pwzTempFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); |
@@ -1330,6 +1327,7 @@ extern "C" HRESULT DAPI FileCreateTempW( | |||
1330 | LExit: | 1327 | LExit: |
1331 | ReleaseFile(hTempFile); | 1328 | ReleaseFile(hTempFile); |
1332 | ReleaseStr(pwzTempFile); | 1329 | ReleaseStr(pwzTempFile); |
1330 | ReleaseStr(pwzTempPath); | ||
1333 | 1331 | ||
1334 | return hr; | 1332 | return hr; |
1335 | } | 1333 | } |
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/dirutil.h b/src/libs/dutil/WixToolset.DUtil/inc/dirutil.h index 42268a16..b8fc0431 100644 --- a/src/libs/dutil/WixToolset.DUtil/inc/dirutil.h +++ b/src/libs/dutil/WixToolset.DUtil/inc/dirutil.h | |||
@@ -20,8 +20,7 @@ BOOL DAPI DirExists( | |||
20 | 20 | ||
21 | HRESULT DAPI DirCreateTempPath( | 21 | HRESULT DAPI DirCreateTempPath( |
22 | __in_z LPCWSTR wzPrefix, | 22 | __in_z LPCWSTR wzPrefix, |
23 | __out_ecount_z(cchPath) LPWSTR wzPath, | 23 | __out_opt LPWSTR* psczTempFile |
24 | __in DWORD cchPath | ||
25 | ); | 24 | ); |
26 | 25 | ||
27 | HRESULT DAPI DirEnsureExists( | 26 | HRESULT DAPI DirEnsureExists( |
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h b/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h index 971ef887..de46b95d 100644 --- a/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h +++ b/src/libs/dutil/WixToolset.DUtil/inc/pathutil.h | |||
@@ -159,19 +159,31 @@ DAPI_(HRESULT) PathRelativeToModule( | |||
159 | /******************************************************************* | 159 | /******************************************************************* |
160 | PathCreateTempFile | 160 | PathCreateTempFile |
161 | 161 | ||
162 | Note: if wzDirectory is null, ::GetTempPath() will be used instead. | 162 | Note: if wzDirectory is null, ::GetTempPath2() will be used instead. |
163 | if wzFileNameTemplate is null, GetTempFileName() will be used instead. | 163 | if wzFileNameTemplate is null, GetTempFileName() will be used instead. |
164 | *******************************************************************/ | 164 | *******************************************************************/ |
165 | DAPI_(HRESULT) PathCreateTempFile( | 165 | DAPI_(HRESULT) PathCreateTempFile( |
166 | __in_opt LPCWSTR wzDirectory, | 166 | __in_opt LPCWSTR wzDirectory, |
167 | __in_opt __format_string LPCWSTR wzFileNameTemplate, | 167 | __in_opt __format_string LPCWSTR wzFileNameTemplate, |
168 | __in DWORD dwUniqueCount, | 168 | __in DWORD dwUniqueCount, |
169 | __in_z LPCWSTR wzPrefix, | ||
169 | __in DWORD dwFileAttributes, | 170 | __in DWORD dwFileAttributes, |
170 | __out_opt LPWSTR* psczTempFile, | 171 | __out_opt LPWSTR* psczTempFile, |
171 | __out_opt HANDLE* phTempFile | 172 | __out_opt HANDLE* phTempFile |
172 | ); | 173 | ); |
173 | 174 | ||
174 | /******************************************************************* | 175 | /******************************************************************* |
176 | PathGetTempFileName - wrapper around ::GetTempFileName. | ||
177 | If the wzPathName is too long, it will use its own algorithm. | ||
178 | *******************************************************************/ | ||
179 | DAPI_(HRESULT) PathGetTempFileName( | ||
180 | __in LPCWSTR wzPathName, | ||
181 | __in LPCWSTR wzPrefixString, | ||
182 | __in UINT uUnique, | ||
183 | __out LPWSTR* psczTempFileName | ||
184 | ); | ||
185 | |||
186 | /******************************************************************* | ||
175 | PathCreateTimeBasedTempFile - creates an empty temp file based on current | 187 | PathCreateTimeBasedTempFile - creates an empty temp file based on current |
176 | system time | 188 | system time |
177 | ********************************************************************/ | 189 | ********************************************************************/ |
@@ -187,7 +199,7 @@ DAPI_(HRESULT) PathCreateTimeBasedTempFile( | |||
187 | /******************************************************************* | 199 | /******************************************************************* |
188 | PathCreateTempDirectory | 200 | PathCreateTempDirectory |
189 | 201 | ||
190 | Note: if wzDirectory is null, ::GetTempPath() will be used instead. | 202 | Note: if wzDirectory is null, ::GetTempPath2() will be used instead. |
191 | *******************************************************************/ | 203 | *******************************************************************/ |
192 | DAPI_(HRESULT) PathCreateTempDirectory( | 204 | DAPI_(HRESULT) PathCreateTempDirectory( |
193 | __in_opt LPCWSTR wzDirectory, | 205 | __in_opt LPCWSTR wzDirectory, |
@@ -201,7 +213,24 @@ DAPI_(HRESULT) PathCreateTempDirectory( | |||
201 | that is backslash terminated. | 213 | that is backslash terminated. |
202 | *******************************************************************/ | 214 | *******************************************************************/ |
203 | DAPI_(HRESULT) PathGetTempPath( | 215 | DAPI_(HRESULT) PathGetTempPath( |
204 | __out_z LPWSTR* psczTempPath | 216 | __out_z LPWSTR* psczTempPath, |
217 | __out_opt SIZE_T* pcch | ||
218 | ); | ||
219 | |||
220 | /******************************************************************* | ||
221 | PathGetSystemDirectory - returns the path to the system folder | ||
222 | that is backslash terminated. | ||
223 | *******************************************************************/ | ||
224 | DAPI_(HRESULT) PathGetSystemDirectory( | ||
225 | __out_z LPWSTR* psczSystemPath | ||
226 | ); | ||
227 | |||
228 | /******************************************************************* | ||
229 | PathGetSystemWow64Directory - returns the path to the system WoW 64 folder | ||
230 | that is backslash terminated. | ||
231 | *******************************************************************/ | ||
232 | DAPI_(HRESULT) PathGetSystemWow64Directory( | ||
233 | __out_z LPWSTR* psczSystemPath | ||
205 | ); | 234 | ); |
206 | 235 | ||
207 | /******************************************************************* | 236 | /******************************************************************* |
@@ -223,12 +252,11 @@ DAPI_(HRESULT) PathGetSystemTempPaths( | |||
223 | ); | 252 | ); |
224 | 253 | ||
225 | /******************************************************************* | 254 | /******************************************************************* |
226 | PathGetKnownFolder - returns the path to a well-known shell folder | 255 | PathGetVolumePathName - wrapper for ::GetVolumePathNameW. |
227 | |||
228 | *******************************************************************/ | 256 | *******************************************************************/ |
229 | DAPI_(HRESULT) PathGetKnownFolder( | 257 | DAPI_(HRESULT) PathGetVolumePathName( |
230 | __in int csidl, | 258 | __in_z LPCWSTR wzFileName, |
231 | __out LPWSTR* psczKnownFolder | 259 | __out_z LPWSTR* psczVolumePathName |
232 | ); | 260 | ); |
233 | 261 | ||
234 | /******************************************************************* | 262 | /******************************************************************* |
@@ -340,6 +368,20 @@ DAPI_(HRESULT) PathGetHierarchyArray( | |||
340 | __inout LPUINT pcPathArray | 368 | __inout LPUINT pcPathArray |
341 | ); | 369 | ); |
342 | 370 | ||
371 | /******************************************************************** | ||
372 | Path2FunctionAllowFallback - allow functions only available in newer versions of Windows. | ||
373 | Typically used for unit testing. | ||
374 | |||
375 | *********************************************************************/ | ||
376 | void DAPI Path2FunctionAllowFallback(); | ||
377 | |||
378 | /******************************************************************** | ||
379 | Path2FunctionForceFallback - ignore functions only available in newer versions of Windows. | ||
380 | Typically used for unit testing. | ||
381 | |||
382 | *********************************************************************/ | ||
383 | void DAPI Path2FunctionForceFallback(); | ||
384 | |||
343 | /******************************************************************* | 385 | /******************************************************************* |
344 | PathCanonicalizePath - wrapper around PathCanonicalizeW. | 386 | PathCanonicalizePath - wrapper around PathCanonicalizeW. |
345 | *******************************************************************/ | 387 | *******************************************************************/ |
@@ -349,6 +391,15 @@ DAPI_(HRESULT) PathCanonicalizePath( | |||
349 | ); | 391 | ); |
350 | 392 | ||
351 | /******************************************************************* | 393 | /******************************************************************* |
394 | PathAllocCanonicalizePath - wrapper around PathAllocCanonicalize. | ||
395 | *******************************************************************/ | ||
396 | DAPI_(HRESULT) PathAllocCanonicalizePath( | ||
397 | __in_z LPCWSTR wzPath, | ||
398 | __in DWORD dwFlags, | ||
399 | __deref_out_z LPWSTR* psczCanonicalized | ||
400 | ); | ||
401 | |||
402 | /******************************************************************* | ||
352 | PathCanonicalizeForComparison - canonicalizes the path based on the given flags. | 403 | PathCanonicalizeForComparison - canonicalizes the path based on the given flags. |
353 | . and .. directories are collapsed. | 404 | . and .. directories are collapsed. |
354 | All / are replaced with \. | 405 | All / are replaced with \. |
diff --git a/src/libs/dutil/WixToolset.DUtil/inc/shelutil.h b/src/libs/dutil/WixToolset.DUtil/inc/shelutil.h index 0b9f539d..2ee7ce87 100644 --- a/src/libs/dutil/WixToolset.DUtil/inc/shelutil.h +++ b/src/libs/dutil/WixToolset.DUtil/inc/shelutil.h | |||
@@ -33,10 +33,25 @@ HRESULT DAPI ShelExecUnelevated( | |||
33 | __in_z_opt LPCWSTR wzWorkingDirectory, | 33 | __in_z_opt LPCWSTR wzWorkingDirectory, |
34 | __in int nShowCmd | 34 | __in int nShowCmd |
35 | ); | 35 | ); |
36 | |||
37 | /******************************************************************** | ||
38 | ShelGetFolder() - translates the CSIDL into KNOWNFOLDERID and calls ShelGetKnownFolder. | ||
39 | If that returns E_NOTIMPL then falls back to ::SHGetFolderPathW. | ||
40 | The CSIDL_FLAG values are not supported, CSIDL_FLAG_CREATE is always used. | ||
41 | The path is backslash terminated. | ||
42 | |||
43 | *******************************************************************/ | ||
36 | HRESULT DAPI ShelGetFolder( | 44 | HRESULT DAPI ShelGetFolder( |
37 | __out_z LPWSTR* psczFolderPath, | 45 | __out_z LPWSTR* psczFolderPath, |
38 | __in int csidlFolder | 46 | __in int csidlFolder |
39 | ); | 47 | ); |
48 | |||
49 | /******************************************************************** | ||
50 | ShelGetKnownFolder() - gets a folder by KNOWNFOLDERID with ::SHGetKnownFolderPath. | ||
51 | The path is backslash terminated. | ||
52 | |||
53 | Note: return E_NOTIMPL if called on pre-Vista operating systems. | ||
54 | *******************************************************************/ | ||
40 | HRESULT DAPI ShelGetKnownFolder( | 55 | HRESULT DAPI ShelGetKnownFolder( |
41 | __out_z LPWSTR* psczFolderPath, | 56 | __out_z LPWSTR* psczFolderPath, |
42 | __in REFKNOWNFOLDERID rfidFolder | 57 | __in REFKNOWNFOLDERID rfidFolder |
diff --git a/src/libs/dutil/WixToolset.DUtil/logutil.cpp b/src/libs/dutil/WixToolset.DUtil/logutil.cpp index 88a90d8c..3a130b4e 100644 --- a/src/libs/dutil/WixToolset.DUtil/logutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/logutil.cpp | |||
@@ -684,9 +684,10 @@ LExit: | |||
684 | extern "C" HRESULT DAPI LogHeader() | 684 | extern "C" HRESULT DAPI LogHeader() |
685 | { | 685 | { |
686 | HRESULT hr = S_OK; | 686 | HRESULT hr = S_OK; |
687 | WCHAR wzComputerName[MAX_PATH]; | 687 | WCHAR wzComputerName[MAX_COMPUTERNAME_LENGTH + 1] = { }; |
688 | DWORD cchComputerName = countof(wzComputerName); | 688 | DWORD cchComputerName = countof(wzComputerName); |
689 | WCHAR wzPath[MAX_PATH]; | 689 | LPWSTR sczPath = NULL; |
690 | LPCWSTR wzPath = NULL; | ||
690 | DWORD dwMajorVersion = 0; | 691 | DWORD dwMajorVersion = 0; |
691 | DWORD dwMinorVersion = 0; | 692 | DWORD dwMinorVersion = 0; |
692 | LPCSTR szLevel = LOGUTIL_UNKNOWN; | 693 | LPCSTR szLevel = LOGUTIL_UNKNOWN; |
@@ -695,12 +696,19 @@ extern "C" HRESULT DAPI LogHeader() | |||
695 | // | 696 | // |
696 | // get the interesting data | 697 | // get the interesting data |
697 | // | 698 | // |
698 | if (!::GetModuleFileNameW(NULL, wzPath, countof(wzPath))) | 699 | |
700 | hr = PathForCurrentProcess(&sczPath, NULL); | ||
701 | if (FAILED(hr)) | ||
702 | { | ||
703 | wzPath = L""; | ||
704 | } | ||
705 | else | ||
699 | { | 706 | { |
700 | memset(wzPath, 0, sizeof(wzPath)); | 707 | wzPath = sczPath; |
708 | |||
709 | hr = FileVersion(wzPath, &dwMajorVersion, &dwMinorVersion); | ||
701 | } | 710 | } |
702 | 711 | ||
703 | hr = FileVersion(wzPath, &dwMajorVersion, &dwMinorVersion); | ||
704 | if (FAILED(hr)) | 712 | if (FAILED(hr)) |
705 | { | 713 | { |
706 | dwMajorVersion = 0; | 714 | dwMajorVersion = 0; |
@@ -743,6 +751,7 @@ extern "C" HRESULT DAPI LogHeader() | |||
743 | hr = S_OK; | 751 | hr = S_OK; |
744 | 752 | ||
745 | ReleaseStr(sczCurrentDateTime); | 753 | ReleaseStr(sczCurrentDateTime); |
754 | ReleaseStr(sczPath); | ||
746 | 755 | ||
747 | return hr; | 756 | return hr; |
748 | } | 757 | } |
diff --git a/src/libs/dutil/WixToolset.DUtil/path2utl.cpp b/src/libs/dutil/WixToolset.DUtil/path2utl.cpp index 3c4b2f88..862a743d 100644 --- a/src/libs/dutil/WixToolset.DUtil/path2utl.cpp +++ b/src/libs/dutil/WixToolset.DUtil/path2utl.cpp | |||
@@ -19,6 +19,65 @@ | |||
19 | #define PathExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_PATHUTIL, g, x, s, __VA_ARGS__) | 19 | #define PathExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_PATHUTIL, g, x, s, __VA_ARGS__) |
20 | 20 | ||
21 | 21 | ||
22 | typedef HRESULT(WINAPI* PFN_PATH_ALLOC_CANONICALIZE)( | ||
23 | __in LPCWSTR wzSource, | ||
24 | __in DWORD dwFlags, | ||
25 | __out_z LPWSTR* psczPathOut | ||
26 | ); | ||
27 | |||
28 | static BOOL vfInitialized = FALSE; | ||
29 | static HMODULE vhPathApiSet_1_1_0 = NULL; | ||
30 | static PFN_PATH_ALLOC_CANONICALIZE vpfnPathAllocCanonicalize = NULL; | ||
31 | static BOOL vfForceFallback = FALSE; | ||
32 | |||
33 | // from PathCch.h | ||
34 | #ifndef PATHCCH_ALLOW_LONG_PATHS | ||
35 | #define PATHCCH_ALLOW_LONG_PATHS 0x01 | ||
36 | #endif | ||
37 | |||
38 | static HRESULT Initialize() | ||
39 | { | ||
40 | HRESULT hr = S_OK; | ||
41 | DWORD er = ERROR_SUCCESS; | ||
42 | |||
43 | if (vfInitialized) | ||
44 | { | ||
45 | ExitFunction(); | ||
46 | } | ||
47 | |||
48 | hr = LoadSystemApiSet(L"api-ms-win-core-path-l1-1-0.dll", &vhPathApiSet_1_1_0); | ||
49 | if (E_MODNOTFOUND == hr) | ||
50 | { | ||
51 | hr = E_NOTIMPL; | ||
52 | } | ||
53 | PathExitOnFailure(hr, "Failed to load api-ms-win-core-path-l1-1-0.dll"); | ||
54 | |||
55 | vpfnPathAllocCanonicalize = reinterpret_cast<PFN_PATH_ALLOC_CANONICALIZE>(::GetProcAddress(vhPathApiSet_1_1_0, "PathAllocCanonicalize")); | ||
56 | if (!vpfnPathAllocCanonicalize) | ||
57 | { | ||
58 | er = ::GetLastError(); | ||
59 | PathExitWithRootFailure(hr, ERROR_PROC_NOT_FOUND == er ? E_NOTIMPL : HRESULT_FROM_WIN32(er), "Failed to get address of PathAllocCanonicalize."); | ||
60 | } | ||
61 | |||
62 | vfInitialized = TRUE; | ||
63 | |||
64 | LExit: | ||
65 | return hr; | ||
66 | } | ||
67 | |||
68 | |||
69 | DAPI_(void) Path2FunctionAllowFallback() | ||
70 | { | ||
71 | vfForceFallback = FALSE; | ||
72 | } | ||
73 | |||
74 | |||
75 | DAPI_(void) Path2FunctionForceFallback() | ||
76 | { | ||
77 | vfForceFallback = TRUE; | ||
78 | } | ||
79 | |||
80 | |||
22 | DAPI_(HRESULT) PathCanonicalizePath( | 81 | DAPI_(HRESULT) PathCanonicalizePath( |
23 | __in_z LPCWSTR wzPath, | 82 | __in_z LPCWSTR wzPath, |
24 | __deref_out_z LPWSTR* psczCanonicalized | 83 | __deref_out_z LPWSTR* psczCanonicalized |
@@ -43,6 +102,37 @@ LExit: | |||
43 | return hr; | 102 | return hr; |
44 | } | 103 | } |
45 | 104 | ||
105 | DAPI_(HRESULT) PathAllocCanonicalizePath( | ||
106 | __in_z LPCWSTR wzPath, | ||
107 | __in DWORD dwFlags, | ||
108 | __deref_out_z LPWSTR* psczCanonicalized | ||
109 | ) | ||
110 | { | ||
111 | HRESULT hr = S_OK; | ||
112 | LPWSTR sczCanonicalizedPath = NULL; | ||
113 | |||
114 | hr = Initialize(); | ||
115 | if (E_NOTIMPL == hr || SUCCEEDED(hr) && !vpfnPathAllocCanonicalize) | ||
116 | { | ||
117 | ExitFunction1(hr = E_NOTIMPL); | ||
118 | } | ||
119 | PathExitOnFailure(hr, "Failed to initialize path2utl."); | ||
120 | |||
121 | hr = vpfnPathAllocCanonicalize(wzPath, dwFlags, &sczCanonicalizedPath); | ||
122 | PathExitOnFailure(hr, "Failed to canonicalize: %ls", wzPath); | ||
123 | |||
124 | hr = StrAllocString(psczCanonicalized, sczCanonicalizedPath, 0); | ||
125 | PathExitOnFailure(hr, "Failed to copy the canonicalized path."); | ||
126 | |||
127 | LExit: | ||
128 | if (sczCanonicalizedPath) | ||
129 | { | ||
130 | ::LocalFree(sczCanonicalizedPath); | ||
131 | } | ||
132 | |||
133 | return hr; | ||
134 | } | ||
135 | |||
46 | DAPI_(HRESULT) PathCanonicalizeForComparison( | 136 | DAPI_(HRESULT) PathCanonicalizeForComparison( |
47 | __in_z LPCWSTR wzPath, | 137 | __in_z LPCWSTR wzPath, |
48 | __in DWORD dwCanonicalizeFlags, | 138 | __in DWORD dwCanonicalizeFlags, |
@@ -75,7 +165,19 @@ DAPI_(HRESULT) PathCanonicalizeForComparison( | |||
75 | 165 | ||
76 | if (*wzNormalizedPath) | 166 | if (*wzNormalizedPath) |
77 | { | 167 | { |
78 | hr = PathCanonicalizePath(wzNormalizedPath, psczCanonicalized); | 168 | if (!vfForceFallback) |
169 | { | ||
170 | hr = PathAllocCanonicalizePath(wzNormalizedPath, PATHCCH_ALLOW_LONG_PATHS, psczCanonicalized); | ||
171 | } | ||
172 | else | ||
173 | { | ||
174 | hr = E_NOTIMPL; | ||
175 | } | ||
176 | |||
177 | if (E_NOTIMPL == hr) | ||
178 | { | ||
179 | hr = PathCanonicalizePath(wzNormalizedPath, psczCanonicalized); | ||
180 | } | ||
79 | PathExitOnFailure(hr, "Failed to canonicalize: %ls", wzNormalizedPath); | 181 | PathExitOnFailure(hr, "Failed to canonicalize: %ls", wzNormalizedPath); |
80 | } | 182 | } |
81 | else | 183 | else |
@@ -273,33 +375,52 @@ DAPI_(HRESULT) PathSystemWindowsSubdirectory( | |||
273 | ) | 375 | ) |
274 | { | 376 | { |
275 | HRESULT hr = S_OK; | 377 | HRESULT hr = S_OK; |
276 | WCHAR wzTempPath[MAX_PATH + 1] = { }; | 378 | LPWSTR sczWindowsPath = NULL; |
379 | DWORD cchBuffer = MAX_PATH + 1; | ||
277 | DWORD cch = 0; | 380 | DWORD cch = 0; |
278 | 381 | ||
279 | cch = ::GetSystemWindowsDirectoryW(wzTempPath, countof(wzTempPath)); | 382 | hr = StrAlloc(&sczWindowsPath, cchBuffer); |
280 | if (!cch) | 383 | PathExitOnFailure(hr, "Failed to alloc Windows directory path."); |
281 | { | 384 | |
282 | PathExitWithLastError(hr, "Failed to get Windows directory path."); | 385 | cch = ::GetSystemWindowsDirectoryW(sczWindowsPath, cchBuffer); |
283 | } | 386 | PathExitOnNullWithLastError(cch, hr, "Failed to get Windows directory path with default size."); |
284 | else if (cch >= countof(wzTempPath)) | 387 | |
388 | cch += 1; // add 1 for null terminator. | ||
389 | |||
390 | if (cch > cchBuffer) | ||
285 | { | 391 | { |
286 | PathExitWithRootFailure(hr, E_INSUFFICIENT_BUFFER, "Windows directory path too long."); | 392 | hr = StrAlloc(&sczWindowsPath, cch); |
393 | PathExitOnFailure(hr, "Failed to realloc Windows directory path."); | ||
394 | |||
395 | cchBuffer = cch; | ||
396 | |||
397 | cch = ::GetSystemWindowsDirectoryW(sczWindowsPath, cchBuffer); | ||
398 | PathExitOnNullWithLastError(cch, hr, "Failed to get Windows directory path with returned size."); | ||
399 | |||
400 | cch += 1; // add 1 for null terminator. | ||
401 | |||
402 | if (cch > cchBuffer) | ||
403 | { | ||
404 | PathExitWithRootFailure(hr, E_INSUFFICIENT_BUFFER, "Failed to get Windows directory path with returned size."); | ||
405 | } | ||
287 | } | 406 | } |
288 | 407 | ||
289 | if (wzSubdirectory) | 408 | if (wzSubdirectory) |
290 | { | 409 | { |
291 | hr = PathConcatRelativeToBase(wzTempPath, wzSubdirectory, psczFullPath); | 410 | hr = PathConcatRelativeToBase(sczWindowsPath, wzSubdirectory, psczFullPath); |
292 | PathExitOnFailure(hr, "Failed to concat subdirectory on Windows directory path."); | 411 | PathExitOnFailure(hr, "Failed to concat subdirectory on Windows directory path."); |
293 | } | 412 | } |
294 | else | 413 | else |
295 | { | 414 | { |
296 | hr = StrAllocString(psczFullPath, wzTempPath, 0); | 415 | *psczFullPath = sczWindowsPath; |
297 | PathExitOnFailure(hr, "Failed to copy Windows directory path."); | 416 | sczWindowsPath = NULL; |
298 | } | 417 | } |
299 | 418 | ||
300 | hr = PathBackslashTerminate(psczFullPath); | 419 | hr = PathBackslashTerminate(psczFullPath); |
301 | PathExitOnFailure(hr, "Failed to terminate Windows directory path with backslash."); | 420 | PathExitOnFailure(hr, "Failed to terminate Windows directory path with backslash."); |
302 | 421 | ||
303 | LExit: | 422 | LExit: |
423 | ReleaseStr(sczWindowsPath); | ||
424 | |||
304 | return hr; | 425 | return hr; |
305 | } | 426 | } |
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; |
diff --git a/src/libs/dutil/WixToolset.DUtil/rexutil.cpp b/src/libs/dutil/WixToolset.DUtil/rexutil.cpp index 155ca714..ce28beb3 100644 --- a/src/libs/dutil/WixToolset.DUtil/rexutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/rexutil.cpp | |||
@@ -28,7 +28,7 @@ static ERF verf; | |||
28 | static FAKE_FILE vrgffFileTable[FILETABLESIZE]; | 28 | static FAKE_FILE vrgffFileTable[FILETABLESIZE]; |
29 | static DWORD vcbRes; | 29 | static DWORD vcbRes; |
30 | static LPCBYTE vpbRes; | 30 | static LPCBYTE vpbRes; |
31 | static CHAR vszResource[MAX_PATH]; | 31 | static LPSTR vpszResource = NULL; |
32 | static REX_CALLBACK_WRITE vpfnWrite = NULL; | 32 | static REX_CALLBACK_WRITE vpfnWrite = NULL; |
33 | 33 | ||
34 | static HRESULT vhrLastError = S_OK; | 34 | static HRESULT vhrLastError = S_OK; |
@@ -85,6 +85,8 @@ LExit: | |||
85 | { | 85 | { |
86 | ::FDIDestroy(vhfdi); | 86 | ::FDIDestroy(vhfdi); |
87 | vhfdi = NULL; | 87 | vhfdi = NULL; |
88 | |||
89 | ReleaseNullStr(vpszResource); | ||
88 | } | 90 | } |
89 | 91 | ||
90 | return hr; | 92 | return hr; |
@@ -101,6 +103,8 @@ extern "C" void RexUninitialize() | |||
101 | { | 103 | { |
102 | ::FDIDestroy(vhfdi); | 104 | ::FDIDestroy(vhfdi); |
103 | vhfdi = NULL; | 105 | vhfdi = NULL; |
106 | |||
107 | ReleaseNullStr(vpszResource); | ||
104 | } | 108 | } |
105 | } | 109 | } |
106 | 110 | ||
@@ -124,12 +128,12 @@ extern "C" HRESULT RexExtract( | |||
124 | { | 128 | { |
125 | Assert(vhfdi); | 129 | Assert(vhfdi); |
126 | HRESULT hr = S_OK; | 130 | HRESULT hr = S_OK; |
127 | BOOL fResult; | 131 | BOOL fResult = FALSE; |
128 | 132 | ||
129 | HRSRC hResInfo = NULL; | 133 | HRSRC hResInfo = NULL; |
130 | HANDLE hRes = NULL; | 134 | HANDLE hRes = NULL; |
131 | 135 | ||
132 | REX_CALLBACK_STRUCT rcs; | 136 | REX_CALLBACK_STRUCT rcs = { }; |
133 | 137 | ||
134 | // remember the write callback | 138 | // remember the write callback |
135 | vpfnWrite = pfnWrite; | 139 | vpfnWrite = pfnWrite; |
@@ -158,7 +162,7 @@ extern "C" HRESULT RexExtract( | |||
158 | // RexExitOnLastError(hr, "failed to convert cabinet resource name to ASCII: %ls", wzResource); | 162 | // RexExitOnLastError(hr, "failed to convert cabinet resource name to ASCII: %ls", wzResource); |
159 | //} | 163 | //} |
160 | 164 | ||
161 | hr = ::StringCchCopyA(vszResource, countof(vszResource), szResource); | 165 | hr = StrAnsiAllocStringAnsi(&vpszResource, szResource, 0); |
162 | RexExitOnFailure(hr, "Failed to copy resource name to global."); | 166 | RexExitOnFailure(hr, "Failed to copy resource name to global."); |
163 | 167 | ||
164 | // | 168 | // |
@@ -171,7 +175,7 @@ extern "C" HRESULT RexExtract( | |||
171 | rcs.pfnProgress = pfnProgress; | 175 | rcs.pfnProgress = pfnProgress; |
172 | rcs.pvContext = pvContext; | 176 | rcs.pvContext = pvContext; |
173 | 177 | ||
174 | fResult = ::FDICopy(vhfdi, vszResource, "", 0, RexCallback, NULL, static_cast<void*>(&rcs)); | 178 | fResult = ::FDICopy(vhfdi, vpszResource, "", 0, RexCallback, NULL, static_cast<void*>(&rcs)); |
175 | if (!fResult && !rcs.fStopExtracting) // if something went wrong and it wasn't us just stopping the extraction, then return a failure | 179 | if (!fResult && !rcs.fStopExtracting) // if something went wrong and it wasn't us just stopping the extraction, then return a failure |
176 | { | 180 | { |
177 | hr = vhrLastError; // TODO: put verf info in trace message here | 181 | hr = vhrLastError; // TODO: put verf info in trace message here |
@@ -227,7 +231,7 @@ static __callback INT_PTR FAR DIAMONDAPI RexOpen(__in_z char FAR *pszFile, int o | |||
227 | RexExitOnFailure(hr, "File table exceeded"); | 231 | RexExitOnFailure(hr, "File table exceeded"); |
228 | } | 232 | } |
229 | 233 | ||
230 | if (0 == lstrcmpA(vszResource, pszFile)) | 234 | if (0 == lstrcmpA(vpszResource, pszFile)) |
231 | { | 235 | { |
232 | vrgffFileTable[i].fUsed = TRUE; | 236 | vrgffFileTable[i].fUsed = TRUE; |
233 | vrgffFileTable[i].fftType = MEMORY_FILE; | 237 | vrgffFileTable[i].fftType = MEMORY_FILE; |
@@ -436,15 +440,16 @@ static __callback INT_PTR DIAMONDAPI RexCallback(FDINOTIFICATIONTYPE iNotificati | |||
436 | HANDLE hFile = INVALID_HANDLE_VALUE; | 440 | HANDLE hFile = INVALID_HANDLE_VALUE; |
437 | 441 | ||
438 | REX_CALLBACK_STRUCT* prcs = static_cast<REX_CALLBACK_STRUCT*>(pFDINotify->pv); | 442 | REX_CALLBACK_STRUCT* prcs = static_cast<REX_CALLBACK_STRUCT*>(pFDINotify->pv); |
439 | LPCSTR sz; | 443 | LPCSTR sz = NULL; |
440 | WCHAR wz[MAX_PATH]; | 444 | LPWSTR pwz = NULL; |
441 | FILETIME ft; | 445 | LPWSTR pwzPath = NULL; |
446 | FILETIME ft = { }; | ||
442 | int i = 0; | 447 | int i = 0; |
443 | 448 | ||
444 | switch (iNotification) | 449 | switch (iNotification) |
445 | { | 450 | { |
446 | case fdintCOPY_FILE: // beGIN extracting a resource from cabinet | 451 | case fdintCOPY_FILE: // beGIN extracting a resource from cabinet |
447 | Assert(pFDINotify->psz1); | 452 | Assert(pFDINotify->psz1 && prcs); |
448 | 453 | ||
449 | if (prcs->fStopExtracting) | 454 | if (prcs->fStopExtracting) |
450 | { | 455 | { |
@@ -453,55 +458,50 @@ static __callback INT_PTR DIAMONDAPI RexCallback(FDINOTIFICATIONTYPE iNotificati | |||
453 | 458 | ||
454 | // convert params to useful variables | 459 | // convert params to useful variables |
455 | sz = static_cast<LPCSTR>(pFDINotify->psz1); | 460 | sz = static_cast<LPCSTR>(pFDINotify->psz1); |
456 | if (!::MultiByteToWideChar(CP_ACP, 0, sz, -1, wz, countof(wz))) | 461 | RexExitOnNull(sz, hr, E_INVALIDARG, "No cabinet file ID given to convert"); |
457 | { | 462 | |
458 | RexExitWithLastError(hr, "failed to convert cabinet file id to unicode: %s", sz); | 463 | hr = StrAllocStringAnsi(&pwz, sz, 0, CP_ACP); |
459 | } | 464 | RexExitOnFailure(hr, "failed to convert cabinet file id to unicode: %hs", sz); |
460 | 465 | ||
461 | if (prcs->pfnProgress) | 466 | if (prcs->pfnProgress) |
462 | { | 467 | { |
463 | hr = prcs->pfnProgress(TRUE, wz, prcs->pvContext); | 468 | hr = prcs->pfnProgress(TRUE, pwz, prcs->pvContext); |
464 | if (S_OK != hr) | 469 | if (S_OK != hr) |
465 | { | 470 | { |
466 | ExitFunction(); | 471 | ExitFunction(); |
467 | } | 472 | } |
468 | } | 473 | } |
469 | 474 | ||
470 | if (L'*' == *prcs->pwzExtract || 0 == lstrcmpW(prcs->pwzExtract, wz)) | 475 | if (L'*' == *prcs->pwzExtract || 0 == lstrcmpW(prcs->pwzExtract, pwz)) |
471 | { | 476 | { |
472 | // get the created date for the resource in the cabinet | 477 | // get the created date for the resource in the cabinet |
473 | if (!::DosDateTimeToFileTime(pFDINotify->date, pFDINotify->time, &ft)) | 478 | if (!::DosDateTimeToFileTime(pFDINotify->date, pFDINotify->time, &ft)) |
474 | { | 479 | { |
475 | RexExitWithLastError(hr, "failed to get time for resource: %ls", wz); | 480 | RexExitWithLastError(hr, "failed to get time for resource: %ls", pwz); |
476 | } | 481 | } |
477 | 482 | ||
478 | WCHAR wzPath[MAX_PATH]; | ||
479 | |||
480 | hr = ::StringCchCopyW(wzPath, countof(wzPath), prcs->pwzExtractDir); | ||
481 | RexExitOnFailure(hr, "failed to copy extract directory: %ls for file: %ls", prcs->pwzExtractDir, wz); | ||
482 | |||
483 | if (L'*' == *prcs->pwzExtract) | 483 | if (L'*' == *prcs->pwzExtract) |
484 | { | 484 | { |
485 | hr = ::StringCchCatW(wzPath, countof(wzPath), wz); | 485 | hr = PathConcat(prcs->pwzExtractDir, pwz, &pwzPath); |
486 | RexExitOnFailure(hr, "failed to concat onto path: %ls file: %ls", wzPath, wz); | 486 | RexExitOnFailure(hr, "failed to concat onto path: %ls file: %ls", prcs->pwzExtractDir, pwz); |
487 | } | 487 | } |
488 | else | 488 | else |
489 | { | 489 | { |
490 | Assert(*prcs->pwzExtractName); | 490 | Assert(*prcs->pwzExtractName); |
491 | 491 | ||
492 | hr = ::StringCchCatW(wzPath, countof(wzPath), prcs->pwzExtractName); | 492 | hr = PathConcat(prcs->pwzExtractDir, prcs->pwzExtractName, &pwzPath); |
493 | RexExitOnFailure(hr, "failed to concat onto path: %ls file: %ls", wzPath, prcs->pwzExtractName); | 493 | RexExitOnFailure(hr, "failed to concat onto path: %ls file: %ls", prcs->pwzExtractDir, prcs->pwzExtractName); |
494 | } | 494 | } |
495 | 495 | ||
496 | // Quickly chop off the file name part of the path to ensure the path exists | 496 | // Quickly chop off the file name part of the path to ensure the path exists |
497 | // then put the file name back on the path (by putting the first character | 497 | // then put the file name back on the path (by putting the first character |
498 | // back over the null terminator). | 498 | // back over the null terminator). |
499 | LPWSTR wzFile = PathFile(wzPath); | 499 | LPWSTR wzFile = PathFile(pwzPath); |
500 | WCHAR wzFileFirstChar = *wzFile; | 500 | WCHAR wzFileFirstChar = *wzFile; |
501 | *wzFile = L'\0'; | 501 | *wzFile = L'\0'; |
502 | 502 | ||
503 | hr = DirEnsureExists(wzPath, NULL); | 503 | hr = DirEnsureExists(pwzPath, NULL); |
504 | RexExitOnFailure(hr, "failed to ensure directory: %ls", wzPath); | 504 | RexExitOnFailure(hr, "failed to ensure directory: %ls", pwzPath); |
505 | 505 | ||
506 | hr = S_OK; | 506 | hr = S_OK; |
507 | 507 | ||
@@ -524,10 +524,10 @@ static __callback INT_PTR DIAMONDAPI RexCallback(FDINOTIFICATIONTYPE iNotificati | |||
524 | } | 524 | } |
525 | 525 | ||
526 | // open the file | 526 | // open the file |
527 | hFile = ::CreateFileW(wzPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); | 527 | hFile = ::CreateFileW(pwzPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); |
528 | if (INVALID_HANDLE_VALUE == hFile) | 528 | if (INVALID_HANDLE_VALUE == hFile) |
529 | { | 529 | { |
530 | RexExitWithLastError(hr, "failed to open file: %ls", wzPath); | 530 | RexExitWithLastError(hr, "failed to open file: %ls", pwzPath); |
531 | } | 531 | } |
532 | 532 | ||
533 | vrgffFileTable[i].fUsed = TRUE; | 533 | vrgffFileTable[i].fUsed = TRUE; |
@@ -554,20 +554,20 @@ static __callback INT_PTR DIAMONDAPI RexCallback(FDINOTIFICATIONTYPE iNotificati | |||
554 | 554 | ||
555 | break; | 555 | break; |
556 | case fdintCLOSE_FILE_INFO: // resource extraction complete | 556 | case fdintCLOSE_FILE_INFO: // resource extraction complete |
557 | Assert(pFDINotify->hf && pFDINotify->psz1); | 557 | Assert(pFDINotify->hf && prcs && pFDINotify->psz1); |
558 | 558 | ||
559 | // convert params to useful variables | 559 | // convert params to useful variables |
560 | sz = static_cast<LPCSTR>(pFDINotify->psz1); | 560 | sz = static_cast<LPCSTR>(pFDINotify->psz1); |
561 | if (!::MultiByteToWideChar(CP_ACP, 0, sz, -1, wz, countof(wz))) | 561 | RexExitOnNull(sz, hr, E_INVALIDARG, "No cabinet file ID given to convert"); |
562 | { | 562 | |
563 | RexExitWithLastError(hr, "failed to convert cabinet file id to unicode: %s", sz); | 563 | hr = StrAllocStringAnsi(&pwz, sz, 0, CP_ACP); |
564 | } | 564 | RexExitOnFailure(hr, "failed to convert cabinet file id to unicode: %hs", sz); |
565 | 565 | ||
566 | RexClose(pFDINotify->hf); | 566 | RexClose(pFDINotify->hf); |
567 | 567 | ||
568 | if (prcs->pfnProgress) | 568 | if (prcs->pfnProgress) |
569 | { | 569 | { |
570 | hr = prcs->pfnProgress(FALSE, wz, prcs->pvContext); | 570 | hr = prcs->pfnProgress(FALSE, pwz, prcs->pvContext); |
571 | } | 571 | } |
572 | 572 | ||
573 | if (S_OK == hr && L'*' == *prcs->pwzExtract) // if everything is okay and we're extracting all files, keep going | 573 | if (S_OK == hr && L'*' == *prcs->pwzExtract) // if everything is okay and we're extracting all files, keep going |
@@ -597,5 +597,8 @@ LExit: | |||
597 | vhrLastError = hr; | 597 | vhrLastError = hr; |
598 | } | 598 | } |
599 | 599 | ||
600 | ReleaseStr(pwz); | ||
601 | ReleaseStr(pwzPath); | ||
602 | |||
600 | return (S_OK == hr) ? ipResult : -1; | 603 | return (S_OK == hr) ? ipResult : -1; |
601 | } | 604 | } |
diff --git a/src/libs/dutil/WixToolset.DUtil/sceutil.cpp b/src/libs/dutil/WixToolset.DUtil/sceutil.cpp index 4eede74f..590c937a 100644 --- a/src/libs/dutil/WixToolset.DUtil/sceutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/sceutil.cpp | |||
@@ -317,7 +317,7 @@ extern "C" HRESULT DAPI SceOpenDatabase( | |||
317 | { | 317 | { |
318 | HRESULT hr = S_OK; | 318 | HRESULT hr = S_OK; |
319 | DWORD dwVersionFound = 0; | 319 | DWORD dwVersionFound = 0; |
320 | WCHAR wzTempDbFile[MAX_PATH]; | 320 | LPWSTR sczTempDbFile = NULL; |
321 | LPCWSTR wzPathToOpen = NULL; | 321 | LPCWSTR wzPathToOpen = NULL; |
322 | LPWSTR sczSchemaType = NULL; | 322 | LPWSTR sczSchemaType = NULL; |
323 | SCE_DATABASE *pNewSceDatabase = NULL; | 323 | SCE_DATABASE *pNewSceDatabase = NULL; |
@@ -343,16 +343,16 @@ extern "C" HRESULT DAPI SceOpenDatabase( | |||
343 | // TODO: had trouble getting SQL CE to read a file read-only, so we're copying it to a temp path for now. | 343 | // TODO: had trouble getting SQL CE to read a file read-only, so we're copying it to a temp path for now. |
344 | if (fReadOnly) | 344 | if (fReadOnly) |
345 | { | 345 | { |
346 | hr = DirCreateTempPath(PathFile(sczFile), (LPWSTR)wzTempDbFile, _countof(wzTempDbFile)); | 346 | hr = DirCreateTempPath(PathFile(sczFile), &sczTempDbFile); |
347 | ExitOnFailure(hr, "Failed to get temp path"); | 347 | ExitOnFailure(hr, "Failed to get temp path"); |
348 | 348 | ||
349 | hr = FileEnsureCopy(sczFile, (LPCWSTR)wzTempDbFile, TRUE); | 349 | hr = FileEnsureCopy(sczFile, sczTempDbFile, TRUE); |
350 | ExitOnFailure(hr, "Failed to copy file to temp path"); | 350 | ExitOnFailure(hr, "Failed to copy file to temp path"); |
351 | 351 | ||
352 | hr = StrAllocString(&pNewSceDatabaseInternal->sczTempDbFile, (LPCWSTR)wzTempDbFile, 0); | 352 | hr = StrAllocString(&pNewSceDatabaseInternal->sczTempDbFile, sczTempDbFile, 0); |
353 | ExitOnFailure(hr, "Failed to copy temp db file path"); | 353 | ExitOnFailure(hr, "Failed to copy temp db file path"); |
354 | 354 | ||
355 | wzPathToOpen = (LPCWSTR)wzTempDbFile; | 355 | wzPathToOpen = sczTempDbFile; |
356 | } | 356 | } |
357 | else | 357 | else |
358 | { | 358 | { |
@@ -424,6 +424,7 @@ extern "C" HRESULT DAPI SceOpenDatabase( | |||
424 | LExit: | 424 | LExit: |
425 | ReleaseBSTR(rgdbpDataSourceProp[0].vValue.bstrVal); | 425 | ReleaseBSTR(rgdbpDataSourceProp[0].vValue.bstrVal); |
426 | ReleaseStr(sczSchemaType); | 426 | ReleaseStr(sczSchemaType); |
427 | ReleaseStr(sczTempDbFile); | ||
427 | ReleaseDatabase(pNewSceDatabase); | 428 | ReleaseDatabase(pNewSceDatabase); |
428 | 429 | ||
429 | return hr; | 430 | return hr; |
diff --git a/src/libs/dutil/WixToolset.DUtil/shelutil.cpp b/src/libs/dutil/WixToolset.DUtil/shelutil.cpp index 2eb9a52a..72a0e5ce 100644 --- a/src/libs/dutil/WixToolset.DUtil/shelutil.cpp +++ b/src/libs/dutil/WixToolset.DUtil/shelutil.cpp | |||
@@ -9,6 +9,7 @@ | |||
9 | #define ShelExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_SHELUTIL, x, s, __VA_ARGS__) | 9 | #define ShelExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_SHELUTIL, x, s, __VA_ARGS__) |
10 | #define ShelExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_SHELUTIL, x, s, __VA_ARGS__) | 10 | #define ShelExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_SHELUTIL, x, s, __VA_ARGS__) |
11 | #define ShelExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_SHELUTIL, x, s, __VA_ARGS__) | 11 | #define ShelExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_SHELUTIL, x, s, __VA_ARGS__) |
12 | #define ShelExitWithRootFailure(x, e, s, ...) ExitWithRootFailureSource(DUTIL_SOURCE_SHELUTIL, x, e, s, __VA_ARGS__) | ||
12 | #define ShelExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_SHELUTIL, x, s, __VA_ARGS__) | 13 | #define ShelExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_SHELUTIL, x, s, __VA_ARGS__) |
13 | #define ShelExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_SHELUTIL, p, x, e, s, __VA_ARGS__) | 14 | #define ShelExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_SHELUTIL, p, x, e, s, __VA_ARGS__) |
14 | #define ShelExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_SHELUTIL, p, x, s, __VA_ARGS__) | 15 | #define ShelExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_SHELUTIL, p, x, s, __VA_ARGS__) |
@@ -19,6 +20,10 @@ | |||
19 | 20 | ||
20 | static PFN_SHELLEXECUTEEXW vpfnShellExecuteExW = ::ShellExecuteExW; | 21 | static PFN_SHELLEXECUTEEXW vpfnShellExecuteExW = ::ShellExecuteExW; |
21 | 22 | ||
23 | static HRESULT DAPI GetFolderFromCsidl( | ||
24 | __out_z LPWSTR* psczFolderPath, | ||
25 | __in int csidlFolder | ||
26 | ); | ||
22 | static HRESULT GetDesktopShellView( | 27 | static HRESULT GetDesktopShellView( |
23 | __in REFIID riid, | 28 | __in REFIID riid, |
24 | __out void **ppv | 29 | __out void **ppv |
@@ -57,7 +62,14 @@ extern "C" HRESULT DAPI ShelExec( | |||
57 | ) | 62 | ) |
58 | { | 63 | { |
59 | HRESULT hr = S_OK; | 64 | HRESULT hr = S_OK; |
60 | SHELLEXECUTEINFOW shExecInfo = {}; | 65 | SHELLEXECUTEINFOW shExecInfo = { }; |
66 | size_t cchWorkingDirectory = 0; | ||
67 | |||
68 | // CreateProcessW has undocumented MAX_PATH restriction for lpCurrentDirectory even when long path support is enabled. | ||
69 | if (wzWorkingDirectory && FAILED(::StringCchLengthW(wzWorkingDirectory, MAX_PATH - 1, &cchWorkingDirectory))) | ||
70 | { | ||
71 | wzWorkingDirectory = NULL; | ||
72 | } | ||
61 | 73 | ||
62 | shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); | 74 | shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); |
63 | shExecInfo.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS; | 75 | shExecInfo.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS; |
@@ -159,11 +171,7 @@ LExit: | |||
159 | } | 171 | } |
160 | 172 | ||
161 | 173 | ||
162 | /******************************************************************** | 174 | static HRESULT DAPI GetFolderFromCsidl( |
163 | ShelGetFolder() - gets a folder by CSIDL. | ||
164 | |||
165 | *******************************************************************/ | ||
166 | extern "C" HRESULT DAPI ShelGetFolder( | ||
167 | __out_z LPWSTR* psczFolderPath, | 175 | __out_z LPWSTR* psczFolderPath, |
168 | __in int csidlFolder | 176 | __in int csidlFolder |
169 | ) | 177 | ) |
@@ -185,19 +193,6 @@ LExit: | |||
185 | } | 193 | } |
186 | 194 | ||
187 | 195 | ||
188 | /******************************************************************** | ||
189 | ShelGetKnownFolder() - gets a folder by KNOWNFOLDERID. | ||
190 | |||
191 | Note: return E_NOTIMPL if called on pre-Vista operating systems. | ||
192 | *******************************************************************/ | ||
193 | #ifndef REFKNOWNFOLDERID | ||
194 | #define REFKNOWNFOLDERID REFGUID | ||
195 | #endif | ||
196 | |||
197 | #ifndef KF_FLAG_CREATE | ||
198 | #define KF_FLAG_CREATE 0x00008000 // Make sure that the folder already exists or create it and apply security specified in folder definition | ||
199 | #endif | ||
200 | |||
201 | EXTERN_C typedef HRESULT (STDAPICALLTYPE *PFN_SHGetKnownFolderPath)( | 196 | EXTERN_C typedef HRESULT (STDAPICALLTYPE *PFN_SHGetKnownFolderPath)( |
202 | REFKNOWNFOLDERID rfid, | 197 | REFKNOWNFOLDERID rfid, |
203 | DWORD dwFlags, | 198 | DWORD dwFlags, |
@@ -249,6 +244,181 @@ LExit: | |||
249 | return hr; | 244 | return hr; |
250 | } | 245 | } |
251 | 246 | ||
247 | extern "C" HRESULT DAPI ShelGetFolder( | ||
248 | __out_z LPWSTR* psczFolderPath, | ||
249 | __in int csidlFolder | ||
250 | ) | ||
251 | { | ||
252 | HRESULT hr = S_OK; | ||
253 | LPWSTR sczPath = NULL; | ||
254 | KNOWNFOLDERID rfid = { }; | ||
255 | |||
256 | csidlFolder &= ~CSIDL_FLAG_MASK; | ||
257 | |||
258 | switch (csidlFolder) | ||
259 | { | ||
260 | case CSIDL_ADMINTOOLS: | ||
261 | rfid = FOLDERID_AdminTools; | ||
262 | break; | ||
263 | case CSIDL_APPDATA: | ||
264 | rfid = FOLDERID_RoamingAppData; | ||
265 | break; | ||
266 | case CSIDL_CDBURN_AREA: | ||
267 | rfid = FOLDERID_CDBurning; | ||
268 | break; | ||
269 | case CSIDL_COMMON_ADMINTOOLS: | ||
270 | rfid = FOLDERID_CommonAdminTools; | ||
271 | break; | ||
272 | case CSIDL_COMMON_APPDATA: | ||
273 | rfid = FOLDERID_ProgramData; | ||
274 | break; | ||
275 | case CSIDL_COMMON_DESKTOPDIRECTORY: | ||
276 | rfid = FOLDERID_PublicDesktop; | ||
277 | break; | ||
278 | case CSIDL_COMMON_DOCUMENTS: | ||
279 | rfid = FOLDERID_PublicDocuments; | ||
280 | break; | ||
281 | case CSIDL_COMMON_MUSIC: | ||
282 | rfid = FOLDERID_PublicMusic; | ||
283 | break; | ||
284 | case CSIDL_COMMON_OEM_LINKS: | ||
285 | rfid = FOLDERID_CommonOEMLinks; | ||
286 | break; | ||
287 | case CSIDL_COMMON_PICTURES: | ||
288 | rfid = FOLDERID_PublicPictures; | ||
289 | break; | ||
290 | case CSIDL_COMMON_PROGRAMS: | ||
291 | rfid = FOLDERID_CommonPrograms; | ||
292 | break; | ||
293 | case CSIDL_COMMON_STARTMENU: | ||
294 | rfid = FOLDERID_CommonStartMenu; | ||
295 | break; | ||
296 | case CSIDL_COMMON_STARTUP: __fallthrough; | ||
297 | case CSIDL_COMMON_ALTSTARTUP: | ||
298 | rfid = FOLDERID_CommonStartup; | ||
299 | break; | ||
300 | case CSIDL_COMMON_TEMPLATES: | ||
301 | rfid = FOLDERID_CommonTemplates; | ||
302 | break; | ||
303 | case CSIDL_COMMON_VIDEO: | ||
304 | rfid = FOLDERID_PublicVideos; | ||
305 | break; | ||
306 | case CSIDL_COOKIES: | ||
307 | rfid = FOLDERID_Cookies; | ||
308 | break; | ||
309 | case CSIDL_DESKTOP: | ||
310 | case CSIDL_DESKTOPDIRECTORY: | ||
311 | rfid = FOLDERID_Desktop; | ||
312 | break; | ||
313 | case CSIDL_FAVORITES: __fallthrough; | ||
314 | case CSIDL_COMMON_FAVORITES: | ||
315 | rfid = FOLDERID_Favorites; | ||
316 | break; | ||
317 | case CSIDL_FONTS: | ||
318 | rfid = FOLDERID_Fonts; | ||
319 | break; | ||
320 | case CSIDL_HISTORY: | ||
321 | rfid = FOLDERID_History; | ||
322 | break; | ||
323 | case CSIDL_INTERNET_CACHE: | ||
324 | rfid = FOLDERID_InternetCache; | ||
325 | break; | ||
326 | case CSIDL_LOCAL_APPDATA: | ||
327 | rfid = FOLDERID_LocalAppData; | ||
328 | break; | ||
329 | case CSIDL_MYMUSIC: | ||
330 | rfid = FOLDERID_Music; | ||
331 | break; | ||
332 | case CSIDL_MYPICTURES: | ||
333 | rfid = FOLDERID_Pictures; | ||
334 | break; | ||
335 | case CSIDL_MYVIDEO: | ||
336 | rfid = FOLDERID_Videos; | ||
337 | break; | ||
338 | case CSIDL_NETHOOD: | ||
339 | rfid = FOLDERID_NetHood; | ||
340 | break; | ||
341 | case CSIDL_PERSONAL: | ||
342 | rfid = FOLDERID_Documents; | ||
343 | break; | ||
344 | case CSIDL_PRINTHOOD: | ||
345 | rfid = FOLDERID_PrintHood; | ||
346 | break; | ||
347 | case CSIDL_PROFILE: | ||
348 | rfid = FOLDERID_Profile; | ||
349 | break; | ||
350 | case CSIDL_PROGRAM_FILES: | ||
351 | rfid = FOLDERID_ProgramFiles; | ||
352 | break; | ||
353 | case CSIDL_PROGRAM_FILESX86: | ||
354 | rfid = FOLDERID_ProgramFilesX86; | ||
355 | break; | ||
356 | case CSIDL_PROGRAM_FILES_COMMON: | ||
357 | rfid = FOLDERID_ProgramFilesCommon; | ||
358 | break; | ||
359 | case CSIDL_PROGRAM_FILES_COMMONX86: | ||
360 | rfid = FOLDERID_ProgramFilesCommonX86; | ||
361 | break; | ||
362 | case CSIDL_PROGRAMS: | ||
363 | rfid = FOLDERID_Programs; | ||
364 | break; | ||
365 | case CSIDL_RECENT: | ||
366 | rfid = FOLDERID_Recent; | ||
367 | break; | ||
368 | case CSIDL_RESOURCES: | ||
369 | rfid = FOLDERID_ResourceDir; | ||
370 | break; | ||
371 | case CSIDL_RESOURCES_LOCALIZED: | ||
372 | rfid = FOLDERID_LocalizedResourcesDir; | ||
373 | break; | ||
374 | case CSIDL_SENDTO: | ||
375 | rfid = FOLDERID_SendTo; | ||
376 | break; | ||
377 | case CSIDL_STARTMENU: | ||
378 | rfid = FOLDERID_StartMenu; | ||
379 | break; | ||
380 | case CSIDL_STARTUP: | ||
381 | case CSIDL_ALTSTARTUP: | ||
382 | rfid = FOLDERID_Startup; | ||
383 | break; | ||
384 | case CSIDL_SYSTEM: | ||
385 | rfid = FOLDERID_System; | ||
386 | break; | ||
387 | case CSIDL_SYSTEMX86: | ||
388 | rfid = FOLDERID_SystemX86; | ||
389 | break; | ||
390 | case CSIDL_TEMPLATES: | ||
391 | rfid = FOLDERID_Templates; | ||
392 | break; | ||
393 | case CSIDL_WINDOWS: | ||
394 | rfid = FOLDERID_Windows; | ||
395 | break; | ||
396 | default: | ||
397 | ShelExitWithRootFailure(hr, E_INVALIDARG, "Unknown csidl: %d", csidlFolder); | ||
398 | } | ||
399 | |||
400 | hr = ShelGetKnownFolder(&sczPath, rfid); | ||
401 | if (E_NOTIMPL == hr) | ||
402 | { | ||
403 | hr = S_FALSE; | ||
404 | } | ||
405 | ShelExitOnFailure(hr, "Failed to get known folder."); | ||
406 | |||
407 | if (S_FALSE == hr) | ||
408 | { | ||
409 | hr = GetFolderFromCsidl(&sczPath, csidlFolder); | ||
410 | ShelExitOnFailure(hr, "Failed to get csidl folder."); | ||
411 | } | ||
412 | |||
413 | *psczFolderPath = sczPath; | ||
414 | sczPath = NULL; | ||
415 | |||
416 | LExit: | ||
417 | ReleaseStr(sczPath); | ||
418 | |||
419 | return hr; | ||
420 | } | ||
421 | |||
252 | 422 | ||
253 | // Internal functions. | 423 | // Internal functions. |
254 | 424 | ||
@@ -287,7 +457,7 @@ static HRESULT GetDesktopShellView( | |||
287 | else if (S_FALSE == hr) | 457 | else if (S_FALSE == hr) |
288 | { | 458 | { |
289 | //Windows XP | 459 | //Windows XP |
290 | hr = SHGetDesktopFolder(&psf); | 460 | hr = ::SHGetDesktopFolder(&psf); |
291 | ShelExitOnFailure(hr, "Failed to get desktop folder."); | 461 | ShelExitOnFailure(hr, "Failed to get desktop folder."); |
292 | 462 | ||
293 | hr = psf->CreateViewObject(NULL, IID_IShellView, ppv); | 463 | hr = psf->CreateViewObject(NULL, IID_IShellView, ppv); |
diff --git a/src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp b/src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp index e9ef1047..109c558c 100644 --- a/src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp +++ b/src/libs/dutil/test/DUtilUnitTest/PathUtilTest.cpp | |||
@@ -7,6 +7,11 @@ using namespace System::IO; | |||
7 | using namespace Xunit; | 7 | using namespace Xunit; |
8 | using namespace WixBuildTools::TestSupport; | 8 | using namespace WixBuildTools::TestSupport; |
9 | 9 | ||
10 | // from PathCch.h | ||
11 | #ifndef PATHCCH_ALLOW_LONG_PATHS | ||
12 | #define PATHCCH_ALLOW_LONG_PATHS 0x01 | ||
13 | #endif | ||
14 | |||
10 | namespace DutilTests | 15 | namespace DutilTests |
11 | { | 16 | { |
12 | public ref class PathUtil | 17 | public ref class PathUtil |
@@ -102,18 +107,54 @@ namespace DutilTests | |||
102 | } | 107 | } |
103 | 108 | ||
104 | [Fact] | 109 | [Fact] |
110 | void PathCanonicalizeForComparisonFallbackTest() | ||
111 | { | ||
112 | Path2FunctionForceFallback(); | ||
113 | |||
114 | try | ||
115 | { | ||
116 | PathCanonicalizeForComparisonTestCore(FALSE); | ||
117 | } | ||
118 | finally | ||
119 | { | ||
120 | Path2FunctionAllowFallback(); | ||
121 | } | ||
122 | } | ||
123 | |||
124 | [Fact] | ||
105 | void PathCanonicalizeForComparisonTest() | 125 | void PathCanonicalizeForComparisonTest() |
106 | { | 126 | { |
127 | PathCanonicalizeForComparisonTestCore(TRUE); | ||
128 | } | ||
129 | |||
130 | void PathCanonicalizeForComparisonTestCore(BOOL fLongPathSupported) | ||
131 | { | ||
107 | HRESULT hr = S_OK; | 132 | HRESULT hr = S_OK; |
108 | LPWSTR sczCanonicalized = NULL; | 133 | LPWSTR sczCanonicalized = NULL; |
109 | 134 | ||
110 | try | 135 | try |
111 | { | 136 | { |
112 | hr = PathCanonicalizeForComparison(L"C:\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789", 0, &sczCanonicalized); | 137 | hr = PathCanonicalizeForComparison(L"C:\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789", 0, &sczCanonicalized); |
113 | Assert::Equal<HRESULT>(HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE), hr); | 138 | if (!fLongPathSupported) |
139 | { | ||
140 | Assert::Equal<HRESULT>(HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE), hr); | ||
141 | } | ||
142 | else | ||
143 | { | ||
144 | NativeAssert::Succeeded(hr, "Failed to canonicalize path"); | ||
145 | NativeAssert::StringEqual(L"\\\\?\\C:\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789", sczCanonicalized); | ||
146 | } | ||
114 | 147 | ||
115 | hr = PathCanonicalizeForComparison(L"\\\\?\\C:\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789", 0, &sczCanonicalized); | 148 | hr = PathCanonicalizeForComparison(L"\\\\?\\C:\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789", 0, &sczCanonicalized); |
116 | Assert::Equal<HRESULT>(HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE), hr); | 149 | if (!fLongPathSupported) |
150 | { | ||
151 | Assert::Equal<HRESULT>(HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE), hr); | ||
152 | } | ||
153 | else | ||
154 | { | ||
155 | NativeAssert::Succeeded(hr, "Failed to canonicalize path"); | ||
156 | NativeAssert::StringEqual(L"\\\\?\\C:\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789", sczCanonicalized); | ||
157 | } | ||
117 | 158 | ||
118 | hr = PathCanonicalizeForComparison(L"\\\\server", PATH_CANONICALIZE_KEEP_UNC_ROOT, &sczCanonicalized); | 159 | hr = PathCanonicalizeForComparison(L"\\\\server", PATH_CANONICALIZE_KEEP_UNC_ROOT, &sczCanonicalized); |
119 | NativeAssert::Succeeded(hr, "Failed to canonicalize path"); | 160 | NativeAssert::Succeeded(hr, "Failed to canonicalize path"); |
@@ -238,6 +279,52 @@ namespace DutilTests | |||
238 | } | 279 | } |
239 | 280 | ||
240 | [Fact] | 281 | [Fact] |
282 | void PathAllocCanonicalizePathTest() | ||
283 | { | ||
284 | HRESULT hr = S_OK; | ||
285 | LPWSTR sczCanonicalized = NULL; | ||
286 | |||
287 | try | ||
288 | { | ||
289 | hr = PathAllocCanonicalizePath(L"C:\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789", PATHCCH_ALLOW_LONG_PATHS, &sczCanonicalized); | ||
290 | NativeAssert::Succeeded(hr, "Failed to canonicalize path"); | ||
291 | NativeAssert::StringEqual(L"\\\\?\\C:\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789", sczCanonicalized); | ||
292 | |||
293 | hr = PathAllocCanonicalizePath(L"abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789", PATHCCH_ALLOW_LONG_PATHS, &sczCanonicalized); | ||
294 | NativeAssert::Succeeded(hr, "Failed to canonicalize path"); | ||
295 | NativeAssert::StringEqual(L"abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789\\abcdefghijklomnopqrstuvwxyz0123456789", sczCanonicalized); | ||
296 | |||
297 | hr = PathAllocCanonicalizePath(L"\\\\server\\share\\..\\..\\otherdir\\unc.exe", PATHCCH_ALLOW_LONG_PATHS, &sczCanonicalized); | ||
298 | NativeAssert::Succeeded(hr, "Failed to canonicalize path"); | ||
299 | NativeAssert::StringEqual(L"\\\\otherdir\\unc.exe", sczCanonicalized); // This is surprising. | ||
300 | |||
301 | hr = PathAllocCanonicalizePath(L"C:\\dir\\subdir\\..\\..\\otherdir\\backslashes.exe", PATHCCH_ALLOW_LONG_PATHS, &sczCanonicalized); | ||
302 | NativeAssert::Succeeded(hr, "Failed to canonicalize path"); | ||
303 | NativeAssert::StringEqual(L"C:\\otherdir\\backslashes.exe", sczCanonicalized); | ||
304 | |||
305 | hr = PathAllocCanonicalizePath(L"C:/dir/subdir/../../otherdir/forwardslashes.exe", PATHCCH_ALLOW_LONG_PATHS, &sczCanonicalized); | ||
306 | NativeAssert::Succeeded(hr, "Failed to canonicalize path"); | ||
307 | NativeAssert::StringEqual(L"C:/dir/subdir/../../otherdir/forwardslashes.exe", sczCanonicalized); | ||
308 | |||
309 | hr = PathAllocCanonicalizePath(L"\\\\?\\C:\\test\\..\\validlongpath.exe", PATHCCH_ALLOW_LONG_PATHS, &sczCanonicalized); | ||
310 | NativeAssert::Succeeded(hr, "Failed to canonicalize path"); | ||
311 | NativeAssert::StringEqual(L"C:\\validlongpath.exe", sczCanonicalized); | ||
312 | |||
313 | hr = PathAllocCanonicalizePath(L"\\\\?\\test\\..\\invalidlongpath.exe", PATHCCH_ALLOW_LONG_PATHS, &sczCanonicalized); | ||
314 | NativeAssert::Succeeded(hr, "Failed to canonicalize path"); | ||
315 | NativeAssert::StringEqual(L"\\\\?\\invalidlongpath.exe", sczCanonicalized); | ||
316 | |||
317 | hr = PathAllocCanonicalizePath(L"C:\\.\\invalid:pathchars?.exe", PATHCCH_ALLOW_LONG_PATHS, &sczCanonicalized); | ||
318 | NativeAssert::Succeeded(hr, "Failed to canonicalize path"); | ||
319 | NativeAssert::StringEqual(L"C:\\invalid:pathchars?.exe", sczCanonicalized); | ||
320 | } | ||
321 | finally | ||
322 | { | ||
323 | ReleaseStr(sczCanonicalized); | ||
324 | } | ||
325 | } | ||
326 | |||
327 | [Fact] | ||
241 | void PathConcatTest() | 328 | void PathConcatTest() |
242 | { | 329 | { |
243 | HRESULT hr = S_OK; | 330 | HRESULT hr = S_OK; |
@@ -545,6 +632,25 @@ namespace DutilTests | |||
545 | } | 632 | } |
546 | 633 | ||
547 | [Fact] | 634 | [Fact] |
635 | void PathForCurrentProcessTest() | ||
636 | { | ||
637 | HRESULT hr = S_OK; | ||
638 | LPWSTR sczPath = NULL; | ||
639 | |||
640 | try | ||
641 | { | ||
642 | hr = PathForCurrentProcess(&sczPath, NULL); | ||
643 | NativeAssert::Succeeded(hr, "Failed to get current process path."); | ||
644 | |||
645 | WixAssert::StringEqual(System::Diagnostics::Process::GetCurrentProcess()->MainModule->FileName, gcnew String(sczPath), false); | ||
646 | } | ||
647 | finally | ||
648 | { | ||
649 | ReleaseStr(sczPath); | ||
650 | } | ||
651 | } | ||
652 | |||
653 | [Fact] | ||
548 | void PathGetDirectoryTest() | 654 | void PathGetDirectoryTest() |
549 | { | 655 | { |
550 | HRESULT hr = S_OK; | 656 | HRESULT hr = S_OK; |
@@ -828,6 +934,78 @@ namespace DutilTests | |||
828 | } | 934 | } |
829 | 935 | ||
830 | [Fact] | 936 | [Fact] |
937 | void PathGetTempPathTest() | ||
938 | { | ||
939 | HRESULT hr = S_OK; | ||
940 | LPCWSTR wzEnvName = L"TMP"; | ||
941 | LPCWSTR wzEnvName2 = L"TEMP"; | ||
942 | LPCWSTR wzLongTempPath = L"C:\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\\cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\\"; | ||
943 | LPWSTR sczTempPath = NULL; | ||
944 | WCHAR wzOriginalTemp[MAX_PATH + 1] = { }; | ||
945 | WCHAR wzOriginalTemp2[MAX_PATH + 1] = { }; | ||
946 | DWORD cch = 0; | ||
947 | DWORD cch2 = 0; | ||
948 | SIZE_T cchTemp = 0; | ||
949 | size_t cchTemp2 = 0; | ||
950 | |||
951 | try | ||
952 | { | ||
953 | cch = ::GetEnvironmentVariableW(wzEnvName, wzOriginalTemp, countof(wzOriginalTemp)); | ||
954 | Assert::NotEqual<DWORD>(0, cch); | ||
955 | |||
956 | if (!::SetEnvironmentVariableW(wzEnvName, wzLongTempPath)) | ||
957 | { | ||
958 | Assert::Equal<DWORD>(0xFFFFFFFF, ::GetLastError()); | ||
959 | } | ||
960 | |||
961 | cch2 = ::GetEnvironmentVariableW(wzEnvName2, wzOriginalTemp2, countof(wzOriginalTemp2)); | ||
962 | Assert::NotEqual<DWORD>(0, cch2); | ||
963 | |||
964 | hr = PathGetTempPath(&sczTempPath, &cchTemp); | ||
965 | NativeAssert::Succeeded(hr, "Failed to get temp path."); | ||
966 | |||
967 | PathFixedBackslashTerminate(wzOriginalTemp2, countof(wzOriginalTemp2)); | ||
968 | |||
969 | hr = ::StringCchLengthW(wzOriginalTemp2, countof(wzOriginalTemp2), &cchTemp2); | ||
970 | NativeAssert::Succeeded(hr, "Failed to get temp path length."); | ||
971 | |||
972 | NativeAssert::StringEqual(wzOriginalTemp2, sczTempPath); | ||
973 | Assert::Equal<SIZE_T>(cchTemp2, cchTemp); | ||
974 | } | ||
975 | finally | ||
976 | { | ||
977 | if (cch) | ||
978 | { | ||
979 | ::SetEnvironmentVariableW(wzEnvName, wzOriginalTemp); | ||
980 | } | ||
981 | |||
982 | ReleaseStr(sczTempPath); | ||
983 | } | ||
984 | } | ||
985 | |||
986 | [Fact] | ||
987 | void PathGetVolumePathNameTest() | ||
988 | { | ||
989 | HRESULT hr = S_OK; | ||
990 | LPWSTR sczVolumePathName = NULL; | ||
991 | |||
992 | try | ||
993 | { | ||
994 | hr = StrAlloc(&sczVolumePathName, 1); | ||
995 | NativeAssert::Succeeded(hr, "Failed to alloc volume path name."); | ||
996 | |||
997 | hr = PathGetVolumePathName(L"C:\\Windows", &sczVolumePathName); | ||
998 | NativeAssert::Succeeded(hr, "PathGetVolumePathName failed."); | ||
999 | |||
1000 | NativeAssert::StringEqual(L"C:\\", sczVolumePathName); | ||
1001 | } | ||
1002 | finally | ||
1003 | { | ||
1004 | ReleaseStr(sczVolumePathName); | ||
1005 | } | ||
1006 | } | ||
1007 | |||
1008 | [Fact] | ||
831 | void PathNormalizeSlashesFixedTest() | 1009 | void PathNormalizeSlashesFixedTest() |
832 | { | 1010 | { |
833 | HRESULT hr = S_OK; | 1011 | HRESULT hr = S_OK; |