aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-06-14 15:09:49 -0500
committerSean Hall <r.sean.hall@gmail.com>2022-06-14 21:51:14 -0500
commitdea657295df261bb0e3e4d620eeae321531e3a11 (patch)
tree718a4b3c9697a2b6e926ad74404dc22f2cc4d22b
parent6f6e4ced9f398ff37a44b91fdba62479cde29d06 (diff)
downloadwix-dea657295df261bb0e3e4d620eeae321531e3a11.tar.gz
wix-dea657295df261bb0e3e4d620eeae321531e3a11.tar.bz2
wix-dea657295df261bb0e3e4d620eeae321531e3a11.zip
Add ability for non-vital cache package action.
-rw-r--r--src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h25
-rw-r--r--src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs29
-rw-r--r--src/api/burn/WixToolset.Mba.Core/EventArgs.cs27
-rw-r--r--src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs40
-rw-r--r--src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs5
-rw-r--r--src/api/burn/balutil/inc/BAFunctions.h1
-rw-r--r--src/api/burn/balutil/inc/BalBaseBAFunctions.h11
-rw-r--r--src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h1
-rw-r--r--src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h11
-rw-r--r--src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h14
-rw-r--r--src/api/burn/balutil/inc/IBootstrapperApplication.h9
-rw-r--r--src/burn/engine/apply.cpp51
-rw-r--r--src/burn/engine/core.cpp2
-rw-r--r--src/burn/engine/engine.mc4
-rw-r--r--src/burn/engine/logging.cpp29
-rw-r--r--src/burn/engine/logging.h8
-rw-r--r--src/burn/engine/package.h12
-rw-r--r--src/burn/engine/plan.cpp111
-rw-r--r--src/burn/engine/plan.h5
-rw-r--r--src/burn/engine/userexperience.cpp40
-rw-r--r--src/burn/engine/userexperience.h9
-rw-r--r--src/burn/test/BurnUnitTest/PlanTest.cpp179
-rw-r--r--src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp14
-rw-r--r--src/test/burn/TestBA/TestBA.cs32
-rw-r--r--src/test/burn/TestData/ExePackageTests/PackageTestExe/PackageTestExe.wixproj16
-rw-r--r--src/test/burn/TestData/ExePackageTests/PackageTestExe/ProductComponents.wxs12
-rw-r--r--src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackageUninstallFailure/PerMachineArpEntryExePackageUninstallFailure.wixproj18
-rw-r--r--src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackageUninstallFailure/PerMachineArpEntryExePackageUninstallFailure.wxs24
-rw-r--r--src/test/burn/TestData/TestBA/TestBAWixlib/TestExe.wxs7
-rw-r--r--src/test/burn/WixToolsetTest.BurnE2E/ExePackageTests.cs117
-rw-r--r--src/test/burn/WixToolsetTest.BurnE2E/Utilities/TestBAController.cs15
31 files changed, 723 insertions, 155 deletions
diff --git a/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h b/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
index ea3be214..ad3ef8a3 100644
--- a/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
+++ b/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
@@ -226,6 +226,7 @@ enum BOOTSTRAPPER_APPLICATION_MESSAGE
226 BOOTSTRAPPER_APPLICATION_MESSAGE_ONAPPLYDOWNGRADE, 226 BOOTSTRAPPER_APPLICATION_MESSAGE_ONAPPLYDOWNGRADE,
227 BOOTSTRAPPER_APPLICATION_MESSAGE_ONEXECUTEPROCESSCANCEL, 227 BOOTSTRAPPER_APPLICATION_MESSAGE_ONEXECUTEPROCESSCANCEL,
228 BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTRELATEDBUNDLEPACKAGE, 228 BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTRELATEDBUNDLEPACKAGE,
229 BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPACKAGENONVITALVALIDATIONFAILURE,
229}; 230};
230 231
231enum BOOTSTRAPPER_APPLYCOMPLETE_ACTION 232enum BOOTSTRAPPER_APPLYCOMPLETE_ACTION
@@ -257,6 +258,14 @@ enum BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION
257 BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_RETRY, 258 BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_RETRY,
258}; 259};
259 260
261enum BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION
262{
263 BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION_NONE,
264 // Instructs the engine to try to acquire the package so execution can use it.
265 // Most of the time this is used for installing the package during rollback.
266 BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION_ACQUIRE,
267};
268
260enum BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION 269enum BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION
261{ 270{
262 BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION_NONE, 271 BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION_NONE,
@@ -546,6 +555,8 @@ struct BA_ONCACHEPACKAGEBEGIN_ARGS
546 LPCWSTR wzPackageId; 555 LPCWSTR wzPackageId;
547 DWORD cCachePayloads; 556 DWORD cCachePayloads;
548 DWORD64 dw64PackageCacheSize; 557 DWORD64 dw64PackageCacheSize;
558 // If caching a package is not vital, then acquisition will be skipped unless the BA opts in through OnCachePackageNonVitalValidationFailure.
559 BOOL fVital;
549}; 560};
550 561
551struct BA_ONCACHEPACKAGEBEGIN_RESULTS 562struct BA_ONCACHEPACKAGEBEGIN_RESULTS
@@ -568,6 +579,20 @@ struct BA_ONCACHEPACKAGECOMPLETE_RESULTS
568 BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION action; 579 BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION action;
569}; 580};
570 581
582struct BA_ONCACHEPACKAGENONVITALVALIDATIONFAILURE_ARGS
583{
584 DWORD cbSize;
585 LPCWSTR wzPackageId;
586 HRESULT hrStatus;
587 BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION recommendation;
588};
589
590struct BA_ONCACHEPACKAGENONVITALVALIDATIONFAILURE_RESULTS
591{
592 DWORD cbSize;
593 BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION action;
594};
595
571struct BA_ONCACHEPAYLOADEXTRACTBEGIN_ARGS 596struct BA_ONCACHEPAYLOADEXTRACTBEGIN_ARGS
572{ 597{
573 DWORD cbSize; 598 DWORD cbSize;
diff --git a/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs b/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs
index bb34a33e..fe9322ce 100644
--- a/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs
+++ b/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs
@@ -280,6 +280,9 @@ namespace WixToolset.Mba.Core
280 /// <inheritdoc/> 280 /// <inheritdoc/>
281 public event EventHandler<DetectRelatedBundlePackageEventArgs> DetectRelatedBundlePackage; 281 public event EventHandler<DetectRelatedBundlePackageEventArgs> DetectRelatedBundlePackage;
282 282
283 /// <inheritdoc/>
284 public event EventHandler<CachePackageNonVitalValidationFailureEventArgs> CachePackageNonVitalValidationFailure;
285
283 /// <summary> 286 /// <summary>
284 /// Entry point that is called when the bootstrapper application is ready to run. 287 /// Entry point that is called when the bootstrapper application is ready to run.
285 /// </summary> 288 /// </summary>
@@ -1376,6 +1379,18 @@ namespace WixToolset.Mba.Core
1376 } 1379 }
1377 } 1380 }
1378 1381
1382 /// <summary>
1383 /// Called by the engine, raises the <see cref="CachePackageNonVitalValidationFailure"/> event.
1384 /// </summary>
1385 protected virtual void OnCachePackageNonVitalValidationFailure(CachePackageNonVitalValidationFailureEventArgs args)
1386 {
1387 EventHandler<CachePackageNonVitalValidationFailureEventArgs> handler = this.CachePackageNonVitalValidationFailure;
1388 if (null != handler)
1389 {
1390 handler(this, args);
1391 }
1392 }
1393
1379 #region IBootstrapperApplication Members 1394 #region IBootstrapperApplication Members
1380 1395
1381 int IBootstrapperApplication.BAProc(int message, IntPtr pvArgs, IntPtr pvResults, IntPtr pvContext) 1396 int IBootstrapperApplication.BAProc(int message, IntPtr pvArgs, IntPtr pvResults, IntPtr pvContext)
@@ -1570,6 +1585,7 @@ namespace WixToolset.Mba.Core
1570 this.OnPlanPackageBegin(args); 1585 this.OnPlanPackageBegin(args);
1571 1586
1572 pRequestedState = args.State; 1587 pRequestedState = args.State;
1588 pRequestedCacheType = args.CacheType;
1573 fCancel = args.Cancel; 1589 fCancel = args.Cancel;
1574 return args.HResult; 1590 return args.HResult;
1575 } 1591 }
@@ -1728,9 +1744,9 @@ namespace WixToolset.Mba.Core
1728 return args.HResult; 1744 return args.HResult;
1729 } 1745 }
1730 1746
1731 int IBootstrapperApplication.OnCachePackageBegin(string wzPackageId, int cCachePayloads, long dw64PackageCacheSize, ref bool fCancel) 1747 int IBootstrapperApplication.OnCachePackageBegin(string wzPackageId, int cCachePayloads, long dw64PackageCacheSize, bool fVital, ref bool fCancel)
1732 { 1748 {
1733 CachePackageBeginEventArgs args = new CachePackageBeginEventArgs(wzPackageId, cCachePayloads, dw64PackageCacheSize, fCancel); 1749 CachePackageBeginEventArgs args = new CachePackageBeginEventArgs(wzPackageId, cCachePayloads, dw64PackageCacheSize, fVital, fCancel);
1734 this.OnCachePackageBegin(args); 1750 this.OnCachePackageBegin(args);
1735 1751
1736 fCancel = args.Cancel; 1752 fCancel = args.Cancel;
@@ -2131,6 +2147,15 @@ namespace WixToolset.Mba.Core
2131 return args.HResult; 2147 return args.HResult;
2132 } 2148 }
2133 2149
2150 int IBootstrapperApplication.OnCachePackageNonVitalValidationFailure(string wzPackageId, int hrStatus, BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION recommendation, ref BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION action)
2151 {
2152 CachePackageNonVitalValidationFailureEventArgs args = new CachePackageNonVitalValidationFailureEventArgs(wzPackageId, hrStatus, recommendation, action);
2153 this.OnCachePackageNonVitalValidationFailure(args);
2154
2155 action = args.Action;
2156 return args.HResult;
2157 }
2158
2134 #endregion 2159 #endregion
2135 } 2160 }
2136} 2161}
diff --git a/src/api/burn/WixToolset.Mba.Core/EventArgs.cs b/src/api/burn/WixToolset.Mba.Core/EventArgs.cs
index be113700..2b414d91 100644
--- a/src/api/burn/WixToolset.Mba.Core/EventArgs.cs
+++ b/src/api/burn/WixToolset.Mba.Core/EventArgs.cs
@@ -1930,12 +1930,13 @@ namespace WixToolset.Mba.Core
1930 public class CachePackageBeginEventArgs : CancellableHResultEventArgs 1930 public class CachePackageBeginEventArgs : CancellableHResultEventArgs
1931 { 1931 {
1932 /// <summary /> 1932 /// <summary />
1933 public CachePackageBeginEventArgs(string packageId, int cachePayloads, long packageCacheSize, bool cancelRecommendation) 1933 public CachePackageBeginEventArgs(string packageId, int cachePayloads, long packageCacheSize, bool vital, bool cancelRecommendation)
1934 : base(cancelRecommendation) 1934 : base(cancelRecommendation)
1935 { 1935 {
1936 this.PackageId = packageId; 1936 this.PackageId = packageId;
1937 this.CachePayloads = cachePayloads; 1937 this.CachePayloads = cachePayloads;
1938 this.PackageCacheSize = packageCacheSize; 1938 this.PackageCacheSize = packageCacheSize;
1939 this.Vital = vital;
1939 } 1940 }
1940 1941
1941 /// <summary> 1942 /// <summary>
@@ -1952,6 +1953,11 @@ namespace WixToolset.Mba.Core
1952 /// Gets the size on disk required by the specific package. 1953 /// Gets the size on disk required by the specific package.
1953 /// </summary> 1954 /// </summary>
1954 public long PackageCacheSize { get; private set; } 1955 public long PackageCacheSize { get; private set; }
1956
1957 /// <summary>
1958 /// If caching a package is not vital, then acquisition will be skipped unless the BA opts in through <see cref="IDefaultBootstrapperApplication.CachePackageNonVitalValidationFailure"/>.
1959 /// </summary>
1960 public bool Vital { get; private set; }
1955 } 1961 }
1956 1962
1957 /// <summary> 1963 /// <summary>
@@ -2482,4 +2488,23 @@ namespace WixToolset.Mba.Core
2482 /// </summary> 2488 /// </summary>
2483 public string Version { get; private set; } 2489 public string Version { get; private set; }
2484 } 2490 }
2491
2492 /// <summary>
2493 /// Event arguments for <see cref="IDefaultBootstrapperApplication.CachePackageNonVitalValidationFailure"/>
2494 /// </summary>
2495 [Serializable]
2496 public class CachePackageNonVitalValidationFailureEventArgs : ActionEventArgs<BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION>
2497 {
2498 /// <summary />
2499 public CachePackageNonVitalValidationFailureEventArgs(string packageId, int hrStatus, BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION recommendation, BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION action)
2500 : base(hrStatus, recommendation, action)
2501 {
2502 this.PackageId = packageId;
2503 }
2504
2505 /// <summary>
2506 /// Gets the identity of the package that was being validated.
2507 /// </summary>
2508 public string PackageId { get; private set; }
2509 }
2485} 2510}
diff --git a/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs b/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs
index 8ce99808..87da2191 100644
--- a/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs
+++ b/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs
@@ -553,17 +553,13 @@ namespace WixToolset.Mba.Core
553 /// <summary> 553 /// <summary>
554 /// See <see cref="IDefaultBootstrapperApplication.CachePackageBegin"/>. 554 /// See <see cref="IDefaultBootstrapperApplication.CachePackageBegin"/>.
555 /// </summary> 555 /// </summary>
556 /// <param name="wzPackageId"></param>
557 /// <param name="cCachePayloads"></param>
558 /// <param name="dw64PackageCacheSize"></param>
559 /// <param name="fCancel"></param>
560 /// <returns></returns>
561 [PreserveSig] 556 [PreserveSig]
562 [return: MarshalAs(UnmanagedType.I4)] 557 [return: MarshalAs(UnmanagedType.I4)]
563 int OnCachePackageBegin( 558 int OnCachePackageBegin(
564 [MarshalAs(UnmanagedType.LPWStr)] string wzPackageId, 559 [MarshalAs(UnmanagedType.LPWStr)] string wzPackageId,
565 [MarshalAs(UnmanagedType.U4)] int cCachePayloads, 560 [MarshalAs(UnmanagedType.U4)] int cCachePayloads,
566 [MarshalAs(UnmanagedType.U8)] long dw64PackageCacheSize, 561 [MarshalAs(UnmanagedType.U8)] long dw64PackageCacheSize,
562 [MarshalAs(UnmanagedType.Bool)] bool fVital,
567 [MarshalAs(UnmanagedType.Bool)] ref bool fCancel 563 [MarshalAs(UnmanagedType.Bool)] ref bool fCancel
568 ); 564 );
569 565
@@ -672,11 +668,6 @@ namespace WixToolset.Mba.Core
672 /// <summary> 668 /// <summary>
673 /// See <see cref="IDefaultBootstrapperApplication.CachePackageComplete"/>. 669 /// See <see cref="IDefaultBootstrapperApplication.CachePackageComplete"/>.
674 /// </summary> 670 /// </summary>
675 /// <param name="wzPackageId"></param>
676 /// <param name="hrStatus"></param>
677 /// <param name="recommendation"></param>
678 /// <param name="action"></param>
679 /// <returns></returns>
680 [PreserveSig] 671 [PreserveSig]
681 [return: MarshalAs(UnmanagedType.I4)] 672 [return: MarshalAs(UnmanagedType.I4)]
682 int OnCachePackageComplete( 673 int OnCachePackageComplete(
@@ -1184,6 +1175,18 @@ namespace WixToolset.Mba.Core
1184 [MarshalAs(UnmanagedType.LPWStr)] string wzVersion, 1175 [MarshalAs(UnmanagedType.LPWStr)] string wzVersion,
1185 [MarshalAs(UnmanagedType.Bool)] ref bool fCancel 1176 [MarshalAs(UnmanagedType.Bool)] ref bool fCancel
1186 ); 1177 );
1178
1179 /// <summary>
1180 /// See <see cref="IDefaultBootstrapperApplication.CachePackageNonVitalValidationFailure"/>.
1181 /// </summary>
1182 [PreserveSig]
1183 [return: MarshalAs(UnmanagedType.I4)]
1184 int OnCachePackageNonVitalValidationFailure(
1185 [MarshalAs(UnmanagedType.LPWStr)] string wzPackageId,
1186 int hrStatus,
1187 BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION recommendation,
1188 ref BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION action
1189 );
1187 } 1190 }
1188 1191
1189 /// <summary> 1192 /// <summary>
@@ -1871,6 +1874,23 @@ namespace WixToolset.Mba.Core
1871 } 1874 }
1872 1875
1873 /// <summary> 1876 /// <summary>
1877 /// The available actions for <see cref="IDefaultBootstrapperApplication.CachePackageNonVitalValidationFailure"/>
1878 /// </summary>
1879 public enum BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION
1880 {
1881 /// <summary>
1882 ///
1883 /// </summary>
1884 None,
1885
1886 /// <summary>
1887 /// Instructs the engine to try to acquire the package so execution can use it.
1888 /// Most of the time this is used for installing the package during rollback.
1889 /// </summary>
1890 Acquire,
1891 }
1892
1893 /// <summary>
1874 /// The available actions for <see cref="IDefaultBootstrapperApplication.CacheVerifyComplete"/>. 1894 /// The available actions for <see cref="IDefaultBootstrapperApplication.CacheVerifyComplete"/>.
1875 /// </summary> 1895 /// </summary>
1876 public enum BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION 1896 public enum BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION
diff --git a/src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs b/src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs
index 2535f756..2fa88bdb 100644
--- a/src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs
+++ b/src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs
@@ -94,6 +94,11 @@ namespace WixToolset.Mba.Core
94 event EventHandler<CachePackageCompleteEventArgs> CachePackageComplete; 94 event EventHandler<CachePackageCompleteEventArgs> CachePackageComplete;
95 95
96 /// <summary> 96 /// <summary>
97 /// Fired when the engine failed validating a package in the package cache that is non-vital to execution.
98 /// </summary>
99 event EventHandler<CachePackageNonVitalValidationFailureEventArgs> CachePackageNonVitalValidationFailure;
100
101 /// <summary>
97 /// Fired when the engine begins the extraction of the payload from the container. 102 /// Fired when the engine begins the extraction of the payload from the container.
98 /// </summary> 103 /// </summary>
99 event EventHandler<CachePayloadExtractBeginEventArgs> CachePayloadExtractBegin; 104 event EventHandler<CachePayloadExtractBeginEventArgs> CachePayloadExtractBegin;
diff --git a/src/api/burn/balutil/inc/BAFunctions.h b/src/api/burn/balutil/inc/BAFunctions.h
index b23dd02e..8ecc04ff 100644
--- a/src/api/burn/balutil/inc/BAFunctions.h
+++ b/src/api/burn/balutil/inc/BAFunctions.h
@@ -92,6 +92,7 @@ enum BA_FUNCTIONS_MESSAGE
92 BA_FUNCTIONS_MESSAGE_ONAPPLYDOWNGRADE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONAPPLYDOWNGRADE, 92 BA_FUNCTIONS_MESSAGE_ONAPPLYDOWNGRADE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONAPPLYDOWNGRADE,
93 BA_FUNCTIONS_MESSAGE_ONEXECUTEPROCESSCANCEL = BOOTSTRAPPER_APPLICATION_MESSAGE_ONEXECUTEPROCESSCANCEL, 93 BA_FUNCTIONS_MESSAGE_ONEXECUTEPROCESSCANCEL = BOOTSTRAPPER_APPLICATION_MESSAGE_ONEXECUTEPROCESSCANCEL,
94 BA_FUNCTIONS_MESSAGE_ONDETECTRELATEDBUNDLEPACKAGE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTRELATEDBUNDLEPACKAGE, 94 BA_FUNCTIONS_MESSAGE_ONDETECTRELATEDBUNDLEPACKAGE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTRELATEDBUNDLEPACKAGE,
95 BA_FUNCTIONS_MESSAGE_ONCACHEPACKAGENONVITALVALIDATIONFAILURE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPACKAGENONVITALVALIDATIONFAILURE,
95 96
96 BA_FUNCTIONS_MESSAGE_ONTHEMELOADED = 1024, 97 BA_FUNCTIONS_MESSAGE_ONTHEMELOADED = 1024,
97 BA_FUNCTIONS_MESSAGE_WNDPROC, 98 BA_FUNCTIONS_MESSAGE_WNDPROC,
diff --git a/src/api/burn/balutil/inc/BalBaseBAFunctions.h b/src/api/burn/balutil/inc/BalBaseBAFunctions.h
index ca070553..49e97815 100644
--- a/src/api/burn/balutil/inc/BalBaseBAFunctions.h
+++ b/src/api/burn/balutil/inc/BalBaseBAFunctions.h
@@ -447,6 +447,7 @@ public: // IBootstrapperApplication
447 __in_z LPCWSTR /*wzPackageId*/, 447 __in_z LPCWSTR /*wzPackageId*/,
448 __in DWORD /*cCachePayloads*/, 448 __in DWORD /*cCachePayloads*/,
449 __in DWORD64 /*dw64PackageCacheSize*/, 449 __in DWORD64 /*dw64PackageCacheSize*/,
450 __in BOOL /*fVital*/,
450 __inout BOOL* /*pfCancel*/ 451 __inout BOOL* /*pfCancel*/
451 ) 452 )
452 { 453 {
@@ -892,6 +893,16 @@ public: // IBootstrapperApplication
892 return S_OK; 893 return S_OK;
893 } 894 }
894 895
896 virtual STDMETHODIMP OnCachePackageNonVitalValidationFailure(
897 __in_z LPCWSTR /*wzPackageId*/,
898 __in HRESULT /*hrStatus*/,
899 __in BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION /*recommendation*/,
900 __inout BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION* /*pAction*/
901 )
902 {
903 return S_OK;
904 }
905
895public: // IBAFunctions 906public: // IBAFunctions
896 virtual STDMETHODIMP OnPlan( 907 virtual STDMETHODIMP OnPlan(
897 ) 908 )
diff --git a/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h b/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h
index ff92717d..e10decfc 100644
--- a/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h
+++ b/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h
@@ -163,6 +163,7 @@ static HRESULT WINAPI BalBaseBAFunctionsProc(
163 case BA_FUNCTIONS_MESSAGE_ONAPPLYDOWNGRADE: 163 case BA_FUNCTIONS_MESSAGE_ONAPPLYDOWNGRADE:
164 case BA_FUNCTIONS_MESSAGE_ONEXECUTEPROCESSCANCEL: 164 case BA_FUNCTIONS_MESSAGE_ONEXECUTEPROCESSCANCEL:
165 case BA_FUNCTIONS_MESSAGE_ONDETECTRELATEDBUNDLEPACKAGE: 165 case BA_FUNCTIONS_MESSAGE_ONDETECTRELATEDBUNDLEPACKAGE:
166 case BA_FUNCTIONS_MESSAGE_ONCACHEPACKAGENONVITALVALIDATIONFAILURE:
166 hr = BalBaseBootstrapperApplicationProc((BOOTSTRAPPER_APPLICATION_MESSAGE)message, pvArgs, pvResults, pvContext); 167 hr = BalBaseBootstrapperApplicationProc((BOOTSTRAPPER_APPLICATION_MESSAGE)message, pvArgs, pvResults, pvContext);
167 break; 168 break;
168 case BA_FUNCTIONS_MESSAGE_ONTHEMELOADED: 169 case BA_FUNCTIONS_MESSAGE_ONTHEMELOADED:
diff --git a/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h b/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h
index fc9c4dd7..aa1ca56f 100644
--- a/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h
+++ b/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h
@@ -505,6 +505,7 @@ public: // IBootstrapperApplication
505 __in_z LPCWSTR /*wzPackageId*/, 505 __in_z LPCWSTR /*wzPackageId*/,
506 __in DWORD /*cCachePayloads*/, 506 __in DWORD /*cCachePayloads*/,
507 __in DWORD64 /*dw64PackageCacheSize*/, 507 __in DWORD64 /*dw64PackageCacheSize*/,
508 __in BOOL /*fVital*/,
508 __inout BOOL* pfCancel 509 __inout BOOL* pfCancel
509 ) 510 )
510 { 511 {
@@ -1084,6 +1085,16 @@ public: // IBootstrapperApplication
1084 return S_OK; 1085 return S_OK;
1085 } 1086 }
1086 1087
1088 virtual STDMETHODIMP OnCachePackageNonVitalValidationFailure(
1089 __in_z LPCWSTR /*wzPackageId*/,
1090 __in HRESULT /*hrStatus*/,
1091 __in BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION /*recommendation*/,
1092 __inout BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION* /*pAction*/
1093 )
1094 {
1095 return S_OK;
1096 }
1097
1087public: //CBalBaseBootstrapperApplication 1098public: //CBalBaseBootstrapperApplication
1088 virtual STDMETHODIMP Initialize( 1099 virtual STDMETHODIMP Initialize(
1089 __in const BOOTSTRAPPER_CREATE_ARGS* pCreateArgs 1100 __in const BOOTSTRAPPER_CREATE_ARGS* pCreateArgs
diff --git a/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h b/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h
index 92243540..3054731f 100644
--- a/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h
+++ b/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h
@@ -330,7 +330,7 @@ static HRESULT BalBaseBAProcOnCachePackageBegin(
330 __inout BA_ONCACHEPACKAGEBEGIN_RESULTS* pResults 330 __inout BA_ONCACHEPACKAGEBEGIN_RESULTS* pResults
331 ) 331 )
332{ 332{
333 return pBA->OnCachePackageBegin(pArgs->wzPackageId, pArgs->cCachePayloads, pArgs->dw64PackageCacheSize, &pResults->fCancel); 333 return pBA->OnCachePackageBegin(pArgs->wzPackageId, pArgs->cCachePayloads, pArgs->dw64PackageCacheSize, pArgs->fVital, &pResults->fCancel);
334} 334}
335 335
336static HRESULT BalBaseBAProcOnCacheAcquireBegin( 336static HRESULT BalBaseBAProcOnCacheAcquireBegin(
@@ -756,6 +756,15 @@ static HRESULT BalBaseBAProcOnDetectRelatedBundlePackage(
756 return pBA->OnDetectRelatedBundlePackage(pArgs->wzPackageId, pArgs->wzBundleId, pArgs->relationType, pArgs->fPerMachine, pArgs->wzVersion, &pResults->fCancel); 756 return pBA->OnDetectRelatedBundlePackage(pArgs->wzPackageId, pArgs->wzBundleId, pArgs->relationType, pArgs->fPerMachine, pArgs->wzVersion, &pResults->fCancel);
757} 757}
758 758
759static HRESULT BalBaseBAProcOnCachePackageNonVitalValidationFailure(
760 __in IBootstrapperApplication* pBA,
761 __in BA_ONCACHEPACKAGENONVITALVALIDATIONFAILURE_ARGS* pArgs,
762 __inout BA_ONCACHEPACKAGENONVITALVALIDATIONFAILURE_RESULTS* pResults
763 )
764{
765 return pBA->OnCachePackageNonVitalValidationFailure(pArgs->wzPackageId, pArgs->hrStatus, pArgs->recommendation, &pResults->action);
766}
767
759/******************************************************************* 768/*******************************************************************
760BalBaseBootstrapperApplicationProc - requires pvContext to be of type IBootstrapperApplication. 769BalBaseBootstrapperApplicationProc - requires pvContext to be of type IBootstrapperApplication.
761 Provides a default mapping between the new message based BA interface and 770 Provides a default mapping between the new message based BA interface and
@@ -1024,6 +1033,9 @@ static HRESULT WINAPI BalBaseBootstrapperApplicationProc(
1024 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTRELATEDBUNDLEPACKAGE: 1033 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTRELATEDBUNDLEPACKAGE:
1025 hr = BalBaseBAProcOnDetectRelatedBundlePackage(pBA, reinterpret_cast<BA_ONDETECTRELATEDBUNDLEPACKAGE_ARGS*>(pvArgs), reinterpret_cast<BA_ONDETECTRELATEDBUNDLEPACKAGE_RESULTS*>(pvResults)); 1034 hr = BalBaseBAProcOnDetectRelatedBundlePackage(pBA, reinterpret_cast<BA_ONDETECTRELATEDBUNDLEPACKAGE_ARGS*>(pvArgs), reinterpret_cast<BA_ONDETECTRELATEDBUNDLEPACKAGE_RESULTS*>(pvResults));
1026 break; 1035 break;
1036 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPACKAGENONVITALVALIDATIONFAILURE:
1037 hr = BalBaseBAProcOnCachePackageNonVitalValidationFailure(pBA, reinterpret_cast<BA_ONCACHEPACKAGENONVITALVALIDATIONFAILURE_ARGS*>(pvArgs), reinterpret_cast<BA_ONCACHEPACKAGENONVITALVALIDATIONFAILURE_RESULTS*>(pvResults));
1038 break;
1027 } 1039 }
1028 } 1040 }
1029 1041
diff --git a/src/api/burn/balutil/inc/IBootstrapperApplication.h b/src/api/burn/balutil/inc/IBootstrapperApplication.h
index 382d5aad..0362e171 100644
--- a/src/api/burn/balutil/inc/IBootstrapperApplication.h
+++ b/src/api/burn/balutil/inc/IBootstrapperApplication.h
@@ -343,6 +343,7 @@ DECLARE_INTERFACE_IID_(IBootstrapperApplication, IUnknown, "53C31D56-49C0-426B-A
343 __in_z LPCWSTR wzPackageId, 343 __in_z LPCWSTR wzPackageId,
344 __in DWORD cCachePayloads, 344 __in DWORD cCachePayloads,
345 __in DWORD64 dw64PackageCacheSize, 345 __in DWORD64 dw64PackageCacheSize,
346 __in BOOL fVital,
346 __inout BOOL* pfCancel 347 __inout BOOL* pfCancel
347 ) = 0; 348 ) = 0;
348 349
@@ -728,4 +729,12 @@ DECLARE_INTERFACE_IID_(IBootstrapperApplication, IUnknown, "53C31D56-49C0-426B-A
728 __in_z LPCWSTR wzVersion, 729 __in_z LPCWSTR wzVersion,
729 __inout BOOL* pfCancel 730 __inout BOOL* pfCancel
730 ) = 0; 731 ) = 0;
732
733 // OnCachePackageNonVitalValidationFailure - called when the engine failed validating a package in the package cache that is non-vital to execution.
734 STDMETHOD(OnCachePackageNonVitalValidationFailure)(
735 __in_z LPCWSTR wzPackageId,
736 __in HRESULT hrStatus,
737 __in BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION recommendation,
738 __inout BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION* pAction
739 ) = 0;
731}; 740};
diff --git a/src/burn/engine/apply.cpp b/src/burn/engine/apply.cpp
index 048cd98b..d215cfe5 100644
--- a/src/burn/engine/apply.cpp
+++ b/src/burn/engine/apply.cpp
@@ -110,7 +110,8 @@ static HRESULT ApplyLayoutContainer(
110static HRESULT ApplyProcessPayload( 110static HRESULT ApplyProcessPayload(
111 __in BURN_CACHE_CONTEXT* pContext, 111 __in BURN_CACHE_CONTEXT* pContext,
112 __in_opt BURN_PACKAGE* pPackage, 112 __in_opt BURN_PACKAGE* pPackage,
113 __in BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem 113 __in BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem,
114 __in BOOL fVital
114 ); 115 );
115static HRESULT ApplyCacheVerifyContainerOrPayload( 116static HRESULT ApplyCacheVerifyContainerOrPayload(
116 __in BURN_CACHE_CONTEXT* pContext, 117 __in BURN_CACHE_CONTEXT* pContext,
@@ -203,6 +204,10 @@ static HRESULT DoRollbackActions(
203 __in DWORD dwCheckpoint, 204 __in DWORD dwCheckpoint,
204 __out BOOTSTRAPPER_APPLY_RESTART* pRestart 205 __out BOOTSTRAPPER_APPLY_RESTART* pRestart
205 ); 206 );
207static BOOL ShouldSkipPackage(
208 __in BURN_PACKAGE* pPackage,
209 __in BOOL fRollback
210 );
206static HRESULT ExecuteRelatedBundle( 211static HRESULT ExecuteRelatedBundle(
207 __in BURN_ENGINE_STATE* pEngineState, 212 __in BURN_ENGINE_STATE* pEngineState,
208 __in BURN_EXECUTE_ACTION* pExecuteAction, 213 __in BURN_EXECUTE_ACTION* pExecuteAction,
@@ -379,6 +384,7 @@ extern "C" void ApplyReset(
379 { 384 {
380 BURN_PACKAGE* pPackage = pPackages->rgPackages + i; 385 BURN_PACKAGE* pPackage = pPackages->rgPackages + i;
381 pPackage->hrCacheResult = S_OK; 386 pPackage->hrCacheResult = S_OK;
387 pPackage->fAcquireOptionalSource = FALSE;
382 pPackage->fReachedExecution = FALSE; 388 pPackage->fReachedExecution = FALSE;
383 pPackage->fAbandonedProcess = FALSE; 389 pPackage->fAbandonedProcess = FALSE;
384 pPackage->transactionRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; 390 pPackage->transactionRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
@@ -633,7 +639,7 @@ extern "C" HRESULT ApplyCache(
633 break; 639 break;
634 640
635 case BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT: 641 case BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT:
636 if (!::SetEvent(pCacheAction->syncpoint.hEvent)) 642 if (!::SetEvent(pCacheAction->syncpoint.pPackage->hCacheEvent))
637 { 643 {
638 ExitWithLastError(hr, "Failed to set syncpoint event."); 644 ExitWithLastError(hr, "Failed to set syncpoint event.");
639 } 645 }
@@ -959,12 +965,13 @@ static HRESULT ApplyCachePackage(
959 HRESULT hr = S_OK; 965 HRESULT hr = S_OK;
960 BOOL fCanceledBegin = FALSE; 966 BOOL fCanceledBegin = FALSE;
961 BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION cachePackageCompleteAction = BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_NONE; 967 BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION cachePackageCompleteAction = BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_NONE;
968 BOOL fVital = pPackage->fCacheVital;
962 969
963 for (;;) 970 for (;;)
964 { 971 {
965 fCanceledBegin = FALSE; 972 fCanceledBegin = FALSE;
966 973
967 hr = UserExperienceOnCachePackageBegin(pContext->pUX, pPackage->sczId, pPackage->payloads.cItems, pPackage->payloads.qwTotalSize); 974 hr = UserExperienceOnCachePackageBegin(pContext->pUX, pPackage->sczId, pPackage->payloads.cItems, pPackage->payloads.qwTotalSize, fVital);
968 if (FAILED(hr)) 975 if (FAILED(hr))
969 { 976 {
970 fCanceledBegin = TRUE; 977 fCanceledBegin = TRUE;
@@ -975,7 +982,7 @@ static HRESULT ApplyCachePackage(
975 { 982 {
976 BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem = pPackage->payloads.rgItems + i; 983 BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem = pPackage->payloads.rgItems + i;
977 984
978 hr = ApplyProcessPayload(pContext, pPackage, pPayloadGroupItem); 985 hr = ApplyProcessPayload(pContext, pPackage, pPayloadGroupItem, fVital);
979 if (FAILED(hr)) 986 if (FAILED(hr))
980 { 987 {
981 break; 988 break;
@@ -984,7 +991,7 @@ static HRESULT ApplyCachePackage(
984 } 991 }
985 992
986 pPackage->hrCacheResult = hr; 993 pPackage->hrCacheResult = hr;
987 cachePackageCompleteAction = SUCCEEDED(hr) || pPackage->fVital || fCanceledBegin ? BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_NONE : BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_IGNORE; 994 cachePackageCompleteAction = SUCCEEDED(hr) || (pPackage->fVital && fVital) || fCanceledBegin ? BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_NONE : BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_IGNORE;
988 UserExperienceOnCachePackageComplete(pContext->pUX, pPackage->sczId, hr, &cachePackageCompleteAction); 995 UserExperienceOnCachePackageComplete(pContext->pUX, pPackage->sczId, hr, &cachePackageCompleteAction);
989 996
990 if (SUCCEEDED(hr)) 997 if (SUCCEEDED(hr))
@@ -1014,7 +1021,7 @@ static HRESULT ApplyCachePackage(
1014 1021
1015 continue; 1022 continue;
1016 } 1023 }
1017 else if (BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_IGNORE == cachePackageCompleteAction && !pPackage->fVital) // ignore non-vital download failures. 1024 else if (BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_IGNORE == cachePackageCompleteAction && (!pPackage->fVital || !fVital)) // ignore non-vital download failures.
1018 { 1025 {
1019 LogId(REPORT_STANDARD, MSG_CACHE_CONTINUING_NONVITAL_PACKAGE, pPackage->sczId, hr); 1026 LogId(REPORT_STANDARD, MSG_CACHE_CONTINUING_NONVITAL_PACKAGE, pPackage->sczId, hr);
1020 hr = S_OK; 1027 hr = S_OK;
@@ -1101,7 +1108,7 @@ static HRESULT ApplyLayoutBundle(
1101 { 1108 {
1102 BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem = pPayloads->rgItems + i; 1109 BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem = pPayloads->rgItems + i;
1103 1110
1104 hr = ApplyProcessPayload(pContext, NULL, pPayloadGroupItem); 1111 hr = ApplyProcessPayload(pContext, NULL, pPayloadGroupItem, TRUE);
1105 ExitOnFailure(hr, "Failed to layout bundle payload: %ls", pPayloadGroupItem->pPayload->sczKey); 1112 ExitOnFailure(hr, "Failed to layout bundle payload: %ls", pPayloadGroupItem->pPayload->sczKey);
1106 } 1113 }
1107 1114
@@ -1164,12 +1171,14 @@ LExit:
1164static HRESULT ApplyProcessPayload( 1171static HRESULT ApplyProcessPayload(
1165 __in BURN_CACHE_CONTEXT* pContext, 1172 __in BURN_CACHE_CONTEXT* pContext,
1166 __in_opt BURN_PACKAGE* pPackage, 1173 __in_opt BURN_PACKAGE* pPackage,
1167 __in BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem 1174 __in BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem,
1175 __in BOOL fVital
1168 ) 1176 )
1169{ 1177{
1170 HRESULT hr = S_OK; 1178 HRESULT hr = S_OK;
1171 DWORD cTryAgainAttempts = 0; 1179 DWORD cTryAgainAttempts = 0;
1172 BOOL fRetry = FALSE; 1180 BOOL fRetry = FALSE;
1181 BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION action = BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION_NONE;
1173 BURN_PAYLOAD* pPayload = pPayloadGroupItem->pPayload; 1182 BURN_PAYLOAD* pPayload = pPayloadGroupItem->pPayload;
1174 1183
1175 Assert(pContext->pPayloads && pPackage || pContext->wzLayoutDirectory); 1184 Assert(pContext->pPayloads && pPackage || pContext->wzLayoutDirectory);
@@ -1184,6 +1193,18 @@ static HRESULT ApplyProcessPayload(
1184 { 1193 {
1185 ExitFunction(); 1194 ExitFunction();
1186 } 1195 }
1196 else if (pPackage && !pPackage->fAcquireOptionalSource && !fVital)
1197 {
1198 HRESULT hrResponse = UserExperienceOnCachePackageNonVitalValidationFailure(pContext->pUX, pPackage->sczId, hr, &action);
1199 ExitOnRootFailure(hrResponse, "BA aborted cache package non-vital failure.");
1200
1201 if (BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION_ACQUIRE != action)
1202 {
1203 ExitFunction();
1204 }
1205
1206 pPackage->fAcquireOptionalSource = TRUE;
1207 }
1187 1208
1188 for (;;) 1209 for (;;)
1189 { 1210 {
@@ -2567,10 +2588,20 @@ static BOOL ShouldSkipPackage(
2567 ) 2588 )
2568{ 2589{
2569 BOOL fSkip = FALSE; 2590 BOOL fSkip = FALSE;
2591 BURN_CACHE_PACKAGE_TYPE cachePackageType = fRollback ? pPackage->rollbackCacheType : pPackage->executeCacheType;
2592 BOOL fCacheVital = BURN_CACHE_PACKAGE_TYPE_REQUIRED == cachePackageType;
2570 2593
2571 if (FAILED(pPackage->hrCacheResult)) 2594 if (fCacheVital && FAILED(pPackage->hrCacheResult))
2572 { 2595 {
2573 LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pPackage->sczId, pPackage->hrCacheResult); 2596 if (fRollback)
2597 {
2598 LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_ROLLBACK_NO_CACHE, pPackage->sczId, pPackage->hrCacheResult, LoggingActionStateToString(pPackage->rollback));
2599 }
2600 else
2601 {
2602 LogId(REPORT_STANDARD, MSG_APPLY_SKIPPED_FAILED_CACHED_PACKAGE, pPackage->sczId, pPackage->hrCacheResult);
2603 }
2604
2574 ExitFunction1(fSkip = TRUE); 2605 ExitFunction1(fSkip = TRUE);
2575 } 2606 }
2576 else if (fRollback && pPackage->fAbandonedProcess) 2607 else if (fRollback && pPackage->fAbandonedProcess)
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp
index 8dfa0010..c1e3a12c 100644
--- a/src/burn/engine/core.cpp
+++ b/src/burn/engine/core.cpp
@@ -2329,7 +2329,7 @@ static void LogPackages(
2329 LogRollbackBoundary(pPackage->pRollbackBoundaryBackward); 2329 LogRollbackBoundary(pPackage->pRollbackBoundaryBackward);
2330 } 2330 }
2331 2331
2332 LogId(REPORT_STANDARD, MSG_PLANNED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingRequestStateToString(pPackage->defaultRequested), LoggingRequestStateToString(pPackage->requested), LoggingActionStateToString(pPackage->execute), LoggingActionStateToString(pPackage->rollback), LoggingCacheTypeToString(pPackage->authoredCacheType), LoggingCacheTypeToString(pPackage->cacheType), LoggingBoolToString(pPackage->fPlannedCache), LoggingBoolToString(pPackage->fPlannedUncache), LoggingDependencyActionToString(pPackage->dependencyExecute), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedInstallRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedCacheRegistrationState)); 2332 LogId(REPORT_STANDARD, MSG_PLANNED_PACKAGE, pPackage->sczId, LoggingPackageStateToString(pPackage->currentState), LoggingRequestStateToString(pPackage->defaultRequested), LoggingRequestStateToString(pPackage->requested), LoggingActionStateToString(pPackage->execute), LoggingActionStateToString(pPackage->rollback), LoggingCacheTypeToString(pPackage->authoredCacheType), LoggingCacheTypeToString(pPackage->cacheType), LoggingPlannedCacheToString(pPackage), LoggingBoolToString(pPackage->fPlannedUncache), LoggingDependencyActionToString(pPackage->dependencyExecute), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedInstallRegistrationState), LoggingPackageRegistrationStateToString(pPackage->fCanAffectRegistration, pPackage->expectedCacheRegistrationState));
2333 2333
2334 if (BURN_PACKAGE_TYPE_MSI == pPackage->type) 2334 if (BURN_PACKAGE_TYPE_MSI == pPackage->type)
2335 { 2335 {
diff --git a/src/burn/engine/engine.mc b/src/burn/engine/engine.mc
index 52524edb..f5e3ca27 100644
--- a/src/burn/engine/engine.mc
+++ b/src/burn/engine/engine.mc
@@ -417,9 +417,9 @@ Planned related bundle: %1!ls!, detect type: %2!hs!, default plan type: %3!hs!,
417 417
418MessageId=208 418MessageId=208
419Severity=Warning 419Severity=Warning
420SymbolicName=MSG_PLAN_DISABLING_ROLLBACK_NO_CACHE 420SymbolicName=MSG_APPLY_SKIPPED_ROLLBACK_NO_CACHE
421Language=English 421Language=English
422Plan disabled rollback due to incomplete cache for package: %1!ls!, original rollback action: %2!hs! 422Skipping apply rollback of package: %1!ls! due to cache error: 0x%2!x!, original rollback action: %3!hs!. Continuing...
423. 423.
424 424
425MessageId=209 425MessageId=209
diff --git a/src/burn/engine/logging.cpp b/src/burn/engine/logging.cpp
index 77f5079c..1020d01f 100644
--- a/src/burn/engine/logging.cpp
+++ b/src/burn/engine/logging.cpp
@@ -445,6 +445,23 @@ extern "C" LPCSTR LoggingCacheTypeToString(
445 } 445 }
446} 446}
447 447
448extern "C" LPCSTR LoggingCachePackageTypeToString(
449 BURN_CACHE_PACKAGE_TYPE cachePackageType
450 )
451{
452 switch (cachePackageType)
453 {
454 case BURN_CACHE_PACKAGE_TYPE_NONE:
455 return "None";
456 case BURN_CACHE_PACKAGE_TYPE_OPTIONAL:
457 return "Optional";
458 case BURN_CACHE_PACKAGE_TYPE_REQUIRED:
459 return "Required";
460 default:
461 return "Invalid";
462 }
463}
464
448extern "C" LPCSTR LoggingDependencyActionToString( 465extern "C" LPCSTR LoggingDependencyActionToString(
449 BURN_DEPENDENCY_ACTION action 466 BURN_DEPENDENCY_ACTION action
450 ) 467 )
@@ -669,6 +686,18 @@ extern "C" LPCSTR LoggingPerMachineToString(
669 return "PerUser"; 686 return "PerUser";
670} 687}
671 688
689extern "C" LPCSTR LoggingPlannedCacheToString(
690 __in const BURN_PACKAGE* pPackage
691 )
692{
693 if (!pPackage->hCacheEvent)
694 {
695 return "No";
696 }
697
698 return pPackage->fCacheVital ? "Vital" : "NonVital";
699}
700
672extern "C" LPCSTR LoggingRegistrationTypeToString( 701extern "C" LPCSTR LoggingRegistrationTypeToString(
673 __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType 702 __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType
674 ) 703 )
diff --git a/src/burn/engine/logging.h b/src/burn/engine/logging.h
index 857394b9..000b04f8 100644
--- a/src/burn/engine/logging.h
+++ b/src/burn/engine/logging.h
@@ -92,6 +92,10 @@ LPCSTR LoggingCacheTypeToString(
92 BOOTSTRAPPER_CACHE_TYPE cacheType 92 BOOTSTRAPPER_CACHE_TYPE cacheType
93 ); 93 );
94 94
95LPCSTR LoggingCachePackageTypeToString(
96 BURN_CACHE_PACKAGE_TYPE cachePackageType
97 );
98
95LPCSTR LoggingDependencyActionToString( 99LPCSTR LoggingDependencyActionToString(
96 BURN_DEPENDENCY_ACTION action 100 BURN_DEPENDENCY_ACTION action
97 ); 101 );
@@ -142,6 +146,10 @@ LPCSTR LoggingPerMachineToString(
142 __in BOOL fPerMachine 146 __in BOOL fPerMachine
143 ); 147 );
144 148
149LPCSTR LoggingPlannedCacheToString(
150 __in const BURN_PACKAGE* pPackage
151 );
152
145LPCSTR LoggingRegistrationTypeToString( 153LPCSTR LoggingRegistrationTypeToString(
146 __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType 154 __in BOOTSTRAPPER_REGISTRATION_TYPE registrationType
147 ); 155 );
diff --git a/src/burn/engine/package.h b/src/burn/engine/package.h
index 85f34de5..5fccf50a 100644
--- a/src/burn/engine/package.h
+++ b/src/burn/engine/package.h
@@ -16,6 +16,13 @@ typedef _BURN_PACKAGE BURN_PACKAGE;
16 16
17const DWORD BURN_PACKAGE_INVALID_PATCH_INDEX = 0x80000000; 17const DWORD BURN_PACKAGE_INVALID_PATCH_INDEX = 0x80000000;
18 18
19enum BURN_CACHE_PACKAGE_TYPE
20{
21 BURN_CACHE_PACKAGE_TYPE_NONE,
22 BURN_CACHE_PACKAGE_TYPE_OPTIONAL,
23 BURN_CACHE_PACKAGE_TYPE_REQUIRED,
24};
25
19enum BURN_EXE_DETECTION_TYPE 26enum BURN_EXE_DETECTION_TYPE
20{ 27{
21 BURN_EXE_DETECTION_TYPE_NONE, 28 BURN_EXE_DETECTION_TYPE_NONE,
@@ -277,7 +284,7 @@ typedef struct _BURN_PACKAGE
277 BOOTSTRAPPER_CACHE_TYPE cacheType; // only valid during Plan. 284 BOOTSTRAPPER_CACHE_TYPE cacheType; // only valid during Plan.
278 BOOTSTRAPPER_REQUEST_STATE defaultRequested;// only valid during Plan. 285 BOOTSTRAPPER_REQUEST_STATE defaultRequested;// only valid during Plan.
279 BOOTSTRAPPER_REQUEST_STATE requested; // only valid during Plan. 286 BOOTSTRAPPER_REQUEST_STATE requested; // only valid during Plan.
280 BOOL fPlannedCache; // only valid during Plan. 287 BOOL fCacheVital; // only valid during Plan.
281 BOOL fPlannedUncache; // only valid during Plan. 288 BOOL fPlannedUncache; // only valid during Plan.
282 BOOTSTRAPPER_ACTION_STATE execute; // only valid during Plan. 289 BOOTSTRAPPER_ACTION_STATE execute; // only valid during Plan.
283 BOOTSTRAPPER_ACTION_STATE rollback; // only valid during Plan. 290 BOOTSTRAPPER_ACTION_STATE rollback; // only valid during Plan.
@@ -286,9 +293,12 @@ typedef struct _BURN_PACKAGE
286 BURN_DEPENDENCY_ACTION dependencyExecute; // only valid during Plan. 293 BURN_DEPENDENCY_ACTION dependencyExecute; // only valid during Plan.
287 BURN_DEPENDENCY_ACTION dependencyRollback; // only valid during Plan. 294 BURN_DEPENDENCY_ACTION dependencyRollback; // only valid during Plan.
288 BOOL fDependencyManagerWasHere; // only valid during Plan. 295 BOOL fDependencyManagerWasHere; // only valid during Plan.
296 BURN_CACHE_PACKAGE_TYPE executeCacheType; // only valid during Plan.
297 BURN_CACHE_PACKAGE_TYPE rollbackCacheType; // only valid during Plan.
289 HANDLE hCacheEvent; // only valid during Plan. 298 HANDLE hCacheEvent; // only valid during Plan.
290 LPWSTR sczCacheFolder; // only valid during Apply. 299 LPWSTR sczCacheFolder; // only valid during Apply.
291 HRESULT hrCacheResult; // only valid during Apply. 300 HRESULT hrCacheResult; // only valid during Apply.
301 BOOL fAcquireOptionalSource; // only valid during Apply.
292 BOOL fReachedExecution; // only valid during Apply. 302 BOOL fReachedExecution; // only valid during Apply.
293 BOOL fAbandonedProcess; // only valid during Apply. 303 BOOL fAbandonedProcess; // only valid during Apply.
294 304
diff --git a/src/burn/engine/plan.cpp b/src/burn/engine/plan.cpp
index 419d3272..18f9b274 100644
--- a/src/burn/engine/plan.cpp
+++ b/src/burn/engine/plan.cpp
@@ -78,11 +78,13 @@ static HRESULT AddRegistrationAction(
78 ); 78 );
79static HRESULT AddCachePackage( 79static HRESULT AddCachePackage(
80 __in BURN_PLAN* pPlan, 80 __in BURN_PLAN* pPlan,
81 __in BURN_PACKAGE* pPackage 81 __in BURN_PACKAGE* pPackage,
82 __in BOOL fVital
82 ); 83 );
83static HRESULT AddCachePackageHelper( 84static HRESULT AddCachePackageHelper(
84 __in BURN_PLAN* pPlan, 85 __in BURN_PLAN* pPlan,
85 __in BURN_PACKAGE* pPackage 86 __in BURN_PACKAGE* pPackage,
87 __in BOOL fVital
86 ); 88 );
87static HRESULT AddCacheSlipstreamMsps( 89static HRESULT AddCacheSlipstreamMsps(
88 __in BURN_PLAN* pPlan, 90 __in BURN_PLAN* pPlan,
@@ -134,7 +136,7 @@ static HRESULT CalculateExecuteActions(
134 __in BURN_PACKAGE* pPackage, 136 __in BURN_PACKAGE* pPackage,
135 __in_opt BURN_ROLLBACK_BOUNDARY* pActiveRollbackBoundary 137 __in_opt BURN_ROLLBACK_BOUNDARY* pActiveRollbackBoundary
136 ); 138 );
137static BOOL NeedsCache( 139static BURN_CACHE_PACKAGE_TYPE GetCachePackageType(
138 __in BURN_PACKAGE* pPackage, 140 __in BURN_PACKAGE* pPackage,
139 __in BOOL fExecute 141 __in BOOL fExecute
140 ); 142 );
@@ -894,7 +896,7 @@ static HRESULT PlanPackagesHelper(
894 DWORD iPackage = fReverseOrder ? cPackages - 1 - i : i; 896 DWORD iPackage = fReverseOrder ? cPackages - 1 - i : i;
895 BURN_PACKAGE* pPackage = rgPackages + iPackage; 897 BURN_PACKAGE* pPackage = rgPackages + iPackage;
896 898
897 UserExperienceOnPlannedPackage(pUX, pPackage->sczId, pPackage->execute, pPackage->rollback, pPackage->fPlannedCache, pPackage->fPlannedUncache); 899 UserExperienceOnPlannedPackage(pUX, pPackage->sczId, pPackage->execute, pPackage->rollback, NULL != pPackage->hCacheEvent, pPackage->fPlannedUncache);
898 900
899 if (pPackage->compatiblePackage.fPlannable) 901 if (pPackage->compatiblePackage.fPlannable)
900 { 902 {
@@ -999,7 +1001,7 @@ static HRESULT ProcessPackage(
999 { 1001 {
1000 if (BOOTSTRAPPER_REQUEST_STATE_NONE != pPackage->requested) 1002 if (BOOTSTRAPPER_REQUEST_STATE_NONE != pPackage->requested)
1001 { 1003 {
1002 hr = PlanLayoutPackage(pPlan, pPackage); 1004 hr = PlanLayoutPackage(pPlan, pPackage, TRUE);
1003 ExitOnFailure(hr, "Failed to plan layout package."); 1005 ExitOnFailure(hr, "Failed to plan layout package.");
1004 } 1006 }
1005 } 1007 }
@@ -1015,7 +1017,7 @@ static HRESULT ProcessPackage(
1015 { 1017 {
1016 if (ForceCache(pPlan, pPackage)) 1018 if (ForceCache(pPlan, pPackage))
1017 { 1019 {
1018 hr = AddCachePackage(pPlan, pPackage); 1020 hr = AddCachePackage(pPlan, pPackage, TRUE);
1019 ExitOnFailure(hr, "Failed to plan cache package."); 1021 ExitOnFailure(hr, "Failed to plan cache package.");
1020 1022
1021 if (pPackage->fPerMachine) 1023 if (pPackage->fPerMachine)
@@ -1127,7 +1129,8 @@ LExit:
1127 1129
1128extern "C" HRESULT PlanLayoutPackage( 1130extern "C" HRESULT PlanLayoutPackage(
1129 __in BURN_PLAN* pPlan, 1131 __in BURN_PLAN* pPlan,
1130 __in BURN_PACKAGE* pPackage 1132 __in BURN_PACKAGE* pPackage,
1133 __in BOOL fVital
1131 ) 1134 )
1132{ 1135{
1133 HRESULT hr = S_OK; 1136 HRESULT hr = S_OK;
@@ -1143,6 +1146,7 @@ extern "C" HRESULT PlanLayoutPackage(
1143 1146
1144 pCacheAction->type = BURN_CACHE_ACTION_TYPE_PACKAGE; 1147 pCacheAction->type = BURN_CACHE_ACTION_TYPE_PACKAGE;
1145 pCacheAction->package.pPackage = pPackage; 1148 pCacheAction->package.pPackage = pPackage;
1149 pPackage->fCacheVital = fVital;
1146 1150
1147 ++pPlan->cOverallProgressTicksTotal; 1151 ++pPlan->cOverallProgressTicksTotal;
1148 1152
@@ -1170,18 +1174,14 @@ extern "C" HRESULT PlanExecutePackage(
1170 hr = DependencyPlanPackageBegin(fPerMachine, pPackage, pPlan); 1174 hr = DependencyPlanPackageBegin(fPerMachine, pPackage, pPlan);
1171 ExitOnFailure(hr, "Failed to begin plan dependency actions for package: %ls", pPackage->sczId); 1175 ExitOnFailure(hr, "Failed to begin plan dependency actions for package: %ls", pPackage->sczId);
1172 1176
1173 if (fRequestedCache || NeedsCache(pPackage, TRUE)) 1177 pPackage->executeCacheType = fRequestedCache ? BURN_CACHE_PACKAGE_TYPE_REQUIRED : GetCachePackageType(pPackage, TRUE);
1178 pPackage->rollbackCacheType = GetCachePackageType(pPackage, FALSE);
1179
1180 if (BURN_CACHE_PACKAGE_TYPE_NONE != pPackage->executeCacheType || BURN_CACHE_PACKAGE_TYPE_NONE != pPackage->rollbackCacheType)
1174 { 1181 {
1175 hr = AddCachePackage(pPlan, pPackage); 1182 hr = AddCachePackage(pPlan, pPackage, BURN_CACHE_PACKAGE_TYPE_REQUIRED == pPackage->executeCacheType);
1176 ExitOnFailure(hr, "Failed to plan cache package."); 1183 ExitOnFailure(hr, "Failed to plan cache package.");
1177 } 1184 }
1178 else if (!pPackage->fCached && NeedsCache(pPackage, FALSE))
1179 {
1180 // TODO: this decision should be made during apply instead of plan based on whether the package is actually cached.
1181 // If the package is not in the cache, disable any rollback that would require the package from the cache.
1182 LogId(REPORT_STANDARD, MSG_PLAN_DISABLING_ROLLBACK_NO_CACHE, pPackage->sczId, LoggingActionStateToString(pPackage->rollback));
1183 pPackage->rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
1184 }
1185 1185
1186 // Add execute actions. 1186 // Add execute actions.
1187 switch (pPackage->type) 1187 switch (pPackage->type)
@@ -1364,6 +1364,8 @@ extern "C" HRESULT PlanRelatedBundlesInitialize(
1364 pRelatedBundle->package.requested = BOOTSTRAPPER_REQUEST_STATE_NONE; 1364 pRelatedBundle->package.requested = BOOTSTRAPPER_REQUEST_STATE_NONE;
1365 pRelatedBundle->defaultPlanRelationType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE; 1365 pRelatedBundle->defaultPlanRelationType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE;
1366 pRelatedBundle->planRelationType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE; 1366 pRelatedBundle->planRelationType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE;
1367 pRelatedBundle->package.executeCacheType = BURN_CACHE_PACKAGE_TYPE_NONE;
1368 pRelatedBundle->package.rollbackCacheType = BURN_CACHE_PACKAGE_TYPE_NONE;
1367 1369
1368 // Determine the plan relation type even if later it is ignored due to the planned action, the command relation type, or the related bundle not being plannable. 1370 // Determine the plan relation type even if later it is ignored due to the planned action, the command relation type, or the related bundle not being plannable.
1369 // This gives more information to the BA in case it wants to override default behavior. 1371 // This gives more information to the BA in case it wants to override default behavior.
@@ -2088,10 +2090,6 @@ static void UninitializeCacheAction(
2088{ 2090{
2089 switch (pCacheAction->type) 2091 switch (pCacheAction->type)
2090 { 2092 {
2091 case BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT:
2092 ReleaseHandle(pCacheAction->syncpoint.hEvent);
2093 break;
2094
2095 case BURN_CACHE_ACTION_TYPE_LAYOUT_BUNDLE: 2093 case BURN_CACHE_ACTION_TYPE_LAYOUT_BUNDLE:
2096 ReleaseStr(pCacheAction->bundleLayout.sczExecutableName); 2094 ReleaseStr(pCacheAction->bundleLayout.sczExecutableName);
2097 ReleaseStr(pCacheAction->bundleLayout.sczUnverifiedPath); 2095 ReleaseStr(pCacheAction->bundleLayout.sczUnverifiedPath);
@@ -2145,7 +2143,7 @@ static void ResetPlannedPackageState(
2145 pPackage->cacheType = pPackage->authoredCacheType; 2143 pPackage->cacheType = pPackage->authoredCacheType;
2146 pPackage->defaultRequested = BOOTSTRAPPER_REQUEST_STATE_NONE; 2144 pPackage->defaultRequested = BOOTSTRAPPER_REQUEST_STATE_NONE;
2147 pPackage->requested = BOOTSTRAPPER_REQUEST_STATE_NONE; 2145 pPackage->requested = BOOTSTRAPPER_REQUEST_STATE_NONE;
2148 pPackage->fPlannedCache = FALSE; 2146 pPackage->fCacheVital = FALSE;
2149 pPackage->fPlannedUncache = FALSE; 2147 pPackage->fPlannedUncache = FALSE;
2150 pPackage->execute = BOOTSTRAPPER_ACTION_STATE_NONE; 2148 pPackage->execute = BOOTSTRAPPER_ACTION_STATE_NONE;
2151 pPackage->rollback = BOOTSTRAPPER_ACTION_STATE_NONE; 2149 pPackage->rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
@@ -2156,7 +2154,9 @@ static void ResetPlannedPackageState(
2156 pPackage->fDependencyManagerWasHere = FALSE; 2154 pPackage->fDependencyManagerWasHere = FALSE;
2157 pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; 2155 pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
2158 pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN; 2156 pPackage->expectedInstallRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
2159 pPackage->hCacheEvent = NULL; 2157 pPackage->executeCacheType = BURN_CACHE_PACKAGE_TYPE_NONE;
2158 pPackage->rollbackCacheType = BURN_CACHE_PACKAGE_TYPE_NONE;
2159 ReleaseHandle(pPackage->hCacheEvent);
2160 2160
2161 ReleaseNullStr(pPackage->sczCacheFolder); 2161 ReleaseNullStr(pPackage->sczCacheFolder);
2162 2162
@@ -2314,19 +2314,21 @@ LExit:
2314 2314
2315static HRESULT AddCachePackage( 2315static HRESULT AddCachePackage(
2316 __in BURN_PLAN* pPlan, 2316 __in BURN_PLAN* pPlan,
2317 __in BURN_PACKAGE* pPackage 2317 __in BURN_PACKAGE* pPackage,
2318 __in BOOL fVital
2318 ) 2319 )
2319{ 2320{
2320 HRESULT hr = S_OK; 2321 HRESULT hr = S_OK;
2321 2322
2322 // If this is an MSI package with slipstream MSPs, ensure the MSPs are cached first. 2323 // If this is an MSI package with slipstream MSPs, ensure the MSPs are cached first.
2323 if (BURN_PACKAGE_TYPE_MSI == pPackage->type && 0 < pPackage->Msi.cSlipstreamMspPackages) 2324 // TODO: Slipstream packages are not accounted for when caching the MSI package is optional.
2325 if (BURN_PACKAGE_TYPE_MSI == pPackage->type && 0 < pPackage->Msi.cSlipstreamMspPackages && fVital)
2324 { 2326 {
2325 hr = AddCacheSlipstreamMsps(pPlan, pPackage); 2327 hr = AddCacheSlipstreamMsps(pPlan, pPackage);
2326 ExitOnFailure(hr, "Failed to plan slipstream patches for package."); 2328 ExitOnFailure(hr, "Failed to plan slipstream patches for package.");
2327 } 2329 }
2328 2330
2329 hr = AddCachePackageHelper(pPlan, pPackage); 2331 hr = AddCachePackageHelper(pPlan, pPackage, fVital);
2330 ExitOnFailure(hr, "Failed to plan cache package."); 2332 ExitOnFailure(hr, "Failed to plan cache package.");
2331 2333
2332LExit: 2334LExit:
@@ -2335,7 +2337,8 @@ LExit:
2335 2337
2336static HRESULT AddCachePackageHelper( 2338static HRESULT AddCachePackageHelper(
2337 __in BURN_PLAN* pPlan, 2339 __in BURN_PLAN* pPlan,
2338 __in BURN_PACKAGE* pPackage 2340 __in BURN_PACKAGE* pPackage,
2341 __in BOOL fVital
2339 ) 2342 )
2340{ 2343{
2341 AssertSz(pPackage->sczCacheId && *pPackage->sczCacheId, "AddCachePackageHelper() expects the package to have a cache id."); 2344 AssertSz(pPackage->sczCacheId && *pPackage->sczCacheId, "AddCachePackageHelper() expects the package to have a cache id.");
@@ -2354,6 +2357,9 @@ static HRESULT AddCachePackageHelper(
2354 ExitFunction(); 2357 ExitFunction();
2355 } 2358 }
2356 2359
2360 pPackage->hCacheEvent = ::CreateEventW(NULL, TRUE, FALSE, NULL);
2361 ExitOnNullWithLastError(pPackage->hCacheEvent, hr, "Failed to create syncpoint event.");
2362
2357 // Cache checkpoints happen before the package is cached because downloading packages' 2363 // Cache checkpoints happen before the package is cached because downloading packages'
2358 // payloads will not roll themselves back the way installation packages rollback on 2364 // payloads will not roll themselves back the way installation packages rollback on
2359 // failure automatically. 2365 // failure automatically.
@@ -2381,7 +2387,7 @@ static HRESULT AddCachePackageHelper(
2381 pCacheAction->checkpoint.dwId = dwCheckpoint; 2387 pCacheAction->checkpoint.dwId = dwCheckpoint;
2382 } 2388 }
2383 2389
2384 hr = PlanLayoutPackage(pPlan, pPackage); 2390 hr = PlanLayoutPackage(pPlan, pPackage, fVital);
2385 ExitOnFailure(hr, "Failed to plan cache for package."); 2391 ExitOnFailure(hr, "Failed to plan cache for package.");
2386 2392
2387 // Create syncpoint action. 2393 // Create syncpoint action.
@@ -2389,15 +2395,11 @@ static HRESULT AddCachePackageHelper(
2389 ExitOnFailure(hr, "Failed to append cache action."); 2395 ExitOnFailure(hr, "Failed to append cache action.");
2390 2396
2391 pCacheAction->type = BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT; 2397 pCacheAction->type = BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT;
2392 pCacheAction->syncpoint.hEvent = ::CreateEventW(NULL, TRUE, FALSE, NULL); 2398 pCacheAction->syncpoint.pPackage = pPackage;
2393 ExitOnNullWithLastError(pCacheAction->syncpoint.hEvent, hr, "Failed to create syncpoint event.");
2394
2395 pPackage->hCacheEvent = pCacheAction->syncpoint.hEvent;
2396 2399
2397 hr = PlanExecuteCacheSyncAndRollback(pPlan, pPackage); 2400 hr = PlanExecuteCacheSyncAndRollback(pPlan, pPackage);
2398 ExitOnFailure(hr, "Failed to plan package cache syncpoint"); 2401 ExitOnFailure(hr, "Failed to plan package cache syncpoint");
2399 2402
2400 pPackage->fPlannedCache = TRUE;
2401 if (pPackage->fCanAffectRegistration) 2403 if (pPackage->fCanAffectRegistration)
2402 { 2404 {
2403 pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT; 2405 pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
@@ -2421,7 +2423,7 @@ static HRESULT AddCacheSlipstreamMsps(
2421 BURN_PACKAGE* pMspPackage = pPackage->Msi.rgSlipstreamMsps[i].pMspPackage; 2423 BURN_PACKAGE* pMspPackage = pPackage->Msi.rgSlipstreamMsps[i].pMspPackage;
2422 AssertSz(BURN_PACKAGE_TYPE_MSP == pMspPackage->type, "Only MSP packages can be slipstream patches."); 2424 AssertSz(BURN_PACKAGE_TYPE_MSP == pMspPackage->type, "Only MSP packages can be slipstream patches.");
2423 2425
2424 hr = AddCachePackageHelper(pPlan, pMspPackage); 2426 hr = AddCachePackageHelper(pPlan, pMspPackage, TRUE);
2425 ExitOnFailure(hr, "Failed to plan slipstream MSP: %ls", pMspPackage->sczId); 2427 ExitOnFailure(hr, "Failed to plan slipstream MSP: %ls", pMspPackage->sczId);
2426 } 2428 }
2427 2429
@@ -2791,22 +2793,41 @@ LExit:
2791 return hr; 2793 return hr;
2792} 2794}
2793 2795
2794static BOOL NeedsCache( 2796static BURN_CACHE_PACKAGE_TYPE GetCachePackageType(
2795 __in BURN_PACKAGE* pPackage, 2797 __in BURN_PACKAGE* pPackage,
2796 __in BOOL fExecute 2798 __in BOOL fExecute
2797 ) 2799 )
2798{ 2800{
2799 BOOTSTRAPPER_ACTION_STATE action = fExecute ? pPackage->execute : pPackage->rollback; 2801 BURN_CACHE_PACKAGE_TYPE cachePackageType = BURN_CACHE_PACKAGE_TYPE_NONE;
2800 // TODO: bundles could theoretically use package cache 2802
2801 if (BURN_PACKAGE_TYPE_BUNDLE == pPackage->type || // Bundle and Exe packages require the package for all operations (even uninstall). 2803 switch (fExecute ? pPackage->execute : pPackage->rollback)
2802 BURN_PACKAGE_TYPE_EXE == pPackage->type && BURN_EXE_DETECTION_TYPE_ARP != pPackage->Exe.detectionType)
2803 {
2804 return BOOTSTRAPPER_ACTION_STATE_NONE != action;
2805 }
2806 else // The other package types can uninstall without the original package.
2807 { 2804 {
2808 return BOOTSTRAPPER_ACTION_STATE_UNINSTALL < action; 2805 case BOOTSTRAPPER_ACTION_STATE_NONE:
2806 break;
2807 case BOOTSTRAPPER_ACTION_STATE_UNINSTALL:
2808 if (BURN_PACKAGE_TYPE_BUNDLE == pPackage->type ||
2809 BURN_PACKAGE_TYPE_EXE == pPackage->type && BURN_EXE_DETECTION_TYPE_ARP != pPackage->Exe.detectionType)
2810 {
2811 // Bundle and non-ArpEntry Exe packages require the package for all operations (even uninstall).
2812 // TODO: bundles could theoretically use package cache.
2813 cachePackageType = BURN_CACHE_PACKAGE_TYPE_REQUIRED;
2814 }
2815 else
2816 {
2817 // The other package types can uninstall without the original package.
2818 cachePackageType = BURN_CACHE_PACKAGE_TYPE_NONE;
2819 }
2820 break;
2821 case BOOTSTRAPPER_ACTION_STATE_INSTALL: __fallthrough;
2822 case BOOTSTRAPPER_ACTION_STATE_MODIFY: __fallthrough;
2823 case BOOTSTRAPPER_ACTION_STATE_REPAIR: __fallthrough;
2824 case BOOTSTRAPPER_ACTION_STATE_MINOR_UPGRADE: __fallthrough;
2825 default:
2826 cachePackageType = BURN_CACHE_PACKAGE_TYPE_REQUIRED;
2827 break;
2809 } 2828 }
2829
2830 return cachePackageType;
2810} 2831}
2811 2832
2812static BOOL ForceCache( 2833static BOOL ForceCache(
@@ -2881,7 +2902,7 @@ static void CacheActionLog(
2881 break; 2902 break;
2882 2903
2883 case BURN_CACHE_ACTION_TYPE_PACKAGE: 2904 case BURN_CACHE_ACTION_TYPE_PACKAGE:
2884 LogStringLine(PlanDumpLevel, "%ls action[%u]: PACKAGE id: %ls", wzBase, iAction, pAction->package.pPackage->sczId); 2905 LogStringLine(PlanDumpLevel, "%ls action[%u]: PACKAGE id: %ls, vital: %hs, execute cache type: %hs, rollback cache type: %hs", wzBase, iAction, pAction->package.pPackage->sczId, LoggingBoolToString(pAction->package.pPackage->fCacheVital), LoggingCachePackageTypeToString(pAction->package.pPackage->executeCacheType), LoggingCachePackageTypeToString(pAction->package.pPackage->rollbackCacheType));
2885 break; 2906 break;
2886 2907
2887 case BURN_CACHE_ACTION_TYPE_ROLLBACK_PACKAGE: 2908 case BURN_CACHE_ACTION_TYPE_ROLLBACK_PACKAGE:
@@ -2889,7 +2910,7 @@ static void CacheActionLog(
2889 break; 2910 break;
2890 2911
2891 case BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT: 2912 case BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT:
2892 LogStringLine(PlanDumpLevel, "%ls action[%u]: SIGNAL_SYNCPOINT event handle: 0x%p", wzBase, iAction, pAction->syncpoint.hEvent); 2913 LogStringLine(PlanDumpLevel, "%ls action[%u]: SIGNAL_SYNCPOINT package id: %ls, event handle: 0x%p", wzBase, iAction, pAction->syncpoint.pPackage->sczId, pAction->syncpoint.pPackage->hCacheEvent);
2893 break; 2914 break;
2894 2915
2895 default: 2916 default:
diff --git a/src/burn/engine/plan.h b/src/burn/engine/plan.h
index 46a9a363..386de2c6 100644
--- a/src/burn/engine/plan.h
+++ b/src/burn/engine/plan.h
@@ -117,7 +117,7 @@ typedef struct _BURN_CACHE_ACTION
117 } rollbackPackage; 117 } rollbackPackage;
118 struct 118 struct
119 { 119 {
120 HANDLE hEvent; 120 BURN_PACKAGE* pPackage;
121 } syncpoint; 121 } syncpoint;
122 struct 122 struct
123 { 123 {
@@ -392,7 +392,8 @@ HRESULT PlanLayoutContainer(
392 ); 392 );
393HRESULT PlanLayoutPackage( 393HRESULT PlanLayoutPackage(
394 __in BURN_PLAN* pPlan, 394 __in BURN_PLAN* pPlan,
395 __in BURN_PACKAGE* pPackage 395 __in BURN_PACKAGE* pPackage,
396 __in BOOL fVital
396 ); 397 );
397HRESULT PlanExecutePackage( 398HRESULT PlanExecutePackage(
398 __in BOOL fPerMachine, 399 __in BOOL fPerMachine,
diff --git a/src/burn/engine/userexperience.cpp b/src/burn/engine/userexperience.cpp
index 87ef4de1..a97234ef 100644
--- a/src/burn/engine/userexperience.cpp
+++ b/src/burn/engine/userexperience.cpp
@@ -104,7 +104,7 @@ extern "C" HRESULT UserExperienceLoad(
104 args.pCommand = pCommand; 104 args.pCommand = pCommand;
105 args.pfnBootstrapperEngineProc = EngineForApplicationProc; 105 args.pfnBootstrapperEngineProc = EngineForApplicationProc;
106 args.pvBootstrapperEngineProcContext = pEngineContext; 106 args.pvBootstrapperEngineProcContext = pEngineContext;
107 args.qwEngineAPIVersion = MAKEQWORDVERSION(2022, 3, 31, 0); 107 args.qwEngineAPIVersion = MAKEQWORDVERSION(2022, 6, 10, 0);
108 108
109 results.cbSize = sizeof(BOOTSTRAPPER_CREATE_RESULTS); 109 results.cbSize = sizeof(BOOTSTRAPPER_CREATE_RESULTS);
110 110
@@ -726,7 +726,8 @@ EXTERN_C BAAPI UserExperienceOnCachePackageBegin(
726 __in BURN_USER_EXPERIENCE* pUserExperience, 726 __in BURN_USER_EXPERIENCE* pUserExperience,
727 __in_z LPCWSTR wzPackageId, 727 __in_z LPCWSTR wzPackageId,
728 __in DWORD cCachePayloads, 728 __in DWORD cCachePayloads,
729 __in DWORD64 dw64PackageCacheSize 729 __in DWORD64 dw64PackageCacheSize,
730 __in BOOL fVital
730 ) 731 )
731{ 732{
732 HRESULT hr = S_OK; 733 HRESULT hr = S_OK;
@@ -737,6 +738,7 @@ EXTERN_C BAAPI UserExperienceOnCachePackageBegin(
737 args.wzPackageId = wzPackageId; 738 args.wzPackageId = wzPackageId;
738 args.cCachePayloads = cCachePayloads; 739 args.cCachePayloads = cCachePayloads;
739 args.dw64PackageCacheSize = dw64PackageCacheSize; 740 args.dw64PackageCacheSize = dw64PackageCacheSize;
741 args.fVital = fVital;
740 742
741 results.cbSize = sizeof(results); 743 results.cbSize = sizeof(results);
742 744
@@ -783,6 +785,40 @@ LExit:
783 return hr; 785 return hr;
784} 786}
785 787
788EXTERN_C BAAPI UserExperienceOnCachePackageNonVitalValidationFailure(
789 __in BURN_USER_EXPERIENCE* pUserExperience,
790 __in_z LPCWSTR wzPackageId,
791 __in HRESULT hrStatus,
792 __inout BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION* pAction
793 )
794{
795 HRESULT hr = S_OK;
796 BA_ONCACHEPACKAGENONVITALVALIDATIONFAILURE_ARGS args = { };
797 BA_ONCACHEPACKAGENONVITALVALIDATIONFAILURE_RESULTS results = { };
798
799 args.cbSize = sizeof(args);
800 args.wzPackageId = wzPackageId;
801 args.hrStatus = hrStatus;
802 args.recommendation = *pAction;
803
804 results.cbSize = sizeof(results);
805 results.action = *pAction;
806
807 hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPACKAGENONVITALVALIDATIONFAILURE, &args, &results);
808 ExitOnFailure(hr, "BA OnCachePackageNonVitalValidationFailure failed.");
809
810 switch (results.action)
811 {
812 case BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION_NONE: __fallthrough;
813 case BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION_ACQUIRE:
814 *pAction = results.action;
815 break;
816 }
817
818LExit:
819 return hr;
820}
821
786EXTERN_C BAAPI UserExperienceOnCachePayloadExtractBegin( 822EXTERN_C BAAPI UserExperienceOnCachePayloadExtractBegin(
787 __in BURN_USER_EXPERIENCE* pUserExperience, 823 __in BURN_USER_EXPERIENCE* pUserExperience,
788 __in_z_opt LPCWSTR wzContainerId, 824 __in_z_opt LPCWSTR wzContainerId,
diff --git a/src/burn/engine/userexperience.h b/src/burn/engine/userexperience.h
index 94b73f7d..9f183208 100644
--- a/src/burn/engine/userexperience.h
+++ b/src/burn/engine/userexperience.h
@@ -189,7 +189,14 @@ BAAPI UserExperienceOnCachePackageBegin(
189 __in BURN_USER_EXPERIENCE* pUserExperience, 189 __in BURN_USER_EXPERIENCE* pUserExperience,
190 __in_z LPCWSTR wzPackageId, 190 __in_z LPCWSTR wzPackageId,
191 __in DWORD cCachePayloads, 191 __in DWORD cCachePayloads,
192 __in DWORD64 dw64PackageCacheSize 192 __in DWORD64 dw64PackageCacheSize,
193 __in BOOL fVital
194 );
195BAAPI UserExperienceOnCachePackageNonVitalValidationFailure(
196 __in BURN_USER_EXPERIENCE* pUserExperience,
197 __in_z LPCWSTR wzPackageId,
198 __in HRESULT hrStatus,
199 __inout BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION* pAction
193 ); 200 );
194BAAPI UserExperienceOnCachePackageComplete( 201BAAPI UserExperienceOnCachePackageComplete(
195 __in BURN_USER_EXPERIENCE* pUserExperience, 202 __in BURN_USER_EXPERIENCE* pUserExperience,
diff --git a/src/burn/test/BurnUnitTest/PlanTest.cpp b/src/burn/test/BurnUnitTest/PlanTest.cpp
index 2135d9f5..37027ada 100644
--- a/src/burn/test/BurnUnitTest/PlanTest.cpp
+++ b/src/burn/test/BurnUnitTest/PlanTest.cpp
@@ -87,8 +87,8 @@ namespace Bootstrapper
87 fRollback = FALSE; 87 fRollback = FALSE;
88 dwIndex = 0; 88 dwIndex = 0;
89 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 89 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
90 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"TestExe"); 90 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"TestExe", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
91 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++); 91 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"TestExe");
92 Assert::Equal(dwIndex, pPlan->cCacheActions); 92 Assert::Equal(dwIndex, pPlan->cCacheActions);
93 93
94 fRollback = TRUE; 94 fRollback = TRUE;
@@ -259,19 +259,24 @@ namespace Bootstrapper
259 259
260 fRollback = FALSE; 260 fRollback = FALSE;
261 dwIndex = 0; 261 dwIndex = 0;
262 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
263 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"TestExe", FALSE, BURN_CACHE_PACKAGE_TYPE_NONE, BURN_CACHE_PACKAGE_TYPE_REQUIRED);
264 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"TestExe");
262 Assert::Equal(dwIndex, pPlan->cCacheActions); 265 Assert::Equal(dwIndex, pPlan->cCacheActions);
263 266
264 fRollback = TRUE; 267 fRollback = TRUE;
265 dwIndex = 0; 268 dwIndex = 0;
266 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); 269 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
267 270
268 Assert::Equal(0ull, pPlan->qwCacheSizeTotal); 271 Assert::Equal(143724ull, pPlan->qwCacheSizeTotal);
269 272
270 fRollback = FALSE; 273 fRollback = FALSE;
271 dwIndex = 0; 274 dwIndex = 0;
272 DWORD dwExecuteCheckpointId = 1; 275 DWORD dwExecuteCheckpointId = 2;
273 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 276 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
274 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 277 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
278 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"TestExe");
279 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
275 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"TestExe", BOOTSTRAPPER_ACTION_STATE_UNINSTALL); 280 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"TestExe", BOOTSTRAPPER_ACTION_STATE_UNINSTALL);
276 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 281 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
277 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 282 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -280,8 +285,9 @@ namespace Bootstrapper
280 285
281 fRollback = TRUE; 286 fRollback = TRUE;
282 dwIndex = 0; 287 dwIndex = 0;
283 dwExecuteCheckpointId = 1; 288 dwExecuteCheckpointId = 2;
284 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 289 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
290 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
285 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"TestExe", BOOTSTRAPPER_ACTION_STATE_INSTALL); 291 ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"TestExe", BOOTSTRAPPER_ACTION_STATE_INSTALL);
286 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 292 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
287 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 293 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -290,7 +296,7 @@ namespace Bootstrapper
290 Assert::Equal(dwIndex, pPlan->cRollbackActions); 296 Assert::Equal(dwIndex, pPlan->cRollbackActions);
291 297
292 Assert::Equal(1ul, pPlan->cExecutePackagesTotal); 298 Assert::Equal(1ul, pPlan->cExecutePackagesTotal);
293 Assert::Equal(1ul, pPlan->cOverallProgressTicksTotal); 299 Assert::Equal(2ul, pPlan->cOverallProgressTicksTotal);
294 300
295 dwIndex = 0; 301 dwIndex = 0;
296 Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions); 302 Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions);
@@ -347,14 +353,14 @@ namespace Bootstrapper
347 fRollback = FALSE; 353 fRollback = FALSE;
348 dwIndex = 0; 354 dwIndex = 0;
349 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 355 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
350 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA"); 356 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
351 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++); 357 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
352 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 9); 358 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 9);
353 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageB"); 359 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageB", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
354 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++); 360 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageB");
355 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 14); 361 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 14);
356 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageC"); 362 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageC", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
357 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++); 363 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageC");
358 Assert::Equal(dwIndex, pPlan->cCacheActions); 364 Assert::Equal(dwIndex, pPlan->cCacheActions);
359 365
360 fRollback = TRUE; 366 fRollback = TRUE;
@@ -506,13 +512,16 @@ namespace Bootstrapper
506 512
507 fRollback = FALSE; 513 fRollback = FALSE;
508 dwIndex = 0; 514 dwIndex = 0;
515 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 9);
516 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", FALSE, BURN_CACHE_PACKAGE_TYPE_NONE, BURN_CACHE_PACKAGE_TYPE_REQUIRED);
517 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
509 Assert::Equal(dwIndex, pPlan->cCacheActions); 518 Assert::Equal(dwIndex, pPlan->cCacheActions);
510 519
511 fRollback = TRUE; 520 fRollback = TRUE;
512 dwIndex = 0; 521 dwIndex = 0;
513 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); 522 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
514 523
515 Assert::Equal(0ull, pPlan->qwCacheSizeTotal); 524 Assert::Equal(185118ull, pPlan->qwCacheSizeTotal);
516 525
517 fRollback = FALSE; 526 fRollback = FALSE;
518 dwIndex = 0; 527 dwIndex = 0;
@@ -536,6 +545,9 @@ namespace Bootstrapper
536 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 545 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
537 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++); 546 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
538 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 547 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
548 dwExecuteCheckpointId += 1; // cache checkpoints
549 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
550 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
539 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 551 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
540 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{E6469F05-BDC8-4EB8-B218-67412543EFAA}", unregisterActions1, 1); 552 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{E6469F05-BDC8-4EB8-B218-67412543EFAA}", unregisterActions1, 1);
541 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 553 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -565,6 +577,8 @@ namespace Bootstrapper
565 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 577 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
566 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++); 578 ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
567 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 579 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
580 dwExecuteCheckpointId += 1; // cache checkpoints
581 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
568 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{E6469F05-BDC8-4EB8-B218-67412543EFAA}", registerActions1, 1); 582 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{E6469F05-BDC8-4EB8-B218-67412543EFAA}", registerActions1, 1);
569 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 583 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
570 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", registerActions1, 1); 584 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", registerActions1, 1);
@@ -577,7 +591,7 @@ namespace Bootstrapper
577 Assert::Equal(dwIndex, pPlan->cRollbackActions); 591 Assert::Equal(dwIndex, pPlan->cRollbackActions);
578 592
579 Assert::Equal(3ul, pPlan->cExecutePackagesTotal); 593 Assert::Equal(3ul, pPlan->cExecutePackagesTotal);
580 Assert::Equal(3ul, pPlan->cOverallProgressTicksTotal); 594 Assert::Equal(4ul, pPlan->cOverallProgressTicksTotal);
581 595
582 dwIndex = 0; 596 dwIndex = 0;
583 Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions); 597 Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions);
@@ -640,11 +654,11 @@ namespace Bootstrapper
640 fRollback = FALSE; 654 fRollback = FALSE;
641 dwIndex = 0; 655 dwIndex = 0;
642 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 656 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
643 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA"); 657 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_REQUIRED);
644 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++); 658 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
645 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 6); 659 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 6);
646 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageB"); 660 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageB", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_REQUIRED);
647 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++); 661 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageB");
648 Assert::Equal(dwIndex, pPlan->cCacheActions); 662 Assert::Equal(dwIndex, pPlan->cCacheActions);
649 663
650 fRollback = TRUE; 664 fRollback = TRUE;
@@ -753,8 +767,8 @@ namespace Bootstrapper
753 fRollback = FALSE; 767 fRollback = FALSE;
754 dwIndex = 0; 768 dwIndex = 0;
755 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 2); 769 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 2);
756 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageB"); 770 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageB", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
757 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++); 771 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageB");
758 Assert::Equal(dwIndex, pPlan->cCacheActions); 772 Assert::Equal(dwIndex, pPlan->cCacheActions);
759 773
760 fRollback = TRUE; 774 fRollback = TRUE;
@@ -949,8 +963,8 @@ namespace Bootstrapper
949 fRollback = FALSE; 963 fRollback = FALSE;
950 dwIndex = 0; 964 dwIndex = 0;
951 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 965 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
952 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA"); 966 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
953 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++); 967 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
954 Assert::Equal(dwIndex, pPlan->cCacheActions); 968 Assert::Equal(dwIndex, pPlan->cCacheActions);
955 969
956 fRollback = TRUE; 970 fRollback = TRUE;
@@ -1068,8 +1082,8 @@ namespace Bootstrapper
1068 fRollback = FALSE; 1082 fRollback = FALSE;
1069 dwIndex = 0; 1083 dwIndex = 0;
1070 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 1084 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
1071 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA"); 1085 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
1072 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++); 1086 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
1073 Assert::Equal(dwIndex, pPlan->cCacheActions); 1087 Assert::Equal(dwIndex, pPlan->cCacheActions);
1074 1088
1075 fRollback = TRUE; 1089 fRollback = TRUE;
@@ -1170,8 +1184,8 @@ namespace Bootstrapper
1170 fRollback = FALSE; 1184 fRollback = FALSE;
1171 dwIndex = 0; 1185 dwIndex = 0;
1172 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 1186 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
1173 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"ExeA"); 1187 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"ExeA", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_REQUIRED);
1174 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++); 1188 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"ExeA");
1175 Assert::Equal(dwIndex, pPlan->cCacheActions); 1189 Assert::Equal(dwIndex, pPlan->cCacheActions);
1176 1190
1177 fRollback = TRUE; 1191 fRollback = TRUE;
@@ -1264,8 +1278,8 @@ namespace Bootstrapper
1264 fRollback = FALSE; 1278 fRollback = FALSE;
1265 dwIndex = 0; 1279 dwIndex = 0;
1266 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 1280 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
1267 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA"); 1281 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
1268 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++); 1282 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
1269 Assert::Equal(dwIndex, pPlan->cCacheActions); 1283 Assert::Equal(dwIndex, pPlan->cCacheActions);
1270 1284
1271 fRollback = TRUE; 1285 fRollback = TRUE;
@@ -1515,8 +1529,8 @@ namespace Bootstrapper
1515 fRollback = FALSE; 1529 fRollback = FALSE;
1516 dwIndex = 0; 1530 dwIndex = 0;
1517 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 1531 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
1518 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA"); 1532 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
1519 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++); 1533 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
1520 Assert::Equal(dwIndex, pPlan->cCacheActions); 1534 Assert::Equal(dwIndex, pPlan->cCacheActions);
1521 1535
1522 fRollback = TRUE; 1536 fRollback = TRUE;
@@ -1610,8 +1624,8 @@ namespace Bootstrapper
1610 fRollback = FALSE; 1624 fRollback = FALSE;
1611 dwIndex = 0; 1625 dwIndex = 0;
1612 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 1626 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
1613 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA"); 1627 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
1614 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++); 1628 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
1615 Assert::Equal(dwIndex, pPlan->cCacheActions); 1629 Assert::Equal(dwIndex, pPlan->cCacheActions);
1616 1630
1617 fRollback = TRUE; 1631 fRollback = TRUE;
@@ -1794,19 +1808,24 @@ namespace Bootstrapper
1794 1808
1795 fRollback = FALSE; 1809 fRollback = FALSE;
1796 dwIndex = 0; 1810 dwIndex = 0;
1811 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
1812 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", FALSE, BURN_CACHE_PACKAGE_TYPE_NONE, BURN_CACHE_PACKAGE_TYPE_REQUIRED);
1813 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
1797 Assert::Equal(dwIndex, pPlan->cCacheActions); 1814 Assert::Equal(dwIndex, pPlan->cCacheActions);
1798 1815
1799 fRollback = TRUE; 1816 fRollback = TRUE;
1800 dwIndex = 0; 1817 dwIndex = 0;
1801 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); 1818 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
1802 1819
1803 Assert::Equal(0ull, pPlan->qwCacheSizeTotal); 1820 Assert::Equal(175674ull, pPlan->qwCacheSizeTotal);
1804 1821
1805 fRollback = FALSE; 1822 fRollback = FALSE;
1806 dwIndex = 0; 1823 dwIndex = 0;
1807 DWORD dwExecuteCheckpointId = 1; 1824 DWORD dwExecuteCheckpointId = 2;
1808 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 1825 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
1809 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 1826 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
1827 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
1828 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
1810 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", unregisterActions1, 1); 1829 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", unregisterActions1, 1);
1811 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 1830 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
1812 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", unregisterActions1, 1); 1831 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", unregisterActions1, 1);
@@ -1819,8 +1838,9 @@ namespace Bootstrapper
1819 1838
1820 fRollback = TRUE; 1839 fRollback = TRUE;
1821 dwIndex = 0; 1840 dwIndex = 0;
1822 dwExecuteCheckpointId = 1; 1841 dwExecuteCheckpointId = 2;
1823 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 1842 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
1843 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
1824 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", registerActions1, 1); 1844 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", registerActions1, 1);
1825 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 1845 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
1826 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", registerActions1, 1); 1846 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", registerActions1, 1);
@@ -1833,7 +1853,7 @@ namespace Bootstrapper
1833 Assert::Equal(dwIndex, pPlan->cRollbackActions); 1853 Assert::Equal(dwIndex, pPlan->cRollbackActions);
1834 1854
1835 Assert::Equal(1ul, pPlan->cExecutePackagesTotal); 1855 Assert::Equal(1ul, pPlan->cExecutePackagesTotal);
1836 Assert::Equal(1ul, pPlan->cOverallProgressTicksTotal); 1856 Assert::Equal(2ul, pPlan->cOverallProgressTicksTotal);
1837 1857
1838 dwIndex = 0; 1858 dwIndex = 0;
1839 Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions); 1859 Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions);
@@ -2043,19 +2063,24 @@ namespace Bootstrapper
2043 2063
2044 fRollback = FALSE; 2064 fRollback = FALSE;
2045 dwIndex = 0; 2065 dwIndex = 0;
2066 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
2067 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", FALSE, BURN_CACHE_PACKAGE_TYPE_NONE, BURN_CACHE_PACKAGE_TYPE_REQUIRED);
2068 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
2046 Assert::Equal(dwIndex, pPlan->cCacheActions); 2069 Assert::Equal(dwIndex, pPlan->cCacheActions);
2047 2070
2048 fRollback = TRUE; 2071 fRollback = TRUE;
2049 dwIndex = 0; 2072 dwIndex = 0;
2050 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); 2073 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
2051 2074
2052 Assert::Equal(0ull, pPlan->qwCacheSizeTotal); 2075 Assert::Equal(175674ull, pPlan->qwCacheSizeTotal);
2053 2076
2054 fRollback = FALSE; 2077 fRollback = FALSE;
2055 dwIndex = 0; 2078 dwIndex = 0;
2056 DWORD dwExecuteCheckpointId = 1; 2079 DWORD dwExecuteCheckpointId = 2;
2057 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 2080 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
2058 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 2081 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2082 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
2083 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2059 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", unregisterActions1, 1); 2084 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", unregisterActions1, 1);
2060 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 2085 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2061 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", unregisterActions1, 1); 2086 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", unregisterActions1, 1);
@@ -2068,8 +2093,9 @@ namespace Bootstrapper
2068 2093
2069 fRollback = TRUE; 2094 fRollback = TRUE;
2070 dwIndex = 0; 2095 dwIndex = 0;
2071 dwExecuteCheckpointId = 1; 2096 dwExecuteCheckpointId = 2;
2072 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 2097 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
2098 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2073 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", registerActions1, 1); 2099 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", registerActions1, 1);
2074 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 2100 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2075 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", registerActions1, 1); 2101 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", registerActions1, 1);
@@ -2082,7 +2108,7 @@ namespace Bootstrapper
2082 Assert::Equal(dwIndex, pPlan->cRollbackActions); 2108 Assert::Equal(dwIndex, pPlan->cRollbackActions);
2083 2109
2084 Assert::Equal(1ul, pPlan->cExecutePackagesTotal); 2110 Assert::Equal(1ul, pPlan->cExecutePackagesTotal);
2085 Assert::Equal(1ul, pPlan->cOverallProgressTicksTotal); 2111 Assert::Equal(2ul, pPlan->cOverallProgressTicksTotal);
2086 2112
2087 dwIndex = 0; 2113 dwIndex = 0;
2088 Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions); 2114 Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions);
@@ -2139,8 +2165,8 @@ namespace Bootstrapper
2139 fRollback = FALSE; 2165 fRollback = FALSE;
2140 dwIndex = 0; 2166 dwIndex = 0;
2141 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 2167 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
2142 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"test.msu"); 2168 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"test.msu", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
2143 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++); 2169 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"test.msu");
2144 Assert::Equal(dwIndex, pPlan->cCacheActions); 2170 Assert::Equal(dwIndex, pPlan->cCacheActions);
2145 2171
2146 fRollback = TRUE; 2172 fRollback = TRUE;
@@ -2233,14 +2259,14 @@ namespace Bootstrapper
2233 fRollback = FALSE; 2259 fRollback = FALSE;
2234 dwIndex = 0; 2260 dwIndex = 0;
2235 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 2261 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
2236 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"NetFx48Web"); 2262 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"NetFx48Web", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
2237 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++); 2263 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"NetFx48Web");
2238 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 3); 2264 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 3);
2239 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PatchA"); 2265 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PatchA", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
2240 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++); 2266 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PatchA");
2241 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 5); 2267 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 5);
2242 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA"); 2268 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
2243 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++); 2269 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
2244 Assert::Equal(dwIndex, pPlan->cCacheActions); 2270 Assert::Equal(dwIndex, pPlan->cCacheActions);
2245 2271
2246 fRollback = TRUE; 2272 fRollback = TRUE;
@@ -2363,26 +2389,37 @@ namespace Bootstrapper
2363 2389
2364 fRollback = FALSE; 2390 fRollback = FALSE;
2365 dwIndex = 0; 2391 dwIndex = 0;
2392 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
2393 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PatchA", FALSE, BURN_CACHE_PACKAGE_TYPE_NONE, BURN_CACHE_PACKAGE_TYPE_REQUIRED);
2394 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PatchA");
2395 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 6);
2396 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", FALSE, BURN_CACHE_PACKAGE_TYPE_NONE, BURN_CACHE_PACKAGE_TYPE_REQUIRED);
2397 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
2366 Assert::Equal(dwIndex, pPlan->cCacheActions); 2398 Assert::Equal(dwIndex, pPlan->cCacheActions);
2367 2399
2368 fRollback = TRUE; 2400 fRollback = TRUE;
2369 dwIndex = 0; 2401 dwIndex = 0;
2370 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); 2402 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
2371 2403
2372 Assert::Equal(0ull, pPlan->qwCacheSizeTotal); 2404 Assert::Equal(212992ull, pPlan->qwCacheSizeTotal);
2373 2405
2374 fRollback = FALSE; 2406 fRollback = FALSE;
2375 dwIndex = 0; 2407 dwIndex = 0;
2376 DWORD dwExecuteCheckpointId = 1; 2408 DWORD dwExecuteCheckpointId = 2;
2377 BURN_EXECUTE_ACTION* pExecuteAction = NULL; 2409 BURN_EXECUTE_ACTION* pExecuteAction = NULL;
2378 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 2410 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
2379 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 2411 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2412 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PatchA");
2413 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2380 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PatchA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", unregisterActions1, 1); 2414 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PatchA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", unregisterActions1, 1);
2381 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 2415 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2382 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PatchA", unregisterActions1, 1); 2416 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PatchA", unregisterActions1, 1);
2383 pExecuteAction = ValidateDeletedExecuteMspTarget(pPlan, fRollback, dwIndex++, L"PatchA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, L"{5FF7F534-3FFC-41E0-80CD-E6361E5E7B7B}", TRUE, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, BOOTSTRAPPER_MSI_FILE_VERSIONING_MISSING_OR_OLDER, TRUE); 2417 pExecuteAction = ValidateDeletedExecuteMspTarget(pPlan, fRollback, dwIndex++, L"PatchA", BOOTSTRAPPER_ACTION_STATE_UNINSTALL, L"{5FF7F534-3FFC-41E0-80CD-E6361E5E7B7B}", TRUE, BURN_MSI_PROPERTY_UNINSTALL, INSTALLUILEVEL_NONE, FALSE, BOOTSTRAPPER_MSI_FILE_VERSIONING_MISSING_OR_OLDER, TRUE);
2384 ValidateExecuteMspTargetPatch(pExecuteAction, 0, L"PatchA"); 2418 ValidateExecuteMspTargetPatch(pExecuteAction, 0, L"PatchA");
2385 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 2419 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2420 dwExecuteCheckpointId += 1; // cache checkpoints
2421 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2422 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
2386 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 2423 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2387 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", unregisterActions1, 1); 2424 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", unregisterActions1, 1);
2388 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 2425 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -2396,8 +2433,9 @@ namespace Bootstrapper
2396 2433
2397 fRollback = TRUE; 2434 fRollback = TRUE;
2398 dwIndex = 0; 2435 dwIndex = 0;
2399 dwExecuteCheckpointId = 1; 2436 dwExecuteCheckpointId = 2;
2400 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 2437 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
2438 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2401 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PatchA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", registerActions1, 1); 2439 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PatchA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", registerActions1, 1);
2402 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 2440 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2403 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PatchA", registerActions1, 1); 2441 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PatchA", registerActions1, 1);
@@ -2405,6 +2443,8 @@ namespace Bootstrapper
2405 pExecuteAction = ValidateDeletedExecuteMspTarget(pPlan, fRollback, dwIndex++, L"PatchA", BOOTSTRAPPER_ACTION_STATE_INSTALL, L"{5FF7F534-3FFC-41E0-80CD-E6361E5E7B7B}", TRUE, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, BOOTSTRAPPER_MSI_FILE_VERSIONING_MISSING_OR_OLDER, TRUE); 2443 pExecuteAction = ValidateDeletedExecuteMspTarget(pPlan, fRollback, dwIndex++, L"PatchA", BOOTSTRAPPER_ACTION_STATE_INSTALL, L"{5FF7F534-3FFC-41E0-80CD-E6361E5E7B7B}", TRUE, BURN_MSI_PROPERTY_INSTALL, INSTALLUILEVEL_NONE, FALSE, BOOTSTRAPPER_MSI_FILE_VERSIONING_MISSING_OR_OLDER, TRUE);
2406 ValidateExecuteMspTargetPatch(pExecuteAction, 0, L"PatchA"); 2444 ValidateExecuteMspTargetPatch(pExecuteAction, 0, L"PatchA");
2407 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 2445 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2446 dwExecuteCheckpointId += 1; // cache checkpoints
2447 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2408 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", registerActions1, 1); 2448 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", registerActions1, 1);
2409 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 2449 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2410 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", registerActions1, 1); 2450 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", registerActions1, 1);
@@ -2417,7 +2457,7 @@ namespace Bootstrapper
2417 Assert::Equal(dwIndex, pPlan->cRollbackActions); 2457 Assert::Equal(dwIndex, pPlan->cRollbackActions);
2418 2458
2419 Assert::Equal(2ul, pPlan->cExecutePackagesTotal); 2459 Assert::Equal(2ul, pPlan->cExecutePackagesTotal);
2420 Assert::Equal(2ul, pPlan->cOverallProgressTicksTotal); 2460 Assert::Equal(4ul, pPlan->cOverallProgressTicksTotal);
2421 2461
2422 dwIndex = 0; 2462 dwIndex = 0;
2423 Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions); 2463 Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions);
@@ -2479,19 +2519,24 @@ namespace Bootstrapper
2479 2519
2480 fRollback = FALSE; 2520 fRollback = FALSE;
2481 dwIndex = 0; 2521 dwIndex = 0;
2522 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
2523 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", FALSE, BURN_CACHE_PACKAGE_TYPE_NONE, BURN_CACHE_PACKAGE_TYPE_REQUIRED);
2524 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
2482 Assert::Equal(dwIndex, pPlan->cCacheActions); 2525 Assert::Equal(dwIndex, pPlan->cCacheActions);
2483 2526
2484 fRollback = TRUE; 2527 fRollback = TRUE;
2485 dwIndex = 0; 2528 dwIndex = 0;
2486 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions); 2529 Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
2487 2530
2488 Assert::Equal(0ull, pPlan->qwCacheSizeTotal); 2531 Assert::Equal(131072ull, pPlan->qwCacheSizeTotal);
2489 2532
2490 fRollback = FALSE; 2533 fRollback = FALSE;
2491 dwIndex = 0; 2534 dwIndex = 0;
2492 DWORD dwExecuteCheckpointId = 1; 2535 DWORD dwExecuteCheckpointId = 2;
2493 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 2536 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
2494 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 2537 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2538 ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
2539 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2495 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", unregisterActions1, 1); 2540 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", unregisterActions1, 1);
2496 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 2541 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2497 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", unregisterActions1, 1); 2542 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", unregisterActions1, 1);
@@ -2504,8 +2549,9 @@ namespace Bootstrapper
2504 2549
2505 fRollback = TRUE; 2550 fRollback = TRUE;
2506 dwIndex = 0; 2551 dwIndex = 0;
2507 dwExecuteCheckpointId = 1; 2552 dwExecuteCheckpointId = 2;
2508 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE); 2553 ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
2554 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2509 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", registerActions1, 1); 2555 ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", registerActions1, 1);
2510 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++); 2556 ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2511 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", registerActions1, 1); 2557 ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", registerActions1, 1);
@@ -2518,7 +2564,7 @@ namespace Bootstrapper
2518 Assert::Equal(dwIndex, pPlan->cRollbackActions); 2564 Assert::Equal(dwIndex, pPlan->cRollbackActions);
2519 2565
2520 Assert::Equal(1ul, pPlan->cExecutePackagesTotal); 2566 Assert::Equal(1ul, pPlan->cExecutePackagesTotal);
2521 Assert::Equal(1ul, pPlan->cOverallProgressTicksTotal); 2567 Assert::Equal(2ul, pPlan->cOverallProgressTicksTotal);
2522 2568
2523 dwIndex = 0; 2569 dwIndex = 0;
2524 Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions); 2570 Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions);
@@ -2575,11 +2621,11 @@ namespace Bootstrapper
2575 fRollback = FALSE; 2621 fRollback = FALSE;
2576 dwIndex = 0; 2622 dwIndex = 0;
2577 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1); 2623 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
2578 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"NetFx48Web"); 2624 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"NetFx48Web", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
2579 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++); 2625 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"NetFx48Web");
2580 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 4); 2626 ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 4);
2581 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA"); 2627 ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
2582 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++); 2628 ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
2583 Assert::Equal(dwIndex, pPlan->cCacheActions); 2629 Assert::Equal(dwIndex, pPlan->cCacheActions);
2584 2630
2585 fRollback = TRUE; 2631 fRollback = TRUE;
@@ -3008,12 +3054,18 @@ namespace Bootstrapper
3008 __in BURN_PLAN* pPlan, 3054 __in BURN_PLAN* pPlan,
3009 __in BOOL fRollback, 3055 __in BOOL fRollback,
3010 __in DWORD dwIndex, 3056 __in DWORD dwIndex,
3011 __in LPCWSTR wzPackageId 3057 __in LPCWSTR wzPackageId,
3058 __in BOOL fVital,
3059 __in BURN_CACHE_PACKAGE_TYPE executeCacheType,
3060 __in BURN_CACHE_PACKAGE_TYPE rollbackCacheType
3012 ) 3061 )
3013 { 3062 {
3014 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex); 3063 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
3015 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_PACKAGE, pAction->type); 3064 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_PACKAGE, pAction->type);
3016 NativeAssert::StringEqual(wzPackageId, pAction->package.pPackage->sczId); 3065 NativeAssert::StringEqual(wzPackageId, pAction->package.pPackage->sczId);
3066 Assert::Equal<BOOL>(fVital, pAction->package.pPackage->fCacheVital);
3067 Assert::Equal<DWORD>(executeCacheType, pAction->package.pPackage->executeCacheType);
3068 Assert::Equal<DWORD>(rollbackCacheType, pAction->package.pPackage->rollbackCacheType);
3017 return dwIndex + 1; 3069 return dwIndex + 1;
3018 } 3070 }
3019 3071
@@ -3032,12 +3084,13 @@ namespace Bootstrapper
3032 void ValidateCacheSignalSyncpoint( 3084 void ValidateCacheSignalSyncpoint(
3033 __in BURN_PLAN* pPlan, 3085 __in BURN_PLAN* pPlan,
3034 __in BOOL fRollback, 3086 __in BOOL fRollback,
3035 __in DWORD dwIndex 3087 __in DWORD dwIndex,
3088 __in LPCWSTR wzPackageId
3036 ) 3089 )
3037 { 3090 {
3038 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex); 3091 BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
3039 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT, pAction->type); 3092 Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT, pAction->type);
3040 Assert::NotEqual((DWORD_PTR)NULL, (DWORD_PTR)pAction->syncpoint.hEvent); 3093 NativeAssert::StringEqual(wzPackageId, pAction->syncpoint.pPackage->sczId);
3041 } 3094 }
3042 3095
3043 void ValidateCleanAction( 3096 void ValidateCleanAction(
diff --git a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
index 9c0f9576..9aa58a28 100644
--- a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
+++ b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
@@ -655,6 +655,7 @@ public: // IBootstrapperApplication
655 __in_z LPCWSTR wzPackageId, 655 __in_z LPCWSTR wzPackageId,
656 __in DWORD cCachePayloads, 656 __in DWORD cCachePayloads,
657 __in DWORD64 dw64PackageCacheSize, 657 __in DWORD64 dw64PackageCacheSize,
658 __in BOOL fVital,
658 __inout BOOL* pfCancel 659 __inout BOOL* pfCancel
659 ) 660 )
660 { 661 {
@@ -673,7 +674,7 @@ public: // IBootstrapperApplication
673 } 674 }
674 } 675 }
675 676
676 return __super::OnCachePackageBegin(wzPackageId, cCachePayloads, dw64PackageCacheSize, pfCancel); 677 return __super::OnCachePackageBegin(wzPackageId, cCachePayloads, dw64PackageCacheSize, fVital, pfCancel);
677 } 678 }
678 679
679 680
@@ -1488,6 +1489,9 @@ public: // IBootstrapperApplication
1488 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTRELATEDBUNDLEPACKAGE: 1489 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTRELATEDBUNDLEPACKAGE:
1489 OnDetectRelatedBundlePackageFallback(reinterpret_cast<BA_ONDETECTRELATEDBUNDLEPACKAGE_ARGS*>(pvArgs), reinterpret_cast<BA_ONDETECTRELATEDBUNDLEPACKAGE_RESULTS*>(pvResults)); 1490 OnDetectRelatedBundlePackageFallback(reinterpret_cast<BA_ONDETECTRELATEDBUNDLEPACKAGE_ARGS*>(pvArgs), reinterpret_cast<BA_ONDETECTRELATEDBUNDLEPACKAGE_RESULTS*>(pvResults));
1490 break; 1491 break;
1492 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPACKAGENONVITALVALIDATIONFAILURE:
1493 OnCachePackageNonVitalValidationFailureFallback(reinterpret_cast<BA_ONCACHEPACKAGENONVITALVALIDATIONFAILURE_ARGS*>(pvArgs), reinterpret_cast<BA_ONCACHEPACKAGENONVITALVALIDATIONFAILURE_RESULTS*>(pvResults));
1494 break;
1491 default: 1495 default:
1492#ifdef DEBUG 1496#ifdef DEBUG
1493 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: Forwarding unknown BA message: %d", message); 1497 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: Forwarding unknown BA message: %d", message);
@@ -2177,6 +2181,14 @@ private: // privates
2177 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONDETECTRELATEDBUNDLEPACKAGE, pArgs, pResults, m_pvBAFunctionsProcContext); 2181 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONDETECTRELATEDBUNDLEPACKAGE, pArgs, pResults, m_pvBAFunctionsProcContext);
2178 } 2182 }
2179 2183
2184 void OnCachePackageNonVitalValidationFailureFallback(
2185 __in BA_ONCACHEPACKAGENONVITALVALIDATIONFAILURE_ARGS* pArgs,
2186 __inout BA_ONCACHEPACKAGENONVITALVALIDATIONFAILURE_RESULTS* pResults
2187 )
2188 {
2189 m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONCACHEPACKAGENONVITALVALIDATIONFAILURE, pArgs, pResults, m_pvBAFunctionsProcContext);
2190 }
2191
2180 2192
2181public: //CBalBaseBootstrapperApplication 2193public: //CBalBaseBootstrapperApplication
2182 virtual STDMETHODIMP Initialize( 2194 virtual STDMETHODIMP Initialize(
diff --git a/src/test/burn/TestBA/TestBA.cs b/src/test/burn/TestBA/TestBA.cs
index 9ca82377..7e3d2623 100644
--- a/src/test/burn/TestBA/TestBA.cs
+++ b/src/test/burn/TestBA/TestBA.cs
@@ -27,6 +27,7 @@ namespace WixToolset.Test.BA
27 27
28 private string updateBundlePath; 28 private string updateBundlePath;
29 29
30 private bool allowAcquireAfterValidationFailure;
30 private bool forceKeepRegistration; 31 private bool forceKeepRegistration;
31 private bool immediatelyQuit; 32 private bool immediatelyQuit;
32 private bool quitAfterDetect; 33 private bool quitAfterDetect;
@@ -85,7 +86,11 @@ namespace WixToolset.Test.BA
85 86
86 List<string> verifyArguments = this.ReadVerifyArguments(); 87 List<string> verifyArguments = this.ReadVerifyArguments();
87 88
88 foreach (string arg in BootstrapperCommand.ParseCommandLineToArgs(this.Command.CommandLine)) 89 IBootstrapperApplicationData baManifest = new BootstrapperApplicationData();
90 IMbaCommand mbaCommand = this.Command.ParseCommandLine();
91 mbaCommand.SetOverridableVariables(baManifest.Bundle.OverridableVariables, this.engine);
92
93 foreach (string arg in mbaCommand.UnknownCommandLineArgs)
89 { 94 {
90 // If we're not in the update already, process the updatebundle. 95 // If we're not in the update already, process the updatebundle.
91 if (this.Command.Relation != RelationType.Update && arg.StartsWith("-updatebundle:", StringComparison.OrdinalIgnoreCase)) 96 if (this.Command.Relation != RelationType.Update && arg.StartsWith("-updatebundle:", StringComparison.OrdinalIgnoreCase))
@@ -126,6 +131,12 @@ namespace WixToolset.Test.BA
126 redetectCount = 0; 131 redetectCount = 0;
127 } 132 }
128 133
134 string allowAcquireAfterValidationFailure = this.ReadPackageAction(null, "AllowAcquireAfterValidationFailure");
135 if (String.IsNullOrEmpty(allowAcquireAfterValidationFailure) || !Boolean.TryParse(allowAcquireAfterValidationFailure, out this.allowAcquireAfterValidationFailure))
136 {
137 this.allowAcquireAfterValidationFailure = false;
138 }
139
129 string explicitlyElevateAndPlanFromOnElevateBegin = this.ReadPackageAction(null, "ExplicitlyElevateAndPlanFromOnElevateBegin"); 140 string explicitlyElevateAndPlanFromOnElevateBegin = this.ReadPackageAction(null, "ExplicitlyElevateAndPlanFromOnElevateBegin");
130 if (String.IsNullOrEmpty(explicitlyElevateAndPlanFromOnElevateBegin) || !Boolean.TryParse(explicitlyElevateAndPlanFromOnElevateBegin, out this.explicitlyElevateAndPlanFromOnElevateBegin)) 141 if (String.IsNullOrEmpty(explicitlyElevateAndPlanFromOnElevateBegin) || !Boolean.TryParse(explicitlyElevateAndPlanFromOnElevateBegin, out this.explicitlyElevateAndPlanFromOnElevateBegin))
131 { 142 {
@@ -277,6 +288,15 @@ namespace WixToolset.Test.BA
277 { 288 {
278 args.State = state; 289 args.State = state;
279 } 290 }
291
292 BOOTSTRAPPER_CACHE_TYPE cacheType;
293 string cacheAction = this.ReadPackageAction(args.PackageId, "CacheRequested");
294 if (TryParseEnum<BOOTSTRAPPER_CACHE_TYPE>(cacheAction, out cacheType))
295 {
296 args.CacheType = cacheType;
297 }
298
299 this.Log("OnPlanPackageBegin() - id: {0}, defaultState: {1}, requestedState: {2}, defaultCache: {3}, requestedCache: {4}", args.PackageId, args.RecommendedState, args.State, args.RecommendedCacheType, args.CacheType);
280 } 300 }
281 301
282 protected override void OnPlanPatchTarget(PlanPatchTargetEventArgs args) 302 protected override void OnPlanPatchTarget(PlanPatchTargetEventArgs args)
@@ -337,6 +357,16 @@ namespace WixToolset.Test.BA
337 } 357 }
338 } 358 }
339 359
360 protected override void OnCachePackageNonVitalValidationFailure(CachePackageNonVitalValidationFailureEventArgs args)
361 {
362 if (this.allowAcquireAfterValidationFailure)
363 {
364 args.Action = BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION.Acquire;
365 }
366
367 this.Log("OnCachePackageNonVitalValidationFailure() - id: {0}, default: {1}, requested: {2}", args.PackageId, args.Recommendation, args.Action);
368 }
369
340 protected override void OnCacheAcquireProgress(CacheAcquireProgressEventArgs args) 370 protected override void OnCacheAcquireProgress(CacheAcquireProgressEventArgs args)
341 { 371 {
342 this.Log("OnCacheAcquireProgress() - container/package: {0}, payload: {1}, progress: {2}, total: {3}, overall progress: {4}%", args.PackageOrContainerId, args.PayloadId, args.Progress, args.Total, args.OverallPercentage); 372 this.Log("OnCacheAcquireProgress() - container/package: {0}, payload: {1}, progress: {2}, total: {3}, overall progress: {4}%", args.PackageOrContainerId, args.PayloadId, args.Progress, args.Total, args.OverallPercentage);
diff --git a/src/test/burn/TestData/ExePackageTests/PackageTestExe/PackageTestExe.wixproj b/src/test/burn/TestData/ExePackageTests/PackageTestExe/PackageTestExe.wixproj
new file mode 100644
index 00000000..57e99a1b
--- /dev/null
+++ b/src/test/burn/TestData/ExePackageTests/PackageTestExe/PackageTestExe.wixproj
@@ -0,0 +1,16 @@
1<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2<Project Sdk="WixToolset.Sdk">
3 <PropertyGroup>
4 <ProductComponentsRef>true</ProductComponentsRef>
5 <UpgradeCode>{9281948B-9C8D-4914-A00E-3EF0F98D17EB}</UpgradeCode>
6 </PropertyGroup>
7 <ItemGroup>
8 <Compile Include="..\..\Templates\Package.wxs" Link="Package.wxs" />
9 </ItemGroup>
10 <ItemGroup>
11 <ProjectReference Include="..\..\TestBA\TestBAWixlib\testbawixlib.wixproj" />
12 </ItemGroup>
13 <ItemGroup>
14 <PackageReference Include="WixToolset.Util.wixext" />
15 </ItemGroup>
16</Project> \ No newline at end of file
diff --git a/src/test/burn/TestData/ExePackageTests/PackageTestExe/ProductComponents.wxs b/src/test/burn/TestData/ExePackageTests/PackageTestExe/ProductComponents.wxs
new file mode 100644
index 00000000..b42c5c5a
--- /dev/null
+++ b/src/test/burn/TestData/ExePackageTests/PackageTestExe/ProductComponents.wxs
@@ -0,0 +1,12 @@
1<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2
3<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">
4 <Fragment>
5 <ComponentGroup Id="ProductComponents">
6 <ComponentRef Id="TestExeComponent" />
7 </ComponentGroup>
8
9 <util:FailWhenDeferred />
10 <Property Id="WIXFAILWHENDEFERRED" Secure="yes" />
11 </Fragment>
12</Wix>
diff --git a/src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackageUninstallFailure/PerMachineArpEntryExePackageUninstallFailure.wixproj b/src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackageUninstallFailure/PerMachineArpEntryExePackageUninstallFailure.wixproj
new file mode 100644
index 00000000..bbab2b75
--- /dev/null
+++ b/src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackageUninstallFailure/PerMachineArpEntryExePackageUninstallFailure.wixproj
@@ -0,0 +1,18 @@
1<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2<Project Sdk="WixToolset.Sdk">
3 <PropertyGroup>
4 <OutputType>Bundle</OutputType>
5 <UpgradeCode>{799DF604-49CB-4B2C-9FD9-A1C4F93A2FDE}</UpgradeCode>
6 </PropertyGroup>
7 <ItemGroup>
8 <Compile Include="..\..\Templates\Bundle.wxs" Link="Bundle.wxs" />
9 </ItemGroup>
10 <ItemGroup>
11 <ProjectReference Include="..\..\TestBA\TestBAWixlib\testbawixlib.wixproj" />
12 <ProjectReference Include="..\PackageTestExe\PackageTestExe.wixproj" />
13 </ItemGroup>
14 <ItemGroup>
15 <PackageReference Include="WixToolset.Bal.wixext" />
16 <PackageReference Include="WixToolset.NetFx.wixext" />
17 </ItemGroup>
18</Project> \ No newline at end of file
diff --git a/src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackageUninstallFailure/PerMachineArpEntryExePackageUninstallFailure.wxs b/src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackageUninstallFailure/PerMachineArpEntryExePackageUninstallFailure.wxs
new file mode 100644
index 00000000..ffa98d4e
--- /dev/null
+++ b/src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackageUninstallFailure/PerMachineArpEntryExePackageUninstallFailure.wxs
@@ -0,0 +1,24 @@
1<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2
3<?define ArpId = {2BE9DAA8-E202-4E42-B25E-B39AA987A59C}?>
4<?define ArpKeyPath = HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$(var.ArpId)?>
5<?define ArpVersion = 1.0.0.0?>
6<?define TestExePath = [ProgramFilesFolder]~Test WiX\$(var.TestGroupName)\PackageTestExe\testexe.exe?>
7
8<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
9 <Fragment>
10 <Variable Name="FAILWHENDEFERRED" bal:Overridable="yes" />
11
12 <PackageGroup Id="BundlePackages">
13 <MsiPackage Id="PackageTestExe" SourceFile="$(var.PackageTestExe.TargetPath)">
14 <MsiProperty Name="WIXFAILWHENDEFERRED" Value="[FAILWHENDEFERRED]" />
15 </MsiPackage>
16 <ExePackage Id="TestExe" PerMachine="yes"
17 InstallArguments="/regw &quot;$(var.ArpKeyPath),DisplayVersion,String,$(var.ArpVersion)&quot; /regw &quot;$(var.ArpKeyPath),QuietUninstallString,String,\&quot;$(var.TestExePath)\&quot; /regd \&quot;$(var.ArpKeyPath)\&quot;&quot;">
18 <ArpEntry Id="$(var.ArpId)" Version="$(var.ArpVersion)" Win64="no" />
19
20 <PayloadGroupRef Id="TestExePayloads" />
21 </ExePackage>
22 </PackageGroup>
23 </Fragment>
24</Wix>
diff --git a/src/test/burn/TestData/TestBA/TestBAWixlib/TestExe.wxs b/src/test/burn/TestData/TestBA/TestBAWixlib/TestExe.wxs
index f27275b0..84da0983 100644
--- a/src/test/burn/TestData/TestBA/TestBAWixlib/TestExe.wxs
+++ b/src/test/burn/TestData/TestBA/TestBAWixlib/TestExe.wxs
@@ -6,4 +6,11 @@
6 <Payload SourceFile="!(bindpath.net2x86)\TestExe.exe.config" /> 6 <Payload SourceFile="!(bindpath.net2x86)\TestExe.exe.config" />
7 </PayloadGroup> 7 </PayloadGroup>
8 </Fragment> 8 </Fragment>
9
10 <Fragment>
11 <Component Id="TestExeComponent" Directory="INSTALLFOLDER">
12 <File Source="!(bindpath.net2x86)\TestExe.exe" KeyPath="yes" />
13 <File Source="!(bindpath.net2x86)\TestExe.exe.config" />
14 </Component>
15 </Fragment>
9</Wix> 16</Wix>
diff --git a/src/test/burn/WixToolsetTest.BurnE2E/ExePackageTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/ExePackageTests.cs
index dc6515b5..e76461f3 100644
--- a/src/test/burn/WixToolsetTest.BurnE2E/ExePackageTests.cs
+++ b/src/test/burn/WixToolsetTest.BurnE2E/ExePackageTests.cs
@@ -3,6 +3,7 @@
3namespace WixToolsetTest.BurnE2E 3namespace WixToolsetTest.BurnE2E
4{ 4{
5 using WixTestTools; 5 using WixTestTools;
6 using WixToolset.Mba.Core;
6 using Xunit; 7 using Xunit;
7 using Xunit.Abstractions; 8 using Xunit.Abstractions;
8 9
@@ -13,9 +14,9 @@ namespace WixToolsetTest.BurnE2E
13 [RuntimeFact] 14 [RuntimeFact]
14 public void CanInstallAndUninstallPerMachineArpEntryExePackage() 15 public void CanInstallAndUninstallPerMachineArpEntryExePackage()
15 { 16 {
16 const string arpId = "{4D9EC36A-1E63-4244-875C-3ECB0A2CAE30}";
17 var perMachineArpEntryExePackageBundle = this.CreateBundleInstaller(@"PerMachineArpEntryExePackage"); 17 var perMachineArpEntryExePackageBundle = this.CreateBundleInstaller(@"PerMachineArpEntryExePackage");
18 var arpEntryExePackage = this.CreateArpEntryInstaller(perMachineArpEntryExePackageBundle, "TestExe"); 18 var arpEntryExePackage = this.CreateArpEntryInstaller(perMachineArpEntryExePackageBundle, "TestExe");
19 var arpId = arpEntryExePackage.ArpId;
19 20
20 arpEntryExePackage.VerifyRegistered(false); 21 arpEntryExePackage.VerifyRegistered(false);
21 22
@@ -23,21 +24,113 @@ namespace WixToolsetTest.BurnE2E
23 perMachineArpEntryExePackageBundle.VerifyRegisteredAndInPackageCache(); 24 perMachineArpEntryExePackageBundle.VerifyRegisteredAndInPackageCache();
24 arpEntryExePackage.VerifyRegistered(true); 25 arpEntryExePackage.VerifyRegistered(true);
25 26
26 LogVerifier.MessageInLogFile(installLogPath, $"TestExe.exe\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},DisplayVersion,String,1.0.0.0\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},QuietUninstallString,String,\\\""); 27 Assert.True(LogVerifier.MessageInLogFile(installLogPath, $"TestExe.exe\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},DisplayVersion,String,1.0.0.0\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},QuietUninstallString,String,\\\""));
27 28
28 var uninstallLogPath = perMachineArpEntryExePackageBundle.Uninstall(); 29 var uninstallLogPath = perMachineArpEntryExePackageBundle.Uninstall();
29 perMachineArpEntryExePackageBundle.VerifyUnregisteredAndRemovedFromPackageCache(); 30 perMachineArpEntryExePackageBundle.VerifyUnregisteredAndRemovedFromPackageCache();
30 arpEntryExePackage.VerifyRegistered(false); 31 arpEntryExePackage.VerifyRegistered(false);
31 32
32 LogVerifier.MessageInLogFile(uninstallLogPath, $"testexe.exe\" /regd HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}"); 33 Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, $"testexe.exe\" /regd HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}"));
33 } 34 }
34 35
35 [RuntimeFact] 36 [RuntimeFact]
36 public void CanUninstallPerMachineArpEntryExePackageOnRollback() 37 public void CanRecacheAndReinstallPerMachineArpEntryExePackageOnUninstallRollback()
38 {
39 var packageTestExe = this.CreatePackageInstaller("PackageTestExe");
40 var perMachineArpEntryExePackageUninstallFailureBundle = this.CreateBundleInstaller(@"PerMachineArpEntryExePackageUninstallFailure");
41 var arpEntryExePackage = this.CreateArpEntryInstaller(perMachineArpEntryExePackageUninstallFailureBundle, "TestExe");
42 var arpId = arpEntryExePackage.ArpId;
43 var testBAController = this.CreateTestBAController();
44
45 arpEntryExePackage.VerifyRegistered(false);
46 packageTestExe.VerifyInstalled(false);
47
48 testBAController.SetPackageRequestedCacheType("TestExe", BOOTSTRAPPER_CACHE_TYPE.Remove);
49
50 var installLogPath = perMachineArpEntryExePackageUninstallFailureBundle.Install();
51 perMachineArpEntryExePackageUninstallFailureBundle.VerifyRegisteredAndInPackageCache();
52 arpEntryExePackage.VerifyRegistered(true);
53 packageTestExe.VerifyInstalled(true);
54
55 Assert.True(LogVerifier.MessageInLogFile(installLogPath, $"TestExe.exe\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},DisplayVersion,String,1.0.0.0\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},QuietUninstallString,String,\\\""));
56
57 testBAController.ResetPackageStates("TestExe");
58 testBAController.SetAllowAcquireAfterValidationFailure();
59
60 var uninstallLogPath = perMachineArpEntryExePackageUninstallFailureBundle.Uninstall((int)MSIExec.MSIExecReturnCode.ERROR_INSTALL_FAILURE, "FAILWHENDEFERRED=1");
61 perMachineArpEntryExePackageUninstallFailureBundle.VerifyRegisteredAndInPackageCache();
62 arpEntryExePackage.VerifyRegistered(true);
63 packageTestExe.VerifyInstalled(true);
64
65 Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, "TESTBA: OnCachePackageNonVitalValidationFailure() - id: TestExe, default: None, requested: Acquire"));
66 Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, $"testexe.exe\" /regd HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}"));
67 Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, $"TestExe.exe\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},DisplayVersion,String,1.0.0.0\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},QuietUninstallString,String,\\\""));
68 }
69
70 [RuntimeFact]
71 public void CanReinstallPerMachineArpEntryExePackageOnUninstallRollback()
72 {
73 var packageTestExe = this.CreatePackageInstaller("PackageTestExe");
74 var perMachineArpEntryExePackageUninstallFailureBundle = this.CreateBundleInstaller(@"PerMachineArpEntryExePackageUninstallFailure");
75 var arpEntryExePackage = this.CreateArpEntryInstaller(perMachineArpEntryExePackageUninstallFailureBundle, "TestExe");
76 var arpId = arpEntryExePackage.ArpId;
77
78 arpEntryExePackage.VerifyRegistered(false);
79 packageTestExe.VerifyInstalled(false);
80
81 var installLogPath = perMachineArpEntryExePackageUninstallFailureBundle.Install();
82 perMachineArpEntryExePackageUninstallFailureBundle.VerifyRegisteredAndInPackageCache();
83 arpEntryExePackage.VerifyRegistered(true);
84 packageTestExe.VerifyInstalled(true);
85
86 Assert.True(LogVerifier.MessageInLogFile(installLogPath, $"TestExe.exe\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},DisplayVersion,String,1.0.0.0\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},QuietUninstallString,String,\\\""));
87
88 var uninstallLogPath = perMachineArpEntryExePackageUninstallFailureBundle.Uninstall((int)MSIExec.MSIExecReturnCode.ERROR_INSTALL_FAILURE, "FAILWHENDEFERRED=1");
89 perMachineArpEntryExePackageUninstallFailureBundle.VerifyRegisteredAndInPackageCache();
90 arpEntryExePackage.VerifyRegistered(true);
91 packageTestExe.VerifyInstalled(true);
92
93 Assert.False(LogVerifier.MessageInLogFile(uninstallLogPath, "TESTBA: OnCachePackageNonVitalValidationFailure() - id: TestExe"));
94 Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, $"testexe.exe\" /regd HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}"));
95 Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, $"TestExe.exe\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},DisplayVersion,String,1.0.0.0\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},QuietUninstallString,String,\\\""));
96 }
97
98 [RuntimeFact]
99 public void CanSkipReinstallPerMachineArpEntryExePackageOnUninstallRollback()
100 {
101 var packageTestExe = this.CreatePackageInstaller("PackageTestExe");
102 var perMachineArpEntryExePackageUninstallFailureBundle = this.CreateBundleInstaller(@"PerMachineArpEntryExePackageUninstallFailure");
103 var arpEntryExePackage = this.CreateArpEntryInstaller(perMachineArpEntryExePackageUninstallFailureBundle, "TestExe");
104 var arpId = arpEntryExePackage.ArpId;
105 var testBAController = this.CreateTestBAController();
106
107 arpEntryExePackage.VerifyRegistered(false);
108 packageTestExe.VerifyInstalled(false);
109
110 testBAController.SetPackageRequestedCacheType("TestExe", BOOTSTRAPPER_CACHE_TYPE.Remove);
111
112 var installLogPath = perMachineArpEntryExePackageUninstallFailureBundle.Install();
113 perMachineArpEntryExePackageUninstallFailureBundle.VerifyRegisteredAndInPackageCache();
114 arpEntryExePackage.VerifyRegistered(true);
115 packageTestExe.VerifyInstalled(true);
116
117 Assert.True(LogVerifier.MessageInLogFile(installLogPath, $"TestExe.exe\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},DisplayVersion,String,1.0.0.0\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},QuietUninstallString,String,\\\""));
118
119 var uninstallLogPath = perMachineArpEntryExePackageUninstallFailureBundle.Uninstall((int)MSIExec.MSIExecReturnCode.ERROR_INSTALL_FAILURE, "FAILWHENDEFERRED=1");
120 perMachineArpEntryExePackageUninstallFailureBundle.VerifyRegisteredAndInPackageCache();
121 arpEntryExePackage.VerifyRegistered(false);
122 packageTestExe.VerifyInstalled(true);
123
124 Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, "TESTBA: OnCachePackageNonVitalValidationFailure() - id: TestExe, default: None, requested: None"));
125 Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, $"testexe.exe\" /regd HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}"));
126 }
127
128 [RuntimeFact]
129 public void CanUninstallPerMachineArpEntryExePackageOnInstallRollback()
37 { 130 {
38 const string arpId = "{80E90929-EEA5-48A7-A680-A0237A1CAD84}";
39 var perMachineArpEntryExePackageFailureBundle = this.CreateBundleInstaller(@"PerMachineArpEntryExePackageFailure"); 131 var perMachineArpEntryExePackageFailureBundle = this.CreateBundleInstaller(@"PerMachineArpEntryExePackageFailure");
40 var arpEntryExePackage = this.CreateArpEntryInstaller(perMachineArpEntryExePackageFailureBundle, "TestExe"); 132 var arpEntryExePackage = this.CreateArpEntryInstaller(perMachineArpEntryExePackageFailureBundle, "TestExe");
133 var arpId = arpEntryExePackage.ArpId;
41 134
42 arpEntryExePackage.VerifyRegistered(false); 135 arpEntryExePackage.VerifyRegistered(false);
43 136
@@ -45,16 +138,16 @@ namespace WixToolsetTest.BurnE2E
45 perMachineArpEntryExePackageFailureBundle.VerifyUnregisteredAndRemovedFromPackageCache(); 138 perMachineArpEntryExePackageFailureBundle.VerifyUnregisteredAndRemovedFromPackageCache();
46 arpEntryExePackage.VerifyRegistered(false); 139 arpEntryExePackage.VerifyRegistered(false);
47 140
48 LogVerifier.MessageInLogFile(installLogPath, $"TestExe.exe\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},DisplayVersion,String,1.0.0.0\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},QuietUninstallString,String,\\\""); 141 Assert.True(LogVerifier.MessageInLogFile(installLogPath, $"TestExe.exe\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},DisplayVersion,String,1.0.0.0\" /regw \"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},QuietUninstallString,String,\\\""));
49 LogVerifier.MessageInLogFile(installLogPath, $"testexe.exe\" /regd HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}"); 142 Assert.True(LogVerifier.MessageInLogFile(installLogPath, $"testexe.exe\" /regd HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}"));
50 } 143 }
51 144
52 [RuntimeFact] 145 [RuntimeFact]
53 public void CanInstallAndUninstallPerUserArpEntryExePackage() 146 public void CanInstallAndUninstallPerUserArpEntryExePackage()
54 { 147 {
55 const string arpId = "{9B5300C7-9B34-4670-9614-185B02AB87EF}";
56 var perUserArpEntryExePackageBundle = this.CreateBundleInstaller(@"PerUserArpEntryExePackage"); 148 var perUserArpEntryExePackageBundle = this.CreateBundleInstaller(@"PerUserArpEntryExePackage");
57 var arpEntryExePackage = this.CreateArpEntryInstaller(perUserArpEntryExePackageBundle, "TestExe"); 149 var arpEntryExePackage = this.CreateArpEntryInstaller(perUserArpEntryExePackageBundle, "TestExe");
150 var arpId = arpEntryExePackage.ArpId;
58 151
59 arpEntryExePackage.VerifyRegistered(false); 152 arpEntryExePackage.VerifyRegistered(false);
60 153
@@ -62,21 +155,21 @@ namespace WixToolsetTest.BurnE2E
62 perUserArpEntryExePackageBundle.VerifyRegisteredAndInPackageCache(); 155 perUserArpEntryExePackageBundle.VerifyRegisteredAndInPackageCache();
63 arpEntryExePackage.VerifyRegistered(true); 156 arpEntryExePackage.VerifyRegistered(true);
64 157
65 LogVerifier.MessageInLogFile(installLogPath, $"TestExe.exe\" /regw \"HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},DisplayVersion,String,1.0.0.0\" /regw \"HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},QuietUninstallString,String,\\\""); 158 Assert.True(LogVerifier.MessageInLogFile(installLogPath, $"TestExe.exe\" /regw \"HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},DisplayVersion,String,1.0.0.0\" /regw \"HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},QuietUninstallString,String,\\\""));
66 159
67 var uninstallLogPath = perUserArpEntryExePackageBundle.Uninstall(); 160 var uninstallLogPath = perUserArpEntryExePackageBundle.Uninstall();
68 perUserArpEntryExePackageBundle.VerifyUnregisteredAndRemovedFromPackageCache(); 161 perUserArpEntryExePackageBundle.VerifyUnregisteredAndRemovedFromPackageCache();
69 arpEntryExePackage.VerifyRegistered(false); 162 arpEntryExePackage.VerifyRegistered(false);
70 163
71 LogVerifier.MessageInLogFile(uninstallLogPath, $"testexe.exe\" /regd HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}"); 164 Assert.True(LogVerifier.MessageInLogFile(uninstallLogPath, $"testexe.exe\" /regd HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}"));
72 } 165 }
73 166
74 [RuntimeFact] 167 [RuntimeFact]
75 public void FailsUninstallWhenPerUserArpEntryExePackageMissingQuietUninstallString() 168 public void FailsUninstallWhenPerUserArpEntryExePackageMissingQuietUninstallString()
76 { 169 {
77 const string arpId = "{DE9F8594-5856-4454-AB10-3C01ED246D7D}";
78 var brokenPerUserArpEntryExePackageBundle = this.CreateBundleInstaller(@"BrokenPerUserArpEntryExePackage"); 170 var brokenPerUserArpEntryExePackageBundle = this.CreateBundleInstaller(@"BrokenPerUserArpEntryExePackage");
79 var arpEntryExePackage = this.CreateArpEntryInstaller(brokenPerUserArpEntryExePackageBundle, "TestExe"); 171 var arpEntryExePackage = this.CreateArpEntryInstaller(brokenPerUserArpEntryExePackageBundle, "TestExe");
172 var arpId = arpEntryExePackage.ArpId;
80 173
81 arpEntryExePackage.VerifyRegistered(false); 174 arpEntryExePackage.VerifyRegistered(false);
82 brokenPerUserArpEntryExePackageBundle.VerifyUnregisteredAndRemovedFromPackageCache(); 175 brokenPerUserArpEntryExePackageBundle.VerifyUnregisteredAndRemovedFromPackageCache();
@@ -85,7 +178,7 @@ namespace WixToolsetTest.BurnE2E
85 brokenPerUserArpEntryExePackageBundle.VerifyRegisteredAndInPackageCache(); 178 brokenPerUserArpEntryExePackageBundle.VerifyRegisteredAndInPackageCache();
86 arpEntryExePackage.VerifyRegistered(true); 179 arpEntryExePackage.VerifyRegistered(true);
87 180
88 LogVerifier.MessageInLogFile(installLogPath, $"TestExe.exe\" /regw \"HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},DisplayVersion,String,1.0.0.0\""); 181 Assert.True(LogVerifier.MessageInLogFile(installLogPath, $"TestExe.exe\" /regw \"HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId},DisplayVersion,String,1.0.0.0\""));
89 182
90 brokenPerUserArpEntryExePackageBundle.Uninstall((int)MSIExec.MSIExecReturnCode.ERROR_INVALID_PARAMETER); 183 brokenPerUserArpEntryExePackageBundle.Uninstall((int)MSIExec.MSIExecReturnCode.ERROR_INVALID_PARAMETER);
91 brokenPerUserArpEntryExePackageBundle.VerifyRegisteredAndInPackageCache(); 184 brokenPerUserArpEntryExePackageBundle.VerifyRegisteredAndInPackageCache();
diff --git a/src/test/burn/WixToolsetTest.BurnE2E/Utilities/TestBAController.cs b/src/test/burn/WixToolsetTest.BurnE2E/Utilities/TestBAController.cs
index 8e6611a2..3f9d76b8 100644
--- a/src/test/burn/WixToolsetTest.BurnE2E/Utilities/TestBAController.cs
+++ b/src/test/burn/WixToolsetTest.BurnE2E/Utilities/TestBAController.cs
@@ -42,6 +42,11 @@ namespace WixToolsetTest.BurnE2E
42 } 42 }
43 } 43 }
44 44
45 public void SetAllowAcquireAfterValidationFailure(string value = "true")
46 {
47 this.SetBurnTestValue("AllowAcquireAfterValidationFailure", value);
48 }
49
45 public void SetExplicitlyElevateAndPlanFromOnElevateBegin(string value = "true") 50 public void SetExplicitlyElevateAndPlanFromOnElevateBegin(string value = "true")
46 { 51 {
47 this.SetBurnTestValue("ExplicitlyElevateAndPlanFromOnElevateBegin", value); 52 this.SetBurnTestValue("ExplicitlyElevateAndPlanFromOnElevateBegin", value);
@@ -133,6 +138,16 @@ namespace WixToolsetTest.BurnE2E
133 } 138 }
134 139
135 /// <summary> 140 /// <summary>
141 /// Sets the requested cache type for a package that the TestBA will return to the engine during plan.
142 /// </summary>
143 /// <param name="packageId">Package identity.</param>
144 /// <param name="type">Cache type to request.</param>
145 public void SetPackageRequestedCacheType(string packageId, BOOTSTRAPPER_CACHE_TYPE type)
146 {
147 this.SetPackageState(packageId, "CacheRequested", type.ToString());
148 }
149
150 /// <summary>
136 /// Sets the requested state for a package that the TestBA will return to the engine during plan. 151 /// Sets the requested state for a package that the TestBA will return to the engine during plan.
137 /// </summary> 152 /// </summary>
138 /// <param name="packageId">Package identity.</param> 153 /// <param name="packageId">Package identity.</param>