Add BA events for setting the update bundle.
Fixes #6410
Sean Hall committed
Dec 10, 2021 at 11:42 UTC
fc30db9fa3aa1d25a6ef078452864673caa67ec5
24 files changed
+535
-37
src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
+25
@@ -197,6 +197,8 @@ enum BOOTSTRAPPER_APPLICATION_MESSAGE
197
BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPAYLOADEXTRACTCOMPLETE,
198
BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPAYLOADEXTRACTPROGRESS,
199
BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANROLLBACKBOUNDARY,
200
+ BOOTSTRAPPER_APPLICATION_MESSAGE_ONSETUPDATEBEGIN,
201
+ BOOTSTRAPPER_APPLICATION_MESSAGE_ONSETUPDATECOMPLETE,
202
};
203
204
enum BOOTSTRAPPER_APPLYCOMPLETE_ACTION
@@ -1228,6 +1230,29 @@ struct BA_ONROLLBACKMSITRANSACTIONCOMPLETE_RESULTS
1230
DWORD cbSize;
1231
};
1232
1233
+struct BA_ONSETUPDATEBEGIN_ARGS
1234
+{
1235
+ DWORD cbSize;
1236
+};
1237
+
1238
+struct BA_ONSETUPDATEBEGIN_RESULTS
1239
+{
1240
+ DWORD cbSize;
1241
+};
1242
+
1243
+struct BA_ONSETUPDATECOMPLETE_ARGS
1244
+{
1245
+ DWORD cbSize;
1246
+ HRESULT hrStatus;
1247
+ LPCWSTR wzPreviousPackageId;
1248
+ LPCWSTR wzNewPackageId;
1249
+};
1250
+
1251
+struct BA_ONSETUPDATECOMPLETE_RESULTS
1252
+{
1253
+ DWORD cbSize;
1254
+};
1255
+
1256
struct BA_ONSHUTDOWN_ARGS
1257
{
1258
DWORD cbSize;
src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs
+48
@@ -253,6 +253,12 @@ namespace WixToolset.Mba.Core
253
/// <inheritdoc/>
254
public event EventHandler<CachePayloadExtractCompleteEventArgs> CachePayloadExtractComplete;
255
256
+ /// <inheritdoc/>
257
+ public event EventHandler<SetUpdateBeginEventArgs> SetUpdateBegin;
258
+
259
+ /// <inheritdoc/>
260
+ public event EventHandler<SetUpdateCompleteEventArgs> SetUpdateComplete;
261
+
262
/// <summary>
263
/// Entry point that is called when the bootstrapper application is ready to run.
264
/// </summary>
@@ -1225,6 +1231,32 @@ namespace WixToolset.Mba.Core
1231
}
1232
}
1233
1234
+ /// <summary>
1235
+ /// Called by the engine, raises the <see cref="SetUpdateBegin"/> event.
1236
+ /// </summary>
1237
+ /// <param name="args"></param>
1238
+ protected virtual void OnSetUpdateBegin(SetUpdateBeginEventArgs args)
1239
+ {
1240
+ EventHandler<SetUpdateBeginEventArgs> handler = this.SetUpdateBegin;
1241
+ if (null != handler)
1242
+ {
1243
+ handler(this, args);
1244
+ }
1245
+ }
1246
+
1247
+ /// <summary>
1248
+ /// Called by the engine, raises the <see cref="SetUpdateComplete"/> event.
1249
+ /// </summary>
1250
+ /// <param name="args"></param>
1251
+ protected virtual void OnSetUpdateComplete(SetUpdateCompleteEventArgs args)
1252
+ {
1253
+ EventHandler<SetUpdateCompleteEventArgs> handler = this.SetUpdateComplete;
1254
+ if (null != handler)
1255
+ {
1256
+ handler(this, args);
1257
+ }
1258
+ }
1259
+
1260
#region IBootstrapperApplication Members
1261
1262
int IBootstrapperApplication.BAProc(int message, IntPtr pvArgs, IntPtr pvResults, IntPtr pvContext)
@@ -1895,6 +1927,22 @@ namespace WixToolset.Mba.Core
1927
return args.HResult;
1928
}
1929
1930
+ int IBootstrapperApplication.OnSetUpdateBegin()
1931
+ {
1932
+ SetUpdateBeginEventArgs args = new SetUpdateBeginEventArgs();
1933
+ this.OnSetUpdateBegin(args);
1934
+
1935
+ return args.HResult;
1936
+ }
1937
+
1938
+ int IBootstrapperApplication.OnSetUpdateComplete(int hrStatus, string wzPreviousPackageId, string wzNewPackageId)
1939
+ {
1940
+ SetUpdateCompleteEventArgs args = new SetUpdateCompleteEventArgs(hrStatus, wzPreviousPackageId, wzNewPackageId);
1941
+ this.OnSetUpdateComplete(args);
1942
+
1943
+ return args.HResult;
1944
+ }
1945
+
1946
#endregion
1947
}
1948
}
src/api/burn/WixToolset.Mba.Core/BundleInfo.cs
+8
@@ -41,6 +41,14 @@ namespace WixToolset.Mba.Core
41
return package;
42
}
43
44
+ /// <inheritdoc/>
45
+ public IPackageInfo AddUpdateBundleAsPackage(SetUpdateCompleteEventArgs e)
46
+ {
47
+ var package = PackageInfo.GetUpdateBundleAsPackage(e.NewPackageId);
48
+ this.Packages.Add(package.Id, package);
49
+ return package;
50
+ }
51
+
52
/// <summary>
53
/// Parses BA manifest from the given stream.
54
/// </summary>
src/api/burn/WixToolset.Mba.Core/EventArgs.cs
+37
@@ -2230,4 +2230,41 @@ namespace WixToolset.Mba.Core
2230
/// </summary>
2231
public string PayloadId { get; private set; }
2232
}
2233
+
2234
+ /// <summary>
2235
+ /// EventArgs for <see cref="IDefaultBootstrapperApplication.SetUpdateBegin"/>.
2236
+ /// </summary>
2237
+ [Serializable]
2238
+ public class SetUpdateBeginEventArgs : HResultEventArgs
2239
+ {
2240
+ /// <summary />
2241
+ public SetUpdateBeginEventArgs()
2242
+ {
2243
+ }
2244
+ }
2245
+
2246
+ /// <summary>
2247
+ /// Event arguments for <see cref="IDefaultBootstrapperApplication.SetUpdateComplete"/>
2248
+ /// </summary>
2249
+ [Serializable]
2250
+ public class SetUpdateCompleteEventArgs : StatusEventArgs
2251
+ {
2252
+ /// <summary />
2253
+ public SetUpdateCompleteEventArgs(int hrStatus, string previousPackageId, string newPackageId)
2254
+ : base(hrStatus)
2255
+ {
2256
+ this.PreviousPackageId = previousPackageId;
2257
+ this.NewPackageId = newPackageId;
2258
+ }
2259
+
2260
+ /// <summary>
2261
+ /// Gets the identifier of the update package that was removed.
2262
+ /// </summary>
2263
+ public string PreviousPackageId { get; private set; }
2264
+
2265
+ /// <summary>
2266
+ /// Gets the identifier of the update package that was added.
2267
+ /// </summary>
2268
+ public string NewPackageId { get; private set; }
2269
+ }
2270
}
src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs
+18
@@ -1097,6 +1097,24 @@ namespace WixToolset.Mba.Core
1097
[MarshalAs(UnmanagedType.LPWStr)] string wzPayloadId,
1098
int hrStatus
1099
);
1100
+
1101
+ /// <summary>
1102
+ /// See <see cref="IDefaultBootstrapperApplication.SetUpdateBegin"/>.
1103
+ /// </summary>
1104
+ [PreserveSig]
1105
+ [return: MarshalAs(UnmanagedType.I4)]
1106
+ int OnSetUpdateBegin();
1107
+
1108
+ /// <summary>
1109
+ /// See <see cref="IDefaultBootstrapperApplication.SetUpdateComplete"/>.
1110
+ /// </summary>
1111
+ [PreserveSig]
1112
+ [return: MarshalAs(UnmanagedType.I4)]
1113
+ int OnSetUpdateComplete(
1114
+ int hrStatus,
1115
+ [MarshalAs(UnmanagedType.LPWStr)] string wzPreviousPackageId,
1116
+ [MarshalAs(UnmanagedType.LPWStr)] string wzNewPackageId
1117
+ );
1118
}
1119
1120
/// <summary>
src/api/burn/WixToolset.Mba.Core/IBundleInfo.cs
+7
@@ -40,5 +40,12 @@ namespace WixToolset.Mba.Core
40
/// <param name="e"></param>
41
/// <returns>The created <see cref="IPackageInfo"/>.</returns>
42
IPackageInfo AddRelatedBundleAsPackage(DetectRelatedBundleEventArgs e);
43
+
44
+ /// <summary>
45
+ /// Adds an update bundle as a package.
46
+ /// </summary>
47
+ /// <param name="e"></param>
48
+ /// <returns>The created <see cref="IPackageInfo"/>.</returns>
49
+ IPackageInfo AddUpdateBundleAsPackage(SetUpdateCompleteEventArgs e);
50
}
51
}
\ No newline at end of file
src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs
+10
@@ -343,6 +343,16 @@ namespace WixToolset.Mba.Core
343
/// </summary>
344
event EventHandler<RollbackMsiTransactionCompleteEventArgs> RollbackMsiTransactionComplete;
345
346
+ /// <summary>
347
+ /// Fired when the engine has begun to setup the update package.
348
+ /// </summary>
349
+ event EventHandler<SetUpdateBeginEventArgs> SetUpdateBegin;
350
+
351
+ /// <summary>
352
+ /// Fired when the engine has completed setting up the update package.
353
+ /// </summary>
354
+ event EventHandler<SetUpdateCompleteEventArgs> SetUpdateComplete;
355
+
356
/// <summary>
357
/// Fired when the engine is shutting down the bootstrapper application.
358
/// </summary>
src/api/burn/WixToolset.Mba.Core/PackageInfo.cs
+19
@@ -51,6 +51,11 @@ namespace WixToolset.Mba.Core
51
///
52
/// </summary>
53
PatchBundle,
54
+
55
+ /// <summary>
56
+ ///
57
+ /// </summary>
58
+ UpdateBundle,
59
}
60
61
/// <summary>
@@ -269,6 +274,20 @@ namespace WixToolset.Mba.Core
274
return package;
275
}
276
277
+ /// <summary>
278
+ ///
279
+ /// </summary>
280
+ /// <param name="id"></param>
281
+ /// <returns></returns>
282
+ public static IPackageInfo GetUpdateBundleAsPackage(string id)
283
+ {
284
+ PackageInfo package = new PackageInfo();
285
+ package.Id = id;
286
+ package.Type = PackageType.UpdateBundle;
287
+
288
+ return package;
289
+ }
290
+
291
internal static void ParseBalPackageInfoFromXml(XPathNavigator root, XmlNamespaceManager namespaceManager, Dictionary<string, IPackageInfo> packagesById)
292
{
293
XPathNodeIterator nodes = root.Select("/p:BootstrapperApplicationData/p:WixBalPackageInfo", namespaceManager);
src/api/burn/balutil/balinfo.cpp
+42
-1
@@ -166,7 +166,7 @@ LExit:
166
167
DAPI_(HRESULT) BalInfoAddRelatedBundleAsPackage(
168
__in BAL_INFO_PACKAGES* pPackages,
169
- __in LPCWSTR wzId,
169
+ __in_z LPCWSTR wzId,
170
__in BOOTSTRAPPER_RELATION_TYPE relationType,
171
__in BOOL /*fPerMachine*/,
172
__out_opt BAL_INFO_PACKAGE** ppPackage
@@ -228,6 +228,47 @@ LExit:
228
}
229
230
231
+DAPI_(HRESULT) BalInfoAddUpdateBundleAsPackage(
232
+ __in BAL_INFO_PACKAGES* pPackages,
233
+ __in_z LPCWSTR wzId,
234
+ __in_z LPCWSTR /*wzPreviousId*/,
235
+ __out_opt BAL_INFO_PACKAGE** ppPackage
236
+ )
237
+{
238
+ HRESULT hr = S_OK;
239
+ BAL_INFO_PACKAGE* pPackage = NULL;
240
+
241
+ // Check to see if the bundle is already in the list of packages.
242
+ for (DWORD i = 0; i < pPackages->cPackages; ++i)
243
+ {
244
+ if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, wzId, -1, pPackages->rgPackages[i].sczId, -1))
245
+ {
246
+ ExitFunction1(hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS));
247
+ }
248
+ }
249
+
250
+ // Add the update bundle as a package.
251
+ hr = MemEnsureArraySize(reinterpret_cast<LPVOID*>(&pPackages->rgPackages), pPackages->cPackages + 1, sizeof(BAL_INFO_PACKAGE), 2);
252
+ ExitOnFailure(hr, "Failed to allocate memory for update bundle package information.");
253
+
254
+ pPackage = pPackages->rgPackages + pPackages->cPackages;
255
+ ++pPackages->cPackages;
256
+
257
+ hr = StrAllocString(&pPackage->sczId, wzId, 0);
258
+ ExitOnFailure(hr, "Failed to copy update bundle package id.");
259
+
260
+ pPackage->type = BAL_INFO_PACKAGE_TYPE_BUNDLE_UPDATE;
261
+
262
+ if (ppPackage)
263
+ {
264
+ *ppPackage = pPackage;
265
+ }
266
+
267
+LExit:
268
+ return hr;
269
+}
270
+
271
+
272
DAPI_(HRESULT) BalInfoFindPackageById(
273
__in BAL_INFO_PACKAGES* pPackages,
274
__in LPCWSTR wzId,
src/api/burn/balutil/inc/BAFunctions.h
+2
@@ -82,6 +82,8 @@ enum BA_FUNCTIONS_MESSAGE
82
BA_FUNCTIONS_MESSAGE_ONCACHEPAYLOADEXTRACTCOMPLETE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPAYLOADEXTRACTCOMPLETE,
83
BA_FUNCTIONS_MESSAGE_ONCACHEPAYLOADEXTRACTPROGRESS = BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPAYLOADEXTRACTPROGRESS,
84
BA_FUNCTIONS_MESSAGE_ONPLANROLLBACKBOUNDARY = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANROLLBACKBOUNDARY,
85
+ BA_FUNCTIONS_MESSAGE_ONSETUPDATEBEGIN = BOOTSTRAPPER_APPLICATION_MESSAGE_ONSETUPDATEBEGIN,
86
+ BA_FUNCTIONS_MESSAGE_ONSETUPDATECOMPLETE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONSETUPDATECOMPLETE,
87
88
BA_FUNCTIONS_MESSAGE_ONTHEMELOADED = 1024,
89
BA_FUNCTIONS_MESSAGE_WNDPROC,
src/api/burn/balutil/inc/BalBaseBAFunctions.h
+14
@@ -794,6 +794,20 @@ public: // IBootstrapperApplication
794
return S_OK;
795
}
796
797
+ virtual STDMETHODIMP OnSetUpdateBegin()
798
+ {
799
+ return S_OK;
800
+ }
801
+
802
+ virtual STDMETHODIMP OnSetUpdateComplete(
803
+ __in HRESULT /*hrStatus*/,
804
+ __in_z_opt LPCWSTR /*wzPreviousPackageId*/,
805
+ __in_z_opt LPCWSTR /*wzNewPackageId*/
806
+ )
807
+ {
808
+ return S_OK;
809
+ }
810
+
811
public: // IBAFunctions
812
virtual STDMETHODIMP OnPlan(
813
)
src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h
+2
@@ -153,6 +153,8 @@ static HRESULT WINAPI BalBaseBAFunctionsProc(
153
case BA_FUNCTIONS_MESSAGE_ONCACHEPAYLOADEXTRACTCOMPLETE:
154
case BA_FUNCTIONS_MESSAGE_ONCACHEPAYLOADEXTRACTPROGRESS:
155
case BA_FUNCTIONS_MESSAGE_ONPLANROLLBACKBOUNDARY:
156
+ case BA_FUNCTIONS_MESSAGE_ONSETUPDATEBEGIN:
157
+ case BA_FUNCTIONS_MESSAGE_ONSETUPDATECOMPLETE:
158
hr = BalBaseBootstrapperApplicationProc((BOOTSTRAPPER_APPLICATION_MESSAGE)message, pvArgs, pvResults, pvContext);
159
break;
160
case BA_FUNCTIONS_MESSAGE_ONTHEMELOADED:
src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h
+14
@@ -990,6 +990,20 @@ public: // IBootstrapperApplication
990
return S_OK;
991
}
992
993
+ virtual STDMETHODIMP OnSetUpdateBegin()
994
+ {
995
+ return S_OK;
996
+ }
997
+
998
+ virtual STDMETHODIMP OnSetUpdateComplete(
999
+ __in HRESULT /*hrStatus*/,
1000
+ __in_z_opt LPCWSTR /*wzPreviousPackageId*/,
1001
+ __in_z_opt LPCWSTR /*wzNewPackageId*/
1002
+ )
1003
+ {
1004
+ return S_OK;
1005
+ }
1006
+
1007
public: //CBalBaseBootstrapperApplication
1008
virtual STDMETHODIMP Initialize(
1009
__in const BOOTSTRAPPER_CREATE_ARGS* pCreateArgs
src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h
+24
@@ -666,6 +666,24 @@ static HRESULT BalBaseBAProcOnCachePayloadExtractComplete(
666
return pBA->OnCachePayloadExtractComplete(pArgs->wzContainerId, pArgs->wzPayloadId, pArgs->hrStatus);
667
}
668
669
+static HRESULT BalBaseBAProcOnSetUpdateBegin(
670
+ __in IBootstrapperApplication* pBA,
671
+ __in BA_ONSETUPDATEBEGIN_ARGS* /*pArgs*/,
672
+ __inout BA_ONSETUPDATEBEGIN_RESULTS* /*pResults*/
673
+ )
674
+{
675
+ return pBA->OnSetUpdateBegin();
676
+}
677
+
678
+static HRESULT BalBaseBAProcOnSetUpdateComplete(
679
+ __in IBootstrapperApplication* pBA,
680
+ __in BA_ONSETUPDATECOMPLETE_ARGS* pArgs,
681
+ __inout BA_ONSETUPDATECOMPLETE_RESULTS* /*pResults*/
682
+ )
683
+{
684
+ return pBA->OnSetUpdateComplete(pArgs->hrStatus, pArgs->wzPreviousPackageId, pArgs->wzNewPackageId);
685
+}
686
+
687
/*******************************************************************
688
BalBaseBootstrapperApplicationProc - requires pvContext to be of type IBootstrapperApplication.
689
Provides a default mapping between the new message based BA interface and
@@ -904,6 +922,12 @@ static HRESULT WINAPI BalBaseBootstrapperApplicationProc(
922
case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANROLLBACKBOUNDARY:
923
hr = BalBaseBAProcOnPlanRollbackBoundary(pBA, reinterpret_cast<BA_ONPLANROLLBACKBOUNDARY_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANROLLBACKBOUNDARY_RESULTS*>(pvResults));
924
break;
925
+ case BOOTSTRAPPER_APPLICATION_MESSAGE_ONSETUPDATEBEGIN:
926
+ hr = BalBaseBAProcOnSetUpdateBegin(pBA, reinterpret_cast<BA_ONSETUPDATEBEGIN_ARGS*>(pvArgs), reinterpret_cast<BA_ONSETUPDATEBEGIN_RESULTS*>(pvResults));
927
+ break;
928
+ case BOOTSTRAPPER_APPLICATION_MESSAGE_ONSETUPDATECOMPLETE:
929
+ hr = BalBaseBAProcOnSetUpdateComplete(pBA, reinterpret_cast<BA_ONSETUPDATECOMPLETE_ARGS*>(pvArgs), reinterpret_cast<BA_ONSETUPDATECOMPLETE_RESULTS*>(pvResults));
930
+ break;
931
}
932
}
933
src/api/burn/balutil/inc/IBootstrapperApplication.h
+8
@@ -658,4 +658,12 @@ DECLARE_INTERFACE_IID_(IBootstrapperApplication, IUnknown, "53C31D56-49C0-426B-A
658
__in_z_opt LPCWSTR wzPayloadId,
659
__in HRESULT hrStatus
660
) = 0;
661
+
662
+ STDMETHOD(OnSetUpdateBegin)() = 0;
663
+
664
+ STDMETHOD(OnSetUpdateComplete)(
665
+ __in HRESULT hrStatus,
666
+ __in_z_opt LPCWSTR wzPreviousPackageId,
667
+ __in_z_opt LPCWSTR wzNewPackageId
668
+ ) = 0;
669
};
src/api/burn/balutil/inc/balinfo.h
+14
-1
@@ -16,6 +16,7 @@ typedef enum BAL_INFO_PACKAGE_TYPE
16
BAL_INFO_PACKAGE_TYPE_BUNDLE_UPGRADE,
17
BAL_INFO_PACKAGE_TYPE_BUNDLE_ADDON,
18
BAL_INFO_PACKAGE_TYPE_BUNDLE_PATCH,
19
+ BAL_INFO_PACKAGE_TYPE_BUNDLE_UPDATE,
20
} BAL_INFO_PACKAGE_TYPE;
21
22
typedef enum _BAL_INFO_RESTART
@@ -125,13 +126,25 @@ DAPI_(HRESULT) BalInfoParseFromXml(
126
********************************************************************/
127
DAPI_(HRESULT) BalInfoAddRelatedBundleAsPackage(
128
__in BAL_INFO_PACKAGES* pPackages,
128
- __in LPCWSTR wzId,
129
+ __in_z LPCWSTR wzId,
130
__in BOOTSTRAPPER_RELATION_TYPE relationType,
131
__in BOOL fPerMachine,
132
__out_opt BAL_INFO_PACKAGE** ppPackage
133
);
134
135
136
+/*******************************************************************
137
+ BalInfoAddUpdateBundleAsPackage - adds an update bundle as a package.
138
+
139
+ ********************************************************************/
140
+DAPI_(HRESULT) BalInfoAddUpdateBundleAsPackage(
141
+ __in BAL_INFO_PACKAGES* pPackages,
142
+ __in_z LPCWSTR wzId,
143
+ __in_z LPCWSTR wzPreviousId,
144
+ __out_opt BAL_INFO_PACKAGE** ppPackage
145
+ );
146
+
147
+
148
/*******************************************************************
149
BalInfoFindPackageById - finds a package by its id.
150
src/burn/engine/core.cpp
+1
-1
@@ -1193,7 +1193,7 @@ extern "C" HRESULT CoreCreateUpdateBundleCommandLine(
1193
{
1194
HRESULT hr = S_OK;
1195
1196
- hr = CoreRecreateCommandLine(psczCommandLine, BOOTSTRAPPER_ACTION_INSTALL, pInternalCommand, pCommand, BOOTSTRAPPER_RELATION_NONE, FALSE);
1196
+ hr = CoreRecreateCommandLine(psczCommandLine, BOOTSTRAPPER_ACTION_INSTALL, pInternalCommand, pCommand, BOOTSTRAPPER_RELATION_UPDATE, FALSE);
1197
ExitOnFailure(hr, "Failed to recreate update bundle command-line.");
1198
1199
LExit:
src/burn/engine/externalengine.cpp
+52
-34
@@ -269,64 +269,82 @@ HRESULT ExternalEngineSetUpdate(
269
)
270
{
271
HRESULT hr = S_OK;
272
+ BOOL fLeaveCriticalSection = FALSE;
273
LPWSTR sczFilePath = NULL;
274
LPWSTR sczCommandline = NULL;
275
+ LPWSTR sczPreviousId = NULL;
276
+ LPCWSTR wzNewId = NULL;
277
UUID guid = { };
278
WCHAR wzGuid[39];
279
RPC_STATUS rs = RPC_S_OK;
280
+ BOOL fRemove = (!wzLocalSource || !*wzLocalSource) && (!wzDownloadSource || !*wzDownloadSource);
281
+
282
+ UserExperienceOnSetUpdateBegin(&pEngineState->userExperience);
283
284
::EnterCriticalSection(&pEngineState->userExperience.csEngineActive);
285
+ fLeaveCriticalSection = TRUE;
286
hr = UserExperienceEnsureEngineInactive(&pEngineState->userExperience);
287
ExitOnFailure(hr, "Engine is active, cannot change engine state.");
288
282
- if ((!wzLocalSource || !*wzLocalSource) && (!wzDownloadSource || !*wzDownloadSource))
283
- {
284
- UpdateUninitialize(&pEngineState->update);
285
- }
286
- else if (BOOTSTRAPPER_UPDATE_HASH_TYPE_NONE == hashType && (0 != cbHash || rgbHash))
289
+ if (!fRemove)
290
{
288
- hr = E_INVALIDARG;
291
+ if (BOOTSTRAPPER_UPDATE_HASH_TYPE_NONE == hashType && (0 != cbHash || rgbHash))
292
+ {
293
+ ExitFunction1(hr = E_INVALIDARG);
294
+ }
295
+ else if (BOOTSTRAPPER_UPDATE_HASH_TYPE_SHA512 == hashType && (SHA512_HASH_LEN != cbHash || !rgbHash))
296
+ {
297
+ ExitFunction1(hr = E_INVALIDARG);
298
+ }
299
}
290
- else if (BOOTSTRAPPER_UPDATE_HASH_TYPE_SHA512 == hashType && (SHA512_HASH_LEN != cbHash || !rgbHash))
300
+
301
+ sczPreviousId = pEngineState->update.package.sczId;
302
+ pEngineState->update.package.sczId = NULL;
303
+ UpdateUninitialize(&pEngineState->update);
304
+
305
+ if (fRemove)
306
{
292
- hr = E_INVALIDARG;
307
+ ExitFunction();
308
}
294
- else
295
- {
296
- UpdateUninitialize(&pEngineState->update);
309
298
- hr = CoreCreateUpdateBundleCommandLine(&sczCommandline, &pEngineState->internalCommand, &pEngineState->command);
299
- ExitOnFailure(hr, "Failed to create command-line for update bundle.");
310
+ hr = CoreCreateUpdateBundleCommandLine(&sczCommandline, &pEngineState->internalCommand, &pEngineState->command);
311
+ ExitOnFailure(hr, "Failed to create command-line for update bundle.");
312
301
- // Bundles would fail to use the downloaded update bundle, as the running bundle would be one of the search paths.
302
- // Here I am generating a random guid, but in the future it would be nice if the feed would provide the ID of the update.
303
- rs = ::UuidCreate(&guid);
304
- hr = HRESULT_FROM_RPC(rs);
305
- ExitOnFailure(hr, "Failed to create bundle update guid.");
313
+ // Bundles would fail to use the downloaded update bundle, as the running bundle would be one of the search paths.
314
+ // Here I am generating a random guid, but in the future it would be nice if the feed would provide the ID of the update.
315
+ rs = ::UuidCreate(&guid);
316
+ hr = HRESULT_FROM_RPC(rs);
317
+ ExitOnFailure(hr, "Failed to create bundle update guid.");
318
307
- if (!::StringFromGUID2(guid, wzGuid, countof(wzGuid)))
308
- {
309
- hr = E_OUTOFMEMORY;
310
- ExitOnRootFailure(hr, "Failed to convert bundle update guid into string.");
311
- }
319
+ if (!::StringFromGUID2(guid, wzGuid, countof(wzGuid)))
320
+ {
321
+ hr = E_OUTOFMEMORY;
322
+ ExitOnRootFailure(hr, "Failed to convert bundle update guid into string.");
323
+ }
324
313
- hr = StrAllocFormatted(&sczFilePath, L"%ls\\%ls", wzGuid, pEngineState->registration.sczExecutableName);
314
- ExitOnFailure(hr, "Failed to build bundle update file path.");
325
+ hr = StrAllocFormatted(&sczFilePath, L"%ls\\%ls", wzGuid, pEngineState->registration.sczExecutableName);
326
+ ExitOnFailure(hr, "Failed to build bundle update file path.");
327
316
- if (!wzLocalSource || !*wzLocalSource)
317
- {
318
- wzLocalSource = sczFilePath;
319
- }
328
+ if (!wzLocalSource || !*wzLocalSource)
329
+ {
330
+ wzLocalSource = sczFilePath;
331
+ }
332
321
- hr = PseudoBundleInitialize(FILEMAKEVERSION(rmj, rmm, rup, rpr), &pEngineState->update.package, FALSE, pEngineState->registration.sczId, BOOTSTRAPPER_RELATION_UPDATE, BOOTSTRAPPER_PACKAGE_STATE_ABSENT, FALSE, sczFilePath, wzLocalSource, wzDownloadSource, qwSize, TRUE, sczCommandline, NULL, NULL, NULL, rgbHash, cbHash);
322
- ExitOnFailure(hr, "Failed to set update bundle.");
333
+ hr = PseudoBundleInitializeUpdateBundle(&pEngineState->update.package, wzGuid, pEngineState->registration.sczId, sczFilePath, wzLocalSource, wzDownloadSource, qwSize, sczCommandline, rgbHash, cbHash);
334
+ ExitOnFailure(hr, "Failed to set update bundle.");
335
324
- pEngineState->update.fUpdateAvailable = TRUE;
325
- }
336
+ pEngineState->update.fUpdateAvailable = TRUE;
337
+ wzNewId = wzGuid;
338
339
LExit:
328
- ::LeaveCriticalSection(&pEngineState->userExperience.csEngineActive);
340
+ if (fLeaveCriticalSection)
341
+ {
342
+ ::LeaveCriticalSection(&pEngineState->userExperience.csEngineActive);
343
+ }
344
+
345
+ UserExperienceOnSetUpdateComplete(&pEngineState->userExperience, hr, sczPreviousId, wzNewId);
346
347
+ ReleaseStr(sczPreviousId);
348
ReleaseStr(sczCommandline);
349
ReleaseStr(sczFilePath);
350
src/burn/engine/pseudobundle.cpp
+77
@@ -240,3 +240,80 @@ LExit:
240
ReleaseStr(sczArguments);
241
return hr;
242
}
243
+
244
+extern "C" HRESULT PseudoBundleInitializeUpdateBundle(
245
+ __in BURN_PACKAGE* pPackage,
246
+ __in_z LPCWSTR wzId,
247
+ __in_z LPCWSTR wzCacheId,
248
+ __in_z LPCWSTR wzFilePath,
249
+ __in_z LPCWSTR wzLocalSource,
250
+ __in_z_opt LPCWSTR wzDownloadSource,
251
+ __in DWORD64 qwSize,
252
+ __in_z LPCWSTR wzInstallArguments,
253
+ __in_opt const BYTE* pbHash,
254
+ __in const DWORD cbHash
255
+ )
256
+{
257
+ HRESULT hr = S_OK;
258
+ BURN_PAYLOAD* pPayload = NULL;
259
+
260
+ // Initialize the single payload, and fill out all the necessary fields
261
+ pPackage->payloads.rgItems = (BURN_PAYLOAD_GROUP_ITEM*)MemAlloc(sizeof(BURN_PAYLOAD_GROUP_ITEM), TRUE);
262
+ ExitOnNull(pPackage->payloads.rgItems, hr, E_OUTOFMEMORY, "Failed to allocate space for burn payload group inside of update bundle struct");
263
+ pPackage->payloads.cItems = 1;
264
+
265
+ pPayload = (BURN_PAYLOAD*)MemAlloc(sizeof(BURN_PAYLOAD), TRUE);
266
+ ExitOnNull(pPayload, hr, E_OUTOFMEMORY, "Failed to allocate space for burn payload inside of update bundle struct");
267
+ pPackage->payloads.rgItems[0].pPayload = pPayload;
268
+ pPayload->packaging = BURN_PAYLOAD_PACKAGING_EXTERNAL;
269
+ pPayload->qwFileSize = qwSize;
270
+ pPayload->verification = BURN_PAYLOAD_VERIFICATION_UPDATE_BUNDLE;
271
+
272
+ hr = StrAllocString(&pPayload->sczKey, wzId, 0);
273
+ ExitOnFailure(hr, "Failed to copy key for pseudo bundle payload.");
274
+
275
+ hr = StrAllocString(&pPayload->sczFilePath, wzFilePath, 0);
276
+ ExitOnFailure(hr, "Failed to copy filename for pseudo bundle.");
277
+
278
+ hr = StrAllocString(&pPayload->sczSourcePath, wzLocalSource, 0);
279
+ ExitOnFailure(hr, "Failed to copy local source path for pseudo bundle.");
280
+
281
+ if (wzDownloadSource && *wzDownloadSource)
282
+ {
283
+ hr = StrAllocString(&pPayload->downloadSource.sczUrl, wzDownloadSource, 0);
284
+ ExitOnFailure(hr, "Failed to copy download source for pseudo bundle.");
285
+ }
286
+
287
+ if (pbHash)
288
+ {
289
+ pPayload->pbHash = static_cast<BYTE*>(MemAlloc(cbHash, FALSE));
290
+ ExitOnNull(pPayload->pbHash, hr, E_OUTOFMEMORY, "Failed to allocate memory for update bundle payload hash.");
291
+
292
+ pPayload->cbHash = cbHash;
293
+ memcpy_s(pPayload->pbHash, pPayload->cbHash, pbHash, cbHash);
294
+ }
295
+
296
+ pPackage->Exe.fPseudoBundle = TRUE;
297
+
298
+ pPackage->type = BURN_PACKAGE_TYPE_EXE;
299
+ pPackage->currentState = BOOTSTRAPPER_PACKAGE_STATE_ABSENT;
300
+ pPackage->qwInstallSize = qwSize;
301
+ pPackage->qwSize = qwSize;
302
+ pPackage->fVital = TRUE;
303
+
304
+ hr = StrAllocString(&pPackage->sczId, wzId, 0);
305
+ ExitOnFailure(hr, "Failed to copy id for update bundle.");
306
+
307
+ hr = StrAllocString(&pPackage->sczCacheId, wzCacheId, 0);
308
+ ExitOnFailure(hr, "Failed to copy cache id for update bundle.");
309
+
310
+ hr = StrAllocString(&pPackage->Exe.sczInstallArguments, wzInstallArguments, 0);
311
+ ExitOnFailure(hr, "Failed to copy install arguments for update bundle package");
312
+
313
+ // Assume the update bundle has the same engine version as this one.
314
+ pPackage->Exe.protocol = BURN_EXE_PROTOCOL_TYPE_BURN;
315
+ pPackage->Exe.fSupportsAncestors = TRUE;
316
+
317
+LExit:
318
+ return hr;
319
+}
\ No newline at end of file
src/burn/engine/pseudobundle.h
+12
@@ -32,6 +32,18 @@ HRESULT PseudoBundleInitializePassthrough(
32
__in BOOTSTRAPPER_COMMAND* pCommand,
33
__in BURN_PACKAGE* pPackage
34
);
35
+HRESULT PseudoBundleInitializeUpdateBundle(
36
+ __in BURN_PACKAGE* pPackage,
37
+ __in_z LPCWSTR wzId,
38
+ __in_z LPCWSTR wzCacheId,
39
+ __in_z LPCWSTR wzFilePath,
40
+ __in_z LPCWSTR wzLocalSource,
41
+ __in_z_opt LPCWSTR wzDownloadSource,
42
+ __in DWORD64 qwSize,
43
+ __in_z LPCWSTR wzInstallArguments,
44
+ __in_opt const BYTE* pbHash,
45
+ __in const DWORD cbHash
46
+ );
47
48
#if defined(__cplusplus)
49
}
src/burn/engine/userexperience.cpp
+44
@@ -2241,6 +2241,50 @@ LExit:
2241
return hr;
2242
}
2243
2244
+EXTERN_C BAAPI UserExperienceOnSetUpdateBegin(
2245
+ __in BURN_USER_EXPERIENCE* pUserExperience
2246
+ )
2247
+{
2248
+ HRESULT hr = S_OK;
2249
+ BA_ONSETUPDATEBEGIN_ARGS args = { };
2250
+ BA_ONSETUPDATEBEGIN_RESULTS results = { };
2251
+
2252
+ args.cbSize = sizeof(args);
2253
+
2254
+ results.cbSize = sizeof(results);
2255
+
2256
+ hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONSETUPDATEBEGIN, &args, &results);
2257
+ ExitOnFailure(hr, "BA OnSetUpdateBegin failed.");
2258
+
2259
+LExit:
2260
+ return hr;
2261
+}
2262
+
2263
+EXTERN_C BAAPI UserExperienceOnSetUpdateComplete(
2264
+ __in BURN_USER_EXPERIENCE* pUserExperience,
2265
+ __in HRESULT hrStatus,
2266
+ __in_z_opt LPCWSTR wzPreviousPackageId,
2267
+ __in_z_opt LPCWSTR wzNewPackageId
2268
+ )
2269
+{
2270
+ HRESULT hr = S_OK;
2271
+ BA_ONSETUPDATECOMPLETE_ARGS args = { };
2272
+ BA_ONSETUPDATECOMPLETE_RESULTS results = { };
2273
+
2274
+ args.cbSize = sizeof(args);
2275
+ args.hrStatus = hrStatus;
2276
+ args.wzPreviousPackageId = wzPreviousPackageId;
2277
+ args.wzNewPackageId = wzNewPackageId;
2278
+
2279
+ results.cbSize = sizeof(results);
2280
+
2281
+ hr = SendBAMessage(pUserExperience, BOOTSTRAPPER_APPLICATION_MESSAGE_ONSETUPDATECOMPLETE, &args, &results);
2282
+ ExitOnFailure(hr, "BA OnSetUpdateComplete failed.");
2283
+
2284
+LExit:
2285
+ return hr;
2286
+}
2287
+
2288
EXTERN_C BAAPI UserExperienceOnShutdown(
2289
__in BURN_USER_EXPERIENCE* pUserExperience,
2290
__inout BOOTSTRAPPER_SHUTDOWN_ACTION* pAction
src/burn/engine/userexperience.h
+9
@@ -505,6 +505,15 @@ BAAPI UserExperienceOnRollbackMsiTransactionComplete(
505
__in LPCWSTR wzTransactionId,
506
__in HRESULT hrStatus
507
);
508
+BAAPI UserExperienceOnSetUpdateBegin(
509
+ __in BURN_USER_EXPERIENCE* pUserExperience
510
+ );
511
+BAAPI UserExperienceOnSetUpdateComplete(
512
+ __in BURN_USER_EXPERIENCE* pUserExperience,
513
+ __in HRESULT hrStatus,
514
+ __in_z_opt LPCWSTR wzPreviousPackageId,
515
+ __in_z_opt LPCWSTR wzNewPackageId
516
+ );
517
BAAPI UserExperienceOnShutdown(
518
__in BURN_USER_EXPERIENCE* pUserExperience,
519
__inout BOOTSTRAPPER_SHUTDOWN_ACTION* pAction
src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
+39
@@ -1169,6 +1169,23 @@ public: // IBootstrapperApplication
1169
return hr;
1170
}
1171
1172
+ virtual STDMETHODIMP OnSetUpdateComplete(
1173
+ __in HRESULT hrStatus,
1174
+ __in_z_opt LPCWSTR wzPreviousPackageId,
1175
+ __in_z_opt LPCWSTR wzNewPackageId
1176
+ )
1177
+ {
1178
+ BAL_INFO_PACKAGE* pPackage = NULL;
1179
+
1180
+ if (SUCCEEDED(hrStatus) && wzNewPackageId &&
1181
+ SUCCEEDED(BalInfoAddUpdateBundleAsPackage(&m_Bundle.packages, wzNewPackageId, wzPreviousPackageId, &pPackage)))
1182
+ {
1183
+ InitializePackageInfoForPackage(pPackage);
1184
+ }
1185
+
1186
+ return S_OK;
1187
+ }
1188
+
1189
virtual STDMETHODIMP_(void) BAProcFallback(
1190
__in BOOTSTRAPPER_APPLICATION_MESSAGE message,
1191
__in const LPVOID pvArgs,
@@ -1400,6 +1417,12 @@ public: // IBootstrapperApplication
1417
case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANROLLBACKBOUNDARY:
1418
OnPlanRollbackBoundaryFallback(reinterpret_cast<BA_ONPLANROLLBACKBOUNDARY_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANROLLBACKBOUNDARY_RESULTS*>(pvResults));
1419
break;
1420
+ case BOOTSTRAPPER_APPLICATION_MESSAGE_ONSETUPDATEBEGIN:
1421
+ OnSetUpdateBeginFallback(reinterpret_cast<BA_ONSETUPDATEBEGIN_ARGS*>(pvArgs), reinterpret_cast<BA_ONSETUPDATEBEGIN_RESULTS*>(pvResults));
1422
+ break;
1423
+ case BOOTSTRAPPER_APPLICATION_MESSAGE_ONSETUPDATECOMPLETE:
1424
+ OnSetUpdateCompleteFallback(reinterpret_cast<BA_ONSETUPDATECOMPLETE_ARGS*>(pvArgs), reinterpret_cast<BA_ONSETUPDATECOMPLETE_RESULTS*>(pvResults));
1425
+ break;
1426
default:
1427
#ifdef DEBUG
1428
BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: Forwarding unknown BA message: %d", message);
@@ -2003,6 +2026,22 @@ private: // privates
2026
BalLogId(BOOTSTRAPPER_LOG_LEVEL_STANDARD, MSG_WIXSTDBA_PLANNED_ROLLBACK_BOUNDARY, m_hModule, pArgs->wzRollbackBoundaryId, LoggingBoolToString(fTransaction), LoggingBoolToString(pResults->fTransaction));
2027
}
2028
2029
+ void OnSetUpdateBeginFallback(
2030
+ __in BA_ONSETUPDATEBEGIN_ARGS* pArgs,
2031
+ __inout BA_ONSETUPDATEBEGIN_RESULTS* pResults
2032
+ )
2033
+ {
2034
+ m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONSETUPDATEBEGIN, pArgs, pResults, m_pvBAFunctionsProcContext);
2035
+ }
2036
+
2037
+ void OnSetUpdateCompleteFallback(
2038
+ __in BA_ONSETUPDATECOMPLETE_ARGS* pArgs,
2039
+ __inout BA_ONSETUPDATECOMPLETE_RESULTS* pResults
2040
+ )
2041
+ {
2042
+ m_pfnBAFunctionsProc(BA_FUNCTIONS_MESSAGE_ONSETUPDATECOMPLETE, pArgs, pResults, m_pvBAFunctionsProcContext);
2043
+ }
2044
+
2045
2046
public: //CBalBaseBootstrapperApplication
2047
virtual STDMETHODIMP Initialize(
src/test/burn/WixToolset.WixBA/InstallationViewModel.cs
+9
@@ -85,6 +85,7 @@ namespace WixToolset.WixBA
85
WixBA.Model.Bootstrapper.ExecutePackageComplete += this.ExecutePackageComplete;
86
WixBA.Model.Bootstrapper.Error += this.ExecuteError;
87
WixBA.Model.Bootstrapper.ApplyComplete += this.ApplyComplete;
88
+ WixBA.Model.Bootstrapper.SetUpdateComplete += this.SetUpdateComplete;
89
}
90
91
void RootPropertyChanged(object sender, PropertyChangedEventArgs e)
@@ -409,6 +410,14 @@ namespace WixToolset.WixBA
410
}
411
}
412
413
+ private void SetUpdateComplete(object sender, SetUpdateCompleteEventArgs e)
414
+ {
415
+ if (!String.IsNullOrEmpty(e.NewPackageId) && !WixBA.Model.BAManifest.Bundle.Packages.ContainsKey(e.NewPackageId))
416
+ {
417
+ WixBA.Model.BAManifest.Bundle.AddUpdateBundleAsPackage(e);
418
+ }
419
+ }
420
+
421
private void DetectComplete(object sender, DetectCompleteEventArgs e)
422
{
423
// Parse the command line string before any planning.