aboutsummaryrefslogtreecommitdiff
path: root/src/ext/Bal/dnchost
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2021-05-03 15:55:48 -0700
committerRob Mensching <rob@firegiant.com>2021-05-03 15:55:48 -0700
commitba7bab476501c16e437b0aee71c1be02c3dda176 (patch)
tree814fba485c29a7dfe1adb396169e27ed641ef9a3 /src/ext/Bal/dnchost
parent14987a72cc1a3493ca8f80693d273352fc314bd9 (diff)
downloadwix-ba7bab476501c16e437b0aee71c1be02c3dda176.tar.gz
wix-ba7bab476501c16e437b0aee71c1be02c3dda176.tar.bz2
wix-ba7bab476501c16e437b0aee71c1be02c3dda176.zip
Move Bal.wixext into ext
Diffstat (limited to 'src/ext/Bal/dnchost')
-rw-r--r--src/ext/Bal/dnchost/coreclrhost.h137
-rw-r--r--src/ext/Bal/dnchost/dnchost.cpp309
-rw-r--r--src/ext/Bal/dnchost/dnchost.def6
-rw-r--r--src/ext/Bal/dnchost/dnchost.h35
-rw-r--r--src/ext/Bal/dnchost/dnchost.vcxproj106
-rw-r--r--src/ext/Bal/dnchost/dncutil.cpp411
-rw-r--r--src/ext/Bal/dnchost/dncutil.h38
-rw-r--r--src/ext/Bal/dnchost/packages.config13
-rw-r--r--src/ext/Bal/dnchost/precomp.cpp3
-rw-r--r--src/ext/Bal/dnchost/precomp.h31
10 files changed, 1089 insertions, 0 deletions
diff --git a/src/ext/Bal/dnchost/coreclrhost.h b/src/ext/Bal/dnchost/coreclrhost.h
new file mode 100644
index 00000000..07f28735
--- /dev/null
+++ b/src/ext/Bal/dnchost/coreclrhost.h
@@ -0,0 +1,137 @@
1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5
6
7// ***** ABOUT THIS HEADER *****
8// **************************************************************************************
9//
10// This is the version on 2019-12-22 from
11// https://github.com/dotnet/runtime/blob/master/src/coreclr/src/coreclr/hosts/inc/coreclrhost.h
12//
13// **************************************************************************************
14// ****************************
15
16
17//
18// APIs for hosting CoreCLR
19//
20
21#ifndef __CORECLR_HOST_H__
22#define __CORECLR_HOST_H__
23
24#if defined(_WIN32) && defined(_M_IX86)
25#define CORECLR_CALLING_CONVENTION __stdcall
26#else
27#define CORECLR_CALLING_CONVENTION
28#endif
29
30// For each hosting API, we define a function prototype and a function pointer
31// The prototype is useful for implicit linking against the dynamic coreclr
32// library and the pointer for explicit dynamic loading (dlopen, LoadLibrary)
33#define CORECLR_HOSTING_API(function, ...) \
34 extern "C" int CORECLR_CALLING_CONVENTION function(__VA_ARGS__); \
35 typedef int (CORECLR_CALLING_CONVENTION *function##_ptr)(__VA_ARGS__)
36
37//
38// Initialize the CoreCLR. Creates and starts CoreCLR host and creates an app domain
39//
40// Parameters:
41// exePath - Absolute path of the executable that invoked the ExecuteAssembly (the native host application)
42// appDomainFriendlyName - Friendly name of the app domain that will be created to execute the assembly
43// propertyCount - Number of properties (elements of the following two arguments)
44// propertyKeys - Keys of properties of the app domain
45// propertyValues - Values of properties of the app domain
46// hostHandle - Output parameter, handle of the created host
47// domainId - Output parameter, id of the created app domain
48//
49// Returns:
50// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
51//
52CORECLR_HOSTING_API(coreclr_initialize,
53 const char* exePath,
54 const char* appDomainFriendlyName,
55 int propertyCount,
56 const char** propertyKeys,
57 const char** propertyValues,
58 void** hostHandle,
59 unsigned int* domainId);
60
61//
62// Shutdown CoreCLR. It unloads the app domain and stops the CoreCLR host.
63//
64// Parameters:
65// hostHandle - Handle of the host
66// domainId - Id of the domain
67//
68// Returns:
69// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
70//
71CORECLR_HOSTING_API(coreclr_shutdown,
72 void* hostHandle,
73 unsigned int domainId);
74
75//
76// Shutdown CoreCLR. It unloads the app domain and stops the CoreCLR host.
77//
78// Parameters:
79// hostHandle - Handle of the host
80// domainId - Id of the domain
81// latchedExitCode - Latched exit code after domain unloaded
82//
83// Returns:
84// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
85//
86CORECLR_HOSTING_API(coreclr_shutdown_2,
87 void* hostHandle,
88 unsigned int domainId,
89 int* latchedExitCode);
90
91//
92// Create a native callable function pointer for a managed method.
93//
94// Parameters:
95// hostHandle - Handle of the host
96// domainId - Id of the domain
97// entryPointAssemblyName - Name of the assembly which holds the custom entry point
98// entryPointTypeName - Name of the type which holds the custom entry point
99// entryPointMethodName - Name of the method which is the custom entry point
100// delegate - Output parameter, the function stores a native callable function pointer to the delegate at the specified address
101//
102// Returns:
103// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
104//
105CORECLR_HOSTING_API(coreclr_create_delegate,
106 void* hostHandle,
107 unsigned int domainId,
108 const char* entryPointAssemblyName,
109 const char* entryPointTypeName,
110 const char* entryPointMethodName,
111 void** delegate);
112
113//
114// Execute a managed assembly with given arguments
115//
116// Parameters:
117// hostHandle - Handle of the host
118// domainId - Id of the domain
119// argc - Number of arguments passed to the executed assembly
120// argv - Array of arguments passed to the executed assembly
121// managedAssemblyPath - Path of the managed assembly to execute (or NULL if using a custom entrypoint).
122// exitCode - Exit code returned by the executed assembly
123//
124// Returns:
125// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
126//
127CORECLR_HOSTING_API(coreclr_execute_assembly,
128 void* hostHandle,
129 unsigned int domainId,
130 int argc,
131 const char** argv,
132 const char* managedAssemblyPath,
133 unsigned int* exitCode);
134
135#undef CORECLR_HOSTING_API
136
137#endif // __CORECLR_HOST_H__ \ No newline at end of file
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}
diff --git a/src/ext/Bal/dnchost/dnchost.def b/src/ext/Bal/dnchost/dnchost.def
new file mode 100644
index 00000000..4488df94
--- /dev/null
+++ b/src/ext/Bal/dnchost/dnchost.def
@@ -0,0 +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.
2
3
4EXPORTS
5 BootstrapperApplicationCreate
6 BootstrapperApplicationDestroy
diff --git a/src/ext/Bal/dnchost/dnchost.h b/src/ext/Bal/dnchost/dnchost.h
new file mode 100644
index 00000000..22fd8f5e
--- /dev/null
+++ b/src/ext/Bal/dnchost/dnchost.h
@@ -0,0 +1,35 @@
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
5enum DNCHOSTTYPE
6{
7 DNCHOSTTYPE_UNKNOWN,
8 DNCHOSTTYPE_FDD,
9 DNCHOSTTYPE_SCD,
10};
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
20{
21 BOOL fInitialized;
22 BOOL fInitializedRuntime;
23 HINSTANCE hInstance;
24 LPWSTR sczModuleFullPath;
25 LPWSTR sczAppBase;
26 LPWSTR sczManagedHostPath;
27 LPWSTR sczBaFactoryAssemblyName;
28 LPWSTR sczBaFactoryAssemblyPath;
29 LPWSTR sczBaFactoryDepsJsonPath;
30 LPWSTR sczBaFactoryRuntimeConfigPath;
31 DNCHOSTTYPE type;
32 HOSTFXR_STATE hostfxrState;
33 IBootstrapperApplicationFactory* pAppFactory;
34 HMODULE hMbapreqModule;
35};
diff --git a/src/ext/Bal/dnchost/dnchost.vcxproj b/src/ext/Bal/dnchost/dnchost.vcxproj
new file mode 100644
index 00000000..bef3f77e
--- /dev/null
+++ b/src/ext/Bal/dnchost/dnchost.vcxproj
@@ -0,0 +1,106 @@
1<?xml version="1.0" encoding="utf-8"?>
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<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
4 <Import Project="..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.props" Condition="Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.props')" />
5 <Import Project="..\..\packages\Microsoft.SourceLink.Common.1.0.0\build\Microsoft.SourceLink.Common.props" Condition="Exists('..\..\packages\Microsoft.SourceLink.Common.1.0.0\build\Microsoft.SourceLink.Common.props')" />
6 <Import Project="..\..\packages\Microsoft.Build.Tasks.Git.1.0.0\build\Microsoft.Build.Tasks.Git.props" Condition="Exists('..\..\packages\Microsoft.Build.Tasks.Git.1.0.0\build\Microsoft.Build.Tasks.Git.props')" />
7 <Import Project="..\..\packages\WixToolset.BalUtil.4.0.58\build\WixToolset.BalUtil.props" Condition="Exists('..\..\packages\WixToolset.BalUtil.4.0.58\build\WixToolset.BalUtil.props')" />
8 <Import Project="..\..\packages\WixToolset.BootstrapperCore.Native.4.0.141\build\WixToolset.BootstrapperCore.Native.props" Condition="Exists('..\..\packages\WixToolset.BootstrapperCore.Native.4.0.141\build\WixToolset.BootstrapperCore.Native.props')" />
9 <Import Project="..\..\packages\WixToolset.DUtil.4.0.72\build\WixToolset.DUtil.props" Condition="Exists('..\..\packages\WixToolset.DUtil.4.0.72\build\WixToolset.DUtil.props')" />
10 <ItemGroup Label="ProjectConfigurations">
11 <ProjectConfiguration Include="Debug|ARM64">
12 <Configuration>Debug</Configuration>
13 <Platform>ARM64</Platform>
14 </ProjectConfiguration>
15 <ProjectConfiguration Include="Release|ARM64">
16 <Configuration>Release</Configuration>
17 <Platform>ARM64</Platform>
18 </ProjectConfiguration>
19 <ProjectConfiguration Include="Debug|Win32">
20 <Configuration>Debug</Configuration>
21 <Platform>Win32</Platform>
22 </ProjectConfiguration>
23 <ProjectConfiguration Include="Release|Win32">
24 <Configuration>Release</Configuration>
25 <Platform>Win32</Platform>
26 </ProjectConfiguration>
27 <ProjectConfiguration Include="Debug|x64">
28 <Configuration>Debug</Configuration>
29 <Platform>x64</Platform>
30 </ProjectConfiguration>
31 <ProjectConfiguration Include="Release|x64">
32 <Configuration>Release</Configuration>
33 <Platform>x64</Platform>
34 </ProjectConfiguration>
35 </ItemGroup>
36 <PropertyGroup Label="Globals">
37 <ProjectGuid>{B6F70281-6583-4138-BB7F-AABFEBBB3CA2}</ProjectGuid>
38 <ConfigurationType>DynamicLibrary</ConfigurationType>
39 <PlatformToolset>v142</PlatformToolset>
40 <CharacterSet>Unicode</CharacterSet>
41 <TargetName>dnchost</TargetName>
42 <ProjectModuleDefinitionFile>dnchost.def</ProjectModuleDefinitionFile>
43 </PropertyGroup>
44 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
45 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
46 <PropertyGroup>
47 <NetHostPlatform>$(Platform)</NetHostPlatform>
48 <NetHostPlatform Condition=" '$(NetHostPlatform)'=='Win32' ">x86</NetHostPlatform>
49 <NetHostPath>..\..\packages\runtime.win-$(NetHostPlatform).Microsoft.NETCore.DotNetAppHost.5.0.0\runtimes\win-$(NetHostPlatform)\native\</NetHostPath>
50 <ProjectAdditionalLinkLibraries>shlwapi.lib;$(NetHostPath)libnethost.lib</ProjectAdditionalLinkLibraries>
51 </PropertyGroup>
52 <ItemGroup>
53 <ClCompile Include="dnchost.cpp" />
54 <ClCompile Include="dncutil.cpp" />
55 <ClCompile Include="precomp.cpp">
56 <PrecompiledHeader>Create</PrecompiledHeader>
57 </ClCompile>
58 </ItemGroup>
59 <ItemGroup>
60 <ClInclude Include="coreclrhost.h" />
61 <ClInclude Include="dnchost.h" />
62 <ClInclude Include="dncutil.h" />
63 <ClInclude Include="precomp.h" />
64 </ItemGroup>
65 <ItemGroup>
66 <None Include="dnchost.def" />
67 </ItemGroup>
68 <ItemGroup>
69 <None Include="packages.config" />
70 </ItemGroup>
71 <ItemDefinitionGroup>
72 <ClCompile>
73 <AdditionalIncludeDirectories>$(BaseOutputPath)obj;$(NetHostPath);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
74 </ClCompile>
75 <Link>
76 <AdditionalOptions>/LTCG %(AdditionalOptions)</AdditionalOptions>
77 </Link>
78 </ItemDefinitionGroup>
79 <ItemGroup>
80 <ProjectReference Include="..\WixToolset.Dnc.Host\WixToolset.Dnc.Host.csproj">
81 <Project>{0D780900-C2FF-4FA2-8CB5-8A19768724C5}</Project>
82 <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
83 <SkipGetTargetFrameworkProperties>true</SkipGetTargetFrameworkProperties>
84 </ProjectReference>
85 </ItemGroup>
86 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
87 <Import Project="..\..\packages\Microsoft.Build.Tasks.Git.1.0.0\build\Microsoft.Build.Tasks.Git.targets" Condition="Exists('..\..\packages\Microsoft.Build.Tasks.Git.1.0.0\build\Microsoft.Build.Tasks.Git.targets')" />
88 <Import Project="..\..\packages\Microsoft.SourceLink.Common.1.0.0\build\Microsoft.SourceLink.Common.targets" Condition="Exists('..\..\packages\Microsoft.SourceLink.Common.1.0.0\build\Microsoft.SourceLink.Common.targets')" />
89 <Import Project="..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.targets" Condition="Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.targets')" />
90 <Import Project="..\..\packages\Nerdbank.GitVersioning.3.3.37\build\Nerdbank.GitVersioning.targets" Condition="Exists('..\..\packages\Nerdbank.GitVersioning.3.3.37\build\Nerdbank.GitVersioning.targets')" />
91 <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
92 <PropertyGroup>
93 <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
94 </PropertyGroup>
95 <Error Condition="!Exists('..\..\packages\Microsoft.Build.Tasks.Git.1.0.0\build\Microsoft.Build.Tasks.Git.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Build.Tasks.Git.1.0.0\build\Microsoft.Build.Tasks.Git.props'))" />
96 <Error Condition="!Exists('..\..\packages\Microsoft.Build.Tasks.Git.1.0.0\build\Microsoft.Build.Tasks.Git.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.Build.Tasks.Git.1.0.0\build\Microsoft.Build.Tasks.Git.targets'))" />
97 <Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.Common.1.0.0\build\Microsoft.SourceLink.Common.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.Common.1.0.0\build\Microsoft.SourceLink.Common.props'))" />
98 <Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.Common.1.0.0\build\Microsoft.SourceLink.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.Common.1.0.0\build\Microsoft.SourceLink.Common.targets'))" />
99 <Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.props'))" />
100 <Error Condition="!Exists('..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Microsoft.SourceLink.GitHub.1.0.0\build\Microsoft.SourceLink.GitHub.targets'))" />
101 <Error Condition="!Exists('..\..\packages\Nerdbank.GitVersioning.3.3.37\build\Nerdbank.GitVersioning.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Nerdbank.GitVersioning.3.3.37\build\Nerdbank.GitVersioning.targets'))" />
102 <Error Condition="!Exists('..\..\packages\WixToolset.BalUtil.4.0.58\build\WixToolset.BalUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.BalUtil.4.0.58\build\WixToolset.BalUtil.props'))" />
103 <Error Condition="!Exists('..\..\packages\WixToolset.BootstrapperCore.Native.4.0.141\build\WixToolset.BootstrapperCore.Native.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.BootstrapperCore.Native.4.0.141\build\WixToolset.BootstrapperCore.Native.props'))" />
104 <Error Condition="!Exists('..\..\packages\WixToolset.DUtil.4.0.72\build\WixToolset.DUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.DUtil.4.0.72\build\WixToolset.DUtil.props'))" />
105 </Target>
106</Project> \ No newline at end of file
diff --git a/src/ext/Bal/dnchost/dncutil.cpp b/src/ext/Bal/dnchost/dncutil.cpp
new file mode 100644
index 00000000..34d14911
--- /dev/null
+++ b/src/ext/Bal/dnchost/dncutil.cpp
@@ -0,0 +1,411 @@
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
5// https://github.com/dotnet/runtime/blob/master/src/installer/corehost/error_codes.h
6#define InvalidArgFailure 0x80008081
7#define HostApiBufferTooSmall 0x80008098
8#define HostApiUnsupportedVersion 0x800080a2
9
10// internal function declarations
11
12static HRESULT GetHostfxrPath(
13 __in HOSTFXR_STATE* pState,
14 __in LPCWSTR wzNativeHostPath
15 );
16static HRESULT LoadHostfxr(
17 __in HOSTFXR_STATE* pState
18 );
19static HRESULT InitializeHostfxr(
20 __in HOSTFXR_STATE* pState,
21 __in LPCWSTR wzManagedHostPath,
22 __in LPCWSTR wzDepsJsonPath,
23 __in LPCWSTR wzRuntimeConfigPath
24 );
25static HRESULT InitializeCoreClr(
26 __in HOSTFXR_STATE* pState,
27 __in LPCWSTR wzNativeHostPath
28 );
29static HRESULT InitializeCoreClrPre5(
30 __in HOSTFXR_STATE* pState,
31 __in LPCWSTR wzNativeHostPath
32 );
33static HRESULT LoadCoreClr(
34 __in HOSTFXR_STATE* pState,
35 __in LPCWSTR wzCoreClrPath
36 );
37static HRESULT StartCoreClr(
38 __in HOSTFXR_STATE* pState,
39 __in LPCWSTR wzNativeHostPath,
40 __in DWORD cProperties,
41 __in LPCWSTR* propertyKeys,
42 __in LPCWSTR* propertyValues
43 );
44
45
46// function definitions
47
48HRESULT DnchostLoadRuntime(
49 __in HOSTFXR_STATE* pState,
50 __in LPCWSTR wzNativeHostPath,
51 __in LPCWSTR wzManagedHostPath,
52 __in LPCWSTR wzDepsJsonPath,
53 __in LPCWSTR wzRuntimeConfigPath
54 )
55{
56 HRESULT hr = S_OK;
57
58 hr = GetHostfxrPath(pState, wzNativeHostPath);
59 BalExitOnFailure(hr, "Failed to find hostfxr.");
60
61 hr = LoadHostfxr(pState);
62 BalExitOnFailure(hr, "Failed to load hostfxr.");
63
64 hr = InitializeHostfxr(pState, wzManagedHostPath, wzDepsJsonPath, wzRuntimeConfigPath);
65 BalExitOnFailure(hr, "Failed to initialize hostfxr.");
66
67 hr = InitializeCoreClr(pState, wzNativeHostPath);
68 BalExitOnFailure(hr, "Failed to initialize coreclr.");
69
70LExit:
71 return hr;
72}
73
74HRESULT DnchostCreateFactory(
75 __in HOSTFXR_STATE* pState,
76 __in LPCWSTR wzBaFactoryAssemblyName,
77 __in LPCWSTR wzBaFactoryAssemblyPath,
78 __out IBootstrapperApplicationFactory** ppAppFactory
79 )
80{
81 HRESULT hr = S_OK;
82 PFNCREATEBAFACTORY pfnCreateBAFactory = NULL;
83
84 if (pState->pfnGetFunctionPointer)
85 {
86 hr = pState->pfnGetFunctionPointer(
87 DNC_ENTRY_TYPEW,
88 DNC_STATIC_ENTRY_METHODW,
89 DNC_STATIC_ENTRY_DELEGATEW,
90 NULL,
91 NULL,
92 reinterpret_cast<void**>(&pfnCreateBAFactory));
93 BalExitOnFailure(hr, "Failed to create delegate through GetFunctionPointer.");
94 }
95 else
96 {
97 hr = pState->pfnCoreclrCreateDelegate(
98 pState->pClrHandle,
99 pState->dwDomainId,
100 DNC_ASSEMBLY_FULL_NAME,
101 DNC_ENTRY_TYPE,
102 DNC_STATIC_ENTRY_METHOD,
103 reinterpret_cast<void**>(&pfnCreateBAFactory));
104 BalExitOnFailure(hr, "Failed to create delegate in app domain.");
105 }
106
107 *ppAppFactory = pfnCreateBAFactory(wzBaFactoryAssemblyName, wzBaFactoryAssemblyPath);
108
109LExit:
110 return hr;
111}
112
113static HRESULT GetHostfxrPath(
114 __in HOSTFXR_STATE* pState,
115 __in LPCWSTR wzNativeHostPath
116 )
117{
118 HRESULT hr = S_OK;
119 get_hostfxr_parameters getHostfxrParameters = { };
120 int nrc = 0;
121 size_t cchHostFxrPath = MAX_PATH;
122
123 getHostfxrParameters.size = sizeof(get_hostfxr_parameters);
124 getHostfxrParameters.assembly_path = wzNativeHostPath;
125
126 // get_hostfxr_path does a full search on every call, so
127 // minimize the number of calls
128 // need to loop
129 for (;;)
130 {
131 cchHostFxrPath *= 2;
132 hr = StrAlloc(&pState->sczHostfxrPath, cchHostFxrPath);
133 BalExitOnFailure(hr, "Failed to allocate hostFxrPath.");
134
135 nrc = get_hostfxr_path(pState->sczHostfxrPath, &cchHostFxrPath, &getHostfxrParameters);
136 if (HostApiBufferTooSmall != nrc)
137 {
138 break;
139 }
140 }
141 if (0 != nrc)
142 {
143 BalExitOnFailure(hr = nrc, "GetHostfxrPath failed");
144 }
145
146LExit:
147 return hr;
148}
149
150static HRESULT LoadHostfxr(
151 __in HOSTFXR_STATE* pState
152 )
153{
154 HRESULT hr = S_OK;
155 HMODULE hHostfxr;
156
157 hHostfxr = ::LoadLibraryExW(pState->sczHostfxrPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
158 BalExitOnNullWithLastError(hHostfxr, hr, "Failed to load hostfxr from '%ls'.", pState->sczHostfxrPath);
159
160 pState->pfnHostfxrInitializeForApp = reinterpret_cast<hostfxr_initialize_for_dotnet_command_line_fn>(::GetProcAddress(hHostfxr, "hostfxr_initialize_for_dotnet_command_line"));
161 BalExitOnNullWithLastError(pState->pfnHostfxrInitializeForApp, hr, "Failed to get procedure address for hostfxr_initialize_for_dotnet_command_line.");
162
163 pState->pfnHostfxrGetRuntimeProperties = reinterpret_cast<hostfxr_get_runtime_properties_fn>(::GetProcAddress(hHostfxr, "hostfxr_get_runtime_properties"));
164 BalExitOnNullWithLastError(pState->pfnHostfxrGetRuntimeProperties, hr, "Failed to get procedure address for hostfxr_get_runtime_properties.");
165
166 pState->pfnHostfxrSetErrorWriter = reinterpret_cast<hostfxr_set_error_writer_fn>(::GetProcAddress(hHostfxr, "hostfxr_set_error_writer"));
167 BalExitOnNullWithLastError(pState->pfnHostfxrSetErrorWriter, hr, "Failed to get procedure address for hostfxr_set_error_writer.");
168
169 pState->pfnHostfxrClose = reinterpret_cast<hostfxr_close_fn>(::GetProcAddress(hHostfxr, "hostfxr_close"));
170 BalExitOnNullWithLastError(pState->pfnHostfxrClose, hr, "Failed to get procedure address for hostfxr_close.");
171
172 pState->pfnHostfxrGetRuntimeDelegate = reinterpret_cast<hostfxr_get_runtime_delegate_fn>(::GetProcAddress(hHostfxr, "hostfxr_get_runtime_delegate"));
173 BalExitOnNullWithLastError(pState->pfnHostfxrGetRuntimeDelegate, hr, "Failed to get procedure address for hostfxr_get_runtime_delegate.");
174
175LExit:
176 // Never unload the module since it isn't meant to be unloaded.
177
178 return hr;
179}
180
181static void HOSTFXR_CALLTYPE DnchostErrorWriter(
182 __in LPCWSTR wzMessage
183 )
184{
185 BOOTSTRAPPER_LOG_LEVEL level = BOOTSTRAPPER_LOG_LEVEL_ERROR;
186
187 if (CSTR_EQUAL == ::CompareString(LOCALE_INVARIANT, 0, wzMessage, -1, L"The requested delegate type is not available in the target framework.", -1))
188 {
189 level = BOOTSTRAPPER_LOG_LEVEL_DEBUG;
190 }
191
192 BalLog(level, "error from hostfxr: %ls", wzMessage);
193}
194
195static HRESULT InitializeHostfxr(
196 __in HOSTFXR_STATE* pState,
197 __in LPCWSTR wzManagedHostPath,
198 __in LPCWSTR wzDepsJsonPath,
199 __in LPCWSTR wzRuntimeConfigPath
200 )
201{
202 HRESULT hr = S_OK;
203
204 pState->pfnHostfxrSetErrorWriter(static_cast<hostfxr_error_writer_fn>(&DnchostErrorWriter));
205
206 LPCWSTR argv[] = {
207 L"exec",
208 L"--depsfile",
209 wzDepsJsonPath,
210 L"--runtimeconfig",
211 wzRuntimeConfigPath,
212 wzManagedHostPath,
213 };
214 hr = pState->pfnHostfxrInitializeForApp(sizeof(argv)/sizeof(LPWSTR), argv, NULL, &pState->hostContextHandle);
215 BalExitOnFailure(hr, "HostfxrInitializeForApp failed");
216
217LExit:
218 return hr;
219}
220
221static HRESULT InitializeCoreClr(
222 __in HOSTFXR_STATE* pState,
223 __in LPCWSTR wzNativeHostPath
224 )
225{
226 HRESULT hr = S_OK;
227
228 hr = pState->pfnHostfxrGetRuntimeDelegate(pState->hostContextHandle, hdt_get_function_pointer, reinterpret_cast<void**>(&pState->pfnGetFunctionPointer));
229 if (InvalidArgFailure == hr || // old versions of hostfxr don't allow calling GetRuntimeDelegate from InitializeForApp.
230 HostApiUnsupportedVersion == hr) // hdt_get_function_pointer was added in .NET 5.
231 {
232 hr = InitializeCoreClrPre5(pState, wzNativeHostPath);
233 }
234 else
235 {
236 ExitOnFailure(hr, "HostfxrGetRuntimeDelegate failed");
237 }
238
239LExit:
240 return hr;
241}
242
243static HRESULT InitializeCoreClrPre5(
244 __in HOSTFXR_STATE* pState,
245 __in LPCWSTR wzNativeHostPath
246 )
247{
248 HRESULT hr = S_OK;
249 int32_t rc = 0;
250 LPCWSTR* rgPropertyKeys = NULL;
251 LPCWSTR* rgPropertyValues = NULL;
252 size_t cProperties = 0;
253 LPWSTR* rgDirectories = NULL;
254 UINT cDirectories = 0;
255 LPWSTR sczCoreClrPath = NULL;
256
257 // We are not using hostfxr as it was intended to be used. We need to initialize hostfxr so that it properly initializes hostpolicy -
258 // there are pieces of the framework such as AssemblyDependencyResolver that won't work without that. We also need hostfxr to find a
259 // compatible framework for framework-dependent deployed BAs. We had to use hostfxr_initialize_for_dotnet_command_line since
260 // hostfxr_initialize_for_runtime_config doesn't currently (3.x) support self-contained deployed BAs. That means we're supposed to
261 // start the runtime through hostfxr_run_app, but that method shuts down the runtime before returning. We actually want to call
262 // hostfxr_get_runtime_delegate, but that method currently requires hostfxr to be initialized through
263 // hostfxr_initialize_for_runtime_config. So we're forced to locate coreclr.dll and manually load the runtime ourselves.
264
265 // Unfortunately, that's not the only problem. hostfxr has global state that tracks whether it started the runtime. While we keep our
266 // hostfxr_handle open, everyone that calls the hostfxr_initialize_* methods will block until we have started the runtime through
267 // hostfxr or closed our handle. If we close the handle, then hostfxr could potentially try to load a second runtime into the
268 // process, which is not supported. We're going to just keep our handle open since no one else in the process should be trying to
269 // start the runtime anyway.
270
271 rc = pState->pfnHostfxrGetRuntimeProperties(pState->hostContextHandle, &cProperties, rgPropertyKeys, rgPropertyValues);
272 if (HostApiBufferTooSmall != rc)
273 {
274 BalExitOnFailure(hr = rc, "HostfxrGetRuntimeProperties failed to return required size.");
275 }
276
277 rgPropertyKeys = static_cast<LPCWSTR*>(MemAlloc(sizeof(LPWSTR) * cProperties, TRUE));
278 rgPropertyValues = static_cast<LPCWSTR*>(MemAlloc(sizeof(LPWSTR) * cProperties, TRUE));
279 if (!rgPropertyKeys || !rgPropertyValues)
280 {
281 BalExitOnFailure(hr = E_OUTOFMEMORY, "Failed to allocate buffers for runtime properties.");
282 }
283
284 hr = pState->pfnHostfxrGetRuntimeProperties(pState->hostContextHandle, &cProperties, rgPropertyKeys, rgPropertyValues);
285 BalExitOnFailure(hr, "HostfxrGetRuntimeProperties failed.");
286
287 for (DWORD i = 0; i < cProperties; ++i)
288 {
289 if (CSTR_EQUAL == ::CompareString(LOCALE_INVARIANT, 0, rgPropertyKeys[i], -1, L"NATIVE_DLL_SEARCH_DIRECTORIES", -1))
290 {
291 hr = StrSplitAllocArray(&rgDirectories, &cDirectories, rgPropertyValues[i], L";");
292 BalExitOnFailure(hr, "Failed to split NATIVE_DLL_SEARCH_DIRECTORIES '%ls'", rgPropertyValues[i]);
293 }
294 }
295
296 for (DWORD i = 0; i < cDirectories; ++i)
297 {
298 hr = PathConcat(rgDirectories[i], L"coreclr.dll", &sczCoreClrPath);
299 BalExitOnFailure(hr, "Failed to allocate path to coreclr.");
300
301 if (::PathFileExists(sczCoreClrPath))
302 {
303 break;
304 }
305 else
306 {
307 ReleaseNullStr(sczCoreClrPath);
308 }
309 }
310
311 if (!sczCoreClrPath)
312 {
313 for (DWORD i = 0; i < cProperties; ++i)
314 {
315 BalLog(BOOTSTRAPPER_LOG_LEVEL_ERROR, "%ls: %ls", rgPropertyKeys[i], rgPropertyValues[i]);
316 }
317 BalExitOnFailure(hr = E_FILENOTFOUND, "Failed to locate coreclr.dll.");
318 }
319
320 hr = LoadCoreClr(pState, sczCoreClrPath);
321 BalExitOnFailure(hr, "Failed to load coreclr.");
322
323 hr = StartCoreClr(pState, wzNativeHostPath, (DWORD)cProperties, rgPropertyKeys, rgPropertyValues);
324 BalExitOnFailure(hr, "Failed to start coreclr.");
325
326LExit:
327 MemFree(rgDirectories);
328 MemFree(rgPropertyValues);
329 MemFree(rgPropertyKeys);
330 ReleaseStr(sczCoreClrPath);
331
332 return hr;
333}
334
335static HRESULT LoadCoreClr(
336 __in HOSTFXR_STATE* pState,
337 __in LPCWSTR wzCoreClrPath
338 )
339{
340 HRESULT hr = S_OK;
341 HMODULE hModule = NULL;
342
343 hModule = ::LoadLibraryExW(wzCoreClrPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
344 BalExitOnNullWithLastError(hModule, hr, "Failed to load coreclr.dll from '%ls'.", wzCoreClrPath);
345
346 pState->pfnCoreclrInitialize = reinterpret_cast<coreclr_initialize_ptr>(::GetProcAddress(hModule, "coreclr_initialize"));
347 BalExitOnNullWithLastError(pState->pfnCoreclrInitialize, hr, "Failed to get procedure address for coreclr_initialize.");
348
349 pState->pfnCoreclrCreateDelegate = reinterpret_cast<coreclr_create_delegate_ptr>(::GetProcAddress(hModule, "coreclr_create_delegate"));
350 BalExitOnNullWithLastError(pState->pfnCoreclrCreateDelegate, hr, "Failed to get procedure address for coreclr_create_delegate.");
351
352LExit:
353 // Never unload the module since coreclr doesn't support it.
354
355 return hr;
356}
357
358static HRESULT StartCoreClr(
359 __in HOSTFXR_STATE* pState,
360 __in LPCWSTR wzNativeHostPath,
361 __in DWORD cProperties,
362 __in LPCWSTR* propertyKeys,
363 __in LPCWSTR* propertyValues
364 )
365{
366 HRESULT hr = S_OK;
367 LPSTR szNativeHostPath = NULL;
368 LPSTR* rgPropertyKeys = NULL;
369 LPSTR* rgPropertyValues = NULL;
370
371 rgPropertyKeys = static_cast<LPSTR*>(MemAlloc(sizeof(LPSTR) * cProperties, TRUE));
372 rgPropertyValues = static_cast<LPSTR*>(MemAlloc(sizeof(LPSTR) * cProperties, TRUE));
373 if (!rgPropertyKeys || !rgPropertyValues)
374 {
375 BalExitOnFailure(hr = E_OUTOFMEMORY, "Failed to allocate buffers for runtime properties.");
376 }
377
378 hr = StrAnsiAllocString(&szNativeHostPath, wzNativeHostPath, 0, CP_UTF8);
379 BalExitOnFailure(hr, "Failed to convert module path to UTF8: %ls", wzNativeHostPath);
380
381 for (DWORD i = 0; i < cProperties; ++i)
382 {
383 hr = StrAnsiAllocString(&rgPropertyKeys[i], propertyKeys[i], 0, CP_UTF8);
384 BalExitOnFailure(hr, "Failed to convert property key to UTF8: %ls", propertyKeys[i]);
385
386 hr = StrAnsiAllocString(&rgPropertyValues[i], propertyValues[i], 0, CP_UTF8);
387 BalExitOnFailure(hr, "Failed to convert property value to UTF8: %ls", propertyValues[i]);
388 }
389
390 hr = pState->pfnCoreclrInitialize(szNativeHostPath, "MBA", cProperties, (LPCSTR*)rgPropertyKeys, (LPCSTR*)rgPropertyValues, &pState->pClrHandle, &pState->dwDomainId);
391 BalExitOnFailure(hr, "CoreclrInitialize failed.");
392
393LExit:
394 for (DWORD i = 0; i < cProperties; ++i)
395 {
396 if (rgPropertyKeys)
397 {
398 ReleaseStr(rgPropertyKeys[i]);
399 }
400
401 if (rgPropertyValues)
402 {
403 ReleaseStr(rgPropertyValues[i]);
404 }
405 }
406 ReleaseMem(rgPropertyValues);
407 ReleaseMem(rgPropertyKeys);
408 ReleaseStr(szNativeHostPath);
409
410 return hr;
411}
diff --git a/src/ext/Bal/dnchost/dncutil.h b/src/ext/Bal/dnchost/dncutil.h
new file mode 100644
index 00000000..85eda3b2
--- /dev/null
+++ b/src/ext/Bal/dnchost/dncutil.h
@@ -0,0 +1,38 @@
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
4typedef IBootstrapperApplicationFactory* (STDMETHODCALLTYPE* PFNCREATEBAFACTORY)(
5 __in LPCWSTR wzBaFactoryAssemblyName,
6 __in LPCWSTR wzBaFactoryAssemblyPath
7 );
8
9struct HOSTFXR_STATE
10{
11 LPWSTR sczHostfxrPath;
12 hostfxr_handle hostContextHandle;
13 hostfxr_initialize_for_dotnet_command_line_fn pfnHostfxrInitializeForApp;
14 hostfxr_get_runtime_properties_fn pfnHostfxrGetRuntimeProperties;
15 hostfxr_set_error_writer_fn pfnHostfxrSetErrorWriter;
16 hostfxr_close_fn pfnHostfxrClose;
17 hostfxr_get_runtime_delegate_fn pfnHostfxrGetRuntimeDelegate;
18 get_function_pointer_fn pfnGetFunctionPointer;
19 coreclr_initialize_ptr pfnCoreclrInitialize;
20 coreclr_create_delegate_ptr pfnCoreclrCreateDelegate;
21 void* pClrHandle;
22 UINT dwDomainId;
23};
24
25HRESULT DnchostLoadRuntime(
26 __in HOSTFXR_STATE* pState,
27 __in LPCWSTR wzNativeHostPath,
28 __in LPCWSTR wzManagedHostPath,
29 __in LPCWSTR wzDepsJsonPath,
30 __in LPCWSTR wzRuntimeConfigPath
31 );
32
33HRESULT DnchostCreateFactory(
34 __in HOSTFXR_STATE* pState,
35 __in LPCWSTR wzBaFactoryAssemblyName,
36 __in LPCWSTR wzBaFactoryAssemblyPath,
37 __out IBootstrapperApplicationFactory** ppAppFactory
38 );
diff --git a/src/ext/Bal/dnchost/packages.config b/src/ext/Bal/dnchost/packages.config
new file mode 100644
index 00000000..6c369364
--- /dev/null
+++ b/src/ext/Bal/dnchost/packages.config
@@ -0,0 +1,13 @@
1<?xml version="1.0" encoding="utf-8"?>
2<packages>
3 <package id="Microsoft.Build.Tasks.Git" version="1.0.0" targetFramework="native" developmentDependency="true" />
4 <package id="Microsoft.SourceLink.Common" version="1.0.0" targetFramework="native" developmentDependency="true" />
5 <package id="Microsoft.SourceLink.GitHub" version="1.0.0" targetFramework="native" developmentDependency="true" />
6 <package id="Nerdbank.GitVersioning" version="3.3.37" targetFramework="native" developmentDependency="true" />
7 <package id="runtime.win-arm64.Microsoft.NETCore.DotNetAppHost" version="5.0.0" targetFramework="native" />
8 <package id="runtime.win-x64.Microsoft.NETCore.DotNetAppHost" version="5.0.0" targetFramework="native" />
9 <package id="runtime.win-x86.Microsoft.NETCore.DotNetAppHost" version="5.0.0" targetFramework="native" />
10 <package id="WixToolset.BalUtil" version="4.0.58" targetFramework="native" />
11 <package id="WixToolset.BootstrapperCore.Native" version="4.0.141" targetFramework="native" />
12 <package id="WixToolset.DUtil" version="4.0.72" targetFramework="native" />
13</packages> \ No newline at end of file
diff --git a/src/ext/Bal/dnchost/precomp.cpp b/src/ext/Bal/dnchost/precomp.cpp
new file mode 100644
index 00000000..37664a1c
--- /dev/null
+++ b/src/ext/Bal/dnchost/precomp.cpp
@@ -0,0 +1,3 @@
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"
diff --git a/src/ext/Bal/dnchost/precomp.h b/src/ext/Bal/dnchost/precomp.h
new file mode 100644
index 00000000..84ff6424
--- /dev/null
+++ b/src/ext/Bal/dnchost/precomp.h
@@ -0,0 +1,31 @@
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#include <windows.h>
5#include <msiquery.h>
6#include <corerror.h>
7#include <Shlwapi.h>
8
9#include <dutil.h>
10#include <memutil.h>
11#include <pathutil.h>
12#include <strutil.h>
13#include <xmlutil.h>
14
15#include <BootstrapperEngine.h>
16#include <BootstrapperApplication.h>
17
18#include <IBootstrapperEngine.h>
19#include <IBootstrapperApplication.h>
20#include <IBootstrapperApplicationFactory.h>
21#include <balutil.h>
22
23#include <WixToolset.Dnc.Host.h>
24#define NETHOST_USE_AS_STATIC
25#include <nethost.h>
26#include <hostfxr.h>
27#include <coreclr_delegates.h>
28
29#include "coreclrhost.h"
30#include "dncutil.h"
31#include "dnchost.h"