Add ability for non-vital cache package action.
Sean Hall committed
Jun 14, 2022 at 15:09 UTC
dea657295df261bb0e3e4d620eeae321531e3a11
31 files changed
+723
-155
src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
+25
@@ -226,6 +226,7 @@ enum BOOTSTRAPPER_APPLICATION_MESSAGE
226
BOOTSTRAPPER_APPLICATION_MESSAGE_ONAPPLYDOWNGRADE,
227
BOOTSTRAPPER_APPLICATION_MESSAGE_ONEXECUTEPROCESSCANCEL,
228
BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTRELATEDBUNDLEPACKAGE,
229
+ BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPACKAGENONVITALVALIDATIONFAILURE,
230
};
231
232
enum BOOTSTRAPPER_APPLYCOMPLETE_ACTION
@@ -257,6 +258,14 @@ enum BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION
258
BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_RETRY,
259
};
260
261
+enum 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
+
269
enum BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION
270
{
271
BOOTSTRAPPER_CACHEVERIFYCOMPLETE_ACTION_NONE,
@@ -546,6 +555,8 @@ struct BA_ONCACHEPACKAGEBEGIN_ARGS
555
LPCWSTR wzPackageId;
556
DWORD cCachePayloads;
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;
560
};
561
562
struct BA_ONCACHEPACKAGEBEGIN_RESULTS
@@ -568,6 +579,20 @@ struct BA_ONCACHEPACKAGECOMPLETE_RESULTS
579
BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION action;
580
};
581
582
+struct BA_ONCACHEPACKAGENONVITALVALIDATIONFAILURE_ARGS
583
+{
584
+ DWORD cbSize;
585
+ LPCWSTR wzPackageId;
586
+ HRESULT hrStatus;
587
+ BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION recommendation;
588
+};
589
+
590
+struct BA_ONCACHEPACKAGENONVITALVALIDATIONFAILURE_RESULTS
591
+{
592
+ DWORD cbSize;
593
+ BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION action;
594
+};
595
+
596
struct BA_ONCACHEPAYLOADEXTRACTBEGIN_ARGS
597
{
598
DWORD cbSize;
src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs
+27
-2
@@ -280,6 +280,9 @@ namespace WixToolset.Mba.Core
280
/// <inheritdoc/>
281
public event EventHandler<DetectRelatedBundlePackageEventArgs> DetectRelatedBundlePackage;
282
283
+ /// <inheritdoc/>
284
+ public event EventHandler<CachePackageNonVitalValidationFailureEventArgs> CachePackageNonVitalValidationFailure;
285
+
286
/// <summary>
287
/// Entry point that is called when the bootstrapper application is ready to run.
288
/// </summary>
@@ -1376,6 +1379,18 @@ namespace WixToolset.Mba.Core
1379
}
1380
}
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
+
1394
#region IBootstrapperApplication Members
1395
1396
int IBootstrapperApplication.BAProc(int message, IntPtr pvArgs, IntPtr pvResults, IntPtr pvContext)
@@ -1570,6 +1585,7 @@ namespace WixToolset.Mba.Core
1585
this.OnPlanPackageBegin(args);
1586
1587
pRequestedState = args.State;
1588
+ pRequestedCacheType = args.CacheType;
1589
fCancel = args.Cancel;
1590
return args.HResult;
1591
}
@@ -1728,9 +1744,9 @@ namespace WixToolset.Mba.Core
1744
return args.HResult;
1745
}
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)
1748
{
1733
- CachePackageBeginEventArgs args = new CachePackageBeginEventArgs(wzPackageId, cCachePayloads, dw64PackageCacheSize, fCancel);
1749
+ CachePackageBeginEventArgs args = new CachePackageBeginEventArgs(wzPackageId, cCachePayloads, dw64PackageCacheSize, fVital, fCancel);
1750
this.OnCachePackageBegin(args);
1751
1752
fCancel = args.Cancel;
@@ -2131,6 +2147,15 @@ namespace WixToolset.Mba.Core
2147
return args.HResult;
2148
}
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
+
2159
#endregion
2160
}
2161
}
src/api/burn/WixToolset.Mba.Core/EventArgs.cs
+26
-1
@@ -1930,12 +1930,13 @@ namespace WixToolset.Mba.Core
1930
public class CachePackageBeginEventArgs : CancellableHResultEventArgs
1931
{
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)
1935
{
1936
this.PackageId = packageId;
1937
this.CachePayloads = cachePayloads;
1938
this.PackageCacheSize = packageCacheSize;
1939
+ this.Vital = vital;
1940
}
1941
1942
/// <summary>
@@ -1952,6 +1953,11 @@ namespace WixToolset.Mba.Core
1953
/// Gets the size on disk required by the specific package.
1954
/// </summary>
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; }
1961
}
1962
1963
/// <summary>
@@ -2482,4 +2488,23 @@ namespace WixToolset.Mba.Core
2488
/// </summary>
2489
public string Version { get; private set; }
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
+ }
2510
}
src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs
+30
-10
@@ -553,17 +553,13 @@ namespace WixToolset.Mba.Core
553
/// <summary>
554
/// See <see cref="IDefaultBootstrapperApplication.CachePackageBegin"/>.
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>
556
[PreserveSig]
557
[return: MarshalAs(UnmanagedType.I4)]
558
int OnCachePackageBegin(
559
[MarshalAs(UnmanagedType.LPWStr)] string wzPackageId,
560
[MarshalAs(UnmanagedType.U4)] int cCachePayloads,
561
[MarshalAs(UnmanagedType.U8)] long dw64PackageCacheSize,
562
+ [MarshalAs(UnmanagedType.Bool)] bool fVital,
563
[MarshalAs(UnmanagedType.Bool)] ref bool fCancel
564
);
565
@@ -672,11 +668,6 @@ namespace WixToolset.Mba.Core
668
/// <summary>
669
/// See <see cref="IDefaultBootstrapperApplication.CachePackageComplete"/>.
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>
671
[PreserveSig]
672
[return: MarshalAs(UnmanagedType.I4)]
673
int OnCachePackageComplete(
@@ -1184,6 +1175,18 @@ namespace WixToolset.Mba.Core
1175
[MarshalAs(UnmanagedType.LPWStr)] string wzVersion,
1176
[MarshalAs(UnmanagedType.Bool)] ref bool fCancel
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
+ );
1190
}
1191
1192
/// <summary>
@@ -1870,6 +1873,23 @@ namespace WixToolset.Mba.Core
1873
Retry,
1874
}
1875
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>
1894
/// The available actions for <see cref="IDefaultBootstrapperApplication.CacheVerifyComplete"/>.
1895
/// </summary>
src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs
+5
@@ -93,6 +93,11 @@ namespace WixToolset.Mba.Core
93
/// </summary>
94
event EventHandler<CachePackageCompleteEventArgs> CachePackageComplete;
95
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>
102
/// Fired when the engine begins the extraction of the payload from the container.
103
/// </summary>
src/api/burn/balutil/inc/BAFunctions.h
+1
@@ -92,6 +92,7 @@ enum BA_FUNCTIONS_MESSAGE
92
BA_FUNCTIONS_MESSAGE_ONAPPLYDOWNGRADE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONAPPLYDOWNGRADE,
93
BA_FUNCTIONS_MESSAGE_ONEXECUTEPROCESSCANCEL = BOOTSTRAPPER_APPLICATION_MESSAGE_ONEXECUTEPROCESSCANCEL,
94
BA_FUNCTIONS_MESSAGE_ONDETECTRELATEDBUNDLEPACKAGE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTRELATEDBUNDLEPACKAGE,
95
+ BA_FUNCTIONS_MESSAGE_ONCACHEPACKAGENONVITALVALIDATIONFAILURE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPACKAGENONVITALVALIDATIONFAILURE,
96
97
BA_FUNCTIONS_MESSAGE_ONTHEMELOADED = 1024,
98
BA_FUNCTIONS_MESSAGE_WNDPROC,
src/api/burn/balutil/inc/BalBaseBAFunctions.h
+11
@@ -447,6 +447,7 @@ public: // IBootstrapperApplication
447
__in_z LPCWSTR /*wzPackageId*/,
448
__in DWORD /*cCachePayloads*/,
449
__in DWORD64 /*dw64PackageCacheSize*/,
450
+ __in BOOL /*fVital*/,
451
__inout BOOL* /*pfCancel*/
452
)
453
{
@@ -892,6 +893,16 @@ public: // IBootstrapperApplication
893
return S_OK;
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
+
906
public: // IBAFunctions
907
virtual STDMETHODIMP OnPlan(
908
)
src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h
+1
@@ -163,6 +163,7 @@ static HRESULT WINAPI BalBaseBAFunctionsProc(
163
case BA_FUNCTIONS_MESSAGE_ONAPPLYDOWNGRADE:
164
case BA_FUNCTIONS_MESSAGE_ONEXECUTEPROCESSCANCEL:
165
case BA_FUNCTIONS_MESSAGE_ONDETECTRELATEDBUNDLEPACKAGE:
166
+ case BA_FUNCTIONS_MESSAGE_ONCACHEPACKAGENONVITALVALIDATIONFAILURE:
167
hr = BalBaseBootstrapperApplicationProc((BOOTSTRAPPER_APPLICATION_MESSAGE)message, pvArgs, pvResults, pvContext);
168
break;
169
case BA_FUNCTIONS_MESSAGE_ONTHEMELOADED:
src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h
+11
@@ -505,6 +505,7 @@ public: // IBootstrapperApplication
505
__in_z LPCWSTR /*wzPackageId*/,
506
__in DWORD /*cCachePayloads*/,
507
__in DWORD64 /*dw64PackageCacheSize*/,
508
+ __in BOOL /*fVital*/,
509
__inout BOOL* pfCancel
510
)
511
{
@@ -1084,6 +1085,16 @@ public: // IBootstrapperApplication
1085
return S_OK;
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
+
1098
public: //CBalBaseBootstrapperApplication
1099
virtual STDMETHODIMP Initialize(
1100
__in const BOOTSTRAPPER_CREATE_ARGS* pCreateArgs
src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h
+13
-1
@@ -330,7 +330,7 @@ static HRESULT BalBaseBAProcOnCachePackageBegin(
330
__inout BA_ONCACHEPACKAGEBEGIN_RESULTS* pResults
331
)
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
}
335
336
static 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);
757
}
758
759
+static 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
+
768
/*******************************************************************
769
BalBaseBootstrapperApplicationProc - requires pvContext to be of type IBootstrapperApplication.
770
Provides a default mapping between the new message based BA interface and
@@ -1024,6 +1033,9 @@ static HRESULT WINAPI BalBaseBootstrapperApplicationProc(
1033
case BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTRELATEDBUNDLEPACKAGE:
1034
hr = BalBaseBAProcOnDetectRelatedBundlePackage(pBA, reinterpret_cast<BA_ONDETECTRELATEDBUNDLEPACKAGE_ARGS*>(pvArgs), reinterpret_cast<BA_ONDETECTRELATEDBUNDLEPACKAGE_RESULTS*>(pvResults));
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;
1039
}
1040
}
1041
src/api/burn/balutil/inc/IBootstrapperApplication.h
+9
@@ -343,6 +343,7 @@ DECLARE_INTERFACE_IID_(IBootstrapperApplication, IUnknown, "53C31D56-49C0-426B-A
343
__in_z LPCWSTR wzPackageId,
344
__in DWORD cCachePayloads,
345
__in DWORD64 dw64PackageCacheSize,
346
+ __in BOOL fVital,
347
__inout BOOL* pfCancel
348
) = 0;
349
@@ -728,4 +729,12 @@ DECLARE_INTERFACE_IID_(IBootstrapperApplication, IUnknown, "53C31D56-49C0-426B-A
729
__in_z LPCWSTR wzVersion,
730
__inout BOOL* pfCancel
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;
740
};
src/burn/engine/apply.cpp
+41
-10
@@ -110,7 +110,8 @@ static HRESULT ApplyLayoutContainer(
110
static HRESULT ApplyProcessPayload(
111
__in BURN_CACHE_CONTEXT* pContext,
112
__in_opt BURN_PACKAGE* pPackage,
113
- __in BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem
113
+ __in BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem,
114
+ __in BOOL fVital
115
);
116
static HRESULT ApplyCacheVerifyContainerOrPayload(
117
__in BURN_CACHE_CONTEXT* pContext,
@@ -203,6 +204,10 @@ static HRESULT DoRollbackActions(
204
__in DWORD dwCheckpoint,
205
__out BOOTSTRAPPER_APPLY_RESTART* pRestart
206
);
207
+static BOOL ShouldSkipPackage(
208
+ __in BURN_PACKAGE* pPackage,
209
+ __in BOOL fRollback
210
+ );
211
static HRESULT ExecuteRelatedBundle(
212
__in BURN_ENGINE_STATE* pEngineState,
213
__in BURN_EXECUTE_ACTION* pExecuteAction,
@@ -379,6 +384,7 @@ extern "C" void ApplyReset(
384
{
385
BURN_PACKAGE* pPackage = pPackages->rgPackages + i;
386
pPackage->hrCacheResult = S_OK;
387
+ pPackage->fAcquireOptionalSource = FALSE;
388
pPackage->fReachedExecution = FALSE;
389
pPackage->fAbandonedProcess = FALSE;
390
pPackage->transactionRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_UNKNOWN;
@@ -633,7 +639,7 @@ extern "C" HRESULT ApplyCache(
639
break;
640
641
case BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT:
636
- if (!::SetEvent(pCacheAction->syncpoint.hEvent))
642
+ if (!::SetEvent(pCacheAction->syncpoint.pPackage->hCacheEvent))
643
{
644
ExitWithLastError(hr, "Failed to set syncpoint event.");
645
}
@@ -959,12 +965,13 @@ static HRESULT ApplyCachePackage(
965
HRESULT hr = S_OK;
966
BOOL fCanceledBegin = FALSE;
967
BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION cachePackageCompleteAction = BOOTSTRAPPER_CACHEPACKAGECOMPLETE_ACTION_NONE;
968
+ BOOL fVital = pPackage->fCacheVital;
969
970
for (;;)
971
{
972
fCanceledBegin = FALSE;
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);
975
if (FAILED(hr))
976
{
977
fCanceledBegin = TRUE;
@@ -975,7 +982,7 @@ static HRESULT ApplyCachePackage(
982
{
983
BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem = pPackage->payloads.rgItems + i;
984
978
- hr = ApplyProcessPayload(pContext, pPackage, pPayloadGroupItem);
985
+ hr = ApplyProcessPayload(pContext, pPackage, pPayloadGroupItem, fVital);
986
if (FAILED(hr))
987
{
988
break;
@@ -984,7 +991,7 @@ static HRESULT ApplyCachePackage(
991
}
992
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;
995
UserExperienceOnCachePackageComplete(pContext->pUX, pPackage->sczId, hr, &cachePackageCompleteAction);
996
997
if (SUCCEEDED(hr))
@@ -1014,7 +1021,7 @@ static HRESULT ApplyCachePackage(
1021
1022
continue;
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.
1025
{
1026
LogId(REPORT_STANDARD, MSG_CACHE_CONTINUING_NONVITAL_PACKAGE, pPackage->sczId, hr);
1027
hr = S_OK;
@@ -1101,7 +1108,7 @@ static HRESULT ApplyLayoutBundle(
1108
{
1109
BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem = pPayloads->rgItems + i;
1110
1104
- hr = ApplyProcessPayload(pContext, NULL, pPayloadGroupItem);
1111
+ hr = ApplyProcessPayload(pContext, NULL, pPayloadGroupItem, TRUE);
1112
ExitOnFailure(hr, "Failed to layout bundle payload: %ls", pPayloadGroupItem->pPayload->sczKey);
1113
}
1114
@@ -1164,12 +1171,14 @@ LExit:
1171
static HRESULT ApplyProcessPayload(
1172
__in BURN_CACHE_CONTEXT* pContext,
1173
__in_opt BURN_PACKAGE* pPackage,
1167
- __in BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem
1174
+ __in BURN_PAYLOAD_GROUP_ITEM* pPayloadGroupItem,
1175
+ __in BOOL fVital
1176
)
1177
{
1178
HRESULT hr = S_OK;
1179
DWORD cTryAgainAttempts = 0;
1180
BOOL fRetry = FALSE;
1181
+ BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION action = BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION_NONE;
1182
BURN_PAYLOAD* pPayload = pPayloadGroupItem->pPayload;
1183
1184
Assert(pContext->pPayloads && pPackage || pContext->wzLayoutDirectory);
@@ -1184,6 +1193,18 @@ static HRESULT ApplyProcessPayload(
1193
{
1194
ExitFunction();
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
+ }
1208
1209
for (;;)
1210
{
@@ -2567,10 +2588,20 @@ static BOOL ShouldSkipPackage(
2588
)
2589
{
2590
BOOL fSkip = FALSE;
2591
+ BURN_CACHE_PACKAGE_TYPE cachePackageType = fRollback ? pPackage->rollbackCacheType : pPackage->executeCacheType;
2592
+ BOOL fCacheVital = BURN_CACHE_PACKAGE_TYPE_REQUIRED == cachePackageType;
2593
2571
- if (FAILED(pPackage->hrCacheResult))
2594
+ if (fCacheVital && FAILED(pPackage->hrCacheResult))
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
+
2605
ExitFunction1(fSkip = TRUE);
2606
}
2607
else if (fRollback && pPackage->fAbandonedProcess)
src/burn/engine/core.cpp
+1
-1
@@ -2329,7 +2329,7 @@ static void LogPackages(
2329
LogRollbackBoundary(pPackage->pRollbackBoundaryBackward);
2330
}
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
2334
if (BURN_PACKAGE_TYPE_MSI == pPackage->type)
2335
{
src/burn/engine/engine.mc
+2
-2
@@ -417,9 +417,9 @@ Planned related bundle: %1!ls!, detect type: %2!hs!, default plan type: %3!hs!,
417
418
MessageId=208
419
Severity=Warning
420
-SymbolicName=MSG_PLAN_DISABLING_ROLLBACK_NO_CACHE
420
+SymbolicName=MSG_APPLY_SKIPPED_ROLLBACK_NO_CACHE
421
Language=English
422
-Plan disabled rollback due to incomplete cache for package: %1!ls!, original rollback action: %2!hs!
422
+Skipping apply rollback of package: %1!ls! due to cache error: 0x%2!x!, original rollback action: %3!hs!. Continuing...
423
.
424
425
MessageId=209
src/burn/engine/logging.cpp
+29
@@ -445,6 +445,23 @@ extern "C" LPCSTR LoggingCacheTypeToString(
445
}
446
}
447
448
+extern "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
+
465
extern "C" LPCSTR LoggingDependencyActionToString(
466
BURN_DEPENDENCY_ACTION action
467
)
@@ -669,6 +686,18 @@ extern "C" LPCSTR LoggingPerMachineToString(
686
return "PerUser";
687
}
688
689
+extern "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
+
701
extern "C" LPCSTR LoggingRegistrationTypeToString(
702
__in BOOTSTRAPPER_REGISTRATION_TYPE registrationType
703
)
src/burn/engine/logging.h
+8
@@ -92,6 +92,10 @@ LPCSTR LoggingCacheTypeToString(
92
BOOTSTRAPPER_CACHE_TYPE cacheType
93
);
94
95
+LPCSTR LoggingCachePackageTypeToString(
96
+ BURN_CACHE_PACKAGE_TYPE cachePackageType
97
+ );
98
+
99
LPCSTR LoggingDependencyActionToString(
100
BURN_DEPENDENCY_ACTION action
101
);
@@ -142,6 +146,10 @@ LPCSTR LoggingPerMachineToString(
146
__in BOOL fPerMachine
147
);
148
149
+LPCSTR LoggingPlannedCacheToString(
150
+ __in const BURN_PACKAGE* pPackage
151
+ );
152
+
153
LPCSTR LoggingRegistrationTypeToString(
154
__in BOOTSTRAPPER_REGISTRATION_TYPE registrationType
155
);
src/burn/engine/package.h
+11
-1
@@ -16,6 +16,13 @@ typedef _BURN_PACKAGE BURN_PACKAGE;
16
17
const DWORD BURN_PACKAGE_INVALID_PATCH_INDEX = 0x80000000;
18
19
+enum 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
+
26
enum BURN_EXE_DETECTION_TYPE
27
{
28
BURN_EXE_DETECTION_TYPE_NONE,
@@ -277,7 +284,7 @@ typedef struct _BURN_PACKAGE
284
BOOTSTRAPPER_CACHE_TYPE cacheType; // only valid during Plan.
285
BOOTSTRAPPER_REQUEST_STATE defaultRequested;// 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.
288
BOOL fPlannedUncache; // only valid during Plan.
289
BOOTSTRAPPER_ACTION_STATE execute; // only valid during Plan.
290
BOOTSTRAPPER_ACTION_STATE rollback; // only valid during Plan.
@@ -286,9 +293,12 @@ typedef struct _BURN_PACKAGE
293
BURN_DEPENDENCY_ACTION dependencyExecute; // only valid during Plan.
294
BURN_DEPENDENCY_ACTION dependencyRollback; // 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.
298
HANDLE hCacheEvent; // only valid during Plan.
299
LPWSTR sczCacheFolder; // only valid during Apply.
300
HRESULT hrCacheResult; // only valid during Apply.
301
+ BOOL fAcquireOptionalSource; // only valid during Apply.
302
BOOL fReachedExecution; // only valid during Apply.
303
BOOL fAbandonedProcess; // only valid during Apply.
304
src/burn/engine/plan.cpp
+66
-45
@@ -78,11 +78,13 @@ static HRESULT AddRegistrationAction(
78
);
79
static HRESULT AddCachePackage(
80
__in BURN_PLAN* pPlan,
81
- __in BURN_PACKAGE* pPackage
81
+ __in BURN_PACKAGE* pPackage,
82
+ __in BOOL fVital
83
);
84
static HRESULT AddCachePackageHelper(
85
__in BURN_PLAN* pPlan,
85
- __in BURN_PACKAGE* pPackage
86
+ __in BURN_PACKAGE* pPackage,
87
+ __in BOOL fVital
88
);
89
static HRESULT AddCacheSlipstreamMsps(
90
__in BURN_PLAN* pPlan,
@@ -134,7 +136,7 @@ static HRESULT CalculateExecuteActions(
136
__in BURN_PACKAGE* pPackage,
137
__in_opt BURN_ROLLBACK_BOUNDARY* pActiveRollbackBoundary
138
);
137
-static BOOL NeedsCache(
139
+static BURN_CACHE_PACKAGE_TYPE GetCachePackageType(
140
__in BURN_PACKAGE* pPackage,
141
__in BOOL fExecute
142
);
@@ -894,7 +896,7 @@ static HRESULT PlanPackagesHelper(
896
DWORD iPackage = fReverseOrder ? cPackages - 1 - i : i;
897
BURN_PACKAGE* pPackage = rgPackages + iPackage;
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);
900
901
if (pPackage->compatiblePackage.fPlannable)
902
{
@@ -999,7 +1001,7 @@ static HRESULT ProcessPackage(
1001
{
1002
if (BOOTSTRAPPER_REQUEST_STATE_NONE != pPackage->requested)
1003
{
1002
- hr = PlanLayoutPackage(pPlan, pPackage);
1004
+ hr = PlanLayoutPackage(pPlan, pPackage, TRUE);
1005
ExitOnFailure(hr, "Failed to plan layout package.");
1006
}
1007
}
@@ -1015,7 +1017,7 @@ static HRESULT ProcessPackage(
1017
{
1018
if (ForceCache(pPlan, pPackage))
1019
{
1018
- hr = AddCachePackage(pPlan, pPackage);
1020
+ hr = AddCachePackage(pPlan, pPackage, TRUE);
1021
ExitOnFailure(hr, "Failed to plan cache package.");
1022
1023
if (pPackage->fPerMachine)
@@ -1127,7 +1129,8 @@ LExit:
1129
1130
extern "C" HRESULT PlanLayoutPackage(
1131
__in BURN_PLAN* pPlan,
1130
- __in BURN_PACKAGE* pPackage
1132
+ __in BURN_PACKAGE* pPackage,
1133
+ __in BOOL fVital
1134
)
1135
{
1136
HRESULT hr = S_OK;
@@ -1143,6 +1146,7 @@ extern "C" HRESULT PlanLayoutPackage(
1146
1147
pCacheAction->type = BURN_CACHE_ACTION_TYPE_PACKAGE;
1148
pCacheAction->package.pPackage = pPackage;
1149
+ pPackage->fCacheVital = fVital;
1150
1151
++pPlan->cOverallProgressTicksTotal;
1152
@@ -1170,18 +1174,14 @@ extern "C" HRESULT PlanExecutePackage(
1174
hr = DependencyPlanPackageBegin(fPerMachine, pPackage, pPlan);
1175
ExitOnFailure(hr, "Failed to begin plan dependency actions for package: %ls", pPackage->sczId);
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)
1181
{
1175
- hr = AddCachePackage(pPlan, pPackage);
1182
+ hr = AddCachePackage(pPlan, pPackage, BURN_CACHE_PACKAGE_TYPE_REQUIRED == pPackage->executeCacheType);
1183
ExitOnFailure(hr, "Failed to plan cache package.");
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
1186
// Add execute actions.
1187
switch (pPackage->type)
@@ -1364,6 +1364,8 @@ extern "C" HRESULT PlanRelatedBundlesInitialize(
1364
pRelatedBundle->package.requested = BOOTSTRAPPER_REQUEST_STATE_NONE;
1365
pRelatedBundle->defaultPlanRelationType = 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;
1369
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.
1371
// This gives more information to the BA in case it wants to override default behavior.
@@ -2088,10 +2090,6 @@ static void UninitializeCacheAction(
2090
{
2091
switch (pCacheAction->type)
2092
{
2091
- case BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT:
2092
- ReleaseHandle(pCacheAction->syncpoint.hEvent);
2093
- break;
2094
-
2093
case BURN_CACHE_ACTION_TYPE_LAYOUT_BUNDLE:
2094
ReleaseStr(pCacheAction->bundleLayout.sczExecutableName);
2095
ReleaseStr(pCacheAction->bundleLayout.sczUnverifiedPath);
@@ -2145,7 +2143,7 @@ static void ResetPlannedPackageState(
2143
pPackage->cacheType = pPackage->authoredCacheType;
2144
pPackage->defaultRequested = BOOTSTRAPPER_REQUEST_STATE_NONE;
2145
pPackage->requested = BOOTSTRAPPER_REQUEST_STATE_NONE;
2148
- pPackage->fPlannedCache = FALSE;
2146
+ pPackage->fCacheVital = FALSE;
2147
pPackage->fPlannedUncache = FALSE;
2148
pPackage->execute = BOOTSTRAPPER_ACTION_STATE_NONE;
2149
pPackage->rollback = BOOTSTRAPPER_ACTION_STATE_NONE;
@@ -2156,7 +2154,9 @@ static void ResetPlannedPackageState(
2154
pPackage->fDependencyManagerWasHere = FALSE;
2155
pPackage->expectedCacheRegistrationState = 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
2161
ReleaseNullStr(pPackage->sczCacheFolder);
2162
@@ -2314,19 +2314,21 @@ LExit:
2314
2315
static HRESULT AddCachePackage(
2316
__in BURN_PLAN* pPlan,
2317
- __in BURN_PACKAGE* pPackage
2317
+ __in BURN_PACKAGE* pPackage,
2318
+ __in BOOL fVital
2319
)
2320
{
2321
HRESULT hr = S_OK;
2322
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)
2326
{
2327
hr = AddCacheSlipstreamMsps(pPlan, pPackage);
2328
ExitOnFailure(hr, "Failed to plan slipstream patches for package.");
2329
}
2330
2329
- hr = AddCachePackageHelper(pPlan, pPackage);
2331
+ hr = AddCachePackageHelper(pPlan, pPackage, fVital);
2332
ExitOnFailure(hr, "Failed to plan cache package.");
2333
2334
LExit:
@@ -2335,7 +2337,8 @@ LExit:
2337
2338
static HRESULT AddCachePackageHelper(
2339
__in BURN_PLAN* pPlan,
2338
- __in BURN_PACKAGE* pPackage
2340
+ __in BURN_PACKAGE* pPackage,
2341
+ __in BOOL fVital
2342
)
2343
{
2344
AssertSz(pPackage->sczCacheId && *pPackage->sczCacheId, "AddCachePackageHelper() expects the package to have a cache id.");
@@ -2354,6 +2357,9 @@ static HRESULT AddCachePackageHelper(
2357
ExitFunction();
2358
}
2359
2360
+ pPackage->hCacheEvent = ::CreateEventW(NULL, TRUE, FALSE, NULL);
2361
+ ExitOnNullWithLastError(pPackage->hCacheEvent, hr, "Failed to create syncpoint event.");
2362
+
2363
// Cache checkpoints happen before the package is cached because downloading packages'
2364
// payloads will not roll themselves back the way installation packages rollback on
2365
// failure automatically.
@@ -2381,7 +2387,7 @@ static HRESULT AddCachePackageHelper(
2387
pCacheAction->checkpoint.dwId = dwCheckpoint;
2388
}
2389
2384
- hr = PlanLayoutPackage(pPlan, pPackage);
2390
+ hr = PlanLayoutPackage(pPlan, pPackage, fVital);
2391
ExitOnFailure(hr, "Failed to plan cache for package.");
2392
2393
// Create syncpoint action.
@@ -2389,15 +2395,11 @@ static HRESULT AddCachePackageHelper(
2395
ExitOnFailure(hr, "Failed to append cache action.");
2396
2397
pCacheAction->type = BURN_CACHE_ACTION_TYPE_SIGNAL_SYNCPOINT;
2392
- pCacheAction->syncpoint.hEvent = ::CreateEventW(NULL, TRUE, FALSE, NULL);
2393
- ExitOnNullWithLastError(pCacheAction->syncpoint.hEvent, hr, "Failed to create syncpoint event.");
2394
-
2395
- pPackage->hCacheEvent = pCacheAction->syncpoint.hEvent;
2398
+ pCacheAction->syncpoint.pPackage = pPackage;
2399
2400
hr = PlanExecuteCacheSyncAndRollback(pPlan, pPackage);
2401
ExitOnFailure(hr, "Failed to plan package cache syncpoint");
2402
2400
- pPackage->fPlannedCache = TRUE;
2403
if (pPackage->fCanAffectRegistration)
2404
{
2405
pPackage->expectedCacheRegistrationState = BURN_PACKAGE_REGISTRATION_STATE_PRESENT;
@@ -2421,7 +2423,7 @@ static HRESULT AddCacheSlipstreamMsps(
2423
BURN_PACKAGE* pMspPackage = pPackage->Msi.rgSlipstreamMsps[i].pMspPackage;
2424
AssertSz(BURN_PACKAGE_TYPE_MSP == pMspPackage->type, "Only MSP packages can be slipstream patches.");
2425
2424
- hr = AddCachePackageHelper(pPlan, pMspPackage);
2426
+ hr = AddCachePackageHelper(pPlan, pMspPackage, TRUE);
2427
ExitOnFailure(hr, "Failed to plan slipstream MSP: %ls", pMspPackage->sczId);
2428
}
2429
@@ -2791,22 +2793,41 @@ LExit:
2793
return hr;
2794
}
2795
2794
-static BOOL NeedsCache(
2796
+static BURN_CACHE_PACKAGE_TYPE GetCachePackageType(
2797
__in BURN_PACKAGE* pPackage,
2798
__in BOOL fExecute
2799
)
2800
{
2799
- BOOTSTRAPPER_ACTION_STATE action = fExecute ? pPackage->execute : pPackage->rollback;
2800
- // TODO: bundles could theoretically use package cache
2801
- if (BURN_PACKAGE_TYPE_BUNDLE == pPackage->type || // Bundle and Exe packages require the package for all operations (even uninstall).
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.
2801
+ BURN_CACHE_PACKAGE_TYPE cachePackageType = BURN_CACHE_PACKAGE_TYPE_NONE;
2802
+
2803
+ switch (fExecute ? pPackage->execute : pPackage->rollback)
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;
2828
}
2829
+
2830
+ return cachePackageType;
2831
}
2832
2833
static BOOL ForceCache(
@@ -2881,7 +2902,7 @@ static void CacheActionLog(
2902
break;
2903
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));
2906
break;
2907
2908
case BURN_CACHE_ACTION_TYPE_ROLLBACK_PACKAGE:
@@ -2889,7 +2910,7 @@ static void CacheActionLog(
2910
break;
2911
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);
2914
break;
2915
2916
default:
src/burn/engine/plan.h
+3
-2
@@ -117,7 +117,7 @@ typedef struct _BURN_CACHE_ACTION
117
} rollbackPackage;
118
struct
119
{
120
- HANDLE hEvent;
120
+ BURN_PACKAGE* pPackage;
121
} syncpoint;
122
struct
123
{
@@ -392,7 +392,8 @@ HRESULT PlanLayoutContainer(
392
);
393
HRESULT PlanLayoutPackage(
394
__in BURN_PLAN* pPlan,
395
- __in BURN_PACKAGE* pPackage
395
+ __in BURN_PACKAGE* pPackage,
396
+ __in BOOL fVital
397
);
398
HRESULT PlanExecutePackage(
399
__in BOOL fPerMachine,
src/burn/engine/userexperience.cpp
+38
-2
@@ -104,7 +104,7 @@ extern "C" HRESULT UserExperienceLoad(
104
args.pCommand = pCommand;
105
args.pfnBootstrapperEngineProc = EngineForApplicationProc;
106
args.pvBootstrapperEngineProcContext = pEngineContext;
107
- args.qwEngineAPIVersion = MAKEQWORDVERSION(2022, 3, 31, 0);
107
+ args.qwEngineAPIVersion = MAKEQWORDVERSION(2022, 6, 10, 0);
108
109
results.cbSize = sizeof(BOOTSTRAPPER_CREATE_RESULTS);
110
@@ -726,7 +726,8 @@ EXTERN_C BAAPI UserExperienceOnCachePackageBegin(
726
__in BURN_USER_EXPERIENCE* pUserExperience,
727
__in_z LPCWSTR wzPackageId,
728
__in DWORD cCachePayloads,
729
- __in DWORD64 dw64PackageCacheSize
729
+ __in DWORD64 dw64PackageCacheSize,
730
+ __in BOOL fVital
731
)
732
{
733
HRESULT hr = S_OK;
@@ -737,6 +738,7 @@ EXTERN_C BAAPI UserExperienceOnCachePackageBegin(
738
args.wzPackageId = wzPackageId;
739
args.cCachePayloads = cCachePayloads;
740
args.dw64PackageCacheSize = dw64PackageCacheSize;
741
+ args.fVital = fVital;
742
743
results.cbSize = sizeof(results);
744
@@ -783,6 +785,40 @@ LExit:
785
return hr;
786
}
787
788
+EXTERN_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
+
818
+LExit:
819
+ return hr;
820
+}
821
+
822
EXTERN_C BAAPI UserExperienceOnCachePayloadExtractBegin(
823
__in BURN_USER_EXPERIENCE* pUserExperience,
824
__in_z_opt LPCWSTR wzContainerId,
src/burn/engine/userexperience.h
+8
-1
@@ -189,7 +189,14 @@ BAAPI UserExperienceOnCachePackageBegin(
189
__in BURN_USER_EXPERIENCE* pUserExperience,
190
__in_z LPCWSTR wzPackageId,
191
__in DWORD cCachePayloads,
192
- __in DWORD64 dw64PackageCacheSize
192
+ __in DWORD64 dw64PackageCacheSize,
193
+ __in BOOL fVital
194
+ );
195
+BAAPI UserExperienceOnCachePackageNonVitalValidationFailure(
196
+ __in BURN_USER_EXPERIENCE* pUserExperience,
197
+ __in_z LPCWSTR wzPackageId,
198
+ __in HRESULT hrStatus,
199
+ __inout BOOTSTRAPPER_CACHEPACKAGENONVITALVALIDATIONFAILURE_ACTION* pAction
200
);
201
BAAPI UserExperienceOnCachePackageComplete(
202
__in BURN_USER_EXPERIENCE* pUserExperience,
src/burn/test/BurnUnitTest/PlanTest.cpp
+116
-63
@@ -87,8 +87,8 @@ namespace Bootstrapper
87
fRollback = FALSE;
88
dwIndex = 0;
89
ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
90
- ValidateCachePackage(pPlan, fRollback, dwIndex++, L"TestExe");
91
- ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
90
+ ValidateCachePackage(pPlan, fRollback, dwIndex++, L"TestExe", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
91
+ ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"TestExe");
92
Assert::Equal(dwIndex, pPlan->cCacheActions);
93
94
fRollback = TRUE;
@@ -259,19 +259,24 @@ namespace Bootstrapper
259
260
fRollback = FALSE;
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");
265
Assert::Equal(dwIndex, pPlan->cCacheActions);
266
267
fRollback = TRUE;
268
dwIndex = 0;
269
Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
270
268
- Assert::Equal(0ull, pPlan->qwCacheSizeTotal);
271
+ Assert::Equal(143724ull, pPlan->qwCacheSizeTotal);
272
273
fRollback = FALSE;
274
dwIndex = 0;
272
- DWORD dwExecuteCheckpointId = 1;
275
+ DWORD dwExecuteCheckpointId = 2;
276
ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
277
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
278
+ ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"TestExe");
279
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
280
ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"TestExe", BOOTSTRAPPER_ACTION_STATE_UNINSTALL);
281
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
282
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -280,8 +285,9 @@ namespace Bootstrapper
285
286
fRollback = TRUE;
287
dwIndex = 0;
283
- dwExecuteCheckpointId = 1;
288
+ dwExecuteCheckpointId = 2;
289
ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
290
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
291
ValidateExecuteExePackage(pPlan, fRollback, dwIndex++, L"TestExe", BOOTSTRAPPER_ACTION_STATE_INSTALL);
292
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
293
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -290,7 +296,7 @@ namespace Bootstrapper
296
Assert::Equal(dwIndex, pPlan->cRollbackActions);
297
298
Assert::Equal(1ul, pPlan->cExecutePackagesTotal);
293
- Assert::Equal(1ul, pPlan->cOverallProgressTicksTotal);
299
+ Assert::Equal(2ul, pPlan->cOverallProgressTicksTotal);
300
301
dwIndex = 0;
302
Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions);
@@ -347,14 +353,14 @@ namespace Bootstrapper
353
fRollback = FALSE;
354
dwIndex = 0;
355
ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
350
- ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
351
- ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
356
+ ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
357
+ ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
358
ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 9);
353
- ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageB");
354
- ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
359
+ ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageB", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
360
+ ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageB");
361
ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 14);
356
- ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageC");
357
- ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
362
+ ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageC", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
363
+ ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageC");
364
Assert::Equal(dwIndex, pPlan->cCacheActions);
365
366
fRollback = TRUE;
@@ -506,13 +512,16 @@ namespace Bootstrapper
512
513
fRollback = FALSE;
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");
518
Assert::Equal(dwIndex, pPlan->cCacheActions);
519
520
fRollback = TRUE;
521
dwIndex = 0;
522
Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
523
515
- Assert::Equal(0ull, pPlan->qwCacheSizeTotal);
524
+ Assert::Equal(185118ull, pPlan->qwCacheSizeTotal);
525
526
fRollback = FALSE;
527
dwIndex = 0;
@@ -536,6 +545,9 @@ namespace Bootstrapper
545
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
546
ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
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");
551
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
552
ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{E6469F05-BDC8-4EB8-B218-67412543EFAA}", unregisterActions1, 1);
553
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -565,6 +577,8 @@ namespace Bootstrapper
577
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
578
ValidateExecuteRollbackBoundaryEnd(pPlan, fRollback, dwIndex++);
579
ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
580
+ dwExecuteCheckpointId += 1; // cache checkpoints
581
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
582
ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{E6469F05-BDC8-4EB8-B218-67412543EFAA}", registerActions1, 1);
583
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
584
ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", registerActions1, 1);
@@ -577,7 +591,7 @@ namespace Bootstrapper
591
Assert::Equal(dwIndex, pPlan->cRollbackActions);
592
593
Assert::Equal(3ul, pPlan->cExecutePackagesTotal);
580
- Assert::Equal(3ul, pPlan->cOverallProgressTicksTotal);
594
+ Assert::Equal(4ul, pPlan->cOverallProgressTicksTotal);
595
596
dwIndex = 0;
597
Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions);
@@ -640,11 +654,11 @@ namespace Bootstrapper
654
fRollback = FALSE;
655
dwIndex = 0;
656
ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
643
- ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
644
- ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
657
+ ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_REQUIRED);
658
+ ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
659
ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 6);
646
- ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageB");
647
- ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
660
+ ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageB", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_REQUIRED);
661
+ ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageB");
662
Assert::Equal(dwIndex, pPlan->cCacheActions);
663
664
fRollback = TRUE;
@@ -753,8 +767,8 @@ namespace Bootstrapper
767
fRollback = FALSE;
768
dwIndex = 0;
769
ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 2);
756
- ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageB");
757
- ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
770
+ ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageB", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
771
+ ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageB");
772
Assert::Equal(dwIndex, pPlan->cCacheActions);
773
774
fRollback = TRUE;
@@ -949,8 +963,8 @@ namespace Bootstrapper
963
fRollback = FALSE;
964
dwIndex = 0;
965
ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
952
- ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
953
- ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
966
+ ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
967
+ ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
968
Assert::Equal(dwIndex, pPlan->cCacheActions);
969
970
fRollback = TRUE;
@@ -1068,8 +1082,8 @@ namespace Bootstrapper
1082
fRollback = FALSE;
1083
dwIndex = 0;
1084
ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
1071
- ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
1072
- ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
1085
+ ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
1086
+ ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
1087
Assert::Equal(dwIndex, pPlan->cCacheActions);
1088
1089
fRollback = TRUE;
@@ -1170,8 +1184,8 @@ namespace Bootstrapper
1184
fRollback = FALSE;
1185
dwIndex = 0;
1186
ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
1173
- ValidateCachePackage(pPlan, fRollback, dwIndex++, L"ExeA");
1174
- ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
1187
+ ValidateCachePackage(pPlan, fRollback, dwIndex++, L"ExeA", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_REQUIRED);
1188
+ ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"ExeA");
1189
Assert::Equal(dwIndex, pPlan->cCacheActions);
1190
1191
fRollback = TRUE;
@@ -1264,8 +1278,8 @@ namespace Bootstrapper
1278
fRollback = FALSE;
1279
dwIndex = 0;
1280
ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
1267
- ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
1268
- ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
1281
+ ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
1282
+ ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
1283
Assert::Equal(dwIndex, pPlan->cCacheActions);
1284
1285
fRollback = TRUE;
@@ -1515,8 +1529,8 @@ namespace Bootstrapper
1529
fRollback = FALSE;
1530
dwIndex = 0;
1531
ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
1518
- ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
1519
- ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
1532
+ ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
1533
+ ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
1534
Assert::Equal(dwIndex, pPlan->cCacheActions);
1535
1536
fRollback = TRUE;
@@ -1610,8 +1624,8 @@ namespace Bootstrapper
1624
fRollback = FALSE;
1625
dwIndex = 0;
1626
ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
1613
- ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
1614
- ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
1627
+ ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
1628
+ ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
1629
Assert::Equal(dwIndex, pPlan->cCacheActions);
1630
1631
fRollback = TRUE;
@@ -1794,19 +1808,24 @@ namespace Bootstrapper
1808
1809
fRollback = FALSE;
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");
1814
Assert::Equal(dwIndex, pPlan->cCacheActions);
1815
1816
fRollback = TRUE;
1817
dwIndex = 0;
1818
Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
1819
1803
- Assert::Equal(0ull, pPlan->qwCacheSizeTotal);
1820
+ Assert::Equal(175674ull, pPlan->qwCacheSizeTotal);
1821
1822
fRollback = FALSE;
1823
dwIndex = 0;
1807
- DWORD dwExecuteCheckpointId = 1;
1824
+ DWORD dwExecuteCheckpointId = 2;
1825
ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
1826
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
1827
+ ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
1828
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
1829
ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", unregisterActions1, 1);
1830
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
1831
ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", unregisterActions1, 1);
@@ -1819,8 +1838,9 @@ namespace Bootstrapper
1838
1839
fRollback = TRUE;
1840
dwIndex = 0;
1822
- dwExecuteCheckpointId = 1;
1841
+ dwExecuteCheckpointId = 2;
1842
ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
1843
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
1844
ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", registerActions1, 1);
1845
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
1846
ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", registerActions1, 1);
@@ -1833,7 +1853,7 @@ namespace Bootstrapper
1853
Assert::Equal(dwIndex, pPlan->cRollbackActions);
1854
1855
Assert::Equal(1ul, pPlan->cExecutePackagesTotal);
1836
- Assert::Equal(1ul, pPlan->cOverallProgressTicksTotal);
1856
+ Assert::Equal(2ul, pPlan->cOverallProgressTicksTotal);
1857
1858
dwIndex = 0;
1859
Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions);
@@ -2043,19 +2063,24 @@ namespace Bootstrapper
2063
2064
fRollback = FALSE;
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");
2069
Assert::Equal(dwIndex, pPlan->cCacheActions);
2070
2071
fRollback = TRUE;
2072
dwIndex = 0;
2073
Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
2074
2052
- Assert::Equal(0ull, pPlan->qwCacheSizeTotal);
2075
+ Assert::Equal(175674ull, pPlan->qwCacheSizeTotal);
2076
2077
fRollback = FALSE;
2078
dwIndex = 0;
2056
- DWORD dwExecuteCheckpointId = 1;
2079
+ DWORD dwExecuteCheckpointId = 2;
2080
ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
2081
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2082
+ ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
2083
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2084
ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", unregisterActions1, 1);
2085
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2086
ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", unregisterActions1, 1);
@@ -2068,8 +2093,9 @@ namespace Bootstrapper
2093
2094
fRollback = TRUE;
2095
dwIndex = 0;
2071
- dwExecuteCheckpointId = 1;
2096
+ dwExecuteCheckpointId = 2;
2097
ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
2098
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2099
ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{A6F0CBF7-1578-450C-B9D7-9CF2EEC40002}", registerActions1, 1);
2100
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2101
ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", registerActions1, 1);
@@ -2082,7 +2108,7 @@ namespace Bootstrapper
2108
Assert::Equal(dwIndex, pPlan->cRollbackActions);
2109
2110
Assert::Equal(1ul, pPlan->cExecutePackagesTotal);
2085
- Assert::Equal(1ul, pPlan->cOverallProgressTicksTotal);
2111
+ Assert::Equal(2ul, pPlan->cOverallProgressTicksTotal);
2112
2113
dwIndex = 0;
2114
Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions);
@@ -2139,8 +2165,8 @@ namespace Bootstrapper
2165
fRollback = FALSE;
2166
dwIndex = 0;
2167
ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
2142
- ValidateCachePackage(pPlan, fRollback, dwIndex++, L"test.msu");
2143
- ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
2168
+ ValidateCachePackage(pPlan, fRollback, dwIndex++, L"test.msu", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
2169
+ ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"test.msu");
2170
Assert::Equal(dwIndex, pPlan->cCacheActions);
2171
2172
fRollback = TRUE;
@@ -2233,14 +2259,14 @@ namespace Bootstrapper
2259
fRollback = FALSE;
2260
dwIndex = 0;
2261
ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
2236
- ValidateCachePackage(pPlan, fRollback, dwIndex++, L"NetFx48Web");
2237
- ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
2262
+ ValidateCachePackage(pPlan, fRollback, dwIndex++, L"NetFx48Web", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
2263
+ ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"NetFx48Web");
2264
ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 3);
2239
- ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PatchA");
2240
- ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
2265
+ ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PatchA", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
2266
+ ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PatchA");
2267
ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 5);
2242
- ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
2243
- ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
2268
+ ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
2269
+ ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
2270
Assert::Equal(dwIndex, pPlan->cCacheActions);
2271
2272
fRollback = TRUE;
@@ -2363,26 +2389,37 @@ namespace Bootstrapper
2389
2390
fRollback = FALSE;
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");
2398
Assert::Equal(dwIndex, pPlan->cCacheActions);
2399
2400
fRollback = TRUE;
2401
dwIndex = 0;
2402
Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
2403
2372
- Assert::Equal(0ull, pPlan->qwCacheSizeTotal);
2404
+ Assert::Equal(212992ull, pPlan->qwCacheSizeTotal);
2405
2406
fRollback = FALSE;
2407
dwIndex = 0;
2376
- DWORD dwExecuteCheckpointId = 1;
2408
+ DWORD dwExecuteCheckpointId = 2;
2409
BURN_EXECUTE_ACTION* pExecuteAction = NULL;
2410
ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
2411
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2412
+ ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PatchA");
2413
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2414
ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PatchA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", unregisterActions1, 1);
2415
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2416
ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PatchA", unregisterActions1, 1);
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);
2418
ValidateExecuteMspTargetPatch(pExecuteAction, 0, L"PatchA");
2419
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2420
+ dwExecuteCheckpointId += 1; // cache checkpoints
2421
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2422
+ ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
2423
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2424
ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", unregisterActions1, 1);
2425
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
@@ -2396,8 +2433,9 @@ namespace Bootstrapper
2433
2434
fRollback = TRUE;
2435
dwIndex = 0;
2399
- dwExecuteCheckpointId = 1;
2436
+ dwExecuteCheckpointId = 2;
2437
ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
2438
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2439
ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PatchA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", registerActions1, 1);
2440
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2441
ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PatchA", registerActions1, 1);
@@ -2405,6 +2443,8 @@ namespace Bootstrapper
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);
2444
ValidateExecuteMspTargetPatch(pExecuteAction, 0, L"PatchA");
2445
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2446
+ dwExecuteCheckpointId += 1; // cache checkpoints
2447
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2448
ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", registerActions1, 1);
2449
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2450
ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", registerActions1, 1);
@@ -2417,7 +2457,7 @@ namespace Bootstrapper
2457
Assert::Equal(dwIndex, pPlan->cRollbackActions);
2458
2459
Assert::Equal(2ul, pPlan->cExecutePackagesTotal);
2420
- Assert::Equal(2ul, pPlan->cOverallProgressTicksTotal);
2460
+ Assert::Equal(4ul, pPlan->cOverallProgressTicksTotal);
2461
2462
dwIndex = 0;
2463
Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions);
@@ -2479,19 +2519,24 @@ namespace Bootstrapper
2519
2520
fRollback = FALSE;
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");
2525
Assert::Equal(dwIndex, pPlan->cCacheActions);
2526
2527
fRollback = TRUE;
2528
dwIndex = 0;
2529
Assert::Equal(dwIndex, pPlan->cRollbackCacheActions);
2530
2488
- Assert::Equal(0ull, pPlan->qwCacheSizeTotal);
2531
+ Assert::Equal(131072ull, pPlan->qwCacheSizeTotal);
2532
2533
fRollback = FALSE;
2534
dwIndex = 0;
2492
- DWORD dwExecuteCheckpointId = 1;
2535
+ DWORD dwExecuteCheckpointId = 2;
2536
ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
2537
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2538
+ ValidateExecuteWaitCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
2539
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2540
ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", unregisterActions1, 1);
2541
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2542
ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", unregisterActions1, 1);
@@ -2504,8 +2549,9 @@ namespace Bootstrapper
2549
2550
fRollback = TRUE;
2551
dwIndex = 0;
2507
- dwExecuteCheckpointId = 1;
2552
+ dwExecuteCheckpointId = 2;
2553
ValidateExecuteRollbackBoundaryStart(pPlan, fRollback, dwIndex++, L"WixDefaultBoundary", TRUE, FALSE);
2554
+ ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2555
ValidateExecutePackageDependency(pPlan, fRollback, dwIndex++, L"PackageA", L"{22D1DDBA-284D-40A7-BD14-95EA07906F21}", registerActions1, 1);
2556
ValidateExecuteCheckpoint(pPlan, fRollback, dwIndex++, dwExecuteCheckpointId++);
2557
ValidateExecutePackageProvider(pPlan, fRollback, dwIndex++, L"PackageA", registerActions1, 1);
@@ -2518,7 +2564,7 @@ namespace Bootstrapper
2564
Assert::Equal(dwIndex, pPlan->cRollbackActions);
2565
2566
Assert::Equal(1ul, pPlan->cExecutePackagesTotal);
2521
- Assert::Equal(1ul, pPlan->cOverallProgressTicksTotal);
2567
+ Assert::Equal(2ul, pPlan->cOverallProgressTicksTotal);
2568
2569
dwIndex = 0;
2570
Assert::Equal(dwIndex, pPlan->cRestoreRelatedBundleActions);
@@ -2575,11 +2621,11 @@ namespace Bootstrapper
2621
fRollback = FALSE;
2622
dwIndex = 0;
2623
ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 1);
2578
- ValidateCachePackage(pPlan, fRollback, dwIndex++, L"NetFx48Web");
2579
- ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
2624
+ ValidateCachePackage(pPlan, fRollback, dwIndex++, L"NetFx48Web", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
2625
+ ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"NetFx48Web");
2626
ValidateCacheCheckpoint(pPlan, fRollback, dwIndex++, 4);
2581
- ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA");
2582
- ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++);
2627
+ ValidateCachePackage(pPlan, fRollback, dwIndex++, L"PackageA", TRUE, BURN_CACHE_PACKAGE_TYPE_REQUIRED, BURN_CACHE_PACKAGE_TYPE_NONE);
2628
+ ValidateCacheSignalSyncpoint(pPlan, fRollback, dwIndex++, L"PackageA");
2629
Assert::Equal(dwIndex, pPlan->cCacheActions);
2630
2631
fRollback = TRUE;
@@ -3008,12 +3054,18 @@ namespace Bootstrapper
3054
__in BURN_PLAN* pPlan,
3055
__in BOOL fRollback,
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
3061
)
3062
{
3063
BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
3064
Assert::Equal<DWORD>(BURN_CACHE_ACTION_TYPE_PACKAGE, pAction->type);
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);
3069
return dwIndex + 1;
3070
}
3071
@@ -3032,12 +3084,13 @@ namespace Bootstrapper
3084
void ValidateCacheSignalSyncpoint(
3085
__in BURN_PLAN* pPlan,
3086
__in BOOL fRollback,
3035
- __in DWORD dwIndex
3087
+ __in DWORD dwIndex,
3088
+ __in LPCWSTR wzPackageId
3089
)
3090
{
3091
BURN_CACHE_ACTION* pAction = ValidateCacheActionExists(pPlan, fRollback, dwIndex);
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);
3094
}
3095
3096
void ValidateCleanAction(
src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
+13
-1
@@ -655,6 +655,7 @@ public: // IBootstrapperApplication
655
__in_z LPCWSTR wzPackageId,
656
__in DWORD cCachePayloads,
657
__in DWORD64 dw64PackageCacheSize,
658
+ __in BOOL fVital,
659
__inout BOOL* pfCancel
660
)
661
{
@@ -673,7 +674,7 @@ public: // IBootstrapperApplication
674
}
675
}
676
676
- return __super::OnCachePackageBegin(wzPackageId, cCachePayloads, dw64PackageCacheSize, pfCancel);
677
+ return __super::OnCachePackageBegin(wzPackageId, cCachePayloads, dw64PackageCacheSize, fVital, pfCancel);
678
}
679
680
@@ -1488,6 +1489,9 @@ public: // IBootstrapperApplication
1489
case BOOTSTRAPPER_APPLICATION_MESSAGE_ONDETECTRELATEDBUNDLEPACKAGE:
1490
OnDetectRelatedBundlePackageFallback(reinterpret_cast<BA_ONDETECTRELATEDBUNDLEPACKAGE_ARGS*>(pvArgs), reinterpret_cast<BA_ONDETECTRELATEDBUNDLEPACKAGE_RESULTS*>(pvResults));
1491
break;
1492
+ case BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPACKAGENONVITALVALIDATIONFAILURE:
1493
+ OnCachePackageNonVitalValidationFailureFallback(reinterpret_cast<BA_ONCACHEPACKAGENONVITALVALIDATIONFAILURE_ARGS*>(pvArgs), reinterpret_cast<BA_ONCACHEPACKAGENONVITALVALIDATIONFAILURE_RESULTS*>(pvResults));
1494
+ break;
1495
default:
1496
#ifdef DEBUG
1497
BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: Forwarding unknown BA message: %d", message);
@@ -2177,6 +2181,14 @@ private: // privates
2181
m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONDETECTRELATEDBUNDLEPACKAGE, pArgs, pResults, m_pvBAFunctionsProcContext);
2182
}
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
+
2192
2193
public: //CBalBaseBootstrapperApplication
2194
virtual STDMETHODIMP Initialize(
src/test/burn/TestBA/TestBA.cs
+31
-1
@@ -27,6 +27,7 @@ namespace WixToolset.Test.BA
27
28
private string updateBundlePath;
29
30
+ private bool allowAcquireAfterValidationFailure;
31
private bool forceKeepRegistration;
32
private bool immediatelyQuit;
33
private bool quitAfterDetect;
@@ -85,7 +86,11 @@ namespace WixToolset.Test.BA
86
87
List<string> verifyArguments = this.ReadVerifyArguments();
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)
94
{
95
// If we're not in the update already, process the updatebundle.
96
if (this.Command.Relation != RelationType.Update && arg.StartsWith("-updatebundle:", StringComparison.OrdinalIgnoreCase))
@@ -126,6 +131,12 @@ namespace WixToolset.Test.BA
131
redetectCount = 0;
132
}
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
+
140
string explicitlyElevateAndPlanFromOnElevateBegin = this.ReadPackageAction(null, "ExplicitlyElevateAndPlanFromOnElevateBegin");
141
if (String.IsNullOrEmpty(explicitlyElevateAndPlanFromOnElevateBegin) || !Boolean.TryParse(explicitlyElevateAndPlanFromOnElevateBegin, out this.explicitlyElevateAndPlanFromOnElevateBegin))
142
{
@@ -277,6 +288,15 @@ namespace WixToolset.Test.BA
288
{
289
args.State = state;
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);
300
}
301
302
protected override void OnPlanPatchTarget(PlanPatchTargetEventArgs args)
@@ -337,6 +357,16 @@ namespace WixToolset.Test.BA
357
}
358
}
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
+
370
protected override void OnCacheAcquireProgress(CacheAcquireProgressEventArgs args)
371
{
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);
src/test/burn/TestData/ExePackageTests/PackageTestExe/PackageTestExe.wixproj
new
+16
@@ -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
src/test/burn/TestData/ExePackageTests/PackageTestExe/ProductComponents.wxs
new
+12
@@ -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>
src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackageUninstallFailure/PerMachineArpEntryExePackageUninstallFailure.wixproj
new
+18
@@ -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
src/test/burn/TestData/ExePackageTests/PerMachineArpEntryExePackageUninstallFailure/PerMachineArpEntryExePackageUninstallFailure.wxs
new
+24
@@ -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 "$(var.ArpKeyPath),DisplayVersion,String,$(var.ArpVersion)" /regw "$(var.ArpKeyPath),QuietUninstallString,String,\"$(var.TestExePath)\" /regd \"$(var.ArpKeyPath)\""">
18
+ <ArpEntry Id="$(var.ArpId)" Version="$(var.ArpVersion)" Win64="no" />
19
+
20
+ <PayloadGroupRef Id="TestExePayloads" />
21
+ </ExePackage>
22
+ </PackageGroup>
23
+ </Fragment>
24
+</Wix>
src/test/burn/TestData/TestBA/TestBAWixlib/TestExe.wxs
+7
@@ -6,4 +6,11 @@
6
<Payload SourceFile="!(bindpath.net2x86)\TestExe.exe.config" />
7
</PayloadGroup>
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>
16
</Wix>
src/test/burn/WixToolsetTest.BurnE2E/ExePackageTests.cs
+105
-12
@@ -3,6 +3,7 @@
3
namespace WixToolsetTest.BurnE2E
4
{
5
using WixTestTools;
6
+ using WixToolset.Mba.Core;
7
using Xunit;
8
using Xunit.Abstractions;
9
@@ -13,9 +14,9 @@ namespace WixToolsetTest.BurnE2E
14
[RuntimeFact]
15
public void CanInstallAndUninstallPerMachineArpEntryExePackage()
16
{
16
- const string arpId = "{4D9EC36A-1E63-4244-875C-3ECB0A2CAE30}";
17
var perMachineArpEntryExePackageBundle = this.CreateBundleInstaller(@"PerMachineArpEntryExePackage");
18
var arpEntryExePackage = this.CreateArpEntryInstaller(perMachineArpEntryExePackageBundle, "TestExe");
19
+ var arpId = arpEntryExePackage.ArpId;
20
21
arpEntryExePackage.VerifyRegistered(false);
22
@@ -23,21 +24,113 @@ namespace WixToolsetTest.BurnE2E
24
perMachineArpEntryExePackageBundle.VerifyRegisteredAndInPackageCache();
25
arpEntryExePackage.VerifyRegistered(true);
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,\\\""));
28
29
var uninstallLogPath = perMachineArpEntryExePackageBundle.Uninstall();
30
perMachineArpEntryExePackageBundle.VerifyUnregisteredAndRemovedFromPackageCache();
31
arpEntryExePackage.VerifyRegistered(false);
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}"));
34
}
35
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()
130
{
38
- const string arpId = "{80E90929-EEA5-48A7-A680-A0237A1CAD84}";
131
var perMachineArpEntryExePackageFailureBundle = this.CreateBundleInstaller(@"PerMachineArpEntryExePackageFailure");
132
var arpEntryExePackage = this.CreateArpEntryInstaller(perMachineArpEntryExePackageFailureBundle, "TestExe");
133
+ var arpId = arpEntryExePackage.ArpId;
134
135
arpEntryExePackage.VerifyRegistered(false);
136
@@ -45,16 +138,16 @@ namespace WixToolsetTest.BurnE2E
138
perMachineArpEntryExePackageFailureBundle.VerifyUnregisteredAndRemovedFromPackageCache();
139
arpEntryExePackage.VerifyRegistered(false);
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,\\\"");
49
- LogVerifier.MessageInLogFile(installLogPath, $"testexe.exe\" /regd HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}");
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,\\\""));
142
+ Assert.True(LogVerifier.MessageInLogFile(installLogPath, $"testexe.exe\" /regd HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{arpId}"));
143
}
144
145
[RuntimeFact]
146
public void CanInstallAndUninstallPerUserArpEntryExePackage()
147
{
55
- const string arpId = "{9B5300C7-9B34-4670-9614-185B02AB87EF}";
148
var perUserArpEntryExePackageBundle = this.CreateBundleInstaller(@"PerUserArpEntryExePackage");
149
var arpEntryExePackage = this.CreateArpEntryInstaller(perUserArpEntryExePackageBundle, "TestExe");
150
+ var arpId = arpEntryExePackage.ArpId;
151
152
arpEntryExePackage.VerifyRegistered(false);
153
@@ -62,21 +155,21 @@ namespace WixToolsetTest.BurnE2E
155
perUserArpEntryExePackageBundle.VerifyRegisteredAndInPackageCache();
156
arpEntryExePackage.VerifyRegistered(true);
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,\\\""));
159
160
var uninstallLogPath = perUserArpEntryExePackageBundle.Uninstall();
161
perUserArpEntryExePackageBundle.VerifyUnregisteredAndRemovedFromPackageCache();
162
arpEntryExePackage.VerifyRegistered(false);
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}"));
165
}
166
167
[RuntimeFact]
168
public void FailsUninstallWhenPerUserArpEntryExePackageMissingQuietUninstallString()
169
{
77
- const string arpId = "{DE9F8594-5856-4454-AB10-3C01ED246D7D}";
170
var brokenPerUserArpEntryExePackageBundle = this.CreateBundleInstaller(@"BrokenPerUserArpEntryExePackage");
171
var arpEntryExePackage = this.CreateArpEntryInstaller(brokenPerUserArpEntryExePackageBundle, "TestExe");
172
+ var arpId = arpEntryExePackage.ArpId;
173
174
arpEntryExePackage.VerifyRegistered(false);
175
brokenPerUserArpEntryExePackageBundle.VerifyUnregisteredAndRemovedFromPackageCache();
@@ -85,7 +178,7 @@ namespace WixToolsetTest.BurnE2E
178
brokenPerUserArpEntryExePackageBundle.VerifyRegisteredAndInPackageCache();
179
arpEntryExePackage.VerifyRegistered(true);
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\""));
182
183
brokenPerUserArpEntryExePackageBundle.Uninstall((int)MSIExec.MSIExecReturnCode.ERROR_INVALID_PARAMETER);
184
brokenPerUserArpEntryExePackageBundle.VerifyRegisteredAndInPackageCache();
src/test/burn/WixToolsetTest.BurnE2E/Utilities/TestBAController.cs
+15
@@ -42,6 +42,11 @@ namespace WixToolsetTest.BurnE2E
42
}
43
}
44
45
+ public void SetAllowAcquireAfterValidationFailure(string value = "true")
46
+ {
47
+ this.SetBurnTestValue("AllowAcquireAfterValidationFailure", value);
48
+ }
49
+
50
public void SetExplicitlyElevateAndPlanFromOnElevateBegin(string value = "true")
51
{
52
this.SetBurnTestValue("ExplicitlyElevateAndPlanFromOnElevateBegin", value);
@@ -132,6 +137,16 @@ namespace WixToolsetTest.BurnE2E
137
this.SetPackageState(packageId, "RetryExecuteFilesInUse", retryCount.HasValue ? retryCount.ToString() : null);
138
}
139
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>
151
/// Sets the requested state for a package that the TestBA will return to the engine during plan.
152
/// </summary>