aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2021-05-13 20:46:08 -0500
committerSean Hall <r.sean.hall@gmail.com>2021-05-19 12:15:13 -0500
commit2c085b3aa89150fff9a0ea6df2cde0ce56e3066d (patch)
treed5c1cfb9e6fa1cc1270c813d28a6ca3ee4f84b0b
parentf88ffc7f5c1710b5e106d7e6aea7f1e32fb15dfe (diff)
downloadwix-2c085b3aa89150fff9a0ea6df2cde0ce56e3066d.tar.gz
wix-2c085b3aa89150fff9a0ea6df2cde0ce56e3066d.tar.bz2
wix-2c085b3aa89150fff9a0ea6df2cde0ce56e3066d.zip
Add InProgressDisplayName for bundles.
#6296
-rw-r--r--src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h13
-rw-r--r--src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs11
-rw-r--r--src/api/burn/WixToolset.Mba.Core/EventArgs.cs46
-rw-r--r--src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs35
-rw-r--r--src/api/burn/balutil/inc/BalBaseBAFunctions.h8
-rw-r--r--src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h8
-rw-r--r--src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h6
-rw-r--r--src/api/burn/balutil/inc/IBootstrapperApplication.h8
-rw-r--r--src/api/wix/WixToolset.Data/Burn/BurnConstants.cs1
-rw-r--r--src/api/wix/WixToolset.Data/Symbols/WixBundleSymbol.cs8
-rw-r--r--src/api/wix/api_wix.sln14
-rw-r--r--src/burn/engine/apply.cpp87
-rw-r--r--src/burn/engine/core.h3
-rw-r--r--src/burn/engine/elevation.cpp36
-rw-r--r--src/burn/engine/elevation.h9
-rw-r--r--src/burn/engine/engine.mc2
-rw-r--r--src/burn/engine/logging.cpp17
-rw-r--r--src/burn/engine/logging.h4
-rw-r--r--src/burn/engine/registration.cpp140
-rw-r--r--src/burn/engine/registration.h10
-rw-r--r--src/burn/engine/userexperience.cpp18
-rw-r--r--src/burn/engine/userexperience.h5
-rw-r--r--src/burn/test/BurnUnitTest/RegistrationTest.cpp38
-rw-r--r--src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs5
-rw-r--r--src/wix/WixToolset.Core/Compiler_Bundle.cs24
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/BundleFixture.cs2
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimpleBundle/Bundle.en-us.wxl1
-rw-r--r--src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimpleBundle/Bundle.wxs2
28 files changed, 391 insertions, 170 deletions
diff --git a/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h b/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
index 2a6d5c8a..56f6b361 100644
--- a/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
+++ b/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
@@ -20,6 +20,13 @@ enum BOOTSTRAPPER_RESTART
20 BOOTSTRAPPER_RESTART_ALWAYS, 20 BOOTSTRAPPER_RESTART_ALWAYS,
21}; 21};
22 22
23enum BOOTSTRAPPER_REGISTRATION_TYPE
24{
25 BOOTSTRAPPER_REGISTRATION_TYPE_NONE, // The engine will ignore NONE if it recommended INPROGRESS or FULL.
26 BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS,
27 BOOTSTRAPPER_REGISTRATION_TYPE_FULL,
28};
29
23enum BOOTSTRAPPER_RESUME_TYPE 30enum BOOTSTRAPPER_RESUME_TYPE
24{ 31{
25 BOOTSTRAPPER_RESUME_TYPE_NONE, 32 BOOTSTRAPPER_RESUME_TYPE_NONE,
@@ -1163,12 +1170,14 @@ struct BA_ONPROGRESS_RESULTS
1163struct BA_ONREGISTERBEGIN_ARGS 1170struct BA_ONREGISTERBEGIN_ARGS
1164{ 1171{
1165 DWORD cbSize; 1172 DWORD cbSize;
1173 BOOTSTRAPPER_REGISTRATION_TYPE recommendedRegistrationType;
1166}; 1174};
1167 1175
1168struct BA_ONREGISTERBEGIN_RESULTS 1176struct BA_ONREGISTERBEGIN_RESULTS
1169{ 1177{
1170 DWORD cbSize; 1178 DWORD cbSize;
1171 BOOL fCancel; 1179 BOOL fCancel;
1180 BOOTSTRAPPER_REGISTRATION_TYPE registrationType;
1172}; 1181};
1173 1182
1174struct BA_ONREGISTERCOMPLETE_ARGS 1183struct BA_ONREGISTERCOMPLETE_ARGS
@@ -1262,13 +1271,13 @@ struct BA_ONSYSTEMSHUTDOWN_RESULTS
1262struct BA_ONUNREGISTERBEGIN_ARGS 1271struct BA_ONUNREGISTERBEGIN_ARGS
1263{ 1272{
1264 DWORD cbSize; 1273 DWORD cbSize;
1265 BOOL fKeepRegistration; 1274 BOOTSTRAPPER_REGISTRATION_TYPE recommendedRegistrationType;
1266}; 1275};
1267 1276
1268struct BA_ONUNREGISTERBEGIN_RESULTS 1277struct BA_ONUNREGISTERBEGIN_RESULTS
1269{ 1278{
1270 DWORD cbSize; 1279 DWORD cbSize;
1271 BOOL fForceKeepRegistration; 1280 BOOTSTRAPPER_REGISTRATION_TYPE registrationType;
1272}; 1281};
1273 1282
1274struct BA_ONUNREGISTERCOMPLETE_ARGS 1283struct BA_ONUNREGISTERCOMPLETE_ARGS
diff --git a/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs b/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs
index 072d3ef0..d7dbf04c 100644
--- a/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs
+++ b/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs
@@ -1490,12 +1490,13 @@ namespace WixToolset.Mba.Core
1490 return args.HResult; 1490 return args.HResult;
1491 } 1491 }
1492 1492
1493 int IBootstrapperApplication.OnRegisterBegin(ref bool fCancel) 1493 int IBootstrapperApplication.OnRegisterBegin(RegistrationType recommendedRegistrationType, ref bool fCancel, ref RegistrationType registrationType)
1494 { 1494 {
1495 RegisterBeginEventArgs args = new RegisterBeginEventArgs(fCancel); 1495 RegisterBeginEventArgs args = new RegisterBeginEventArgs(recommendedRegistrationType, fCancel, registrationType);
1496 this.OnRegisterBegin(args); 1496 this.OnRegisterBegin(args);
1497 1497
1498 fCancel = args.Cancel; 1498 fCancel = args.Cancel;
1499 registrationType = args.RegistrationType;
1499 return args.HResult; 1500 return args.HResult;
1500 } 1501 }
1501 1502
@@ -1679,12 +1680,12 @@ namespace WixToolset.Mba.Core
1679 return args.HResult; 1680 return args.HResult;
1680 } 1681 }
1681 1682
1682 int IBootstrapperApplication.OnUnregisterBegin(bool fKeepRegistration, ref bool fForceKeepRegistration) 1683 int IBootstrapperApplication.OnUnregisterBegin(RegistrationType recommendedRegistrationType, ref RegistrationType registrationType)
1683 { 1684 {
1684 UnregisterBeginEventArgs args = new UnregisterBeginEventArgs(fKeepRegistration, fForceKeepRegistration); 1685 UnregisterBeginEventArgs args = new UnregisterBeginEventArgs(recommendedRegistrationType, registrationType);
1685 this.OnUnregisterBegin(args); 1686 this.OnUnregisterBegin(args);
1686 1687
1687 fForceKeepRegistration = args.ForceKeepRegistration; 1688 registrationType = args.RegistrationType;
1688 return args.HResult; 1689 return args.HResult;
1689 } 1690 }
1690 1691
diff --git a/src/api/burn/WixToolset.Mba.Core/EventArgs.cs b/src/api/burn/WixToolset.Mba.Core/EventArgs.cs
index 8ef8af14..00d90c83 100644
--- a/src/api/burn/WixToolset.Mba.Core/EventArgs.cs
+++ b/src/api/burn/WixToolset.Mba.Core/EventArgs.cs
@@ -1184,22 +1184,31 @@ namespace WixToolset.Mba.Core
1184 public class RegisterBeginEventArgs : CancellableHResultEventArgs 1184 public class RegisterBeginEventArgs : CancellableHResultEventArgs
1185 { 1185 {
1186 /// <summary /> 1186 /// <summary />
1187 public RegisterBeginEventArgs(bool cancelRecommendation) 1187 public RegisterBeginEventArgs(RegistrationType recommendedRegistrationType, bool cancelRecommendation, RegistrationType registrationType)
1188 : base(cancelRecommendation) 1188 : base(cancelRecommendation)
1189 { 1189 {
1190 this.RecommendedRegistrationType = recommendedRegistrationType;
1191 this.RegistrationType = registrationType;
1190 } 1192 }
1193
1194 /// <summary>
1195 /// Gets the recommended registration type.
1196 /// </summary>
1197 public RegistrationType RecommendedRegistrationType { get; private set; }
1198
1199 /// <summary>
1200 /// Gets or sets the registration type.
1201 /// </summary>
1202 public RegistrationType RegistrationType { get; set; }
1191 } 1203 }
1192 1204
1193 /// <summary> 1205 /// <summary>
1194 /// Additional arguments used when the engine has completed registering the location and visilibity of the bundle. 1206 /// Event arguments for <see cref="IDefaultBootstrapperApplication.RegisterComplete"/>.
1195 /// </summary> 1207 /// </summary>
1196 [Serializable] 1208 [Serializable]
1197 public class RegisterCompleteEventArgs : StatusEventArgs 1209 public class RegisterCompleteEventArgs : StatusEventArgs
1198 { 1210 {
1199 /// <summary> 1211 /// <summary />
1200 /// Creates a new instance of the <see cref="RegisterCompleteEventArgs"/> class.
1201 /// </summary>
1202 /// <param name="hrStatus">The return code of the operation.</param>
1203 public RegisterCompleteEventArgs(int hrStatus) 1212 public RegisterCompleteEventArgs(int hrStatus)
1204 : base(hrStatus) 1213 : base(hrStatus)
1205 { 1214 {
@@ -1212,26 +1221,22 @@ namespace WixToolset.Mba.Core
1212 [Serializable] 1221 [Serializable]
1213 public class UnregisterBeginEventArgs : HResultEventArgs 1222 public class UnregisterBeginEventArgs : HResultEventArgs
1214 { 1223 {
1215 /// <summary> 1224 /// <summary />
1216 /// 1225 public UnregisterBeginEventArgs(RegistrationType recommendedRegistrationType, RegistrationType registrationType)
1217 /// </summary>
1218 /// <param name="keepRegistration"></param>
1219 /// <param name="forceKeepRegistration"></param>
1220 public UnregisterBeginEventArgs(bool keepRegistration, bool forceKeepRegistration)
1221 { 1226 {
1222 this.KeepRegistration = keepRegistration; 1227 this.RecommendedRegistrationType = recommendedRegistrationType;
1223 this.ForceKeepRegistration = forceKeepRegistration; 1228 this.RegistrationType = registrationType;
1224 } 1229 }
1225 1230
1226 /// <summary> 1231 /// <summary>
1227 /// Indicates whether the engine will uninstall the bundle. 1232 /// Gets the recommended registration type.
1228 /// </summary> 1233 /// </summary>
1229 public bool ForceKeepRegistration { get; set; } 1234 public RegistrationType RecommendedRegistrationType { get; private set; }
1230 1235
1231 /// <summary> 1236 /// <summary>
1232 /// If <see cref="KeepRegistration"/> is FALSE, then this can be set to TRUE to make the engine keep the bundle installed. 1237 /// Gets or sets the registration type.
1233 /// </summary> 1238 /// </summary>
1234 public bool KeepRegistration { get; private set; } 1239 public RegistrationType RegistrationType { get; set; }
1235 } 1240 }
1236 1241
1237 /// <summary> 1242 /// <summary>
@@ -1240,10 +1245,7 @@ namespace WixToolset.Mba.Core
1240 [Serializable] 1245 [Serializable]
1241 public class UnregisterCompleteEventArgs : StatusEventArgs 1246 public class UnregisterCompleteEventArgs : StatusEventArgs
1242 { 1247 {
1243 /// <summary> 1248 /// <summary />
1244 ///
1245 /// </summary>
1246 /// <param name="hrStatus"></param>
1247 public UnregisterCompleteEventArgs(int hrStatus) 1249 public UnregisterCompleteEventArgs(int hrStatus)
1248 : base(hrStatus) 1250 : base(hrStatus)
1249 { 1251 {
diff --git a/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs b/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs
index 530fb1a9..e6e03906 100644
--- a/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs
+++ b/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs
@@ -500,12 +500,12 @@ namespace WixToolset.Mba.Core
500 /// <summary> 500 /// <summary>
501 /// See <see cref="IDefaultBootstrapperApplication.RegisterBegin"/>. 501 /// See <see cref="IDefaultBootstrapperApplication.RegisterBegin"/>.
502 /// </summary> 502 /// </summary>
503 /// <param name="fCancel"></param>
504 /// <returns></returns>
505 [PreserveSig] 503 [PreserveSig]
506 [return: MarshalAs(UnmanagedType.I4)] 504 [return: MarshalAs(UnmanagedType.I4)]
507 int OnRegisterBegin( 505 int OnRegisterBegin(
508 [MarshalAs(UnmanagedType.Bool)] ref bool fCancel 506 [MarshalAs(UnmanagedType.I4)] RegistrationType recommendedRegistrationType,
507 [MarshalAs(UnmanagedType.Bool)] ref bool fCancel,
508 [MarshalAs(UnmanagedType.I4)] ref RegistrationType pRegistrationType
509 ); 509 );
510 510
511 /// <summary> 511 /// <summary>
@@ -820,14 +820,11 @@ namespace WixToolset.Mba.Core
820 /// <summary> 820 /// <summary>
821 /// See <see cref="IDefaultBootstrapperApplication.UnregisterBegin"/>. 821 /// See <see cref="IDefaultBootstrapperApplication.UnregisterBegin"/>.
822 /// </summary> 822 /// </summary>
823 /// <param name="fKeepRegistration"></param>
824 /// <param name="fForceKeepRegistration"></param>
825 /// <returns></returns>
826 [PreserveSig] 823 [PreserveSig]
827 [return: MarshalAs(UnmanagedType.I4)] 824 [return: MarshalAs(UnmanagedType.I4)]
828 int OnUnregisterBegin( 825 int OnUnregisterBegin(
829 [MarshalAs(UnmanagedType.Bool)] bool fKeepRegistration, 826 [MarshalAs(UnmanagedType.I4)] RegistrationType recommendedRegistrationType,
830 [MarshalAs(UnmanagedType.Bool)] ref bool fForceKeepRegistration 827 [MarshalAs(UnmanagedType.I4)] ref RegistrationType pRegistrationType
831 ); 828 );
832 829
833 /// <summary> 830 /// <summary>
@@ -1260,6 +1257,28 @@ namespace WixToolset.Mba.Core
1260 } 1257 }
1261 1258
1262 /// <summary> 1259 /// <summary>
1260 /// The display name to use when registering in Add/Remove Programs.
1261 /// </summary>
1262 public enum RegistrationType
1263 {
1264 /// <summary>
1265 /// No registration.
1266 /// The engine will ignore None if it recommended InProgress or Full.
1267 /// </summary>
1268 None,
1269
1270 /// <summary>
1271 /// The in-progress display name.
1272 /// </summary>
1273 InProgress,
1274
1275 /// <summary>
1276 /// The default display name.
1277 /// </summary>
1278 Full,
1279 }
1280
1281 /// <summary>
1263 /// Result codes (based on Dialog Box Command IDs from WinUser.h). 1282 /// Result codes (based on Dialog Box Command IDs from WinUser.h).
1264 /// </summary> 1283 /// </summary>
1265 public enum Result 1284 public enum Result
diff --git a/src/api/burn/balutil/inc/BalBaseBAFunctions.h b/src/api/burn/balutil/inc/BalBaseBAFunctions.h
index ee2e452f..c5771efc 100644
--- a/src/api/burn/balutil/inc/BalBaseBAFunctions.h
+++ b/src/api/burn/balutil/inc/BalBaseBAFunctions.h
@@ -379,7 +379,9 @@ public: // IBootstrapperApplication
379 } 379 }
380 380
381 virtual STDMETHODIMP OnRegisterBegin( 381 virtual STDMETHODIMP OnRegisterBegin(
382 __inout BOOL* /*pfCancel*/ 382 __in BOOTSTRAPPER_REGISTRATION_TYPE /*recommendedRegistrationType*/,
383 __inout BOOL* /*pfCancel*/,
384 __inout BOOTSTRAPPER_REGISTRATION_TYPE* /*pRegistrationType*/
383 ) 385 )
384 { 386 {
385 return S_OK; 387 return S_OK;
@@ -597,8 +599,8 @@ public: // IBootstrapperApplication
597 } 599 }
598 600
599 virtual STDMETHODIMP OnUnregisterBegin( 601 virtual STDMETHODIMP OnUnregisterBegin(
600 __in BOOL /*fKeepRegistration*/, 602 __in BOOTSTRAPPER_REGISTRATION_TYPE /*recommendedRegistrationType*/,
601 __inout BOOL* /*pfForceKeepRegistration*/ 603 __inout BOOTSTRAPPER_REGISTRATION_TYPE* /*pRegistrationType*/
602 ) 604 )
603 { 605 {
604 return S_OK; 606 return S_OK;
diff --git a/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h b/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h
index bf21c4a5..393987ba 100644
--- a/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h
+++ b/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h
@@ -435,7 +435,9 @@ public: // IBootstrapperApplication
435 } 435 }
436 436
437 virtual STDMETHODIMP OnRegisterBegin( 437 virtual STDMETHODIMP OnRegisterBegin(
438 __inout BOOL* pfCancel 438 __in BOOTSTRAPPER_REGISTRATION_TYPE /*recommendedRegistrationType*/,
439 __inout BOOL* pfCancel,
440 __inout BOOTSTRAPPER_REGISTRATION_TYPE* /*pRegistrationType*/
439 ) 441 )
440 { 442 {
441 *pfCancel |= CheckCanceled(); 443 *pfCancel |= CheckCanceled();
@@ -769,8 +771,8 @@ public: // IBootstrapperApplication
769 } 771 }
770 772
771 virtual STDMETHODIMP OnUnregisterBegin( 773 virtual STDMETHODIMP OnUnregisterBegin(
772 __in BOOL /*fKeepRegistration*/, 774 __in BOOTSTRAPPER_REGISTRATION_TYPE /*recommendedRegistrationType*/,
773 __inout BOOL* /*pfForceKeepRegistration*/ 775 __inout BOOTSTRAPPER_REGISTRATION_TYPE* /*pRegistrationType*/
774 ) 776 )
775 { 777 {
776 return S_OK; 778 return S_OK;
diff --git a/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h b/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h
index 7fe3ffd8..69031d62 100644
--- a/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h
+++ b/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h
@@ -263,11 +263,11 @@ static HRESULT BalBaseBAProcOnError(
263 263
264static HRESULT BalBaseBAProcOnRegisterBegin( 264static HRESULT BalBaseBAProcOnRegisterBegin(
265 __in IBootstrapperApplication* pBA, 265 __in IBootstrapperApplication* pBA,
266 __in BA_ONREGISTERBEGIN_ARGS* /*pArgs*/, 266 __in BA_ONREGISTERBEGIN_ARGS* pArgs,
267 __inout BA_ONREGISTERBEGIN_RESULTS* pResults 267 __inout BA_ONREGISTERBEGIN_RESULTS* pResults
268 ) 268 )
269{ 269{
270 return pBA->OnRegisterBegin(&pResults->fCancel); 270 return pBA->OnRegisterBegin(pArgs->recommendedRegistrationType, &pResults->fCancel, &pResults->registrationType);
271} 271}
272 272
273static HRESULT BalBaseBAProcOnRegisterComplete( 273static HRESULT BalBaseBAProcOnRegisterComplete(
@@ -456,7 +456,7 @@ static HRESULT BalBaseBAProcOnUnregisterBegin(
456 __inout BA_ONUNREGISTERBEGIN_RESULTS* pResults 456 __inout BA_ONUNREGISTERBEGIN_RESULTS* pResults
457 ) 457 )
458{ 458{
459 return pBA->OnUnregisterBegin(pArgs->fKeepRegistration, &pResults->fForceKeepRegistration); 459 return pBA->OnUnregisterBegin(pArgs->recommendedRegistrationType, &pResults->registrationType);
460} 460}
461 461
462static HRESULT BalBaseBAProcOnUnregisterComplete( 462static HRESULT BalBaseBAProcOnUnregisterComplete(
diff --git a/src/api/burn/balutil/inc/IBootstrapperApplication.h b/src/api/burn/balutil/inc/IBootstrapperApplication.h
index c284cb49..98b88f44 100644
--- a/src/api/burn/balutil/inc/IBootstrapperApplication.h
+++ b/src/api/burn/balutil/inc/IBootstrapperApplication.h
@@ -280,7 +280,9 @@ DECLARE_INTERFACE_IID_(IBootstrapperApplication, IUnknown, "53C31D56-49C0-426B-A
280 // OnRegisterBegin - called when the engine registers the bundle. 280 // OnRegisterBegin - called when the engine registers the bundle.
281 // 281 //
282 STDMETHOD(OnRegisterBegin)( 282 STDMETHOD(OnRegisterBegin)(
283 __inout BOOL* pfCancel 283 __in BOOTSTRAPPER_REGISTRATION_TYPE recommendedRegistrationType,
284 __inout BOOL* pfCancel,
285 __inout BOOTSTRAPPER_REGISTRATION_TYPE* pRegistrationType
284 ) = 0; 286 ) = 0;
285 287
286 // OnRegisterComplete - called when the engine registration is 288 // OnRegisterComplete - called when the engine registration is
@@ -519,8 +521,8 @@ DECLARE_INTERFACE_IID_(IBootstrapperApplication, IUnknown, "53C31D56-49C0-426B-A
519 // OnUnregisterBegin - called when the engine unregisters the bundle. 521 // OnUnregisterBegin - called when the engine unregisters the bundle.
520 // 522 //
521 STDMETHOD(OnUnregisterBegin)( 523 STDMETHOD(OnUnregisterBegin)(
522 __in BOOL fKeepRegistration, 524 __in BOOTSTRAPPER_REGISTRATION_TYPE recommendedRegistrationType,
523 __inout BOOL* pfForceKeepRegistration 525 __inout BOOTSTRAPPER_REGISTRATION_TYPE* pRegistrationType
524 ) = 0; 526 ) = 0;
525 527
526 // OnUnregisterComplete - called when the engine unregistration is complete. 528 // OnUnregisterComplete - called when the engine unregistration is complete.
diff --git a/src/api/wix/WixToolset.Data/Burn/BurnConstants.cs b/src/api/wix/WixToolset.Data/Burn/BurnConstants.cs
index 484b144d..1ecccbd2 100644
--- a/src/api/wix/WixToolset.Data/Burn/BurnConstants.cs
+++ b/src/api/wix/WixToolset.Data/Burn/BurnConstants.cs
@@ -18,6 +18,7 @@ namespace WixToolset.Data.Burn
18 public const string BundleExtensionSearchSymbolDefinitionTag = "WixBundleExtensionSearch"; 18 public const string BundleExtensionSearchSymbolDefinitionTag = "WixBundleExtensionSearch";
19 19
20 // The following constants must stay in sync with src\burn\engine\core.h 20 // The following constants must stay in sync with src\burn\engine\core.h
21 public const string BURN_BUNDLE_INPROGRESS_NAME = "WixBundleInProgressName";
21 public const string BURN_BUNDLE_NAME = "WixBundleName"; 22 public const string BURN_BUNDLE_NAME = "WixBundleName";
22 public const string BURN_BUNDLE_ORIGINAL_SOURCE = "WixBundleOriginalSource"; 23 public const string BURN_BUNDLE_ORIGINAL_SOURCE = "WixBundleOriginalSource";
23 public const string BURN_BUNDLE_ORIGINAL_SOURCE_FOLDER = "WixBundleOriginalSourceFolder"; 24 public const string BURN_BUNDLE_ORIGINAL_SOURCE_FOLDER = "WixBundleOriginalSourceFolder";
diff --git a/src/api/wix/WixToolset.Data/Symbols/WixBundleSymbol.cs b/src/api/wix/WixToolset.Data/Symbols/WixBundleSymbol.cs
index 8cad5c36..9724cbd7 100644
--- a/src/api/wix/WixToolset.Data/Symbols/WixBundleSymbol.cs
+++ b/src/api/wix/WixToolset.Data/Symbols/WixBundleSymbol.cs
@@ -32,6 +32,7 @@ namespace WixToolset.Data
32 new IntermediateFieldDefinition(nameof(WixBundleSymbolFields.ParentName), IntermediateFieldType.String), 32 new IntermediateFieldDefinition(nameof(WixBundleSymbolFields.ParentName), IntermediateFieldType.String),
33 new IntermediateFieldDefinition(nameof(WixBundleSymbolFields.BundleId), IntermediateFieldType.String), 33 new IntermediateFieldDefinition(nameof(WixBundleSymbolFields.BundleId), IntermediateFieldType.String),
34 new IntermediateFieldDefinition(nameof(WixBundleSymbolFields.ProviderKey), IntermediateFieldType.String), 34 new IntermediateFieldDefinition(nameof(WixBundleSymbolFields.ProviderKey), IntermediateFieldType.String),
35 new IntermediateFieldDefinition(nameof(WixBundleSymbolFields.InProgressName), IntermediateFieldType.String),
35 }, 36 },
36 typeof(WixBundleSymbol)); 37 typeof(WixBundleSymbol));
37 } 38 }
@@ -65,6 +66,7 @@ namespace WixToolset.Data.Symbols
65 ParentName, 66 ParentName,
66 BundleId, 67 BundleId,
67 ProviderKey, 68 ProviderKey,
69 InProgressName,
68 } 70 }
69 71
70 [Flags] 72 [Flags]
@@ -221,6 +223,12 @@ namespace WixToolset.Data.Symbols
221 set => this.Set((int)WixBundleSymbolFields.ProviderKey, value); 223 set => this.Set((int)WixBundleSymbolFields.ProviderKey, value);
222 } 224 }
223 225
226 public string InProgressName
227 {
228 get => (string)this.Fields[(int)WixBundleSymbolFields.InProgressName];
229 set => this.Set((int)WixBundleSymbolFields.InProgressName, value);
230 }
231
224 public PackagingType DefaultPackagingType => (this.Compressed.HasValue && !this.Compressed.Value) ? PackagingType.External : PackagingType.Embedded; 232 public PackagingType DefaultPackagingType => (this.Compressed.HasValue && !this.Compressed.Value) ? PackagingType.External : PackagingType.Embedded;
225 233
226 public bool DisableModify => (this.Attributes & WixBundleAttributes.DisableModify) == WixBundleAttributes.DisableModify; 234 public bool DisableModify => (this.Attributes & WixBundleAttributes.DisableModify) == WixBundleAttributes.DisableModify;
diff --git a/src/api/wix/api_wix.sln b/src/api/wix/api_wix.sln
index 6b799e66..6096c12a 100644
--- a/src/api/wix/api_wix.sln
+++ b/src/api/wix/api_wix.sln
@@ -1,7 +1,7 @@
1 1
2Microsoft Visual Studio Solution File, Format Version 12.00 2Microsoft Visual Studio Solution File, Format Version 12.00
3# Visual Studio 15 3# Visual Studio Version 16
4VisualStudioVersion = 15.0.27004.2009 4VisualStudioVersion = 16.0.31205.134
5MinimumVisualStudioVersion = 10.0.40219.1 5MinimumVisualStudioVersion = 10.0.40219.1
6Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.Data", "WixToolset.Data\WixToolset.Data.csproj", "{73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}" 6Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.Data", "WixToolset.Data\WixToolset.Data.csproj", "{73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}"
7EndProject 7EndProject
@@ -12,43 +12,33 @@ EndProject
12Global 12Global
13 GlobalSection(SolutionConfigurationPlatforms) = preSolution 13 GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 Debug|Any CPU = Debug|Any CPU 14 Debug|Any CPU = Debug|Any CPU
15 Debug|arm = Debug|arm
16 Debug|x64 = Debug|x64 15 Debug|x64 = Debug|x64
17 Debug|x86 = Debug|x86 16 Debug|x86 = Debug|x86
18 Release|Any CPU = Release|Any CPU 17 Release|Any CPU = Release|Any CPU
19 Release|arm = Release|arm
20 Release|x64 = Release|x64 18 Release|x64 = Release|x64
21 Release|x86 = Release|x86 19 Release|x86 = Release|x86
22 EndGlobalSection 20 EndGlobalSection
23 GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 GlobalSection(ProjectConfigurationPlatforms) = postSolution
24 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 22 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Debug|Any CPU.Build.0 = Debug|Any CPU 23 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Debug|arm.ActiveCfg = Debug|Any CPU
27 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Debug|arm.Build.0 = Debug|Any CPU
28 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Debug|x64.ActiveCfg = Debug|Any CPU 24 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Debug|x64.ActiveCfg = Debug|Any CPU
29 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Debug|x64.Build.0 = Debug|Any CPU 25 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Debug|x64.Build.0 = Debug|Any CPU
30 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Debug|x86.ActiveCfg = Debug|Any CPU 26 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Debug|x86.ActiveCfg = Debug|Any CPU
31 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Debug|x86.Build.0 = Debug|Any CPU 27 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Debug|x86.Build.0 = Debug|Any CPU
32 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Release|Any CPU.Build.0 = Release|Any CPU 29 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Release|Any CPU.Build.0 = Release|Any CPU
34 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Release|arm.ActiveCfg = Release|Any CPU
35 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Release|arm.Build.0 = Release|Any CPU
36 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Release|x64.ActiveCfg = Release|Any CPU 30 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Release|x64.ActiveCfg = Release|Any CPU
37 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Release|x64.Build.0 = Release|Any CPU 31 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Release|x64.Build.0 = Release|Any CPU
38 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Release|x86.ActiveCfg = Release|Any CPU 32 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Release|x86.ActiveCfg = Release|Any CPU
39 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Release|x86.Build.0 = Release|Any CPU 33 {73ADBD3A-8FB2-47DB-BC79-9BC61C40F2E0}.Release|x86.Build.0 = Release|Any CPU
40 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 34 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
41 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Debug|Any CPU.Build.0 = Debug|Any CPU 35 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
42 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Debug|arm.ActiveCfg = Debug|Any CPU
43 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Debug|arm.Build.0 = Debug|Any CPU
44 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Debug|x64.ActiveCfg = Debug|Any CPU 36 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Debug|x64.ActiveCfg = Debug|Any CPU
45 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Debug|x64.Build.0 = Debug|Any CPU 37 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Debug|x64.Build.0 = Debug|Any CPU
46 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Debug|x86.ActiveCfg = Debug|Any CPU 38 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Debug|x86.ActiveCfg = Debug|Any CPU
47 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Debug|x86.Build.0 = Debug|Any CPU 39 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Debug|x86.Build.0 = Debug|Any CPU
48 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Release|Any CPU.ActiveCfg = Release|Any CPU 40 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
49 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Release|Any CPU.Build.0 = Release|Any CPU 41 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Release|Any CPU.Build.0 = Release|Any CPU
50 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Release|arm.ActiveCfg = Release|Any CPU
51 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Release|arm.Build.0 = Release|Any CPU
52 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Release|x64.ActiveCfg = Release|Any CPU 42 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Release|x64.ActiveCfg = Release|Any CPU
53 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Release|x64.Build.0 = Release|Any CPU 43 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Release|x64.Build.0 = Release|Any CPU
54 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Release|x86.ActiveCfg = Release|Any CPU 44 {6C1FA8B7-BF3C-4735-95F8-26DEEFEF00C8}.Release|x86.ActiveCfg = Release|Any CPU
diff --git a/src/burn/engine/apply.cpp b/src/burn/engine/apply.cpp
index aad9e6eb..c32f4c84 100644
--- a/src/burn/engine/apply.cpp
+++ b/src/burn/engine/apply.cpp
@@ -75,7 +75,8 @@ static HRESULT WINAPI AuthenticationRequired(
75 75
76static void CalculateKeepRegistration( 76static void CalculateKeepRegistration(
77 __in BURN_ENGINE_STATE* pEngineState, 77 __in BURN_ENGINE_STATE* pEngineState,
78 __inout BOOL* pfKeepRegistration 78 __in BOOL fLog,
79 __inout BOOTSTRAPPER_REGISTRATION_TYPE* pRegistrationType
79 ); 80 );
80static HRESULT ExecuteDependentRegistrationActions( 81static HRESULT ExecuteDependentRegistrationActions(
81 __in HANDLE hPipe, 82 __in HANDLE hPipe,
@@ -376,8 +377,11 @@ extern "C" HRESULT ApplyRegister(
376{ 377{
377 HRESULT hr = S_OK; 378 HRESULT hr = S_OK;
378 LPWSTR sczEngineWorkingPath = NULL; 379 LPWSTR sczEngineWorkingPath = NULL;
380 BOOTSTRAPPER_REGISTRATION_TYPE registrationType = BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS;
379 381
380 hr = UserExperienceOnRegisterBegin(&pEngineState->userExperience); 382 CalculateKeepRegistration(pEngineState, FALSE, &registrationType);
383
384 hr = UserExperienceOnRegisterBegin(&pEngineState->userExperience, &registrationType);
381 ExitOnRootFailure(hr, "BA aborted register begin."); 385 ExitOnRootFailure(hr, "BA aborted register begin.");
382 386
383 // If we have a resume mode that suggests the bundle is on the machine. 387 // If we have a resume mode that suggests the bundle is on the machine.
@@ -386,12 +390,12 @@ extern "C" HRESULT ApplyRegister(
386 // resume previous session 390 // resume previous session
387 if (pEngineState->registration.fPerMachine) 391 if (pEngineState->registration.fPerMachine)
388 { 392 {
389 hr = ElevationSessionResume(pEngineState->companionConnection.hPipe, pEngineState->registration.sczResumeCommandLine, pEngineState->registration.fDisableResume, &pEngineState->variables); 393 hr = ElevationSessionResume(pEngineState->companionConnection.hPipe, pEngineState->registration.sczResumeCommandLine, pEngineState->registration.fDisableResume, &pEngineState->variables, registrationType);
390 ExitOnFailure(hr, "Failed to resume registration session in per-machine process."); 394 ExitOnFailure(hr, "Failed to resume registration session in per-machine process.");
391 } 395 }
392 else 396 else
393 { 397 {
394 hr = RegistrationSessionResume(&pEngineState->registration, &pEngineState->variables); 398 hr = RegistrationSessionResume(&pEngineState->registration, &pEngineState->variables, registrationType);
395 ExitOnFailure(hr, "Failed to resume registration session."); 399 ExitOnFailure(hr, "Failed to resume registration session.");
396 } 400 }
397 } 401 }
@@ -403,12 +407,12 @@ extern "C" HRESULT ApplyRegister(
403 // begin new session 407 // begin new session
404 if (pEngineState->registration.fPerMachine) 408 if (pEngineState->registration.fPerMachine)
405 { 409 {
406 hr = ElevationSessionBegin(pEngineState->companionConnection.hPipe, sczEngineWorkingPath, pEngineState->registration.sczResumeCommandLine, pEngineState->registration.fDisableResume, &pEngineState->variables, pEngineState->plan.dwRegistrationOperations, pEngineState->plan.dependencyRegistrationAction, pEngineState->plan.qwEstimatedSize); 410 hr = ElevationSessionBegin(pEngineState->companionConnection.hPipe, sczEngineWorkingPath, pEngineState->registration.sczResumeCommandLine, pEngineState->registration.fDisableResume, &pEngineState->variables, pEngineState->plan.dwRegistrationOperations, pEngineState->plan.dependencyRegistrationAction, pEngineState->plan.qwEstimatedSize, registrationType);
407 ExitOnFailure(hr, "Failed to begin registration session in per-machine process."); 411 ExitOnFailure(hr, "Failed to begin registration session in per-machine process.");
408 } 412 }
409 else 413 else
410 { 414 {
411 hr = RegistrationSessionBegin(sczEngineWorkingPath, &pEngineState->registration, &pEngineState->variables, pEngineState->plan.dwRegistrationOperations, pEngineState->plan.dependencyRegistrationAction, pEngineState->plan.qwEstimatedSize); 415 hr = RegistrationSessionBegin(sczEngineWorkingPath, &pEngineState->registration, &pEngineState->variables, pEngineState->plan.dwRegistrationOperations, pEngineState->plan.dependencyRegistrationAction, pEngineState->plan.qwEstimatedSize, registrationType);
412 ExitOnFailure(hr, "Failed to begin registration session."); 416 ExitOnFailure(hr, "Failed to begin registration session.");
413 } 417 }
414 } 418 }
@@ -441,17 +445,11 @@ extern "C" HRESULT ApplyUnregister(
441{ 445{
442 HRESULT hr = S_OK; 446 HRESULT hr = S_OK;
443 BURN_RESUME_MODE resumeMode = BURN_RESUME_MODE_NONE; 447 BURN_RESUME_MODE resumeMode = BURN_RESUME_MODE_NONE;
444 BOOL fKeepRegistration = pEngineState->plan.fDisallowRemoval; 448 BOOTSTRAPPER_REGISTRATION_TYPE defaultRegistrationType = BOOTSTRAPPER_REGISTRATION_TYPE_NONE;
445 449 BOOTSTRAPPER_REGISTRATION_TYPE registrationType = BOOTSTRAPPER_REGISTRATION_TYPE_NONE;
446 CalculateKeepRegistration(pEngineState, &fKeepRegistration);
447
448 hr = UserExperienceOnUnregisterBegin(&pEngineState->userExperience, &fKeepRegistration);
449 ExitOnRootFailure(hr, "BA aborted unregister begin.");
450 450
451 // Calculate the correct resume mode. If a restart has been initiated, that trumps all other 451 // Calculate special cases for the resume mode. If a restart has been initiated, that trumps all other
452 // modes. If the user chose to suspend the install then we'll use that as the resume mode. 452 // modes. If the user chose to suspend the install then we'll use that as the resume mode.
453 // Barring those special cases, if it was determined that we should keep the registration then
454 // do that, otherwise the resume mode was initialized to none and registration will be removed.
455 if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == restart) 453 if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == restart)
456 { 454 {
457 resumeMode = BURN_RESUME_MODE_REBOOT_PENDING; 455 resumeMode = BURN_RESUME_MODE_REBOOT_PENDING;
@@ -460,28 +458,50 @@ extern "C" HRESULT ApplyUnregister(
460 { 458 {
461 resumeMode = BURN_RESUME_MODE_SUSPEND; 459 resumeMode = BURN_RESUME_MODE_SUSPEND;
462 } 460 }
463 else if (fKeepRegistration) 461 else if (pEngineState->plan.fDisallowRemoval)
462 {
463 resumeMode = BURN_RESUME_MODE_ARP;
464 }
465
466 // If there was a special case, make sure the registration is kept.
467 if (BURN_RESUME_MODE_NONE < resumeMode)
468 {
469 defaultRegistrationType = BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS;
470 }
471
472 CalculateKeepRegistration(pEngineState, TRUE, &defaultRegistrationType);
473
474 registrationType = defaultRegistrationType;
475
476 hr = UserExperienceOnUnregisterBegin(&pEngineState->userExperience, &registrationType);
477 ExitOnRootFailure(hr, "BA aborted unregister begin.");
478
479 // Barring the special cases, if it was determined that we should keep the registration then
480 // do that, otherwise the resume mode is NONE and registration will be removed.
481 if (BURN_RESUME_MODE_NONE == resumeMode && BOOTSTRAPPER_REGISTRATION_TYPE_NONE < registrationType)
464 { 482 {
465 resumeMode = BURN_RESUME_MODE_ARP; 483 resumeMode = BURN_RESUME_MODE_ARP;
466 } 484 }
467 485
468 // If apply failed in any way and we're going to be keeping the bundle registered then 486 // If apply failed in any way and we're going to be keeping the bundle registered then
469 // execute any rollback dependency registration actions. 487 // execute any rollback dependency registration actions.
470 if (fFailed && fKeepRegistration) 488 if (fFailed && BURN_RESUME_MODE_NONE < resumeMode)
471 { 489 {
472 // Execute any rollback registration actions. 490 // Execute any rollback registration actions.
473 HRESULT hrRegistrationRollback = ExecuteDependentRegistrationActions(pEngineState->companionConnection.hPipe, &pEngineState->registration, pEngineState->plan.rgRollbackRegistrationActions, pEngineState->plan.cRollbackRegistrationActions); 491 HRESULT hrRegistrationRollback = ExecuteDependentRegistrationActions(pEngineState->companionConnection.hPipe, &pEngineState->registration, pEngineState->plan.rgRollbackRegistrationActions, pEngineState->plan.cRollbackRegistrationActions);
474 UNREFERENCED_PARAMETER(hrRegistrationRollback); 492 IgnoreRollbackError(hrRegistrationRollback, "Dependent registration actions failed");
475 } 493 }
476 494
495 LogId(REPORT_STANDARD, MSG_SESSION_END, pEngineState->registration.sczRegistrationKey, LoggingResumeModeToString(resumeMode), LoggingRestartToString(restart), LoggingBoolToString(pEngineState->registration.fDisableResume), LoggingRegistrationTypeToString(defaultRegistrationType), LoggingRegistrationTypeToString(registrationType));
496
477 if (pEngineState->registration.fPerMachine) 497 if (pEngineState->registration.fPerMachine)
478 { 498 {
479 hr = ElevationSessionEnd(pEngineState->companionConnection.hPipe, resumeMode, restart, pEngineState->plan.dependencyRegistrationAction); 499 hr = ElevationSessionEnd(pEngineState->companionConnection.hPipe, resumeMode, restart, pEngineState->plan.dependencyRegistrationAction, registrationType);
480 ExitOnFailure(hr, "Failed to end session in per-machine process."); 500 ExitOnFailure(hr, "Failed to end session in per-machine process.");
481 } 501 }
482 else 502 else
483 { 503 {
484 hr = RegistrationSessionEnd(&pEngineState->registration, &pEngineState->variables, &pEngineState->packages, resumeMode, restart, pEngineState->plan.dependencyRegistrationAction); 504 hr = RegistrationSessionEnd(&pEngineState->registration, &pEngineState->variables, &pEngineState->packages, resumeMode, restart, pEngineState->plan.dependencyRegistrationAction, registrationType);
485 ExitOnFailure(hr, "Failed to end session in per-user process."); 505 ExitOnFailure(hr, "Failed to end session in per-user process.");
486 } 506 }
487 507
@@ -751,10 +771,14 @@ extern "C" void ApplyClean(
751 771
752static void CalculateKeepRegistration( 772static void CalculateKeepRegistration(
753 __in BURN_ENGINE_STATE* pEngineState, 773 __in BURN_ENGINE_STATE* pEngineState,
754 __inout BOOL* pfKeepRegistration 774 __in BOOL fLog,
775 __inout BOOTSTRAPPER_REGISTRATION_TYPE* pRegistrationType
755 ) 776 )
756{ 777{
757 LogId(REPORT_STANDARD, MSG_POST_APPLY_CALCULATE_REGISTRATION); 778 if (fLog)
779 {
780 LogId(REPORT_STANDARD, MSG_POST_APPLY_CALCULATE_REGISTRATION);
781 }
758 782
759 for (DWORD i = 0; i < pEngineState->packages.cPackages; ++i) 783 for (DWORD i = 0; i < pEngineState->packages.cPackages; ++i)
760 { 784 {
@@ -765,17 +789,28 @@ static void CalculateKeepRegistration(
765 MspEngineFinalizeInstallRegistrationState(pPackage); 789 MspEngineFinalizeInstallRegistrationState(pPackage);
766 } 790 }
767 791
768 LogId(REPORT_STANDARD, MSG_POST_APPLY_PACKAGE, pPackage->sczId, LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->installRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->cacheRegistrationState)); 792 if (fLog)
793 {
794 LogId(REPORT_STANDARD, MSG_POST_APPLY_PACKAGE, pPackage->sczId, LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->installRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->cacheRegistrationState));
795 }
769 796
770 if (!pPackage->fCanAffectRegistration) 797 if (!pPackage->fCanAffectRegistration)
771 { 798 {
772 continue; 799 continue;
773 } 800 }
774 801
775 if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->installRegistrationState || 802 if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->installRegistrationState)
776 BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->cacheRegistrationState) 803 {
804 *pRegistrationType = BOOTSTRAPPER_REGISTRATION_TYPE_FULL;
805
806 if (!fLog)
807 {
808 break;
809 }
810 }
811 else if (BURN_PACKAGE_REGISTRATION_STATE_PRESENT == pPackage->cacheRegistrationState && BOOTSTRAPPER_REGISTRATION_TYPE_NONE == *pRegistrationType)
777 { 812 {
778 *pfKeepRegistration = TRUE; 813 *pRegistrationType = BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS;
779 } 814 }
780 } 815 }
781} 816}
diff --git a/src/burn/engine/core.h b/src/burn/engine/core.h
index 27cb2e25..3a28188b 100644
--- a/src/burn/engine/core.h
+++ b/src/burn/engine/core.h
@@ -48,8 +48,9 @@ const LPCWSTR BURN_BUNDLE_UILEVEL = L"WixBundleUILevel";
48const LPCWSTR BURN_BUNDLE_VERSION = L"WixBundleVersion"; 48const LPCWSTR BURN_BUNDLE_VERSION = L"WixBundleVersion";
49const LPCWSTR BURN_REBOOT_PENDING = L"RebootPending"; 49const LPCWSTR BURN_REBOOT_PENDING = L"RebootPending";
50 50
51// The following constants must stay in sync with src\wix\Binder.cs 51// The following constants must stay in sync with src\api\wix\WixToolset.Data\Burn\BurnConstants.cs
52const LPCWSTR BURN_BUNDLE_NAME = L"WixBundleName"; 52const LPCWSTR BURN_BUNDLE_NAME = L"WixBundleName";
53const LPCWSTR BURN_BUNDLE_INPROGRESS_NAME = L"WixBundleInProgressName";
53const LPCWSTR BURN_BUNDLE_ORIGINAL_SOURCE = L"WixBundleOriginalSource"; 54const LPCWSTR BURN_BUNDLE_ORIGINAL_SOURCE = L"WixBundleOriginalSource";
54const LPCWSTR BURN_BUNDLE_ORIGINAL_SOURCE_FOLDER = L"WixBundleOriginalSourceFolder"; 55const LPCWSTR BURN_BUNDLE_ORIGINAL_SOURCE_FOLDER = L"WixBundleOriginalSourceFolder";
55const LPCWSTR BURN_BUNDLE_LAST_USED_SOURCE = L"WixBundleLastUsedSource"; 56const LPCWSTR BURN_BUNDLE_LAST_USED_SOURCE = L"WixBundleLastUsedSource";
diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp
index 85e4b692..db2a82a6 100644
--- a/src/burn/engine/elevation.cpp
+++ b/src/burn/engine/elevation.cpp
@@ -477,7 +477,8 @@ extern "C" HRESULT ElevationSessionBegin(
477 __in BURN_VARIABLES* pVariables, 477 __in BURN_VARIABLES* pVariables,
478 __in DWORD dwRegistrationOperations, 478 __in DWORD dwRegistrationOperations,
479 __in BURN_DEPENDENCY_REGISTRATION_ACTION dependencyRegistrationAction, 479 __in BURN_DEPENDENCY_REGISTRATION_ACTION dependencyRegistrationAction,
480 __in DWORD64 qwEstimatedSize 480 __in DWORD64 qwEstimatedSize,
481 __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType
481 ) 482 )
482{ 483{
483 HRESULT hr = S_OK; 484 HRESULT hr = S_OK;
@@ -504,6 +505,9 @@ extern "C" HRESULT ElevationSessionBegin(
504 hr = BuffWriteNumber64(&pbData, &cbData, qwEstimatedSize); 505 hr = BuffWriteNumber64(&pbData, &cbData, qwEstimatedSize);
505 ExitOnFailure(hr, "Failed to write estimated size to message buffer."); 506 ExitOnFailure(hr, "Failed to write estimated size to message buffer.");
506 507
508 hr = BuffWriteNumber(&pbData, &cbData, (DWORD)registrationType);
509 ExitOnFailure(hr, "Failed to write registration type to message buffer.");
510
507 hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData); 511 hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData);
508 ExitOnFailure(hr, "Failed to write variables."); 512 ExitOnFailure(hr, "Failed to write variables.");
509 513
@@ -527,7 +531,8 @@ extern "C" HRESULT ElevationSessionResume(
527 __in HANDLE hPipe, 531 __in HANDLE hPipe,
528 __in_z LPCWSTR wzResumeCommandLine, 532 __in_z LPCWSTR wzResumeCommandLine,
529 __in BOOL fDisableResume, 533 __in BOOL fDisableResume,
530 __in BURN_VARIABLES* pVariables 534 __in BURN_VARIABLES* pVariables,
535 __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType
531 ) 536 )
532{ 537{
533 HRESULT hr = S_OK; 538 HRESULT hr = S_OK;
@@ -542,6 +547,9 @@ extern "C" HRESULT ElevationSessionResume(
542 hr = BuffWriteNumber(&pbData, &cbData, fDisableResume); 547 hr = BuffWriteNumber(&pbData, &cbData, fDisableResume);
543 ExitOnFailure(hr, "Failed to write resume flag."); 548 ExitOnFailure(hr, "Failed to write resume flag.");
544 549
550 hr = BuffWriteNumber(&pbData, &cbData, (DWORD)registrationType);
551 ExitOnFailure(hr, "Failed to write registration type to message buffer.");
552
545 hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData); 553 hr = VariableSerialize(pVariables, FALSE, &pbData, &cbData);
546 ExitOnFailure(hr, "Failed to write variables."); 554 ExitOnFailure(hr, "Failed to write variables.");
547 555
@@ -565,7 +573,8 @@ extern "C" HRESULT ElevationSessionEnd(
565 __in HANDLE hPipe, 573 __in HANDLE hPipe,
566 __in BURN_RESUME_MODE resumeMode, 574 __in BURN_RESUME_MODE resumeMode,
567 __in BOOTSTRAPPER_APPLY_RESTART restart, 575 __in BOOTSTRAPPER_APPLY_RESTART restart,
568 __in BURN_DEPENDENCY_REGISTRATION_ACTION dependencyRegistrationAction 576 __in BURN_DEPENDENCY_REGISTRATION_ACTION dependencyRegistrationAction,
577 __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType
569 ) 578 )
570{ 579{
571 HRESULT hr = S_OK; 580 HRESULT hr = S_OK;
@@ -583,6 +592,9 @@ extern "C" HRESULT ElevationSessionEnd(
583 hr = BuffWriteNumber(&pbData, &cbData, (DWORD)dependencyRegistrationAction); 592 hr = BuffWriteNumber(&pbData, &cbData, (DWORD)dependencyRegistrationAction);
584 ExitOnFailure(hr, "Failed to write dependency registration action to message buffer."); 593 ExitOnFailure(hr, "Failed to write dependency registration action to message buffer.");
585 594
595 hr = BuffWriteNumber(&pbData, &cbData, (DWORD)registrationType);
596 ExitOnFailure(hr, "Failed to write registration type to message buffer.");
597
586 // send message 598 // send message
587 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_SESSION_END, pbData, cbData, NULL, NULL, &dwResult); 599 hr = PipeSendMessage(hPipe, BURN_ELEVATION_MESSAGE_TYPE_SESSION_END, pbData, cbData, NULL, NULL, &dwResult);
588 ExitOnFailure(hr, "Failed to send message to per-machine process."); 600 ExitOnFailure(hr, "Failed to send message to per-machine process.");
@@ -2080,6 +2092,7 @@ static HRESULT OnSessionBegin(
2080 DWORD dwRegistrationOperations = 0; 2092 DWORD dwRegistrationOperations = 0;
2081 DWORD dwDependencyRegistrationAction = 0; 2093 DWORD dwDependencyRegistrationAction = 0;
2082 DWORD64 qwEstimatedSize = 0; 2094 DWORD64 qwEstimatedSize = 0;
2095 DWORD dwRegistrationType = 0;
2083 2096
2084 // Deserialize message data. 2097 // Deserialize message data.
2085 hr = BuffReadString(pbData, cbData, &iData, &sczEngineWorkingPath); 2098 hr = BuffReadString(pbData, cbData, &iData, &sczEngineWorkingPath);
@@ -2100,11 +2113,14 @@ static HRESULT OnSessionBegin(
2100 hr = BuffReadNumber64(pbData, cbData, &iData, &qwEstimatedSize); 2113 hr = BuffReadNumber64(pbData, cbData, &iData, &qwEstimatedSize);
2101 ExitOnFailure(hr, "Failed to read estimated size."); 2114 ExitOnFailure(hr, "Failed to read estimated size.");
2102 2115
2116 hr = BuffReadNumber(pbData, cbData, &iData, &dwRegistrationType);
2117 ExitOnFailure(hr, "Failed to read dependency registration action.");
2118
2103 hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData); 2119 hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData);
2104 ExitOnFailure(hr, "Failed to read variables."); 2120 ExitOnFailure(hr, "Failed to read variables.");
2105 2121
2106 // Begin session in per-machine process. 2122 // Begin session in per-machine process.
2107 hr = RegistrationSessionBegin(sczEngineWorkingPath, pRegistration, pVariables, dwRegistrationOperations, (BURN_DEPENDENCY_REGISTRATION_ACTION)dwDependencyRegistrationAction, qwEstimatedSize); 2123 hr = RegistrationSessionBegin(sczEngineWorkingPath, pRegistration, pVariables, dwRegistrationOperations, (BURN_DEPENDENCY_REGISTRATION_ACTION)dwDependencyRegistrationAction, qwEstimatedSize, (BOOTSTRAPPER_REGISTRATION_TYPE)dwRegistrationType);
2108 ExitOnFailure(hr, "Failed to begin registration session."); 2124 ExitOnFailure(hr, "Failed to begin registration session.");
2109 2125
2110LExit: 2126LExit:
@@ -2122,6 +2138,7 @@ static HRESULT OnSessionResume(
2122{ 2138{
2123 HRESULT hr = S_OK; 2139 HRESULT hr = S_OK;
2124 SIZE_T iData = 0; 2140 SIZE_T iData = 0;
2141 DWORD dwRegistrationType = 0;
2125 2142
2126 // Deserialize message data. 2143 // Deserialize message data.
2127 hr = BuffReadString(pbData, cbData, &iData, &pRegistration->sczResumeCommandLine); 2144 hr = BuffReadString(pbData, cbData, &iData, &pRegistration->sczResumeCommandLine);
@@ -2130,11 +2147,14 @@ static HRESULT OnSessionResume(
2130 hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&pRegistration->fDisableResume); 2147 hr = BuffReadNumber(pbData, cbData, &iData, (DWORD*)&pRegistration->fDisableResume);
2131 ExitOnFailure(hr, "Failed to read resume flag."); 2148 ExitOnFailure(hr, "Failed to read resume flag.");
2132 2149
2150 hr = BuffReadNumber(pbData, cbData, &iData, &dwRegistrationType);
2151 ExitOnFailure(hr, "Failed to read dependency registration action.");
2152
2133 hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData); 2153 hr = VariableDeserialize(pVariables, FALSE, pbData, cbData, &iData);
2134 ExitOnFailure(hr, "Failed to read variables."); 2154 ExitOnFailure(hr, "Failed to read variables.");
2135 2155
2136 // resume session in per-machine process 2156 // resume session in per-machine process
2137 hr = RegistrationSessionResume(pRegistration, pVariables); 2157 hr = RegistrationSessionResume(pRegistration, pVariables, (BOOTSTRAPPER_REGISTRATION_TYPE)dwRegistrationType);
2138 ExitOnFailure(hr, "Failed to resume registration session."); 2158 ExitOnFailure(hr, "Failed to resume registration session.");
2139 2159
2140LExit: 2160LExit:
@@ -2154,6 +2174,7 @@ static HRESULT OnSessionEnd(
2154 DWORD dwResumeMode = 0; 2174 DWORD dwResumeMode = 0;
2155 DWORD dwRestart = 0; 2175 DWORD dwRestart = 0;
2156 DWORD dwDependencyRegistrationAction = 0; 2176 DWORD dwDependencyRegistrationAction = 0;
2177 DWORD dwRegistrationType = 0;
2157 2178
2158 // Deserialize message data. 2179 // Deserialize message data.
2159 hr = BuffReadNumber(pbData, cbData, &iData, &dwResumeMode); 2180 hr = BuffReadNumber(pbData, cbData, &iData, &dwResumeMode);
@@ -2165,8 +2186,11 @@ static HRESULT OnSessionEnd(
2165 hr = BuffReadNumber(pbData, cbData, &iData, &dwDependencyRegistrationAction); 2186 hr = BuffReadNumber(pbData, cbData, &iData, &dwDependencyRegistrationAction);
2166 ExitOnFailure(hr, "Failed to read dependency registration action."); 2187 ExitOnFailure(hr, "Failed to read dependency registration action.");
2167 2188
2189 hr = BuffReadNumber(pbData, cbData, &iData, &dwRegistrationType);
2190 ExitOnFailure(hr, "Failed to read dependency registration action.");
2191
2168 // suspend session in per-machine process 2192 // suspend session in per-machine process
2169 hr = RegistrationSessionEnd(pRegistration, pVariables, pPackages, (BURN_RESUME_MODE)dwResumeMode, (BOOTSTRAPPER_APPLY_RESTART)dwRestart, (BURN_DEPENDENCY_REGISTRATION_ACTION)dwDependencyRegistrationAction); 2193 hr = RegistrationSessionEnd(pRegistration, pVariables, pPackages, (BURN_RESUME_MODE)dwResumeMode, (BOOTSTRAPPER_APPLY_RESTART)dwRestart, (BURN_DEPENDENCY_REGISTRATION_ACTION)dwDependencyRegistrationAction, (BOOTSTRAPPER_REGISTRATION_TYPE)dwRegistrationType);
2170 ExitOnFailure(hr, "Failed to suspend registration session."); 2194 ExitOnFailure(hr, "Failed to suspend registration session.");
2171 2195
2172LExit: 2196LExit:
diff --git a/src/burn/engine/elevation.h b/src/burn/engine/elevation.h
index af2dec8b..00dca8dc 100644
--- a/src/burn/engine/elevation.h
+++ b/src/burn/engine/elevation.h
@@ -31,19 +31,22 @@ HRESULT ElevationSessionBegin(
31 __in BURN_VARIABLES* pVariables, 31 __in BURN_VARIABLES* pVariables,
32 __in DWORD dwRegistrationOperations, 32 __in DWORD dwRegistrationOperations,
33 __in BURN_DEPENDENCY_REGISTRATION_ACTION dependencyRegistrationAction, 33 __in BURN_DEPENDENCY_REGISTRATION_ACTION dependencyRegistrationAction,
34 __in DWORD64 qwEstimatedSize 34 __in DWORD64 qwEstimatedSize,
35 __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType
35 ); 36 );
36HRESULT ElevationSessionResume( 37HRESULT ElevationSessionResume(
37 __in HANDLE hPipe, 38 __in HANDLE hPipe,
38 __in_z LPCWSTR wzResumeCommandLine, 39 __in_z LPCWSTR wzResumeCommandLine,
39 __in BOOL fDisableResume, 40 __in BOOL fDisableResume,
40 __in BURN_VARIABLES* pVariables 41 __in BURN_VARIABLES* pVariables,
42 __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType
41 ); 43 );
42HRESULT ElevationSessionEnd( 44HRESULT ElevationSessionEnd(
43 __in HANDLE hPipe, 45 __in HANDLE hPipe,
44 __in BURN_RESUME_MODE resumeMode, 46 __in BURN_RESUME_MODE resumeMode,
45 __in BOOTSTRAPPER_APPLY_RESTART restart, 47 __in BOOTSTRAPPER_APPLY_RESTART restart,
46 __in BURN_DEPENDENCY_REGISTRATION_ACTION dependencyRegistrationAction 48 __in BURN_DEPENDENCY_REGISTRATION_ACTION dependencyRegistrationAction,
49 __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType
47 ); 50 );
48HRESULT ElevationSaveState( 51HRESULT ElevationSaveState(
49 __in HANDLE hPipe, 52 __in HANDLE hPipe,
diff --git a/src/burn/engine/engine.mc b/src/burn/engine/engine.mc
index 929bf67a..ad9d676f 100644
--- a/src/burn/engine/engine.mc
+++ b/src/burn/engine/engine.mc
@@ -889,7 +889,7 @@ MessageId=372
889Severity=Success 889Severity=Success
890SymbolicName=MSG_SESSION_END 890SymbolicName=MSG_SESSION_END
891Language=English 891Language=English
892Session end, registration key: %1!ls!, resume: %2!hs!, restart: %3!hs!, disable resume: %4!hs! 892Session end, registration key: %1!ls!, resume: %2!hs!, restart: %3!hs!, disable resume: %4!hs!, default registration: %5!hs!, ba requested registration: %6!hs!
893. 893.
894 894
895MessageId=373 895MessageId=373
diff --git a/src/burn/engine/logging.cpp b/src/burn/engine/logging.cpp
index 7ee1ec85..2db7defd 100644
--- a/src/burn/engine/logging.cpp
+++ b/src/burn/engine/logging.cpp
@@ -561,6 +561,23 @@ extern "C" LPCSTR LoggingPerMachineToString(
561 return "PerUser"; 561 return "PerUser";
562} 562}
563 563
564extern "C" LPCSTR LoggingRegistrationTypeToString(
565 __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType
566 )
567{
568 switch (registrationType)
569 {
570 case BOOTSTRAPPER_REGISTRATION_TYPE_NONE:
571 return "None";
572 case BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS:
573 return "InProgress";
574 case BOOTSTRAPPER_REGISTRATION_TYPE_FULL:
575 return "Full";
576 default:
577 return "Invalid";
578 }
579}
580
564extern "C" LPCSTR LoggingRestartToString( 581extern "C" LPCSTR LoggingRestartToString(
565 __in BOOTSTRAPPER_APPLY_RESTART restart 582 __in BOOTSTRAPPER_APPLY_RESTART restart
566 ) 583 )
diff --git a/src/burn/engine/logging.h b/src/burn/engine/logging.h
index 909ce591..21ea6297 100644
--- a/src/burn/engine/logging.h
+++ b/src/burn/engine/logging.h
@@ -123,6 +123,10 @@ LPCSTR LoggingPerMachineToString(
123 __in BOOL fPerMachine 123 __in BOOL fPerMachine
124 ); 124 );
125 125
126LPCSTR LoggingRegistrationTypeToString(
127 __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType
128 );
129
126LPCSTR LoggingRestartToString( 130LPCSTR LoggingRestartToString(
127 __in BOOTSTRAPPER_APPLY_RESTART restart 131 __in BOOTSTRAPPER_APPLY_RESTART restart
128 ); 132 );
diff --git a/src/burn/engine/registration.cpp b/src/burn/engine/registration.cpp
index 5b246112..eed1fee2 100644
--- a/src/burn/engine/registration.cpp
+++ b/src/burn/engine/registration.cpp
@@ -46,12 +46,23 @@ static HRESULT SetPaths(
46static HRESULT GetBundleManufacturer( 46static HRESULT GetBundleManufacturer(
47 __in BURN_REGISTRATION* pRegistration, 47 __in BURN_REGISTRATION* pRegistration,
48 __in BURN_VARIABLES* pVariables, 48 __in BURN_VARIABLES* pVariables,
49 __out LPWSTR* psczBundleManufacturer 49 __out_z LPWSTR* psczBundleManufacturer
50 );
51static HRESULT GetBundleInProgressName(
52 __in BURN_REGISTRATION* pRegistration,
53 __in BURN_VARIABLES* pVariables,
54 __out_z LPWSTR* psczBundleName
50 ); 55 );
51static HRESULT GetBundleName( 56static HRESULT GetBundleName(
52 __in BURN_REGISTRATION* pRegistration, 57 __in BURN_REGISTRATION* pRegistration,
53 __in BURN_VARIABLES* pVariables, 58 __in BURN_VARIABLES* pVariables,
54 __out LPWSTR* psczBundleName 59 __out_z LPWSTR* psczBundleName
60 );
61static HRESULT EnsureRegistrationVariable(
62 __in BURN_VARIABLES* pVariables,
63 __in_z LPCWSTR wzVariable,
64 __in_z LPCWSTR wzDefaultValue,
65 __out_z LPWSTR* psczValue
55 ); 66 );
56static HRESULT UpdateResumeMode( 67static HRESULT UpdateResumeMode(
57 __in BURN_REGISTRATION* pRegistration, 68 __in BURN_REGISTRATION* pRegistration,
@@ -91,7 +102,8 @@ static HRESULT RegWriteStringVariable(
91static HRESULT UpdateBundleNameRegistration( 102static HRESULT UpdateBundleNameRegistration(
92 __in BURN_REGISTRATION* pRegistration, 103 __in BURN_REGISTRATION* pRegistration,
93 __in BURN_VARIABLES* pVariables, 104 __in BURN_VARIABLES* pVariables,
94 __in HKEY hkRegistration 105 __in HKEY hkRegistration,
106 __in BOOL fInProgressRegistration
95 ); 107 );
96static BOOL IsWuRebootPending(); 108static BOOL IsWuRebootPending();
97static BOOL IsBundleRebootPending( 109static BOOL IsBundleRebootPending(
@@ -176,6 +188,13 @@ extern "C" HRESULT RegistrationParseFromXml(
176 ExitOnFailure(hr, "Failed to get @DisplayName."); 188 ExitOnFailure(hr, "Failed to get @DisplayName.");
177 } 189 }
178 190
191 // @InProgressDisplayName
192 hr = XmlGetAttributeEx(pixnArpNode, L"InProgressDisplayName", &pRegistration->sczInProgressDisplayName);
193 if (E_NOTFOUND != hr)
194 {
195 ExitOnFailure(hr, "Failed to get @InProgressDisplayName.");
196 }
197
179 // @DisplayVersion 198 // @DisplayVersion
180 hr = XmlGetAttributeEx(pixnArpNode, L"DisplayVersion", &pRegistration->sczDisplayVersion); 199 hr = XmlGetAttributeEx(pixnArpNode, L"DisplayVersion", &pRegistration->sczDisplayVersion);
181 if (E_NOTFOUND != hr) 200 if (E_NOTFOUND != hr)
@@ -372,6 +391,7 @@ extern "C" void RegistrationUninitialize(
372 ReleaseStr(pRegistration->sczStateFile); 391 ReleaseStr(pRegistration->sczStateFile);
373 392
374 ReleaseStr(pRegistration->sczDisplayName); 393 ReleaseStr(pRegistration->sczDisplayName);
394 ReleaseStr(pRegistration->sczInProgressDisplayName);
375 ReleaseStr(pRegistration->sczDisplayVersion); 395 ReleaseStr(pRegistration->sczDisplayVersion);
376 ReleaseStr(pRegistration->sczPublisher); 396 ReleaseStr(pRegistration->sczPublisher);
377 ReleaseStr(pRegistration->sczHelpLink); 397 ReleaseStr(pRegistration->sczHelpLink);
@@ -421,8 +441,7 @@ extern "C" HRESULT RegistrationSetVariables(
421 ) 441 )
422{ 442{
423 HRESULT hr = S_OK; 443 HRESULT hr = S_OK;
424 LPWSTR sczBundleManufacturer = NULL; 444 LPWSTR scz = NULL;
425 LPWSTR sczBundleName = NULL;
426 445
427 if (pRegistration->fInstalled) 446 if (pRegistration->fInstalled)
428 { 447 {
@@ -431,10 +450,13 @@ extern "C" HRESULT RegistrationSetVariables(
431 } 450 }
432 451
433 // Ensure the registration bundle name is updated. 452 // Ensure the registration bundle name is updated.
434 hr = GetBundleName(pRegistration, pVariables, &sczBundleName); 453 hr = GetBundleInProgressName(pRegistration, pVariables, &scz);
435 ExitOnFailure(hr, "Failed to initialize bundle name."); 454 ExitOnFailure(hr, "Failed to initialize bundle name.");
436 455
437 hr = GetBundleManufacturer(pRegistration, pVariables, &sczBundleName); 456 hr = GetBundleName(pRegistration, pVariables, &scz);
457 ExitOnFailure(hr, "Failed to initialize bundle name.");
458
459 hr = GetBundleManufacturer(pRegistration, pVariables, &scz);
438 ExitOnFailure(hr, "Failed to initialize bundle manufacturer."); 460 ExitOnFailure(hr, "Failed to initialize bundle manufacturer.");
439 461
440 if (pRegistration->sczActiveParent && *pRegistration->sczActiveParent) 462 if (pRegistration->sczActiveParent && *pRegistration->sczActiveParent)
@@ -456,8 +478,7 @@ extern "C" HRESULT RegistrationSetVariables(
456 ExitOnFailure(hr, "Failed to overwrite the bundle reboot-pending built-in variable."); 478 ExitOnFailure(hr, "Failed to overwrite the bundle reboot-pending built-in variable.");
457 479
458LExit: 480LExit:
459 ReleaseStr(sczBundleManufacturer); 481 ReleaseStr(scz);
460 ReleaseStr(sczBundleName);
461 482
462 return hr; 483 return hr;
463} 484}
@@ -595,7 +616,8 @@ extern "C" HRESULT RegistrationSessionBegin(
595 __in BURN_VARIABLES* pVariables, 616 __in BURN_VARIABLES* pVariables,
596 __in DWORD dwRegistrationOptions, 617 __in DWORD dwRegistrationOptions,
597 __in BURN_DEPENDENCY_REGISTRATION_ACTION dependencyRegistrationAction, 618 __in BURN_DEPENDENCY_REGISTRATION_ACTION dependencyRegistrationAction,
598 __in DWORD64 qwEstimatedSize 619 __in DWORD64 qwEstimatedSize,
620 __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType
599 ) 621 )
600{ 622{
601 HRESULT hr = S_OK; 623 HRESULT hr = S_OK;
@@ -603,6 +625,8 @@ extern "C" HRESULT RegistrationSessionBegin(
603 HKEY hkRegistration = NULL; 625 HKEY hkRegistration = NULL;
604 LPWSTR sczPublisher = NULL; 626 LPWSTR sczPublisher = NULL;
605 627
628 AssertSz(BOOTSTRAPPER_REGISTRATION_TYPE_NONE != registrationType, "Registration type can't be NONE");
629
606 LogId(REPORT_VERBOSE, MSG_SESSION_BEGIN, pRegistration->sczRegistrationKey, dwRegistrationOptions, LoggingBoolToString(pRegistration->fDisableResume)); 630 LogId(REPORT_VERBOSE, MSG_SESSION_BEGIN, pRegistration->sczRegistrationKey, dwRegistrationOptions, LoggingBoolToString(pRegistration->fDisableResume));
607 631
608 // Cache bundle executable. 632 // Cache bundle executable.
@@ -668,7 +692,7 @@ extern "C" HRESULT RegistrationSessionBegin(
668 ExitOnFailure(hr, "Failed to write %ls value.", REGISTRY_BUNDLE_DISPLAY_ICON); 692 ExitOnFailure(hr, "Failed to write %ls value.", REGISTRY_BUNDLE_DISPLAY_ICON);
669 693
670 // update display name 694 // update display name
671 hr = UpdateBundleNameRegistration(pRegistration, pVariables, hkRegistration); 695 hr = UpdateBundleNameRegistration(pRegistration, pVariables, hkRegistration, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS == registrationType);
672 ExitOnFailure(hr, "Failed to update name and publisher."); 696 ExitOnFailure(hr, "Failed to update name and publisher.");
673 697
674 // DisplayVersion: provided by UI 698 // DisplayVersion: provided by UI
@@ -841,12 +865,15 @@ LExit:
841*******************************************************************/ 865*******************************************************************/
842extern "C" HRESULT RegistrationSessionResume( 866extern "C" HRESULT RegistrationSessionResume(
843 __in BURN_REGISTRATION* pRegistration, 867 __in BURN_REGISTRATION* pRegistration,
844 __in BURN_VARIABLES* pVariables 868 __in BURN_VARIABLES* pVariables,
869 __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType
845 ) 870 )
846{ 871{
847 HRESULT hr = S_OK; 872 HRESULT hr = S_OK;
848 HKEY hkRegistration = NULL; 873 HKEY hkRegistration = NULL;
849 874
875 AssertSz(BOOTSTRAPPER_REGISTRATION_TYPE_NONE != registrationType, "Registration type can't be NONE");
876
850 // open registration key 877 // open registration key
851 hr = RegOpen(pRegistration->hkRoot, pRegistration->sczRegistrationKey, KEY_WRITE, &hkRegistration); 878 hr = RegOpen(pRegistration->hkRoot, pRegistration->sczRegistrationKey, KEY_WRITE, &hkRegistration);
852 ExitOnFailure(hr, "Failed to open registration key."); 879 ExitOnFailure(hr, "Failed to open registration key.");
@@ -856,7 +883,7 @@ extern "C" HRESULT RegistrationSessionResume(
856 ExitOnFailure(hr, "Failed to update resume mode."); 883 ExitOnFailure(hr, "Failed to update resume mode.");
857 884
858 // update display name 885 // update display name
859 hr = UpdateBundleNameRegistration(pRegistration, pVariables, hkRegistration); 886 hr = UpdateBundleNameRegistration(pRegistration, pVariables, hkRegistration, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS == registrationType);
860 ExitOnFailure(hr, "Failed to update name and publisher."); 887 ExitOnFailure(hr, "Failed to update name and publisher.");
861 888
862LExit: 889LExit:
@@ -876,7 +903,8 @@ extern "C" HRESULT RegistrationSessionEnd(
876 __in BURN_PACKAGES* pPackages, 903 __in BURN_PACKAGES* pPackages,
877 __in BURN_RESUME_MODE resumeMode, 904 __in BURN_RESUME_MODE resumeMode,
878 __in BOOTSTRAPPER_APPLY_RESTART restart, 905 __in BOOTSTRAPPER_APPLY_RESTART restart,
879 __in BURN_DEPENDENCY_REGISTRATION_ACTION dependencyRegistrationAction 906 __in BURN_DEPENDENCY_REGISTRATION_ACTION dependencyRegistrationAction,
907 __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType
880 ) 908 )
881{ 909{
882 HRESULT hr = S_OK; 910 HRESULT hr = S_OK;
@@ -884,8 +912,6 @@ extern "C" HRESULT RegistrationSessionEnd(
884 HKEY hkRebootRequired = NULL; 912 HKEY hkRebootRequired = NULL;
885 HKEY hkRegistration = NULL; 913 HKEY hkRegistration = NULL;
886 914
887 LogId(REPORT_STANDARD, MSG_SESSION_END, pRegistration->sczRegistrationKey, LoggingResumeModeToString(resumeMode), LoggingRestartToString(restart), LoggingBoolToString(pRegistration->fDisableResume));
888
889 // If a restart is required for any reason, write a volatile registry key to track of 915 // If a restart is required for any reason, write a volatile registry key to track of
890 // of that fact until the reboot has taken place. 916 // of that fact until the reboot has taken place.
891 if (BOOTSTRAPPER_APPLY_RESTART_NONE != restart) 917 if (BOOTSTRAPPER_APPLY_RESTART_NONE != restart)
@@ -910,6 +936,8 @@ extern "C" HRESULT RegistrationSessionEnd(
910 // If no resume mode, then remove the bundle registration. 936 // If no resume mode, then remove the bundle registration.
911 if (BURN_RESUME_MODE_NONE == resumeMode) 937 if (BURN_RESUME_MODE_NONE == resumeMode)
912 { 938 {
939 AssertSz(BOOTSTRAPPER_REGISTRATION_TYPE_NONE == registrationType, "Registration type must be NONE if resume mode is NONE");
940
913 // If we just registered the bundle dependency but something went wrong and caused us to not 941 // If we just registered the bundle dependency but something went wrong and caused us to not
914 // keep the bundle registration (like rollback) or we are supposed to unregister the bundle 942 // keep the bundle registration (like rollback) or we are supposed to unregister the bundle
915 // dependency when unregistering the bundle, do so. 943 // dependency when unregistering the bundle, do so.
@@ -939,9 +967,15 @@ extern "C" HRESULT RegistrationSessionEnd(
939 } 967 }
940 else // the mode needs to be updated so open the registration key. 968 else // the mode needs to be updated so open the registration key.
941 { 969 {
970 AssertSz(BOOTSTRAPPER_REGISTRATION_TYPE_NONE != registrationType, "Registration type must not be NONE if resume mode is not NONE");
971
942 // Open registration key. 972 // Open registration key.
943 hr = RegOpen(pRegistration->hkRoot, pRegistration->sczRegistrationKey, KEY_WRITE, &hkRegistration); 973 hr = RegOpen(pRegistration->hkRoot, pRegistration->sczRegistrationKey, KEY_WRITE, &hkRegistration);
944 ExitOnFailure(hr, "Failed to open registration key."); 974 ExitOnFailure(hr, "Failed to open registration key.");
975
976 // update display name
977 hr = UpdateBundleNameRegistration(pRegistration, pVariables, hkRegistration, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS == registrationType);
978 ExitOnFailure(hr, "Failed to update name and publisher.");
945 } 979 }
946 980
947 // Update resume mode. 981 // Update resume mode.
@@ -1133,44 +1167,69 @@ LExit:
1133static HRESULT GetBundleManufacturer( 1167static HRESULT GetBundleManufacturer(
1134 __in BURN_REGISTRATION* pRegistration, 1168 __in BURN_REGISTRATION* pRegistration,
1135 __in BURN_VARIABLES* pVariables, 1169 __in BURN_VARIABLES* pVariables,
1136 __out LPWSTR* psczBundleManufacturer 1170 __out_z LPWSTR* psczBundleManufacturer
1137 ) 1171 )
1138{ 1172{
1139 HRESULT hr = S_OK; 1173 HRESULT hr = S_OK;
1140 LPCWSTR wzPublisher = pRegistration->sczPublisher ? pRegistration->sczPublisher : L""; 1174 LPCWSTR wzPublisher = pRegistration->sczPublisher ? pRegistration->sczPublisher : L"";
1141 1175
1142 hr = VariableGetString(pVariables, BURN_BUNDLE_MANUFACTURER, psczBundleManufacturer); 1176 hr = EnsureRegistrationVariable(pVariables, BURN_BUNDLE_MANUFACTURER, wzPublisher, psczBundleManufacturer);
1143 if (E_NOTFOUND == hr)
1144 {
1145 hr = VariableSetString(pVariables, BURN_BUNDLE_MANUFACTURER, wzPublisher, FALSE, FALSE);
1146 ExitOnFailure(hr, "Failed to set bundle manufacturer.");
1147
1148 hr = StrAllocString(psczBundleManufacturer, wzPublisher, 0);
1149 }
1150 ExitOnFailure(hr, "Failed to get bundle manufacturer."); 1177 ExitOnFailure(hr, "Failed to get bundle manufacturer.");
1151 1178
1152LExit: 1179LExit:
1153 return hr; 1180 return hr;
1154} 1181}
1155 1182
1183static HRESULT GetBundleInProgressName(
1184 __in BURN_REGISTRATION* pRegistration,
1185 __in BURN_VARIABLES* pVariables,
1186 __out_z LPWSTR* psczInProgressBundleName
1187 )
1188{
1189 HRESULT hr = S_OK;
1190 LPCWSTR wzInProgressDisplayName = pRegistration->sczInProgressDisplayName ? pRegistration->sczInProgressDisplayName : L"";
1191
1192 hr = EnsureRegistrationVariable(pVariables, BURN_BUNDLE_INPROGRESS_NAME, wzInProgressDisplayName, psczInProgressBundleName);
1193 ExitOnFailure(hr, "Failed to ensure in-progress bundle name.");
1194
1195LExit:
1196 return hr;
1197}
1198
1156static HRESULT GetBundleName( 1199static HRESULT GetBundleName(
1157 __in BURN_REGISTRATION* pRegistration, 1200 __in BURN_REGISTRATION* pRegistration,
1158 __in BURN_VARIABLES* pVariables, 1201 __in BURN_VARIABLES* pVariables,
1159 __out LPWSTR* psczBundleName 1202 __out_z LPWSTR* psczBundleName
1160 ) 1203 )
1161{ 1204{
1162 HRESULT hr = S_OK; 1205 HRESULT hr = S_OK;
1163 LPCWSTR wzDisplayName = pRegistration->sczDisplayName ? pRegistration->sczDisplayName : L""; 1206 LPCWSTR wzDisplayName = pRegistration->sczDisplayName ? pRegistration->sczDisplayName : L"";
1164 1207
1165 hr = VariableGetString(pVariables, BURN_BUNDLE_NAME, psczBundleName); 1208 hr = EnsureRegistrationVariable(pVariables, BURN_BUNDLE_NAME, wzDisplayName, psczBundleName);
1209 ExitOnFailure(hr, "Failed to ensure bundle name.");
1210
1211LExit:
1212 return hr;
1213}
1214
1215static HRESULT EnsureRegistrationVariable(
1216 __in BURN_VARIABLES* pVariables,
1217 __in_z LPCWSTR wzVariable,
1218 __in_z LPCWSTR wzDefaultValue,
1219 __out_z LPWSTR* psczValue
1220 )
1221{
1222 HRESULT hr = S_OK;
1223
1224 hr = VariableGetString(pVariables, wzVariable, psczValue);
1166 if (E_NOTFOUND == hr) 1225 if (E_NOTFOUND == hr)
1167 { 1226 {
1168 hr = VariableSetString(pVariables, BURN_BUNDLE_NAME, wzDisplayName, FALSE, FALSE); 1227 hr = VariableSetString(pVariables, wzVariable, wzDefaultValue, FALSE, FALSE);
1169 ExitOnFailure(hr, "Failed to set bundle name."); 1228 ExitOnFailure(hr, "Failed to set registration variable.");
1170 1229
1171 hr = StrAllocString(psczBundleName, wzDisplayName, 0); 1230 hr = StrAllocString(psczValue, wzDefaultValue, 0);
1172 } 1231 }
1173 ExitOnFailure(hr, "Failed to get bundle name."); 1232 ExitOnFailure(hr, "Failed to get registration variable.");
1174 1233
1175LExit: 1234LExit:
1176 return hr; 1235 return hr;
@@ -1584,15 +1643,26 @@ LExit:
1584static HRESULT UpdateBundleNameRegistration( 1643static HRESULT UpdateBundleNameRegistration(
1585 __in BURN_REGISTRATION* pRegistration, 1644 __in BURN_REGISTRATION* pRegistration,
1586 __in BURN_VARIABLES* pVariables, 1645 __in BURN_VARIABLES* pVariables,
1587 __in HKEY hkRegistration 1646 __in HKEY hkRegistration,
1647 __in BOOL fInProgressRegistration
1588 ) 1648 )
1589{ 1649{
1590 HRESULT hr = S_OK; 1650 HRESULT hr = S_OK;
1591 LPWSTR sczDisplayName = NULL; 1651 LPWSTR sczDisplayName = NULL;
1592 1652
1593 // DisplayName: provided by UI 1653 if (fInProgressRegistration)
1594 hr = GetBundleName(pRegistration, pVariables, &sczDisplayName); 1654 {
1595 hr = RegWriteString(hkRegistration, BURN_REGISTRATION_REGISTRY_BUNDLE_DISPLAY_NAME, SUCCEEDED(hr) ? sczDisplayName : pRegistration->sczDisplayName); 1655 hr = GetBundleInProgressName(pRegistration, pVariables, &sczDisplayName);
1656 ExitOnFailure(hr, "Failed to get bundle in-progress name.");
1657 }
1658
1659 if (!sczDisplayName || !*sczDisplayName)
1660 {
1661 hr = GetBundleName(pRegistration, pVariables, &sczDisplayName);
1662 ExitOnFailure(hr, "Failed to get bundle name.");
1663 }
1664
1665 hr = RegWriteString(hkRegistration, BURN_REGISTRATION_REGISTRY_BUNDLE_DISPLAY_NAME, sczDisplayName);
1596 ExitOnFailure(hr, "Failed to write %ls value.", BURN_REGISTRATION_REGISTRY_BUNDLE_DISPLAY_NAME); 1666 ExitOnFailure(hr, "Failed to write %ls value.", BURN_REGISTRATION_REGISTRY_BUNDLE_DISPLAY_NAME);
1597 1667
1598LExit: 1668LExit:
diff --git a/src/burn/engine/registration.h b/src/burn/engine/registration.h
index 6d8a6d2a..936e5966 100644
--- a/src/burn/engine/registration.h
+++ b/src/burn/engine/registration.h
@@ -123,6 +123,7 @@ typedef struct _BURN_REGISTRATION
123 123
124 // ARP registration 124 // ARP registration
125 LPWSTR sczDisplayName; 125 LPWSTR sczDisplayName;
126 LPWSTR sczInProgressDisplayName;
126 LPWSTR sczDisplayVersion; 127 LPWSTR sczDisplayVersion;
127 LPWSTR sczPublisher; 128 LPWSTR sczPublisher;
128 LPWSTR sczHelpLink; 129 LPWSTR sczHelpLink;
@@ -190,11 +191,13 @@ HRESULT RegistrationSessionBegin(
190 __in BURN_VARIABLES* pVariables, 191 __in BURN_VARIABLES* pVariables,
191 __in DWORD dwRegistrationOptions, 192 __in DWORD dwRegistrationOptions,
192 __in BURN_DEPENDENCY_REGISTRATION_ACTION dependencyRegistrationAction, 193 __in BURN_DEPENDENCY_REGISTRATION_ACTION dependencyRegistrationAction,
193 __in DWORD64 qwEstimatedSize 194 __in DWORD64 qwEstimatedSize,
195 __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType
194 ); 196 );
195HRESULT RegistrationSessionResume( 197HRESULT RegistrationSessionResume(
196 __in BURN_REGISTRATION* pRegistration, 198 __in BURN_REGISTRATION* pRegistration,
197 __in BURN_VARIABLES* pVariables 199 __in BURN_VARIABLES* pVariables,
200 __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType
198 ); 201 );
199HRESULT RegistrationSessionEnd( 202HRESULT RegistrationSessionEnd(
200 __in BURN_REGISTRATION* pRegistration, 203 __in BURN_REGISTRATION* pRegistration,
@@ -202,7 +205,8 @@ HRESULT RegistrationSessionEnd(
202 __in BURN_PACKAGES* pPackages, 205 __in BURN_PACKAGES* pPackages,
203 __in BURN_RESUME_MODE resumeMode, 206 __in BURN_RESUME_MODE resumeMode,
204 __in BOOTSTRAPPER_APPLY_RESTART restart, 207 __in BOOTSTRAPPER_APPLY_RESTART restart,
205 __in BURN_DEPENDENCY_REGISTRATION_ACTION dependencyRegistrationAction 208 __in BURN_DEPENDENCY_REGISTRATION_ACTION dependencyRegistrationAction,
209 __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType
206 ); 210 );
207HRESULT RegistrationSaveState( 211HRESULT RegistrationSaveState(
208 __in BURN_REGISTRATION* pRegistration, 212 __in BURN_REGISTRATION* pRegistration,
diff --git a/src/burn/engine/userexperience.cpp b/src/burn/engine/userexperience.cpp
index 5a54f26e..07f4b831 100644
--- a/src/burn/engine/userexperience.cpp
+++ b/src/burn/engine/userexperience.cpp
@@ -2119,7 +2119,8 @@ EXTERN_C BAAPI UserExperienceOnProgress(
2119} 2119}
2120 2120
2121EXTERN_C BAAPI UserExperienceOnRegisterBegin( 2121EXTERN_C BAAPI UserExperienceOnRegisterBegin(
2122 __in BURN_USER_EXPERIENCE* pUserExperience 2122 __in BURN_USER_EXPERIENCE* pUserExperience,
2123 __inout BOOTSTRAPPER_REGISTRATION_TYPE* pRegistrationType
2123 ) 2124 )
2124{ 2125{
2125 HRESULT hr = S_OK; 2126 HRESULT hr = S_OK;
@@ -2127,8 +2128,10 @@ EXTERN_C BAAPI UserExperienceOnRegisterBegin(
2127 BA_ONREGISTERBEGIN_RESULTS results = { }; 2128 BA_ONREGISTERBEGIN_RESULTS results = { };
2128 2129
2129 args.cbSize = sizeof(args); 2130 args.cbSize = sizeof(args);
2131 args.recommendedRegistrationType = *pRegistrationType;
2130 2132
2131 results.cbSize = sizeof(results); 2133 results.cbSize = sizeof(results);
2134 results.registrationType = *pRegistrationType;
2132 2135
2133 hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONREGISTERBEGIN, &args, &results); 2136 hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONREGISTERBEGIN, &args, &results);
2134 ExitOnFailure(hr, "BA OnRegisterBegin failed."); 2137 ExitOnFailure(hr, "BA OnRegisterBegin failed.");
@@ -2137,6 +2140,10 @@ EXTERN_C BAAPI UserExperienceOnRegisterBegin(
2137 { 2140 {
2138 hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT); 2141 hr = HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT);
2139 } 2142 }
2143 else if (BOOTSTRAPPER_REGISTRATION_TYPE_NONE < results.registrationType && BOOTSTRAPPER_REGISTRATION_TYPE_FULL >= results.registrationType)
2144 {
2145 *pRegistrationType = results.registrationType;
2146 }
2140 2147
2141LExit: 2148LExit:
2142 return hr; 2149 return hr;
@@ -2316,7 +2323,7 @@ LExit:
2316 2323
2317EXTERN_C BAAPI UserExperienceOnUnregisterBegin( 2324EXTERN_C BAAPI UserExperienceOnUnregisterBegin(
2318 __in BURN_USER_EXPERIENCE* pUserExperience, 2325 __in BURN_USER_EXPERIENCE* pUserExperience,
2319 __inout BOOL* pfKeepRegistration 2326 __inout BOOTSTRAPPER_REGISTRATION_TYPE* pRegistrationType
2320 ) 2327 )
2321{ 2328{
2322 HRESULT hr = S_OK; 2329 HRESULT hr = S_OK;
@@ -2324,16 +2331,17 @@ EXTERN_C BAAPI UserExperienceOnUnregisterBegin(
2324 BA_ONUNREGISTERBEGIN_RESULTS results = { }; 2331 BA_ONUNREGISTERBEGIN_RESULTS results = { };
2325 2332
2326 args.cbSize = sizeof(args); 2333 args.cbSize = sizeof(args);
2327 args.fKeepRegistration = *pfKeepRegistration; 2334 args.recommendedRegistrationType = *pRegistrationType;
2328 2335
2329 results.cbSize = sizeof(results); 2336 results.cbSize = sizeof(results);
2337 results.registrationType = *pRegistrationType;
2330 2338
2331 hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONUNREGISTERBEGIN, &args, &results); 2339 hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONUNREGISTERBEGIN, &args, &results);
2332 ExitOnFailure(hr, "BA OnUnregisterBegin failed."); 2340 ExitOnFailure(hr, "BA OnUnregisterBegin failed.");
2333 2341
2334 if (!args.fKeepRegistration && results.fForceKeepRegistration) 2342 if (BOOTSTRAPPER_REGISTRATION_TYPE_NONE < results.registrationType && BOOTSTRAPPER_REGISTRATION_TYPE_FULL >= results.registrationType)
2335 { 2343 {
2336 *pfKeepRegistration = TRUE; 2344 *pRegistrationType = results.registrationType;
2337 } 2345 }
2338 2346
2339LExit: 2347LExit:
diff --git a/src/burn/engine/userexperience.h b/src/burn/engine/userexperience.h
index f2453dca..56bc3239 100644
--- a/src/burn/engine/userexperience.h
+++ b/src/burn/engine/userexperience.h
@@ -486,7 +486,8 @@ BAAPI UserExperienceOnProgress(
486 __in DWORD dwOverallPercentage 486 __in DWORD dwOverallPercentage
487 ); 487 );
488BAAPI UserExperienceOnRegisterBegin( 488BAAPI UserExperienceOnRegisterBegin(
489 __in BURN_USER_EXPERIENCE* pUserExperience 489 __in BURN_USER_EXPERIENCE* pUserExperience,
490 __inout BOOTSTRAPPER_REGISTRATION_TYPE* pRegistrationType
490 ); 491 );
491BAAPI UserExperienceOnRegisterComplete( 492BAAPI UserExperienceOnRegisterComplete(
492 __in BURN_USER_EXPERIENCE* pUserExperience, 493 __in BURN_USER_EXPERIENCE* pUserExperience,
@@ -522,7 +523,7 @@ BAAPI UserExperienceOnSystemShutdown(
522 ); 523 );
523BAAPI UserExperienceOnUnregisterBegin( 524BAAPI UserExperienceOnUnregisterBegin(
524 __in BURN_USER_EXPERIENCE* pUserExperience, 525 __in BURN_USER_EXPERIENCE* pUserExperience,
525 __inout BOOL* pfKeepRegistration 526 __inout BOOTSTRAPPER_REGISTRATION_TYPE* pRegistrationType
526 ); 527 );
527BAAPI UserExperienceOnUnregisterComplete( 528BAAPI UserExperienceOnUnregisterComplete(
528 __in BURN_USER_EXPERIENCE* pUserExperience, 529 __in BURN_USER_EXPERIENCE* pUserExperience,
diff --git a/src/burn/test/BurnUnitTest/RegistrationTest.cpp b/src/burn/test/BurnUnitTest/RegistrationTest.cpp
index 7b126f61..96bdb2bf 100644
--- a/src/burn/test/BurnUnitTest/RegistrationTest.cpp
+++ b/src/burn/test/BurnUnitTest/RegistrationTest.cpp
@@ -112,7 +112,7 @@ namespace Bootstrapper
112 TestThrowOnFailure(hr, L"Failed to get current process path."); 112 TestThrowOnFailure(hr, L"Failed to get current process path.");
113 113
114 // write registration 114 // write registration
115 hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE | BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0); 115 hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_CACHE_BUNDLE | BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
116 TestThrowOnFailure(hr, L"Failed to register bundle."); 116 TestThrowOnFailure(hr, L"Failed to register bundle.");
117 117
118 // verify that registration was created 118 // verify that registration was created
@@ -123,7 +123,7 @@ namespace Bootstrapper
123 Assert::Equal<String^>(String::Concat(L"\"", Path::Combine(cacheDirectory, gcnew String(L"setup.exe")), L"\" /burn.runonce"), (String^)(Registry::GetValue(gcnew String(TEST_RUN_KEY), gcnew String(L"{D54F896D-1952-43e6-9C67-B5652240618C}"), nullptr))); 123 Assert::Equal<String^>(String::Concat(L"\"", Path::Combine(cacheDirectory, gcnew String(L"setup.exe")), L"\" /burn.runonce"), (String^)(Registry::GetValue(gcnew String(TEST_RUN_KEY), gcnew String(L"{D54F896D-1952-43e6-9C67-B5652240618C}"), nullptr)));
124 124
125 // end session 125 // end session
126 hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER); 126 hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_NONE);
127 TestThrowOnFailure(hr, L"Failed to unregister bundle."); 127 TestThrowOnFailure(hr, L"Failed to unregister bundle.");
128 128
129 // verify that registration was removed 129 // verify that registration was removed
@@ -178,7 +178,7 @@ namespace Bootstrapper
178 L" <Payload Id='ux.dll' FilePath='ux.dll' Packaging='embedded' SourcePath='ux.dll' Hash='000000000000' />" 178 L" <Payload Id='ux.dll' FilePath='ux.dll' Packaging='embedded' SourcePath='ux.dll' Hash='000000000000' />"
179 L" </UX>" 179 L" </UX>"
180 L" <Registration Id='{D54F896D-1952-43e6-9C67-B5652240618C}' UpgradeCode='{D54F896D-1952-43e6-9C67-B5652240618C}' Tag='foo' ProviderKey='foo' Version='1.0.0.0' ExecutableName='setup.exe' PerMachine='no'>" 180 L" <Registration Id='{D54F896D-1952-43e6-9C67-B5652240618C}' UpgradeCode='{D54F896D-1952-43e6-9C67-B5652240618C}' Tag='foo' ProviderKey='foo' Version='1.0.0.0' ExecutableName='setup.exe' PerMachine='no'>"
181 L" <Arp Register='yes' Publisher='WiX Toolset' DisplayName='Product1' DisplayVersion='1.0.0.0' />" 181 L" <Arp Register='yes' Publisher='WiX Toolset' DisplayName='Product1' InProgressDisplayName='Product1 Installation' DisplayVersion='1.0.0.0' />"
182 L" </Registration>" 182 L" </Registration>"
183 L"</Bundle>"; 183 L"</Bundle>";
184 184
@@ -205,15 +205,16 @@ namespace Bootstrapper
205 // 205 //
206 206
207 // write registration 207 // write registration
208 hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0); 208 hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
209 TestThrowOnFailure(hr, L"Failed to register bundle."); 209 TestThrowOnFailure(hr, L"Failed to register bundle.");
210 210
211 // verify that registration was created 211 // verify that registration was created
212 Assert::Equal<String^>(gcnew String(L"Product1 Installation"), (String^)Registry::GetValue(gcnew String(TEST_UNINSTALL_KEY), gcnew String(L"DisplayName"), nullptr));
212 Assert::Equal(Int32(BURN_RESUME_MODE_ACTIVE), (Int32)Registry::GetValue(gcnew String(TEST_UNINSTALL_KEY), gcnew String(L"Resume"), nullptr)); 213 Assert::Equal(Int32(BURN_RESUME_MODE_ACTIVE), (Int32)Registry::GetValue(gcnew String(TEST_UNINSTALL_KEY), gcnew String(L"Resume"), nullptr));
213 Assert::Equal<String^>(String::Concat(L"\"", Path::Combine(cacheDirectory, gcnew String(L"setup.exe")), L"\" /burn.runonce"), (String^)Registry::GetValue(gcnew String(TEST_RUN_KEY), gcnew String(L"{D54F896D-1952-43e6-9C67-B5652240618C}"), nullptr)); 214 Assert::Equal<String^>(String::Concat(L"\"", Path::Combine(cacheDirectory, gcnew String(L"setup.exe")), L"\" /burn.runonce"), (String^)Registry::GetValue(gcnew String(TEST_RUN_KEY), gcnew String(L"{D54F896D-1952-43e6-9C67-B5652240618C}"), nullptr));
214 215
215 // complete registration 216 // complete registration
216 hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_ARP, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER); 217 hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_ARP, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
217 TestThrowOnFailure(hr, L"Failed to unregister bundle."); 218 TestThrowOnFailure(hr, L"Failed to unregister bundle.");
218 219
219 // verify that registration was updated 220 // verify that registration was updated
@@ -226,7 +227,7 @@ namespace Bootstrapper
226 // 227 //
227 228
228 // write registration 229 // write registration
229 hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, 0); 230 hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
230 TestThrowOnFailure(hr, L"Failed to register bundle."); 231 TestThrowOnFailure(hr, L"Failed to register bundle.");
231 232
232 // verify that registration was updated 233 // verify that registration was updated
@@ -235,7 +236,7 @@ namespace Bootstrapper
235 Assert::Equal<String^>(String::Concat(L"\"", Path::Combine(cacheDirectory, gcnew String(L"setup.exe")), L"\" /burn.runonce"), (String^)Registry::GetValue(gcnew String(TEST_RUN_KEY), gcnew String(L"{D54F896D-1952-43e6-9C67-B5652240618C}"), nullptr)); 236 Assert::Equal<String^>(String::Concat(L"\"", Path::Combine(cacheDirectory, gcnew String(L"setup.exe")), L"\" /burn.runonce"), (String^)Registry::GetValue(gcnew String(TEST_RUN_KEY), gcnew String(L"{D54F896D-1952-43e6-9C67-B5652240618C}"), nullptr));
236 237
237 // delete registration 238 // delete registration
238 hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER); 239 hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_NONE);
239 TestThrowOnFailure(hr, L"Failed to unregister bundle."); 240 TestThrowOnFailure(hr, L"Failed to unregister bundle.");
240 241
241 // verify that registration was removed 242 // verify that registration was removed
@@ -316,7 +317,7 @@ namespace Bootstrapper
316 // 317 //
317 318
318 // write registration 319 // write registration
319 hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0); 320 hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
320 TestThrowOnFailure(hr, L"Failed to register bundle."); 321 TestThrowOnFailure(hr, L"Failed to register bundle.");
321 322
322 // verify that registration was created 323 // verify that registration was created
@@ -324,10 +325,11 @@ namespace Bootstrapper
324 Assert::Equal<String^>(String::Concat(L"\"", Path::Combine(cacheDirectory, gcnew String(L"setup.exe")), L"\" /burn.runonce"), (String^)Registry::GetValue(gcnew String(TEST_RUN_KEY), gcnew String(L"{D54F896D-1952-43e6-9C67-B5652240618C}"), nullptr)); 325 Assert::Equal<String^>(String::Concat(L"\"", Path::Combine(cacheDirectory, gcnew String(L"setup.exe")), L"\" /burn.runonce"), (String^)Registry::GetValue(gcnew String(TEST_RUN_KEY), gcnew String(L"{D54F896D-1952-43e6-9C67-B5652240618C}"), nullptr));
325 326
326 // complete registration 327 // complete registration
327 hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_ARP, BOOTSTRAPPER_APPLY_RESTART_REQUIRED, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER); 328 hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_ARP, BOOTSTRAPPER_APPLY_RESTART_REQUIRED, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_FULL);
328 TestThrowOnFailure(hr, L"Failed to unregister bundle."); 329 TestThrowOnFailure(hr, L"Failed to unregister bundle.");
329 330
330 // verify that registration variables were updated 331 // verify that registration variables were updated
332 Assert::Equal<String^>(gcnew String(L"Product1"), (String^)Registry::GetValue(gcnew String(TEST_UNINSTALL_KEY), gcnew String(L"DisplayName"), nullptr));
331 registration.fInstalled = TRUE; 333 registration.fInstalled = TRUE;
332 334
333 hr = RegistrationSetVariables(&registration, &variables); 335 hr = RegistrationSetVariables(&registration, &variables);
@@ -344,7 +346,7 @@ namespace Bootstrapper
344 // 346 //
345 347
346 // delete registration 348 // delete registration
347 hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER); 349 hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_NONE);
348 TestThrowOnFailure(hr, L"Failed to unregister bundle."); 350 TestThrowOnFailure(hr, L"Failed to unregister bundle.");
349 351
350 // verify that registration was removed 352 // verify that registration was removed
@@ -427,7 +429,7 @@ namespace Bootstrapper
427 // 429 //
428 430
429 // write registration 431 // write registration
430 hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0); 432 hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
431 TestThrowOnFailure(hr, L"Failed to register bundle."); 433 TestThrowOnFailure(hr, L"Failed to register bundle.");
432 434
433 // verify that registration was created 435 // verify that registration was created
@@ -435,7 +437,7 @@ namespace Bootstrapper
435 Assert::Equal<String^>(String::Concat(L"\"", Path::Combine(cacheDirectory, gcnew String(L"setup.exe")), L"\" /burn.runonce"), (String^)Registry::GetValue(gcnew String(TEST_RUN_KEY), gcnew String(L"{D54F896D-1952-43e6-9C67-B5652240618C}"), nullptr)); 437 Assert::Equal<String^>(String::Concat(L"\"", Path::Combine(cacheDirectory, gcnew String(L"setup.exe")), L"\" /burn.runonce"), (String^)Registry::GetValue(gcnew String(TEST_RUN_KEY), gcnew String(L"{D54F896D-1952-43e6-9C67-B5652240618C}"), nullptr));
436 438
437 // finish registration 439 // finish registration
438 hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_ARP, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER); 440 hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_ARP, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_FULL);
439 TestThrowOnFailure(hr, L"Failed to register bundle."); 441 TestThrowOnFailure(hr, L"Failed to register bundle.");
440 442
441 // verify that registration was updated 443 // verify that registration was updated
@@ -460,7 +462,7 @@ namespace Bootstrapper
460 // 462 //
461 463
462 // write registration 464 // write registration
463 hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, 0); 465 hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
464 TestThrowOnFailure(hr, L"Failed to register bundle."); 466 TestThrowOnFailure(hr, L"Failed to register bundle.");
465 467
466 // verify that registration was updated 468 // verify that registration was updated
@@ -468,7 +470,7 @@ namespace Bootstrapper
468 Assert::Equal<String^>(String::Concat(L"\"", Path::Combine(cacheDirectory, gcnew String(L"setup.exe")), L"\" /burn.runonce"), (String^)Registry::GetValue(gcnew String(TEST_RUN_KEY), gcnew String(L"{D54F896D-1952-43e6-9C67-B5652240618C}"), nullptr)); 470 Assert::Equal<String^>(String::Concat(L"\"", Path::Combine(cacheDirectory, gcnew String(L"setup.exe")), L"\" /burn.runonce"), (String^)Registry::GetValue(gcnew String(TEST_RUN_KEY), gcnew String(L"{D54F896D-1952-43e6-9C67-B5652240618C}"), nullptr));
469 471
470 // delete registration 472 // delete registration
471 hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER); 473 hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_NONE);
472 TestThrowOnFailure(hr, L"Failed to unregister bundle."); 474 TestThrowOnFailure(hr, L"Failed to unregister bundle.");
473 475
474 // verify that registration was removed 476 // verify that registration was removed
@@ -560,7 +562,7 @@ namespace Bootstrapper
560 Assert::Equal((int)BOOTSTRAPPER_RESUME_TYPE_NONE, (int)resumeType); 562 Assert::Equal((int)BOOTSTRAPPER_RESUME_TYPE_NONE, (int)resumeType);
561 563
562 // begin session 564 // begin session
563 hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0); 565 hr = RegistrationSessionBegin(sczCurrentProcess, &registration, &variables, BURN_REGISTRATION_ACTION_OPERATIONS_WRITE_REGISTRATION, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, 0, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
564 TestThrowOnFailure(hr, L"Failed to register bundle."); 566 TestThrowOnFailure(hr, L"Failed to register bundle.");
565 567
566 hr = RegistrationSaveState(&registration, rgbData, sizeof(rgbData)); 568 hr = RegistrationSaveState(&registration, rgbData, sizeof(rgbData));
@@ -573,7 +575,7 @@ namespace Bootstrapper
573 Assert::Equal((int)BOOTSTRAPPER_RESUME_TYPE_INTERRUPTED, (int)resumeType); 575 Assert::Equal((int)BOOTSTRAPPER_RESUME_TYPE_INTERRUPTED, (int)resumeType);
574 576
575 // suspend session 577 // suspend session
576 hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_SUSPEND, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER); 578 hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_SUSPEND, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_REGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
577 TestThrowOnFailure(hr, L"Failed to suspend session."); 579 TestThrowOnFailure(hr, L"Failed to suspend session.");
578 580
579 // verify that run key was removed 581 // verify that run key was removed
@@ -593,14 +595,14 @@ namespace Bootstrapper
593 Assert::True(0 == memcmp(pbBuffer, rgbData, sizeof(rgbData))); 595 Assert::True(0 == memcmp(pbBuffer, rgbData, sizeof(rgbData)));
594 596
595 // write active resume mode 597 // write active resume mode
596 hr = RegistrationSessionResume(&registration, &variables); 598 hr = RegistrationSessionResume(&registration, &variables, BOOTSTRAPPER_REGISTRATION_TYPE_INPROGRESS);
597 TestThrowOnFailure(hr, L"Failed to write active resume mode."); 599 TestThrowOnFailure(hr, L"Failed to write active resume mode.");
598 600
599 // verify that run key was put back 601 // verify that run key was put back
600 Assert::NotEqual((Object^)nullptr, Registry::GetValue(gcnew String(TEST_RUN_KEY), gcnew String(L"{D54F896D-1952-43e6-9C67-B5652240618C}"), nullptr)); 602 Assert::NotEqual((Object^)nullptr, Registry::GetValue(gcnew String(TEST_RUN_KEY), gcnew String(L"{D54F896D-1952-43e6-9C67-B5652240618C}"), nullptr));
601 603
602 // end session 604 // end session
603 hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER); 605 hr = RegistrationSessionEnd(&registration, &variables, &packages, BURN_RESUME_MODE_NONE, BOOTSTRAPPER_APPLY_RESTART_NONE, BURN_DEPENDENCY_REGISTRATION_ACTION_UNREGISTER, BOOTSTRAPPER_REGISTRATION_TYPE_NONE);
604 TestThrowOnFailure(hr, L"Failed to unregister bundle."); 606 TestThrowOnFailure(hr, L"Failed to unregister bundle.");
605 607
606 // read resume type after session 608 // read resume type after session
diff --git a/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs b/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs
index e95fee54..77f20e5c 100644
--- a/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs
+++ b/src/wix/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs
@@ -210,6 +210,11 @@ namespace WixToolset.Core.Burn.Bundles
210 writer.WriteAttributeString("DisplayName", this.BundleSymbol.Name); 210 writer.WriteAttributeString("DisplayName", this.BundleSymbol.Name);
211 writer.WriteAttributeString("DisplayVersion", this.BundleSymbol.Version); 211 writer.WriteAttributeString("DisplayVersion", this.BundleSymbol.Version);
212 212
213 if (!String.IsNullOrEmpty(this.BundleSymbol.InProgressName))
214 {
215 writer.WriteAttributeString("InProgressDisplayName", this.BundleSymbol.InProgressName);
216 }
217
213 if (!String.IsNullOrEmpty(this.BundleSymbol.Manufacturer)) 218 if (!String.IsNullOrEmpty(this.BundleSymbol.Manufacturer))
214 { 219 {
215 writer.WriteAttributeString("Publisher", this.BundleSymbol.Manufacturer); 220 writer.WriteAttributeString("Publisher", this.BundleSymbol.Manufacturer);
diff --git a/src/wix/WixToolset.Core/Compiler_Bundle.cs b/src/wix/WixToolset.Core/Compiler_Bundle.cs
index 1ca3fb00..3e238b82 100644
--- a/src/wix/WixToolset.Core/Compiler_Bundle.cs
+++ b/src/wix/WixToolset.Core/Compiler_Bundle.cs
@@ -122,6 +122,7 @@ namespace WixToolset.Core
122 WixBundleAttributes attributes = 0; 122 WixBundleAttributes attributes = 0;
123 string helpTelephone = null; 123 string helpTelephone = null;
124 string helpUrl = null; 124 string helpUrl = null;
125 string inProgressName = null;
125 string manufacturer = null; 126 string manufacturer = null;
126 string name = null; 127 string name = null;
127 string tag = null; 128 string tag = null;
@@ -190,6 +191,9 @@ namespace WixToolset.Core
190 case "IconSourceFile": 191 case "IconSourceFile":
191 iconSourceFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib); 192 iconSourceFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
192 break; 193 break;
194 case "InProgressName":
195 inProgressName = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
196 break;
193 case "Name": 197 case "Name":
194 name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); 198 name = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
195 break; 199 break;
@@ -247,6 +251,12 @@ namespace WixToolset.Core
247 } 251 }
248 } 252 }
249 253
254 if (String.IsNullOrEmpty(name) && !String.IsNullOrEmpty(inProgressName))
255 {
256 name = inProgressName;
257 inProgressName = null;
258 }
259
250 if (String.IsNullOrEmpty(name)) 260 if (String.IsNullOrEmpty(name))
251 { 261 {
252 logVariablePrefixAndExtension = String.Concat("WixBundleLog:Setup:log"); 262 logVariablePrefixAndExtension = String.Concat("WixBundleLog:Setup:log");
@@ -280,7 +290,6 @@ namespace WixToolset.Core
280 } 290 }
281 } 291 }
282 292
283 var baSeen = false;
284 var chainSeen = false; 293 var chainSeen = false;
285 var logSeen = false; 294 var logSeen = false;
286 295
@@ -294,13 +303,7 @@ namespace WixToolset.Core
294 this.ParseApprovedExeForElevation(child); 303 this.ParseApprovedExeForElevation(child);
295 break; 304 break;
296 case "BootstrapperApplication": 305 case "BootstrapperApplication":
297 if (baSeen)
298 {
299 var childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(child);
300 this.Core.Write(ErrorMessages.TooManyChildren(childSourceLineNumbers, node.Name.LocalName, "BootstrapperApplication"));
301 }
302 this.ParseBootstrapperApplicationElement(child); 306 this.ParseBootstrapperApplicationElement(child);
303 baSeen = true;
304 break; 307 break;
305 case "BootstrapperApplicationRef": 308 case "BootstrapperApplicationRef":
306 this.ParseBootstrapperApplicationRefElement(child); 309 this.ParseBootstrapperApplicationRefElement(child);
@@ -397,6 +400,7 @@ namespace WixToolset.Core
397 UpgradeCode = upgradeCode, 400 UpgradeCode = upgradeCode,
398 Version = version, 401 Version = version,
399 Copyright = copyright, 402 Copyright = copyright,
403 InProgressName = inProgressName,
400 Name = name, 404 Name = name,
401 Manufacturer = manufacturer, 405 Manufacturer = manufacturer,
402 Attributes = attributes, 406 Attributes = attributes,
@@ -437,6 +441,12 @@ namespace WixToolset.Core
437 }); 441 });
438 442
439 // Ensure that the bundle stores the well-known persisted values. 443 // Ensure that the bundle stores the well-known persisted values.
444 this.Core.AddSymbol(new WixBundleVariableSymbol(sourceLineNumbers, new Identifier(AccessModifier.Section, BurnConstants.BURN_BUNDLE_INPROGRESS_NAME))
445 {
446 Hidden = false,
447 Persisted = true,
448 });
449
440 this.Core.AddSymbol(new WixBundleVariableSymbol(sourceLineNumbers, new Identifier(AccessModifier.Section, BurnConstants.BURN_BUNDLE_NAME)) 450 this.Core.AddSymbol(new WixBundleVariableSymbol(sourceLineNumbers, new Identifier(AccessModifier.Section, BurnConstants.BURN_BUNDLE_NAME))
441 { 451 {
442 Hidden = false, 452 Hidden = false,
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/BundleFixture.cs b/src/wix/test/WixToolsetTest.CoreIntegration/BundleFixture.cs
index ab644080..40167eda 100644
--- a/src/wix/test/WixToolsetTest.CoreIntegration/BundleFixture.cs
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/BundleFixture.cs
@@ -116,7 +116,7 @@ namespace WixToolsetTest.CoreIntegration
116 var registrationElements = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Registration"); 116 var registrationElements = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Registration");
117 var registrationElement = (XmlNode)Assert.Single(registrationElements); 117 var registrationElement = (XmlNode)Assert.Single(registrationElements);
118 Assert.Equal($"<Registration Id='{bundleSymbol.BundleId}' ExecutableName='test.exe' PerMachine='yes' Tag='' Version='1.0.0.0' ProviderKey='{bundleSymbol.BundleId}'>" + 118 Assert.Equal($"<Registration Id='{bundleSymbol.BundleId}' ExecutableName='test.exe' PerMachine='yes' Tag='' Version='1.0.0.0' ProviderKey='{bundleSymbol.BundleId}'>" +
119 "<Arp Register='yes' DisplayName='~TestBundle' DisplayVersion='1.0.0.0' Publisher='Example Corporation' />" + 119 "<Arp Register='yes' DisplayName='~TestBundle' DisplayVersion='1.0.0.0' InProgressDisplayName='~InProgressTestBundle' Publisher='Example Corporation' />" +
120 "</Registration>", registrationElement.GetTestXml()); 120 "</Registration>", registrationElement.GetTestXml());
121 121
122 var msiPayloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload[@Id='test.msi']"); 122 var msiPayloads = extractResult.SelectManifestNodes("/burn:BurnManifest/burn:Payload[@Id='test.msi']");
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimpleBundle/Bundle.en-us.wxl b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimpleBundle/Bundle.en-us.wxl
index bc1dee83..2a7af0b3 100644
--- a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimpleBundle/Bundle.en-us.wxl
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimpleBundle/Bundle.en-us.wxl
@@ -6,5 +6,6 @@ This file contains the declaration of all the localizable strings.
6<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US"> 6<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US">
7 7
8 <String Id="BundleName">~TestBundle</String> 8 <String Id="BundleName">~TestBundle</String>
9 <String Id="BundleInProgressName">~InProgressTestBundle</String>
9 10
10</WixLocalization> 11</WixLocalization>
diff --git a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimpleBundle/Bundle.wxs b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimpleBundle/Bundle.wxs
index 21749c07..01b9e716 100644
--- a/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimpleBundle/Bundle.wxs
+++ b/src/wix/test/WixToolsetTest.CoreIntegration/TestData/SimpleBundle/Bundle.wxs
@@ -1,5 +1,5 @@
1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"> 1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 <Bundle Name="!(loc.BundleName)" Version="!(bind.packageVersion.test.msi)" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a"> 2 <Bundle Name="!(loc.BundleName)" InProgressName="!(loc.BundleInProgressName)" Version="!(bind.packageVersion.test.msi)" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
3 <BootstrapperApplication> 3 <BootstrapperApplication>
4 <BootstrapperApplicationDll SourceFile="fakeba.dll" /> 4 <BootstrapperApplicationDll SourceFile="fakeba.dll" />
5 </BootstrapperApplication> 5 </BootstrapperApplication>