aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2021-12-10 11:42:44 -0600
committerSean Hall <r.sean.hall@gmail.com>2021-12-11 20:03:13 -0600
commitfc30db9fa3aa1d25a6ef078452864673caa67ec5 (patch)
treee3415a5a1329a867b2934a038243e95098214ec3 /src
parent1d58b3333d1d694d08b68f6c87223aa504bfe773 (diff)
downloadwix-fc30db9fa3aa1d25a6ef078452864673caa67ec5.tar.gz
wix-fc30db9fa3aa1d25a6ef078452864673caa67ec5.tar.bz2
wix-fc30db9fa3aa1d25a6ef078452864673caa67ec5.zip
Add BA events for setting the update bundle.
Fixes #6410
Diffstat (limited to 'src')
-rw-r--r--src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h25
-rw-r--r--src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs48
-rw-r--r--src/api/burn/WixToolset.Mba.Core/BundleInfo.cs8
-rw-r--r--src/api/burn/WixToolset.Mba.Core/EventArgs.cs37
-rw-r--r--src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs18
-rw-r--r--src/api/burn/WixToolset.Mba.Core/IBundleInfo.cs7
-rw-r--r--src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs10
-rw-r--r--src/api/burn/WixToolset.Mba.Core/PackageInfo.cs19
-rw-r--r--src/api/burn/balutil/balinfo.cpp43
-rw-r--r--src/api/burn/balutil/inc/BAFunctions.h2
-rw-r--r--src/api/burn/balutil/inc/BalBaseBAFunctions.h14
-rw-r--r--src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h2
-rw-r--r--src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h14
-rw-r--r--src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h24
-rw-r--r--src/api/burn/balutil/inc/IBootstrapperApplication.h8
-rw-r--r--src/api/burn/balutil/inc/balinfo.h15
-rw-r--r--src/burn/engine/core.cpp2
-rw-r--r--src/burn/engine/externalengine.cpp86
-rw-r--r--src/burn/engine/pseudobundle.cpp77
-rw-r--r--src/burn/engine/pseudobundle.h12
-rw-r--r--src/burn/engine/userexperience.cpp44
-rw-r--r--src/burn/engine/userexperience.h9
-rw-r--r--src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp39
-rw-r--r--src/test/burn/WixToolset.WixBA/InstallationViewModel.cs9
24 files changed, 535 insertions, 37 deletions
diff --git a/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h b/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
index ad920577..2ffcf9d6 100644
--- a/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
+++ b/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
@@ -197,6 +197,8 @@ enum BOOTSTRAPPER_APPLICATION_MESSAGE
197 BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPAYLOADEXTRACTCOMPLETE, 197 BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPAYLOADEXTRACTCOMPLETE,
198 BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPAYLOADEXTRACTPROGRESS, 198 BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPAYLOADEXTRACTPROGRESS,
199 BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANROLLBACKBOUNDARY, 199 BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANROLLBACKBOUNDARY,
200 BOOTSTRAPPER_APPLICATION_MESSAGE_ONSETUPDATEBEGIN,
201 BOOTSTRAPPER_APPLICATION_MESSAGE_ONSETUPDATECOMPLETE,
200}; 202};
201 203
202enum BOOTSTRAPPER_APPLYCOMPLETE_ACTION 204enum BOOTSTRAPPER_APPLYCOMPLETE_ACTION
@@ -1228,6 +1230,29 @@ struct BA_ONROLLBACKMSITRANSACTIONCOMPLETE_RESULTS
1228 DWORD cbSize; 1230 DWORD cbSize;
1229}; 1231};
1230 1232
1233struct BA_ONSETUPDATEBEGIN_ARGS
1234{
1235 DWORD cbSize;
1236};
1237
1238struct BA_ONSETUPDATEBEGIN_RESULTS
1239{
1240 DWORD cbSize;
1241};
1242
1243struct BA_ONSETUPDATECOMPLETE_ARGS
1244{
1245 DWORD cbSize;
1246 HRESULT hrStatus;
1247 LPCWSTR wzPreviousPackageId;
1248 LPCWSTR wzNewPackageId;
1249};
1250
1251struct BA_ONSETUPDATECOMPLETE_RESULTS
1252{
1253 DWORD cbSize;
1254};
1255
1231struct BA_ONSHUTDOWN_ARGS 1256struct BA_ONSHUTDOWN_ARGS
1232{ 1257{
1233 DWORD cbSize; 1258 DWORD cbSize;
diff --git a/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs b/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs
index 0520463f..a78bf43f 100644
--- a/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs
+++ b/src/api/burn/WixToolset.Mba.Core/BootstrapperApplication.cs
@@ -253,6 +253,12 @@ namespace WixToolset.Mba.Core
253 /// <inheritdoc/> 253 /// <inheritdoc/>
254 public event EventHandler<CachePayloadExtractCompleteEventArgs> CachePayloadExtractComplete; 254 public event EventHandler<CachePayloadExtractCompleteEventArgs> CachePayloadExtractComplete;
255 255
256 /// <inheritdoc/>
257 public event EventHandler<SetUpdateBeginEventArgs> SetUpdateBegin;
258
259 /// <inheritdoc/>
260 public event EventHandler<SetUpdateCompleteEventArgs> SetUpdateComplete;
261
256 /// <summary> 262 /// <summary>
257 /// Entry point that is called when the bootstrapper application is ready to run. 263 /// Entry point that is called when the bootstrapper application is ready to run.
258 /// </summary> 264 /// </summary>
@@ -1225,6 +1231,32 @@ namespace WixToolset.Mba.Core
1225 } 1231 }
1226 } 1232 }
1227 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
1228 #region IBootstrapperApplication Members 1260 #region IBootstrapperApplication Members
1229 1261
1230 int IBootstrapperApplication.BAProc(int message, IntPtr pvArgs, IntPtr pvResults, IntPtr pvContext) 1262 int IBootstrapperApplication.BAProc(int message, IntPtr pvArgs, IntPtr pvResults, IntPtr pvContext)
@@ -1895,6 +1927,22 @@ namespace WixToolset.Mba.Core
1895 return args.HResult; 1927 return args.HResult;
1896 } 1928 }
1897 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
1898 #endregion 1946 #endregion
1899 } 1947 }
1900} 1948}
diff --git a/src/api/burn/WixToolset.Mba.Core/BundleInfo.cs b/src/api/burn/WixToolset.Mba.Core/BundleInfo.cs
index 4a533bf9..ee751ebf 100644
--- a/src/api/burn/WixToolset.Mba.Core/BundleInfo.cs
+++ b/src/api/burn/WixToolset.Mba.Core/BundleInfo.cs
@@ -41,6 +41,14 @@ namespace WixToolset.Mba.Core
41 return package; 41 return package;
42 } 42 }
43 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
44 /// <summary> 52 /// <summary>
45 /// Parses BA manifest from the given stream. 53 /// Parses BA manifest from the given stream.
46 /// </summary> 54 /// </summary>
diff --git a/src/api/burn/WixToolset.Mba.Core/EventArgs.cs b/src/api/burn/WixToolset.Mba.Core/EventArgs.cs
index 556db821..55c9e74c 100644
--- a/src/api/burn/WixToolset.Mba.Core/EventArgs.cs
+++ b/src/api/burn/WixToolset.Mba.Core/EventArgs.cs
@@ -2230,4 +2230,41 @@ namespace WixToolset.Mba.Core
2230 /// </summary> 2230 /// </summary>
2231 public string PayloadId { get; private set; } 2231 public string PayloadId { get; private set; }
2232 } 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 }
2233} 2270}
diff --git a/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs b/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs
index 259c407f..f0c0b7ec 100644
--- a/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs
+++ b/src/api/burn/WixToolset.Mba.Core/IBootstrapperApplication.cs
@@ -1097,6 +1097,24 @@ namespace WixToolset.Mba.Core
1097 [MarshalAs(UnmanagedType.LPWStr)] string wzPayloadId, 1097 [MarshalAs(UnmanagedType.LPWStr)] string wzPayloadId,
1098 int hrStatus 1098 int hrStatus
1099 ); 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 );
1100 } 1118 }
1101 1119
1102 /// <summary> 1120 /// <summary>
diff --git a/src/api/burn/WixToolset.Mba.Core/IBundleInfo.cs b/src/api/burn/WixToolset.Mba.Core/IBundleInfo.cs
index 35decc88..3227b72d 100644
--- a/src/api/burn/WixToolset.Mba.Core/IBundleInfo.cs
+++ b/src/api/burn/WixToolset.Mba.Core/IBundleInfo.cs
@@ -40,5 +40,12 @@ namespace WixToolset.Mba.Core
40 /// <param name="e"></param> 40 /// <param name="e"></param>
41 /// <returns>The created <see cref="IPackageInfo"/>.</returns> 41 /// <returns>The created <see cref="IPackageInfo"/>.</returns>
42 IPackageInfo AddRelatedBundleAsPackage(DetectRelatedBundleEventArgs e); 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);
43 } 50 }
44} \ No newline at end of file 51} \ No newline at end of file
diff --git a/src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs b/src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs
index 20ce9f88..e809a965 100644
--- a/src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs
+++ b/src/api/burn/WixToolset.Mba.Core/IDefaultBootstrapperApplication.cs
@@ -344,6 +344,16 @@ namespace WixToolset.Mba.Core
344 event EventHandler<RollbackMsiTransactionCompleteEventArgs> RollbackMsiTransactionComplete; 344 event EventHandler<RollbackMsiTransactionCompleteEventArgs> RollbackMsiTransactionComplete;
345 345
346 /// <summary> 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>
347 /// Fired when the engine is shutting down the bootstrapper application. 357 /// Fired when the engine is shutting down the bootstrapper application.
348 /// </summary> 358 /// </summary>
349 event EventHandler<ShutdownEventArgs> Shutdown; 359 event EventHandler<ShutdownEventArgs> Shutdown;
diff --git a/src/api/burn/WixToolset.Mba.Core/PackageInfo.cs b/src/api/burn/WixToolset.Mba.Core/PackageInfo.cs
index 567a7cdd..3681a497 100644
--- a/src/api/burn/WixToolset.Mba.Core/PackageInfo.cs
+++ b/src/api/burn/WixToolset.Mba.Core/PackageInfo.cs
@@ -51,6 +51,11 @@ namespace WixToolset.Mba.Core
51 /// 51 ///
52 /// </summary> 52 /// </summary>
53 PatchBundle, 53 PatchBundle,
54
55 /// <summary>
56 ///
57 /// </summary>
58 UpdateBundle,
54 } 59 }
55 60
56 /// <summary> 61 /// <summary>
@@ -269,6 +274,20 @@ namespace WixToolset.Mba.Core
269 return package; 274 return package;
270 } 275 }
271 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
272 internal static void ParseBalPackageInfoFromXml(XPathNavigator root, XmlNamespaceManager namespaceManager, Dictionary<string, IPackageInfo> packagesById) 291 internal static void ParseBalPackageInfoFromXml(XPathNavigator root, XmlNamespaceManager namespaceManager, Dictionary<string, IPackageInfo> packagesById)
273 { 292 {
274 XPathNodeIterator nodes = root.Select("/p:BootstrapperApplicationData/p:WixBalPackageInfo", namespaceManager); 293 XPathNodeIterator nodes = root.Select("/p:BootstrapperApplicationData/p:WixBalPackageInfo", namespaceManager);
diff --git a/src/api/burn/balutil/balinfo.cpp b/src/api/burn/balutil/balinfo.cpp
index 2746f49e..d9cc9b76 100644
--- a/src/api/burn/balutil/balinfo.cpp
+++ b/src/api/burn/balutil/balinfo.cpp
@@ -166,7 +166,7 @@ LExit:
166 166
167DAPI_(HRESULT) BalInfoAddRelatedBundleAsPackage( 167DAPI_(HRESULT) BalInfoAddRelatedBundleAsPackage(
168 __in BAL_INFO_PACKAGES* pPackages, 168 __in BAL_INFO_PACKAGES* pPackages,
169 __in LPCWSTR wzId, 169 __in_z LPCWSTR wzId,
170 __in BOOTSTRAPPER_RELATION_TYPE relationType, 170 __in BOOTSTRAPPER_RELATION_TYPE relationType,
171 __in BOOL /*fPerMachine*/, 171 __in BOOL /*fPerMachine*/,
172 __out_opt BAL_INFO_PACKAGE** ppPackage 172 __out_opt BAL_INFO_PACKAGE** ppPackage
@@ -228,6 +228,47 @@ LExit:
228} 228}
229 229
230 230
231DAPI_(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
267LExit:
268 return hr;
269}
270
271
231DAPI_(HRESULT) BalInfoFindPackageById( 272DAPI_(HRESULT) BalInfoFindPackageById(
232 __in BAL_INFO_PACKAGES* pPackages, 273 __in BAL_INFO_PACKAGES* pPackages,
233 __in LPCWSTR wzId, 274 __in LPCWSTR wzId,
diff --git a/src/api/burn/balutil/inc/BAFunctions.h b/src/api/burn/balutil/inc/BAFunctions.h
index 21cace1f..2698a6e3 100644
--- a/src/api/burn/balutil/inc/BAFunctions.h
+++ b/src/api/burn/balutil/inc/BAFunctions.h
@@ -82,6 +82,8 @@ enum BA_FUNCTIONS_MESSAGE
82 BA_FUNCTIONS_MESSAGE_ONCACHEPAYLOADEXTRACTCOMPLETE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPAYLOADEXTRACTCOMPLETE, 82 BA_FUNCTIONS_MESSAGE_ONCACHEPAYLOADEXTRACTCOMPLETE = BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPAYLOADEXTRACTCOMPLETE,
83 BA_FUNCTIONS_MESSAGE_ONCACHEPAYLOADEXTRACTPROGRESS = BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPAYLOADEXTRACTPROGRESS, 83 BA_FUNCTIONS_MESSAGE_ONCACHEPAYLOADEXTRACTPROGRESS = BOOTSTRAPPER_APPLICATION_MESSAGE_ONCACHEPAYLOADEXTRACTPROGRESS,
84 BA_FUNCTIONS_MESSAGE_ONPLANROLLBACKBOUNDARY = BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANROLLBACKBOUNDARY, 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,
85 87
86 BA_FUNCTIONS_MESSAGE_ONTHEMELOADED = 1024, 88 BA_FUNCTIONS_MESSAGE_ONTHEMELOADED = 1024,
87 BA_FUNCTIONS_MESSAGE_WNDPROC, 89 BA_FUNCTIONS_MESSAGE_WNDPROC,
diff --git a/src/api/burn/balutil/inc/BalBaseBAFunctions.h b/src/api/burn/balutil/inc/BalBaseBAFunctions.h
index e45db2dc..8d9bddca 100644
--- a/src/api/burn/balutil/inc/BalBaseBAFunctions.h
+++ b/src/api/burn/balutil/inc/BalBaseBAFunctions.h
@@ -794,6 +794,20 @@ public: // IBootstrapperApplication
794 return S_OK; 794 return S_OK;
795 } 795 }
796 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
797public: // IBAFunctions 811public: // IBAFunctions
798 virtual STDMETHODIMP OnPlan( 812 virtual STDMETHODIMP OnPlan(
799 ) 813 )
diff --git a/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h b/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h
index e841c660..1ab0df59 100644
--- a/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h
+++ b/src/api/burn/balutil/inc/BalBaseBAFunctionsProc.h
@@ -153,6 +153,8 @@ static HRESULT WINAPI BalBaseBAFunctionsProc(
153 case BA_FUNCTIONS_MESSAGE_ONCACHEPAYLOADEXTRACTCOMPLETE: 153 case BA_FUNCTIONS_MESSAGE_ONCACHEPAYLOADEXTRACTCOMPLETE:
154 case BA_FUNCTIONS_MESSAGE_ONCACHEPAYLOADEXTRACTPROGRESS: 154 case BA_FUNCTIONS_MESSAGE_ONCACHEPAYLOADEXTRACTPROGRESS:
155 case BA_FUNCTIONS_MESSAGE_ONPLANROLLBACKBOUNDARY: 155 case BA_FUNCTIONS_MESSAGE_ONPLANROLLBACKBOUNDARY:
156 case BA_FUNCTIONS_MESSAGE_ONSETUPDATEBEGIN:
157 case BA_FUNCTIONS_MESSAGE_ONSETUPDATECOMPLETE:
156 hr = BalBaseBootstrapperApplicationProc((BOOTSTRAPPER_APPLICATION_MESSAGE)message, pvArgs, pvResults, pvContext); 158 hr = BalBaseBootstrapperApplicationProc((BOOTSTRAPPER_APPLICATION_MESSAGE)message, pvArgs, pvResults, pvContext);
157 break; 159 break;
158 case BA_FUNCTIONS_MESSAGE_ONTHEMELOADED: 160 case BA_FUNCTIONS_MESSAGE_ONTHEMELOADED:
diff --git a/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h b/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h
index c10b662c..4d043dfe 100644
--- a/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h
+++ b/src/api/burn/balutil/inc/BalBaseBootstrapperApplication.h
@@ -990,6 +990,20 @@ public: // IBootstrapperApplication
990 return S_OK; 990 return S_OK;
991 } 991 }
992 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
993public: //CBalBaseBootstrapperApplication 1007public: //CBalBaseBootstrapperApplication
994 virtual STDMETHODIMP Initialize( 1008 virtual STDMETHODIMP Initialize(
995 __in const BOOTSTRAPPER_CREATE_ARGS* pCreateArgs 1009 __in const BOOTSTRAPPER_CREATE_ARGS* pCreateArgs
diff --git a/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h b/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h
index f17e1fcb..59bfc1f8 100644
--- a/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h
+++ b/src/api/burn/balutil/inc/BalBaseBootstrapperApplicationProc.h
@@ -666,6 +666,24 @@ static HRESULT BalBaseBAProcOnCachePayloadExtractComplete(
666 return pBA->OnCachePayloadExtractComplete(pArgs->wzContainerId, pArgs->wzPayloadId, pArgs->hrStatus); 666 return pBA->OnCachePayloadExtractComplete(pArgs->wzContainerId, pArgs->wzPayloadId, pArgs->hrStatus);
667} 667}
668 668
669static 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
678static 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
669/******************************************************************* 687/*******************************************************************
670BalBaseBootstrapperApplicationProc - requires pvContext to be of type IBootstrapperApplication. 688BalBaseBootstrapperApplicationProc - requires pvContext to be of type IBootstrapperApplication.
671 Provides a default mapping between the new message based BA interface and 689 Provides a default mapping between the new message based BA interface and
@@ -904,6 +922,12 @@ static HRESULT WINAPI BalBaseBootstrapperApplicationProc(
904 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANROLLBACKBOUNDARY: 922 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANROLLBACKBOUNDARY:
905 hr = BalBaseBAProcOnPlanRollbackBoundary(pBA, reinterpret_cast<BA_ONPLANROLLBACKBOUNDARY_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANROLLBACKBOUNDARY_RESULTS*>(pvResults)); 923 hr = BalBaseBAProcOnPlanRollbackBoundary(pBA, reinterpret_cast<BA_ONPLANROLLBACKBOUNDARY_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANROLLBACKBOUNDARY_RESULTS*>(pvResults));
906 break; 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;
907 } 931 }
908 } 932 }
909 933
diff --git a/src/api/burn/balutil/inc/IBootstrapperApplication.h b/src/api/burn/balutil/inc/IBootstrapperApplication.h
index 1fc99988..be9b7b6e 100644
--- a/src/api/burn/balutil/inc/IBootstrapperApplication.h
+++ b/src/api/burn/balutil/inc/IBootstrapperApplication.h
@@ -658,4 +658,12 @@ DECLARE_INTERFACE_IID_(IBootstrapperApplication, IUnknown, "53C31D56-49C0-426B-A
658 __in_z_opt LPCWSTR wzPayloadId, 658 __in_z_opt LPCWSTR wzPayloadId,
659 __in HRESULT hrStatus 659 __in HRESULT hrStatus
660 ) = 0; 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;
661}; 669};
diff --git a/src/api/burn/balutil/inc/balinfo.h b/src/api/burn/balutil/inc/balinfo.h
index 769becb2..8f61685f 100644
--- a/src/api/burn/balutil/inc/balinfo.h
+++ b/src/api/burn/balutil/inc/balinfo.h
@@ -16,6 +16,7 @@ typedef enum BAL_INFO_PACKAGE_TYPE
16 BAL_INFO_PACKAGE_TYPE_BUNDLE_UPGRADE, 16 BAL_INFO_PACKAGE_TYPE_BUNDLE_UPGRADE,
17 BAL_INFO_PACKAGE_TYPE_BUNDLE_ADDON, 17 BAL_INFO_PACKAGE_TYPE_BUNDLE_ADDON,
18 BAL_INFO_PACKAGE_TYPE_BUNDLE_PATCH, 18 BAL_INFO_PACKAGE_TYPE_BUNDLE_PATCH,
19 BAL_INFO_PACKAGE_TYPE_BUNDLE_UPDATE,
19} BAL_INFO_PACKAGE_TYPE; 20} BAL_INFO_PACKAGE_TYPE;
20 21
21typedef enum _BAL_INFO_RESTART 22typedef enum _BAL_INFO_RESTART
@@ -125,7 +126,7 @@ DAPI_(HRESULT) BalInfoParseFromXml(
125 ********************************************************************/ 126 ********************************************************************/
126DAPI_(HRESULT) BalInfoAddRelatedBundleAsPackage( 127DAPI_(HRESULT) BalInfoAddRelatedBundleAsPackage(
127 __in BAL_INFO_PACKAGES* pPackages, 128 __in BAL_INFO_PACKAGES* pPackages,
128 __in LPCWSTR wzId, 129 __in_z LPCWSTR wzId,
129 __in BOOTSTRAPPER_RELATION_TYPE relationType, 130 __in BOOTSTRAPPER_RELATION_TYPE relationType,
130 __in BOOL fPerMachine, 131 __in BOOL fPerMachine,
131 __out_opt BAL_INFO_PACKAGE** ppPackage 132 __out_opt BAL_INFO_PACKAGE** ppPackage
@@ -133,6 +134,18 @@ DAPI_(HRESULT) BalInfoAddRelatedBundleAsPackage(
133 134
134 135
135/******************************************************************* 136/*******************************************************************
137 BalInfoAddUpdateBundleAsPackage - adds an update bundle as a package.
138
139 ********************************************************************/
140DAPI_(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/*******************************************************************
136 BalInfoFindPackageById - finds a package by its id. 149 BalInfoFindPackageById - finds a package by its id.
137 150
138 ********************************************************************/ 151 ********************************************************************/
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp
index bbd0ff96..812c7261 100644
--- a/src/burn/engine/core.cpp
+++ b/src/burn/engine/core.cpp
@@ -1193,7 +1193,7 @@ extern "C" HRESULT CoreCreateUpdateBundleCommandLine(
1193{ 1193{
1194 HRESULT hr = S_OK; 1194 HRESULT hr = S_OK;
1195 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."); 1197 ExitOnFailure(hr, "Failed to recreate update bundle command-line.");
1198 1198
1199LExit: 1199LExit:
diff --git a/src/burn/engine/externalengine.cpp b/src/burn/engine/externalengine.cpp
index da84c83d..abe9b8bc 100644
--- a/src/burn/engine/externalengine.cpp
+++ b/src/burn/engine/externalengine.cpp
@@ -269,64 +269,82 @@ HRESULT ExternalEngineSetUpdate(
269 ) 269 )
270{ 270{
271 HRESULT hr = S_OK; 271 HRESULT hr = S_OK;
272 BOOL fLeaveCriticalSection = FALSE;
272 LPWSTR sczFilePath = NULL; 273 LPWSTR sczFilePath = NULL;
273 LPWSTR sczCommandline = NULL; 274 LPWSTR sczCommandline = NULL;
275 LPWSTR sczPreviousId = NULL;
276 LPCWSTR wzNewId = NULL;
274 UUID guid = { }; 277 UUID guid = { };
275 WCHAR wzGuid[39]; 278 WCHAR wzGuid[39];
276 RPC_STATUS rs = RPC_S_OK; 279 RPC_STATUS rs = RPC_S_OK;
280 BOOL fRemove = (!wzLocalSource || !*wzLocalSource) && (!wzDownloadSource || !*wzDownloadSource);
281
282 UserExperienceOnSetUpdateBegin(&pEngineState->userExperience);
277 283
278 ::EnterCriticalSection(&pEngineState->userExperience.csEngineActive); 284 ::EnterCriticalSection(&pEngineState->userExperience.csEngineActive);
285 fLeaveCriticalSection = TRUE;
279 hr = UserExperienceEnsureEngineInactive(&pEngineState->userExperience); 286 hr = UserExperienceEnsureEngineInactive(&pEngineState->userExperience);
280 ExitOnFailure(hr, "Engine is active, cannot change engine state."); 287 ExitOnFailure(hr, "Engine is active, cannot change engine state.");
281 288
282 if ((!wzLocalSource || !*wzLocalSource) && (!wzDownloadSource || !*wzDownloadSource)) 289 if (!fRemove)
283 {
284 UpdateUninitialize(&pEngineState->update);
285 }
286 else if (BOOTSTRAPPER_UPDATE_HASH_TYPE_NONE == hashType && (0 != cbHash || rgbHash))
287 { 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 }
289 } 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)
291 { 306 {
292 hr = E_INVALIDARG; 307 ExitFunction();
293 } 308 }
294 else
295 {
296 UpdateUninitialize(&pEngineState->update);
297 309
298 hr = CoreCreateUpdateBundleCommandLine(&sczCommandline, &pEngineState->internalCommand, &pEngineState->command); 310 hr = CoreCreateUpdateBundleCommandLine(&sczCommandline, &pEngineState->internalCommand, &pEngineState->command);
299 ExitOnFailure(hr, "Failed to create command-line for update bundle."); 311 ExitOnFailure(hr, "Failed to create command-line for update bundle.");
300 312
301 // Bundles would fail to use the downloaded update bundle, as the running bundle would be one of the search paths. 313 // 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. 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.
303 rs = ::UuidCreate(&guid); 315 rs = ::UuidCreate(&guid);
304 hr = HRESULT_FROM_RPC(rs); 316 hr = HRESULT_FROM_RPC(rs);
305 ExitOnFailure(hr, "Failed to create bundle update guid."); 317 ExitOnFailure(hr, "Failed to create bundle update guid.");
306 318
307 if (!::StringFromGUID2(guid, wzGuid, countof(wzGuid))) 319 if (!::StringFromGUID2(guid, wzGuid, countof(wzGuid)))
308 { 320 {
309 hr = E_OUTOFMEMORY; 321 hr = E_OUTOFMEMORY;
310 ExitOnRootFailure(hr, "Failed to convert bundle update guid into string."); 322 ExitOnRootFailure(hr, "Failed to convert bundle update guid into string.");
311 } 323 }
312 324
313 hr = StrAllocFormatted(&sczFilePath, L"%ls\\%ls", wzGuid, pEngineState->registration.sczExecutableName); 325 hr = StrAllocFormatted(&sczFilePath, L"%ls\\%ls", wzGuid, pEngineState->registration.sczExecutableName);
314 ExitOnFailure(hr, "Failed to build bundle update file path."); 326 ExitOnFailure(hr, "Failed to build bundle update file path.");
315 327
316 if (!wzLocalSource || !*wzLocalSource) 328 if (!wzLocalSource || !*wzLocalSource)
317 { 329 {
318 wzLocalSource = sczFilePath; 330 wzLocalSource = sczFilePath;
319 } 331 }
320 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); 333 hr = PseudoBundleInitializeUpdateBundle(&pEngineState->update.package, wzGuid, pEngineState->registration.sczId, sczFilePath, wzLocalSource, wzDownloadSource, qwSize, sczCommandline, rgbHash, cbHash);
322 ExitOnFailure(hr, "Failed to set update bundle."); 334 ExitOnFailure(hr, "Failed to set update bundle.");
323 335
324 pEngineState->update.fUpdateAvailable = TRUE; 336 pEngineState->update.fUpdateAvailable = TRUE;
325 } 337 wzNewId = wzGuid;
326 338
327LExit: 339LExit:
328 ::LeaveCriticalSection(&pEngineState->userExperience.csEngineActive); 340 if (fLeaveCriticalSection)
341 {
342 ::LeaveCriticalSection(&pEngineState->userExperience.csEngineActive);
343 }
344
345 UserExperienceOnSetUpdateComplete(&pEngineState->userExperience, hr, sczPreviousId, wzNewId);
329 346
347 ReleaseStr(sczPreviousId);
330 ReleaseStr(sczCommandline); 348 ReleaseStr(sczCommandline);
331 ReleaseStr(sczFilePath); 349 ReleaseStr(sczFilePath);
332 350
diff --git a/src/burn/engine/pseudobundle.cpp b/src/burn/engine/pseudobundle.cpp
index 52b7bd8a..91c6c14f 100644
--- a/src/burn/engine/pseudobundle.cpp
+++ b/src/burn/engine/pseudobundle.cpp
@@ -240,3 +240,80 @@ LExit:
240 ReleaseStr(sczArguments); 240 ReleaseStr(sczArguments);
241 return hr; 241 return hr;
242} 242}
243
244extern "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
317LExit:
318 return hr;
319} \ No newline at end of file
diff --git a/src/burn/engine/pseudobundle.h b/src/burn/engine/pseudobundle.h
index aa26d29d..0fd4cbdb 100644
--- a/src/burn/engine/pseudobundle.h
+++ b/src/burn/engine/pseudobundle.h
@@ -32,6 +32,18 @@ HRESULT PseudoBundleInitializePassthrough(
32 __in BOOTSTRAPPER_COMMAND* pCommand, 32 __in BOOTSTRAPPER_COMMAND* pCommand,
33 __in BURN_PACKAGE* pPackage 33 __in BURN_PACKAGE* pPackage
34 ); 34 );
35HRESULT 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 );
35 47
36#if defined(__cplusplus) 48#if defined(__cplusplus)
37} 49}
diff --git a/src/burn/engine/userexperience.cpp b/src/burn/engine/userexperience.cpp
index 2bd6ecaf..a6d670ea 100644
--- a/src/burn/engine/userexperience.cpp
+++ b/src/burn/engine/userexperience.cpp
@@ -2241,6 +2241,50 @@ LExit:
2241 return hr; 2241 return hr;
2242} 2242}
2243 2243
2244EXTERN_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
2259LExit:
2260 return hr;
2261}
2262
2263EXTERN_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
2284LExit:
2285 return hr;
2286}
2287
2244EXTERN_C BAAPI UserExperienceOnShutdown( 2288EXTERN_C BAAPI UserExperienceOnShutdown(
2245 __in BURN_USER_EXPERIENCE* pUserExperience, 2289 __in BURN_USER_EXPERIENCE* pUserExperience,
2246 __inout BOOTSTRAPPER_SHUTDOWN_ACTION* pAction 2290 __inout BOOTSTRAPPER_SHUTDOWN_ACTION* pAction
diff --git a/src/burn/engine/userexperience.h b/src/burn/engine/userexperience.h
index 2493569b..f7ac962c 100644
--- a/src/burn/engine/userexperience.h
+++ b/src/burn/engine/userexperience.h
@@ -505,6 +505,15 @@ BAAPI UserExperienceOnRollbackMsiTransactionComplete(
505 __in LPCWSTR wzTransactionId, 505 __in LPCWSTR wzTransactionId,
506 __in HRESULT hrStatus 506 __in HRESULT hrStatus
507 ); 507 );
508BAAPI UserExperienceOnSetUpdateBegin(
509 __in BURN_USER_EXPERIENCE* pUserExperience
510 );
511BAAPI UserExperienceOnSetUpdateComplete(
512 __in BURN_USER_EXPERIENCE* pUserExperience,
513 __in HRESULT hrStatus,
514 __in_z_opt LPCWSTR wzPreviousPackageId,
515 __in_z_opt LPCWSTR wzNewPackageId
516 );
508BAAPI UserExperienceOnShutdown( 517BAAPI UserExperienceOnShutdown(
509 __in BURN_USER_EXPERIENCE* pUserExperience, 518 __in BURN_USER_EXPERIENCE* pUserExperience,
510 __inout BOOTSTRAPPER_SHUTDOWN_ACTION* pAction 519 __inout BOOTSTRAPPER_SHUTDOWN_ACTION* pAction
diff --git a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
index abf5af83..ec3c268a 100644
--- a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
+++ b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
@@ -1169,6 +1169,23 @@ public: // IBootstrapperApplication
1169 return hr; 1169 return hr;
1170 } 1170 }
1171 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
1172 virtual STDMETHODIMP_(void) BAProcFallback( 1189 virtual STDMETHODIMP_(void) BAProcFallback(
1173 __in BOOTSTRAPPER_APPLICATION_MESSAGE message, 1190 __in BOOTSTRAPPER_APPLICATION_MESSAGE message,
1174 __in const LPVOID pvArgs, 1191 __in const LPVOID pvArgs,
@@ -1400,6 +1417,12 @@ public: // IBootstrapperApplication
1400 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANROLLBACKBOUNDARY: 1417 case BOOTSTRAPPER_APPLICATION_MESSAGE_ONPLANROLLBACKBOUNDARY:
1401 OnPlanRollbackBoundaryFallback(reinterpret_cast<BA_ONPLANROLLBACKBOUNDARY_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANROLLBACKBOUNDARY_RESULTS*>(pvResults)); 1418 OnPlanRollbackBoundaryFallback(reinterpret_cast<BA_ONPLANROLLBACKBOUNDARY_ARGS*>(pvArgs), reinterpret_cast<BA_ONPLANROLLBACKBOUNDARY_RESULTS*>(pvResults));
1402 break; 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;
1403 default: 1426 default:
1404#ifdef DEBUG 1427#ifdef DEBUG
1405 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: Forwarding unknown BA message: %d", message); 1428 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "WIXSTDBA: Forwarding unknown BA message: %d", message);
@@ -2003,6 +2026,22 @@ private: // privates
2003 BalLogId(BOOTSTRAPPER_LOG_LEVEL_STANDARD, MSG_WIXSTDBA_PLANNED_ROLLBACK_BOUNDARY, m_hModule, pArgs->wzRollbackBoundaryId, LoggingBoolToString(fTransaction), LoggingBoolToString(pResults->fTransaction)); 2026 BalLogId(BOOTSTRAPPER_LOG_LEVEL_STANDARD, MSG_WIXSTDBA_PLANNED_ROLLBACK_BOUNDARY, m_hModule, pArgs->wzRollbackBoundaryId, LoggingBoolToString(fTransaction), LoggingBoolToString(pResults->fTransaction));
2004 } 2027 }
2005 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
2006 2045
2007public: //CBalBaseBootstrapperApplication 2046public: //CBalBaseBootstrapperApplication
2008 virtual STDMETHODIMP Initialize( 2047 virtual STDMETHODIMP Initialize(
diff --git a/src/test/burn/WixToolset.WixBA/InstallationViewModel.cs b/src/test/burn/WixToolset.WixBA/InstallationViewModel.cs
index 14ea561f..1846d51b 100644
--- a/src/test/burn/WixToolset.WixBA/InstallationViewModel.cs
+++ b/src/test/burn/WixToolset.WixBA/InstallationViewModel.cs
@@ -85,6 +85,7 @@ namespace WixToolset.WixBA
85 WixBA.Model.Bootstrapper.ExecutePackageComplete += this.ExecutePackageComplete; 85 WixBA.Model.Bootstrapper.ExecutePackageComplete += this.ExecutePackageComplete;
86 WixBA.Model.Bootstrapper.Error += this.ExecuteError; 86 WixBA.Model.Bootstrapper.Error += this.ExecuteError;
87 WixBA.Model.Bootstrapper.ApplyComplete += this.ApplyComplete; 87 WixBA.Model.Bootstrapper.ApplyComplete += this.ApplyComplete;
88 WixBA.Model.Bootstrapper.SetUpdateComplete += this.SetUpdateComplete;
88 } 89 }
89 90
90 void RootPropertyChanged(object sender, PropertyChangedEventArgs e) 91 void RootPropertyChanged(object sender, PropertyChangedEventArgs e)
@@ -409,6 +410,14 @@ namespace WixToolset.WixBA
409 } 410 }
410 } 411 }
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
412 private void DetectComplete(object sender, DetectCompleteEventArgs e) 421 private void DetectComplete(object sender, DetectCompleteEventArgs e)
413 { 422 {
414 // Parse the command line string before any planning. 423 // Parse the command line string before any planning.