Split libhost.h into multiple headers and cleanup (dotnet/core-setup#5391)
authorVitek Karas <vitek.karas@microsoft.com>
Fri, 8 Mar 2019 21:49:23 +0000 (13:49 -0800)
committerGitHub <noreply@github.com>
Fri, 8 Mar 2019 21:49:23 +0000 (13:49 -0800)
Commit migrated from https://github.com/dotnet/core-setup/commit/3586f526ae50b9c1f7e31019a317a7358f1f2170

16 files changed:
src/installer/corehost/cli/args.cpp
src/installer/corehost/cli/args.h
src/installer/corehost/cli/deps_resolver.cpp
src/installer/corehost/cli/fxr/CMakeLists.txt
src/installer/corehost/cli/fxr/corehost_init.h [new file with mode: 0644]
src/installer/corehost/cli/fxr/framework_info.h
src/installer/corehost/cli/fxr/fx_muxer.cpp
src/installer/corehost/cli/fxr/fx_muxer.h
src/installer/corehost/cli/fxr/hostfxr.cpp
src/installer/corehost/cli/fxr/sdk_info.h
src/installer/corehost/cli/host_interface.h [new file with mode: 0644]
src/installer/corehost/cli/hostpolicy.cpp
src/installer/corehost/cli/hostpolicy/CMakeLists.txt
src/installer/corehost/cli/hostpolicy_init.h [new file with mode: 0644]
src/installer/corehost/cli/libhost.cpp [deleted file]
src/installer/corehost/cli/libhost.h [deleted file]

index 01042ba..ac17e74 100644 (file)
@@ -4,7 +4,6 @@
 #include "args.h"
 #include "utils.h"
 #include "coreclr.h"
-#include "libhost.h"
 
 arguments_t::arguments_t()
     : managed_application(_X(""))
index fd56f65..44a5479 100644 (file)
@@ -8,7 +8,7 @@
 #include "pal.h"
 #include "trace.h"
 #include "deps_format.h"
-#include "libhost.h"
+#include "hostpolicy_init.h"
 
 struct probe_config_t
 {
index 8651cb0..d8abbde 100644 (file)
@@ -11,7 +11,6 @@
 #include "deps_resolver.h"
 #include "utils.h"
 #include "fx_ver.h"
-#include "libhost.h"
 
 const pal::string_t MissingAssemblyMessage = _X(
     "%s:\n"
index 4b45037..b3909ea 100644 (file)
@@ -13,7 +13,6 @@ include_directories(../json/casablanca/include)
 set(SOURCES
     ../../common/trace.cpp
     ../../common/utils.cpp
-    ../libhost.cpp
     ../deps_format.cpp
     ../deps_entry.cpp
     ../host_startup_info.cpp
diff --git a/src/installer/corehost/cli/fxr/corehost_init.h b/src/installer/corehost/cli/fxr/corehost_init.h
new file mode 100644 (file)
index 0000000..5aeb3bd
--- /dev/null
@@ -0,0 +1,173 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef __COREHOST_INIT_H__
+#define __COREHOST_INIT_H__
+
+#include "pal.h"
+#include "host_interface.h"
+#include "fx_definition.h"
+
+class corehost_init_t
+{
+private:
+    std::vector<pal::string_t> m_clr_keys;
+    std::vector<pal::string_t> m_clr_values;
+    std::vector<const pal::char_t*> m_clr_keys_cstr;
+    std::vector<const pal::char_t*> m_clr_values_cstr;
+    const pal::string_t m_tfm;
+    const pal::string_t m_deps_file;
+    const pal::string_t m_additional_deps_serialized;
+    bool m_is_framework_dependent;
+    std::vector<pal::string_t> m_probe_paths;
+    std::vector<const pal::char_t*> m_probe_paths_cstr;
+    host_mode_t m_host_mode;
+    host_interface_t m_host_interface;
+    std::vector<pal::string_t> m_fx_names;
+    std::vector<const pal::char_t*> m_fx_names_cstr;
+    std::vector<pal::string_t> m_fx_dirs;
+    std::vector<const pal::char_t*> m_fx_dirs_cstr;
+    std::vector<pal::string_t> m_fx_requested_versions;
+    std::vector<const pal::char_t*> m_fx_requested_versions_cstr;
+    std::vector<pal::string_t> m_fx_found_versions;
+    std::vector<const pal::char_t*> m_fx_found_versions_cstr;
+    const pal::string_t m_host_command;
+    const pal::string_t m_host_info_host_path;
+    const pal::string_t m_host_info_dotnet_root;
+    const pal::string_t m_host_info_app_path;
+public:
+    corehost_init_t(
+        const pal::string_t& host_command,
+        const host_startup_info_t& host_info,
+        const pal::string_t& deps_file,
+        const pal::string_t& additional_deps_serialized,
+        const std::vector<pal::string_t>& probe_paths,
+        const host_mode_t mode,
+        const fx_definition_vector_t& fx_definitions)
+        : m_host_command(host_command)
+        , m_host_info_host_path(host_info.host_path)
+        , m_host_info_dotnet_root(host_info.dotnet_root)
+        , m_host_info_app_path(host_info.app_path)
+        , m_deps_file(deps_file)
+        , m_additional_deps_serialized(additional_deps_serialized)
+        , m_is_framework_dependent(get_app(fx_definitions).get_runtime_config().get_is_framework_dependent())
+        , m_probe_paths(probe_paths)
+        , m_host_mode(mode)
+        , m_host_interface()
+        , m_tfm(get_app(fx_definitions).get_runtime_config().get_tfm())
+    {
+        make_cstr_arr(m_probe_paths, &m_probe_paths_cstr);
+
+        int fx_count = fx_definitions.size();
+        m_fx_names.reserve(fx_count);
+        m_fx_dirs.reserve(fx_count);
+        m_fx_requested_versions.reserve(fx_count);
+        m_fx_found_versions.reserve(fx_count);
+
+        std::unordered_map<pal::string_t, pal::string_t> combined_properties;
+        for (auto& fx : fx_definitions)
+        {
+            fx->get_runtime_config().combine_properties(combined_properties);
+
+            m_fx_names.push_back(fx->get_name());
+            m_fx_dirs.push_back(fx->get_dir());
+            m_fx_requested_versions.push_back(fx->get_requested_version());
+            m_fx_found_versions.push_back(fx->get_found_version());
+        }
+
+        for (const auto& kv : combined_properties)
+        {
+            m_clr_keys.push_back(kv.first);
+            m_clr_values.push_back(kv.second);
+        }
+
+        make_cstr_arr(m_fx_names, &m_fx_names_cstr);
+        make_cstr_arr(m_fx_dirs, &m_fx_dirs_cstr);
+        make_cstr_arr(m_fx_requested_versions, &m_fx_requested_versions_cstr);
+        make_cstr_arr(m_fx_found_versions, &m_fx_found_versions_cstr);
+        make_cstr_arr(m_clr_keys, &m_clr_keys_cstr);
+        make_cstr_arr(m_clr_values, &m_clr_values_cstr);
+    }
+
+    const pal::string_t& tfm() const
+    {
+        return m_tfm;
+    }
+
+    const host_interface_t& get_host_init_data()
+    {
+        host_interface_t& hi = m_host_interface;
+
+        hi.version_lo = HOST_INTERFACE_LAYOUT_VERSION_LO;
+        hi.version_hi = HOST_INTERFACE_LAYOUT_VERSION_HI;
+
+        hi.config_keys.len = m_clr_keys_cstr.size();
+        hi.config_keys.arr = m_clr_keys_cstr.data();
+
+        hi.config_values.len = m_clr_values_cstr.size();
+        hi.config_values.arr = m_clr_values_cstr.data();
+
+        // Keep these for backwards compat
+        if (m_fx_names_cstr.size() > 1)
+        {
+            hi.fx_name = m_fx_names_cstr[1];
+            hi.fx_dir = m_fx_dirs_cstr[1];
+            hi.fx_ver = m_fx_requested_versions_cstr[1];
+        }
+        else
+        {
+            hi.fx_name = _X("");
+            hi.fx_dir = _X("");
+            hi.fx_ver = _X("");
+        }
+
+        hi.deps_file = m_deps_file.c_str();
+        hi.additional_deps_serialized = m_additional_deps_serialized.c_str();
+        hi.is_framework_dependent = m_is_framework_dependent;
+
+        hi.probe_paths.len = m_probe_paths_cstr.size();
+        hi.probe_paths.arr = m_probe_paths_cstr.data();
+
+        // These are not used anymore, but we have to keep them for backward compat reasons.
+        // Set default values.
+        hi.patch_roll_forward = true;
+        hi.prerelease_roll_forward = false;
+
+        hi.host_mode = m_host_mode;
+
+        hi.tfm = m_tfm.c_str();
+
+        hi.fx_names.len = m_fx_names_cstr.size();
+        hi.fx_names.arr = m_fx_names_cstr.data();
+
+        hi.fx_dirs.len = m_fx_dirs_cstr.size();
+        hi.fx_dirs.arr = m_fx_dirs_cstr.data();
+
+        hi.fx_requested_versions.len = m_fx_requested_versions_cstr.size();
+        hi.fx_requested_versions.arr = m_fx_requested_versions_cstr.data();
+
+        hi.fx_found_versions.len = m_fx_found_versions_cstr.size();
+        hi.fx_found_versions.arr = m_fx_found_versions_cstr.data();
+
+        hi.host_command = m_host_command.c_str();
+
+        hi.host_info_host_path = m_host_info_host_path.c_str();
+        hi.host_info_dotnet_root = m_host_info_dotnet_root.c_str();
+        hi.host_info_app_path = m_host_info_app_path.c_str();
+
+        return hi;
+    }
+
+private:
+
+    static void make_cstr_arr(const std::vector<pal::string_t>& arr, std::vector<const pal::char_t*>* out)
+    {
+        out->reserve(arr.size());
+        for (const auto& str : arr)
+        {
+            out->push_back(str.c_str());
+        }
+    }
+};
+
+#endif // __COREHOST_INIT_H__
\ No newline at end of file
index d502f95..4953882 100644 (file)
@@ -4,7 +4,8 @@
 #ifndef __FRAMEWORK_INFO_H_
 #define __FRAMEWORK_INFO_H_
 
-#include "libhost.h"
+#include "pal.h"
+#include "fx_ver.h"
 
 struct framework_info
 {
index 8438147..863f489 100644 (file)
@@ -5,6 +5,7 @@
 #include <mutex>
 #include "args.h"
 #include "cpprest/json.h"
+#include "corehost_init.h"
 #include "deps_format.h"
 #include "error_codes.h"
 #include "framework_info.h"
@@ -13,7 +14,6 @@
 #include "fx_reference.h"
 #include "fx_ver.h"
 #include "host_startup_info.h"
-#include "libhost.h"
 #include "pal.h"
 #include "runtime_config.h"
 #include "sdk_info.h"
@@ -402,6 +402,48 @@ bool resolve_hostpolicy_dir_from_probe_paths(const pal::string_t& version, const
     return false;
 }
 
+void get_runtime_config_paths_from_arg(const pal::string_t& arg, pal::string_t* cfg, pal::string_t* dev_cfg)
+{
+    auto name = get_filename_without_ext(arg);
+
+    auto json_name = name + _X(".json");
+    auto dev_json_name = name + _X(".dev.json");
+
+    auto json_path = get_directory(arg);
+    auto dev_json_path = json_path;
+
+    append_path(&json_path, json_name.c_str());
+    append_path(&dev_json_path, dev_json_name.c_str());
+
+    trace::verbose(_X("Runtime config is cfg=%s dev=%s"), json_path.c_str(), dev_json_path.c_str());
+
+    dev_cfg->assign(dev_json_path);
+    cfg->assign(json_path);
+}
+
+void get_runtime_config_paths(const pal::string_t& path, const pal::string_t& name, pal::string_t* cfg, pal::string_t* dev_cfg)
+{
+    auto json_path = path;
+    auto json_name = name + _X(".runtimeconfig.json");
+    append_path(&json_path, json_name.c_str());
+    cfg->assign(json_path);
+
+    auto dev_json_path = path;
+    auto dev_json_name = name + _X(".runtimeconfig.dev.json");
+    append_path(&dev_json_path, dev_json_name.c_str());
+    dev_cfg->assign(dev_json_path);
+
+    trace::verbose(_X("Runtime config is cfg=%s dev=%s"), json_path.c_str(), dev_json_path.c_str());
+}
+
+void get_runtime_config_paths_from_app(const pal::string_t& app, pal::string_t* cfg, pal::string_t* dev_cfg)
+{
+    auto name = get_filename_without_ext(app);
+    auto path = get_directory(app);
+
+    get_runtime_config_paths(path, name, cfg, dev_cfg);
+}
+
 /**
 * Return name of deps file for app.
 */
@@ -1010,6 +1052,35 @@ int read_config(
     return StatusCode::Success;
 }
 
+host_mode_t detect_operating_mode(const host_startup_info_t& host_info)
+{
+    if (coreclr_exists_in_dir(host_info.dotnet_root))
+    {
+        // Detect between standalone apphost or legacy split mode (specifying --depsfile and --runtimeconfig)
+
+        pal::string_t deps_in_dotnet_root = host_info.dotnet_root;
+        pal::string_t deps_filename = host_info.get_app_name() + _X(".deps.json");
+        append_path(&deps_in_dotnet_root, deps_filename.c_str());
+        bool deps_exists = pal::file_exists(deps_in_dotnet_root);
+
+        trace::info(_X("Detecting mode... CoreCLR present in dotnet root [%s] and checking if [%s] file present=[%d]"),
+            host_info.dotnet_root.c_str(), deps_filename.c_str(), deps_exists);
+
+        // Name of runtimeconfig file; since no path is included here the check is in the current working directory
+        pal::string_t config_in_cwd = host_info.get_app_name() + _X(".runtimeconfig.json");
+
+        return (deps_exists || !pal::file_exists(config_in_cwd)) && pal::file_exists(host_info.app_path) ? host_mode_t::apphost : host_mode_t::split_fx;
+    }
+
+    if (pal::file_exists(host_info.app_path))
+    {
+        // Framework-dependent apphost
+        return host_mode_t::apphost;
+    }
+
+    return host_mode_t::muxer;
+}
+
 int fx_muxer_t::soft_roll_forward_helper(
     const fx_reference_t& newer,
     const fx_reference_t& older,
index cdf00bd..4ed98c0 100644 (file)
@@ -8,7 +8,9 @@ struct fx_ver_t;
 struct host_startup_info_t;
 
 #include <corehost.h>
-#include "libhost.h"
+#include "fx_definition.h"
+#include "host_interface.h"
+#include "host_startup_info.h"
 
 const int Max_Framework_Resolve_Retries = 100;
 
index 09638f1..a430f5f 100644 (file)
@@ -8,7 +8,6 @@
 #include "fx_ver.h"
 #include "fx_muxer.h"
 #include "error_codes.h"
-#include "libhost.h"
 #include "corehost.h"
 #include "runtime_config.h"
 #include "sdk_info.h"
index 1c296fc..399b94e 100644 (file)
@@ -4,7 +4,8 @@
 #ifndef __SDK_INFO_H_
 #define __SDK_INFO_H_
 
-#include "libhost.h"
+#include "pal.h"
+#include "fx_ver.h"
 
 struct sdk_info
 {
diff --git a/src/installer/corehost/cli/host_interface.h b/src/installer/corehost/cli/host_interface.h
new file mode 100644 (file)
index 0000000..d0bd2f0
--- /dev/null
@@ -0,0 +1,97 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef __HOST_INTERFACE_H__
+#define __HOST_INTERFACE_H__
+
+#include "pal.h"
+
+enum host_mode_t
+{
+    invalid = 0,
+
+    muxer,          // Invoked as "dotnet.exe".
+
+    apphost,        // Invoked as <appname>.exe from the application base; this is the renamed "apphost.exe".
+
+    split_fx,       // Invoked as "corehost.exe" for xunit scenarios. Supported for backwards compat for 1.x apps.
+                    // Split FX means, the host is operating like "corerun.exe" in a split location from the application base (CORE_ROOT equivalent),
+                    // but it has its "hostfxr.dll" next to it.
+
+    libhost,        // Invoked from a non-exe scenario (e.g. COM Activation or self-hosting native application)
+};
+
+#define _HOST_INTERFACE_PACK 1
+#pragma pack(push, _HOST_INTERFACE_PACK)
+struct strarr_t
+{
+    // DO NOT modify this struct. It is used in a layout
+    // dependent manner. Create another for your use.
+    size_t len;
+    const pal::char_t** arr;
+};
+
+struct host_interface_t
+{
+    size_t version_lo;                // Just assign sizeof() to this field.
+    size_t version_hi;                // Breaking changes to the layout -- increment HOST_INTERFACE_LAYOUT_VERSION
+    strarr_t config_keys;
+    strarr_t config_values;
+    const pal::char_t* fx_dir;
+    const pal::char_t* fx_name;
+    const pal::char_t* deps_file;
+    size_t is_framework_dependent;
+    strarr_t probe_paths;
+    size_t patch_roll_forward;
+    size_t prerelease_roll_forward;
+    size_t host_mode;
+    const pal::char_t* tfm;
+    const pal::char_t* additional_deps_serialized;
+    const pal::char_t* fx_ver;
+    strarr_t fx_names;
+    strarr_t fx_dirs;
+    strarr_t fx_requested_versions;
+    strarr_t fx_found_versions;
+    const pal::char_t* host_command;
+    const pal::char_t* host_info_host_path;
+    const pal::char_t* host_info_dotnet_root;
+    const pal::char_t* host_info_app_path;
+    // !! WARNING / WARNING / WARNING / WARNING / WARNING / WARNING / WARNING / WARNING / WARNING
+    // !! 1. Only append to this structure to maintain compat.
+    // !! 2. Any nested structs should not use compiler specific padding (pack with _HOST_INTERFACE_PACK)
+    // !! 3. Do not take address of the fields of this struct or be prepared to deal with unaligned accesses.
+    // !! 4. Must be POD types; only use non-const size_t and pointer types; no access modifiers.
+    // !! 5. Do not reorder fields or change any existing field types.
+    // !! 6. Add static asserts for fields you add.
+};
+#pragma pack(pop)
+static_assert(_HOST_INTERFACE_PACK == 1, "Packing size should not be modified for back compat");
+static_assert(offsetof(host_interface_t, version_lo) == 0 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(offsetof(host_interface_t, version_hi) == 1 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(offsetof(host_interface_t, config_keys) == 2 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(offsetof(host_interface_t, config_values) == 4 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(offsetof(host_interface_t, fx_dir) == 6 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(offsetof(host_interface_t, fx_name) == 7 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(offsetof(host_interface_t, deps_file) == 8 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(offsetof(host_interface_t, is_framework_dependent) == 9 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(offsetof(host_interface_t, probe_paths) == 10 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(offsetof(host_interface_t, patch_roll_forward) == 12 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(offsetof(host_interface_t, prerelease_roll_forward) == 13 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(offsetof(host_interface_t, host_mode) == 14 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(offsetof(host_interface_t, tfm) == 15 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(offsetof(host_interface_t, additional_deps_serialized) == 16 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(offsetof(host_interface_t, fx_ver) == 17 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(offsetof(host_interface_t, fx_names) == 18 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(offsetof(host_interface_t, fx_dirs) == 20 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(offsetof(host_interface_t, fx_requested_versions) == 22 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(offsetof(host_interface_t, fx_found_versions) == 24 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(offsetof(host_interface_t, host_command) == 26 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(offsetof(host_interface_t, host_info_host_path) == 27 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(offsetof(host_interface_t, host_info_dotnet_root) == 28 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(offsetof(host_interface_t, host_info_app_path) == 29 * sizeof(size_t), "Struct offset breaks backwards compatibility");
+static_assert(sizeof(host_interface_t) == 30 * sizeof(size_t), "Did you add static asserts for the newly added fields?");
+
+#define HOST_INTERFACE_LAYOUT_VERSION_HI 0x16041101 // YYMMDD:nn always increases when layout breaks compat.
+#define HOST_INTERFACE_LAYOUT_VERSION_LO sizeof(host_interface_t)
+
+#endif // __HOST_INTERFACE_H__
index d1c0365..5f2b455 100644 (file)
@@ -11,7 +11,6 @@
 #include "coreclr.h"
 #include "corehost.h"
 #include "cpprest/json.h"
-#include "libhost.h"
 #include "error_codes.h"
 #include "breadcrumbs.h"
 #include "host_startup_info.h"
index 203b652..483c6c6 100644 (file)
@@ -14,7 +14,6 @@ include_directories(../json/casablanca/include)
 set(SOURCES
     ../../common/trace.cpp
     ../../common/utils.cpp
-    ../libhost.cpp
     ../runtime_config.cpp
     ../json/casablanca/src/json/json.cpp
     ../json/casablanca/src/json/json_parsing.cpp
diff --git a/src/installer/corehost/cli/hostpolicy_init.h b/src/installer/corehost/cli/hostpolicy_init.h
new file mode 100644 (file)
index 0000000..6ede732
--- /dev/null
@@ -0,0 +1,172 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+#ifndef __HOSTPOLICY_INIT_H__
+#define __HOSTPOLICY_INIT_H__
+#include "trace.h"
+#include "host_interface.h"
+#include "host_startup_info.h"
+#include "fx_definition.h"
+#include "fx_ver.h"
+
+struct hostpolicy_init_t
+{
+    std::vector<std::vector<char>> cfg_keys;
+    std::vector<std::vector<char>> cfg_values;
+    pal::string_t deps_file;
+    pal::string_t additional_deps_serialized;
+    std::vector<pal::string_t> probe_paths;
+    fx_definition_vector_t fx_definitions;
+    pal::string_t tfm;
+    host_mode_t host_mode;
+    bool patch_roll_forward;
+    bool prerelease_roll_forward;
+    bool is_framework_dependent;
+    pal::string_t host_command;
+    host_startup_info_t host_info;
+
+    static bool init(host_interface_t* input, hostpolicy_init_t* init)
+    {
+        // Check if there are any breaking changes.
+        if (input->version_hi != HOST_INTERFACE_LAYOUT_VERSION_HI)
+        {
+            trace::error(_X("The version of the data layout used to initialize %s is [0x%04x]; expected version [0x%04x]"), LIBHOSTPOLICY_NAME, input->version_hi, HOST_INTERFACE_LAYOUT_VERSION_HI);
+            return false;
+        }
+
+        trace::verbose(_X("Reading from host interface version: [0x%04x:%d] to initialize policy version: [0x%04x:%d]"), input->version_hi, input->version_lo, HOST_INTERFACE_LAYOUT_VERSION_HI, HOST_INTERFACE_LAYOUT_VERSION_LO);
+
+        //This check is to ensure is an old hostfxr can still load new hostpolicy.
+        //We should not read garbage due to potentially shorter struct size
+
+        pal::string_t fx_requested_ver;
+
+        if (input->version_lo >= offsetof(host_interface_t, host_mode) + sizeof(input->host_mode))
+        {
+            make_clrstr_arr(input->config_keys.len, input->config_keys.arr, &init->cfg_keys);
+            make_clrstr_arr(input->config_values.len, input->config_values.arr, &init->cfg_values);
+
+            init->deps_file = input->deps_file;
+            init->is_framework_dependent = input->is_framework_dependent;
+
+            make_palstr_arr(input->probe_paths.len, input->probe_paths.arr, &init->probe_paths);
+
+            init->patch_roll_forward = input->patch_roll_forward;
+            init->prerelease_roll_forward = input->prerelease_roll_forward;
+            init->host_mode = (host_mode_t)input->host_mode;
+        }
+        else
+        {
+            trace::error(_X("The size of the data layout used to initialize %s is %d; expected at least %d"), LIBHOSTPOLICY_NAME, input->version_lo, 
+                offsetof(host_interface_t, host_mode) + sizeof(input->host_mode));
+        }
+
+        //An old hostfxr may not provide these fields.
+        //The version_lo (sizeof) the old hostfxr saw at build time will be
+        //smaller and we should not attempt to read the fields in that case.
+        if (input->version_lo >= offsetof(host_interface_t, tfm) + sizeof(input->tfm))
+        {
+            init->tfm = input->tfm;
+        }
+        
+        if (input->version_lo >= offsetof(host_interface_t, fx_ver) + sizeof(input->fx_ver))
+        {
+            init->additional_deps_serialized = input->additional_deps_serialized;
+            fx_requested_ver = input->fx_ver;
+        }
+
+        int fx_count = 0;
+        if (input->version_lo >= offsetof(host_interface_t, fx_names) + sizeof(input->fx_names))
+        {
+            int fx_count = input->fx_names.len;
+            assert(fx_count > 0);
+            assert(fx_count == input->fx_dirs.len);
+            assert(fx_count == input->fx_requested_versions.len);
+            assert(fx_count == input->fx_found_versions.len);
+
+            std::vector<pal::string_t> fx_names;
+            std::vector<pal::string_t> fx_dirs;
+            std::vector<pal::string_t> fx_requested_versions;
+            std::vector<pal::string_t> fx_found_versions;
+
+            make_palstr_arr(input->fx_names.len, input->fx_names.arr, &fx_names);
+            make_palstr_arr(input->fx_dirs.len, input->fx_dirs.arr, &fx_dirs);
+            make_palstr_arr(input->fx_requested_versions.len, input->fx_requested_versions.arr, &fx_requested_versions);
+            make_palstr_arr(input->fx_found_versions.len, input->fx_found_versions.arr, &fx_found_versions);
+
+            init->fx_definitions.reserve(fx_count);
+            for (int i = 0; i < fx_count; ++i)
+            {
+                auto fx = new fx_definition_t(fx_names[i], fx_dirs[i], fx_requested_versions[i], fx_found_versions[i]);
+                init->fx_definitions.push_back(std::unique_ptr<fx_definition_t>(fx));
+            }
+        }
+        else
+        {
+            // Backward compat; create the fx_definitions[0] and [1] from the previous information
+            init->fx_definitions.reserve(2);
+
+            auto fx = new fx_definition_t();
+            init->fx_definitions.push_back(std::unique_ptr<fx_definition_t>(fx));
+
+            if (init->is_framework_dependent)
+            {
+                pal::string_t fx_dir = input->fx_dir;
+                pal::string_t fx_name = input->fx_name;
+
+                // The found_ver was not passed previously, so obtain that from fx_dir
+                pal::string_t fx_found_ver;
+                size_t index = fx_dir.rfind(DIR_SEPARATOR);
+                if (index != pal::string_t::npos)
+                {
+                    fx_found_ver = fx_dir.substr(index + 1);
+                }
+
+                fx = new fx_definition_t(fx_name, fx_dir, fx_requested_ver, fx_found_ver);
+                init->fx_definitions.push_back(std::unique_ptr<fx_definition_t>(fx));
+            }
+        }
+
+        // Initialize the host command
+        init_host_command(input, init);
+
+        if (input->version_lo >= offsetof(host_interface_t, host_info_host_path) + sizeof(input->host_info_host_path))
+        {
+            init->host_info.host_path = input->host_info_host_path;
+            init->host_info.dotnet_root = input->host_info_dotnet_root;
+            init->host_info.app_path = input->host_info_app_path;
+            // For the backwards compat case, this will be later initialized with argv[0]
+        }
+
+        return true;
+    }
+
+    static void init_host_command(host_interface_t* input, hostpolicy_init_t* init)
+    {
+        if (input->version_lo >= offsetof(host_interface_t, host_command) + sizeof(input->host_command))
+        {
+            init->host_command = input->host_command;
+        }
+    }
+
+private:
+    static void make_palstr_arr(int argc, const pal::char_t** argv, std::vector<pal::string_t>* out)
+    {
+        out->reserve(argc);
+        for (int i = 0; i < argc; ++i)
+        {
+            out->push_back(argv[i]);
+        }
+    }
+
+    static void make_clrstr_arr(int argc, const pal::char_t** argv, std::vector<std::vector<char>>* out)
+    {
+        out->resize(argc);
+        for (int i = 0; i < argc; ++i)
+        {
+            pal::pal_clrstring(pal::string_t(argv[i]), &(*out)[i]);
+        }
+    }
+};
+
+#endif // __HOSTPOLICY_INIT_H__
diff --git a/src/installer/corehost/cli/libhost.cpp b/src/installer/corehost/cli/libhost.cpp
deleted file mode 100644 (file)
index 81b5277..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright (c) .NET Foundation and contributors. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-#include "pal.h"
-#include "utils.h"
-#include "trace.h"
-#include "libhost.h"
-#include "host_startup_info.h"
-
-void get_runtime_config_paths_from_app(const pal::string_t& app, pal::string_t* cfg, pal::string_t* dev_cfg)
-{
-    auto name = get_filename_without_ext(app);
-    auto path = get_directory(app);
-
-    get_runtime_config_paths(path, name, cfg, dev_cfg);
-}
-
-void get_runtime_config_paths_from_arg(const pal::string_t& arg, pal::string_t* cfg, pal::string_t* dev_cfg)
-{
-    auto name = get_filename_without_ext(arg);
-
-    auto json_name = name + _X(".json");
-    auto dev_json_name = name + _X(".dev.json");
-
-    auto json_path = get_directory(arg);
-    auto dev_json_path = json_path;
-
-    append_path(&json_path, json_name.c_str());
-    append_path(&dev_json_path, dev_json_name.c_str());
-
-    trace::verbose(_X("Runtime config is cfg=%s dev=%s"), json_path.c_str(), dev_json_path.c_str());
-
-    dev_cfg->assign(dev_json_path);
-    cfg->assign(json_path);
-}
-
-void get_runtime_config_paths(const pal::string_t& path, const pal::string_t& name, pal::string_t* cfg, pal::string_t* dev_cfg)
-{
-    auto json_path = path;
-    auto json_name = name + _X(".runtimeconfig.json");
-    append_path(&json_path, json_name.c_str());
-    cfg->assign(json_path);
-
-    auto dev_json_path = path;
-    auto dev_json_name = name + _X(".runtimeconfig.dev.json");
-    append_path(&dev_json_path, dev_json_name.c_str());
-    dev_cfg->assign(dev_json_path);
-
-    trace::verbose(_X("Runtime config is cfg=%s dev=%s"), json_path.c_str(), dev_json_path.c_str());
-}
-
-host_mode_t detect_operating_mode(const host_startup_info_t& host_info)
-{
-    if (coreclr_exists_in_dir(host_info.dotnet_root))
-    {
-        // Detect between standalone apphost or legacy split mode (specifying --depsfile and --runtimeconfig)
-
-        pal::string_t deps_in_dotnet_root = host_info.dotnet_root;
-        pal::string_t deps_filename = host_info.get_app_name() + _X(".deps.json");
-        append_path(&deps_in_dotnet_root, deps_filename.c_str());
-        bool deps_exists = pal::file_exists(deps_in_dotnet_root);
-
-        trace::info(_X("Detecting mode... CoreCLR present in dotnet root [%s] and checking if [%s] file present=[%d]"),
-            host_info.dotnet_root.c_str(), deps_filename.c_str(), deps_exists);
-
-        // Name of runtimeconfig file; since no path is included here the check is in the current working directory
-        pal::string_t config_in_cwd = host_info.get_app_name() + _X(".runtimeconfig.json");
-
-        return (deps_exists || !pal::file_exists(config_in_cwd)) && pal::file_exists(host_info.app_path) ? host_mode_t::apphost : host_mode_t::split_fx;
-    }
-
-    if (pal::file_exists(host_info.app_path))
-    {
-        // Framework-dependent apphost
-        return host_mode_t::apphost;
-    }
-
-    return host_mode_t::muxer;
-}
-
-void try_patch_roll_forward_in_dir(const pal::string_t& cur_dir, const fx_ver_t& start_ver, pal::string_t* max_str)
-{
-    pal::string_t path = cur_dir;
-
-    if (trace::is_enabled())
-    {
-        pal::string_t start_str = start_ver.as_str();
-        trace::verbose(_X("Reading patch roll forward candidates in dir [%s] for version [%s]"), path.c_str(), start_str.c_str());
-    }
-
-    pal::string_t maj_min_star = start_ver.patch_glob();
-
-    std::vector<pal::string_t> list;
-    pal::readdir_onlydirectories(path, maj_min_star, &list);
-
-    fx_ver_t max_ver = start_ver;
-    fx_ver_t ver;
-    for (const auto& str : list)
-    {
-        trace::verbose(_X("Considering patch roll forward candidate version [%s]"), str.c_str());
-        if (fx_ver_t::parse(str, &ver, true))
-        {
-            max_ver = std::max(ver, max_ver);
-        }
-    }
-    max_str->assign(max_ver.as_str());
-
-    if (trace::is_enabled())
-    {
-        pal::string_t start_str = start_ver.as_str();
-        trace::verbose(_X("Patch roll forwarded [%s] -> [%s] in [%s]"), start_str.c_str(), max_str->c_str(), path.c_str());
-    }
-}
-
-void try_prerelease_roll_forward_in_dir(const pal::string_t& cur_dir, const fx_ver_t& start_ver, pal::string_t* max_str)
-{
-    pal::string_t path = cur_dir;
-
-    if (trace::is_enabled())
-    {
-        pal::string_t start_str = start_ver.as_str();
-        trace::verbose(_X("Reading prerelease roll forward candidates in dir [%s] for version [%s]"), path.c_str(), start_str.c_str());
-    }
-
-    pal::string_t maj_min_pat_star = start_ver.prerelease_glob();
-
-    std::vector<pal::string_t> list;
-    pal::readdir_onlydirectories(path, maj_min_pat_star, &list);
-
-    fx_ver_t max_ver = start_ver;
-    fx_ver_t ver;
-    for (const auto& str : list)
-    {
-        trace::verbose(_X("Considering prerelease roll forward candidate version [%s]"), str.c_str());
-        if (fx_ver_t::parse(str, &ver, false)
-            && ver.is_prerelease()) // Pre-release can roll forward to only pre-release
-        {
-            max_ver = std::max(ver, max_ver);
-        }
-    }
-    max_str->assign(max_ver.as_str());
-
-    if (trace::is_enabled())
-    {
-        pal::string_t start_str = start_ver.as_str();
-        trace::verbose(_X("Prerelease roll forwarded [%s] -> [%s] in [%s]"), start_str.c_str(), max_str->c_str(), path.c_str());
-    }
-}
diff --git a/src/installer/corehost/cli/libhost.h b/src/installer/corehost/cli/libhost.h
deleted file mode 100644 (file)
index 913e4fe..0000000
+++ /dev/null
@@ -1,436 +0,0 @@
-// Copyright (c) .NET Foundation and contributors. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-#ifndef __LIBHOST_H__
-#define __LIBHOST_H__
-#include <stdint.h>
-#include "trace.h"
-#include "host_startup_info.h"
-#include "runtime_config.h"
-#include "fx_definition.h"
-#include "fx_ver.h"
-
-enum host_mode_t
-{
-    invalid = 0,
-
-    muxer,          // Invoked as "dotnet.exe".
-
-    apphost,        // Invoked as <appname>.exe from the application base; this is the renamed "apphost.exe".
-
-    split_fx,       // Invoked as "corehost.exe" for xunit scenarios. Supported for backwards compat for 1.x apps.
-                    // Split FX means, the host is operating like "corerun.exe" in a split location from the application base (CORE_ROOT equivalent),
-                    // but it has its "hostfxr.dll" next to it.
-
-    libhost,        // Invoked from a non-exe scenario (e.g. COM Activation or self-hosting native application)
-};
-
-class fx_ver_t;
-class runtime_config_t;
-
-#define _HOST_INTERFACE_PACK 1
-#pragma pack(push, _HOST_INTERFACE_PACK)
-struct strarr_t
-{
-    // DO NOT modify this struct. It is used in a layout
-    // dependent manner. Create another for your use.
-    size_t len;
-    const pal::char_t** arr;
-};
-
-struct host_interface_t
-{
-    size_t version_lo;                // Just assign sizeof() to this field.
-    size_t version_hi;                // Breaking changes to the layout -- increment HOST_INTERFACE_LAYOUT_VERSION
-    strarr_t config_keys;
-    strarr_t config_values;
-    const pal::char_t* fx_dir;
-    const pal::char_t* fx_name;
-    const pal::char_t* deps_file;
-    size_t is_framework_dependent;
-    strarr_t probe_paths;
-    size_t patch_roll_forward;
-    size_t prerelease_roll_forward;
-    size_t host_mode;
-    const pal::char_t* tfm;
-    const pal::char_t* additional_deps_serialized;
-    const pal::char_t* fx_ver;
-    strarr_t fx_names;
-    strarr_t fx_dirs;
-    strarr_t fx_requested_versions;
-    strarr_t fx_found_versions;
-    const pal::char_t* host_command;
-    const pal::char_t* host_info_host_path;
-    const pal::char_t* host_info_dotnet_root;
-    const pal::char_t* host_info_app_path;
-    // !! WARNING / WARNING / WARNING / WARNING / WARNING / WARNING / WARNING / WARNING / WARNING
-    // !! 1. Only append to this structure to maintain compat.
-    // !! 2. Any nested structs should not use compiler specific padding (pack with _HOST_INTERFACE_PACK)
-    // !! 3. Do not take address of the fields of this struct or be prepared to deal with unaligned accesses.
-    // !! 4. Must be POD types; only use non-const size_t and pointer types; no access modifiers.
-    // !! 5. Do not reorder fields or change any existing field types.
-    // !! 6. Add static asserts for fields you add.
-};
-#pragma pack(pop)
-static_assert(_HOST_INTERFACE_PACK == 1, "Packing size should not be modified for back compat");
-static_assert(offsetof(host_interface_t, version_lo) == 0 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(offsetof(host_interface_t, version_hi) == 1 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(offsetof(host_interface_t, config_keys) == 2 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(offsetof(host_interface_t, config_values) == 4 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(offsetof(host_interface_t, fx_dir) == 6 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(offsetof(host_interface_t, fx_name) == 7 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(offsetof(host_interface_t, deps_file) == 8 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(offsetof(host_interface_t, is_framework_dependent) == 9 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(offsetof(host_interface_t, probe_paths) == 10 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(offsetof(host_interface_t, patch_roll_forward) == 12 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(offsetof(host_interface_t, prerelease_roll_forward) == 13 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(offsetof(host_interface_t, host_mode) == 14 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(offsetof(host_interface_t, tfm) == 15 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(offsetof(host_interface_t, additional_deps_serialized) == 16 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(offsetof(host_interface_t, fx_ver) == 17 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(offsetof(host_interface_t, fx_names) == 18 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(offsetof(host_interface_t, fx_dirs) == 20 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(offsetof(host_interface_t, fx_requested_versions) == 22 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(offsetof(host_interface_t, fx_found_versions) == 24 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(offsetof(host_interface_t, host_command) == 26 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(offsetof(host_interface_t, host_info_host_path) == 27 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(offsetof(host_interface_t, host_info_dotnet_root) == 28 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(offsetof(host_interface_t, host_info_app_path) == 29 * sizeof(size_t), "Struct offset breaks backwards compatibility");
-static_assert(sizeof(host_interface_t) == 30 * sizeof(size_t), "Did you add static asserts for the newly added fields?");
-
-#define HOST_INTERFACE_LAYOUT_VERSION_HI 0x16041101 // YYMMDD:nn always increases when layout breaks compat.
-#define HOST_INTERFACE_LAYOUT_VERSION_LO sizeof(host_interface_t)
-
-class corehost_init_t
-{
-private:
-    std::vector<pal::string_t> m_clr_keys;
-    std::vector<pal::string_t> m_clr_values;
-    std::vector<const pal::char_t*> m_clr_keys_cstr;
-    std::vector<const pal::char_t*> m_clr_values_cstr;
-    const pal::string_t m_tfm;
-    const pal::string_t m_deps_file;
-    const pal::string_t m_additional_deps_serialized;
-    bool m_is_framework_dependent;
-    std::vector<pal::string_t> m_probe_paths;
-    std::vector<const pal::char_t*> m_probe_paths_cstr;
-    host_mode_t m_host_mode;
-    host_interface_t m_host_interface;
-    std::vector<pal::string_t> m_fx_names;
-    std::vector<const pal::char_t*> m_fx_names_cstr;
-    std::vector<pal::string_t> m_fx_dirs;
-    std::vector<const pal::char_t*> m_fx_dirs_cstr;
-    std::vector<pal::string_t> m_fx_requested_versions;
-    std::vector<const pal::char_t*> m_fx_requested_versions_cstr;
-    std::vector<pal::string_t> m_fx_found_versions;
-    std::vector<const pal::char_t*> m_fx_found_versions_cstr;
-    const pal::string_t m_host_command;
-    const pal::string_t m_host_info_host_path;
-    const pal::string_t m_host_info_dotnet_root;
-    const pal::string_t m_host_info_app_path;
-public:
-    corehost_init_t(
-        const pal::string_t& host_command,
-        const host_startup_info_t& host_info,
-        const pal::string_t& deps_file,
-        const pal::string_t& additional_deps_serialized,
-        const std::vector<pal::string_t>& probe_paths,
-        const host_mode_t mode,
-        const fx_definition_vector_t& fx_definitions)
-        : m_host_command(host_command)
-        , m_host_info_host_path(host_info.host_path)
-        , m_host_info_dotnet_root(host_info.dotnet_root)
-        , m_host_info_app_path(host_info.app_path)
-        , m_deps_file(deps_file)
-        , m_additional_deps_serialized(additional_deps_serialized)
-        , m_is_framework_dependent(get_app(fx_definitions).get_runtime_config().get_is_framework_dependent())
-        , m_probe_paths(probe_paths)
-        , m_host_mode(mode)
-        , m_host_interface()
-        , m_tfm(get_app(fx_definitions).get_runtime_config().get_tfm())
-    {
-        make_cstr_arr(m_probe_paths, &m_probe_paths_cstr);
-
-        int fx_count = fx_definitions.size();
-        m_fx_names.reserve(fx_count);
-        m_fx_dirs.reserve(fx_count);
-        m_fx_requested_versions.reserve(fx_count);
-        m_fx_found_versions.reserve(fx_count);
-
-        std::unordered_map<pal::string_t, pal::string_t> combined_properties;
-        for (auto& fx : fx_definitions)
-        {
-            fx->get_runtime_config().combine_properties(combined_properties);
-
-            m_fx_names.push_back(fx->get_name());
-            m_fx_dirs.push_back(fx->get_dir());
-            m_fx_requested_versions.push_back(fx->get_requested_version());
-            m_fx_found_versions.push_back(fx->get_found_version());
-        }
-
-        for (const auto& kv : combined_properties)
-        {
-            m_clr_keys.push_back(kv.first);
-            m_clr_values.push_back(kv.second);
-        }
-
-        make_cstr_arr(m_fx_names, &m_fx_names_cstr);
-        make_cstr_arr(m_fx_dirs, &m_fx_dirs_cstr);
-        make_cstr_arr(m_fx_requested_versions, &m_fx_requested_versions_cstr);
-        make_cstr_arr(m_fx_found_versions, &m_fx_found_versions_cstr);
-        make_cstr_arr(m_clr_keys, &m_clr_keys_cstr);
-        make_cstr_arr(m_clr_values, &m_clr_values_cstr);
-    }
-
-    const pal::string_t& tfm() const
-    {
-        return m_tfm;
-    }
-
-    const host_interface_t& get_host_init_data()
-    {
-        host_interface_t& hi = m_host_interface;
-
-        hi.version_lo = HOST_INTERFACE_LAYOUT_VERSION_LO;
-        hi.version_hi = HOST_INTERFACE_LAYOUT_VERSION_HI;
-
-        hi.config_keys.len = m_clr_keys_cstr.size();
-        hi.config_keys.arr = m_clr_keys_cstr.data();
-
-        hi.config_values.len = m_clr_values_cstr.size();
-        hi.config_values.arr = m_clr_values_cstr.data();
-
-        // Keep these for backwards compat
-        if (m_fx_names_cstr.size() > 1)
-        {
-            hi.fx_name = m_fx_names_cstr[1];
-            hi.fx_dir = m_fx_dirs_cstr[1];
-            hi.fx_ver = m_fx_requested_versions_cstr[1];
-        }
-        else
-        {
-            hi.fx_name = _X("");
-            hi.fx_dir = _X("");
-            hi.fx_ver = _X("");
-        }
-
-        hi.deps_file = m_deps_file.c_str();
-        hi.additional_deps_serialized = m_additional_deps_serialized.c_str();
-        hi.is_framework_dependent = m_is_framework_dependent;
-
-        hi.probe_paths.len = m_probe_paths_cstr.size();
-        hi.probe_paths.arr = m_probe_paths_cstr.data();
-
-        // These are not used anymore, but we have to keep them for backward compat reasons.
-        // Set default values.
-        hi.patch_roll_forward = true;
-        hi.prerelease_roll_forward = false;
-
-        hi.host_mode = m_host_mode;
-
-        hi.tfm = m_tfm.c_str();
-
-        hi.fx_names.len = m_fx_names_cstr.size();
-        hi.fx_names.arr = m_fx_names_cstr.data();
-
-        hi.fx_dirs.len = m_fx_dirs_cstr.size();
-        hi.fx_dirs.arr = m_fx_dirs_cstr.data();
-
-        hi.fx_requested_versions.len = m_fx_requested_versions_cstr.size();
-        hi.fx_requested_versions.arr = m_fx_requested_versions_cstr.data();
-
-        hi.fx_found_versions.len = m_fx_found_versions_cstr.size();
-        hi.fx_found_versions.arr = m_fx_found_versions_cstr.data();
-
-        hi.host_command = m_host_command.c_str();
-
-        hi.host_info_host_path = m_host_info_host_path.c_str();
-        hi.host_info_dotnet_root = m_host_info_dotnet_root.c_str();
-        hi.host_info_app_path = m_host_info_app_path.c_str();
-
-        return hi;
-    }
-
-private:
-
-    static void make_cstr_arr(const std::vector<pal::string_t>& arr, std::vector<const pal::char_t*>* out)
-    {
-        out->reserve(arr.size());
-        for (const auto& str : arr)
-        {
-            out->push_back(str.c_str());
-        }
-    }
-};
-
-struct hostpolicy_init_t
-{
-    std::vector<std::vector<char>> cfg_keys;
-    std::vector<std::vector<char>> cfg_values;
-    pal::string_t deps_file;
-    pal::string_t additional_deps_serialized;
-    std::vector<pal::string_t> probe_paths;
-    fx_definition_vector_t fx_definitions;
-    pal::string_t tfm;
-    host_mode_t host_mode;
-    bool patch_roll_forward;
-    bool prerelease_roll_forward;
-    bool is_framework_dependent;
-    pal::string_t host_command;
-    host_startup_info_t host_info;
-
-    static bool init(host_interface_t* input, hostpolicy_init_t* init)
-    {
-        // Check if there are any breaking changes.
-        if (input->version_hi != HOST_INTERFACE_LAYOUT_VERSION_HI)
-        {
-            trace::error(_X("The version of the data layout used to initialize %s is [0x%04x]; expected version [0x%04x]"), LIBHOSTPOLICY_NAME, input->version_hi, HOST_INTERFACE_LAYOUT_VERSION_HI);
-            return false;
-        }
-
-        trace::verbose(_X("Reading from host interface version: [0x%04x:%d] to initialize policy version: [0x%04x:%d]"), input->version_hi, input->version_lo, HOST_INTERFACE_LAYOUT_VERSION_HI, HOST_INTERFACE_LAYOUT_VERSION_LO);
-
-        //This check is to ensure is an old hostfxr can still load new hostpolicy.
-        //We should not read garbage due to potentially shorter struct size
-
-        pal::string_t fx_requested_ver;
-
-        if (input->version_lo >= offsetof(host_interface_t, host_mode) + sizeof(input->host_mode))
-        {
-            make_clrstr_arr(input->config_keys.len, input->config_keys.arr, &init->cfg_keys);
-            make_clrstr_arr(input->config_values.len, input->config_values.arr, &init->cfg_values);
-
-            init->deps_file = input->deps_file;
-            init->is_framework_dependent = input->is_framework_dependent;
-
-            make_palstr_arr(input->probe_paths.len, input->probe_paths.arr, &init->probe_paths);
-
-            init->patch_roll_forward = input->patch_roll_forward;
-            init->prerelease_roll_forward = input->prerelease_roll_forward;
-            init->host_mode = (host_mode_t)input->host_mode;
-        }
-        else
-        {
-            trace::error(_X("The size of the data layout used to initialize %s is %d; expected at least %d"), LIBHOSTPOLICY_NAME, input->version_lo, 
-                offsetof(host_interface_t, host_mode) + sizeof(input->host_mode));
-        }
-
-        //An old hostfxr may not provide these fields.
-        //The version_lo (sizeof) the old hostfxr saw at build time will be
-        //smaller and we should not attempt to read the fields in that case.
-        if (input->version_lo >= offsetof(host_interface_t, tfm) + sizeof(input->tfm))
-        {
-            init->tfm = input->tfm;
-        }
-        
-        if (input->version_lo >= offsetof(host_interface_t, fx_ver) + sizeof(input->fx_ver))
-        {
-            init->additional_deps_serialized = input->additional_deps_serialized;
-            fx_requested_ver = input->fx_ver;
-        }
-
-        int fx_count = 0;
-        if (input->version_lo >= offsetof(host_interface_t, fx_names) + sizeof(input->fx_names))
-        {
-            int fx_count = input->fx_names.len;
-            assert(fx_count > 0);
-            assert(fx_count == input->fx_dirs.len);
-            assert(fx_count == input->fx_requested_versions.len);
-            assert(fx_count == input->fx_found_versions.len);
-
-            std::vector<pal::string_t> fx_names;
-            std::vector<pal::string_t> fx_dirs;
-            std::vector<pal::string_t> fx_requested_versions;
-            std::vector<pal::string_t> fx_found_versions;
-
-            make_palstr_arr(input->fx_names.len, input->fx_names.arr, &fx_names);
-            make_palstr_arr(input->fx_dirs.len, input->fx_dirs.arr, &fx_dirs);
-            make_palstr_arr(input->fx_requested_versions.len, input->fx_requested_versions.arr, &fx_requested_versions);
-            make_palstr_arr(input->fx_found_versions.len, input->fx_found_versions.arr, &fx_found_versions);
-
-            init->fx_definitions.reserve(fx_count);
-            for (int i = 0; i < fx_count; ++i)
-            {
-                auto fx = new fx_definition_t(fx_names[i], fx_dirs[i], fx_requested_versions[i], fx_found_versions[i]);
-                init->fx_definitions.push_back(std::unique_ptr<fx_definition_t>(fx));
-            }
-        }
-        else
-        {
-            // Backward compat; create the fx_definitions[0] and [1] from the previous information
-            init->fx_definitions.reserve(2);
-
-            auto fx = new fx_definition_t();
-            init->fx_definitions.push_back(std::unique_ptr<fx_definition_t>(fx));
-
-            if (init->is_framework_dependent)
-            {
-                pal::string_t fx_dir = input->fx_dir;
-                pal::string_t fx_name = input->fx_name;
-
-                // The found_ver was not passed previously, so obtain that from fx_dir
-                pal::string_t fx_found_ver;
-                size_t index = fx_dir.rfind(DIR_SEPARATOR);
-                if (index != pal::string_t::npos)
-                {
-                    fx_found_ver = fx_dir.substr(index + 1);
-                }
-
-                fx = new fx_definition_t(fx_name, fx_dir, fx_requested_ver, fx_found_ver);
-                init->fx_definitions.push_back(std::unique_ptr<fx_definition_t>(fx));
-            }
-        }
-
-        // Initialize the host command
-        init_host_command(input, init);
-
-        if (input->version_lo >= offsetof(host_interface_t, host_info_host_path) + sizeof(input->host_info_host_path))
-        {
-            init->host_info.host_path = input->host_info_host_path;
-            init->host_info.dotnet_root = input->host_info_dotnet_root;
-            init->host_info.app_path = input->host_info_app_path;
-            // For the backwards compat case, this will be later initialized with argv[0]
-        }
-
-        return true;
-    }
-
-    static void init_host_command(host_interface_t* input, hostpolicy_init_t* init)
-    {
-        if (input->version_lo >= offsetof(host_interface_t, host_command) + sizeof(input->host_command))
-        {
-            init->host_command = input->host_command;
-        }
-    }
-
-private:
-    static void make_palstr_arr(int argc, const pal::char_t** argv, std::vector<pal::string_t>* out)
-    {
-        out->reserve(argc);
-        for (int i = 0; i < argc; ++i)
-        {
-            out->push_back(argv[i]);
-        }
-    }
-
-    static void make_clrstr_arr(int argc, const pal::char_t** argv, std::vector<std::vector<char>>* out)
-    {
-        out->resize(argc);
-        for (int i = 0; i < argc; ++i)
-        {
-            pal::pal_clrstring(pal::string_t(argv[i]), &(*out)[i]);
-        }
-    }
-};
-
-void get_runtime_config_paths_from_app(const pal::string_t& file, pal::string_t* config_file, pal::string_t* dev_config_file);
-void get_runtime_config_paths_from_arg(const pal::string_t& file, pal::string_t* config_file, pal::string_t* dev_config_file);
-void get_runtime_config_paths(const pal::string_t& path, const pal::string_t& name, pal::string_t* config_file, pal::string_t* dev_config_file);
-
-host_mode_t detect_operating_mode(const host_startup_info_t& host_info);
-bool hostpolicy_exists_in_svc(pal::string_t* resolved_dir);
-
-void try_patch_roll_forward_in_dir(const pal::string_t& cur_dir, const fx_ver_t& start_ver, pal::string_t* max_str);
-void try_prerelease_roll_forward_in_dir(const pal::string_t& cur_dir, const fx_ver_t& start_ver, pal::string_t* max_str);
-
-#endif // __LIBHOST_H__