diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2021-04-16 10:20:41 -0500 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2021-04-19 23:12:55 -0500 |
commit | 5d6046bee5021052da4a666c1e2ceeb0f16af349 (patch) | |
tree | 589ddcbe270e2e4df8cffdbd26792bcee4c29e1c | |
parent | b941c2754748251520dc5032d11396c9844fad8e (diff) | |
download | wix-5d6046bee5021052da4a666c1e2ceeb0f16af349.tar.gz wix-5d6046bee5021052da4a666c1e2ceeb0f16af349.tar.bz2 wix-5d6046bee5021052da4a666c1e2ceeb0f16af349.zip |
Replace OnResolveSource with OnCacheAcquireResolving
Inactivate the engine during OnCacheAcquireBegin and Complete to allow setting the source from there.
Fixes #3640
Contributes to #5253
-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 |