Skip to content

Commit

Permalink
Separate MsiTransaction from RollbackBoundary- a rollback boundary ma…
Browse files Browse the repository at this point in the history
…y contain several transactions
  • Loading branch information
nirbar committed Apr 18, 2024
1 parent a4f9456 commit 15b1d34
Show file tree
Hide file tree
Showing 71 changed files with 1,721 additions and 507 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ This repository contains the PanelSwWix4: A custom WiX Toolset codebase

# Customizations:

- [Harvest AdditionalOptions](https://github.com/wixtoolset/issues/issues/7427): Allow customized AdditionalOptions for all HarvestX MSBuild ItemGroups
- [Fix MultiSzInsertString](https://github.com/wixtoolset/issues/issues/7311) to create a double-null terminated buffer
- [6298](https://github.com/wixtoolset/issues/issues/6298): Extract detached containers with "wix burn extract"
- ExePackage/@DetectVersionVariable: Support using one of the XxxSearch elements to provide a version number in a variable to test against the package's version.
- [4889](https://github.com/wixtoolset/issues/issues/4889): Support custom container compressions using bundle extensions
- Un-plan MSI transaction if it contains less than 2 packages
- Add BA methods OnPlanMsiTransaction, OnPlanMsiTransactionComplete: Let BA opt-out of MSI transactions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,10 @@ public abstract class BootstrapperApplication : MarshalByRefObject, IDefaultBoot
public event EventHandler<PlanRelatedBundleTypeEventArgs> PlanRelatedBundleType;

/// <inheritdoc/>
public event EventHandler<PlanRollbackBoundaryEventArgs> PlanRollbackBoundary;
public event EventHandler<PlanMsiTransactionEventArgs> PlanMsiTransaction;

/// <inheritdoc/>
public event EventHandler<PlanMsiTransactionCompleteEventArgs> PlanMsiTransactionComplete;

/// <inheritdoc/>
public event EventHandler<PlanPackageBeginEventArgs> PlanPackageBegin;
Expand Down Expand Up @@ -561,11 +564,25 @@ protected virtual void OnPlanRelatedBundleType(PlanRelatedBundleTypeEventArgs ar
}

/// <summary>
/// Called by the engine, raises the <see cref="PlanRollbackBoundary"/> event.
/// Called by the engine, raises the <see cref="PlanMsiTransaction"/> event.
/// Before <see cref="OnPlanMsiPackage(PlanMsiPackageEventArgs)"/> of the first package in the transaction.
/// </summary>
protected virtual void OnPlanRollbackBoundary(PlanRollbackBoundaryEventArgs args)
protected virtual void OnPlanMsiTransaction(PlanMsiTransactionEventArgs args)
{
EventHandler<PlanRollbackBoundaryEventArgs> handler = this.PlanRollbackBoundary;
EventHandler<PlanMsiTransactionEventArgs> handler = this.PlanMsiTransaction;
if (null != handler)
{
handler(this, args);
}
}

/// <summary>
/// Called by the engine, raises the <see cref="PlanMsiTransactionComplete"/> event.
/// After <see cref="OnPlanMsiPackage(PlanMsiPackageEventArgs)"/> of the last package in the transaction.
/// </summary>
protected virtual void OnPlanMsiTransactionComplete(PlanMsiTransactionCompleteEventArgs args)
{
EventHandler<PlanMsiTransactionCompleteEventArgs> handler = this.PlanMsiTransactionComplete;
if (null != handler)
{
handler(this, args);
Expand Down Expand Up @@ -1586,16 +1603,25 @@ int IBootstrapperApplication.OnPlanRelatedBundleType(string wzBundleId, RelatedB
return args.HResult;
}

int IBootstrapperApplication.OnPlanRollbackBoundary(string wzRollbackBoundaryId, bool fRecommendedTransaction, ref bool fTransaction, ref bool fCancel)
int IBootstrapperApplication.OnPlanMsiTransaction(string wzTransactionId, ref bool fTransaction, ref bool fCancel)
{
PlanRollbackBoundaryEventArgs args = new PlanRollbackBoundaryEventArgs(wzRollbackBoundaryId, fRecommendedTransaction, fTransaction, fCancel);
this.OnPlanRollbackBoundary(args);
PlanMsiTransactionEventArgs args = new PlanMsiTransactionEventArgs(wzTransactionId, fTransaction, fCancel);
this.OnPlanMsiTransaction(args);

fTransaction = args.Transaction;
fCancel = args.Cancel;
return args.HResult;
}

int IBootstrapperApplication.OnPlanMsiTransactionComplete(string wzTransactionId, uint dwPackagesInTransaction, bool fPlanned, ref bool fCancel)
{
PlanMsiTransactionCompleteEventArgs args = new PlanMsiTransactionCompleteEventArgs(wzTransactionId, dwPackagesInTransaction, fPlanned, fCancel);
this.OnPlanMsiTransactionComplete(args);

fCancel = args.Cancel;
return args.HResult;
}

int IBootstrapperApplication.OnPlanPackageBegin(string wzPackageId, PackageState state, bool fCached, BOOTSTRAPPER_PACKAGE_CONDITION_RESULT installCondition, BOOTSTRAPPER_PACKAGE_CONDITION_RESULT repairCondition, RequestState recommendedState, BOOTSTRAPPER_CACHE_TYPE recommendedCacheType, ref RequestState pRequestedState, ref BOOTSTRAPPER_CACHE_TYPE pRequestedCacheType, ref bool fCancel)
{
PlanPackageBeginEventArgs args = new PlanPackageBeginEventArgs(wzPackageId, state, fCached, installCondition, repairCondition, recommendedState, recommendedCacheType, pRequestedState, pRequestedCacheType, fCancel);
Expand Down
53 changes: 40 additions & 13 deletions src/api/burn/WixToolset.BootstrapperApplicationApi/EventArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1016,39 +1016,66 @@ public PlanCompatibleMsiPackageCompleteEventArgs(string packageId, string compat
}

/// <summary>
/// Event arguments for <see cref="IDefaultBootstrapperApplication.PlanRollbackBoundary"/>
/// Event arguments for <see cref="IDefaultBootstrapperApplication.PlanMsiTransaction"/>
/// </summary>
[Serializable]
public class PlanRollbackBoundaryEventArgs : CancellableHResultEventArgs
public class PlanMsiTransactionEventArgs : CancellableHResultEventArgs
{
/// <summary>
/// This class is for events raised by the engine.
/// It is not intended to be instantiated by user code.
/// </summary>
public PlanRollbackBoundaryEventArgs(string rollbackBoundaryId, bool recommendedTransaction, bool transaction, bool cancelRecommendation)
public PlanMsiTransactionEventArgs(string transactionId, bool transaction, bool cancelRecommendation)
: base(cancelRecommendation)
{
this.RollbackBoundaryId = rollbackBoundaryId;
this.RecommendedTransaction = recommendedTransaction;
this.TransactionId = transactionId;
this.Transaction = transaction;
}

/// <summary>
/// Gets the identity of the rollback boundary to plan for.
/// Gets the identity of the MSI transaction to plan for.
/// </summary>
public string RollbackBoundaryId { get; private set; }
public string TransactionId { get; private set; }

/// <summary>
/// Whether or not the rollback boundary was authored to use an MSI transaction.
/// Whether or not an MSI transaction will be used.
/// Setting the value to false will cause the packages to be executed without a wrapping MSI transaction.
/// </summary>
public bool RecommendedTransaction { get; private set; }
public bool Transaction { get; set; }
}

/// <summary>
/// Event arguments for <see cref="IDefaultBootstrapperApplication.PlanMsiTransactionComplete"/>
/// </summary>
[Serializable]
public class PlanMsiTransactionCompleteEventArgs : CancellableHResultEventArgs
{
/// <summary>
/// Whether or not an MSI transaction will be used in the rollback boundary.
/// If <see cref="RecommendedTransaction"/> is false, setting the value to true has no effect.
/// If <see cref="RecommendedTransaction"/> is true, setting the value to false will cause the packages inside this rollback boundary to be executed without a wrapping MSI transaction.
/// This class is for events raised by the engine.
/// It is not intended to be instantiated by user code.
/// </summary>
public bool Transaction { get; set; }
public PlanMsiTransactionCompleteEventArgs(string transactionId, uint packagesInTransaction, bool planned, bool cancelRecommendation)
: base(cancelRecommendation)
{
this.TransactionId = transactionId;
this.PackagesInTransaction = packagesInTransaction;
this.Planned = planned;
}

/// <summary>
/// Gets the identity of the MSI transaction to plan for.
/// </summary>
public string TransactionId { get; private set; }

/// <summary>
/// The number of packages that were planned for this transaction.
/// </summary>
public uint PackagesInTransaction { get; private set; }

/// <summary>
/// Whether or not an MSI transaction will be used. The engine may decide to unplan a transaction if it contains one or zero packages.
/// </summary>
public bool Planned { get; private set; }
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,17 +250,28 @@ int OnPlanRelatedBundle(
);

/// <summary>
/// See <see cref="IDefaultBootstrapperApplication.PlanRollbackBoundary"/>.
/// See <see cref="IDefaultBootstrapperApplication.PlanMsiTransaction"/>.
/// </summary>
[PreserveSig]
[return: MarshalAs(UnmanagedType.I4)]
int OnPlanRollbackBoundary(
[MarshalAs(UnmanagedType.LPWStr)] string wzRollbackBoundaryId,
[MarshalAs(UnmanagedType.Bool)] bool fRecommendedTransaction,
int OnPlanMsiTransaction(
[MarshalAs(UnmanagedType.LPWStr)] string wzTransactionId,
[MarshalAs(UnmanagedType.Bool)] ref bool fTransaction,
[MarshalAs(UnmanagedType.Bool)] ref bool fCancel
);

/// <summary>
/// See <see cref="IDefaultBootstrapperApplication.PlanMsiTransactionComplete"/>.
/// </summary>
[PreserveSig]
[return: MarshalAs(UnmanagedType.I4)]
int OnPlanMsiTransactionComplete(
[MarshalAs(UnmanagedType.LPWStr)] string wzTransactionId,
[MarshalAs(UnmanagedType.U4)] uint dwPackagesInTransaction,
[MarshalAs(UnmanagedType.Bool)] bool fPlanned,
[MarshalAs(UnmanagedType.Bool)] ref bool fCancel
);

/// <summary>
/// See <see cref="IDefaultBootstrapperApplication.PlanPackageBegin"/>.
/// </summary>
Expand Down Expand Up @@ -1803,6 +1814,11 @@ public enum BOOTSTRAPPER_EXECUTEMSITRANSACTIONCOMPLETE_ACTION
/// The engine will launch again after the machine is restarted.
/// </summary>
Restart,

/// <summary>
/// Instructs the engine to retry ending the transaction.
/// </summary>
Retry,
};

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -374,9 +374,14 @@ public interface IDefaultBootstrapperApplication : IBootstrapperApplication
event EventHandler<PlanRestoreRelatedBundleEventArgs> PlanRestoreRelatedBundle;

/// <summary>
/// Fired when the engine is planning a rollback boundary.
/// Fired when the engine is planning a MSI transaction, before <see cref="PlanMsiPackage"/> of the first package in the transaction.
/// </summary>
event EventHandler<PlanRollbackBoundaryEventArgs> PlanRollbackBoundary;
event EventHandler<PlanMsiTransactionEventArgs> PlanMsiTransaction;

/// <summary>
/// Fired when the engine is planning a MSI transaction commit, after <see cref="PlanMsiPackage"/> of the last package in the transaction.
/// </summary>
event EventHandler<PlanMsiTransactionCompleteEventArgs> PlanMsiTransactionComplete;

/// <summary>
/// Fired when the engine has changed progress for the bundle installation.
Expand Down
2 changes: 1 addition & 1 deletion src/api/burn/balutil/balretry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ DAPI_(HRESULT) BalRetryEndContainerOrPayload(
if (FAILED(hrError) && vrgRetryInfo[type].cRetries < vdwMaxRetries && IsActiveRetryEntry(type, wzId))
{
// Retry on all errors except the following.
if (HRESULT_FROM_WIN32(ERROR_INSTALL_USEREXIT) != hrError &&
if (E_INSTALLUSEREXIT != hrError &&
BG_E_NETWORK_DISCONNECTED != hrError &&
HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hrError &&
HRESULT_FROM_WIN32(ERROR_INTERNET_NAME_NOT_RESOLVED) != hrError)
Expand Down
16 changes: 13 additions & 3 deletions src/api/burn/balutil/inc/BootstrapperApplicationBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,9 +286,8 @@ class CBootstrapperApplicationBase : public IBootstrapperApplication
return S_OK;
}

virtual STDMETHODIMP OnPlanRollbackBoundary(
__in_z LPCWSTR /*wzRollbackBoundaryId*/,
__in BOOL /*fRecommendedTransaction*/,
virtual STDMETHODIMP OnPlanMsiTransaction(
__in_z LPCWSTR /*wzTransactionId*/,
__inout BOOL* /*pfTransaction*/,
__inout BOOL* pfCancel
)
Expand All @@ -297,6 +296,17 @@ class CBootstrapperApplicationBase : public IBootstrapperApplication
return S_OK;
}

virtual STDMETHODIMP OnPlanMsiTransactionComplete(
__in_z LPCWSTR /*wzTransactionId*/,
__in DWORD /*dwPackagesInTransaction*/,
__in BOOL /*fPlanned*/,
__inout BOOL* pfCancel
)
{
*pfCancel |= CheckCanceled();
return S_OK;
}

virtual STDMETHODIMP OnPlanPackageBegin(
__in_z LPCWSTR /*wzPackageId*/,
__in BOOTSTRAPPER_PACKAGE_STATE /*state*/,
Expand Down
15 changes: 11 additions & 4 deletions src/api/burn/balutil/inc/IBootstrapperApplication.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,21 @@ DECLARE_INTERFACE_IID_(IBootstrapperApplication, IUnknown, "53C31D56-49C0-426B-A
__inout BOOL* pfCancel
) = 0;

// OnPlanRollbackBoundary - called when the engine is planning a rollback boundary.
STDMETHOD(OnPlanRollbackBoundary)(
__in_z LPCWSTR wzRollbackBoundaryId,
__in BOOL fRecommendedTransaction,
// OnPlanMsiTransaction - called when the engine is planning a MSI transaction.
STDMETHOD(OnPlanMsiTransaction)(
__in_z LPCWSTR wzTransactionId,
__inout BOOL* pfTransaction,
__inout BOOL* pfCancel
) = 0;

// OnPlanMsiTransactionComplete - called when the engine has finished planning a MSI transaction.
STDMETHOD(OnPlanMsiTransactionComplete)(
__in_z LPCWSTR wzTransactionId,
__in DWORD dwPackagesInTransaction,
__in BOOL fPlanned,
__inout BOOL* pfCancel
) = 0;

// OnPlanPackageBegin - called when the engine has begun getting the BA's input
// for planning a package.
STDMETHOD(OnPlanPackageBegin)(
Expand Down
Loading

0 comments on commit 15b1d34

Please sign in to comment.