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