@joebigelow / wix / commits / d4c76dd1

Send more progress during cache verification. Add verifyStep to OnCacheVerifyProgress. Send OnContainerOrPayloadVerify events only if file existed in cache.

Send more progress during cache verification. Add verifyStep to OnCacheVerifyProgress. Send OnContainerOrPayloadVerify events only if file existed in cache.

Sean Hall committed Apr 17, 2021 at 20:58 UTC d4c76dd11f5a096b4fd3ee9c5efc1f44559ac3da
11 files changed +712 -148
src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
+8
@@ -64,6 +64,13 @@ enum BOOTSTRAPPER_CACHE_OPERATION
64 BOOTSTRAPPER_CACHE_OPERATION_EXTRACT,
65 };
66
67 +enum 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 +
74 enum BOOTSTRAPPER_APPLY_RESTART
75 {
76 BOOTSTRAPPER_APPLY_RESTART_NONE,
@@ -553,6 +560,7 @@ struct BA_ONCACHEVERIFYPROGRESS_ARGS
560 DWORD64 dw64Progress;
561 DWORD64 dw64Total;
562 DWORD dwOverallPercentage;
563 + BOOTSTRAPPER_CACHE_VERIFY_STEP verifyStep;
564 };
565
566 struct BA_ONCACHEVERIFYPROGRESS_RESULTS
src/engine/apply.cpp
+117 -54
@@ -14,9 +14,12 @@ const DWORD BURN_CACHE_MAX_RECOMMENDED_VERIFY_TRYAGAIN_ATTEMPTS = 2;
14 enum BURN_CACHE_PROGRESS_TYPE
15 {
16 BURN_CACHE_PROGRESS_TYPE_ACQUIRE,
17 - BURN_CACHE_PROGRESS_TYPE_VERIFY,
17 BURN_CACHE_PROGRESS_TYPE_CONTAINER_OR_PAYLOAD_VERIFY,
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,
23 };
24
25 // structs
@@ -151,6 +154,10 @@ static HRESULT DownloadPayload(
154 __in BURN_CACHE_PROGRESS_CONTEXT* pProgress,
155 __in_z LPCWSTR wzDestinationPath
156 );
157 +static HRESULT CALLBACK CacheMessageHandler(
158 + __in BURN_CACHE_MESSAGE* pMessage,
159 + __in LPVOID pvContext
160 + );
161 static HRESULT CompleteCacheProgress(
162 __in BURN_CACHE_PROGRESS_CONTEXT* pContext,
163 __in DWORD64 qwFileSize
@@ -993,7 +1000,8 @@ static HRESULT ApplyLayoutContainer(
1000 }
1001
1002 ++cTryAgainAttempts;
996 - pContext->qwSuccessfulCacheProgress -= pContainer->qwFileSize;
1003 + pContext->qwSuccessfulCacheProgress -= pContainer->qwCommittedCacheProgress;
1004 + pContainer->qwCommittedCacheProgress = 0;
1005 ReleaseNullStr(pContext->sczLastUsedFolderCandidate);
1006 LogErrorId(hr, MSG_APPLY_RETRYING_CONTAINER, pContainer->sczId, NULL, NULL);
1007 }
@@ -1075,49 +1083,25 @@ static HRESULT ApplyCacheVerifyContainerOrPayload(
1083
1084 HRESULT hr = S_OK;
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;
1086
1087 progress.pCacheContext = pContext;
1088 progress.pContainer = pContainer;
1089 progress.pPackage = pPackage;
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.");
1091
1092 if (pContainer)
1093 {
1093 - hr = CacheVerifyContainer(pContainer, pContext->wzLayoutDirectory);
1094 + hr = CacheVerifyContainer(pContainer, pContext->wzLayoutDirectory, CacheMessageHandler, CacheProgressRoutine, &progress);
1095 }
1096 else if (!pContext->wzLayoutDirectory && INVALID_HANDLE_VALUE != pContext->hPipe)
1097 {
1097 - hr = ElevationCacheVerifyPayload(pContext->hPipe, pPackage, pPayloadGroupItem->pPayload);
1098 + hr = ElevationCacheVerifyPayload(pContext->hPipe, pPackage, pPayloadGroupItem->pPayload, CacheMessageHandler, CacheProgressRoutine, &progress);
1099 }
1100 else
1101 {
1101 - hr = CacheVerifyPayload(pPayloadGroupItem->pPayload, pContext->wzLayoutDirectory ? pContext->wzLayoutDirectory : pPackage->sczCacheFolder);
1102 - }
1103 -
1104 - // This was best effort to avoid acquiring the container or payload.
1105 - if (FAILED(hr))
1106 - {
1107 - ExitFunction();
1102 + hr = CacheVerifyPayload(pPayloadGroupItem->pPayload, pContext->wzLayoutDirectory ? pContext->wzLayoutDirectory : pPackage->sczCacheFolder, CacheMessageHandler, CacheProgressRoutine, &progress);
1103 }
1104
1110 - pContext->qwSuccessfulCacheProgress += qwFileSize;
1111 - if (pPayloadGroupItem)
1112 - {
1113 - pPayloadGroupItem->qwCommittedCacheProgress += qwFileSize;
1114 - }
1115 -
1116 - hr = CompleteCacheProgress(&progress, qwFileSize);
1117 -
1118 -LExit:
1119 - UserExperienceOnCacheContainerOrPayloadVerifyComplete(pContext->pUX, wzPackageOrContainerId, wzPayloadId, hr);
1120 -
1105 return hr;
1106 }
1107
@@ -1252,8 +1236,6 @@ static HRESULT LayoutBundle(
1236 ExitOnRootFailure(hr, "BA aborted cache payload verify begin.");
1237 }
1238
1255 - pContext->qwSuccessfulCacheProgress += qwBundleSize;
1256 -
1239 progress.type = BURN_CACHE_PROGRESS_TYPE_CONTAINER_OR_PAYLOAD_VERIFY;
1240 hr = CompleteCacheProgress(&progress, qwBundleSize);
1241
@@ -1306,8 +1288,6 @@ static HRESULT LayoutBundle(
1288 break;
1289 }
1290
1309 - progress.type = BURN_CACHE_PROGRESS_TYPE_VERIFY;
1310 -
1291 do
1292 {
1293 fCanceledBegin = FALSE;
@@ -1320,12 +1300,7 @@ static HRESULT LayoutBundle(
1300 }
1301 else
1302 {
1323 - hr = CacheLayoutBundle(wzExecutableName, pContext->wzLayoutDirectory, wzUnverifiedPath);
1324 -
1325 - if (SUCCEEDED(hr))
1326 - {
1327 - hr = CompleteCacheProgress(&progress, qwBundleSize);
1328 - }
1303 + hr = CacheLayoutBundle(wzExecutableName, pContext->wzLayoutDirectory, wzUnverifiedPath, qwBundleSize, CacheMessageHandler, CacheProgressRoutine, &progress);
1304 }
1305
1306 BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION action = BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION_NONE;
@@ -1346,7 +1321,7 @@ static HRESULT LayoutBundle(
1321
1322 if (fRetry)
1323 {
1349 - pContext->qwSuccessfulCacheProgress -= qwBundleSize;
1324 + pContext->qwSuccessfulCacheProgress -= qwBundleSize; // Acquire
1325 }
1326 } while (fRetry);
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(
1534
1535 *pfRetry = FALSE;
1536 progress.pCacheContext = pContext;
1562 - progress.type = BURN_CACHE_PROGRESS_TYPE_VERIFY;
1537 progress.pContainer = pContainer;
1538 progress.pPackage = pPackage;
1539 progress.pPayloadGroupItem = pPayloadGroupItem;
@@ -1580,28 +1554,23 @@ static HRESULT LayoutOrCacheContainerOrPayload(
1554 {
1555 if (pContainer)
1556 {
1583 - hr = CacheLayoutContainer(pContainer, pContext->wzLayoutDirectory, wzUnverifiedPath, fMove);
1557 + hr = CacheLayoutContainer(pContainer, pContext->wzLayoutDirectory, wzUnverifiedPath, fMove, CacheMessageHandler, CacheProgressRoutine, &progress);
1558 }
1559 else
1560 {
1587 - hr = CacheLayoutPayload(pPayload, pContext->wzLayoutDirectory, wzUnverifiedPath, fMove);
1561 + hr = CacheLayoutPayload(pPayload, pContext->wzLayoutDirectory, wzUnverifiedPath, fMove, CacheMessageHandler, CacheProgressRoutine, &progress);
1562 }
1563 }
1564 else if (INVALID_HANDLE_VALUE != pContext->hPipe) // pass the decision off to the elevated process.
1565 {
1592 - hr = ElevationCacheCompletePayload(pContext->hPipe, pPackage, pPayload, wzUnverifiedPath, fMove);
1566 + hr = ElevationCacheCompletePayload(pContext->hPipe, pPackage, pPayload, wzUnverifiedPath, fMove, CacheMessageHandler, CacheProgressRoutine, &progress);
1567 }
1568 else // complete the payload.
1569 {
1596 - hr = CacheCompletePayload(pPackage->fPerMachine, pPayload, pPackage->sczCacheId, wzUnverifiedPath, fMove);
1570 + hr = CacheCompletePayload(pPackage->fPerMachine, pPayload, pPackage->sczCacheId, wzUnverifiedPath, fMove, CacheMessageHandler, CacheProgressRoutine, &progress);
1571 }
1572 }
1573
1600 - if (SUCCEEDED(hr))
1601 - {
1602 - hr = CompleteCacheProgress(&progress, pContainer ? pContainer->qwFileSize : pPayload->qwFileSize);
1603 - }
1604 -
1574 if (SUCCEEDED(hr) && fCanAffectRegistration)
1575 {
1576 pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
@@ -1820,6 +1789,54 @@ LExit:
1789 return hr;
1790 }
1791
1792 +static 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 +
1840 static HRESULT CompleteCacheProgress(
1841 __in BURN_CACHE_PROGRESS_CONTEXT* pContext,
1842 __in DWORD64 qwFileSize
@@ -1829,9 +1846,29 @@ static HRESULT CompleteCacheProgress(
1846 LARGE_INTEGER liContainerOrPayloadSize = { };
1847 LARGE_INTEGER liZero = { };
1848 DWORD dwResult = 0;
1849 + DWORD64 qwCommitSize = 0;
1850
1851 liContainerOrPayloadSize.QuadPart = qwFileSize;
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 +
1872 dwResult = CacheProgressRoutine(liContainerOrPayloadSize, liContainerOrPayloadSize, liZero, liZero, 0, 0, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, pContext);
1873
1874 if (PROGRESS_CONTINUE == dwResult)
@@ -1851,7 +1888,7 @@ static HRESULT CompleteCacheProgress(
1888 pContext->pPayloadGroupItem->qwCommittedCacheProgress += qwFileSize;
1889 }
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)
1892 {
1893 // We successfully copied from a source location, set that as the last used source.
1894 CacheSetLastUsedSource(pContext->pCacheContext->pVariables, pContext->pCacheContext->sczLastUsedFolderCandidate, pContext->pContainer ? pContext->pContainer->sczFilePath : pContext->pPayloadGroupItem->pPayload->sczFilePath);
@@ -1867,6 +1904,20 @@ static HRESULT CompleteCacheProgress(
1904 {
1905 hr = pContext->hrError;
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 + }
1921 }
1922
1923 return hr;
@@ -1903,9 +1954,21 @@ static DWORD CALLBACK CacheProgressRoutine(
1954 hr = UserExperienceOnCacheAcquireProgress(pProgress->pCacheContext->pUX, wzPackageOrContainerId, wzPayloadId, TotalBytesTransferred.QuadPart, TotalFileSize.QuadPart, dwOverallPercentage);
1955 ExitOnRootFailure(hr, "BA aborted acquire of %hs: %ls", pProgress->pContainer ? "container" : "payload", pProgress->pContainer ? wzPackageOrContainerId : wzPayloadId);
1956 break;
1906 - case BURN_CACHE_PROGRESS_TYPE_VERIFY:
1907 - hr = UserExperienceOnCacheVerifyProgress(pProgress->pCacheContext->pUX, wzPackageOrContainerId, wzPayloadId, TotalBytesTransferred.QuadPart, TotalFileSize.QuadPart, dwOverallPercentage);
1908 - ExitOnRootFailure(hr, "BA aborted verify of %hs: %ls", pProgress->pContainer ? "container" : "payload", pProgress->pContainer ? wzPackageOrContainerId : wzPayloadId);
1957 + case BURN_CACHE_PROGRESS_TYPE_PAYLOAD_VERIFY:
1958 + hr = UserExperienceOnCacheVerifyProgress(pProgress->pCacheContext->pUX, wzPackageOrContainerId, wzPayloadId, TotalBytesTransferred.QuadPart, TotalFileSize.QuadPart, dwOverallPercentage, BOOTSTRAPPER_CACHE_VERIFY_STEP_HASH);
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);
1972 break;
1973 case BURN_CACHE_PROGRESS_TYPE_CONTAINER_OR_PAYLOAD_VERIFY:
1974 hr = UserExperienceOnCacheContainerOrPayloadVerifyProgress(pProgress->pCacheContext->pUX, wzPackageOrContainerId, wzPayloadId, TotalBytesTransferred.QuadPart, TotalFileSize.QuadPart, dwOverallPercentage);
src/engine/cache.cpp
+201 -62
@@ -44,28 +44,47 @@ static HRESULT VerifyThenTransferContainer(
44 __in BURN_CONTAINER* pContainer,
45 __in_z LPCWSTR wzCachedPath,
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
51 );
52 static HRESULT VerifyThenTransferPayload(
53 __in BURN_PAYLOAD* pPayload,
54 __in_z LPCWSTR wzCachedPath,
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
60 );
55 -static HRESULT TransferWorkingPathToUnverifiedPath(
56 - __in_z LPCWSTR wzWorkingPath,
57 - __in_z LPCWSTR wzUnverifiedPayloadPath,
58 - __in BOOL fMove
61 +static HRESULT CacheTransferFileWithRetry(
62 + __in_z LPCWSTR wzSourcePath,
63 + __in_z LPCWSTR wzDestinationPath,
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
70 );
71 static HRESULT VerifyFileAgainstContainer(
72 __in BURN_CONTAINER* pContainer,
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
79 );
80 static HRESULT VerifyFileAgainstPayload(
81 __in BURN_PAYLOAD* pPayload,
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
88 );
89 static HRESULT ResetPathPermissions(
90 __in BOOL fPerMachine,
@@ -99,7 +118,26 @@ static HRESULT VerifyHash(
118 __in DWORD cbHash,
119 __in DWORD64 qwFileSize,
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 + );
127 +static HRESULT SendCacheBeginMessage(
128 + __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
129 + __in LPVOID pContext,
130 + __in BURN_CACHE_STEP cacheStep
131 + );
132 +static HRESULT SendCacheSuccessMessage(
133 + __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
134 + __in LPVOID pContext,
135 + __in DWORD64 qwFileSize
136 + );
137 +static HRESULT SendCacheCompleteMessage(
138 + __in PFN_BURNCACHEMESSAGEHANDLER pfnCacheMessageHandler,
139 + __in LPVOID pContext,
140 + __in HRESULT hrStatus
141 );
142
143
@@ -754,7 +792,11 @@ LExit:
792 extern "C" HRESULT CacheLayoutBundle(
793 __in_z LPCWSTR wzExecutableName,
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
800 )
801 {
802 HRESULT hr = S_OK;
@@ -765,7 +807,7 @@ extern "C" HRESULT CacheLayoutBundle(
807
808 LogStringLine(REPORT_STANDARD, "Layout bundle from: '%ls' to: '%ls'", wzSourceBundlePath, sczTargetPath);
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);
811 ExitOnFailure(hr, "Failed to layout bundle from: '%ls' to '%ls'", wzSourceBundlePath, sczTargetPath);
812
813 LExit:
@@ -838,7 +880,10 @@ extern "C" HRESULT CacheLayoutContainer(
880 __in BURN_CONTAINER* pContainer,
881 __in_z_opt LPCWSTR wzLayoutDirectory,
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
887 )
888 {
889 HRESULT hr = S_OK;
@@ -847,7 +892,7 @@ extern "C" HRESULT CacheLayoutContainer(
892 hr = PathConcat(wzLayoutDirectory, pContainer->sczFilePath, &sczCachedPath);
893 ExitOnFailure(hr, "Failed to concat complete cached path.");
894
850 - hr = VerifyThenTransferContainer(pContainer, sczCachedPath, wzUnverifiedContainerPath, fMove);
895 + hr = VerifyThenTransferContainer(pContainer, sczCachedPath, wzUnverifiedContainerPath, fMove, pfnCacheMessageHandler, pfnProgress, pContext);
896 ExitOnFailure(hr, "Failed to layout container from cached path: %ls", sczCachedPath);
897
898 LExit:
@@ -860,7 +905,10 @@ extern "C" HRESULT CacheLayoutPayload(
905 __in BURN_PAYLOAD* pPayload,
906 __in_z_opt LPCWSTR wzLayoutDirectory,
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
912 )
913 {
914 HRESULT hr = S_OK;
@@ -869,7 +917,7 @@ extern "C" HRESULT CacheLayoutPayload(
917 hr = PathConcat(wzLayoutDirectory, pPayload->sczFilePath, &sczCachedPath);
918 ExitOnFailure(hr, "Failed to concat complete cached path.");
919
872 - hr = VerifyThenTransferPayload(pPayload, sczCachedPath, wzUnverifiedPayloadPath, fMove);
920 + hr = VerifyThenTransferPayload(pPayload, sczCachedPath, wzUnverifiedPayloadPath, fMove, pfnCacheMessageHandler, pfnProgress, pContext);
921 ExitOnFailure(hr, "Failed to layout payload from cached payload: %ls", sczCachedPath);
922
923 LExit:
@@ -883,7 +931,10 @@ extern "C" HRESULT CacheCompletePayload(
931 __in BURN_PAYLOAD* pPayload,
932 __in_z LPCWSTR wzCacheId,
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
938 )
939 {
940 HRESULT hr = S_OK;
@@ -898,7 +949,7 @@ extern "C" HRESULT CacheCompletePayload(
949 ExitOnFailure(hr, "Failed to concat complete cached path.");
950
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);
953 if (SUCCEEDED(hr))
954 {
955 ExitFunction();
@@ -910,10 +961,21 @@ extern "C" HRESULT CacheCompletePayload(
961 // If the working path exists, let's get it into the unverified path so we can reset the ACLs and verify the file.
962 if (FileExistsEx(wzWorkingPayloadPath, NULL))
963 {
913 - hr = TransferWorkingPathToUnverifiedPath(wzWorkingPayloadPath, sczUnverifiedPayloadPath, fMove);
964 + hr = CacheTransferFileWithRetry(wzWorkingPayloadPath, sczUnverifiedPayloadPath, fMove, BURN_CACHE_STEP_STAGE, pPayload->qwFileSize, pfnCacheMessageHandler, pfnProgress, pContext);
965 ExitOnFailure(hr, "Failed to transfer working path to unverified path for payload: %ls.", pPayload->sczKey);
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.
979 {
980 hr = E_FILENOTFOUND;
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(
984 hr = ResetPathPermissions(fPerMachine, sczUnverifiedPayloadPath);
985 ExitOnFailure(hr, "Failed to reset permissions on unverified cached payload: %ls", pPayload->sczKey);
986
925 - hr = VerifyFileAgainstPayload(pPayload, sczUnverifiedPayloadPath, FALSE);
987 + hr = VerifyFileAgainstPayload(pPayload, sczUnverifiedPayloadPath, FALSE, BURN_CACHE_STEP_HASH, pfnCacheMessageHandler, pfnProgress, pContext);
988 LogExitOnFailure(hr, MSG_FAILED_VERIFY_PAYLOAD, "Failed to verify payload: %ls at path: %ls", pPayload->sczKey, sczUnverifiedPayloadPath, NULL);
989
990 LogId(REPORT_STANDARD, MSG_VERIFIED_ACQUIRED_PAYLOAD, pPayload->sczKey, sczUnverifiedPayloadPath, fMove ? "moving" : "copying", sczCachedPath);
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);
993 ExitOnFailure(hr, "Failed to move verified file to complete payload path: %ls", sczCachedPath);
994
995 ::DecryptFileW(sczCachedPath, 0); // Let's try to make sure it's not encrypted.
@@ -942,7 +1004,10 @@ LExit:
1004
1005 extern "C" HRESULT CacheVerifyContainer(
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
1011 )
1012 {
1013 HRESULT hr = S_OK;
@@ -951,7 +1016,7 @@ extern "C" HRESULT CacheVerifyContainer(
1016 hr = PathConcat(wzCachedDirectory, pContainer->sczFilePath, &sczCachedPath);
1017 ExitOnFailure(hr, "Failed to concat complete cached path.");
1018
954 - hr = VerifyFileAgainstContainer(pContainer, sczCachedPath, TRUE);
1019 + hr = VerifyFileAgainstContainer(pContainer, sczCachedPath, TRUE, BURN_CACHE_STEP_HASH_TO_SKIP_ACQUIRE, pfnCacheMessageHandler, pfnProgress, pContext);
1020
1021 LExit:
1022 ReleaseStr(sczCachedPath);
@@ -961,7 +1026,10 @@ LExit:
1026
1027 extern "C" HRESULT CacheVerifyPayload(
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
1033 )
1034 {
1035 HRESULT hr = S_OK;
@@ -970,7 +1038,7 @@ extern "C" HRESULT CacheVerifyPayload(
1038 hr = PathConcat(wzCachedDirectory, pPayload->sczFilePath, &sczCachedPath);
1039 ExitOnFailure(hr, "Failed to concat complete cached path.");
1040
973 - hr = VerifyFileAgainstPayload(pPayload, sczCachedPath, TRUE);
1041 + hr = VerifyFileAgainstPayload(pPayload, sczCachedPath, TRUE, BURN_CACHE_STEP_HASH_TO_SKIP_ACQUIRE, pfnCacheMessageHandler, pfnProgress, pContext);
1042
1043 LExit:
1044 ReleaseStr(sczCachedPath);
@@ -1342,7 +1410,10 @@ static HRESULT VerifyThenTransferContainer(
1410 __in BURN_CONTAINER* pContainer,
1411 __in_z LPCWSTR wzCachedPath,
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
1417 )
1418 {
1419 HRESULT hr = S_OK;
@@ -1358,22 +1429,13 @@ static HRESULT VerifyThenTransferContainer(
1429 // Container should have a hash we can use to verify with.
1430 if (pContainer->pbHash)
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);
1433 ExitOnFailure(hr, "Failed to verify container hash: %ls", wzCachedPath);
1434 }
1435
1436 LogStringLine(REPORT_STANDARD, "%ls container from working path '%ls' to path '%ls'", fMove ? L"Moving" : L"Copying", wzUnverifiedContainerPath, wzCachedPath);
1437
1367 - if (fMove)
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 - }
1438 + hr = CacheTransferFileWithRetry(wzUnverifiedContainerPath, wzCachedPath, fMove, BURN_CACHE_STEP_FINALIZE, pContainer->qwFileSize, pfnCacheMessageHandler, pfnProgress, pContext);
1439
1440 LExit:
1441 ReleaseFileHandle(hFile);
@@ -1385,7 +1447,10 @@ static HRESULT VerifyThenTransferPayload(
1447 __in BURN_PAYLOAD* pPayload,
1448 __in_z LPCWSTR wzCachedPath,
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
1454 )
1455 {
1456 HRESULT hr = S_OK;
@@ -1400,22 +1465,13 @@ static HRESULT VerifyThenTransferPayload(
1465
1466 if (pPayload->pbHash) // the payload should have a hash we can use to verify it.
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);
1469 ExitOnFailure(hr, "Failed to verify payload hash: %ls", wzCachedPath);
1470 }
1471
1472 LogStringLine(REPORT_STANDARD, "%ls payload from working path '%ls' to path '%ls'", fMove ? L"Moving" : L"Copying", wzUnverifiedPayloadPath, wzCachedPath);
1473
1409 - if (fMove)
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 - }
1474 + hr = CacheTransferFileWithRetry(wzUnverifiedPayloadPath, wzCachedPath, fMove, BURN_CACHE_STEP_FINALIZE, pPayload->qwFileSize, pfnCacheMessageHandler, pfnProgress, pContext);
1475
1476 LExit:
1477 ReleaseFileHandle(hFile);
@@ -1423,33 +1479,50 @@ LExit:
1479 return hr;
1480 }
1481
1426 -static HRESULT TransferWorkingPathToUnverifiedPath(
1427 - __in_z LPCWSTR wzWorkingPath,
1428 - __in_z LPCWSTR wzUnverifiedPayloadPath,
1429 - __in BOOL fMove
1482 +static HRESULT CacheTransferFileWithRetry(
1483 + __in_z LPCWSTR wzSourcePath,
1484 + __in_z LPCWSTR wzDestinationPath,
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
1491 )
1492 {
1493 HRESULT hr = S_OK;
1494
1495 + hr = SendCacheBeginMessage(pfnCacheMessageHandler, pContext, cacheStep);
1496 + ExitOnFailure(hr, "Aborted cache file transfer begin.");
1497 +
1498 + // TODO: send progress during the file transfer.
1499 if (fMove)
1500 {
1436 - hr = FileEnsureMoveWithRetry(wzWorkingPath, wzUnverifiedPayloadPath, TRUE, TRUE, FILE_OPERATION_RETRY_COUNT, FILE_OPERATION_RETRY_WAIT);
1437 - ExitOnFailure(hr, "Failed to move %ls to %ls", wzWorkingPath, wzUnverifiedPayloadPath);
1501 + hr = FileEnsureMoveWithRetry(wzSourcePath, wzDestinationPath, TRUE, TRUE, FILE_OPERATION_RETRY_COUNT, FILE_OPERATION_RETRY_WAIT);
1502 + ExitOnFailure(hr, "Failed to move %ls to %ls", wzSourcePath, wzDestinationPath);
1503 }
1504 else
1505 {
1441 - hr = FileEnsureCopyWithRetry(wzWorkingPath, wzUnverifiedPayloadPath, TRUE, FILE_OPERATION_RETRY_COUNT, FILE_OPERATION_RETRY_WAIT);
1442 - ExitOnFailure(hr, "Failed to copy %ls to %ls", wzWorkingPath, wzUnverifiedPayloadPath);
1506 + hr = FileEnsureCopyWithRetry(wzSourcePath, wzDestinationPath, TRUE, FILE_OPERATION_RETRY_COUNT, FILE_OPERATION_RETRY_WAIT);
1507 + ExitOnFailure(hr, "Failed to copy %ls to %ls", wzSourcePath, wzDestinationPath);
1508 }
1509
1510 + hr = SendCacheSuccessMessage(pfnCacheMessageHandler, pContext, qwFileSize);
1511 +
1512 LExit:
1513 + SendCacheCompleteMessage(pfnCacheMessageHandler, pContext, hr);
1514 +
1515 return hr;
1516 }
1517
1518 static HRESULT VerifyFileAgainstContainer(
1519 __in BURN_CONTAINER* pContainer,
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
1526 )
1527 {
1528 HRESULT hr = S_OK;
@@ -1469,7 +1542,7 @@ static HRESULT VerifyFileAgainstContainer(
1542
1543 if (pContainer->pbHash) // the container should have a hash we can use to verify it.
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);
1546 ExitOnFailure(hr, "Failed to verify hash of container: %ls", pContainer->sczId);
1547 }
1548
@@ -1498,7 +1571,11 @@ LExit:
1571 static HRESULT VerifyFileAgainstPayload(
1572 __in BURN_PAYLOAD* pPayload,
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
1579 )
1580 {
1581 HRESULT hr = S_OK;
@@ -1518,7 +1595,7 @@ static HRESULT VerifyFileAgainstPayload(
1595
1596 if (pPayload->pbHash) // the payload should have a hash we can use to verify it.
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);
1599 ExitOnFailure(hr, "Failed to verify hash of payload: %ls", pPayload->sczKey);
1600 }
1601
@@ -1881,7 +1958,11 @@ static HRESULT VerifyHash(
1958 __in DWORD cbHash,
1959 __in DWORD64 qwFileSize,
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
1966 )
1967 {
1968 UNREFERENCED_PARAMETER(wzUnverifiedPayloadPath);
@@ -1893,6 +1974,9 @@ static HRESULT VerifyHash(
1974 LPWSTR pszExpected = NULL;
1975 LPWSTR pszActual = NULL;
1976
1977 + hr = SendCacheBeginMessage(pfnCacheMessageHandler, pContext, cacheStep);
1978 + ExitOnFailure(hr, "Aborted cache verify hash begin.");
1979 +
1980 hr = FileSizeByHandle(hFile, &llSize);
1981 ExitOnFailure(hr, "Failed to get file size for path: %ls", wzUnverifiedPayloadPath);
1982
@@ -1922,9 +2006,64 @@ static HRESULT VerifyHash(
2006 }
2007 }
2008
2009 + hr = SendCacheSuccessMessage(pfnCacheMessageHandler, pContext, qwFileSize);
2010 +
2011 LExit:
2012 + SendCacheCompleteMessage(pfnCacheMessageHandler, pContext, hr);
2013 +
2014 ReleaseStr(pszActual);
2015 ReleaseStr(pszExpected);
2016
2017 return hr;
2018 }
2019 +
2020 +static 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 +
2037 +static 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 +
2054 +static 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 +}
src/engine/cache.h
+67 -7
@@ -7,7 +7,48 @@
7 extern "C" {
8 #endif
9
10 -// structs
10 +
11 +enum BURN_CACHE_MESSAGE_TYPE
12 +{
13 + BURN_CACHE_MESSAGE_BEGIN,
14 + BURN_CACHE_MESSAGE_SUCCESS,
15 + BURN_CACHE_MESSAGE_COMPLETE,
16 +};
17 +
18 +enum 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 +
27 +typedef 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 +
48 +typedef HRESULT(CALLBACK* PFN_BURNCACHEMESSAGEHANDLER)(
49 + __in BURN_CACHE_MESSAGE* pMessage,
50 + __in LPVOID pvContext
51 + );
52
53 // functions
54
@@ -95,7 +136,11 @@ HRESULT CacheBundleToWorkingDirectory(
136 HRESULT CacheLayoutBundle(
137 __in_z LPCWSTR wzExecutableName,
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
144 );
145 HRESULT CacheCompleteBundle(
146 __in BOOL fPerMachine,
@@ -110,28 +155,43 @@ HRESULT CacheLayoutContainer(
155 __in BURN_CONTAINER* pContainer,
156 __in_z_opt LPCWSTR wzLayoutDirectory,
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
162 );
163 HRESULT CacheLayoutPayload(
164 __in BURN_PAYLOAD* pPayload,
165 __in_z_opt LPCWSTR wzLayoutDirectory,
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
171 );
172 HRESULT CacheCompletePayload(
173 __in BOOL fPerMachine,
174 __in BURN_PAYLOAD* pPayload,
175 __in_z LPCWSTR wzCacheId,
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
181 );
182 HRESULT CacheVerifyContainer(
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
188 );
189 HRESULT CacheVerifyPayload(
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
195 );
196 HRESULT CacheRemoveWorkingFolder(
197 __in_z_opt LPCWSTR wzBundleId
src/engine/elevation.cpp
+244 -9
@@ -35,11 +35,15 @@ typedef enum _BURN_ELEVATION_MESSAGE_TYPE
35 BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_PAUSE_AU_COMPLETE,
36 BURN_ELEVATION_MESSAGE_TYPE_APPLY_INITIALIZE_SYSTEM_RESTORE_POINT_BEGIN,
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,
41 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_PROGRESS,
42 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_ERROR,
43 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_MESSAGE,
44 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_FILES_IN_USE,
45 BURN_ELEVATION_MESSAGE_TYPE_LAUNCH_APPROVED_EXE_PROCESSID,
46 + BURN_ELEVATION_MESSAGE_TYPE_PROGRESS_ROUTINE,
47 } BURN_ELEVATION_MESSAGE_TYPE;
48
49
@@ -52,6 +56,13 @@ typedef struct _BURN_ELEVATION_APPLY_INITIALIZE_MESSAGE_CONTEXT
56 BOOL fSrpCompleteNeeded;
57 } BURN_ELEVATION_APPLY_INITIALIZE_MESSAGE_CONTEXT;
58
59 +typedef 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 +
66 typedef struct _BURN_ELEVATION_GENERIC_MESSAGE_CONTEXT
67 {
68 PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler;
@@ -99,6 +110,11 @@ static HRESULT ProcessApplyInitializeMessages(
110 __in_opt LPVOID pvContext,
111 __out DWORD* pdwResult
112 );
113 +static HRESULT ProcessBurnCacheMessages(
114 + __in BURN_PIPE_MESSAGE* pMsg,
115 + __in LPVOID pvContext,
116 + __out DWORD* pdwResult
117 + );
118 static HRESULT ProcessGenericExecuteMessages(
119 __in BURN_PIPE_MESSAGE* pMsg,
120 __in LPVOID pvContext,
@@ -114,6 +130,12 @@ static HRESULT ProcessLaunchApprovedExeMessages(
130 __in_opt LPVOID pvContext,
131 __out DWORD* pdwResult
132 );
133 +static HRESULT ProcessProgressRoutineMessage(
134 + __in BURN_PIPE_MESSAGE* pMsg,
135 + __in LPPROGRESS_ROUTINE pfnProgress,
136 + __in LPVOID pvContext,
137 + __out DWORD* pdwResult
138 + );
139 static HRESULT ProcessElevatedChildMessage(
140 __in BURN_PIPE_MESSAGE* pMsg,
141 __in_opt LPVOID pvContext,
@@ -165,12 +187,14 @@ static HRESULT OnSaveState(
187 __in DWORD cbData
188 );
189 static HRESULT OnCacheCompletePayload(
190 + __in HANDLE hPipe,
191 __in BURN_PACKAGES* pPackages,
192 __in BURN_PAYLOADS* pPayloads,
193 __in BYTE* pbData,
194 __in DWORD cbData
195 );
196 static HRESULT OnCacheVerifyPayload(
197 + __in HANDLE hPipe,
198 __in BURN_PACKAGES* pPackages,
199 __in BURN_PAYLOADS* pPayloads,
200 __in BYTE* pbData,
@@ -225,6 +249,21 @@ static HRESULT OnExecutePackageDependencyAction(
249 __in BYTE* pbData,
250 __in DWORD cbData
251 );
252 +static HRESULT CALLBACK BurnCacheMessageHandler(
253 + __in BURN_CACHE_MESSAGE* pMessage,
254 + __in LPVOID pvContext
255 + );
256 +static 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 + );
267 static int GenericExecuteMessageHandler(
268 __in GENERIC_EXECUTE_MESSAGE* pMessage,
269 __in LPVOID pvContext
@@ -582,13 +621,21 @@ extern "C" HRESULT ElevationCacheCompletePayload(
621 __in BURN_PACKAGE* pPackage,
622 __in BURN_PAYLOAD* pPayload,
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
628 )
629 {
630 HRESULT hr = S_OK;
631 BYTE* pbData = NULL;
632 SIZE_T cbData = 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;
639
640 // serialize message data
641 hr = BuffWriteString(&pbData, &cbData, pPackage->sczId);
@@ -604,7 +651,7 @@ extern "C" HRESULT ElevationCacheCompletePayload(
651 ExitOnFailure(hr, "Failed to write move flag to message buffer.");
652
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);
655 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_CACHE_COMPLETE_PAYLOAD message to per-machine process.");
656
657 hr = (HRESULT)dwResult;
@@ -618,13 +665,21 @@ LExit:
665 extern "C" HRESULT ElevationCacheVerifyPayload(
666 __in HANDLE hPipe,
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
672 )
673 {
674 HRESULT hr = S_OK;
675 BYTE* pbData = NULL;
676 SIZE_T cbData = 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;
683
684 // serialize message data
685 hr = BuffWriteString(&pbData, &cbData, pPackage->sczId);
@@ -634,7 +689,7 @@ extern "C" HRESULT ElevationCacheVerifyPayload(
689 ExitOnFailure(hr, "Failed to write payload id to message buffer.");
690
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);
693 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_CACHE_VERIFY_PAYLOAD message to per-machine process.");
694
695 hr = (HRESULT)dwResult;
@@ -1377,6 +1432,69 @@ LExit:
1432 return hr;
1433 }
1434
1435 +static 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 +
1494 +LExit:
1495 + return hr;
1496 +}
1497 +
1498 static HRESULT ProcessGenericExecuteMessages(
1499 __in BURN_PIPE_MESSAGE* pMsg,
1500 __in LPVOID pvContext,
@@ -1596,11 +1714,41 @@ LExit:
1714 return hr;
1715 }
1716
1717 +static 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 +
1743 +LExit:
1744 + return hr;
1745 +}
1746 +
1747 static HRESULT ProcessElevatedChildMessage(
1748 __in BURN_PIPE_MESSAGE* pMsg,
1749 __in_opt LPVOID pvContext,
1750 __out DWORD* pdwResult
1603 -)
1751 + )
1752 {
1753 HRESULT hr = S_OK;
1754 BURN_ELEVATION_CHILD_MESSAGE_CONTEXT* pContext = static_cast<BURN_ELEVATION_CHILD_MESSAGE_CONTEXT*>(pvContext);
@@ -1705,11 +1853,11 @@ static HRESULT ProcessElevatedChildCacheMessage(
1853 switch (pMsg->dwMessage)
1854 {
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);
1857 break;
1858
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);
1861 break;
1862
1863 case BURN_ELEVATION_MESSAGE_TYPE_CACHE_CLEANUP:
@@ -2002,6 +2150,7 @@ LExit:
2150 }
2151
2152 static HRESULT OnCacheCompletePayload(
2153 + __in HANDLE hPipe,
2154 __in BURN_PACKAGES* pPackages,
2155 __in BURN_PAYLOADS* pPayloads,
2156 __in BYTE* pbData,
@@ -2043,7 +2192,7 @@ static HRESULT OnCacheCompletePayload(
2192
2193 if (pPackage && pPayload) // complete payload.
2194 {
2046 - hr = CacheCompletePayload(pPackage->fPerMachine, pPayload, pPackage->sczCacheId, sczUnverifiedPath, fMove);
2195 + hr = CacheCompletePayload(pPackage->fPerMachine, pPayload, pPackage->sczCacheId, sczUnverifiedPath, fMove, BurnCacheMessageHandler, ElevatedProgressRoutine, hPipe);
2196 ExitOnFailure(hr, "Failed to cache payload: %ls", pPayload->sczKey);
2197 }
2198 else
@@ -2060,6 +2209,7 @@ LExit:
2209 }
2210
2211 static HRESULT OnCacheVerifyPayload(
2212 + __in HANDLE hPipe,
2213 __in BURN_PACKAGES* pPackages,
2214 __in BURN_PAYLOADS* pPayloads,
2215 __in BYTE* pbData,
@@ -2097,7 +2247,7 @@ static HRESULT OnCacheVerifyPayload(
2247 hr = CacheGetCompletedPath(TRUE, pPackage->sczCacheId, &sczCacheDirectory);
2248 ExitOnFailure(hr, "Failed to get cached path for package with cache id: %ls", pPackage->sczCacheId);
2249
2100 - hr = CacheVerifyPayload(pPayload, sczCacheDirectory);
2250 + hr = CacheVerifyPayload(pPayload, sczCacheDirectory, BurnCacheMessageHandler, ElevatedProgressRoutine, hPipe);
2251 }
2252 else
2253 {
@@ -2573,6 +2723,91 @@ LExit:
2723 return hr;
2724 }
2725
2726 +static 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 +
2770 +LExit:
2771 + ReleaseBuffer(pbData);
2772 +
2773 + return hr;
2774 +}
2775 +
2776 +static 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 +
2805 +LExit:
2806 + ReleaseBuffer(pbData);
2807 +
2808 + return dwResult;
2809 +}
2810 +
2811 static int GenericExecuteMessageHandler(
2812 __in GENERIC_EXECUTE_MESSAGE* pMessage,
2813 __in LPVOID pvContext
src/engine/elevation.h
+8 -2
@@ -55,12 +55,18 @@ HRESULT ElevationCacheCompletePayload(
55 __in BURN_PACKAGE* pPackage,
56 __in BURN_PAYLOAD* pPayload,
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
62 );
63 HRESULT ElevationCacheVerifyPayload(
64 __in HANDLE hPipe,
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
70 );
71 HRESULT ElevationCacheCleanup(
72 __in HANDLE hPipe
src/engine/plan.cpp
+12 -6
@@ -431,8 +431,8 @@ extern "C" HRESULT PlanLayoutBundle(
431 pCacheAction->bundleLayout.qwBundleSize = qwBundleSize;
432 pCacheAction->bundleLayout.pPayloadGroup = pLayoutPayloads;
433
434 - // Acquire + Verify
435 - pPlan->qwCacheSizeTotal += 2 * qwBundleSize;
434 + // Acquire + Verify + Finalize
435 + pPlan->qwCacheSizeTotal += 3 * qwBundleSize;
436
437 ++pPlan->cOverallProgressTicksTotal;
438
@@ -1006,8 +1006,8 @@ extern "C" HRESULT PlanLayoutContainer(
1006 pCacheAction->type = BURN_CACHE_ACTION_TYPE_CONTAINER;
1007 pCacheAction->container.pContainer = pContainer;
1008
1009 - // Acquire + Verify
1010 - pPlan->qwCacheSizeTotal += 2 * pContainer->qwFileSize;
1009 + // Acquire + Verify + Finalize
1010 + pPlan->qwCacheSizeTotal += 3 * pContainer->qwFileSize;
1011 }
1012 }
1013 else
@@ -2249,8 +2249,14 @@ static HRESULT ProcessPayloadGroup(
2249
2250 if (!pPlan->sczLayoutDirectory || !pPayload->pContainer)
2251 {
2252 - // Acquire + Verify
2253 - pPlan->qwCacheSizeTotal += 2 * pPayload->qwFileSize;
2252 + // Acquire + Verify + Finalize
2253 + pPlan->qwCacheSizeTotal += 3 * pPayload->qwFileSize;
2254 +
2255 + if (!pPlan->sczLayoutDirectory)
2256 + {
2257 + // Staging
2258 + pPlan->qwCacheSizeTotal += pPayload->qwFileSize;
2259 + }
2260 }
2261
2262 if (!pPlan->sczLayoutDirectory && pPayload->pContainer && 1 == pPayload->cRemainingInstances)
src/engine/userexperience.cpp
+3 -1
@@ -912,7 +912,8 @@ EXTERN_C BAAPI UserExperienceOnCacheVerifyProgress(
912 __in_z_opt LPCWSTR wzPayloadId,
913 __in DWORD64 dw64Progress,
914 __in DWORD64 dw64Total,
915 - __in DWORD dwOverallPercentage
915 + __in DWORD dwOverallPercentage,
916 + __in BOOTSTRAPPER_CACHE_VERIFY_STEP verifyStep
917 )
918 {
919 HRESULT hr = S_OK;
@@ -925,6 +926,7 @@ EXTERN_C BAAPI UserExperienceOnCacheVerifyProgress(
926 args.dw64Progress = dw64Progress;
927 args.dw64Total = dw64Total;
928 args.dwOverallPercentage = dwOverallPercentage;
929 + args.verifyStep = verifyStep;
930
931 results.cbSize = sizeof(results);
932
src/engine/userexperience.h
+2 -1
@@ -233,7 +233,8 @@ BAAPI UserExperienceOnCacheVerifyProgress(
233 __in_z_opt LPCWSTR wzPayloadId,
234 __in DWORD64 dw64Progress,
235 __in DWORD64 dw64Total,
236 - __in DWORD dwOverallPercentage
236 + __in DWORD dwOverallPercentage,
237 + __in BOOTSTRAPPER_CACHE_VERIFY_STEP verifyStep
238 );
239 BAAPI UserExperienceOnCommitMsiTransactionBegin(
240 __in BURN_USER_EXPERIENCE* pUserExperience,
src/test/BurnUnitTest/CacheTest.cpp
+45 -1
@@ -2,6 +2,26 @@
2
3 #include "precomp.h"
4
5 +static HRESULT CALLBACK CacheTestEventRoutine(
6 + __in BURN_CACHE_MESSAGE* pMessage,
7 + __in LPVOID pvContext
8 + );
9 +
10 +static 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 +
22 +typedef struct _CACHE_TEST_CONTEXT
23 +{
24 +} CACHE_TEST_CONTEXT;
25
26 namespace Microsoft
27 {
@@ -33,6 +53,7 @@ namespace Bootstrapper
53 LPWSTR sczPayloadPath = NULL;
54 BYTE* pb = NULL;
55 DWORD cb = NULL;
56 + CACHE_TEST_CONTEXT context = { };
57
58 try
59 {
@@ -51,7 +72,7 @@ namespace Bootstrapper
72 payload.pbHash = pb;
73 payload.cbHash = cb;
74
54 - hr = CacheCompletePayload(package.fPerMachine, &payload, package.sczCacheId, sczPayloadPath, FALSE);
75 + hr = CacheCompletePayload(package.fPerMachine, &payload, package.sczCacheId, sczPayloadPath, FALSE, CacheTestEventRoutine, CacheTestProgressRoutine, &context);
76 Assert::Equal(S_OK, hr);
77 }
78 finally
@@ -73,3 +94,26 @@ namespace Bootstrapper
94 }
95 }
96 }
97 +
98 +static HRESULT CALLBACK CacheTestEventRoutine(
99 + __in BURN_CACHE_MESSAGE* /*pMessage*/,
100 + __in LPVOID /*pvContext*/
101 + )
102 +{
103 + return S_OK;
104 +}
105 +
106 +static 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 +}
src/test/BurnUnitTest/PlanTest.cpp
+5 -5
@@ -71,7 +71,7 @@ namespace Bootstrapper
71 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
72
73 Assert::Equal(107082ull, pPlan->qwEstimatedSize);
74 - Assert::Equal(303687ull, pPlan->qwCacheSizeTotal);
74 + Assert::Equal(506145ull, pPlan->qwCacheSizeTotal);
75
76 fRollback = FALSE;
77 dwIndex = 0;
@@ -308,7 +308,7 @@ namespace Bootstrapper
308 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
309
310 Assert::Equal(35694ull, pPlan->qwEstimatedSize);
311 - Assert::Equal(101229ull, pPlan->qwCacheSizeTotal);
311 + Assert::Equal(168715ull, pPlan->qwCacheSizeTotal);
312
313 fRollback = FALSE;
314 dwIndex = 0;
@@ -388,7 +388,7 @@ namespace Bootstrapper
388 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
389
390 Assert::Equal(33743ull, pPlan->qwEstimatedSize);
391 - Assert::Equal(101229ull, pPlan->qwCacheSizeTotal);
391 + Assert::Equal(168715ull, pPlan->qwCacheSizeTotal);
392
393 fRollback = FALSE;
394 dwIndex = 0;
@@ -458,7 +458,7 @@ namespace Bootstrapper
458 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
459
460 Assert::Equal(35694ull, pPlan->qwEstimatedSize);
461 - Assert::Equal(101229ull, pPlan->qwCacheSizeTotal);
461 + Assert::Equal(168715ull, pPlan->qwCacheSizeTotal);
462
463 fRollback = FALSE;
464 dwIndex = 0;
@@ -739,7 +739,7 @@ namespace Bootstrapper
739 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
740
741 Assert::Equal(3055111ull, pPlan->qwEstimatedSize);
742 - Assert::Equal(106496ull, pPlan->qwCacheSizeTotal);
742 + Assert::Equal(212992ull, pPlan->qwCacheSizeTotal);
743
744 fRollback = FALSE;
745 dwIndex = 0;