@joebigelow / wix-1 / commits / fc30db9f

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.