aboutsummaryrefslogtreecommitdiff
path: root/src/burn/engine
diff options
context:
space:
mode:
authorBob Arnson <bob@firegiant.com>2026-02-04 20:47:04 -0500
committerBob Arnson <bob@firegiant.com>2026-02-04 20:47:04 -0500
commitedccb203c421d2bd820062024088c6698424d9ee (patch)
tree6b47c3eb5ca53bd9f79f3d032dc1a596d411bf38 /src/burn/engine
parenta3d3963f806117ce123d95e8b77e73e1c1545b25 (diff)
downloadwix-bob/ConfigurableScopeBundles.tar.gz
wix-bob/ConfigurableScopeBundles.tar.bz2
wix-bob/ConfigurableScopeBundles.zip
Support dual-purpose packages in Burn.bob/ConfigurableScopeBundles
Fixes https://github.com/wixtoolset/issues/issues/8958
Diffstat (limited to 'src/burn/engine')
-rw-r--r--src/burn/engine/apply.cpp2
-rw-r--r--src/burn/engine/baengine.cpp5
-rw-r--r--src/burn/engine/baengine.h1
-rw-r--r--src/burn/engine/cache.cpp8
-rw-r--r--src/burn/engine/core.cpp42
-rw-r--r--src/burn/engine/core.h5
-rw-r--r--src/burn/engine/dependency.cpp72
-rw-r--r--src/burn/engine/elevation.cpp43
-rw-r--r--src/burn/engine/engine.cpp7
-rw-r--r--src/burn/engine/engine.mc29
-rw-r--r--src/burn/engine/engine.vcxproj17
-rw-r--r--src/burn/engine/externalengine.cpp6
-rw-r--r--src/burn/engine/externalengine.h5
-rw-r--r--src/burn/engine/logging.cpp36
-rw-r--r--src/burn/engine/logging.h7
-rw-r--r--src/burn/engine/msiengine.cpp49
-rw-r--r--src/burn/engine/msiengine.h2
-rw-r--r--src/burn/engine/mspengine.cpp4
-rw-r--r--src/burn/engine/package.cpp48
-rw-r--r--src/burn/engine/package.h7
-rw-r--r--src/burn/engine/plan.cpp73
-rw-r--r--src/burn/engine/plan.h12
-rw-r--r--src/burn/engine/registration.cpp287
-rw-r--r--src/burn/engine/registration.h11
-rw-r--r--src/burn/engine/relatedbundle.cpp4
-rw-r--r--src/burn/engine/uithread.cpp2
-rw-r--r--src/burn/engine/variable.cpp2
27 files changed, 597 insertions, 189 deletions
diff --git a/src/burn/engine/apply.cpp b/src/burn/engine/apply.cpp
index e4e76a6c..68aded71 100644
--- a/src/burn/engine/apply.cpp
+++ b/src/burn/engine/apply.cpp
@@ -632,7 +632,7 @@ extern "C" HRESULT ApplyCache(
632 { 632 {
633 hr = ElevationCachePreparePackage(hPipe, pPackage); 633 hr = ElevationCachePreparePackage(hPipe, pPackage);
634 } 634 }
635 LogExitOnFailure(hr, MSG_CACHE_PREPARE_PACKAGE_FAILED, "Cache prepare package failed: %ls", pPackage->sczId, NULL, NULL); 635 LogExitOnFailure(hr, MSG_CACHE_PREPARE_PACKAGE_FAILED, "Cache prepare package failed: %ls", pPackage->sczId);
636 } 636 }
637 637
638 hr = ApplyCachePackage(&cacheContext, pPackage); 638 hr = ApplyCachePackage(&cacheContext, pPackage);
diff --git a/src/burn/engine/baengine.cpp b/src/burn/engine/baengine.cpp
index d1704ad9..e48f71c0 100644
--- a/src/burn/engine/baengine.cpp
+++ b/src/burn/engine/baengine.cpp
@@ -1134,12 +1134,15 @@ static HRESULT BAEnginePlan(
1134 hr = BuffReaderReadNumber(pReaderArgs, reinterpret_cast<DWORD*>(&args.action)); 1134 hr = BuffReaderReadNumber(pReaderArgs, reinterpret_cast<DWORD*>(&args.action));
1135 ExitOnFailure(hr, "Failed to read plan action of BAEnginePlan args."); 1135 ExitOnFailure(hr, "Failed to read plan action of BAEnginePlan args.");
1136 1136
1137 hr = BuffReaderReadNumber(pReaderArgs, reinterpret_cast<DWORD*>(&args.plannedScope));
1138 ExitOnFailure(hr, "Failed to read plan scope of BAEnginePlan args.");
1139
1137 // Read results. 1140 // Read results.
1138 hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion); 1141 hr = BuffReaderReadNumber(pReaderResults, &results.dwApiVersion);
1139 ExitOnFailure(hr, "Failed to read API version of BAEnginePlan results."); 1142 ExitOnFailure(hr, "Failed to read API version of BAEnginePlan results.");
1140 1143
1141 // Execute. 1144 // Execute.
1142 hr = ExternalEnginePlan(pContext, args.action); 1145 hr = ExternalEnginePlan(pContext, args.action, args.plannedScope);
1143 ExitOnFailure(hr, "Failed to plan in the engine."); 1146 ExitOnFailure(hr, "Failed to plan in the engine.");
1144 1147
1145 // Pack result. 1148 // Pack result.
diff --git a/src/burn/engine/baengine.h b/src/burn/engine/baengine.h
index 97cfea9c..39e5ae0b 100644
--- a/src/burn/engine/baengine.h
+++ b/src/burn/engine/baengine.h
@@ -31,6 +31,7 @@ typedef struct _BAENGINE_ACTION
31 struct 31 struct
32 { 32 {
33 BOOTSTRAPPER_ACTION action; 33 BOOTSTRAPPER_ACTION action;
34 BOOTSTRAPPER_SCOPE plannedScope;
34 } plan; 35 } plan;
35 struct 36 struct
36 { 37 {
diff --git a/src/burn/engine/cache.cpp b/src/burn/engine/cache.cpp
index c85a1be4..21bd42be 100644
--- a/src/burn/engine/cache.cpp
+++ b/src/burn/engine/cache.cpp
@@ -36,8 +36,8 @@ static HRESULT SecurePerMachineCacheRoot(
36static HRESULT CreateCompletedPath( 36static HRESULT CreateCompletedPath(
37 __in BURN_CACHE* pCache, 37 __in BURN_CACHE* pCache,
38 __in BOOL fPerMachine, 38 __in BOOL fPerMachine,
39 __in LPCWSTR wzCacheId, 39 __in_z LPCWSTR wzId,
40 __in LPCWSTR wzFilePath, 40 __in_z_opt LPCWSTR wzFilePath,
41 __out_z LPWSTR* psczCachePath 41 __out_z LPWSTR* psczCachePath
42 ); 42 );
43static HRESULT CreateUnverifiedPath( 43static HRESULT CreateUnverifiedPath(
@@ -1658,8 +1658,8 @@ LExit:
1658static HRESULT CreateCompletedPath( 1658static HRESULT CreateCompletedPath(
1659 __in BURN_CACHE* pCache, 1659 __in BURN_CACHE* pCache,
1660 __in BOOL fPerMachine, 1660 __in BOOL fPerMachine,
1661 __in LPCWSTR wzId, 1661 __in_z LPCWSTR wzId,
1662 __in LPCWSTR wzFilePath, 1662 __in_z_opt LPCWSTR wzFilePath,
1663 __out_z LPWSTR* psczCachePath 1663 __out_z LPWSTR* psczCachePath
1664 ) 1664 )
1665{ 1665{
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp
index 2dfa4857..7937bd65 100644
--- a/src/burn/engine/core.cpp
+++ b/src/burn/engine/core.cpp
@@ -379,7 +379,7 @@ extern "C" HRESULT CoreDetect(
379 pEngineState->registration.fEligibleForCleanup = FALSE; 379 pEngineState->registration.fEligibleForCleanup = FALSE;
380 } 380 }
381 381
382 LogId(REPORT_STANDARD, MSG_DETECTED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingBoolToString(pPackage->fCached), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->installRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->cacheRegistrationState)); 382 LogId(REPORT_STANDARD, MSG_DETECTED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingBoolToString(pPackage->fCached), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->installRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->cacheRegistrationState), LoggingPackageScopeToString(pPackage->scope));
383 383
384 if (BURN_PACKAGE_TYPE_MSI == pPackage->type) 384 if (BURN_PACKAGE_TYPE_MSI == pPackage->type)
385 { 385 {
@@ -424,8 +424,9 @@ LExit:
424 424
425extern "C" HRESULT CorePlan( 425extern "C" HRESULT CorePlan(
426 __in BURN_ENGINE_STATE* pEngineState, 426 __in BURN_ENGINE_STATE* pEngineState,
427 __in BOOTSTRAPPER_ACTION action 427 __in BOOTSTRAPPER_ACTION action,
428 ) 428 __in BOOTSTRAPPER_SCOPE plannedScope
429)
429{ 430{
430 HRESULT hr = S_OK; 431 HRESULT hr = S_OK;
431 BOOL fPlanBegan = FALSE; 432 BOOL fPlanBegan = FALSE;
@@ -433,7 +434,7 @@ extern "C" HRESULT CorePlan(
433 BURN_PACKAGE* pForwardCompatibleBundlePackage = NULL; 434 BURN_PACKAGE* pForwardCompatibleBundlePackage = NULL;
434 BOOL fContinuePlanning = TRUE; // assume we won't skip planning due to dependencies. 435 BOOL fContinuePlanning = TRUE; // assume we won't skip planning due to dependencies.
435 436
436 LogId(REPORT_STANDARD, MSG_PLAN_BEGIN, pEngineState->packages.cPackages, LoggingBurnActionToString(action)); 437 LogId(REPORT_STANDARD, MSG_PLAN_BEGIN, pEngineState->packages.cPackages, LoggingBurnActionToString(action), LoggingBundleScopeToString(plannedScope));
437 438
438 fPlanBegan = TRUE; 439 fPlanBegan = TRUE;
439 hr = BACallbackOnPlanBegin(&pEngineState->userExperience, pEngineState->packages.cPackages); 440 hr = BACallbackOnPlanBegin(&pEngineState->userExperience, pEngineState->packages.cPackages);
@@ -452,12 +453,13 @@ extern "C" HRESULT CorePlan(
452 pEngineState->fPlanned = FALSE; 453 pEngineState->fPlanned = FALSE;
453 PlanReset(&pEngineState->plan, &pEngineState->variables, &pEngineState->containers, &pEngineState->packages, &pEngineState->layoutPayloads); 454 PlanReset(&pEngineState->plan, &pEngineState->variables, &pEngineState->containers, &pEngineState->packages, &pEngineState->layoutPayloads);
454 455
455 hr = PlanSetVariables(action, &pEngineState->variables); 456 hr = PlanSetVariables(action, pEngineState->registration.scope, pEngineState->plan.plannedScope, &pEngineState->variables);
456 ExitOnFailure(hr, "Failed to update action."); 457 ExitOnFailure(hr, "Failed to update plan variables.");
457 458
458 // Remember the overall action state in the plan since it shapes the changes 459 // Remember the overall action state in the plan since it shapes the changes
459 // we make everywhere. 460 // we make everywhere.
460 pEngineState->plan.action = action; 461 pEngineState->plan.action = action;
462 pEngineState->plan.plannedScope = plannedScope;
461 pEngineState->plan.pCache = &pEngineState->cache; 463 pEngineState->plan.pCache = &pEngineState->cache;
462 pEngineState->plan.pCommand = &pEngineState->command; 464 pEngineState->plan.pCommand = &pEngineState->command;
463 pEngineState->plan.pInternalCommand = &pEngineState->internalCommand; 465 pEngineState->plan.pInternalCommand = &pEngineState->internalCommand;
@@ -467,6 +469,17 @@ extern "C" HRESULT CorePlan(
467 pEngineState->plan.fDisableRollback = pEngineState->fDisableRollback || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pEngineState->plan.action; 469 pEngineState->plan.fDisableRollback = pEngineState->fDisableRollback || BOOTSTRAPPER_ACTION_UNSAFE_UNINSTALL == pEngineState->plan.action;
468 pEngineState->plan.fPlanPackageCacheRollback = BOOTSTRAPPER_REGISTRATION_TYPE_NONE == pEngineState->registration.detectedRegistrationType; 470 pEngineState->plan.fPlanPackageCacheRollback = BOOTSTRAPPER_REGISTRATION_TYPE_NONE == pEngineState->registration.detectedRegistrationType;
469 471
472 hr = PlanPackagesAndBundleScope(pEngineState->packages.rgPackages, pEngineState->packages.cPackages, pEngineState->plan.plannedScope, pEngineState->registration.scope, pEngineState->command.commandLineScope, &pEngineState->plan.plannedScope, &pEngineState->registration.fPerMachine);
473 ExitOnFailure(hr, "Failed to determine packages and bundle scope.");
474
475 if (BOOTSTRAPPER_PACKAGE_SCOPE_PER_MACHINE_OR_PER_USER == pEngineState->registration.scope || BOOTSTRAPPER_PACKAGE_SCOPE_PER_USER_OR_PER_MACHINE == pEngineState->registration.scope)
476 {
477 LogId(REPORT_STANDARD, MSG_PLAN_CONFIGURED_SCOPE, LoggingInstallScopeToString(pEngineState->registration.fPerMachine));
478 }
479
480 hr = RegistrationSetPaths(&pEngineState->registration, &pEngineState->cache);
481 ExitOnFailure(hr, "Failed to set registration paths.");
482
470 // Set resume commandline 483 // Set resume commandline
471 hr = PlanSetResumeCommand(&pEngineState->plan, &pEngineState->registration, &pEngineState->log); 484 hr = PlanSetResumeCommand(&pEngineState->plan, &pEngineState->registration, &pEngineState->log);
472 ExitOnFailure(hr, "Failed to set resume command"); 485 ExitOnFailure(hr, "Failed to set resume command");
@@ -475,7 +488,7 @@ extern "C" HRESULT CorePlan(
475 ExitOnFailure(hr, "Failed to initialize the dependencies for the plan."); 488 ExitOnFailure(hr, "Failed to initialize the dependencies for the plan.");
476 489
477 hr = RegistrationPlanInitialize(&pEngineState->registration); 490 hr = RegistrationPlanInitialize(&pEngineState->registration);
478 ExitOnFailure(hr, "Failed to initialize registration for the plan."); 491 ExitOnFailure(hr, "Failed to initialize the plan for registration.");
479 492
480 if (BOOTSTRAPPER_ACTION_LAYOUT == action) 493 if (BOOTSTRAPPER_ACTION_LAYOUT == action)
481 { 494 {
@@ -556,6 +569,9 @@ extern "C" HRESULT CorePlan(
556 LogPackages(pUpgradeBundlePackage, pForwardCompatibleBundlePackage, &pEngineState->packages, &pEngineState->registration.relatedBundles, action); 569 LogPackages(pUpgradeBundlePackage, pForwardCompatibleBundlePackage, &pEngineState->packages, &pEngineState->registration.relatedBundles, action);
557 } 570 }
558 571
572 hr = PlanSetVariables(action, pEngineState->registration.scope, pEngineState->plan.plannedScope, &pEngineState->variables);
573 ExitOnFailure(hr, "Failed to update plan variables after planning.");
574
559 PlanDump(&pEngineState->plan); 575 PlanDump(&pEngineState->plan);
560 576
561LExit: 577LExit:
@@ -1331,7 +1347,7 @@ extern "C" void CoreCleanup(
1331 ExitFunction(); 1347 ExitFunction();
1332 } 1348 }
1333 1349
1334 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_UNINSTALL); 1350 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_UNINSTALL, BOOTSTRAPPER_SCOPE_DEFAULT);
1335 ExitOnFailure(hr, "Plan during cleanup failed"); 1351 ExitOnFailure(hr, "Plan during cleanup failed");
1336 1352
1337 hr = CoreApply(pEngineState, pEngineState->hMessageWindow); 1353 hr = CoreApply(pEngineState, pEngineState->hMessageWindow);
@@ -1470,6 +1486,14 @@ extern "C" HRESULT CoreParseCommandLine(
1470 { 1486 {
1471 pInternalCommand->fDisableSystemRestore = TRUE; 1487 pInternalCommand->fDisableSystemRestore = TRUE;
1472 } 1488 }
1489 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"peruser", -1, TRUE))
1490 {
1491 pCommand->commandLineScope = BOOTSTRAPPER_SCOPE_PER_USER;
1492 }
1493 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"permachine", -1, TRUE))
1494 {
1495 pCommand->commandLineScope = BOOTSTRAPPER_SCOPE_PER_MACHINE;
1496 }
1473 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"originalsource", -1, TRUE)) 1497 else if (CSTR_EQUAL == ::CompareStringOrdinal(&argv[i][1], -1, L"originalsource", -1, TRUE))
1474 { 1498 {
1475 if (i + 1 >= argc) 1499 if (i + 1 >= argc)
@@ -2346,7 +2370,7 @@ static void LogPackages(
2346 LogRollbackBoundary(pPackage->pRollbackBoundaryBackward); 2370 LogRollbackBoundary(pPackage->pRollbackBoundaryBackward);
2347 } 2371 }
2348 2372
2349 LogId(REPORT_STANDARD, MSG_PLANNED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingRequestStateToString(pPackage->defaultRequested), LoggingRequestStateToString(pPackage->requested), LoggingActionStateToString(pPackage->execute), LoggingActionStateToString(pPackage->rollback), LoggingCacheTypeToString(pPackage->authoredCacheType), LoggingCacheTypeToString(pPackage->cacheType), LoggingPlannedCacheToString(pPackage), LoggingBoolToString(pPackage->fPlannedUncache), LoggingDependencyActionToString(pPackage->dependencyExecute), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedInstallRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedCacheRegistrationState)); 2373 LogId(REPORT_STANDARD, MSG_PLANNED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingRequestStateToString(pPackage->defaultRequested), LoggingRequestStateToString(pPackage->requested), LoggingActionStateToString(pPackage->execute), LoggingActionStateToString(pPackage->rollback), LoggingCacheTypeToString(pPackage->authoredCacheType), LoggingCacheTypeToString(pPackage->cacheType), LoggingPlannedCacheToString(pPackage), LoggingBoolToString(pPackage->fPlannedUncache), LoggingDependencyActionToString(pPackage->dependencyExecute), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedInstallRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedCacheRegistrationState), LoggingInstallScopeToString(pPackage->fPerMachine));
2350 2374
2351 if (BURN_PACKAGE_TYPE_MSI == pPackage->type) 2375 if (BURN_PACKAGE_TYPE_MSI == pPackage->type)
2352 { 2376 {
diff --git a/src/burn/engine/core.h b/src/burn/engine/core.h
index cf615e35..75c0c941 100644
--- a/src/burn/engine/core.h
+++ b/src/burn/engine/core.h
@@ -45,7 +45,9 @@ const LPCWSTR BURN_BUNDLE_EXECUTE_PACKAGE_ACTION = L"WixBundleExecutePackageActi
45const LPCWSTR BURN_BUNDLE_FORCED_RESTART_PACKAGE = L"WixBundleForcedRestartPackage"; 45const LPCWSTR BURN_BUNDLE_FORCED_RESTART_PACKAGE = L"WixBundleForcedRestartPackage";
46const LPCWSTR BURN_BUNDLE_INSTALLED = L"WixBundleInstalled"; 46const LPCWSTR BURN_BUNDLE_INSTALLED = L"WixBundleInstalled";
47const LPCWSTR BURN_BUNDLE_ELEVATED = L"WixBundleElevated"; 47const LPCWSTR BURN_BUNDLE_ELEVATED = L"WixBundleElevated";
48const LPCWSTR BURN_BUNDLE_PLANNED_SCOPE = L"WixBundlePlannedScope";
48const LPCWSTR BURN_BUNDLE_PROVIDER_KEY = L"WixBundleProviderKey"; 49const LPCWSTR BURN_BUNDLE_PROVIDER_KEY = L"WixBundleProviderKey";
50const LPCWSTR BURN_BUNDLE_SCOPE = L"WixBundleScope";
49const LPCWSTR BURN_BUNDLE_SOURCE_PROCESS_PATH = L"WixBundleSourceProcessPath"; 51const LPCWSTR BURN_BUNDLE_SOURCE_PROCESS_PATH = L"WixBundleSourceProcessPath";
50const LPCWSTR BURN_BUNDLE_SOURCE_PROCESS_FOLDER = L"WixBundleSourceProcessFolder"; 52const LPCWSTR BURN_BUNDLE_SOURCE_PROCESS_FOLDER = L"WixBundleSourceProcessFolder";
51const LPCWSTR BURN_BUNDLE_TAG = L"WixBundleTag"; 53const LPCWSTR BURN_BUNDLE_TAG = L"WixBundleTag";
@@ -243,7 +245,8 @@ HRESULT CoreDetect(
243 ); 245 );
244HRESULT CorePlan( 246HRESULT CorePlan(
245 __in BURN_ENGINE_STATE* pEngineState, 247 __in BURN_ENGINE_STATE* pEngineState,
246 __in BOOTSTRAPPER_ACTION action 248 __in BOOTSTRAPPER_ACTION action,
249 __in BOOTSTRAPPER_SCOPE scope
247 ); 250 );
248HRESULT CoreElevate( 251HRESULT CoreElevate(
249 __in BURN_ENGINE_STATE* pEngineState, 252 __in BURN_ENGINE_STATE* pEngineState,
diff --git a/src/burn/engine/dependency.cpp b/src/burn/engine/dependency.cpp
index 94a8a1e4..7cd0db9f 100644
--- a/src/burn/engine/dependency.cpp
+++ b/src/burn/engine/dependency.cpp
@@ -12,6 +12,7 @@ const LPCWSTR vcszIgnoreDependenciesDelim = L";";
12 12
13static HRESULT DetectPackageDependents( 13static HRESULT DetectPackageDependents(
14 __in BURN_PACKAGE* pPackage, 14 __in BURN_PACKAGE* pPackage,
15 __in BOOL fPackagePerMachine,
15 __in const BURN_REGISTRATION* pRegistration 16 __in const BURN_REGISTRATION* pRegistration
16 ); 17 );
17 18
@@ -249,7 +250,22 @@ extern "C" HRESULT DependencyDetectProviderKeyBundleCode(
249{ 250{
250 HRESULT hr = S_OK; 251 HRESULT hr = S_OK;
251 252
252 hr = DepGetProviderInformation(pRegistration->hkRoot, pRegistration->sczProviderKey, &pRegistration->sczDetectedProviderKeyBundleCode, NULL, NULL); 253 // For configurable packages, check both scopes because until planning,
254 // we can't know their planned scope.
255 if (pRegistration->hkRoot)
256 {
257 hr = DepGetProviderInformation(pRegistration->hkRoot, pRegistration->sczProviderKey, &pRegistration->sczDetectedProviderKeyBundleCode, NULL, NULL);
258 }
259 else
260 {
261 hr = DepGetProviderInformation(HKEY_LOCAL_MACHINE, pRegistration->sczProviderKey, &pRegistration->sczDetectedProviderKeyBundleCode, NULL, NULL);
262
263 if (E_NOTFOUND == hr)
264 {
265 hr = DepGetProviderInformation(HKEY_CURRENT_USER, pRegistration->sczProviderKey, &pRegistration->sczDetectedProviderKeyBundleCode, NULL, NULL);
266 }
267 }
268
253 if (E_NOTFOUND == hr) 269 if (E_NOTFOUND == hr)
254 { 270 {
255 ReleaseNullStr(pRegistration->sczDetectedProviderKeyBundleCode); 271 ReleaseNullStr(pRegistration->sczDetectedProviderKeyBundleCode);
@@ -284,7 +300,21 @@ extern "C" HRESULT DependencyDetectBundle(
284 hr = DependencyDetectProviderKeyBundleCode(pRegistration); 300 hr = DependencyDetectProviderKeyBundleCode(pRegistration);
285 ExitOnFailure(hr, "Failed to detect provider key bundle code."); 301 ExitOnFailure(hr, "Failed to detect provider key bundle code.");
286 302
287 hr = DepCheckDependents(pRegistration->hkRoot, pRegistration->sczProviderKey, 0, NULL, &pRegistration->rgDependents, &pRegistration->cDependents); 303 // For configurable packages, check both scopes because until planning,
304 // we can't know their planned scope.
305 if (pRegistration->hkRoot)
306 {
307 hr = DepCheckDependents(pRegistration->hkRoot, pRegistration->sczProviderKey, 0, NULL, &pRegistration->rgDependents, &pRegistration->cDependents);
308 }
309 else
310 {
311 hr = DepCheckDependents(HKEY_LOCAL_MACHINE, pRegistration->sczProviderKey, 0, NULL, &pRegistration->rgDependents, &pRegistration->cDependents);
312
313 if (E_NOTFOUND == hr)
314 {
315 hr = DepCheckDependents(HKEY_CURRENT_USER, pRegistration->sczProviderKey, 0, NULL, &pRegistration->rgDependents, &pRegistration->cDependents);
316 }
317 }
288 ExitOnPathFailure(hr, fExists, "Failed dependents check on bundle."); 318 ExitOnPathFailure(hr, fExists, "Failed dependents check on bundle.");
289 319
290 if (pDependencies->fSelfDependent || pDependencies->fActiveParent) 320 if (pDependencies->fSelfDependent || pDependencies->fActiveParent)
@@ -292,13 +322,13 @@ extern "C" HRESULT DependencyDetectBundle(
292 for (DWORD i = 0; i < pRegistration->cDependents; ++i) 322 for (DWORD i = 0; i < pRegistration->cDependents; ++i)
293 { 323 {
294 DEPENDENCY* pDependent = pRegistration->rgDependents + i; 324 DEPENDENCY* pDependent = pRegistration->rgDependents + i;
295 325
296 if (pDependencies->fActiveParent && CSTR_EQUAL == ::CompareStringOrdinal(pDependencies->wzActiveParent, -1, pDependent->sczKey, -1, TRUE)) 326 if (pDependent && pDependencies->fActiveParent && CSTR_EQUAL == ::CompareStringOrdinal(pDependencies->wzActiveParent, -1, pDependent->sczKey, -1, TRUE))
297 { 327 {
298 pRegistration->fParentRegisteredAsDependent = TRUE; 328 pRegistration->fParentRegisteredAsDependent = TRUE;
299 } 329 }
300 330
301 if (pDependencies->fSelfDependent && CSTR_EQUAL == ::CompareStringOrdinal(pDependencies->wzSelfDependent, -1, pDependent->sczKey, -1, TRUE)) 331 if (pDependent && pDependencies->fSelfDependent && CSTR_EQUAL == ::CompareStringOrdinal(pDependencies->wzSelfDependent, -1, pDependent->sczKey, -1, TRUE))
302 { 332 {
303 pRegistration->fSelfRegisteredAsDependent = TRUE; 333 pRegistration->fSelfRegisteredAsDependent = TRUE;
304 } 334 }
@@ -316,11 +346,24 @@ extern "C" HRESULT DependencyDetectChainPackage(
316{ 346{
317 HRESULT hr = S_OK; 347 HRESULT hr = S_OK;
318 348
319 hr = DetectPackageDependents(pPackage, pRegistration); 349 if (BOOTSTRAPPER_PACKAGE_SCOPE_PER_USER_OR_PER_MACHINE == pPackage->scope || BOOTSTRAPPER_PACKAGE_SCOPE_PER_MACHINE_OR_PER_USER == pPackage->scope)
320 ExitOnFailure(hr, "Failed to detect dependents for package '%ls'", pPackage->sczId); 350 {
351 // For configurable packages, check both scopes because until planning,
352 // we can't know their planned scope.
353 hr = DetectPackageDependents(pPackage, /*fPerMachine*/TRUE, pRegistration);
354 ExitOnFailure(hr, "Failed to detect per-machine dependents for configurable package '%ls'", pPackage->sczId);
355
356 hr = DetectPackageDependents(pPackage, /*fPerMachine*/FALSE, pRegistration);
357 ExitOnFailure(hr, "Failed to detect per-user dependents for configurable package '%ls'", pPackage->sczId);
358 }
359 else
360 {
361 hr = DetectPackageDependents(pPackage, pPackage->fPerMachine, pRegistration);
362 ExitOnFailure(hr, "Failed to detect dependents for %hs package '%ls'", LoggingInstallScopeToString(pPackage->fPerMachine), pPackage->sczId);
363 }
321 364
322 hr = DependencyDetectCompatibleEntry(pPackage, pRegistration); 365 hr = DependencyDetectCompatibleEntry(pPackage, pRegistration);
323 ExitOnFailure(hr, "Failed to detect compatible package for package '%ls'", pPackage->sczId); 366 ExitOnFailure(hr, "Failed to detect compatible package for %hs package '%ls'", LoggingInstallScopeToString(pPackage->fPerMachine), pPackage->sczId);
324 367
325LExit: 368LExit:
326 return hr; 369 return hr;
@@ -336,7 +379,7 @@ extern "C" HRESULT DependencyDetectRelatedBundle(
336 379
337 if (pRelatedBundle->fPlannable) 380 if (pRelatedBundle->fPlannable)
338 { 381 {
339 hr = DetectPackageDependents(pPackage, pRegistration); 382 hr = DetectPackageDependents(pPackage, pPackage->fPerMachine, pRegistration);
340 ExitOnFailure(hr, "Failed to detect dependents for related bundle '%ls'", pPackage->sczId); 383 ExitOnFailure(hr, "Failed to detect dependents for related bundle '%ls'", pPackage->sczId);
341 } 384 }
342 385
@@ -626,7 +669,7 @@ LExit:
626} 669}
627 670
628extern "C" HRESULT DependencyPlanPackage( 671extern "C" HRESULT DependencyPlanPackage(
629 __in_opt DWORD *pdwInsertSequence, 672 __in_opt DWORD* pdwInsertSequence,
630 __in const BURN_PACKAGE* pPackage, 673 __in const BURN_PACKAGE* pPackage,
631 __in BURN_PLAN* pPlan 674 __in BURN_PLAN* pPlan
632 ) 675 )
@@ -946,18 +989,19 @@ LExit:
946 989
947static HRESULT DetectPackageDependents( 990static HRESULT DetectPackageDependents(
948 __in BURN_PACKAGE* pPackage, 991 __in BURN_PACKAGE* pPackage,
992 __in BOOL fPackagePerMachine,
949 __in const BURN_REGISTRATION* pRegistration 993 __in const BURN_REGISTRATION* pRegistration
950 ) 994 )
951{ 995{
952 HRESULT hr = S_OK; 996 HRESULT hr = S_OK;
953 HKEY hkHive = pPackage->fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 997 HKEY hkHive = fPackagePerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
954 BOOL fCanIgnorePresence = pPackage->fCanAffectRegistration && 0 < pPackage->cDependencyProviders && 998 BOOL fCanIgnorePresence = pPackage->fCanAffectRegistration && 0 < pPackage->cDependencyProviders &&
955 (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->cacheRegistrationState || BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->installRegistrationState); 999 (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->cacheRegistrationState || BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->installRegistrationState);
956 BOOL fBundleRegisteredAsDependent = FALSE; 1000 BOOL fBundleRegisteredAsDependent = FALSE;
957 1001
958 // There's currently no point in getting the dependents if the scope doesn't match, 1002 // There's currently no point in getting the dependents if the scope doesn't match,
959 // because they will just get ignored. 1003 // because they will just get ignored.
960 if (pRegistration->fPerMachine != pPackage->fPerMachine) 1004 if (pRegistration->fPerMachine != fPackagePerMachine)
961 { 1005 {
962 ExitFunction(); 1006 ExitFunction();
963 } 1007 }
@@ -979,7 +1023,7 @@ static HRESULT DetectPackageDependents(
979 { 1023 {
980 DEPENDENCY* pDependent = pProvider->rgDependents + iDependent; 1024 DEPENDENCY* pDependent = pProvider->rgDependents + iDependent;
981 1025
982 if (CSTR_EQUAL == ::CompareStringOrdinal(pRegistration->sczCode, -1, pDependent->sczKey, -1, TRUE)) 1026 if (pDependent && CSTR_EQUAL == ::CompareStringOrdinal(pRegistration->sczCode, -1, pDependent->sczKey, -1, TRUE))
983 { 1027 {
984 pProvider->fBundleRegisteredAsDependent = TRUE; 1028 pProvider->fBundleRegisteredAsDependent = TRUE;
985 fBundleRegisteredAsDependent = TRUE; 1029 fBundleRegisteredAsDependent = TRUE;
@@ -994,10 +1038,12 @@ static HRESULT DetectPackageDependents(
994 { 1038 {
995 pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED; 1039 pPackage->cacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED;
996 } 1040 }
1041
997 if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->installRegistrationState) 1042 if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->installRegistrationState)
998 { 1043 {
999 pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED; 1044 pPackage->installRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_IGNORED;
1000 } 1045 }
1046
1001 if (BURN_PACKAGE_TYPE_MSP == pPackage->type) 1047 if (BURN_PACKAGE_TYPE_MSP == pPackage->type)
1002 { 1048 {
1003 for (DWORD i = 0; i < pPackage->Msp.cTargetProductCodes; ++i) 1049 for (DWORD i = 0; i < pPackage->Msp.cTargetProductCodes; ++i)
diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp
index ef87841f..711ce4af 100644
--- a/src/burn/engine/elevation.cpp
+++ b/src/burn/engine/elevation.cpp
@@ -1191,7 +1191,6 @@ extern "C" HRESULT ElevationExecuteMsiPackage(
1191 hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData); 1191 hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData);
1192 ExitOnFailure(hr, "Failed to write variables."); 1192 ExitOnFailure(hr, "Failed to write variables.");
1193 1193
1194
1195 // send message 1194 // send message
1196 context.pfnMessageHandler = pfnMessageHandler; 1195 context.pfnMessageHandler = pfnMessageHandler;
1197 context.pvContext = pvContext; 1196 context.pvContext = pvContext;
@@ -2572,6 +2571,11 @@ static HRESULT OnSessionBegin(
2572 ExitOnFailure(hr, "Failed to read variables."); 2571 ExitOnFailure(hr, "Failed to read variables.");
2573 2572
2574 // Begin session in per-machine process. 2573 // Begin session in per-machine process.
2574 pRegistration->fPerMachine = TRUE;
2575
2576 hr = RegistrationSetPaths(pRegistration, pCache);
2577 ExitOnFailure(hr, "Failed to set elevated registration paths.");
2578
2575 hr = RegistrationSessionBegin(sczEngineWorkingPath, pRegistration, pCache, pVariables, dwRegistrationOperations, qwEstimatedSize, (BOOTSTRAPPER_REGISTRATION_TYPE)dwRegistrationType); 2579 hr = RegistrationSessionBegin(sczEngineWorkingPath, pRegistration, pCache, pVariables, dwRegistrationOperations, qwEstimatedSize, (BOOTSTRAPPER_REGISTRATION_TYPE)dwRegistrationType);
2576 ExitOnFailure(hr, "Failed to begin registration session."); 2580 ExitOnFailure(hr, "Failed to begin registration session.");
2577 2581
@@ -2657,6 +2661,8 @@ static HRESULT OnCachePreparePackage(
2657 { 2661 {
2658 hr = PackageFindById(pPackages, scz, &pPackage); 2662 hr = PackageFindById(pPackages, scz, &pPackage);
2659 ExitOnFailure(hr, "Failed to find package: %ls", scz); 2663 ExitOnFailure(hr, "Failed to find package: %ls", scz);
2664
2665 pPackage->fPerMachine = TRUE;
2660 } 2666 }
2661 else 2667 else
2662 { 2668 {
@@ -2698,6 +2704,8 @@ static HRESULT OnCacheCompletePayload(
2698 { 2704 {
2699 hr = PackageFindById(pPackages, scz, &pPackage); 2705 hr = PackageFindById(pPackages, scz, &pPackage);
2700 ExitOnFailure(hr, "Failed to find package: %ls", scz); 2706 ExitOnFailure(hr, "Failed to find package: %ls", scz);
2707
2708 pPackage->fPerMachine = TRUE;
2701 } 2709 }
2702 2710
2703 hr = BuffReadString(pbData, cbData, &iData, &scz); 2711 hr = BuffReadString(pbData, cbData, &iData, &scz);
@@ -2717,8 +2725,8 @@ static HRESULT OnCacheCompletePayload(
2717 2725
2718 if (pPackage && pPayload) // complete payload. 2726 if (pPackage && pPayload) // complete payload.
2719 { 2727 {
2720 hr = CacheCompletePayload(pCache, pPackage->fPerMachine, pPayload, pPackage->sczCacheId, sczUnverifiedPath, fMove, BurnCacheMessageHandler, ElevatedProgressRoutine, hPipe); 2728 hr = CacheCompletePayload(pCache, TRUE/*fPerMachine*/, pPayload, pPackage->sczCacheId, sczUnverifiedPath, fMove, BurnCacheMessageHandler, ElevatedProgressRoutine, hPipe);
2721 ExitOnFailure(hr, "Failed to cache payload: %ls", pPayload->sczKey); 2729 ExitOnFailure(hr, "Failed to cache per-machine payload: %ls", pPayload->sczKey);
2722 } 2730 }
2723 else 2731 else
2724 { 2732 {
@@ -2755,6 +2763,8 @@ static HRESULT OnCacheVerifyPayload(
2755 { 2763 {
2756 hr = PackageFindById(pPackages, scz, &pPackage); 2764 hr = PackageFindById(pPackages, scz, &pPackage);
2757 ExitOnFailure(hr, "Failed to find package: %ls", scz); 2765 ExitOnFailure(hr, "Failed to find package: %ls", scz);
2766
2767 pPackage->fPerMachine = TRUE;
2758 } 2768 }
2759 2769
2760 hr = BuffReadString(pbData, cbData, &iData, &scz); 2770 hr = BuffReadString(pbData, cbData, &iData, &scz);
@@ -2970,6 +2980,8 @@ static HRESULT OnExecuteBundlePackage(
2970 hr = PackageFindById(pPackages, sczPackage, &executeAction.bundlePackage.pPackage); 2980 hr = PackageFindById(pPackages, sczPackage, &executeAction.bundlePackage.pPackage);
2971 ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); 2981 ExitOnFailure(hr, "Failed to find package: %ls", sczPackage);
2972 2982
2983 executeAction.bundlePackage.pPackage->fPerMachine = TRUE;
2984
2973 if (BURN_PACKAGE_TYPE_BUNDLE != executeAction.bundlePackage.pPackage->type) 2985 if (BURN_PACKAGE_TYPE_BUNDLE != executeAction.bundlePackage.pPackage->type)
2974 { 2986 {
2975 ExitWithRootFailure(hr, E_INVALIDARG, "Package is not a BUNDLE package: %ls", sczPackage); 2987 ExitWithRootFailure(hr, E_INVALIDARG, "Package is not a BUNDLE package: %ls", sczPackage);
@@ -3052,6 +3064,8 @@ static HRESULT OnExecuteExePackage(
3052 hr = PackageFindById(pPackages, sczPackage, &executeAction.exePackage.pPackage); 3064 hr = PackageFindById(pPackages, sczPackage, &executeAction.exePackage.pPackage);
3053 ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); 3065 ExitOnFailure(hr, "Failed to find package: %ls", sczPackage);
3054 3066
3067 executeAction.exePackage.pPackage->fPerMachine = TRUE;
3068
3055 if (BURN_PACKAGE_TYPE_EXE != executeAction.exePackage.pPackage->type) 3069 if (BURN_PACKAGE_TYPE_EXE != executeAction.exePackage.pPackage->type)
3056 { 3070 {
3057 ExitWithRootFailure(hr, E_INVALIDARG, "Package is not an EXE package: %ls", sczPackage); 3071 ExitWithRootFailure(hr, E_INVALIDARG, "Package is not an EXE package: %ls", sczPackage);
@@ -3113,6 +3127,8 @@ static HRESULT OnExecuteMsiPackage(
3113 hr = PackageFindById(pPackages, sczPackage, &executeAction.msiPackage.pPackage); 3127 hr = PackageFindById(pPackages, sczPackage, &executeAction.msiPackage.pPackage);
3114 ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); 3128 ExitOnFailure(hr, "Failed to find package: %ls", sczPackage);
3115 3129
3130 executeAction.msiPackage.pPackage->fPerMachine = TRUE;
3131
3116 hr = BuffReadPointer(pbData, cbData, &iData, (DWORD_PTR*)&hwndParent); 3132 hr = BuffReadPointer(pbData, cbData, &iData, (DWORD_PTR*)&hwndParent);
3117 ExitOnFailure(hr, "Failed to read parent hwnd."); 3133 ExitOnFailure(hr, "Failed to read parent hwnd.");
3118 3134
@@ -3205,6 +3221,8 @@ static HRESULT OnExecuteMspPackage(
3205 hr = PackageFindById(pPackages, sczPackage, &executeAction.mspTarget.pPackage); 3221 hr = PackageFindById(pPackages, sczPackage, &executeAction.mspTarget.pPackage);
3206 ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); 3222 ExitOnFailure(hr, "Failed to find package: %ls", sczPackage);
3207 3223
3224 executeAction.mspTarget.pPackage->fPerMachine = TRUE;
3225
3208 hr = BuffReadPointer(pbData, cbData, &iData, (DWORD_PTR*)&hwndParent); 3226 hr = BuffReadPointer(pbData, cbData, &iData, (DWORD_PTR*)&hwndParent);
3209 ExitOnFailure(hr, "Failed to read parent hwnd."); 3227 ExitOnFailure(hr, "Failed to read parent hwnd.");
3210 3228
@@ -3246,6 +3264,8 @@ static HRESULT OnExecuteMspPackage(
3246 3264
3247 hr = PackageFindById(pPackages, sczPackage, &executeAction.mspTarget.rgOrderedPatches[i].pPackage); 3265 hr = PackageFindById(pPackages, sczPackage, &executeAction.mspTarget.rgOrderedPatches[i].pPackage);
3248 ExitOnFailure(hr, "Failed to find ordered patch package: %ls", sczPackage); 3266 ExitOnFailure(hr, "Failed to find ordered patch package: %ls", sczPackage);
3267
3268 executeAction.mspTarget.rgOrderedPatches[i].pPackage->fPerMachine = TRUE;
3249 } 3269 }
3250 } 3270 }
3251 3271
@@ -3310,6 +3330,8 @@ static HRESULT OnExecuteMsuPackage(
3310 hr = PackageFindById(pPackages, sczPackage, &executeAction.msuPackage.pPackage); 3330 hr = PackageFindById(pPackages, sczPackage, &executeAction.msuPackage.pPackage);
3311 ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); 3331 ExitOnFailure(hr, "Failed to find package: %ls", sczPackage);
3312 3332
3333 executeAction.msuPackage.pPackage->fPerMachine = TRUE;
3334
3313 if (BURN_PACKAGE_TYPE_MSU != executeAction.msuPackage.pPackage->type) 3335 if (BURN_PACKAGE_TYPE_MSU != executeAction.msuPackage.pPackage->type)
3314 { 3336 {
3315 ExitWithRootFailure(hr, E_INVALIDARG, "Package is not an MSU package: %ls", sczPackage); 3337 ExitWithRootFailure(hr, E_INVALIDARG, "Package is not an MSU package: %ls", sczPackage);
@@ -3371,6 +3393,8 @@ static HRESULT OnUninstallMsiCompatiblePackage(
3371 hr = PackageFindById(pPackages, sczPackageId, &pPackage); 3393 hr = PackageFindById(pPackages, sczPackageId, &pPackage);
3372 ExitOnFailure(hr, "Failed to find package: %ls", sczPackageId); 3394 ExitOnFailure(hr, "Failed to find package: %ls", sczPackageId);
3373 3395
3396 pPackage->fPerMachine = TRUE;
3397
3374 executeAction.uninstallMsiCompatiblePackage.pParentPackage = pPackage; 3398 executeAction.uninstallMsiCompatiblePackage.pParentPackage = pPackage;
3375 pCompatiblePackage = &pPackage->compatiblePackage; 3399 pCompatiblePackage = &pPackage->compatiblePackage;
3376 3400
@@ -3424,6 +3448,8 @@ static HRESULT OnExecutePackageProviderAction(
3424 } 3448 }
3425 ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); 3449 ExitOnFailure(hr, "Failed to find package: %ls", sczPackage);
3426 3450
3451 executeAction.packageProvider.pPackage->fPerMachine;
3452
3427 hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&fRollback); 3453 hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&fRollback);
3428 ExitOnFailure(hr, "Failed to read rollback flag."); 3454 ExitOnFailure(hr, "Failed to read rollback flag.");
3429 3455
@@ -3436,11 +3462,6 @@ static HRESULT OnExecutePackageProviderAction(
3436 ExitOnFailure(hr, "Failed to read provider action."); 3462 ExitOnFailure(hr, "Failed to read provider action.");
3437 } 3463 }
3438 3464
3439 if (!executeAction.packageProvider.pPackage->fPerMachine)
3440 {
3441 ExitWithRootFailure(hr, E_INVALIDARG, "ExecutePackageProviderAction called for per-user package.");
3442 }
3443
3444 // Execute the package provider action. 3465 // Execute the package provider action.
3445 hr = DependencyExecutePackageProviderAction(&executeAction, fRollback); 3466 hr = DependencyExecutePackageProviderAction(&executeAction, fRollback);
3446 ExitOnFailure(hr, "Failed to execute package provider action."); 3467 ExitOnFailure(hr, "Failed to execute package provider action.");
@@ -3479,6 +3500,8 @@ static HRESULT OnExecutePackageDependencyAction(
3479 } 3500 }
3480 ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); 3501 ExitOnFailure(hr, "Failed to find package: %ls", sczPackage);
3481 3502
3503 executeAction.packageDependency.pPackage->fPerMachine = TRUE;
3504
3482 hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&fRollback); 3505 hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&fRollback);
3483 ExitOnFailure(hr, "Failed to read rollback flag."); 3506 ExitOnFailure(hr, "Failed to read rollback flag.");
3484 3507
@@ -3784,6 +3807,8 @@ static HRESULT OnCleanCompatiblePackage(
3784 hr = PackageFindById(pPackages, sczPackageId, &pPackage); 3807 hr = PackageFindById(pPackages, sczPackageId, &pPackage);
3785 ExitOnFailure(hr, "Failed to find package: %ls", sczPackageId); 3808 ExitOnFailure(hr, "Failed to find package: %ls", sczPackageId);
3786 3809
3810 pPackage->fPerMachine = TRUE;
3811
3787 pCompatiblePackage = &pPackage->compatiblePackage; 3812 pCompatiblePackage = &pPackage->compatiblePackage;
3788 3813
3789 if (!pCompatiblePackage->fDetected || !pCompatiblePackage->compatibleEntry.sczId || !pCompatiblePackage->sczCacheId || !*pCompatiblePackage->sczCacheId) 3814 if (!pCompatiblePackage->fDetected || !pCompatiblePackage->compatibleEntry.sczId || !pCompatiblePackage->sczCacheId || !*pCompatiblePackage->sczCacheId)
@@ -3826,6 +3851,8 @@ static HRESULT OnCleanPackage(
3826 hr = PackageFindById(pPackages, sczPackage, &pPackage); 3851 hr = PackageFindById(pPackages, sczPackage, &pPackage);
3827 ExitOnFailure(hr, "Failed to find package: %ls", sczPackage); 3852 ExitOnFailure(hr, "Failed to find package: %ls", sczPackage);
3828 3853
3854 pPackage->fPerMachine = TRUE;
3855
3829 // Remove the package from the cache. 3856 // Remove the package from the cache.
3830 hr = CacheRemovePackage(pCache, TRUE, pPackage->sczId, pPackage->sczCacheId); 3857 hr = CacheRemovePackage(pCache, TRUE, pPackage->sczId, pPackage->sczCacheId);
3831 ExitOnFailure(hr, "Failed to remove from cache package: %ls", pPackage->sczId); 3858 ExitOnFailure(hr, "Failed to remove from cache package: %ls", pPackage->sczId);
diff --git a/src/burn/engine/engine.cpp b/src/burn/engine/engine.cpp
index d432f732..8423da41 100644
--- a/src/burn/engine/engine.cpp
+++ b/src/burn/engine/engine.cpp
@@ -16,11 +16,6 @@ static HRESULT InitializeEngineState(
16static void UninitializeEngineState( 16static void UninitializeEngineState(
17 __in BURN_ENGINE_STATE* pEngineState 17 __in BURN_ENGINE_STATE* pEngineState
18 ); 18 );
19#if 0
20static HRESULT RunUntrusted(
21 __in BURN_ENGINE_STATE* pEngineState
22 );
23#endif
24static HRESULT RunNormal( 19static HRESULT RunNormal(
25 __in HINSTANCE hInstance, 20 __in HINSTANCE hInstance,
26 __in BURN_ENGINE_STATE* pEngineState 21 __in BURN_ENGINE_STATE* pEngineState
@@ -812,7 +807,7 @@ static HRESULT ProcessMessage(
812 break; 807 break;
813 808
814 case WM_BURN_PLAN: 809 case WM_BURN_PLAN:
815 hr = CorePlan(pEngineState, pAction->plan.action); 810 hr = CorePlan(pEngineState, pAction->plan.action, pAction->plan.plannedScope);
816 break; 811 break;
817 812
818 case WM_BURN_ELEVATE: 813 case WM_BURN_ELEVATE:
diff --git a/src/burn/engine/engine.mc b/src/burn/engine/engine.mc
index 776f7832..8e2f1a2e 100644
--- a/src/burn/engine/engine.mc
+++ b/src/burn/engine/engine.mc
@@ -271,7 +271,7 @@ MessageId=101
271Severity=Success 271Severity=Success
272SymbolicName=MSG_DETECTED_PACKAGE 272SymbolicName=MSG_DETECTED_PACKAGE
273Language=English 273Language=English
274Detected package: %1!ls!, state: %2!hs!, cached: %3!hs!, install registration state: %4!hs!, cache registration state: %5!hs! 274Detected package: %1!ls!, state: %2!hs!, authored scope: %6!hs!, cached: %3!hs!, install registration state: %4!hs!, cache registration state: %5!hs!
275. 275.
276 276
277MessageId=102 277MessageId=102
@@ -404,14 +404,21 @@ MessageId=200
404Severity=Success 404Severity=Success
405SymbolicName=MSG_PLAN_BEGIN 405SymbolicName=MSG_PLAN_BEGIN
406Language=English 406Language=English
407Plan begin, %1!u! packages, action: %2!hs! 407Plan begin, %1!u! packages, action: %2!hs!, planned scope: %3!hs!
408.
409
410MessageId=226
411Severity=Success
412SymbolicName=MSG_PLAN_CONFIGURED_SCOPE
413Language=English
414Planned configurable scope: %1!hs!
408. 415.
409 416
410MessageId=201 417MessageId=201
411Severity=Success 418Severity=Success
412SymbolicName=MSG_PLANNED_PACKAGE 419SymbolicName=MSG_PLANNED_PACKAGE
413Language=English 420Language=English
414Planned package: %1!ls!, state: %2!hs!, default requested: %3!hs!, ba requested: %4!hs!, execute: %5!hs!, rollback: %6!hs!, default cache strategy: %7!hs!, ba requested strategy: %8!hs!, cache: %9!hs!, uncache: %10!hs!, dependency: %11!hs!, expected install registration state: %12!hs!, expected cache registration state: %13!hs! 421Planned package: %1!ls!, state: %2!hs!, default requested: %3!hs!, ba requested: %4!hs!, execute: %5!hs!, rollback: %6!hs!, scope: %14!hs!, default cache strategy: %7!hs!, ba requested strategy: %8!hs!, cache: %9!hs!, uncache: %10!hs!, dependency: %11!hs!, expected install registration state: %12!hs!, expected cache registration state: %13!hs!
415. 422.
416 423
417MessageId=203 424MessageId=203
@@ -782,7 +789,7 @@ MessageId=328
782Severity=Warning 789Severity=Warning
783SymbolicName=MSG_DEPENDENCY_PACKAGE_DEPENDENT 790SymbolicName=MSG_DEPENDENCY_PACKAGE_DEPENDENT
784Language=English 791Language=English
785Found dependent: %1!ls!, name: %2!ls! 792 Found dependent: %1!ls!, name: %2!ls!
786. 793.
787 794
788MessageId=329 795MessageId=329
@@ -1288,3 +1295,17 @@ SymbolicName=MSG_DEPENDENCY_PACKAGE_DEPENDENTS_OVERRIDDEN
1288Language=English 1295Language=English
1289BA requested to uninstall package: %1!ls!, despite dependents: 1296BA requested to uninstall package: %1!ls!, despite dependents:
1290. 1297.
1298MessageId=702
1299Severity=Warning
1300SymbolicName=MSG_SCOPE_IGNORED_BA_SCOPE
1301Language=English
1302Scope command-line switch ignored because the bootstrapper application already specified a scope.
1303.
1304
1305MessageId=703
1306Severity=Warning
1307SymbolicName=MSG_SCOPE_IGNORED_UNCONFIGURABLE
1308Language=English
1309Scope command-line switch ignored because the bundle doesn't have any packages with configurable scope.
1310.
1311
diff --git a/src/burn/engine/engine.vcxproj b/src/burn/engine/engine.vcxproj
index 98556ea6..5ab9f1ce 100644
--- a/src/burn/engine/engine.vcxproj
+++ b/src/burn/engine/engine.vcxproj
@@ -1,6 +1,5 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> 2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 3<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
5 <ItemGroup Label="ProjectConfigurations"> 4 <ItemGroup Label="ProjectConfigurations">
6 <ProjectConfiguration Include="Debug|Win32"> 5 <ProjectConfiguration Include="Debug|Win32">
@@ -28,7 +27,6 @@
28 <Platform>ARM64</Platform> 27 <Platform>ARM64</Platform>
29 </ProjectConfiguration> 28 </ProjectConfiguration>
30 </ItemGroup> 29 </ItemGroup>
31
32 <PropertyGroup Label="Globals"> 30 <PropertyGroup Label="Globals">
33 <ProjectGuid>{8119537D-E1D9-6591-D51A-49768A2F9C37}</ProjectGuid> 31 <ProjectGuid>{8119537D-E1D9-6591-D51A-49768A2F9C37}</ProjectGuid>
34 <ConfigurationType>StaticLibrary</ConfigurationType> 32 <ConfigurationType>StaticLibrary</ConfigurationType>
@@ -37,20 +35,15 @@
37 <Description>Native component of WixToolset.Burn</Description> 35 <Description>Native component of WixToolset.Burn</Description>
38 <CustomBuildBeforeTargets>ClCompile</CustomBuildBeforeTargets> 36 <CustomBuildBeforeTargets>ClCompile</CustomBuildBeforeTargets>
39 </PropertyGroup> 37 </PropertyGroup>
40
41 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> 38 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
42 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> 39 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
43
44 <PropertyGroup> 40 <PropertyGroup>
45 <ProjectAdditionalIncludeDirectories>..\..\api\burn\inc;$(BurnGeneratedHeaderDirectory);$(ProjectAdditionalIncludeDirectories)</ProjectAdditionalIncludeDirectories> 41 <ProjectAdditionalIncludeDirectories>..\..\api\burn\inc;$(BurnGeneratedHeaderDirectory);$(ProjectAdditionalIncludeDirectories)</ProjectAdditionalIncludeDirectories>
46 </PropertyGroup> 42 </PropertyGroup>
47
48 <ImportGroup Label="ExtensionSettings"> 43 <ImportGroup Label="ExtensionSettings">
49 </ImportGroup> 44 </ImportGroup>
50
51 <ImportGroup Label="Shared"> 45 <ImportGroup Label="Shared">
52 </ImportGroup> 46 </ImportGroup>
53
54 <ItemGroup> 47 <ItemGroup>
55 <ClCompile Include="apply.cpp" /> 48 <ClCompile Include="apply.cpp" />
56 <ClCompile Include="approvedexe.cpp" /> 49 <ClCompile Include="approvedexe.cpp" />
@@ -97,7 +90,6 @@
97 <ClCompile Include="variable.cpp" /> 90 <ClCompile Include="variable.cpp" />
98 <ClCompile Include="variant.cpp" /> 91 <ClCompile Include="variant.cpp" />
99 </ItemGroup> 92 </ItemGroup>
100
101 <ItemGroup> 93 <ItemGroup>
102 <ClInclude Include="apply.h" /> 94 <ClInclude Include="apply.h" />
103 <ClInclude Include="approvedexe.h" /> 95 <ClInclude Include="approvedexe.h" />
@@ -147,7 +139,6 @@
147 <ClInclude Include="variable.h" /> 139 <ClInclude Include="variable.h" />
148 <ClInclude Include="variant.h" /> 140 <ClInclude Include="variant.h" />
149 </ItemGroup> 141 </ItemGroup>
150
151 <ItemDefinitionGroup> 142 <ItemDefinitionGroup>
152 <CustomBuildStep> 143 <CustomBuildStep>
153 <Message>Compiling message file...</Message> 144 <Message>Compiling message file...</Message>
@@ -157,7 +148,6 @@ rc.exe -fo "$(OutDir)engine.res" "$(IntDir)engine.messages.rc"</Command>
157 <Outputs>$(IntDir)engine.messages.h;$(IntDir)engine.messages.rc</Outputs> 148 <Outputs>$(IntDir)engine.messages.h;$(IntDir)engine.messages.rc</Outputs>
158 </CustomBuildStep> 149 </CustomBuildStep>
159 </ItemDefinitionGroup> 150 </ItemDefinitionGroup>
160
161 <Target Name="SetWixVersion" BeforeTargets="ClCompile"> 151 <Target Name="SetWixVersion" BeforeTargets="ClCompile">
162 <PropertyGroup> 152 <PropertyGroup>
163 <rmj>$(SomeVerInfoMajor)</rmj> 153 <rmj>$(SomeVerInfoMajor)</rmj>
@@ -172,11 +162,12 @@ rc.exe -fo "$(OutDir)engine.res" "$(IntDir)engine.messages.rc"</Command>
172 </ItemGroup> 162 </ItemGroup>
173 <WriteLinesToFile Overwrite="true" File="$(BurnGeneratedHeaderDirectory)engine.version.h" Lines="@(BurnVersionLines)" /> 163 <WriteLinesToFile Overwrite="true" File="$(BurnGeneratedHeaderDirectory)engine.version.h" Lines="@(BurnVersionLines)" />
174 </Target> 164 </Target>
175
176 <ItemGroup> 165 <ItemGroup>
177 <PackageReference Include="WixToolset.DUtil" /> 166 <PackageReference Include="WixToolset.DUtil" />
178 <PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" /> 167 <PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />
179 </ItemGroup> 168 </ItemGroup>
180 169 <ItemGroup>
170 <None Include="engine.mc" />
171 </ItemGroup>
181 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> 172 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
182</Project> 173</Project> \ No newline at end of file
diff --git a/src/burn/engine/externalengine.cpp b/src/burn/engine/externalengine.cpp
index 352d184c..d4814dc1 100644
--- a/src/burn/engine/externalengine.cpp
+++ b/src/burn/engine/externalengine.cpp
@@ -633,8 +633,9 @@ LExit:
633 633
634HRESULT ExternalEnginePlan( 634HRESULT ExternalEnginePlan(
635 __in BAENGINE_CONTEXT* pEngineContext, 635 __in BAENGINE_CONTEXT* pEngineContext,
636 __in const BOOTSTRAPPER_ACTION action 636 __in const BOOTSTRAPPER_ACTION action,
637 ) 637 __in const BOOTSTRAPPER_SCOPE plannedScope
638)
638{ 639{
639 HRESULT hr = S_OK; 640 HRESULT hr = S_OK;
640 BAENGINE_ACTION* pAction = NULL; 641 BAENGINE_ACTION* pAction = NULL;
@@ -649,6 +650,7 @@ HRESULT ExternalEnginePlan(
649 650
650 pAction->dwMessage = WM_BURN_PLAN; 651 pAction->dwMessage = WM_BURN_PLAN;
651 pAction->plan.action = action; 652 pAction->plan.action = action;
653 pAction->plan.plannedScope = plannedScope;
652 654
653 hr = EnqueueAction(pEngineContext, &pAction); 655 hr = EnqueueAction(pEngineContext, &pAction);
654 ExitOnFailure(hr, "Failed to enqueue plan action."); 656 ExitOnFailure(hr, "Failed to enqueue plan action.");
diff --git a/src/burn/engine/externalengine.h b/src/burn/engine/externalengine.h
index 9b95e645..1053d0c0 100644
--- a/src/burn/engine/externalengine.h
+++ b/src/burn/engine/externalengine.h
@@ -146,8 +146,9 @@ HRESULT ExternalEngineDetect(
146 146
147HRESULT ExternalEnginePlan( 147HRESULT ExternalEnginePlan(
148 __in BAENGINE_CONTEXT* pEngineContext, 148 __in BAENGINE_CONTEXT* pEngineContext,
149 __in const BOOTSTRAPPER_ACTION action 149 __in const BOOTSTRAPPER_ACTION action,
150 ); 150 __in const BOOTSTRAPPER_SCOPE plannedScope
151);
151 152
152HRESULT ExternalEngineElevate( 153HRESULT ExternalEngineElevate(
153 __in BAENGINE_CONTEXT* pEngineContext, 154 __in BAENGINE_CONTEXT* pEngineContext,
diff --git a/src/burn/engine/logging.cpp b/src/burn/engine/logging.cpp
index 52123499..47f52d27 100644
--- a/src/burn/engine/logging.cpp
+++ b/src/burn/engine/logging.cpp
@@ -968,6 +968,42 @@ extern "C" LPCSTR LoggingInstallScopeToString(
968 return fPerMachine ? "PerMachine" : "PerUser"; 968 return fPerMachine ? "PerMachine" : "PerUser";
969} 969}
970 970
971extern "C" LPCSTR LoggingPackageScopeToString(
972 __in BOOTSTRAPPER_PACKAGE_SCOPE scope
973 )
974{
975 switch (scope)
976 {
977 case BOOTSTRAPPER_PACKAGE_SCOPE_PER_MACHINE:
978 return "PerMachine";
979 case BOOTSTRAPPER_PACKAGE_SCOPE_PER_MACHINE_OR_PER_USER:
980 return "PerMachineOrUser";
981 case BOOTSTRAPPER_PACKAGE_SCOPE_PER_USER_OR_PER_MACHINE:
982 return "PerUserOrMachine";
983 case BOOTSTRAPPER_PACKAGE_SCOPE_PER_USER:
984 return "PerUser";
985 default:
986 return "Invalid";
987 }
988}
989
990extern "C" LPCSTR LoggingBundleScopeToString(
991 __in BOOTSTRAPPER_SCOPE scope
992 )
993{
994 switch (scope)
995 {
996 case BOOTSTRAPPER_SCOPE_DEFAULT:
997 return "Default";
998 case BOOTSTRAPPER_SCOPE_PER_MACHINE:
999 return "PerMachine";
1000 case BOOTSTRAPPER_SCOPE_PER_USER:
1001 return "PerUser";
1002 default:
1003 return "Invalid";
1004 }
1005}
1006
971 1007
972// internal function declarations 1008// internal function declarations
973 1009
diff --git a/src/burn/engine/logging.h b/src/burn/engine/logging.h
index b28a53d4..76103732 100644
--- a/src/burn/engine/logging.h
+++ b/src/burn/engine/logging.h
@@ -202,6 +202,13 @@ LPCSTR LoggingInstallScopeToString(
202 __in BOOL fPerMachine 202 __in BOOL fPerMachine
203 ); 203 );
204 204
205LPCSTR LoggingPackageScopeToString(
206 __in BOOTSTRAPPER_PACKAGE_SCOPE scope
207 );
208
209LPCSTR LoggingBundleScopeToString(
210 __in BOOTSTRAPPER_SCOPE scope
211 );
205 212
206#if defined(__cplusplus) 213#if defined(__cplusplus)
207} 214}
diff --git a/src/burn/engine/msiengine.cpp b/src/burn/engine/msiengine.cpp
index a1379054..11bb8a0e 100644
--- a/src/burn/engine/msiengine.cpp
+++ b/src/burn/engine/msiengine.cpp
@@ -454,7 +454,18 @@ extern "C" HRESULT MsiEngineDetectPackage(
454 454
455 // detect self by product code 455 // detect self by product code
456 // TODO: what to do about MSIINSTALLCONTEXT_USERMANAGED? 456 // TODO: what to do about MSIINSTALLCONTEXT_USERMANAGED?
457 hr = WiuGetProductInfoEx(pPackage->Msi.sczProductCode, NULL, pPackage->fPerMachine ? MSIINSTALLCONTEXT_MACHINE : MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONSTRING, &sczInstalledVersion); 457 if (BOOTSTRAPPER_PACKAGE_SCOPE_PER_MACHINE_OR_PER_USER == pPackage->scope || BOOTSTRAPPER_PACKAGE_SCOPE_PER_USER_OR_PER_MACHINE == pPackage->scope)
458 {
459 hr = WiuGetProductInfoEx(pPackage->Msi.sczProductCode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_VERSIONSTRING, &sczInstalledVersion);
460 if (FAILED(hr))
461 {
462 hr = WiuGetProductInfoEx(pPackage->Msi.sczProductCode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONSTRING, &sczInstalledVersion);
463 }
464 }
465 else
466 {
467 hr = WiuGetProductInfoEx(pPackage->Msi.sczProductCode, NULL, pPackage->scope == BOOTSTRAPPER_PACKAGE_SCOPE_PER_MACHINE ? MSIINSTALLCONTEXT_MACHINE : MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONSTRING, &sczInstalledVersion);
468 }
458 if (SUCCEEDED(hr)) 469 if (SUCCEEDED(hr))
459 { 470 {
460 fDetectFeatures = TRUE; 471 fDetectFeatures = TRUE;
@@ -777,7 +788,18 @@ extern "C" HRESULT MsiEngineDetectCompatiblePackage(
777 ExitFunction(); 788 ExitFunction();
778 } 789 }
779 790
780 hr = WiuGetProductInfoEx(wzCompatibleProductCode, NULL, pPackage->fPerMachine ? MSIINSTALLCONTEXT_MACHINE : MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONSTRING, &sczVersion); 791 if (BOOTSTRAPPER_PACKAGE_SCOPE_PER_MACHINE_OR_PER_USER == pPackage->scope || BOOTSTRAPPER_PACKAGE_SCOPE_PER_USER_OR_PER_MACHINE == pPackage->scope)
792 {
793 hr = WiuGetProductInfoEx(wzCompatibleProductCode, NULL, MSIINSTALLCONTEXT_MACHINE, INSTALLPROPERTY_VERSIONSTRING, &sczVersion);
794 if (FAILED(hr))
795 {
796 hr = WiuGetProductInfoEx(wzCompatibleProductCode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONSTRING, &sczVersion);
797 }
798 }
799 else
800 {
801 hr = WiuGetProductInfoEx(wzCompatibleProductCode, NULL, pPackage->scope == BOOTSTRAPPER_PACKAGE_SCOPE_PER_MACHINE ? MSIINSTALLCONTEXT_MACHINE : MSIINSTALLCONTEXT_USERUNMANAGED, INSTALLPROPERTY_VERSIONSTRING, &sczVersion);
802 }
781 if (HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT) == hr || HRESULT_FROM_WIN32(ERROR_UNKNOWN_PROPERTY) == hr || E_INVALIDARG == hr) 803 if (HRESULT_FROM_WIN32(ERROR_UNKNOWN_PRODUCT) == hr || HRESULT_FROM_WIN32(ERROR_UNKNOWN_PROPERTY) == hr || E_INVALIDARG == hr)
782 { 804 {
783 ExitFunction1(hr = S_OK); 805 ExitFunction1(hr = S_OK);
@@ -1336,10 +1358,10 @@ extern "C" HRESULT MsiEngineExecutePackage(
1336 hr = ConcatPatchProperty(pCache, pPackage, fRollback, &sczObfuscatedProperties); 1358 hr = ConcatPatchProperty(pCache, pPackage, fRollback, &sczObfuscatedProperties);
1337 ExitOnFailure(hr, "Failed to add patch properties to obfuscated argument string."); 1359 ExitOnFailure(hr, "Failed to add patch properties to obfuscated argument string.");
1338 1360
1339 hr = MsiEngineConcatBurnProperties(pExecuteAction->msiPackage.action, pExecuteAction->msiPackage.actionMsiProperty, pExecuteAction->msiPackage.fileVersioning, TRUE, 0 != pPackage->Msi.cFeatures, &sczProperties); 1361 hr = MsiEngineConcatBurnProperties(pExecuteAction->msiPackage.action, pExecuteAction->msiPackage.actionMsiProperty, pExecuteAction->msiPackage.fileVersioning, TRUE, 0 != pPackage->Msi.cFeatures, pExecuteAction->msiPackage.pPackage->scope, pExecuteAction->msiPackage.pPackage->fPerMachine, &sczProperties);
1340 ExitOnFailure(hr, "Failed to add action property to argument string."); 1362 ExitOnFailure(hr, "Failed to add action property to argument string.");
1341 1363
1342 hr = MsiEngineConcatBurnProperties(pExecuteAction->msiPackage.action, pExecuteAction->msiPackage.actionMsiProperty, pExecuteAction->msiPackage.fileVersioning, TRUE, 0 != pPackage->Msi.cFeatures, &sczObfuscatedProperties); 1364 hr = MsiEngineConcatBurnProperties(pExecuteAction->msiPackage.action, pExecuteAction->msiPackage.actionMsiProperty, pExecuteAction->msiPackage.fileVersioning, TRUE, 0 != pPackage->Msi.cFeatures, pPackage->scope, pPackage->fPerMachine, &sczObfuscatedProperties);
1343 ExitOnFailure(hr, "Failed to add action property to obfuscated argument string."); 1365 ExitOnFailure(hr, "Failed to add action property to obfuscated argument string.");
1344 1366
1345 LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(pExecuteAction->msiPackage.action), sczMsiPath, sczObfuscatedProperties ? sczObfuscatedProperties : L""); 1367 LogId(REPORT_STANDARD, MSG_APPLYING_PACKAGE, LoggingRollbackOrExecute(fRollback), pPackage->sczId, LoggingActionStateToString(pExecuteAction->msiPackage.action), sczMsiPath, sczObfuscatedProperties ? sczObfuscatedProperties : L"");
@@ -1449,7 +1471,7 @@ extern "C" HRESULT MsiEngineUninstallCompatiblePackage(
1449 ExitOnFailure(hr, "Failed to enable logging for compatible package: %ls to: %ls", pCompatibleEntry->sczId, pExecuteAction->uninstallMsiCompatiblePackage.sczLogPath); 1471 ExitOnFailure(hr, "Failed to enable logging for compatible package: %ls to: %ls", pCompatibleEntry->sczId, pExecuteAction->uninstallMsiCompatiblePackage.sczLogPath);
1450 } 1472 }
1451 1473
1452 hr = MsiEngineConcatBurnProperties(action, burnMsiProperty, fileVersioning, TRUE, FALSE, &sczProperties); 1474 hr = MsiEngineConcatBurnProperties(action, burnMsiProperty, fileVersioning, TRUE, FALSE, pParentPackage->scope, pParentPackage->fPerMachine, &sczProperties);
1453 ExitOnFailure(hr, "Failed to add action property to argument string."); 1475 ExitOnFailure(hr, "Failed to add action property to argument string.");
1454 1476
1455 LogId(REPORT_STANDARD, MSG_APPLYING_ORPHAN_COMPATIBLE_PACKAGE, LoggingRollbackOrExecute(fRollback), pCompatibleEntry->sczId, pParentPackage->sczId, LoggingActionStateToString(action), sczProperties ? sczProperties : L""); 1477 LogId(REPORT_STANDARD, MSG_APPLYING_ORPHAN_COMPATIBLE_PACKAGE, LoggingRollbackOrExecute(fRollback), pCompatibleEntry->sczId, pParentPackage->sczId, LoggingActionStateToString(action), sczProperties ? sczProperties : L"");
@@ -1491,6 +1513,8 @@ extern "C" HRESULT MsiEngineConcatBurnProperties(
1491 __in BOOTSTRAPPER_MSI_FILE_VERSIONING fileVersioning, 1513 __in BOOTSTRAPPER_MSI_FILE_VERSIONING fileVersioning,
1492 __in BOOL fMsiPackage, 1514 __in BOOL fMsiPackage,
1493 __in BOOL fFeatureSelectionEnabled, 1515 __in BOOL fFeatureSelectionEnabled,
1516 __in BOOTSTRAPPER_PACKAGE_SCOPE scope,
1517 __in BOOL fPlannedPerMachineScope,
1494 __deref_out_z LPWSTR* psczProperties 1518 __deref_out_z LPWSTR* psczProperties
1495 ) 1519 )
1496{ 1520{
@@ -1534,6 +1558,7 @@ extern "C" HRESULT MsiEngineConcatBurnProperties(
1534 break; 1558 break;
1535 } 1559 }
1536 1560
1561 // Append properties used by WixUI (and usable otherwise) to adjust internal UI behavior.
1537 switch (actionMsiProperty) 1562 switch (actionMsiProperty)
1538 { 1563 {
1539 case BURN_MSI_PROPERTY_INSTALL: 1564 case BURN_MSI_PROPERTY_INSTALL:
@@ -1581,6 +1606,20 @@ extern "C" HRESULT MsiEngineConcatBurnProperties(
1581 ExitOnFailure(hr, "Failed to add reinstall mode."); 1606 ExitOnFailure(hr, "Failed to add reinstall mode.");
1582 } 1607 }
1583 1608
1609 if (BOOTSTRAPPER_PACKAGE_SCOPE_PER_USER_OR_PER_MACHINE == scope || BOOTSTRAPPER_PACKAGE_SCOPE_PER_MACHINE_OR_PER_USER == scope)
1610 {
1611 if (fPlannedPerMachineScope)
1612 {
1613 hr = StrAllocConcatFormattedSecure(psczProperties, L" MSIINSTALLPERUSER=\"\"");
1614 ExitOnFailure(hr, "Failed to add per-machine scope properties.");
1615 }
1616 else
1617 {
1618 hr = StrAllocConcatFormattedSecure(psczProperties, L" MSIINSTALLPERUSER=\"1\"");
1619 ExitOnFailure(hr, "Failed to add per-user scope properties.");
1620 }
1621 }
1622
1584 hr = StrAllocConcatSecure(psczProperties, L" REBOOT=ReallySuppress", 0); 1623 hr = StrAllocConcatSecure(psczProperties, L" REBOOT=ReallySuppress", 0);
1585 ExitOnFailure(hr, "Failed to add reboot suppression property."); 1624 ExitOnFailure(hr, "Failed to add reboot suppression property.");
1586 1625
diff --git a/src/burn/engine/msiengine.h b/src/burn/engine/msiengine.h
index 862c4f6a..d4660dc8 100644
--- a/src/burn/engine/msiengine.h
+++ b/src/burn/engine/msiengine.h
@@ -93,6 +93,8 @@ HRESULT MsiEngineConcatBurnProperties(
93 __in BOOTSTRAPPER_MSI_FILE_VERSIONING fileVersioning, 93 __in BOOTSTRAPPER_MSI_FILE_VERSIONING fileVersioning,
94 __in BOOL fMsiPackage, 94 __in BOOL fMsiPackage,
95 __in BOOL fFeatureSelectionEnabled, 95 __in BOOL fFeatureSelectionEnabled,
96 __in BOOTSTRAPPER_PACKAGE_SCOPE scope,
97 __in BOOL fPlannedPerMachineScope,
96 __deref_out_z LPWSTR* psczProperties 98 __deref_out_z LPWSTR* psczProperties
97 ); 99 );
98HRESULT MsiEngineConcatPackageProperties( 100HRESULT MsiEngineConcatPackageProperties(
diff --git a/src/burn/engine/mspengine.cpp b/src/burn/engine/mspengine.cpp
index e8ef7fcb..18be3cc6 100644
--- a/src/burn/engine/mspengine.cpp
+++ b/src/burn/engine/mspengine.cpp
@@ -676,10 +676,10 @@ extern "C" HRESULT MspEngineExecutePackage(
676 } 676 }
677 677
678 // Always add Burn properties last. 678 // Always add Burn properties last.
679 hr = MsiEngineConcatBurnProperties(pExecuteAction->mspTarget.action, pExecuteAction->mspTarget.actionMsiProperty, pExecuteAction->mspTarget.fileVersioning, FALSE, FALSE, &sczProperties); 679 hr = MsiEngineConcatBurnProperties(pExecuteAction->mspTarget.action, pExecuteAction->mspTarget.actionMsiProperty, pExecuteAction->mspTarget.fileVersioning, FALSE, FALSE, pExecuteAction->mspTarget.pPackage->scope, pExecuteAction->mspTarget.pPackage->fPerMachine, &sczProperties);
680 ExitOnFailure(hr, "Failed to add action property to argument string."); 680 ExitOnFailure(hr, "Failed to add action property to argument string.");
681 681
682 hr = MsiEngineConcatBurnProperties(pExecuteAction->mspTarget.action, pExecuteAction->mspTarget.actionMsiProperty, pExecuteAction->mspTarget.fileVersioning, FALSE, FALSE, &sczObfuscatedProperties); 682 hr = MsiEngineConcatBurnProperties(pExecuteAction->mspTarget.action, pExecuteAction->mspTarget.actionMsiProperty, pExecuteAction->mspTarget.fileVersioning, FALSE, FALSE, pExecuteAction->mspTarget.pPackage->scope, pExecuteAction->mspTarget.pPackage->fPerMachine, &sczObfuscatedProperties);
683 ExitOnFailure(hr, "Failed to add action property to obfuscated argument string."); 683 ExitOnFailure(hr, "Failed to add action property to obfuscated argument string.");
684 684
685 LogId(REPORT_STANDARD, MSG_APPLYING_PATCH_PACKAGE, pExecuteAction->mspTarget.pPackage->sczId, LoggingActionStateToString(pExecuteAction->mspTarget.action), sczPatches, sczObfuscatedProperties, pExecuteAction->mspTarget.sczTargetProductCode); 685 LogId(REPORT_STANDARD, MSG_APPLYING_PATCH_PACKAGE, pExecuteAction->mspTarget.pPackage->sczId, LoggingActionStateToString(pExecuteAction->mspTarget.action), sczPatches, sczObfuscatedProperties, pExecuteAction->mspTarget.sczTargetProductCode);
diff --git a/src/burn/engine/package.cpp b/src/burn/engine/package.cpp
index 3bf676ba..61b73dc6 100644
--- a/src/burn/engine/package.cpp
+++ b/src/burn/engine/package.cpp
@@ -154,9 +154,12 @@ extern "C" HRESULT PackagesParseFromXml(
154 hr = XmlGetAttributeUInt64(pixnNode, L"InstallSize", &pPackage->qwInstallSize); 154 hr = XmlGetAttributeUInt64(pixnNode, L"InstallSize", &pPackage->qwInstallSize);
155 ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @InstallSize."); 155 ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @InstallSize.");
156 156
157 // @PerMachine 157 // @Scope
158 hr = XmlGetYesNoAttribute(pixnNode, L"PerMachine", &pPackage->fPerMachine); 158 hr = PackageParseScopeFromXml(pixnNode, &pPackage->scope);
159 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @PerMachine."); 159 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Scope.");
160
161 // Shortcut for static per-machine or per-user packages.
162 pPackage->fPerMachine = BOOTSTRAPPER_PACKAGE_SCOPE_PER_MACHINE == pPackage->scope;
160 163
161 // @Permanent 164 // @Permanent
162 hr = XmlGetYesNoAttribute(pixnNode, L"Permanent", &pPackage->fPermanent); 165 hr = XmlGetYesNoAttribute(pixnNode, L"Permanent", &pPackage->fPermanent);
@@ -593,6 +596,45 @@ LExit:
593 return hr; 596 return hr;
594} 597}
595 598
599extern "C" HRESULT PackageParseScopeFromXml(
600 __in IXMLDOMNode* pixn,
601 __in BOOTSTRAPPER_PACKAGE_SCOPE* pScope
602)
603{
604 HRESULT hr = S_OK;
605 LPWSTR scz = NULL;
606
607 hr = XmlGetAttributeEx(pixn, L"Scope", &scz);
608 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Scope.");
609
610 if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, scz, -1, L"perMachine", -1))
611 {
612 *pScope = BOOTSTRAPPER_PACKAGE_SCOPE_PER_MACHINE;
613 }
614 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, scz, -1, L"perUser", -1))
615 {
616 *pScope = BOOTSTRAPPER_PACKAGE_SCOPE_PER_USER;
617 }
618 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, scz, -1, L"perUserOrMachine", -1))
619 {
620 *pScope = BOOTSTRAPPER_PACKAGE_SCOPE_PER_USER_OR_PER_MACHINE;
621 }
622 else if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, scz, -1, L"perMachineOrUser", -1))
623 {
624 *pScope = BOOTSTRAPPER_PACKAGE_SCOPE_PER_MACHINE_OR_PER_USER;
625 }
626 else
627 {
628 hr = E_UNEXPECTED;
629 ExitOnRootFailure(hr, "Invalid scope: %ls", scz);
630 }
631
632LExit:
633 ReleaseStr(scz);
634
635 return hr;
636}
637
596 638
597// internal function declarations 639// internal function declarations
598 640
diff --git a/src/burn/engine/package.h b/src/burn/engine/package.h
index d596d7c0..5397e9cc 100644
--- a/src/burn/engine/package.h
+++ b/src/burn/engine/package.h
@@ -268,7 +268,8 @@ typedef struct _BURN_PACKAGE
268 268
269 LPWSTR sczInstallCondition; 269 LPWSTR sczInstallCondition;
270 LPWSTR sczRepairCondition; 270 LPWSTR sczRepairCondition;
271 BOOL fPerMachine; 271 BOOTSTRAPPER_PACKAGE_SCOPE scope;
272 BOOL fPerMachine; // only valid after Plan (for PUOM/PMOU packages).
272 BOOL fPermanent; 273 BOOL fPermanent;
273 BOOL fVital; 274 BOOL fVital;
274 BOOL fCanAffectRegistration; 275 BOOL fCanAffectRegistration;
@@ -483,6 +484,10 @@ HRESULT PackageFindRollbackBoundaryById(
483 __in_z LPCWSTR wzId, 484 __in_z LPCWSTR wzId,
484 __out BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary 485 __out BURN_ROLLBACK_BOUNDARY** ppRollbackBoundary
485 ); 486 );
487HRESULT PackageParseScopeFromXml(
488 __in IXMLDOMNode* pixn,
489 __in BOOTSTRAPPER_PACKAGE_SCOPE* pScope
490 );
486 491
487 492
488#if defined(__cplusplus) 493#if defined(__cplusplus)
diff --git a/src/burn/engine/plan.cpp b/src/burn/engine/plan.cpp
index edc09033..6c46269b 100644
--- a/src/burn/engine/plan.cpp
+++ b/src/burn/engine/plan.cpp
@@ -278,7 +278,7 @@ extern "C" void PlanReset(
278 } 278 }
279 } 279 }
280 280
281 PlanSetVariables(BOOTSTRAPPER_ACTION_UNKNOWN, pVariables); 281 PlanSetVariables(BOOTSTRAPPER_ACTION_UNKNOWN, BOOTSTRAPPER_PACKAGE_SCOPE_INVALID, BOOTSTRAPPER_SCOPE_DEFAULT, pVariables);
282} 282}
283 283
284extern "C" void PlanUninitializeExecuteAction( 284extern "C" void PlanUninitializeExecuteAction(
@@ -332,6 +332,8 @@ extern "C" void PlanUninitializeExecuteAction(
332 332
333extern "C" HRESULT PlanSetVariables( 333extern "C" HRESULT PlanSetVariables(
334 __in BOOTSTRAPPER_ACTION action, 334 __in BOOTSTRAPPER_ACTION action,
335 __in BOOTSTRAPPER_PACKAGE_SCOPE authoredScope,
336 __in BOOTSTRAPPER_SCOPE plannedScope,
335 __in BURN_VARIABLES* pVariables 337 __in BURN_VARIABLES* pVariables
336 ) 338 )
337{ 339{
@@ -340,6 +342,12 @@ extern "C" HRESULT PlanSetVariables(
340 hr = VariableSetNumeric(pVariables, BURN_BUNDLE_ACTION, action, TRUE); 342 hr = VariableSetNumeric(pVariables, BURN_BUNDLE_ACTION, action, TRUE);
341 ExitOnFailure(hr, "Failed to set the bundle action built-in variable."); 343 ExitOnFailure(hr, "Failed to set the bundle action built-in variable.");
342 344
345 hr = VariableSetNumeric(pVariables, BURN_BUNDLE_SCOPE, authoredScope, TRUE);
346 ExitOnFailure(hr, "Failed to set the bundle authored scope built-in variable.");
347
348 hr = VariableSetNumeric(pVariables, BURN_BUNDLE_PLANNED_SCOPE, plannedScope, TRUE);
349 ExitOnFailure(hr, "Failed to set the bundle planned scope built-in variable.");
350
343LExit: 351LExit:
344 return hr; 352 return hr;
345} 353}
@@ -812,6 +820,66 @@ LExit:
812 return hr; 820 return hr;
813} 821}
814 822
823extern "C" HRESULT PlanPackagesAndBundleScope(
824 __in BURN_PACKAGE* rgPackages,
825 __in DWORD cPackages,
826 __in BOOTSTRAPPER_SCOPE scope,
827 __in BOOTSTRAPPER_PACKAGE_SCOPE authoredScope,
828 __in BOOTSTRAPPER_SCOPE commandLineScope,
829 __out BOOTSTRAPPER_SCOPE* pResultingScope,
830 __out BOOL* pfRegistrationPerMachine
831)
832{
833 HRESULT hr = S_OK;
834 BOOL fRegistrationPerMachine = TRUE;
835
836 // If a scope was specified on the command line and the BA didn't set a scope,
837 // let the command-line switch override.
838 if (BOOTSTRAPPER_SCOPE_DEFAULT != commandLineScope)
839 {
840 if (BOOTSTRAPPER_PACKAGE_SCOPE_PER_MACHINE_OR_PER_USER == authoredScope || BOOTSTRAPPER_PACKAGE_SCOPE_PER_USER_OR_PER_MACHINE == authoredScope)
841 {
842 if (BOOTSTRAPPER_SCOPE_DEFAULT == scope)
843 {
844 scope = commandLineScope;
845 }
846 else
847 {
848 LogId(REPORT_STANDARD, MSG_SCOPE_IGNORED_BA_SCOPE);
849 }
850 }
851 else
852 {
853 LogId(REPORT_STANDARD, MSG_SCOPE_IGNORED_UNCONFIGURABLE);
854 }
855 }
856
857 for (DWORD i = 0; i < cPackages; ++i)
858 {
859 BURN_PACKAGE* pPackage = rgPackages + i;
860
861 pPackage->fPerMachine =
862 (BOOTSTRAPPER_PACKAGE_SCOPE_PER_MACHINE == pPackage->scope)
863 || (BOOTSTRAPPER_PACKAGE_SCOPE_PER_MACHINE_OR_PER_USER == pPackage->scope &&
864 (BOOTSTRAPPER_SCOPE_DEFAULT == scope || BOOTSTRAPPER_SCOPE_PER_MACHINE == scope))
865 || (BOOTSTRAPPER_PACKAGE_SCOPE_PER_USER_OR_PER_MACHINE == pPackage->scope &&
866 BOOTSTRAPPER_SCOPE_PER_MACHINE == scope);
867
868 // Any per-user package makes the registration per-user as well.
869 if (!pPackage->fPerMachine)
870 {
871 fRegistrationPerMachine = FALSE;
872 }
873 }
874
875 *pResultingScope = scope;
876 *pfRegistrationPerMachine = fRegistrationPerMachine;
877
878//LExit:
879 return hr;
880}
881
882
815static HRESULT PlanPackagesHelper( 883static HRESULT PlanPackagesHelper(
816 __in BURN_PACKAGE* rgPackages, 884 __in BURN_PACKAGE* rgPackages,
817 __in DWORD cPackages, 885 __in DWORD cPackages,
@@ -2971,7 +3039,7 @@ static void ExecuteActionLog(
2971 break; 3039 break;
2972 3040
2973 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE: 3041 case BURN_EXECUTE_ACTION_TYPE_MSI_PACKAGE:
2974 LogStringLine(PlanDumpLevel, "%ls action[%u]: MSI_PACKAGE package id: %ls, action: %hs, action msi property: %ls, ui level: %u, disable externaluihandler: %hs, file versioning: %hs, log path: %ls, logging attrib: %u", wzBase, iAction, pAction->msiPackage.pPackage->sczId, LoggingActionStateToString(pAction->msiPackage.action), LoggingBurnMsiPropertyToString(pAction->msiPackage.actionMsiProperty), pAction->msiPackage.uiLevel, LoggingBoolToString(pAction->msiPackage.fDisableExternalUiHandler), LoggingMsiFileVersioningToString(pAction->msiPackage.fileVersioning), pAction->msiPackage.sczLogPath, pAction->msiPackage.dwLoggingAttributes); 3042 LogStringLine(PlanDumpLevel, "%ls action[%u]: MSI_PACKAGE package id: %ls, scope: %hs, action: %hs, action msi property: %ls, ui level: %u, disable externaluihandler: %hs, file versioning: %hs, log path: %ls, logging attrib: %u", wzBase, iAction, pAction->msiPackage.pPackage->sczId, LoggingPackageScopeToString(pAction->msiPackage.pPackage->scope), LoggingActionStateToString(pAction->msiPackage.action), LoggingBurnMsiPropertyToString(pAction->msiPackage.actionMsiProperty), pAction->msiPackage.uiLevel, LoggingBoolToString(pAction->msiPackage.fDisableExternalUiHandler), LoggingMsiFileVersioningToString(pAction->msiPackage.fileVersioning), pAction->msiPackage.sczLogPath, pAction->msiPackage.dwLoggingAttributes);
2975 for (DWORD j = 0; j < pAction->msiPackage.pPackage->Msi.cSlipstreamMspPackages; ++j) 3043 for (DWORD j = 0; j < pAction->msiPackage.pPackage->Msi.cSlipstreamMspPackages; ++j)
2976 { 3044 {
2977 const BURN_SLIPSTREAM_MSP* pSlipstreamMsp = pAction->msiPackage.pPackage->Msi.rgSlipstreamMsps + j; 3045 const BURN_SLIPSTREAM_MSP* pSlipstreamMsp = pAction->msiPackage.pPackage->Msi.rgSlipstreamMsps + j;
@@ -3083,6 +3151,7 @@ extern "C" void PlanDump(
3083 LogStringLine(PlanDumpLevel, " bundle code: %ls", pPlan->wzBundleCode); 3151 LogStringLine(PlanDumpLevel, " bundle code: %ls", pPlan->wzBundleCode);
3084 LogStringLine(PlanDumpLevel, " bundle provider key: %ls", pPlan->wzBundleProviderKey); 3152 LogStringLine(PlanDumpLevel, " bundle provider key: %ls", pPlan->wzBundleProviderKey);
3085 LogStringLine(PlanDumpLevel, " use-forward-compatible: %hs", LoggingTrueFalseToString(pPlan->fEnabledForwardCompatibleBundle)); 3153 LogStringLine(PlanDumpLevel, " use-forward-compatible: %hs", LoggingTrueFalseToString(pPlan->fEnabledForwardCompatibleBundle));
3154 LogStringLine(PlanDumpLevel, " planned scope: %hs", LoggingBundleScopeToString(pPlan->plannedScope));
3086 LogStringLine(PlanDumpLevel, " per-machine: %hs", LoggingTrueFalseToString(pPlan->fPerMachine)); 3155 LogStringLine(PlanDumpLevel, " per-machine: %hs", LoggingTrueFalseToString(pPlan->fPerMachine));
3087 LogStringLine(PlanDumpLevel, " can affect machine state: %hs", LoggingTrueFalseToString(pPlan->fCanAffectMachineState)); 3156 LogStringLine(PlanDumpLevel, " can affect machine state: %hs", LoggingTrueFalseToString(pPlan->fCanAffectMachineState));
3088 LogStringLine(PlanDumpLevel, " disable-rollback: %hs", LoggingTrueFalseToString(pPlan->fDisableRollback)); 3157 LogStringLine(PlanDumpLevel, " disable-rollback: %hs", LoggingTrueFalseToString(pPlan->fDisableRollback));
diff --git a/src/burn/engine/plan.h b/src/burn/engine/plan.h
index 03b1423d..a20d7c76 100644
--- a/src/burn/engine/plan.h
+++ b/src/burn/engine/plan.h
@@ -249,6 +249,7 @@ typedef struct _BURN_CLEAN_ACTION
249typedef struct _BURN_PLAN 249typedef struct _BURN_PLAN
250{ 250{
251 BOOTSTRAPPER_ACTION action; 251 BOOTSTRAPPER_ACTION action;
252 BOOTSTRAPPER_SCOPE plannedScope;
252 BURN_CACHE* pCache; 253 BURN_CACHE* pCache;
253 BOOTSTRAPPER_COMMAND* pCommand; 254 BOOTSTRAPPER_COMMAND* pCommand;
254 BURN_ENGINE_COMMAND* pInternalCommand; 255 BURN_ENGINE_COMMAND* pInternalCommand;
@@ -328,6 +329,8 @@ void PlanUninitializeExecuteAction(
328 ); 329 );
329HRESULT PlanSetVariables( 330HRESULT PlanSetVariables(
330 __in BOOTSTRAPPER_ACTION action, 331 __in BOOTSTRAPPER_ACTION action,
332 __in BOOTSTRAPPER_PACKAGE_SCOPE authoredScope,
333 __in BOOTSTRAPPER_SCOPE plannedScope,
331 __in BURN_VARIABLES* pVariables 334 __in BURN_VARIABLES* pVariables
332 ); 335 );
333HRESULT PlanDefaultRelatedBundlePlanType( 336HRESULT PlanDefaultRelatedBundlePlanType(
@@ -479,6 +482,15 @@ HRESULT PlanSetResumeCommand(
479void PlanDump( 482void PlanDump(
480 __in BURN_PLAN* pPlan 483 __in BURN_PLAN* pPlan
481 ); 484 );
485HRESULT PlanPackagesAndBundleScope(
486 __in BURN_PACKAGE* rgPackages,
487 __in DWORD cPackages,
488 __in BOOTSTRAPPER_SCOPE scope,
489 __in BOOTSTRAPPER_PACKAGE_SCOPE authoredScope,
490 __in BOOTSTRAPPER_SCOPE commandLineScope,
491 __out BOOTSTRAPPER_SCOPE* pResultingScope,
492 __out BOOL* pfPerMachine
493);
482 494
483#if defined(__cplusplus) 495#if defined(__cplusplus)
484} 496}
diff --git a/src/burn/engine/registration.cpp b/src/burn/engine/registration.cpp
index 9733e92c..fa1b024a 100644
--- a/src/burn/engine/registration.cpp
+++ b/src/burn/engine/registration.cpp
@@ -39,10 +39,6 @@ static HRESULT ParseSoftwareTagsFromXml(
39 __out BURN_SOFTWARE_TAG** prgSoftwareTags, 39 __out BURN_SOFTWARE_TAG** prgSoftwareTags,
40 __out DWORD* pcSoftwareTags 40 __out DWORD* pcSoftwareTags
41 ); 41 );
42static HRESULT SetPaths(
43 __in BURN_REGISTRATION* pRegistration,
44 __in BURN_CACHE* pCache
45 );
46static HRESULT GetBundleManufacturer( 42static HRESULT GetBundleManufacturer(
47 __in BURN_REGISTRATION* pRegistration, 43 __in BURN_REGISTRATION* pRegistration,
48 __in BURN_VARIABLES* pVariables, 44 __in BURN_VARIABLES* pVariables,
@@ -108,6 +104,15 @@ static HRESULT UpdateEstimatedSize(
108 ); 104 );
109static BOOL IsWuRebootPending(); 105static BOOL IsWuRebootPending();
110static BOOL IsRegistryRebootPending(); 106static BOOL IsRegistryRebootPending();
107static HRESULT RegistrationDetectResumeTypeByHive(
108 __in HKEY hkRegistrationRoot,
109 __in BURN_REGISTRATION* pRegistration,
110 __out BOOTSTRAPPER_RESUME_TYPE* pResumeType
111);
112static HRESULT DetectInstalled(
113 __in BURN_REGISTRATION* pRegistration,
114 __in HKEY hkRoot
115);
111 116
112// function definitions 117// function definitions
113 118
@@ -163,9 +168,9 @@ extern "C" HRESULT RegistrationParseFromXml(
163 hr = XmlGetAttributeEx(pixnRegistrationNode, L"ExecutableName", &pRegistration->sczExecutableName); 168 hr = XmlGetAttributeEx(pixnRegistrationNode, L"ExecutableName", &pRegistration->sczExecutableName);
164 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @ExecutableName."); 169 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @ExecutableName.");
165 170
166 // @PerMachine 171 // @Scope
167 hr = XmlGetYesNoAttribute(pixnRegistrationNode, L"PerMachine", &pRegistration->fPerMachine); 172 hr = PackageParseScopeFromXml(pixnRegistrationNode, &pRegistration->scope);
168 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @PerMachine."); 173 ExitOnOptionalXmlQueryFailure(hr, fFoundXml, "Failed to get @Scope.");
169 174
170 // select ARP node 175 // select ARP node
171 hr = XmlSelectSingleNode(pixnRegistrationNode, L"Arp", &pixnArpNode); 176 hr = XmlSelectSingleNode(pixnRegistrationNode, L"Arp", &pixnArpNode);
@@ -285,8 +290,18 @@ extern "C" HRESULT RegistrationParseFromXml(
285 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Classification."); 290 ExitOnRequiredXmlQueryFailure(hr, "Failed to get @Classification.");
286 } 291 }
287 292
288 hr = SetPaths(pRegistration, pCache); 293 // Handle the easy case of build-time bundle scope early.
289 ExitOnFailure(hr, "Failed to set registration paths."); 294 if (BOOTSTRAPPER_PACKAGE_SCOPE_PER_MACHINE == pRegistration->scope || BOOTSTRAPPER_PACKAGE_SCOPE_PER_USER == pRegistration->scope)
295 {
296 pRegistration->fPerMachine = BOOTSTRAPPER_PACKAGE_SCOPE_PER_MACHINE == pRegistration->scope;
297
298 hr = RegistrationSetPaths(pRegistration, pCache);
299 ExitOnFailure(hr, "Failed to set registration paths for fixed scope.");
300 }
301 else
302 {
303 pRegistration->hkRoot = reinterpret_cast<HKEY>(0ull);
304 }
290 305
291LExit: 306LExit:
292 ReleaseObject(pixnRegistrationNode); 307 ReleaseObject(pixnRegistrationNode);
@@ -452,31 +467,28 @@ LExit:
452 467
453extern "C" HRESULT RegistrationDetectInstalled( 468extern "C" HRESULT RegistrationDetectInstalled(
454 __in BURN_REGISTRATION* pRegistration 469 __in BURN_REGISTRATION* pRegistration
455 ) 470)
456{ 471{
457 HRESULT hr = S_OK; 472 HRESULT hr = S_OK;
458 HKEY hkRegistration = NULL;
459 DWORD dwInstalled = 0;
460 473
461 pRegistration->fCached = FileExistsEx(pRegistration->sczCacheExecutablePath, NULL); 474 if (pRegistration->hkRoot)
462 pRegistration->detectedRegistrationType = BOOTSTRAPPER_REGISTRATION_TYPE_NONE;
463
464 // open registration key
465 hr = RegOpen(pRegistration->hkRoot, pRegistration->sczRegistrationKey, KEY_QUERY_VALUE, &hkRegistration);
466 if (SUCCEEDED(hr))
467 { 475 {
468 hr = RegReadNumber(hkRegistration, REGISTRY_BUNDLE_INSTALLED, &dwInstalled); 476 hr = DetectInstalled(pRegistration, pRegistration->hkRoot);
469
470 pRegistration->detectedRegistrationType = (1 == dwInstalled) ? BOOTSTRAPPER_REGISTRATION_TYPE_FULL : BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS;
471 } 477 }
472 478 else
473 // Not finding the key or value is okay.
474 if (E_FILENOTFOUND == hr || E_PATHNOTFOUND == hr)
475 { 479 {
476 hr = S_OK; 480 // For PUOM/PMOU bundles, check per-machine then fall back to per-user.
481 hr = DetectInstalled(pRegistration, HKEY_LOCAL_MACHINE);
482 ExitOnFailure(hr, "Failed to detect HKEY_LOCAL_MACHINE bundle registration install state.");
483
484 if (BOOTSTRAPPER_REGISTRATION_TYPE_NONE == pRegistration->detectedRegistrationType)
485 {
486 hr = DetectInstalled(pRegistration, HKEY_CURRENT_USER);
487 ExitOnFailure(hr, "Failed to detect HKEY_CURRENT_USER bundle registration install state.");
488 }
477 } 489 }
478 490
479 ReleaseRegKey(hkRegistration); 491LExit:
480 return hr; 492 return hr;
481} 493}
482 494
@@ -488,63 +500,26 @@ extern "C" HRESULT RegistrationDetectInstalled(
488extern "C" HRESULT RegistrationDetectResumeType( 500extern "C" HRESULT RegistrationDetectResumeType(
489 __in BURN_REGISTRATION* pRegistration, 501 __in BURN_REGISTRATION* pRegistration,
490 __out BOOTSTRAPPER_RESUME_TYPE* pResumeType 502 __out BOOTSTRAPPER_RESUME_TYPE* pResumeType
491 ) 503)
492{ 504{
493 HRESULT hr = S_OK; 505 HRESULT hr = S_OK;
494 HKEY hkRegistration = NULL;
495 BOOL fExists = FALSE;
496 DWORD dwResume = 0;
497 506
498 // open registration key 507 if (pRegistration->hkRoot)
499 hr = RegOpen(pRegistration->hkRoot, pRegistration->sczRegistrationKey, KEY_QUERY_VALUE, &hkRegistration);
500 ExitOnPathFailure(hr, fExists, "Failed to open registration key.");
501
502 if (!fExists)
503 { 508 {
504 *pResumeType = BOOTSTRAPPER_RESUME_TYPE_NONE; 509 hr = RegistrationDetectResumeTypeByHive(pRegistration->hkRoot, pRegistration, pResumeType);
505 ExitFunction();
506 } 510 }
507 511 else
508 // read Resume value
509 hr = RegReadNumber(hkRegistration, L"Resume", &dwResume);
510 ExitOnPathFailure(hr, fExists, "Failed to read Resume value.");
511
512 if (!fExists)
513 {
514 *pResumeType = BOOTSTRAPPER_RESUME_TYPE_INVALID;
515 ExitFunction();
516 }
517
518 switch (dwResume)
519 { 512 {
520 case BURN_RESUME_MODE_ACTIVE: 513 hr = RegistrationDetectResumeTypeByHive(HKEY_LOCAL_MACHINE, pRegistration, pResumeType);
521 // a previous run was interrupted
522 *pResumeType = BOOTSTRAPPER_RESUME_TYPE_INTERRUPTED;
523 break;
524
525 case BURN_RESUME_MODE_SUSPEND:
526 *pResumeType = BOOTSTRAPPER_RESUME_TYPE_SUSPEND;
527 break;
528
529 case BURN_RESUME_MODE_ARP:
530 *pResumeType = BOOTSTRAPPER_RESUME_TYPE_ARP;
531 break;
532
533 case BURN_RESUME_MODE_REBOOT_PENDING:
534 // The volatile pending registry doesn't exist (checked above) which means
535 // the system was successfully restarted.
536 *pResumeType = BOOTSTRAPPER_RESUME_TYPE_REBOOT;
537 break;
538 514
539 default: 515 if (BOOTSTRAPPER_RESUME_TYPE_NONE == *pResumeType)
540 // the value stored in the registry is not valid 516 {
541 *pResumeType = BOOTSTRAPPER_RESUME_TYPE_INVALID; 517 hr = RegistrationDetectResumeTypeByHive(HKEY_CURRENT_USER, pRegistration, pResumeType);
542 break; 518 }
543 } 519 }
520 ExitOnFailure(hr, "Failed to find bundle registration: %ls", pRegistration->sczRegistrationKey);
544 521
545LExit: 522LExit:
546 ReleaseRegKey(hkRegistration);
547
548 return hr; 523 return hr;
549} 524}
550 525
@@ -889,7 +864,7 @@ extern "C" HRESULT RegistrationSessionEnd(
889 864
890 // Open registration key. 865 // Open registration key.
891 hr = RegOpen(pRegistration->hkRoot, pRegistration->sczRegistrationKey, KEY_WRITE, &hkRegistration); 866 hr = RegOpen(pRegistration->hkRoot, pRegistration->sczRegistrationKey, KEY_WRITE, &hkRegistration);
892 ExitOnFailure(hr, "Failed to open registration key."); 867 ExitOnFailure(hr, "Failed to open registration key for ending session.");
893 868
894 // update display name 869 // update display name
895 hr = UpdateBundleNameRegistration(pRegistration, pVariables, hkRegistration, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS == registrationType); 870 hr = UpdateBundleNameRegistration(pRegistration, pVariables, hkRegistration, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS == registrationType);
@@ -1068,6 +1043,39 @@ extern "C" HRESULT RegistrationGetResumeCommandLine(
1068 return hr; 1043 return hr;
1069} 1044}
1070 1045
1046extern "C" HRESULT RegistrationSetPaths(
1047 __in BURN_REGISTRATION* pRegistration,
1048 __in BURN_CACHE* pCache
1049 )
1050{
1051 HRESULT hr = S_OK;
1052 LPWSTR sczCacheDirectory = NULL;
1053
1054 // save registration key root
1055 pRegistration->hkRoot = pRegistration->fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
1056
1057 // build uninstall registry key path
1058 hr = StrAllocFormatted(&pRegistration->sczRegistrationKey, L"%ls\\%ls", BURN_REGISTRATION_REGISTRY_UNINSTALL_KEY, pRegistration->sczCode);
1059 ExitOnFailure(hr, "Failed to build uninstall registry key path.");
1060
1061 // build cache directory
1062 hr = CacheGetCompletedPath(pCache, pRegistration->fPerMachine, pRegistration->sczCode, &sczCacheDirectory);
1063 ExitOnFailure(hr, "Failed to build cache directory.");
1064
1065 // build cached executable path
1066 hr = PathConcatRelativeToFullyQualifiedBase(sczCacheDirectory, pRegistration->sczExecutableName, &pRegistration->sczCacheExecutablePath);
1067 ExitOnFailure(hr, "Failed to build cached executable path.");
1068
1069 // build state file path
1070 hr = StrAllocFormatted(&pRegistration->sczStateFile, L"%ls\\state.rsm", sczCacheDirectory);
1071 ExitOnFailure(hr, "Failed to build state file path.");
1072
1073LExit:
1074 ReleaseStr(sczCacheDirectory);
1075
1076 return hr;
1077}
1078
1071 1079
1072// internal helper functions 1080// internal helper functions
1073 1081
@@ -1141,38 +1149,6 @@ LExit:
1141 return hr; 1149 return hr;
1142} 1150}
1143 1151
1144static HRESULT SetPaths(
1145 __in BURN_REGISTRATION* pRegistration,
1146 __in BURN_CACHE* pCache
1147 )
1148{
1149 HRESULT hr = S_OK;
1150 LPWSTR sczCacheDirectory = NULL;
1151
1152 // save registration key root
1153 pRegistration->hkRoot = pRegistration->fPerMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
1154
1155 // build uninstall registry key path
1156 hr = StrAllocFormatted(&pRegistration->sczRegistrationKey, L"%ls\\%ls", BURN_REGISTRATION_REGISTRY_UNINSTALL_KEY, pRegistration->sczCode);
1157 ExitOnFailure(hr, "Failed to build uninstall registry key path.");
1158
1159 // build cache directory
1160 hr = CacheGetCompletedPath(pCache, pRegistration->fPerMachine, pRegistration->sczCode, &sczCacheDirectory);
1161 ExitOnFailure(hr, "Failed to build cache directory.");
1162
1163 // build cached executable path
1164 hr = PathConcatRelativeToFullyQualifiedBase(sczCacheDirectory, pRegistration->sczExecutableName, &pRegistration->sczCacheExecutablePath);
1165 ExitOnFailure(hr, "Failed to build cached executable path.");
1166
1167 // build state file path
1168 hr = StrAllocFormatted(&pRegistration->sczStateFile, L"%ls\\state.rsm", sczCacheDirectory);
1169 ExitOnFailure(hr, "Failed to build state file path.");
1170
1171LExit:
1172 ReleaseStr(sczCacheDirectory);
1173 return hr;
1174}
1175
1176static HRESULT GetBundleManufacturer( 1152static HRESULT GetBundleManufacturer(
1177 __in BURN_REGISTRATION* pRegistration, 1153 __in BURN_REGISTRATION* pRegistration,
1178 __in BURN_VARIABLES* pVariables, 1154 __in BURN_VARIABLES* pVariables,
@@ -1703,3 +1679,102 @@ static BOOL IsRegistryRebootPending()
1703 1679
1704 return fRebootPending; 1680 return fRebootPending;
1705} 1681}
1682
1683static HRESULT RegistrationDetectResumeTypeByHive(
1684 __in HKEY hkRegistrationRoot,
1685 __in BURN_REGISTRATION* pRegistration,
1686 __out BOOTSTRAPPER_RESUME_TYPE* pResumeType
1687)
1688{
1689 HRESULT hr = S_OK;
1690 HKEY hkRegistration = NULL;
1691 BOOL fExists = FALSE;
1692 DWORD dwResume = 0;
1693
1694 *pResumeType = BOOTSTRAPPER_RESUME_TYPE_NONE;
1695
1696 // open registration key
1697 hr = RegOpen(hkRegistrationRoot, pRegistration->sczRegistrationKey, KEY_QUERY_VALUE, &hkRegistration);
1698 ExitOnPathFailure(hr, fExists, "Failed to open registration key.");
1699
1700 if (!fExists)
1701 {
1702 *pResumeType = BOOTSTRAPPER_RESUME_TYPE_NONE;
1703 ExitFunction();
1704 }
1705
1706 // read Resume value
1707 hr = RegReadNumber(hkRegistration, L"Resume", &dwResume);
1708 ExitOnPathFailure(hr, fExists, "Failed to read Resume value.");
1709
1710 if (!fExists)
1711 {
1712 *pResumeType = BOOTSTRAPPER_RESUME_TYPE_INVALID;
1713 ExitFunction();
1714 }
1715
1716 switch (dwResume)
1717 {
1718 case BURN_RESUME_MODE_ACTIVE:
1719 // a previous run was interrupted
1720 *pResumeType = BOOTSTRAPPER_RESUME_TYPE_INTERRUPTED;
1721 break;
1722
1723 case BURN_RESUME_MODE_SUSPEND:
1724 *pResumeType = BOOTSTRAPPER_RESUME_TYPE_SUSPEND;
1725 break;
1726
1727 case BURN_RESUME_MODE_ARP:
1728 *pResumeType = BOOTSTRAPPER_RESUME_TYPE_ARP;
1729 break;
1730
1731 case BURN_RESUME_MODE_REBOOT_PENDING:
1732 // The volatile pending registry doesn't exist (checked above) which means
1733 // the system was successfully restarted.
1734 *pResumeType = BOOTSTRAPPER_RESUME_TYPE_REBOOT;
1735 break;
1736
1737 default:
1738 // the value stored in the registry is not valid
1739 *pResumeType = BOOTSTRAPPER_RESUME_TYPE_INVALID;
1740 break;
1741 }
1742
1743LExit:
1744 ReleaseRegKey(hkRegistration);
1745
1746 return hr;
1747}
1748
1749static HRESULT DetectInstalled(
1750 __in BURN_REGISTRATION* pRegistration,
1751 __in HKEY hkRoot
1752)
1753{
1754 HRESULT hr = S_OK;
1755 HKEY hkRegistration = NULL;
1756 DWORD dwInstalled = 0;
1757
1758 pRegistration->fCached = pRegistration->sczCacheExecutablePath && FileExistsEx(pRegistration->sczCacheExecutablePath, NULL);
1759 pRegistration->detectedRegistrationType = BOOTSTRAPPER_REGISTRATION_TYPE_NONE;
1760
1761 // open registration key
1762 hr = RegOpen(hkRoot, pRegistration->sczRegistrationKey, KEY_QUERY_VALUE, &hkRegistration);
1763 if (SUCCEEDED(hr))
1764 {
1765 hr = RegReadNumber(hkRegistration, REGISTRY_BUNDLE_INSTALLED, &dwInstalled);
1766
1767 pRegistration->detectedRegistrationType = (1 == dwInstalled) ? BOOTSTRAPPER_REGISTRATION_TYPE_FULL : BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS;
1768 }
1769
1770 // Not finding the key or value is okay.
1771 if (E_FILENOTFOUND == hr || E_PATHNOTFOUND == hr)
1772 {
1773 hr = S_OK;
1774 }
1775
1776 ReleaseRegKey(hkRegistration);
1777
1778 return hr;
1779}
1780
diff --git a/src/burn/engine/registration.h b/src/burn/engine/registration.h
index 326f21c6..e83b75b6 100644
--- a/src/burn/engine/registration.h
+++ b/src/burn/engine/registration.h
@@ -94,11 +94,12 @@ typedef struct _BURN_SOFTWARE_TAGS
94 94
95typedef struct _BURN_REGISTRATION 95typedef struct _BURN_REGISTRATION
96{ 96{
97 BOOL fPerMachine; 97 BOOL fPerMachine; // For PUOM/PMOU bundles, only valid after planning.
98 BOOL fForceSystemComponent; 98 BOOL fForceSystemComponent;
99 BOOL fDisableResume; 99 BOOL fDisableResume;
100 BOOL fCached; 100 BOOL fCached;
101 BOOTSTRAPPER_REGISTRATION_TYPE detectedRegistrationType; 101 BOOTSTRAPPER_REGISTRATION_TYPE detectedRegistrationType;
102 BOOTSTRAPPER_PACKAGE_SCOPE scope;
102 LPWSTR sczCode; 103 LPWSTR sczCode;
103 LPWSTR sczTag; 104 LPWSTR sczTag;
104 105
@@ -167,7 +168,7 @@ HRESULT RegistrationParseFromXml(
167 __in BURN_REGISTRATION* pRegistration, 168 __in BURN_REGISTRATION* pRegistration,
168 __in BURN_CACHE* pCache, 169 __in BURN_CACHE* pCache,
169 __in IXMLDOMNode* pixnBundle 170 __in IXMLDOMNode* pixnBundle
170 ); 171);
171void RegistrationUninitialize( 172void RegistrationUninitialize(
172 __in BURN_REGISTRATION* pRegistration 173 __in BURN_REGISTRATION* pRegistration
173 ); 174 );
@@ -191,7 +192,7 @@ HRESULT RegistrationDetectRelatedBundles(
191 ); 192 );
192HRESULT RegistrationPlanInitialize( 193HRESULT RegistrationPlanInitialize(
193 __in BURN_REGISTRATION* pRegistration 194 __in BURN_REGISTRATION* pRegistration
194 ); 195);
195HRESULT RegistrationSessionBegin( 196HRESULT RegistrationSessionBegin(
196 __in_z LPCWSTR wzEngineWorkingPath, 197 __in_z LPCWSTR wzEngineWorkingPath,
197 __in BURN_REGISTRATION* pRegistration, 198 __in BURN_REGISTRATION* pRegistration,
@@ -225,6 +226,10 @@ HRESULT RegistrationGetResumeCommandLine(
225 __in const BURN_REGISTRATION* pRegistration, 226 __in const BURN_REGISTRATION* pRegistration,
226 __deref_out_z LPWSTR* psczResumeCommandLine 227 __deref_out_z LPWSTR* psczResumeCommandLine
227 ); 228 );
229HRESULT RegistrationSetPaths(
230 __in BURN_REGISTRATION* pRegistration,
231 __in BURN_CACHE* pCache
232 );
228 233
229 234
230#if defined(__cplusplus) 235#if defined(__cplusplus)
diff --git a/src/burn/engine/relatedbundle.cpp b/src/burn/engine/relatedbundle.cpp
index c9aa7170..d0b97af0 100644
--- a/src/burn/engine/relatedbundle.cpp
+++ b/src/burn/engine/relatedbundle.cpp
@@ -22,7 +22,7 @@ static __callback int __cdecl CompareRelatedBundlesPlan(
22 ); 22 );
23static BUNDLE_QUERY_CALLBACK_RESULT CALLBACK QueryRelatedBundlesCallback( 23static BUNDLE_QUERY_CALLBACK_RESULT CALLBACK QueryRelatedBundlesCallback(
24 __in const BUNDLE_QUERY_RELATED_BUNDLE_RESULT* pBundle, 24 __in const BUNDLE_QUERY_RELATED_BUNDLE_RESULT* pBundle,
25 __in_opt LPVOID pvContext 25 __in LPVOID pvContext
26 ); 26 );
27static HRESULT LoadIfRelatedBundle( 27static HRESULT LoadIfRelatedBundle(
28 __in const BUNDLE_QUERY_RELATED_BUNDLE_RESULT* pBundle, 28 __in const BUNDLE_QUERY_RELATED_BUNDLE_RESULT* pBundle,
@@ -258,7 +258,7 @@ static __callback int __cdecl CompareRelatedBundlesPlan(
258 258
259static BUNDLE_QUERY_CALLBACK_RESULT CALLBACK QueryRelatedBundlesCallback( 259static BUNDLE_QUERY_CALLBACK_RESULT CALLBACK QueryRelatedBundlesCallback(
260 __in const BUNDLE_QUERY_RELATED_BUNDLE_RESULT* pBundle, 260 __in const BUNDLE_QUERY_RELATED_BUNDLE_RESULT* pBundle,
261 __in_opt LPVOID pvContext 261 __in LPVOID pvContext
262 ) 262 )
263{ 263{
264 HRESULT hr = S_OK; 264 HRESULT hr = S_OK;
diff --git a/src/burn/engine/uithread.cpp b/src/burn/engine/uithread.cpp
index 9beb9f80..1f7db965 100644
--- a/src/burn/engine/uithread.cpp
+++ b/src/burn/engine/uithread.cpp
@@ -123,7 +123,7 @@ static DWORD WINAPI ThreadProc(
123 info.pEngineState = pEngineState; 123 info.pEngineState = pEngineState;
124 124
125 // Create the window to handle reboots without activating it. 125 // Create the window to handle reboots without activating it.
126 hWnd = ::CreateWindowExW(WS_EX_NOACTIVATE, wc.lpszClassName, NULL, WS_POPUP, 0, 0, 0, 0, HWND_DESKTOP, NULL, pContext->hInstance, &info); 126 hWnd = ::CreateWindowExW(WS_EX_NOACTIVATE, wc.lpszClassName, BURN_UITHREAD_CLASS_WINDOW, WS_POPUP, 0, 0, 0, 0, HWND_DESKTOP, NULL, pContext->hInstance, &info);
127 ExitOnNullWithLastError(hWnd, hr, "Failed to create Burn UI thread window."); 127 ExitOnNullWithLastError(hWnd, hr, "Failed to create Burn UI thread window.");
128 128
129 ::ShowWindow(hWnd, SW_SHOWNA); 129 ::ShowWindow(hWnd, SW_SHOWNA);
diff --git a/src/burn/engine/variable.cpp b/src/burn/engine/variable.cpp
index a795d76c..1b7dc4d1 100644
--- a/src/burn/engine/variable.cpp
+++ b/src/burn/engine/variable.cpp
@@ -305,6 +305,8 @@ extern "C" HRESULT VariableInitialize(
305 {BURN_BUNDLE_TAG, InitializeVariableString, (DWORD_PTR)L"", FALSE, TRUE}, 305 {BURN_BUNDLE_TAG, InitializeVariableString, (DWORD_PTR)L"", FALSE, TRUE},
306 {BURN_BUNDLE_UILEVEL, InitializeVariableNumeric, 0, FALSE, TRUE}, 306 {BURN_BUNDLE_UILEVEL, InitializeVariableNumeric, 0, FALSE, TRUE},
307 {BURN_BUNDLE_VERSION, InitializeVariableVersion, (DWORD_PTR)L"0", FALSE, TRUE}, 307 {BURN_BUNDLE_VERSION, InitializeVariableVersion, (DWORD_PTR)L"0", FALSE, TRUE},
308 {BURN_BUNDLE_SCOPE, InitializeVariableNumeric, 0, FALSE, TRUE},
309 {BURN_BUNDLE_PLANNED_SCOPE, InitializeVariableNumeric, 0, FALSE, TRUE},
308 }; 310 };
309 311
310 const WELL_KNOWN_VARIABLE_DECLARATION vrgWellKnownVariableNames[] = 312 const WELL_KNOWN_VARIABLE_DECLARATION vrgWellKnownVariableNames[] =