aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-01-03 15:35:14 -0600
committerSean Hall <r.sean.hall@gmail.com>2022-01-04 19:19:43 -0600
commit1f5314302b3c8bc1977aed79df1d05c52608f382 (patch)
treef0fef3a4462352c914a4cc9413515d07f2244703
parentdb44f6cf3b1eb476e47384f2eccba5712808def5 (diff)
downloadwix-1f5314302b3c8bc1977aed79df1d05c52608f382.tar.gz
wix-1f5314302b3c8bc1977aed79df1d05c52608f382.tar.bz2
wix-1f5314302b3c8bc1977aed79df1d05c52608f382.zip
Don't assume Exe packages with Burn protocol are bundles.
Related to #3693
-rw-r--r--src/burn/engine/apply.cpp94
-rw-r--r--src/burn/engine/bundlepackageengine.cpp460
-rw-r--r--src/burn/engine/bundlepackageengine.h38
-rw-r--r--src/burn/engine/core.cpp14
-rw-r--r--src/burn/engine/elevation.cpp166
-rw-r--r--src/burn/engine/elevation.h9
-rw-r--r--src/burn/engine/engine.vcxproj2
-rw-r--r--src/burn/engine/exeengine.cpp177
-rw-r--r--src/burn/engine/exeengine.h20
-rw-r--r--src/burn/engine/package.cpp22
-rw-r--r--src/burn/engine/package.h22
-rw-r--r--src/burn/engine/plan.cpp128
-rw-r--r--src/burn/engine/plan.h22
-rw-r--r--src/burn/engine/precomp.h1
-rw-r--r--src/burn/engine/pseudobundle.cpp153
-rw-r--r--src/burn/engine/pseudobundle.h15
-rw-r--r--src/burn/engine/relatedbundle.cpp47
-rw-r--r--src/burn/engine/relatedbundle.h5
-rw-r--r--src/burn/test/BurnUnitTest/PlanTest.cpp33
19 files changed, 1018 insertions, 410 deletions
diff --git a/src/burn/engine/apply.cpp b/src/burn/engine/apply.cpp
index e2939f40..99884234 100644
--- a/src/burn/engine/apply.cpp
+++ b/src/burn/engine/apply.cpp
@@ -201,6 +201,15 @@ static HRESULT DoRollbackActions(
201 __in DWORD dwCheckpoint, 201 __in DWORD dwCheckpoint,
202 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 202 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
203 ); 203 );
204static 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 );
204static HRESULT ExecuteExePackage( 213static HRESULT ExecuteExePackage(
205 __in BURN_ENGINE_STATE* pEngineState, 214 __in BURN_ENGINE_STATE* pEngineState,
206 __in BURN_EXECUTE_ACTION* pExecuteAction, 215 __in BURN_EXECUTE_ACTION* pExecuteAction,
@@ -686,6 +695,9 @@ extern "C" HRESULT ApplyExecute(
686 LPCWSTR wzId = NULL; 695 LPCWSTR wzId = NULL;
687 switch (pExecuteAction->type) 696 switch (pExecuteAction->type)
688 { 697 {
698 case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE:
699 wzId = pExecuteAction->relatedBundle.pRelatedBundle->package.sczId;
700 break;
689 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: 701 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
690 wzId = pExecuteAction->exePackage.pPackage->sczId; 702 wzId = pExecuteAction->exePackage.pPackage->sczId;
691 break; 703 break;
@@ -2285,6 +2297,11 @@ static HRESULT DoExecuteAction(
2285 } 2297 }
2286 break; 2298 break;
2287 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
2288 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: 2305 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
2289 hr = ExecuteExePackage(pEngineState, pExecuteAction, pContext, FALSE, &fRetry, pfSuspend, &restart); 2306 hr = ExecuteExePackage(pEngineState, pExecuteAction, pContext, FALSE, &fRetry, pfSuspend, &restart);
2290 ExitOnFailure(hr, "Failed to execute EXE package."); 2307 ExitOnFailure(hr, "Failed to execute EXE package.");
@@ -2399,6 +2416,11 @@ static HRESULT DoRollbackActions(
2399 case BURN_EXECUTE_ACTION_TYPE_CHECKPOINT: 2416 case BURN_EXECUTE_ACTION_TYPE_CHECKPOINT:
2400 break; 2417 break;
2401 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
2402 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: 2424 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
2403 hr = ExecuteExePackage(pEngineState, pRollbackAction, pContext, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart); 2425 hr = ExecuteExePackage(pEngineState, pRollbackAction, pContext, TRUE, &fRetryIgnored, &fSuspendIgnored, &restart);
2404 IgnoreRollbackError(hr, "Failed to rollback EXE package."); 2426 IgnoreRollbackError(hr, "Failed to rollback EXE package.");
@@ -2462,6 +2484,78 @@ LExit:
2462 return hr; 2484 return hr;
2463} 2485}
2464 2486
2487static 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
2550LExit:
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
2465static HRESULT ExecuteExePackage( 2559static HRESULT ExecuteExePackage(
2466 __in BURN_ENGINE_STATE* pEngineState, 2560 __in BURN_ENGINE_STATE* pEngineState,
2467 __in BURN_EXECUTE_ACTION* pExecuteAction, 2561 __in BURN_EXECUTE_ACTION* pExecuteAction,
diff --git a/src/burn/engine/bundlepackageengine.cpp b/src/burn/engine/bundlepackageengine.cpp
new file mode 100644
index 00000000..10022b6a
--- /dev/null
+++ b/src/burn/engine/bundlepackageengine.cpp
@@ -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
9extern "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//
36extern "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
136LExit:
137 return hr;
138}
139
140//
141// PlanAdd - adds the calculated execute and rollback actions for the package.
142//
143extern "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
228LExit:
229 return hr;
230}
231
232extern "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
442LExit:
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}
diff --git a/src/burn/engine/bundlepackageengine.h b/src/burn/engine/bundlepackageengine.h
new file mode 100644
index 00000000..0d59907d
--- /dev/null
+++ b/src/burn/engine/bundlepackageengine.h
@@ -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)
6extern "C" {
7#endif
8
9
10// function declarations
11
12void BundlePackageEnginePackageUninitialize(
13 __in BURN_PACKAGE* pPackage
14 );
15HRESULT BundlePackageEnginePlanCalculatePackage(
16 __in BURN_PACKAGE* pPackage
17 );
18HRESULT 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 );
25HRESULT 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
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp
index 30c64b01..8a181e7c 100644
--- a/src/burn/engine/core.cpp
+++ b/src/burn/engine/core.cpp
@@ -228,11 +228,11 @@ extern "C" HRESULT CoreInitializeConstants(
228 { 228 {
229 BURN_PACKAGE* pPackage = pEngineState->packages.rgPackages + i; 229 BURN_PACKAGE* pPackage = pEngineState->packages.rgPackages + i;
230 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 { 232 {
233 // Pass along any ancestors and ourself to prevent infinite loops. 233 // Pass along any ancestors and ourself to prevent infinite loops.
234 pPackage->Exe.wzAncestors = pRegistration->sczBundlePackageAncestors; 234 pPackage->Bundle.wzAncestors = pRegistration->sczBundlePackageAncestors;
235 pPackage->Exe.wzEngineWorkingDirectory = pInternalCommand->sczEngineWorkingDirectory; 235 pPackage->Bundle.wzEngineWorkingDirectory = pInternalCommand->sczEngineWorkingDirectory;
236 } 236 }
237 } 237 }
238 238
@@ -518,7 +518,7 @@ extern "C" HRESULT CorePlan(
518 ExitOnFailure(hr, "Failed to plan the layout of the bundle."); 518 ExitOnFailure(hr, "Failed to plan the layout of the bundle.");
519 519
520 // Plan the packages' layout. 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."); 522 ExitOnFailure(hr, "Failed to plan packages.");
523 } 523 }
524 else if (BOOTSTRAPPER_ACTION_UPDATE_REPLACE == action || BOOTSTRAPPER_ACTION_UPDATE_REPLACE_EMBEDDED == action) 524 else if (BOOTSTRAPPER_ACTION_UPDATE_REPLACE == action || BOOTSTRAPPER_ACTION_UPDATE_REPLACE_EMBEDDED == action)
@@ -527,7 +527,7 @@ extern "C" HRESULT CorePlan(
527 527
528 pUpgradeBundlePackage = &pEngineState->update.package; 528 pUpgradeBundlePackage = &pEngineState->update.package;
529 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."); 531 ExitOnFailure(hr, "Failed to plan update.");
532 } 532 }
533 else 533 else
@@ -541,7 +541,7 @@ extern "C" HRESULT CorePlan(
541 541
542 pForwardCompatibleBundlePackage = &pEngineState->plan.forwardCompatibleBundle; 542 pForwardCompatibleBundlePackage = &pEngineState->plan.forwardCompatibleBundle;
543 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."); 545 ExitOnFailure(hr, "Failed to plan passthrough.");
546 } 546 }
547 else // doing an action that modifies the machine state. 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); 562 hr = PlanRelatedBundlesBegin(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, &pEngineState->plan);
563 ExitOnFailure(hr, "Failed to plan related bundles."); 563 ExitOnFailure(hr, "Failed to plan related bundles.");
564 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."); 566 ExitOnFailure(hr, "Failed to plan packages.");
567 567
568 // Schedule the update of related bundles last. 568 // Schedule the update of related bundles last.
diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp
index 6c4a775f..355b4a34 100644
--- a/src/burn/engine/elevation.cpp
+++ b/src/burn/engine/elevation.cpp
@@ -19,6 +19,7 @@ typedef enum _BURN_ELEVATION_MESSAGE_TYPE
19 BURN_ELEVATION_MESSAGE_TYPE_CACHE_VERIFY_PAYLOAD, 19 BURN_ELEVATION_MESSAGE_TYPE_CACHE_VERIFY_PAYLOAD,
20 BURN_ELEVATION_MESSAGE_TYPE_CACHE_CLEANUP, 20 BURN_ELEVATION_MESSAGE_TYPE_CACHE_CLEANUP,
21 BURN_ELEVATION_MESSAGE_TYPE_PROCESS_DEPENDENT_REGISTRATION, 21 BURN_ELEVATION_MESSAGE_TYPE_PROCESS_DEPENDENT_REGISTRATION,
22 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_RELATED_BUNDLE,
22 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE, 23 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE,
23 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE, 24 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE,
24 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSP_PACKAGE, 25 BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSP_PACKAGE,
@@ -230,11 +231,18 @@ static HRESULT OnProcessDependentRegistration(
230 __in BYTE* pbData, 231 __in BYTE* pbData,
231 __in SIZE_T cbData 232 __in SIZE_T cbData
232 ); 233 );
234static 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 );
233static HRESULT OnExecuteExePackage( 242static HRESULT OnExecuteExePackage(
234 __in HANDLE hPipe, 243 __in HANDLE hPipe,
235 __in BURN_CACHE* pCache, 244 __in BURN_CACHE* pCache,
236 __in BURN_PACKAGES* pPackages, 245 __in BURN_PACKAGES* pPackages,
237 __in BURN_RELATED_BUNDLES* pRelatedBundles,
238 __in BURN_VARIABLES* pVariables, 246 __in BURN_VARIABLES* pVariables,
239 __in BYTE* pbData, 247 __in BYTE* pbData,
240 __in SIZE_T cbData 248 __in SIZE_T cbData
@@ -818,10 +826,10 @@ LExit:
818} 826}
819 827
820/******************************************************************* 828/*******************************************************************
821 ElevationExecuteExePackage - 829 ElevationExecuteRelatedBundle -
822 830
823*******************************************************************/ 831*******************************************************************/
824extern "C" HRESULT ElevationExecuteExePackage( 832extern "C" HRESULT ElevationExecuteRelatedBundle(
825 __in HANDLE hPipe, 833 __in HANDLE hPipe,
826 __in BURN_EXECUTE_ACTION* pExecuteAction, 834 __in BURN_EXECUTE_ACTION* pExecuteAction,
827 __in BURN_VARIABLES* pVariables, 835 __in BURN_VARIABLES* pVariables,
@@ -838,22 +846,22 @@ extern "C" HRESULT ElevationExecuteExePackage(
838 DWORD dwResult = 0; 846 DWORD dwResult = 0;
839 847
840 // serialize message data 848 // serialize message data
841 hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.pPackage->sczId); 849 hr = BuffWriteString(&pbData, &cbData, pExecuteAction->relatedBundle.pRelatedBundle->package.sczId);
842 ExitOnFailure(hr, "Failed to write package id to message buffer."); 850 ExitOnFailure(hr, "Failed to write package id to message buffer.");
843 851
844 hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->exePackage.action); 852 hr = BuffWriteNumber(&pbData, &cbData, (DWORD)pExecuteAction->relatedBundle.action);
845 ExitOnFailure(hr, "Failed to write action to message buffer."); 853 ExitOnFailure(hr, "Failed to write action to message buffer.");
846 854
847 hr = BuffWriteNumber(&pbData, &cbData, fRollback); 855 hr = BuffWriteNumber(&pbData, &cbData, fRollback);
848 ExitOnFailure(hr, "Failed to write rollback."); 856 ExitOnFailure(hr, "Failed to write rollback.");
849 857
850 hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczIgnoreDependencies); 858 hr = BuffWriteString(&pbData, &cbData, pExecuteAction->relatedBundle.sczIgnoreDependencies);
851 ExitOnFailure(hr, "Failed to write the list of dependencies to ignore to the message buffer."); 859 ExitOnFailure(hr, "Failed to write the list of dependencies to ignore to the message buffer.");
852 860
853 hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczAncestors); 861 hr = BuffWriteString(&pbData, &cbData, pExecuteAction->relatedBundle.sczAncestors);
854 ExitOnFailure(hr, "Failed to write the list of ancestors to the message buffer."); 862 ExitOnFailure(hr, "Failed to write the list of ancestors to the message buffer.");
855 863
856 hr = BuffWriteString(&pbData, &cbData, pExecuteAction->exePackage.sczEngineWorkingDirectory); 864 hr = BuffWriteString(&pbData, &cbData, pExecuteAction->relatedBundle.sczEngineWorkingDirectory);
857 ExitOnFailure(hr, "Failed to write the custom working directory to the message buffer."); 865 ExitOnFailure(hr, "Failed to write the custom working directory to the message buffer.");
858 866
859 hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData); 867 hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData);
@@ -863,6 +871,54 @@ extern "C" HRESULT ElevationExecuteExePackage(
863 context.pfnGenericMessageHandler = pfnGenericMessageHandler; 871 context.pfnGenericMessageHandler = pfnGenericMessageHandler;
864 context.pvContext = pvContext; 872 context.pvContext = pvContext;
865 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
879LExit:
880 ReleaseBuffer(pbData);
881
882 return hr;
883}
884
885/*******************************************************************
886 ElevationExecuteExePackage -
887
888*******************************************************************/
889extern "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
866 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE, pbData, cbData, ProcessGenericExecuteMessages, &context, &dwResult); 922 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE, pbData, cbData, ProcessGenericExecuteMessages, &context, &dwResult);
867 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE message to per-machine process."); 923 ExitOnFailure(hr, "Failed to send BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE message to per-machine process.");
868 924
@@ -1911,8 +1967,12 @@ static HRESULT ProcessElevatedChildMessage(
1911 hrResult = OnProcessDependentRegistration(pContext->pRegistration, (BYTE*)pMsg->pvData, pMsg->cbData); 1967 hrResult = OnProcessDependentRegistration(pContext->pRegistration, (BYTE*)pMsg->pvData, pMsg->cbData);
1912 break; 1968 break;
1913 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
1914 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_EXE_PACKAGE: 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);
1916 break; 1976 break;
1917 1977
1918 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE: 1978 case BURN_ELEVATION_MESSAGE_TYPE_EXECUTE_MSI_PACKAGE:
@@ -2473,10 +2533,9 @@ LExit:
2473 return hr; 2533 return hr;
2474} 2534}
2475 2535
2476static HRESULT OnExecuteExePackage( 2536static HRESULT OnExecuteRelatedBundle(
2477 __in HANDLE hPipe, 2537 __in HANDLE hPipe,
2478 __in BURN_CACHE* pCache, 2538 __in BURN_CACHE* pCache,
2479 __in BURN_PACKAGES* pPackages,
2480 __in BURN_RELATED_BUNDLES* pRelatedBundles, 2539 __in BURN_RELATED_BUNDLES* pRelatedBundles,
2481 __in BURN_VARIABLES* pVariables, 2540 __in BURN_VARIABLES* pVariables,
2482 __in BYTE* pbData, 2541 __in BYTE* pbData,
@@ -2491,15 +2550,15 @@ static HRESULT OnExecuteExePackage(
2491 LPWSTR sczIgnoreDependencies = NULL; 2550 LPWSTR sczIgnoreDependencies = NULL;
2492 LPWSTR sczAncestors = NULL; 2551 LPWSTR sczAncestors = NULL;
2493 LPWSTR sczEngineWorkingDirectory = NULL; 2552 LPWSTR sczEngineWorkingDirectory = NULL;
2494 BOOTSTRAPPER_APPLY_RESTART exeRestart = BOOTSTRAPPER_APPLY_RESTART_NONE; 2553 BOOTSTRAPPER_APPLY_RESTART bundleRestart = BOOTSTRAPPER_APPLY_RESTART_NONE;
2495 2554
2496 executeAction.type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE; 2555 executeAction.type = BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE;
2497 2556
2498 // Deserialize message data. 2557 // Deserialize message data.
2499 hr = BuffReadString(pbData, cbData, &iData, &sczPackage); 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.");
2501 2560
2502 hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.exePackage.action); 2561 hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&executeAction.relatedBundle.action);
2503 ExitOnFailure(hr, "Failed to read action."); 2562 ExitOnFailure(hr, "Failed to read action.");
2504 2563
2505 hr = BuffReadNumber(pbData, cbData, &iData, &dwRollback); 2564 hr = BuffReadNumber(pbData, cbData, &iData, &dwRollback);
@@ -2517,36 +2576,32 @@ static HRESULT OnExecuteExePackage(
2517 hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData); 2576 hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData);
2518 ExitOnFailure(hr, "Failed to read variables."); 2577 ExitOnFailure(hr, "Failed to read variables.");
2519 2578
2520 hr = PackageFindById(pPackages, sczPackage, &executeAction.exePackage.pPackage); 2579 hr = RelatedBundleFindById(pRelatedBundles, sczPackage, &executeAction.relatedBundle.pRelatedBundle);
2521 if (E_NOTFOUND == hr) 2580 ExitOnFailure(hr, "Failed to find related bundle: %ls", sczPackage);
2522 {
2523 hr = PackageFindRelatedById(pRelatedBundles, sczPackage, &executeAction.exePackage.pPackage);
2524 }
2525 ExitOnFailure(hr, "Failed to find package: %ls", sczPackage);
2526 2581
2527 // Pass the list of dependencies to ignore, if any, to the related bundle. 2582 // Pass the list of dependencies to ignore, if any, to the related bundle.
2528 if (sczIgnoreDependencies && *sczIgnoreDependencies) 2583 if (sczIgnoreDependencies && *sczIgnoreDependencies)
2529 { 2584 {
2530 hr = StrAllocString(&executeAction.exePackage.sczIgnoreDependencies, sczIgnoreDependencies, 0); 2585 hr = StrAllocString(&executeAction.relatedBundle.sczIgnoreDependencies, sczIgnoreDependencies, 0);
2531 ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore."); 2586 ExitOnFailure(hr, "Failed to allocate the list of dependencies to ignore.");
2532 } 2587 }
2533 2588
2534 // Pass the list of ancestors, if any, to the related bundle. 2589 // Pass the list of ancestors, if any, to the related bundle.
2535 if (sczAncestors && *sczAncestors) 2590 if (sczAncestors && *sczAncestors)
2536 { 2591 {
2537 hr = StrAllocString(&executeAction.exePackage.sczAncestors, sczAncestors, 0); 2592 hr = StrAllocString(&executeAction.relatedBundle.sczAncestors, sczAncestors, 0);
2538 ExitOnFailure(hr, "Failed to allocate the list of ancestors."); 2593 ExitOnFailure(hr, "Failed to allocate the list of ancestors.");
2539 } 2594 }
2540 2595
2541 if (sczEngineWorkingDirectory && *sczEngineWorkingDirectory) 2596 if (sczEngineWorkingDirectory && *sczEngineWorkingDirectory)
2542 { 2597 {
2543 hr = StrAllocString(&executeAction.exePackage.sczEngineWorkingDirectory, sczEngineWorkingDirectory, 0); 2598 hr = StrAllocString(&executeAction.relatedBundle.sczEngineWorkingDirectory, sczEngineWorkingDirectory, 0);
2544 ExitOnFailure(hr, "Failed to allocate the custom working directory."); 2599 ExitOnFailure(hr, "Failed to allocate the custom working directory.");
2545 } 2600 }
2546 2601
2547 // Execute EXE package. 2602 // Execute related bundle.
2548 hr = ExeEngineExecutePackage(&executeAction, pCache, pVariables, static_cast<BOOL>(dwRollback), GenericExecuteMessageHandler, hPipe, &exeRestart); 2603 hr = BundlePackageEngineExecuteRelatedBundle(&executeAction, pCache, pVariables, static_cast<BOOL>(dwRollback), GenericExecuteMessageHandler, hPipe, &bundleRestart);
2549 ExitOnFailure(hr, "Failed to execute EXE package."); 2604 ExitOnFailure(hr, "Failed to execute related bundle.");
2550 2605
2551LExit: 2606LExit:
2552 ReleaseStr(sczEngineWorkingDirectory); 2607 ReleaseStr(sczEngineWorkingDirectory);
@@ -2557,6 +2612,63 @@ LExit:
2557 2612
2558 if (SUCCEEDED(hr)) 2613 if (SUCCEEDED(hr))
2559 { 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
2628static 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
2666LExit:
2667 ReleaseStr(sczPackage);
2668 PlanUninitializeExecuteAction(&executeAction);
2669
2670 if (SUCCEEDED(hr))
2671 {
2560 if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == exeRestart) 2672 if (BOOTSTRAPPER_APPLY_RESTART_REQUIRED == exeRestart)
2561 { 2673 {
2562 hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED); 2674 hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED);
diff --git a/src/burn/engine/elevation.h b/src/burn/engine/elevation.h
index ad1141bb..0e63c687 100644
--- a/src/burn/engine/elevation.h
+++ b/src/burn/engine/elevation.h
@@ -80,6 +80,15 @@ HRESULT ElevationProcessDependentRegistration(
80 __in HANDLE hPipe, 80 __in HANDLE hPipe,
81 __in const BURN_DEPENDENT_REGISTRATION_ACTION* pAction 81 __in const BURN_DEPENDENT_REGISTRATION_ACTION* pAction
82 ); 82 );
83HRESULT 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 );
83HRESULT ElevationExecuteExePackage( 92HRESULT ElevationExecuteExePackage(
84 __in HANDLE hPipe, 93 __in HANDLE hPipe,
85 __in BURN_EXECUTE_ACTION* pExecuteAction, 94 __in BURN_EXECUTE_ACTION* pExecuteAction,
diff --git a/src/burn/engine/engine.vcxproj b/src/burn/engine/engine.vcxproj
index 3d6ed181..5c4860f1 100644
--- a/src/burn/engine/engine.vcxproj
+++ b/src/burn/engine/engine.vcxproj
@@ -52,6 +52,7 @@
52 <ItemGroup> 52 <ItemGroup>
53 <ClCompile Include="apply.cpp" /> 53 <ClCompile Include="apply.cpp" />
54 <ClCompile Include="approvedexe.cpp" /> 54 <ClCompile Include="approvedexe.cpp" />
55 <ClCompile Include="bundlepackageengine.cpp" />
55 <ClCompile Include="burnextension.cpp" /> 56 <ClCompile Include="burnextension.cpp" />
56 <ClCompile Include="detect.cpp" /> 57 <ClCompile Include="detect.cpp" />
57 <ClCompile Include="embedded.cpp" /> 58 <ClCompile Include="embedded.cpp" />
@@ -101,6 +102,7 @@
101 <ClInclude Include="..\..\api\burn\WixToolset.BootstrapperCore.Native\inc\BootstrapperEngine.h" /> 102 <ClInclude Include="..\..\api\burn\WixToolset.BootstrapperCore.Native\inc\BootstrapperEngine.h" />
102 <ClInclude Include="..\..\api\burn\WixToolset.BootstrapperCore.Native\inc\BundleExtension.h" /> 103 <ClInclude Include="..\..\api\burn\WixToolset.BootstrapperCore.Native\inc\BundleExtension.h" />
103 <ClInclude Include="..\..\api\burn\WixToolset.BootstrapperCore.Native\inc\BundleExtensionEngine.h" /> 104 <ClInclude Include="..\..\api\burn\WixToolset.BootstrapperCore.Native\inc\BundleExtensionEngine.h" />
105 <ClInclude Include="bundlepackageengine.h" />
104 <ClInclude Include="burnextension.h" /> 106 <ClInclude Include="burnextension.h" />
105 <ClInclude Include="cabextract.h" /> 107 <ClInclude Include="cabextract.h" />
106 <ClInclude Include="cache.h" /> 108 <ClInclude Include="cache.h" />
diff --git a/src/burn/engine/exeengine.cpp b/src/burn/engine/exeengine.cpp
index b728f599..45349ed0 100644
--- a/src/burn/engine/exeengine.cpp
+++ b/src/burn/engine/exeengine.cpp
@@ -3,23 +3,6 @@
3#include "precomp.h" 3#include "precomp.h"
4 4
5 5
6// internal function declarations
7
8static HRESULT HandleExitCode(
9 __in BURN_PACKAGE* pPackage,
10 __in DWORD dwExitCode,
11 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
12 );
13static HRESULT ParseCommandLineArgumentsFromXml(
14 __in IXMLDOMNode* pixnExePackage,
15 __in BURN_PACKAGE* pPackage
16 );
17static HRESULT ParseExitCodesFromXml(
18 __in IXMLDOMNode* pixnExePackage,
19 __in BURN_PACKAGE* pPackage
20 );
21
22
23// function definitions 6// function definitions
24 7
25extern "C" HRESULT ExeEngineParsePackageFromXml( 8extern "C" HRESULT ExeEngineParsePackageFromXml(
@@ -82,10 +65,10 @@ extern "C" HRESULT ExeEngineParsePackageFromXml(
82 ExitOnFailure(hr, "Failed to get @Protocol."); 65 ExitOnFailure(hr, "Failed to get @Protocol.");
83 } 66 }
84 67
85 hr = ParseExitCodesFromXml(pixnExePackage, pPackage); 68 hr = ExeEngineParseExitCodesFromXml(pixnExePackage, &pPackage->Exe.rgExitCodes, &pPackage->Exe.cExitCodes);
86 ExitOnFailure(hr, "Failed to parse exit codes."); 69 ExitOnFailure(hr, "Failed to parse exit codes.");
87 70
88 hr = ParseCommandLineArgumentsFromXml(pixnExePackage, pPackage); 71 hr = ExeEngineParseCommandLineArgumentsFromXml(pixnExePackage, &pPackage->Exe.rgCommandLineArguments, &pPackage->Exe.cCommandLineArguments);
89 ExitOnFailure(hr, "Failed to parse command lines."); 72 ExitOnFailure(hr, "Failed to parse command lines.");
90 73
91LExit: 74LExit:
@@ -104,8 +87,6 @@ extern "C" void ExeEnginePackageUninitialize(
104 ReleaseStr(pPackage->Exe.sczInstallArguments); 87 ReleaseStr(pPackage->Exe.sczInstallArguments);
105 ReleaseStr(pPackage->Exe.sczRepairArguments); 88 ReleaseStr(pPackage->Exe.sczRepairArguments);
106 ReleaseStr(pPackage->Exe.sczUninstallArguments); 89 ReleaseStr(pPackage->Exe.sczUninstallArguments);
107 ReleaseStr(pPackage->Exe.sczIgnoreDependencies);
108 //ReleaseStr(pPackage->Exe.sczProgressSwitch);
109 ReleaseMem(pPackage->Exe.rgExitCodes); 90 ReleaseMem(pPackage->Exe.rgExitCodes);
110 91
111 // free command-line arguments 92 // free command-line arguments
@@ -113,11 +94,7 @@ extern "C" void ExeEnginePackageUninitialize(
113 { 94 {
114 for (DWORD i = 0; i < pPackage->Exe.cCommandLineArguments; ++i) 95 for (DWORD i = 0; i < pPackage->Exe.cCommandLineArguments; ++i)
115 { 96 {
116 BURN_EXE_COMMAND_LINE_ARGUMENT* pCommandLineArgument = &pPackage->Exe.rgCommandLineArguments[i]; 97 ExeEngineCommandLineArgumentUninitialize(pPackage->Exe.rgCommandLineArguments + i);
117 ReleaseStr(pCommandLineArgument->sczInstallArgument);
118 ReleaseStr(pCommandLineArgument->sczUninstallArgument);
119 ReleaseStr(pCommandLineArgument->sczRepairArgument);
120 ReleaseStr(pCommandLineArgument->sczCondition);
121 } 98 }
122 MemFree(pPackage->Exe.rgCommandLineArguments); 99 MemFree(pPackage->Exe.rgCommandLineArguments);
123 } 100 }
@@ -126,6 +103,16 @@ extern "C" void ExeEnginePackageUninitialize(
126 memset(&pPackage->Exe, 0, sizeof(pPackage->Exe)); 103 memset(&pPackage->Exe, 0, sizeof(pPackage->Exe));
127} 104}
128 105
106extern "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
129extern "C" HRESULT ExeEngineDetectPackage( 116extern "C" HRESULT ExeEngineDetectPackage(
130 __in BURN_PACKAGE* pPackage, 117 __in BURN_PACKAGE* pPackage,
131 __in BURN_VARIABLES* pVariables 118 __in BURN_VARIABLES* pVariables
@@ -264,7 +251,6 @@ LExit:
264// PlanAdd - adds the calculated execute and rollback actions for the package. 251// PlanAdd - adds the calculated execute and rollback actions for the package.
265// 252//
266extern "C" HRESULT ExeEnginePlanAddPackage( 253extern "C" HRESULT ExeEnginePlanAddPackage(
267 __in_opt DWORD *pdwInsertSequence,
268 __in BURN_PACKAGE* pPackage, 254 __in BURN_PACKAGE* pPackage,
269 __in BURN_PLAN* pPlan, 255 __in BURN_PLAN* pPlan,
270 __in BURN_LOGGING* pLog, 256 __in BURN_LOGGING* pLog,
@@ -274,46 +260,19 @@ extern "C" HRESULT ExeEnginePlanAddPackage(
274 HRESULT hr = S_OK; 260 HRESULT hr = S_OK;
275 BURN_EXECUTE_ACTION* pAction = NULL; 261 BURN_EXECUTE_ACTION* pAction = NULL;
276 262
277 hr = DependencyPlanPackage(pdwInsertSequence, pPackage, pPlan); 263 hr = DependencyPlanPackage(NULL, pPackage, pPlan);
278 ExitOnFailure(hr, "Failed to plan package dependency actions."); 264 ExitOnFailure(hr, "Failed to plan package dependency actions.");
279 265
280 // add execute action 266 // add execute action
281 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute) 267 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute)
282 { 268 {
283 if (NULL != pdwInsertSequence) 269 hr = PlanAppendExecuteAction(pPlan, &pAction);
284 { 270 ExitOnFailure(hr, "Failed to append execute action.");
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 }
293 271
294 pAction->type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE; 272 pAction->type = BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE;
295 pAction->exePackage.pPackage = pPackage; 273 pAction->exePackage.pPackage = pPackage;
296 pAction->exePackage.fFireAndForget = (BOOTSTRAPPER_ACTION_UPDATE_REPLACE == pPlan->action);
297 pAction->exePackage.action = pPackage->execute; 274 pAction->exePackage.action = pPackage->execute;
298 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
317 LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, NULL); // ignore errors. 276 LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, NULL); // ignore errors.
318 } 277 }
319 278
@@ -327,18 +286,6 @@ extern "C" HRESULT ExeEnginePlanAddPackage(
327 pAction->exePackage.pPackage = pPackage; 286 pAction->exePackage.pPackage = pPackage;
328 pAction->exePackage.action = pPackage->rollback; 287 pAction->exePackage.action = pPackage->rollback;
329 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
342 LoggingSetPackageVariable(pPackage, NULL, TRUE, pLog, pVariables, NULL); // ignore errors. 289 LoggingSetPackageVariable(pPackage, NULL, TRUE, pLog, pVariables, NULL); // ignore errors.
343 } 290 }
344 291
@@ -452,13 +399,13 @@ extern "C" HRESULT ExeEngineExecutePackage(
452 hr = VariableFormatString(pVariables, sczArguments, &sczArgumentsFormatted, NULL); 399 hr = VariableFormatString(pVariables, sczArguments, &sczArgumentsFormatted, NULL);
453 ExitOnFailure(hr, "Failed to format argument string."); 400 ExitOnFailure(hr, "Failed to format argument string.");
454 401
455 hr = StrAllocFormattedSecure(&sczCommand, L"\"%ls\" %s", sczExecutablePath, sczArgumentsFormatted); 402 hr = StrAllocFormattedSecure(&sczCommand, L"\"%ls\" %ls", sczExecutablePath, sczArgumentsFormatted);
456 ExitOnFailure(hr, "Failed to create executable command."); 403 ExitOnFailure(hr, "Failed to create executable command.");
457 404
458 hr = VariableFormatStringObfuscated(pVariables, sczArguments, &sczArgumentsObfuscated, NULL); 405 hr = VariableFormatStringObfuscated(pVariables, sczArguments, &sczArgumentsObfuscated, NULL);
459 ExitOnFailure(hr, "Failed to format obfuscated argument string."); 406 ExitOnFailure(hr, "Failed to format obfuscated argument string.");
460 407
461 hr = StrAllocFormatted(&sczCommandObfuscated, L"\"%ls\" %s", sczExecutablePath, sczArgumentsObfuscated); 408 hr = StrAllocFormatted(&sczCommandObfuscated, L"\"%ls\" %ls", sczExecutablePath, sczArgumentsObfuscated);
462 } 409 }
463 else 410 else
464 { 411 {
@@ -469,47 +416,15 @@ extern "C" HRESULT ExeEngineExecutePackage(
469 } 416 }
470 ExitOnFailure(hr, "Failed to create obfuscated executable command."); 417 ExitOnFailure(hr, "Failed to create obfuscated executable command.");
471 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
504 // Log before we add the secret pipe name and client token for embedded processes. 419 // Log before we add the secret pipe name and client token for embedded processes.
505 LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(pExecuteAction->exePackage.action), sczExecutablePath, sczCommandObfuscated); 420 LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(pExecuteAction->exePackage.action), sczExecutablePath, sczCommandObfuscated);
506 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)
508 { 423 {
509 hr = EmbeddedRunBundle(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode); 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);
511 } 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)
513 { 428 {
514 hr = NetFxRunChainer(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode); 429 hr = NetFxRunChainer(sczExecutablePath, sczCommand, pfnGenericMessageHandler, pvContext, &dwExitCode);
515 ExitOnFailure(hr, "Failed to run netfx chainer: %ls", sczExecutablePath); 430 ExitOnFailure(hr, "Failed to run netfx chainer: %ls", sczExecutablePath);
@@ -524,7 +439,7 @@ extern "C" HRESULT ExeEngineExecutePackage(
524 ExitWithLastError(hr, "Failed to CreateProcess on path: %ls", sczExecutablePath); 439 ExitWithLastError(hr, "Failed to CreateProcess on path: %ls", sczExecutablePath);
525 } 440 }
526 441
527 if (pExecuteAction->exePackage.fFireAndForget) 442 if (pPackage->Exe.fFireAndForget)
528 { 443 {
529 ::WaitForInputIdle(pi.hProcess, 5000); 444 ::WaitForInputIdle(pi.hProcess, 5000);
530 ExitFunction(); 445 ExitFunction();
@@ -547,7 +462,7 @@ extern "C" HRESULT ExeEngineExecutePackage(
547 } while (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr); 462 } while (HRESULT_FROM_WIN32(WAIT_TIMEOUT) == hr);
548 } 463 }
549 464
550 hr = HandleExitCode(pPackage, dwExitCode, pRestart); 465 hr = ExeEngineHandleExitCode(pPackage->Exe.rgExitCodes, pPackage->Exe.cExitCodes, dwExitCode, pRestart);
551 ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode); 466 ExitOnRootFailure(hr, "Process returned error: 0x%x", dwExitCode);
552 467
553LExit: 468LExit:
@@ -595,12 +510,10 @@ LExit:
595 return; 510 return;
596} 511}
597 512
598 513extern "C" HRESULT ExeEngineParseExitCodesFromXml(
599// internal helper functions 514 __in IXMLDOMNode* pixnPackage,
600 515 __inout BURN_EXE_EXIT_CODE** prgExitCodes,
601static HRESULT ParseExitCodesFromXml( 516 __inout DWORD* pcExitCodes
602 __in IXMLDOMNode* pixnExePackage,
603 __in BURN_PACKAGE* pPackage
604 ) 517 )
605{ 518{
606 HRESULT hr = S_OK; 519 HRESULT hr = S_OK;
@@ -610,7 +523,7 @@ static HRESULT ParseExitCodesFromXml(
610 LPWSTR scz = NULL; 523 LPWSTR scz = NULL;
611 524
612 // select exit code nodes 525 // select exit code nodes
613 hr = XmlSelectNodes(pixnExePackage, L"ExitCode", &pixnNodes); 526 hr = XmlSelectNodes(pixnPackage, L"ExitCode", &pixnNodes);
614 ExitOnFailure(hr, "Failed to select exit code nodes."); 527 ExitOnFailure(hr, "Failed to select exit code nodes.");
615 528
616 // get exit code node count 529 // get exit code node count
@@ -620,15 +533,15 @@ static HRESULT ParseExitCodesFromXml(
620 if (cNodes) 533 if (cNodes)
621 { 534 {
622 // allocate memory for exit codes 535 // allocate memory for exit codes
623 pPackage->Exe.rgExitCodes = (BURN_EXE_EXIT_CODE*) MemAlloc(sizeof(BURN_EXE_EXIT_CODE) * cNodes, TRUE); 536 *prgExitCodes = (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."); 537 ExitOnNull(*prgExitCodes, hr, E_OUTOFMEMORY, "Failed to allocate memory for exit code structs.");
625 538
626 pPackage->Exe.cExitCodes = cNodes; 539 *pcExitCodes = cNodes;
627 540
628 // parse package elements 541 // parse package elements
629 for (DWORD i = 0; i < cNodes; ++i) 542 for (DWORD i = 0; i < cNodes; ++i)
630 { 543 {
631 BURN_EXE_EXIT_CODE* pExitCode = &pPackage->Exe.rgExitCodes[i]; 544 BURN_EXE_EXIT_CODE* pExitCode = *prgExitCodes + i;
632 545
633 hr = XmlNextElement(pixnNodes, &pixnNode, NULL); 546 hr = XmlNextElement(pixnNodes, &pixnNode, NULL);
634 ExitOnFailure(hr, "Failed to get next node."); 547 ExitOnFailure(hr, "Failed to get next node.");
@@ -666,9 +579,10 @@ LExit:
666 return hr; 579 return hr;
667} 580}
668 581
669static HRESULT ParseCommandLineArgumentsFromXml( 582extern "C" HRESULT ExeEngineParseCommandLineArgumentsFromXml(
670 __in IXMLDOMNode* pixnExePackage, 583 __in IXMLDOMNode* pixnPackage,
671 __in BURN_PACKAGE* pPackage 584 __inout BURN_EXE_COMMAND_LINE_ARGUMENT** prgCommandLineArguments,
585 __inout DWORD* pcCommandLineArguments
672 ) 586 )
673{ 587{
674 HRESULT hr = S_OK; 588 HRESULT hr = S_OK;
@@ -678,7 +592,7 @@ static HRESULT ParseCommandLineArgumentsFromXml(
678 LPWSTR scz = NULL; 592 LPWSTR scz = NULL;
679 593
680 // Select command-line argument nodes. 594 // Select command-line argument nodes.
681 hr = XmlSelectNodes(pixnExePackage, L"CommandLine", &pixnNodes); 595 hr = XmlSelectNodes(pixnPackage, L"CommandLine", &pixnNodes);
682 ExitOnFailure(hr, "Failed to select command-line argument nodes."); 596 ExitOnFailure(hr, "Failed to select command-line argument nodes.");
683 597
684 // Get command-line argument node count. 598 // Get command-line argument node count.
@@ -687,15 +601,15 @@ static HRESULT ParseCommandLineArgumentsFromXml(
687 601
688 if (cNodes) 602 if (cNodes)
689 { 603 {
690 pPackage->Exe.rgCommandLineArguments = (BURN_EXE_COMMAND_LINE_ARGUMENT*) MemAlloc(sizeof(BURN_EXE_COMMAND_LINE_ARGUMENT) * cNodes, TRUE); 604 *prgCommandLineArguments = (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."); 605 ExitOnNull(*prgCommandLineArguments, hr, E_OUTOFMEMORY, "Failed to allocate memory for command-line argument structs.");
692 606
693 pPackage->Exe.cCommandLineArguments = cNodes; 607 *pcCommandLineArguments = cNodes;
694 608
695 // Parse command-line argument elements. 609 // Parse command-line argument elements.
696 for (DWORD i = 0; i < cNodes; ++i) 610 for (DWORD i = 0; i < cNodes; ++i)
697 { 611 {
698 BURN_EXE_COMMAND_LINE_ARGUMENT* pCommandLineArgument = &pPackage->Exe.rgCommandLineArguments[i]; 612 BURN_EXE_COMMAND_LINE_ARGUMENT* pCommandLineArgument = *prgCommandLineArguments + i;
699 613
700 hr = XmlNextElement(pixnNodes, &pixnNode, NULL); 614 hr = XmlNextElement(pixnNodes, &pixnNode, NULL);
701 ExitOnFailure(hr, "Failed to get next command-line argument node."); 615 ExitOnFailure(hr, "Failed to get next command-line argument node.");
@@ -731,8 +645,9 @@ LExit:
731 return hr; 645 return hr;
732} 646}
733 647
734static HRESULT HandleExitCode( 648extern "C" HRESULT ExeEngineHandleExitCode(
735 __in BURN_PACKAGE* pPackage, 649 __in BURN_EXE_EXIT_CODE* rgCustomExitCodes,
650 __in DWORD cCustomExitCodes,
736 __in DWORD dwExitCode, 651 __in DWORD dwExitCode,
737 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 652 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
738 ) 653 )
@@ -740,9 +655,9 @@ static HRESULT HandleExitCode(
740 HRESULT hr = S_OK; 655 HRESULT hr = S_OK;
741 BURN_EXE_EXIT_CODE_TYPE typeCode = BURN_EXE_EXIT_CODE_TYPE_NONE; 656 BURN_EXE_EXIT_CODE_TYPE typeCode = BURN_EXE_EXIT_CODE_TYPE_NONE;
742 657
743 for (DWORD i = 0; i < pPackage->Exe.cExitCodes; ++i) 658 for (DWORD i = 0; i < cCustomExitCodes; ++i)
744 { 659 {
745 BURN_EXE_EXIT_CODE* pExitCode = &pPackage->Exe.rgExitCodes[i]; 660 BURN_EXE_EXIT_CODE* pExitCode = rgCustomExitCodes + i;
746 661
747 // If this is a wildcard, use the last one we come across. 662 // If this is a wildcard, use the last one we come across.
748 if (pExitCode->fWildcard) 663 if (pExitCode->fWildcard)
diff --git a/src/burn/engine/exeengine.h b/src/burn/engine/exeengine.h
index 877968cd..bd5d7ea9 100644
--- a/src/burn/engine/exeengine.h
+++ b/src/burn/engine/exeengine.h
@@ -16,6 +16,9 @@ HRESULT ExeEngineParsePackageFromXml(
16void ExeEnginePackageUninitialize( 16void ExeEnginePackageUninitialize(
17 __in BURN_PACKAGE* pPackage 17 __in BURN_PACKAGE* pPackage
18 ); 18 );
19void ExeEngineCommandLineArgumentUninitialize(
20 __in BURN_EXE_COMMAND_LINE_ARGUMENT* pCommandLineArgument
21 );
19HRESULT ExeEngineDetectPackage( 22HRESULT ExeEngineDetectPackage(
20 __in BURN_PACKAGE* pPackage, 23 __in BURN_PACKAGE* pPackage,
21 __in BURN_VARIABLES* pVariables 24 __in BURN_VARIABLES* pVariables
@@ -24,7 +27,6 @@ HRESULT ExeEnginePlanCalculatePackage(
24 __in BURN_PACKAGE* pPackage 27 __in BURN_PACKAGE* pPackage
25 ); 28 );
26HRESULT ExeEnginePlanAddPackage( 29HRESULT ExeEnginePlanAddPackage(
27 __in_opt DWORD *pdwInsertSequence,
28 __in BURN_PACKAGE* pPackage, 30 __in BURN_PACKAGE* pPackage,
29 __in BURN_PLAN* pPlan, 31 __in BURN_PLAN* pPlan,
30 __in BURN_LOGGING* pLog, 32 __in BURN_LOGGING* pLog,
@@ -43,6 +45,22 @@ void ExeEngineUpdateInstallRegistrationState(
43 __in BURN_EXECUTE_ACTION* pAction, 45 __in BURN_EXECUTE_ACTION* pAction,
44 __in HRESULT hrExecute 46 __in HRESULT hrExecute
45 ); 47 );
48HRESULT ExeEngineParseExitCodesFromXml(
49 __in IXMLDOMNode* pixnPackage,
50 __inout BURN_EXE_EXIT_CODE** prgExitCodes,
51 __inout DWORD* pcExitCodes
52 );
53HRESULT ExeEngineParseCommandLineArgumentsFromXml(
54 __in IXMLDOMNode* pixnPackage,
55 __inout BURN_EXE_COMMAND_LINE_ARGUMENT** prgCommandLineArguments,
56 __inout DWORD* pcCommandLineArguments
57 );
58HRESULT ExeEngineHandleExitCode(
59 __in BURN_EXE_EXIT_CODE* rgCustomExitCodes,
60 __in DWORD cCustomExitCodes,
61 __in DWORD dwExitCode,
62 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
63 );
46 64
47 65
48#if defined(__cplusplus) 66#if defined(__cplusplus)
diff --git a/src/burn/engine/package.cpp b/src/burn/engine/package.cpp
index bea48cb5..d9087f79 100644
--- a/src/burn/engine/package.cpp
+++ b/src/burn/engine/package.cpp
@@ -350,6 +350,9 @@ extern "C" void PackageUninitialize(
350 350
351 switch (pPackage->type) 351 switch (pPackage->type)
352 { 352 {
353 case BURN_PACKAGE_TYPE_BUNDLE:
354 BundlePackageEnginePackageUninitialize(pPackage);
355 break;
353 case BURN_PACKAGE_TYPE_EXE: 356 case BURN_PACKAGE_TYPE_EXE:
354 ExeEnginePackageUninitialize(pPackage); // TODO: Modularization 357 ExeEnginePackageUninitialize(pPackage); // TODO: Modularization
355 break; 358 break;
@@ -439,22 +442,11 @@ extern "C" HRESULT PackageFindRelatedById(
439 ) 442 )
440{ 443{
441 HRESULT hr = S_OK; 444 HRESULT hr = S_OK;
442 BURN_PACKAGE* pPackage = NULL; 445 BURN_RELATED_BUNDLE* pRelatedBundle = NULL;
443 446
444 for (DWORD i = 0; i < pRelatedBundles->cRelatedBundles; ++i) 447 hr = RelatedBundleFindById(pRelatedBundles, wzId, &pRelatedBundle);
445 { 448 *ppPackage = FAILED(hr) ? NULL : &pRelatedBundle->package;
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 }
454 449
455 hr = E_NOTFOUND;
456
457LExit:
458 return hr; 450 return hr;
459} 451}
460 452
diff --git a/src/burn/engine/package.h b/src/burn/engine/package.h
index f2a1c304..10b5f33c 100644
--- a/src/burn/engine/package.h
+++ b/src/burn/engine/package.h
@@ -35,6 +35,7 @@ enum BURN_EXE_PROTOCOL_TYPE
35enum BURN_PACKAGE_TYPE 35enum BURN_PACKAGE_TYPE
36{ 36{
37 BURN_PACKAGE_TYPE_NONE, 37 BURN_PACKAGE_TYPE_NONE,
38 BURN_PACKAGE_TYPE_BUNDLE,
38 BURN_PACKAGE_TYPE_EXE, 39 BURN_PACKAGE_TYPE_EXE,
39 BURN_PACKAGE_TYPE_MSI, 40 BURN_PACKAGE_TYPE_MSI,
40 BURN_PACKAGE_TYPE_MSP, 41 BURN_PACKAGE_TYPE_MSP,
@@ -263,21 +264,36 @@ typedef struct _BURN_PACKAGE
263 { 264 {
264 struct 265 struct
265 { 266 {
266 LPWSTR sczDetectCondition;
267 LPWSTR sczInstallArguments; 267 LPWSTR sczInstallArguments;
268 LPWSTR sczRepairArguments; 268 LPWSTR sczRepairArguments;
269 LPWSTR sczUninstallArguments; 269 LPWSTR sczUninstallArguments;
270
270 LPWSTR sczIgnoreDependencies; 271 LPWSTR sczIgnoreDependencies;
271 LPCWSTR wzAncestors; // points directly into engine state. 272 LPCWSTR wzAncestors; // points directly into engine state.
272 LPCWSTR wzEngineWorkingDirectory; // points directly into engine state. 273 LPCWSTR wzEngineWorkingDirectory; // points directly into engine state.
273 274
274 BOOL fPseudoBundle; 275 BOOL fPseudoBundle;
276 BOOL fRepairable;
277 BOOL fSupportsBurnProtocol;
275 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;
276 BOOL fRepairable; 294 BOOL fRepairable;
277 BURN_EXE_PROTOCOL_TYPE protocol; 295 BURN_EXE_PROTOCOL_TYPE protocol;
278 296
279 BOOL fSupportsAncestors;
280
281 BURN_EXE_EXIT_CODE* rgExitCodes; 297 BURN_EXE_EXIT_CODE* rgExitCodes;
282 DWORD cExitCodes; 298 DWORD cExitCodes;
283 299
diff --git a/src/burn/engine/plan.cpp b/src/burn/engine/plan.cpp
index 0f63a945..e0e9a82b 100644
--- a/src/burn/engine/plan.cpp
+++ b/src/burn/engine/plan.cpp
@@ -36,16 +36,13 @@ static HRESULT PlanPackagesHelper(
36 __in BURN_USER_EXPERIENCE* pUX, 36 __in BURN_USER_EXPERIENCE* pUX,
37 __in BURN_PLAN* pPlan, 37 __in BURN_PLAN* pPlan,
38 __in BURN_LOGGING* pLog, 38 __in BURN_LOGGING* pLog,
39 __in BURN_VARIABLES* pVariables, 39 __in BURN_VARIABLES* pVariables
40 __in BOOTSTRAPPER_DISPLAY display,
41 __in BOOTSTRAPPER_RELATION_TYPE relationType
42 ); 40 );
43static HRESULT InitializePackage( 41static HRESULT InitializePackage(
44 __in BURN_PLAN* pPlan, 42 __in BURN_PLAN* pPlan,
45 __in BURN_USER_EXPERIENCE* pUX, 43 __in BURN_USER_EXPERIENCE* pUX,
46 __in BURN_VARIABLES* pVariables, 44 __in BURN_VARIABLES* pVariables,
47 __in BURN_PACKAGE* pPackage, 45 __in BURN_PACKAGE* pPackage
48 __in BOOTSTRAPPER_RELATION_TYPE relationType
49 ); 46 );
50static HRESULT ProcessPackage( 47static HRESULT ProcessPackage(
51 __in BOOL fBundlePerMachine, 48 __in BOOL fBundlePerMachine,
@@ -54,7 +51,6 @@ static HRESULT ProcessPackage(
54 __in BURN_PACKAGE* pPackage, 51 __in BURN_PACKAGE* pPackage,
55 __in BURN_LOGGING* pLog, 52 __in BURN_LOGGING* pLog,
56 __in BURN_VARIABLES* pVariables, 53 __in BURN_VARIABLES* pVariables,
57 __in BOOTSTRAPPER_DISPLAY display,
58 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary 54 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary
59 ); 55 );
60static HRESULT ProcessPackageRollbackBoundary( 56static HRESULT ProcessPackageRollbackBoundary(
@@ -266,10 +262,10 @@ extern "C" void PlanUninitializeExecuteAction(
266{ 262{
267 switch (pExecuteAction->type) 263 switch (pExecuteAction->type)
268 { 264 {
269 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: 265 case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE:
270 ReleaseStr(pExecuteAction->exePackage.sczIgnoreDependencies); 266 ReleaseStr(pExecuteAction->relatedBundle.sczIgnoreDependencies);
271 ReleaseStr(pExecuteAction->exePackage.sczAncestors); 267 ReleaseStr(pExecuteAction->relatedBundle.sczAncestors);
272 ReleaseStr(pExecuteAction->exePackage.sczEngineWorkingDirectory); 268 ReleaseStr(pExecuteAction->relatedBundle.sczEngineWorkingDirectory);
273 break; 269 break;
274 270
275 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: 271 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE:
@@ -500,14 +496,12 @@ extern "C" HRESULT PlanPackages(
500 __in BURN_PACKAGES* pPackages, 496 __in BURN_PACKAGES* pPackages,
501 __in BURN_PLAN* pPlan, 497 __in BURN_PLAN* pPlan,
502 __in BURN_LOGGING* pLog, 498 __in BURN_LOGGING* pLog,
503 __in BURN_VARIABLES* pVariables, 499 __in BURN_VARIABLES* pVariables
504 __in BOOTSTRAPPER_DISPLAY display,
505 __in BOOTSTRAPPER_RELATION_TYPE relationType
506 ) 500 )
507{ 501{
508 HRESULT hr = S_OK; 502 HRESULT hr = S_OK;
509 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);
511 505
512 return hr; 506 return hr;
513} 507}
@@ -712,15 +706,13 @@ extern "C" HRESULT PlanPassThroughBundle(
712 __in BURN_PACKAGE* pPackage, 706 __in BURN_PACKAGE* pPackage,
713 __in BURN_PLAN* pPlan, 707 __in BURN_PLAN* pPlan,
714 __in BURN_LOGGING* pLog, 708 __in BURN_LOGGING* pLog,
715 __in BURN_VARIABLES* pVariables, 709 __in BURN_VARIABLES* pVariables
716 __in BOOTSTRAPPER_DISPLAY display,
717 __in BOOTSTRAPPER_RELATION_TYPE relationType
718 ) 710 )
719{ 711{
720 HRESULT hr = S_OK; 712 HRESULT hr = S_OK;
721 713
722 // Plan passthrough package. 714 // Plan passthrough package.
723 hr = PlanPackagesHelper(pPackage, 1, pUX, pPlan, pLog, pVariables, display, relationType); 715 hr = PlanPackagesHelper(pPackage, 1, pUX, pPlan, pLog, pVariables);
724 ExitOnFailure(hr, "Failed to process passthrough package."); 716 ExitOnFailure(hr, "Failed to process passthrough package.");
725 717
726LExit: 718LExit:
@@ -732,15 +724,17 @@ extern "C" HRESULT PlanUpdateBundle(
732 __in BURN_PACKAGE* pPackage, 724 __in BURN_PACKAGE* pPackage,
733 __in BURN_PLAN* pPlan, 725 __in BURN_PLAN* pPlan,
734 __in BURN_LOGGING* pLog, 726 __in BURN_LOGGING* pLog,
735 __in BURN_VARIABLES* pVariables, 727 __in BURN_VARIABLES* pVariables
736 __in BOOTSTRAPPER_DISPLAY display,
737 __in BOOTSTRAPPER_RELATION_TYPE relationType
738 ) 728 )
739{ 729{
740 HRESULT hr = S_OK; 730 HRESULT hr = S_OK;
741 731
732 Assert(!pPackage->fPerMachine);
733 Assert(BURN_PACKAGE_TYPE_EXE == pPackage->type);
734 pPackage->Exe.fFireAndForget = BOOTSTRAPPER_ACTION_UPDATE_REPLACE == pPlan->action;
735
742 // Plan update package. 736 // Plan update package.
743 hr = PlanPackagesHelper(pPackage, 1, pUX, pPlan, pLog, pVariables, display, relationType); 737 hr = PlanPackagesHelper(pPackage, 1, pUX, pPlan, pLog, pVariables);
744 ExitOnFailure(hr, "Failed to process update package."); 738 ExitOnFailure(hr, "Failed to process update package.");
745 739
746LExit: 740LExit:
@@ -753,9 +747,7 @@ static HRESULT PlanPackagesHelper(
753 __in BURN_USER_EXPERIENCE* pUX, 747 __in BURN_USER_EXPERIENCE* pUX,
754 __in BURN_PLAN* pPlan, 748 __in BURN_PLAN* pPlan,
755 __in BURN_LOGGING* pLog, 749 __in BURN_LOGGING* pLog,
756 __in BURN_VARIABLES* pVariables, 750 __in BURN_VARIABLES* pVariables
757 __in BOOTSTRAPPER_DISPLAY display,
758 __in BOOTSTRAPPER_RELATION_TYPE relationType
759 ) 751 )
760{ 752{
761 HRESULT hr = S_OK; 753 HRESULT hr = S_OK;
@@ -768,7 +760,7 @@ static HRESULT PlanPackagesHelper(
768 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i; 760 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i;
769 BURN_PACKAGE* pPackage = rgPackages + iPackage; 761 BURN_PACKAGE* pPackage = rgPackages + iPackage;
770 762
771 hr = InitializePackage(pPlan, pUX, pVariables, pPackage, relationType); 763 hr = InitializePackage(pPlan, pUX, pVariables, pPackage);
772 ExitOnFailure(hr, "Failed to initialize package."); 764 ExitOnFailure(hr, "Failed to initialize package.");
773 } 765 }
774 766
@@ -791,7 +783,7 @@ static HRESULT PlanPackagesHelper(
791 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i; 783 DWORD iPackage = (BOOTSTRAPPER_ACTION_UNINSTALL == pPlan->action) ? cPackages - 1 - i : i;
792 BURN_PACKAGE* pPackage = rgPackages + iPackage; 784 BURN_PACKAGE* pPackage = rgPackages + iPackage;
793 785
794 hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, display, &pRollbackBoundary); 786 hr = ProcessPackage(fBundlePerMachine, pUX, pPlan, pPackage, pLog, pVariables, &pRollbackBoundary);
795 ExitOnFailure(hr, "Failed to process package."); 787 ExitOnFailure(hr, "Failed to process package.");
796 } 788 }
797 789
@@ -841,14 +833,24 @@ static HRESULT InitializePackage(
841 __in BURN_PLAN* pPlan, 833 __in BURN_PLAN* pPlan,
842 __in BURN_USER_EXPERIENCE* pUX, 834 __in BURN_USER_EXPERIENCE* pUX,
843 __in BURN_VARIABLES* pVariables, 835 __in BURN_VARIABLES* pVariables,
844 __in BURN_PACKAGE* pPackage, 836 __in BURN_PACKAGE* pPackage
845 __in BOOTSTRAPPER_RELATION_TYPE relationType
846 ) 837 )
847{ 838{
848 HRESULT hr = S_OK; 839 HRESULT hr = S_OK;
849 BOOTSTRAPPER_PACKAGE_CONDITION_RESULT installCondition = BOOTSTRAPPER_PACKAGE_CONDITION_DEFAULT; 840 BOOTSTRAPPER_PACKAGE_CONDITION_RESULT installCondition = BOOTSTRAPPER_PACKAGE_CONDITION_DEFAULT;
850 BOOL fInstallCondition = FALSE; 841 BOOL fInstallCondition = FALSE;
851 BOOL fBeginCalled = 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 }
852 854
853 if (pPackage->fCanAffectRegistration) 855 if (pPackage->fCanAffectRegistration)
854 { 856 {
@@ -896,7 +898,6 @@ static HRESULT ProcessPackage(
896 __in BURN_PACKAGE* pPackage, 898 __in BURN_PACKAGE* pPackage,
897 __in BURN_LOGGING* pLog, 899 __in BURN_LOGGING* pLog,
898 __in BURN_VARIABLES* pVariables, 900 __in BURN_VARIABLES* pVariables,
899 __in BOOTSTRAPPER_DISPLAY display,
900 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary 901 __inout BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary
901 ) 902 )
902{ 903{
@@ -920,7 +921,7 @@ static HRESULT ProcessPackage(
920 if (BOOTSTRAPPER_REQUEST_STATE_NONE != pPackage->requested) 921 if (BOOTSTRAPPER_REQUEST_STATE_NONE != pPackage->requested)
921 { 922 {
922 // If the package is in a requested state, plan it. 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);
924 ExitOnFailure(hr, "Failed to plan execute package."); 925 ExitOnFailure(hr, "Failed to plan execute package.");
925 } 926 }
926 else 927 else
@@ -1064,7 +1065,6 @@ LExit:
1064 1065
1065extern "C" HRESULT PlanExecutePackage( 1066extern "C" HRESULT PlanExecutePackage(
1066 __in BOOL fPerMachine, 1067 __in BOOL fPerMachine,
1067 __in BOOTSTRAPPER_DISPLAY display,
1068 __in BURN_USER_EXPERIENCE* pUserExperience, 1068 __in BURN_USER_EXPERIENCE* pUserExperience,
1069 __in BURN_PLAN* pPlan, 1069 __in BURN_PLAN* pPlan,
1070 __in BURN_PACKAGE* pPackage, 1070 __in BURN_PACKAGE* pPackage,
@@ -1073,6 +1073,7 @@ extern "C" HRESULT PlanExecutePackage(
1073 ) 1073 )
1074{ 1074{
1075 HRESULT hr = S_OK; 1075 HRESULT hr = S_OK;
1076 BOOTSTRAPPER_DISPLAY display = pPlan->pCommand->display;
1076 BOOL fRequestedCache = BOOTSTRAPPER_CACHE_TYPE_REMOVE < pPackage->cacheType && (BOOTSTRAPPER_REQUEST_STATE_CACHE == pPackage->requested || ForceCache(pPlan, pPackage)); 1077 BOOL fRequestedCache = BOOTSTRAPPER_CACHE_TYPE_REMOVE < pPackage->cacheType && (BOOTSTRAPPER_REQUEST_STATE_CACHE == pPackage->requested || ForceCache(pPlan, pPackage));
1077 1078
1078 hr = CalculateExecuteActions(pPackage, pPlan->pActiveRollbackBoundary); 1079 hr = CalculateExecuteActions(pPackage, pPlan->pActiveRollbackBoundary);
@@ -1124,7 +1125,7 @@ extern "C" HRESULT PlanExecutePackage(
1124 switch (pPackage->type) 1125 switch (pPackage->type)
1125 { 1126 {
1126 case BURN_PACKAGE_TYPE_EXE: 1127 case BURN_PACKAGE_TYPE_EXE:
1127 hr = ExeEnginePlanAddPackage(NULL, pPackage, pPlan, pLog, pVariables); 1128 hr = ExeEnginePlanAddPackage(pPackage, pPlan, pLog, pVariables);
1128 break; 1129 break;
1129 1130
1130 case BURN_PACKAGE_TYPE_MSI: 1131 case BURN_PACKAGE_TYPE_MSI:
@@ -1288,8 +1289,8 @@ extern "C" HRESULT PlanRelatedBundlesBegin(
1288 } 1289 }
1289 1290
1290 // Pass along any ancestors and ourself to prevent infinite loops. 1291 // Pass along any ancestors and ourself to prevent infinite loops.
1291 pRelatedBundle->package.Exe.wzAncestors = pRegistration->sczBundlePackageAncestors; 1292 pRelatedBundle->package.Bundle.wzAncestors = pRegistration->sczBundlePackageAncestors;
1292 pRelatedBundle->package.Exe.wzEngineWorkingDirectory = pPlan->pInternalCommand->sczEngineWorkingDirectory; 1293 pRelatedBundle->package.Bundle.wzEngineWorkingDirectory = pPlan->pInternalCommand->sczEngineWorkingDirectory;
1293 1294
1294 hr = PlanDefaultRelatedBundleRequestState(relationType, pRelatedBundle->relationType, pPlan->action, pRegistration->pVersion, pRelatedBundle->pVersion, &pRelatedBundle->package.requested); 1295 hr = PlanDefaultRelatedBundleRequestState(relationType, pRelatedBundle->relationType, pPlan->action, pRegistration->pVersion, pRelatedBundle->pVersion, &pRelatedBundle->package.requested);
1295 ExitOnFailure(hr, "Failed to get default request state for related bundle."); 1296 ExitOnFailure(hr, "Failed to get default request state for related bundle.");
@@ -1349,37 +1350,38 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1349 1350
1350 for (DWORD i = 0; i < pPlan->cExecuteActions; ++i) 1351 for (DWORD i = 0; i < pPlan->cExecuteActions; ++i)
1351 { 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)
1353 { 1354 {
1354 fExecutingAnyPackage = TRUE; 1355 case BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE:
1355 1356 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].relatedBundle.action)
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)
1358 { 1357 {
1359 if (0 < pPackage->cDependencyProviders) 1358 fExecutingAnyPackage = TRUE;
1359
1360 BURN_PACKAGE* pPackage = &pPlan->rgExecuteActions[i].relatedBundle.pRelatedBundle->package;
1361 if (pPackage->cDependencyProviders)
1360 { 1362 {
1361 // Bundles only support a single provider key. 1363 // Bundles only support a single provider key.
1362 const BURN_DEPENDENCY_PROVIDER* pProvider = pPackage->rgDependencyProviders; 1364 const BURN_DEPENDENCY_PROVIDER* pProvider = pPackage->rgDependencyProviders;
1363 DictAddKey(sdProviderKeys, pProvider->sczKey); 1365 DictAddKey(sdProviderKeys, pProvider->sczKey);
1364 } 1366 }
1365 } 1367 }
1366 } 1368 break;
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;
1374 1369
1375 case BURN_EXECUTE_ACTION_TYPE_MSP_TARGET: 1370 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE:
1376 fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].mspTarget.action); 1371 fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].exePackage.action);
1377 break; 1372 break;
1378 1373
1379 case BURN_EXECUTE_ACTION_TYPE_MSU_PACKAGE: 1374 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE:
1380 fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].msuPackage.action); 1375 fExecutingAnyPackage |= (BOOTSTRAPPER_ACTION_STATE_NONE != pPlan->rgExecuteActions[i].msiPackage.action);
1381 break; 1376 break;
1382 } 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;
1383 } 1385 }
1384 } 1386 }
1385 1387
@@ -1422,7 +1424,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1422 if (BOOTSTRAPPER_RELATION_ADDON == pRelatedBundle->relationType || BOOTSTRAPPER_RELATION_PATCH == pRelatedBundle->relationType) 1424 if (BOOTSTRAPPER_RELATION_ADDON == pRelatedBundle->relationType || BOOTSTRAPPER_RELATION_PATCH == pRelatedBundle->relationType)
1423 { 1425 {
1424 // Addon and patch bundles will be passed a list of dependencies to ignore for planning. 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);
1426 ExitOnFailure(hr, "Failed to copy the list of dependencies to ignore."); 1428 ExitOnFailure(hr, "Failed to copy the list of dependencies to ignore.");
1427 1429
1428 // Uninstall addons and patches early in the chain, before other packages are uninstalled. 1430 // Uninstall addons and patches early in the chain, before other packages are uninstalled.
@@ -1434,8 +1436,8 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1434 1436
1435 if (BOOTSTRAPPER_REQUEST_STATE_NONE != pRelatedBundle->package.requested) 1437 if (BOOTSTRAPPER_REQUEST_STATE_NONE != pRelatedBundle->package.requested)
1436 { 1438 {
1437 hr = ExeEnginePlanCalculatePackage(&pRelatedBundle->package); 1439 hr = BundlePackageEnginePlanCalculatePackage(&pRelatedBundle->package);
1438 ExitOnFailure(hr, "Failed to calcuate plan for related bundle: %ls", pRelatedBundle->package.sczId); 1440 ExitOnFailure(hr, "Failed to calculate plan for related bundle: %ls", pRelatedBundle->package.sczId);
1439 1441
1440 // Calculate package states based on reference count for addon and patch related bundles. 1442 // Calculate package states based on reference count for addon and patch related bundles.
1441 if (BOOTSTRAPPER_RELATION_ADDON == pRelatedBundle->relationType || BOOTSTRAPPER_RELATION_PATCH == pRelatedBundle->relationType) 1443 if (BOOTSTRAPPER_RELATION_ADDON == pRelatedBundle->relationType || BOOTSTRAPPER_RELATION_PATCH == pRelatedBundle->relationType)
@@ -1450,7 +1452,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1450 } 1452 }
1451 } 1453 }
1452 1454
1453 hr = ExeEnginePlanAddPackage(pdwInsertIndex, &pRelatedBundle->package, pPlan, pLog, pVariables); 1455 hr = BundlePackageEnginePlanAddRelatedBundle(pdwInsertIndex, pRelatedBundle, pPlan, pLog, pVariables);
1454 ExitOnFailure(hr, "Failed to add to plan related bundle: %ls", pRelatedBundle->package.sczId); 1456 ExitOnFailure(hr, "Failed to add to plan related bundle: %ls", pRelatedBundle->package.sczId);
1455 1457
1456 // Calculate package states based on reference count for addon and patch related bundles. 1458 // Calculate package states based on reference count for addon and patch related bundles.
@@ -2603,8 +2605,12 @@ static void ExecuteActionLog(
2603 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)); 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));
2604 break; 2606 break;
2605 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
2606 case BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE: 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));
2608 break; 2614 break;
2609 2615
2610 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: 2616 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE:
diff --git a/src/burn/engine/plan.h b/src/burn/engine/plan.h
index f0560e6e..6be19a10 100644
--- a/src/burn/engine/plan.h
+++ b/src/burn/engine/plan.h
@@ -50,6 +50,7 @@ enum BURN_EXECUTE_ACTION_TYPE
50 BURN_EXECUTE_ACTION_TYPE_CHECKPOINT, 50 BURN_EXECUTE_ACTION_TYPE_CHECKPOINT,
51 BURN_EXECUTE_ACTION_TYPE_WAIT_CACHE_PACKAGE, 51 BURN_EXECUTE_ACTION_TYPE_WAIT_CACHE_PACKAGE,
52 BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE, 52 BURN_EXECUTE_ACTION_TYPE_UNCACHE_PACKAGE,
53 BURN_EXECUTE_ACTION_TYPE_RELATED_BUNDLE,
53 BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE, 54 BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE,
54 BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE, 55 BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE,
55 BURN_EXECUTE_ACTION_TYPE_MSP_TARGET, 56 BURN_EXECUTE_ACTION_TYPE_MSP_TARGET,
@@ -160,12 +161,16 @@ typedef struct _BURN_EXECUTE_ACTION
160 } uncachePackage; 161 } uncachePackage;
161 struct 162 struct
162 { 163 {
163 BURN_PACKAGE* pPackage; 164 BURN_RELATED_BUNDLE* pRelatedBundle;
164 BOOL fFireAndForget;
165 BOOTSTRAPPER_ACTION_STATE action; 165 BOOTSTRAPPER_ACTION_STATE action;
166 LPWSTR sczIgnoreDependencies; 166 LPWSTR sczIgnoreDependencies;
167 LPWSTR sczAncestors; 167 LPWSTR sczAncestors;
168 LPWSTR sczEngineWorkingDirectory; 168 LPWSTR sczEngineWorkingDirectory;
169 } relatedBundle;
170 struct
171 {
172 BURN_PACKAGE* pPackage;
173 BOOTSTRAPPER_ACTION_STATE action;
169 } exePackage; 174 } exePackage;
170 struct 175 struct
171 { 176 {
@@ -339,9 +344,7 @@ HRESULT PlanPackages(
339 __in BURN_PACKAGES* pPackages, 344 __in BURN_PACKAGES* pPackages,
340 __in BURN_PLAN* pPlan, 345 __in BURN_PLAN* pPlan,
341 __in BURN_LOGGING* pLog, 346 __in BURN_LOGGING* pLog,
342 __in BURN_VARIABLES* pVariables, 347 __in BURN_VARIABLES* pVariables
343 __in BOOTSTRAPPER_DISPLAY display,
344 __in BOOTSTRAPPER_RELATION_TYPE relationType
345 ); 348 );
346HRESULT PlanRegistration( 349HRESULT PlanRegistration(
347 __in BURN_PLAN* pPlan, 350 __in BURN_PLAN* pPlan,
@@ -356,18 +359,14 @@ HRESULT PlanPassThroughBundle(
356 __in BURN_PACKAGE* pPackage, 359 __in BURN_PACKAGE* pPackage,
357 __in BURN_PLAN* pPlan, 360 __in BURN_PLAN* pPlan,
358 __in BURN_LOGGING* pLog, 361 __in BURN_LOGGING* pLog,
359 __in BURN_VARIABLES* pVariables, 362 __in BURN_VARIABLES* pVariables
360 __in BOOTSTRAPPER_DISPLAY display,
361 __in BOOTSTRAPPER_RELATION_TYPE relationType
362 ); 363 );
363HRESULT PlanUpdateBundle( 364HRESULT PlanUpdateBundle(
364 __in BURN_USER_EXPERIENCE* pUX, 365 __in BURN_USER_EXPERIENCE* pUX,
365 __in BURN_PACKAGE* pPackage, 366 __in BURN_PACKAGE* pPackage,
366 __in BURN_PLAN* pPlan, 367 __in BURN_PLAN* pPlan,
367 __in BURN_LOGGING* pLog, 368 __in BURN_LOGGING* pLog,
368 __in BURN_VARIABLES* pVariables, 369 __in BURN_VARIABLES* pVariables
369 __in BOOTSTRAPPER_DISPLAY display,
370 __in BOOTSTRAPPER_RELATION_TYPE relationType
371 ); 370 );
372HRESULT PlanLayoutContainer( 371HRESULT PlanLayoutContainer(
373 __in BURN_PLAN* pPlan, 372 __in BURN_PLAN* pPlan,
@@ -379,7 +378,6 @@ HRESULT PlanLayoutPackage(
379 ); 378 );
380HRESULT PlanExecutePackage( 379HRESULT PlanExecutePackage(
381 __in BOOL fPerMachine, 380 __in BOOL fPerMachine,
382 __in BOOTSTRAPPER_DISPLAY display,
383 __in BURN_USER_EXPERIENCE* pUserExperience, 381 __in BURN_USER_EXPERIENCE* pUserExperience,
384 __in BURN_PLAN* pPlan, 382 __in BURN_PLAN* pPlan,
385 __in BURN_PACKAGE* pPackage, 383 __in BURN_PACKAGE* pPackage,
diff --git a/src/burn/engine/precomp.h b/src/burn/engine/precomp.h
index 3b4d989b..26adf44c 100644
--- a/src/burn/engine/precomp.h
+++ b/src/burn/engine/precomp.h
@@ -86,6 +86,7 @@
86#include "dependency.h" 86#include "dependency.h"
87#include "core.h" 87#include "core.h"
88#include "apply.h" 88#include "apply.h"
89#include "bundlepackageengine.h"
89#include "exeengine.h" 90#include "exeengine.h"
90#include "msiengine.h" 91#include "msiengine.h"
91#include "mspengine.h" 92#include "mspengine.h"
diff --git a/src/burn/engine/pseudobundle.cpp b/src/burn/engine/pseudobundle.cpp
index 14dd2b77..7b670035 100644
--- a/src/burn/engine/pseudobundle.cpp
+++ b/src/burn/engine/pseudobundle.cpp
@@ -3,36 +3,24 @@
3#include "precomp.h" 3#include "precomp.h"
4 4
5 5
6extern "C" HRESULT PseudoBundleInitialize( 6extern "C" HRESULT PseudoBundleInitializeRelated(
7 __in BURN_PACKAGE* pPackage, 7 __in BURN_PACKAGE* pPackage,
8 __in BOOL fSupportsBurnProtocol, 8 __in BOOL fSupportsBurnProtocol,
9 __in BOOL fPerMachine, 9 __in BOOL fPerMachine,
10 __in_z LPCWSTR wzId, 10 __in_z LPCWSTR wzId,
11#ifdef DEBUG
11 __in BOOTSTRAPPER_RELATION_TYPE relationType, 12 __in BOOTSTRAPPER_RELATION_TYPE relationType,
12 __in BOOTSTRAPPER_PACKAGE_STATE state, 13#endif
13 __in BOOL fCached, 14 __in BOOL fCached,
14 __in_z LPCWSTR wzFilePath, 15 __in_z LPCWSTR wzFilePath,
15 __in_z LPCWSTR wzLocalSource,
16 __in_z_opt LPCWSTR wzDownloadSource,
17 __in DWORD64 qwSize, 16 __in DWORD64 qwSize,
18 __in BOOL fVital, 17 __in_opt BURN_DEPENDENCY_PROVIDER* pDependencyProvider
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
25 ) 18 )
26{ 19{
27 HRESULT hr = S_OK; 20 HRESULT hr = S_OK;
28 LPWSTR sczRelationTypeCommandLineSwitch = NULL;
29 BURN_PAYLOAD* pPayload = NULL; 21 BURN_PAYLOAD* pPayload = NULL;
30 22
31 LPCWSTR wzRelationTypeCommandLine = CoreRelationTypeToCommandLineString(relationType); 23 AssertSz(BOOTSTRAPPER_RELATION_UPDATE != relationType, "Update pseudo bundles must use PseudoBundleInitializeUpdateBundle instead.");
32 if (wzRelationTypeCommandLine)
33 {
34 hr = StrAllocFormatted(&sczRelationTypeCommandLineSwitch, L" -%ls", wzRelationTypeCommandLine);
35 }
36 24
37 // Initialize the single payload, and fill out all the necessary fields 25 // Initialize the single payload, and fill out all the necessary fields
38 pPackage->payloads.rgItems = (BURN_PAYLOAD_GROUP_ITEM*)MemAlloc(sizeof(BURN_PAYLOAD_GROUP_ITEM), TRUE); 26 pPackage->payloads.rgItems = (BURN_PAYLOAD_GROUP_ITEM*)MemAlloc(sizeof(BURN_PAYLOAD_GROUP_ITEM), TRUE);
@@ -51,41 +39,21 @@ extern "C" HRESULT PseudoBundleInitialize(
51 hr = StrAllocString(&pPayload->sczFilePath, wzFilePath, 0); 39 hr = StrAllocString(&pPayload->sczFilePath, wzFilePath, 0);
52 ExitOnFailure(hr, "Failed to copy filename for pseudo bundle."); 40 ExitOnFailure(hr, "Failed to copy filename for pseudo bundle.");
53 41
54 hr = StrAllocString(&pPayload->sczSourcePath, wzLocalSource, 0); 42 hr = StrAllocString(&pPayload->sczSourcePath, wzFilePath, 0);
55 ExitOnFailure(hr, "Failed to copy local source path for pseudo bundle."); 43 ExitOnFailure(hr, "Failed to copy local source path for pseudo bundle.");
56 44
57 if (wzDownloadSource && *wzDownloadSource) 45 pPackage->type = BURN_PACKAGE_TYPE_BUNDLE;
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;
80 pPackage->fPerMachine = fPerMachine; 46 pPackage->fPerMachine = fPerMachine;
81 pPackage->currentState = state; 47 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_PRESENT;
82 pPackage->fCached = fCached; 48 pPackage->fCached = fCached;
83 pPackage->qwInstallSize = qwSize; 49 pPackage->qwInstallSize = qwSize;
84 pPackage->qwSize = qwSize; 50 pPackage->qwSize = qwSize;
85 pPackage->fVital = fVital; 51 pPackage->fVital = FALSE;
86 52
87 pPackage->Exe.protocol = fSupportsBurnProtocol ? BURN_EXE_PROTOCOL_TYPE_BURN : BURN_EXE_PROTOCOL_TYPE_NONE; 53 pPackage->fUninstallable = TRUE;
88 pPackage->Exe.fSupportsAncestors = TRUE; 54 pPackage->Bundle.fPseudoBundle = TRUE;
55 pPackage->Bundle.fRepairable = TRUE;
56 pPackage->Bundle.fSupportsBurnProtocol = fSupportsBurnProtocol;
89 57
90 hr = StrAllocString(&pPackage->sczId, wzId, 0); 58 hr = StrAllocString(&pPackage->sczId, wzId, 0);
91 ExitOnFailure(hr, "Failed to copy key for pseudo bundle."); 59 ExitOnFailure(hr, "Failed to copy key for pseudo bundle.");
@@ -93,47 +61,6 @@ extern "C" HRESULT PseudoBundleInitialize(
93 hr = StrAllocString(&pPackage->sczCacheId, wzId, 0); 61 hr = StrAllocString(&pPackage->sczCacheId, wzId, 0);
94 ExitOnFailure(hr, "Failed to copy cache id for pseudo bundle."); 62 ExitOnFailure(hr, "Failed to copy cache id for pseudo bundle.");
95 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
137 if (pDependencyProvider) 64 if (pDependencyProvider)
138 { 65 {
139 pPackage->rgDependencyProviders = (BURN_DEPENDENCY_PROVIDER*)MemAlloc(sizeof(BURN_DEPENDENCY_PROVIDER), TRUE); 66 pPackage->rgDependencyProviders = (BURN_DEPENDENCY_PROVIDER*)MemAlloc(sizeof(BURN_DEPENDENCY_PROVIDER), TRUE);
@@ -153,8 +80,6 @@ extern "C" HRESULT PseudoBundleInitialize(
153 } 80 }
154 81
155LExit: 82LExit:
156 ReleaseStr(sczRelationTypeCommandLineSwitch);
157
158 return hr; 83 return hr;
159} 84}
160 85
@@ -165,7 +90,7 @@ extern "C" HRESULT PseudoBundleInitializePassthrough(
165 __in BURN_PACKAGE* pPackage 90 __in BURN_PACKAGE* pPackage
166 ) 91 )
167{ 92{
168 Assert(BURN_PACKAGE_TYPE_EXE == pPackage->type); 93 Assert(BURN_PACKAGE_TYPE_BUNDLE == pPackage->type);
169 94
170 HRESULT hr = S_OK; 95 HRESULT hr = S_OK;
171 LPWSTR sczArguments = NULL; 96 LPWSTR sczArguments = NULL;
@@ -180,59 +105,29 @@ extern "C" HRESULT PseudoBundleInitializePassthrough(
180 pPassthroughPackage->payloads.rgItems[iPayload].pPayload = pPackage->payloads.rgItems[iPayload].pPayload; 105 pPassthroughPackage->payloads.rgItems[iPayload].pPayload = pPackage->payloads.rgItems[iPayload].pPayload;
181 } 106 }
182 107
183 pPassthroughPackage->Exe.fPseudoBundle = TRUE;
184
185 pPassthroughPackage->fPerMachine = FALSE; // passthrough bundles are always launched per-user. 108 pPassthroughPackage->fPerMachine = FALSE; // passthrough bundles are always launched per-user.
186 pPassthroughPackage->type = pPackage->type; 109 pPassthroughPackage->type = BURN_PACKAGE_TYPE_EXE;
187 pPassthroughPackage->currentState = pPackage->currentState; 110 pPassthroughPackage->currentState = pPackage->currentState;
188 pPassthroughPackage->fCached = pPackage->fCached; 111 pPassthroughPackage->fCached = pPackage->fCached;
189 pPassthroughPackage->qwInstallSize = pPackage->qwInstallSize; 112 pPassthroughPackage->qwInstallSize = pPackage->qwInstallSize;
190 pPassthroughPackage->qwSize = pPackage->qwSize; 113 pPassthroughPackage->qwSize = pPackage->qwSize;
191 pPassthroughPackage->fVital = pPackage->fVital; 114 pPassthroughPackage->fVital = pPackage->fVital;
192 115
116 pPassthroughPackage->Exe.fPseudoBundle = TRUE;
117 pPassthroughPackage->Exe.protocol = pPackage->Bundle.fSupportsBurnProtocol ? BURN_EXE_PROTOCOL_TYPE_BURN : BURN_EXE_PROTOCOL_TYPE_NONE;
118
193 hr = StrAllocString(&pPassthroughPackage->sczId, pPackage->sczId, 0); 119 hr = StrAllocString(&pPassthroughPackage->sczId, pPackage->sczId, 0);
194 ExitOnFailure(hr, "Failed to copy key for passthrough pseudo bundle."); 120 ExitOnFailure(hr, "Failed to copy key for passthrough pseudo bundle.");
195 121
196 hr = StrAllocString(&pPassthroughPackage->sczCacheId, pPackage->sczCacheId, 0); 122 hr = StrAllocString(&pPassthroughPackage->sczCacheId, pPackage->sczCacheId, 0);
197 ExitOnFailure(hr, "Failed to copy cache id for passthrough pseudo bundle."); 123 ExitOnFailure(hr, "Failed to copy cache id for passthrough pseudo bundle.");
198 124
199 pPassthroughPackage->Exe.protocol = pPackage->Exe.protocol;
200
201 hr = CoreCreatePassthroughBundleCommandLine(&sczArguments, pInternalCommand, pCommand); 125 hr = CoreCreatePassthroughBundleCommandLine(&sczArguments, pInternalCommand, pCommand);
202 ExitOnFailure(hr, "Failed to create command-line arguments."); 126 ExitOnFailure(hr, "Failed to create command-line arguments.");
203 127
204 hr = StrAllocString(&pPassthroughPackage->Exe.sczInstallArguments, sczArguments, 0); 128 hr = StrAllocString(&pPassthroughPackage->Exe.sczInstallArguments, sczArguments, 0);
205 ExitOnFailure(hr, "Failed to copy install arguments for passthrough bundle package"); 129 ExitOnFailure(hr, "Failed to copy install arguments for passthrough bundle package");
206 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
236LExit: 131LExit:
237 ReleaseStr(sczArguments); 132 ReleaseStr(sczArguments);
238 return hr; 133 return hr;
@@ -290,14 +185,16 @@ extern "C" HRESULT PseudoBundleInitializeUpdateBundle(
290 memcpy_s(pPayload->pbHash, pPayload->cbHash, pbHash, cbHash); 185 memcpy_s(pPayload->pbHash, pPayload->cbHash, pbHash, cbHash);
291 } 186 }
292 187
293 pPackage->Exe.fPseudoBundle = TRUE;
294
295 pPackage->type = BURN_PACKAGE_TYPE_EXE; 188 pPackage->type = BURN_PACKAGE_TYPE_EXE;
296 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT; 189 pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT;
297 pPackage->qwInstallSize = qwSize; 190 pPackage->qwInstallSize = qwSize;
298 pPackage->qwSize = qwSize; 191 pPackage->qwSize = qwSize;
299 pPackage->fVital = TRUE; 192 pPackage->fVital = TRUE;
300 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
301 hr = StrAllocString(&pPackage->sczId, wzId, 0); 198 hr = StrAllocString(&pPackage->sczId, wzId, 0);
302 ExitOnFailure(hr, "Failed to copy id for update bundle."); 199 ExitOnFailure(hr, "Failed to copy id for update bundle.");
303 200
@@ -307,10 +204,6 @@ extern "C" HRESULT PseudoBundleInitializeUpdateBundle(
307 hr = StrAllocString(&pPackage->Exe.sczInstallArguments, wzInstallArguments, 0); 204 hr = StrAllocString(&pPackage->Exe.sczInstallArguments, wzInstallArguments, 0);
308 ExitOnFailure(hr, "Failed to copy install arguments for update bundle package"); 205 ExitOnFailure(hr, "Failed to copy install arguments for update bundle package");
309 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
314LExit: 207LExit:
315 return hr; 208 return hr;
316} \ No newline at end of file 209}
diff --git a/src/burn/engine/pseudobundle.h b/src/burn/engine/pseudobundle.h
index 22132c5e..78a681df 100644
--- a/src/burn/engine/pseudobundle.h
+++ b/src/burn/engine/pseudobundle.h
@@ -6,25 +6,18 @@
6extern "C" { 6extern "C" {
7#endif 7#endif
8 8
9HRESULT PseudoBundleInitialize( 9HRESULT PseudoBundleInitializeRelated(
10 __in BURN_PACKAGE* pPackage, 10 __in BURN_PACKAGE* pPackage,
11 __in BOOL fSupportsBurnProtocol, 11 __in BOOL fSupportsBurnProtocol,
12 __in BOOL fPerMachine, 12 __in BOOL fPerMachine,
13 __in_z LPCWSTR wzId, 13 __in_z LPCWSTR wzId,
14#ifdef DEBUG
14 __in BOOTSTRAPPER_RELATION_TYPE relationType, 15 __in BOOTSTRAPPER_RELATION_TYPE relationType,
15 __in BOOTSTRAPPER_PACKAGE_STATE state, 16#endif
16 __in BOOL fCached, 17 __in BOOL fCached,
17 __in_z LPCWSTR wzFilePath, 18 __in_z LPCWSTR wzFilePath,
18 __in_z LPCWSTR wzLocalSource,
19 __in_z_opt LPCWSTR wzDownloadSource,
20 __in DWORD64 qwSize, 19 __in DWORD64 qwSize,
21 __in BOOL fVital, 20 __in_opt BURN_DEPENDENCY_PROVIDER* pDependencyProvider
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
28 ); 21 );
29HRESULT PseudoBundleInitializePassthrough( 22HRESULT PseudoBundleInitializePassthrough(
30 __in BURN_PACKAGE* pPassthroughPackage, 23 __in BURN_PACKAGE* pPassthroughPackage,
diff --git a/src/burn/engine/relatedbundle.cpp b/src/burn/engine/relatedbundle.cpp
index 4a694ef6..e2380aab 100644
--- a/src/burn/engine/relatedbundle.cpp
+++ b/src/burn/engine/relatedbundle.cpp
@@ -98,6 +98,37 @@ extern "C" void RelatedBundlesUninitialize(
98} 98}
99 99
100 100
101extern "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
127LExit:
128 return hr;
129}
130
131
101// internal helper functions 132// internal helper functions
102 133
103static HRESULT LoadIfRelatedBundle( 134static HRESULT LoadIfRelatedBundle(
@@ -410,6 +441,7 @@ static HRESULT LoadRelatedBundleFromKey(
410 BOOL fCached = FALSE; 441 BOOL fCached = FALSE;
411 DWORD64 qwFileSize = 0; 442 DWORD64 qwFileSize = 0;
412 BURN_DEPENDENCY_PROVIDER dependencyProvider = { }; 443 BURN_DEPENDENCY_PROVIDER dependencyProvider = { };
444 BURN_DEPENDENCY_PROVIDER* pBundleDependencyProvider = NULL;
413 445
414 // Only support progress from engines that are compatible. 446 // Only support progress from engines that are compatible.
415 hr = RegReadNumber(hkBundleId, BURN_REGISTRATION_REGISTRY_ENGINE_PROTOCOL_VERSION, &dwEngineProtocolVersion); 447 hr = RegReadNumber(hkBundleId, BURN_REGISTRATION_REGISTRY_ENGINE_PROTOCOL_VERSION, &dwEngineProtocolVersion);
@@ -458,6 +490,11 @@ static HRESULT LoadRelatedBundleFromKey(
458 if (E_FILENOTFOUND != hr) 490 if (E_FILENOTFOUND != hr)
459 { 491 {
460 ExitOnFailure(hr, "Failed to read provider key from registry for bundle: %ls", wzRelatedBundleId); 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;
461 498
462 dependencyProvider.fImported = TRUE; 499 dependencyProvider.fImported = TRUE;
463 500
@@ -480,11 +517,11 @@ static HRESULT LoadRelatedBundleFromKey(
480 517
481 pRelatedBundle->relationType = relationType; 518 pRelatedBundle->relationType = relationType;
482 519
483 hr = PseudoBundleInitialize(&pRelatedBundle->package, fSupportsBurnProtocol, fPerMachine, wzRelatedBundleId, pRelatedBundle->relationType, 520 hr = PseudoBundleInitializeRelated(&pRelatedBundle->package, fSupportsBurnProtocol, fPerMachine, wzRelatedBundleId,
484 BOOTSTRAPPER_PACKAGE_STATE_PRESENT, fCached, sczCachePath, sczCachePath, NULL, qwFileSize, FALSE, 521#ifdef DEBUG
485 L"-quiet", L"-repair -quiet", L"-uninstall -quiet", 522 pRelatedBundle->relationType,
486 (dependencyProvider.sczKey && *dependencyProvider.sczKey) ? &dependencyProvider : NULL, 523#endif
487 NULL, 0); 524 fCached, sczCachePath, qwFileSize, pBundleDependencyProvider);
488 ExitOnFailure(hr, "Failed to initialize related bundle to represent bundle: %ls", wzRelatedBundleId); 525 ExitOnFailure(hr, "Failed to initialize related bundle to represent bundle: %ls", wzRelatedBundleId);
489 526
490LExit: 527LExit:
diff --git a/src/burn/engine/relatedbundle.h b/src/burn/engine/relatedbundle.h
index 01691c25..0113c8ee 100644
--- a/src/burn/engine/relatedbundle.h
+++ b/src/burn/engine/relatedbundle.h
@@ -14,6 +14,11 @@ HRESULT RelatedBundlesInitializeForScope(
14void RelatedBundlesUninitialize( 14void RelatedBundlesUninitialize(
15 __in BURN_RELATED_BUNDLES* pRelatedBundles 15 __in BURN_RELATED_BUNDLES* pRelatedBundles
16 ); 16 );
17HRESULT RelatedBundleFindById(
18 __in BURN_RELATED_BUNDLES* pRelatedBundles,
19 __in_z LPCWSTR wzId,
20 __out BURN_RELATED_BUNDLE** ppRelatedBundle
21 );
17 22
18#if defined(__cplusplus) 23#if defined(__cplusplus)
19} 24}
diff --git a/src/burn/test/BurnUnitTest/PlanTest.cpp b/src/burn/test/BurnUnitTest/PlanTest.cpp
index 35ddb22f..7e704c23 100644
--- a/src/burn/test/BurnUnitTest/PlanTest.cpp
+++ b/src/burn/test/BurnUnitTest/PlanTest.cpp
@@ -117,7 +117,7 @@ namespace Bootstrapper
117 ValidateExecuteCommitMsiTransaction(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ"); 117 ValidateExecuteCommitMsiTransaction(pPlan, fRollback, dwIndex++, L"rbaOCA08D8ky7uBOK71_6FWz1K3TuQ");
118 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 118 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
119 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++); 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); 121 Assert::Equal(dwIndex, pPlan->cExecuteActions);
122 122
123 fRollback = TRUE; 123 fRollback = TRUE;
@@ -155,7 +155,7 @@ namespace Bootstrapper
155 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 155 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
156 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 156 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
157 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++); 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); 159 Assert::Equal(dwIndex, pPlan->cRollbackActions);
160 160
161 Assert::Equal(4ul, pPlan->cExecutePackagesTotal); 161 Assert::Equal(4ul, pPlan->cExecutePackagesTotal);
@@ -496,7 +496,7 @@ namespace Bootstrapper
496 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 496 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
497 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 497 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
498 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++); 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); 500 Assert::Equal(dwIndex, pPlan->cExecuteActions);
501 501
502 fRollback = TRUE; 502 fRollback = TRUE;
@@ -514,7 +514,7 @@ namespace Bootstrapper
514 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 514 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
515 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 515 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
516 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++); 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); 518 Assert::Equal(dwIndex, pPlan->cRollbackActions);
519 519
520 Assert::Equal(2ul, pPlan->cExecutePackagesTotal); 520 Assert::Equal(2ul, pPlan->cExecutePackagesTotal);
@@ -1154,7 +1154,11 @@ namespace Bootstrapper
1154 pRelatedBundle->fPlannable = TRUE; 1154 pRelatedBundle->fPlannable = TRUE;
1155 pRelatedBundle->relationType = BOOTSTRAPPER_RELATION_UPGRADE; 1155 pRelatedBundle->relationType = BOOTSTRAPPER_RELATION_UPGRADE;
1156 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);
1158 NativeAssert::Succeeded(hr, "Failed to initialize related bundle to represent bundle: %ls", wzId); 1162 NativeAssert::Succeeded(hr, "Failed to initialize related bundle to represent bundle: %ls", wzId);
1159 1163
1160 ++pRelatedBundles->cRelatedBundles; 1164 ++pRelatedBundles->cRelatedBundles;
@@ -1310,7 +1314,7 @@ namespace Bootstrapper
1310 Assert::Equal<BOOL>(FALSE, pAction->fDeleted); 1314 Assert::Equal<BOOL>(FALSE, pAction->fDeleted);
1311 } 1315 }
1312 1316
1313 void ValidateExecuteExePackage( 1317 void ValidateExecuteRelatedBundle(
1314 __in BURN_PLAN* pPlan, 1318 __in BURN_PLAN* pPlan,
1315 __in BOOL fRollback, 1319 __in BOOL fRollback,
1316 __in DWORD dwIndex, 1320 __in DWORD dwIndex,
@@ -1320,10 +1324,25 @@ namespace Bootstrapper
1320 ) 1324 )
1321 { 1325 {
1322 BURN_EXECUTE_ACTION* pAction = ValidateExecuteActionExists(pPlan, fRollback, dwIndex); 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);
1323 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE, pAction->type); 1343 Assert::Equal<DWORD>(BURN_EXECUTE_ACTION_TYPE_EXE_PACKAGE, pAction->type);
1324 NativeAssert::StringEqual(wzPackageId, pAction->exePackage.pPackage->sczId); 1344 NativeAssert::StringEqual(wzPackageId, pAction->exePackage.pPackage->sczId);
1325 Assert::Equal<DWORD>(action, pAction->exePackage.action); 1345 Assert::Equal<DWORD>(action, pAction->exePackage.action);
1326 NativeAssert::StringEqual(wzIgnoreDependencies, pAction->exePackage.sczIgnoreDependencies);
1327 Assert::Equal<BOOL>(FALSE, pAction->fDeleted); 1346 Assert::Equal<BOOL>(FALSE, pAction->fDeleted);
1328 } 1347 }
1329 1348