aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2021-04-17 20:58:32 -0500
committerSean Hall <r.sean.hall@gmail.com>2021-04-19 23:12:55 -0500
commitd4c76dd11f5a096b4fd3ee9c5efc1f44559ac3da (patch)
tree002f0351a05420b3cc1cbca052d4159cfc11706d
parent26151ceeb5c57e3fd0bf73e9c13d8d72b41cce74 (diff)
downloadwix-d4c76dd11f5a096b4fd3ee9c5efc1f44559ac3da.tar.gz
wix-d4c76dd11f5a096b4fd3ee9c5efc1f44559ac3da.tar.bz2
wix-d4c76dd11f5a096b4fd3ee9c5efc1f44559ac3da.zip
Send more progress during cache verification.
Add verifyStep to OnCacheVerifyProgress. Send OnContainerOrPayloadVerify events only if file existed in cache.
-rw-r--r--src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h8
-rw-r--r--src/engine/apply.cpp171
-rw-r--r--src/engine/cache.cpp263
-rw-r--r--src/engine/cache.h74
-rw-r--r--src/engine/elevation.cpp253
-rw-r--r--src/engine/elevation.h10
-rw-r--r--src/engine/plan.cpp18
-rw-r--r--src/engine/userexperience.cpp4
-rw-r--r--src/engine/userexperience.h3
-rw-r--r--src/test/BurnUnitTest/CacheTest.cpp46
-rw-r--r--src/test/BurnUnitTest/PlanTest.cpp10
11 files changed, 712 insertions, 148 deletions
diff --git a/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h b/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
index e1920107..d8994c26 100644
--- a/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
+++ b/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
@@ -64,6 +64,13 @@ enum BOOTSTRAPPER_CACHE_OPERATION
64 BOOTSTRAPPER_CACHE_OPERATION_EXTRACT, 64 BOOTSTRAPPER_CACHE_OPERATION_EXTRACT,
65}; 65};
66 66
67enum BOOTSTRAPPER_CACHE_VERIFY_STEP
68{
69 BOOTSTRAPPER_CACHE_VERIFY_STEP_STAGE,
70 BOOTSTRAPPER_CACHE_VERIFY_STEP_HASH,
71 BOOTSTRAPPER_CACHE_VERIFY_STEP_FINALIZE,
72};
73
67enum BOOTSTRAPPER_APPLY_RESTART 74enum BOOTSTRAPPER_APPLY_RESTART
68{ 75{
69 BOOTSTRAPPER_APPLY_RESTART_NONE, 76 BOOTSTRAPPER_APPLY_RESTART_NONE,
@@ -553,6 +560,7 @@ struct BA_ONCACHEVERIFYPROGRESS_ARGS
553 DWORD64 dw64Progress; 560 DWORD64 dw64Progress;
554 DWORD64 dw64Total; 561 DWORD64 dw64Total;
555 DWORD dwOverallPercentage; 562 DWORD dwOverallPercentage;
563 BOOTSTRAPPER_CACHE_VERIFY_STEP verifyStep;
556}; 564};
557 565
558struct BA_ONCACHEVERIFYPROGRESS_RESULTS 566struct BA_ONCACHEVERIFYPROGRESS_RESULTS
diff --git a/src/engine/apply.cpp b/src/engine/apply.cpp
index 304c88f4..6f6225b4 100644
--- a/src/engine/apply.cpp
+++ b/src/engine/apply.cpp
@@ -14,9 +14,12 @@ const DWORD BURN_CACHE_MAX_RECOMMENDED_VERIFY_TRYAGAIN_ATTEMPTS = 2;
14enum BURN_CACHE_PROGRESS_TYPE 14enum BURN_CACHE_PROGRESS_TYPE
15{ 15{
16 BURN_CACHE_PROGRESS_TYPE_ACQUIRE, 16 BURN_CACHE_PROGRESS_TYPE_ACQUIRE,
17 BURN_CACHE_PROGRESS_TYPE_VERIFY,
18 BURN_CACHE_PROGRESS_TYPE_CONTAINER_OR_PAYLOAD_VERIFY, 17 BURN_CACHE_PROGRESS_TYPE_CONTAINER_OR_PAYLOAD_VERIFY,
19 BURN_CACHE_PROGRESS_TYPE_EXTRACT, 18 BURN_CACHE_PROGRESS_TYPE_EXTRACT,
19 BURN_CACHE_PROGRESS_TYPE_FINALIZE,
20 BURN_CACHE_PROGRESS_TYPE_HASH,
21 BURN_CACHE_PROGRESS_TYPE_PAYLOAD_VERIFY,
22 BURN_CACHE_PROGRESS_TYPE_STAGE,
20}; 23};
21 24
22// structs 25// structs
@@ -151,6 +154,10 @@ static HRESULT DownloadPayload(
151 __in BURN_CACHE_PROGRESS_CONTEXT* pProgress, 154 __in BURN_CACHE_PROGRESS_CONTEXT* pProgress,
152 __in_z LPCWSTR wzDestinationPath 155 __in_z LPCWSTR wzDestinationPath
153 ); 156 );
157static HRESULT CALLBACK CacheMessageHandler(
158 __in BURN_CACHE_MESSAGE* pMessage,
159 __in LPVOID pvContext
160 );
154static HRESULT CompleteCacheProgress( 161static HRESULT CompleteCacheProgress(
155 __in BURN_CACHE_PROGRESS_CONTEXT* pContext, 162 __in BURN_CACHE_PROGRESS_CONTEXT* pContext,
156 __in DWORD64 qwFileSize 163 __in DWORD64 qwFileSize
@@ -993,7 +1000,8 @@ static HRESULT ApplyLayoutContainer(
993 } 1000 }
994 1001
995 ++cTryAgainAttempts; 1002 ++cTryAgainAttempts;
996 pContext->qwSuccessfulCacheProgress -= pContainer->qwFileSize; 1003 pContext->qwSuccessfulCacheProgress -= pContainer->qwCommittedCacheProgress;
1004 pContainer->qwCommittedCacheProgress = 0;
997 ReleaseNullStr(pContext->sczLastUsedFolderCandidate); 1005 ReleaseNullStr(pContext->sczLastUsedFolderCandidate);
998 LogErrorId(hr, MSG_APPLY_RETRYING_CONTAINER, pContainer->sczId, NULL, NULL); 1006 LogErrorId(hr, MSG_APPLY_RETRYING_CONTAINER, pContainer->sczId, NULL, NULL);
999 } 1007 }
@@ -1075,49 +1083,25 @@ static HRESULT ApplyCacheVerifyContainerOrPayload(
1075 1083
1076 HRESULT hr = S_OK; 1084 HRESULT hr = S_OK;
1077 BURN_CACHE_PROGRESS_CONTEXT progress = { }; 1085 BURN_CACHE_PROGRESS_CONTEXT progress = { };
1078 LPCWSTR wzPackageOrContainerId = pContainer ? pContainer->sczId : pPackage ? pPackage->sczId : NULL;
1079 LPCWSTR wzPayloadId = pPayloadGroupItem ? pPayloadGroupItem->pPayload->sczKey : NULL;
1080 DWORD64 qwFileSize = pContainer ? pContainer->qwFileSize : pPayloadGroupItem->pPayload->qwFileSize;
1081 1086
1082 progress.pCacheContext = pContext; 1087 progress.pCacheContext = pContext;
1083 progress.pContainer = pContainer; 1088 progress.pContainer = pContainer;
1084 progress.pPackage = pPackage; 1089 progress.pPackage = pPackage;
1085 progress.pPayloadGroupItem = pPayloadGroupItem; 1090 progress.pPayloadGroupItem = pPayloadGroupItem;
1086 progress.type = BURN_CACHE_PROGRESS_TYPE_CONTAINER_OR_PAYLOAD_VERIFY;
1087
1088 hr = UserExperienceOnCacheContainerOrPayloadVerifyBegin(pContext->pUX, wzPackageOrContainerId, wzPayloadId);
1089 ExitOnRootFailure(hr, "BA aborted cache container or payload verify begin.");
1090 1091
1091 if (pContainer) 1092 if (pContainer)
1092 { 1093 {
1093 hr = CacheVerifyContainer(pContainer, pContext->wzLayoutDirectory); 1094 hr = CacheVerifyContainer(pContainer, pContext->wzLayoutDirectory, CacheMessageHandler, CacheProgressRoutine, &progress);
1094 } 1095 }
1095 else if (!pContext->wzLayoutDirectory && INVALID_HANDLE_VALUE != pContext->hPipe) 1096 else if (!pContext->wzLayoutDirectory && INVALID_HANDLE_VALUE != pContext->hPipe)
1096 { 1097 {
1097 hr = ElevationCacheVerifyPayload(pContext->hPipe, pPackage, pPayloadGroupItem->pPayload); 1098 hr = ElevationCacheVerifyPayload(pContext->hPipe, pPackage, pPayloadGroupItem->pPayload, CacheMessageHandler, CacheProgressRoutine, &progress);
1098 } 1099 }
1099 else 1100 else
1100 { 1101 {
1101 hr = CacheVerifyPayload(pPayloadGroupItem->pPayload, pContext->wzLayoutDirectory ? pContext->wzLayoutDirectory : pPackage->sczCacheFolder); 1102 hr = CacheVerifyPayload(pPayloadGroupItem->pPayload, pContext->wzLayoutDirectory ? pContext->wzLayoutDirectory : pPackage->sczCacheFolder, CacheMessageHandler, CacheProgressRoutine, &progress);
1102 }
1103
1104 // This was best effort to avoid acquiring the container or payload.
1105 if (FAILED(hr))
1106 {
1107 ExitFunction();
1108 } 1103 }
1109 1104
1110 pContext->qwSuccessfulCacheProgress += qwFileSize;
1111 if (pPayloadGroupItem)
1112 {
1113 pPayloadGroupItem->qwCommittedCacheProgress += qwFileSize;
1114 }
1115
1116 hr = CompleteCacheProgress(&progress, qwFileSize);
1117
1118LExit:
1119 UserExperienceOnCacheContainerOrPayloadVerifyComplete(pContext->pUX, wzPackageOrContainerId, wzPayloadId, hr);
1120
1121 return hr; 1105 return hr;
1122} 1106}
1123 1107
@@ -1252,8 +1236,6 @@ static HRESULT LayoutBundle(
1252 ExitOnRootFailure(hr, "BA aborted cache payload verify begin."); 1236 ExitOnRootFailure(hr, "BA aborted cache payload verify begin.");
1253 } 1237 }
1254 1238
1255 pContext->qwSuccessfulCacheProgress += qwBundleSize;
1256
1257 progress.type = BURN_CACHE_PROGRESS_TYPE_CONTAINER_OR_PAYLOAD_VERIFY; 1239 progress.type = BURN_CACHE_PROGRESS_TYPE_CONTAINER_OR_PAYLOAD_VERIFY;
1258 hr = CompleteCacheProgress(&progress, qwBundleSize); 1240 hr = CompleteCacheProgress(&progress, qwBundleSize);
1259 1241
@@ -1306,8 +1288,6 @@ static HRESULT LayoutBundle(
1306 break; 1288 break;
1307 } 1289 }
1308 1290
1309 progress.type = BURN_CACHE_PROGRESS_TYPE_VERIFY;
1310
1311 do 1291 do
1312 { 1292 {
1313 fCanceledBegin = FALSE; 1293 fCanceledBegin = FALSE;
@@ -1320,12 +1300,7 @@ static HRESULT LayoutBundle(
1320 } 1300 }
1321 else 1301 else
1322 { 1302 {
1323 hr = CacheLayoutBundle(wzExecutableName, pContext->wzLayoutDirectory, wzUnverifiedPath); 1303 hr = CacheLayoutBundle(wzExecutableName, pContext->wzLayoutDirectory, wzUnverifiedPath, qwBundleSize, CacheMessageHandler, CacheProgressRoutine, &progress);
1324
1325 if (SUCCEEDED(hr))
1326 {
1327 hr = CompleteCacheProgress(&progress, qwBundleSize);
1328 }
1329 } 1304 }
1330 1305
1331 BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION action = BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION_NONE; 1306 BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION action = BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION_NONE;
@@ -1346,7 +1321,7 @@ static HRESULT LayoutBundle(
1346 1321
1347 if (fRetry) 1322 if (fRetry)
1348 { 1323 {
1349 pContext->qwSuccessfulCacheProgress -= qwBundleSize; 1324 pContext->qwSuccessfulCacheProgress -= qwBundleSize; // Acquire
1350 } 1325 }
1351 } while (fRetry); 1326 } while (fRetry);
1352 LogExitOnFailure(hr, MSG_FAILED_LAYOUT_BUNDLE, "Failed to layout bundle: %ls to layout directory: %ls", sczBundlePath, pContext->wzLayoutDirectory); 1327 LogExitOnFailure(hr, MSG_FAILED_LAYOUT_BUNDLE, "Failed to layout bundle: %ls to layout directory: %ls", sczBundlePath, pContext->wzLayoutDirectory);
@@ -1559,7 +1534,6 @@ static HRESULT LayoutOrCacheContainerOrPayload(
1559 1534
1560 *pfRetry = FALSE; 1535 *pfRetry = FALSE;
1561 progress.pCacheContext = pContext; 1536 progress.pCacheContext = pContext;
1562 progress.type = BURN_CACHE_PROGRESS_TYPE_VERIFY;
1563 progress.pContainer = pContainer; 1537 progress.pContainer = pContainer;
1564 progress.pPackage = pPackage; 1538 progress.pPackage = pPackage;
1565 progress.pPayloadGroupItem = pPayloadGroupItem; 1539 progress.pPayloadGroupItem = pPayloadGroupItem;
@@ -1580,28 +1554,23 @@ static HRESULT LayoutOrCacheContainerOrPayload(
1580 { 1554 {
1581 if (pContainer) 1555 if (pContainer)
1582 { 1556 {
1583 hr = CacheLayoutContainer(pContainer, pContext->wzLayoutDirectory, wzUnverifiedPath, fMove); 1557 hr = CacheLayoutContainer(pContainer, pContext->wzLayoutDirectory, wzUnverifiedPath, fMove, CacheMessageHandler, CacheProgressRoutine, &progress);
1584 } 1558 }
1585 else 1559 else
1586 { 1560 {
1587 hr = CacheLayoutPayload(pPayload, pContext->wzLayoutDirectory, wzUnverifiedPath, fMove); 1561 hr = CacheLayoutPayload(pPayload, pContext->wzLayoutDirectory, wzUnverifiedPath, fMove, CacheMessageHandler, CacheProgressRoutine, &progress);
1588 } 1562 }
1589 } 1563 }
1590 else if (INVALID_HANDLE_VALUE != pContext->hPipe) // pass the decision off to the elevated process. 1564 else if (INVALID_HANDLE_VALUE != pContext->hPipe) // pass the decision off to the elevated process.
1591 { 1565 {
1592 hr = ElevationCacheCompletePayload(pContext->hPipe, pPackage, pPayload, wzUnverifiedPath, fMove); 1566 hr = ElevationCacheCompletePayload(pContext->hPipe, pPackage, pPayload, wzUnverifiedPath, fMove, CacheMessageHandler, CacheProgressRoutine, &progress);
1593 } 1567 }
1594 else // complete the payload. 1568 else // complete the payload.
1595 { 1569 {
1596 hr = CacheCompletePayload(pPackage->fPerMachine, pPayload, pPackage->sczCacheId, wzUnverifiedPath, fMove); 1570 hr = CacheCompletePayload(pPackage->fPerMachine, pPayload, pPackage->sczCacheId, wzUnverifiedPath, fMove, CacheMessageHandler, CacheProgressRoutine, &progress);
1597 } 1571 }
1598 } 1572 }
1599 1573
1600 if (SUCCEEDED(hr))
1601 {
1602 hr = CompleteCacheProgress(&progress, pContainer ? pContainer->qwFileSize : pPayload->qwFileSize);
1603 }
1604
1605 if (SUCCEEDED(hr) && fCanAffectRegistration) 1574 if (SUCCEEDED(hr) && fCanAffectRegistration)
1606 { 1575 {
1607 pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; 1576 pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
@@ -1820,6 +1789,54 @@ LExit:
1820 return hr; 1789 return hr;
1821} 1790}
1822 1791
1792static HRESULT CALLBACK CacheMessageHandler(
1793 __in BURN_CACHE_MESSAGE* pMessage,
1794 __in LPVOID pvContext
1795 )
1796{
1797 HRESULT hr = S_OK;
1798 BURN_CACHE_PROGRESS_CONTEXT* pProgress = static_cast<BURN_CACHE_PROGRESS_CONTEXT*>(pvContext);
1799 LPCWSTR wzPackageOrContainerId = pProgress->pContainer ? pProgress->pContainer->sczId : pProgress->pPackage ? pProgress->pPackage->sczId : NULL;
1800 LPCWSTR wzPayloadId = pProgress->pPayloadGroupItem ? pProgress->pPayloadGroupItem->pPayload->sczKey : pProgress->pPayload ? pProgress->pPayload->sczKey : NULL;
1801
1802 switch (pMessage->type)
1803 {
1804 case BURN_CACHE_MESSAGE_BEGIN:
1805 switch (pMessage->begin.cacheStep)
1806 {
1807 case BURN_CACHE_STEP_HASH_TO_SKIP_ACQUIRE:
1808 pProgress->type = BURN_CACHE_PROGRESS_TYPE_CONTAINER_OR_PAYLOAD_VERIFY;
1809 hr = UserExperienceOnCacheContainerOrPayloadVerifyBegin(pProgress->pCacheContext->pUX, wzPackageOrContainerId, wzPayloadId);
1810 break;
1811 case BURN_CACHE_STEP_HASH_TO_SKIP_VERIFY:
1812 pProgress->type = BURN_CACHE_PROGRESS_TYPE_PAYLOAD_VERIFY;
1813 break;
1814 case BURN_CACHE_STEP_STAGE:
1815 pProgress->type = BURN_CACHE_PROGRESS_TYPE_STAGE;
1816 break;
1817 case BURN_CACHE_STEP_HASH:
1818 pProgress->type = BURN_CACHE_PROGRESS_TYPE_HASH;
1819 break;
1820 case BURN_CACHE_STEP_FINALIZE:
1821 pProgress->type = BURN_CACHE_PROGRESS_TYPE_FINALIZE;
1822 break;
1823 }
1824 break;
1825 case BURN_CACHE_MESSAGE_SUCCESS:
1826 hr = CompleteCacheProgress(pProgress, pMessage->success.qwFileSize);
1827 break;
1828 case BURN_CACHE_MESSAGE_COMPLETE:
1829 switch (pProgress->type)
1830 {
1831 case BURN_CACHE_PROGRESS_TYPE_CONTAINER_OR_PAYLOAD_VERIFY:
1832 hr = UserExperienceOnCacheContainerOrPayloadVerifyComplete(pProgress->pCacheContext->pUX, wzPackageOrContainerId, wzPayloadId, hr);
1833 break;
1834 }
1835 }
1836
1837 return hr;
1838}
1839
1823static HRESULT CompleteCacheProgress( 1840static HRESULT CompleteCacheProgress(
1824 __in BURN_CACHE_PROGRESS_CONTEXT* pContext, 1841 __in BURN_CACHE_PROGRESS_CONTEXT* pContext,
1825 __in DWORD64 qwFileSize 1842 __in DWORD64 qwFileSize
@@ -1829,9 +1846,29 @@ static HRESULT CompleteCacheProgress(
1829 LARGE_INTEGER liContainerOrPayloadSize = { }; 1846 LARGE_INTEGER liContainerOrPayloadSize = { };
1830 LARGE_INTEGER liZero = { }; 1847 LARGE_INTEGER liZero = { };
1831 DWORD dwResult = 0; 1848 DWORD dwResult = 0;
1849 DWORD64 qwCommitSize = 0;
1832 1850
1833 liContainerOrPayloadSize.QuadPart = qwFileSize; 1851 liContainerOrPayloadSize.QuadPart = qwFileSize;
1834 1852
1853 // Need to commit the steps that were skipped.
1854 if (BURN_CACHE_PROGRESS_TYPE_CONTAINER_OR_PAYLOAD_VERIFY == pContext->type || BURN_CACHE_PROGRESS_TYPE_PAYLOAD_VERIFY == pContext->type)
1855 {
1856 Assert(!pContext->pPayload);
1857
1858 qwCommitSize = qwFileSize * (pContext->pCacheContext->wzLayoutDirectory ? 2 : 3); // Acquire (+ Stage) + Hash + Finalize - 1 (that's added later)
1859
1860 pContext->pCacheContext->qwSuccessfulCacheProgress += qwCommitSize;
1861
1862 if (pContext->pContainer)
1863 {
1864 pContext->pContainer->qwCommittedCacheProgress += qwCommitSize;
1865 }
1866 else if (pContext->pPayloadGroupItem)
1867 {
1868 pContext->pPayloadGroupItem->qwCommittedCacheProgress += qwCommitSize;
1869 }
1870 }
1871
1835 dwResult = CacheProgressRoutine(liContainerOrPayloadSize, liContainerOrPayloadSize, liZero, liZero, 0, 0, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, pContext); 1872 dwResult = CacheProgressRoutine(liContainerOrPayloadSize, liContainerOrPayloadSize, liZero, liZero, 0, 0, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, pContext);
1836 1873
1837 if (PROGRESS_CONTINUE == dwResult) 1874 if (PROGRESS_CONTINUE == dwResult)
@@ -1851,7 +1888,7 @@ static HRESULT CompleteCacheProgress(
1851 pContext->pPayloadGroupItem->qwCommittedCacheProgress += qwFileSize; 1888 pContext->pPayloadGroupItem->qwCommittedCacheProgress += qwFileSize;
1852 } 1889 }
1853 1890
1854 if (BURN_CACHE_PROGRESS_TYPE_VERIFY == pContext->type && pContext->pCacheContext->sczLastUsedFolderCandidate) 1891 if (BURN_CACHE_PROGRESS_TYPE_FINALIZE == pContext->type && pContext->pCacheContext->sczLastUsedFolderCandidate)
1855 { 1892 {
1856 // We successfully copied from a source location, set that as the last used source. 1893 // We successfully copied from a source location, set that as the last used source.
1857 CacheSetLastUsedSource(pContext->pCacheContext->pVariables, pContext->pCacheContext->sczLastUsedFolderCandidate, pContext->pContainer ? pContext->pContainer->sczFilePath : pContext->pPayloadGroupItem->pPayload->sczFilePath); 1894 CacheSetLastUsedSource(pContext->pCacheContext->pVariables, pContext->pCacheContext->sczLastUsedFolderCandidate, pContext->pContainer ? pContext->pContainer->sczFilePath : pContext->pPayloadGroupItem->pPayload->sczFilePath);
@@ -1867,6 +1904,20 @@ static HRESULT CompleteCacheProgress(
1867 { 1904 {
1868 hr = pContext->hrError; 1905 hr = pContext->hrError;
1869 } 1906 }
1907
1908 if (qwCommitSize)
1909 {
1910 pContext->pCacheContext->qwSuccessfulCacheProgress -= qwCommitSize;
1911
1912 if (pContext->pContainer)
1913 {
1914 pContext->pContainer->qwCommittedCacheProgress -= qwCommitSize;
1915 }
1916 else if (pContext->pPayloadGroupItem)
1917 {
1918 pContext->pPayloadGroupItem->qwCommittedCacheProgress -= qwCommitSize;
1919 }
1920 }
1870 } 1921 }
1871 1922
1872 return hr; 1923 return hr;
@@ -1903,9 +1954,21 @@ static DWORD CALLBACK CacheProgressRoutine(
1903 hr = UserExperienceOnCacheAcquireProgress(pProgress->pCacheContext->pUX, wzPackageOrContainerId, wzPayloadId, TotalBytesTransferred.QuadPart, TotalFileSize.QuadPart, dwOverallPercentage); 1954 hr = UserExperienceOnCacheAcquireProgress(pProgress->pCacheContext->pUX, wzPackageOrContainerId, wzPayloadId, TotalBytesTransferred.QuadPart, TotalFileSize.QuadPart, dwOverallPercentage);
1904 ExitOnRootFailure(hr, "BA aborted acquire of %hs: %ls", pProgress->pContainer ? "container" : "payload", pProgress->pContainer ? wzPackageOrContainerId : wzPayloadId); 1955 ExitOnRootFailure(hr, "BA aborted acquire of %hs: %ls", pProgress->pContainer ? "container" : "payload", pProgress->pContainer ? wzPackageOrContainerId : wzPayloadId);
1905 break; 1956 break;
1906 case BURN_CACHE_PROGRESS_TYPE_VERIFY: 1957 case BURN_CACHE_PROGRESS_TYPE_PAYLOAD_VERIFY:
1907 hr = UserExperienceOnCacheVerifyProgress(pProgress->pCacheContext->pUX, wzPackageOrContainerId, wzPayloadId, TotalBytesTransferred.QuadPart, TotalFileSize.QuadPart, dwOverallPercentage); 1958 hr = UserExperienceOnCacheVerifyProgress(pProgress->pCacheContext->pUX, wzPackageOrContainerId, wzPayloadId, TotalBytesTransferred.QuadPart, TotalFileSize.QuadPart, dwOverallPercentage, BOOTSTRAPPER_CACHE_VERIFY_STEP_HASH);
1908 ExitOnRootFailure(hr, "BA aborted verify of %hs: %ls", pProgress->pContainer ? "container" : "payload", pProgress->pContainer ? wzPackageOrContainerId : wzPayloadId); 1959 ExitOnRootFailure(hr, "BA aborted payload verify step during verify of %hs: %ls", pProgress->pContainer ? "container" : "payload", pProgress->pContainer ? wzPackageOrContainerId : wzPayloadId);
1960 break;
1961 case BURN_CACHE_PROGRESS_TYPE_STAGE:
1962 hr = UserExperienceOnCacheVerifyProgress(pProgress->pCacheContext->pUX, wzPackageOrContainerId, wzPayloadId, TotalBytesTransferred.QuadPart, TotalFileSize.QuadPart, dwOverallPercentage, BOOTSTRAPPER_CACHE_VERIFY_STEP_STAGE);
1963 ExitOnRootFailure(hr, "BA aborted stage step during verify of %hs: %ls", pProgress->pContainer ? "container" : "payload", pProgress->pContainer ? wzPackageOrContainerId : wzPayloadId);
1964 break;
1965 case BURN_CACHE_PROGRESS_TYPE_HASH:
1966 hr = UserExperienceOnCacheVerifyProgress(pProgress->pCacheContext->pUX, wzPackageOrContainerId, wzPayloadId, TotalBytesTransferred.QuadPart, TotalFileSize.QuadPart, dwOverallPercentage, BOOTSTRAPPER_CACHE_VERIFY_STEP_HASH);
1967 ExitOnRootFailure(hr, "BA aborted hash step during verify of %hs: %ls", pProgress->pContainer ? "container" : "payload", pProgress->pContainer ? wzPackageOrContainerId : wzPayloadId);
1968 break;
1969 case BURN_CACHE_PROGRESS_TYPE_FINALIZE:
1970 hr = UserExperienceOnCacheVerifyProgress(pProgress->pCacheContext->pUX, wzPackageOrContainerId, wzPayloadId, TotalBytesTransferred.QuadPart, TotalFileSize.QuadPart, dwOverallPercentage, BOOTSTRAPPER_CACHE_VERIFY_STEP_FINALIZE);
1971 ExitOnRootFailure(hr, "BA aborted finalize step during verify of %hs: %ls", pProgress->pContainer ? "container" : "payload", pProgress->pContainer ? wzPackageOrContainerId : wzPayloadId);
1909 break; 1972 break;
1910 case BURN_CACHE_PROGRESS_TYPE_CONTAINER_OR_PAYLOAD_VERIFY: 1973 case BURN_CACHE_PROGRESS_TYPE_CONTAINER_OR_PAYLOAD_VERIFY:
1911 hr = UserExperienceOnCacheContainerOrPayloadVerifyProgress(pProgress->pCacheContext->pUX, wzPackageOrContainerId, wzPayloadId, TotalBytesTransferred.QuadPart, TotalFileSize.QuadPart, dwOverallPercentage); 1974 hr = UserExperienceOnCacheContainerOrPayloadVerifyProgress(pProgress->pCacheContext->pUX, wzPackageOrContainerId, wzPayloadId, TotalBytesTransferred.QuadPart, TotalFileSize.QuadPart, dwOverallPercentage);
diff --git a/src/engine/cache.cpp b/src/engine/cache.cpp
index 9aa94d1d..16f2c1e5 100644
--- a/src/engine/cache.cpp
+++ b/src/engine/cache.cpp
@@ -44,28 +44,47 @@ static HRESULT VerifyThenTransferContainer(
44 __in BURN_CONTAINER* pContainer, 44 __in BURN_CONTAINER* pContainer,
45 __in_z LPCWSTR wzCachedPath, 45 __in_z LPCWSTR wzCachedPath,
46 __in_z LPCWSTR wzUnverifiedContainerPath, 46 __in_z LPCWSTR wzUnverifiedContainerPath,
47 __in BOOL fMove 47 __in BOOL fMove,
48 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
49 __in LPPROGRESS_ROUTINE pfnProgress,
50 __in LPVOID pContext
48 ); 51 );
49static HRESULT VerifyThenTransferPayload( 52static HRESULT VerifyThenTransferPayload(
50 __in BURN_PAYLOAD* pPayload, 53 __in BURN_PAYLOAD* pPayload,
51 __in_z LPCWSTR wzCachedPath, 54 __in_z LPCWSTR wzCachedPath,
52 __in_z LPCWSTR wzUnverifiedPayloadPath, 55 __in_z LPCWSTR wzUnverifiedPayloadPath,
53 __in BOOL fMove 56 __in BOOL fMove,
57 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
58 __in LPPROGRESS_ROUTINE pfnProgress,
59 __in LPVOID pContext
54 ); 60 );
55static HRESULT TransferWorkingPathToUnverifiedPath( 61static HRESULT CacheTransferFileWithRetry(
56 __in_z LPCWSTR wzWorkingPath, 62 __in_z LPCWSTR wzSourcePath,
57 __in_z LPCWSTR wzUnverifiedPayloadPath, 63 __in_z LPCWSTR wzDestinationPath,
58 __in BOOL fMove 64 __in BOOL fMove,
65 __in BURN_CACHE_STEP cacheStep,
66 __in DWORD64 qwFileSize,
67 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
68 __in LPPROGRESS_ROUTINE pfnProgress,
69 __in LPVOID pContext
59 ); 70 );
60static HRESULT VerifyFileAgainstContainer( 71static HRESULT VerifyFileAgainstContainer(
61 __in BURN_CONTAINER* pContainer, 72 __in BURN_CONTAINER* pContainer,
62 __in_z LPCWSTR wzVerifyPath, 73 __in_z LPCWSTR wzVerifyPath,
63 __in BOOL fAlreadyCached 74 __in BOOL fAlreadyCached,
75 __in BURN_CACHE_STEP cacheStep,
76 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
77 __in LPPROGRESS_ROUTINE pfnProgress,
78 __in LPVOID pContext
64 ); 79 );
65static HRESULT VerifyFileAgainstPayload( 80static HRESULT VerifyFileAgainstPayload(
66 __in BURN_PAYLOAD* pPayload, 81 __in BURN_PAYLOAD* pPayload,
67 __in_z LPCWSTR wzVerifyPath, 82 __in_z LPCWSTR wzVerifyPath,
68 __in BOOL fAlreadyCached 83 __in BOOL fAlreadyCached,
84 __in BURN_CACHE_STEP cacheStep,
85 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
86 __in LPPROGRESS_ROUTINE pfnProgress,
87 __in LPVOID pContext
69 ); 88 );
70static HRESULT ResetPathPermissions( 89static HRESULT ResetPathPermissions(
71 __in BOOL fPerMachine, 90 __in BOOL fPerMachine,
@@ -99,7 +118,26 @@ static HRESULT VerifyHash(
99 __in DWORD cbHash, 118 __in DWORD cbHash,
100 __in DWORD64 qwFileSize, 119 __in DWORD64 qwFileSize,
101 __in_z LPCWSTR wzUnverifiedPayloadPath, 120 __in_z LPCWSTR wzUnverifiedPayloadPath,
102 __in HANDLE hFile 121 __in HANDLE hFile,
122 __in BURN_CACHE_STEP cacheStep,
123 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
124 __in LPPROGRESS_ROUTINE pfnProgress,
125 __in LPVOID pContext
126 );
127static HRESULT SendCacheBeginMessage(
128 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
129 __in LPVOID pContext,
130 __in BURN_CACHE_STEP cacheStep
131 );
132static HRESULT SendCacheSuccessMessage(
133 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
134 __in LPVOID pContext,
135 __in DWORD64 qwFileSize
136 );
137static HRESULT SendCacheCompleteMessage(
138 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
139 __in LPVOID pContext,
140 __in HRESULT hrStatus
103 ); 141 );
104 142
105 143
@@ -754,7 +792,11 @@ LExit:
754extern "C" HRESULT CacheLayoutBundle( 792extern "C" HRESULT CacheLayoutBundle(
755 __in_z LPCWSTR wzExecutableName, 793 __in_z LPCWSTR wzExecutableName,
756 __in_z LPCWSTR wzLayoutDirectory, 794 __in_z LPCWSTR wzLayoutDirectory,
757 __in_z LPCWSTR wzSourceBundlePath 795 __in_z LPCWSTR wzSourceBundlePath,
796 __in DWORD64 qwBundleSize,
797 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
798 __in LPPROGRESS_ROUTINE pfnProgress,
799 __in LPVOID pContext
758 ) 800 )
759{ 801{
760 HRESULT hr = S_OK; 802 HRESULT hr = S_OK;
@@ -765,7 +807,7 @@ extern "C" HRESULT CacheLayoutBundle(
765 807
766 LogStringLine(REPORT_STANDARD, "Layout bundle from: '%ls' to: '%ls'", wzSourceBundlePath, sczTargetPath); 808 LogStringLine(REPORT_STANDARD, "Layout bundle from: '%ls' to: '%ls'", wzSourceBundlePath, sczTargetPath);
767 809
768 hr = FileEnsureMoveWithRetry(wzSourceBundlePath, sczTargetPath, TRUE, TRUE, FILE_OPERATION_RETRY_COUNT, FILE_OPERATION_RETRY_WAIT); 810 hr = CacheTransferFileWithRetry(wzSourceBundlePath, sczTargetPath, TRUE, BURN_CACHE_STEP_FINALIZE, qwBundleSize, pfnCacheMessageHandler, pfnProgress, pContext);
769 ExitOnFailure(hr, "Failed to layout bundle from: '%ls' to '%ls'", wzSourceBundlePath, sczTargetPath); 811 ExitOnFailure(hr, "Failed to layout bundle from: '%ls' to '%ls'", wzSourceBundlePath, sczTargetPath);
770 812
771LExit: 813LExit:
@@ -838,7 +880,10 @@ extern "C" HRESULT CacheLayoutContainer(
838 __in BURN_CONTAINER* pContainer, 880 __in BURN_CONTAINER* pContainer,
839 __in_z_opt LPCWSTR wzLayoutDirectory, 881 __in_z_opt LPCWSTR wzLayoutDirectory,
840 __in_z LPCWSTR wzUnverifiedContainerPath, 882 __in_z LPCWSTR wzUnverifiedContainerPath,
841 __in BOOL fMove 883 __in BOOL fMove,
884 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
885 __in LPPROGRESS_ROUTINE pfnProgress,
886 __in LPVOID pContext
842 ) 887 )
843{ 888{
844 HRESULT hr = S_OK; 889 HRESULT hr = S_OK;
@@ -847,7 +892,7 @@ extern "C" HRESULT CacheLayoutContainer(
847 hr = PathConcat(wzLayoutDirectory, pContainer->sczFilePath, &sczCachedPath); 892 hr = PathConcat(wzLayoutDirectory, pContainer->sczFilePath, &sczCachedPath);
848 ExitOnFailure(hr, "Failed to concat complete cached path."); 893 ExitOnFailure(hr, "Failed to concat complete cached path.");
849 894
850 hr = VerifyThenTransferContainer(pContainer, sczCachedPath, wzUnverifiedContainerPath, fMove); 895 hr = VerifyThenTransferContainer(pContainer, sczCachedPath, wzUnverifiedContainerPath, fMove, pfnCacheMessageHandler, pfnProgress, pContext);
851 ExitOnFailure(hr, "Failed to layout container from cached path: %ls", sczCachedPath); 896 ExitOnFailure(hr, "Failed to layout container from cached path: %ls", sczCachedPath);
852 897
853LExit: 898LExit:
@@ -860,7 +905,10 @@ extern "C" HRESULT CacheLayoutPayload(
860 __in BURN_PAYLOAD* pPayload, 905 __in BURN_PAYLOAD* pPayload,
861 __in_z_opt LPCWSTR wzLayoutDirectory, 906 __in_z_opt LPCWSTR wzLayoutDirectory,
862 __in_z LPCWSTR wzUnverifiedPayloadPath, 907 __in_z LPCWSTR wzUnverifiedPayloadPath,
863 __in BOOL fMove 908 __in BOOL fMove,
909 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
910 __in LPPROGRESS_ROUTINE pfnProgress,
911 __in LPVOID pContext
864 ) 912 )
865{ 913{
866 HRESULT hr = S_OK; 914 HRESULT hr = S_OK;
@@ -869,7 +917,7 @@ extern "C" HRESULT CacheLayoutPayload(
869 hr = PathConcat(wzLayoutDirectory, pPayload->sczFilePath, &sczCachedPath); 917 hr = PathConcat(wzLayoutDirectory, pPayload->sczFilePath, &sczCachedPath);
870 ExitOnFailure(hr, "Failed to concat complete cached path."); 918 ExitOnFailure(hr, "Failed to concat complete cached path.");
871 919
872 hr = VerifyThenTransferPayload(pPayload, sczCachedPath, wzUnverifiedPayloadPath, fMove); 920 hr = VerifyThenTransferPayload(pPayload, sczCachedPath, wzUnverifiedPayloadPath, fMove, pfnCacheMessageHandler, pfnProgress, pContext);
873 ExitOnFailure(hr, "Failed to layout payload from cached payload: %ls", sczCachedPath); 921 ExitOnFailure(hr, "Failed to layout payload from cached payload: %ls", sczCachedPath);
874 922
875LExit: 923LExit:
@@ -883,7 +931,10 @@ extern "C" HRESULT CacheCompletePayload(
883 __in BURN_PAYLOAD* pPayload, 931 __in BURN_PAYLOAD* pPayload,
884 __in_z LPCWSTR wzCacheId, 932 __in_z LPCWSTR wzCacheId,
885 __in_z LPCWSTR wzWorkingPayloadPath, 933 __in_z LPCWSTR wzWorkingPayloadPath,
886 __in BOOL fMove 934 __in BOOL fMove,
935 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
936 __in LPPROGRESS_ROUTINE pfnProgress,
937 __in LPVOID pContext
887 ) 938 )
888{ 939{
889 HRESULT hr = S_OK; 940 HRESULT hr = S_OK;
@@ -898,7 +949,7 @@ extern "C" HRESULT CacheCompletePayload(
898 ExitOnFailure(hr, "Failed to concat complete cached path."); 949 ExitOnFailure(hr, "Failed to concat complete cached path.");
899 950
900 // If the cached file matches what we expected, we're good. 951 // If the cached file matches what we expected, we're good.
901 hr = VerifyFileAgainstPayload(pPayload, sczCachedPath, TRUE); 952 hr = VerifyFileAgainstPayload(pPayload, sczCachedPath, TRUE, BURN_CACHE_STEP_HASH_TO_SKIP_VERIFY, pfnCacheMessageHandler, pfnProgress, pContext);
902 if (SUCCEEDED(hr)) 953 if (SUCCEEDED(hr))
903 { 954 {
904 ExitFunction(); 955 ExitFunction();
@@ -910,10 +961,21 @@ extern "C" HRESULT CacheCompletePayload(
910 // If the working path exists, let's get it into the unverified path so we can reset the ACLs and verify the file. 961 // If the working path exists, let's get it into the unverified path so we can reset the ACLs and verify the file.
911 if (FileExistsEx(wzWorkingPayloadPath, NULL)) 962 if (FileExistsEx(wzWorkingPayloadPath, NULL))
912 { 963 {
913 hr = TransferWorkingPathToUnverifiedPath(wzWorkingPayloadPath, sczUnverifiedPayloadPath, fMove); 964 hr = CacheTransferFileWithRetry(wzWorkingPayloadPath, sczUnverifiedPayloadPath, fMove, BURN_CACHE_STEP_STAGE, pPayload->qwFileSize, pfnCacheMessageHandler, pfnProgress, pContext);
914 ExitOnFailure(hr, "Failed to transfer working path to unverified path for payload: %ls.", pPayload->sczKey); 965 ExitOnFailure(hr, "Failed to transfer working path to unverified path for payload: %ls.", pPayload->sczKey);
915 } 966 }
916 else if (!FileExistsEx(sczUnverifiedPayloadPath, NULL)) // if the working path and unverified path do not exist, nothing we can do. 967 else if (FileExistsEx(sczUnverifiedPayloadPath, NULL))
968 {
969 // Make sure the staging progress is sent even though there was nothing to do.
970 hr = SendCacheBeginMessage(pfnCacheMessageHandler, pContext, BURN_CACHE_STEP_STAGE);
971 if (SUCCEEDED(hr))
972 {
973 hr = SendCacheSuccessMessage(pfnCacheMessageHandler, pContext, pPayload->qwFileSize);
974 }
975 SendCacheCompleteMessage(pfnCacheMessageHandler, pContext, hr);
976 ExitOnFailure(hr, "Aborted transferring working path to unverified path for payload: %ls.", pPayload->sczKey);
977 }
978 else // if the working path and unverified path do not exist, nothing we can do.
917 { 979 {
918 hr = E_FILENOTFOUND; 980 hr = E_FILENOTFOUND;
919 ExitOnFailure(hr, "Failed to find payload: %ls in working path: %ls and unverified path: %ls", pPayload->sczKey, wzWorkingPayloadPath, sczUnverifiedPayloadPath); 981 ExitOnFailure(hr, "Failed to find payload: %ls in working path: %ls and unverified path: %ls", pPayload->sczKey, wzWorkingPayloadPath, sczUnverifiedPayloadPath);
@@ -922,12 +984,12 @@ extern "C" HRESULT CacheCompletePayload(
922 hr = ResetPathPermissions(fPerMachine, sczUnverifiedPayloadPath); 984 hr = ResetPathPermissions(fPerMachine, sczUnverifiedPayloadPath);
923 ExitOnFailure(hr, "Failed to reset permissions on unverified cached payload: %ls", pPayload->sczKey); 985 ExitOnFailure(hr, "Failed to reset permissions on unverified cached payload: %ls", pPayload->sczKey);
924 986
925 hr = VerifyFileAgainstPayload(pPayload, sczUnverifiedPayloadPath, FALSE); 987 hr = VerifyFileAgainstPayload(pPayload, sczUnverifiedPayloadPath, FALSE, BURN_CACHE_STEP_HASH, pfnCacheMessageHandler, pfnProgress, pContext);
926 LogExitOnFailure(hr, MSG_FAILED_VERIFY_PAYLOAD, "Failed to verify payload: %ls at path: %ls", pPayload->sczKey, sczUnverifiedPayloadPath, NULL); 988 LogExitOnFailure(hr, MSG_FAILED_VERIFY_PAYLOAD, "Failed to verify payload: %ls at path: %ls", pPayload->sczKey, sczUnverifiedPayloadPath, NULL);
927 989
928 LogId(REPORT_STANDARD, MSG_VERIFIED_ACQUIRED_PAYLOAD, pPayload->sczKey, sczUnverifiedPayloadPath, fMove ? "moving" : "copying", sczCachedPath); 990 LogId(REPORT_STANDARD, MSG_VERIFIED_ACQUIRED_PAYLOAD, pPayload->sczKey, sczUnverifiedPayloadPath, fMove ? "moving" : "copying", sczCachedPath);
929 991
930 hr = FileEnsureMoveWithRetry(sczUnverifiedPayloadPath, sczCachedPath, TRUE, TRUE, FILE_OPERATION_RETRY_COUNT, FILE_OPERATION_RETRY_WAIT); 992 hr = CacheTransferFileWithRetry(sczUnverifiedPayloadPath, sczCachedPath, TRUE, BURN_CACHE_STEP_FINALIZE, pPayload->qwFileSize, pfnCacheMessageHandler, pfnProgress, pContext);
931 ExitOnFailure(hr, "Failed to move verified file to complete payload path: %ls", sczCachedPath); 993 ExitOnFailure(hr, "Failed to move verified file to complete payload path: %ls", sczCachedPath);
932 994
933 ::DecryptFileW(sczCachedPath, 0); // Let's try to make sure it's not encrypted. 995 ::DecryptFileW(sczCachedPath, 0); // Let's try to make sure it's not encrypted.
@@ -942,7 +1004,10 @@ LExit:
942 1004
943extern "C" HRESULT CacheVerifyContainer( 1005extern "C" HRESULT CacheVerifyContainer(
944 __in BURN_CONTAINER* pContainer, 1006 __in BURN_CONTAINER* pContainer,
945 __in_z LPCWSTR wzCachedDirectory 1007 __in_z LPCWSTR wzCachedDirectory,
1008 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
1009 __in LPPROGRESS_ROUTINE pfnProgress,
1010 __in LPVOID pContext
946 ) 1011 )
947{ 1012{
948 HRESULT hr = S_OK; 1013 HRESULT hr = S_OK;
@@ -951,7 +1016,7 @@ extern "C" HRESULT CacheVerifyContainer(
951 hr = PathConcat(wzCachedDirectory, pContainer->sczFilePath, &sczCachedPath); 1016 hr = PathConcat(wzCachedDirectory, pContainer->sczFilePath, &sczCachedPath);
952 ExitOnFailure(hr, "Failed to concat complete cached path."); 1017 ExitOnFailure(hr, "Failed to concat complete cached path.");
953 1018
954 hr = VerifyFileAgainstContainer(pContainer, sczCachedPath, TRUE); 1019 hr = VerifyFileAgainstContainer(pContainer, sczCachedPath, TRUE, BURN_CACHE_STEP_HASH_TO_SKIP_ACQUIRE, pfnCacheMessageHandler, pfnProgress, pContext);
955 1020
956LExit: 1021LExit:
957 ReleaseStr(sczCachedPath); 1022 ReleaseStr(sczCachedPath);
@@ -961,7 +1026,10 @@ LExit:
961 1026
962extern "C" HRESULT CacheVerifyPayload( 1027extern "C" HRESULT CacheVerifyPayload(
963 __in BURN_PAYLOAD* pPayload, 1028 __in BURN_PAYLOAD* pPayload,
964 __in_z LPCWSTR wzCachedDirectory 1029 __in_z LPCWSTR wzCachedDirectory,
1030 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
1031 __in LPPROGRESS_ROUTINE pfnProgress,
1032 __in LPVOID pContext
965 ) 1033 )
966{ 1034{
967 HRESULT hr = S_OK; 1035 HRESULT hr = S_OK;
@@ -970,7 +1038,7 @@ extern "C" HRESULT CacheVerifyPayload(
970 hr = PathConcat(wzCachedDirectory, pPayload->sczFilePath, &sczCachedPath); 1038 hr = PathConcat(wzCachedDirectory, pPayload->sczFilePath, &sczCachedPath);
971 ExitOnFailure(hr, "Failed to concat complete cached path."); 1039 ExitOnFailure(hr, "Failed to concat complete cached path.");
972 1040
973 hr = VerifyFileAgainstPayload(pPayload, sczCachedPath, TRUE); 1041 hr = VerifyFileAgainstPayload(pPayload, sczCachedPath, TRUE, BURN_CACHE_STEP_HASH_TO_SKIP_ACQUIRE, pfnCacheMessageHandler, pfnProgress, pContext);
974 1042
975LExit: 1043LExit:
976 ReleaseStr(sczCachedPath); 1044 ReleaseStr(sczCachedPath);
@@ -1342,7 +1410,10 @@ static HRESULT VerifyThenTransferContainer(
1342 __in BURN_CONTAINER* pContainer, 1410 __in BURN_CONTAINER* pContainer,
1343 __in_z LPCWSTR wzCachedPath, 1411 __in_z LPCWSTR wzCachedPath,
1344 __in_z LPCWSTR wzUnverifiedContainerPath, 1412 __in_z LPCWSTR wzUnverifiedContainerPath,
1345 __in BOOL fMove 1413 __in BOOL fMove,
1414 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
1415 __in LPPROGRESS_ROUTINE pfnProgress,
1416 __in LPVOID pContext
1346 ) 1417 )
1347{ 1418{
1348 HRESULT hr = S_OK; 1419 HRESULT hr = S_OK;
@@ -1358,22 +1429,13 @@ static HRESULT VerifyThenTransferContainer(
1358 // Container should have a hash we can use to verify with. 1429 // Container should have a hash we can use to verify with.
1359 if (pContainer->pbHash) 1430 if (pContainer->pbHash)
1360 { 1431 {
1361 hr = VerifyHash(pContainer->pbHash, pContainer->cbHash, pContainer->qwFileSize, wzUnverifiedContainerPath, hFile); 1432 hr = VerifyHash(pContainer->pbHash, pContainer->cbHash, pContainer->qwFileSize, wzUnverifiedContainerPath, hFile, BURN_CACHE_STEP_HASH, pfnCacheMessageHandler, pfnProgress, pContext);
1362 ExitOnFailure(hr, "Failed to verify container hash: %ls", wzCachedPath); 1433 ExitOnFailure(hr, "Failed to verify container hash: %ls", wzCachedPath);
1363 } 1434 }
1364 1435
1365 LogStringLine(REPORT_STANDARD, "%ls container from working path '%ls' to path '%ls'", fMove ? L"Moving" : L"Copying", wzUnverifiedContainerPath, wzCachedPath); 1436 LogStringLine(REPORT_STANDARD, "%ls container from working path '%ls' to path '%ls'", fMove ? L"Moving" : L"Copying", wzUnverifiedContainerPath, wzCachedPath);
1366 1437
1367 if (fMove) 1438 hr = CacheTransferFileWithRetry(wzUnverifiedContainerPath, wzCachedPath, fMove, BURN_CACHE_STEP_FINALIZE, pContainer->qwFileSize, pfnCacheMessageHandler, pfnProgress, pContext);
1368 {
1369 hr = FileEnsureMoveWithRetry(wzUnverifiedContainerPath, wzCachedPath, TRUE, TRUE, FILE_OPERATION_RETRY_COUNT, FILE_OPERATION_RETRY_WAIT);
1370 ExitOnFailure(hr, "Failed to move %ls to %ls", wzUnverifiedContainerPath, wzCachedPath);
1371 }
1372 else
1373 {
1374 hr = FileEnsureCopyWithRetry(wzUnverifiedContainerPath, wzCachedPath, TRUE, FILE_OPERATION_RETRY_COUNT, FILE_OPERATION_RETRY_WAIT);
1375 ExitOnFailure(hr, "Failed to copy %ls to %ls", wzUnverifiedContainerPath, wzCachedPath);
1376 }
1377 1439
1378LExit: 1440LExit:
1379 ReleaseFileHandle(hFile); 1441 ReleaseFileHandle(hFile);
@@ -1385,7 +1447,10 @@ static HRESULT VerifyThenTransferPayload(
1385 __in BURN_PAYLOAD* pPayload, 1447 __in BURN_PAYLOAD* pPayload,
1386 __in_z LPCWSTR wzCachedPath, 1448 __in_z LPCWSTR wzCachedPath,
1387 __in_z LPCWSTR wzUnverifiedPayloadPath, 1449 __in_z LPCWSTR wzUnverifiedPayloadPath,
1388 __in BOOL fMove 1450 __in BOOL fMove,
1451 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
1452 __in LPPROGRESS_ROUTINE pfnProgress,
1453 __in LPVOID pContext
1389 ) 1454 )
1390{ 1455{
1391 HRESULT hr = S_OK; 1456 HRESULT hr = S_OK;
@@ -1400,22 +1465,13 @@ static HRESULT VerifyThenTransferPayload(
1400 1465
1401 if (pPayload->pbHash) // the payload should have a hash we can use to verify it. 1466 if (pPayload->pbHash) // the payload should have a hash we can use to verify it.
1402 { 1467 {
1403 hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, pPayload->qwFileSize, wzUnverifiedPayloadPath, hFile); 1468 hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, pPayload->qwFileSize, wzUnverifiedPayloadPath, hFile, BURN_CACHE_STEP_HASH, pfnCacheMessageHandler, pfnProgress, pContext);
1404 ExitOnFailure(hr, "Failed to verify payload hash: %ls", wzCachedPath); 1469 ExitOnFailure(hr, "Failed to verify payload hash: %ls", wzCachedPath);
1405 } 1470 }
1406 1471
1407 LogStringLine(REPORT_STANDARD, "%ls payload from working path '%ls' to path '%ls'", fMove ? L"Moving" : L"Copying", wzUnverifiedPayloadPath, wzCachedPath); 1472 LogStringLine(REPORT_STANDARD, "%ls payload from working path '%ls' to path '%ls'", fMove ? L"Moving" : L"Copying", wzUnverifiedPayloadPath, wzCachedPath);
1408 1473
1409 if (fMove) 1474 hr = CacheTransferFileWithRetry(wzUnverifiedPayloadPath, wzCachedPath, fMove, BURN_CACHE_STEP_FINALIZE, pPayload->qwFileSize, pfnCacheMessageHandler, pfnProgress, pContext);
1410 {
1411 hr = FileEnsureMoveWithRetry(wzUnverifiedPayloadPath, wzCachedPath, TRUE, TRUE, FILE_OPERATION_RETRY_COUNT, FILE_OPERATION_RETRY_WAIT);
1412 ExitOnFailure(hr, "Failed to move %ls to %ls", wzUnverifiedPayloadPath, wzCachedPath);
1413 }
1414 else
1415 {
1416 hr = FileEnsureCopyWithRetry(wzUnverifiedPayloadPath, wzCachedPath, TRUE, FILE_OPERATION_RETRY_COUNT, FILE_OPERATION_RETRY_WAIT);
1417 ExitOnFailure(hr, "Failed to copy %ls to %ls", wzUnverifiedPayloadPath, wzCachedPath);
1418 }
1419 1475
1420LExit: 1476LExit:
1421 ReleaseFileHandle(hFile); 1477 ReleaseFileHandle(hFile);
@@ -1423,33 +1479,50 @@ LExit:
1423 return hr; 1479 return hr;
1424} 1480}
1425 1481
1426static HRESULT TransferWorkingPathToUnverifiedPath( 1482static HRESULT CacheTransferFileWithRetry(
1427 __in_z LPCWSTR wzWorkingPath, 1483 __in_z LPCWSTR wzSourcePath,
1428 __in_z LPCWSTR wzUnverifiedPayloadPath, 1484 __in_z LPCWSTR wzDestinationPath,
1429 __in BOOL fMove 1485 __in BOOL fMove,
1486 __in BURN_CACHE_STEP cacheStep,
1487 __in DWORD64 qwFileSize,
1488 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
1489 __in LPPROGRESS_ROUTINE /*pfnProgress*/,
1490 __in LPVOID pContext
1430 ) 1491 )
1431{ 1492{
1432 HRESULT hr = S_OK; 1493 HRESULT hr = S_OK;
1433 1494
1495 hr = SendCacheBeginMessage(pfnCacheMessageHandler, pContext, cacheStep);
1496 ExitOnFailure(hr, "Aborted cache file transfer begin.");
1497
1498 // TODO: send progress during the file transfer.
1434 if (fMove) 1499 if (fMove)
1435 { 1500 {
1436 hr = FileEnsureMoveWithRetry(wzWorkingPath, wzUnverifiedPayloadPath, TRUE, TRUE, FILE_OPERATION_RETRY_COUNT, FILE_OPERATION_RETRY_WAIT); 1501 hr = FileEnsureMoveWithRetry(wzSourcePath, wzDestinationPath, TRUE, TRUE, FILE_OPERATION_RETRY_COUNT, FILE_OPERATION_RETRY_WAIT);
1437 ExitOnFailure(hr, "Failed to move %ls to %ls", wzWorkingPath, wzUnverifiedPayloadPath); 1502 ExitOnFailure(hr, "Failed to move %ls to %ls", wzSourcePath, wzDestinationPath);
1438 } 1503 }
1439 else 1504 else
1440 { 1505 {
1441 hr = FileEnsureCopyWithRetry(wzWorkingPath, wzUnverifiedPayloadPath, TRUE, FILE_OPERATION_RETRY_COUNT, FILE_OPERATION_RETRY_WAIT); 1506 hr = FileEnsureCopyWithRetry(wzSourcePath, wzDestinationPath, TRUE, FILE_OPERATION_RETRY_COUNT, FILE_OPERATION_RETRY_WAIT);
1442 ExitOnFailure(hr, "Failed to copy %ls to %ls", wzWorkingPath, wzUnverifiedPayloadPath); 1507 ExitOnFailure(hr, "Failed to copy %ls to %ls", wzSourcePath, wzDestinationPath);
1443 } 1508 }
1444 1509
1510 hr = SendCacheSuccessMessage(pfnCacheMessageHandler, pContext, qwFileSize);
1511
1445LExit: 1512LExit:
1513 SendCacheCompleteMessage(pfnCacheMessageHandler, pContext, hr);
1514
1446 return hr; 1515 return hr;
1447} 1516}
1448 1517
1449static HRESULT VerifyFileAgainstContainer( 1518static HRESULT VerifyFileAgainstContainer(
1450 __in BURN_CONTAINER* pContainer, 1519 __in BURN_CONTAINER* pContainer,
1451 __in_z LPCWSTR wzVerifyPath, 1520 __in_z LPCWSTR wzVerifyPath,
1452 __in BOOL fAlreadyCached 1521 __in BOOL fAlreadyCached,
1522 __in BURN_CACHE_STEP cacheStep,
1523 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
1524 __in LPPROGRESS_ROUTINE pfnProgress,
1525 __in LPVOID pContext
1453 ) 1526 )
1454{ 1527{
1455 HRESULT hr = S_OK; 1528 HRESULT hr = S_OK;
@@ -1469,7 +1542,7 @@ static HRESULT VerifyFileAgainstContainer(
1469 1542
1470 if (pContainer->pbHash) // the container should have a hash we can use to verify it. 1543 if (pContainer->pbHash) // the container should have a hash we can use to verify it.
1471 { 1544 {
1472 hr = VerifyHash(pContainer->pbHash, pContainer->cbHash, pContainer->qwFileSize, wzVerifyPath, hFile); 1545 hr = VerifyHash(pContainer->pbHash, pContainer->cbHash, pContainer->qwFileSize, wzVerifyPath, hFile, cacheStep, pfnCacheMessageHandler, pfnProgress, pContext);
1473 ExitOnFailure(hr, "Failed to verify hash of container: %ls", pContainer->sczId); 1546 ExitOnFailure(hr, "Failed to verify hash of container: %ls", pContainer->sczId);
1474 } 1547 }
1475 1548
@@ -1498,7 +1571,11 @@ LExit:
1498static HRESULT VerifyFileAgainstPayload( 1571static HRESULT VerifyFileAgainstPayload(
1499 __in BURN_PAYLOAD* pPayload, 1572 __in BURN_PAYLOAD* pPayload,
1500 __in_z LPCWSTR wzVerifyPath, 1573 __in_z LPCWSTR wzVerifyPath,
1501 __in BOOL fAlreadyCached 1574 __in BOOL fAlreadyCached,
1575 __in BURN_CACHE_STEP cacheStep,
1576 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
1577 __in LPPROGRESS_ROUTINE pfnProgress,
1578 __in LPVOID pContext
1502 ) 1579 )
1503{ 1580{
1504 HRESULT hr = S_OK; 1581 HRESULT hr = S_OK;
@@ -1518,7 +1595,7 @@ static HRESULT VerifyFileAgainstPayload(
1518 1595
1519 if (pPayload->pbHash) // the payload should have a hash we can use to verify it. 1596 if (pPayload->pbHash) // the payload should have a hash we can use to verify it.
1520 { 1597 {
1521 hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, pPayload->qwFileSize, wzVerifyPath, hFile); 1598 hr = VerifyHash(pPayload->pbHash, pPayload->cbHash, pPayload->qwFileSize, wzVerifyPath, hFile, cacheStep, pfnCacheMessageHandler, pfnProgress, pContext);
1522 ExitOnFailure(hr, "Failed to verify hash of payload: %ls", pPayload->sczKey); 1599 ExitOnFailure(hr, "Failed to verify hash of payload: %ls", pPayload->sczKey);
1523 } 1600 }
1524 1601
@@ -1881,7 +1958,11 @@ static HRESULT VerifyHash(
1881 __in DWORD cbHash, 1958 __in DWORD cbHash,
1882 __in DWORD64 qwFileSize, 1959 __in DWORD64 qwFileSize,
1883 __in_z LPCWSTR wzUnverifiedPayloadPath, 1960 __in_z LPCWSTR wzUnverifiedPayloadPath,
1884 __in HANDLE hFile 1961 __in HANDLE hFile,
1962 __in BURN_CACHE_STEP cacheStep,
1963 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
1964 __in LPPROGRESS_ROUTINE /*pfnProgress*/,
1965 __in LPVOID pContext
1885 ) 1966 )
1886{ 1967{
1887 UNREFERENCED_PARAMETER(wzUnverifiedPayloadPath); 1968 UNREFERENCED_PARAMETER(wzUnverifiedPayloadPath);
@@ -1893,6 +1974,9 @@ static HRESULT VerifyHash(
1893 LPWSTR pszExpected = NULL; 1974 LPWSTR pszExpected = NULL;
1894 LPWSTR pszActual = NULL; 1975 LPWSTR pszActual = NULL;
1895 1976
1977 hr = SendCacheBeginMessage(pfnCacheMessageHandler, pContext, cacheStep);
1978 ExitOnFailure(hr, "Aborted cache verify hash begin.");
1979
1896 hr = FileSizeByHandle(hFile, &llSize); 1980 hr = FileSizeByHandle(hFile, &llSize);
1897 ExitOnFailure(hr, "Failed to get file size for path: %ls", wzUnverifiedPayloadPath); 1981 ExitOnFailure(hr, "Failed to get file size for path: %ls", wzUnverifiedPayloadPath);
1898 1982
@@ -1922,9 +2006,64 @@ static HRESULT VerifyHash(
1922 } 2006 }
1923 } 2007 }
1924 2008
2009 hr = SendCacheSuccessMessage(pfnCacheMessageHandler, pContext, qwFileSize);
2010
1925LExit: 2011LExit:
2012 SendCacheCompleteMessage(pfnCacheMessageHandler, pContext, hr);
2013
1926 ReleaseStr(pszActual); 2014 ReleaseStr(pszActual);
1927 ReleaseStr(pszExpected); 2015 ReleaseStr(pszExpected);
1928 2016
1929 return hr; 2017 return hr;
1930} 2018}
2019
2020static HRESULT SendCacheBeginMessage(
2021 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
2022 __in LPVOID pContext,
2023 __in BURN_CACHE_STEP cacheStep
2024 )
2025{
2026 HRESULT hr = S_OK;
2027 BURN_CACHE_MESSAGE message = { };
2028
2029 message.type = BURN_CACHE_MESSAGE_BEGIN;
2030 message.begin.cacheStep = cacheStep;
2031
2032 hr = pfnCacheMessageHandler(&message, pContext);
2033
2034 return hr;
2035}
2036
2037static HRESULT SendCacheSuccessMessage(
2038 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
2039 __in LPVOID pContext,
2040 __in DWORD64 qwFileSize
2041 )
2042{
2043 HRESULT hr = S_OK;
2044 BURN_CACHE_MESSAGE message = { };
2045
2046 message.type = BURN_CACHE_MESSAGE_SUCCESS;
2047 message.success.qwFileSize = qwFileSize;
2048
2049 hr = pfnCacheMessageHandler(&message, pContext);
2050
2051 return hr;
2052}
2053
2054static HRESULT SendCacheCompleteMessage(
2055 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
2056 __in LPVOID pContext,
2057 __in HRESULT hrStatus
2058 )
2059{
2060 HRESULT hr = S_OK;
2061 BURN_CACHE_MESSAGE message = { };
2062
2063 message.type = BURN_CACHE_MESSAGE_COMPLETE;
2064 message.complete.hrStatus = hrStatus;
2065
2066 hr = pfnCacheMessageHandler(&message, pContext);
2067
2068 return hr;
2069}
diff --git a/src/engine/cache.h b/src/engine/cache.h
index cf062a85..cd964649 100644
--- a/src/engine/cache.h
+++ b/src/engine/cache.h
@@ -7,7 +7,48 @@
7extern "C" { 7extern "C" {
8#endif 8#endif
9 9
10// structs 10
11enum BURN_CACHE_MESSAGE_TYPE
12{
13 BURN_CACHE_MESSAGE_BEGIN,
14 BURN_CACHE_MESSAGE_SUCCESS,
15 BURN_CACHE_MESSAGE_COMPLETE,
16};
17
18enum BURN_CACHE_STEP
19{
20 BURN_CACHE_STEP_HASH_TO_SKIP_ACQUIRE,
21 BURN_CACHE_STEP_HASH_TO_SKIP_VERIFY,
22 BURN_CACHE_STEP_STAGE,
23 BURN_CACHE_STEP_HASH,
24 BURN_CACHE_STEP_FINALIZE,
25};
26
27typedef struct _BURN_CACHE_MESSAGE
28{
29 BURN_CACHE_MESSAGE_TYPE type;
30
31 union
32 {
33 struct
34 {
35 BURN_CACHE_STEP cacheStep;
36 } begin;
37 struct
38 {
39 DWORD64 qwFileSize;
40 } success;
41 struct
42 {
43 HRESULT hrStatus;
44 } complete;
45 };
46} BURN_CACHE_MESSAGE;
47
48typedef HRESULT(CALLBACK* PFN_BURNCACHEMESSAGEHANDLER)(
49 __in BURN_CACHE_MESSAGE* pMessage,
50 __in LPVOID pvContext
51 );
11 52
12// functions 53// functions
13 54
@@ -95,7 +136,11 @@ HRESULT CacheBundleToWorkingDirectory(
95HRESULT CacheLayoutBundle( 136HRESULT CacheLayoutBundle(
96 __in_z LPCWSTR wzExecutableName, 137 __in_z LPCWSTR wzExecutableName,
97 __in_z LPCWSTR wzLayoutDirectory, 138 __in_z LPCWSTR wzLayoutDirectory,
98 __in_z LPCWSTR wzSourceBundlePath 139 __in_z LPCWSTR wzSourceBundlePath,
140 __in DWORD64 qwBundleSize,
141 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
142 __in LPPROGRESS_ROUTINE pfnProgress,
143 __in LPVOID pContext
99 ); 144 );
100HRESULT CacheCompleteBundle( 145HRESULT CacheCompleteBundle(
101 __in BOOL fPerMachine, 146 __in BOOL fPerMachine,
@@ -110,28 +155,43 @@ HRESULT CacheLayoutContainer(
110 __in BURN_CONTAINER* pContainer, 155 __in BURN_CONTAINER* pContainer,
111 __in_z_opt LPCWSTR wzLayoutDirectory, 156 __in_z_opt LPCWSTR wzLayoutDirectory,
112 __in_z LPCWSTR wzUnverifiedContainerPath, 157 __in_z LPCWSTR wzUnverifiedContainerPath,
113 __in BOOL fMove 158 __in BOOL fMove,
159 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
160 __in LPPROGRESS_ROUTINE pfnProgress,
161 __in LPVOID pContext
114 ); 162 );
115HRESULT CacheLayoutPayload( 163HRESULT CacheLayoutPayload(
116 __in BURN_PAYLOAD* pPayload, 164 __in BURN_PAYLOAD* pPayload,
117 __in_z_opt LPCWSTR wzLayoutDirectory, 165 __in_z_opt LPCWSTR wzLayoutDirectory,
118 __in_z LPCWSTR wzUnverifiedPayloadPath, 166 __in_z LPCWSTR wzUnverifiedPayloadPath,
119 __in BOOL fMove 167 __in BOOL fMove,
168 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
169 __in LPPROGRESS_ROUTINE pfnProgress,
170 __in LPVOID pContext
120 ); 171 );
121HRESULT CacheCompletePayload( 172HRESULT CacheCompletePayload(
122 __in BOOL fPerMachine, 173 __in BOOL fPerMachine,
123 __in BURN_PAYLOAD* pPayload, 174 __in BURN_PAYLOAD* pPayload,
124 __in_z LPCWSTR wzCacheId, 175 __in_z LPCWSTR wzCacheId,
125 __in_z LPCWSTR wzUnverifiedPayloadPath, 176 __in_z LPCWSTR wzUnverifiedPayloadPath,
126 __in BOOL fMove 177 __in BOOL fMove,
178 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
179 __in LPPROGRESS_ROUTINE pfnProgress,
180 __in LPVOID pContext
127 ); 181 );
128HRESULT CacheVerifyContainer( 182HRESULT CacheVerifyContainer(
129 __in BURN_CONTAINER* pContainer, 183 __in BURN_CONTAINER* pContainer,
130 __in_z LPCWSTR wzCachedDirectory 184 __in_z LPCWSTR wzCachedDirectory,
185 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
186 __in LPPROGRESS_ROUTINE pfnProgress,
187 __in LPVOID pContext
131 ); 188 );
132HRESULT CacheVerifyPayload( 189HRESULT CacheVerifyPayload(
133 __in BURN_PAYLOAD* pPayload, 190 __in BURN_PAYLOAD* pPayload,
134 __in_z LPCWSTR wzCachedDirectory 191 __in_z LPCWSTR wzCachedDirectory,
192 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
193 __in LPPROGRESS_ROUTINE pfnProgress,
194 __in LPVOID pContext
135 ); 195 );
136HRESULT CacheRemoveWorkingFolder( 196HRESULT CacheRemoveWorkingFolder(
137 __in_z_opt LPCWSTR wzBundleId 197 __in_z_opt LPCWSTR wzBundleId
diff --git a/src/engine/elevation.cpp b/src/engine/elevation.cpp
index 502c5462..3a448923 100644
--- a/src/engine/elevation.cpp
+++ b/src/engine/elevation.cpp
@@ -35,11 +35,15 @@ typedef enum _BURN_ELEVATION_MESSAGE_TYPE
35 BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_PAUSE_AU_COMPLETE, 35 BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_PAUSE_AU_COMPLETE,
36 BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_SYSTEM_RESTORE_POINT_BEGIN, 36 BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_SYSTEM_RESTORE_POINT_BEGIN,
37 BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_SYSTEM_RESTORE_POINT_COMPLETE, 37 BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_SYSTEM_RESTORE_POINT_COMPLETE,
38 BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_BEGIN,
39 BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_COMPLETE,
40 BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_SUCCESS,
38 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS, 41 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS,
39 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR, 42 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR,
40 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_MESSAGE, 43 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_MESSAGE,
41 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_FILES_IN_USE, 44 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_FILES_IN_USE,
42 BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE_PROCESSID, 45 BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE_PROCESSID,
46 BURN_ELEVATION_MESSAGE_TYPE_PROGRESS_ROUTINE,
43} BURN_ELEVATION_MESSAGE_TYPE; 47} BURN_ELEVATION_MESSAGE_TYPE;
44 48
45 49
@@ -52,6 +56,13 @@ typedef struct _BURN_ELEVATION_APPLY_INITIALIZE_MESSAGE_CONTEXT
52 BOOL fSrpCompleteNeeded; 56 BOOL fSrpCompleteNeeded;
53} BURN_ELEVATION_APPLY_INITIALIZE_MESSAGE_CONTEXT; 57} BURN_ELEVATION_APPLY_INITIALIZE_MESSAGE_CONTEXT;
54 58
59typedef struct _BURN_ELEVATION_CACHE_MESSAGE_CONTEXT
60{
61 PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler;
62 LPPROGRESS_ROUTINE pfnProgress;
63 LPVOID pvContext;
64} BURN_ELEVATION_CACHE_MESSAGE_CONTEXT;
65
55typedef struct _BURN_ELEVATION_GENERIC_MESSAGE_CONTEXT 66typedef struct _BURN_ELEVATION_GENERIC_MESSAGE_CONTEXT
56{ 67{
57 PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler; 68 PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler;
@@ -99,6 +110,11 @@ static HRESULT ProcessApplyInitializeMessages(
99 __in_opt LPVOID pvContext, 110 __in_opt LPVOID pvContext,
100 __out DWORD* pdwResult 111 __out DWORD* pdwResult
101 ); 112 );
113static HRESULT ProcessBurnCacheMessages(
114 __in BURN_PIPE_MESSAGE* pMsg,
115 __in LPVOID pvContext,
116 __out DWORD* pdwResult
117 );
102static HRESULT ProcessGenericExecuteMessages( 118static HRESULT ProcessGenericExecuteMessages(
103 __in BURN_PIPE_MESSAGE* pMsg, 119 __in BURN_PIPE_MESSAGE* pMsg,
104 __in LPVOID pvContext, 120 __in LPVOID pvContext,
@@ -114,6 +130,12 @@ static HRESULT ProcessLaunchApprovedExeMessages(
114 __in_opt LPVOID pvContext, 130 __in_opt LPVOID pvContext,
115 __out DWORD* pdwResult 131 __out DWORD* pdwResult
116 ); 132 );
133static HRESULT ProcessProgressRoutineMessage(
134 __in BURN_PIPE_MESSAGE* pMsg,
135 __in LPPROGRESS_ROUTINE pfnProgress,
136 __in LPVOID pvContext,
137 __out DWORD* pdwResult
138 );
117static HRESULT ProcessElevatedChildMessage( 139static HRESULT ProcessElevatedChildMessage(
118 __in BURN_PIPE_MESSAGE* pMsg, 140 __in BURN_PIPE_MESSAGE* pMsg,
119 __in_opt LPVOID pvContext, 141 __in_opt LPVOID pvContext,
@@ -165,12 +187,14 @@ static HRESULT OnSaveState(
165 __in DWORD cbData 187 __in DWORD cbData
166 ); 188 );
167static HRESULT OnCacheCompletePayload( 189static HRESULT OnCacheCompletePayload(
190 __in HANDLE hPipe,
168 __in BURN_PACKAGES* pPackages, 191 __in BURN_PACKAGES* pPackages,
169 __in BURN_PAYLOADS* pPayloads, 192 __in BURN_PAYLOADS* pPayloads,
170 __in BYTE* pbData, 193 __in BYTE* pbData,
171 __in DWORD cbData 194 __in DWORD cbData
172 ); 195 );
173static HRESULT OnCacheVerifyPayload( 196static HRESULT OnCacheVerifyPayload(
197 __in HANDLE hPipe,
174 __in BURN_PACKAGES* pPackages, 198 __in BURN_PACKAGES* pPackages,
175 __in BURN_PAYLOADS* pPayloads, 199 __in BURN_PAYLOADS* pPayloads,
176 __in BYTE* pbData, 200 __in BYTE* pbData,
@@ -225,6 +249,21 @@ static HRESULT OnExecutePackageDependencyAction(
225 __in BYTE* pbData, 249 __in BYTE* pbData,
226 __in DWORD cbData 250 __in DWORD cbData
227 ); 251 );
252static HRESULT CALLBACK BurnCacheMessageHandler(
253 __in BURN_CACHE_MESSAGE* pMessage,
254 __in LPVOID pvContext
255 );
256static DWORD CALLBACK ElevatedProgressRoutine(
257 __in LARGE_INTEGER TotalFileSize,
258 __in LARGE_INTEGER TotalBytesTransferred,
259 __in LARGE_INTEGER StreamSize,
260 __in LARGE_INTEGER StreamBytesTransferred,
261 __in DWORD dwStreamNumber,
262 __in DWORD dwCallbackReason,
263 __in HANDLE hSourceFile,
264 __in HANDLE hDestinationFile,
265 __in_opt LPVOID lpData
266 );
228static int GenericExecuteMessageHandler( 267static int GenericExecuteMessageHandler(
229 __in GENERIC_EXECUTE_MESSAGE* pMessage, 268 __in GENERIC_EXECUTE_MESSAGE* pMessage,
230 __in LPVOID pvContext 269 __in LPVOID pvContext
@@ -582,13 +621,21 @@ extern "C" HRESULT ElevationCacheCompletePayload(
582 __in BURN_PACKAGE* pPackage, 621 __in BURN_PACKAGE* pPackage,
583 __in BURN_PAYLOAD* pPayload, 622 __in BURN_PAYLOAD* pPayload,
584 __in_z LPCWSTR wzUnverifiedPath, 623 __in_z LPCWSTR wzUnverifiedPath,
585 __in BOOL fMove 624 __in BOOL fMove,
625 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
626 __in LPPROGRESS_ROUTINE pfnProgress,
627 __in LPVOID pContext
586 ) 628 )
587{ 629{
588 HRESULT hr = S_OK; 630 HRESULT hr = S_OK;
589 BYTE* pbData = NULL; 631 BYTE* pbData = NULL;
590 SIZE_T cbData = 0; 632 SIZE_T cbData = 0;
591 DWORD dwResult = 0; 633 DWORD dwResult = 0;
634 BURN_ELEVATION_CACHE_MESSAGE_CONTEXT context = { };
635
636 context.pfnCacheMessageHandler = pfnCacheMessageHandler;
637 context.pfnProgress = pfnProgress;
638 context.pvContext = pContext;
592 639
593 // serialize message data 640 // serialize message data
594 hr = BuffWriteString(&pbData, &cbData, pPackage->sczId); 641 hr = BuffWriteString(&pbData, &cbData, pPackage->sczId);
@@ -604,7 +651,7 @@ extern "C" HRESULT ElevationCacheCompletePayload(
604 ExitOnFailure(hr, "Failed to write move flag to message buffer."); 651 ExitOnFailure(hr, "Failed to write move flag to message buffer.");
605 652
606 // send message 653 // send message
607 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_CACHE_COMPLETE_PAYLOAD, pbData, cbData, NULL, NULL, &dwResult); 654 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_CACHE_COMPLETE_PAYLOAD, pbData, cbData, ProcessBurnCacheMessages, &context, &dwResult);
608 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_CACHE_COMPLETE_PAYLOAD message to per-machine process."); 655 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_CACHE_COMPLETE_PAYLOAD message to per-machine process.");
609 656
610 hr = (HRESULT)dwResult; 657 hr = (HRESULT)dwResult;
@@ -618,13 +665,21 @@ LExit:
618extern "C" HRESULT ElevationCacheVerifyPayload( 665extern "C" HRESULT ElevationCacheVerifyPayload(
619 __in HANDLE hPipe, 666 __in HANDLE hPipe,
620 __in BURN_PACKAGE* pPackage, 667 __in BURN_PACKAGE* pPackage,
621 __in BURN_PAYLOAD* pPayload 668 __in BURN_PAYLOAD* pPayload,
669 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
670 __in LPPROGRESS_ROUTINE pfnProgress,
671 __in LPVOID pContext
622 ) 672 )
623{ 673{
624 HRESULT hr = S_OK; 674 HRESULT hr = S_OK;
625 BYTE* pbData = NULL; 675 BYTE* pbData = NULL;
626 SIZE_T cbData = 0; 676 SIZE_T cbData = 0;
627 DWORD dwResult = 0; 677 DWORD dwResult = 0;
678 BURN_ELEVATION_CACHE_MESSAGE_CONTEXT context = { };
679
680 context.pfnCacheMessageHandler = pfnCacheMessageHandler;
681 context.pfnProgress = pfnProgress;
682 context.pvContext = pContext;
628 683
629 // serialize message data 684 // serialize message data
630 hr = BuffWriteString(&pbData, &cbData, pPackage->sczId); 685 hr = BuffWriteString(&pbData, &cbData, pPackage->sczId);
@@ -634,7 +689,7 @@ extern "C" HRESULT ElevationCacheVerifyPayload(
634 ExitOnFailure(hr, "Failed to write payload id to message buffer."); 689 ExitOnFailure(hr, "Failed to write payload id to message buffer.");
635 690
636 // send message 691 // send message
637 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_CACHE_VERIFY_PAYLOAD, pbData, cbData, NULL, NULL, &dwResult); 692 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_CACHE_VERIFY_PAYLOAD, pbData, cbData, ProcessBurnCacheMessages, &context, &dwResult);
638 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_CACHE_VERIFY_PAYLOAD message to per-machine process."); 693 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_CACHE_VERIFY_PAYLOAD message to per-machine process.");
639 694
640 hr = (HRESULT)dwResult; 695 hr = (HRESULT)dwResult;
@@ -1377,6 +1432,69 @@ LExit:
1377 return hr; 1432 return hr;
1378} 1433}
1379 1434
1435static HRESULT ProcessBurnCacheMessages(
1436 __in BURN_PIPE_MESSAGE* pMsg,
1437 __in LPVOID pvContext,
1438 __out DWORD* pdwResult
1439 )
1440{
1441 HRESULT hr = S_OK;
1442 SIZE_T iData = 0;
1443 BURN_ELEVATION_CACHE_MESSAGE_CONTEXT* pContext = static_cast<BURN_ELEVATION_CACHE_MESSAGE_CONTEXT*>(pvContext);
1444 BURN_CACHE_MESSAGE message = { };
1445 BOOL fProgressRoutine = FALSE;
1446
1447 // Process the message.
1448 switch (pMsg->dwMessage)
1449 {
1450 case BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_BEGIN:
1451 // read message parameters
1452 hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, reinterpret_cast<DWORD*>(&message.begin.cacheStep));
1453 ExitOnFailure(hr, "Failed to read begin cache step.");
1454
1455 message.type = BURN_CACHE_MESSAGE_BEGIN;
1456 break;
1457
1458 case BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_COMPLETE:
1459 // read message parameters
1460 hr = BuffReadNumber((BYTE*)pMsg->pvData, pMsg->cbData, &iData, reinterpret_cast<DWORD*>(&message.complete.hrStatus));
1461 ExitOnFailure(hr, "Failed to read complete hresult.");
1462
1463 message.type = BURN_CACHE_MESSAGE_COMPLETE;
1464 break;
1465
1466 case BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_SUCCESS:
1467 // read message parameters
1468 hr = BuffReadNumber64((BYTE*)pMsg->pvData, pMsg->cbData, &iData, &message.success.qwFileSize);
1469 ExitOnFailure(hr, "Failed to read begin cache step.");
1470
1471 message.type = BURN_CACHE_MESSAGE_SUCCESS;
1472 break;
1473
1474 case BURN_ELEVATION_MESSAGE_TYPE_PROGRESS_ROUTINE:
1475 fProgressRoutine = TRUE;
1476 break;
1477
1478 default:
1479 hr = E_INVALIDARG;
1480 ExitOnRootFailure(hr, "Invalid burn cache message.");
1481 break;
1482 }
1483
1484 if (fProgressRoutine)
1485 {
1486 hr = ProcessProgressRoutineMessage(pMsg, pContext->pfnProgress, pContext->pvContext, pdwResult);
1487 }
1488 else
1489 {
1490 hr = pContext->pfnCacheMessageHandler(&message, pContext->pvContext);
1491 *pdwResult = static_cast<DWORD>(hr);
1492 }
1493
1494LExit:
1495 return hr;
1496}
1497
1380static HRESULT ProcessGenericExecuteMessages( 1498static HRESULT ProcessGenericExecuteMessages(
1381 __in BURN_PIPE_MESSAGE* pMsg, 1499 __in BURN_PIPE_MESSAGE* pMsg,
1382 __in LPVOID pvContext, 1500 __in LPVOID pvContext,
@@ -1596,11 +1714,41 @@ LExit:
1596 return hr; 1714 return hr;
1597} 1715}
1598 1716
1717static HRESULT ProcessProgressRoutineMessage(
1718 __in BURN_PIPE_MESSAGE* pMsg,
1719 __in LPPROGRESS_ROUTINE pfnProgress,
1720 __in LPVOID pvContext,
1721 __out DWORD* pdwResult
1722 )
1723{
1724 HRESULT hr = S_OK;
1725 SIZE_T iData = 0;
1726 LARGE_INTEGER liTotalFileSize = { };
1727 LARGE_INTEGER liTotalBytesTransferred = { };
1728 LARGE_INTEGER liStreamSize = { };
1729 LARGE_INTEGER liStreamBytesTransferred = { };
1730 DWORD dwStreamNumber = 0;
1731 DWORD dwCallbackReason = CALLBACK_CHUNK_FINISHED;
1732 HANDLE hSourceFile = INVALID_HANDLE_VALUE;
1733 HANDLE hDestinationFile = INVALID_HANDLE_VALUE;
1734
1735 hr = BuffReadNumber64((BYTE*)pMsg->pvData, pMsg->cbData, &iData, reinterpret_cast<DWORD64*>(&liTotalFileSize.QuadPart));
1736 ExitOnFailure(hr, "Failed to read total file size for progress.");
1737
1738 hr = BuffReadNumber64((BYTE*)pMsg->pvData, pMsg->cbData, &iData, reinterpret_cast<DWORD64*>(&liTotalBytesTransferred.QuadPart));
1739 ExitOnFailure(hr, "Failed to read total bytes transferred for progress.");
1740
1741 *pdwResult = pfnProgress(liTotalFileSize, liTotalBytesTransferred, liStreamSize, liStreamBytesTransferred, dwStreamNumber, dwCallbackReason, hSourceFile, hDestinationFile, pvContext);
1742
1743LExit:
1744 return hr;
1745}
1746
1599static HRESULT ProcessElevatedChildMessage( 1747static HRESULT ProcessElevatedChildMessage(
1600 __in BURN_PIPE_MESSAGE* pMsg, 1748 __in BURN_PIPE_MESSAGE* pMsg,
1601 __in_opt LPVOID pvContext, 1749 __in_opt LPVOID pvContext,
1602 __out DWORD* pdwResult 1750 __out DWORD* pdwResult
1603) 1751 )
1604{ 1752{
1605 HRESULT hr = S_OK; 1753 HRESULT hr = S_OK;
1606 BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext = static_cast<BURN_ELEVATION_CHILD_MESSAGE_CONTEXT*>(pvContext); 1754 BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext = static_cast<BURN_ELEVATION_CHILD_MESSAGE_CONTEXT*>(pvContext);
@@ -1705,11 +1853,11 @@ static HRESULT ProcessElevatedChildCacheMessage(
1705 switch (pMsg->dwMessage) 1853 switch (pMsg->dwMessage)
1706 { 1854 {
1707 case BURN_ELEVATION_MESSAGE_TYPE_CACHE_COMPLETE_PAYLOAD: 1855 case BURN_ELEVATION_MESSAGE_TYPE_CACHE_COMPLETE_PAYLOAD:
1708 hrResult = OnCacheCompletePayload(pContext->pPackages, pContext->pPayloads, (BYTE*)pMsg->pvData, pMsg->cbData); 1856 hrResult = OnCacheCompletePayload(pContext->hPipe, pContext->pPackages, pContext->pPayloads, (BYTE*)pMsg->pvData, pMsg->cbData);
1709 break; 1857 break;
1710 1858
1711 case BURN_ELEVATION_MESSAGE_TYPE_CACHE_VERIFY_PAYLOAD: 1859 case BURN_ELEVATION_MESSAGE_TYPE_CACHE_VERIFY_PAYLOAD:
1712 hrResult = OnCacheVerifyPayload(pContext->pPackages, pContext->pPayloads, (BYTE*)pMsg->pvData, pMsg->cbData); 1860 hrResult = OnCacheVerifyPayload(pContext->hPipe, pContext->pPackages, pContext->pPayloads, (BYTE*)pMsg->pvData, pMsg->cbData);
1713 break; 1861 break;
1714 1862
1715 case BURN_ELEVATION_MESSAGE_TYPE_CACHE_CLEANUP: 1863 case BURN_ELEVATION_MESSAGE_TYPE_CACHE_CLEANUP:
@@ -2002,6 +2150,7 @@ LExit:
2002} 2150}
2003 2151
2004static HRESULT OnCacheCompletePayload( 2152static HRESULT OnCacheCompletePayload(
2153 __in HANDLE hPipe,
2005 __in BURN_PACKAGES* pPackages, 2154 __in BURN_PACKAGES* pPackages,
2006 __in BURN_PAYLOADS* pPayloads, 2155 __in BURN_PAYLOADS* pPayloads,
2007 __in BYTE* pbData, 2156 __in BYTE* pbData,
@@ -2043,7 +2192,7 @@ static HRESULT OnCacheCompletePayload(
2043 2192
2044 if (pPackage && pPayload) // complete payload. 2193 if (pPackage && pPayload) // complete payload.
2045 { 2194 {
2046 hr = CacheCompletePayload(pPackage->fPerMachine, pPayload, pPackage->sczCacheId, sczUnverifiedPath, fMove); 2195 hr = CacheCompletePayload(pPackage->fPerMachine, pPayload, pPackage->sczCacheId, sczUnverifiedPath, fMove, BurnCacheMessageHandler, ElevatedProgressRoutine, hPipe);
2047 ExitOnFailure(hr, "Failed to cache payload: %ls", pPayload->sczKey); 2196 ExitOnFailure(hr, "Failed to cache payload: %ls", pPayload->sczKey);
2048 } 2197 }
2049 else 2198 else
@@ -2060,6 +2209,7 @@ LExit:
2060} 2209}
2061 2210
2062static HRESULT OnCacheVerifyPayload( 2211static HRESULT OnCacheVerifyPayload(
2212 __in HANDLE hPipe,
2063 __in BURN_PACKAGES* pPackages, 2213 __in BURN_PACKAGES* pPackages,
2064 __in BURN_PAYLOADS* pPayloads, 2214 __in BURN_PAYLOADS* pPayloads,
2065 __in BYTE* pbData, 2215 __in BYTE* pbData,
@@ -2097,7 +2247,7 @@ static HRESULT OnCacheVerifyPayload(
2097 hr = CacheGetCompletedPath(TRUE, pPackage->sczCacheId, &sczCacheDirectory); 2247 hr = CacheGetCompletedPath(TRUE, pPackage->sczCacheId, &sczCacheDirectory);
2098 ExitOnFailure(hr, "Failed to get cached path for package with cache id: %ls", pPackage->sczCacheId); 2248 ExitOnFailure(hr, "Failed to get cached path for package with cache id: %ls", pPackage->sczCacheId);
2099 2249
2100 hr = CacheVerifyPayload(pPayload, sczCacheDirectory); 2250 hr = CacheVerifyPayload(pPayload, sczCacheDirectory, BurnCacheMessageHandler, ElevatedProgressRoutine, hPipe);
2101 } 2251 }
2102 else 2252 else
2103 { 2253 {
@@ -2573,6 +2723,91 @@ LExit:
2573 return hr; 2723 return hr;
2574} 2724}
2575 2725
2726static HRESULT CALLBACK BurnCacheMessageHandler(
2727 __in BURN_CACHE_MESSAGE* pMessage,
2728 __in LPVOID pvContext
2729 )
2730{
2731 HRESULT hr = S_OK;
2732 DWORD dwResult = 0;
2733 HANDLE hPipe = (HANDLE)pvContext;
2734 BYTE* pbData = NULL;
2735 SIZE_T cbData = 0;
2736 DWORD dwMessage = 0;
2737
2738 switch (pMessage->type)
2739 {
2740 case BURN_CACHE_MESSAGE_BEGIN:
2741 // serialize message data
2742 hr = BuffWriteNumber(&pbData, &cbData, pMessage->begin.cacheStep);
2743 ExitOnFailure(hr, "Failed to write progress percentage to message buffer.");
2744
2745 dwMessage = BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_BEGIN;
2746 break;
2747
2748 case BURN_CACHE_MESSAGE_COMPLETE:
2749 // serialize message data
2750 hr = BuffWriteNumber(&pbData, &cbData, pMessage->complete.hrStatus);
2751 ExitOnFailure(hr, "Failed to write error code to message buffer.");
2752
2753 dwMessage = BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_COMPLETE;
2754 break;
2755
2756 case BURN_CACHE_MESSAGE_SUCCESS:
2757 hr = BuffWriteNumber64(&pbData, &cbData, pMessage->success.qwFileSize);
2758 ExitOnFailure(hr, "Failed to count of files in use to message buffer.");
2759
2760 dwMessage = BURN_ELEVATION_MESSAGE_TYPE_BURN_CACHE_SUCCESS;
2761 break;
2762 }
2763
2764 // send message
2765 hr = PipeSendMessage(hPipe, dwMessage, pbData, cbData, NULL, NULL, &dwResult);
2766 ExitOnFailure(hr, "Failed to send burn cache message to per-user process.");
2767
2768 hr = dwResult;
2769
2770LExit:
2771 ReleaseBuffer(pbData);
2772
2773 return hr;
2774}
2775
2776static DWORD CALLBACK ElevatedProgressRoutine(
2777 __in LARGE_INTEGER TotalFileSize,
2778 __in LARGE_INTEGER TotalBytesTransferred,
2779 __in LARGE_INTEGER /*StreamSize*/,
2780 __in LARGE_INTEGER /*StreamBytesTransferred*/,
2781 __in DWORD /*dwStreamNumber*/,
2782 __in DWORD /*dwCallbackReason*/,
2783 __in HANDLE /*hSourceFile*/,
2784 __in HANDLE /*hDestinationFile*/,
2785 __in_opt LPVOID lpData
2786 )
2787{
2788 HRESULT hr = S_OK;
2789 DWORD dwResult = 0;
2790 HANDLE hPipe = (HANDLE)lpData;
2791 BYTE* pbData = NULL;
2792 SIZE_T cbData = 0;
2793 DWORD dwMessage = BURN_ELEVATION_MESSAGE_TYPE_PROGRESS_ROUTINE;
2794
2795 hr = BuffWriteNumber64(&pbData, &cbData, TotalFileSize.QuadPart);
2796 ExitOnFailure(hr, "Failed to write total file size progress to message buffer.");
2797
2798 hr = BuffWriteNumber64(&pbData, &cbData, TotalBytesTransferred.QuadPart);
2799 ExitOnFailure(hr, "Failed to write total bytes transferred progress to message buffer.");
2800
2801 // send message
2802 hr = PipeSendMessage(hPipe, dwMessage, pbData, cbData, NULL, NULL, &dwResult);
2803 ExitOnFailure(hr, "Failed to send progress routine message to per-user process.");
2804
2805LExit:
2806 ReleaseBuffer(pbData);
2807
2808 return dwResult;
2809}
2810
2576static int GenericExecuteMessageHandler( 2811static int GenericExecuteMessageHandler(
2577 __in GENERIC_EXECUTE_MESSAGE* pMessage, 2812 __in GENERIC_EXECUTE_MESSAGE* pMessage,
2578 __in LPVOID pvContext 2813 __in LPVOID pvContext
diff --git a/src/engine/elevation.h b/src/engine/elevation.h
index fd7ee110..9244f36c 100644
--- a/src/engine/elevation.h
+++ b/src/engine/elevation.h
@@ -55,12 +55,18 @@ HRESULT ElevationCacheCompletePayload(
55 __in BURN_PACKAGE* pPackage, 55 __in BURN_PACKAGE* pPackage,
56 __in BURN_PAYLOAD* pPayload, 56 __in BURN_PAYLOAD* pPayload,
57 __in_z LPCWSTR wzUnverifiedPath, 57 __in_z LPCWSTR wzUnverifiedPath,
58 __in BOOL fMove 58 __in BOOL fMove,
59 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
60 __in LPPROGRESS_ROUTINE pfnProgress,
61 __in LPVOID pContext
59 ); 62 );
60HRESULT ElevationCacheVerifyPayload( 63HRESULT ElevationCacheVerifyPayload(
61 __in HANDLE hPipe, 64 __in HANDLE hPipe,
62 __in BURN_PACKAGE* pPackage, 65 __in BURN_PACKAGE* pPackage,
63 __in BURN_PAYLOAD* pPayload 66 __in BURN_PAYLOAD* pPayload,
67 __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
68 __in LPPROGRESS_ROUTINE pfnProgress,
69 __in LPVOID pContext
64 ); 70 );
65HRESULT ElevationCacheCleanup( 71HRESULT ElevationCacheCleanup(
66 __in HANDLE hPipe 72 __in HANDLE hPipe
diff --git a/src/engine/plan.cpp b/src/engine/plan.cpp
index bf929835..f662c445 100644
--- a/src/engine/plan.cpp
+++ b/src/engine/plan.cpp
@@ -431,8 +431,8 @@ extern "C" HRESULT PlanLayoutBundle(
431 pCacheAction->bundleLayout.qwBundleSize = qwBundleSize; 431 pCacheAction->bundleLayout.qwBundleSize = qwBundleSize;
432 pCacheAction->bundleLayout.pPayloadGroup = pLayoutPayloads; 432 pCacheAction->bundleLayout.pPayloadGroup = pLayoutPayloads;
433 433
434 // Acquire + Verify 434 // Acquire + Verify + Finalize
435 pPlan->qwCacheSizeTotal += 2 * qwBundleSize; 435 pPlan->qwCacheSizeTotal += 3 * qwBundleSize;
436 436
437 ++pPlan->cOverallProgressTicksTotal; 437 ++pPlan->cOverallProgressTicksTotal;
438 438
@@ -1006,8 +1006,8 @@ extern "C" HRESULT PlanLayoutContainer(
1006 pCacheAction->type = BURN_CACHE_ACTION_TYPE_CONTAINER; 1006 pCacheAction->type = BURN_CACHE_ACTION_TYPE_CONTAINER;
1007 pCacheAction->container.pContainer = pContainer; 1007 pCacheAction->container.pContainer = pContainer;
1008 1008
1009 // Acquire + Verify 1009 // Acquire + Verify + Finalize
1010 pPlan->qwCacheSizeTotal += 2 * pContainer->qwFileSize; 1010 pPlan->qwCacheSizeTotal += 3 * pContainer->qwFileSize;
1011 } 1011 }
1012 } 1012 }
1013 else 1013 else
@@ -2249,8 +2249,14 @@ static HRESULT ProcessPayloadGroup(
2249 2249
2250 if (!pPlan->sczLayoutDirectory || !pPayload->pContainer) 2250 if (!pPlan->sczLayoutDirectory || !pPayload->pContainer)
2251 { 2251 {
2252 // Acquire + Verify 2252 // Acquire + Verify + Finalize
2253 pPlan->qwCacheSizeTotal += 2 * pPayload->qwFileSize; 2253 pPlan->qwCacheSizeTotal += 3 * pPayload->qwFileSize;
2254
2255 if (!pPlan->sczLayoutDirectory)
2256 {
2257 // Staging
2258 pPlan->qwCacheSizeTotal += pPayload->qwFileSize;
2259 }
2254 } 2260 }
2255 2261
2256 if (!pPlan->sczLayoutDirectory && pPayload->pContainer && 1 == pPayload->cRemainingInstances) 2262 if (!pPlan->sczLayoutDirectory && pPayload->pContainer && 1 == pPayload->cRemainingInstances)
diff --git a/src/engine/userexperience.cpp b/src/engine/userexperience.cpp
index 279a00b5..8c6f29f3 100644
--- a/src/engine/userexperience.cpp
+++ b/src/engine/userexperience.cpp
@@ -912,7 +912,8 @@ EXTERN_C BAAPI UserExperienceOnCacheVerifyProgress(
912 __in_z_opt LPCWSTR wzPayloadId, 912 __in_z_opt LPCWSTR wzPayloadId,
913 __in DWORD64 dw64Progress, 913 __in DWORD64 dw64Progress,
914 __in DWORD64 dw64Total, 914 __in DWORD64 dw64Total,
915 __in DWORD dwOverallPercentage 915 __in DWORD dwOverallPercentage,
916 __in BOOTSTRAPPER_CACHE_VERIFY_STEP verifyStep
916 ) 917 )
917{ 918{
918 HRESULT hr = S_OK; 919 HRESULT hr = S_OK;
@@ -925,6 +926,7 @@ EXTERN_C BAAPI UserExperienceOnCacheVerifyProgress(
925 args.dw64Progress = dw64Progress; 926 args.dw64Progress = dw64Progress;
926 args.dw64Total = dw64Total; 927 args.dw64Total = dw64Total;
927 args.dwOverallPercentage = dwOverallPercentage; 928 args.dwOverallPercentage = dwOverallPercentage;
929 args.verifyStep = verifyStep;
928 930
929 results.cbSize = sizeof(results); 931 results.cbSize = sizeof(results);
930 932
diff --git a/src/engine/userexperience.h b/src/engine/userexperience.h
index a848e60d..58e0431e 100644
--- a/src/engine/userexperience.h
+++ b/src/engine/userexperience.h
@@ -233,7 +233,8 @@ BAAPI UserExperienceOnCacheVerifyProgress(
233 __in_z_opt LPCWSTR wzPayloadId, 233 __in_z_opt LPCWSTR wzPayloadId,
234 __in DWORD64 dw64Progress, 234 __in DWORD64 dw64Progress,
235 __in DWORD64 dw64Total, 235 __in DWORD64 dw64Total,
236 __in DWORD dwOverallPercentage 236 __in DWORD dwOverallPercentage,
237 __in BOOTSTRAPPER_CACHE_VERIFY_STEP verifyStep
237 ); 238 );
238BAAPI UserExperienceOnCommitMsiTransactionBegin( 239BAAPI UserExperienceOnCommitMsiTransactionBegin(
239 __in BURN_USER_EXPERIENCE* pUserExperience, 240 __in BURN_USER_EXPERIENCE* pUserExperience,
diff --git a/src/test/BurnUnitTest/CacheTest.cpp b/src/test/BurnUnitTest/CacheTest.cpp
index fc0b4531..d0cc237f 100644
--- a/src/test/BurnUnitTest/CacheTest.cpp
+++ b/src/test/BurnUnitTest/CacheTest.cpp
@@ -2,6 +2,26 @@
2 2
3#include "precomp.h" 3#include "precomp.h"
4 4
5static HRESULT CALLBACK CacheTestEventRoutine(
6 __in BURN_CACHE_MESSAGE* pMessage,
7 __in LPVOID pvContext
8 );
9
10static DWORD CALLBACK CacheTestProgressRoutine(
11 __in LARGE_INTEGER TotalFileSize,
12 __in LARGE_INTEGER TotalBytesTransferred,
13 __in LARGE_INTEGER StreamSize,
14 __in LARGE_INTEGER StreamBytesTransferred,
15 __in DWORD dwStreamNumber,
16 __in DWORD dwCallbackReason,
17 __in HANDLE hSourceFile,
18 __in HANDLE hDestinationFile,
19 __in_opt LPVOID lpData
20 );
21
22typedef struct _CACHE_TEST_CONTEXT
23{
24} CACHE_TEST_CONTEXT;
5 25
6namespace Microsoft 26namespace Microsoft
7{ 27{
@@ -33,6 +53,7 @@ namespace Bootstrapper
33 LPWSTR sczPayloadPath = NULL; 53 LPWSTR sczPayloadPath = NULL;
34 BYTE* pb = NULL; 54 BYTE* pb = NULL;
35 DWORD cb = NULL; 55 DWORD cb = NULL;
56 CACHE_TEST_CONTEXT context = { };
36 57
37 try 58 try
38 { 59 {
@@ -51,7 +72,7 @@ namespace Bootstrapper
51 payload.pbHash = pb; 72 payload.pbHash = pb;
52 payload.cbHash = cb; 73 payload.cbHash = cb;
53 74
54 hr = CacheCompletePayload(package.fPerMachine, &payload, package.sczCacheId, sczPayloadPath, FALSE); 75 hr = CacheCompletePayload(package.fPerMachine, &payload, package.sczCacheId, sczPayloadPath, FALSE, CacheTestEventRoutine, CacheTestProgressRoutine, &context);
55 Assert::Equal(S_OK, hr); 76 Assert::Equal(S_OK, hr);
56 } 77 }
57 finally 78 finally
@@ -73,3 +94,26 @@ namespace Bootstrapper
73} 94}
74} 95}
75} 96}
97
98static HRESULT CALLBACK CacheTestEventRoutine(
99 __in BURN_CACHE_MESSAGE* /*pMessage*/,
100 __in LPVOID /*pvContext*/
101 )
102{
103 return S_OK;
104}
105
106static DWORD CALLBACK CacheTestProgressRoutine(
107 __in LARGE_INTEGER /*TotalFileSize*/,
108 __in LARGE_INTEGER /*TotalBytesTransferred*/,
109 __in LARGE_INTEGER /*StreamSize*/,
110 __in LARGE_INTEGER /*StreamBytesTransferred*/,
111 __in DWORD /*dwStreamNumber*/,
112 __in DWORD /*dwCallbackReason*/,
113 __in HANDLE /*hSourceFile*/,
114 __in HANDLE /*hDestinationFile*/,
115 __in_opt LPVOID /*lpData*/
116 )
117{
118 return PROGRESS_QUIET;
119}
diff --git a/src/test/BurnUnitTest/PlanTest.cpp b/src/test/BurnUnitTest/PlanTest.cpp
index c073696b..a7c1d83c 100644
--- a/src/test/BurnUnitTest/PlanTest.cpp
+++ b/src/test/BurnUnitTest/PlanTest.cpp
@@ -71,7 +71,7 @@ namespace Bootstrapper
71 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); 71 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
72 72
73 Assert::Equal(107082ull, pPlan->qwEstimatedSize); 73 Assert::Equal(107082ull, pPlan->qwEstimatedSize);
74 Assert::Equal(303687ull, pPlan->qwCacheSizeTotal); 74 Assert::Equal(506145ull, pPlan->qwCacheSizeTotal);
75 75
76 fRollback = FALSE; 76 fRollback = FALSE;
77 dwIndex = 0; 77 dwIndex = 0;
@@ -308,7 +308,7 @@ namespace Bootstrapper
308 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); 308 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
309 309
310 Assert::Equal(35694ull, pPlan->qwEstimatedSize); 310 Assert::Equal(35694ull, pPlan->qwEstimatedSize);
311 Assert::Equal(101229ull, pPlan->qwCacheSizeTotal); 311 Assert::Equal(168715ull, pPlan->qwCacheSizeTotal);
312 312
313 fRollback = FALSE; 313 fRollback = FALSE;
314 dwIndex = 0; 314 dwIndex = 0;
@@ -388,7 +388,7 @@ namespace Bootstrapper
388 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); 388 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
389 389
390 Assert::Equal(33743ull, pPlan->qwEstimatedSize); 390 Assert::Equal(33743ull, pPlan->qwEstimatedSize);
391 Assert::Equal(101229ull, pPlan->qwCacheSizeTotal); 391 Assert::Equal(168715ull, pPlan->qwCacheSizeTotal);
392 392
393 fRollback = FALSE; 393 fRollback = FALSE;
394 dwIndex = 0; 394 dwIndex = 0;
@@ -458,7 +458,7 @@ namespace Bootstrapper
458 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); 458 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
459 459
460 Assert::Equal(35694ull, pPlan->qwEstimatedSize); 460 Assert::Equal(35694ull, pPlan->qwEstimatedSize);
461 Assert::Equal(101229ull, pPlan->qwCacheSizeTotal); 461 Assert::Equal(168715ull, pPlan->qwCacheSizeTotal);
462 462
463 fRollback = FALSE; 463 fRollback = FALSE;
464 dwIndex = 0; 464 dwIndex = 0;
@@ -739,7 +739,7 @@ namespace Bootstrapper
739 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); 739 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
740 740
741 Assert::Equal(3055111ull, pPlan->qwEstimatedSize); 741 Assert::Equal(3055111ull, pPlan->qwEstimatedSize);
742 Assert::Equal(106496ull, pPlan->qwCacheSizeTotal); 742 Assert::Equal(212992ull, pPlan->qwCacheSizeTotal);
743 743
744 fRollback = FALSE; 744 fRollback = FALSE;
745 dwIndex = 0; 745 dwIndex = 0;