summaryrefslogtreecommitdiff
path: root/src/libs/dutil/WixToolset.DUtil/cabcutil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/cabcutil.cpp')
-rw-r--r--src/libs/dutil/WixToolset.DUtil/cabcutil.cpp86
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
360LExit: 334LExit:
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
649LExit: 625LExit:
@@ -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
1161LExit: 1140LExit:
@@ -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 {