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; |
