Fix inject problems (#820)

* CoreCLR: resolve and load nethost on demand instead of requiring it on load

* Remove nethost loading from C# side

* Added option to not chain Process.Dispose; see for last error only if result is empty
This commit is contained in:
kizer 2022-04-25 17:13:32 +09:00 committed by GitHub
parent 5b4833a6f7
commit 9a38a9470c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 57 additions and 94 deletions

View file

@ -2,12 +2,14 @@
#include "CoreCLR.h"
#include <Windows.h>
#include <filesystem>
#include <iostream>
#include "nethost/nethost.h"
#pragma comment(lib, "nethost/libnethost.lib")
CoreCLR::CoreCLR() {}
CoreCLR::CoreCLR(void* calling_module)
: m_calling_module(calling_module)
{
}
/* Core public functions */
int CoreCLR::load_hostfxr()
@ -18,19 +20,43 @@ int CoreCLR::load_hostfxr()
int CoreCLR::load_hostfxr(const struct get_hostfxr_parameters* parameters)
{
// Get the path to CoreCLR's hostfxr
std::wstring calling_module_path(MAX_PATH, L'\0');
do
{
calling_module_path.resize(GetModuleFileNameW(static_cast<HMODULE>(m_calling_module), &calling_module_path[0], static_cast<DWORD>(calling_module_path.size())));
}
while (!calling_module_path.empty() && GetLastError() == ERROR_INSUFFICIENT_BUFFER);
if (calling_module_path.empty())
return -1;
calling_module_path = (std::filesystem::path(calling_module_path).parent_path() / L"nethost.dll").wstring();
auto lib_nethost = reinterpret_cast<void*>(load_library(calling_module_path.c_str()));
if (!lib_nethost)
return -1;
auto get_hostfxr_path = reinterpret_cast<get_hostfxr_path_type>(
get_export(lib_nethost, "get_hostfxr_path"));
if (!get_hostfxr_path)
return -1;
wchar_t buffer[MAX_PATH]{};
size_t buffer_size = sizeof buffer / sizeof(wchar_t);
if (int rc = get_hostfxr_path(buffer, &buffer_size, parameters); rc != 0)
return rc;
// Load hostfxr and get desired exports
auto lib = reinterpret_cast<void*>(load_library(buffer));
auto lib_hostfxr = reinterpret_cast<void*>(load_library(buffer));
if (!lib_hostfxr)
return -1;
m_hostfxr_initialize_for_runtime_config_fptr = reinterpret_cast<hostfxr_initialize_for_runtime_config_fn>(
get_export(lib, "hostfxr_initialize_for_runtime_config"));
get_export(lib_hostfxr, "hostfxr_initialize_for_runtime_config"));
m_hostfxr_get_runtime_delegate_fptr = reinterpret_cast<hostfxr_get_runtime_delegate_fn>(
get_export(lib, "hostfxr_get_runtime_delegate"));
get_export(lib_hostfxr, "hostfxr_get_runtime_delegate"));
m_hostfxr_close_fptr = reinterpret_cast<hostfxr_close_fn>(
get_export(lib, "hostfxr_close"));
get_export(lib_hostfxr, "hostfxr_close"));
return m_hostfxr_initialize_for_runtime_config_fptr
&& m_hostfxr_get_runtime_delegate_fptr

View file

@ -5,8 +5,10 @@
#include "nethost/nethost.h"
class CoreCLR {
public:
explicit CoreCLR();
void* const m_calling_module;
public:
explicit CoreCLR(void* calling_module);
~CoreCLR() = default;
int load_hostfxr();
@ -32,7 +34,7 @@ class CoreCLR {
void* reserved,
void** delegate) const;
private:
private:
/* HostFXR delegates. */
hostfxr_initialize_for_runtime_config_fn m_hostfxr_initialize_for_runtime_config_fptr{};
hostfxr_get_runtime_delegate_fn m_hostfxr_get_runtime_delegate_fptr{};

View file

@ -26,6 +26,7 @@ void ConsoleTeardown()
std::optional<CoreCLR> g_clr;
int InitializeClrAndGetEntryPoint(
void* calling_module,
std::wstring runtimeconfig_path,
std::wstring module_path,
std::wstring entrypoint_assembly_name,
@ -33,7 +34,7 @@ int InitializeClrAndGetEntryPoint(
std::wstring entrypoint_delegate_type_name,
void** entrypoint_fn)
{
g_clr = CoreCLR();
g_clr.emplace(calling_module);
int result;
SetEnvironmentVariable(L"DOTNET_MULTILEVEL_LOOKUP", L"0");

View file

@ -2,6 +2,7 @@ void ConsoleSetup(const std::wstring console_name);
void ConsoleTeardown();
int InitializeClrAndGetEntryPoint(
void* calling_module,
std::wstring runtimeconfig_path,
std::wstring module_path,
std::wstring entrypoint_assembly_name,

Binary file not shown.

View file

@ -6,36 +6,6 @@
#include <stddef.h>
#ifdef _WIN32
#ifdef NETHOST_EXPORT
#define NETHOST_API __declspec(dllexport)
#else
// Consuming the nethost as a static library
// Shouldn't export attempt to dllimport.
#ifdef NETHOST_USE_AS_STATIC
#define NETHOST_API
#else
#define NETHOST_API __declspec(dllimport)
#endif
#endif
#define NETHOST_CALLTYPE __stdcall
#ifdef _WCHAR_T_DEFINED
typedef wchar_t char_t;
#else
typedef unsigned short char_t;
#endif
#else
#ifdef NETHOST_EXPORT
#define NETHOST_API __attribute__((__visibility__("default")))
#else
#define NETHOST_API
#endif
#define NETHOST_CALLTYPE
typedef char char_t;
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -87,10 +57,10 @@ struct get_hostfxr_parameters {
// The full search for the hostfxr library is done on every call. To minimize the need
// to call this function multiple times, pass a large buffer (e.g. PATH_MAX).
//
NETHOST_API int NETHOST_CALLTYPE get_hostfxr_path(
char_t * buffer,
size_t * buffer_size,
const struct get_hostfxr_parameters *parameters);
using get_hostfxr_path_type = int(__stdcall *)(
char_t* buffer,
size_t* buffer_size,
const struct get_hostfxr_parameters* parameters);
#ifdef __cplusplus
} // extern "C"

Binary file not shown.