diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2021-04-16 10:29:10 -0500 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2021-04-19 23:12:55 -0500 |
commit | 9a061c70f8d87d4f4703bd88a0eaae98c3cfc1d5 (patch) | |
tree | d124655bcfb2aff4a026b8aac5c8b5e7d8e060c3 | |
parent | 66360b60b0298c88d32ce2b5e5ce5befa1c09ff8 (diff) | |
download | wix-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.cpp | 317 | ||||
-rw-r--r-- | src/engine/engine.mc | 21 | ||||
-rw-r--r-- | src/engine/plan.cpp | 8 |
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 | ||
43 | typedef struct _BURN_EXECUTE_CONTEXT | 43 | typedef 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 | ); |
105 | static HRESULT AcquireContainerOrPayload( | 105 | static 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 | ); |
111 | static HRESULT AcquireContainerOrPayload( | ||
112 | __in BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT* pProgress, | ||
113 | __out BOOL* pfRetry | ||
114 | ); | ||
111 | static HRESULT LayoutOrCacheContainerOrPayload( | 115 | static 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 | ); |
134 | static HRESULT CompleteCacheProgress( | ||
135 | __in BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT* pContext, | ||
136 | __in DWORD64 qwFileSize | ||
137 | ); | ||
130 | static DWORD CALLBACK CacheProgressRoutine( | 138 | static 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 | ||
1175 | static HRESULT AcquireContainerOrPayload( | 1177 | static 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 | |||
1208 | LExit: | ||
1209 | return hr; | ||
1210 | } | ||
1211 | |||
1212 | static 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 | ||
1338 | LExit: | 1328 | LExit: |
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 | ||
1588 | static 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 | |||
1627 | static DWORD CALLBACK CacheProgressRoutine( | 1621 | static 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 | |||
1649 | LExit: | ||
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 | |||
724 | Acquiring package: %1!ls!, payload: %2!ls!, %3!hs! from: %4!ls! | 724 | Acquiring package: %1!ls!, payload: %2!ls!, %3!hs! from: %4!ls! |
725 | . | 725 | . |
726 | 726 | ||
727 | MessageId=347 | ||
728 | Severity=Warning | ||
729 | SymbolicName=MSG_APPLY_RETRYING_CONTAINER | ||
730 | Language=English | ||
731 | Application requested retry of container: %2!ls!, encountered error: %1!ls!. Retrying... | ||
732 | . | ||
733 | |||
727 | MessageId=348 | 734 | MessageId=348 |
728 | Severity=Warning | 735 | Severity=Warning |
729 | SymbolicName=MSG_APPLY_RETRYING_PACKAGE | 736 | SymbolicName=MSG_APPLY_RETRYING_PACKAGE |
@@ -780,6 +787,20 @@ Language=English | |||
780 | Unable to register source directory: %1!ls!, product: %2!ls!, reason: 0x%3!x!. Continuing... | 787 | Unable to register source directory: %1!ls!, product: %2!ls!, reason: 0x%3!x!. Continuing... |
781 | . | 788 | . |
782 | 789 | ||
790 | MessageId=356 | ||
791 | Severity=Warning | ||
792 | SymbolicName=MSG_APPLY_RETRYING_ACQUIRE_CONTAINER | ||
793 | Language=English | ||
794 | Application requested retry acquire of container: %2!ls!, encountered error: %1!ls!. Retrying... | ||
795 | . | ||
796 | |||
797 | MessageId=357 | ||
798 | Severity=Warning | ||
799 | SymbolicName=MSG_APPLY_RETRYING_ACQUIRE_PAYLOAD | ||
800 | Language=English | ||
801 | Application requested retry acquire of payload: %2!ls!, encountered error: %1!ls!. Retrying... | ||
802 | . | ||
803 | |||
783 | MessageId=358 | 804 | MessageId=358 |
784 | Severity=Success | 805 | Severity=Success |
785 | SymbolicName=MSG_PAUSE_AU_STARTING | 806 | SymbolicName=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) |