aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h18
-rw-r--r--src/api/burn/balutil/inc/BAFunctions.h17
-rw-r--r--src/api/burn/balutil/inc/balutil.h1
-rw-r--r--src/burn/engine/engine.cpp4
-rw-r--r--src/burn/engine/userexperience.cpp15
-rw-r--r--src/burn/engine/userexperience.h4
-rw-r--r--src/ext/Bal/Samples/bafunctions/bafunctions.cpp2
-rw-r--r--src/ext/Bal/dnchost/dnchost.cpp51
-rw-r--r--src/ext/Bal/dnchost/dnchost.h8
-rw-r--r--src/ext/Bal/dnchost/dnchost.vcxproj2
-rw-r--r--src/ext/Bal/dnchost/precomp.h2
-rw-r--r--src/ext/Bal/mbahost/mbahost.cpp289
-rw-r--r--src/ext/Bal/mbahost/mbahost.h17
-rw-r--r--src/ext/Bal/mbahost/mbahost.vcxproj3
-rw-r--r--src/ext/Bal/mbahost/precomp.h17
-rw-r--r--src/ext/Bal/test/examples/TestEngine/ReloadEngine.cpp4
-rw-r--r--src/ext/Bal/test/examples/TestEngine/ShutdownEngine.cpp2
-rw-r--r--src/ext/Bal/test/examples/TestEngine/TestEngine.cpp16
-rw-r--r--src/ext/Bal/test/examples/TestEngine/TestEngine.h6
-rw-r--r--src/ext/Bal/test/examples/TestEngine/WaitForQuitEngine.cpp2
-rw-r--r--src/ext/Bal/wixstdba/Resources/1028/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/1029/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/1030/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/1031/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/1032/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/1035/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/1036/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/1038/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/1040/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/1041/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/1042/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/1043/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/1044/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/1045/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/1046/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/1049/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/1051/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/1053/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/1055/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/1060/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/2052/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/2070/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/3082/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/dncpreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/Resources/mbapreq.wxl1
-rw-r--r--src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp320
-rw-r--r--src/ext/Bal/wixstdba/inc/preqba.h16
-rw-r--r--src/ext/Bal/wixstdba/precomp.h66
-rw-r--r--src/ext/Bal/wixstdba/wixstdba.cpp54
-rw-r--r--src/ext/Bal/wixstdba/wixstdba.def6
-rw-r--r--src/ext/Bal/wixstdba/wixstdba.vcxproj1
-rw-r--r--src/test/burn/TestBA/TestBA.cs8
-rw-r--r--src/test/burn/TestData/Manual/BafThmutilTesting/precomp.cpp2
-rw-r--r--src/test/burn/WixToolset.WixBA/WixBA.cs9
-rw-r--r--src/test/burn/WixToolsetTest.BurnE2E/PrereqBaTests.cs6
55 files changed, 500 insertions, 493 deletions
diff --git a/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h b/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
index 228cb6ff..ea3be214 100644
--- a/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
+++ b/src/api/burn/WixToolset.BootstrapperCore.Native/inc/BootstrapperApplication.h
@@ -1494,7 +1494,22 @@ extern "C" typedef HRESULT(WINAPI *PFN_BOOTSTRAPPER_APPLICATION_PROC)(
1494 __in_opt LPVOID pvContext 1494 __in_opt LPVOID pvContext
1495 ); 1495 );
1496 1496
1497extern "C" typedef void (WINAPI *PFN_BOOTSTRAPPER_APPLICATION_DESTROY)(); 1497struct BOOTSTRAPPER_DESTROY_ARGS
1498{
1499 DWORD cbSize;
1500 BOOL fReload;
1501};
1502
1503struct BOOTSTRAPPER_DESTROY_RESULTS
1504{
1505 DWORD cbSize;
1506 BOOL fDisableUnloading; // indicates the BA dll must not be unloaded after BootstrapperApplicationDestroy.
1507};
1508
1509extern "C" typedef void (WINAPI *PFN_BOOTSTRAPPER_APPLICATION_DESTROY)(
1510 __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs,
1511 __inout BOOTSTRAPPER_DESTROY_RESULTS* pResults
1512 );
1498 1513
1499 1514
1500 1515
@@ -1512,7 +1527,6 @@ struct BOOTSTRAPPER_CREATE_RESULTS
1512 DWORD cbSize; 1527 DWORD cbSize;
1513 PFN_BOOTSTRAPPER_APPLICATION_PROC pfnBootstrapperApplicationProc; 1528 PFN_BOOTSTRAPPER_APPLICATION_PROC pfnBootstrapperApplicationProc;
1514 LPVOID pvBootstrapperApplicationProcContext; 1529 LPVOID pvBootstrapperApplicationProcContext;
1515 BOOL fDisableUnloading; // indicates the BA dll must not be unloaded after BootstrapperApplicationDestroy.
1516}; 1530};
1517 1531
1518extern "C" typedef HRESULT(WINAPI *PFN_BOOTSTRAPPER_APPLICATION_CREATE)( 1532extern "C" typedef HRESULT(WINAPI *PFN_BOOTSTRAPPER_APPLICATION_CREATE)(
diff --git a/src/api/burn/balutil/inc/BAFunctions.h b/src/api/burn/balutil/inc/BAFunctions.h
index c1057ab6..b23dd02e 100644
--- a/src/api/burn/balutil/inc/BAFunctions.h
+++ b/src/api/burn/balutil/inc/BAFunctions.h
@@ -126,6 +126,18 @@ struct BA_FUNCTIONS_CREATE_RESULTS
126 LPVOID pvBAFunctionsProcContext; 126 LPVOID pvBAFunctionsProcContext;
127}; 127};
128 128
129struct BA_FUNCTIONS_DESTROY_ARGS
130{
131 DWORD cbSize;
132 BOOL fReload;
133};
134
135struct BA_FUNCTIONS_DESTROY_RESULTS
136{
137 DWORD cbSize;
138 BOOL fDisableUnloading; // indicates the BAFunctions dll must not be unloaded after BAFunctionsDestroy.
139};
140
129struct BA_FUNCTIONS_ONTHEMECONTROLLOADED_ARGS 141struct BA_FUNCTIONS_ONTHEMECONTROLLOADED_ARGS
130{ 142{
131 DWORD cbSize; 143 DWORD cbSize;
@@ -218,7 +230,10 @@ typedef HRESULT(WINAPI *PFN_BA_FUNCTIONS_CREATE)(
218 __inout BA_FUNCTIONS_CREATE_RESULTS* pResults 230 __inout BA_FUNCTIONS_CREATE_RESULTS* pResults
219 ); 231 );
220 232
221typedef void (WINAPI *PFN_BA_FUNCTIONS_DESTROY)(); 233typedef void (WINAPI *PFN_BA_FUNCTIONS_DESTROY)(
234 __in const BA_FUNCTIONS_DESTROY_ARGS* pArgs,
235 __inout BA_FUNCTIONS_DESTROY_RESULTS* pResults
236 );
222 237
223#ifdef __cplusplus 238#ifdef __cplusplus
224} 239}
diff --git a/src/api/burn/balutil/inc/balutil.h b/src/api/burn/balutil/inc/balutil.h
index 2e370db7..33f1a6de 100644
--- a/src/api/burn/balutil/inc/balutil.h
+++ b/src/api/burn/balutil/inc/balutil.h
@@ -39,6 +39,7 @@ static const HRESULT E_WIXSTDBA_CONDITION_FAILED = MAKE_HRESULT(SEVERITY_ERROR,
39 39
40static const HRESULT E_MBAHOST_NET452_ON_WIN7RTM = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIX, 1000); 40static const HRESULT E_MBAHOST_NET452_ON_WIN7RTM = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIX, 1000);
41static const HRESULT E_DNCHOST_SCD_RUNTIME_FAILURE = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIX, 1001); 41static const HRESULT E_DNCHOST_SCD_RUNTIME_FAILURE = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIX, 1001);
42static const HRESULT E_PREREQBA_INFINITE_LOOP = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIX, 1002);
42 43
43 44
44/******************************************************************* 45/*******************************************************************
diff --git a/src/burn/engine/engine.cpp b/src/burn/engine/engine.cpp
index ee848acf..a408ed4a 100644
--- a/src/burn/engine/engine.cpp
+++ b/src/burn/engine/engine.cpp
@@ -796,7 +796,7 @@ LExit:
796 else if (BOOTSTRAPPER_SHUTDOWN_ACTION_RELOAD_BOOTSTRAPPER == shutdownAction) 796 else if (BOOTSTRAPPER_SHUTDOWN_ACTION_RELOAD_BOOTSTRAPPER == shutdownAction)
797 { 797 {
798 LogId(REPORT_STANDARD, MSG_BA_REQUESTED_RELOAD); 798 LogId(REPORT_STANDARD, MSG_BA_REQUESTED_RELOAD);
799 *pfReloadApp = TRUE; 799 *pfReloadApp = SUCCEEDED(hr);
800 } 800 }
801 else if (BOOTSTRAPPER_SHUTDOWN_ACTION_SKIP_CLEANUP == shutdownAction) 801 else if (BOOTSTRAPPER_SHUTDOWN_ACTION_SKIP_CLEANUP == shutdownAction)
802 { 802 {
@@ -806,7 +806,7 @@ LExit:
806 } 806 }
807 807
808 // Unload BA. 808 // Unload BA.
809 UserExperienceUnload(&pEngineState->userExperience); 809 UserExperienceUnload(&pEngineState->userExperience, *pfReloadApp);
810 810
811 return hr; 811 return hr;
812} 812}
diff --git a/src/burn/engine/userexperience.cpp b/src/burn/engine/userexperience.cpp
index 4325a6ee..87ef4de1 100644
--- a/src/burn/engine/userexperience.cpp
+++ b/src/burn/engine/userexperience.cpp
@@ -122,7 +122,6 @@ extern "C" HRESULT UserExperienceLoad(
122 122
123 pUserExperience->pfnBAProc = results.pfnBootstrapperApplicationProc; 123 pUserExperience->pfnBAProc = results.pfnBootstrapperApplicationProc;
124 pUserExperience->pvBAProcContext = results.pvBootstrapperApplicationProcContext; 124 pUserExperience->pvBAProcContext = results.pvBootstrapperApplicationProcContext;
125 pUserExperience->fDisableUnloading = results.fDisableUnloading;
126 125
127LExit: 126LExit:
128 return hr; 127 return hr;
@@ -133,10 +132,18 @@ LExit:
133 132
134*******************************************************************/ 133*******************************************************************/
135extern "C" HRESULT UserExperienceUnload( 134extern "C" HRESULT UserExperienceUnload(
136 __in BURN_USER_EXPERIENCE* pUserExperience 135 __in BURN_USER_EXPERIENCE* pUserExperience,
136 __in BOOL fReload
137 ) 137 )
138{ 138{
139 HRESULT hr = S_OK; 139 HRESULT hr = S_OK;
140 BOOTSTRAPPER_DESTROY_ARGS args = { };
141 BOOTSTRAPPER_DESTROY_RESULTS results = { };
142
143 args.cbSize = sizeof(BOOTSTRAPPER_DESTROY_ARGS);
144 args.fReload = fReload;
145
146 results.cbSize = sizeof(BOOTSTRAPPER_DESTROY_RESULTS);
140 147
141 if (pUserExperience->hUXModule) 148 if (pUserExperience->hUXModule)
142 { 149 {
@@ -144,11 +151,11 @@ extern "C" HRESULT UserExperienceUnload(
144 PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = (PFN_BOOTSTRAPPER_APPLICATION_DESTROY)::GetProcAddress(pUserExperience->hUXModule, "BootstrapperApplicationDestroy"); 151 PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = (PFN_BOOTSTRAPPER_APPLICATION_DESTROY)::GetProcAddress(pUserExperience->hUXModule, "BootstrapperApplicationDestroy");
145 if (pfnDestroy) 152 if (pfnDestroy)
146 { 153 {
147 pfnDestroy(); 154 pfnDestroy(&args, &results);
148 } 155 }
149 156
150 // Free BA DLL if it supports it. 157 // Free BA DLL if it supports it.
151 if (!pUserExperience->fDisableUnloading && !::FreeLibrary(pUserExperience->hUXModule)) 158 if (!results.fDisableUnloading && !::FreeLibrary(pUserExperience->hUXModule))
152 { 159 {
153 hr = HRESULT_FROM_WIN32(::GetLastError()); 160 hr = HRESULT_FROM_WIN32(::GetLastError());
154 TraceError(hr, "Failed to unload BA DLL."); 161 TraceError(hr, "Failed to unload BA DLL.");
diff --git a/src/burn/engine/userexperience.h b/src/burn/engine/userexperience.h
index e7489710..94b73f7d 100644
--- a/src/burn/engine/userexperience.h
+++ b/src/burn/engine/userexperience.h
@@ -22,7 +22,6 @@ typedef struct _BURN_USER_EXPERIENCE
22 HMODULE hUXModule; 22 HMODULE hUXModule;
23 PFN_BOOTSTRAPPER_APPLICATION_PROC pfnBAProc; 23 PFN_BOOTSTRAPPER_APPLICATION_PROC pfnBAProc;
24 LPVOID pvBAProcContext; 24 LPVOID pvBAProcContext;
25 BOOL fDisableUnloading;
26 LPWSTR sczTempDirectory; 25 LPWSTR sczTempDirectory;
27 26
28 CRITICAL_SECTION csEngineActive; // Changing the engine active state in the user experience must be 27 CRITICAL_SECTION csEngineActive; // Changing the engine active state in the user experience must be
@@ -61,7 +60,8 @@ HRESULT UserExperienceLoad(
61 __in BOOTSTRAPPER_COMMAND* pCommand 60 __in BOOTSTRAPPER_COMMAND* pCommand
62 ); 61 );
63HRESULT UserExperienceUnload( 62HRESULT UserExperienceUnload(
64 __in BURN_USER_EXPERIENCE* pUserExperience 63 __in BURN_USER_EXPERIENCE* pUserExperience,
64 __in BOOL fReload
65 ); 65 );
66HRESULT UserExperienceEnsureWorkingFolder( 66HRESULT UserExperienceEnsureWorkingFolder(
67 __in BURN_CACHE* pCache, 67 __in BURN_CACHE* pCache,
diff --git a/src/ext/Bal/Samples/bafunctions/bafunctions.cpp b/src/ext/Bal/Samples/bafunctions/bafunctions.cpp
index b20f4230..fc9d1177 100644
--- a/src/ext/Bal/Samples/bafunctions/bafunctions.cpp
+++ b/src/ext/Bal/Samples/bafunctions/bafunctions.cpp
@@ -40,6 +40,8 @@ LExit:
40} 40}
41 41
42extern "C" void WINAPI BAFunctionsDestroy( 42extern "C" void WINAPI BAFunctionsDestroy(
43 __in const BA_FUNCTIONS_DESTROY_ARGS* /*pArgs*/,
44 __inout BA_FUNCTIONS_DESTROY_RESULTS* /*pResults*/
43 ) 45 )
44{ 46{
45 BalUninitialize(); 47 BalUninitialize();
diff --git a/src/ext/Bal/dnchost/dnchost.cpp b/src/ext/Bal/dnchost/dnchost.cpp
index 644ba30e..6c066f43 100644
--- a/src/ext/Bal/dnchost/dnchost.cpp
+++ b/src/ext/Bal/dnchost/dnchost.cpp
@@ -21,9 +21,8 @@ static HRESULT LoadManagedBootstrapperApplicationFactory(
21 __in DNCSTATE* pState 21 __in DNCSTATE* pState
22 ); 22 );
23static HRESULT CreatePrerequisiteBA( 23static HRESULT CreatePrerequisiteBA(
24 __in HRESULT hrHostInitialization, 24 __in DNCSTATE* pState,
25 __in IBootstrapperEngine* pEngine, 25 __in IBootstrapperEngine* pEngine,
26 __in LPCWSTR wzAppBase,
27 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, 26 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
28 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults 27 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
29 ); 28 );
@@ -58,13 +57,8 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate(
58 ) 57 )
59{ 58{
60 HRESULT hr = S_OK; 59 HRESULT hr = S_OK;
61 HRESULT hrHostInitialization = S_OK;
62 IBootstrapperEngine* pEngine = NULL; 60 IBootstrapperEngine* pEngine = NULL;
63 61
64 // coreclr.dll doesn't support unloading, so the rest of the .NET Core hosting stack doesn't support it either.
65 // This means we also can't unload.
66 pResults->fDisableUnloading = TRUE;
67
68 hr = BalInitializeFromCreateArgs(pArgs, &pEngine); 62 hr = BalInitializeFromCreateArgs(pArgs, &pEngine);
69 ExitOnFailure(hr, "Failed to initialize Bal."); 63 ExitOnFailure(hr, "Failed to initialize Bal.");
70 64
@@ -106,16 +100,22 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate(
106 { 100 {
107 if (DNCHOSTTYPE_SCD == vstate.type) 101 if (DNCHOSTTYPE_SCD == vstate.type)
108 { 102 {
109 hrHostInitialization = E_DNCHOST_SCD_RUNTIME_FAILURE; 103 vstate.prereqData.hrHostInitialization = E_DNCHOST_SCD_RUNTIME_FAILURE;
110 BalLogError(hr, "The self-contained .NET Core runtime failed to load. This is an unrecoverable error."); 104 BalLogError(hr, "The self-contained .NET Core runtime failed to load. This is an unrecoverable error.");
111 } 105 }
106 else if (vstate.prereqData.fCompleted)
107 {
108 hr = E_PREREQBA_INFINITE_LOOP;
109 BalLogError(hr, "The prerequisites were already installed. The bootstrapper application will not be reloaded to prevent an infinite loop.");
110 vstate.prereqData.hrHostInitialization = hr;
111 }
112 else 112 else
113 { 113 {
114 hrHostInitialization = S_OK; 114 vstate.prereqData.hrHostInitialization = S_OK;
115 } 115 }
116 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application because .NET Core host could not be loaded, error: 0x%08x.", hr); 116 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application because .NET Core host could not be loaded, error: 0x%08x.", hr);
117 117
118 hr = CreatePrerequisiteBA(hrHostInitialization, pEngine, vstate.sczAppBase, pArgs, pResults); 118 hr = CreatePrerequisiteBA(&vstate, pEngine, pArgs, pResults);
119 BalExitOnFailure(hr, "Failed to create the pre-requisite bootstrapper application."); 119 BalExitOnFailure(hr, "Failed to create the pre-requisite bootstrapper application.");
120 } 120 }
121 121
@@ -125,14 +125,21 @@ LExit:
125 return hr; 125 return hr;
126} 126}
127 127
128extern "C" void WINAPI BootstrapperApplicationDestroy() 128extern "C" void WINAPI BootstrapperApplicationDestroy(
129 __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs,
130 __in BOOTSTRAPPER_DESTROY_RESULTS* pResults
131 )
129{ 132{
133 BOOTSTRAPPER_DESTROY_RESULTS childResults = { };
134
135 childResults.cbSize = sizeof(BOOTSTRAPPER_DESTROY_RESULTS);
136
130 if (vstate.hMbapreqModule) 137 if (vstate.hMbapreqModule)
131 { 138 {
132 PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = reinterpret_cast<PFN_BOOTSTRAPPER_APPLICATION_DESTROY>(::GetProcAddress(vstate.hMbapreqModule, "DncPrereqBootstrapperApplicationDestroy")); 139 PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = reinterpret_cast<PFN_BOOTSTRAPPER_APPLICATION_DESTROY>(::GetProcAddress(vstate.hMbapreqModule, "PrereqBootstrapperApplicationDestroy"));
133 if (pfnDestroy) 140 if (pfnDestroy)
134 { 141 {
135 (*pfnDestroy)(); 142 (*pfnDestroy)(pArgs, &childResults);
136 } 143 }
137 144
138 ::FreeLibrary(vstate.hMbapreqModule); 145 ::FreeLibrary(vstate.hMbapreqModule);
@@ -140,6 +147,9 @@ extern "C" void WINAPI BootstrapperApplicationDestroy()
140 } 147 }
141 148
142 BalUninitialize(); 149 BalUninitialize();
150
151 // Need to keep track of state between reloads.
152 pResults->fDisableUnloading = TRUE;
143} 153}
144 154
145static HRESULT LoadModulePaths( 155static HRESULT LoadModulePaths(
@@ -262,9 +272,8 @@ static HRESULT LoadManagedBootstrapperApplicationFactory(
262} 272}
263 273
264static HRESULT CreatePrerequisiteBA( 274static HRESULT CreatePrerequisiteBA(
265 __in HRESULT hrHostInitialization, 275 __in DNCSTATE* pState,
266 __in IBootstrapperEngine* pEngine, 276 __in IBootstrapperEngine* pEngine,
267 __in LPCWSTR wzAppBase,
268 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, 277 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
269 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults 278 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
270 ) 279 )
@@ -273,19 +282,19 @@ static HRESULT CreatePrerequisiteBA(
273 LPWSTR sczDncpreqPath = NULL; 282 LPWSTR sczDncpreqPath = NULL;
274 HMODULE hModule = NULL; 283 HMODULE hModule = NULL;
275 284
276 hr = PathConcat(wzAppBase, L"dncpreq.dll", &sczDncpreqPath); 285 hr = PathConcat(pState->sczAppBase, L"dncpreq.dll", &sczDncpreqPath);
277 BalExitOnFailure(hr, "Failed to get path to pre-requisite BA."); 286 BalExitOnFailure(hr, "Failed to get path to pre-requisite BA.");
278 287
279 hModule = ::LoadLibraryW(sczDncpreqPath); 288 hModule = ::LoadLibraryExW(sczDncpreqPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
280 BalExitOnNullWithLastError(hModule, hr, "Failed to load pre-requisite BA DLL."); 289 BalExitOnNullWithLastError(hModule, hr, "Failed to load pre-requisite BA DLL.");
281 290
282 PFN_DNCPREQ_BOOTSTRAPPER_APPLICATION_CREATE pfnCreate = reinterpret_cast<PFN_DNCPREQ_BOOTSTRAPPER_APPLICATION_CREATE>(::GetProcAddress(hModule, "DncPrereqBootstrapperApplicationCreate")); 291 PFN_PREQ_BOOTSTRAPPER_APPLICATION_CREATE pfnCreate = reinterpret_cast<PFN_PREQ_BOOTSTRAPPER_APPLICATION_CREATE>(::GetProcAddress(hModule, "PrereqBootstrapperApplicationCreate"));
283 BalExitOnNullWithLastError(pfnCreate, hr, "Failed to get DncPrereqBootstrapperApplicationCreate entry-point from: %ls", sczDncpreqPath); 292 BalExitOnNullWithLastError(pfnCreate, hr, "Failed to get PrereqBootstrapperApplicationCreate entry-point from: %ls", sczDncpreqPath);
284 293
285 hr = pfnCreate(hrHostInitialization, pEngine, pArgs, pResults); 294 hr = pfnCreate(&pState->prereqData, pEngine, pArgs, pResults);
286 BalExitOnFailure(hr, "Failed to create prequisite bootstrapper app."); 295 BalExitOnFailure(hr, "Failed to create prequisite bootstrapper app.");
287 296
288 vstate.hMbapreqModule = hModule; 297 pState->hMbapreqModule = hModule;
289 hModule = NULL; 298 hModule = NULL;
290 299
291LExit: 300LExit:
diff --git a/src/ext/Bal/dnchost/dnchost.h b/src/ext/Bal/dnchost/dnchost.h
index b0ba9638..000cf43d 100644
--- a/src/ext/Bal/dnchost/dnchost.h
+++ b/src/ext/Bal/dnchost/dnchost.h
@@ -9,13 +9,6 @@ enum DNCHOSTTYPE
9 DNCHOSTTYPE_SCD, 9 DNCHOSTTYPE_SCD,
10}; 10};
11 11
12extern "C" typedef HRESULT(WINAPI* PFN_DNCPREQ_BOOTSTRAPPER_APPLICATION_CREATE)(
13 __in HRESULT hrHostInitialization,
14 __in IBootstrapperEngine* pEngine,
15 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
16 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
17 );
18
19struct DNCSTATE 12struct DNCSTATE
20{ 13{
21 BOOL fInitialized; 14 BOOL fInitialized;
@@ -31,4 +24,5 @@ struct DNCSTATE
31 HOSTFXR_STATE hostfxrState; 24 HOSTFXR_STATE hostfxrState;
32 IBootstrapperApplicationFactory* pAppFactory; 25 IBootstrapperApplicationFactory* pAppFactory;
33 HMODULE hMbapreqModule; 26 HMODULE hMbapreqModule;
27 PREQBA_DATA prereqData;
34}; 28};
diff --git a/src/ext/Bal/dnchost/dnchost.vcxproj b/src/ext/Bal/dnchost/dnchost.vcxproj
index ca0c09d6..b258ccae 100644
--- a/src/ext/Bal/dnchost/dnchost.vcxproj
+++ b/src/ext/Bal/dnchost/dnchost.vcxproj
@@ -50,7 +50,7 @@
50 <NetHostPlatform>$(Platform)</NetHostPlatform> 50 <NetHostPlatform>$(Platform)</NetHostPlatform>
51 <NetHostPlatform Condition=" '$(NetHostPlatform)'=='Win32' ">x86</NetHostPlatform> 51 <NetHostPlatform Condition=" '$(NetHostPlatform)'=='Win32' ">x86</NetHostPlatform>
52 <NetHostPath>..\..\..\..\packages\runtime.win-$(NetHostPlatform).Microsoft.NETCore.DotNetAppHost.6.0.4\runtimes\win-$(NetHostPlatform)\native\</NetHostPath> 52 <NetHostPath>..\..\..\..\packages\runtime.win-$(NetHostPlatform).Microsoft.NETCore.DotNetAppHost.6.0.4\runtimes\win-$(NetHostPlatform)\native\</NetHostPath>
53 <ProjectAdditionalIncludeDirectories>$(BaseOutputPath)obj;$(NetHostPath)</ProjectAdditionalIncludeDirectories> 53 <ProjectAdditionalIncludeDirectories>$(BaseOutputPath)obj;$(NetHostPath);..\wixstdba\inc</ProjectAdditionalIncludeDirectories>
54 <ProjectAdditionalLinkLibraries>shlwapi.lib;$(NetHostPath)libnethost.lib</ProjectAdditionalLinkLibraries> 54 <ProjectAdditionalLinkLibraries>shlwapi.lib;$(NetHostPath)libnethost.lib</ProjectAdditionalLinkLibraries>
55 </PropertyGroup> 55 </PropertyGroup>
56 56
diff --git a/src/ext/Bal/dnchost/precomp.h b/src/ext/Bal/dnchost/precomp.h
index 7aefc4e3..5f365fba 100644
--- a/src/ext/Bal/dnchost/precomp.h
+++ b/src/ext/Bal/dnchost/precomp.h
@@ -25,6 +25,8 @@
25#include <hostfxr.h> 25#include <hostfxr.h>
26#include <coreclr_delegates.h> 26#include <coreclr_delegates.h>
27 27
28#include <preqba.h>
29
28#include "coreclrhost.h" 30#include "coreclrhost.h"
29#include "dncutil.h" 31#include "dncutil.h"
30#include "dnchost.h" 32#include "dnchost.h"
diff --git a/src/ext/Bal/mbahost/mbahost.cpp b/src/ext/Bal/mbahost/mbahost.cpp
index a9585389..3de77a05 100644
--- a/src/ext/Bal/mbahost/mbahost.cpp
+++ b/src/ext/Bal/mbahost/mbahost.cpp
@@ -1,7 +1,6 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. 1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2 2
3#include "precomp.h" 3#include "precomp.h"
4#include <WixToolset.Mba.Host.h> // includes the generated assembly name macros.
5 4
6static const DWORD NET452_RELEASE = 379893; 5static const DWORD NET452_RELEASE = 379893;
7 6
@@ -14,26 +13,16 @@ extern "C" typedef HRESULT (WINAPI *PFN_CORBINDTOCURRENTRUNTIME)(
14 __out LPVOID *ppv 13 __out LPVOID *ppv
15 ); 14 );
16 15
17extern "C" typedef HRESULT(WINAPI *PFN_MBAPREQ_BOOTSTRAPPER_APPLICATION_CREATE)( 16static MBASTATE vstate = { };
18 __in HRESULT hrHostInitialization,
19 __in IBootstrapperEngine* pEngine,
20 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
21 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
22 );
23
24static HINSTANCE vhInstance = NULL;
25static ICorRuntimeHost *vpCLRHost = NULL;
26static _AppDomain *vpAppDomain = NULL;
27static HMODULE vhMbapreqModule = NULL;
28 17
29 18
30// internal function declarations 19// internal function declarations
31 20
32static HRESULT GetAppDomain( 21static HRESULT GetAppDomain(
33 __out _AppDomain** ppAppDomain 22 __in MBASTATE* pState
34 ); 23 );
35static HRESULT GetAppBase( 24static HRESULT LoadModulePaths(
36 __out LPWSTR* psczAppBase 25 __in MBASTATE* pState
37 ); 26 );
38static HRESULT CheckSupportedFrameworks( 27static HRESULT CheckSupportedFrameworks(
39 __in LPCWSTR wzConfigPath 28 __in LPCWSTR wzConfigPath
@@ -43,9 +32,8 @@ static HRESULT UpdateSupportedRuntime(
43 __in IXMLDOMNode* pixnSupportedFramework, 32 __in IXMLDOMNode* pixnSupportedFramework,
44 __out BOOL* pfUpdatedManifest 33 __out BOOL* pfUpdatedManifest
45 ); 34 );
46static HRESULT GetCLRHost( 35static HRESULT LoadRuntime(
47 __in LPCWSTR wzConfigPath, 36 __in MBASTATE* pState
48 __out ICorRuntimeHost** ppCLRHost
49 ); 37 );
50static HRESULT CreateManagedBootstrapperApplication( 38static HRESULT CreateManagedBootstrapperApplication(
51 __in _AppDomain* pAppDomain, 39 __in _AppDomain* pAppDomain,
@@ -57,7 +45,7 @@ static HRESULT CreateManagedBootstrapperApplicationFactory(
57 __out IBootstrapperApplicationFactory** ppAppFactory 45 __out IBootstrapperApplicationFactory** ppAppFactory
58 ); 46 );
59static HRESULT CreatePrerequisiteBA( 47static HRESULT CreatePrerequisiteBA(
60 __in HRESULT hrHostInitialization, 48 __in MBASTATE* pState,
61 __in IBootstrapperEngine* pEngine, 49 __in IBootstrapperEngine* pEngine,
62 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, 50 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
63 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults 51 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
@@ -78,11 +66,11 @@ extern "C" BOOL WINAPI DllMain(
78 { 66 {
79 case DLL_PROCESS_ATTACH: 67 case DLL_PROCESS_ATTACH:
80 ::DisableThreadLibraryCalls(hInstance); 68 ::DisableThreadLibraryCalls(hInstance);
81 vhInstance = hInstance; 69 vstate.hInstance = hInstance;
82 break; 70 break;
83 71
84 case DLL_PROCESS_DETACH: 72 case DLL_PROCESS_DETACH:
85 vhInstance = NULL; 73 vstate.hInstance = NULL;
86 break; 74 break;
87 } 75 }
88 76
@@ -96,18 +84,39 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate(
96 ) 84 )
97{ 85{
98 HRESULT hr = S_OK; 86 HRESULT hr = S_OK;
99 HRESULT hrHostInitialization = S_OK;
100 IBootstrapperEngine* pEngine = NULL; 87 IBootstrapperEngine* pEngine = NULL;
101 88
89 if (vstate.fStoppedRuntime)
90 {
91 BalExitWithRootFailure(hr, E_INVALIDSTATE, "Reloaded mbahost after stopping .NET runtime.");
92 }
93
102 hr = BalInitializeFromCreateArgs(pArgs, &pEngine); 94 hr = BalInitializeFromCreateArgs(pArgs, &pEngine);
103 ExitOnFailure(hr, "Failed to initialize Bal."); 95 ExitOnFailure(hr, "Failed to initialize Bal.");
104 96
105 hr = GetAppDomain(&vpAppDomain); 97 if (!vstate.fInitialized)
106 if (SUCCEEDED(hr)) 98 {
99 hr = LoadModulePaths(&vstate);
100 BalExitOnFailure(hr, "Failed to load the module paths.");
101
102 vstate.fInitialized = TRUE;
103 }
104
105 if (!vstate.fInitializedRuntime)
106 {
107 hr = LoadRuntime(&vstate);
108
109 vstate.fInitializedRuntime = SUCCEEDED(hr);
110 }
111
112 if (vstate.fInitializedRuntime)
107 { 113 {
114 hr = GetAppDomain(&vstate);
115 BalExitOnFailure(hr, "Failed to create the AppDomain for the managed bootstrapper application.");
116
108 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading managed bootstrapper application."); 117 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading managed bootstrapper application.");
109 118
110 hr = CreateManagedBootstrapperApplication(vpAppDomain, pArgs, pResults); 119 hr = CreateManagedBootstrapperApplication(vstate.pAppDomain, pArgs, pResults);
111 BalExitOnFailure(hr, "Failed to create the managed bootstrapper application."); 120 BalExitOnFailure(hr, "Failed to create the managed bootstrapper application.");
112 } 121 }
113 else // fallback to the prerequisite BA. 122 else // fallback to the prerequisite BA.
@@ -115,16 +124,22 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate(
115 if (E_MBAHOST_NET452_ON_WIN7RTM == hr) 124 if (E_MBAHOST_NET452_ON_WIN7RTM == hr)
116 { 125 {
117 BalLogError(hr, "The Burn engine cannot run with an MBA under the .NET 4 CLR on Windows 7 RTM with .NET 4.5.2 (or greater) installed."); 126 BalLogError(hr, "The Burn engine cannot run with an MBA under the .NET 4 CLR on Windows 7 RTM with .NET 4.5.2 (or greater) installed.");
118 hrHostInitialization = hr; 127 vstate.prereqData.hrHostInitialization = hr;
128 }
129 else if (vstate.prereqData.fCompleted)
130 {
131 hr = E_PREREQBA_INFINITE_LOOP;
132 BalLogError(hr, "The prerequisites were already installed. The bootstrapper application will not be reloaded to prevent an infinite loop.");
133 vstate.prereqData.hrHostInitialization = hr;
119 } 134 }
120 else 135 else
121 { 136 {
122 hrHostInitialization = S_OK; 137 vstate.prereqData.hrHostInitialization = S_OK;
123 } 138 }
124 139
125 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application because managed host could not be loaded, error: 0x%08x.", hr); 140 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application because managed host could not be loaded, error: 0x%08x.", hr);
126 141
127 hr = CreatePrerequisiteBA(hrHostInitialization, pEngine, pArgs, pResults); 142 hr = CreatePrerequisiteBA(&vstate, pEngine, pArgs, pResults);
128 BalExitOnFailure(hr, "Failed to create the pre-requisite bootstrapper application."); 143 BalExitOnFailure(hr, "Failed to create the pre-requisite bootstrapper application.");
129 } 144 }
130 145
@@ -134,73 +149,65 @@ LExit:
134 return hr; 149 return hr;
135} 150}
136 151
137extern "C" void WINAPI BootstrapperApplicationDestroy() 152extern "C" void WINAPI BootstrapperApplicationDestroy(
153 __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs,
154 __in BOOTSTRAPPER_DESTROY_RESULTS* pResults
155 )
138{ 156{
139 if (vpAppDomain) 157 BOOTSTRAPPER_DESTROY_RESULTS childResults = { };
158
159 if (vstate.pAppDomain)
140 { 160 {
141 HRESULT hr = vpCLRHost->UnloadDomain(vpAppDomain); 161 HRESULT hr = vstate.pCLRHost->UnloadDomain(vstate.pAppDomain);
142 if (FAILED(hr)) 162 if (FAILED(hr))
143 { 163 {
144 BalLogError(hr, "Failed to unload app domain."); 164 BalLogError(hr, "Failed to unload app domain.");
145 } 165 }
146 166
147 vpAppDomain->Release(); 167 vstate.pAppDomain->Release();
168 vstate.pAppDomain = NULL;
148 } 169 }
149 170
150 if (vpCLRHost) 171 // pCLRHost can only be stopped once per process.
172 if (vstate.pCLRHost && !pArgs->fReload)
151 { 173 {
152 vpCLRHost->Stop(); 174 vstate.pCLRHost->Stop();
153 vpCLRHost->Release(); 175 vstate.pCLRHost->Release();
176 vstate.pCLRHost = NULL;
177 vstate.fStoppedRuntime = TRUE;
154 } 178 }
155 179
156 if (vhMbapreqModule) 180 if (vstate.hMbapreqModule)
157 { 181 {
158 PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = reinterpret_cast<PFN_BOOTSTRAPPER_APPLICATION_DESTROY>(::GetProcAddress(vhMbapreqModule, "MbaPrereqBootstrapperApplicationDestroy")); 182 PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = reinterpret_cast<PFN_BOOTSTRAPPER_APPLICATION_DESTROY>(::GetProcAddress(vstate.hMbapreqModule, "PrereqBootstrapperApplicationDestroy"));
159 if (pfnDestroy) 183 if (pfnDestroy)
160 { 184 {
161 (*pfnDestroy)(); 185 (*pfnDestroy)(pArgs, &childResults);
162 } 186 }
163 187
164 ::FreeLibrary(vhMbapreqModule); 188 ::FreeLibrary(vstate.hMbapreqModule);
165 vhMbapreqModule = NULL; 189 vstate.hMbapreqModule = NULL;
166 } 190 }
167 191
168 BalUninitialize(); 192 BalUninitialize();
193
194 // Need to keep track of state between reloads.
195 pResults->fDisableUnloading = TRUE;
169} 196}
170 197
171// Gets the custom AppDomain for loading managed BA. 198// Gets the custom AppDomain for loading managed BA.
172static HRESULT GetAppDomain( 199static HRESULT GetAppDomain(
173 __out _AppDomain **ppAppDomain 200 __in MBASTATE* pState
174 ) 201 )
175{ 202{
176 HRESULT hr = S_OK; 203 HRESULT hr = S_OK;
177 ICorRuntimeHost *pCLRHost = NULL;
178 IUnknown *pUnk = NULL; 204 IUnknown *pUnk = NULL;
179 LPWSTR sczAppBase = NULL; 205 IAppDomainSetup* pAppDomainSetup = NULL;
180 LPWSTR sczConfigPath = NULL;
181 IAppDomainSetup *pAppDomainSetup;
182 BSTR bstrAppBase = NULL; 206 BSTR bstrAppBase = NULL;
183 BSTR bstrConfigPath = NULL; 207 BSTR bstrConfigPath = NULL;
184 208
185 hr = GetAppBase(&sczAppBase);
186 ExitOnFailure(hr, "Failed to get the host base path.");
187
188 hr = PathConcat(sczAppBase, MBA_CONFIG_FILE_NAME, &sczConfigPath);
189 ExitOnFailure(hr, "Failed to get the full path to the application configuration file.");
190
191 // Check that the supported framework is installed.
192 hr = CheckSupportedFrameworks(sczConfigPath);
193 ExitOnFailure(hr, "Failed to find supported framework.");
194
195 // Load the CLR.
196 hr = GetCLRHost(sczConfigPath, &pCLRHost);
197 ExitOnFailure(hr, "Failed to create the CLR host.");
198
199 hr = pCLRHost->Start();
200 ExitOnRootFailure(hr, "Failed to start the CLR host.");
201
202 // Create the setup information for a new AppDomain to set the app base and config. 209 // Create the setup information for a new AppDomain to set the app base and config.
203 hr = pCLRHost->CreateDomainSetup(&pUnk); 210 hr = pState->pCLRHost->CreateDomainSetup(&pUnk);
204 ExitOnRootFailure(hr, "Failed to create the AppDomainSetup object."); 211 ExitOnRootFailure(hr, "Failed to create the AppDomainSetup object.");
205 212
206 hr = pUnk->QueryInterface(__uuidof(IAppDomainSetup), reinterpret_cast<LPVOID*>(&pAppDomainSetup)); 213 hr = pUnk->QueryInterface(__uuidof(IAppDomainSetup), reinterpret_cast<LPVOID*>(&pAppDomainSetup));
@@ -208,49 +215,49 @@ static HRESULT GetAppDomain(
208 ReleaseNullObject(pUnk); 215 ReleaseNullObject(pUnk);
209 216
210 // Set properties on the AppDomainSetup object. 217 // Set properties on the AppDomainSetup object.
211 bstrAppBase = ::SysAllocString(sczAppBase); 218 bstrAppBase = ::SysAllocString(pState->sczAppBase);
212 ExitOnNull(bstrAppBase, hr, E_OUTOFMEMORY, "Failed to allocate the application base path for the AppDomainSetup."); 219 ExitOnNull(bstrAppBase, hr, E_OUTOFMEMORY, "Failed to allocate the application base path for the AppDomainSetup.");
213 220
214 hr = pAppDomainSetup->put_ApplicationBase(bstrAppBase); 221 hr = pAppDomainSetup->put_ApplicationBase(bstrAppBase);
215 ExitOnRootFailure(hr, "Failed to set the application base path for the AppDomainSetup."); 222 ExitOnRootFailure(hr, "Failed to set the application base path for the AppDomainSetup.");
216 223
217 bstrConfigPath = ::SysAllocString(sczConfigPath); 224 bstrConfigPath = ::SysAllocString(pState->sczConfigPath);
218 ExitOnNull(bstrConfigPath, hr, E_OUTOFMEMORY, "Failed to allocate the application configuration file for the AppDomainSetup."); 225 ExitOnNull(bstrConfigPath, hr, E_OUTOFMEMORY, "Failed to allocate the application configuration file for the AppDomainSetup.");
219 226
220 hr = pAppDomainSetup->put_ConfigurationFile(bstrConfigPath); 227 hr = pAppDomainSetup->put_ConfigurationFile(bstrConfigPath);
221 ExitOnRootFailure(hr, "Failed to set the configuration file path for the AppDomainSetup."); 228 ExitOnRootFailure(hr, "Failed to set the configuration file path for the AppDomainSetup.");
222 229
223 // Create the AppDomain to load the factory type. 230 // Create the AppDomain to load the factory type.
224 hr = pCLRHost->CreateDomainEx(L"MBA", pAppDomainSetup, NULL, &pUnk); 231 hr = pState->pCLRHost->CreateDomainEx(L"MBA", pAppDomainSetup, NULL, &pUnk);
225 ExitOnRootFailure(hr, "Failed to create the MBA AppDomain."); 232 ExitOnRootFailure(hr, "Failed to create the MBA AppDomain.");
226 233
227 hr = pUnk->QueryInterface(__uuidof(_AppDomain), reinterpret_cast<LPVOID*>(ppAppDomain)); 234 hr = pUnk->QueryInterface(__uuidof(_AppDomain), reinterpret_cast<LPVOID*>(&pState->pAppDomain));
228 ExitOnRootFailure(hr, "Failed to query for the _AppDomain interface."); 235 ExitOnRootFailure(hr, "Failed to query for the _AppDomain interface.");
229 236
230LExit: 237LExit:
231 ReleaseBSTR(bstrConfigPath); 238 ReleaseBSTR(bstrConfigPath);
232 ReleaseBSTR(bstrAppBase); 239 ReleaseBSTR(bstrAppBase);
233 ReleaseStr(sczConfigPath);
234 ReleaseStr(sczAppBase);
235 ReleaseNullObject(pUnk); 240 ReleaseNullObject(pUnk);
236 ReleaseNullObject(pCLRHost);
237 241
238 return hr; 242 return hr;
239} 243}
240 244
241static HRESULT GetAppBase( 245static HRESULT LoadModulePaths(
242 __out LPWSTR *psczAppBase 246 __in MBASTATE* pState
243 ) 247 )
244{ 248{
245 HRESULT hr = S_OK; 249 HRESULT hr = S_OK;
246 LPWSTR sczFullPath = NULL; 250 LPWSTR sczFullPath = NULL;
247 251
248 hr = PathForCurrentProcess(&sczFullPath, vhInstance); 252 hr = PathForCurrentProcess(&sczFullPath, pState->hInstance);
249 ExitOnFailure(hr, "Failed to get the full host path."); 253 ExitOnFailure(hr, "Failed to get the full host path.");
250 254
251 hr = PathGetDirectory(sczFullPath, psczAppBase); 255 hr = PathGetDirectory(sczFullPath, &pState->sczAppBase);
252 ExitOnFailure(hr, "Failed to get the directory of the full process path."); 256 ExitOnFailure(hr, "Failed to get the directory of the full process path.");
253 257
258 hr = PathConcat(pState->sczAppBase, MBA_CONFIG_FILE_NAME, &pState->sczConfigPath);
259 ExitOnFailure(hr, "Failed to get the full path to the application configuration file.");
260
254LExit: 261LExit:
255 ReleaseStr(sczFullPath); 262 ReleaseStr(sczFullPath);
256 263
@@ -390,9 +397,8 @@ LExit:
390} 397}
391 398
392// Gets the CLR host and caches it. 399// Gets the CLR host and caches it.
393static HRESULT GetCLRHost( 400static HRESULT LoadRuntime(
394 __in LPCWSTR wzConfigPath, 401 __in MBASTATE* pState
395 __out ICorRuntimeHost **ppCLRHost
396 ) 402 )
397{ 403{
398 HRESULT hr = S_OK; 404 HRESULT hr = S_OK;
@@ -411,84 +417,81 @@ static HRESULT GetCLRHost(
411 // Always set the error mode because we will always restore it below. 417 // Always set the error mode because we will always restore it below.
412 uiMode = ::SetErrorMode(0); 418 uiMode = ::SetErrorMode(0);
413 419
414 // Cache the CLR host to be shutdown later. This can occur on a different thread. 420 // Check that the supported framework is installed.
415 if (!vpCLRHost) 421 hr = CheckSupportedFrameworks(pState->sczConfigPath);
416 { 422 ExitOnFailure(hr, "Failed to find supported framework.");
417 // Disable message boxes from being displayed on error and blocking execution.
418 ::SetErrorMode(uiMode | SEM_FAILCRITICALERRORS);
419 423
420 hr = LoadSystemLibrary(L"mscoree.dll", &hModule); 424 // Cache the CLR host to be shutdown later. This can occur on a different thread.
421 ExitOnFailure(hr, "Failed to load mscoree.dll"); 425 // Disable message boxes from being displayed on error and blocking execution.
426 ::SetErrorMode(uiMode | SEM_FAILCRITICALERRORS);
422 427
423 pfnCLRCreateInstance = reinterpret_cast<CLRCreateInstanceFnPtr>(::GetProcAddress(hModule, "CLRCreateInstance")); 428 hr = LoadSystemLibrary(L"mscoree.dll", &hModule);
424 429 ExitOnFailure(hr, "Failed to load mscoree.dll");
425 if (pfnCLRCreateInstance)
426 {
427 hr = pfnCLRCreateInstance(CLSID_CLRMetaHostPolicy, IID_ICLRMetaHostPolicy, reinterpret_cast<LPVOID*>(&pCLRMetaHostPolicy));
428 if (E_NOTIMPL != hr)
429 {
430 ExitOnRootFailure(hr, "Failed to create instance of ICLRMetaHostPolicy.");
431 430
432 fFallbackToCorBindToCurrentRuntime = FALSE; 431 pfnCLRCreateInstance = reinterpret_cast<CLRCreateInstanceFnPtr>(::GetProcAddress(hModule, "CLRCreateInstance"));
433 }
434 }
435 432
436 if (fFallbackToCorBindToCurrentRuntime) 433 if (pfnCLRCreateInstance)
434 {
435 hr = pfnCLRCreateInstance(CLSID_CLRMetaHostPolicy, IID_ICLRMetaHostPolicy, reinterpret_cast<LPVOID*>(&pCLRMetaHostPolicy));
436 if (E_NOTIMPL != hr)
437 { 437 {
438 pfnCorBindToCurrentRuntime = reinterpret_cast<PFN_CORBINDTOCURRENTRUNTIME>(::GetProcAddress(hModule, "CorBindToCurrentRuntime")); 438 ExitOnRootFailure(hr, "Failed to create instance of ICLRMetaHostPolicy.");
439 ExitOnNullWithLastError(pfnCorBindToCurrentRuntime, hr, "Failed to get procedure address for CorBindToCurrentRuntime.");
440 439
441 hr = pfnCorBindToCurrentRuntime(wzConfigPath, CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast<LPVOID*>(&vpCLRHost)); 440 fFallbackToCorBindToCurrentRuntime = FALSE;
442 ExitOnRootFailure(hr, "Failed to create the CLR host using the application configuration file path.");
443 } 441 }
444 else 442 }
445 {
446
447 hr = SHCreateStreamOnFileEx(wzConfigPath, STGM_READ | STGM_SHARE_DENY_WRITE, 0, FALSE, NULL, &pCfgStream);
448 ExitOnFailure(hr, "Failed to load bootstrapper config file from path: %ls", wzConfigPath);
449 443
450 hr = pCLRMetaHostPolicy->GetRequestedRuntime(METAHOST_POLICY_HIGHCOMPAT, NULL, pCfgStream, NULL, &cchVersion, NULL, NULL, &dwConfigFlags, IID_ICLRRuntimeInfo, reinterpret_cast<LPVOID*>(&pCLRRuntimeInfo)); 444 if (fFallbackToCorBindToCurrentRuntime)
451 ExitOnRootFailure(hr, "Failed to get the CLR runtime info using the application configuration file path."); 445 {
446 pfnCorBindToCurrentRuntime = reinterpret_cast<PFN_CORBINDTOCURRENTRUNTIME>(::GetProcAddress(hModule, "CorBindToCurrentRuntime"));
447 ExitOnNullWithLastError(pfnCorBindToCurrentRuntime, hr, "Failed to get procedure address for CorBindToCurrentRuntime.");
452 448
453 // .NET 4 RTM had a bug where it wouldn't set pcchVersion if pwzVersion was NULL. 449 hr = pfnCorBindToCurrentRuntime(pState->sczConfigPath, CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast<LPVOID*>(&pState->pCLRHost));
454 if (!cchVersion) 450 ExitOnRootFailure(hr, "Failed to create the CLR host using the application configuration file path.");
455 { 451 }
456 hr = pCLRRuntimeInfo->GetVersionString(NULL, &cchVersion); 452 else
457 if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) != hr) 453 {
458 {
459 ExitOnFailure(hr, "Failed to get the length of the CLR version string.");
460 }
461 }
462 454
463 hr = StrAlloc(&pwzVersion, cchVersion); 455 hr = SHCreateStreamOnFileEx(pState->sczConfigPath, STGM_READ | STGM_SHARE_DENY_WRITE, 0, FALSE, NULL, &pCfgStream);
464 ExitOnFailure(hr, "Failed to allocate the CLR version string."); 456 ExitOnFailure(hr, "Failed to load bootstrapper config file from path: %ls", pState->sczConfigPath);
465 457
466 hr = pCLRRuntimeInfo->GetVersionString(pwzVersion, &cchVersion); 458 hr = pCLRMetaHostPolicy->GetRequestedRuntime(METAHOST_POLICY_HIGHCOMPAT, NULL, pCfgStream, NULL, &cchVersion, NULL, NULL, &dwConfigFlags, IID_ICLRRuntimeInfo, reinterpret_cast<LPVOID*>(&pCLRRuntimeInfo));
467 ExitOnFailure(hr, "Failed to get the CLR version string."); 459 ExitOnRootFailure(hr, "Failed to get the CLR runtime info using the application configuration file path.");
468 460
469 if (CSTR_EQUAL == CompareString(LOCALE_NEUTRAL, 0, L"v4.0.30319", -1, pwzVersion, cchVersion)) 461 // .NET 4 RTM had a bug where it wouldn't set pcchVersion if pwzVersion was NULL.
462 if (!cchVersion)
463 {
464 hr = pCLRRuntimeInfo->GetVersionString(NULL, &cchVersion);
465 if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) != hr)
470 { 466 {
471 hr = VerifyNET4RuntimeIsSupported(); 467 ExitOnFailure(hr, "Failed to get the length of the CLR version string.");
472 ExitOnFailure(hr, "Found unsupported .NET 4 Runtime.");
473 } 468 }
469 }
474 470
475 if (METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_TRUE == (METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_MASK & dwConfigFlags)) 471 hr = StrAlloc(&pwzVersion, cchVersion);
476 { 472 ExitOnFailure(hr, "Failed to allocate the CLR version string.");
477 hr = pCLRRuntimeInfo->BindAsLegacyV2Runtime();
478 ExitOnRootFailure(hr, "Failed to bind as legacy V2 runtime.");
479 }
480 473
481 hr = pCLRRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast<LPVOID*>(&vpCLRHost)); 474 hr = pCLRRuntimeInfo->GetVersionString(pwzVersion, &cchVersion);
482 ExitOnRootFailure(hr, "Failed to get instance of ICorRuntimeHost."); 475 ExitOnFailure(hr, "Failed to get the CLR version string.");
476
477 if (CSTR_EQUAL == CompareString(LOCALE_NEUTRAL, 0, L"v4.0.30319", -1, pwzVersion, cchVersion))
478 {
479 hr = VerifyNET4RuntimeIsSupported();
480 ExitOnFailure(hr, "Found unsupported .NET 4 Runtime.");
481 }
483 482
484 // TODO: use ICLRRuntimeHost instead of ICorRuntimeHost on .NET 4 since the former is faster and the latter is deprecated 483 if (METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_TRUE == (METAHOST_CONFIG_FLAGS_LEGACY_V2_ACTIVATION_POLICY_MASK & dwConfigFlags))
485 //hr = pCLRRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, reinterpret_cast<LPVOID*>(&pCLRRuntimeHost)); 484 {
486 //ExitOnRootFailure(hr, "Failed to get instance of ICLRRuntimeHost."); 485 hr = pCLRRuntimeInfo->BindAsLegacyV2Runtime();
486 ExitOnRootFailure(hr, "Failed to bind as legacy V2 runtime.");
487 } 487 }
488
489 hr = pCLRRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_ICorRuntimeHost, reinterpret_cast<LPVOID*>(&pState->pCLRHost));
490 ExitOnRootFailure(hr, "Failed to get instance of ICorRuntimeHost.");
488 } 491 }
489 492
490 vpCLRHost->AddRef(); 493 hr = pState->pCLRHost->Start();
491 *ppCLRHost = vpCLRHost; 494 ExitOnRootFailure(hr, "Failed to start the CLR host.");
492 495
493LExit: 496LExit:
494 ReleaseStr(pwzVersion); 497 ReleaseStr(pwzVersion);
@@ -569,7 +572,7 @@ LExit:
569} 572}
570 573
571static HRESULT CreatePrerequisiteBA( 574static HRESULT CreatePrerequisiteBA(
572 __in HRESULT hrHostInitialization, 575 __in MBASTATE* pState,
573 __in IBootstrapperEngine* pEngine, 576 __in IBootstrapperEngine* pEngine,
574 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, 577 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
575 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults 578 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
@@ -579,19 +582,19 @@ static HRESULT CreatePrerequisiteBA(
579 LPWSTR sczMbapreqPath = NULL; 582 LPWSTR sczMbapreqPath = NULL;
580 HMODULE hModule = NULL; 583 HMODULE hModule = NULL;
581 584
582 hr = PathRelativeToModule(&sczMbapreqPath, L"mbapreq.dll", vhInstance); 585 hr = PathConcat(pState->sczAppBase, L"mbapreq.dll", &sczMbapreqPath);
583 ExitOnFailure(hr, "Failed to get path to pre-requisite BA."); 586 BalExitOnFailure(hr, "Failed to get path to pre-requisite BA.");
584 587
585 hModule = ::LoadLibraryW(sczMbapreqPath); 588 hModule = ::LoadLibraryExW(sczMbapreqPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
586 ExitOnNullWithLastError(hModule, hr, "Failed to load pre-requisite BA DLL."); 589 ExitOnNullWithLastError(hModule, hr, "Failed to load pre-requisite BA DLL.");
587 590
588 PFN_MBAPREQ_BOOTSTRAPPER_APPLICATION_CREATE pfnCreate = reinterpret_cast<PFN_MBAPREQ_BOOTSTRAPPER_APPLICATION_CREATE>(::GetProcAddress(hModule, "MbaPrereqBootstrapperApplicationCreate")); 591 PFN_PREQ_BOOTSTRAPPER_APPLICATION_CREATE pfnCreate = reinterpret_cast<PFN_PREQ_BOOTSTRAPPER_APPLICATION_CREATE>(::GetProcAddress(hModule, "PrereqBootstrapperApplicationCreate"));
589 ExitOnNullWithLastError(pfnCreate, hr, "Failed to get MbaPrereqBootstrapperApplicationCreate entry-point from: %ls", sczMbapreqPath); 592 ExitOnNullWithLastError(pfnCreate, hr, "Failed to get PrereqBootstrapperApplicationCreate entry-point from: %ls", sczMbapreqPath);
590 593
591 hr = pfnCreate(hrHostInitialization, pEngine, pArgs, pResults); 594 hr = pfnCreate(&pState->prereqData, pEngine, pArgs, pResults);
592 ExitOnFailure(hr, "Failed to create prequisite bootstrapper app."); 595 ExitOnFailure(hr, "Failed to create prequisite bootstrapper app.");
593 596
594 vhMbapreqModule = hModule; 597 pState->hMbapreqModule = hModule;
595 hModule = NULL; 598 hModule = NULL;
596 599
597LExit: 600LExit:
diff --git a/src/ext/Bal/mbahost/mbahost.h b/src/ext/Bal/mbahost/mbahost.h
new file mode 100644
index 00000000..19cf8311
--- /dev/null
+++ b/src/ext/Bal/mbahost/mbahost.h
@@ -0,0 +1,17 @@
1#pragma once
2// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
3
4
5struct MBASTATE
6{
7 BOOL fInitialized;
8 BOOL fInitializedRuntime;
9 BOOL fStoppedRuntime;
10 HINSTANCE hInstance;
11 LPWSTR sczAppBase;
12 LPWSTR sczConfigPath;
13 mscorlib::_AppDomain* pAppDomain;
14 ICorRuntimeHost* pCLRHost;
15 HMODULE hMbapreqModule;
16 PREQBA_DATA prereqData;
17};
diff --git a/src/ext/Bal/mbahost/mbahost.vcxproj b/src/ext/Bal/mbahost/mbahost.vcxproj
index cd90776b..a8fbbcc2 100644
--- a/src/ext/Bal/mbahost/mbahost.vcxproj
+++ b/src/ext/Bal/mbahost/mbahost.vcxproj
@@ -41,7 +41,7 @@
41 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> 41 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
42 42
43 <PropertyGroup> 43 <PropertyGroup>
44 <ProjectAdditionalIncludeDirectories>$(BaseOutputPath)obj</ProjectAdditionalIncludeDirectories> 44 <ProjectAdditionalIncludeDirectories>$(BaseOutputPath)obj;..\wixstdba\inc</ProjectAdditionalIncludeDirectories>
45 <ProjectAdditionalLinkLibraries>shlwapi.lib</ProjectAdditionalLinkLibraries> 45 <ProjectAdditionalLinkLibraries>shlwapi.lib</ProjectAdditionalLinkLibraries>
46 </PropertyGroup> 46 </PropertyGroup>
47 47
@@ -52,6 +52,7 @@
52 </ClCompile> 52 </ClCompile>
53 </ItemGroup> 53 </ItemGroup>
54 <ItemGroup> 54 <ItemGroup>
55 <ClInclude Include="mbahost.h" />
55 <ClInclude Include="precomp.h" /> 56 <ClInclude Include="precomp.h" />
56 </ItemGroup> 57 </ItemGroup>
57 <ItemGroup> 58 <ItemGroup>
diff --git a/src/ext/Bal/mbahost/precomp.h b/src/ext/Bal/mbahost/precomp.h
index d29a23f3..a07f2fc0 100644
--- a/src/ext/Bal/mbahost/precomp.h
+++ b/src/ext/Bal/mbahost/precomp.h
@@ -16,10 +16,15 @@
16#include <strutil.h> 16#include <strutil.h>
17#include <xmlutil.h> 17#include <xmlutil.h>
18 18
19#include "BootstrapperEngine.h" 19#include <BootstrapperEngine.h>
20#include "BootstrapperApplication.h" 20#include <BootstrapperApplication.h>
21#include "IBootstrapperEngine.h" 21#include <IBootstrapperEngine.h>
22#include "IBootstrapperApplication.h" 22#include <IBootstrapperApplication.h>
23#include "IBootstrapperApplicationFactory.h" 23#include <IBootstrapperApplicationFactory.h>
24 24
25#include "balutil.h" 25#include <balutil.h>
26
27#include <preqba.h>
28#include <WixToolset.Mba.Host.h> // includes the generated assembly name macros.
29
30#include "mbahost.h"
diff --git a/src/ext/Bal/test/examples/TestEngine/ReloadEngine.cpp b/src/ext/Bal/test/examples/TestEngine/ReloadEngine.cpp
index 46fd9afa..3f290b86 100644
--- a/src/ext/Bal/test/examples/TestEngine/ReloadEngine.cpp
+++ b/src/ext/Bal/test/examples/TestEngine/ReloadEngine.cpp
@@ -31,7 +31,7 @@ HRESULT RunReloadEngine(
31 hr = pTestEngine->SendShutdownEvent(BOOTSTRAPPER_SHUTDOWN_ACTION_RELOAD_BOOTSTRAPPER); 31 hr = pTestEngine->SendShutdownEvent(BOOTSTRAPPER_SHUTDOWN_ACTION_RELOAD_BOOTSTRAPPER);
32 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "BA returned failure for OnShutdown."); 32 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "BA returned failure for OnShutdown.");
33 33
34 pTestEngine->UnloadBA(); 34 pTestEngine->UnloadBA(TRUE);
35 35
36 hr = pTestEngine->LoadBA(wzBAFilePath); 36 hr = pTestEngine->LoadBA(wzBAFilePath);
37 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to load BA."); 37 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Failed to load BA.");
@@ -48,7 +48,7 @@ HRESULT RunReloadEngine(
48 hr = pTestEngine->SendShutdownEvent(BOOTSTRAPPER_SHUTDOWN_ACTION_RESTART); 48 hr = pTestEngine->SendShutdownEvent(BOOTSTRAPPER_SHUTDOWN_ACTION_RESTART);
49 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "BA returned failure for OnShutdown."); 49 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "BA returned failure for OnShutdown.");
50 50
51 pTestEngine->UnloadBA(); 51 pTestEngine->UnloadBA(FALSE);
52 52
53LExit: 53LExit:
54 return hr; 54 return hr;
diff --git a/src/ext/Bal/test/examples/TestEngine/ShutdownEngine.cpp b/src/ext/Bal/test/examples/TestEngine/ShutdownEngine.cpp
index 3b876e4e..b5c8c462 100644
--- a/src/ext/Bal/test/examples/TestEngine/ShutdownEngine.cpp
+++ b/src/ext/Bal/test/examples/TestEngine/ShutdownEngine.cpp
@@ -31,7 +31,7 @@ HRESULT RunShutdownEngine(
31 hr = pTestEngine->SendShutdownEvent(BOOTSTRAPPER_SHUTDOWN_ACTION_RELOAD_BOOTSTRAPPER); 31 hr = pTestEngine->SendShutdownEvent(BOOTSTRAPPER_SHUTDOWN_ACTION_RELOAD_BOOTSTRAPPER);
32 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "BA returned failure for OnShutdown."); 32 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "BA returned failure for OnShutdown.");
33 33
34 pTestEngine->UnloadBA(); 34 pTestEngine->UnloadBA(FALSE);
35 35
36LExit: 36LExit:
37 return hr; 37 return hr;
diff --git a/src/ext/Bal/test/examples/TestEngine/TestEngine.cpp b/src/ext/Bal/test/examples/TestEngine/TestEngine.cpp
index 4c7ec1c3..5c6ed398 100644
--- a/src/ext/Bal/test/examples/TestEngine/TestEngine.cpp
+++ b/src/ext/Bal/test/examples/TestEngine/TestEngine.cpp
@@ -147,10 +147,18 @@ HRESULT TestEngine::SimulateQuit(
147 return BAEngineQuit(&args, &results); 147 return BAEngineQuit(&args, &results);
148} 148}
149 149
150void TestEngine::UnloadBA() 150void TestEngine::UnloadBA(
151 __in BOOL fReload
152 )
151{ 153{
152 PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = NULL; 154 PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = NULL;
153 BOOL fDisableUnloading = m_pCreateResults && m_pCreateResults->fDisableUnloading; 155 BOOTSTRAPPER_DESTROY_ARGS args = { };
156 BOOTSTRAPPER_DESTROY_RESULTS results = { };
157
158 args.cbSize = sizeof(args);
159 args.fReload = fReload;
160
161 results.cbSize = sizeof(results);
154 162
155 ReleaseNullMem(m_pCreateResults); 163 ReleaseNullMem(m_pCreateResults);
156 164
@@ -158,12 +166,12 @@ void TestEngine::UnloadBA()
158 166
159 if (pfnDestroy) 167 if (pfnDestroy)
160 { 168 {
161 pfnDestroy(); 169 pfnDestroy(&args, &results);
162 } 170 }
163 171
164 if (m_hBAModule) 172 if (m_hBAModule)
165 { 173 {
166 if (!fDisableUnloading) 174 if (!results.fDisableUnloading)
167 { 175 {
168 ::FreeLibrary(m_hBAModule); 176 ::FreeLibrary(m_hBAModule);
169 } 177 }
diff --git a/src/ext/Bal/test/examples/TestEngine/TestEngine.h b/src/ext/Bal/test/examples/TestEngine/TestEngine.h
index 44e813bd..248e979a 100644
--- a/src/ext/Bal/test/examples/TestEngine/TestEngine.h
+++ b/src/ext/Bal/test/examples/TestEngine/TestEngine.h
@@ -44,7 +44,9 @@ public:
44 __in DWORD dwExitCode 44 __in DWORD dwExitCode
45 ); 45 );
46 46
47 void UnloadBA(); 47 void UnloadBA(
48 __in BOOL fReload
49 );
48 50
49private: 51private:
50 HRESULT BAEngineLog( 52 HRESULT BAEngineLog(
@@ -77,4 +79,4 @@ private:
77 HMODULE m_hBAModule; 79 HMODULE m_hBAModule;
78 BOOTSTRAPPER_CREATE_RESULTS* m_pCreateResults; 80 BOOTSTRAPPER_CREATE_RESULTS* m_pCreateResults;
79 DWORD m_dwThreadId; 81 DWORD m_dwThreadId;
80}; \ No newline at end of file 82};
diff --git a/src/ext/Bal/test/examples/TestEngine/WaitForQuitEngine.cpp b/src/ext/Bal/test/examples/TestEngine/WaitForQuitEngine.cpp
index 2f80ba75..64b618f4 100644
--- a/src/ext/Bal/test/examples/TestEngine/WaitForQuitEngine.cpp
+++ b/src/ext/Bal/test/examples/TestEngine/WaitForQuitEngine.cpp
@@ -28,7 +28,7 @@ HRESULT RunWaitForQuitEngine(
28 hr = pTestEngine->SendShutdownEvent(BOOTSTRAPPER_SHUTDOWN_ACTION_RELOAD_BOOTSTRAPPER); 28 hr = pTestEngine->SendShutdownEvent(BOOTSTRAPPER_SHUTDOWN_ACTION_RELOAD_BOOTSTRAPPER);
29 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "BA returned failure for OnShutdown."); 29 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "BA returned failure for OnShutdown.");
30 30
31 pTestEngine->UnloadBA(); 31 pTestEngine->UnloadBA(FALSE);
32 32
33LExit: 33LExit:
34 return hr; 34 return hr;
diff --git a/src/ext/Bal/wixstdba/Resources/1028/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1028/mbapreq.wxl
index 19e79bac..f574bb9b 100644
--- a/src/ext/Bal/wixstdba/Resources/1028/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/1028/mbapreq.wxl
@@ -29,5 +29,6 @@
29 <String Id="FailureRestartButton">重新啟動(&amp;R)</String> 29 <String Id="FailureRestartButton">重新啟動(&amp;R)</String>
30 <String Id="FailureCloseButton">關閉(&amp;C)</String> 30 <String Id="FailureCloseButton">關閉(&amp;C)</String>
31 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 31 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
32 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
32 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 33 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
33</WixLocalization> 34</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/1029/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1029/mbapreq.wxl
index e6e6f469..11d9f85a 100644
--- a/src/ext/Bal/wixstdba/Resources/1029/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/1029/mbapreq.wxl
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Restartovat</String> 32 <String Id="FailureRestartButton">&amp;Restartovat</String>
33 <String Id="FailureCloseButton">&amp;Zavřít</String> 33 <String Id="FailureCloseButton">&amp;Zavřít</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
35 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
36</WixLocalization> 37</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/1030/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1030/mbapreq.wxl
index 98518edc..50412e12 100644
--- a/src/ext/Bal/wixstdba/Resources/1030/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/1030/mbapreq.wxl
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Genstart</String> 32 <String Id="FailureRestartButton">&amp;Genstart</String>
33 <String Id="FailureCloseButton">&amp;Luk</String> 33 <String Id="FailureCloseButton">&amp;Luk</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
35 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
36</WixLocalization> 37</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/1031/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1031/mbapreq.wxl
index e60b0c9a..4df66298 100644
--- a/src/ext/Bal/wixstdba/Resources/1031/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/1031/mbapreq.wxl
@@ -35,5 +35,6 @@
35 <String Id="FailureRestartButton">&amp;Neu starten</String> 35 <String Id="FailureRestartButton">&amp;Neu starten</String>
36 <String Id="FailureCloseButton">&amp;Schließen</String> 36 <String Id="FailureCloseButton">&amp;Schließen</String>
37 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 37 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
38 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
38 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 39 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
39</WixLocalization> 40</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/1032/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1032/mbapreq.wxl
index ea5dc130..05ac553f 100644
--- a/src/ext/Bal/wixstdba/Resources/1032/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/1032/mbapreq.wxl
@@ -34,5 +34,6 @@
34 <String Id="FailureRestartButton">&amp;Επανεκκίνηση</String> 34 <String Id="FailureRestartButton">&amp;Επανεκκίνηση</String>
35 <String Id="FailureCloseButton">&amp;Κλείσιμο</String> 35 <String Id="FailureCloseButton">&amp;Κλείσιμο</String>
36 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 36 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
37 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
37 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 38 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
38</WixLocalization> 39</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/1035/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1035/mbapreq.wxl
index 803cacf5..2b7c0519 100644
--- a/src/ext/Bal/wixstdba/Resources/1035/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/1035/mbapreq.wxl
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Käynnistä uudelleen</String> 32 <String Id="FailureRestartButton">&amp;Käynnistä uudelleen</String>
33 <String Id="FailureCloseButton">&amp;Sulje</String> 33 <String Id="FailureCloseButton">&amp;Sulje</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
35 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
36</WixLocalization> 37</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/1036/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1036/mbapreq.wxl
index fb927f2b..3ae1cbd9 100644
--- a/src/ext/Bal/wixstdba/Resources/1036/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/1036/mbapreq.wxl
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Redémarrer</String> 32 <String Id="FailureRestartButton">&amp;Redémarrer</String>
33 <String Id="FailureCloseButton">&amp;Fermer</String> 33 <String Id="FailureCloseButton">&amp;Fermer</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
35 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
36</WixLocalization> 37</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/1038/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1038/mbapreq.wxl
index 78c008b2..f491d6f2 100644
--- a/src/ext/Bal/wixstdba/Resources/1038/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/1038/mbapreq.wxl
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Újraindítás</String> 32 <String Id="FailureRestartButton">&amp;Újraindítás</String>
33 <String Id="FailureCloseButton">&amp;Bezárás</String> 33 <String Id="FailureCloseButton">&amp;Bezárás</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
35 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
36</WixLocalization> 37</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/1040/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1040/mbapreq.wxl
index b7966340..50bc73e8 100644
--- a/src/ext/Bal/wixstdba/Resources/1040/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/1040/mbapreq.wxl
@@ -33,5 +33,6 @@
33 <String Id="FailureRestartButton">&amp;Riavvia</String> 33 <String Id="FailureRestartButton">&amp;Riavvia</String>
34 <String Id="FailureCloseButton">&amp;Chiudi</String> 34 <String Id="FailureCloseButton">&amp;Chiudi</String>
35 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 35 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
36 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 37 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
37</WixLocalization> 38</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/1041/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1041/mbapreq.wxl
index 9b7aa323..106c704a 100644
--- a/src/ext/Bal/wixstdba/Resources/1041/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/1041/mbapreq.wxl
@@ -29,5 +29,6 @@
29 <String Id="FailureRestartButton">再起動(&amp;R)</String> 29 <String Id="FailureRestartButton">再起動(&amp;R)</String>
30 <String Id="FailureCloseButton">閉じる(&amp;C)</String> 30 <String Id="FailureCloseButton">閉じる(&amp;C)</String>
31 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 31 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
32 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
32 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 33 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
33</WixLocalization> 34</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/1042/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1042/mbapreq.wxl
index 445d445b..24655588 100644
--- a/src/ext/Bal/wixstdba/Resources/1042/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/1042/mbapreq.wxl
@@ -29,5 +29,6 @@
29 <String Id="FailureRestartButton">다시 시작(&amp;R)</String> 29 <String Id="FailureRestartButton">다시 시작(&amp;R)</String>
30 <String Id="FailureCloseButton">닫기(&amp;C)</String> 30 <String Id="FailureCloseButton">닫기(&amp;C)</String>
31 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 31 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
32 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
32 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 33 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
33</WixLocalization> 34</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/1043/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1043/mbapreq.wxl
index 60ba996e..d2e572fc 100644
--- a/src/ext/Bal/wixstdba/Resources/1043/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/1043/mbapreq.wxl
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Opnieuw opstarten</String> 32 <String Id="FailureRestartButton">&amp;Opnieuw opstarten</String>
33 <String Id="FailureCloseButton">&amp;Sluiten</String> 33 <String Id="FailureCloseButton">&amp;Sluiten</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
35 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
36</WixLocalization> 37</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/1044/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1044/mbapreq.wxl
index e0718b8d..cb6036ee 100644
--- a/src/ext/Bal/wixstdba/Resources/1044/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/1044/mbapreq.wxl
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Start på nytt</String> 32 <String Id="FailureRestartButton">&amp;Start på nytt</String>
33 <String Id="FailureCloseButton">&amp;Lukk</String> 33 <String Id="FailureCloseButton">&amp;Lukk</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
35 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
36</WixLocalization> 37</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/1045/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1045/mbapreq.wxl
index 8b4eb758..41832b13 100644
--- a/src/ext/Bal/wixstdba/Resources/1045/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/1045/mbapreq.wxl
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Uruchom ponownie</String> 32 <String Id="FailureRestartButton">&amp;Uruchom ponownie</String>
33 <String Id="FailureCloseButton">&amp;Zamknij</String> 33 <String Id="FailureCloseButton">&amp;Zamknij</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
35 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
36</WixLocalization> 37</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/1046/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1046/mbapreq.wxl
index 0155eb39..08968f93 100644
--- a/src/ext/Bal/wixstdba/Resources/1046/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/1046/mbapreq.wxl
@@ -31,5 +31,6 @@
31 <String Id="FailureRestartButton">&amp;Reiniciar</String> 31 <String Id="FailureRestartButton">&amp;Reiniciar</String>
32 <String Id="FailureCloseButton">&amp;Fechar</String> 32 <String Id="FailureCloseButton">&amp;Fechar</String>
33 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 33 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
34 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
34 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 35 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
35</WixLocalization> 36</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/1049/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1049/mbapreq.wxl
index 87350745..271d5563 100644
--- a/src/ext/Bal/wixstdba/Resources/1049/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/1049/mbapreq.wxl
@@ -31,5 +31,6 @@
31 <String Id="FailureRestartButton">&amp;Перезагрузить</String> 31 <String Id="FailureRestartButton">&amp;Перезагрузить</String>
32 <String Id="FailureCloseButton">&amp;Закрыть</String> 32 <String Id="FailureCloseButton">&amp;Закрыть</String>
33 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 33 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
34 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
34 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 35 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
35</WixLocalization> 36</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/1051/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1051/mbapreq.wxl
index 7645a37f..ce6f6eda 100644
--- a/src/ext/Bal/wixstdba/Resources/1051/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/1051/mbapreq.wxl
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Reštartovať</String> 32 <String Id="FailureRestartButton">&amp;Reštartovať</String>
33 <String Id="FailureCloseButton">&amp;Zavrieť</String> 33 <String Id="FailureCloseButton">&amp;Zavrieť</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
35 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
36</WixLocalization> 37</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/1053/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1053/mbapreq.wxl
index b00205d8..2d0581b1 100644
--- a/src/ext/Bal/wixstdba/Resources/1053/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/1053/mbapreq.wxl
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Starta om</String> 32 <String Id="FailureRestartButton">&amp;Starta om</String>
33 <String Id="FailureCloseButton">&amp;Stäng</String> 33 <String Id="FailureCloseButton">&amp;Stäng</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
35 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
36</WixLocalization> 37</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/1055/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1055/mbapreq.wxl
index 00c3c187..c48a44da 100644
--- a/src/ext/Bal/wixstdba/Resources/1055/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/1055/mbapreq.wxl
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Yeniden Başlat</String> 32 <String Id="FailureRestartButton">&amp;Yeniden Başlat</String>
33 <String Id="FailureCloseButton">&amp;Kapat</String> 33 <String Id="FailureCloseButton">&amp;Kapat</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
35 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
36</WixLocalization> 37</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/1060/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/1060/mbapreq.wxl
index 72d48267..0398a7f1 100644
--- a/src/ext/Bal/wixstdba/Resources/1060/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/1060/mbapreq.wxl
@@ -32,5 +32,6 @@
32 <String Id="FailureRestartButton">&amp;Ponovni zagon</String> 32 <String Id="FailureRestartButton">&amp;Ponovni zagon</String>
33 <String Id="FailureCloseButton">&amp;Zapri</String> 33 <String Id="FailureCloseButton">&amp;Zapri</String>
34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 34 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
35 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
35 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
36</WixLocalization> 37</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/2052/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/2052/mbapreq.wxl
index 365ee7e6..09f09cb3 100644
--- a/src/ext/Bal/wixstdba/Resources/2052/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/2052/mbapreq.wxl
@@ -29,5 +29,6 @@
29 <String Id="FailureRestartButton">重启(&amp;R)</String> 29 <String Id="FailureRestartButton">重启(&amp;R)</String>
30 <String Id="FailureCloseButton">关闭(&amp;C)</String> 30 <String Id="FailureCloseButton">关闭(&amp;C)</String>
31 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 31 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
32 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
32 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 33 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
33</WixLocalization> 34</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/2070/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/2070/mbapreq.wxl
index 442a5571..f22822d8 100644
--- a/src/ext/Bal/wixstdba/Resources/2070/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/2070/mbapreq.wxl
@@ -31,5 +31,6 @@
31 <String Id="FailureRestartButton">&amp;Reiniciar</String> 31 <String Id="FailureRestartButton">&amp;Reiniciar</String>
32 <String Id="FailureCloseButton">&amp;Fechar</String> 32 <String Id="FailureCloseButton">&amp;Fechar</String>
33 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 33 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
34 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
34 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 35 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
35</WixLocalization> 36</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/3082/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/3082/mbapreq.wxl
index 37c0dc05..edbf01c4 100644
--- a/src/ext/Bal/wixstdba/Resources/3082/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/3082/mbapreq.wxl
@@ -33,5 +33,6 @@
33 <String Id="FailureRestartButton">&amp;Reiniciar</String> 33 <String Id="FailureRestartButton">&amp;Reiniciar</String>
34 <String Id="FailureCloseButton">&amp;Cerrar</String> 34 <String Id="FailureCloseButton">&amp;Cerrar</String>
35 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 35 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
36 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
36 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 37 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
37</WixLocalization> 38</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/dncpreq.wxl b/src/ext/Bal/wixstdba/Resources/dncpreq.wxl
index a53b1c83..22fcd3dc 100644
--- a/src/ext/Bal/wixstdba/Resources/dncpreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/dncpreq.wxl
@@ -29,5 +29,6 @@
29 <String Id="FailureRestartButton">&amp;Restart</String> 29 <String Id="FailureRestartButton">&amp;Restart</String>
30 <String Id="FailureCloseButton">&amp;Close</String> 30 <String Id="FailureCloseButton">&amp;Close</String>
31 <String Id="SCDRUNTIMEFAILUREErrorMessage">[WixBundleName] cannot run on this machine. Install the latest updates and/or the latest OS to run in a supported environment.</String> 31 <String Id="SCDRUNTIMEFAILUREErrorMessage">[WixBundleName] cannot run on this machine. Install the latest updates and/or the latest OS to run in a supported environment.</String>
32 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Core runtime even though all of the prerequisites are installed.</String>
32 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 33 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
33</WixLocalization> 34</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/Resources/mbapreq.wxl b/src/ext/Bal/wixstdba/Resources/mbapreq.wxl
index 5d410888..77859d31 100644
--- a/src/ext/Bal/wixstdba/Resources/mbapreq.wxl
+++ b/src/ext/Bal/wixstdba/Resources/mbapreq.wxl
@@ -29,5 +29,6 @@
29 <String Id="FailureRestartButton">&amp;Restart</String> 29 <String Id="FailureRestartButton">&amp;Restart</String>
30 <String Id="FailureCloseButton">&amp;Close</String> 30 <String Id="FailureCloseButton">&amp;Close</String>
31 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String> 31 <String Id="NET452WIN7RTMErrorMessage">[WixBundleName] cannot run on Windows 7 RTM with .NET 4.5.2 installed. Install Windows 7 SP1 to run in a supported environment.</String>
32 <String Id="PREREQBAINFINITELOOPErrorMessage">[WixBundleName] failed to load the .NET Framework runtime even though all of the prerequisites are installed.</String>
32 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String> 33 <String Id="ErrorFailNoActionReboot">No action was taken as a system reboot is required.</String>
33</WixLocalization> 34</WixLocalization>
diff --git a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
index dd00a563..3774f49c 100644
--- a/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
+++ b/src/ext/Bal/wixstdba/WixStandardBootstrapperApplication.cpp
@@ -123,14 +123,6 @@ enum WIXSTDBA_CONTROL
123 LAST_WIXSTDBA_CONTROL, 123 LAST_WIXSTDBA_CONTROL,
124}; 124};
125 125
126typedef struct _WIXSTDBA_PACKAGE_INFO
127{
128 LPWSTR sczPackageId;
129 BOOL fWasAlreadyInstalled;
130 BOOL fPlannedToBeInstalled;
131 BOOL fSuccessfullyInstalled;
132} WIXSTDBA_PACKAGE_INFO;
133
134 126
135static HRESULT DAPI EvaluateVariableConditionCallback( 127static HRESULT DAPI EvaluateVariableConditionCallback(
136 __in_z LPCWSTR wzCondition, 128 __in_z LPCWSTR wzCondition,
@@ -229,10 +221,7 @@ public: // IBootstrapperApplication
229 { 221 {
230 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "The prerequisites were successfully installed. The bootstrapper application will be reloaded."); 222 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "The prerequisites were successfully installed. The bootstrapper application will be reloaded.");
231 *pAction = BOOTSTRAPPER_SHUTDOWN_ACTION_RELOAD_BOOTSTRAPPER; 223 *pAction = BOOTSTRAPPER_SHUTDOWN_ACTION_RELOAD_BOOTSTRAPPER;
232 } 224 m_pPrereqData->fCompleted = TRUE;
233 else if (m_fPrereqAlreadyInstalled)
234 {
235 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "The prerequisites were already installed. The bootstrapper application will not be reloaded to prevent an infinite loop.");
236 } 225 }
237 else if (m_fPrereq) 226 else if (m_fPrereq)
238 { 227 {
@@ -311,38 +300,14 @@ public: // IBootstrapperApplication
311 300
312 if (!fMissingFromCache) 301 if (!fMissingFromCache)
313 { 302 {
314 if (SUCCEEDED(BalInfoAddRelatedBundleAsPackage(&m_Bundle.packages, wzBundleId, relationType, fPerMachine, &pPackage))) 303 BalInfoAddRelatedBundleAsPackage(&m_Bundle.packages, wzBundleId, relationType, fPerMachine, &pPackage);
315 { 304 // Best effort
316 InitializePackageInfoForPackage(pPackage);
317 }
318 } 305 }
319 306
320 return CBalBaseBootstrapperApplication::OnDetectRelatedBundle(wzBundleId, relationType, wzBundleTag, fPerMachine, wzVersion, fMissingFromCache, pfCancel); 307 return CBalBaseBootstrapperApplication::OnDetectRelatedBundle(wzBundleId, relationType, wzBundleTag, fPerMachine, wzVersion, fMissingFromCache, pfCancel);
321 } 308 }
322 309
323 310
324 virtual STDMETHODIMP OnDetectPackageComplete(
325 __in LPCWSTR wzPackageId,
326 __in HRESULT /*hrStatus*/,
327 __in BOOTSTRAPPER_PACKAGE_STATE state,
328 __in BOOL /*fCached*/
329 )
330 {
331 WIXSTDBA_PACKAGE_INFO* pPackageInfo = NULL;
332 BAL_INFO_PACKAGE* pPackage = NULL;
333
334 if (BOOTSTRAPPER_PACKAGE_STATE_PRESENT == state &&
335 SUCCEEDED(GetPackageInfo(wzPackageId, &pPackageInfo, &pPackage)) &&
336 pPackageInfo)
337 {
338 // If the package is already installed, remember that.
339 pPackageInfo->fWasAlreadyInstalled = TRUE;
340 }
341
342 return S_OK;
343 }
344
345
346 virtual STDMETHODIMP OnDetectComplete( 311 virtual STDMETHODIMP OnDetectComplete(
347 __in HRESULT hrStatus, 312 __in HRESULT hrStatus,
348 __in BOOL /*fEligibleForCleanup*/ 313 __in BOOL /*fEligibleForCleanup*/
@@ -366,29 +331,10 @@ public: // IBootstrapperApplication
366 if (fEvaluateConditions) 331 if (fEvaluateConditions)
367 { 332 {
368 hrStatus = EvaluateConditions(); 333 hrStatus = EvaluateConditions();
369 }
370 334
371 if (FAILED(hrStatus)) 335 if (FAILED(hrStatus))
372 {
373 fSkipToPlan = FALSE;
374 }
375 else
376 {
377 if (m_fPrereq)
378 { 336 {
379 m_fPrereqAlreadyInstalled = TRUE; 337 fSkipToPlan = FALSE;
380
381 // At this point we have to assume that all prerequisite packages need to be installed, so set to false if any of them aren't installed.
382 for (DWORD i = 0; i < m_Bundle.packages.cPackages; ++i)
383 {
384 BAL_INFO_PACKAGE* pPackage = &m_Bundle.packages.rgPackages[i];
385 WIXSTDBA_PACKAGE_INFO* pPackageInfo = reinterpret_cast<WIXSTDBA_PACKAGE_INFO*>(pPackage->pvCustomData);
386 if (pPackage->fPrereqPackage && pPackageInfo && !pPackageInfo->fWasAlreadyInstalled)
387 {
388 m_fPrereqAlreadyInstalled = FALSE;
389 break;
390 }
391 }
392 } 338 }
393 } 339 }
394 340
@@ -403,20 +349,20 @@ public: // IBootstrapperApplication
403 } 349 }
404 350
405 351
406 virtual STDMETHODIMP OnPlanRelatedBundle( 352 virtual STDMETHODIMP OnPlanRelatedBundleType(
407 __in_z LPCWSTR wzBundleId, 353 __in_z LPCWSTR wzBundleId,
408 __in BOOTSTRAPPER_REQUEST_STATE recommendedState, 354 __in BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE recommendedType,
409 __inout_z BOOTSTRAPPER_REQUEST_STATE* pRequestedState, 355 __inout BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE* pRequestedType,
410 __inout BOOL* pfCancel 356 __inout BOOL* pfCancel
411 ) 357 )
412 { 358 {
413 // If we're only installing prerequisites, do not touch related bundles. 359 // If we're only installing prerequisites, do not touch related bundles.
414 if (m_fPrereq) 360 if (m_fPrereq)
415 { 361 {
416 *pRequestedState = BOOTSTRAPPER_REQUEST_STATE_NONE; 362 *pRequestedType = BOOTSTRAPPER_RELATED_BUNDLE_PLAN_TYPE_NONE;
417 } 363 }
418 364
419 return CBalBaseBootstrapperApplication::OnPlanRelatedBundle(wzBundleId, recommendedState, pRequestedState, pfCancel); 365 return CBalBaseBootstrapperApplication::OnPlanRelatedBundleType(wzBundleId, recommendedType, pRequestedType, pfCancel);
420 } 366 }
421 367
422 368
@@ -434,7 +380,6 @@ public: // IBootstrapperApplication
434 ) 380 )
435 { 381 {
436 HRESULT hr = S_OK; 382 HRESULT hr = S_OK;
437 WIXSTDBA_PACKAGE_INFO* pPackageInfo = NULL;
438 BAL_INFO_PACKAGE* pPackage = NULL; 383 BAL_INFO_PACKAGE* pPackage = NULL;
439 384
440 // If we're planning to install prerequisites, install them. The prerequisites need to be installed 385 // If we're planning to install prerequisites, install them. The prerequisites need to be installed
@@ -443,10 +388,11 @@ public: // IBootstrapperApplication
443 { 388 {
444 // Only install prerequisite packages, and check the InstallCondition on them. 389 // Only install prerequisite packages, and check the InstallCondition on them.
445 BOOL fInstall = FALSE; 390 BOOL fInstall = FALSE;
446 hr = GetPackageInfo(wzPackageId, &pPackageInfo, &pPackage); 391
447 if (SUCCEEDED(hr) && pPackage->fPrereqPackage && pPackageInfo) 392 hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage);
393 if (SUCCEEDED(hr) && pPackage->fPrereqPackage)
448 { 394 {
449 pPackageInfo->fPlannedToBeInstalled = fInstall = BOOTSTRAPPER_PACKAGE_CONDITION_FALSE != installCondition; 395 fInstall = BOOTSTRAPPER_PACKAGE_CONDITION_FALSE != installCondition;
450 } 396 }
451 397
452 if (fInstall) 398 if (fInstall)
@@ -503,7 +449,6 @@ public: // IBootstrapperApplication
503 ) 449 )
504 { 450 {
505 HRESULT hr = S_OK; 451 HRESULT hr = S_OK;
506 WIXSTDBA_PACKAGE_INFO* pPackageInfo = NULL;
507 BAL_INFO_PACKAGE* pPackage = NULL; 452 BAL_INFO_PACKAGE* pPackage = NULL;
508 BOOL fShowInternalUI = FALSE; 453 BOOL fShowInternalUI = FALSE;
509 INSTALLUILEVEL uiLevel = INSTALLUILEVEL_NOCHANGE; 454 INSTALLUILEVEL uiLevel = INSTALLUILEVEL_NOCHANGE;
@@ -521,7 +466,7 @@ public: // IBootstrapperApplication
521 466
522 if (INSTALLUILEVEL_NOCHANGE != uiLevel) 467 if (INSTALLUILEVEL_NOCHANGE != uiLevel)
523 { 468 {
524 hr = GetPackageInfo(wzPackageId, &pPackageInfo, &pPackage); 469 hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage);
525 if (SUCCEEDED(hr) && pPackage->sczDisplayInternalUICondition) 470 if (SUCCEEDED(hr) && pPackage->sczDisplayInternalUICondition)
526 { 471 {
527 hr = BalEvaluateCondition(pPackage->sczDisplayInternalUICondition, &fShowInternalUI); 472 hr = BalEvaluateCondition(pPackage->sczDisplayInternalUICondition, &fShowInternalUI);
@@ -545,23 +490,6 @@ public: // IBootstrapperApplication
545 { 490 {
546 HRESULT hr = S_OK; 491 HRESULT hr = S_OK;
547 492
548 if (m_fPrereq)
549 {
550 m_fPrereqAlreadyInstalled = TRUE;
551
552 // Now that we've planned the packages, we can focus on the prerequisite packages that are supposed to be installed.
553 for (DWORD i = 0; i < m_Bundle.packages.cPackages; ++i)
554 {
555 BAL_INFO_PACKAGE* pPackage = &m_Bundle.packages.rgPackages[i];
556 WIXSTDBA_PACKAGE_INFO* pPackageInfo = reinterpret_cast<WIXSTDBA_PACKAGE_INFO*>(pPackage->pvCustomData);
557 if (pPackage->fPrereqPackage && pPackageInfo && !pPackageInfo->fWasAlreadyInstalled && pPackageInfo->fPlannedToBeInstalled)
558 {
559 m_fPrereqAlreadyInstalled = FALSE;
560 break;
561 }
562 }
563 }
564
565 SetState(WIXSTDBA_STATE_PLANNED, hrStatus); 493 SetState(WIXSTDBA_STATE_PLANNED, hrStatus);
566 494
567 if (SUCCEEDED(hrStatus)) 495 if (SUCCEEDED(hrStatus))
@@ -1033,13 +961,10 @@ public: // IBootstrapperApplication
1033 961
1034 hr = __super::OnExecutePackageComplete(wzPackageId, hrStatus, restart, recommendation, pAction); 962 hr = __super::OnExecutePackageComplete(wzPackageId, hrStatus, restart, recommendation, pAction);
1035 963
1036 WIXSTDBA_PACKAGE_INFO* pPackageInfo = NULL; 964 BAL_INFO_PACKAGE* pPackage = NULL;
1037 BAL_INFO_PACKAGE* pPackage; 965 HRESULT hrPrereq = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage);
1038 HRESULT hrPrereq = GetPackageInfo(wzPackageId, &pPackageInfo, &pPackage); 966 if (SUCCEEDED(hrPrereq))
1039 if (SUCCEEDED(hrPrereq) && pPackageInfo)
1040 { 967 {
1041 pPackageInfo->fSuccessfullyInstalled = SUCCEEDED(hrStatus);
1042
1043 // If the prerequisite required a restart (any restart) then do an immediate 968 // If the prerequisite required a restart (any restart) then do an immediate
1044 // restart to ensure that the bundle will get launched again post reboot. 969 // restart to ensure that the bundle will get launched again post reboot.
1045 if (m_fPrereq && pPackage->fPrereqPackage && BOOTSTRAPPER_APPLY_RESTART_NONE != restart) 970 if (m_fPrereq && pPackage->fPrereqPackage && BOOTSTRAPPER_APPLY_RESTART_NONE != restart)
@@ -1157,28 +1082,7 @@ public: // IBootstrapperApplication
1157 1082
1158 if (m_fPrereq) 1083 if (m_fPrereq)
1159 { 1084 {
1160 m_fPrereqInstalled = TRUE; 1085 m_fPrereqInstalled = SUCCEEDED(hrStatus);
1161 BOOL fInstalledAPackage = FALSE;
1162
1163 for (DWORD i = 0; i < m_Bundle.packages.cPackages; ++i)
1164 {
1165 BAL_INFO_PACKAGE* pPackage = &m_Bundle.packages.rgPackages[i];
1166 WIXSTDBA_PACKAGE_INFO* pPackageInfo = reinterpret_cast<WIXSTDBA_PACKAGE_INFO*>(pPackage->pvCustomData);
1167 if (pPackage->fPrereqPackage && pPackageInfo && pPackageInfo->fPlannedToBeInstalled && !pPackageInfo->fWasAlreadyInstalled)
1168 {
1169 if (pPackageInfo->fSuccessfullyInstalled)
1170 {
1171 fInstalledAPackage = TRUE;
1172 }
1173 else
1174 {
1175 m_fPrereqInstalled = FALSE;
1176 break;
1177 }
1178 }
1179 }
1180
1181 m_fPrereqInstalled = m_fPrereqInstalled && fInstalledAPackage;
1182 } 1086 }
1183 1087
1184 // If we are showing UI, wait a beat before moving to the final screen. 1088 // If we are showing UI, wait a beat before moving to the final screen.
@@ -1223,10 +1127,10 @@ public: // IBootstrapperApplication
1223 { 1127 {
1224 BAL_INFO_PACKAGE* pPackage = NULL; 1128 BAL_INFO_PACKAGE* pPackage = NULL;
1225 1129
1226 if (SUCCEEDED(hrStatus) && wzNewPackageId && 1130 if (SUCCEEDED(hrStatus) && wzNewPackageId)
1227 SUCCEEDED(BalInfoAddUpdateBundleAsPackage(&m_Bundle.packages, wzNewPackageId, wzPreviousPackageId, &pPackage)))
1228 { 1131 {
1229 InitializePackageInfoForPackage(pPackage); 1132 BalInfoAddUpdateBundleAsPackage(&m_Bundle.packages, wzNewPackageId, wzPreviousPackageId, &pPackage);
1133 // Best effort
1230 } 1134 }
1231 1135
1232 return S_OK; 1136 return S_OK;
@@ -2201,6 +2105,36 @@ public: //CBalBaseBootstrapperApplication
2201 return hr; 2105 return hr;
2202 } 2106 }
2203 2107
2108 void Uninitialize(
2109 __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs,
2110 __in BOOTSTRAPPER_DESTROY_RESULTS* /*pResults*/
2111 )
2112 {
2113 if (m_hBAFModule)
2114 {
2115 BA_FUNCTIONS_DESTROY_ARGS args = { };
2116 BA_FUNCTIONS_DESTROY_RESULTS results = { };
2117
2118 args.cbSize = sizeof(BA_FUNCTIONS_DESTROY_ARGS);
2119 args.fReload = pArgs->fReload;
2120
2121 results.cbSize = sizeof(BA_FUNCTIONS_DESTROY_RESULTS);
2122
2123 PFN_BA_FUNCTIONS_DESTROY pfnBAFunctionsDestroy = reinterpret_cast<PFN_BA_FUNCTIONS_DESTROY>(::GetProcAddress(m_hBAFModule, "BAFunctionsDestroy"));
2124 if (pfnBAFunctionsDestroy)
2125 {
2126 pfnBAFunctionsDestroy(&args, &results);
2127 }
2128
2129 if (!results.fDisableUnloading)
2130 {
2131 ::FreeLibrary(m_hBAFModule);
2132 m_hBAFModule = NULL;
2133 }
2134 }
2135 }
2136
2137
2204private: 2138private:
2205 // 2139 //
2206 // UiThreadProc - entrypoint for UI thread. 2140 // UiThreadProc - entrypoint for UI thread.
@@ -2214,6 +2148,7 @@ private:
2214 BOOL fComInitialized = FALSE; 2148 BOOL fComInitialized = FALSE;
2215 BOOL fRet = FALSE; 2149 BOOL fRet = FALSE;
2216 MSG msg = { }; 2150 MSG msg = { };
2151 DWORD dwQuit = 0;
2217 2152
2218 // Initialize COM and theme. 2153 // Initialize COM and theme.
2219 hr = ::CoInitialize(NULL); 2154 hr = ::CoInitialize(NULL);
@@ -2274,8 +2209,6 @@ private:
2274 pThis->DestroyMainWindow(); 2209 pThis->DestroyMainWindow();
2275 pThis->UninitializeTaskbarButton(); 2210 pThis->UninitializeTaskbarButton();
2276 2211
2277 // initiate engine shutdown
2278 DWORD dwQuit = HRESULT_CODE(hr);
2279 if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == pThis->m_restartResult) 2212 if (BOOTSTRAPPER_APPLY_RESTART_INITIATED == pThis->m_restartResult)
2280 { 2213 {
2281 dwQuit = ERROR_SUCCESS_REBOOT_INITIATED; 2214 dwQuit = ERROR_SUCCESS_REBOOT_INITIATED;
@@ -2284,6 +2217,17 @@ private:
2284 { 2217 {
2285 dwQuit = ERROR_SUCCESS_REBOOT_REQUIRED; 2218 dwQuit = ERROR_SUCCESS_REBOOT_REQUIRED;
2286 } 2219 }
2220 else if (SEVERITY_ERROR == HRESULT_SEVERITY(hr) && FACILITY_WIN32 == HRESULT_FACILITY(hr))
2221 {
2222 // Convert Win32 HRESULTs back to the error code.
2223 dwQuit = HRESULT_CODE(hr);
2224 }
2225 else
2226 {
2227 dwQuit = hr;
2228 }
2229
2230 // initiate engine shutdown
2287 pThis->m_pEngine->Quit(dwQuit); 2231 pThis->m_pEngine->Quit(dwQuit);
2288 2232
2289 ReleaseTheme(pThis->m_pTheme); 2233 ReleaseTheme(pThis->m_pTheme);
@@ -2335,9 +2279,6 @@ private:
2335 GetBundleFileVersion(); 2279 GetBundleFileVersion();
2336 // don't fail if we couldn't get the version info; best-effort only 2280 // don't fail if we couldn't get the version info; best-effort only
2337 2281
2338 hr = InitializePackageInfo();
2339 BalExitOnFailure(hr, "Failed to initialize wixstdba package information.");
2340
2341 if (m_fPrereq) 2282 if (m_fPrereq)
2342 { 2283 {
2343 hr = InitializePrerequisiteInformation(); 2284 hr = InitializePrerequisiteInformation();
@@ -2521,38 +2462,6 @@ private:
2521 } 2462 }
2522 2463
2523 2464
2524 HRESULT InitializePackageInfo()
2525 {
2526 HRESULT hr = S_OK;
2527 BAL_INFO_PACKAGE* pPackage = NULL;
2528
2529 for (DWORD i = 0; i < m_Bundle.packages.cPackages; ++i)
2530 {
2531 pPackage = &m_Bundle.packages.rgPackages[i];
2532
2533 hr = InitializePackageInfoForPackage(pPackage);
2534 BalExitOnFailure(hr, "Failed to initialize wixstdba package info for package: %ls.", pPackage->sczId);
2535 }
2536
2537 LExit:
2538 return hr;
2539 }
2540
2541
2542 HRESULT InitializePackageInfoForPackage(
2543 __in BAL_INFO_PACKAGE* pPackage
2544 )
2545 {
2546 HRESULT hr = S_OK;
2547
2548 pPackage->pvCustomData = MemAlloc(sizeof(WIXSTDBA_PACKAGE_INFO), TRUE);
2549 BalExitOnNull(pPackage->pvCustomData, hr, E_OUTOFMEMORY, "Failed to allocate memory for wixstdba package info.");
2550
2551 LExit:
2552 return hr;
2553 }
2554
2555
2556 HRESULT InitializePrerequisiteInformation() 2465 HRESULT InitializePrerequisiteInformation()
2557 { 2466 {
2558 HRESULT hr = S_OK; 2467 HRESULT hr = S_OK;
@@ -2673,35 +2582,6 @@ private:
2673 return hr; 2582 return hr;
2674 } 2583 }
2675 2584
2676 HRESULT GetPackageInfo(
2677 __in_z LPCWSTR wzPackageId,
2678 __out WIXSTDBA_PACKAGE_INFO** ppPackageInfo,
2679 __out BAL_INFO_PACKAGE** ppPackage
2680 )
2681 {
2682 HRESULT hr = E_NOTFOUND;
2683 WIXSTDBA_PACKAGE_INFO* pPackageInfo = NULL;
2684 BAL_INFO_PACKAGE* pPackage = NULL;
2685
2686 Assert(wzPackageId && *wzPackageId);
2687 Assert(ppPackage);
2688 Assert(ppPackageInfo);
2689
2690 hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage);
2691 if (E_NOTFOUND != hr)
2692 {
2693 ExitOnFailure(hr, "Failed trying to find the requested package.");
2694
2695 pPackageInfo = reinterpret_cast<WIXSTDBA_PACKAGE_INFO*>(pPackage->pvCustomData);
2696 }
2697
2698 *ppPackageInfo = pPackageInfo;
2699 *ppPackage = pPackage;
2700
2701 LExit:
2702 return hr;
2703 }
2704
2705 2585
2706 // 2586 //
2707 // Get the file version of the bootstrapper and record in bootstrapper log file 2587 // Get the file version of the bootstrapper and record in bootstrapper log file
@@ -3408,6 +3288,23 @@ private:
3408 } 3288 }
3409 } 3289 }
3410 } 3290 }
3291 else if (E_PREREQBA_INFINITE_LOOP == m_hrFinal)
3292 {
3293 HRESULT hr = StrAllocString(&sczUnformattedText, L"#(loc.PREREQBAINFINITELOOPErrorMessage)", 0);
3294 if (FAILED(hr))
3295 {
3296 BalLogError(hr, "Failed to initialize PREREQBAINFINITELOOPErrorMessage loc identifier.");
3297 }
3298 else
3299 {
3300 hr = LocLocalizeString(m_pWixLoc, &sczUnformattedText);
3301 if (FAILED(hr))
3302 {
3303 BalLogError(hr, "Failed to localize PREREQBAINFINITELOOPErrorMessage: %ls", sczUnformattedText);
3304 ReleaseNullStr(sczUnformattedText);
3305 }
3306 }
3307 }
3411 else // try to get the error message from the error code. 3308 else // try to get the error message from the error code.
3412 { 3309 {
3413 StrAllocFromError(&sczUnformattedText, m_hrFinal, NULL); 3310 StrAllocFromError(&sczUnformattedText, m_hrFinal, NULL);
@@ -3424,14 +3321,9 @@ private:
3424 StrAllocString(&sczText, sczUnformattedText, 0); 3321 StrAllocString(&sczText, sczUnformattedText, 0);
3425 } 3322 }
3426 } 3323 }
3427 else if (E_MBAHOST_NET452_ON_WIN7RTM == m_hrFinal) 3324 else if (E_MBAHOST_NET452_ON_WIN7RTM == m_hrFinal ||
3428 { 3325 E_DNCHOST_SCD_RUNTIME_FAILURE == m_hrFinal ||
3429 if (sczUnformattedText) 3326 E_PREREQBA_INFINITE_LOOP == m_hrFinal)
3430 {
3431 BalFormatString(sczUnformattedText, &sczText);
3432 }
3433 }
3434 else if (E_DNCHOST_SCD_RUNTIME_FAILURE == m_hrFinal)
3435 { 3327 {
3436 if (sczUnformattedText) 3328 if (sczUnformattedText)
3437 { 3329 {
@@ -4180,8 +4072,7 @@ public:
4180 // 4072 //
4181 CWixStandardBootstrapperApplication( 4073 CWixStandardBootstrapperApplication(
4182 __in HMODULE hModule, 4074 __in HMODULE hModule,
4183 __in BOOL fPrereq, 4075 __in_opt PREQBA_DATA* pPrereqData,
4184 __in HRESULT hrHostInitialization,
4185 __in IBootstrapperEngine* pEngine 4076 __in IBootstrapperEngine* pEngine
4186 ) : CBalBaseBootstrapperApplication(pEngine, 3, 3000) 4077 ) : CBalBaseBootstrapperApplication(pEngine, 3, 3000)
4187 { 4078 {
@@ -4210,7 +4101,7 @@ public:
4210 m_hWnd = NULL; 4101 m_hWnd = NULL;
4211 4102
4212 m_state = WIXSTDBA_STATE_INITIALIZING; 4103 m_state = WIXSTDBA_STATE_INITIALIZING;
4213 m_hrFinal = hrHostInitialization; 4104 m_hrFinal = pPrereqData ? pPrereqData->hrHostInitialization : S_OK;
4214 4105
4215 m_restartResult = BOOTSTRAPPER_APPLY_RESTART_NONE; 4106 m_restartResult = BOOTSTRAPPER_APPLY_RESTART_NONE;
4216 m_fRestartRequired = FALSE; 4107 m_fRestartRequired = FALSE;
@@ -4231,9 +4122,9 @@ public:
4231 m_fShowingInternalUiThisPackage = FALSE; 4122 m_fShowingInternalUiThisPackage = FALSE;
4232 m_fTriedToLaunchElevated = FALSE; 4123 m_fTriedToLaunchElevated = FALSE;
4233 4124
4234 m_fPrereq = fPrereq; 4125 m_pPrereqData = pPrereqData;
4126 m_fPrereq = NULL != pPrereqData;
4235 m_fPrereqInstalled = FALSE; 4127 m_fPrereqInstalled = FALSE;
4236 m_fPrereqAlreadyInstalled = FALSE;
4237 4128
4238 pEngine->AddRef(); 4129 pEngine->AddRef();
4239 m_pEngine = pEngine; 4130 m_pEngine = pEngine;
@@ -4418,11 +4309,6 @@ public:
4418 AssertSz(!m_pTaskbarList, "Taskbar should have been released before destructor."); 4309 AssertSz(!m_pTaskbarList, "Taskbar should have been released before destructor.");
4419 AssertSz(!m_pTheme, "Theme should have been released before destructor."); 4310 AssertSz(!m_pTheme, "Theme should have been released before destructor.");
4420 4311
4421 for (DWORD i = 0; i < m_Bundle.packages.cPackages; ++i)
4422 {
4423 ReleaseMem(m_Bundle.packages.rgPackages[i].pvCustomData);
4424 }
4425
4426 ::DeleteCriticalSection(&m_csShowingInternalUiThisPackage); 4312 ::DeleteCriticalSection(&m_csShowingInternalUiThisPackage);
4427 ReleaseStr(m_sczFailedMessage); 4313 ReleaseStr(m_sczFailedMessage);
4428 ReleaseStr(m_sczConfirmCloseMessage); 4314 ReleaseStr(m_sczConfirmCloseMessage);
@@ -4436,18 +4322,6 @@ public:
4436 ReleaseStr(m_sczBundleVersion); 4322 ReleaseStr(m_sczBundleVersion);
4437 ReleaseStr(m_sczAfterForcedRestartPackage); 4323 ReleaseStr(m_sczAfterForcedRestartPackage);
4438 ReleaseNullObject(m_pEngine); 4324 ReleaseNullObject(m_pEngine);
4439
4440 if (m_hBAFModule)
4441 {
4442 PFN_BA_FUNCTIONS_DESTROY pfnBAFunctionsDestroy = reinterpret_cast<PFN_BA_FUNCTIONS_DESTROY>(::GetProcAddress(m_hBAFModule, "BAFunctionsDestroy"));
4443 if (pfnBAFunctionsDestroy)
4444 {
4445 pfnBAFunctionsDestroy();
4446 }
4447
4448 ::FreeLibrary(m_hBAFModule);
4449 m_hBAFModule = NULL;
4450 }
4451 } 4325 }
4452 4326
4453private: 4327private:
@@ -4529,9 +4403,9 @@ private:
4529 BOOL m_fSupportCacheOnly; 4403 BOOL m_fSupportCacheOnly;
4530 BOOL m_fRequestedCacheOnly; 4404 BOOL m_fRequestedCacheOnly;
4531 4405
4406 PREQBA_DATA* m_pPrereqData;
4532 BOOL m_fPrereq; 4407 BOOL m_fPrereq;
4533 BOOL m_fPrereqInstalled; 4408 BOOL m_fPrereqInstalled;
4534 BOOL m_fPrereqAlreadyInstalled;
4535 4409
4536 ITaskbarList3* m_pTaskbarList; 4410 ITaskbarList3* m_pTaskbarList;
4537 UINT m_uTaskbarButtonCreatedMessage; 4411 UINT m_uTaskbarButtonCreatedMessage;
@@ -4551,8 +4425,7 @@ private:
4551// 4425//
4552HRESULT CreateBootstrapperApplication( 4426HRESULT CreateBootstrapperApplication(
4553 __in HMODULE hModule, 4427 __in HMODULE hModule,
4554 __in BOOL fPrereq, 4428 __in_opt PREQBA_DATA* pPrereqData,
4555 __in HRESULT hrHostInitialization,
4556 __in IBootstrapperEngine* pEngine, 4429 __in IBootstrapperEngine* pEngine,
4557 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, 4430 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
4558 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults, 4431 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults,
@@ -4567,7 +4440,7 @@ HRESULT CreateBootstrapperApplication(
4567 BalExitOnFailure(hr = E_INVALIDARG, "Engine requested Unknown display type."); 4440 BalExitOnFailure(hr = E_INVALIDARG, "Engine requested Unknown display type.");
4568 } 4441 }
4569 4442
4570 pApplication = new CWixStandardBootstrapperApplication(hModule, fPrereq, hrHostInitialization, pEngine); 4443 pApplication = new CWixStandardBootstrapperApplication(hModule, pPrereqData, pEngine);
4571 BalExitOnNull(pApplication, hr, E_OUTOFMEMORY, "Failed to create new standard bootstrapper application object."); 4444 BalExitOnNull(pApplication, hr, E_OUTOFMEMORY, "Failed to create new standard bootstrapper application object.");
4572 4445
4573 hr = pApplication->Initialize(pArgs); 4446 hr = pApplication->Initialize(pArgs);
@@ -4584,6 +4457,17 @@ LExit:
4584} 4457}
4585 4458
4586 4459
4460void DestroyBootstrapperApplication(
4461 __in IBootstrapperApplication* pApplication,
4462 __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs,
4463 __inout BOOTSTRAPPER_DESTROY_RESULTS* pResults
4464 )
4465{
4466 CWixStandardBootstrapperApplication* pBA = (CWixStandardBootstrapperApplication*)pApplication;
4467 pBA->Uninitialize(pArgs, pResults);
4468}
4469
4470
4587static HRESULT DAPI EvaluateVariableConditionCallback( 4471static HRESULT DAPI EvaluateVariableConditionCallback(
4588 __in_z LPCWSTR wzCondition, 4472 __in_z LPCWSTR wzCondition,
4589 __out BOOL* pf, 4473 __out BOOL* pf,
diff --git a/src/ext/Bal/wixstdba/inc/preqba.h b/src/ext/Bal/wixstdba/inc/preqba.h
new file mode 100644
index 00000000..93a547ed
--- /dev/null
+++ b/src/ext/Bal/wixstdba/inc/preqba.h
@@ -0,0 +1,16 @@
1#pragma once
2// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
3
4
5struct PREQBA_DATA
6{
7 HRESULT hrHostInitialization;
8 BOOL fCompleted;
9};
10
11extern "C" typedef HRESULT(WINAPI* PFN_PREQ_BOOTSTRAPPER_APPLICATION_CREATE)(
12 __in PREQBA_DATA* pPreqData,
13 __in IBootstrapperEngine* pEngine,
14 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
15 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
16 );
diff --git a/src/ext/Bal/wixstdba/precomp.h b/src/ext/Bal/wixstdba/precomp.h
index ba56ae6d..290c125b 100644
--- a/src/ext/Bal/wixstdba/precomp.h
+++ b/src/ext/Bal/wixstdba/precomp.h
@@ -17,43 +17,49 @@
17#include <strsafe.h> 17#include <strsafe.h>
18#include <stddef.h> 18#include <stddef.h>
19 19
20#include "dutil.h" 20#include <dutil.h>
21#include "apputil.h" 21#include <apputil.h>
22#include "memutil.h" 22#include <memutil.h>
23#include "dictutil.h" 23#include <dictutil.h>
24#include "dirutil.h" 24#include <dirutil.h>
25#include "fileutil.h" 25#include <fileutil.h>
26#include "locutil.h" 26#include <locutil.h>
27#include "logutil.h" 27#include <logutil.h>
28#include "pathutil.h" 28#include <pathutil.h>
29#include "resrutil.h" 29#include <resrutil.h>
30#include "shelutil.h" 30#include <shelutil.h>
31#include "strutil.h" 31#include <strutil.h>
32#include "wndutil.h" 32#include <wndutil.h>
33#include "thmutil.h" 33#include <thmutil.h>
34#include "verutil.h" 34#include <verutil.h>
35#include "uriutil.h" 35#include <uriutil.h>
36#include "xmlutil.h" 36#include <xmlutil.h>
37
38#include "BootstrapperEngine.h"
39#include "BootstrapperApplication.h"
40#include "IBootstrapperEngine.h"
41#include "IBootstrapperApplication.h"
42
43#include "balutil.h"
44#include "balinfo.h"
45#include "balcondition.h"
46
47#include "BAFunctions.h"
48 37
38#include <BootstrapperEngine.h>
39#include <BootstrapperApplication.h>
40#include <IBootstrapperEngine.h>
41#include <IBootstrapperApplication.h>
42
43#include <balutil.h>
44#include <balinfo.h>
45#include <balcondition.h>
46
47#include <BAFunctions.h>
48
49#include "inc\preqba.h"
49#include "wixstdba.messages.h" 50#include "wixstdba.messages.h"
50 51
51HRESULT CreateBootstrapperApplication( 52HRESULT CreateBootstrapperApplication(
52 __in HMODULE hModule, 53 __in HMODULE hModule,
53 __in BOOL fPrereq, 54 __in_opt PREQBA_DATA* pPrereqData,
54 __in HRESULT hrHostInitialization,
55 __in IBootstrapperEngine* pEngine, 55 __in IBootstrapperEngine* pEngine,
56 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, 56 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
57 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults, 57 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults,
58 __out IBootstrapperApplication** ppApplication 58 __out IBootstrapperApplication** ppApplication
59 ); 59 );
60
61void DestroyBootstrapperApplication(
62 __in IBootstrapperApplication* pApplication,
63 __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs,
64 __inout BOOTSTRAPPER_DESTROY_RESULTS* pResults
65 );
diff --git a/src/ext/Bal/wixstdba/wixstdba.cpp b/src/ext/Bal/wixstdba/wixstdba.cpp
index a96f1738..47f3f677 100644
--- a/src/ext/Bal/wixstdba/wixstdba.cpp
+++ b/src/ext/Bal/wixstdba/wixstdba.cpp
@@ -50,7 +50,7 @@ extern "C" HRESULT WINAPI BootstrapperApplicationCreate(
50 hr = BalInitializeFromCreateArgs(pArgs, &pEngine); 50 hr = BalInitializeFromCreateArgs(pArgs, &pEngine);
51 ExitOnFailure(hr, "Failed to initialize Bal."); 51 ExitOnFailure(hr, "Failed to initialize Bal.");
52 52
53 hr = CreateBootstrapperApplication(vhInstance, FALSE, S_OK, pEngine, pArgs, pResults, &vpApplication); 53 hr = CreateBootstrapperApplication(vhInstance, NULL, pEngine, pArgs, pResults, &vpApplication);
54 BalExitOnFailure(hr, "Failed to create bootstrapper application interface."); 54 BalExitOnFailure(hr, "Failed to create bootstrapper application interface.");
55 55
56LExit: 56LExit:
@@ -60,45 +60,24 @@ LExit:
60} 60}
61 61
62 62
63extern "C" void WINAPI BootstrapperApplicationDestroy() 63extern "C" void WINAPI BootstrapperApplicationDestroy(
64{ 64 __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs,
65 ReleaseNullObject(vpApplication); 65 __in BOOTSTRAPPER_DESTROY_RESULTS* pResults
66 BalUninitialize();
67 DutilUninitialize();
68}
69
70
71extern "C" HRESULT WINAPI DncPrereqBootstrapperApplicationCreate(
72 __in HRESULT hrHostInitialization,
73 __in IBootstrapperEngine* pEngine,
74 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
75 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
76 ) 66 )
77{ 67{
78 HRESULT hr = S_OK; 68 if (vpApplication)
79 69 {
80 DutilInitialize(&WixstdbaTraceError); 70 DestroyBootstrapperApplication(vpApplication, pArgs, pResults);
81 71 }
82 BalInitialize(pEngine);
83
84 hr = CreateBootstrapperApplication(vhInstance, TRUE, hrHostInitialization, pEngine, pArgs, pResults, &vpApplication);
85 BalExitOnFailure(hr, "Failed to create .NET Core prerequisite bootstrapper application interface.");
86
87LExit:
88 return hr;
89}
90
91 72
92extern "C" void WINAPI DncPrereqBootstrapperApplicationDestroy()
93{
94 ReleaseNullObject(vpApplication); 73 ReleaseNullObject(vpApplication);
95 BalUninitialize(); 74 BalUninitialize();
96 DutilUninitialize(); 75 DutilUninitialize();
97} 76}
98 77
99 78
100extern "C" HRESULT WINAPI MbaPrereqBootstrapperApplicationCreate( 79extern "C" HRESULT WINAPI PrereqBootstrapperApplicationCreate(
101 __in HRESULT hrHostInitialization, 80 __in_opt PREQBA_DATA* pPrereqData,
102 __in IBootstrapperEngine* pEngine, 81 __in IBootstrapperEngine* pEngine,
103 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs, 82 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
104 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults 83 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
@@ -110,19 +89,20 @@ extern "C" HRESULT WINAPI MbaPrereqBootstrapperApplicationCreate(
110 89
111 BalInitialize(pEngine); 90 BalInitialize(pEngine);
112 91
113 hr = CreateBootstrapperApplication(vhInstance, TRUE, hrHostInitialization, pEngine, pArgs, pResults, &vpApplication); 92 hr = CreateBootstrapperApplication(vhInstance, pPrereqData, pEngine, pArgs, pResults, &vpApplication);
114 BalExitOnFailure(hr, "Failed to create managed prerequisite bootstrapper application interface."); 93 BalExitOnFailure(hr, "Failed to create prerequisite bootstrapper application interface.");
115 94
116LExit: 95LExit:
117 return hr; 96 return hr;
118} 97}
119 98
120 99
121extern "C" void WINAPI MbaPrereqBootstrapperApplicationDestroy() 100extern "C" void WINAPI PrereqBootstrapperApplicationDestroy(
101 __in const BOOTSTRAPPER_DESTROY_ARGS* pArgs,
102 __in BOOTSTRAPPER_DESTROY_RESULTS* pResults
103 )
122{ 104{
123 ReleaseNullObject(vpApplication); 105 BootstrapperApplicationDestroy(pArgs, pResults);
124 BalUninitialize();
125 DutilUninitialize();
126} 106}
127 107
128static void CALLBACK WixstdbaTraceError( 108static void CALLBACK WixstdbaTraceError(
diff --git a/src/ext/Bal/wixstdba/wixstdba.def b/src/ext/Bal/wixstdba/wixstdba.def
index ba9980d3..e377196b 100644
--- a/src/ext/Bal/wixstdba/wixstdba.def
+++ b/src/ext/Bal/wixstdba/wixstdba.def
@@ -4,7 +4,5 @@
4EXPORTS 4EXPORTS
5 BootstrapperApplicationCreate 5 BootstrapperApplicationCreate
6 BootstrapperApplicationDestroy 6 BootstrapperApplicationDestroy
7 DncPrereqBootstrapperApplicationCreate 7 PrereqBootstrapperApplicationCreate
8 DncPrereqBootstrapperApplicationDestroy 8 PrereqBootstrapperApplicationDestroy
9 MbaPrereqBootstrapperApplicationCreate
10 MbaPrereqBootstrapperApplicationDestroy
diff --git a/src/ext/Bal/wixstdba/wixstdba.vcxproj b/src/ext/Bal/wixstdba/wixstdba.vcxproj
index a43cc345..9273c1ed 100644
--- a/src/ext/Bal/wixstdba/wixstdba.vcxproj
+++ b/src/ext/Bal/wixstdba/wixstdba.vcxproj
@@ -52,6 +52,7 @@
52 <ClCompile Include="wixstdba.cpp" /> 52 <ClCompile Include="wixstdba.cpp" />
53 </ItemGroup> 53 </ItemGroup>
54 <ItemGroup> 54 <ItemGroup>
55 <ClInclude Include="inc\preqba.h" />
55 <ClInclude Include="precomp.h" /> 56 <ClInclude Include="precomp.h" />
56 <ClInclude Include="resource.h" /> 57 <ClInclude Include="resource.h" />
57 </ItemGroup> 58 </ItemGroup>
diff --git a/src/test/burn/TestBA/TestBA.cs b/src/test/burn/TestBA/TestBA.cs
index 5f492efd..1548c05b 100644
--- a/src/test/burn/TestBA/TestBA.cs
+++ b/src/test/burn/TestBA/TestBA.cs
@@ -171,7 +171,13 @@ namespace WixToolset.Test.BA
171 this.dummyWindow.Dispose(); 171 this.dummyWindow.Dispose();
172 } 172 }
173 173
174 this.Engine.Quit(this.result & 0xFFFF); // return plain old Win32 error, not HRESULT. 174 var exitCode = this.result;
175 if ((exitCode & 0xFFFF0000) == unchecked(0x80070000))
176 {
177 exitCode &= 0xFFFF; // return plain old Win32 error, not HRESULT.
178 }
179
180 this.Engine.Quit(exitCode);
175 } 181 }
176 182
177 protected override void OnDetectUpdateBegin(DetectUpdateBeginEventArgs args) 183 protected override void OnDetectUpdateBegin(DetectUpdateBeginEventArgs args)
diff --git a/src/test/burn/TestData/Manual/BafThmutilTesting/precomp.cpp b/src/test/burn/TestData/Manual/BafThmutilTesting/precomp.cpp
index b20f4230..fc9d1177 100644
--- a/src/test/burn/TestData/Manual/BafThmutilTesting/precomp.cpp
+++ b/src/test/burn/TestData/Manual/BafThmutilTesting/precomp.cpp
@@ -40,6 +40,8 @@ LExit:
40} 40}
41 41
42extern "C" void WINAPI BAFunctionsDestroy( 42extern "C" void WINAPI BAFunctionsDestroy(
43 __in const BA_FUNCTIONS_DESTROY_ARGS* /*pArgs*/,
44 __inout BA_FUNCTIONS_DESTROY_RESULTS* /*pResults*/
43 ) 45 )
44{ 46{
45 BalUninitialize(); 47 BalUninitialize();
diff --git a/src/test/burn/WixToolset.WixBA/WixBA.cs b/src/test/burn/WixToolset.WixBA/WixBA.cs
index 68288f2d..60426ca8 100644
--- a/src/test/burn/WixToolset.WixBA/WixBA.cs
+++ b/src/test/burn/WixToolset.WixBA/WixBA.cs
@@ -179,7 +179,14 @@ namespace WixToolset.WixBA
179 Threading.Dispatcher.Run(); 179 Threading.Dispatcher.Run();
180 180
181 this.PostTelemetry(); 181 this.PostTelemetry();
182 this.Engine.Quit(WixBA.Model.Result); 182
183 var exitCode = WixBA.Model.Result;
184 if ((exitCode & 0xFFFF0000) == unchecked(0x80070000))
185 {
186 exitCode &= 0xFFFF; // return plain old Win32 error, not HRESULT.
187 }
188
189 this.Engine.Quit(exitCode);
183 } 190 }
184 191
185 private void PostTelemetry() 192 private void PostTelemetry()
diff --git a/src/test/burn/WixToolsetTest.BurnE2E/PrereqBaTests.cs b/src/test/burn/WixToolsetTest.BurnE2E/PrereqBaTests.cs
index ec828f89..52e165b4 100644
--- a/src/test/burn/WixToolsetTest.BurnE2E/PrereqBaTests.cs
+++ b/src/test/burn/WixToolsetTest.BurnE2E/PrereqBaTests.cs
@@ -12,6 +12,8 @@ namespace WixToolsetTest.BurnE2E
12 { 12 {
13 public PrereqBaTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { } 13 public PrereqBaTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { }
14 14
15 const int E_PREREQBA_INFINITE_LOOP = -2_114_714_646;
16
15 /// <summary> 17 /// <summary>
16 /// This bundle purposely provides a .runtimeconfig.json file that requires a version of .NET Core that doesn't exist, 18 /// This bundle purposely provides a .runtimeconfig.json file that requires a version of .NET Core that doesn't exist,
17 /// with an MSI package to represent the prerequisite package. 19 /// with an MSI package to represent the prerequisite package.
@@ -32,7 +34,7 @@ namespace WixToolsetTest.BurnE2E
32 // Source file should *not* be installed 34 // Source file should *not* be installed
33 Assert.False(File.Exists(packageASourceCodeInstalled), $"Package A payload should not be there on test start: {packageASourceCodeInstalled}"); 35 Assert.False(File.Exists(packageASourceCodeInstalled), $"Package A payload should not be there on test start: {packageASourceCodeInstalled}");
34 36
35 bundleA.Install(); 37 bundleA.Install(E_PREREQBA_INFINITE_LOOP);
36 38
37 // Part of the test is Install actually completing. 39 // Part of the test is Install actually completing.
38 40
@@ -63,7 +65,7 @@ namespace WixToolsetTest.BurnE2E
63 // Source file should *not* be installed 65 // Source file should *not* be installed
64 Assert.False(File.Exists(packageBSourceCodeInstalled), $"Package B payload should not be there on test start: {packageBSourceCodeInstalled}"); 66 Assert.False(File.Exists(packageBSourceCodeInstalled), $"Package B payload should not be there on test start: {packageBSourceCodeInstalled}");
65 67
66 bundleB.Install(); 68 bundleB.Install(E_PREREQBA_INFINITE_LOOP);
67 69
68 // Part of the test is Install actually completing. 70 // Part of the test is Install actually completing.
69 71