mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 10:17:22 +01:00
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:
parent
5b4833a6f7
commit
9a38a9470c
15 changed files with 57 additions and 94 deletions
|
|
@ -117,10 +117,6 @@
|
||||||
<ClInclude Include="pch.h" />
|
<ClInclude Include="pch.h" />
|
||||||
<ClInclude Include="veh.h" />
|
<ClInclude Include="veh.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Library Include="..\lib\CoreCLR\nethost\libnethost.lib" />
|
|
||||||
<Library Include="..\lib\CoreCLR\nethost\nethost.lib" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Target Name="RemoveExtraFiles" AfterTargets="PostBuildEvent">
|
<Target Name="RemoveExtraFiles" AfterTargets="PostBuildEvent">
|
||||||
<Delete Files="$(OutDir)$(TargetName).lib" />
|
<Delete Files="$(OutDir)$(TargetName).lib" />
|
||||||
<Delete Files="$(OutDir)$(TargetName).exp" />
|
<Delete Files="$(OutDir)$(TargetName).exp" />
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="Library Files">
|
|
||||||
<UniqueIdentifier>{18be40ac-9367-46ff-b848-4c528aa97a8d}</UniqueIdentifier>
|
|
||||||
<Extensions>lib</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="CoreCLR">
|
<Filter Include="CoreCLR">
|
||||||
<UniqueIdentifier>{dc468303-865e-43bd-908f-a3542c4bb669}</UniqueIdentifier>
|
<UniqueIdentifier>{dc468303-865e-43bd-908f-a3542c4bb669}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
|
@ -56,12 +52,4 @@
|
||||||
<Filter>Dalamud.Boot DLL</Filter>
|
<Filter>Dalamud.Boot DLL</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Library Include="..\lib\CoreCLR\nethost\nethost.lib">
|
|
||||||
<Filter>Library Files</Filter>
|
|
||||||
</Library>
|
|
||||||
<Library Include="..\lib\CoreCLR\nethost\libnethost.lib">
|
|
||||||
<Filter>Library Files</Filter>
|
|
||||||
</Library>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
@ -68,6 +68,7 @@ DllExport DWORD WINAPI Initialize(LPVOID lpParam)
|
||||||
|
|
||||||
void* entrypoint_vfn;
|
void* entrypoint_vfn;
|
||||||
int result = InitializeClrAndGetEntryPoint(
|
int result = InitializeClrAndGetEntryPoint(
|
||||||
|
g_hModule,
|
||||||
runtimeconfig_path,
|
runtimeconfig_path,
|
||||||
module_path,
|
module_path,
|
||||||
L"Dalamud.EntryPoint, Dalamud",
|
L"Dalamud.EntryPoint, Dalamud",
|
||||||
|
|
|
||||||
|
|
@ -99,10 +99,6 @@
|
||||||
<ClInclude Include="..\lib\CoreCLR\nethost\nethost.h" />
|
<ClInclude Include="..\lib\CoreCLR\nethost\nethost.h" />
|
||||||
<ClInclude Include="..\lib\CoreCLR\pch.h" />
|
<ClInclude Include="..\lib\CoreCLR\pch.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Library Include="..\lib\CoreCLR\nethost\libnethost.lib" />
|
|
||||||
<Library Include="..\lib\CoreCLR\nethost\nethost.lib" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Target Name="RemoveExtraFiles" AfterTargets="PostBuildEvent">
|
<Target Name="RemoveExtraFiles" AfterTargets="PostBuildEvent">
|
||||||
<Delete Files="$(OutDir)$(TargetName).lib" />
|
<Delete Files="$(OutDir)$(TargetName).lib" />
|
||||||
<Delete Files="$(OutDir)$(TargetName).exp" />
|
<Delete Files="$(OutDir)$(TargetName).exp" />
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,6 @@
|
||||||
<UniqueIdentifier>{4faac519-3a73-4b2b-96e7-fb597f02c0be}</UniqueIdentifier>
|
<UniqueIdentifier>{4faac519-3a73-4b2b-96e7-fb597f02c0be}</UniqueIdentifier>
|
||||||
<Extensions>ico;rc</Extensions>
|
<Extensions>ico;rc</Extensions>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter Include="Library Files">
|
|
||||||
<UniqueIdentifier>{6aff1bed-6979-4bc9-94e8-ddafb626e6bf}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Image Include="dalamud.ico">
|
<Image Include="dalamud.ico">
|
||||||
|
|
@ -55,12 +52,4 @@
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Library Include="..\lib\CoreCLR\nethost\nethost.lib">
|
|
||||||
<Filter>Library Files</Filter>
|
|
||||||
</Library>
|
|
||||||
<Library Include="..\lib\CoreCLR\nethost\libnethost.lib">
|
|
||||||
<Filter>Library Files</Filter>
|
|
||||||
</Library>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
@ -21,6 +21,7 @@ int wmain(int argc, wchar_t** argv)
|
||||||
|
|
||||||
void* entrypoint_vfn;
|
void* entrypoint_vfn;
|
||||||
int result = InitializeClrAndGetEntryPoint(
|
int result = InitializeClrAndGetEntryPoint(
|
||||||
|
GetModuleHandleW(nullptr),
|
||||||
runtimeconfig_path,
|
runtimeconfig_path,
|
||||||
module_path,
|
module_path,
|
||||||
L"Dalamud.Injector.EntryPoint, Dalamud.Injector",
|
L"Dalamud.Injector.EntryPoint, Dalamud.Injector",
|
||||||
|
|
|
||||||
|
|
@ -634,17 +634,13 @@ namespace Dalamud.Injector
|
||||||
|
|
||||||
private static void Inject(Process process, DalamudStartInfo startInfo)
|
private static void Inject(Process process, DalamudStartInfo startInfo)
|
||||||
{
|
{
|
||||||
var nethostName = "nethost.dll";
|
|
||||||
var bootName = "Dalamud.Boot.dll";
|
var bootName = "Dalamud.Boot.dll";
|
||||||
|
|
||||||
var nethostPath = Path.GetFullPath(nethostName);
|
|
||||||
var bootPath = Path.GetFullPath(bootName);
|
var bootPath = Path.GetFullPath(bootName);
|
||||||
|
|
||||||
// ======================================================
|
// ======================================================
|
||||||
|
|
||||||
using var injector = new Injector(process);
|
using var injector = new Injector(process, false);
|
||||||
|
|
||||||
injector.LoadLibrary(nethostPath, out _);
|
|
||||||
injector.LoadLibrary(bootPath, out var bootModule);
|
injector.LoadLibrary(bootPath, out var bootModule);
|
||||||
|
|
||||||
// ======================================================
|
// ======================================================
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ namespace Dalamud.Injector
|
||||||
internal sealed class Injector : IDisposable
|
internal sealed class Injector : IDisposable
|
||||||
{
|
{
|
||||||
private readonly Process targetProcess;
|
private readonly Process targetProcess;
|
||||||
|
private readonly bool disposeTargetProcess;
|
||||||
private readonly ExternalMemory extMemory;
|
private readonly ExternalMemory extMemory;
|
||||||
private readonly CircularBuffer circularBuffer;
|
private readonly CircularBuffer circularBuffer;
|
||||||
private readonly PrivateMemoryBuffer memoryBuffer;
|
private readonly PrivateMemoryBuffer memoryBuffer;
|
||||||
|
|
@ -41,9 +42,11 @@ namespace Dalamud.Injector
|
||||||
/// Initializes a new instance of the <see cref="Injector"/> class.
|
/// Initializes a new instance of the <see cref="Injector"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="targetProcess">Process to inject.</param>
|
/// <param name="targetProcess">Process to inject.</param>
|
||||||
public Injector(Process targetProcess)
|
/// <param name="disposeTargetProcess">Dispose given process on disposing self.</param>
|
||||||
|
public Injector(Process targetProcess, bool disposeTargetProcess = true)
|
||||||
{
|
{
|
||||||
this.targetProcess = targetProcess;
|
this.targetProcess = targetProcess;
|
||||||
|
this.disposeTargetProcess = disposeTargetProcess;
|
||||||
|
|
||||||
this.extMemory = new ExternalMemory(targetProcess);
|
this.extMemory = new ExternalMemory(targetProcess);
|
||||||
this.circularBuffer = new CircularBuffer(4096, this.extMemory);
|
this.circularBuffer = new CircularBuffer(4096, this.extMemory);
|
||||||
|
|
@ -67,6 +70,7 @@ namespace Dalamud.Injector
|
||||||
{
|
{
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
|
|
||||||
|
if (this.disposeTargetProcess)
|
||||||
this.targetProcess?.Dispose();
|
this.targetProcess?.Dispose();
|
||||||
this.circularBuffer?.Dispose();
|
this.circularBuffer?.Dispose();
|
||||||
this.memoryBuffer?.Dispose();
|
this.memoryBuffer?.Dispose();
|
||||||
|
|
@ -85,14 +89,9 @@ namespace Dalamud.Injector
|
||||||
throw new Exception("Unable to allocate LoadLibraryW parameter");
|
throw new Exception("Unable to allocate LoadLibraryW parameter");
|
||||||
|
|
||||||
this.CallRemoteFunction(this.loadLibraryShellPtr, lpParameter, out var err);
|
this.CallRemoteFunction(this.loadLibraryShellPtr, lpParameter, out var err);
|
||||||
|
|
||||||
if (err != 0)
|
|
||||||
throw new Exception($"LoadLibraryW(\"{modulePath}\") failure: {new Win32Exception((int)err).Message} ({err})");
|
|
||||||
|
|
||||||
address = this.extMemory.Read<IntPtr>(this.loadLibraryRetPtr);
|
address = this.extMemory.Read<IntPtr>(this.loadLibraryRetPtr);
|
||||||
|
|
||||||
if (address == IntPtr.Zero)
|
if (address == IntPtr.Zero)
|
||||||
throw new Exception($"LoadLibraryW(\"{modulePath}\") failure: Error code unavailable");
|
throw new Exception($"LoadLibraryW(\"{modulePath}\") failure: {new Win32Exception((int)err).Message} ({err})");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -110,12 +109,9 @@ namespace Dalamud.Injector
|
||||||
throw new Exception("Unable to allocate GetProcAddress parameter ptr");
|
throw new Exception("Unable to allocate GetProcAddress parameter ptr");
|
||||||
|
|
||||||
this.CallRemoteFunction(this.getProcAddressShellPtr, lpParameter, out var err);
|
this.CallRemoteFunction(this.getProcAddressShellPtr, lpParameter, out var err);
|
||||||
if (err != 0)
|
address = this.extMemory.Read<IntPtr>(this.getProcAddressRetPtr);
|
||||||
throw new Exception($"GetProcAddress(0x{module:X}, \"{functionName}\") failure: {new Win32Exception((int)err).Message} ({err})");
|
|
||||||
|
|
||||||
this.extMemory.Read(this.getProcAddressRetPtr, out address);
|
|
||||||
if (address == IntPtr.Zero)
|
if (address == IntPtr.Zero)
|
||||||
throw new Exception($"GetProcAddress(0x{module:X}, \"{functionName}\") failure: Error code unavailable");
|
throw new Exception($"GetProcAddress(0x{module:X}, \"{functionName}\") failure: {new Win32Exception((int)err).Message} ({err})");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,14 @@
|
||||||
|
|
||||||
#include "CoreCLR.h"
|
#include "CoreCLR.h"
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
#include <filesystem>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "nethost/nethost.h"
|
#include "nethost/nethost.h"
|
||||||
|
|
||||||
#pragma comment(lib, "nethost/libnethost.lib")
|
CoreCLR::CoreCLR(void* calling_module)
|
||||||
|
: m_calling_module(calling_module)
|
||||||
CoreCLR::CoreCLR() {}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/* Core public functions */
|
/* Core public functions */
|
||||||
int CoreCLR::load_hostfxr()
|
int CoreCLR::load_hostfxr()
|
||||||
|
|
@ -18,19 +20,43 @@ int CoreCLR::load_hostfxr()
|
||||||
int CoreCLR::load_hostfxr(const struct get_hostfxr_parameters* parameters)
|
int CoreCLR::load_hostfxr(const struct get_hostfxr_parameters* parameters)
|
||||||
{
|
{
|
||||||
// Get the path to CoreCLR's hostfxr
|
// 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]{};
|
wchar_t buffer[MAX_PATH]{};
|
||||||
size_t buffer_size = sizeof buffer / sizeof(wchar_t);
|
size_t buffer_size = sizeof buffer / sizeof(wchar_t);
|
||||||
if (int rc = get_hostfxr_path(buffer, &buffer_size, parameters); rc != 0)
|
if (int rc = get_hostfxr_path(buffer, &buffer_size, parameters); rc != 0)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
// Load hostfxr and get desired exports
|
// 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>(
|
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>(
|
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>(
|
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
|
return m_hostfxr_initialize_for_runtime_config_fptr
|
||||||
&& m_hostfxr_get_runtime_delegate_fptr
|
&& m_hostfxr_get_runtime_delegate_fptr
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,10 @@
|
||||||
#include "nethost/nethost.h"
|
#include "nethost/nethost.h"
|
||||||
|
|
||||||
class CoreCLR {
|
class CoreCLR {
|
||||||
public:
|
void* const m_calling_module;
|
||||||
explicit CoreCLR();
|
|
||||||
|
public:
|
||||||
|
explicit CoreCLR(void* calling_module);
|
||||||
~CoreCLR() = default;
|
~CoreCLR() = default;
|
||||||
|
|
||||||
int load_hostfxr();
|
int load_hostfxr();
|
||||||
|
|
@ -32,7 +34,7 @@ class CoreCLR {
|
||||||
void* reserved,
|
void* reserved,
|
||||||
void** delegate) const;
|
void** delegate) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/* HostFXR delegates. */
|
/* HostFXR delegates. */
|
||||||
hostfxr_initialize_for_runtime_config_fn m_hostfxr_initialize_for_runtime_config_fptr{};
|
hostfxr_initialize_for_runtime_config_fn m_hostfxr_initialize_for_runtime_config_fptr{};
|
||||||
hostfxr_get_runtime_delegate_fn m_hostfxr_get_runtime_delegate_fptr{};
|
hostfxr_get_runtime_delegate_fn m_hostfxr_get_runtime_delegate_fptr{};
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ void ConsoleTeardown()
|
||||||
std::optional<CoreCLR> g_clr;
|
std::optional<CoreCLR> g_clr;
|
||||||
|
|
||||||
int InitializeClrAndGetEntryPoint(
|
int InitializeClrAndGetEntryPoint(
|
||||||
|
void* calling_module,
|
||||||
std::wstring runtimeconfig_path,
|
std::wstring runtimeconfig_path,
|
||||||
std::wstring module_path,
|
std::wstring module_path,
|
||||||
std::wstring entrypoint_assembly_name,
|
std::wstring entrypoint_assembly_name,
|
||||||
|
|
@ -33,7 +34,7 @@ int InitializeClrAndGetEntryPoint(
|
||||||
std::wstring entrypoint_delegate_type_name,
|
std::wstring entrypoint_delegate_type_name,
|
||||||
void** entrypoint_fn)
|
void** entrypoint_fn)
|
||||||
{
|
{
|
||||||
g_clr = CoreCLR();
|
g_clr.emplace(calling_module);
|
||||||
|
|
||||||
int result;
|
int result;
|
||||||
SetEnvironmentVariable(L"DOTNET_MULTILEVEL_LOOKUP", L"0");
|
SetEnvironmentVariable(L"DOTNET_MULTILEVEL_LOOKUP", L"0");
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ void ConsoleSetup(const std::wstring console_name);
|
||||||
void ConsoleTeardown();
|
void ConsoleTeardown();
|
||||||
|
|
||||||
int InitializeClrAndGetEntryPoint(
|
int InitializeClrAndGetEntryPoint(
|
||||||
|
void* calling_module,
|
||||||
std::wstring runtimeconfig_path,
|
std::wstring runtimeconfig_path,
|
||||||
std::wstring module_path,
|
std::wstring module_path,
|
||||||
std::wstring entrypoint_assembly_name,
|
std::wstring entrypoint_assembly_name,
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -6,36 +6,6 @@
|
||||||
|
|
||||||
#include <stddef.h>
|
#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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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
|
// 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).
|
// to call this function multiple times, pass a large buffer (e.g. PATH_MAX).
|
||||||
//
|
//
|
||||||
NETHOST_API int NETHOST_CALLTYPE get_hostfxr_path(
|
using get_hostfxr_path_type = int(__stdcall *)(
|
||||||
char_t * buffer,
|
char_t* buffer,
|
||||||
size_t * buffer_size,
|
size_t* buffer_size,
|
||||||
const struct get_hostfxr_parameters *parameters);
|
const struct get_hostfxr_parameters* parameters);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue