diff options
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/cabcutil.cpp')
-rw-r--r-- | src/libs/dutil/WixToolset.DUtil/cabcutil.cpp | 86 |
1 files changed, 35 insertions, 51 deletions
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 | { |