aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2021-04-16 10:29:10 -0500
committerSean Hall <r.sean.hall@gmail.com>2021-04-19 23:12:55 -0500
commit9a061c70f8d87d4f4703bd88a0eaae98c3cfc1d5 (patch)
treed124655bcfb2aff4a026b8aac5c8b5e7d8e060c3
parent66360b60b0298c88d32ce2b5e5ce5befa1c09ff8 (diff)
downloadwix-9a061c70f8d87d4f4703bd88a0eaae98c3cfc1d5.tar.gz
wix-9a061c70f8d87d4f4703bd88a0eaae98c3cfc1d5.tar.bz2
wix-9a061c70f8d87d4f4703bd88a0eaae98c3cfc1d5.zip
Always send OnCacheAcquireProgress at least once per payload.
Always send OnCacheAcquireProgress between OnCacheAcquireBegin and OnCacheAcquireComplete. Track the successful cache acquisition progress during the final progress call.
-rw-r--r--src/engine/apply.cpp317
-rw-r--r--src/engine/engine.mc21
-rw-r--r--src/engine/plan.cpp8
3 files changed, 185 insertions, 161 deletions
diff --git a/src/engine/apply.cpp b/src/engine/apply.cpp
index c39a7746..e62db4d2 100644
--- a/src/engine/apply.cpp
+++ b/src/engine/apply.cpp
@@ -37,7 +37,7 @@ typedef struct _BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT
37 BURN_PAYLOAD* pPayload; 37 BURN_PAYLOAD* pPayload;
38 38
39 BOOL fCancel; 39 BOOL fCancel;
40 BOOL fError; 40 HRESULT hrError;
41} BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT; 41} BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT;
42 42
43typedef struct _BURN_EXECUTE_CONTEXT 43typedef struct _BURN_EXECUTE_CONTEXT
@@ -102,12 +102,16 @@ static HRESULT LayoutBundle(
102 __in_z LPCWSTR wzExecutableName, 102 __in_z LPCWSTR wzExecutableName,
103 __in_z LPCWSTR wzUnverifiedPath 103 __in_z LPCWSTR wzUnverifiedPath
104 ); 104 );
105static HRESULT AcquireContainerOrPayload( 105static HRESULT ApplyAcquireContainerOrPayload(
106 __in BURN_CACHE_CONTEXT* pContext, 106 __in BURN_CACHE_CONTEXT* pContext,
107 __in_opt BURN_CONTAINER* pContainer, 107 __in_opt BURN_CONTAINER* pContainer,
108 __in_opt BURN_PACKAGE* pPackage, 108 __in_opt BURN_PACKAGE* pPackage,
109 __in_opt BURN_PAYLOAD* pPayload 109 __in_opt BURN_PAYLOAD* pPayload
110 ); 110 );
111static HRESULT AcquireContainerOrPayload(
112 __in BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT* pProgress,
113 __out BOOL* pfRetry
114 );
111static HRESULT LayoutOrCacheContainerOrPayload( 115static HRESULT LayoutOrCacheContainerOrPayload(
112 __in BURN_CACHE_CONTEXT* pContext, 116 __in BURN_CACHE_CONTEXT* pContext,
113 __in_opt BURN_CONTAINER* pContainer, 117 __in_opt BURN_CONTAINER* pContainer,
@@ -127,6 +131,10 @@ static HRESULT DownloadPayload(
127 __in BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT* pProgress, 131 __in BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT* pProgress,
128 __in_z LPCWSTR wzDestinationPath 132 __in_z LPCWSTR wzDestinationPath
129 ); 133 );
134static HRESULT CompleteCacheProgress(
135 __in BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT* pContext,
136 __in DWORD64 qwFileSize
137 );
130static DWORD CALLBACK CacheProgressRoutine( 138static DWORD CALLBACK CacheProgressRoutine(
131 __in LARGE_INTEGER TotalFileSize, 139 __in LARGE_INTEGER TotalFileSize,
132 __in LARGE_INTEGER TotalBytesTransferred, 140 __in LARGE_INTEGER TotalBytesTransferred,
@@ -833,12 +841,10 @@ static HRESULT ApplyExtractContainer(
833 841
834 if (!pContainer->fActuallyAttached) 842 if (!pContainer->fActuallyAttached)
835 { 843 {
836 hr = AcquireContainerOrPayload(pContext, pContainer, NULL, NULL); 844 hr = ApplyAcquireContainerOrPayload(pContext, pContainer, NULL, NULL);
837 LogExitOnFailure(hr, MSG_FAILED_ACQUIRE_CONTAINER, "Failed to acquire container: %ls to working path: %ls", pContainer->sczId, pContainer->sczUnverifiedPath); 845 LogExitOnFailure(hr, MSG_FAILED_ACQUIRE_CONTAINER, "Failed to acquire container: %ls to working path: %ls", pContainer->sczId, pContainer->sczUnverifiedPath);
838 } 846 }
839 847
840 pContext->qwSuccessfulCacheProgress += pContainer->qwFileSize;
841
842 hr = ExtractContainer(pContext, pContainer); 848 hr = ExtractContainer(pContext, pContainer);
843 LogExitOnFailure(hr, MSG_FAILED_EXTRACT_CONTAINER, "Failed to extract payloads from container: %ls to working path: %ls", pContainer->sczId, pContainer->sczUnverifiedPath); 849 LogExitOnFailure(hr, MSG_FAILED_EXTRACT_CONTAINER, "Failed to extract payloads from container: %ls to working path: %ls", pContainer->sczId, pContainer->sczUnverifiedPath);
844 850
@@ -903,11 +909,9 @@ static HRESULT ApplyLayoutContainer(
903 { 909 {
904 fRetry = FALSE; 910 fRetry = FALSE;
905 911
906 hr = AcquireContainerOrPayload(pContext, pContainer, NULL, NULL); 912 hr = ApplyAcquireContainerOrPayload(pContext, pContainer, NULL, NULL);
907 LogExitOnFailure(hr, MSG_FAILED_ACQUIRE_CONTAINER, "Failed to acquire container: %ls to working path: %ls", pContainer->sczId, pContainer->sczUnverifiedPath); 913 LogExitOnFailure(hr, MSG_FAILED_ACQUIRE_CONTAINER, "Failed to acquire container: %ls to working path: %ls", pContainer->sczId, pContainer->sczUnverifiedPath);
908 914
909 pContext->qwSuccessfulCacheProgress += pContainer->qwFileSize;
910
911 hr = LayoutOrCacheContainerOrPayload(pContext, pContainer, NULL, NULL, TRUE, cTryAgainAttempts, &fRetry); 915 hr = LayoutOrCacheContainerOrPayload(pContext, pContainer, NULL, NULL, TRUE, cTryAgainAttempts, &fRetry);
912 if (SUCCEEDED(hr)) 916 if (SUCCEEDED(hr))
913 { 917 {
@@ -932,7 +936,7 @@ static HRESULT ApplyLayoutContainer(
932 ++cTryAgainAttempts; 936 ++cTryAgainAttempts;
933 pContext->qwSuccessfulCacheProgress -= pContainer->qwFileSize; 937 pContext->qwSuccessfulCacheProgress -= pContainer->qwFileSize;
934 ReleaseNullStr(pContext->sczLastUsedFolderCandidate); 938 ReleaseNullStr(pContext->sczLastUsedFolderCandidate);
935 LogErrorId(hr, MSG_APPLY_RETRYING_PAYLOAD, pContainer->sczId, NULL, NULL); 939 LogErrorId(hr, MSG_APPLY_RETRYING_CONTAINER, pContainer->sczId, NULL, NULL);
936 } 940 }
937 } 941 }
938 942
@@ -971,11 +975,9 @@ static HRESULT ApplyProcessPayload(
971 { 975 {
972 fRetry = FALSE; 976 fRetry = FALSE;
973 977
974 hr = AcquireContainerOrPayload(pContext, NULL, pPackage, pPayload); 978 hr = ApplyAcquireContainerOrPayload(pContext, NULL, pPackage, pPayload);
975 LogExitOnFailure(hr, MSG_FAILED_ACQUIRE_PAYLOAD, "Failed to acquire payload: %ls to working path: %ls", pPayload->sczKey, pPayload->sczUnverifiedPath); 979 LogExitOnFailure(hr, MSG_FAILED_ACQUIRE_PAYLOAD, "Failed to acquire payload: %ls to working path: %ls", pPayload->sczKey, pPayload->sczUnverifiedPath);
976 980
977 pContext->qwSuccessfulCacheProgress += pPayload->qwFileSize;
978
979 // TODO: set fMove to TRUE appropriately 981 // TODO: set fMove to TRUE appropriately
980 hr = LayoutOrCacheContainerOrPayload(pContext, NULL, pPackage, pPayload, FALSE, cTryAgainAttempts, &fRetry); 982 hr = LayoutOrCacheContainerOrPayload(pContext, NULL, pPackage, pPayload, FALSE, cTryAgainAttempts, &fRetry);
981 if (SUCCEEDED(hr)) 983 if (SUCCEEDED(hr))
@@ -1172,7 +1174,7 @@ LExit:
1172 return hr; 1174 return hr;
1173} 1175}
1174 1176
1175static HRESULT AcquireContainerOrPayload( 1177static HRESULT ApplyAcquireContainerOrPayload(
1176 __in BURN_CACHE_CONTEXT* pContext, 1178 __in BURN_CACHE_CONTEXT* pContext,
1177 __in_opt BURN_CONTAINER* pContainer, 1179 __in_opt BURN_CONTAINER* pContainer,
1178 __in_opt BURN_PACKAGE* pPackage, 1180 __in_opt BURN_PACKAGE* pPackage,
@@ -1182,164 +1184,149 @@ static HRESULT AcquireContainerOrPayload(
1182 AssertSz(pContainer || pPayload, "Must provide a container or a payload."); 1184 AssertSz(pContainer || pPayload, "Must provide a container or a payload.");
1183 1185
1184 HRESULT hr = S_OK; 1186 HRESULT hr = S_OK;
1187 BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT progress = { };
1188 BOOL fRetry = FALSE;
1189
1190 progress.pCacheContext = pContext;
1191 progress.pContainer = pContainer;
1192 progress.pPackage = pPackage;
1193 progress.pPayload = pPayload;
1194
1195 do
1196 {
1197 hr = AcquireContainerOrPayload(&progress, &fRetry);
1198
1199 if (fRetry)
1200 {
1201 hr = S_OK;
1202 LogErrorId(hr, pContainer ? MSG_APPLY_RETRYING_ACQUIRE_CONTAINER : MSG_APPLY_RETRYING_ACQUIRE_PAYLOAD, pContainer ? pContainer->sczId : pPayload->sczKey, NULL, NULL);
1203 }
1204
1205 ExitOnFailure(hr, "Failed to acquire %hs: %ls", pContainer ? "container" : "payload", pContainer ? pContainer->sczId : pPayload->sczKey);
1206 } while (fRetry);
1207
1208LExit:
1209 return hr;
1210}
1211
1212static HRESULT AcquireContainerOrPayload(
1213 __in BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT* pProgress,
1214 __out BOOL* pfRetry
1215 )
1216{
1217 BURN_CACHE_CONTEXT* pContext = pProgress->pCacheContext;
1218 BURN_CONTAINER* pContainer = pProgress->pContainer;
1219 BURN_PACKAGE* pPackage = pProgress->pPackage;
1220 BURN_PAYLOAD* pPayload = pProgress->pPayload;
1221 AssertSz(pContainer || pPayload, "Must provide a container or a payload.");
1222
1223 HRESULT hr = S_OK;
1185 int nEquivalentPaths = 0; 1224 int nEquivalentPaths = 0;
1186 LPCWSTR wzPackageOrContainerId = pContainer ? pContainer->sczId : pPackage ? pPackage->sczId : NULL; 1225 LPCWSTR wzPackageOrContainerId = pContainer ? pContainer->sczId : pPackage ? pPackage->sczId : NULL;
1187 LPCWSTR wzPayloadId = pPayload ? pPayload->sczKey : NULL; 1226 LPCWSTR wzPayloadId = pPayload ? pPayload->sczKey : NULL;
1188 LPCWSTR wzPayloadContainerId = pPayload && pPayload->pContainer ? pPayload->pContainer->sczId : NULL; 1227 LPCWSTR wzPayloadContainerId = pPayload && pPayload->pContainer ? pPayload->pContainer->sczId : NULL;
1189 LPCWSTR wzDestinationPath = pContainer ? pContainer->sczUnverifiedPath: pPayload->sczUnverifiedPath; 1228 LPCWSTR wzDestinationPath = pContainer ? pContainer->sczUnverifiedPath: pPayload->sczUnverifiedPath;
1190 LPCWSTR wzRelativePath = pContainer ? pContainer->sczFilePath : pPayload->sczFilePath; 1229 LPCWSTR wzRelativePath = pContainer ? pContainer->sczFilePath : pPayload->sczFilePath;
1191 BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT progress = { };
1192 BOOL fBeginCalled = FALSE;
1193 BOOL fRetry = FALSE;
1194 DWORD dwChosenSearchPath = 0; 1230 DWORD dwChosenSearchPath = 0;
1195 BOOTSTRAPPER_CACHE_OPERATION cacheOperation = BOOTSTRAPPER_CACHE_OPERATION_NONE; 1231 BOOTSTRAPPER_CACHE_OPERATION cacheOperation = BOOTSTRAPPER_CACHE_OPERATION_NONE;
1196 LPWSTR* pwzDownloadUrl = pContainer ? &pContainer->downloadSource.sczUrl : &pPayload->downloadSource.sczUrl; 1232 LPWSTR* pwzDownloadUrl = pContainer ? &pContainer->downloadSource.sczUrl : &pPayload->downloadSource.sczUrl;
1197 LPWSTR* pwzSourcePath = pContainer ? &pContainer->sczSourcePath : &pPayload->sczSourcePath; 1233 LPWSTR* pwzSourcePath = pContainer ? &pContainer->sczSourcePath : &pPayload->sczSourcePath;
1234 BOOL fFoundLocal = FALSE;
1198 1235
1199 progress.pCacheContext = pContext; 1236 pContext->cSearchPaths = 0;
1200 progress.pContainer = pContainer; 1237 *pfRetry = FALSE;
1201 progress.pPackage = pPackage; 1238 pProgress->fCancel = FALSE;
1202 progress.pPayload = pPayload;
1203
1204 do
1205 {
1206 BOOL fFoundLocal = FALSE;
1207 1239
1208 pContext->cSearchPaths = 0; 1240 hr = UserExperienceOnCacheAcquireBegin(pContext->pUX, wzPackageOrContainerId, wzPayloadId, pwzSourcePath, pwzDownloadUrl, wzPayloadContainerId, &cacheOperation);
1209 dwChosenSearchPath = 0; 1241 ExitOnRootFailure(hr, "BA aborted cache acquire begin.");
1210 fRetry = FALSE;
1211 progress.fCancel = FALSE;
1212 fBeginCalled = TRUE;
1213 1242
1214 hr = UserExperienceOnCacheAcquireBegin(pContext->pUX, wzPackageOrContainerId, wzPayloadId, pwzSourcePath, pwzDownloadUrl, wzPayloadContainerId, &cacheOperation); 1243 // Skip the Resolving event and probing local paths if the BA already knew it wanted to download or extract.
1215 ExitOnRootFailure(hr, "BA aborted cache acquire begin."); 1244 if (BOOTSTRAPPER_CACHE_OPERATION_DOWNLOAD != cacheOperation &&
1245 BOOTSTRAPPER_CACHE_OPERATION_EXTRACT != cacheOperation)
1246 {
1247 hr = CacheGetLocalSourcePaths(wzRelativePath, *pwzSourcePath, wzDestinationPath, pContext->wzLayoutDirectory, pContext->pVariables, &pContext->rgSearchPaths, &pContext->cSearchPaths);
1248 ExitOnFailure(hr, "Failed to search local source.");
1216 1249
1217 // Skip the Resolving event and probing local paths if the BA already knew it wanted to download or extract. 1250 for (DWORD i = 0; i < pContext->cSearchPaths; ++i)
1218 if (BOOTSTRAPPER_CACHE_OPERATION_DOWNLOAD != cacheOperation &&
1219 BOOTSTRAPPER_CACHE_OPERATION_EXTRACT != cacheOperation)
1220 { 1251 {
1221 hr = CacheGetLocalSourcePaths(wzRelativePath, *pwzSourcePath, wzDestinationPath, pContext->wzLayoutDirectory, pContext->pVariables, &pContext->rgSearchPaths, &pContext->cSearchPaths); 1252 // If the file exists locally, choose it.
1222 ExitOnFailure(hr, "Failed to search local source."); 1253 if (FileExistsEx(pContext->rgSearchPaths[i], NULL))
1223
1224 for (DWORD i = 0; i < pContext->cSearchPaths; ++i)
1225 { 1254 {
1226 // If the file exists locally, choose it. 1255 dwChosenSearchPath = i;
1227 if (FileExistsEx(pContext->rgSearchPaths[i], NULL))
1228 {
1229 dwChosenSearchPath = i;
1230 1256
1231 fFoundLocal = TRUE; 1257 fFoundLocal = TRUE;
1232 break; 1258 break;
1233 }
1234 } 1259 }
1260 }
1235 1261
1236 if (BOOTSTRAPPER_CACHE_OPERATION_COPY == cacheOperation) 1262 if (BOOTSTRAPPER_CACHE_OPERATION_COPY == cacheOperation)
1237 { 1263 {
1238 if (!fFoundLocal) 1264 if (!fFoundLocal)
1239 {
1240 cacheOperation = BOOTSTRAPPER_CACHE_OPERATION_NONE;
1241 }
1242 }
1243 else
1244 { 1265 {
1245 if (fFoundLocal) // the file exists locally, so copy it. 1266 cacheOperation = BOOTSTRAPPER_CACHE_OPERATION_NONE;
1246 {
1247 cacheOperation = BOOTSTRAPPER_CACHE_OPERATION_COPY;
1248 }
1249 else if (wzPayloadContainerId)
1250 {
1251 cacheOperation = BOOTSTRAPPER_CACHE_OPERATION_EXTRACT;
1252 }
1253 else if (*pwzDownloadUrl && **pwzDownloadUrl)
1254 {
1255 cacheOperation = BOOTSTRAPPER_CACHE_OPERATION_DOWNLOAD;
1256 }
1257 } 1267 }
1258
1259 // Let the BA have a chance to override the action, but their chance to change the source is during begin or complete.
1260 hr = UserExperienceOnCacheAcquireResolving(pContext->pUX, wzPackageOrContainerId, wzPayloadId, pContext->rgSearchPaths, pContext->cSearchPaths, fFoundLocal, &dwChosenSearchPath, *pwzDownloadUrl, wzPayloadContainerId, &cacheOperation);
1261 ExitOnRootFailure(hr, "BA aborted cache acquire resolving.");
1262 } 1268 }
1263 1269 else
1264 switch (cacheOperation)
1265 { 1270 {
1266 case BOOTSTRAPPER_CACHE_OPERATION_COPY: 1271 if (fFoundLocal) // the file exists locally, so copy it.
1267 // If the source path and destination path are different, do the copy (otherwise there's no point).
1268 hr = PathCompare(pContext->rgSearchPaths[dwChosenSearchPath], wzDestinationPath, &nEquivalentPaths);
1269 ExitOnFailure(hr, "Failed to determine if payload paths were equivalent, source: %ls, destination: %ls.", pContext->rgSearchPaths[dwChosenSearchPath], wzDestinationPath);
1270
1271 if (CSTR_EQUAL != nEquivalentPaths)
1272 { 1272 {
1273 hr = CopyPayload(&progress, INVALID_HANDLE_VALUE, pContext->rgSearchPaths[dwChosenSearchPath], wzDestinationPath); 1273 cacheOperation = BOOTSTRAPPER_CACHE_OPERATION_COPY;
1274 // Error handling happens after sending complete message to BA.
1275
1276 // Store the source path so it can be used as the LastUsedFolder if it passes verification.
1277 pContext->sczLastUsedFolderCandidate = pContext->rgSearchPaths[dwChosenSearchPath];
1278 pContext->rgSearchPaths[dwChosenSearchPath] = NULL;
1279 } 1274 }
1280 1275 else if (wzPayloadContainerId)
1281 fBeginCalled = FALSE;
1282 UserExperienceOnCacheAcquireComplete(pContext->pUX, wzPackageOrContainerId, wzPayloadId, hr, &fRetry);
1283 if (fRetry)
1284 { 1276 {
1285 hr = S_OK; 1277 cacheOperation = BOOTSTRAPPER_CACHE_OPERATION_EXTRACT;
1286 } 1278 }
1287 1279 else if (*pwzDownloadUrl && **pwzDownloadUrl)
1288 ExitOnFailure(hr, "Failed to acquire payload from: '%ls' to working path: '%ls'", pContext->rgSearchPaths[dwChosenSearchPath], wzDestinationPath);
1289
1290 break;
1291 case BOOTSTRAPPER_CACHE_OPERATION_DOWNLOAD:
1292 hr = DownloadPayload(&progress, wzDestinationPath);
1293 // Error handling happens after sending complete message to BA.
1294
1295 fBeginCalled = FALSE;
1296 UserExperienceOnCacheAcquireComplete(pContext->pUX, wzPackageOrContainerId, wzPayloadId, hr, &fRetry);
1297 if (fRetry)
1298 { 1280 {
1299 hr = S_OK; 1281 cacheOperation = BOOTSTRAPPER_CACHE_OPERATION_DOWNLOAD;
1300 } 1282 }
1283 }
1301 1284
1302 ExitOnFailure(hr, "Failed to acquire payload from: '%ls' to working path: '%ls'", *pwzDownloadUrl, wzDestinationPath); 1285 // Let the BA have a chance to override the action, but their chance to change the source is during begin or complete.
1286 hr = UserExperienceOnCacheAcquireResolving(pContext->pUX, wzPackageOrContainerId, wzPayloadId, pContext->rgSearchPaths, pContext->cSearchPaths, fFoundLocal, &dwChosenSearchPath, *pwzDownloadUrl, wzPayloadContainerId, &cacheOperation);
1287 ExitOnRootFailure(hr, "BA aborted cache acquire resolving.");
1288 }
1303 1289
1304 break; 1290 switch (cacheOperation)
1305 case BOOTSTRAPPER_CACHE_OPERATION_EXTRACT: 1291 {
1306 Assert(pPayload->pContainer); 1292 case BOOTSTRAPPER_CACHE_OPERATION_COPY:
1293 // If the source path and destination path are different, do the copy (otherwise there's no point).
1294 hr = PathCompare(pContext->rgSearchPaths[dwChosenSearchPath], wzDestinationPath, &nEquivalentPaths);
1295 ExitOnFailure(hr, "Failed to determine if payload paths were equivalent, source: %ls, destination: %ls.", pContext->rgSearchPaths[dwChosenSearchPath], wzDestinationPath);
1307 1296
1308 hr = ApplyExtractContainer(pContext, pPayload->pContainer); 1297 if (CSTR_EQUAL != nEquivalentPaths)
1309 // Error handling happens after sending complete message to BA. 1298 {
1299 hr = CopyPayload(pProgress, INVALID_HANDLE_VALUE, pContext->rgSearchPaths[dwChosenSearchPath], wzDestinationPath);
1300 ExitOnFailure(hr, "Failed to copy payload: %ls", wzPayloadId);
1310 1301
1311 fBeginCalled = FALSE; 1302 // Store the source path so it can be used as the LastUsedFolder if it passes verification.
1312 UserExperienceOnCacheAcquireComplete(pContext->pUX, wzPackageOrContainerId, wzPayloadId, hr, &fRetry); 1303 pContext->sczLastUsedFolderCandidate = pContext->rgSearchPaths[dwChosenSearchPath];
1313 if (fRetry) 1304 pContext->rgSearchPaths[dwChosenSearchPath] = NULL;
1314 { 1305 }
1315 hr = S_OK;
1316 }
1317 1306
1318 ExitOnFailure(hr, "Failed to extract container for payload: %ls", wzPayloadId); 1307 break;
1308 case BOOTSTRAPPER_CACHE_OPERATION_DOWNLOAD:
1309 hr = DownloadPayload(pProgress, wzDestinationPath);
1310 ExitOnFailure(hr, "Failed to download payload: %ls", wzPayloadId);
1319 1311
1320 break; 1312 break;
1321 case BOOTSTRAPPER_CACHE_OPERATION_NONE: 1313 case BOOTSTRAPPER_CACHE_OPERATION_EXTRACT:
1322 hr = E_FILENOTFOUND; 1314 Assert(pPayload->pContainer);
1323 LogErrorId(hr, MSG_RESOLVE_SOURCE_FAILED, wzPayloadId, pPackage ? pPackage->sczId : NULL, pContainer ? pContainer->sczId : NULL);
1324 1315
1325 fBeginCalled = FALSE; 1316 hr = ApplyExtractContainer(pContext, pPayload->pContainer);
1326 UserExperienceOnCacheAcquireComplete(pContext->pUX, wzPackageOrContainerId, wzPayloadId, hr, &fRetry); 1317 ExitOnFailure(hr, "Failed to extract container for payload: %ls", wzPayloadId);
1327 if (fRetry)
1328 {
1329 hr = S_OK;
1330 }
1331 1318
1332 ExitOnFailure(hr, "Failed to resolve source, payload: %ls, package: %ls, container: %ls", wzPayloadId, pPackage ? pPackage->sczId : NULL, pContainer ? pContainer->sczId : NULL); 1319 break;
1320 default:
1321 hr = E_FILENOTFOUND;
1322 LogExitOnFailure(hr, MSG_RESOLVE_SOURCE_FAILED, "Failed to resolve source, payload: %ls, package: %ls, container: %ls", wzPayloadId, pPackage ? pPackage->sczId : NULL, pContainer ? pContainer->sczId : NULL);
1323 }
1333 1324
1334 break; 1325 // Send 100% complete here. This is sometimes the only progress sent to the BA.
1335 } 1326 hr = CompleteCacheProgress(pProgress, pContainer ? pContainer->qwFileSize : pPayload->qwFileSize);
1336 } while (fRetry);
1337 1327
1338LExit: 1328LExit:
1339 if (fBeginCalled) 1329 UserExperienceOnCacheAcquireComplete(pContext->pUX, wzPackageOrContainerId, wzPayloadId, hr, pfRetry);
1340 {
1341 UserExperienceOnCacheAcquireComplete(pContext->pUX, wzPackageOrContainerId, wzPayloadId, hr, &fRetry);
1342 }
1343 1330
1344 pContext->cSearchPathsMax = max(pContext->cSearchPaths, pContext->cSearchPathsMax); 1331 pContext->cSearchPathsMax = max(pContext->cSearchPaths, pContext->cSearchPathsMax);
1345 1332
@@ -1360,9 +1347,6 @@ static HRESULT LayoutOrCacheContainerOrPayload(
1360 LPCWSTR wzPackageOrContainerId = pContainer ? pContainer->sczId : pPackage ? pPackage->sczId : L""; 1347 LPCWSTR wzPackageOrContainerId = pContainer ? pContainer->sczId : pPackage ? pPackage->sczId : L"";
1361 LPCWSTR wzUnverifiedPath = pContainer ? pContainer->sczUnverifiedPath : pPayload->sczUnverifiedPath; 1348 LPCWSTR wzUnverifiedPath = pContainer ? pContainer->sczUnverifiedPath : pPayload->sczUnverifiedPath;
1362 LPCWSTR wzPayloadId = pPayload ? pPayload->sczKey : L""; 1349 LPCWSTR wzPayloadId = pPayload ? pPayload->sczKey : L"";
1363 LARGE_INTEGER liContainerOrPayloadSize = { };
1364 LARGE_INTEGER liZero = { };
1365 BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT progress = { };
1366 BOOL fCanAffectRegistration = FALSE; 1350 BOOL fCanAffectRegistration = FALSE;
1367 1351
1368 if (!pContext->wzLayoutDirectory) 1352 if (!pContext->wzLayoutDirectory)
@@ -1373,13 +1357,6 @@ static HRESULT LayoutOrCacheContainerOrPayload(
1373 fCanAffectRegistration = pPackage->fCanAffectRegistration; 1357 fCanAffectRegistration = pPackage->fCanAffectRegistration;
1374 } 1358 }
1375 1359
1376 liContainerOrPayloadSize.QuadPart = pContainer ? pContainer->qwFileSize : pPayload->qwFileSize;
1377
1378 progress.pCacheContext = pContext;
1379 progress.pContainer = pContainer;
1380 progress.pPackage = pPackage;
1381 progress.pPayload = pPayload;
1382
1383 *pfRetry = FALSE; 1360 *pfRetry = FALSE;
1384 1361
1385 do 1362 do
@@ -1407,25 +1384,9 @@ static HRESULT LayoutOrCacheContainerOrPayload(
1407 hr = CacheCompletePayload(pPackage->fPerMachine, pPayload, pPackage->sczCacheId, wzUnverifiedPath, fMove); 1384 hr = CacheCompletePayload(pPackage->fPerMachine, pPayload, pPackage->sczCacheId, wzUnverifiedPath, fMove);
1408 } 1385 }
1409 1386
1410 // If succeeded, send 100% complete here. If the payload was already cached this is the first progress the BA 1387 if (SUCCEEDED(hr) && fCanAffectRegistration)
1411 // will get.
1412 if (SUCCEEDED(hr))
1413 { 1388 {
1414 if (fCanAffectRegistration) 1389 pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
1415 {
1416 pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
1417 }
1418
1419 CacheProgressRoutine(liContainerOrPayloadSize, liContainerOrPayloadSize, liZero, liZero, 0, 0, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, &progress);
1420 if (progress.fCancel)
1421 {
1422 hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);
1423 }
1424 else if (progress.fError)
1425 {
1426 hr = HRESULT_FROM_WIN32(ERROR_INSTALL_FAILURE);
1427 }
1428 ExitOnRootFailure(hr, "BA aborted verify of %hs: %ls", pContainer ? "container" : "payload", pContainer ? wzPackageOrContainerId : wzPayloadId);
1429 } 1390 }
1430 1391
1431 BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION action = FAILED(hr) && cTryAgainAttempts < BURN_CACHE_MAX_RECOMMENDED_VERIFY_TRYAGAIN_ATTEMPTS ? BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION_RETRYACQUISITION : BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION_NONE; 1392 BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION action = FAILED(hr) && cTryAgainAttempts < BURN_CACHE_MAX_RECOMMENDED_VERIFY_TRYAGAIN_ATTEMPTS ? BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION_RETRYACQUISITION : BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION_NONE;
@@ -1624,6 +1585,39 @@ LExit:
1624 return hr; 1585 return hr;
1625} 1586}
1626 1587
1588static HRESULT CompleteCacheProgress(
1589 __in BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT* pContext,
1590 __in DWORD64 qwFileSize
1591 )
1592{
1593 HRESULT hr = S_OK;
1594 LARGE_INTEGER liContainerOrPayloadSize = { };
1595 LARGE_INTEGER liZero = { };
1596 DWORD dwResult = 0;
1597
1598 liContainerOrPayloadSize.QuadPart = qwFileSize;
1599
1600 dwResult = CacheProgressRoutine(liContainerOrPayloadSize, liContainerOrPayloadSize, liZero, liZero, 0, 0, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, pContext);
1601
1602 if (PROGRESS_CONTINUE == dwResult)
1603 {
1604 pContext->pCacheContext->qwSuccessfulCacheProgress += qwFileSize;
1605 }
1606 else if (PROGRESS_CANCEL == dwResult)
1607 {
1608 if (pContext->fCancel)
1609 {
1610 hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);
1611 }
1612 else
1613 {
1614 hr = pContext->hrError;
1615 }
1616 }
1617
1618 return hr;
1619}
1620
1627static DWORD CALLBACK CacheProgressRoutine( 1621static DWORD CALLBACK CacheProgressRoutine(
1628 __in LARGE_INTEGER TotalFileSize, 1622 __in LARGE_INTEGER TotalFileSize,
1629 __in LARGE_INTEGER TotalBytesTransferred, 1623 __in LARGE_INTEGER TotalBytesTransferred,
@@ -1650,6 +1644,9 @@ static DWORD CALLBACK CacheProgressRoutine(
1650 DWORD dwOverallPercentage = pProgress->pCacheContext->qwTotalCacheSize ? static_cast<DWORD>(qwCacheProgress * 100 / pProgress->pCacheContext->qwTotalCacheSize) : 0; 1644 DWORD dwOverallPercentage = pProgress->pCacheContext->qwTotalCacheSize ? static_cast<DWORD>(qwCacheProgress * 100 / pProgress->pCacheContext->qwTotalCacheSize) : 0;
1651 1645
1652 hr = UserExperienceOnCacheAcquireProgress(pProgress->pCacheContext->pUX, wzPackageOrContainerId, wzPayloadId, TotalBytesTransferred.QuadPart, TotalFileSize.QuadPart, dwOverallPercentage); 1646 hr = UserExperienceOnCacheAcquireProgress(pProgress->pCacheContext->pUX, wzPackageOrContainerId, wzPayloadId, TotalBytesTransferred.QuadPart, TotalFileSize.QuadPart, dwOverallPercentage);
1647 ExitOnRootFailure(hr, "BA aborted acquire of %hs: %ls", pProgress->pContainer ? "container" : "payload", pProgress->pContainer ? wzPackageOrContainerId : wzPayloadId);
1648
1649LExit:
1653 if (HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) == hr) 1650 if (HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) == hr)
1654 { 1651 {
1655 dwResult = PROGRESS_CANCEL; 1652 dwResult = PROGRESS_CANCEL;
@@ -1658,7 +1655,7 @@ static DWORD CALLBACK CacheProgressRoutine(
1658 else if (FAILED(hr)) 1655 else if (FAILED(hr))
1659 { 1656 {
1660 dwResult = PROGRESS_CANCEL; 1657 dwResult = PROGRESS_CANCEL;
1661 pProgress->fError = TRUE; 1658 pProgress->hrError = hr;
1662 } 1659 }
1663 else 1660 else
1664 { 1661 {
diff --git a/src/engine/engine.mc b/src/engine/engine.mc
index f03bc1ea..0e19d3bb 100644
--- a/src/engine/engine.mc
+++ b/src/engine/engine.mc
@@ -724,6 +724,13 @@ Language=English
724Acquiring package: %1!ls!, payload: %2!ls!, %3!hs! from: %4!ls! 724Acquiring package: %1!ls!, payload: %2!ls!, %3!hs! from: %4!ls!
725. 725.
726 726
727MessageId=347
728Severity=Warning
729SymbolicName=MSG_APPLY_RETRYING_CONTAINER
730Language=English
731Application requested retry of container: %2!ls!, encountered error: %1!ls!. Retrying...
732.
733
727MessageId=348 734MessageId=348
728Severity=Warning 735Severity=Warning
729SymbolicName=MSG_APPLY_RETRYING_PACKAGE 736SymbolicName=MSG_APPLY_RETRYING_PACKAGE
@@ -780,6 +787,20 @@ Language=English
780Unable to register source directory: %1!ls!, product: %2!ls!, reason: 0x%3!x!. Continuing... 787Unable to register source directory: %1!ls!, product: %2!ls!, reason: 0x%3!x!. Continuing...
781. 788.
782 789
790MessageId=356
791Severity=Warning
792SymbolicName=MSG_APPLY_RETRYING_ACQUIRE_CONTAINER
793Language=English
794Application requested retry acquire of container: %2!ls!, encountered error: %1!ls!. Retrying...
795.
796
797MessageId=357
798Severity=Warning
799SymbolicName=MSG_APPLY_RETRYING_ACQUIRE_PAYLOAD
800Language=English
801Application requested retry acquire of payload: %2!ls!, encountered error: %1!ls!. Retrying...
802.
803
783MessageId=358 804MessageId=358
784Severity=Success 805Severity=Success
785SymbolicName=MSG_PAUSE_AU_STARTING 806SymbolicName=MSG_PAUSE_AU_STARTING
diff --git a/src/engine/plan.cpp b/src/engine/plan.cpp
index cfe4893b..a37dcc89 100644
--- a/src/engine/plan.cpp
+++ b/src/engine/plan.cpp
@@ -1010,7 +1010,13 @@ extern "C" HRESULT PlanLayoutContainer(
1010 } 1010 }
1011 else 1011 else
1012 { 1012 {
1013 pPlan->qwCacheSizeTotal += 2 * pContainer->qwFileSize; 1013 if (!pContainer->fActuallyAttached)
1014 {
1015 pPlan->qwCacheSizeTotal += pContainer->qwFileSize;
1016 }
1017
1018 // TODO: This should be the sum of all uncompressed payloads in the container, ideally restricted to the payloads that were actually planned.
1019 pPlan->qwCacheSizeTotal += pContainer->qwFileSize;
1014 } 1020 }
1015 1021
1016 if (!pContainer->sczUnverifiedPath) 1022 if (!pContainer->sczUnverifiedPath)