Replace OnResolveSource with OnCacheAcquireResolving
Inactivate the engine during OnCacheAcquireBegin and Complete to allow setting the source from there. Fixes #3640 Contributes to #5253
Sean Hall committed
Apr 16, 2021 at 10:20 UTC
5d6046bee5021052da4a666c1e2ceeb0f16af349
8 files changed
+413
-331
src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
+33
-30
@@ -54,8 +54,13 @@ enum BOOTSTRAPPER_RELATED_OPERATION
54
55
enum BOOTSTRAPPER_CACHE_OPERATION
56
{
57
+ // There is no source available.
58
+ BOOTSTRAPPER_CACHE_OPERATION_NONE,
59
+ // Copy the payload or container from the chosen local source.
60
BOOTSTRAPPER_CACHE_OPERATION_COPY,
61
+ // Download the payload or container using the download URL.
62
BOOTSTRAPPER_CACHE_OPERATION_DOWNLOAD,
63
+ // Extract the payload from the container.
64
BOOTSTRAPPER_CACHE_OPERATION_EXTRACT,
65
};
66
@@ -112,7 +117,7 @@ enum BOOTSTRAPPER_APPLICATION_MESSAGE
117
BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPACKAGEBEGIN,
118
BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIREBEGIN,
119
BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIREPROGRESS,
115
- BOOTSTRAPPER_APPLICATION_MESSAGE_ONRESOLVESOURCE,
120
+ BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIRERESOLVING,
121
BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIRECOMPLETE,
122
BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEVERIFYBEGIN,
123
BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEVERIFYCOMPLETE,
@@ -158,7 +163,7 @@ enum BOOTSTRAPPER_APPLYCOMPLETE_ACTION
163
enum BOOTSTRAPPER_CACHEACQUIRECOMPLETE_ACTION
164
{
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.
167
// Ignored if hrStatus is a success.
168
BOOTSTRAPPER_CACHEACQUIRECOMPLETE_ACTION_RETRY,
169
};
@@ -202,16 +207,6 @@ enum BOOTSTRAPPER_EXECUTEPACKAGECOMPLETE_ACTION
207
BOOTSTRAPPER_EXECUTEPACKAGECOMPLETE_ACTION_SUSPEND,
208
};
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
-
210
enum BOOTSTRAPPER_SHUTDOWN_ACTION
211
{
212
BOOTSTRAPPER_SHUTDOWN_ACTION_NONE,
@@ -315,14 +310,17 @@ struct BA_ONCACHEACQUIREBEGIN_ARGS
310
DWORD cbSize;
311
LPCWSTR wzPackageOrContainerId;
312
LPCWSTR wzPayloadId;
318
- BOOTSTRAPPER_CACHE_OPERATION operation;
313
LPCWSTR wzSource;
314
+ LPCWSTR wzDownloadUrl;
315
+ LPCWSTR wzPayloadContainerId;
316
+ BOOTSTRAPPER_CACHE_OPERATION recommendation;
317
};
318
319
struct BA_ONCACHEACQUIREBEGIN_RESULTS
320
{
321
DWORD cbSize;
322
BOOL fCancel;
323
+ BOOTSTRAPPER_CACHE_OPERATION action;
324
};
325
326
struct BA_ONCACHEACQUIRECOMPLETE_ARGS
@@ -356,6 +354,28 @@ struct BA_ONCACHEACQUIREPROGRESS_RESULTS
354
BOOL fCancel;
355
};
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
+
379
struct BA_ONCACHEBEGIN_ARGS
380
{
381
DWORD cbSize;
@@ -1013,23 +1033,6 @@ struct BA_ONREGISTERCOMPLETE_RESULTS
1033
DWORD cbSize;
1034
};
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
-
1036
struct BA_ONROLLBACKMSITRANSACTIONBEGIN_ARGS
1037
{
1038
DWORD cbSize;
src/engine/apply.cpp
+132
-110
@@ -23,6 +23,9 @@ typedef struct _BURN_CACHE_CONTEXT
23
DWORD64 qwTotalCacheSize;
24
DWORD64 qwSuccessfulCacheProgress;
25
LPCWSTR wzLayoutDirectory;
26
+ LPWSTR* rgSearchPaths;
27
+ DWORD cSearchPaths;
28
+ DWORD cSearchPathsMax;
29
} BURN_CACHE_CONTEXT;
30
31
typedef struct _BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT
@@ -113,15 +116,6 @@ static HRESULT LayoutOrCacheContainerOrPayload(
116
__in DWORD cTryAgainAttempts,
117
__out BOOL* pfRetry
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
- );
119
static HRESULT CopyPayload(
120
__in BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT* pProgress,
121
__in HANDLE hSourceFile,
@@ -485,6 +479,9 @@ extern "C" HRESULT ApplyCache(
479
cacheContext.qwTotalCacheSize = pPlan->qwCacheSizeTotal;
480
cacheContext.wzLayoutDirectory = pPlan->sczLayoutDirectory;
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
+
485
for (DWORD i = 0; i < pPlan->cCacheActions; ++i)
486
{
487
BURN_CACHE_ACTION* pCacheAction = pPlan->rgCacheActions + i;
@@ -561,6 +558,12 @@ LExit:
558
559
CacheCleanup(FALSE, pPlan->wzBundleId);
560
561
+ for (DWORD i = 0; i < cacheContext.cSearchPathsMax; ++i)
562
+ {
563
+ ReleaseNullStr(cacheContext.rgSearchPaths[i]);
564
+ }
565
+ ReleaseMem(cacheContext.rgSearchPaths);
566
+
567
UserExperienceOnCacheComplete(pUX, hr);
568
return hr;
569
}
@@ -949,17 +952,8 @@ static HRESULT ApplyProcessPayload(
952
{
953
fRetry = FALSE;
954
952
- if (pPayload->pContainer)
953
- {
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
- }
955
+ hr = AcquireContainerOrPayload(pContext, NULL, pPackage, pPayload);
956
+ LogExitOnFailure(hr, MSG_FAILED_ACQUIRE_PAYLOAD, "Failed to acquire payload: %ls to working path: %ls", pPayload->sczKey, pPayload->sczUnverifiedPath);
957
958
pContext->qwSuccessfulCacheProgress += pPayload->qwFileSize;
959
@@ -1054,8 +1048,10 @@ static HRESULT LayoutBundle(
1048
{
1049
HRESULT hr = S_OK;
1050
LPWSTR sczBundlePath = NULL;
1051
+ LPWSTR sczBundleDownloadUrl = NULL;
1052
LPWSTR sczDestinationPath = NULL;
1053
int nEquivalentPaths = 0;
1054
+ BOOTSTRAPPER_CACHE_OPERATION cacheOperation = BOOTSTRAPPER_CACHE_OPERATION_NONE;
1055
BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT progress = { };
1056
BOOL fRetry = FALSE;
1057
BOOL fRetryAcquire = FALSE;
@@ -1096,7 +1092,7 @@ static HRESULT LayoutBundle(
1092
fRetryAcquire = FALSE;
1093
progress.fCancel = FALSE;
1094
1099
- hr = UserExperienceOnCacheAcquireBegin(pContext->pUX, NULL, NULL, BOOTSTRAPPER_CACHE_OPERATION_COPY, sczBundlePath);
1095
+ hr = UserExperienceOnCacheAcquireBegin(pContext->pUX, NULL, NULL, &sczBundlePath, &sczBundleDownloadUrl, NULL, &cacheOperation);
1096
ExitOnRootFailure(hr, "BA aborted cache acquire begin.");
1097
1098
hr = CopyPayload(&progress, pContext->hSourceEngineFile, sczBundlePath, wzUnverifiedPath);
@@ -1142,6 +1138,7 @@ static HRESULT LayoutBundle(
1138
1139
LExit:
1140
ReleaseStr(sczDestinationPath);
1141
+ ReleaseStr(sczBundleDownloadUrl);
1142
ReleaseStr(sczBundlePath);
1143
1144
return hr;
@@ -1160,11 +1157,16 @@ static HRESULT AcquireContainerOrPayload(
1157
int nEquivalentPaths = 0;
1158
LPCWSTR wzPackageOrContainerId = pContainer ? pContainer->sczId : pPackage ? pPackage->sczId : NULL;
1159
LPCWSTR wzPayloadId = pPayload ? pPayload->sczKey : NULL;
1160
+ LPCWSTR wzPayloadContainerId = pPayload && pPayload->pContainer ? pPayload->pContainer->sczId : NULL;
1161
LPCWSTR wzDestinationPath = pContainer ? pContainer->sczUnverifiedPath: pPayload->sczUnverifiedPath;
1162
LPCWSTR wzRelativePath = pContainer ? pContainer->sczFilePath : pPayload->sczFilePath;
1165
- LPWSTR sczSourceFullPath = NULL;
1163
BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT progress = { };
1164
+ BOOL fBeginCalled = 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;
1170
1171
progress.pCacheContext = pContext;
1172
progress.pContainer = pContainer;
@@ -1173,86 +1175,148 @@ static HRESULT AcquireContainerOrPayload(
1175
1176
do
1177
{
1176
- LPCWSTR wzDownloadUrl = pContainer ? pContainer->downloadSource.sczUrl : pPayload->downloadSource.sczUrl;
1177
- LPCWSTR wzSourcePath = pContainer ? pContainer->sczSourcePath : pPayload->sczSourcePath;
1178
-
1178
BOOL fFoundLocal = FALSE;
1180
- BOOL fCopy = FALSE;
1181
- BOOL fDownload = FALSE;
1179
1180
+ pContext->cSearchPaths = 0;
1181
+ dwChosenSearchPath = 0;
1182
fRetry = FALSE;
1183
progress.fCancel = FALSE;
1184
+ fBeginCalled = TRUE;
1185
1186
- hr = CacheFindLocalSource(wzSourcePath, wzDestinationPath, pContext->pVariables, &fFoundLocal, &sczSourceFullPath);
1187
- ExitOnFailure(hr, "Failed to search local source.");
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.");
1186
+ hr = UserExperienceOnCacheAcquireBegin(pContext->pUX, wzPackageOrContainerId, wzPayloadId, pwzSourcePath, pwzDownloadUrl, wzPayloadContainerId, &cacheOperation);
1187
+ ExitOnRootFailure(hr, "BA aborted cache acquire begin.");
1188
1195
- fCopy = (CSTR_EQUAL != nEquivalentPaths);
1196
- }
1197
- else // can't find the file locally, so prompt for source.
1189
+ // Skip the Resolving event and probing local paths if the BA already knew it wanted to download or extract.
1190
+ if (BOOTSTRAPPER_CACHE_OPERATION_DOWNLOAD != cacheOperation &&
1191
+ BOOTSTRAPPER_CACHE_OPERATION_EXTRACT != cacheOperation)
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;
1200
- LogId(REPORT_STANDARD, dwLogId, wzPackageOrContainerId ? wzPackageOrContainerId : L"", wzPayloadId ? wzPayloadId : L"", sczSourceFullPath);
1193
+ hr = CacheGetLocalSourcePaths(wzRelativePath, *pwzSourcePath, wzDestinationPath, pContext->wzLayoutDirectory, pContext->pVariables, &pContext->rgSearchPaths, &pContext->cSearchPaths);
1194
+ ExitOnFailure(hr, "Failed to search local source.");
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
+ }
1207
1204
- // If the BA requested download then ensure a download url is available (it may have been set
1205
- // during PromptForSource so we need to check again).
1206
- if (fDownload)
1208
+ if (BOOTSTRAPPER_CACHE_OPERATION_COPY == cacheOperation)
1209
+ {
1210
+ if (!fFoundLocal)
1211
+ {
1212
+ cacheOperation = BOOTSTRAPPER_CACHE_OPERATION_NONE;
1213
+ }
1214
+ }
1215
+ else
1216
{
1208
- wzDownloadUrl = pContainer ? pContainer->downloadSource.sczUrl : pPayload->downloadSource.sczUrl;
1209
- if (!wzDownloadUrl || !*wzDownloadUrl)
1217
+ if (fFoundLocal) // the file exists locally, so copy it.
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)
1226
{
1211
- hr = E_INVALIDARG;
1227
+ cacheOperation = BOOTSTRAPPER_CACHE_OPERATION_DOWNLOAD;
1228
}
1229
}
1230
1215
- // Log the error
1216
- LogExitOnFailure(hr, MSG_PAYLOAD_FILE_NOT_PRESENT, "Failed while prompting for source (original path '%ls').", sczSourceFullPath);
1231
+ // Let the BA have a chance to override the action, but their chance to change the source is during begin or complete.
1232
+ hr = UserExperienceOnCacheAcquireResolving(pContext->pUX, wzPackageOrContainerId, wzPayloadId, pContext->rgSearchPaths, pContext->cSearchPaths, fFoundLocal, &dwChosenSearchPath, *pwzDownloadUrl, wzPayloadContainerId, &cacheOperation);
1233
+ ExitOnRootFailure(hr, "BA aborted cache acquire resolving.");
1234
}
1235
1219
- if (fCopy)
1236
+ switch (cacheOperation)
1237
{
1221
- hr = UserExperienceOnCacheAcquireBegin(pContext->pUX, wzPackageOrContainerId, wzPayloadId, BOOTSTRAPPER_CACHE_OPERATION_COPY, sczSourceFullPath);
1222
- ExitOnRootFailure(hr, "BA aborted cache acquire begin.");
1238
+ case BOOTSTRAPPER_CACHE_OPERATION_COPY:
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);
1242
1224
- hr = CopyPayload(&progress, INVALID_HANDLE_VALUE, sczSourceFullPath, wzDestinationPath);
1225
- // Error handling happens after sending complete message to BA.
1243
+ if (CSTR_EQUAL != nEquivalentPaths)
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
+ }
1255
1227
- // We successfully copied from a source location, set that as the last used source.
1228
- if (SUCCEEDED(hr))
1256
+ fBeginCalled = FALSE;
1257
+ UserExperienceOnCacheAcquireComplete(pContext->pUX, wzPackageOrContainerId, wzPayloadId, hr, &fRetry);
1258
+ if (fRetry)
1259
{
1230
- CacheSetLastUsedSource(pContext->pVariables, sczSourceFullPath, wzRelativePath);
1260
+ hr = S_OK;
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.");
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:
1267
hr = DownloadPayload(&progress, wzDestinationPath);
1268
// Error handling happens after sending complete message to BA.
1240
- }
1269
1242
- if (fCopy || fDownload)
1243
- {
1270
+ fBeginCalled = FALSE;
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;
1301
UserExperienceOnCacheAcquireComplete(pContext->pUX, wzPackageOrContainerId, wzPayloadId, hr, &fRetry);
1302
if (fRetry)
1303
{
1304
hr = S_OK;
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;
1310
}
1250
- ExitOnFailure(hr, "Failed to acquire payload from: '%ls' to working path: '%ls'", fCopy ? sczSourceFullPath : wzDownloadUrl, wzDestinationPath);
1311
} while (fRetry);
1252
- ExitOnFailure(hr, "Failed to find external payload to cache.");
1312
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);
1320
1321
return hr;
1322
}
@@ -1355,48 +1419,6 @@ LExit:
1419
return hr;
1420
}
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
-
1422
static HRESULT CopyPayload(
1423
__in BURN_CACHE_ACQUIRE_PROGRESS_CONTEXT* pProgress,
1424
__in HANDLE hSourceFile,
src/engine/cache.cpp
+126
-77
@@ -11,7 +11,7 @@ static const DWORD FILE_OPERATION_RETRY_WAIT = 2000;
11
12
static BOOL vfInitializedCache = FALSE;
13
static BOOL vfRunningFromCache = FALSE;
14
-static LPWSTR vsczSourceProcessPath = NULL;
14
+static LPWSTR vsczSourceProcessFolder = NULL;
15
static LPWSTR vsczWorkingFolder = NULL;
16
static LPWSTR vsczDefaultUserPackageCache = NULL;
17
static LPWSTR vsczDefaultMachinePackageCache = NULL;
@@ -140,8 +140,8 @@ extern "C" HRESULT CacheInitialize(
140
wzSourceProcessPath = sczCurrentPath;
141
}
142
143
- hr = StrAllocString(&vsczSourceProcessPath, wzSourceProcessPath, 0);
144
- ExitOnFailure(hr, "Failed to initialize cache source path.");
143
+ hr = PathGetDirectory(wzSourceProcessPath, &vsczSourceProcessFolder);
144
+ ExitOnFailure(hr, "Failed to initialize cache source folder.");
145
146
// If we're not running from the cache, ensure the original source is set.
147
if (!vfRunningFromCache)
@@ -393,112 +393,166 @@ LExit:
393
return hr;
394
}
395
396
-extern "C" HRESULT CacheFindLocalSource(
396
+extern "C" HRESULT CacheGetLocalSourcePaths(
397
+ __in_z LPCWSTR wzRelativePath,
398
__in_z LPCWSTR wzSourcePath,
399
__in_z LPCWSTR wzDestinationPath,
400
+ __in_z_opt LPCWSTR wzLayoutDirectory,
401
__in BURN_VARIABLES* pVariables,
400
- __out BOOL* pfFound,
401
- __out_z LPWSTR* psczSourceFullPath
402
+ __inout LPWSTR** prgSearchPaths,
403
+ __out DWORD* pcSearchPaths
404
)
405
{
406
HRESULT hr = S_OK;
405
- LPWSTR sczSourceProcessFolder = NULL;
407
LPWSTR sczCurrentPath = NULL;
407
- LPWSTR sczLastSourcePath = NULL;
408
LPWSTR sczLastSourceFolder = NULL;
409
- LPWSTR sczLayoutPath = NULL;
410
- LPWSTR sczLayoutFolder = NULL;
411
- LPCWSTR rgwzSearchPaths[4] = { };
409
+ LPWSTR* psczPath = NULL;
410
+ BOOL fPreferSourcePathLocation = FALSE;
411
+ BOOL fTryLastFolder = FALSE;
412
+ BOOL fTryRelativePath = FALSE;
413
+ BOOL fSourceIsAbsolute = FALSE;
414
DWORD cSearchPaths = 0;
415
414
- // If the source path provided is a full path, obviously that is where we should be looking.
415
- if (PathIsAbsolute(wzSourcePath))
416
+ AssertSz(vfInitializedCache, "Cache wasn't initialized");
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)
426
{
417
- rgwzSearchPaths[0] = wzSourcePath;
418
- cSearchPaths = 1;
427
+ hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS);
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.");
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)
448
{
422
- // Use the destination path first.
423
- rgwzSearchPaths[0] = wzDestinationPath;
424
- cSearchPaths = 1;
425
-
426
- // If we're not running from cache or we couldn't get the last source, use
427
- // the source path location. In the case where we are in the bundle's
428
- // package cache and couldn't find a last used source we unfortunately will
429
- // be picking the package cache path which isn't likely to have what we are
430
- // looking for.
431
- hr = GetLastUsedSourceFolder(pVariables, &sczLastSourceFolder);
432
- if (!vfRunningFromCache || FAILED(hr))
449
+ // Calculate the source path location.
450
+ // In the case where we are in the bundle's package cache and
451
+ // couldn't find a last used source that will be the package cache path
452
+ // which isn't likely to have what we are looking for.
453
+ hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS);
454
+ ExitOnFailure(hr, "Failed to ensure size for search paths array.");
455
+
456
+ hr = PathConcat(vsczSourceProcessFolder, wzSourcePath, &sczCurrentPath);
457
+ ExitOnFailure(hr, "Failed to combine source process folder with source.");
458
+
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)
462
{
434
- hr = PathGetDirectory(vsczSourceProcessPath, &sczSourceProcessFolder);
435
- ExitOnFailure(hr, "Failed to get current process directory.");
463
+ (*prgSearchPaths)[cSearchPaths] = sczCurrentPath;
464
+ ++cSearchPaths;
465
+ sczCurrentPath = NULL;
466
+ }
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);
479
ExitOnFailure(hr, "Failed to combine last source with source.");
480
+ }
481
440
- rgwzSearchPaths[cSearchPaths] = sczCurrentPath;
482
+ if (!fPreferSourcePathLocation)
483
+ {
484
+ (*prgSearchPaths)[cSearchPaths] = sczCurrentPath;
485
++cSearchPaths;
486
+ sczCurrentPath = NULL;
487
}
488
444
- // If we have a last used source and it does not duplicate the existing search path,
445
- // add the last used source to the search path second.
446
- if (sczLastSourceFolder && *sczLastSourceFolder)
489
+ // Also consider the layout directory if doing Layout.
490
+ if (wzLayoutDirectory)
491
{
448
- hr = PathConcat(sczLastSourceFolder, wzSourcePath, &sczLastSourcePath);
449
- ExitOnFailure(hr, "Failed to combine last source with source.");
492
+ hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS);
493
+ ExitOnFailure(hr, "Failed to ensure size for search paths array.");
494
451
- if (1 == cSearchPaths || CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, rgwzSearchPaths[1], -1, sczLastSourcePath, -1))
452
- {
453
- rgwzSearchPaths[cSearchPaths] = sczLastSourcePath;
454
- ++cSearchPaths;
455
- }
495
+ psczPath = *prgSearchPaths + cSearchPaths;
496
+ ++cSearchPaths;
497
+
498
+ hr = PathConcat(wzLayoutDirectory, wzSourcePath, psczPath);
499
+ ExitOnFailure(hr, "Failed to combine layout source with source.");
500
}
501
+ }
502
458
- // Also consider the layout directory if set on the command line or by the BA.
459
- hr = VariableGetString(pVariables, BURN_BUNDLE_LAYOUT_DIRECTORY, &sczLayoutFolder);
460
- if (E_NOTFOUND != hr)
503
+ if (fTryRelativePath)
504
+ {
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)
512
{
462
- ExitOnFailure(hr, "Failed to get bundle layout directory property.");
513
+ (*prgSearchPaths)[cSearchPaths] = sczCurrentPath;
514
+ ++cSearchPaths;
515
+ sczCurrentPath = NULL;
516
+ }
517
464
- hr = PathConcat(sczLayoutFolder, wzSourcePath, &sczLayoutPath);
465
- ExitOnFailure(hr, "Failed to combine layout source with source.");
518
+ if (fTryLastFolder)
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.");
522
467
- rgwzSearchPaths[cSearchPaths] = sczLayoutPath;
523
+ psczPath = *prgSearchPaths + cSearchPaths;
524
++cSearchPaths;
525
+
526
+ hr = PathConcat(sczLastSourceFolder, wzRelativePath, psczPath);
527
+ ExitOnFailure(hr, "Failed to combine last source with relative.");
528
}
470
- }
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
+ }
536
474
- for (DWORD i = 0; i < cSearchPaths; ++i)
475
- {
476
- // If the file exists locally, copy its path.
477
- if (FileExistsEx(rgwzSearchPaths[i], NULL))
537
+ if (wzLayoutDirectory)
538
{
479
- hr = StrAllocString(psczSourceFullPath, rgwzSearchPaths[i], 0);
480
- ExitOnFailure(hr, "Failed to copy source path.");
539
+ hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(prgSearchPaths), cSearchPaths + 1, sizeof(LPWSTR), BURN_CACHE_MAX_SEARCH_PATHS);
540
+ ExitOnFailure(hr, "Failed to ensure size for search paths array.");
541
482
- *pfFound = TRUE;
483
- break;
484
- }
485
- }
542
+ psczPath = *prgSearchPaths + cSearchPaths;
543
+ ++cSearchPaths;
544
487
- // If nothing was found, return the first thing in our search path as the
488
- // best path where we thought we should have found the file.
489
- if (!*pfFound)
490
- {
491
- hr = StrAllocString(psczSourceFullPath, rgwzSearchPaths[0], 0);
492
- ExitOnFailure(hr, "Failed to copy source path.");
545
+ hr = PathConcat(wzLayoutDirectory, wzSourcePath, psczPath);
546
+ ExitOnFailure(hr, "Failed to combine layout source with relative.");
547
+ }
548
}
549
550
LExit:
551
ReleaseStr(sczCurrentPath);
497
- ReleaseStr(sczSourceProcessFolder);
552
ReleaseStr(sczLastSourceFolder);
499
- ReleaseStr(sczLastSourcePath);
500
- ReleaseStr(sczLayoutFolder);
501
- ReleaseStr(sczLayoutPath);
553
+
554
+ AssertSz(cSearchPaths <= BURN_CACHE_MAX_SEARCH_PATHS, "Got more than BURN_CACHE_MAX_SEARCH_PATHS search paths");
555
+ *pcSearchPaths = cSearchPaths;
556
557
return hr;
558
}
@@ -1079,7 +1133,7 @@ extern "C" void CacheUninitialize()
1133
ReleaseNullStr(vsczDefaultMachinePackageCache);
1134
ReleaseNullStr(vsczDefaultUserPackageCache);
1135
ReleaseNullStr(vsczWorkingFolder);
1082
- ReleaseNullStr(vsczSourceProcessPath);
1136
+ ReleaseNullStr(vsczSourceProcessFolder);
1137
1138
vfRunningFromCache = FALSE;
1139
vfInitializedCache = FALSE;
@@ -1224,17 +1278,12 @@ static HRESULT GetLastUsedSourceFolder(
1278
)
1279
{
1280
HRESULT hr = S_OK;
1227
- LPWSTR sczOriginalSource = NULL;
1281
1282
hr = VariableGetString(pVariables, BURN_BUNDLE_LAST_USED_SOURCE, psczLastSource);
1283
if (E_NOTFOUND == hr)
1284
{
1285
// Try the original source folder.
1233
- hr = VariableGetString(pVariables, BURN_BUNDLE_ORIGINAL_SOURCE, &sczOriginalSource);
1234
- if (SUCCEEDED(hr))
1235
- {
1236
- hr = PathGetDirectory(sczOriginalSource, psczLastSource);
1237
- }
1286
+ hr = VariableGetString(pVariables, BURN_BUNDLE_ORIGINAL_SOURCE_FOLDER, psczLastSource);
1287
}
1288
1289
return hr;
src/engine/cache.h
+6
-3
@@ -1,6 +1,7 @@
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.
3
4
+#define BURN_CACHE_MAX_SEARCH_PATHS 7
5
6
#ifdef __cplusplus
7
extern "C" {
@@ -52,12 +53,14 @@ HRESULT CacheGetResumePath(
53
__in_z LPCWSTR wzPayloadWorkingPath,
54
__deref_out_z LPWSTR* psczResumePath
55
);
55
-HRESULT CacheFindLocalSource(
56
+HRESULT CacheGetLocalSourcePaths(
57
+ __in_z LPCWSTR wzRelativePath,
58
__in_z LPCWSTR wzSourcePath,
59
__in_z LPCWSTR wzDestinationPath,
60
+ __in_z_opt LPCWSTR wzLayoutDirectory,
61
__in BURN_VARIABLES* pVariables,
59
- __out BOOL* pfFound,
60
- __out_z LPWSTR* psczSourceFullPath
62
+ __inout LPWSTR** prgSearchPaths,
63
+ __out DWORD* pcSearchPaths
64
);
65
HRESULT CacheSetLastUsedSource(
66
__in BURN_VARIABLES* pVariables,
src/engine/engine.mc
+2
-30
@@ -151,9 +151,9 @@ Bundle global condition check didn't succeed - aborting without loading applicat
151
152
MessageId=54
153
Severity=Error
154
-SymbolicName=MSG_PAYLOAD_FILE_NOT_PRESENT
154
+SymbolicName=MSG_RESOLVE_SOURCE_FAILED
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
.
158
159
MessageId=55
@@ -724,34 +724,6 @@ Language=English
724
Acquiring package: %1!ls!, payload: %2!ls!, %3!hs! from: %4!ls!
725
.
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
-
727
MessageId=348
728
Severity=Warning
729
SymbolicName=MSG_APPLY_RETRYING_PACKAGE
src/engine/externalengine.cpp
+17
-26
@@ -269,8 +269,7 @@ HRESULT ExternalEngineSetUpdate(
269
)
270
{
271
HRESULT hr = S_OK;
272
- LPCWSTR sczId = NULL;
273
- LPWSTR sczLocalSource = NULL;
272
+ LPWSTR sczFilePath = NULL;
273
LPWSTR sczCommandline = NULL;
274
UUID guid = { };
275
WCHAR wzGuid[39];
@@ -296,38 +295,30 @@ HRESULT ExternalEngineSetUpdate(
295
{
296
UpdateUninitialize(&pEngineState->update);
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
-
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);
299
ExitOnFailure(hr, "Failed to recreate command-line for update bundle.");
300
308
- // Per-user bundles would fail to use the downloaded update bundle, as the existing install would already be cached
309
- // at the registration id's location. Here I am generating a random guid, but in the future it would be nice if the
310
- // feed would provide the ID of the update.
311
- if (!pEngineState->registration.fPerMachine)
301
+ // Bundles would fail to use the downloaded update bundle, as the running bundle would be one of the search paths.
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.
303
+ rs = ::UuidCreate(&guid);
304
+ hr = HRESULT_FROM_RPC(rs);
305
+ ExitOnFailure(hr, "Failed to create bundle update guid.");
306
+
307
+ if (!::StringFromGUID2(guid, wzGuid, countof(wzGuid)))
308
{
313
- rs = ::UuidCreate(&guid);
314
- hr = HRESULT_FROM_RPC(rs);
315
- ExitOnFailure(hr, "Failed to create bundle update guid.");
309
+ hr = E_OUTOFMEMORY;
310
+ ExitOnRootFailure(hr, "Failed to convert bundle update guid into string.");
311
+ }
312
317
- if (!::StringFromGUID2(guid, wzGuid, countof(wzGuid)))
318
- {
319
- hr = E_OUTOFMEMORY;
320
- ExitOnRootFailure(hr, "Failed to convert bundle update guid into string.");
321
- }
313
+ hr = StrAllocFormatted(&sczFilePath, L"%ls\\%ls", wzGuid, pEngineState->registration.sczExecutableName);
314
+ ExitOnFailure(hr, "Failed to build bundle update file path.");
315
323
- sczId = wzGuid;
324
- }
325
- else
316
+ if (!wzLocalSource || !*wzLocalSource)
317
{
327
- sczId = pEngineState->registration.sczId;
318
+ wzLocalSource = sczFilePath;
319
}
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);
322
ExitOnFailure(hr, "Failed to set update bundle.");
323
324
pEngineState->update.fUpdateAvailable = TRUE;
@@ -337,7 +328,7 @@ LExit:
328
::LeaveCriticalSection(&pEngineState->userExperience.csEngineActive);
329
330
ReleaseStr(sczCommandline);
340
- ReleaseStr(sczLocalSource);
331
+ ReleaseStr(sczFilePath);
332
333
return hr;
334
}
src/engine/userexperience.cpp
+81
-45
@@ -395,29 +395,46 @@ EXTERN_C BAAPI UserExperienceOnCacheAcquireBegin(
395
__in BURN_USER_EXPERIENCE* pUserExperience,
396
__in_z_opt LPCWSTR wzPackageOrContainerId,
397
__in_z_opt LPCWSTR wzPayloadId,
398
- __in BOOTSTRAPPER_CACHE_OPERATION operation,
399
- __in_z LPCWSTR wzSource
398
+ __in_z LPWSTR* pwzSource,
399
+ __in_z LPWSTR* pwzDownloadUrl,
400
+ __in_z_opt LPCWSTR wzPayloadContainerId,
401
+ __out BOOTSTRAPPER_CACHE_OPERATION* pCacheOperation
402
)
403
{
404
HRESULT hr = S_OK;
405
BA_ONCACHEACQUIREBEGIN_ARGS args = { };
406
BA_ONCACHEACQUIREBEGIN_RESULTS results = { };
407
+ *pCacheOperation = BOOTSTRAPPER_CACHE_OPERATION_NONE;
408
409
args.cbSize = sizeof(args);
410
args.wzPackageOrContainerId = wzPackageOrContainerId;
411
args.wzPayloadId = wzPayloadId;
409
- args.operation = operation;
410
- args.wzSource = wzSource;
412
+ args.wzSource = *pwzSource;
413
+ args.wzDownloadUrl = *pwzDownloadUrl;
414
+ args.wzPayloadContainerId = wzPayloadContainerId;
415
+ args.recommendation = *pCacheOperation;
416
417
results.cbSize = sizeof(results);
418
+ results.action = *pCacheOperation;
419
414
- hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIREBEGIN, &args, &results);
420
+ hr = SendBAMessageFromInactiveEngine(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIREBEGIN, &args, &results);
421
ExitOnFailure(hr, "BA OnCacheAcquireBegin failed.");
422
423
if (results.fCancel)
424
{
425
hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);
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
+ }
438
439
LExit:
440
return hr;
@@ -444,7 +461,7 @@ EXTERN_C BAAPI UserExperienceOnCacheAcquireComplete(
461
results.cbSize = sizeof(results);
462
results.action = args.recommendation;
463
447
- hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIRECOMPLETE, &args, &results);
464
+ hr = SendBAMessageFromInactiveEngine(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEACQUIRECOMPLETE, &args, &results);
465
ExitOnFailure(hr, "BA OnCacheAcquireComplete failed.");
466
467
if (FAILED(hrStatus))
@@ -490,6 +507,64 @@ LExit:
507
return hr;
508
}
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
+
568
EXTERN_C BAAPI UserExperienceOnCacheBegin(
569
__in BURN_USER_EXPERIENCE* pUserExperience
570
)
@@ -1861,45 +1936,6 @@ LExit:
1936
return hr;
1937
}
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
-
1939
EXTERN_C BAAPI UserExperienceOnRollbackMsiTransactionBegin(
1940
__in BURN_USER_EXPERIENCE* pUserExperience,
1941
__in LPCWSTR wzTransactionId
src/engine/userexperience.h
+16
-10
@@ -126,8 +126,10 @@ BAAPI UserExperienceOnCacheAcquireBegin(
126
__in BURN_USER_EXPERIENCE* pUserExperience,
127
__in_z_opt LPCWSTR wzPackageOrContainerId,
128
__in_z_opt LPCWSTR wzPayloadId,
129
- __in BOOTSTRAPPER_CACHE_OPERATION operation,
130
- __in_z LPCWSTR wzSource
129
+ __in_z LPWSTR* pwzSource,
130
+ __in_z LPWSTR* pwzDownloadUrl,
131
+ __in_z_opt LPCWSTR wzPayloadContainerId,
132
+ __out BOOTSTRAPPER_CACHE_OPERATION* pCacheOperation
133
);
134
BAAPI UserExperienceOnCacheAcquireComplete(
135
__in BURN_USER_EXPERIENCE* pUserExperience,
@@ -144,6 +146,18 @@ BAAPI UserExperienceOnCacheAcquireProgress(
146
__in DWORD64 dw64Total,
147
__in DWORD dwOverallPercentage
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
+ );
161
BAAPI UserExperienceOnCacheBegin(
162
__in BURN_USER_EXPERIENCE* pUserExperience
163
);
@@ -426,14 +440,6 @@ BAAPI UserExperienceOnRegisterComplete(
440
__in BURN_USER_EXPERIENCE* pUserExperience,
441
__in HRESULT hrStatus
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
- );
443
BAAPI UserExperienceOnRollbackMsiTransactionBegin(
444
__in BURN_USER_EXPERIENCE* pUserExperience,
445
__in LPCWSTR wzTransactionId