aboutsummaryrefslogtreecommitdiff
path: root/src/ext/Bal/dnchost/dnchost.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ext/Bal/dnchost/dnchost.cpp')
-rw-r--r--src/ext/Bal/dnchost/dnchost.cpp309
1 files changed, 309 insertions, 0 deletions
diff --git a/src/ext/Bal/dnchost/dnchost.cpp b/src/ext/Bal/dnchost/dnchost.cpp
new file mode 100644
index 00000000..8ca326fc
--- /dev/null
+++ b/src/ext/Bal/dnchost/dnchost.cpp
@@ -0,0 +1,309 @@
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
3#include "precomp.h"
4
5static DNCSTATE vstate = { };
6
7
8// internal function declarations
9
10static HRESULT LoadModulePaths(
11 __in DNCSTATE* pState
12 );
13static HRESULT LoadDncConfiguration(
14 __in DNCSTATE* pState,
15 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs
16 );
17static HRESULT LoadRuntime(
18 __in DNCSTATE* pState
19 );
20static HRESULT LoadManagedBootstrapperApplicationFactory(
21 __in DNCSTATE* pState
22 );
23static HRESULT CreatePrerequisiteBA(
24 __in HRESULT hrHostInitialization,
25 __in IBootstrapperEngine* pEngine,
26 __in LPCWSTR wzAppBase,
27 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
28 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
29 );
30
31
32// function definitions
33
34extern "C" BOOL WINAPI DllMain(
35 IN HINSTANCE hInstance,
36 IN DWORD dwReason,
37 IN LPVOID /* pvReserved */
38 )
39{
40 switch (dwReason)
41 {
42 case DLL_PROCESS_ATTACH:
43 ::DisableThreadLibraryCalls(hInstance);
44 vstate.hInstance = hInstance;
45 break;
46
47 case DLL_PROCESS_DETACH:
48 vstate.hInstance = NULL;
49 break;
50 }
51
52 return TRUE;
53}
54
55extern "C" HRESULT WINAPI BootstrapperApplicationCreate(
56 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
57 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
58 )
59{
60 HRESULT hr = S_OK;
61 HRESULT hrHostInitialization = S_OK;
62 IBootstrapperEngine* pEngine = NULL;
63
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);
69 ExitOnFailure(hr, "Failed to initialize Bal.");
70
71 if (!vstate.fInitialized)
72 {
73 hr = XmlInitialize();
74 BalExitOnFailure(hr, "Failed to initialize XML.");
75
76 hr = LoadModulePaths(&vstate);
77 BalExitOnFailure(hr, "Failed to get the host base path.");
78
79 hr = LoadDncConfiguration(&vstate, pArgs);
80 BalExitOnFailure(hr, "Failed to get the dnc configuration.");
81
82 vstate.fInitialized = TRUE;
83 }
84
85 if (!vstate.fInitializedRuntime)
86 {
87 hr = LoadRuntime(&vstate);
88
89 vstate.fInitializedRuntime = SUCCEEDED(hr);
90 }
91
92 if (vstate.fInitializedRuntime)
93 {
94 if (!vstate.pAppFactory)
95 {
96 hr = LoadManagedBootstrapperApplicationFactory(&vstate);
97 BalExitOnFailure(hr, "Failed to create the .NET Core bootstrapper application factory.");
98 }
99
100 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading .NET Core %ls bootstrapper application.", DNCHOSTTYPE_FDD == vstate.type ? L"FDD" : L"SCD");
101
102 hr = vstate.pAppFactory->Create(pArgs, pResults);
103 BalExitOnFailure(hr, "Failed to create the .NET Core bootstrapper application.");
104 }
105 else // fallback to the prerequisite BA.
106 {
107 if (DNCHOSTTYPE_SCD == vstate.type)
108 {
109 hrHostInitialization = E_DNCHOST_SCD_RUNTIME_FAILURE;
110 BalLogError(hr, "The self-contained .NET Core runtime failed to load. This is an unrecoverable error.");
111 }
112 else
113 {
114 hrHostInitialization = S_OK;
115 }
116 BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "Loading prerequisite bootstrapper application because .NET Core host could not be loaded, error: 0x%08x.", hr);
117
118 hr = CreatePrerequisiteBA(hrHostInitialization, pEngine, vstate.sczAppBase, pArgs, pResults);
119 BalExitOnFailure(hr, "Failed to create the pre-requisite bootstrapper application.");
120 }
121
122LExit:
123 ReleaseNullObject(pEngine);
124
125 return hr;
126}
127
128extern "C" void WINAPI BootstrapperApplicationDestroy()
129{
130 if (vstate.hMbapreqModule)
131 {
132 PFN_BOOTSTRAPPER_APPLICATION_DESTROY pfnDestroy = reinterpret_cast<PFN_BOOTSTRAPPER_APPLICATION_DESTROY>(::GetProcAddress(vstate.hMbapreqModule, "DncPrereqBootstrapperApplicationDestroy"));
133 if (pfnDestroy)
134 {
135 (*pfnDestroy)();
136 }
137
138 ::FreeLibrary(vstate.hMbapreqModule);
139 vstate.hMbapreqModule = NULL;
140 }
141
142 BalUninitialize();
143}
144
145static HRESULT LoadModulePaths(
146 __in DNCSTATE* pState
147 )
148{
149 HRESULT hr = S_OK;
150
151 hr = PathForCurrentProcess(&pState->sczModuleFullPath, pState->hInstance);
152 BalExitOnFailure(hr, "Failed to get the full host path.");
153
154 hr = PathGetDirectory(pState->sczModuleFullPath, &pState->sczAppBase);
155 BalExitOnFailure(hr, "Failed to get the directory of the full process path.");
156
157 hr = PathConcat(pState->sczAppBase, DNC_ASSEMBLY_FILE_NAME, &pState->sczManagedHostPath);
158 BalExitOnFailure(hr, "Failed to create managed host path.");
159
160LExit:
161 return hr;
162}
163
164static HRESULT LoadDncConfiguration(
165 __in DNCSTATE* pState,
166 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs
167 )
168{
169 HRESULT hr = S_OK;
170 IXMLDOMDocument* pixdManifest = NULL;
171 IXMLDOMNode* pixnHost = NULL;
172 LPWSTR sczPayloadName = NULL;
173 DWORD dwBool = 0;
174
175 hr = XmlLoadDocumentFromFile(pArgs->pCommand->wzBootstrapperApplicationDataPath, &pixdManifest);
176 BalExitOnFailure(hr, "Failed to load BalManifest '%ls'", pArgs->pCommand->wzBootstrapperApplicationDataPath);
177
178 hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixBalBAFactoryAssembly", &pixnHost);
179 BalExitOnFailure(hr, "Failed to get WixBalBAFactoryAssembly element.");
180
181 if (S_FALSE == hr)
182 {
183 hr = E_NOTFOUND;
184 BalExitOnRootFailure(hr, "Failed to find WixBalBAFactoryAssembly element in bootstrapper application config.");
185 }
186
187 hr = XmlGetAttributeEx(pixnHost, L"FilePath", &sczPayloadName);
188 BalExitOnFailure(hr, "Failed to get WixBalBAFactoryAssembly/@FilePath.");
189
190 hr = PathConcat(pArgs->pCommand->wzBootstrapperWorkingFolder, sczPayloadName, &pState->sczBaFactoryAssemblyPath);
191 BalExitOnFailure(hr, "Failed to create BaFactoryAssemblyPath.");
192
193 LPCWSTR wzFileName = PathFile(pState->sczBaFactoryAssemblyPath);
194 LPCWSTR wzExtension = PathExtension(pState->sczBaFactoryAssemblyPath);
195 if (!wzExtension)
196 {
197 BalExitOnFailure(hr = E_FAIL, "BaFactoryAssemblyPath has no extension.");
198 }
199
200 hr = StrAllocString(&pState->sczBaFactoryAssemblyName, wzFileName, wzExtension - wzFileName);
201 BalExitOnFailure(hr, "Failed to copy BAFactoryAssembly payload Name.");
202
203 hr = StrAllocString(&pState->sczBaFactoryDepsJsonPath, pState->sczBaFactoryAssemblyPath, wzExtension - pState->sczBaFactoryAssemblyPath);
204 BalExitOnFailure(hr, "Failed to initialize deps json path.");
205
206 hr = StrAllocString(&pState->sczBaFactoryRuntimeConfigPath, pState->sczBaFactoryDepsJsonPath, 0);
207 BalExitOnFailure(hr, "Failed to initialize runtime config path.");
208
209 hr = StrAllocConcat(&pState->sczBaFactoryDepsJsonPath, L".deps.json", 0);
210 BalExitOnFailure(hr, "Failed to concat extension to deps json path.");
211
212 hr = StrAllocConcat(&pState->sczBaFactoryRuntimeConfigPath, L".runtimeconfig.json", 0);
213 BalExitOnFailure(hr, "Failed to concat extension to runtime config path.");
214
215 pState->type = DNCHOSTTYPE_FDD;
216
217 hr = XmlSelectSingleNode(pixdManifest, L"/BootstrapperApplicationData/WixDncOptions", &pixnHost);
218 if (S_FALSE == hr)
219 {
220 ExitFunction1(hr = S_OK);
221 }
222 BalExitOnFailure(hr, "Failed to find WixDncOptions element in bootstrapper application config.");
223
224 hr = XmlGetAttributeNumber(pixnHost, L"SelfContainedDeployment", &dwBool);
225 if (S_FALSE == hr)
226 {
227 hr = S_OK;
228 }
229 else if (SUCCEEDED(hr) && dwBool)
230 {
231 pState->type = DNCHOSTTYPE_SCD;
232 }
233 BalExitOnFailure(hr, "Failed to get SelfContainedDeployment value.");
234
235LExit:
236 ReleaseStr(sczPayloadName);
237 ReleaseObject(pixnHost);
238 ReleaseObject(pixdManifest);
239
240 return hr;
241}
242
243static HRESULT LoadRuntime(
244 __in DNCSTATE* pState
245 )
246{
247 HRESULT hr = S_OK;
248
249 hr = DnchostLoadRuntime(
250 &pState->hostfxrState,
251 pState->sczModuleFullPath,
252 pState->sczManagedHostPath,
253 pState->sczBaFactoryDepsJsonPath,
254 pState->sczBaFactoryRuntimeConfigPath);
255
256 return hr;
257}
258
259static HRESULT LoadManagedBootstrapperApplicationFactory(
260 __in DNCSTATE* pState
261 )
262{
263 HRESULT hr = S_OK;
264
265 hr = DnchostCreateFactory(
266 &pState->hostfxrState,
267 pState->sczBaFactoryAssemblyName,
268 pState->sczBaFactoryAssemblyPath,
269 &pState->pAppFactory);
270
271 return hr;
272}
273
274static HRESULT CreatePrerequisiteBA(
275 __in HRESULT hrHostInitialization,
276 __in IBootstrapperEngine* pEngine,
277 __in LPCWSTR wzAppBase,
278 __in const BOOTSTRAPPER_CREATE_ARGS* pArgs,
279 __inout BOOTSTRAPPER_CREATE_RESULTS* pResults
280 )
281{
282 HRESULT hr = S_OK;
283 LPWSTR sczDncpreqPath = NULL;
284 HMODULE hModule = NULL;
285
286 hr = PathConcat(wzAppBase, L"dncpreq.dll", &sczDncpreqPath);
287 BalExitOnFailure(hr, "Failed to get path to pre-requisite BA.");
288
289 hModule = ::LoadLibraryW(sczDncpreqPath);
290 BalExitOnNullWithLastError(hModule, hr, "Failed to load pre-requisite BA DLL.");
291
292 PFN_DNCPREQ_BOOTSTRAPPER_APPLICATION_CREATE pfnCreate = reinterpret_cast<PFN_DNCPREQ_BOOTSTRAPPER_APPLICATION_CREATE>(::GetProcAddress(hModule, "DncPrereqBootstrapperApplicationCreate"));
293 BalExitOnNullWithLastError(pfnCreate, hr, "Failed to get DncPrereqBootstrapperApplicationCreate entry-point from: %ls", sczDncpreqPath);
294
295 hr = pfnCreate(hrHostInitialization, pEngine, pArgs, pResults);
296 BalExitOnFailure(hr, "Failed to create prequisite bootstrapper app.");
297
298 vstate.hMbapreqModule = hModule;
299 hModule = NULL;
300
301LExit:
302 if (hModule)
303 {
304 ::FreeLibrary(hModule);
305 }
306 ReleaseStr(sczDncpreqPath);
307
308 return hr;
309}