aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-01-16 16:35:36 -0600
committerSean Hall <r.sean.hall@gmail.com>2022-01-16 22:59:50 -0600
commit5ed5a24fae06b35351235d708b6ab410d8310d33 (patch)
tree1b3e15d3d1fdb5b81c2bb8095f64c8f40a44c464 /src
parenteee408f4f52823038ca6da83693efd135c8511c8 (diff)
downloadwix-5ed5a24fae06b35351235d708b6ab410d8310d33.tar.gz
wix-5ed5a24fae06b35351235d708b6ab410d8310d33.tar.bz2
wix-5ed5a24fae06b35351235d708b6ab410d8310d33.zip
Add BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT.
Make BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT uninstall even if detected absent. Remove fPseudoBundle.
Diffstat (limited to 'src')
-rw-r--r--src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperEngine.h1
-rw-r--r--src/api/burn/WixToolset.Mba.Core/IBootstrapperEngine.cs5
-rw-r--r--src/burn/engine/bundlepackageengine.cpp11
-rw-r--r--src/burn/engine/exeengine.cpp11
-rw-r--r--src/burn/engine/logging.cpp2
-rw-r--r--src/burn/engine/msiengine.cpp36
-rw-r--r--src/burn/engine/mspengine.cpp29
-rw-r--r--src/burn/engine/msuengine.cpp10
-rw-r--r--src/burn/engine/package.h3
-rw-r--r--src/burn/engine/plan.cpp58
-rw-r--r--src/burn/engine/pseudobundle.cpp5
-rw-r--r--src/burn/test/BurnUnitTest/PlanTest.cpp183
12 files changed, 308 insertions, 46 deletions
diff --git a/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperEngine.h b/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperEngine.h
index 56405685..d45c7b2a 100644
--- a/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperEngine.h
+++ b/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperEngine.h
@@ -57,6 +57,7 @@ enum BOOTSTRAPPER_REQUEST_STATE
57 BOOTSTRAPPER_REQUEST_STATE_ABSENT, 57 BOOTSTRAPPER_REQUEST_STATE_ABSENT,
58 BOOTSTRAPPER_REQUEST_STATE_CACHE, 58 BOOTSTRAPPER_REQUEST_STATE_CACHE,
59 BOOTSTRAPPER_REQUEST_STATE_PRESENT, 59 BOOTSTRAPPER_REQUEST_STATE_PRESENT,
60 BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT,
60 BOOTSTRAPPER_REQUEST_STATE_REPAIR, 61 BOOTSTRAPPER_REQUEST_STATE_REPAIR,
61}; 62};
62 63
diff --git a/src/api/burn/WixToolset.Mba.Core/IBootstrapperEngine.cs b/src/api/burn/WixToolset.Mba.Core/IBootstrapperEngine.cs
index 681c6f2c..8ead0919 100644
--- a/src/api/burn/WixToolset.Mba.Core/IBootstrapperEngine.cs
+++ b/src/api/burn/WixToolset.Mba.Core/IBootstrapperEngine.cs
@@ -490,6 +490,11 @@ namespace WixToolset.Mba.Core
490 /// <summary> 490 /// <summary>
491 /// 491 ///
492 /// </summary> 492 /// </summary>
493 ForcePresent,
494
495 /// <summary>
496 ///
497 /// </summary>
493 Repair, 498 Repair,
494 } 499 }
495 500
diff --git a/src/burn/engine/bundlepackageengine.cpp b/src/burn/engine/bundlepackageengine.cpp
index ece0fc3a..cd84601f 100644
--- a/src/burn/engine/bundlepackageengine.cpp
+++ b/src/burn/engine/bundlepackageengine.cpp
@@ -48,7 +48,7 @@ extern "C" HRESULT BundlePackageEnginePlanCalculatePackage(
48 switch (pPackage->requested) 48 switch (pPackage->requested)
49 { 49 {
50 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: 50 case BOOTSTRAPPER_REQUEST_STATE_PRESENT:
51 execute = pPackage->Bundle.fPseudoBundle ? BOOTSTRAPPER_ACTION_STATE_INSTALL : BOOTSTRAPPER_ACTION_STATE_NONE; 51 execute = BOOTSTRAPPER_ACTION_STATE_NONE;
52 break; 52 break;
53 case BOOTSTRAPPER_REQUEST_STATE_REPAIR: 53 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
54 execute = pPackage->Bundle.fRepairable ? BOOTSTRAPPER_ACTION_STATE_REPAIR : BOOTSTRAPPER_ACTION_STATE_NONE; 54 execute = pPackage->Bundle.fRepairable ? BOOTSTRAPPER_ACTION_STATE_REPAIR : BOOTSTRAPPER_ACTION_STATE_NONE;
@@ -60,6 +60,9 @@ extern "C" HRESULT BundlePackageEnginePlanCalculatePackage(
60 case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT: 60 case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT:
61 execute = BOOTSTRAPPER_ACTION_STATE_UNINSTALL; 61 execute = BOOTSTRAPPER_ACTION_STATE_UNINSTALL;
62 break; 62 break;
63 case BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT:
64 execute = BOOTSTRAPPER_ACTION_STATE_INSTALL;
65 break;
63 default: 66 default:
64 execute = BOOTSTRAPPER_ACTION_STATE_NONE; 67 execute = BOOTSTRAPPER_ACTION_STATE_NONE;
65 break; 68 break;
@@ -70,9 +73,13 @@ extern "C" HRESULT BundlePackageEnginePlanCalculatePackage(
70 switch (pPackage->requested) 73 switch (pPackage->requested)
71 { 74 {
72 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; 75 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
76 case BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT: __fallthrough;
73 case BOOTSTRAPPER_REQUEST_STATE_REPAIR: 77 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
74 execute = BOOTSTRAPPER_ACTION_STATE_INSTALL; 78 execute = BOOTSTRAPPER_ACTION_STATE_INSTALL;
75 break; 79 break;
80 case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT:
81 execute = BOOTSTRAPPER_ACTION_STATE_UNINSTALL;
82 break;
76 default: 83 default:
77 execute = BOOTSTRAPPER_ACTION_STATE_NONE; 84 execute = BOOTSTRAPPER_ACTION_STATE_NONE;
78 break; 85 break;
@@ -93,6 +100,7 @@ extern "C" HRESULT BundlePackageEnginePlanCalculatePackage(
93 switch (pPackage->requested) 100 switch (pPackage->requested)
94 { 101 {
95 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; 102 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
103 case BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT: __fallthrough;
96 case BOOTSTRAPPER_REQUEST_STATE_REPAIR: 104 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
97 rollback = BOOTSTRAPPER_ACTION_STATE_NONE; 105 rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
98 break; 106 break;
@@ -110,6 +118,7 @@ extern "C" HRESULT BundlePackageEnginePlanCalculatePackage(
110 switch (pPackage->requested) 118 switch (pPackage->requested)
111 { 119 {
112 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; 120 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
121 case BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT: __fallthrough;
113 case BOOTSTRAPPER_REQUEST_STATE_REPAIR: 122 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
114 rollback = !pPackage->fPermanent ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE; 123 rollback = !pPackage->fPermanent ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
115 break; 124 break;
diff --git a/src/burn/engine/exeengine.cpp b/src/burn/engine/exeengine.cpp
index cf10448f..b13650e5 100644
--- a/src/burn/engine/exeengine.cpp
+++ b/src/burn/engine/exeengine.cpp
@@ -165,7 +165,7 @@ extern "C" HRESULT ExeEnginePlanCalculatePackage(
165 switch (pPackage->requested) 165 switch (pPackage->requested)
166 { 166 {
167 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: 167 case BOOTSTRAPPER_REQUEST_STATE_PRESENT:
168 execute = pPackage->Exe.fPseudoBundle ? BOOTSTRAPPER_ACTION_STATE_INSTALL : BOOTSTRAPPER_ACTION_STATE_NONE; 168 execute = BOOTSTRAPPER_ACTION_STATE_NONE;
169 break; 169 break;
170 case BOOTSTRAPPER_REQUEST_STATE_REPAIR: 170 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
171 execute = pPackage->Exe.fRepairable ? BOOTSTRAPPER_ACTION_STATE_REPAIR : BOOTSTRAPPER_ACTION_STATE_NONE; 171 execute = pPackage->Exe.fRepairable ? BOOTSTRAPPER_ACTION_STATE_REPAIR : BOOTSTRAPPER_ACTION_STATE_NONE;
@@ -177,6 +177,9 @@ extern "C" HRESULT ExeEnginePlanCalculatePackage(
177 case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT: 177 case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT:
178 execute = pPackage->Exe.fUninstallable ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE; 178 execute = pPackage->Exe.fUninstallable ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
179 break; 179 break;
180 case BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT:
181 execute = BOOTSTRAPPER_ACTION_STATE_INSTALL;
182 break;
180 default: 183 default:
181 execute = BOOTSTRAPPER_ACTION_STATE_NONE; 184 execute = BOOTSTRAPPER_ACTION_STATE_NONE;
182 break; 185 break;
@@ -187,9 +190,13 @@ extern "C" HRESULT ExeEnginePlanCalculatePackage(
187 switch (pPackage->requested) 190 switch (pPackage->requested)
188 { 191 {
189 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; 192 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
193 case BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT: __fallthrough;
190 case BOOTSTRAPPER_REQUEST_STATE_REPAIR: 194 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
191 execute = BOOTSTRAPPER_ACTION_STATE_INSTALL; 195 execute = BOOTSTRAPPER_ACTION_STATE_INSTALL;
192 break; 196 break;
197 case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT:
198 execute = pPackage->Exe.fUninstallable ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
199 break;
193 default: 200 default:
194 execute = BOOTSTRAPPER_ACTION_STATE_NONE; 201 execute = BOOTSTRAPPER_ACTION_STATE_NONE;
195 break; 202 break;
@@ -210,6 +217,7 @@ extern "C" HRESULT ExeEnginePlanCalculatePackage(
210 switch (pPackage->requested) 217 switch (pPackage->requested)
211 { 218 {
212 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; 219 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
220 case BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT: __fallthrough;
213 case BOOTSTRAPPER_REQUEST_STATE_REPAIR: 221 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
214 rollback = BOOTSTRAPPER_ACTION_STATE_NONE; 222 rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
215 break; 223 break;
@@ -227,6 +235,7 @@ extern "C" HRESULT ExeEnginePlanCalculatePackage(
227 switch (pPackage->requested) 235 switch (pPackage->requested)
228 { 236 {
229 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; 237 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
238 case BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT: __fallthrough;
230 case BOOTSTRAPPER_REQUEST_STATE_REPAIR: 239 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
231 rollback = !pPackage->fPermanent ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE; 240 rollback = !pPackage->fPermanent ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
232 break; 241 break;
diff --git a/src/burn/engine/logging.cpp b/src/burn/engine/logging.cpp
index 7c048523..c5dd0ed8 100644
--- a/src/burn/engine/logging.cpp
+++ b/src/burn/engine/logging.cpp
@@ -779,6 +779,8 @@ extern "C" LPCSTR LoggingRequestStateToString(
779 return "Cache"; 779 return "Cache";
780 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: 780 case BOOTSTRAPPER_REQUEST_STATE_PRESENT:
781 return "Present"; 781 return "Present";
782 case BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT:
783 return "ForcePresent";
782 case BOOTSTRAPPER_REQUEST_STATE_REPAIR: 784 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
783 return "Repair"; 785 return "Repair";
784 default: 786 default:
diff --git a/src/burn/engine/msiengine.cpp b/src/burn/engine/msiengine.cpp
index 9dd2312e..e3a80c9f 100644
--- a/src/burn/engine/msiengine.cpp
+++ b/src/burn/engine/msiengine.cpp
@@ -920,6 +920,10 @@ extern "C" HRESULT MsiEnginePlanCalculatePackage(
920 { 920 {
921 execute = BOOTSTRAPPER_ACTION_STATE_UNINSTALL; 921 execute = BOOTSTRAPPER_ACTION_STATE_UNINSTALL;
922 } 922 }
923 else if (BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT == pPackage->requested)
924 {
925 execute = BOOTSTRAPPER_ACTION_STATE_INSTALL;
926 }
923 else 927 else
924 { 928 {
925 execute = BOOTSTRAPPER_ACTION_STATE_NONE; 929 execute = BOOTSTRAPPER_ACTION_STATE_NONE;
@@ -931,10 +935,15 @@ extern "C" HRESULT MsiEnginePlanCalculatePackage(
931 switch (pPackage->requested) 935 switch (pPackage->requested)
932 { 936 {
933 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; 937 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
938 case BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT: __fallthrough;
934 case BOOTSTRAPPER_REQUEST_STATE_REPAIR: 939 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
935 execute = BOOTSTRAPPER_ACTION_STATE_INSTALL; 940 execute = BOOTSTRAPPER_ACTION_STATE_INSTALL;
936 break; 941 break;
937 942
943 case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT:
944 execute = BOOTSTRAPPER_ACTION_STATE_UNINSTALL;
945 break;
946
938 default: 947 default:
939 execute = BOOTSTRAPPER_ACTION_STATE_NONE; 948 execute = BOOTSTRAPPER_ACTION_STATE_NONE;
940 break; 949 break;
@@ -958,6 +967,7 @@ extern "C" HRESULT MsiEnginePlanCalculatePackage(
958 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: 967 case BOOTSTRAPPER_REQUEST_STATE_PRESENT:
959 rollback = fRollbackFeatureActionDelta ? BOOTSTRAPPER_ACTION_STATE_MODIFY : BOOTSTRAPPER_ACTION_STATE_NONE; 968 rollback = fRollbackFeatureActionDelta ? BOOTSTRAPPER_ACTION_STATE_MODIFY : BOOTSTRAPPER_ACTION_STATE_NONE;
960 break; 969 break;
970 case BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT: __fallthrough;
961 case BOOTSTRAPPER_REQUEST_STATE_REPAIR: 971 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
962 rollback = BOOTSTRAPPER_ACTION_STATE_NONE; 972 rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
963 break; 973 break;
@@ -972,11 +982,12 @@ extern "C" HRESULT MsiEnginePlanCalculatePackage(
972 break; 982 break;
973 983
974 case BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE: __fallthrough; 984 case BOOTSTRAPPER_PACKAGE_STATE_OBSOLETE: __fallthrough;
975 case BOOTSTRAPPER_PACKAGE_STATE_ABSENT: __fallthrough; 985 case BOOTSTRAPPER_PACKAGE_STATE_ABSENT:
976 // If the package is not permanent and we requested to put the package on the machine then 986 // If the package is not permanent and we requested to put the package on the machine then
977 // remove the package during rollback. 987 // remove the package during rollback.
978 if (!pPackage->fPermanent && 988 if (!pPackage->fPermanent &&
979 (BOOTSTRAPPER_REQUEST_STATE_PRESENT == pPackage->requested || 989 (BOOTSTRAPPER_REQUEST_STATE_PRESENT == pPackage->requested ||
990 BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT == pPackage->requested ||
980 BOOTSTRAPPER_REQUEST_STATE_REPAIR == pPackage->requested)) 991 BOOTSTRAPPER_REQUEST_STATE_REPAIR == pPackage->requested))
981 { 992 {
982 rollback = BOOTSTRAPPER_ACTION_STATE_UNINSTALL; 993 rollback = BOOTSTRAPPER_ACTION_STATE_UNINSTALL;
@@ -1040,6 +1051,18 @@ extern "C" HRESULT MsiEnginePlanAddPackage(
1040 hr = DependencyPlanPackage(NULL, pPackage, pPlan); 1051 hr = DependencyPlanPackage(NULL, pPackage, pPlan);
1041 ExitOnFailure(hr, "Failed to plan package dependency actions."); 1052 ExitOnFailure(hr, "Failed to plan package dependency actions.");
1042 1053
1054 if (pPackage->compatiblePackage.fRemove)
1055 {
1056 hr = PlanAppendExecuteAction(pPlan, &pAction);
1057 ExitOnFailure(hr, "Failed to append execute action.");
1058
1059 pAction->type = BURN_EXECUTE_ACTION_TYPE_UNINSTALL_MSI_COMPATIBLE_PACKAGE;
1060 pAction->uninstallMsiCompatiblePackage.pParentPackage = pPackage;
1061 pAction->uninstallMsiCompatiblePackage.dwLoggingAttributes = pLog->dwAttributes;
1062
1063 LoggingSetCompatiblePackageVariable(pPackage, pLog, pVariables, &pAction->uninstallMsiCompatiblePackage.sczLogPath); // ignore errors.
1064 }
1065
1043 // add rollback action 1066 // add rollback action
1044 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->rollback) 1067 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->rollback)
1045 { 1068 {
@@ -1085,17 +1108,6 @@ extern "C" HRESULT MsiEnginePlanAddPackage(
1085 LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, &pAction->msiPackage.sczLogPath); // ignore errors. 1108 LoggingSetPackageVariable(pPackage, NULL, FALSE, pLog, pVariables, &pAction->msiPackage.sczLogPath); // ignore errors.
1086 pAction->msiPackage.dwLoggingAttributes = pLog->dwAttributes; 1109 pAction->msiPackage.dwLoggingAttributes = pLog->dwAttributes;
1087 } 1110 }
1088 else if (pPackage->compatiblePackage.fRemove)
1089 {
1090 hr = PlanAppendExecuteAction(pPlan, &pAction);
1091 ExitOnFailure(hr, "Failed to append execute action.");
1092
1093 pAction->type = BURN_EXECUTE_ACTION_TYPE_UNINSTALL_MSI_COMPATIBLE_PACKAGE;
1094 pAction->uninstallMsiCompatiblePackage.pParentPackage = pPackage;
1095 pAction->uninstallMsiCompatiblePackage.dwLoggingAttributes = pLog->dwAttributes;
1096
1097 LoggingSetCompatiblePackageVariable(pPackage, pLog, pVariables, &pAction->uninstallMsiCompatiblePackage.sczLogPath); // ignore errors.
1098 }
1099 1111
1100LExit: 1112LExit:
1101 ReleaseMem(rgFeatureActions); 1113 ReleaseMem(rgFeatureActions);
diff --git a/src/burn/engine/mspengine.cpp b/src/burn/engine/mspengine.cpp
index bc6a482a..7403e78c 100644
--- a/src/burn/engine/mspengine.cpp
+++ b/src/burn/engine/mspengine.cpp
@@ -404,6 +404,11 @@ extern "C" HRESULT MspEnginePlanCalculatePackage(
404 execute = BOOTSTRAPPER_ACTION_STATE_UNINSTALL; 404 execute = BOOTSTRAPPER_ACTION_STATE_UNINSTALL;
405 break; 405 break;
406 406
407 case BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT:
408 execute = BOOTSTRAPPER_ACTION_STATE_INSTALL;
409 fWillUninstallAll = FALSE;
410 break;
411
407 default: 412 default:
408 execute = BOOTSTRAPPER_ACTION_STATE_NONE; 413 execute = BOOTSTRAPPER_ACTION_STATE_NONE;
409 fWillUninstallAll = FALSE; 414 fWillUninstallAll = FALSE;
@@ -415,11 +420,16 @@ extern "C" HRESULT MspEnginePlanCalculatePackage(
415 switch (pTargetProduct->requested) 420 switch (pTargetProduct->requested)
416 { 421 {
417 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; 422 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
423 case BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT: __fallthrough;
418 case BOOTSTRAPPER_REQUEST_STATE_REPAIR: 424 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
419 execute = BOOTSTRAPPER_ACTION_STATE_INSTALL; 425 execute = BOOTSTRAPPER_ACTION_STATE_INSTALL;
420 fWillUninstallAll = FALSE; 426 fWillUninstallAll = FALSE;
421 break; 427 break;
422 428
429 case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT:
430 execute = BOOTSTRAPPER_ACTION_STATE_UNINSTALL;
431 break;
432
423 default: 433 default:
424 execute = BOOTSTRAPPER_ACTION_STATE_NONE; 434 execute = BOOTSTRAPPER_ACTION_STATE_NONE;
425 break; 435 break;
@@ -427,9 +437,25 @@ extern "C" HRESULT MspEnginePlanCalculatePackage(
427 break; 437 break;
428 438
429 default: 439 default:
430 if (pTargetProduct->fInstalled) 440 switch (pTargetProduct->requested)
431 { 441 {
442 case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT:
443 execute = BOOTSTRAPPER_ACTION_STATE_UNINSTALL;
444 break;
445
446 case BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT:
447 execute = BOOTSTRAPPER_ACTION_STATE_INSTALL;
432 fWillUninstallAll = FALSE; 448 fWillUninstallAll = FALSE;
449 break;
450
451 default:
452 execute = BOOTSTRAPPER_ACTION_STATE_NONE;
453
454 if (pTargetProduct->fInstalled)
455 {
456 fWillUninstallAll = FALSE;
457 }
458 break;
433 } 459 }
434 break; 460 break;
435 } 461 }
@@ -457,6 +483,7 @@ extern "C" HRESULT MspEnginePlanCalculatePackage(
457 switch (pTargetProduct->requested) 483 switch (pTargetProduct->requested)
458 { 484 {
459 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; 485 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
486 case BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT: __fallthrough;
460 case BOOTSTRAPPER_REQUEST_STATE_REPAIR: 487 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
461 rollback = !pPackage->fPermanent ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE; 488 rollback = !pPackage->fPermanent ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
462 break; 489 break;
diff --git a/src/burn/engine/msuengine.cpp b/src/burn/engine/msuengine.cpp
index 44386a6d..091bbe62 100644
--- a/src/burn/engine/msuengine.cpp
+++ b/src/burn/engine/msuengine.cpp
@@ -124,6 +124,10 @@ extern "C" HRESULT MsuEnginePlanCalculatePackage(
124 execute = pPackage->Msu.fUninstallable ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE; 124 execute = pPackage->Msu.fUninstallable ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
125 break; 125 break;
126 126
127 case BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT:
128 execute = BOOTSTRAPPER_ACTION_STATE_INSTALL;
129 break;
130
127 default: 131 default:
128 execute = BOOTSTRAPPER_ACTION_STATE_NONE; 132 execute = BOOTSTRAPPER_ACTION_STATE_NONE;
129 break; 133 break;
@@ -134,10 +138,15 @@ extern "C" HRESULT MsuEnginePlanCalculatePackage(
134 switch (pPackage->requested) 138 switch (pPackage->requested)
135 { 139 {
136 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; 140 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
141 case BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT: __fallthrough;
137 case BOOTSTRAPPER_REQUEST_STATE_REPAIR: 142 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
138 execute = BOOTSTRAPPER_ACTION_STATE_INSTALL; 143 execute = BOOTSTRAPPER_ACTION_STATE_INSTALL;
139 break; 144 break;
140 145
146 case BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT:
147 execute = pPackage->Msu.fUninstallable ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
148 break;
149
141 default: 150 default:
142 execute = BOOTSTRAPPER_ACTION_STATE_NONE; 151 execute = BOOTSTRAPPER_ACTION_STATE_NONE;
143 break; 152 break;
@@ -172,6 +181,7 @@ extern "C" HRESULT MsuEnginePlanCalculatePackage(
172 switch (pPackage->requested) 181 switch (pPackage->requested)
173 { 182 {
174 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough; 183 case BOOTSTRAPPER_REQUEST_STATE_PRESENT: __fallthrough;
184 case BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT: __fallthrough;
175 case BOOTSTRAPPER_REQUEST_STATE_REPAIR: 185 case BOOTSTRAPPER_REQUEST_STATE_REPAIR:
176 rollback = !pPackage->fPermanent ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE; 186 rollback = !pPackage->fPermanent ? BOOTSTRAPPER_ACTION_STATE_UNINSTALL : BOOTSTRAPPER_ACTION_STATE_NONE;
177 break; 187 break;
diff --git a/src/burn/engine/package.h b/src/burn/engine/package.h
index bbd74ac9..eb812e20 100644
--- a/src/burn/engine/package.h
+++ b/src/burn/engine/package.h
@@ -303,7 +303,6 @@ typedef struct _BURN_PACKAGE
303 LPCWSTR wzAncestors; // points directly into engine state. 303 LPCWSTR wzAncestors; // points directly into engine state.
304 LPCWSTR wzEngineWorkingDirectory; // points directly into engine state. 304 LPCWSTR wzEngineWorkingDirectory; // points directly into engine state.
305 305
306 BOOL fPseudoBundle;
307 BOOL fRepairable; 306 BOOL fRepairable;
308 BOOL fSupportsBurnProtocol; 307 BOOL fSupportsBurnProtocol;
309 308
@@ -320,7 +319,7 @@ typedef struct _BURN_PACKAGE
320 LPWSTR sczRepairArguments; 319 LPWSTR sczRepairArguments;
321 LPWSTR sczUninstallArguments; 320 LPWSTR sczUninstallArguments;
322 321
323 BOOL fPseudoBundle; 322 BOOL fPseudoPackage;
324 BOOL fFireAndForget; 323 BOOL fFireAndForget;
325 BOOL fRepairable; 324 BOOL fRepairable;
326 BOOL fUninstallable; 325 BOOL fUninstallable;
diff --git a/src/burn/engine/plan.cpp b/src/burn/engine/plan.cpp
index b714aab8..2649ee39 100644
--- a/src/burn/engine/plan.cpp
+++ b/src/burn/engine/plan.cpp
@@ -9,6 +9,10 @@
9 9
10// internal function definitions 10// internal function definitions
11 11
12static void PlannedExecutePackage(
13 __in BURN_PLAN* pPlan,
14 __in BURN_PACKAGE* pPackage
15 );
12static void UninitializeRegistrationAction( 16static void UninitializeRegistrationAction(
13 __in BURN_DEPENDENT_REGISTRATION_ACTION* pAction 17 __in BURN_DEPENDENT_REGISTRATION_ACTION* pAction
14 ); 18 );
@@ -855,13 +859,13 @@ static HRESULT InitializePackage(
855 BOOL fBeginCalled = FALSE; 859 BOOL fBeginCalled = FALSE;
856 BOOTSTRAPPER_RELATION_TYPE relationType = pPlan->pCommand->relationType; 860 BOOTSTRAPPER_RELATION_TYPE relationType = pPlan->pCommand->relationType;
857 861
858 if (BURN_PACKAGE_TYPE_EXE == pPackage->type && pPackage->Exe.fPseudoBundle) 862 if (BURN_PACKAGE_TYPE_EXE == pPackage->type && pPackage->Exe.fPseudoPackage)
859 { 863 {
860 // Exe pseudo bundles are not configurable. 864 // Exe pseudo packages are not configurable.
861 // The BA already requested this package to be executed 865 // The BA already requested this package to be executed
862 // * by the overall plan action for UpdateReplace 866 // * by the overall plan action for UpdateReplace
863 // * by enabling the forward compatible bundle for Passthrough 867 // * by enabling the forward compatible bundle for Passthrough
864 pPackage->defaultRequested = pPackage->requested = BOOTSTRAPPER_REQUEST_STATE_PRESENT; 868 pPackage->defaultRequested = pPackage->requested = BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT;
865 ExitFunction(); 869 ExitFunction();
866 } 870 }
867 871
@@ -1164,18 +1168,15 @@ extern "C" HRESULT PlanExecutePackage(
1164 ExitOnFailure(hr, "Failed to complete plan dependency actions for package: %ls", pPackage->sczId); 1168 ExitOnFailure(hr, "Failed to complete plan dependency actions for package: %ls", pPackage->sczId);
1165 1169
1166 // If we are going to take any action on this package, add progress for it. 1170 // If we are going to take any action on this package, add progress for it.
1167 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute || BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->rollback || pPackage->compatiblePackage.fRemove) 1171 if (BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->execute || BOOTSTRAPPER_ACTION_STATE_NONE != pPackage->rollback)
1168 { 1172 {
1169 LoggingIncrementPackageSequence(); 1173 PlannedExecutePackage(pPlan, pPackage);
1170 1174 }
1171 ++pPlan->cExecutePackagesTotal;
1172 ++pPlan->cOverallProgressTicksTotal;
1173 1175
1174 // If package is per-machine and is being executed, flag the plan to be per-machine as well. 1176 // If we are going to take any action on the compatible package, add progress for it.
1175 if (pPackage->fPerMachine) 1177 if (pPackage->compatiblePackage.fRemove)
1176 { 1178 {
1177 pPlan->fPerMachine = TRUE; 1179 PlannedExecutePackage(pPlan, pPackage);
1178 }
1179 } 1180 }
1180 1181
1181LExit: 1182LExit:
@@ -1219,7 +1220,7 @@ extern "C" HRESULT PlanDefaultRelatedBundleRequestState(
1219 } 1220 }
1220 else if (BOOTSTRAPPER_ACTION_INSTALL == action || BOOTSTRAPPER_ACTION_MODIFY == action) 1221 else if (BOOTSTRAPPER_ACTION_INSTALL == action || BOOTSTRAPPER_ACTION_MODIFY == action)
1221 { 1222 {
1222 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_PRESENT; 1223 *pRequestState = BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT;
1223 } 1224 }
1224 else if (BOOTSTRAPPER_ACTION_REPAIR == action) 1225 else if (BOOTSTRAPPER_ACTION_REPAIR == action)
1225 { 1226 {
@@ -1478,16 +1479,7 @@ extern "C" HRESULT PlanRelatedBundlesComplete(
1478 // If we are going to take any action on this package, add progress for it. 1479 // If we are going to take any action on this package, add progress for it.
1479 if (BOOTSTRAPPER_ACTION_STATE_NONE != pRelatedBundle->package.execute || BOOTSTRAPPER_ACTION_STATE_NONE != pRelatedBundle->package.rollback) 1480 if (BOOTSTRAPPER_ACTION_STATE_NONE != pRelatedBundle->package.execute || BOOTSTRAPPER_ACTION_STATE_NONE != pRelatedBundle->package.rollback)
1480 { 1481 {
1481 LoggingIncrementPackageSequence(); 1482 PlannedExecutePackage(pPlan, &pRelatedBundle->package);
1482
1483 ++pPlan->cExecutePackagesTotal;
1484 ++pPlan->cOverallProgressTicksTotal;
1485 }
1486
1487 // If package is per-machine and is being executed, flag the plan to be per-machine as well.
1488 if (pRelatedBundle->package.fPerMachine)
1489 {
1490 pPlan->fPerMachine = TRUE;
1491 } 1483 }
1492 } 1484 }
1493 else if (BOOTSTRAPPER_RELATION_ADDON == pRelatedBundle->relationType || BOOTSTRAPPER_RELATION_PATCH == pRelatedBundle->relationType) 1485 else if (BOOTSTRAPPER_RELATION_ADDON == pRelatedBundle->relationType || BOOTSTRAPPER_RELATION_PATCH == pRelatedBundle->relationType)
@@ -1847,6 +1839,24 @@ LExit:
1847 1839
1848// internal function definitions 1840// internal function definitions
1849 1841
1842
1843static void PlannedExecutePackage(
1844 __in BURN_PLAN* pPlan,
1845 __in BURN_PACKAGE* pPackage
1846 )
1847{
1848 LoggingIncrementPackageSequence();
1849
1850 ++pPlan->cExecutePackagesTotal;
1851 ++pPlan->cOverallProgressTicksTotal;
1852
1853 // If package is per-machine and is being executed, flag the plan to be per-machine as well.
1854 if (pPackage->fPerMachine)
1855 {
1856 pPlan->fPerMachine = TRUE;
1857 }
1858}
1859
1850static void UninitializeRegistrationAction( 1860static void UninitializeRegistrationAction(
1851 __in BURN_DEPENDENT_REGISTRATION_ACTION* pAction 1861 __in BURN_DEPENDENT_REGISTRATION_ACTION* pAction
1852 ) 1862 )
diff --git a/src/burn/engine/pseudobundle.cpp b/src/burn/engine/pseudobundle.cpp
index 153d76e6..94b095c5 100644
--- a/src/burn/engine/pseudobundle.cpp
+++ b/src/burn/engine/pseudobundle.cpp
@@ -51,7 +51,6 @@ extern "C" HRESULT PseudoBundleInitializeRelated(
51 pPackage->fVital = FALSE; 51 pPackage->fVital = FALSE;
52 52
53 pPackage->fPermanent = FALSE; 53 pPackage->fPermanent = FALSE;
54 pPackage->Bundle.fPseudoBundle = TRUE;
55 pPackage->Bundle.fRepairable = TRUE; 54 pPackage->Bundle.fRepairable = TRUE;
56 pPackage->Bundle.fSupportsBurnProtocol = fSupportsBurnProtocol; 55 pPackage->Bundle.fSupportsBurnProtocol = fSupportsBurnProtocol;
57 56
@@ -114,7 +113,7 @@ extern "C" HRESULT PseudoBundleInitializePassthrough(
114 pPassthroughPackage->fVital = pPackage->fVital; 113 pPassthroughPackage->fVital = pPackage->fVital;
115 pPassthroughPackage->fPermanent = TRUE; 114 pPassthroughPackage->fPermanent = TRUE;
116 115
117 pPassthroughPackage->Exe.fPseudoBundle = TRUE; 116 pPassthroughPackage->Exe.fPseudoPackage = TRUE;
118 pPassthroughPackage->Exe.fUninstallable = FALSE; 117 pPassthroughPackage->Exe.fUninstallable = FALSE;
119 pPassthroughPackage->Exe.protocol = pPackage->Bundle.fSupportsBurnProtocol ? BURN_EXE_PROTOCOL_TYPE_BURN : BURN_EXE_PROTOCOL_TYPE_NONE; 118 pPassthroughPackage->Exe.protocol = pPackage->Bundle.fSupportsBurnProtocol ? BURN_EXE_PROTOCOL_TYPE_BURN : BURN_EXE_PROTOCOL_TYPE_NONE;
120 119
@@ -195,7 +194,7 @@ extern "C" HRESULT PseudoBundleInitializeUpdateBundle(
195 194
196 // Trust the BA to only use UPDATE_REPLACE_EMBEDDED when appropriate. 195 // Trust the BA to only use UPDATE_REPLACE_EMBEDDED when appropriate.
197 pPackage->Exe.protocol = BURN_EXE_PROTOCOL_TYPE_BURN; 196 pPackage->Exe.protocol = BURN_EXE_PROTOCOL_TYPE_BURN;
198 pPackage->Exe.fPseudoBundle = TRUE; 197 pPackage->Exe.fPseudoPackage = TRUE;
199 198
200 hr = StrAllocString(&pPackage->sczId, wzId, 0); 199 hr = StrAllocString(&pPackage->sczId, wzId, 0);
201 ExitOnFailure(hr, "Failed to copy id for update bundle."); 200 ExitOnFailure(hr, "Failed to copy id for update bundle.");
diff --git a/src/burn/test/BurnUnitTest/PlanTest.cpp b/src/burn/test/BurnUnitTest/PlanTest.cpp
index 281c32e0..9d86b7cc 100644
--- a/src/burn/test/BurnUnitTest/PlanTest.cpp
+++ b/src/burn/test/BurnUnitTest/PlanTest.cpp
@@ -13,6 +13,11 @@ static LPCWSTR wzMsiTransactionManifestFileName = L"MsiTransaction_BundleAv1_man
13static LPCWSTR wzSingleMsiManifestFileName = L"BasicFunctionality_BundleA_manifest.xml"; 13static LPCWSTR wzSingleMsiManifestFileName = L"BasicFunctionality_BundleA_manifest.xml";
14static LPCWSTR wzSlipstreamManifestFileName = L"Slipstream_BundleA_manifest.xml"; 14static LPCWSTR wzSlipstreamManifestFileName = L"Slipstream_BundleA_manifest.xml";
15 15
16static BOOL vfUsePackageRequestState = FALSE;
17static BOOTSTRAPPER_REQUEST_STATE vPackageRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE;
18static BOOL vfUseRelatedBundleRequestState = FALSE;
19static BOOTSTRAPPER_REQUEST_STATE vRelatedBundleRequestState = BOOTSTRAPPER_REQUEST_STATE_NONE;
20
16namespace Microsoft 21namespace Microsoft
17{ 22{
18namespace Tools 23namespace Tools
@@ -514,6 +519,158 @@ namespace Bootstrapper
514 } 519 }
515 520
516 [Fact] 521 [Fact]
522 void SingleMsiForceAbsentTest()
523 {
524 HRESULT hr = S_OK;
525 BURN_ENGINE_STATE engineState = { };
526 BURN_ENGINE_STATE* pEngineState = &engineState;
527 BURN_PLAN* pPlan = &engineState.plan;
528
529 InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState);
530 DetectAttachedContainerAsAttached(pEngineState);
531 DetectPackagesAsAbsent(pEngineState);
532 DetectUpgradeBundle(pEngineState, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", L"0.9.0.0");
533
534 vfUsePackageRequestState = TRUE;
535 vPackageRequestState = BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT;
536 vfUseRelatedBundleRequestState = TRUE;
537 vRelatedBundleRequestState = BOOTSTRAPPER_REQUEST_STATE_FORCE_ABSENT;
538
539 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_UNINSTALL);
540 NativeAssert::Succeeded(hr, "CorePlan failed");
541
542 Assert::Equal<DWORD>(BOOTSTRAPPER_ACTION_UNINSTALL, pPlan->action);
543 Assert::Equal<BOOL>(TRUE, pPlan->fPerMachine);
544 Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback);
545
546 BOOL fRollback = FALSE;
547 DWORD dwIndex = 0;
548 Assert::Equal(dwIndex, pPlan->cCacheActions);
549
550 fRollback = TRUE;
551 dwIndex = 0;
552 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
553
554 Assert::Equal(0ull, pPlan->qwEstimatedSize);
555 Assert::Equal(0ull, pPlan->qwCacheSizeTotal);
556
557 fRollback = FALSE;
558 dwIndex = 0;
559 DWORD dwExecuteCheckpointId = 1;
560 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
561 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", BURN_DEPENDENCY_ACTION_UNREGISTER);
562 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_UNREGISTER);
563 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, BOOTSTRAPPER_MSI_FILE_VERSIONING_MISSING_OR_OLDER, 0);
564 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
565 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
566 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
567 ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, NULL);
568 Assert::Equal(dwIndex, pPlan->cExecuteActions);
569
570 fRollback = TRUE;
571 dwIndex = 0;
572 dwExecuteCheckpointId = 1;
573 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
574 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
575 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
576 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
577 ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
578 Assert::Equal(dwIndex, pPlan->cRollbackActions);
579
580 Assert::Equal(2ul, pPlan->cExecutePackagesTotal);
581 Assert::Equal(2ul, pPlan->cOverallProgressTicksTotal);
582
583 dwIndex = 0;
584 ValidateCleanAction(pPlan, dwIndex++, L"PackageA");
585 Assert::Equal(dwIndex, pPlan->cCleanActions);
586
587 UINT uIndex = 0;
588 ValidatePlannedProvider(pPlan, uIndex++, L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", NULL);
589 ValidatePlannedProvider(pPlan, uIndex++, L"{64633047-D172-4BBB-B202-64337D15C952}", NULL);
590 Assert::Equal(uIndex, pPlan->cPlannedProviders);
591
592 Assert::Equal(1ul, pEngineState->packages.cPackages);
593 ValidateNonPermanentPackageExpectedStates(&pEngineState->packages.rgPackages[0], L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_ABSENT, BURN_PACKAGE_REGISTRATION_STATE_ABSENT);
594 }
595
596 [Fact]
597 void SingleMsiForcePresentTest()
598 {
599 HRESULT hr = S_OK;
600 BURN_ENGINE_STATE engineState = { };
601 BURN_ENGINE_STATE* pEngineState = &engineState;
602 BURN_PLAN* pPlan = &engineState.plan;
603
604 InitializeEngineStateForCorePlan(wzSingleMsiManifestFileName, pEngineState);
605 DetectPackagesAsPresentAndCached(pEngineState);
606 DetectUpgradeBundle(pEngineState, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", L"0.9.0.0");
607
608 vfUsePackageRequestState = TRUE;
609 vPackageRequestState = BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT;
610 vfUseRelatedBundleRequestState = TRUE;
611 vRelatedBundleRequestState = BOOTSTRAPPER_REQUEST_STATE_FORCE_PRESENT;
612
613 hr = CorePlan(pEngineState, BOOTSTRAPPER_ACTION_MODIFY);
614 NativeAssert::Succeeded(hr, "CorePlan failed");
615
616 Assert::Equal<DWORD>(BOOTSTRAPPER_ACTION_MODIFY, pPlan->action);
617 Assert::Equal<BOOL>(TRUE, pPlan->fPerMachine);
618 Assert::Equal<BOOL>(FALSE, pPlan->fDisableRollback);
619
620 BOOL fRollback = FALSE;
621 DWORD dwIndex = 0;
622 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
623 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
624 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
625 Assert::Equal(dwIndex, pPlan->cCacheActions);
626
627 fRollback = TRUE;
628 dwIndex = 0;
629 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
630
631 Assert::Equal(35694ull, pPlan->qwEstimatedSize);
632 Assert::Equal(175674ull, pPlan->qwCacheSizeTotal);
633
634 fRollback = FALSE;
635 dwIndex = 0;
636 DWORD dwExecuteCheckpointId = 2;
637 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
638 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
639 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
640 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", BURN_DEPENDENCY_ACTION_REGISTER);
641 ValidateExecuteMsiPackage(pPlan, fRollback, dwIndex++, L"PackageA", BOOTSTRAPPER_ACTION_STATE_INSTALL, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, BOOTSTRAPPER_MSI_FILE_VERSIONING_MISSING_OR_OLDER, 0);
642 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", BURN_DEPENDENCY_ACTION_REGISTER);
643 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
644 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
645 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
646 ValidateExecuteRelatedBundle(pPlan, fRollback, dwIndex++, L"{FD9920AD-DBCA-4C6C-8CD5-B47431CE8D21}", BOOTSTRAPPER_ACTION_STATE_INSTALL, NULL);
647 Assert::Equal(dwIndex, pPlan->cExecuteActions);
648
649 fRollback = TRUE;
650 dwIndex = 0;
651 dwExecuteCheckpointId = 2;
652 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
653 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
654 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
655 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
656 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
657 Assert::Equal(dwIndex, pPlan->cRollbackActions);
658
659 Assert::Equal(2ul, pPlan->cExecutePackagesTotal);
660 Assert::Equal(3ul, pPlan->cOverallProgressTicksTotal);
661
662 dwIndex = 0;
663 Assert::Equal(dwIndex, pPlan->cCleanActions);
664
665 UINT uIndex = 0;
666 ValidatePlannedProvider(pPlan, uIndex++, L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", NULL);
667 Assert::Equal(uIndex, pPlan->cPlannedProviders);
668
669 Assert::Equal(1ul, pEngineState->packages.cPackages);
670 ValidateNonPermanentPackageExpectedStates(&pEngineState->packages.rgPackages[0], L"PackageA", BURN_PACKAGE_REGISTRATION_STATE_PRESENT, BURN_PACKAGE_REGISTRATION_STATE_PRESENT);
671 }
672
673 [Fact]
517 void SingleMsiInstallTest() 674 void SingleMsiInstallTest()
518 { 675 {
519 HRESULT hr = S_OK; 676 HRESULT hr = S_OK;
@@ -1015,6 +1172,9 @@ namespace Bootstrapper
1015 HRESULT hr = S_OK; 1172 HRESULT hr = S_OK;
1016 LPWSTR sczFilePath = NULL; 1173 LPWSTR sczFilePath = NULL;
1017 1174
1175 vfUsePackageRequestState = FALSE;
1176 vfUseRelatedBundleRequestState = FALSE;
1177
1018 ::InitializeCriticalSection(&pEngineState->userExperience.csEngineActive); 1178 ::InitializeCriticalSection(&pEngineState->userExperience.csEngineActive);
1019 1179
1020 hr = CacheInitialize(&pEngineState->cache, &pEngineState->internalCommand); 1180 hr = CacheInitialize(&pEngineState->cache, &pEngineState->internalCommand);
@@ -1046,6 +1206,7 @@ namespace Bootstrapper
1046 hr = CacheInitializeSources(&pEngineState->cache, &pEngineState->registration, &pEngineState->variables, &pEngineState->internalCommand); 1206 hr = CacheInitializeSources(&pEngineState->cache, &pEngineState->registration, &pEngineState->variables, &pEngineState->internalCommand);
1047 NativeAssert::Succeeded(hr, "Failed to initialize cache sources."); 1207 NativeAssert::Succeeded(hr, "Failed to initialize cache sources.");
1048 1208
1209 pEngineState->userExperience.hUXModule = reinterpret_cast<HMODULE>(1);
1049 pEngineState->userExperience.pfnBAProc = PlanTestBAProc; 1210 pEngineState->userExperience.pfnBAProc = PlanTestBAProc;
1050 } 1211 }
1051 1212
@@ -1676,11 +1837,29 @@ namespace Bootstrapper
1676} 1837}
1677 1838
1678static HRESULT WINAPI PlanTestBAProc( 1839static HRESULT WINAPI PlanTestBAProc(
1679 __in BOOTSTRAPPER_APPLICATION_MESSAGE /*message*/, 1840 __in BOOTSTRAPPER_APPLICATION_MESSAGE message,
1680 __in const LPVOID /*pvArgs*/, 1841 __in const LPVOID /*pvArgs*/,
1681 __inout LPVOID /*pvResults*/, 1842 __inout LPVOID pvResults,
1682 __in_opt LPVOID /*pvContext*/ 1843 __in_opt LPVOID /*pvContext*/
1683 ) 1844 )
1684{ 1845{
1846 switch (message)
1847 {
1848 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANPACKAGEBEGIN:
1849 if (vfUsePackageRequestState)
1850 {
1851 BA_ONPLANPACKAGEBEGIN_RESULTS* pResults = reinterpret_cast<BA_ONPLANPACKAGEBEGIN_RESULTS*>(pvResults);
1852 pResults->requestedState = vPackageRequestState;
1853 }
1854 break;
1855 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANRELATEDBUNDLE:
1856 if (vfUseRelatedBundleRequestState)
1857 {
1858 BA_ONPLANRELATEDBUNDLE_RESULTS* pResults = reinterpret_cast<BA_ONPLANRELATEDBUNDLE_RESULTS*>(pvResults);
1859 pResults->requestedState = vRelatedBundleRequestState;
1860 }
1861 break;
1862 }
1863
1685 return S_OK; 1864 return S_OK;
1686} 1865}