aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2021-03-10 15:47:59 -0600
committerSean Hall <r.sean.hall@gmail.com>2021-03-11 20:24:18 -0600
commit10ef9d5bfbf81f454113a1c2716009831a916222 (patch)
tree9e2fd8c917787ceba5e4c7f873d715eafbda6920
parent778b65643f19df94947d390a5a17023043d840b4 (diff)
downloadwix-10ef9d5bfbf81f454113a1c2716009831a916222.tar.gz
wix-10ef9d5bfbf81f454113a1c2716009831a916222.tar.bz2
wix-10ef9d5bfbf81f454113a1c2716009831a916222.zip
Determine whether to ignore forward compatible bundles during Plan.
-rw-r--r--src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h20
-rw-r--r--src/engine/core.cpp65
-rw-r--r--src/engine/dependency.cpp23
-rw-r--r--src/engine/dependency.h10
-rw-r--r--src/engine/detect.cpp48
-rw-r--r--src/engine/detect.h3
-rw-r--r--src/engine/engine.mc2
-rw-r--r--src/engine/plan.cpp68
-rw-r--r--src/engine/plan.h10
-rw-r--r--src/engine/registration.h6
-rw-r--r--src/engine/userexperience.cpp43
-rw-r--r--src/engine/userexperience.h12
12 files changed, 200 insertions, 110 deletions
diff --git a/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h b/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
index 6cf3477c..c3242167 100644
--- a/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
+++ b/src/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
@@ -143,6 +143,7 @@ enum BOOTSTRAPPER_APPLICATION_MESSAGE
143 BOOTSTRAPPER_APPLICATION_MESSAGE_ONSYSTEMRESTOREPOINTBEGIN, 143 BOOTSTRAPPER_APPLICATION_MESSAGE_ONSYSTEMRESTOREPOINTBEGIN,
144 BOOTSTRAPPER_APPLICATION_MESSAGE_ONSYSTEMRESTOREPOINTCOMPLETE, 144 BOOTSTRAPPER_APPLICATION_MESSAGE_ONSYSTEMRESTOREPOINTCOMPLETE,
145 BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDPACKAGE, 145 BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANNEDPACKAGE,
146 BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANFORWARDCOMPATIBLEBUNDLE,
146}; 147};
147 148
148enum BOOTSTRAPPER_APPLYCOMPLETE_ACTION 149enum BOOTSTRAPPER_APPLYCOMPLETE_ACTION
@@ -496,7 +497,6 @@ struct BA_ONDETECTFORWARDCOMPATIBLEBUNDLE_RESULTS
496{ 497{
497 DWORD cbSize; 498 DWORD cbSize;
498 BOOL fCancel; 499 BOOL fCancel;
499 BOOL fIgnoreBundle;
500}; 500};
501 501
502struct BA_ONDETECTMSIFEATURE_ARGS 502struct BA_ONDETECTMSIFEATURE_ARGS
@@ -854,6 +854,24 @@ struct BA_ONPLANCOMPLETE_RESULTS
854 DWORD cbSize; 854 DWORD cbSize;
855}; 855};
856 856
857struct BA_ONPLANFORWARDCOMPATIBLEBUNDLE_ARGS
858{
859 DWORD cbSize;
860 LPCWSTR wzBundleId;
861 BOOTSTRAPPER_RELATION_TYPE relationType;
862 LPCWSTR wzBundleTag;
863 BOOL fPerMachine;
864 LPCWSTR wzVersion;
865 BOOL fRecommendedIgnoreBundle;
866};
867
868struct BA_ONPLANFORWARDCOMPATIBLEBUNDLE_RESULTS
869{
870 DWORD cbSize;
871 BOOL fCancel;
872 BOOL fIgnoreBundle;
873};
874
857struct BA_ONPLANMSIFEATURE_ARGS 875struct BA_ONPLANMSIFEATURE_ARGS
858{ 876{
859 DWORD cbSize; 877 DWORD cbSize;
diff --git a/src/engine/core.cpp b/src/engine/core.cpp
index 2f18e4d2..eb8a84fe 100644
--- a/src/engine/core.cpp
+++ b/src/engine/core.cpp
@@ -319,15 +319,8 @@ extern "C" HRESULT CoreDetect(
319 hr = DependencyDetectProviderKeyBundleId(&pEngineState->registration); 319 hr = DependencyDetectProviderKeyBundleId(&pEngineState->registration);
320 if (SUCCEEDED(hr)) 320 if (SUCCEEDED(hr))
321 { 321 {
322 hr = DetectForwardCompatibleBundle(&pEngineState->userExperience, &pEngineState->command, &pEngineState->registration); 322 hr = DetectForwardCompatibleBundles(&pEngineState->userExperience, &pEngineState->registration);
323 ExitOnFailure(hr, "Failed to detect forward compatible bundle."); 323 ExitOnFailure(hr, "Failed to detect forward compatible bundle.");
324
325 // If a forward compatible bundle was detected, skip rest of bundle detection
326 // since we will passthrough.
327 if (pEngineState->registration.fEnabledForwardCompatibleBundle)
328 {
329 ExitFunction();
330 }
331 } 324 }
332 else if (E_NOTFOUND == hr) 325 else if (E_NOTFOUND == hr)
333 { 326 {
@@ -504,39 +497,45 @@ extern "C" HRESULT CorePlan(
504 hr = PlanUpdateBundle(&pEngineState->userExperience, pUpgradeBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, &hSyncpointEvent); 497 hr = PlanUpdateBundle(&pEngineState->userExperience, pUpgradeBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, &hSyncpointEvent);
505 ExitOnFailure(hr, "Failed to plan update."); 498 ExitOnFailure(hr, "Failed to plan update.");
506 } 499 }
507 else if (pEngineState->registration.fEnabledForwardCompatibleBundle) 500 else
508 { 501 {
509 Assert(!pEngineState->plan.fPerMachine); 502 hr = PlanForwardCompatibleBundles(&pEngineState->userExperience, &pEngineState->command, &pEngineState->plan, &pEngineState->registration, action);
503 ExitOnFailure(hr, "Failed to plan forward compatible bundles.");
510 504
511 pForwardCompatibleBundlePackage = &pEngineState->registration.forwardCompatibleBundle; 505 if (pEngineState->plan.fEnabledForwardCompatibleBundle)
512 506 {
513 hr = PlanPassThroughBundle(&pEngineState->userExperience, pForwardCompatibleBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, &hSyncpointEvent); 507 Assert(!pEngineState->plan.fPerMachine);
514 ExitOnFailure(hr, "Failed to plan passthrough.");
515 }
516 else // doing an action that modifies the machine state.
517 {
518 pEngineState->plan.fPerMachine = pEngineState->registration.fPerMachine; // default the scope of the plan to the per-machine state of the bundle.
519 508
520 hr = PlanRegistration(&pEngineState->plan, &pEngineState->registration, pEngineState->command.resumeType, pEngineState->command.relationType, &fContinuePlanning); 509 pForwardCompatibleBundlePackage = &pEngineState->plan.forwardCompatibleBundle;
521 ExitOnFailure(hr, "Failed to plan registration.");
522 510
523 if (fContinuePlanning) 511 hr = PlanPassThroughBundle(&pEngineState->userExperience, pForwardCompatibleBundlePackage, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, &hSyncpointEvent);
512 ExitOnFailure(hr, "Failed to plan passthrough.");
513 }
514 else // doing an action that modifies the machine state.
524 { 515 {
525 // Remember the early index, because we want to be able to insert some related bundles 516 pEngineState->plan.fPerMachine = pEngineState->registration.fPerMachine; // default the scope of the plan to the per-machine state of the bundle.
526 // into the plan before other executed packages. This particularly occurs for uninstallation
527 // of addons and patches, which should be uninstalled before the main product.
528 DWORD dwExecuteActionEarlyIndex = pEngineState->plan.cExecuteActions;
529 517
530 // Plan the related bundles first to support downgrades with ref-counting. 518 hr = PlanRegistration(&pEngineState->plan, &pEngineState->registration, pEngineState->command.resumeType, pEngineState->command.relationType, &fContinuePlanning);
531 hr = PlanRelatedBundlesBegin(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, &pEngineState->plan); 519 ExitOnFailure(hr, "Failed to plan registration.");
532 ExitOnFailure(hr, "Failed to plan related bundles.");
533 520
534 hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, NULL, &hSyncpointEvent); 521 if (fContinuePlanning)
535 ExitOnFailure(hr, "Failed to plan packages."); 522 {
523 // Remember the early index, because we want to be able to insert some related bundles
524 // into the plan before other executed packages. This particularly occurs for uninstallation
525 // of addons and patches, which should be uninstalled before the main product.
526 DWORD dwExecuteActionEarlyIndex = pEngineState->plan.cExecuteActions;
536 527
537 // Schedule the update of related bundles last. 528 // Plan the related bundles first to support downgrades with ref-counting.
538 hr = PlanRelatedBundlesComplete(&pEngineState->registration, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, &hSyncpointEvent, dwExecuteActionEarlyIndex); 529 hr = PlanRelatedBundlesBegin(&pEngineState->userExperience, &pEngineState->registration, pEngineState->command.relationType, &pEngineState->plan);
539 ExitOnFailure(hr, "Failed to schedule related bundles."); 530 ExitOnFailure(hr, "Failed to plan related bundles.");
531
532 hr = PlanPackages(&pEngineState->userExperience, &pEngineState->packages, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, pEngineState->command.display, pEngineState->command.relationType, NULL, &hSyncpointEvent);
533 ExitOnFailure(hr, "Failed to plan packages.");
534
535 // Schedule the update of related bundles last.
536 hr = PlanRelatedBundlesComplete(&pEngineState->registration, &pEngineState->plan, &pEngineState->log, &pEngineState->variables, &hSyncpointEvent, dwExecuteActionEarlyIndex);
537 ExitOnFailure(hr, "Failed to schedule related bundles.");
538 }
540 } 539 }
541 } 540 }
542 541
diff --git a/src/engine/dependency.cpp b/src/engine/dependency.cpp
index 4833de94..9ab76551 100644
--- a/src/engine/dependency.cpp
+++ b/src/engine/dependency.cpp
@@ -234,6 +234,8 @@ extern "C" HRESULT DependencyDetect(
234 BURN_REGISTRATION* pRegistration = &pEngineState->registration; 234 BURN_REGISTRATION* pRegistration = &pEngineState->registration;
235 STRINGDICT_HANDLE sdIgnoredDependents = NULL; 235 STRINGDICT_HANDLE sdIgnoredDependents = NULL;
236 BURN_PACKAGE* pPackage = NULL; 236 BURN_PACKAGE* pPackage = NULL;
237 BOOL fSelfDependent = NULL != pRegistration->wzSelfDependent;
238 BOOL fActiveParent = NULL != pRegistration->sczActiveParent && NULL != *pRegistration->sczActiveParent;
237 239
238 // Always leave this empty so that all dependents get detected. Plan will ignore dependents based on its own logic. 240 // Always leave this empty so that all dependents get detected. Plan will ignore dependents based on its own logic.
239 hr = DictCreateStringList(&sdIgnoredDependents, INITIAL_STRINGDICT_SIZE, DICT_FLAG_CASEINSENSITIVE); 241 hr = DictCreateStringList(&sdIgnoredDependents, INITIAL_STRINGDICT_SIZE, DICT_FLAG_CASEINSENSITIVE);
@@ -263,16 +265,20 @@ extern "C" HRESULT DependencyDetect(
263 ExitOnFailure(hr, "Failed to detect dependents for related bundle '%ls'", pPackage->sczId); 265 ExitOnFailure(hr, "Failed to detect dependents for related bundle '%ls'", pPackage->sczId);
264 } 266 }
265 267
266 if (pRegistration->wzSelfDependent) 268 if (fSelfDependent || fActiveParent)
267 { 269 {
268 for (DWORD i = 0; i < pRegistration->cDependents; ++i) 270 for (DWORD i = 0; i < pRegistration->cDependents; ++i)
269 { 271 {
270 DEPENDENCY* pDependent = pRegistration->rgDependents + i; 272 DEPENDENCY* pDependent = pRegistration->rgDependents + i;
271 273
272 if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->wzSelfDependent, -1, pDependent->sczKey, -1)) 274 if (fActiveParent && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->sczActiveParent, -1, pDependent->sczKey, -1))
275 {
276 pRegistration->fParentRegisteredAsDependent = TRUE;
277 }
278
279 if (fSelfDependent && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->wzSelfDependent, -1, pDependent->sczKey, -1))
273 { 280 {
274 pRegistration->fSelfRegisteredAsDependent = TRUE; 281 pRegistration->fSelfRegisteredAsDependent = TRUE;
275 break;
276 } 282 }
277 } 283 }
278 } 284 }
@@ -348,17 +354,6 @@ LExit:
348 return hr; 354 return hr;
349} 355}
350 356
351extern "C" BOOL DependencyDependentExists(
352 __in const BURN_REGISTRATION* pRegistration,
353 __in_z LPCWSTR wzDependentProviderKey
354 )
355{
356 HRESULT hr = S_OK;
357
358 hr = DepDependentExists(pRegistration->hkRoot, pRegistration->sczProviderKey, wzDependentProviderKey);
359 return SUCCEEDED(hr);
360}
361
362extern "C" HRESULT DependencyPlanPackageBegin( 357extern "C" HRESULT DependencyPlanPackageBegin(
363 __in BOOL fPerMachine, 358 __in BOOL fPerMachine,
364 __in BURN_PACKAGE* pPackage, 359 __in BURN_PACKAGE* pPackage,
diff --git a/src/engine/dependency.h b/src/engine/dependency.h
index efb9f2f2..06a01a20 100644
--- a/src/engine/dependency.h
+++ b/src/engine/dependency.h
@@ -85,16 +85,6 @@ HRESULT DependencyAddIgnoreDependencies(
85 ); 85 );
86 86
87/******************************************************************** 87/********************************************************************
88 DependencyDependentExists - Checks to see if the provider key is
89 already dependent on this bundle.
90
91*********************************************************************/
92BOOL DependencyDependentExists(
93 __in const BURN_REGISTRATION* pRegistration,
94 __in_z LPCWSTR wzDependentProviderKey
95 );
96
97/********************************************************************
98 DependencyPlanPackageBegin - Updates the dependency registration 88 DependencyPlanPackageBegin - Updates the dependency registration
99 action depending on the calculated state for the package. 89 action depending on the calculated state for the package.
100 90
diff --git a/src/engine/detect.cpp b/src/engine/detect.cpp
index 4265cf9b..74e8b9ca 100644
--- a/src/engine/detect.cpp
+++ b/src/engine/detect.cpp
@@ -39,9 +39,9 @@ extern "C" void DetectReset(
39{ 39{
40 RelatedBundlesUninitialize(&pRegistration->relatedBundles); 40 RelatedBundlesUninitialize(&pRegistration->relatedBundles);
41 ReleaseNullStr(pRegistration->sczDetectedProviderKeyBundleId); 41 ReleaseNullStr(pRegistration->sczDetectedProviderKeyBundleId);
42 pRegistration->fEnabledForwardCompatibleBundle = FALSE;
43 PackageUninitialize(&pRegistration->forwardCompatibleBundle);
44 pRegistration->fSelfRegisteredAsDependent = FALSE; 42 pRegistration->fSelfRegisteredAsDependent = FALSE;
43 pRegistration->fParentRegisteredAsDependent = FALSE;
44 pRegistration->fForwardCompatibleBundleExists = FALSE;
45 pRegistration->fEligibleForCleanup = FALSE; 45 pRegistration->fEligibleForCleanup = FALSE;
46 46
47 if (pRegistration->rgIgnoredDependencies) 47 if (pRegistration->rgIgnoredDependencies)
@@ -120,46 +120,20 @@ extern "C" void DetectReset(
120 } 120 }
121} 121}
122 122
123extern "C" HRESULT DetectForwardCompatibleBundle( 123extern "C" HRESULT DetectForwardCompatibleBundles(
124 __in BURN_USER_EXPERIENCE* pUX, 124 __in BURN_USER_EXPERIENCE* pUX,
125 __in BOOTSTRAPPER_COMMAND* pCommand,
126 __in BURN_REGISTRATION* pRegistration 125 __in BURN_REGISTRATION* pRegistration
127 ) 126 )
128{ 127{
129 HRESULT hr = S_OK; 128 HRESULT hr = S_OK;
130 BOOL fRecommendIgnore = TRUE;
131 BOOL fIgnoreBundle = FALSE;
132 int nCompareResult = 0; 129 int nCompareResult = 0;
133 130
134 if (pRegistration->sczDetectedProviderKeyBundleId && 131 if (pRegistration->sczDetectedProviderKeyBundleId &&
135 CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->sczDetectedProviderKeyBundleId, -1, pRegistration->sczId, -1)) 132 CSTR_EQUAL != ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->sczDetectedProviderKeyBundleId, -1, pRegistration->sczId, -1))
136 { 133 {
137 // Only change the recommendation if an active parent was provided.
138 if (pRegistration->sczActiveParent && *pRegistration->sczActiveParent)
139 {
140 // On install, recommend running the forward compatible bundle because there is an active parent. This
141 // will essentially register the parent with the forward compatible bundle.
142 if (BOOTSTRAPPER_ACTION_INSTALL == pCommand->action)
143 {
144 fRecommendIgnore = FALSE;
145 }
146 else if (BOOTSTRAPPER_ACTION_UNINSTALL == pCommand->action ||
147 BOOTSTRAPPER_ACTION_MODIFY == pCommand->action ||
148 BOOTSTRAPPER_ACTION_REPAIR == pCommand->action)
149 {
150 // When modifying the bundle, only recommend running the forward compatible bundle if the parent
151 // is already registered as a dependent of the provider key.
152 if (DependencyDependentExists(pRegistration, pRegistration->sczActiveParent))
153 {
154 fRecommendIgnore = FALSE;
155 }
156 }
157 }
158
159 for (DWORD iRelatedBundle = 0; iRelatedBundle < pRegistration->relatedBundles.cRelatedBundles; ++iRelatedBundle) 134 for (DWORD iRelatedBundle = 0; iRelatedBundle < pRegistration->relatedBundles.cRelatedBundles; ++iRelatedBundle)
160 { 135 {
161 BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + iRelatedBundle; 136 BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + iRelatedBundle;
162 fIgnoreBundle = fRecommendIgnore;
163 137
164 if (BOOTSTRAPPER_RELATION_UPGRADE == pRelatedBundle->relationType && 138 if (BOOTSTRAPPER_RELATION_UPGRADE == pRelatedBundle->relationType &&
165 CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->sczDetectedProviderKeyBundleId, -1, pRelatedBundle->package.sczId, -1)) 139 CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pRegistration->sczDetectedProviderKeyBundleId, -1, pRelatedBundle->package.sczId, -1))
@@ -169,19 +143,13 @@ extern "C" HRESULT DetectForwardCompatibleBundle(
169 143
170 if (nCompareResult <= 0) 144 if (nCompareResult <= 0)
171 { 145 {
172 hr = UserExperienceOnDetectForwardCompatibleBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion, &fIgnoreBundle); 146 pRelatedBundle->fForwardCompatible = TRUE;
173 ExitOnRootFailure(hr, "BA aborted detect forward compatible bundle."); 147 pRegistration->fForwardCompatibleBundleExists = TRUE;
174
175 if (!fIgnoreBundle)
176 {
177 hr = PseudoBundleInitializePassthrough(&pRegistration->forwardCompatibleBundle, pCommand, NULL, pRegistration->sczActiveParent, pRegistration->sczAncestors, &pRelatedBundle->package);
178 ExitOnFailure(hr, "Failed to initialize update bundle.");
179 148
180 pRegistration->fEnabledForwardCompatibleBundle = TRUE; 149 hr = UserExperienceOnDetectForwardCompatibleBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion);
181 } 150 ExitOnRootFailure(hr, "BA aborted detect forward compatible bundle.");
182 151
183 LogId(REPORT_STANDARD, MSG_DETECTED_FORWARD_COMPATIBLE_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), pRelatedBundle->pVersion->sczVersion, LoggingBoolToString(pRegistration->fEnabledForwardCompatibleBundle)); 152 LogId(REPORT_STANDARD, MSG_DETECTED_FORWARD_COMPATIBLE_BUNDLE, pRelatedBundle->package.sczId, LoggingRelationTypeToString(pRelatedBundle->relationType), LoggingPerMachineToString(pRelatedBundle->package.fPerMachine), pRelatedBundle->pVersion->sczVersion);
184 break;
185 } 153 }
186 } 154 }
187 } 155 }
diff --git a/src/engine/detect.h b/src/engine/detect.h
index 7989c9dd..9bc34882 100644
--- a/src/engine/detect.h
+++ b/src/engine/detect.h
@@ -20,9 +20,8 @@ void DetectReset(
20 __in BURN_PACKAGES* pPackages 20 __in BURN_PACKAGES* pPackages
21 ); 21 );
22 22
23HRESULT DetectForwardCompatibleBundle( 23HRESULT DetectForwardCompatibleBundles(
24 __in BURN_USER_EXPERIENCE* pUX, 24 __in BURN_USER_EXPERIENCE* pUX,
25 __in BOOTSTRAPPER_COMMAND* pCommand,
26 __in BURN_REGISTRATION* pRegistration 25 __in BURN_REGISTRATION* pRegistration
27 ); 26 );
28 27
diff --git a/src/engine/engine.mc b/src/engine/engine.mc
index f7b18c59..687d2b60 100644
--- a/src/engine/engine.mc
+++ b/src/engine/engine.mc
@@ -237,7 +237,7 @@ MessageId=107
237Severity=Success 237Severity=Success
238SymbolicName=MSG_DETECTED_FORWARD_COMPATIBLE_BUNDLE 238SymbolicName=MSG_DETECTED_FORWARD_COMPATIBLE_BUNDLE
239Language=English 239Language=English
240Detected forward compatible bundle: %1!ls!, type: %2!hs!, scope: %3!hs!, version: %4!ls!, enabled: %5!hs! 240Detected forward compatible bundle: %1!ls!, type: %2!hs!, scope: %3!hs!, version: %4!ls!
241. 241.
242 242
243MessageId=120 243MessageId=120
diff --git a/src/engine/plan.cpp b/src/engine/plan.cpp
index 4f29209f..87607382 100644
--- a/src/engine/plan.cpp
+++ b/src/engine/plan.cpp
@@ -194,6 +194,8 @@ extern "C" void PlanReset(
194 __in BURN_PACKAGES* pPackages 194 __in BURN_PACKAGES* pPackages
195 ) 195 )
196{ 196{
197 PackageUninitialize(&pPlan->forwardCompatibleBundle);
198
197 if (pPlan->rgRegistrationActions) 199 if (pPlan->rgRegistrationActions)
198 { 200 {
199 for (DWORD i = 0; i < pPlan->cRegistrationActions; ++i) 201 for (DWORD i = 0; i < pPlan->cRegistrationActions; ++i)
@@ -488,6 +490,72 @@ LExit:
488 return hr; 490 return hr;
489} 491}
490 492
493extern "C" HRESULT PlanForwardCompatibleBundles(
494 __in BURN_USER_EXPERIENCE* pUX,
495 __in BOOTSTRAPPER_COMMAND* pCommand,
496 __in BURN_PLAN* pPlan,
497 __in BURN_REGISTRATION* pRegistration,
498 __in BOOTSTRAPPER_ACTION action
499 )
500{
501 HRESULT hr = S_OK;
502 BOOL fRecommendIgnore = TRUE;
503 BOOL fIgnoreBundle = FALSE;
504
505 if (!pRegistration->fForwardCompatibleBundleExists)
506 {
507 ExitFunction();
508 }
509
510 // Only change the recommendation if an active parent was provided.
511 if (pRegistration->sczActiveParent && *pRegistration->sczActiveParent)
512 {
513 // On install, recommend running the forward compatible bundle because there is an active parent. This
514 // will essentially register the parent with the forward compatible bundle.
515 if (BOOTSTRAPPER_ACTION_INSTALL == action)
516 {
517 fRecommendIgnore = FALSE;
518 }
519 else if (BOOTSTRAPPER_ACTION_UNINSTALL == action ||
520 BOOTSTRAPPER_ACTION_MODIFY == action ||
521 BOOTSTRAPPER_ACTION_REPAIR == action)
522 {
523 // When modifying the bundle, only recommend running the forward compatible bundle if the parent
524 // is already registered as a dependent of the provider key.
525 if (pRegistration->fParentRegisteredAsDependent)
526 {
527 fRecommendIgnore = FALSE;
528 }
529 }
530 }
531
532 for (DWORD iRelatedBundle = 0; iRelatedBundle < pRegistration->relatedBundles.cRelatedBundles; ++iRelatedBundle)
533 {
534 BURN_RELATED_BUNDLE* pRelatedBundle = pRegistration->relatedBundles.rgRelatedBundles + iRelatedBundle;
535 if (!pRelatedBundle->fForwardCompatible)
536 {
537 continue;
538 }
539
540 fIgnoreBundle = fRecommendIgnore;
541
542 hr = UserExperienceOnPlanForwardCompatibleBundle(pUX, pRelatedBundle->package.sczId, pRelatedBundle->relationType, pRelatedBundle->sczTag, pRelatedBundle->package.fPerMachine, pRelatedBundle->pVersion, &fIgnoreBundle);
543 ExitOnRootFailure(hr, "BA aborted plan forward compatible bundle.");
544
545 if (!fIgnoreBundle)
546 {
547 hr = PseudoBundleInitializePassthrough(&pPlan->forwardCompatibleBundle, pCommand, NULL, pRegistration->sczActiveParent, pRegistration->sczAncestors, &pRelatedBundle->package);
548 ExitOnFailure(hr, "Failed to initialize pass through bundle.");
549
550 pPlan->fEnabledForwardCompatibleBundle = TRUE;
551 break;
552 }
553 }
554
555LExit:
556 return hr;
557}
558
491extern "C" HRESULT PlanPackages( 559extern "C" HRESULT PlanPackages(
492 __in BURN_USER_EXPERIENCE* pUX, 560 __in BURN_USER_EXPERIENCE* pUX,
493 __in BURN_PACKAGES* pPackages, 561 __in BURN_PACKAGES* pPackages,
diff --git a/src/engine/plan.h b/src/engine/plan.h
index c679d368..e72186c7 100644
--- a/src/engine/plan.h
+++ b/src/engine/plan.h
@@ -322,6 +322,9 @@ typedef struct _BURN_PLAN
322 DWORD cExecutePackagesTotal; 322 DWORD cExecutePackagesTotal;
323 DWORD cOverallProgressTicksTotal; 323 DWORD cOverallProgressTicksTotal;
324 324
325 BOOL fEnabledForwardCompatibleBundle;
326 BURN_PACKAGE forwardCompatibleBundle;
327
325 BURN_DEPENDENCY_REGISTRATION_ACTION dependencyRegistrationAction; 328 BURN_DEPENDENCY_REGISTRATION_ACTION dependencyRegistrationAction;
326 329
327 BURN_DEPENDENT_REGISTRATION_ACTION* rgRegistrationActions; 330 BURN_DEPENDENT_REGISTRATION_ACTION* rgRegistrationActions;
@@ -392,6 +395,13 @@ HRESULT PlanLayoutBundle(
392 __in BURN_PAYLOADS* pPayloads, 395 __in BURN_PAYLOADS* pPayloads,
393 __out_z LPWSTR* psczLayoutDirectory 396 __out_z LPWSTR* psczLayoutDirectory
394 ); 397 );
398HRESULT PlanForwardCompatibleBundles(
399 __in BURN_USER_EXPERIENCE* pUX,
400 __in BOOTSTRAPPER_COMMAND* pCommand,
401 __in BURN_PLAN* pPlan,
402 __in BURN_REGISTRATION* pRegistration,
403 __in BOOTSTRAPPER_ACTION action
404 );
395HRESULT PlanPackages( 405HRESULT PlanPackages(
396 __in BURN_USER_EXPERIENCE* pUX, 406 __in BURN_USER_EXPERIENCE* pUX,
397 __in BURN_PACKAGES* pPackages, 407 __in BURN_PACKAGES* pPackages,
diff --git a/src/engine/registration.h b/src/engine/registration.h
index 4aca5a05..bb87b6e9 100644
--- a/src/engine/registration.h
+++ b/src/engine/registration.h
@@ -58,6 +58,7 @@ typedef struct _BURN_UPDATE_REGISTRATION
58typedef struct _BURN_RELATED_BUNDLE 58typedef struct _BURN_RELATED_BUNDLE
59{ 59{
60 BOOTSTRAPPER_RELATION_TYPE relationType; 60 BOOTSTRAPPER_RELATION_TYPE relationType;
61 BOOL fForwardCompatible;
61 62
62 VERUTIL_VERSION* pVersion; 63 VERUTIL_VERSION* pVersion;
63 LPWSTR sczTag; 64 LPWSTR sczTag;
@@ -146,14 +147,13 @@ typedef struct _BURN_REGISTRATION
146 UINT cDependents; // Only valid after detect. 147 UINT cDependents; // Only valid after detect.
147 LPCWSTR wzSelfDependent; // Only valid after detect. 148 LPCWSTR wzSelfDependent; // Only valid after detect.
148 BOOL fSelfRegisteredAsDependent; // Only valid after detect. 149 BOOL fSelfRegisteredAsDependent; // Only valid after detect.
150 BOOL fParentRegisteredAsDependent; // Only valid after detect.
151 BOOL fForwardCompatibleBundleExists; // Only valid after detect.
149 BOOL fEligibleForCleanup; // Only valid after detect. 152 BOOL fEligibleForCleanup; // Only valid after detect.
150 153
151 LPWSTR sczDetectedProviderKeyBundleId; 154 LPWSTR sczDetectedProviderKeyBundleId;
152 LPWSTR sczAncestors; 155 LPWSTR sczAncestors;
153 LPWSTR sczBundlePackageAncestors; 156 LPWSTR sczBundlePackageAncestors;
154
155 BOOL fEnabledForwardCompatibleBundle;
156 BURN_PACKAGE forwardCompatibleBundle;
157} BURN_REGISTRATION; 157} BURN_REGISTRATION;
158 158
159 159
diff --git a/src/engine/userexperience.cpp b/src/engine/userexperience.cpp
index 40a30c5d..e1e32a87 100644
--- a/src/engine/userexperience.cpp
+++ b/src/engine/userexperience.cpp
@@ -763,8 +763,7 @@ EXTERN_C BAAPI UserExperienceOnDetectForwardCompatibleBundle(
763 __in BOOTSTRAPPER_RELATION_TYPE relationType, 763 __in BOOTSTRAPPER_RELATION_TYPE relationType,
764 __in_z LPCWSTR wzBundleTag, 764 __in_z LPCWSTR wzBundleTag,
765 __in BOOL fPerMachine, 765 __in BOOL fPerMachine,
766 __in VERUTIL_VERSION* pVersion, 766 __in VERUTIL_VERSION* pVersion
767 __inout BOOL* pfIgnoreBundle
768 ) 767 )
769{ 768{
770 HRESULT hr = S_OK; 769 HRESULT hr = S_OK;
@@ -779,7 +778,6 @@ EXTERN_C BAAPI UserExperienceOnDetectForwardCompatibleBundle(
779 args.wzVersion = pVersion->sczVersion; 778 args.wzVersion = pVersion->sczVersion;
780 779
781 results.cbSize = sizeof(results); 780 results.cbSize = sizeof(results);
782 results.fIgnoreBundle = *pfIgnoreBundle;
783 781
784 hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTFORWARDCOMPATIBLEBUNDLE, &args, &results); 782 hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTFORWARDCOMPATIBLEBUNDLE, &args, &results);
785 ExitOnFailure(hr, "BA OnDetectForwardCompatibleBundle failed."); 783 ExitOnFailure(hr, "BA OnDetectForwardCompatibleBundle failed.");
@@ -788,7 +786,6 @@ EXTERN_C BAAPI UserExperienceOnDetectForwardCompatibleBundle(
788 { 786 {
789 hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT); 787 hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);
790 } 788 }
791 *pfIgnoreBundle = results.fIgnoreBundle;
792 789
793LExit: 790LExit:
794 return hr; 791 return hr;
@@ -1567,6 +1564,44 @@ LExit:
1567 return hr; 1564 return hr;
1568} 1565}
1569 1566
1567EXTERN_C BAAPI UserExperienceOnPlanForwardCompatibleBundle(
1568 __in BURN_USER_EXPERIENCE* pUserExperience,
1569 __in_z LPCWSTR wzBundleId,
1570 __in BOOTSTRAPPER_RELATION_TYPE relationType,
1571 __in_z LPCWSTR wzBundleTag,
1572 __in BOOL fPerMachine,
1573 __in VERUTIL_VERSION* pVersion,
1574 __inout BOOL* pfIgnoreBundle
1575 )
1576{
1577 HRESULT hr = S_OK;
1578 BA_ONPLANFORWARDCOMPATIBLEBUNDLE_ARGS args = { };
1579 BA_ONPLANFORWARDCOMPATIBLEBUNDLE_RESULTS results = { };
1580
1581 args.cbSize = sizeof(args);
1582 args.wzBundleId = wzBundleId;
1583 args.relationType = relationType;
1584 args.wzBundleTag = wzBundleTag;
1585 args.fPerMachine = fPerMachine;
1586 args.wzVersion = pVersion->sczVersion;
1587 args.fRecommendedIgnoreBundle = *pfIgnoreBundle;
1588
1589 results.cbSize = sizeof(results);
1590 results.fIgnoreBundle = *pfIgnoreBundle;
1591
1592 hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANFORWARDCOMPATIBLEBUNDLE, &args, &results);
1593 ExitOnFailure(hr, "BA OnPlanForwardCompatibleBundle failed.");
1594
1595 if (results.fCancel)
1596 {
1597 hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);
1598 }
1599 *pfIgnoreBundle = results.fIgnoreBundle;
1600
1601LExit:
1602 return hr;
1603}
1604
1570EXTERN_C BAAPI UserExperienceOnPlanMsiPackage( 1605EXTERN_C BAAPI UserExperienceOnPlanMsiPackage(
1571 __in BURN_USER_EXPERIENCE* pUserExperience, 1606 __in BURN_USER_EXPERIENCE* pUserExperience,
1572 __in_z LPCWSTR wzPackageId, 1607 __in_z LPCWSTR wzPackageId,
diff --git a/src/engine/userexperience.h b/src/engine/userexperience.h
index 754a9030..eccc0786 100644
--- a/src/engine/userexperience.h
+++ b/src/engine/userexperience.h
@@ -200,8 +200,7 @@ BAAPI UserExperienceOnDetectForwardCompatibleBundle(
200 __in BOOTSTRAPPER_RELATION_TYPE relationType, 200 __in BOOTSTRAPPER_RELATION_TYPE relationType,
201 __in_z LPCWSTR wzBundleTag, 201 __in_z LPCWSTR wzBundleTag,
202 __in BOOL fPerMachine, 202 __in BOOL fPerMachine,
203 __in VERUTIL_VERSION* pVersion, 203 __in VERUTIL_VERSION* pVersion
204 __inout BOOL* pfIgnoreBundle
205 ); 204 );
206BAAPI UserExperienceOnDetectMsiFeature( 205BAAPI UserExperienceOnDetectMsiFeature(
207 __in BURN_USER_EXPERIENCE* pUserExperience, 206 __in BURN_USER_EXPERIENCE* pUserExperience,
@@ -357,6 +356,15 @@ BAAPI UserExperienceOnPlanComplete(
357 __in BURN_USER_EXPERIENCE* pUserExperience, 356 __in BURN_USER_EXPERIENCE* pUserExperience,
358 __in HRESULT hrStatus 357 __in HRESULT hrStatus
359 ); 358 );
359BAAPI UserExperienceOnPlanForwardCompatibleBundle(
360 __in BURN_USER_EXPERIENCE* pUserExperience,
361 __in_z LPCWSTR wzBundleId,
362 __in BOOTSTRAPPER_RELATION_TYPE relationType,
363 __in_z LPCWSTR wzBundleTag,
364 __in BOOL fPerMachine,
365 __in VERUTIL_VERSION* pVersion,
366 __inout BOOL* pfIgnoreBundle
367 );
360BAAPI UserExperienceOnPlanMsiFeature( 368BAAPI UserExperienceOnPlanMsiFeature(
361 __in BURN_USER_EXPERIENCE* pUserExperience, 369 __in BURN_USER_EXPERIENCE* pUserExperience,
362 __in_z LPCWSTR wzPackageId, 370 __in_z LPCWSTR wzPackageId,