Don't assume Exe packages with Burn protocol are bundles.
Related to #3693
Sean Hall committed
Jan 3, 2022 at 15:35 UTC
1f5314302b3c8bc1977aed79df1d05c52608f382
19 files changed
+1018
-410
src/burn/engine/apply.cpp
+94
@@ -201,6 +201,15 @@ static HRESULT DoRollbackActions(
201
__in DWORD dwCheckpoint,
202
__out BOOTSTRAPPER_APPLY_RESTART* pRestart
203
);
204
+static HRESULT ExecuteRelatedBundle(
205
+ __in BURN_ENGINE_STATE* pEngineState,
206
+ __in BURN_EXECUTE_ACTION* pExecuteAction,
207
+ __in BURN_EXECUTE_CONTEXT* pContext,
208
+ __in BOOL fRollback,
209
+ __out BOOL* pfRetry,
210
+ __out BOOL* pfSuspend,
211
+ __out BOOTSTRAPPER_APPLY_RESTART* pRestart
212
+ );
213
static HRESULT ExecuteExePackage(
214
__in BURN_ENGINE_STATE* pEngineState,
215
__in BURN_EXECUTE_ACTION* pExecuteAction,
@@ -686,6 +695,9 @@ extern "C" HRESULT ApplyExecute(
695
LPCWSTR wzId = NULL;
696
switch (pExecuteAction->type)
697
{
698
+ case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE:
699
+ wzId = pExecuteAction->relatedBundle.pRelatedBundle->package.sczId;
700
+ break;
701
case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
702
wzId = pExecuteAction->exePackage.pPackage->sczId;
703
break;
@@ -2285,6 +2297,11 @@ static HRESULT DoExecuteAction(
2297
}
2298
break;
2299
2300
+ case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE:
2301
+ hr = ExecuteRelatedBundle(pEngineState, pExecuteAction, pContext, FALSE, &fRetry, pfSuspend, &restart);
2302
+ ExitOnFailure(hr, "Failed to execute related bundle.");
2303
+ break;
2304
+
2305
case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
2306
hr = ExecuteExePackage(pEngineState, pExecuteAction, pContext, FALSE, &fRetry, pfSuspend, &restart);
2307
ExitOnFailure(hr, "Failed to execute EXE package.");
@@ -2399,6 +2416,11 @@ static HRESULT DoRollbackActions(
2416
case BURN_EXECUTE_ACTION_TYPE_CHECKPOINT:
2417
break;
2418
2419
+ case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE:
2420
+ hr = ExecuteRelatedBundle(pEngineState, pRollbackAction, pContext, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart);
2421
+ ExitOnFailure(hr, "Failed to execute related bundle.");
2422
+ break;
2423
+
2424
case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
2425
hr = ExecuteExePackage(pEngineState, pRollbackAction, pContext, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart);
2426
IgnoreRollbackError(hr, "Failed to rollback EXE package.");
@@ -2462,6 +2484,78 @@ LExit:
2484
return hr;
2485
}
2486
2487
+static HRESULT ExecuteRelatedBundle(
2488
+ __in BURN_ENGINE_STATE* pEngineState,
2489
+ __in BURN_EXECUTE_ACTION* pExecuteAction,
2490
+ __in BURN_EXECUTE_CONTEXT* pContext,
2491
+ __in BOOL fRollback,
2492
+ __out BOOL* pfRetry,
2493
+ __out BOOL* pfSuspend,
2494
+ __out BOOTSTRAPPER_APPLY_RESTART* pRestart
2495
+ )
2496
+{
2497
+ HRESULT hr = S_OK;
2498
+ HRESULT hrExecute = S_OK;
2499
+ GENERIC_EXECUTE_MESSAGE message = { };
2500
+ int nResult = 0;
2501
+ BOOL fBeginCalled = FALSE;
2502
+ BURN_RELATED_BUNDLE* pRelatedBundle = pExecuteAction->relatedBundle.pRelatedBundle;
2503
+ BURN_PACKAGE* pPackage = &pRelatedBundle->package;
2504
+
2505
+ if (FAILED(pPackage->hrCacheResult))
2506
+ {
2507
+ LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pPackage->sczId, pPackage->hrCacheResult);
2508
+ ExitFunction1(hr = S_OK);
2509
+ }
2510
+
2511
+ Assert(pContext->fRollback == fRollback);
2512
+ pContext->pExecutingPackage = pPackage;
2513
+ fBeginCalled = TRUE;
2514
+
2515
+ // Send package execute begin to BA.
2516
+ hr = UserExperienceOnExecutePackageBegin(&pEngineState->userExperience, pPackage->sczId, !fRollback, pExecuteAction->relatedBundle.action, INSTALLUILEVEL_NOCHANGE, FALSE);
2517
+ ExitOnRootFailure(hr, "BA aborted execute related bundle begin.");
2518
+
2519
+ message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS;
2520
+ message.dwUIHint = MB_OKCANCEL;
2521
+ message.progress.dwPercentage = fRollback ? 100 : 0;
2522
+ nResult = GenericExecuteMessageHandler(&message, pContext);
2523
+ hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwUIHint, nResult);
2524
+ ExitOnRootFailure(hr, "BA aborted related bundle progress.");
2525
+
2526
+ // Execute package.
2527
+ if (pPackage->fPerMachine)
2528
+ {
2529
+ hrExecute = ElevationExecuteRelatedBundle(pEngineState->companionConnection.hPipe, pExecuteAction, &pEngineState->variables, fRollback, GenericExecuteMessageHandler, pContext, pRestart);
2530
+ ExitOnFailure(hrExecute, "Failed to configure per-machine related bundle.");
2531
+ }
2532
+ else
2533
+ {
2534
+ hrExecute = BundlePackageEngineExecuteRelatedBundle(pExecuteAction, pContext->pCache, &pEngineState->variables, fRollback, GenericExecuteMessageHandler, pContext, pRestart);
2535
+ ExitOnFailure(hrExecute, "Failed to configure per-user related bundle.");
2536
+ }
2537
+
2538
+ message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS;
2539
+ message.dwUIHint = MB_OKCANCEL;
2540
+ message.progress.dwPercentage = fRollback ? 0 : 100;
2541
+ nResult = GenericExecuteMessageHandler(&message, pContext);
2542
+ hr = UserExperienceInterpretExecuteResult(&pEngineState->userExperience, fRollback, message.dwUIHint, nResult);
2543
+ ExitOnRootFailure(hr, "BA aborted related bundle progress.");
2544
+
2545
+ pContext->cExecutedPackages += fRollback ? -1 : 1;
2546
+
2547
+ hr = ReportOverallProgressTicks(&pEngineState->userExperience, fRollback, pEngineState->plan.cOverallProgressTicksTotal, pContext->pApplyContext);
2548
+ ExitOnRootFailure(hr, "BA aborted related bundle execute progress.");
2549
+
2550
+LExit:
2551
+ if (fBeginCalled)
2552
+ {
2553
+ hr = ExecutePackageComplete(&pEngineState->userExperience, &pEngineState->variables, pPackage, hr, hrExecute, fRollback, pRestart, pfRetry, pfSuspend);
2554
+ }
2555
+
2556
+ return hr;
2557
+}
2558
+
2559
static HRESULT ExecuteExePackage(
2560
__in BURN_ENGINE_STATE* pEngineState,
2561
__in BURN_EXECUTE_ACTION* pExecuteAction,
src/burn/engine/bundlepackageengine.cpp
new
+460
@@ -0,0 +1,460 @@
1
+// 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
+
3
+#include "precomp.h"
4
+
5
+
6
+
7
+// function definitions
8
+
9
+extern "C" void BundlePackageEnginePackageUninitialize(
10
+ __in BURN_PACKAGE* pPackage
11
+ )
12
+{
13
+ ReleaseStr(pPackage->Bundle.sczInstallArguments);
14
+ ReleaseStr(pPackage->Bundle.sczRepairArguments);
15
+ ReleaseStr(pPackage->Bundle.sczUninstallArguments);
16
+ ReleaseStr(pPackage->Bundle.sczIgnoreDependencies);
17
+ ReleaseMem(pPackage->Bundle.rgExitCodes);
18
+
19
+ // free command-line arguments
20
+ if (pPackage->Bundle.rgCommandLineArguments)
21
+ {
22
+ for (DWORD i = 0; i < pPackage->Bundle.cCommandLineArguments; ++i)
23
+ {
24
+ ExeEngineCommandLineArgumentUninitialize(pPackage->Bundle.rgCommandLineArguments + i);
25
+ }
26
+ MemFree(pPackage->Bundle.rgCommandLineArguments);
27
+ }
28
+
29
+ // clear struct
30
+ memset(&pPackage->Bundle, 0, sizeof(pPackage->Bundle));
31
+}
32
+
33
+//
34
+// PlanCalculate - calculates the execute and rollback state for the requested package state.
35
+//
36
+extern "C" HRESULT BundlePackageEnginePlanCalculatePackage(
37
+ __in BURN_PACKAGE* pPackage
38
+ )
39
+{
40
+ HRESULT hr = S_OK;
41
+ BOOTSTRAPPER_ACTION_STATE execute = BOOTSTRAPPER_ACTION_STATE_NONE;
42
+ BOOTSTRAPPER_ACTION_STATE rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
43
+
44
+ // execute action
45
+ switch (pPackage->currentState)
46
+ {
47
+ case BOOTSTRAPPER_PACKAGE_STATE_PRESENT:
48
+ switch (pPackage->requested)
49
+ {
50
+ case BOOTSTRAPPER_REQUEST_STATE_PRESENT:
51
+ execute = pPackage->Bundle.fPseudoBundle ? BOOTSTRAPPER_ACTION_STATE_INSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
52
+ break;
53
+ case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
54
+ execute = pPackage->Bundle.fRepairable ? BOOTSTRAPPER_ACTION_STATE_REPAIR : BOOTSTRAPPER_ACTION_STATE_NONE;
55
+ break;
56
+ case BOOTSTRAPPER_REQUEST_STATE_ABSENT: __fallthrough;
57
+ case BOOTSTRAPPER_REQUEST_STATE_CACHE:
58
+ execute = pPackage->fUninstallable ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
59
+ break;
60
+ case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT:
61
+ execute = BOOTSTRAPPER_ACTION_STATE_UNINSTALL;
62
+ break;
63
+ default:
64
+ execute = BOOTSTRAPPER_ACTION_STATE_NONE;
65
+ break;
66
+ }
67
+ break;
68
+
69
+ case BOOTSTRAPPER_PACKAGE_STATE_ABSENT:
70
+ switch (pPackage->requested)
71
+ {
72
+ case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
73
+ case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
74
+ execute = BOOTSTRAPPER_ACTION_STATE_INSTALL;
75
+ break;
76
+ default:
77
+ execute = BOOTSTRAPPER_ACTION_STATE_NONE;
78
+ break;
79
+ }
80
+ break;
81
+
82
+ default:
83
+ hr = E_INVALIDARG;
84
+ ExitOnRootFailure(hr, "Invalid package current state: %d.", pPackage->currentState);
85
+ }
86
+
87
+ // Calculate the rollback action if there is an execute action.
88
+ if (BOOTSTRAPPER_ACTION_STATE_NONE != execute)
89
+ {
90
+ switch (pPackage->currentState)
91
+ {
92
+ case BOOTSTRAPPER_PACKAGE_STATE_PRESENT:
93
+ switch (pPackage->requested)
94
+ {
95
+ case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
96
+ case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
97
+ rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
98
+ break;
99
+ case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT: __fallthrough;
100
+ case BOOTSTRAPPER_REQUEST_STATE_ABSENT:
101
+ rollback = BOOTSTRAPPER_ACTION_STATE_INSTALL;
102
+ break;
103
+ default:
104
+ rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
105
+ break;
106
+ }
107
+ break;
108
+
109
+ case BOOTSTRAPPER_PACKAGE_STATE_ABSENT:
110
+ switch (pPackage->requested)
111
+ {
112
+ case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
113
+ case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
114
+ rollback = pPackage->fUninstallable ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
115
+ break;
116
+ case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT: __fallthrough;
117
+ case BOOTSTRAPPER_REQUEST_STATE_ABSENT:
118
+ rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
119
+ break;
120
+ default:
121
+ rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
122
+ break;
123
+ }
124
+ break;
125
+
126
+ default:
127
+ hr = E_INVALIDARG;
128
+ ExitOnRootFailure(hr, "Invalid package expected state.");
129
+ }
130
+ }
131
+
132
+ // return values
133
+ pPackage->execute = execute;
134
+ pPackage->rollback = rollback;
135
+
136
+LExit:
137
+ return hr;
138
+}
139
+
140
+//
141
+// PlanAdd - adds the calculated execute and rollback actions for the package.
142
+//
143
+extern "C" HRESULT BundlePackageEnginePlanAddRelatedBundle(
144
+ __in_opt DWORD *pdwInsertSequence,
145
+ __in BURN_RELATED_BUNDLE* pRelatedBundle,
146
+ __in BURN_PLAN* pPlan,
147
+ __in BURN_LOGGING* pLog,
148
+ __in BURN_VARIABLES* pVariables
149
+ )
150
+{
151
+ HRESULT hr = S_OK;
152
+ BURN_EXECUTE_ACTION* pAction = NULL;
153
+ BURN_PACKAGE* pPackage = &pRelatedBundle->package;
154
+
155
+ hr = DependencyPlanPackage(pdwInsertSequence, pPackage, pPlan);
156
+ ExitOnFailure(hr, "Failed to plan package dependency actions.");
157
+
158
+ // add execute action
159
+ if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute)
160
+ {
161
+ if (pdwInsertSequence)
162
+ {
163
+ hr = PlanInsertExecuteAction(*pdwInsertSequence, pPlan, &pAction);
164
+ ExitOnFailure(hr, "Failed to insert execute action.");
165
+ }
166
+ else
167
+ {
168
+ hr = PlanAppendExecuteAction(pPlan, &pAction);
169
+ ExitOnFailure(hr, "Failed to append execute action.");
170
+ }
171
+
172
+ pAction->type = BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE;
173
+ pAction->relatedBundle.pRelatedBundle = pRelatedBundle;
174
+ pAction->relatedBundle.action = pPackage->execute;
175
+
176
+ if (pPackage->Bundle.sczIgnoreDependencies)
177
+ {
178
+ hr = StrAllocString(&pAction->relatedBundle.sczIgnoreDependencies, pPackage->Bundle.sczIgnoreDependencies, 0);
179
+ ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
180
+ }
181
+
182
+ if (pPackage->Bundle.wzAncestors)
183
+ {
184
+ hr = StrAllocString(&pAction->relatedBundle.sczAncestors, pPackage->Bundle.wzAncestors, 0);
185
+ ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
186
+ }
187
+
188
+ if (pPackage->Bundle.wzEngineWorkingDirectory)
189
+ {
190
+ hr = StrAllocString(&pAction->relatedBundle.sczEngineWorkingDirectory, pPackage->Bundle.wzEngineWorkingDirectory, 0);
191
+ ExitOnFailure(hr, "Failed to allocate the custom working directory.");
192
+ }
193
+
194
+ LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, NULL); // ignore errors.
195
+ }
196
+
197
+ // add rollback action
198
+ if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->rollback)
199
+ {
200
+ hr = PlanAppendRollbackAction(pPlan, &pAction);
201
+ ExitOnFailure(hr, "Failed to append rollback action.");
202
+
203
+ pAction->type = BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE;
204
+ pAction->relatedBundle.pRelatedBundle = pRelatedBundle;
205
+ pAction->relatedBundle.action = pPackage->rollback;
206
+
207
+ if (pPackage->Bundle.sczIgnoreDependencies)
208
+ {
209
+ hr = StrAllocString(&pAction->relatedBundle.sczIgnoreDependencies, pPackage->Bundle.sczIgnoreDependencies, 0);
210
+ ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
211
+ }
212
+
213
+ if (pPackage->Bundle.wzAncestors)
214
+ {
215
+ hr = StrAllocString(&pAction->relatedBundle.sczAncestors, pPackage->Bundle.wzAncestors, 0);
216
+ ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
217
+ }
218
+
219
+ if (pPackage->Bundle.wzEngineWorkingDirectory)
220
+ {
221
+ hr = StrAllocString(&pAction->relatedBundle.sczEngineWorkingDirectory, pPackage->Bundle.wzEngineWorkingDirectory, 0);
222
+ ExitOnFailure(hr, "Failed to allocate the custom working directory.");
223
+ }
224
+
225
+ LoggingSetPackageVariable(pPackage, NULL, TRUE, pLog, pVariables, NULL); // ignore errors.
226
+ }
227
+
228
+LExit:
229
+ return hr;
230
+}
231
+
232
+extern "C" HRESULT BundlePackageEngineExecuteRelatedBundle(
233
+ __in BURN_EXECUTE_ACTION* pExecuteAction,
234
+ __in BURN_CACHE* pCache,
235
+ __in BURN_VARIABLES* pVariables,
236
+ __in BOOL fRollback,
237
+ __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
238
+ __in LPVOID pvContext,
239
+ __out BOOTSTRAPPER_APPLY_RESTART* pRestart
240
+ )
241
+{
242
+ HRESULT hr = S_OK;
243
+ int nResult = IDNOACTION;
244
+ LPCWSTR wzArguments = NULL;
245
+ LPWSTR sczArguments = NULL;
246
+ LPWSTR sczArgumentsFormatted = NULL;
247
+ LPWSTR sczArgumentsObfuscated = NULL;
248
+ LPWSTR sczCachedDirectory = NULL;
249
+ LPWSTR sczExecutablePath = NULL;
250
+ LPWSTR sczCommand = NULL;
251
+ LPWSTR sczCommandObfuscated = NULL;
252
+ HANDLE hExecutableFile = INVALID_HANDLE_VALUE;
253
+ STARTUPINFOW si = { };
254
+ PROCESS_INFORMATION pi = { };
255
+ DWORD dwExitCode = 0;
256
+ GENERIC_EXECUTE_MESSAGE message = { };
257
+ BOOTSTRAPPER_ACTION_STATE action = pExecuteAction->relatedBundle.action;
258
+ BURN_RELATED_BUNDLE* pRelatedBundle = pExecuteAction->relatedBundle.pRelatedBundle;
259
+ BOOTSTRAPPER_RELATION_TYPE relationType = pRelatedBundle->relationType;
260
+ BURN_PACKAGE* pPackage = &pRelatedBundle->package;
261
+ BURN_PAYLOAD* pPackagePayload = pPackage->payloads.rgItems[0].pPayload;
262
+ LPCWSTR wzRelationTypeCommandLine = CoreRelationTypeToCommandLineString(relationType);
263
+ LPCWSTR wzOperationCommandLine = NULL;
264
+ BOOL fRunEmbedded = pPackage->Bundle.fSupportsBurnProtocol;
265
+
266
+ // get cached executable path
267
+ hr = CacheGetCompletedPath(pCache, pPackage->fPerMachine, pPackage->sczCacheId, &sczCachedDirectory);
268
+ ExitOnFailure(hr, "Failed to get cached path for package: %ls", pPackage->sczId);
269
+
270
+ // Best effort to set the execute package cache folder and action variables.
271
+ VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, sczCachedDirectory, TRUE, FALSE);
272
+ VariableSetNumeric(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_ACTION, action, TRUE);
273
+
274
+ hr = PathConcat(sczCachedDirectory, pPackagePayload->sczFilePath, &sczExecutablePath);
275
+ ExitOnFailure(hr, "Failed to build executable path.");
276
+
277
+ // pick arguments
278
+ switch (action)
279
+ {
280
+ case BOOTSTRAPPER_ACTION_STATE_INSTALL:
281
+ wzArguments = pPackage->Bundle.sczInstallArguments;
282
+ break;
283
+
284
+ case BOOTSTRAPPER_ACTION_STATE_UNINSTALL:
285
+ wzOperationCommandLine = L"-uninstall";
286
+ wzArguments = pPackage->Bundle.sczUninstallArguments;
287
+ break;
288
+
289
+ case BOOTSTRAPPER_ACTION_STATE_REPAIR:
290
+ wzOperationCommandLine = L"-repair";
291
+ wzArguments = pPackage->Bundle.sczRepairArguments;
292
+ break;
293
+
294
+ default:
295
+ hr = E_INVALIDARG;
296
+ ExitOnFailure(hr, "Invalid Bundle package action: %d.", action);
297
+ }
298
+
299
+ // now add optional arguments
300
+ if (wzArguments && *wzArguments)
301
+ {
302
+ hr = StrAllocString(&sczArguments, wzArguments, 0);
303
+ ExitOnFailure(hr, "Failed to copy package arguments.");
304
+ }
305
+
306
+ for (DWORD i = 0; i < pPackage->Bundle.cCommandLineArguments; ++i)
307
+ {
308
+ BURN_EXE_COMMAND_LINE_ARGUMENT* commandLineArgument = &pPackage->Bundle.rgCommandLineArguments[i];
309
+ BOOL fCondition = FALSE;
310
+
311
+ hr = ConditionEvaluate(pVariables, commandLineArgument->sczCondition, &fCondition);
312
+ ExitOnFailure(hr, "Failed to evaluate bundle package command-line condition.");
313
+
314
+ if (fCondition)
315
+ {
316
+ if (sczArguments)
317
+ {
318
+ hr = StrAllocConcat(&sczArguments, L" ", 0);
319
+ ExitOnFailure(hr, "Failed to separate command-line arguments.");
320
+ }
321
+
322
+ switch (action)
323
+ {
324
+ case BOOTSTRAPPER_ACTION_STATE_INSTALL:
325
+ hr = StrAllocConcat(&sczArguments, commandLineArgument->sczInstallArgument, 0);
326
+ ExitOnFailure(hr, "Failed to get command-line argument for install.");
327
+ break;
328
+
329
+ case BOOTSTRAPPER_ACTION_STATE_UNINSTALL:
330
+ hr = StrAllocConcat(&sczArguments, commandLineArgument->sczUninstallArgument, 0);
331
+ ExitOnFailure(hr, "Failed to get command-line argument for uninstall.");
332
+ break;
333
+
334
+ case BOOTSTRAPPER_ACTION_STATE_REPAIR:
335
+ hr = StrAllocConcat(&sczArguments, commandLineArgument->sczRepairArgument, 0);
336
+ ExitOnFailure(hr, "Failed to get command-line argument for repair.");
337
+ break;
338
+
339
+ default:
340
+ hr = E_INVALIDARG;
341
+ ExitOnFailure(hr, "Invalid Bundle package action: %d.", action);
342
+ }
343
+ }
344
+ }
345
+
346
+ // build command
347
+ AppAppendCommandLineArgument(&sczCommand, sczExecutablePath);
348
+ ExitOnFailure(hr, "Failed to create executable command.");
349
+
350
+ if (!fRunEmbedded)
351
+ {
352
+ hr = StrAllocConcat(&sczCommand, L" -quiet", 0);
353
+ ExitOnFailure(hr, "Failed to append quiet argument.");
354
+ }
355
+
356
+ if (wzOperationCommandLine)
357
+ {
358
+ hr = StrAllocConcatFormatted(&sczCommand, L" %ls", wzOperationCommandLine);
359
+ ExitOnFailure(hr, "Failed to append operation argument.");
360
+ }
361
+
362
+ if (wzRelationTypeCommandLine)
363
+ {
364
+ hr = StrAllocConcatFormatted(&sczCommand, L" -%ls", wzRelationTypeCommandLine);
365
+ ExitOnFailure(hr, "Failed to append relation type argument.");
366
+ }
367
+
368
+ // Add the list of dependencies to ignore, if any, to the burn command line.
369
+ if (pExecuteAction->relatedBundle.sczIgnoreDependencies)
370
+ {
371
+ hr = StrAllocConcatFormatted(&sczCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->relatedBundle.sczIgnoreDependencies);
372
+ ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line.");
373
+ }
374
+
375
+ // Add the list of ancestors, if any, to the burn command line.
376
+ if (pExecuteAction->relatedBundle.sczAncestors)
377
+ {
378
+ hr = StrAllocConcatFormatted(&sczCommand, L" -%ls=%ls", BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->relatedBundle.sczAncestors);
379
+ ExitOnFailure(hr, "Failed to append the list of ancestors to the command line.");
380
+ }
381
+
382
+ hr = CoreAppendEngineWorkingDirectoryToCommandLine(pExecuteAction->relatedBundle.sczEngineWorkingDirectory, &sczCommand, NULL);
383
+ ExitOnFailure(hr, "Failed to append the custom working directory to the bundlepackage command line.");
384
+
385
+ hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczCommand, NULL);
386
+ ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF);
387
+
388
+ // Always add user supplied arguments last.
389
+ if (sczArguments && *sczArguments)
390
+ {
391
+ hr = VariableFormatString(pVariables, sczArguments, &sczArgumentsFormatted, NULL);
392
+ ExitOnFailure(hr, "Failed to format argument string.");
393
+
394
+ hr = VariableFormatStringObfuscated(pVariables, sczArguments, &sczArgumentsObfuscated, NULL);
395
+ ExitOnFailure(hr, "Failed to format obfuscated argument string.");
396
+
397
+ hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls %ls", sczCommand, sczArgumentsObfuscated);
398
+ ExitOnFailure(hr, "Failed to copy obfuscated formatted arguments.");
399
+
400
+ hr = StrAllocConcatFormattedSecure(&sczCommand, L" %ls", sczArgumentsFormatted);
401
+ ExitOnFailure(hr, "Failed to copy formatted arguments.");
402
+ }
403
+
404
+ // Log before we add the secret pipe name and client token for embedded processes.
405
+ LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(action), sczExecutablePath, sczCommandObfuscated);
406
+
407
+ if (fRunEmbedded)
408
+ {
409
+ hr = EmbeddedRunBundle(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode);
410
+ ExitOnFailure(hr, "Failed to run bundle as embedded from path: %ls", sczExecutablePath);
411
+ }
412
+ else // create and wait for the executable process while sending fake progress to allow cancel.
413
+ {
414
+ // Make the cache location of the executable the current directory to help those executables
415
+ // that expect stuff to be relative to them.
416
+ si.cb = sizeof(si);
417
+ if (!::CreateProcessW(sczExecutablePath, sczCommand, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, sczCachedDirectory, &si, &pi))
418
+ {
419
+ ExitWithLastError(hr, "Failed to CreateProcess on path: %ls", sczExecutablePath);
420
+ }
421
+
422
+ do
423
+ {
424
+ message.type = GENERIC_EXECUTE_MESSAGE_PROGRESS;
425
+ message.dwUIHint = MB_OKCANCEL;
426
+ message.progress.dwPercentage = 50;
427
+ nResult = pfnGenericMessageHandler(&message, pvContext);
428
+ hr = (IDOK == nResult || IDNOACTION == nResult) ? S_OK : IDCANCEL == nResult ? HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) : HRESULT_FROM_WIN32(ERROR_INSTALL_FAILURE);
429
+ ExitOnRootFailure(hr, "Bootstrapper application aborted during BUNDLE progress.");
430
+
431
+ hr = ProcWaitForCompletion(pi.hProcess, 500, &dwExitCode);
432
+ if (HRESULT_FROM_WIN32(WAIT_TIMEOUT) != hr)
433
+ {
434
+ ExitOnFailure(hr, "Failed to wait for executable to complete: %ls", sczExecutablePath);
435
+ }
436
+ } while (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr);
437
+ }
438
+
439
+ hr = ExeEngineHandleExitCode(pPackage->Bundle.rgExitCodes, pPackage->Bundle.cExitCodes, dwExitCode, pRestart);
440
+ ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode);
441
+
442
+LExit:
443
+ StrSecureZeroFreeString(sczArguments);
444
+ StrSecureZeroFreeString(sczArgumentsFormatted);
445
+ ReleaseStr(sczArgumentsObfuscated);
446
+ ReleaseStr(sczCachedDirectory);
447
+ ReleaseStr(sczExecutablePath);
448
+ StrSecureZeroFreeString(sczCommand);
449
+ ReleaseStr(sczCommandObfuscated);
450
+
451
+ ReleaseHandle(pi.hThread);
452
+ ReleaseHandle(pi.hProcess);
453
+ ReleaseFileHandle(hExecutableFile);
454
+
455
+ // Best effort to clear the execute package cache folder and action variables.
456
+ VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_CACHE_FOLDER, NULL, TRUE, FALSE);
457
+ VariableSetString(pVariables, BURN_BUNDLE_EXECUTE_PACKAGE_ACTION, NULL, TRUE, FALSE);
458
+
459
+ return hr;
460
+}
src/burn/engine/bundlepackageengine.h
new
+38
@@ -0,0 +1,38 @@
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
+
5
+#if defined(__cplusplus)
6
+extern "C" {
7
+#endif
8
+
9
+
10
+// function declarations
11
+
12
+void BundlePackageEnginePackageUninitialize(
13
+ __in BURN_PACKAGE* pPackage
14
+ );
15
+HRESULT BundlePackageEnginePlanCalculatePackage(
16
+ __in BURN_PACKAGE* pPackage
17
+ );
18
+HRESULT BundlePackageEnginePlanAddRelatedBundle(
19
+ __in_opt DWORD *pdwInsertSequence,
20
+ __in BURN_RELATED_BUNDLE* pRelatedBundle,
21
+ __in BURN_PLAN* pPlan,
22
+ __in BURN_LOGGING* pLog,
23
+ __in BURN_VARIABLES* pVariables
24
+ );
25
+HRESULT BundlePackageEngineExecuteRelatedBundle(
26
+ __in BURN_EXECUTE_ACTION* pExecuteAction,
27
+ __in BURN_CACHE* pCache,
28
+ __in BURN_VARIABLES* pVariables,
29
+ __in BOOL fRollback,
30
+ __in PFN_GENERICMESSAGEHANDLER pfnGenericExecuteProgress,
31
+ __in LPVOID pvContext,
32
+ __out BOOTSTRAPPER_APPLY_RESTART* pRestart
33
+ );
34
+
35
+
36
+#if defined(__cplusplus)
37
+}
38
+#endif
src/burn/engine/core.cpp
+7
-7
@@ -228,11 +228,11 @@ extern "C" HRESULT CoreInitializeConstants(
228
{
229
BURN_PACKAGE* pPackage = pEngineState->packages.rgPackages + i;
230
231
- if (BURN_PACKAGE_TYPE_EXE == pPackage->type && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol) // TODO: Don't assume exePackages with burn protocol are bundles.
231
+ if (BURN_PACKAGE_TYPE_BUNDLE == pPackage->type)
232
{
233
// Pass along any ancestors and ourself to prevent infinite loops.
234
- pPackage->Exe.wzAncestors = pRegistration->sczBundlePackageAncestors;
235
- pPackage->Exe.wzEngineWorkingDirectory = pInternalCommand->sczEngineWorkingDirectory;
234
+ pPackage->Bundle.wzAncestors = pRegistration->sczBundlePackageAncestors;
235
+ pPackage->Bundle.wzEngineWorkingDirectory = pInternalCommand->sczEngineWorkingDirectory;
236
}
237
}
238
@@ -518,7 +518,7 @@ extern "C" HRESULT CorePlan(
518
ExitOnFailure(hr, "Failed to plan the layout of the bundle.");
519
520
// Plan the packages' layout.
521
- hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType);
521
+ hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables);
522
ExitOnFailure(hr, "Failed to plan packages.");
523
}
524
else if (BOOTSTRAPPER_ACTION_UPDATE_REPLACE == action || BOOTSTRAPPER_ACTION_UPDATE_REPLACE_EMBEDDED == action)
@@ -527,7 +527,7 @@ extern "C" HRESULT CorePlan(
527
528
pUpgradeBundlePackage = &pEngineState->update.package;
529
530
- hr = PlanUpdateBundle(&pEngineState->userExperience, pUpgradeBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType);
530
+ hr = PlanUpdateBundle(&pEngineState->userExperience, pUpgradeBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables);
531
ExitOnFailure(hr, "Failed to plan update.");
532
}
533
else
@@ -541,7 +541,7 @@ extern "C" HRESULT CorePlan(
541
542
pForwardCompatibleBundlePackage = &pEngineState->plan.forwardCompatibleBundle;
543
544
- hr = PlanPassThroughBundle(&pEngineState->userExperience, pForwardCompatibleBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType);
544
+ hr = PlanPassThroughBundle(&pEngineState->userExperience, pForwardCompatibleBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables);
545
ExitOnFailure(hr, "Failed to plan passthrough.");
546
}
547
else // doing an action that modifies the machine state.
@@ -562,7 +562,7 @@ extern "C" HRESULT CorePlan(
562
hr = PlanRelatedBundlesBegin(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, &pEngineState->plan);
563
ExitOnFailure(hr, "Failed to plan related bundles.");
564
565
- hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType);
565
+ hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables);
566
ExitOnFailure(hr, "Failed to plan packages.");
567
568
// Schedule the update of related bundles last.
src/burn/engine/elevation.cpp
+139
-27
@@ -19,6 +19,7 @@ typedef enum _BURN_ELEVATION_MESSAGE_TYPE
19
BURN_ELEVATION_MESSAGE_TYPE_CACHE_VERIFY_PAYLOAD,
20
BURN_ELEVATION_MESSAGE_TYPE_CACHE_CLEANUP,
21
BURN_ELEVATION_MESSAGE_TYPE_PROCESS_DEPENDENT_REGISTRATION,
22
+ BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_RELATED_BUNDLE,
23
BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE,
24
BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE,
25
BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSP_PACKAGE,
@@ -230,11 +231,18 @@ static HRESULT OnProcessDependentRegistration(
231
__in BYTE* pbData,
232
__in SIZE_T cbData
233
);
234
+static HRESULT OnExecuteRelatedBundle(
235
+ __in HANDLE hPipe,
236
+ __in BURN_CACHE* pCache,
237
+ __in BURN_RELATED_BUNDLES* pRelatedBundles,
238
+ __in BURN_VARIABLES* pVariables,
239
+ __in BYTE* pbData,
240
+ __in SIZE_T cbData
241
+ );
242
static HRESULT OnExecuteExePackage(
243
__in HANDLE hPipe,
244
__in BURN_CACHE* pCache,
245
__in BURN_PACKAGES* pPackages,
237
- __in BURN_RELATED_BUNDLES* pRelatedBundles,
246
__in BURN_VARIABLES* pVariables,
247
__in BYTE* pbData,
248
__in SIZE_T cbData
@@ -818,10 +826,10 @@ LExit:
826
}
827
828
/*******************************************************************
821
- ElevationExecuteExePackage -
829
+ ElevationExecuteRelatedBundle -
830
831
*******************************************************************/
824
-extern "C" HRESULT ElevationExecuteExePackage(
832
+extern "C" HRESULT ElevationExecuteRelatedBundle(
833
__in HANDLE hPipe,
834
__in BURN_EXECUTE_ACTION* pExecuteAction,
835
__in BURN_VARIABLES* pVariables,
@@ -838,22 +846,22 @@ extern "C" HRESULT ElevationExecuteExePackage(
846
DWORD dwResult = 0;
847
848
// serialize message data
841
- hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.pPackage->sczId);
849
+ hr = BuffWriteString(&pbData, &cbData, pExecuteAction->relatedBundle.pRelatedBundle->package.sczId);
850
ExitOnFailure(hr, "Failed to write package id to message buffer.");
851
844
- hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->exePackage.action);
852
+ hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->relatedBundle.action);
853
ExitOnFailure(hr, "Failed to write action to message buffer.");
854
855
hr = BuffWriteNumber(&pbData, &cbData, fRollback);
856
ExitOnFailure(hr, "Failed to write rollback.");
857
850
- hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczIgnoreDependencies);
858
+ hr = BuffWriteString(&pbData, &cbData, pExecuteAction->relatedBundle.sczIgnoreDependencies);
859
ExitOnFailure(hr, "Failed to write the list of dependencies to ignore to the message buffer.");
860
853
- hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczAncestors);
861
+ hr = BuffWriteString(&pbData, &cbData, pExecuteAction->relatedBundle.sczAncestors);
862
ExitOnFailure(hr, "Failed to write the list of ancestors to the message buffer.");
863
856
- hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczEngineWorkingDirectory);
864
+ hr = BuffWriteString(&pbData, &cbData, pExecuteAction->relatedBundle.sczEngineWorkingDirectory);
865
ExitOnFailure(hr, "Failed to write the custom working directory to the message buffer.");
866
867
hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData);
@@ -863,6 +871,54 @@ extern "C" HRESULT ElevationExecuteExePackage(
871
context.pfnGenericMessageHandler = pfnGenericMessageHandler;
872
context.pvContext = pvContext;
873
874
+ hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_RELATED_BUNDLE, pbData, cbData, ProcessGenericExecuteMessages, &context, &dwResult);
875
+ ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_RELATED_BUNDLE message to per-machine process.");
876
+
877
+ hr = ProcessResult(dwResult, pRestart);
878
+
879
+LExit:
880
+ ReleaseBuffer(pbData);
881
+
882
+ return hr;
883
+}
884
+
885
+/*******************************************************************
886
+ ElevationExecuteExePackage -
887
+
888
+*******************************************************************/
889
+extern "C" HRESULT ElevationExecuteExePackage(
890
+ __in HANDLE hPipe,
891
+ __in BURN_EXECUTE_ACTION* pExecuteAction,
892
+ __in BURN_VARIABLES* pVariables,
893
+ __in BOOL fRollback,
894
+ __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
895
+ __in LPVOID pvContext,
896
+ __out BOOTSTRAPPER_APPLY_RESTART* pRestart
897
+ )
898
+{
899
+ HRESULT hr = S_OK;
900
+ BYTE* pbData = NULL;
901
+ SIZE_T cbData = 0;
902
+ BURN_ELEVATION_GENERIC_MESSAGE_CONTEXT context = { };
903
+ DWORD dwResult = 0;
904
+
905
+ // serialize message data
906
+ hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.pPackage->sczId);
907
+ ExitOnFailure(hr, "Failed to write package id to message buffer.");
908
+
909
+ hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->exePackage.action);
910
+ ExitOnFailure(hr, "Failed to write action to message buffer.");
911
+
912
+ hr = BuffWriteNumber(&pbData, &cbData, fRollback);
913
+ ExitOnFailure(hr, "Failed to write rollback.");
914
+
915
+ hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData);
916
+ ExitOnFailure(hr, "Failed to write variables.");
917
+
918
+ // send message
919
+ context.pfnGenericMessageHandler = pfnGenericMessageHandler;
920
+ context.pvContext = pvContext;
921
+
922
hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE, pbData, cbData, ProcessGenericExecuteMessages, &context, &dwResult);
923
ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE message to per-machine process.");
924
@@ -1911,8 +1967,12 @@ static HRESULT ProcessElevatedChildMessage(
1967
hrResult = OnProcessDependentRegistration(pContext->pRegistration, (BYTE*)pMsg->pvData, pMsg->cbData);
1968
break;
1969
1970
+ case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_RELATED_BUNDLE:
1971
+ hrResult = OnExecuteRelatedBundle(pContext->hPipe, pContext->pCache, &pContext->pRegistration->relatedBundles, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
1972
+ break;
1973
+
1974
case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE:
1915
- hrResult = OnExecuteExePackage(pContext->hPipe, pContext->pCache, pContext->pPackages, &pContext->pRegistration->relatedBundles, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
1975
+ hrResult = OnExecuteExePackage(pContext->hPipe, pContext->pCache, pContext->pPackages, pContext->pVariables, (BYTE*)pMsg->pvData, pMsg->cbData);
1976
break;
1977
1978
case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE:
@@ -2473,10 +2533,9 @@ LExit:
2533
return hr;
2534
}
2535
2476
-static HRESULT OnExecuteExePackage(
2536
+static HRESULT OnExecuteRelatedBundle(
2537
__in HANDLE hPipe,
2538
__in BURN_CACHE* pCache,
2479
- __in BURN_PACKAGES* pPackages,
2539
__in BURN_RELATED_BUNDLES* pRelatedBundles,
2540
__in BURN_VARIABLES* pVariables,
2541
__in BYTE* pbData,
@@ -2491,15 +2550,15 @@ static HRESULT OnExecuteExePackage(
2550
LPWSTR sczIgnoreDependencies = NULL;
2551
LPWSTR sczAncestors = NULL;
2552
LPWSTR sczEngineWorkingDirectory = NULL;
2494
- BOOTSTRAPPER_APPLY_RESTART exeRestart = BOOTSTRAPPER_APPLY_RESTART_NONE;
2553
+ BOOTSTRAPPER_APPLY_RESTART bundleRestart = BOOTSTRAPPER_APPLY_RESTART_NONE;
2554
2496
- executeAction.type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE;
2555
+ executeAction.type = BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE;
2556
2557
// Deserialize message data.
2558
hr = BuffReadString(pbData, cbData, &iData, &sczPackage);
2500
- ExitOnFailure(hr, "Failed to read EXE package id.");
2559
+ ExitOnFailure(hr, "Failed to read related bundle id.");
2560
2502
- hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.exePackage.action);
2561
+ hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.relatedBundle.action);
2562
ExitOnFailure(hr, "Failed to read action.");
2563
2564
hr = BuffReadNumber(pbData, cbData, &iData, &dwRollback);
@@ -2517,36 +2576,32 @@ static HRESULT OnExecuteExePackage(
2576
hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData);
2577
ExitOnFailure(hr, "Failed to read variables.");
2578
2520
- hr = PackageFindById(pPackages, sczPackage, &executeAction.exePackage.pPackage);
2521
- if (E_NOTFOUND == hr)
2522
- {
2523
- hr = PackageFindRelatedById(pRelatedBundles, sczPackage, &executeAction.exePackage.pPackage);
2524
- }
2525
- ExitOnFailure(hr, "Failed to find package: %ls", sczPackage);
2579
+ hr = RelatedBundleFindById(pRelatedBundles, sczPackage, &executeAction.relatedBundle.pRelatedBundle);
2580
+ ExitOnFailure(hr, "Failed to find related bundle: %ls", sczPackage);
2581
2582
// Pass the list of dependencies to ignore, if any, to the related bundle.
2583
if (sczIgnoreDependencies && *sczIgnoreDependencies)
2584
{
2530
- hr = StrAllocString(&executeAction.exePackage.sczIgnoreDependencies, sczIgnoreDependencies, 0);
2585
+ hr = StrAllocString(&executeAction.relatedBundle.sczIgnoreDependencies, sczIgnoreDependencies, 0);
2586
ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
2587
}
2588
2589
// Pass the list of ancestors, if any, to the related bundle.
2590
if (sczAncestors && *sczAncestors)
2591
{
2537
- hr = StrAllocString(&executeAction.exePackage.sczAncestors, sczAncestors, 0);
2592
+ hr = StrAllocString(&executeAction.relatedBundle.sczAncestors, sczAncestors, 0);
2593
ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
2594
}
2595
2596
if (sczEngineWorkingDirectory && *sczEngineWorkingDirectory)
2597
{
2543
- hr = StrAllocString(&executeAction.exePackage.sczEngineWorkingDirectory, sczEngineWorkingDirectory, 0);
2598
+ hr = StrAllocString(&executeAction.relatedBundle.sczEngineWorkingDirectory, sczEngineWorkingDirectory, 0);
2599
ExitOnFailure(hr, "Failed to allocate the custom working directory.");
2600
}
2601
2547
- // Execute EXE package.
2548
- hr = ExeEngineExecutePackage(&executeAction, pCache, pVariables, static_cast<BOOL>(dwRollback), GenericExecuteMessageHandler, hPipe, &exeRestart);
2549
- ExitOnFailure(hr, "Failed to execute EXE package.");
2602
+ // Execute related bundle.
2603
+ hr = BundlePackageEngineExecuteRelatedBundle(&executeAction, pCache, pVariables, static_cast<BOOL>(dwRollback), GenericExecuteMessageHandler, hPipe, &bundleRestart);
2604
+ ExitOnFailure(hr, "Failed to execute related bundle.");
2605
2606
LExit:
2607
ReleaseStr(sczEngineWorkingDirectory);
@@ -2555,6 +2610,63 @@ LExit:
2610
ReleaseStr(sczPackage);
2611
PlanUninitializeExecuteAction(&executeAction);
2612
2613
+ if (SUCCEEDED(hr))
2614
+ {
2615
+ if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == bundleRestart)
2616
+ {
2617
+ hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED);
2618
+ }
2619
+ else if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == bundleRestart)
2620
+ {
2621
+ hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_INITIATED);
2622
+ }
2623
+ }
2624
+
2625
+ return hr;
2626
+}
2627
+
2628
+static HRESULT OnExecuteExePackage(
2629
+ __in HANDLE hPipe,
2630
+ __in BURN_CACHE* pCache,
2631
+ __in BURN_PACKAGES* pPackages,
2632
+ __in BURN_VARIABLES* pVariables,
2633
+ __in BYTE* pbData,
2634
+ __in SIZE_T cbData
2635
+ )
2636
+{
2637
+ HRESULT hr = S_OK;
2638
+ SIZE_T iData = 0;
2639
+ LPWSTR sczPackage = NULL;
2640
+ DWORD dwRollback = 0;
2641
+ BURN_EXECUTE_ACTION executeAction = { };
2642
+ BOOTSTRAPPER_APPLY_RESTART exeRestart = BOOTSTRAPPER_APPLY_RESTART_NONE;
2643
+
2644
+ executeAction.type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE;
2645
+
2646
+ // Deserialize message data.
2647
+ hr = BuffReadString(pbData, cbData, &iData, &sczPackage);
2648
+ ExitOnFailure(hr, "Failed to read EXE package id.");
2649
+
2650
+ hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.exePackage.action);
2651
+ ExitOnFailure(hr, "Failed to read action.");
2652
+
2653
+ hr = BuffReadNumber(pbData, cbData, &iData, &dwRollback);
2654
+ ExitOnFailure(hr, "Failed to read rollback.");
2655
+
2656
+ hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData);
2657
+ ExitOnFailure(hr, "Failed to read variables.");
2658
+
2659
+ hr = PackageFindById(pPackages, sczPackage, &executeAction.exePackage.pPackage);
2660
+ ExitOnFailure(hr, "Failed to find package: %ls", sczPackage);
2661
+
2662
+ // Execute EXE package.
2663
+ hr = ExeEngineExecutePackage(&executeAction, pCache, pVariables, static_cast<BOOL>(dwRollback), GenericExecuteMessageHandler, hPipe, &exeRestart);
2664
+ ExitOnFailure(hr, "Failed to execute EXE package.");
2665
+
2666
+LExit:
2667
+ ReleaseStr(sczPackage);
2668
+ PlanUninitializeExecuteAction(&executeAction);
2669
+
2670
if (SUCCEEDED(hr))
2671
{
2672
if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == exeRestart)
src/burn/engine/elevation.h
+9
@@ -80,6 +80,15 @@ HRESULT ElevationProcessDependentRegistration(
80
__in HANDLE hPipe,
81
__in const BURN_DEPENDENT_REGISTRATION_ACTION* pAction
82
);
83
+HRESULT ElevationExecuteRelatedBundle(
84
+ __in HANDLE hPipe,
85
+ __in BURN_EXECUTE_ACTION* pExecuteAction,
86
+ __in BURN_VARIABLES* pVariables,
87
+ __in BOOL fRollback,
88
+ __in PFN_GENERICMESSAGEHANDLER pfnGenericMessageHandler,
89
+ __in LPVOID pvContext,
90
+ __out BOOTSTRAPPER_APPLY_RESTART* pRestart
91
+ );
92
HRESULT ElevationExecuteExePackage(
93
__in HANDLE hPipe,
94
__in BURN_EXECUTE_ACTION* pExecuteAction,
src/burn/engine/engine.vcxproj
+2
@@ -52,6 +52,7 @@
52
<ItemGroup>
53
<ClCompile Include="apply.cpp" />
54
<ClCompile Include="approvedexe.cpp" />
55
+ <ClCompile Include="bundlepackageengine.cpp" />
56
<ClCompile Include="burnextension.cpp" />
57
<ClCompile Include="detect.cpp" />
58
<ClCompile Include="embedded.cpp" />
@@ -101,6 +102,7 @@
102
<ClInclude Include="..\..\api\burn\WixToolset.BootstrapperCore.Native\inc\BootstrapperEngine.h" />
103
<ClInclude Include="..\..\api\burn\WixToolset.BootstrapperCore.Native\inc\BundleExtension.h" />
104
<ClInclude Include="..\..\api\burn\WixToolset.BootstrapperCore.Native\inc\BundleExtensionEngine.h" />
105
+ <ClInclude Include="bundlepackageengine.h" />
106
<ClInclude Include="burnextension.h" />
107
<ClInclude Include="cabextract.h" />
108
<ClInclude Include="cache.h" />
src/burn/engine/exeengine.cpp
+46
-131
@@ -3,23 +3,6 @@
3
#include "precomp.h"
4
5
6
-// internal function declarations
7
-
8
-static HRESULT HandleExitCode(
9
- __in BURN_PACKAGE* pPackage,
10
- __in DWORD dwExitCode,
11
- __out BOOTSTRAPPER_APPLY_RESTART* pRestart
12
- );
13
-static HRESULT ParseCommandLineArgumentsFromXml(
14
- __in IXMLDOMNode* pixnExePackage,
15
- __in BURN_PACKAGE* pPackage
16
- );
17
-static HRESULT ParseExitCodesFromXml(
18
- __in IXMLDOMNode* pixnExePackage,
19
- __in BURN_PACKAGE* pPackage
20
- );
21
-
22
-
6
// function definitions
7
8
extern "C" HRESULT ExeEngineParsePackageFromXml(
@@ -82,10 +65,10 @@ extern "C" HRESULT ExeEngineParsePackageFromXml(
65
ExitOnFailure(hr, "Failed to get @Protocol.");
66
}
67
85
- hr = ParseExitCodesFromXml(pixnExePackage, pPackage);
68
+ hr = ExeEngineParseExitCodesFromXml(pixnExePackage, &pPackage->Exe.rgExitCodes, &pPackage->Exe.cExitCodes);
69
ExitOnFailure(hr, "Failed to parse exit codes.");
70
88
- hr = ParseCommandLineArgumentsFromXml(pixnExePackage, pPackage);
71
+ hr = ExeEngineParseCommandLineArgumentsFromXml(pixnExePackage, &pPackage->Exe.rgCommandLineArguments, &pPackage->Exe.cCommandLineArguments);
72
ExitOnFailure(hr, "Failed to parse command lines.");
73
74
LExit:
@@ -104,8 +87,6 @@ extern "C" void ExeEnginePackageUninitialize(
87
ReleaseStr(pPackage->Exe.sczInstallArguments);
88
ReleaseStr(pPackage->Exe.sczRepairArguments);
89
ReleaseStr(pPackage->Exe.sczUninstallArguments);
107
- ReleaseStr(pPackage->Exe.sczIgnoreDependencies);
108
- //ReleaseStr(pPackage->Exe.sczProgressSwitch);
90
ReleaseMem(pPackage->Exe.rgExitCodes);
91
92
// free command-line arguments
@@ -113,11 +94,7 @@ extern "C" void ExeEnginePackageUninitialize(
94
{
95
for (DWORD i = 0; i < pPackage->Exe.cCommandLineArguments; ++i)
96
{
116
- BURN_EXE_COMMAND_LINE_ARGUMENT* pCommandLineArgument = &pPackage->Exe.rgCommandLineArguments[i];
117
- ReleaseStr(pCommandLineArgument->sczInstallArgument);
118
- ReleaseStr(pCommandLineArgument->sczUninstallArgument);
119
- ReleaseStr(pCommandLineArgument->sczRepairArgument);
120
- ReleaseStr(pCommandLineArgument->sczCondition);
97
+ ExeEngineCommandLineArgumentUninitialize(pPackage->Exe.rgCommandLineArguments + i);
98
}
99
MemFree(pPackage->Exe.rgCommandLineArguments);
100
}
@@ -126,6 +103,16 @@ extern "C" void ExeEnginePackageUninitialize(
103
memset(&pPackage->Exe, 0, sizeof(pPackage->Exe));
104
}
105
106
+extern "C" void ExeEngineCommandLineArgumentUninitialize(
107
+ __in BURN_EXE_COMMAND_LINE_ARGUMENT* pCommandLineArgument
108
+ )
109
+{
110
+ ReleaseStr(pCommandLineArgument->sczInstallArgument);
111
+ ReleaseStr(pCommandLineArgument->sczUninstallArgument);
112
+ ReleaseStr(pCommandLineArgument->sczRepairArgument);
113
+ ReleaseStr(pCommandLineArgument->sczCondition);
114
+}
115
+
116
extern "C" HRESULT ExeEngineDetectPackage(
117
__in BURN_PACKAGE* pPackage,
118
__in BURN_VARIABLES* pVariables
@@ -264,7 +251,6 @@ LExit:
251
// PlanAdd - adds the calculated execute and rollback actions for the package.
252
//
253
extern "C" HRESULT ExeEnginePlanAddPackage(
267
- __in_opt DWORD *pdwInsertSequence,
254
__in BURN_PACKAGE* pPackage,
255
__in BURN_PLAN* pPlan,
256
__in BURN_LOGGING* pLog,
@@ -274,46 +260,19 @@ extern "C" HRESULT ExeEnginePlanAddPackage(
260
HRESULT hr = S_OK;
261
BURN_EXECUTE_ACTION* pAction = NULL;
262
277
- hr = DependencyPlanPackage(pdwInsertSequence, pPackage, pPlan);
263
+ hr = DependencyPlanPackage(NULL, pPackage, pPlan);
264
ExitOnFailure(hr, "Failed to plan package dependency actions.");
265
266
// add execute action
267
if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute)
268
{
283
- if (NULL != pdwInsertSequence)
284
- {
285
- hr = PlanInsertExecuteAction(*pdwInsertSequence, pPlan, &pAction);
286
- ExitOnFailure(hr, "Failed to insert execute action.");
287
- }
288
- else
289
- {
290
- hr = PlanAppendExecuteAction(pPlan, &pAction);
291
- ExitOnFailure(hr, "Failed to append execute action.");
292
- }
269
+ hr = PlanAppendExecuteAction(pPlan, &pAction);
270
+ ExitOnFailure(hr, "Failed to append execute action.");
271
272
pAction->type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE;
273
pAction->exePackage.pPackage = pPackage;
296
- pAction->exePackage.fFireAndForget = (BOOTSTRAPPER_ACTION_UPDATE_REPLACE == pPlan->action);
274
pAction->exePackage.action = pPackage->execute;
275
299
- if (pPackage->Exe.sczIgnoreDependencies)
300
- {
301
- hr = StrAllocString(&pAction->exePackage.sczIgnoreDependencies, pPackage->Exe.sczIgnoreDependencies, 0);
302
- ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
303
- }
304
-
305
- if (pPackage->Exe.wzAncestors)
306
- {
307
- hr = StrAllocString(&pAction->exePackage.sczAncestors, pPackage->Exe.wzAncestors, 0);
308
- ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
309
- }
310
-
311
- if (pPackage->Exe.wzEngineWorkingDirectory)
312
- {
313
- hr = StrAllocString(&pAction->exePackage.sczEngineWorkingDirectory, pPackage->Exe.wzEngineWorkingDirectory, 0);
314
- ExitOnFailure(hr, "Failed to allocate the custom working directory.");
315
- }
316
-
276
LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, NULL); // ignore errors.
277
}
278
@@ -327,18 +286,6 @@ extern "C" HRESULT ExeEnginePlanAddPackage(
286
pAction->exePackage.pPackage = pPackage;
287
pAction->exePackage.action = pPackage->rollback;
288
330
- if (pPackage->Exe.sczIgnoreDependencies)
331
- {
332
- hr = StrAllocString(&pAction->exePackage.sczIgnoreDependencies, pPackage->Exe.sczIgnoreDependencies, 0);
333
- ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
334
- }
335
-
336
- if (pPackage->Exe.wzAncestors)
337
- {
338
- hr = StrAllocString(&pAction->exePackage.sczAncestors, pPackage->Exe.wzAncestors, 0);
339
- ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
340
- }
341
-
289
LoggingSetPackageVariable(pPackage, NULL, TRUE, pLog, pVariables, NULL); // ignore errors.
290
}
291
@@ -452,13 +399,13 @@ extern "C" HRESULT ExeEngineExecutePackage(
399
hr = VariableFormatString(pVariables, sczArguments, &sczArgumentsFormatted, NULL);
400
ExitOnFailure(hr, "Failed to format argument string.");
401
455
- hr = StrAllocFormattedSecure(&sczCommand, L"\"%ls\" %s", sczExecutablePath, sczArgumentsFormatted);
402
+ hr = StrAllocFormattedSecure(&sczCommand, L"\"%ls\" %ls", sczExecutablePath, sczArgumentsFormatted);
403
ExitOnFailure(hr, "Failed to create executable command.");
404
405
hr = VariableFormatStringObfuscated(pVariables, sczArguments, &sczArgumentsObfuscated, NULL);
406
ExitOnFailure(hr, "Failed to format obfuscated argument string.");
407
461
- hr = StrAllocFormatted(&sczCommandObfuscated, L"\"%ls\" %s", sczExecutablePath, sczArgumentsObfuscated);
408
+ hr = StrAllocFormatted(&sczCommandObfuscated, L"\"%ls\" %ls", sczExecutablePath, sczArgumentsObfuscated);
409
}
410
else
411
{
@@ -469,47 +416,15 @@ extern "C" HRESULT ExeEngineExecutePackage(
416
}
417
ExitOnFailure(hr, "Failed to create obfuscated executable command.");
418
472
- if (pPackage->Exe.fSupportsAncestors)
473
- {
474
- // Add the list of dependencies to ignore, if any, to the burn command line.
475
- if (pExecuteAction->exePackage.sczIgnoreDependencies && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol)
476
- {
477
- hr = StrAllocFormattedSecure(&sczCommand, L"%ls -%ls=%ls", sczCommand, BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->exePackage.sczIgnoreDependencies);
478
- ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the command line.");
479
-
480
- hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls -%ls=%ls", sczCommandObfuscated, BURN_COMMANDLINE_SWITCH_IGNOREDEPENDENCIES, pExecuteAction->exePackage.sczIgnoreDependencies);
481
- ExitOnFailure(hr, "Failed to append the list of dependencies to ignore to the obfuscated command line.");
482
- }
483
-
484
- // Add the list of ancestors, if any, to the burn command line.
485
- if (pExecuteAction->exePackage.sczAncestors)
486
- {
487
- hr = StrAllocFormattedSecure(&sczCommand, L"%ls -%ls=%ls", sczCommand, BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->exePackage.sczAncestors);
488
- ExitOnFailure(hr, "Failed to append the list of ancestors to the command line.");
489
-
490
- hr = StrAllocFormatted(&sczCommandObfuscated, L"%ls -%ls=%ls", sczCommandObfuscated, BURN_COMMANDLINE_SWITCH_ANCESTORS, pExecuteAction->exePackage.sczAncestors);
491
- ExitOnFailure(hr, "Failed to append the list of ancestors to the obfuscated command line.");
492
- }
493
- }
494
-
495
- if (BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol)
496
- {
497
- hr = CoreAppendEngineWorkingDirectoryToCommandLine(pExecuteAction->exePackage.sczEngineWorkingDirectory, &sczCommand, &sczCommandObfuscated);
498
- ExitOnFailure(hr, "Failed to append the custom working directory to the exepackage command line.");
499
-
500
- hr = CoreAppendFileHandleSelfToCommandLine(sczExecutablePath, &hExecutableFile, &sczCommand, &sczCommandObfuscated);
501
- ExitOnFailure(hr, "Failed to append %ls", BURN_COMMANDLINE_SWITCH_FILEHANDLE_SELF);
502
- }
503
-
419
// Log before we add the secret pipe name and client token for embedded processes.
420
LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(pExecuteAction->exePackage.action), sczExecutablePath, sczCommandObfuscated);
421
507
- if (!pExecuteAction->exePackage.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol)
422
+ if (!pPackage->Exe.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol)
423
{
424
hr = EmbeddedRunBundle(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode);
510
- ExitOnFailure(hr, "Failed to run bundle as embedded from path: %ls", sczExecutablePath);
425
+ ExitOnFailure(hr, "Failed to run exe with Burn protocol from path: %ls", sczExecutablePath);
426
}
512
- else if (!pExecuteAction->exePackage.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_NETFX4 == pPackage->Exe.protocol)
427
+ else if (!pPackage->Exe.fFireAndForget && BURN_EXE_PROTOCOL_TYPE_NETFX4 == pPackage->Exe.protocol)
428
{
429
hr = NetFxRunChainer(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode);
430
ExitOnFailure(hr, "Failed to run netfx chainer: %ls", sczExecutablePath);
@@ -524,7 +439,7 @@ extern "C" HRESULT ExeEngineExecutePackage(
439
ExitWithLastError(hr, "Failed to CreateProcess on path: %ls", sczExecutablePath);
440
}
441
527
- if (pExecuteAction->exePackage.fFireAndForget)
442
+ if (pPackage->Exe.fFireAndForget)
443
{
444
::WaitForInputIdle(pi.hProcess, 5000);
445
ExitFunction();
@@ -547,7 +462,7 @@ extern "C" HRESULT ExeEngineExecutePackage(
462
} while (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr);
463
}
464
550
- hr = HandleExitCode(pPackage, dwExitCode, pRestart);
465
+ hr = ExeEngineHandleExitCode(pPackage->Exe.rgExitCodes, pPackage->Exe.cExitCodes, dwExitCode, pRestart);
466
ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode);
467
468
LExit:
@@ -595,12 +510,10 @@ LExit:
510
return;
511
}
512
598
-
599
-// internal helper functions
600
-
601
-static HRESULT ParseExitCodesFromXml(
602
- __in IXMLDOMNode* pixnExePackage,
603
- __in BURN_PACKAGE* pPackage
513
+extern "C" HRESULT ExeEngineParseExitCodesFromXml(
514
+ __in IXMLDOMNode* pixnPackage,
515
+ __inout BURN_EXE_EXIT_CODE** prgExitCodes,
516
+ __inout DWORD* pcExitCodes
517
)
518
{
519
HRESULT hr = S_OK;
@@ -610,7 +523,7 @@ static HRESULT ParseExitCodesFromXml(
523
LPWSTR scz = NULL;
524
525
// select exit code nodes
613
- hr = XmlSelectNodes(pixnExePackage, L"ExitCode", &pixnNodes);
526
+ hr = XmlSelectNodes(pixnPackage, L"ExitCode", &pixnNodes);
527
ExitOnFailure(hr, "Failed to select exit code nodes.");
528
529
// get exit code node count
@@ -620,15 +533,15 @@ static HRESULT ParseExitCodesFromXml(
533
if (cNodes)
534
{
535
// allocate memory for exit codes
623
- pPackage->Exe.rgExitCodes = (BURN_EXE_EXIT_CODE*) MemAlloc(sizeof(BURN_EXE_EXIT_CODE) * cNodes, TRUE);
624
- ExitOnNull(pPackage->Exe.rgExitCodes, hr, E_OUTOFMEMORY, "Failed to allocate memory for exit code structs.");
536
+ *prgExitCodes = (BURN_EXE_EXIT_CODE*) MemAlloc(sizeof(BURN_EXE_EXIT_CODE) * cNodes, TRUE);
537
+ ExitOnNull(*prgExitCodes, hr, E_OUTOFMEMORY, "Failed to allocate memory for exit code structs.");
538
626
- pPackage->Exe.cExitCodes = cNodes;
539
+ *pcExitCodes = cNodes;
540
541
// parse package elements
542
for (DWORD i = 0; i < cNodes; ++i)
543
{
631
- BURN_EXE_EXIT_CODE* pExitCode = &pPackage->Exe.rgExitCodes[i];
544
+ BURN_EXE_EXIT_CODE* pExitCode = *prgExitCodes + i;
545
546
hr = XmlNextElement(pixnNodes, &pixnNode, NULL);
547
ExitOnFailure(hr, "Failed to get next node.");
@@ -666,9 +579,10 @@ LExit:
579
return hr;
580
}
581
669
-static HRESULT ParseCommandLineArgumentsFromXml(
670
- __in IXMLDOMNode* pixnExePackage,
671
- __in BURN_PACKAGE* pPackage
582
+extern "C" HRESULT ExeEngineParseCommandLineArgumentsFromXml(
583
+ __in IXMLDOMNode* pixnPackage,
584
+ __inout BURN_EXE_COMMAND_LINE_ARGUMENT** prgCommandLineArguments,
585
+ __inout DWORD* pcCommandLineArguments
586
)
587
{
588
HRESULT hr = S_OK;
@@ -678,7 +592,7 @@ static HRESULT ParseCommandLineArgumentsFromXml(
592
LPWSTR scz = NULL;
593
594
// Select command-line argument nodes.
681
- hr = XmlSelectNodes(pixnExePackage, L"CommandLine", &pixnNodes);
595
+ hr = XmlSelectNodes(pixnPackage, L"CommandLine", &pixnNodes);
596
ExitOnFailure(hr, "Failed to select command-line argument nodes.");
597
598
// Get command-line argument node count.
@@ -687,15 +601,15 @@ static HRESULT ParseCommandLineArgumentsFromXml(
601
602
if (cNodes)
603
{
690
- pPackage->Exe.rgCommandLineArguments = (BURN_EXE_COMMAND_LINE_ARGUMENT*) MemAlloc(sizeof(BURN_EXE_COMMAND_LINE_ARGUMENT) * cNodes, TRUE);
691
- ExitOnNull(pPackage->Exe.rgCommandLineArguments, hr, E_OUTOFMEMORY, "Failed to allocate memory for command-line argument structs.");
604
+ *prgCommandLineArguments = (BURN_EXE_COMMAND_LINE_ARGUMENT*) MemAlloc(sizeof(BURN_EXE_COMMAND_LINE_ARGUMENT) * cNodes, TRUE);
605
+ ExitOnNull(*prgCommandLineArguments, hr, E_OUTOFMEMORY, "Failed to allocate memory for command-line argument structs.");
606
693
- pPackage->Exe.cCommandLineArguments = cNodes;
607
+ *pcCommandLineArguments = cNodes;
608
609
// Parse command-line argument elements.
610
for (DWORD i = 0; i < cNodes; ++i)
611
{
698
- BURN_EXE_COMMAND_LINE_ARGUMENT* pCommandLineArgument = &pPackage->Exe.rgCommandLineArguments[i];
612
+ BURN_EXE_COMMAND_LINE_ARGUMENT* pCommandLineArgument = *prgCommandLineArguments + i;
613
614
hr = XmlNextElement(pixnNodes, &pixnNode, NULL);
615
ExitOnFailure(hr, "Failed to get next command-line argument node.");
@@ -731,8 +645,9 @@ LExit:
645
return hr;
646
}
647
734
-static HRESULT HandleExitCode(
735
- __in BURN_PACKAGE* pPackage,
648
+extern "C" HRESULT ExeEngineHandleExitCode(
649
+ __in BURN_EXE_EXIT_CODE* rgCustomExitCodes,
650
+ __in DWORD cCustomExitCodes,
651
__in DWORD dwExitCode,
652
__out BOOTSTRAPPER_APPLY_RESTART* pRestart
653
)
@@ -740,9 +655,9 @@ static HRESULT HandleExitCode(
655
HRESULT hr = S_OK;
656
BURN_EXE_EXIT_CODE_TYPE typeCode = BURN_EXE_EXIT_CODE_TYPE_NONE;
657
743
- for (DWORD i = 0; i < pPackage->Exe.cExitCodes; ++i)
658
+ for (DWORD i = 0; i < cCustomExitCodes; ++i)
659
{
745
- BURN_EXE_EXIT_CODE* pExitCode = &pPackage->Exe.rgExitCodes[i];
660
+ BURN_EXE_EXIT_CODE* pExitCode = rgCustomExitCodes + i;
661
662
// If this is a wildcard, use the last one we come across.
663
if (pExitCode->fWildcard)
src/burn/engine/exeengine.h
+19
-1
@@ -16,6 +16,9 @@ HRESULT ExeEngineParsePackageFromXml(
16
void ExeEnginePackageUninitialize(
17
__in BURN_PACKAGE* pPackage
18
);
19
+void ExeEngineCommandLineArgumentUninitialize(
20
+ __in BURN_EXE_COMMAND_LINE_ARGUMENT* pCommandLineArgument
21
+ );
22
HRESULT ExeEngineDetectPackage(
23
__in BURN_PACKAGE* pPackage,
24
__in BURN_VARIABLES* pVariables
@@ -24,7 +27,6 @@ HRESULT ExeEnginePlanCalculatePackage(
27
__in BURN_PACKAGE* pPackage
28
);
29
HRESULT ExeEnginePlanAddPackage(
27
- __in_opt DWORD *pdwInsertSequence,
30
__in BURN_PACKAGE* pPackage,
31
__in BURN_PLAN* pPlan,
32
__in BURN_LOGGING* pLog,
@@ -43,6 +45,22 @@ void ExeEngineUpdateInstallRegistrationState(
45
__in BURN_EXECUTE_ACTION* pAction,
46
__in HRESULT hrExecute
47
);
48
+HRESULT ExeEngineParseExitCodesFromXml(
49
+ __in IXMLDOMNode* pixnPackage,
50
+ __inout BURN_EXE_EXIT_CODE** prgExitCodes,
51
+ __inout DWORD* pcExitCodes
52
+ );
53
+HRESULT ExeEngineParseCommandLineArgumentsFromXml(
54
+ __in IXMLDOMNode* pixnPackage,
55
+ __inout BURN_EXE_COMMAND_LINE_ARGUMENT** prgCommandLineArguments,
56
+ __inout DWORD* pcCommandLineArguments
57
+ );
58
+HRESULT ExeEngineHandleExitCode(
59
+ __in BURN_EXE_EXIT_CODE* rgCustomExitCodes,
60
+ __in DWORD cCustomExitCodes,
61
+ __in DWORD dwExitCode,
62
+ __out BOOTSTRAPPER_APPLY_RESTART* pRestart
63
+ );
64
65
66
#if defined(__cplusplus)
src/burn/engine/package.cpp
+7
-15
@@ -350,6 +350,9 @@ extern "C" void PackageUninitialize(
350
351
switch (pPackage->type)
352
{
353
+ case BURN_PACKAGE_TYPE_BUNDLE:
354
+ BundlePackageEnginePackageUninitialize(pPackage);
355
+ break;
356
case BURN_PACKAGE_TYPE_EXE:
357
ExeEnginePackageUninitialize(pPackage); // TODO: Modularization
358
break;
@@ -439,22 +442,11 @@ extern "C" HRESULT PackageFindRelatedById(
442
)
443
{
444
HRESULT hr = S_OK;
442
- BURN_PACKAGE* pPackage = NULL;
443
-
444
- for (DWORD i = 0; i < pRelatedBundles->cRelatedBundles; ++i)
445
- {
446
- pPackage = &pRelatedBundles->rgRelatedBundles[i].package;
447
-
448
- if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPackage->sczId, -1, wzId, -1))
449
- {
450
- *ppPackage = pPackage;
451
- ExitFunction1(hr = S_OK);
452
- }
453
- }
445
+ BURN_RELATED_BUNDLE* pRelatedBundle = NULL;
446
+
447
+ hr = RelatedBundleFindById(pRelatedBundles, wzId, &pRelatedBundle);
448
+ *ppPackage = FAILED(hr) ? NULL : &pRelatedBundle->package;
449
455
- hr = E_NOTFOUND;
456
-
457
-LExit:
450
return hr;
451
}
452
src/burn/engine/package.h
+19
-3
@@ -35,6 +35,7 @@ enum BURN_EXE_PROTOCOL_TYPE
35
enum BURN_PACKAGE_TYPE
36
{
37
BURN_PACKAGE_TYPE_NONE,
38
+ BURN_PACKAGE_TYPE_BUNDLE,
39
BURN_PACKAGE_TYPE_EXE,
40
BURN_PACKAGE_TYPE_MSI,
41
BURN_PACKAGE_TYPE_MSP,
@@ -263,21 +264,36 @@ typedef struct _BURN_PACKAGE
264
{
265
struct
266
{
266
- LPWSTR sczDetectCondition;
267
LPWSTR sczInstallArguments;
268
LPWSTR sczRepairArguments;
269
LPWSTR sczUninstallArguments;
270
+
271
LPWSTR sczIgnoreDependencies;
272
LPCWSTR wzAncestors; // points directly into engine state.
273
LPCWSTR wzEngineWorkingDirectory; // points directly into engine state.
274
275
BOOL fPseudoBundle;
276
+ BOOL fRepairable;
277
+ BOOL fSupportsBurnProtocol;
278
279
+ BURN_EXE_EXIT_CODE* rgExitCodes;
280
+ DWORD cExitCodes;
281
+
282
+ BURN_EXE_COMMAND_LINE_ARGUMENT* rgCommandLineArguments;
283
+ DWORD cCommandLineArguments;
284
+ } Bundle;
285
+ struct
286
+ {
287
+ LPWSTR sczDetectCondition;
288
+ LPWSTR sczInstallArguments;
289
+ LPWSTR sczRepairArguments;
290
+ LPWSTR sczUninstallArguments;
291
+
292
+ BOOL fPseudoBundle;
293
+ BOOL fFireAndForget;
294
BOOL fRepairable;
295
BURN_EXE_PROTOCOL_TYPE protocol;
296
279
- BOOL fSupportsAncestors;
280
-
297
BURN_EXE_EXIT_CODE* rgExitCodes;
298
DWORD cExitCodes;
299
src/burn/engine/plan.cpp
+67
-61
@@ -36,16 +36,13 @@ static HRESULT PlanPackagesHelper(
36
__in BURN_USER_EXPERIENCE* pUX,
37
__in BURN_PLAN* pPlan,
38
__in BURN_LOGGING* pLog,
39
- __in BURN_VARIABLES* pVariables,
40
- __in BOOTSTRAPPER_DISPLAY display,
41
- __in BOOTSTRAPPER_RELATION_TYPE relationType
39
+ __in BURN_VARIABLES* pVariables
40
);
41
static HRESULT InitializePackage(
42
__in BURN_PLAN* pPlan,
43
__in BURN_USER_EXPERIENCE* pUX,
44
__in BURN_VARIABLES* pVariables,
47
- __in BURN_PACKAGE* pPackage,
48
- __in BOOTSTRAPPER_RELATION_TYPE relationType
45
+ __in BURN_PACKAGE* pPackage
46
);
47
static HRESULT ProcessPackage(
48
__in BOOL fBundlePerMachine,
@@ -54,7 +51,6 @@ static HRESULT ProcessPackage(
51
__in BURN_PACKAGE* pPackage,
52
__in BURN_LOGGING* pLog,
53
__in BURN_VARIABLES* pVariables,
57
- __in BOOTSTRAPPER_DISPLAY display,
54
__inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary
55
);
56
static HRESULT ProcessPackageRollbackBoundary(
@@ -266,10 +262,10 @@ extern "C" void PlanUninitializeExecuteAction(
262
{
263
switch (pExecuteAction->type)
264
{
269
- case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
270
- ReleaseStr(pExecuteAction->exePackage.sczIgnoreDependencies);
271
- ReleaseStr(pExecuteAction->exePackage.sczAncestors);
272
- ReleaseStr(pExecuteAction->exePackage.sczEngineWorkingDirectory);
265
+ case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE:
266
+ ReleaseStr(pExecuteAction->relatedBundle.sczIgnoreDependencies);
267
+ ReleaseStr(pExecuteAction->relatedBundle.sczAncestors);
268
+ ReleaseStr(pExecuteAction->relatedBundle.sczEngineWorkingDirectory);
269
break;
270
271
case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE:
@@ -500,14 +496,12 @@ extern "C" HRESULT PlanPackages(
496
__in BURN_PACKAGES* pPackages,
497
__in BURN_PLAN* pPlan,
498
__in BURN_LOGGING* pLog,
503
- __in BURN_VARIABLES* pVariables,
504
- __in BOOTSTRAPPER_DISPLAY display,
505
- __in BOOTSTRAPPER_RELATION_TYPE relationType
499
+ __in BURN_VARIABLES* pVariables
500
)
501
{
502
HRESULT hr = S_OK;
503
510
- hr = PlanPackagesHelper(pPackages->rgPackages, pPackages->cPackages, pUX, pPlan, pLog, pVariables, display, relationType);
504
+ hr = PlanPackagesHelper(pPackages->rgPackages, pPackages->cPackages, pUX, pPlan, pLog, pVariables);
505
506
return hr;
507
}
@@ -712,15 +706,13 @@ extern "C" HRESULT PlanPassThroughBundle(
706
__in BURN_PACKAGE* pPackage,
707
__in BURN_PLAN* pPlan,
708
__in BURN_LOGGING* pLog,
715
- __in BURN_VARIABLES* pVariables,
716
- __in BOOTSTRAPPER_DISPLAY display,
717
- __in BOOTSTRAPPER_RELATION_TYPE relationType
709
+ __in BURN_VARIABLES* pVariables
710
)
711
{
712
HRESULT hr = S_OK;
713
714
// Plan passthrough package.
723
- hr = PlanPackagesHelper(pPackage, 1, pUX, pPlan, pLog, pVariables, display, relationType);
715
+ hr = PlanPackagesHelper(pPackage, 1, pUX, pPlan, pLog, pVariables);
716
ExitOnFailure(hr, "Failed to process passthrough package.");
717
718
LExit:
@@ -732,15 +724,17 @@ extern "C" HRESULT PlanUpdateBundle(
724
__in BURN_PACKAGE* pPackage,
725
__in BURN_PLAN* pPlan,
726
__in BURN_LOGGING* pLog,
735
- __in BURN_VARIABLES* pVariables,
736
- __in BOOTSTRAPPER_DISPLAY display,
737
- __in BOOTSTRAPPER_RELATION_TYPE relationType
727
+ __in BURN_VARIABLES* pVariables
728
)
729
{
730
HRESULT hr = S_OK;
731
732
+ Assert(!pPackage->fPerMachine);
733
+ Assert(BURN_PACKAGE_TYPE_EXE == pPackage->type);
734
+ pPackage->Exe.fFireAndForget = BOOTSTRAPPER_ACTION_UPDATE_REPLACE == pPlan->action;
735
+
736
// Plan update package.
743
- hr = PlanPackagesHelper(pPackage, 1, pUX, pPlan, pLog, pVariables, display, relationType);
737
+ hr = PlanPackagesHelper(pPackage, 1, pUX, pPlan, pLog, pVariables);
738
ExitOnFailure(hr, "Failed to process update package.");
739
740
LExit:
@@ -753,9 +747,7 @@ static HRESULT PlanPackagesHelper(
747
__in BURN_USER_EXPERIENCE* pUX,
748
__in BURN_PLAN* pPlan,
749
__in BURN_LOGGING* pLog,
756
- __in BURN_VARIABLES* pVariables,
757
- __in BOOTSTRAPPER_DISPLAY display,
758
- __in BOOTSTRAPPER_RELATION_TYPE relationType
750
+ __in BURN_VARIABLES* pVariables
751
)
752
{
753
HRESULT hr = S_OK;
@@ -768,7 +760,7 @@ static HRESULT PlanPackagesHelper(
760
DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i;
761
BURN_PACKAGE* pPackage = rgPackages + iPackage;
762
771
- hr = InitializePackage(pPlan, pUX, pVariables, pPackage, relationType);
763
+ hr = InitializePackage(pPlan, pUX, pVariables, pPackage);
764
ExitOnFailure(hr, "Failed to initialize package.");
765
}
766
@@ -791,7 +783,7 @@ static HRESULT PlanPackagesHelper(
783
DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i;
784
BURN_PACKAGE* pPackage = rgPackages + iPackage;
785
794
- hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, &pRollbackBoundary);
786
+ hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, &pRollbackBoundary);
787
ExitOnFailure(hr, "Failed to process package.");
788
}
789
@@ -841,14 +833,24 @@ static HRESULT InitializePackage(
833
__in BURN_PLAN* pPlan,
834
__in BURN_USER_EXPERIENCE* pUX,
835
__in BURN_VARIABLES* pVariables,
844
- __in BURN_PACKAGE* pPackage,
845
- __in BOOTSTRAPPER_RELATION_TYPE relationType
836
+ __in BURN_PACKAGE* pPackage
837
)
838
{
839
HRESULT hr = S_OK;
840
BOOTSTRAPPER_PACKAGE_CONDITION_RESULT installCondition = BOOTSTRAPPER_PACKAGE_CONDITION_DEFAULT;
841
BOOL fInstallCondition = FALSE;
842
BOOL fBeginCalled = FALSE;
843
+ BOOTSTRAPPER_RELATION_TYPE relationType = pPlan->pCommand->relationType;
844
+
845
+ if (BURN_PACKAGE_TYPE_EXE == pPackage->type && pPackage->Exe.fPseudoBundle)
846
+ {
847
+ // Exe pseudo bundles are not configurable.
848
+ // The BA already requested this package to be executed
849
+ // * by the overall plan action for UpdateReplace
850
+ // * by enabling the forward compatible bundle for Passthrough
851
+ pPackage->defaultRequested = pPackage->requested = BOOTSTRAPPER_REQUEST_STATE_PRESENT;
852
+ ExitFunction();
853
+ }
854
855
if (pPackage->fCanAffectRegistration)
856
{
@@ -896,7 +898,6 @@ static HRESULT ProcessPackage(
898
__in BURN_PACKAGE* pPackage,
899
__in BURN_LOGGING* pLog,
900
__in BURN_VARIABLES* pVariables,
899
- __in BOOTSTRAPPER_DISPLAY display,
901
__inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary
902
)
903
{
@@ -920,7 +921,7 @@ static HRESULT ProcessPackage(
921
if (BOOTSTRAPPER_REQUEST_STATE_NONE != pPackage->requested)
922
{
923
// If the package is in a requested state, plan it.
923
- hr = PlanExecutePackage(fBundlePerMachine, display, pUX, pPlan, pPackage, pLog, pVariables);
924
+ hr = PlanExecutePackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables);
925
ExitOnFailure(hr, "Failed to plan execute package.");
926
}
927
else
@@ -1064,7 +1065,6 @@ LExit:
1065
1066
extern "C" HRESULT PlanExecutePackage(
1067
__in BOOL fPerMachine,
1067
- __in BOOTSTRAPPER_DISPLAY display,
1068
__in BURN_USER_EXPERIENCE* pUserExperience,
1069
__in BURN_PLAN* pPlan,
1070
__in BURN_PACKAGE* pPackage,
@@ -1073,6 +1073,7 @@ extern "C" HRESULT PlanExecutePackage(
1073
)
1074
{
1075
HRESULT hr = S_OK;
1076
+ BOOTSTRAPPER_DISPLAY display = pPlan->pCommand->display;
1077
BOOL fRequestedCache = BOOTSTRAPPER_CACHE_TYPE_REMOVE < pPackage->cacheType && (BOOTSTRAPPER_REQUEST_STATE_CACHE == pPackage->requested || ForceCache(pPlan, pPackage));
1078
1079
hr = CalculateExecuteActions(pPackage, pPlan->pActiveRollbackBoundary);
@@ -1124,7 +1125,7 @@ extern "C" HRESULT PlanExecutePackage(
1125
switch (pPackage->type)
1126
{
1127
case BURN_PACKAGE_TYPE_EXE:
1127
- hr = ExeEnginePlanAddPackage(NULL, pPackage, pPlan, pLog, pVariables);
1128
+ hr = ExeEnginePlanAddPackage(pPackage, pPlan, pLog, pVariables);
1129
break;
1130
1131
case BURN_PACKAGE_TYPE_MSI:
@@ -1288,8 +1289,8 @@ extern "C" HRESULT PlanRelatedBundlesBegin(
1289
}
1290
1291
// Pass along any ancestors and ourself to prevent infinite loops.
1291
- pRelatedBundle->package.Exe.wzAncestors = pRegistration->sczBundlePackageAncestors;
1292
- pRelatedBundle->package.Exe.wzEngineWorkingDirectory = pPlan->pInternalCommand->sczEngineWorkingDirectory;
1292
+ pRelatedBundle->package.Bundle.wzAncestors = pRegistration->sczBundlePackageAncestors;
1293
+ pRelatedBundle->package.Bundle.wzEngineWorkingDirectory = pPlan->pInternalCommand->sczEngineWorkingDirectory;
1294
1295
hr = PlanDefaultRelatedBundleRequestState(relationType, pRelatedBundle->relationType, pPlan->action, pRegistration->pVersion, pRelatedBundle->pVersion, &pRelatedBundle->package.requested);
1296
ExitOnFailure(hr, "Failed to get default request state for related bundle.");
@@ -1349,37 +1350,38 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1350
1351
for (DWORD i = 0; i < pPlan->cExecuteActions; ++i)
1352
{
1352
- if (BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE == pPlan->rgExecuteActions[i].type && BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].exePackage.action)
1353
+ switch (pPlan->rgExecuteActions[i].type)
1354
{
1354
- fExecutingAnyPackage = TRUE;
1355
-
1356
- BURN_PACKAGE* pPackage = pPlan->rgExecuteActions[i].packageProvider.pPackage;
1357
- if (BURN_PACKAGE_TYPE_EXE == pPackage->type && BURN_EXE_PROTOCOL_TYPE_BURN == pPackage->Exe.protocol)
1355
+ case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE:
1356
+ if (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].relatedBundle.action)
1357
{
1359
- if (0 < pPackage->cDependencyProviders)
1358
+ fExecutingAnyPackage = TRUE;
1359
+
1360
+ BURN_PACKAGE* pPackage = &pPlan->rgExecuteActions[i].relatedBundle.pRelatedBundle->package;
1361
+ if (pPackage->cDependencyProviders)
1362
{
1363
// Bundles only support a single provider key.
1364
const BURN_DEPENDENCY_PROVIDER* pProvider = pPackage->rgDependencyProviders;
1365
DictAddKey(sdProviderKeys, pProvider->sczKey);
1366
}
1367
}
1366
- }
1367
- else
1368
- {
1369
- switch (pPlan->rgExecuteActions[i].type)
1370
- {
1371
- case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE:
1372
- fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].msiPackage.action);
1373
- break;
1368
+ break;
1369
1375
- case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET:
1376
- fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].mspTarget.action);
1377
- break;
1370
+ case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
1371
+ fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].exePackage.action);
1372
+ break;
1373
1379
- case BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE:
1380
- fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].msuPackage.action);
1381
- break;
1382
- }
1374
+ case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE:
1375
+ fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].msiPackage.action);
1376
+ break;
1377
+
1378
+ case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET:
1379
+ fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].mspTarget.action);
1380
+ break;
1381
+
1382
+ case BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE:
1383
+ fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].msuPackage.action);
1384
+ break;
1385
}
1386
}
1387
@@ -1422,7 +1424,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1424
if (BOOTSTRAPPER_RELATION_ADDON == pRelatedBundle->relationType || BOOTSTRAPPER_RELATION_PATCH == pRelatedBundle->relationType)
1425
{
1426
// Addon and patch bundles will be passed a list of dependencies to ignore for planning.
1425
- hr = StrAllocString(&pRelatedBundle->package.Exe.sczIgnoreDependencies, sczIgnoreDependencies, 0);
1427
+ hr = StrAllocString(&pRelatedBundle->package.Bundle.sczIgnoreDependencies, sczIgnoreDependencies, 0);
1428
ExitOnFailure(hr, "Failed to copy the list of dependencies to ignore.");
1429
1430
// Uninstall addons and patches early in the chain, before other packages are uninstalled.
@@ -1434,8 +1436,8 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1436
1437
if (BOOTSTRAPPER_REQUEST_STATE_NONE != pRelatedBundle->package.requested)
1438
{
1437
- hr = ExeEnginePlanCalculatePackage(&pRelatedBundle->package);
1438
- ExitOnFailure(hr, "Failed to calcuate plan for related bundle: %ls", pRelatedBundle->package.sczId);
1439
+ hr = BundlePackageEnginePlanCalculatePackage(&pRelatedBundle->package);
1440
+ ExitOnFailure(hr, "Failed to calculate plan for related bundle: %ls", pRelatedBundle->package.sczId);
1441
1442
// Calculate package states based on reference count for addon and patch related bundles.
1443
if (BOOTSTRAPPER_RELATION_ADDON == pRelatedBundle->relationType || BOOTSTRAPPER_RELATION_PATCH == pRelatedBundle->relationType)
@@ -1450,7 +1452,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1452
}
1453
}
1454
1453
- hr = ExeEnginePlanAddPackage(pdwInsertIndex, &pRelatedBundle->package, pPlan, pLog, pVariables);
1455
+ hr = BundlePackageEnginePlanAddRelatedBundle(pdwInsertIndex, pRelatedBundle, pPlan, pLog, pVariables);
1456
ExitOnFailure(hr, "Failed to add to plan related bundle: %ls", pRelatedBundle->package.sczId);
1457
1458
// Calculate package states based on reference count for addon and patch related bundles.
@@ -2603,8 +2605,12 @@ static void ExecuteActionLog(
2605
LogStringLine(PlanDumpLevel, "%ls action[%u]: PACKAGE_DEPENDENCY package id: %ls, bundle provider key: %ls, action: %hs", wzBase, iAction, pAction->packageDependency.pPackage->sczId, pAction->packageDependency.sczBundleProviderKey, LoggingDependencyActionToString(pAction->packageDependency.action));
2606
break;
2607
2608
+ case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE:
2609
+ LogStringLine(PlanDumpLevel, "%ls action[%u]: RELATED_BUNDLE package id: %ls, action: %hs, ignore dependencies: %ls", wzBase, iAction, pAction->relatedBundle.pRelatedBundle->package.sczId, LoggingActionStateToString(pAction->relatedBundle.action), pAction->relatedBundle.sczIgnoreDependencies);
2610
+ break;
2611
+
2612
case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
2607
- LogStringLine(PlanDumpLevel, "%ls action[%u]: EXE_PACKAGE package id: %ls, action: %hs, ignore dependencies: %ls", wzBase, iAction, pAction->exePackage.pPackage->sczId, LoggingActionStateToString(pAction->exePackage.action), pAction->exePackage.sczIgnoreDependencies);
2613
+ LogStringLine(PlanDumpLevel, "%ls action[%u]: EXE_PACKAGE package id: %ls, action: %hs", wzBase, iAction, pAction->exePackage.pPackage->sczId, LoggingActionStateToString(pAction->exePackage.action));
2614
break;
2615
2616
case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE:
src/burn/engine/plan.h
+10
-12
@@ -50,6 +50,7 @@ enum BURN_EXECUTE_ACTION_TYPE
50
BURN_EXECUTE_ACTION_TYPE_CHECKPOINT,
51
BURN_EXECUTE_ACTION_TYPE_WAIT_CACHE_PACKAGE,
52
BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE,
53
+ BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE,
54
BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE,
55
BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE,
56
BURN_EXECUTE_ACTION_TYPE_MSP_TARGET,
@@ -160,12 +161,16 @@ typedef struct _BURN_EXECUTE_ACTION
161
} uncachePackage;
162
struct
163
{
163
- BURN_PACKAGE* pPackage;
164
- BOOL fFireAndForget;
164
+ BURN_RELATED_BUNDLE* pRelatedBundle;
165
BOOTSTRAPPER_ACTION_STATE action;
166
LPWSTR sczIgnoreDependencies;
167
LPWSTR sczAncestors;
168
LPWSTR sczEngineWorkingDirectory;
169
+ } relatedBundle;
170
+ struct
171
+ {
172
+ BURN_PACKAGE* pPackage;
173
+ BOOTSTRAPPER_ACTION_STATE action;
174
} exePackage;
175
struct
176
{
@@ -339,9 +344,7 @@ HRESULT PlanPackages(
344
__in BURN_PACKAGES* pPackages,
345
__in BURN_PLAN* pPlan,
346
__in BURN_LOGGING* pLog,
342
- __in BURN_VARIABLES* pVariables,
343
- __in BOOTSTRAPPER_DISPLAY display,
344
- __in BOOTSTRAPPER_RELATION_TYPE relationType
347
+ __in BURN_VARIABLES* pVariables
348
);
349
HRESULT PlanRegistration(
350
__in BURN_PLAN* pPlan,
@@ -356,18 +359,14 @@ HRESULT PlanPassThroughBundle(
359
__in BURN_PACKAGE* pPackage,
360
__in BURN_PLAN* pPlan,
361
__in BURN_LOGGING* pLog,
359
- __in BURN_VARIABLES* pVariables,
360
- __in BOOTSTRAPPER_DISPLAY display,
361
- __in BOOTSTRAPPER_RELATION_TYPE relationType
362
+ __in BURN_VARIABLES* pVariables
363
);
364
HRESULT PlanUpdateBundle(
365
__in BURN_USER_EXPERIENCE* pUX,
366
__in BURN_PACKAGE* pPackage,
367
__in BURN_PLAN* pPlan,
368
__in BURN_LOGGING* pLog,
368
- __in BURN_VARIABLES* pVariables,
369
- __in BOOTSTRAPPER_DISPLAY display,
370
- __in BOOTSTRAPPER_RELATION_TYPE relationType
369
+ __in BURN_VARIABLES* pVariables
370
);
371
HRESULT PlanLayoutContainer(
372
__in BURN_PLAN* pPlan,
@@ -379,7 +378,6 @@ HRESULT PlanLayoutPackage(
378
);
379
HRESULT PlanExecutePackage(
380
__in BOOL fPerMachine,
382
- __in BOOTSTRAPPER_DISPLAY display,
381
__in BURN_USER_EXPERIENCE* pUserExperience,
382
__in BURN_PLAN* pPlan,
383
__in BURN_PACKAGE* pPackage,
src/burn/engine/precomp.h
+1
@@ -86,6 +86,7 @@
86
#include "dependency.h"
87
#include "core.h"
88
#include "apply.h"
89
+#include "bundlepackageengine.h"
90
#include "exeengine.h"
91
#include "msiengine.h"
92
#include "mspengine.h"
src/burn/engine/pseudobundle.cpp
+23
-130
@@ -3,36 +3,24 @@
3
#include "precomp.h"
4
5
6
-extern "C" HRESULT PseudoBundleInitialize(
6
+extern "C" HRESULT PseudoBundleInitializeRelated(
7
__in BURN_PACKAGE* pPackage,
8
__in BOOL fSupportsBurnProtocol,
9
__in BOOL fPerMachine,
10
__in_z LPCWSTR wzId,
11
+#ifdef DEBUG
12
__in BOOTSTRAPPER_RELATION_TYPE relationType,
12
- __in BOOTSTRAPPER_PACKAGE_STATE state,
13
+#endif
14
__in BOOL fCached,
15
__in_z LPCWSTR wzFilePath,
15
- __in_z LPCWSTR wzLocalSource,
16
- __in_z_opt LPCWSTR wzDownloadSource,
16
__in DWORD64 qwSize,
18
- __in BOOL fVital,
19
- __in_z_opt LPCWSTR wzInstallArguments,
20
- __in_z_opt LPCWSTR wzRepairArguments,
21
- __in_z_opt LPCWSTR wzUninstallArguments,
22
- __in_opt BURN_DEPENDENCY_PROVIDER* pDependencyProvider,
23
- __in_opt const BYTE* pbHash,
24
- __in const DWORD cbHash
17
+ __in_opt BURN_DEPENDENCY_PROVIDER* pDependencyProvider
18
)
19
{
20
HRESULT hr = S_OK;
28
- LPWSTR sczRelationTypeCommandLineSwitch = NULL;
21
BURN_PAYLOAD* pPayload = NULL;
22
31
- LPCWSTR wzRelationTypeCommandLine = CoreRelationTypeToCommandLineString(relationType);
32
- if (wzRelationTypeCommandLine)
33
- {
34
- hr = StrAllocFormatted(&sczRelationTypeCommandLineSwitch, L" -%ls", wzRelationTypeCommandLine);
35
- }
23
+ AssertSz(BOOTSTRAPPER_RELATION_UPDATE != relationType, "Update pseudo bundles must use PseudoBundleInitializeUpdateBundle instead.");
24
25
// Initialize the single payload, and fill out all the necessary fields
26
pPackage->payloads.rgItems = (BURN_PAYLOAD_GROUP_ITEM*)MemAlloc(sizeof(BURN_PAYLOAD_GROUP_ITEM), TRUE);
@@ -51,41 +39,21 @@ extern "C" HRESULT PseudoBundleInitialize(
39
hr = StrAllocString(&pPayload->sczFilePath, wzFilePath, 0);
40
ExitOnFailure(hr, "Failed to copy filename for pseudo bundle.");
41
54
- hr = StrAllocString(&pPayload->sczSourcePath, wzLocalSource, 0);
42
+ hr = StrAllocString(&pPayload->sczSourcePath, wzFilePath, 0);
43
ExitOnFailure(hr, "Failed to copy local source path for pseudo bundle.");
44
57
- if (wzDownloadSource && *wzDownloadSource)
58
- {
59
- hr = StrAllocString(&pPayload->downloadSource.sczUrl, wzDownloadSource, 0);
60
- ExitOnFailure(hr, "Failed to copy download source for pseudo bundle.");
61
- }
62
-
63
- if (pbHash)
64
- {
65
- pPayload->pbHash = static_cast<BYTE*>(MemAlloc(cbHash, FALSE));
66
- ExitOnNull(pPayload->pbHash, hr, E_OUTOFMEMORY, "Failed to allocate memory for pseudo bundle payload hash.");
67
-
68
- pPayload->cbHash = cbHash;
69
- memcpy_s(pPayload->pbHash, pPayload->cbHash, pbHash, cbHash);
70
- }
71
-
72
- if (BOOTSTRAPPER_RELATION_UPDATE == relationType)
73
- {
74
- pPayload->verification = BURN_PAYLOAD_VERIFICATION_UPDATE_BUNDLE;
75
- }
76
-
77
- pPackage->Exe.fPseudoBundle = TRUE;
78
-
79
- pPackage->type = BURN_PACKAGE_TYPE_EXE;
45
+ pPackage->type = BURN_PACKAGE_TYPE_BUNDLE;
46
pPackage->fPerMachine = fPerMachine;
81
- pPackage->currentState = state;
47
+ pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_PRESENT;
48
pPackage->fCached = fCached;
49
pPackage->qwInstallSize = qwSize;
50
pPackage->qwSize = qwSize;
85
- pPackage->fVital = fVital;
51
+ pPackage->fVital = FALSE;
52
87
- pPackage->Exe.protocol = fSupportsBurnProtocol ? BURN_EXE_PROTOCOL_TYPE_BURN : BURN_EXE_PROTOCOL_TYPE_NONE;
88
- pPackage->Exe.fSupportsAncestors = TRUE;
53
+ pPackage->fUninstallable = TRUE;
54
+ pPackage->Bundle.fPseudoBundle = TRUE;
55
+ pPackage->Bundle.fRepairable = TRUE;
56
+ pPackage->Bundle.fSupportsBurnProtocol = fSupportsBurnProtocol;
57
58
hr = StrAllocString(&pPackage->sczId, wzId, 0);
59
ExitOnFailure(hr, "Failed to copy key for pseudo bundle.");
@@ -93,47 +61,6 @@ extern "C" HRESULT PseudoBundleInitialize(
61
hr = StrAllocString(&pPackage->sczCacheId, wzId, 0);
62
ExitOnFailure(hr, "Failed to copy cache id for pseudo bundle.");
63
96
- // If we are a self updating bundle, we don't have to have Install arguments.
97
- if (wzInstallArguments)
98
- {
99
- hr = StrAllocString(&pPackage->Exe.sczInstallArguments, wzInstallArguments, 0);
100
- ExitOnFailure(hr, "Failed to copy install arguments for related bundle package");
101
- }
102
-
103
- if (sczRelationTypeCommandLineSwitch)
104
- {
105
- hr = StrAllocConcat(&pPackage->Exe.sczInstallArguments, sczRelationTypeCommandLineSwitch, 0);
106
- ExitOnFailure(hr, "Failed to append relation type to install arguments for related bundle package");
107
- }
108
-
109
- if (wzRepairArguments)
110
- {
111
- hr = StrAllocString(&pPackage->Exe.sczRepairArguments, wzRepairArguments, 0);
112
- ExitOnFailure(hr, "Failed to copy repair arguments for related bundle package");
113
-
114
- if (sczRelationTypeCommandLineSwitch)
115
- {
116
- hr = StrAllocConcat(&pPackage->Exe.sczRepairArguments, sczRelationTypeCommandLineSwitch, 0);
117
- ExitOnFailure(hr, "Failed to append relation type to repair arguments for related bundle package");
118
- }
119
-
120
- pPackage->Exe.fRepairable = TRUE;
121
- }
122
-
123
- if (wzUninstallArguments)
124
- {
125
- hr = StrAllocString(&pPackage->Exe.sczUninstallArguments, wzUninstallArguments, 0);
126
- ExitOnFailure(hr, "Failed to copy uninstall arguments for related bundle package");
127
-
128
- if (sczRelationTypeCommandLineSwitch)
129
- {
130
- hr = StrAllocConcat(&pPackage->Exe.sczUninstallArguments, sczRelationTypeCommandLineSwitch, 0);
131
- ExitOnFailure(hr, "Failed to append relation type to uninstall arguments for related bundle package");
132
- }
133
-
134
- pPackage->fUninstallable = TRUE;
135
- }
136
-
64
if (pDependencyProvider)
65
{
66
pPackage->rgDependencyProviders = (BURN_DEPENDENCY_PROVIDER*)MemAlloc(sizeof(BURN_DEPENDENCY_PROVIDER), TRUE);
@@ -153,8 +80,6 @@ extern "C" HRESULT PseudoBundleInitialize(
80
}
81
82
LExit:
156
- ReleaseStr(sczRelationTypeCommandLineSwitch);
157
-
83
return hr;
84
}
85
@@ -165,7 +90,7 @@ extern "C" HRESULT PseudoBundleInitializePassthrough(
90
__in BURN_PACKAGE* pPackage
91
)
92
{
168
- Assert(BURN_PACKAGE_TYPE_EXE == pPackage->type);
93
+ Assert(BURN_PACKAGE_TYPE_BUNDLE == pPackage->type);
94
95
HRESULT hr = S_OK;
96
LPWSTR sczArguments = NULL;
@@ -180,59 +105,29 @@ extern "C" HRESULT PseudoBundleInitializePassthrough(
105
pPassthroughPackage->payloads.rgItems[iPayload].pPayload = pPackage->payloads.rgItems[iPayload].pPayload;
106
}
107
183
- pPassthroughPackage->Exe.fPseudoBundle = TRUE;
184
-
108
pPassthroughPackage->fPerMachine = FALSE; // passthrough bundles are always launched per-user.
186
- pPassthroughPackage->type = pPackage->type;
109
+ pPassthroughPackage->type = BURN_PACKAGE_TYPE_EXE;
110
pPassthroughPackage->currentState = pPackage->currentState;
111
pPassthroughPackage->fCached = pPackage->fCached;
112
pPassthroughPackage->qwInstallSize = pPackage->qwInstallSize;
113
pPassthroughPackage->qwSize = pPackage->qwSize;
114
pPassthroughPackage->fVital = pPackage->fVital;
115
116
+ pPassthroughPackage->Exe.fPseudoBundle = TRUE;
117
+ pPassthroughPackage->Exe.protocol = pPackage->Bundle.fSupportsBurnProtocol ? BURN_EXE_PROTOCOL_TYPE_BURN : BURN_EXE_PROTOCOL_TYPE_NONE;
118
+
119
hr = StrAllocString(&pPassthroughPackage->sczId, pPackage->sczId, 0);
120
ExitOnFailure(hr, "Failed to copy key for passthrough pseudo bundle.");
121
122
hr = StrAllocString(&pPassthroughPackage->sczCacheId, pPackage->sczCacheId, 0);
123
ExitOnFailure(hr, "Failed to copy cache id for passthrough pseudo bundle.");
124
199
- pPassthroughPackage->Exe.protocol = pPackage->Exe.protocol;
200
-
125
hr = CoreCreatePassthroughBundleCommandLine(&sczArguments, pInternalCommand, pCommand);
126
ExitOnFailure(hr, "Failed to create command-line arguments.");
127
128
hr = StrAllocString(&pPassthroughPackage->Exe.sczInstallArguments, sczArguments, 0);
129
ExitOnFailure(hr, "Failed to copy install arguments for passthrough bundle package");
130
207
- hr = StrAllocString(&pPassthroughPackage->Exe.sczRepairArguments, sczArguments, 0);
208
- ExitOnFailure(hr, "Failed to copy related arguments for passthrough bundle package");
209
-
210
- pPassthroughPackage->Exe.fRepairable = TRUE;
211
-
212
- hr = StrAllocString(&pPassthroughPackage->Exe.sczUninstallArguments, sczArguments, 0);
213
- ExitOnFailure(hr, "Failed to copy uninstall arguments for passthrough bundle package");
214
-
215
- pPassthroughPackage->fUninstallable = TRUE;
216
-
217
- // TODO: consider bringing this back in the near future.
218
- //if (pDependencyProvider)
219
- //{
220
- // pPassthroughPackage->rgDependencyProviders = (BURN_DEPENDENCY_PROVIDER*)MemAlloc(sizeof(BURN_DEPENDENCY_PROVIDER), TRUE);
221
- // ExitOnNull(pPassthroughPackage->rgDependencyProviders, hr, E_OUTOFMEMORY, "Failed to allocate memory for dependency providers.");
222
- // pPassthroughPackage->cDependencyProviders = 1;
223
-
224
- // pPassthroughPackage->rgDependencyProviders[0].fImported = pDependencyProvider->fImported;
225
-
226
- // hr = StrAllocString(&pPassthroughPackage->rgDependencyProviders[0].sczKey, pDependencyProvider->sczKey, 0);
227
- // ExitOnFailure(hr, "Failed to copy key for pseudo bundle.");
228
-
229
- // hr = StrAllocString(&pPassthroughPackage->rgDependencyProviders[0].sczVersion, pDependencyProvider->sczVersion, 0);
230
- // ExitOnFailure(hr, "Failed to copy version for pseudo bundle.");
231
-
232
- // hr = StrAllocString(&pPassthroughPackage->rgDependencyProviders[0].sczDisplayName, pDependencyProvider->sczDisplayName, 0);
233
- // ExitOnFailure(hr, "Failed to copy display name for pseudo bundle.");
234
- //}
235
-
131
LExit:
132
ReleaseStr(sczArguments);
133
return hr;
@@ -290,14 +185,16 @@ extern "C" HRESULT PseudoBundleInitializeUpdateBundle(
185
memcpy_s(pPayload->pbHash, pPayload->cbHash, pbHash, cbHash);
186
}
187
293
- pPackage->Exe.fPseudoBundle = TRUE;
294
-
188
pPackage->type = BURN_PACKAGE_TYPE_EXE;
189
pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT;
190
pPackage->qwInstallSize = qwSize;
191
pPackage->qwSize = qwSize;
192
pPackage->fVital = TRUE;
193
194
+ // Trust the BA to only use UPDATE_REPLACE_EMBEDDED when appropriate.
195
+ pPackage->Exe.protocol = BURN_EXE_PROTOCOL_TYPE_BURN;
196
+ pPackage->Exe.fPseudoBundle = TRUE;
197
+
198
hr = StrAllocString(&pPackage->sczId, wzId, 0);
199
ExitOnFailure(hr, "Failed to copy id for update bundle.");
200
@@ -307,10 +204,6 @@ extern "C" HRESULT PseudoBundleInitializeUpdateBundle(
204
hr = StrAllocString(&pPackage->Exe.sczInstallArguments, wzInstallArguments, 0);
205
ExitOnFailure(hr, "Failed to copy install arguments for update bundle package");
206
310
- // Trust the BA to only use UPDATE_REPLACE_EMBEDDED when appropriate.
311
- pPackage->Exe.protocol = BURN_EXE_PROTOCOL_TYPE_BURN;
312
- pPackage->Exe.fSupportsAncestors = TRUE;
313
-
207
LExit:
208
return hr;
316
-}
\ No newline at end of file
209
+}
src/burn/engine/pseudobundle.h
+4
-11
@@ -6,25 +6,18 @@
6
extern "C" {
7
#endif
8
9
-HRESULT PseudoBundleInitialize(
9
+HRESULT PseudoBundleInitializeRelated(
10
__in BURN_PACKAGE* pPackage,
11
__in BOOL fSupportsBurnProtocol,
12
__in BOOL fPerMachine,
13
__in_z LPCWSTR wzId,
14
+#ifdef DEBUG
15
__in BOOTSTRAPPER_RELATION_TYPE relationType,
15
- __in BOOTSTRAPPER_PACKAGE_STATE state,
16
+#endif
17
__in BOOL fCached,
18
__in_z LPCWSTR wzFilePath,
18
- __in_z LPCWSTR wzLocalSource,
19
- __in_z_opt LPCWSTR wzDownloadSource,
19
__in DWORD64 qwSize,
21
- __in BOOL fVital,
22
- __in_z_opt LPCWSTR wzInstallArguments,
23
- __in_z_opt LPCWSTR wzRepairArguments,
24
- __in_z_opt LPCWSTR wzUninstallArguments,
25
- __in_opt BURN_DEPENDENCY_PROVIDER* pDependencyProvider,
26
- __in_opt const BYTE* pbHash,
27
- __in const DWORD cbHash
20
+ __in_opt BURN_DEPENDENCY_PROVIDER* pDependencyProvider
21
);
22
HRESULT PseudoBundleInitializePassthrough(
23
__in BURN_PACKAGE* pPassthroughPackage,
src/burn/engine/relatedbundle.cpp
+42
-5
@@ -98,6 +98,37 @@ extern "C" void RelatedBundlesUninitialize(
98
}
99
100
101
+extern "C" HRESULT RelatedBundleFindById(
102
+ __in BURN_RELATED_BUNDLES* pRelatedBundles,
103
+ __in_z LPCWSTR wzId,
104
+ __out BURN_RELATED_BUNDLE** ppRelatedBundle
105
+ )
106
+{
107
+ HRESULT hr = S_OK;
108
+ BURN_RELATED_BUNDLE* pRelatedBundle = NULL;
109
+ BURN_PACKAGE* pPackage = NULL;
110
+
111
+ *ppRelatedBundle = NULL;
112
+
113
+ for (DWORD i = 0; i < pRelatedBundles->cRelatedBundles; ++i)
114
+ {
115
+ pRelatedBundle = pRelatedBundles->rgRelatedBundles + i;
116
+ pPackage = &pRelatedBundle->package;
117
+
118
+ if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, 0, pPackage->sczId, -1, wzId, -1))
119
+ {
120
+ *ppRelatedBundle = pRelatedBundle;
121
+ ExitFunction1(hr = S_OK);
122
+ }
123
+ }
124
+
125
+ hr = E_NOTFOUND;
126
+
127
+LExit:
128
+ return hr;
129
+}
130
+
131
+
132
// internal helper functions
133
134
static HRESULT LoadIfRelatedBundle(
@@ -410,6 +441,7 @@ static HRESULT LoadRelatedBundleFromKey(
441
BOOL fCached = FALSE;
442
DWORD64 qwFileSize = 0;
443
BURN_DEPENDENCY_PROVIDER dependencyProvider = { };
444
+ BURN_DEPENDENCY_PROVIDER* pBundleDependencyProvider = NULL;
445
446
// Only support progress from engines that are compatible.
447
hr = RegReadNumber(hkBundleId, BURN_REGISTRATION_REGISTRY_ENGINE_PROTOCOL_VERSION, &dwEngineProtocolVersion);
@@ -458,6 +490,11 @@ static HRESULT LoadRelatedBundleFromKey(
490
if (E_FILENOTFOUND != hr)
491
{
492
ExitOnFailure(hr, "Failed to read provider key from registry for bundle: %ls", wzRelatedBundleId);
493
+ }
494
+
495
+ if (dependencyProvider.sczKey && *dependencyProvider.sczKey)
496
+ {
497
+ pBundleDependencyProvider = &dependencyProvider;
498
499
dependencyProvider.fImported = TRUE;
500
@@ -480,11 +517,11 @@ static HRESULT LoadRelatedBundleFromKey(
517
518
pRelatedBundle->relationType = relationType;
519
483
- hr = PseudoBundleInitialize(&pRelatedBundle->package, fSupportsBurnProtocol, fPerMachine, wzRelatedBundleId, pRelatedBundle->relationType,
484
- BOOTSTRAPPER_PACKAGE_STATE_PRESENT, fCached, sczCachePath, sczCachePath, NULL, qwFileSize, FALSE,
485
- L"-quiet", L"-repair -quiet", L"-uninstall -quiet",
486
- (dependencyProvider.sczKey && *dependencyProvider.sczKey) ? &dependencyProvider : NULL,
487
- NULL, 0);
520
+ hr = PseudoBundleInitializeRelated(&pRelatedBundle->package, fSupportsBurnProtocol, fPerMachine, wzRelatedBundleId,
521
+#ifdef DEBUG
522
+ pRelatedBundle->relationType,
523
+#endif
524
+ fCached, sczCachePath, qwFileSize, pBundleDependencyProvider);
525
ExitOnFailure(hr, "Failed to initialize related bundle to represent bundle: %ls", wzRelatedBundleId);
526
527
LExit:
src/burn/engine/relatedbundle.h
+5
@@ -14,6 +14,11 @@ HRESULT RelatedBundlesInitializeForScope(
14
void RelatedBundlesUninitialize(
15
__in BURN_RELATED_BUNDLES* pRelatedBundles
16
);
17
+HRESULT RelatedBundleFindById(
18
+ __in BURN_RELATED_BUNDLES* pRelatedBundles,
19
+ __in_z LPCWSTR wzId,
20
+ __out BURN_RELATED_BUNDLE** ppRelatedBundle
21
+ );
22
23
#if defined(__cplusplus)
24
}
src/burn/test/BurnUnitTest/PlanTest.cpp
+26
-7
@@ -117,7 +117,7 @@ namespace Bootstrapper
117
ValidateExecuteCommitMsiTransaction(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ");
118
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
119
ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
120
- ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
120
+ ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
121
Assert::Equal(dwIndex, pPlan->cExecuteActions);
122
123
fRollback = TRUE;
@@ -155,7 +155,7 @@ namespace Bootstrapper
155
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
156
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
157
ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
158
- ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
158
+ ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
159
Assert::Equal(dwIndex, pPlan->cRollbackActions);
160
161
Assert::Equal(4ul, pPlan->cExecutePackagesTotal);
@@ -496,7 +496,7 @@ namespace Bootstrapper
496
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
497
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
498
ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
499
- ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
499
+ ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
500
Assert::Equal(dwIndex, pPlan->cExecuteActions);
501
502
fRollback = TRUE;
@@ -514,7 +514,7 @@ namespace Bootstrapper
514
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
515
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
516
ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
517
- ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
517
+ ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
518
Assert::Equal(dwIndex, pPlan->cRollbackActions);
519
520
Assert::Equal(2ul, pPlan->cExecutePackagesTotal);
@@ -1154,7 +1154,11 @@ namespace Bootstrapper
1154
pRelatedBundle->fPlannable = TRUE;
1155
pRelatedBundle->relationType = BOOTSTRAPPER_RELATION_UPGRADE;
1156
1157
- hr = PseudoBundleInitialize(&pRelatedBundle->package, TRUE, TRUE, wzId, pRelatedBundle->relationType, BOOTSTRAPPER_PACKAGE_STATE_PRESENT, TRUE, wzFilePath, wzFilePath, NULL, 0, FALSE, L"-quiet", L"-repair -quiet", L"-uninstall -quiet", &dependencyProvider, NULL, 0);
1157
+ hr = PseudoBundleInitializeRelated(&pRelatedBundle->package, TRUE, TRUE, wzId,
1158
+#ifdef DEBUG
1159
+ pRelatedBundle->relationType,
1160
+#endif
1161
+ TRUE, wzFilePath, 0, &dependencyProvider);
1162
NativeAssert::Succeeded(hr, "Failed to initialize related bundle to represent bundle: %ls", wzId);
1163
1164
++pRelatedBundles->cRelatedBundles;
@@ -1310,7 +1314,7 @@ namespace Bootstrapper
1314
Assert::Equal<BOOL>(FALSE, pAction->fDeleted);
1315
}
1316
1313
- void ValidateExecuteExePackage(
1317
+ void ValidateExecuteRelatedBundle(
1318
__in BURN_PLAN* pPlan,
1319
__in BOOL fRollback,
1320
__in DWORD dwIndex,
@@ -1318,12 +1322,27 @@ namespace Bootstrapper
1322
__in BOOTSTRAPPER_ACTION_STATE action,
1323
__in LPCWSTR wzIgnoreDependencies
1324
)
1325
+ {
1326
+ BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
1327
+ Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE, pAction->type);
1328
+ NativeAssert::StringEqual(wzPackageId, pAction->relatedBundle.pRelatedBundle->package.sczId);
1329
+ Assert::Equal<DWORD>(action, pAction->relatedBundle.action);
1330
+ NativeAssert::StringEqual(wzIgnoreDependencies, pAction->relatedBundle.sczIgnoreDependencies);
1331
+ Assert::Equal<BOOL>(FALSE, pAction->fDeleted);
1332
+ }
1333
+
1334
+ void ValidateExecuteExePackage(
1335
+ __in BURN_PLAN* pPlan,
1336
+ __in BOOL fRollback,
1337
+ __in DWORD dwIndex,
1338
+ __in LPCWSTR wzPackageId,
1339
+ __in BOOTSTRAPPER_ACTION_STATE action
1340
+ )
1341
{
1342
BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex);
1343
Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE, pAction->type);
1344
NativeAssert::StringEqual(wzPackageId, pAction->exePackage.pPackage->sczId);
1345
Assert::Equal<DWORD>(action, pAction->exePackage.action);
1326
- NativeAssert::StringEqual(wzIgnoreDependencies, pAction->exePackage.sczIgnoreDependencies);
1346
Assert::Equal<BOOL>(FALSE, pAction->fDeleted);
1347
}
1348