Reset the package's cache folder only once.
This behavior makes it work similar to the root package cache folder and avoids performance problems when there are many payloads in the package. #4774
Sean Hall committed
May 2, 2021 at 16:48 UTC
4e2054b3ee31b2b9fae3269d76e08817a36fb51f
6 files changed
+145
-24
src/burn/engine/apply.cpp
+11
-4
@@ -549,12 +549,19 @@ extern "C" HRESULT ApplyCache(
549
case BURN_CACHE_ACTION_TYPE_PACKAGE:
550
pPackage = pCacheAction->package.pPackage;
551
552
- if (!pPackage->fPerMachine && !cacheContext.wzLayoutDirectory)
552
+ if (!cacheContext.wzLayoutDirectory)
553
{
554
- hr = CacheGetCompletedPath(FALSE, pPackage->sczCacheId, &pPackage->sczCacheFolder);
555
- ExitOnFailure(hr, "Failed to get cached path for package with cache id: %ls", pPackage->sczCacheId);
554
+ if (!pPackage->fPerMachine || INVALID_HANDLE_VALUE == cacheContext.hPipe)
555
+ {
556
+ hr = CachePreparePackage(pPackage);
557
557
- cacheContext.hPipe = INVALID_HANDLE_VALUE;
558
+ cacheContext.hPipe = INVALID_HANDLE_VALUE;
559
+ }
560
+ else
561
+ {
562
+ hr = ElevationCachePreparePackage(hPipe, pPackage);
563
+ }
564
+ LogExitOnFailure(hr, MSG_CACHE_PREPARE_PACKAGE_FAILED, "Cache prepare package failed: %ls", pPackage->sczId, NULL, NULL);
565
}
566
567
hr = ApplyCachePackage(&cacheContext, pPackage);
src/burn/engine/cache.cpp
+43
-15
@@ -29,7 +29,8 @@ static HRESULT SecurePerMachineCacheRoot();
29
static HRESULT CreateCompletedPath(
30
__in BOOL fPerMachine,
31
__in LPCWSTR wzCacheId,
32
- __out_z LPWSTR* psczCacheDirectory
32
+ __in LPCWSTR wzFilePath,
33
+ __out_z LPWSTR* psczCachePath
34
);
35
static HRESULT CreateUnverifiedPath(
36
__in BOOL fPerMachine,
@@ -750,6 +751,20 @@ extern "C" BOOL CacheBundleRunningFromCache()
751
return vfRunningFromCache;
752
}
753
754
+HRESULT CachePreparePackage(
755
+ __in BURN_PACKAGE* pPackage
756
+ )
757
+{
758
+ HRESULT hr = S_OK;
759
+
760
+ if (!pPackage->sczCacheFolder)
761
+ {
762
+ hr = CreateCompletedPath(pPackage->fPerMachine, pPackage->sczCacheId, NULL, &pPackage->sczCacheFolder);
763
+ }
764
+
765
+ return hr;
766
+}
767
+
768
extern "C" HRESULT CacheBundleToCleanRoom(
769
__in BURN_SECTION* pSection,
770
__deref_out_z_opt LPWSTR* psczCleanRoomBundlePath
@@ -852,7 +867,7 @@ extern "C" HRESULT CacheCompleteBundle(
867
LPWSTR sczSourceDirectory = NULL;
868
LPWSTR sczPayloadSourcePath = NULL;
869
855
- hr = CreateCompletedPath(fPerMachine, wzBundleId, &sczTargetDirectory);
870
+ hr = CreateCompletedPath(fPerMachine, wzBundleId, NULL, &sczTargetDirectory);
871
ExitOnFailure(hr, "Failed to create completed cache path for bundle.");
872
873
hr = PathConcat(sczTargetDirectory, wzExecutableName, &sczTargetPath);
@@ -957,16 +972,12 @@ extern "C" HRESULT CacheCompletePayload(
972
)
973
{
974
HRESULT hr = S_OK;
960
- LPWSTR sczCachedDirectory = NULL;
975
LPWSTR sczCachedPath = NULL;
976
LPWSTR sczUnverifiedPayloadPath = NULL;
977
964
- hr = CreateCompletedPath(fPerMachine, wzCacheId, &sczCachedDirectory);
978
+ hr = CreateCompletedPath(fPerMachine, wzCacheId, pPayload->sczFilePath, &sczCachedPath);
979
ExitOnFailure(hr, "Failed to get cached path for package with cache id: %ls", wzCacheId);
980
967
- hr = PathConcat(sczCachedDirectory, pPayload->sczFilePath, &sczCachedPath);
968
- ExitOnFailure(hr, "Failed to concat complete cached path.");
969
-
981
// If the cached file matches what we expected, we're good.
982
hr = VerifyFileAgainstPayload(pPayload, sczCachedPath, TRUE, BURN_CACHE_STEP_HASH_TO_SKIP_VERIFY, pfnCacheMessageHandler, pfnProgress, pContext);
983
if (SUCCEEDED(hr))
@@ -1016,7 +1027,6 @@ extern "C" HRESULT CacheCompletePayload(
1027
LExit:
1028
ReleaseStr(sczUnverifiedPayloadPath);
1029
ReleaseStr(sczCachedPath);
1019
- ReleaseStr(sczCachedDirectory);
1030
1031
return hr;
1032
}
@@ -1403,11 +1413,13 @@ LExit:
1413
static HRESULT CreateCompletedPath(
1414
__in BOOL fPerMachine,
1415
__in LPCWSTR wzId,
1406
- __out_z LPWSTR* psczCacheDirectory
1416
+ __in LPCWSTR wzFilePath,
1417
+ __out_z LPWSTR* psczCachePath
1418
)
1419
{
1420
HRESULT hr = S_OK;
1421
LPWSTR sczCacheDirectory = NULL;
1422
+ LPWSTR sczCacheFile = NULL;
1423
1424
if (fPerMachine)
1425
{
@@ -1415,22 +1427,38 @@ static HRESULT CreateCompletedPath(
1427
ExitOnFailure(hr, "Failed to secure per-machine cache root.");
1428
}
1429
1418
- // Get the cache completed path, ensure it exists, and reset any permissions people
1419
- // might have tried to set on the directory so we inherit the (correct!) security
1420
- // permissions from the parent directory.
1430
+ // Get the cache completed path.
1431
hr = CacheGetCompletedPath(fPerMachine, wzId, &sczCacheDirectory);
1432
ExitOnFailure(hr, "Failed to get cache directory.");
1433
1434
+ // Ensure it exists.
1435
hr = DirEnsureExists(sczCacheDirectory, NULL);
1436
ExitOnFailure(hr, "Failed to create cache directory: %ls", sczCacheDirectory);
1437
1427
- ResetPathPermissions(fPerMachine, sczCacheDirectory);
1438
+ if (!wzFilePath)
1439
+ {
1440
+ // Reset any permissions people might have tried to set on the directory
1441
+ // so we inherit the (correct!) security permissions from the parent directory.
1442
+ ResetPathPermissions(fPerMachine, sczCacheDirectory);
1443
1429
- *psczCacheDirectory = sczCacheDirectory;
1430
- sczCacheDirectory = NULL;
1444
+ *psczCachePath = sczCacheDirectory;
1445
+ sczCacheDirectory = NULL;
1446
+ }
1447
+ else
1448
+ {
1449
+ // Get the cache completed file path.
1450
+ hr = PathConcat(sczCacheDirectory, wzFilePath, &sczCacheFile);
1451
+ ExitOnFailure(hr, "Failed to construct cache file.");
1452
+
1453
+ // Don't reset permissions here. The payload's package must reset its cache folder when it starts caching.
1454
+
1455
+ *psczCachePath = sczCacheFile;
1456
+ sczCacheFile = NULL;
1457
+ }
1458
1459
LExit:
1460
ReleaseStr(sczCacheDirectory);
1461
+ ReleaseStr(sczCacheFile);
1462
return hr;
1463
}
1464
src/burn/engine/cache.h
+3
@@ -122,6 +122,9 @@ void CacheSendErrorCallback(
122
__out_opt BOOL* pfRetry
123
);
124
BOOL CacheBundleRunningFromCache();
125
+HRESULT CachePreparePackage(
126
+ __in BURN_PACKAGE* pPackage
127
+ );
128
HRESULT CacheBundleToCleanRoom(
129
__in BURN_SECTION* pSection,
130
__deref_out_z_opt LPWSTR* psczCleanRoomBundlePath
src/burn/engine/elevation.cpp
+77
-5
@@ -14,6 +14,7 @@ typedef enum _BURN_ELEVATION_MESSAGE_TYPE
14
BURN_ELEVATION_MESSAGE_TYPE_SESSION_RESUME,
15
BURN_ELEVATION_MESSAGE_TYPE_SESSION_END,
16
BURN_ELEVATION_MESSAGE_TYPE_SAVE_STATE,
17
+ BURN_ELEVATION_MESSAGE_TYPE_CACHE_PREPARE_PACKAGE,
18
BURN_ELEVATION_MESSAGE_TYPE_CACHE_COMPLETE_PAYLOAD,
19
BURN_ELEVATION_MESSAGE_TYPE_CACHE_VERIFY_PAYLOAD,
20
BURN_ELEVATION_MESSAGE_TYPE_CACHE_CLEANUP,
@@ -186,6 +187,11 @@ static HRESULT OnSaveState(
187
__in BYTE* pbData,
188
__in SIZE_T cbData
189
);
190
+static HRESULT OnCachePreparePackage(
191
+ __in BURN_PACKAGES* pPackages,
192
+ __in BYTE* pbData,
193
+ __in SIZE_T cbData
194
+ );
195
static HRESULT OnCacheCompletePayload(
196
__in HANDLE hPipe,
197
__in BURN_PACKAGES* pPackages,
@@ -612,6 +618,32 @@ LExit:
618
return hr;
619
}
620
621
+extern "C" HRESULT ElevationCachePreparePackage(
622
+ __in HANDLE hPipe,
623
+ __in BURN_PACKAGE* pPackage
624
+ )
625
+{
626
+ HRESULT hr = S_OK;
627
+ BYTE* pbData = NULL;
628
+ SIZE_T cbData = 0;
629
+ DWORD dwResult = 0;
630
+
631
+ // Serialize message data.
632
+ hr = BuffWriteString(&pbData, &cbData, pPackage ? pPackage->sczId : NULL);
633
+ ExitOnFailure(hr, "Failed to write package id to message buffer.");
634
+
635
+ // Send message.
636
+ hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_CACHE_PREPARE_PACKAGE, pbData, cbData, NULL, NULL, &dwResult);
637
+ ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_CACHE_PREPARE_PACKAGE message to per-machine process.");
638
+
639
+ hr = (HRESULT)dwResult;
640
+
641
+LExit:
642
+ ReleaseBuffer(pbData);
643
+
644
+ return hr;
645
+}
646
+
647
/*******************************************************************
648
ElevationCacheCompletePayload -
649
@@ -1856,6 +1888,10 @@ static HRESULT ProcessElevatedChildCacheMessage(
1888
1889
switch (pMsg->dwMessage)
1890
{
1891
+ case BURN_ELEVATION_MESSAGE_TYPE_CACHE_PREPARE_PACKAGE:
1892
+ hrResult = OnCachePreparePackage(pContext->pPackages, (BYTE*)pMsg->pvData, pMsg->cbData);
1893
+ break;
1894
+
1895
case BURN_ELEVATION_MESSAGE_TYPE_CACHE_COMPLETE_PAYLOAD:
1896
hrResult = OnCacheCompletePayload(pContext->hPipe, pContext->pPackages, pContext->pPayloads, (BYTE*)pMsg->pvData, pMsg->cbData);
1897
break;
@@ -2153,6 +2189,41 @@ LExit:
2189
return hr;
2190
}
2191
2192
+static HRESULT OnCachePreparePackage(
2193
+ __in BURN_PACKAGES* pPackages,
2194
+ __in BYTE* pbData,
2195
+ __in SIZE_T cbData
2196
+ )
2197
+{
2198
+ HRESULT hr = S_OK;
2199
+ SIZE_T iData = 0;
2200
+ LPWSTR scz = NULL;
2201
+ BURN_PACKAGE* pPackage = NULL;
2202
+
2203
+ // Deserialize message data.
2204
+ hr = BuffReadString(pbData, cbData, &iData, &scz);
2205
+ ExitOnFailure(hr, "Failed to read package id.");
2206
+
2207
+ if (scz && *scz)
2208
+ {
2209
+ hr = PackageFindById(pPackages, scz, &pPackage);
2210
+ ExitOnFailure(hr, "Failed to find package: %ls", scz);
2211
+ }
2212
+ else
2213
+ {
2214
+ hr = E_INVALIDARG;
2215
+ ExitOnRootFailure(hr, "Invalid data passed to cache prepare package.");
2216
+ }
2217
+
2218
+ hr = CachePreparePackage(pPackage);
2219
+ ExitOnFailure(hr, "Failed to prepare cache package.");
2220
+
2221
+LExit:
2222
+ ReleaseStr(scz);
2223
+
2224
+ return hr;
2225
+}
2226
+
2227
static HRESULT OnCacheCompletePayload(
2228
__in HANDLE hPipe,
2229
__in BURN_PACKAGES* pPackages,
@@ -2225,7 +2296,6 @@ static HRESULT OnCacheVerifyPayload(
2296
LPWSTR scz = NULL;
2297
BURN_PACKAGE* pPackage = NULL;
2298
BURN_PAYLOAD* pPayload = NULL;
2228
- LPWSTR sczCacheDirectory = NULL;
2299
2300
// Deserialize message data.
2301
hr = BuffReadString(pbData, cbData, &iData, &scz);
@@ -2248,10 +2318,13 @@ static HRESULT OnCacheVerifyPayload(
2318
2319
if (pPackage && pPayload)
2320
{
2251
- hr = CacheGetCompletedPath(TRUE, pPackage->sczCacheId, &sczCacheDirectory);
2252
- ExitOnFailure(hr, "Failed to get cached path for package with cache id: %ls", pPackage->sczCacheId);
2321
+ if (!pPackage->sczCacheFolder)
2322
+ {
2323
+ hr = E_INVALIDSTATE;
2324
+ ExitOnRootFailure(hr, "Cache verify payload called without starting its package.");
2325
+ }
2326
2254
- hr = CacheVerifyPayload(pPayload, sczCacheDirectory, BurnCacheMessageHandler, ElevatedProgressRoutine, hPipe);
2327
+ hr = CacheVerifyPayload(pPayload, pPackage->sczCacheFolder, BurnCacheMessageHandler, ElevatedProgressRoutine, hPipe);
2328
}
2329
else
2330
{
@@ -2261,7 +2334,6 @@ static HRESULT OnCacheVerifyPayload(
2334
// Nothing should be logged on failure.
2335
2336
LExit:
2264
- ReleaseStr(sczCacheDirectory);
2337
ReleaseStr(scz);
2338
2339
return hr;
src/burn/engine/elevation.h
+4
@@ -50,6 +50,10 @@ HRESULT ElevationSaveState(
50
__in_bcount(cbBuffer) BYTE* pbBuffer,
51
__in SIZE_T cbBuffer
52
);
53
+HRESULT ElevationCachePreparePackage(
54
+ __in HANDLE hPipe,
55
+ __in BURN_PACKAGE* pPackage
56
+ );
57
HRESULT ElevationCacheCompletePayload(
58
__in HANDLE hPipe,
59
__in BURN_PACKAGE* pPackage,
src/burn/engine/engine.mc
+7
@@ -717,6 +717,13 @@ Language=English
717
Acquiring container: %1!ls!, %3!hs! from: %4!ls!
718
.
719
720
+MessageId=337
721
+Severity=Error
722
+SymbolicName=MSG_CACHE_PREPARE_PACKAGE_FAILED
723
+Language=English
724
+Failed to prepare package: %2!ls!, error: 0x%1!ls!
725
+.
726
+
727
MessageId=338
728
Severity=Success
729
SymbolicName=MSG_ACQUIRE_PACKAGE_PAYLOAD