@joebigelow / wix-1 / commits / 31539e7a

Make sure payload unverified path is not read-only during acquisition.

Sean Hall committed Apr 16, 2021 at 10:38 UTC 31539e7a5baf0f75f3cd0e4764c003bb6a8310ce
1 file changed +37 -24
src/engine/apply.cpp
+37 -24
@@ -123,6 +123,9 @@ static HRESULT LayoutOrCacheContainerOrPayload(
123 __in DWORD cTryAgainAttempts,
124 __out BOOL* pfRetry
125 );
126 +static HRESULT PreparePayloadDestinationPath(
127 + __in_z LPCWSTR wzDestinationPath
128 + );
129 static HRESULT CopyPayload(
130 __in BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT* pProgress,
131 __in HANDLE hSourceFile,
@@ -1044,6 +1047,9 @@ static HRESULT ExtractContainer(
1047 BURN_PAYLOAD* pExtract = pContext->pPayloads->rgPayloads + iExtract;
1048 if (pExtract->sczUnverifiedPath && CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, sczExtractPayloadId, -1, pExtract->sczSourcePath, -1))
1049 {
1050 + hr = PreparePayloadDestinationPath(pExtract->sczUnverifiedPath);
1051 + ExitOnFailure(hr, "Failed to prepare payload destination path: %ls", pExtract->sczUnverifiedPath);
1052 +
1053 // TODO: Send progress when extracting stream to file.
1054 hr = ContainerStreamToFile(&context, pExtract->sczUnverifiedPath);
1055 ExitOnFailure(hr, "Failed to extract payload: %ls from container: %ls", sczExtractPayloadId, pContainer->sczId);
@@ -1424,22 +1430,12 @@ LExit:
1430 return hr;
1431 }
1432
1427 -static HRESULT CopyPayload(
1428 - __in BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT* pProgress,
1429 - __in HANDLE hSourceFile,
1430 - __in_z LPCWSTR wzSourcePath,
1433 +static HRESULT PreparePayloadDestinationPath(
1434 __in_z LPCWSTR wzDestinationPath
1435 )
1436 {
1437 HRESULT hr = S_OK;
1438 DWORD dwFileAttributes = 0;
1436 - LPCWSTR wzPackageOrContainerId = pProgress->pContainer ? pProgress->pContainer->sczId : pProgress->pPackage ? pProgress->pPackage->sczId : L"";
1437 - LPCWSTR wzPayloadId = pProgress->pPayload ? pProgress->pPayload->sczKey : L"";
1438 - HANDLE hDestinationFile = INVALID_HANDLE_VALUE;
1439 - HANDLE hSourceOpenedFile = INVALID_HANDLE_VALUE;
1440 -
1441 - DWORD dwLogId = pProgress->pContainer ? (pProgress->pPayload ? MSG_ACQUIRE_CONTAINER_PAYLOAD : MSG_ACQUIRE_CONTAINER) : pProgress->pPackage ? MSG_ACQUIRE_PACKAGE_PAYLOAD : MSG_ACQUIRE_BUNDLE_PAYLOAD;
1442 - LogId(REPORT_STANDARD, dwLogId, wzPackageOrContainerId, wzPayloadId, "copy", wzSourcePath);
1439
1440 // If the destination file already exists, clear the readonly bit to avoid E_ACCESSDENIED.
1441 if (FileExistsEx(wzDestinationPath, &dwFileAttributes))
@@ -1454,6 +1450,34 @@ static HRESULT CopyPayload(
1450 }
1451 }
1452
1453 +LExit:
1454 + if (E_FILENOTFOUND == hr || E_PATHNOTFOUND == hr)
1455 + {
1456 + hr = S_OK;
1457 + }
1458 +
1459 + return hr;
1460 +}
1461 +
1462 +static HRESULT CopyPayload(
1463 + __in BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT* pProgress,
1464 + __in HANDLE hSourceFile,
1465 + __in_z LPCWSTR wzSourcePath,
1466 + __in_z LPCWSTR wzDestinationPath
1467 + )
1468 +{
1469 + HRESULT hr = S_OK;
1470 + LPCWSTR wzPackageOrContainerId = pProgress->pContainer ? pProgress->pContainer->sczId : pProgress->pPackage ? pProgress->pPackage->sczId : L"";
1471 + LPCWSTR wzPayloadId = pProgress->pPayload ? pProgress->pPayload->sczKey : L"";
1472 + HANDLE hDestinationFile = INVALID_HANDLE_VALUE;
1473 + HANDLE hSourceOpenedFile = INVALID_HANDLE_VALUE;
1474 +
1475 + DWORD dwLogId = pProgress->pContainer ? (pProgress->pPayload ? MSG_ACQUIRE_CONTAINER_PAYLOAD : MSG_ACQUIRE_CONTAINER) : pProgress->pPackage ? MSG_ACQUIRE_PACKAGE_PAYLOAD : MSG_ACQUIRE_BUNDLE_PAYLOAD;
1476 + LogId(REPORT_STANDARD, dwLogId, wzPackageOrContainerId, wzPayloadId, "copy", wzSourcePath);
1477 +
1478 + hr = PreparePayloadDestinationPath(wzDestinationPath);
1479 + ExitOnFailure(hr, "Failed to prepare payload destination path: %ls", wzDestinationPath);
1480 +
1481 if (INVALID_HANDLE_VALUE == hSourceFile)
1482 {
1483 hSourceOpenedFile = ::CreateFileW(wzSourcePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
@@ -1503,7 +1527,6 @@ static HRESULT DownloadPayload(
1527 )
1528 {
1529 HRESULT hr = S_OK;
1506 - DWORD dwFileAttributes = 0;
1530 LPCWSTR wzPackageOrContainerId = pProgress->pContainer ? pProgress->pContainer->sczId : pProgress->pPackage ? pProgress->pPackage->sczId : L"";
1531 LPCWSTR wzPayloadId = pProgress->pPayload ? pProgress->pPayload->sczKey : L"";
1532 DOWNLOAD_SOURCE* pDownloadSource = pProgress->pContainer ? &pProgress->pContainer->downloadSource : &pProgress->pPayload->downloadSource;
@@ -1515,18 +1538,8 @@ static HRESULT DownloadPayload(
1538 DWORD dwLogId = pProgress->pContainer ? (pProgress->pPayload ? MSG_ACQUIRE_CONTAINER_PAYLOAD : MSG_ACQUIRE_CONTAINER) : pProgress->pPackage ? MSG_ACQUIRE_PACKAGE_PAYLOAD : MSG_ACQUIRE_BUNDLE_PAYLOAD;
1539 LogId(REPORT_STANDARD, dwLogId, wzPackageOrContainerId, wzPayloadId, "download", pDownloadSource->sczUrl);
1540
1518 - // If the destination file already exists, clear the readonly bit to avoid E_ACCESSDENIED.
1519 - if (FileExistsEx(wzDestinationPath, &dwFileAttributes))
1520 - {
1521 - if (FILE_ATTRIBUTE_READONLY & dwFileAttributes)
1522 - {
1523 - dwFileAttributes &= ~FILE_ATTRIBUTE_READONLY;
1524 - if (!::SetFileAttributes(wzDestinationPath, dwFileAttributes))
1525 - {
1526 - ExitWithLastError(hr, "Failed to clear readonly bit on payload destination path: %ls", wzDestinationPath);
1527 - }
1528 - }
1529 - }
1541 + hr = PreparePayloadDestinationPath(wzDestinationPath);
1542 + ExitOnFailure(hr, "Failed to prepare payload destination path: %ls", wzDestinationPath);
1543
1544 cacheCallback.pfnProgress = CacheProgressRoutine;
1545 cacheCallback.pfnCancel = NULL; // TODO: set this