diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h | 63 | ||||
| -rw-r--r-- | src/engine/apply.cpp | 242 | ||||
| -rw-r--r-- | src/engine/cache.cpp | 203 | ||||
| -rw-r--r-- | src/engine/cache.h | 9 | ||||
| -rw-r--r-- | src/engine/engine.mc | 32 | ||||
| -rw-r--r-- | src/engine/externalengine.cpp | 43 | ||||
| -rw-r--r-- | src/engine/userexperience.cpp | 126 | ||||
| -rw-r--r-- | src/engine/userexperience.h | 26 |
8 files changed, 413 insertions, 331 deletions
diff --git a/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h b/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h index 2d086f38..cf330c29 100644 --- a/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h +++ b/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h | |||
| @@ -54,8 +54,13 @@ enum BOOTSTRAPPER_RELATED_OPERATION | |||
| 54 | 54 | ||
| 55 | enum BOOTSTRAPPER_CACHE_OPERATION | 55 | enum BOOTSTRAPPER_CACHE_OPERATION |
| 56 | { | 56 | { |
| 57 | // There is no source available. | ||
| 58 | BOOTSTRAPPER_CACHE_OPERATION_NONE, | ||
| 59 | // Copy the payload or container from the chosen local source. | ||
| 57 | BOOTSTRAPPER_CACHE_OPERATION_COPY, | 60 | BOOTSTRAPPER_CACHE_OPERATION_COPY, |
| 61 | // Download the payload or container using the download URL. | ||
| 58 | BOOTSTRAPPER_CACHE_OPERATION_DOWNLOAD, | 62 | BOOTSTRAPPER_CACHE_OPERATION_DOWNLOAD, |
| 63 | // Extract the payload from the container. | ||
| 59 | BOOTSTRAPPER_CACHE_OPERATION_EXTRACT, | 64 | BOOTSTRAPPER_CACHE_OPERATION_EXTRACT, |
| 60 | }; | 65 | }; |
| 61 | 66 | ||
| @@ -112,7 +117,7 @@ enum BOOTSTRAPPER_APPLICATION_MESSAGE | |||
| 112 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPACKAGEBEGIN, | 117 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPACKAGEBEGIN, |
| 113 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIREBEGIN, | 118 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIREBEGIN, |
| 114 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIREPROGRESS, | 119 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIREPROGRESS, |
| 115 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONRESOLVESOURCE, | 120 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIRERESOLVING, |
| 116 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIRECOMPLETE, | 121 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIRECOMPLETE, |
| 117 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEVERIFYBEGIN, | 122 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEVERIFYBEGIN, |
| 118 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEVERIFYCOMPLETE, | 123 | BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEVERIFYCOMPLETE, |
| @@ -158,7 +163,7 @@ enum BOOTSTRAPPER_APPLYCOMPLETE_ACTION | |||
| 158 | enum BOOTSTRAPPER_CACHEACQUIRECOMPLETE_ACTION | 163 | enum BOOTSTRAPPER_CACHEACQUIRECOMPLETE_ACTION |
| 159 | { | 164 | { |
| 160 | BOOTSTRAPPER_CACHEACQUIRECOMPLETE_ACTION_NONE, | 165 | BOOTSTRAPPER_CACHEACQUIRECOMPLETE_ACTION_NONE, |
| 161 | // Instructs the engine to try the acquisition of the package again. | 166 | // Instructs the engine to try the acquisition of the payload again. |
| 162 | // Ignored if hrStatus is a success. | 167 | // Ignored if hrStatus is a success. |
| 163 | BOOTSTRAPPER_CACHEACQUIRECOMPLETE_ACTION_RETRY, | 168 | BOOTSTRAPPER_CACHEACQUIRECOMPLETE_ACTION_RETRY, |
| 164 | }; | 169 | }; |
| @@ -202,16 +207,6 @@ enum BOOTSTRAPPER_EXECUTEPACKAGECOMPLETE_ACTION | |||
| 202 | BOOTSTRAPPER_EXECUTEPACKAGECOMPLETE_ACTION_SUSPEND, | 207 | BOOTSTRAPPER_EXECUTEPACKAGECOMPLETE_ACTION_SUSPEND, |
| 203 | }; | 208 | }; |
| 204 | 209 | ||
| 205 | enum BOOTSTRAPPER_RESOLVESOURCE_ACTION | ||
| 206 | { | ||
| 207 | // Instructs the engine that the source can't be found. | ||
| 208 | BOOTSTRAPPER_RESOLVESOURCE_ACTION_NONE, | ||
| 209 | // Instructs the engine to try the local source again. | ||
| 210 | BOOTSTRAPPER_RESOLVESOURCE_ACTION_RETRY, | ||
| 211 | // Instructs the engine to try the download source. | ||
| 212 | BOOTSTRAPPER_RESOLVESOURCE_ACTION_DOWNLOAD, | ||
| 213 | }; | ||
| 214 | |||
| 215 | enum BOOTSTRAPPER_SHUTDOWN_ACTION | 210 | enum BOOTSTRAPPER_SHUTDOWN_ACTION |
| 216 | { | 211 | { |
| 217 | BOOTSTRAPPER_SHUTDOWN_ACTION_NONE, | 212 | BOOTSTRAPPER_SHUTDOWN_ACTION_NONE, |
| @@ -315,14 +310,17 @@ struct BA_ONCACHEACQUIREBEGIN_ARGS | |||
| 315 | DWORD cbSize; | 310 | DWORD cbSize; |
| 316 | LPCWSTR wzPackageOrContainerId; | 311 | LPCWSTR wzPackageOrContainerId; |
| 317 | LPCWSTR wzPayloadId; | 312 | LPCWSTR wzPayloadId; |
| 318 | BOOTSTRAPPER_CACHE_OPERATION operation; | ||
| 319 | LPCWSTR wzSource; | 313 | LPCWSTR wzSource; |
| 314 | LPCWSTR wzDownloadUrl; | ||
| 315 | LPCWSTR wzPayloadContainerId; | ||
| 316 | BOOTSTRAPPER_CACHE_OPERATION recommendation; | ||
| 320 | }; | 317 | }; |
| 321 | 318 | ||
| 322 | struct BA_ONCACHEACQUIREBEGIN_RESULTS | 319 | struct BA_ONCACHEACQUIREBEGIN_RESULTS |
| 323 | { | 320 | { |
| 324 | DWORD cbSize; | 321 | DWORD cbSize; |
| 325 | BOOL fCancel; | 322 | BOOL fCancel; |
| 323 | BOOTSTRAPPER_CACHE_OPERATION action; | ||
| 326 | }; | 324 | }; |
| 327 | 325 | ||
| 328 | struct BA_ONCACHEACQUIRECOMPLETE_ARGS | 326 | struct BA_ONCACHEACQUIRECOMPLETE_ARGS |
| @@ -356,6 +354,28 @@ struct BA_ONCACHEACQUIREPROGRESS_RESULTS | |||
| 356 | BOOL fCancel; | 354 | BOOL fCancel; |
| 357 | }; | 355 | }; |
| 358 | 356 | ||
| 357 | struct BA_ONCACHEACQUIRERESOLVING_ARGS | ||
| 358 | { | ||
| 359 | DWORD cbSize; | ||
| 360 | LPCWSTR wzPackageOrContainerId; | ||
| 361 | LPCWSTR wzPayloadId; | ||
| 362 | LPCWSTR* rgSearchPaths; | ||
| 363 | DWORD cSearchPaths; | ||
| 364 | BOOL fFoundLocal; | ||
| 365 | DWORD dwRecommendedSearchPath; | ||
| 366 | LPCWSTR wzDownloadUrl; | ||
| 367 | LPCWSTR wzPayloadContainerId; | ||
| 368 | BOOTSTRAPPER_CACHE_OPERATION recommendation; | ||
| 369 | }; | ||
| 370 | |||
| 371 | struct BA_ONCACHEACQUIRERESOLVING_RESULTS | ||
| 372 | { | ||
| 373 | DWORD cbSize; | ||
| 374 | DWORD dwChosenSearchPath; | ||
| 375 | BOOTSTRAPPER_CACHE_OPERATION action; | ||
| 376 | BOOL fCancel; | ||
| 377 | }; | ||
| 378 | |||
| 359 | struct BA_ONCACHEBEGIN_ARGS | 379 | struct BA_ONCACHEBEGIN_ARGS |
| 360 | { | 380 | { |
| 361 | DWORD cbSize; | 381 | DWORD cbSize; |
| @@ -1013,23 +1033,6 @@ struct BA_ONREGISTERCOMPLETE_RESULTS | |||
| 1013 | DWORD cbSize; | 1033 | DWORD cbSize; |
| 1014 | }; | 1034 | }; |
| 1015 | 1035 | ||
| 1016 | struct BA_ONRESOLVESOURCE_ARGS | ||
| 1017 | { | ||
| 1018 | DWORD cbSize; | ||
| 1019 | LPCWSTR wzPackageOrContainerId; | ||
| 1020 | LPCWSTR wzPayloadId; | ||
| 1021 | LPCWSTR wzLocalSource; | ||
| 1022 | LPCWSTR wzDownloadSource; | ||
| 1023 | BOOTSTRAPPER_RESOLVESOURCE_ACTION recommendation; | ||
| 1024 | }; | ||
| 1025 | |||
| 1026 | struct BA_ONRESOLVESOURCE_RESULTS | ||
| 1027 | { | ||
| 1028 | DWORD cbSize; | ||
| 1029 | BOOTSTRAPPER_RESOLVESOURCE_ACTION action; | ||
| 1030 | BOOL fCancel; | ||
| 1031 | }; | ||
| 1032 | |||
| 1033 | struct BA_ONROLLBACKMSITRANSACTIONBEGIN_ARGS | 1036 | struct BA_ONROLLBACKMSITRANSACTIONBEGIN_ARGS |
| 1034 | { | 1037 | { |
| 1035 | DWORD cbSize; | 1038 | DWORD cbSize; |
diff --git a/src/engine/apply.cpp b/src/engine/apply.cpp index dffbc6d6..dc9f905b 100644 --- a/src/engine/apply.cpp +++ b/src/engine/apply.cpp | |||
| @@ -23,6 +23,9 @@ typedef struct _BURN_CACHE_CONTEXT | |||
| 23 | DWORD64 qwTotalCacheSize; | 23 | DWORD64 qwTotalCacheSize; |
| 24 | DWORD64 qwSuccessfulCacheProgress; | 24 | DWORD64 qwSuccessfulCacheProgress; |
| 25 | LPCWSTR wzLayoutDirectory; | 25 | LPCWSTR wzLayoutDirectory; |
| 26 | LPWSTR* rgSearchPaths; | ||
| 27 | DWORD cSearchPaths; | ||
| 28 | DWORD cSearchPathsMax; | ||
| 26 | } BURN_CACHE_CONTEXT; | 29 | } BURN_CACHE_CONTEXT; |
| 27 | 30 | ||
| 28 | typedef struct _BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT | 31 | typedef struct _BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT |
| @@ -113,15 +116,6 @@ static HRESULT LayoutOrCacheContainerOrPayload( | |||
| 113 | __in DWORD cTryAgainAttempts, | 116 | __in DWORD cTryAgainAttempts, |
| 114 | __out BOOL* pfRetry | 117 | __out BOOL* pfRetry |
| 115 | ); | 118 | ); |
| 116 | static HRESULT PromptForSource( | ||
| 117 | __in BURN_USER_EXPERIENCE* pUX, | ||
| 118 | __in_z LPCWSTR wzPackageOrContainerId, | ||
| 119 | __in_z_opt LPCWSTR wzPayloadId, | ||
| 120 | __in_z LPCWSTR wzLocalSource, | ||
| 121 | __in_z_opt LPCWSTR wzDownloadSource, | ||
| 122 | __out BOOL* pfRetry, | ||
| 123 | __out BOOL* pfDownload | ||
| 124 | ); | ||
| 125 | static HRESULT CopyPayload( | 119 | static HRESULT CopyPayload( |
| 126 | __in BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT* pProgress, | 120 | __in BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT* pProgress, |
| 127 | __in HANDLE hSourceFile, | 121 | __in HANDLE hSourceFile, |
| @@ -485,6 +479,9 @@ extern "C" HRESULT ApplyCache( | |||
| 485 | cacheContext.qwTotalCacheSize = pPlan->qwCacheSizeTotal; | 479 | cacheContext.qwTotalCacheSize = pPlan->qwCacheSizeTotal; |
| 486 | cacheContext.wzLayoutDirectory = pPlan->sczLayoutDirectory; | 480 | cacheContext.wzLayoutDirectory = pPlan->sczLayoutDirectory; |
| 487 | 481 | ||
| 482 | hr = MemAllocArray(reinterpret_cast<LPVOID*>(&cacheContext.rgSearchPaths), sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS); | ||
| 483 | ExitOnNull(cacheContext.rgSearchPaths, hr, E_OUTOFMEMORY, "Failed to allocate cache search paths array."); | ||
| 484 | |||
| 488 | for (DWORD i = 0; i < pPlan->cCacheActions; ++i) | 485 | for (DWORD i = 0; i < pPlan->cCacheActions; ++i) |
| 489 | { | 486 | { |
| 490 | BURN_CACHE_ACTION* pCacheAction = pPlan->rgCacheActions + i; | 487 | BURN_CACHE_ACTION* pCacheAction = pPlan->rgCacheActions + i; |
| @@ -561,6 +558,12 @@ LExit: | |||
| 561 | 558 | ||
| 562 | CacheCleanup(FALSE, pPlan->wzBundleId); | 559 | CacheCleanup(FALSE, pPlan->wzBundleId); |
| 563 | 560 | ||
| 561 | for (DWORD i = 0; i < cacheContext.cSearchPathsMax; ++i) | ||
| 562 | { | ||
| 563 | ReleaseNullStr(cacheContext.rgSearchPaths[i]); | ||
| 564 | } | ||
| 565 | ReleaseMem(cacheContext.rgSearchPaths); | ||
| 566 | |||
| 564 | UserExperienceOnCacheComplete(pUX, hr); | 567 | UserExperienceOnCacheComplete(pUX, hr); |
| 565 | return hr; | 568 | return hr; |
| 566 | } | 569 | } |
| @@ -949,17 +952,8 @@ static HRESULT ApplyProcessPayload( | |||
| 949 | { | 952 | { |
| 950 | fRetry = FALSE; | 953 | fRetry = FALSE; |
| 951 | 954 | ||
| 952 | if (pPayload->pContainer) | 955 | hr = AcquireContainerOrPayload(pContext, NULL, pPackage, pPayload); |
| 953 | { | 956 | LogExitOnFailure(hr, MSG_FAILED_ACQUIRE_PAYLOAD, "Failed to acquire payload: %ls to working path: %ls", pPayload->sczKey, pPayload->sczUnverifiedPath); |
| 954 | // TODO: only extract container if payload isn't already extracted | ||
| 955 | hr = ApplyExtractContainer(pContext, pPayload->pContainer); | ||
| 956 | ExitOnFailure(hr, "Failed to extract container for payload: %ls", pPayload->sczKey); | ||
| 957 | } | ||
| 958 | else | ||
| 959 | { | ||
| 960 | hr = AcquireContainerOrPayload(pContext, NULL, pPackage, pPayload); | ||
| 961 | LogExitOnFailure(hr, MSG_FAILED_ACQUIRE_PAYLOAD, "Failed to acquire payload: %ls to working path: %ls", pPayload->sczKey, pPayload->sczUnverifiedPath); | ||
| 962 | } | ||
| 963 | 957 | ||
| 964 | pContext->qwSuccessfulCacheProgress += pPayload->qwFileSize; | 958 | pContext->qwSuccessfulCacheProgress += pPayload->qwFileSize; |
| 965 | 959 | ||
| @@ -1054,8 +1048,10 @@ static HRESULT LayoutBundle( | |||
| 1054 | { | 1048 | { |
| 1055 | HRESULT hr = S_OK; | 1049 | HRESULT hr = S_OK; |
| 1056 | LPWSTR sczBundlePath = NULL; | 1050 | LPWSTR sczBundlePath = NULL; |
| 1051 | LPWSTR sczBundleDownloadUrl = NULL; | ||
| 1057 | LPWSTR sczDestinationPath = NULL; | 1052 | LPWSTR sczDestinationPath = NULL; |
| 1058 | int nEquivalentPaths = 0; | 1053 | int nEquivalentPaths = 0; |
| 1054 | BOOTSTRAPPER_CACHE_OPERATION cacheOperation = BOOTSTRAPPER_CACHE_OPERATION_NONE; | ||
| 1059 | BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT progress = { }; | 1055 | BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT progress = { }; |
| 1060 | BOOL fRetry = FALSE; | 1056 | BOOL fRetry = FALSE; |
| 1061 | BOOL fRetryAcquire = FALSE; | 1057 | BOOL fRetryAcquire = FALSE; |
| @@ -1096,7 +1092,7 @@ static HRESULT LayoutBundle( | |||
| 1096 | fRetryAcquire = FALSE; | 1092 | fRetryAcquire = FALSE; |
| 1097 | progress.fCancel = FALSE; | 1093 | progress.fCancel = FALSE; |
| 1098 | 1094 | ||
| 1099 | hr = UserExperienceOnCacheAcquireBegin(pContext->pUX, NULL, NULL, BOOTSTRAPPER_CACHE_OPERATION_COPY, sczBundlePath); | 1095 | hr = UserExperienceOnCacheAcquireBegin(pContext->pUX, NULL, NULL, &sczBundlePath, &sczBundleDownloadUrl, NULL, &cacheOperation); |
| 1100 | ExitOnRootFailure(hr, "BA aborted cache acquire begin."); | 1096 | ExitOnRootFailure(hr, "BA aborted cache acquire begin."); |
| 1101 | 1097 | ||
| 1102 | hr = CopyPayload(&progress, pContext->hSourceEngineFile, sczBundlePath, wzUnverifiedPath); | 1098 | hr = CopyPayload(&progress, pContext->hSourceEngineFile, sczBundlePath, wzUnverifiedPath); |
| @@ -1142,6 +1138,7 @@ static HRESULT LayoutBundle( | |||
| 1142 | 1138 | ||
| 1143 | LExit: | 1139 | LExit: |
| 1144 | ReleaseStr(sczDestinationPath); | 1140 | ReleaseStr(sczDestinationPath); |
| 1141 | ReleaseStr(sczBundleDownloadUrl); | ||
| 1145 | ReleaseStr(sczBundlePath); | 1142 | ReleaseStr(sczBundlePath); |
| 1146 | 1143 | ||
| 1147 | return hr; | 1144 | return hr; |
| @@ -1160,11 +1157,16 @@ static HRESULT AcquireContainerOrPayload( | |||
| 1160 | int nEquivalentPaths = 0; | 1157 | int nEquivalentPaths = 0; |
| 1161 | LPCWSTR wzPackageOrContainerId = pContainer ? pContainer->sczId : pPackage ? pPackage->sczId : NULL; | 1158 | LPCWSTR wzPackageOrContainerId = pContainer ? pContainer->sczId : pPackage ? pPackage->sczId : NULL; |
| 1162 | LPCWSTR wzPayloadId = pPayload ? pPayload->sczKey : NULL; | 1159 | LPCWSTR wzPayloadId = pPayload ? pPayload->sczKey : NULL; |
| 1160 | LPCWSTR wzPayloadContainerId = pPayload && pPayload->pContainer ? pPayload->pContainer->sczId : NULL; | ||
| 1163 | LPCWSTR wzDestinationPath = pContainer ? pContainer->sczUnverifiedPath: pPayload->sczUnverifiedPath; | 1161 | LPCWSTR wzDestinationPath = pContainer ? pContainer->sczUnverifiedPath: pPayload->sczUnverifiedPath; |
| 1164 | LPCWSTR wzRelativePath = pContainer ? pContainer->sczFilePath : pPayload->sczFilePath; | 1162 | LPCWSTR wzRelativePath = pContainer ? pContainer->sczFilePath : pPayload->sczFilePath; |
| 1165 | LPWSTR sczSourceFullPath = NULL; | ||
| 1166 | BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT progress = { }; | 1163 | BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT progress = { }; |
| 1164 | BOOL fBeginCalled = FALSE; | ||
| 1167 | BOOL fRetry = FALSE; | 1165 | BOOL fRetry = FALSE; |
| 1166 | DWORD dwChosenSearchPath = 0; | ||
| 1167 | BOOTSTRAPPER_CACHE_OPERATION cacheOperation = BOOTSTRAPPER_CACHE_OPERATION_NONE; | ||
| 1168 | LPWSTR* pwzDownloadUrl = pContainer ? &pContainer->downloadSource.sczUrl : &pPayload->downloadSource.sczUrl; | ||
| 1169 | LPWSTR* pwzSourcePath = pContainer ? &pContainer->sczSourcePath : &pPayload->sczSourcePath; | ||
| 1168 | 1170 | ||
| 1169 | progress.pCacheContext = pContext; | 1171 | progress.pCacheContext = pContext; |
| 1170 | progress.pContainer = pContainer; | 1172 | progress.pContainer = pContainer; |
| @@ -1173,86 +1175,148 @@ static HRESULT AcquireContainerOrPayload( | |||
| 1173 | 1175 | ||
| 1174 | do | 1176 | do |
| 1175 | { | 1177 | { |
| 1176 | LPCWSTR wzDownloadUrl = pContainer ? pContainer->downloadSource.sczUrl : pPayload->downloadSource.sczUrl; | ||
| 1177 | LPCWSTR wzSourcePath = pContainer ? pContainer->sczSourcePath : pPayload->sczSourcePath; | ||
| 1178 | |||
| 1179 | BOOL fFoundLocal = FALSE; | 1178 | BOOL fFoundLocal = FALSE; |
| 1180 | BOOL fCopy = FALSE; | ||
| 1181 | BOOL fDownload = FALSE; | ||
| 1182 | 1179 | ||
| 1180 | pContext->cSearchPaths = 0; | ||
| 1181 | dwChosenSearchPath = 0; | ||
| 1183 | fRetry = FALSE; | 1182 | fRetry = FALSE; |
| 1184 | progress.fCancel = FALSE; | 1183 | progress.fCancel = FALSE; |
| 1184 | fBeginCalled = TRUE; | ||
| 1185 | 1185 | ||
| 1186 | hr = CacheFindLocalSource(wzSourcePath, wzDestinationPath, pContext->pVariables, &fFoundLocal, &sczSourceFullPath); | 1186 | hr = UserExperienceOnCacheAcquireBegin(pContext->pUX, wzPackageOrContainerId, wzPayloadId, pwzSourcePath, pwzDownloadUrl, wzPayloadContainerId, &cacheOperation); |
| 1187 | ExitOnFailure(hr, "Failed to search local source."); | 1187 | ExitOnRootFailure(hr, "BA aborted cache acquire begin."); |
| 1188 | |||
| 1189 | if (fFoundLocal) // the file exists locally, so copy it. | ||
| 1190 | { | ||
| 1191 | // If the source path and destination path are different, do the copy (otherwise there's no point). | ||
| 1192 | hr = PathCompare(sczSourceFullPath, wzDestinationPath, &nEquivalentPaths); | ||
| 1193 | ExitOnFailure(hr, "Failed to determine if payload source path was equivalent to the destination path."); | ||
| 1194 | 1188 | ||
| 1195 | fCopy = (CSTR_EQUAL != nEquivalentPaths); | 1189 | // Skip the Resolving event and probing local paths if the BA already knew it wanted to download or extract. |
| 1196 | } | 1190 | if (BOOTSTRAPPER_CACHE_OPERATION_DOWNLOAD != cacheOperation && |
| 1197 | else // can't find the file locally, so prompt for source. | 1191 | BOOTSTRAPPER_CACHE_OPERATION_EXTRACT != cacheOperation) |
| 1198 | { | 1192 | { |
| 1199 | DWORD dwLogId = pContainer ? (wzPayloadId ? MSG_PROMPT_CONTAINER_PAYLOAD_SOURCE : MSG_PROMPT_CONTAINER_SOURCE) : pPackage ? MSG_PROMPT_PACKAGE_PAYLOAD_SOURCE : MSG_PROMPT_BUNDLE_PAYLOAD_SOURCE; | 1193 | hr = CacheGetLocalSourcePaths(wzRelativePath, *pwzSourcePath, wzDestinationPath, pContext->wzLayoutDirectory, pContext->pVariables, &pContext->rgSearchPaths, &pContext->cSearchPaths); |
| 1200 | LogId(REPORT_STANDARD, dwLogId, wzPackageOrContainerId ? wzPackageOrContainerId : L"", wzPayloadId ? wzPayloadId : L"", sczSourceFullPath); | 1194 | ExitOnFailure(hr, "Failed to search local source."); |
| 1201 | 1195 | ||
| 1202 | hr = PromptForSource(pContext->pUX, wzPackageOrContainerId, wzPayloadId, sczSourceFullPath, wzDownloadUrl, &fRetry, &fDownload); | 1196 | for (DWORD i = 0; i < pContext->cSearchPaths; ++i) |
| 1197 | { | ||
| 1198 | // If the file exists locally, choose it. | ||
| 1199 | if (FileExistsEx(pContext->rgSearchPaths[i], NULL)) | ||
| 1200 | { | ||
| 1201 | dwChosenSearchPath = i; | ||
| 1202 | |||
| 1203 | fFoundLocal = TRUE; | ||
| 1204 | break; | ||
| 1205 | } | ||
| 1206 | } | ||
| 1203 | 1207 | ||
| 1204 | // If the BA requested download then ensure a download url is available (it may have been set | 1208 | if (BOOTSTRAPPER_CACHE_OPERATION_COPY == cacheOperation) |
| 1205 | // during PromptForSource so we need to check again). | 1209 | { |
| 1206 | if (fDownload) | 1210 | if (!fFoundLocal) |
| 1211 | { | ||
| 1212 | cacheOperation = BOOTSTRAPPER_CACHE_OPERATION_NONE; | ||
| 1213 | } | ||
| 1214 | } | ||
| 1215 | else | ||
| 1207 | { | 1216 | { |
| 1208 | wzDownloadUrl = pContainer ? pContainer->downloadSource.sczUrl : pPayload->downloadSource.sczUrl; | 1217 | if (fFoundLocal) // the file exists locally, so copy it. |
| 1209 | if (!wzDownloadUrl || !*wzDownloadUrl) | 1218 | { |
| 1219 | cacheOperation = BOOTSTRAPPER_CACHE_OPERATION_COPY; | ||
| 1220 | } | ||
| 1221 | else if (wzPayloadContainerId) | ||
| 1222 | { | ||
| 1223 | cacheOperation = BOOTSTRAPPER_CACHE_OPERATION_EXTRACT; | ||
| 1224 | } | ||
| 1225 | else if (*pwzDownloadUrl && **pwzDownloadUrl) | ||
| 1210 | { | 1226 | { |
| 1211 | hr = E_INVALIDARG; | 1227 | cacheOperation = BOOTSTRAPPER_CACHE_OPERATION_DOWNLOAD; |
| 1212 | } | 1228 | } |
| 1213 | } | 1229 | } |
| 1214 | 1230 | ||
| 1215 | // Log the error | 1231 | // Let the BA have a chance to override the action, but their chance to change the source is during begin or complete. |
| 1216 | LogExitOnFailure(hr, MSG_PAYLOAD_FILE_NOT_PRESENT, "Failed while prompting for source (original path '%ls').", sczSourceFullPath); | 1232 | hr = UserExperienceOnCacheAcquireResolving(pContext->pUX, wzPackageOrContainerId, wzPayloadId, pContext->rgSearchPaths, pContext->cSearchPaths, fFoundLocal, &dwChosenSearchPath, *pwzDownloadUrl, wzPayloadContainerId, &cacheOperation); |
| 1233 | ExitOnRootFailure(hr, "BA aborted cache acquire resolving."); | ||
| 1217 | } | 1234 | } |
| 1218 | 1235 | ||
| 1219 | if (fCopy) | 1236 | switch (cacheOperation) |
| 1220 | { | 1237 | { |
| 1221 | hr = UserExperienceOnCacheAcquireBegin(pContext->pUX, wzPackageOrContainerId, wzPayloadId, BOOTSTRAPPER_CACHE_OPERATION_COPY, sczSourceFullPath); | 1238 | case BOOTSTRAPPER_CACHE_OPERATION_COPY: |
| 1222 | ExitOnRootFailure(hr, "BA aborted cache acquire begin."); | 1239 | // If the source path and destination path are different, do the copy (otherwise there's no point). |
| 1240 | hr = PathCompare(pContext->rgSearchPaths[dwChosenSearchPath], wzDestinationPath, &nEquivalentPaths); | ||
| 1241 | ExitOnFailure(hr, "Failed to determine if payload paths were equivalent, source: %ls, destination: %ls.", pContext->rgSearchPaths[dwChosenSearchPath], wzDestinationPath); | ||
| 1223 | 1242 | ||
| 1224 | hr = CopyPayload(&progress, INVALID_HANDLE_VALUE, sczSourceFullPath, wzDestinationPath); | 1243 | if (CSTR_EQUAL != nEquivalentPaths) |
| 1225 | // Error handling happens after sending complete message to BA. | 1244 | { |
| 1245 | hr = CopyPayload(&progress, INVALID_HANDLE_VALUE, pContext->rgSearchPaths[dwChosenSearchPath], wzDestinationPath); | ||
| 1246 | // Error handling happens after sending complete message to BA. | ||
| 1247 | |||
| 1248 | // TODO: wait for verification? | ||
| 1249 | // We successfully copied from a source location, set that as the last used source. | ||
| 1250 | if (SUCCEEDED(hr)) | ||
| 1251 | { | ||
| 1252 | CacheSetLastUsedSource(pContext->pVariables, pContext->rgSearchPaths[dwChosenSearchPath], wzRelativePath); | ||
| 1253 | } | ||
| 1254 | } | ||
| 1226 | 1255 | ||
| 1227 | // We successfully copied from a source location, set that as the last used source. | 1256 | fBeginCalled = FALSE; |
| 1228 | if (SUCCEEDED(hr)) | 1257 | UserExperienceOnCacheAcquireComplete(pContext->pUX, wzPackageOrContainerId, wzPayloadId, hr, &fRetry); |
| 1258 | if (fRetry) | ||
| 1229 | { | 1259 | { |
| 1230 | CacheSetLastUsedSource(pContext->pVariables, sczSourceFullPath, wzRelativePath); | 1260 | hr = S_OK; |
| 1231 | } | 1261 | } |
| 1232 | } | ||
| 1233 | else if (fDownload) | ||
| 1234 | { | ||
| 1235 | hr = UserExperienceOnCacheAcquireBegin(pContext->pUX, wzPackageOrContainerId, wzPayloadId, BOOTSTRAPPER_CACHE_OPERATION_DOWNLOAD, wzDownloadUrl); | ||
| 1236 | ExitOnRootFailure(hr, "BA aborted cache download payload begin."); | ||
| 1237 | 1262 | ||
| 1263 | ExitOnFailure(hr, "Failed to acquire payload from: '%ls' to working path: '%ls'", pContext->rgSearchPaths[dwChosenSearchPath], wzDestinationPath); | ||
| 1264 | |||
| 1265 | break; | ||
| 1266 | case BOOTSTRAPPER_CACHE_OPERATION_DOWNLOAD: | ||
| 1238 | hr = DownloadPayload(&progress, wzDestinationPath); | 1267 | hr = DownloadPayload(&progress, wzDestinationPath); |
| 1239 | // Error handling happens after sending complete message to BA. | 1268 | // Error handling happens after sending complete message to BA. |
| 1240 | } | ||
| 1241 | 1269 | ||
| 1242 | if (fCopy || fDownload) | 1270 | fBeginCalled = FALSE; |
| 1243 | { | 1271 | UserExperienceOnCacheAcquireComplete(pContext->pUX, wzPackageOrContainerId, wzPayloadId, hr, &fRetry); |
| 1272 | if (fRetry) | ||
| 1273 | { | ||
| 1274 | hr = S_OK; | ||
| 1275 | } | ||
| 1276 | |||
| 1277 | ExitOnFailure(hr, "Failed to acquire payload from: '%ls' to working path: '%ls'", *pwzDownloadUrl, wzDestinationPath); | ||
| 1278 | |||
| 1279 | break; | ||
| 1280 | case BOOTSTRAPPER_CACHE_OPERATION_EXTRACT: | ||
| 1281 | Assert(pPayload->pContainer); | ||
| 1282 | |||
| 1283 | hr = ApplyExtractContainer(pContext, pPayload->pContainer); | ||
| 1284 | // Error handling happens after sending complete message to BA. | ||
| 1285 | |||
| 1286 | fBeginCalled = FALSE; | ||
| 1287 | UserExperienceOnCacheAcquireComplete(pContext->pUX, wzPackageOrContainerId, wzPayloadId, hr, &fRetry); | ||
| 1288 | if (fRetry) | ||
| 1289 | { | ||
| 1290 | hr = S_OK; | ||
| 1291 | } | ||
| 1292 | |||
| 1293 | ExitOnFailure(hr, "Failed to extract container for payload: %ls", wzPayloadId); | ||
| 1294 | |||
| 1295 | break; | ||
| 1296 | case BOOTSTRAPPER_CACHE_OPERATION_NONE: | ||
| 1297 | hr = E_FILENOTFOUND; | ||
| 1298 | LogErrorId(hr, MSG_RESOLVE_SOURCE_FAILED, wzPayloadId, pPackage ? pPackage->sczId : NULL, pContainer ? pContainer->sczId : NULL); | ||
| 1299 | |||
| 1300 | fBeginCalled = FALSE; | ||
| 1244 | UserExperienceOnCacheAcquireComplete(pContext->pUX, wzPackageOrContainerId, wzPayloadId, hr, &fRetry); | 1301 | UserExperienceOnCacheAcquireComplete(pContext->pUX, wzPackageOrContainerId, wzPayloadId, hr, &fRetry); |
| 1245 | if (fRetry) | 1302 | if (fRetry) |
| 1246 | { | 1303 | { |
| 1247 | hr = S_OK; | 1304 | hr = S_OK; |
| 1248 | } | 1305 | } |
| 1306 | |||
| 1307 | ExitOnFailure(hr, "Failed to resolve source, payload: %ls, package: %ls, container: %ls", wzPayloadId, pPackage ? pPackage->sczId : NULL, pContainer ? pContainer->sczId : NULL); | ||
| 1308 | |||
| 1309 | break; | ||
| 1249 | } | 1310 | } |
| 1250 | ExitOnFailure(hr, "Failed to acquire payload from: '%ls' to working path: '%ls'", fCopy ? sczSourceFullPath : wzDownloadUrl, wzDestinationPath); | ||
| 1251 | } while (fRetry); | 1311 | } while (fRetry); |
| 1252 | ExitOnFailure(hr, "Failed to find external payload to cache."); | ||
| 1253 | 1312 | ||
| 1254 | LExit: | 1313 | LExit: |
| 1255 | ReleaseStr(sczSourceFullPath); | 1314 | if (fBeginCalled) |
| 1315 | { | ||
| 1316 | UserExperienceOnCacheAcquireComplete(pContext->pUX, wzPackageOrContainerId, wzPayloadId, hr, &fRetry); | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | pContext->cSearchPathsMax = max(pContext->cSearchPaths, pContext->cSearchPathsMax); | ||
| 1256 | 1320 | ||
| 1257 | return hr; | 1321 | return hr; |
| 1258 | } | 1322 | } |
| @@ -1355,48 +1419,6 @@ LExit: | |||
| 1355 | return hr; | 1419 | return hr; |
| 1356 | } | 1420 | } |
| 1357 | 1421 | ||
| 1358 | static HRESULT PromptForSource( | ||
| 1359 | __in BURN_USER_EXPERIENCE* pUX, | ||
| 1360 | __in_z LPCWSTR wzPackageOrContainerId, | ||
| 1361 | __in_z_opt LPCWSTR wzPayloadId, | ||
| 1362 | __in_z LPCWSTR wzLocalSource, | ||
| 1363 | __in_z_opt LPCWSTR wzDownloadSource, | ||
| 1364 | __inout BOOL* pfRetry, | ||
| 1365 | __inout BOOL* pfDownload | ||
| 1366 | ) | ||
| 1367 | { | ||
| 1368 | HRESULT hr = S_OK; | ||
| 1369 | BOOTSTRAPPER_RESOLVESOURCE_ACTION action = BOOTSTRAPPER_RESOLVESOURCE_ACTION_NONE; | ||
| 1370 | |||
| 1371 | hr = UserExperienceOnResolveSource(pUX, wzPackageOrContainerId, wzPayloadId, wzLocalSource, wzDownloadSource, &action); | ||
| 1372 | if (FAILED(hr)) | ||
| 1373 | { | ||
| 1374 | ExitFunction(); | ||
| 1375 | } | ||
| 1376 | |||
| 1377 | switch (action) | ||
| 1378 | { | ||
| 1379 | case BOOTSTRAPPER_RESOLVESOURCE_ACTION_NONE: | ||
| 1380 | hr = E_FILENOTFOUND; | ||
| 1381 | break; | ||
| 1382 | |||
| 1383 | case BOOTSTRAPPER_RESOLVESOURCE_ACTION_RETRY: | ||
| 1384 | *pfRetry = TRUE; | ||
| 1385 | break; | ||
| 1386 | |||
| 1387 | case BOOTSTRAPPER_RESOLVESOURCE_ACTION_DOWNLOAD: | ||
| 1388 | *pfDownload = TRUE; | ||
| 1389 | break; | ||
| 1390 | |||
| 1391 | default: | ||
| 1392 | hr = E_INVALIDARG; | ||
| 1393 | break; | ||
| 1394 | } | ||
| 1395 | |||
| 1396 | LExit: | ||
| 1397 | return hr; | ||
| 1398 | } | ||
| 1399 | |||
| 1400 | static HRESULT CopyPayload( | 1422 | static HRESULT CopyPayload( |
| 1401 | __in BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT* pProgress, | 1423 | __in BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT* pProgress, |
| 1402 | __in HANDLE hSourceFile, | 1424 | __in HANDLE hSourceFile, |
diff --git a/src/engine/cache.cpp b/src/engine/cache.cpp index 6ac313e0..84b7f131 100644 --- a/src/engine/cache.cpp +++ b/src/engine/cache.cpp | |||
| @@ -11,7 +11,7 @@ static const DWORD FILE_OPERATION_RETRY_WAIT = 2000; | |||
| 11 | 11 | ||
| 12 | static BOOL vfInitializedCache = FALSE; | 12 | static BOOL vfInitializedCache = FALSE; |
| 13 | static BOOL vfRunningFromCache = FALSE; | 13 | static BOOL vfRunningFromCache = FALSE; |
| 14 | static LPWSTR vsczSourceProcessPath = NULL; | 14 | static LPWSTR vsczSourceProcessFolder = NULL; |
| 15 | static LPWSTR vsczWorkingFolder = NULL; | 15 | static LPWSTR vsczWorkingFolder = NULL; |
| 16 | static LPWSTR vsczDefaultUserPackageCache = NULL; | 16 | static LPWSTR vsczDefaultUserPackageCache = NULL; |
| 17 | static LPWSTR vsczDefaultMachinePackageCache = NULL; | 17 | static LPWSTR vsczDefaultMachinePackageCache = NULL; |
| @@ -140,8 +140,8 @@ extern "C" HRESULT CacheInitialize( | |||
| 140 | wzSourceProcessPath = sczCurrentPath; | 140 | wzSourceProcessPath = sczCurrentPath; |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | hr = StrAllocString(&vsczSourceProcessPath, wzSourceProcessPath, 0); | 143 | hr = PathGetDirectory(wzSourceProcessPath, &vsczSourceProcessFolder); |
| 144 | ExitOnFailure(hr, "Failed to initialize cache source path."); | 144 | ExitOnFailure(hr, "Failed to initialize cache source folder."); |
| 145 | 145 | ||
| 146 | // If we're not running from the cache, ensure the original source is set. | 146 | // If we're not running from the cache, ensure the original source is set. |
| 147 | if (!vfRunningFromCache) | 147 | if (!vfRunningFromCache) |
| @@ -393,112 +393,166 @@ LExit: | |||
| 393 | return hr; | 393 | return hr; |
| 394 | } | 394 | } |
| 395 | 395 | ||
| 396 | extern "C" HRESULT CacheFindLocalSource( | 396 | extern "C" HRESULT CacheGetLocalSourcePaths( |
| 397 | __in_z LPCWSTR wzRelativePath, | ||
| 397 | __in_z LPCWSTR wzSourcePath, | 398 | __in_z LPCWSTR wzSourcePath, |
| 398 | __in_z LPCWSTR wzDestinationPath, | 399 | __in_z LPCWSTR wzDestinationPath, |
| 400 | __in_z_opt LPCWSTR wzLayoutDirectory, | ||
| 399 | __in BURN_VARIABLES* pVariables, | 401 | __in BURN_VARIABLES* pVariables, |
| 400 | __out BOOL* pfFound, | 402 | __inout LPWSTR** prgSearchPaths, |
| 401 | __out_z LPWSTR* psczSourceFullPath | 403 | __out DWORD* pcSearchPaths |
| 402 | ) | 404 | ) |
| 403 | { | 405 | { |
| 404 | HRESULT hr = S_OK; | 406 | HRESULT hr = S_OK; |
| 405 | LPWSTR sczSourceProcessFolder = NULL; | ||
| 406 | LPWSTR sczCurrentPath = NULL; | 407 | LPWSTR sczCurrentPath = NULL; |
| 407 | LPWSTR sczLastSourcePath = NULL; | ||
| 408 | LPWSTR sczLastSourceFolder = NULL; | 408 | LPWSTR sczLastSourceFolder = NULL; |
| 409 | LPWSTR sczLayoutPath = NULL; | 409 | LPWSTR* psczPath = NULL; |
| 410 | LPWSTR sczLayoutFolder = NULL; | 410 | BOOL fPreferSourcePathLocation = FALSE; |
| 411 | LPCWSTR rgwzSearchPaths[4] = { }; | 411 | BOOL fTryLastFolder = FALSE; |
| 412 | BOOL fTryRelativePath = FALSE; | ||
| 413 | BOOL fSourceIsAbsolute = FALSE; | ||
| 412 | DWORD cSearchPaths = 0; | 414 | DWORD cSearchPaths = 0; |
| 413 | 415 | ||
| 414 | // If the source path provided is a full path, obviously that is where we should be looking. | 416 | AssertSz(vfInitializedCache, "Cache wasn't initialized"); |
| 415 | if (PathIsAbsolute(wzSourcePath)) | 417 | |
| 418 | hr = GetLastUsedSourceFolder(pVariables, &sczLastSourceFolder); | ||
| 419 | fPreferSourcePathLocation = !vfRunningFromCache || FAILED(hr); | ||
| 420 | fTryLastFolder = SUCCEEDED(hr) && sczLastSourceFolder && *sczLastSourceFolder && CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, vsczSourceProcessFolder, -1, sczLastSourceFolder, -1); | ||
| 421 | fTryRelativePath = CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, wzSourcePath, -1, wzRelativePath, -1); | ||
| 422 | fSourceIsAbsolute = PathIsAbsolute(wzSourcePath); | ||
| 423 | |||
| 424 | // If the source path provided is a full path, try that first. | ||
| 425 | if (fSourceIsAbsolute) | ||
| 416 | { | 426 | { |
| 417 | rgwzSearchPaths[0] = wzSourcePath; | 427 | hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS); |
| 418 | cSearchPaths = 1; | 428 | ExitOnFailure(hr, "Failed to ensure size for search paths array."); |
| 429 | |||
| 430 | psczPath = *prgSearchPaths + cSearchPaths; | ||
| 431 | ++cSearchPaths; | ||
| 432 | |||
| 433 | hr = StrAllocString(psczPath, wzSourcePath, 0); | ||
| 434 | ExitOnFailure(hr, "Failed to copy absolute source path."); | ||
| 419 | } | 435 | } |
| 420 | else | 436 | |
| 437 | // Try the destination path next. | ||
| 438 | hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS); | ||
| 439 | ExitOnFailure(hr, "Failed to ensure size for search paths array."); | ||
| 440 | |||
| 441 | psczPath = *prgSearchPaths + cSearchPaths; | ||
| 442 | ++cSearchPaths; | ||
| 443 | |||
| 444 | hr = StrAllocString(psczPath, wzDestinationPath, 0); | ||
| 445 | ExitOnFailure(hr, "Failed to copy absolute source path."); | ||
| 446 | |||
| 447 | if (!fSourceIsAbsolute) | ||
| 421 | { | 448 | { |
| 422 | // Use the destination path first. | 449 | // Calculate the source path location. |
| 423 | rgwzSearchPaths[0] = wzDestinationPath; | 450 | // In the case where we are in the bundle's package cache and |
| 424 | cSearchPaths = 1; | 451 | // couldn't find a last used source that will be the package cache path |
| 425 | 452 | // which isn't likely to have what we are looking for. | |
| 426 | // If we're not running from cache or we couldn't get the last source, use | 453 | hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS); |
| 427 | // the source path location. In the case where we are in the bundle's | 454 | ExitOnFailure(hr, "Failed to ensure size for search paths array."); |
| 428 | // package cache and couldn't find a last used source we unfortunately will | 455 | |
| 429 | // be picking the package cache path which isn't likely to have what we are | 456 | hr = PathConcat(vsczSourceProcessFolder, wzSourcePath, &sczCurrentPath); |
| 430 | // looking for. | 457 | ExitOnFailure(hr, "Failed to combine source process folder with source."); |
| 431 | hr = GetLastUsedSourceFolder(pVariables, &sczLastSourceFolder); | 458 | |
| 432 | if (!vfRunningFromCache || FAILED(hr)) | 459 | // If we're not running from cache or we couldn't get the last source, |
| 460 | // try the source path location next. | ||
| 461 | if (fPreferSourcePathLocation) | ||
| 433 | { | 462 | { |
| 434 | hr = PathGetDirectory(vsczSourceProcessPath, &sczSourceProcessFolder); | 463 | (*prgSearchPaths)[cSearchPaths] = sczCurrentPath; |
| 435 | ExitOnFailure(hr, "Failed to get current process directory."); | 464 | ++cSearchPaths; |
| 465 | sczCurrentPath = NULL; | ||
| 466 | } | ||
| 436 | 467 | ||
| 437 | hr = PathConcat(sczSourceProcessFolder, wzSourcePath, &sczCurrentPath); | 468 | // If we have a last used source and it is not the source path location, |
| 469 | // add the last used source to the search path next. | ||
| 470 | if (fTryLastFolder) | ||
| 471 | { | ||
| 472 | hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS); | ||
| 473 | ExitOnFailure(hr, "Failed to ensure size for search paths array."); | ||
| 474 | |||
| 475 | psczPath = *prgSearchPaths + cSearchPaths; | ||
| 476 | ++cSearchPaths; | ||
| 477 | |||
| 478 | hr = PathConcat(sczLastSourceFolder, wzSourcePath, psczPath); | ||
| 438 | ExitOnFailure(hr, "Failed to combine last source with source."); | 479 | ExitOnFailure(hr, "Failed to combine last source with source."); |
| 480 | } | ||
| 439 | 481 | ||
| 440 | rgwzSearchPaths[cSearchPaths] = sczCurrentPath; | 482 | if (!fPreferSourcePathLocation) |
| 483 | { | ||
| 484 | (*prgSearchPaths)[cSearchPaths] = sczCurrentPath; | ||
| 441 | ++cSearchPaths; | 485 | ++cSearchPaths; |
| 486 | sczCurrentPath = NULL; | ||
| 442 | } | 487 | } |
| 443 | 488 | ||
| 444 | // If we have a last used source and it does not duplicate the existing search path, | 489 | // Also consider the layout directory if doing Layout. |
| 445 | // add the last used source to the search path second. | 490 | if (wzLayoutDirectory) |
| 446 | if (sczLastSourceFolder && *sczLastSourceFolder) | ||
| 447 | { | 491 | { |
| 448 | hr = PathConcat(sczLastSourceFolder, wzSourcePath, &sczLastSourcePath); | 492 | hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS); |
| 449 | ExitOnFailure(hr, "Failed to combine last source with source."); | 493 | ExitOnFailure(hr, "Failed to ensure size for search paths array."); |
| 450 | 494 | ||
| 451 | if (1 == cSearchPaths || CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, rgwzSearchPaths[1], -1, sczLastSourcePath, -1)) | 495 | psczPath = *prgSearchPaths + cSearchPaths; |
| 452 | { | 496 | ++cSearchPaths; |
| 453 | rgwzSearchPaths[cSearchPaths] = sczLastSourcePath; | 497 | |
| 454 | ++cSearchPaths; | 498 | hr = PathConcat(wzLayoutDirectory, wzSourcePath, psczPath); |
| 455 | } | 499 | ExitOnFailure(hr, "Failed to combine layout source with source."); |
| 456 | } | 500 | } |
| 501 | } | ||
| 457 | 502 | ||
| 458 | // Also consider the layout directory if set on the command line or by the BA. | 503 | if (fTryRelativePath) |
| 459 | hr = VariableGetString(pVariables, BURN_BUNDLE_LAYOUT_DIRECTORY, &sczLayoutFolder); | 504 | { |
| 460 | if (E_NOTFOUND != hr) | 505 | hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS); |
| 506 | ExitOnFailure(hr, "Failed to ensure size for search paths array."); | ||
| 507 | |||
| 508 | hr = PathConcat(vsczSourceProcessFolder, wzRelativePath, &sczCurrentPath); | ||
| 509 | ExitOnFailure(hr, "Failed to combine source process folder with relative."); | ||
| 510 | |||
| 511 | if (fPreferSourcePathLocation) | ||
| 461 | { | 512 | { |
| 462 | ExitOnFailure(hr, "Failed to get bundle layout directory property."); | 513 | (*prgSearchPaths)[cSearchPaths] = sczCurrentPath; |
| 514 | ++cSearchPaths; | ||
| 515 | sczCurrentPath = NULL; | ||
| 516 | } | ||
| 463 | 517 | ||
| 464 | hr = PathConcat(sczLayoutFolder, wzSourcePath, &sczLayoutPath); | 518 | if (fTryLastFolder) |
| 465 | ExitOnFailure(hr, "Failed to combine layout source with source."); | 519 | { |
| 520 | hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS); | ||
| 521 | ExitOnFailure(hr, "Failed to ensure size for search paths array."); | ||
| 466 | 522 | ||
| 467 | rgwzSearchPaths[cSearchPaths] = sczLayoutPath; | 523 | psczPath = *prgSearchPaths + cSearchPaths; |
| 468 | ++cSearchPaths; | 524 | ++cSearchPaths; |
| 525 | |||
| 526 | hr = PathConcat(sczLastSourceFolder, wzRelativePath, psczPath); | ||
| 527 | ExitOnFailure(hr, "Failed to combine last source with relative."); | ||
| 469 | } | 528 | } |
| 470 | } | ||
| 471 | 529 | ||
| 472 | *pfFound = FALSE; // assume we won't find the file locally. | 530 | if (!fPreferSourcePathLocation) |
| 531 | { | ||
| 532 | (*prgSearchPaths)[cSearchPaths] = sczCurrentPath; | ||
| 533 | ++cSearchPaths; | ||
| 534 | sczCurrentPath = NULL; | ||
| 535 | } | ||
| 473 | 536 | ||
| 474 | for (DWORD i = 0; i < cSearchPaths; ++i) | 537 | if (wzLayoutDirectory) |
| 475 | { | ||
| 476 | // If the file exists locally, copy its path. | ||
| 477 | if (FileExistsEx(rgwzSearchPaths[i], NULL)) | ||
| 478 | { | 538 | { |
| 479 | hr = StrAllocString(psczSourceFullPath, rgwzSearchPaths[i], 0); | 539 | hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS); |
| 480 | ExitOnFailure(hr, "Failed to copy source path."); | 540 | ExitOnFailure(hr, "Failed to ensure size for search paths array."); |
| 481 | 541 | ||
| 482 | *pfFound = TRUE; | 542 | psczPath = *prgSearchPaths + cSearchPaths; |
| 483 | break; | 543 | ++cSearchPaths; |
| 484 | } | ||
| 485 | } | ||
| 486 | 544 | ||
| 487 | // If nothing was found, return the first thing in our search path as the | 545 | hr = PathConcat(wzLayoutDirectory, wzSourcePath, psczPath); |
| 488 | // best path where we thought we should have found the file. | 546 | ExitOnFailure(hr, "Failed to combine layout source with relative."); |
| 489 | if (!*pfFound) | 547 | } |
| 490 | { | ||
| 491 | hr = StrAllocString(psczSourceFullPath, rgwzSearchPaths[0], 0); | ||
| 492 | ExitOnFailure(hr, "Failed to copy source path."); | ||
| 493 | } | 548 | } |
| 494 | 549 | ||
| 495 | LExit: | 550 | LExit: |
| 496 | ReleaseStr(sczCurrentPath); | 551 | ReleaseStr(sczCurrentPath); |
| 497 | ReleaseStr(sczSourceProcessFolder); | ||
| 498 | ReleaseStr(sczLastSourceFolder); | 552 | ReleaseStr(sczLastSourceFolder); |
| 499 | ReleaseStr(sczLastSourcePath); | 553 | |
| 500 | ReleaseStr(sczLayoutFolder); | 554 | AssertSz(cSearchPaths <= BURN_CACHE_MAX_SEARCH_PATHS, "Got more than BURN_CACHE_MAX_SEARCH_PATHS search paths"); |
| 501 | ReleaseStr(sczLayoutPath); | 555 | *pcSearchPaths = cSearchPaths; |
| 502 | 556 | ||
| 503 | return hr; | 557 | return hr; |
| 504 | } | 558 | } |
| @@ -1079,7 +1133,7 @@ extern "C" void CacheUninitialize() | |||
| 1079 | ReleaseNullStr(vsczDefaultMachinePackageCache); | 1133 | ReleaseNullStr(vsczDefaultMachinePackageCache); |
| 1080 | ReleaseNullStr(vsczDefaultUserPackageCache); | 1134 | ReleaseNullStr(vsczDefaultUserPackageCache); |
| 1081 | ReleaseNullStr(vsczWorkingFolder); | 1135 | ReleaseNullStr(vsczWorkingFolder); |
| 1082 | ReleaseNullStr(vsczSourceProcessPath); | 1136 | ReleaseNullStr(vsczSourceProcessFolder); |
| 1083 | 1137 | ||
| 1084 | vfRunningFromCache = FALSE; | 1138 | vfRunningFromCache = FALSE; |
| 1085 | vfInitializedCache = FALSE; | 1139 | vfInitializedCache = FALSE; |
| @@ -1224,17 +1278,12 @@ static HRESULT GetLastUsedSourceFolder( | |||
| 1224 | ) | 1278 | ) |
| 1225 | { | 1279 | { |
| 1226 | HRESULT hr = S_OK; | 1280 | HRESULT hr = S_OK; |
| 1227 | LPWSTR sczOriginalSource = NULL; | ||
| 1228 | 1281 | ||
| 1229 | hr = VariableGetString(pVariables, BURN_BUNDLE_LAST_USED_SOURCE, psczLastSource); | 1282 | hr = VariableGetString(pVariables, BURN_BUNDLE_LAST_USED_SOURCE, psczLastSource); |
| 1230 | if (E_NOTFOUND == hr) | 1283 | if (E_NOTFOUND == hr) |
| 1231 | { | 1284 | { |
| 1232 | // Try the original source folder. | 1285 | // Try the original source folder. |
| 1233 | hr = VariableGetString(pVariables, BURN_BUNDLE_ORIGINAL_SOURCE, &sczOriginalSource); | 1286 | hr = VariableGetString(pVariables, BURN_BUNDLE_ORIGINAL_SOURCE_FOLDER, psczLastSource); |
| 1234 | if (SUCCEEDED(hr)) | ||
| 1235 | { | ||
| 1236 | hr = PathGetDirectory(sczOriginalSource, psczLastSource); | ||
| 1237 | } | ||
| 1238 | } | 1287 | } |
| 1239 | 1288 | ||
| 1240 | return hr; | 1289 | return hr; |
diff --git a/src/engine/cache.h b/src/engine/cache.h index acc7acb7..eb964f58 100644 --- a/src/engine/cache.h +++ b/src/engine/cache.h | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | #pragma once | 1 | #pragma once |
| 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 2 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
| 3 | 3 | ||
| 4 | #define BURN_CACHE_MAX_SEARCH_PATHS 7 | ||
| 4 | 5 | ||
| 5 | #ifdef __cplusplus | 6 | #ifdef __cplusplus |
| 6 | extern "C" { | 7 | extern "C" { |
| @@ -52,12 +53,14 @@ HRESULT CacheGetResumePath( | |||
| 52 | __in_z LPCWSTR wzPayloadWorkingPath, | 53 | __in_z LPCWSTR wzPayloadWorkingPath, |
| 53 | __deref_out_z LPWSTR* psczResumePath | 54 | __deref_out_z LPWSTR* psczResumePath |
| 54 | ); | 55 | ); |
| 55 | HRESULT CacheFindLocalSource( | 56 | HRESULT CacheGetLocalSourcePaths( |
| 57 | __in_z LPCWSTR wzRelativePath, | ||
| 56 | __in_z LPCWSTR wzSourcePath, | 58 | __in_z LPCWSTR wzSourcePath, |
| 57 | __in_z LPCWSTR wzDestinationPath, | 59 | __in_z LPCWSTR wzDestinationPath, |
| 60 | __in_z_opt LPCWSTR wzLayoutDirectory, | ||
| 58 | __in BURN_VARIABLES* pVariables, | 61 | __in BURN_VARIABLES* pVariables, |
| 59 | __out BOOL* pfFound, | 62 | __inout LPWSTR** prgSearchPaths, |
| 60 | __out_z LPWSTR* psczSourceFullPath | 63 | __out DWORD* pcSearchPaths |
| 61 | ); | 64 | ); |
| 62 | HRESULT CacheSetLastUsedSource( | 65 | HRESULT CacheSetLastUsedSource( |
| 63 | __in BURN_VARIABLES* pVariables, | 66 | __in BURN_VARIABLES* pVariables, |
diff --git a/src/engine/engine.mc b/src/engine/engine.mc index c8b46806..f03bc1ea 100644 --- a/src/engine/engine.mc +++ b/src/engine/engine.mc | |||
| @@ -151,9 +151,9 @@ Bundle global condition check didn't succeed - aborting without loading applicat | |||
| 151 | 151 | ||
| 152 | MessageId=54 | 152 | MessageId=54 |
| 153 | Severity=Error | 153 | Severity=Error |
| 154 | SymbolicName=MSG_PAYLOAD_FILE_NOT_PRESENT | 154 | SymbolicName=MSG_RESOLVE_SOURCE_FAILED |
| 155 | Language=English | 155 | Language=English |
| 156 | Failed to resolve source for file: %2!ls!, error: %1!ls!. | 156 | Failed to resolve source for payload: %2!ls!, package: %3!ls!, container: %4!ls!, error: %1!ls!. |
| 157 | . | 157 | . |
| 158 | 158 | ||
| 159 | MessageId=55 | 159 | MessageId=55 |
| @@ -724,34 +724,6 @@ 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=340 | ||
| 728 | Severity=Warning | ||
| 729 | SymbolicName=MSG_PROMPT_BUNDLE_PAYLOAD_SOURCE | ||
| 730 | Language=English | ||
| 731 | Prompt for source of bundle payload: %2!ls!, path: %3!ls! | ||
| 732 | . | ||
| 733 | |||
| 734 | MessageId=341 | ||
| 735 | Severity=Warning | ||
| 736 | SymbolicName=MSG_PROMPT_CONTAINER_SOURCE | ||
| 737 | Language=English | ||
| 738 | Prompt for source of container: %1!ls!, path: %3!ls! | ||
| 739 | . | ||
| 740 | |||
| 741 | MessageId=342 | ||
| 742 | Severity=Warning | ||
| 743 | SymbolicName=MSG_PROMPT_CONTAINER_PAYLOAD_SOURCE | ||
| 744 | Language=English | ||
| 745 | Prompt for source of container: %1!ls!, payload: %2!ls!, path: %3!ls! | ||
| 746 | . | ||
| 747 | |||
| 748 | MessageId=343 | ||
| 749 | Severity=Warning | ||
| 750 | SymbolicName=MSG_PROMPT_PACKAGE_PAYLOAD_SOURCE | ||
| 751 | Language=English | ||
| 752 | Prompt for source of package: %1!ls!, payload: %2!ls!, path: %3!ls! | ||
| 753 | . | ||
| 754 | |||
| 755 | MessageId=348 | 727 | MessageId=348 |
| 756 | Severity=Warning | 728 | Severity=Warning |
| 757 | SymbolicName=MSG_APPLY_RETRYING_PACKAGE | 729 | SymbolicName=MSG_APPLY_RETRYING_PACKAGE |
diff --git a/src/engine/externalengine.cpp b/src/engine/externalengine.cpp index 7e9bb25c..d6c44736 100644 --- a/src/engine/externalengine.cpp +++ b/src/engine/externalengine.cpp | |||
| @@ -269,8 +269,7 @@ HRESULT ExternalEngineSetUpdate( | |||
| 269 | ) | 269 | ) |
| 270 | { | 270 | { |
| 271 | HRESULT hr = S_OK; | 271 | HRESULT hr = S_OK; |
| 272 | LPCWSTR sczId = NULL; | 272 | LPWSTR sczFilePath = NULL; |
| 273 | LPWSTR sczLocalSource = NULL; | ||
| 274 | LPWSTR sczCommandline = NULL; | 273 | LPWSTR sczCommandline = NULL; |
| 275 | UUID guid = { }; | 274 | UUID guid = { }; |
| 276 | WCHAR wzGuid[39]; | 275 | WCHAR wzGuid[39]; |
| @@ -296,38 +295,30 @@ HRESULT ExternalEngineSetUpdate( | |||
| 296 | { | 295 | { |
| 297 | UpdateUninitialize(&pEngineState->update); | 296 | UpdateUninitialize(&pEngineState->update); |
| 298 | 297 | ||
| 299 | if (!wzLocalSource || !*wzLocalSource) | ||
| 300 | { | ||
| 301 | hr = StrAllocFormatted(&sczLocalSource, L"update\\%ls", pEngineState->registration.sczExecutableName); | ||
| 302 | ExitOnFailure(hr, "Failed to default local update source"); | ||
| 303 | } | ||
| 304 | |||
| 305 | hr = CoreRecreateCommandLine(&sczCommandline, BOOTSTRAPPER_ACTION_INSTALL, pEngineState->command.display, pEngineState->command.restart, BOOTSTRAPPER_RELATION_NONE, FALSE, pEngineState->registration.sczActiveParent, pEngineState->registration.sczAncestors, NULL, pEngineState->command.wzCommandLine); | 298 | hr = CoreRecreateCommandLine(&sczCommandline, BOOTSTRAPPER_ACTION_INSTALL, pEngineState->command.display, pEngineState->command.restart, BOOTSTRAPPER_RELATION_NONE, FALSE, pEngineState->registration.sczActiveParent, pEngineState->registration.sczAncestors, NULL, pEngineState->command.wzCommandLine); |
| 306 | ExitOnFailure(hr, "Failed to recreate command-line for update bundle."); | 299 | ExitOnFailure(hr, "Failed to recreate command-line for update bundle."); |
| 307 | 300 | ||
| 308 | // Per-user bundles would fail to use the downloaded update bundle, as the existing install would already be cached | 301 | // Bundles would fail to use the downloaded update bundle, as the running bundle would be one of the search paths. |
| 309 | // at the registration id's location. Here I am generating a random guid, but in the future it would be nice if the | 302 | // Here I am generating a random guid, but in the future it would be nice if the feed would provide the ID of the update. |
| 310 | // feed would provide the ID of the update. | 303 | rs = ::UuidCreate(&guid); |
| 311 | if (!pEngineState->registration.fPerMachine) | 304 | hr = HRESULT_FROM_RPC(rs); |
| 305 | ExitOnFailure(hr, "Failed to create bundle update guid."); | ||
| 306 | |||
| 307 | if (!::StringFromGUID2(guid, wzGuid, countof(wzGuid))) | ||
| 312 | { | 308 | { |
| 313 | rs = ::UuidCreate(&guid); | 309 | hr = E_OUTOFMEMORY; |
| 314 | hr = HRESULT_FROM_RPC(rs); | 310 | ExitOnRootFailure(hr, "Failed to convert bundle update guid into string."); |
| 315 | ExitOnFailure(hr, "Failed to create bundle update guid."); | 311 | } |
| 316 | 312 | ||
| 317 | if (!::StringFromGUID2(guid, wzGuid, countof(wzGuid))) | 313 | hr = StrAllocFormatted(&sczFilePath, L"%ls\\%ls", wzGuid, pEngineState->registration.sczExecutableName); |
| 318 | { | 314 | ExitOnFailure(hr, "Failed to build bundle update file path."); |
| 319 | hr = E_OUTOFMEMORY; | ||
| 320 | ExitOnRootFailure(hr, "Failed to convert bundle update guid into string."); | ||
| 321 | } | ||
| 322 | 315 | ||
| 323 | sczId = wzGuid; | 316 | if (!wzLocalSource || !*wzLocalSource) |
| 324 | } | ||
| 325 | else | ||
| 326 | { | 317 | { |
| 327 | sczId = pEngineState->registration.sczId; | 318 | wzLocalSource = sczFilePath; |
| 328 | } | 319 | } |
| 329 | 320 | ||
| 330 | hr = PseudoBundleInitialize(FILEMAKEVERSION(rmj, rmm, rup, rpr), &pEngineState->update.package, FALSE, sczId, BOOTSTRAPPER_RELATION_UPDATE, BOOTSTRAPPER_PACKAGE_STATE_ABSENT, FALSE, pEngineState->registration.sczExecutableName, sczLocalSource ? sczLocalSource : wzLocalSource, wzDownloadSource, qwSize, TRUE, sczCommandline, NULL, NULL, NULL, rgbHash, cbHash); | 321 | hr = PseudoBundleInitialize(FILEMAKEVERSION(rmj, rmm, rup, rpr), &pEngineState->update.package, FALSE, pEngineState->registration.sczId, BOOTSTRAPPER_RELATION_UPDATE, BOOTSTRAPPER_PACKAGE_STATE_ABSENT, FALSE, sczFilePath, wzLocalSource, wzDownloadSource, qwSize, TRUE, sczCommandline, NULL, NULL, NULL, rgbHash, cbHash); |
| 331 | ExitOnFailure(hr, "Failed to set update bundle."); | 322 | ExitOnFailure(hr, "Failed to set update bundle."); |
| 332 | 323 | ||
| 333 | pEngineState->update.fUpdateAvailable = TRUE; | 324 | pEngineState->update.fUpdateAvailable = TRUE; |
| @@ -337,7 +328,7 @@ LExit: | |||
| 337 | ::LeaveCriticalSection(&pEngineState->userExperience.csEngineActive); | 328 | ::LeaveCriticalSection(&pEngineState->userExperience.csEngineActive); |
| 338 | 329 | ||
| 339 | ReleaseStr(sczCommandline); | 330 | ReleaseStr(sczCommandline); |
| 340 | ReleaseStr(sczLocalSource); | 331 | ReleaseStr(sczFilePath); |
| 341 | 332 | ||
| 342 | return hr; | 333 | return hr; |
| 343 | } | 334 | } |
diff --git a/src/engine/userexperience.cpp b/src/engine/userexperience.cpp index b6bd65dc..f6ae1491 100644 --- a/src/engine/userexperience.cpp +++ b/src/engine/userexperience.cpp | |||
| @@ -395,29 +395,46 @@ EXTERN_C BAAPI UserExperienceOnCacheAcquireBegin( | |||
| 395 | __in BURN_USER_EXPERIENCE* pUserExperience, | 395 | __in BURN_USER_EXPERIENCE* pUserExperience, |
| 396 | __in_z_opt LPCWSTR wzPackageOrContainerId, | 396 | __in_z_opt LPCWSTR wzPackageOrContainerId, |
| 397 | __in_z_opt LPCWSTR wzPayloadId, | 397 | __in_z_opt LPCWSTR wzPayloadId, |
| 398 | __in BOOTSTRAPPER_CACHE_OPERATION operation, | 398 | __in_z LPWSTR* pwzSource, |
| 399 | __in_z LPCWSTR wzSource | 399 | __in_z LPWSTR* pwzDownloadUrl, |
| 400 | __in_z_opt LPCWSTR wzPayloadContainerId, | ||
| 401 | __out BOOTSTRAPPER_CACHE_OPERATION* pCacheOperation | ||
| 400 | ) | 402 | ) |
| 401 | { | 403 | { |
| 402 | HRESULT hr = S_OK; | 404 | HRESULT hr = S_OK; |
| 403 | BA_ONCACHEACQUIREBEGIN_ARGS args = { }; | 405 | BA_ONCACHEACQUIREBEGIN_ARGS args = { }; |
| 404 | BA_ONCACHEACQUIREBEGIN_RESULTS results = { }; | 406 | BA_ONCACHEACQUIREBEGIN_RESULTS results = { }; |
| 407 | *pCacheOperation = BOOTSTRAPPER_CACHE_OPERATION_NONE; | ||
| 405 | 408 | ||
| 406 | args.cbSize = sizeof(args); | 409 | args.cbSize = sizeof(args); |
| 407 | args.wzPackageOrContainerId = wzPackageOrContainerId; | 410 | args.wzPackageOrContainerId = wzPackageOrContainerId; |
| 408 | args.wzPayloadId = wzPayloadId; | 411 | args.wzPayloadId = wzPayloadId; |
| 409 | args.operation = operation; | 412 | args.wzSource = *pwzSource; |
| 410 | args.wzSource = wzSource; | 413 | args.wzDownloadUrl = *pwzDownloadUrl; |
| 414 | args.wzPayloadContainerId = wzPayloadContainerId; | ||
| 415 | args.recommendation = *pCacheOperation; | ||
| 411 | 416 | ||
| 412 | results.cbSize = sizeof(results); | 417 | results.cbSize = sizeof(results); |
| 418 | results.action = *pCacheOperation; | ||
| 413 | 419 | ||
| 414 | hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIREBEGIN, &args, &results); | 420 | hr = SendBAMessageFromInactiveEngine(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIREBEGIN, &args, &results); |
| 415 | ExitOnFailure(hr, "BA OnCacheAcquireBegin failed."); | 421 | ExitOnFailure(hr, "BA OnCacheAcquireBegin failed."); |
| 416 | 422 | ||
| 417 | if (results.fCancel) | 423 | if (results.fCancel) |
| 418 | { | 424 | { |
| 419 | hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT); | 425 | hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT); |
| 420 | } | 426 | } |
| 427 | else | ||
| 428 | { | ||
| 429 | // Verify the BA requested an action that is possible. | ||
| 430 | if (BOOTSTRAPPER_CACHE_OPERATION_DOWNLOAD == results.action && *pwzDownloadUrl && **pwzDownloadUrl || | ||
| 431 | BOOTSTRAPPER_CACHE_OPERATION_EXTRACT == results.action && wzPayloadContainerId || | ||
| 432 | BOOTSTRAPPER_CACHE_OPERATION_COPY == results.action || | ||
| 433 | BOOTSTRAPPER_CACHE_OPERATION_NONE == results.action) | ||
| 434 | { | ||
| 435 | *pCacheOperation = results.action; | ||
| 436 | } | ||
| 437 | } | ||
| 421 | 438 | ||
| 422 | LExit: | 439 | LExit: |
| 423 | return hr; | 440 | return hr; |
| @@ -444,7 +461,7 @@ EXTERN_C BAAPI UserExperienceOnCacheAcquireComplete( | |||
| 444 | results.cbSize = sizeof(results); | 461 | results.cbSize = sizeof(results); |
| 445 | results.action = args.recommendation; | 462 | results.action = args.recommendation; |
| 446 | 463 | ||
| 447 | hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIRECOMPLETE, &args, &results); | 464 | hr = SendBAMessageFromInactiveEngine(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIRECOMPLETE, &args, &results); |
| 448 | ExitOnFailure(hr, "BA OnCacheAcquireComplete failed."); | 465 | ExitOnFailure(hr, "BA OnCacheAcquireComplete failed."); |
| 449 | 466 | ||
| 450 | if (FAILED(hrStatus)) | 467 | if (FAILED(hrStatus)) |
| @@ -490,6 +507,64 @@ LExit: | |||
| 490 | return hr; | 507 | return hr; |
| 491 | } | 508 | } |
| 492 | 509 | ||
| 510 | EXTERN_C BAAPI UserExperienceOnCacheAcquireResolving( | ||
| 511 | __in BURN_USER_EXPERIENCE* pUserExperience, | ||
| 512 | __in_z_opt LPCWSTR wzPackageOrContainerId, | ||
| 513 | __in_z_opt LPCWSTR wzPayloadId, | ||
| 514 | __in_z LPWSTR* rgSearchPaths, | ||
| 515 | __in DWORD cSearchPaths, | ||
| 516 | __in BOOL fFoundLocal, | ||
| 517 | __in DWORD* pdwChosenSearchPath, | ||
| 518 | __in_z_opt LPCWSTR wzDownloadUrl, | ||
| 519 | __in_z_opt LPCWSTR wzPayloadContainerId, | ||
| 520 | __inout BOOTSTRAPPER_CACHE_OPERATION* pCacheOperation | ||
| 521 | ) | ||
| 522 | { | ||
| 523 | HRESULT hr = S_OK; | ||
| 524 | BA_ONCACHEACQUIRERESOLVING_ARGS args = { }; | ||
| 525 | BA_ONCACHEACQUIRERESOLVING_RESULTS results = { }; | ||
| 526 | |||
| 527 | args.cbSize = sizeof(args); | ||
| 528 | args.wzPackageOrContainerId = wzPackageOrContainerId; | ||
| 529 | args.wzPayloadId = wzPayloadId; | ||
| 530 | args.rgSearchPaths = const_cast<LPCWSTR*>(rgSearchPaths); | ||
| 531 | args.cSearchPaths = cSearchPaths; | ||
| 532 | args.fFoundLocal = fFoundLocal; | ||
| 533 | args.dwRecommendedSearchPath = *pdwChosenSearchPath; | ||
| 534 | args.wzDownloadUrl = wzDownloadUrl; | ||
| 535 | args.recommendation = *pCacheOperation; | ||
| 536 | |||
| 537 | results.cbSize = sizeof(results); | ||
| 538 | results.dwChosenSearchPath = *pdwChosenSearchPath; | ||
| 539 | results.action = *pCacheOperation; | ||
| 540 | |||
| 541 | hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIRERESOLVING, &args, &results); | ||
| 542 | ExitOnFailure(hr, "BA OnCacheAcquireResolving failed."); | ||
| 543 | |||
| 544 | if (results.fCancel) | ||
| 545 | { | ||
| 546 | hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT); | ||
| 547 | } | ||
| 548 | else | ||
| 549 | { | ||
| 550 | // Verify the BA requested an action that is possible. | ||
| 551 | if (BOOTSTRAPPER_CACHE_OPERATION_DOWNLOAD == results.action && wzDownloadUrl && *wzDownloadUrl || | ||
| 552 | BOOTSTRAPPER_CACHE_OPERATION_EXTRACT == results.action && wzPayloadContainerId || | ||
| 553 | BOOTSTRAPPER_CACHE_OPERATION_NONE == results.action) | ||
| 554 | { | ||
| 555 | *pCacheOperation = results.action; | ||
| 556 | } | ||
| 557 | else if (BOOTSTRAPPER_CACHE_OPERATION_COPY == results.action && results.dwChosenSearchPath < cSearchPaths) | ||
| 558 | { | ||
| 559 | *pdwChosenSearchPath = results.dwChosenSearchPath; | ||
| 560 | *pCacheOperation = results.action; | ||
| 561 | } | ||
| 562 | } | ||
| 563 | |||
| 564 | LExit: | ||
| 565 | return hr; | ||
| 566 | } | ||
| 567 | |||
| 493 | EXTERN_C BAAPI UserExperienceOnCacheBegin( | 568 | EXTERN_C BAAPI UserExperienceOnCacheBegin( |
| 494 | __in BURN_USER_EXPERIENCE* pUserExperience | 569 | __in BURN_USER_EXPERIENCE* pUserExperience |
| 495 | ) | 570 | ) |
| @@ -1861,45 +1936,6 @@ LExit: | |||
| 1861 | return hr; | 1936 | return hr; |
| 1862 | } | 1937 | } |
| 1863 | 1938 | ||
| 1864 | EXTERN_C BAAPI UserExperienceOnResolveSource( | ||
| 1865 | __in BURN_USER_EXPERIENCE* pUserExperience, | ||
| 1866 | __in_z LPCWSTR wzPackageOrContainerId, | ||
| 1867 | __in_z_opt LPCWSTR wzPayloadId, | ||
| 1868 | __in_z LPCWSTR wzLocalSource, | ||
| 1869 | __in_z_opt LPCWSTR wzDownloadSource, | ||
| 1870 | __inout BOOTSTRAPPER_RESOLVESOURCE_ACTION* pAction | ||
| 1871 | ) | ||
| 1872 | { | ||
| 1873 | HRESULT hr = S_OK; | ||
| 1874 | BA_ONRESOLVESOURCE_ARGS args = { }; | ||
| 1875 | BA_ONRESOLVESOURCE_RESULTS results = { }; | ||
| 1876 | |||
| 1877 | args.cbSize = sizeof(args); | ||
| 1878 | args.wzPackageOrContainerId = wzPackageOrContainerId; | ||
| 1879 | args.wzPayloadId = wzPayloadId; | ||
| 1880 | args.wzLocalSource = wzLocalSource; | ||
| 1881 | args.wzDownloadSource = wzDownloadSource; | ||
| 1882 | args.recommendation = *pAction; | ||
| 1883 | |||
| 1884 | results.cbSize = sizeof(results); | ||
| 1885 | results.action = *pAction; | ||
| 1886 | |||
| 1887 | hr = SendBAMessageFromInactiveEngine(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONRESOLVESOURCE, &args, &results); | ||
| 1888 | ExitOnFailure(hr, "BA OnResolveSource failed."); | ||
| 1889 | |||
| 1890 | if (results.fCancel) | ||
| 1891 | { | ||
| 1892 | hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT); | ||
| 1893 | } | ||
| 1894 | else | ||
| 1895 | { | ||
| 1896 | *pAction = results.action; | ||
| 1897 | } | ||
| 1898 | |||
| 1899 | LExit: | ||
| 1900 | return hr; | ||
| 1901 | } | ||
| 1902 | |||
| 1903 | EXTERN_C BAAPI UserExperienceOnRollbackMsiTransactionBegin( | 1939 | EXTERN_C BAAPI UserExperienceOnRollbackMsiTransactionBegin( |
| 1904 | __in BURN_USER_EXPERIENCE* pUserExperience, | 1940 | __in BURN_USER_EXPERIENCE* pUserExperience, |
| 1905 | __in LPCWSTR wzTransactionId | 1941 | __in LPCWSTR wzTransactionId |
diff --git a/src/engine/userexperience.h b/src/engine/userexperience.h index a1fb67a0..dd1fb086 100644 --- a/src/engine/userexperience.h +++ b/src/engine/userexperience.h | |||
| @@ -126,8 +126,10 @@ BAAPI UserExperienceOnCacheAcquireBegin( | |||
| 126 | __in BURN_USER_EXPERIENCE* pUserExperience, | 126 | __in BURN_USER_EXPERIENCE* pUserExperience, |
| 127 | __in_z_opt LPCWSTR wzPackageOrContainerId, | 127 | __in_z_opt LPCWSTR wzPackageOrContainerId, |
| 128 | __in_z_opt LPCWSTR wzPayloadId, | 128 | __in_z_opt LPCWSTR wzPayloadId, |
| 129 | __in BOOTSTRAPPER_CACHE_OPERATION operation, | 129 | __in_z LPWSTR* pwzSource, |
| 130 | __in_z LPCWSTR wzSource | 130 | __in_z LPWSTR* pwzDownloadUrl, |
| 131 | __in_z_opt LPCWSTR wzPayloadContainerId, | ||
| 132 | __out BOOTSTRAPPER_CACHE_OPERATION* pCacheOperation | ||
| 131 | ); | 133 | ); |
| 132 | BAAPI UserExperienceOnCacheAcquireComplete( | 134 | BAAPI UserExperienceOnCacheAcquireComplete( |
| 133 | __in BURN_USER_EXPERIENCE* pUserExperience, | 135 | __in BURN_USER_EXPERIENCE* pUserExperience, |
| @@ -144,6 +146,18 @@ BAAPI UserExperienceOnCacheAcquireProgress( | |||
| 144 | __in DWORD64 dw64Total, | 146 | __in DWORD64 dw64Total, |
| 145 | __in DWORD dwOverallPercentage | 147 | __in DWORD dwOverallPercentage |
| 146 | ); | 148 | ); |
| 149 | BAAPI UserExperienceOnCacheAcquireResolving( | ||
| 150 | __in BURN_USER_EXPERIENCE* pUserExperience, | ||
| 151 | __in_z_opt LPCWSTR wzPackageOrContainerId, | ||
| 152 | __in_z_opt LPCWSTR wzPayloadId, | ||
| 153 | __in_z LPWSTR* rgSearchPaths, | ||
| 154 | __in DWORD cSearchPaths, | ||
| 155 | __in BOOL fFoundLocal, | ||
| 156 | __in DWORD* pdwChosenSearchPath, | ||
| 157 | __in_z_opt LPCWSTR wzDownloadUrl, | ||
| 158 | __in_z_opt LPCWSTR wzPayloadContainerId, | ||
| 159 | __inout BOOTSTRAPPER_CACHE_OPERATION* pCacheOperation | ||
| 160 | ); | ||
| 147 | BAAPI UserExperienceOnCacheBegin( | 161 | BAAPI UserExperienceOnCacheBegin( |
| 148 | __in BURN_USER_EXPERIENCE* pUserExperience | 162 | __in BURN_USER_EXPERIENCE* pUserExperience |
| 149 | ); | 163 | ); |
| @@ -426,14 +440,6 @@ BAAPI UserExperienceOnRegisterComplete( | |||
| 426 | __in BURN_USER_EXPERIENCE* pUserExperience, | 440 | __in BURN_USER_EXPERIENCE* pUserExperience, |
| 427 | __in HRESULT hrStatus | 441 | __in HRESULT hrStatus |
| 428 | ); | 442 | ); |
| 429 | BAAPI UserExperienceOnResolveSource( | ||
| 430 | __in BURN_USER_EXPERIENCE* pUserExperience, | ||
| 431 | __in_z LPCWSTR wzPackageOrContainerId, | ||
| 432 | __in_z_opt LPCWSTR wzPayloadId, | ||
| 433 | __in_z LPCWSTR wzLocalSource, | ||
| 434 | __in_z_opt LPCWSTR wzDownloadSource, | ||
| 435 | __inout BOOTSTRAPPER_RESOLVESOURCE_ACTION* pAction | ||
| 436 | ); | ||
| 437 | BAAPI UserExperienceOnRollbackMsiTransactionBegin( | 443 | BAAPI UserExperienceOnRollbackMsiTransactionBegin( |
| 438 | __in BURN_USER_EXPERIENCE* pUserExperience, | 444 | __in BURN_USER_EXPERIENCE* pUserExperience, |
| 439 | __in LPCWSTR wzTransactionId | 445 | __in LPCWSTR wzTransactionId |
