From 89a01e3a7cfe8633313fff47573ac60eccc5e38b Mon Sep 17 00:00:00 2001 From: vitek-karas Date: Tue, 22 Sep 2020 08:36:11 -0700 Subject: [PATCH] Pass system path from host --- src/coreclr/src/dlls/mscoree/mscoree.cpp | 13 +++++++++++-- src/coreclr/src/dlls/mscoree/unixinterface.cpp | 17 ++++++++++++++--- src/coreclr/src/inc/bundle.h | 4 +++- src/coreclr/src/vm/bundle.cpp | 3 ++- .../corehost/cli/hostpolicy/coreclr.cpp | 3 ++- src/installer/corehost/cli/hostpolicy/coreclr.h | 1 + .../cli/hostpolicy/hostpolicy_context.cpp | 16 ++++++++++++++-- 7 files changed, 47 insertions(+), 10 deletions(-) diff --git a/src/coreclr/src/dlls/mscoree/mscoree.cpp b/src/coreclr/src/dlls/mscoree/mscoree.cpp index f9e1e3d89ef68..4ac3a62969758 100644 --- a/src/coreclr/src/dlls/mscoree/mscoree.cpp +++ b/src/coreclr/src/dlls/mscoree/mscoree.cpp @@ -14,6 +14,7 @@ #include "shimload.h" #include "metadataexports.h" #include "ex.h" +#include "bundle.h" #include @@ -336,8 +337,16 @@ STDAPI GetCORSystemDirectoryInternaL(SString& pBuffer) } #else - - if (!PAL_GetPALDirectoryWrapper(pBuffer)) { + if (Bundle::AppIsBundle() && !Bundle::AppBundle->SystemPath().IsEmpty()) + { + EX_TRY + { + pBuffer = Bundle::AppBundle->SystemPath(); + } + EX_CATCH_HRESULT(hr); + } + else if (hr == S_OK && !PAL_GetPALDirectoryWrapper(pBuffer)) + { hr = HRESULT_FROM_GetLastError(); } #endif diff --git a/src/coreclr/src/dlls/mscoree/unixinterface.cpp b/src/coreclr/src/dlls/mscoree/unixinterface.cpp index e23ece9872244..70071e914817e 100644 --- a/src/coreclr/src/dlls/mscoree/unixinterface.cpp +++ b/src/coreclr/src/dlls/mscoree/unixinterface.cpp @@ -120,7 +120,8 @@ static void ConvertConfigPropertiesToUnicode( LPCWSTR** propertyKeysWRef, LPCWSTR** propertyValuesWRef, BundleProbe** bundleProbe, - bool* hostPolicyEmbedded) + bool* hostPolicyEmbedded, + LPCWSTR* systemPath) { LPCWSTR* propertyKeysW = new (nothrow) LPCWSTR[propertyCount]; ASSERTE_ALL_BUILDS(propertyKeysW != nullptr); @@ -144,6 +145,14 @@ static void ConvertConfigPropertiesToUnicode( // The HOSTPOLICY_EMBEDDED property indicates if the executable has hostpolicy statically linked in *hostPolicyEmbedded = (wcscmp(propertyValuesW[propertyIndex], W("true")) == 0); } + else if (strcmp(propertyKeys[propertyIndex], "SYSTEM_PATH") == 0) + { + // This is set by the host if the correct system path can't be determined by looking at the location + // of the runtime module itself. This is the case when the runtime is linked into the single file host + // so there's no coreclr library itself and the entire bundle is extracted onto disk - so for example + // System.Private.CoreLib doesn't exist "next" to the runtime. + *systemPath = propertyValuesW[propertyIndex]; + } } *propertyKeysWRef = propertyKeysW; @@ -187,6 +196,7 @@ int coreclr_initialize( LPCWSTR* propertyValuesW; BundleProbe* bundleProbe = nullptr; bool hostPolicyEmbedded = false; + LPCWSTR systemPath = nullptr; ConvertConfigPropertiesToUnicode( propertyKeys, @@ -195,7 +205,8 @@ int coreclr_initialize( &propertyKeysW, &propertyValuesW, &bundleProbe, - &hostPolicyEmbedded); + &hostPolicyEmbedded, + &systemPath); #ifdef TARGET_UNIX DWORD error = PAL_InitializeCoreCLR(exePath, g_coreclr_embedded); @@ -220,7 +231,7 @@ int coreclr_initialize( if (bundleProbe != nullptr) { - static Bundle bundle(StringToUnicode(exePath), bundleProbe); + static Bundle bundle(StringToUnicode(exePath), systemPath, bundleProbe); Bundle::AppBundle = &bundle; } diff --git a/src/coreclr/src/inc/bundle.h b/src/coreclr/src/inc/bundle.h index c669790350db5..1b313b95d0d46 100644 --- a/src/coreclr/src/inc/bundle.h +++ b/src/coreclr/src/inc/bundle.h @@ -39,11 +39,12 @@ typedef bool(__stdcall BundleProbe)(LPCWSTR, INT64*, INT64*); class Bundle { public: - Bundle(LPCWSTR bundlePath, BundleProbe *probe); + Bundle(LPCWSTR bundlePath, LPCWSTR systemPath, BundleProbe *probe); BundleFileLocation Probe(LPCWSTR path, bool pathIsBundleRelative = false) const; const SString &Path() const { LIMITED_METHOD_CONTRACT; return m_path; } const SString &BasePath() const { LIMITED_METHOD_CONTRACT; return m_basePath; } + const SString &SystemPath() const { LIMITED_METHOD_CONTRACT; return m_systemPath; } static Bundle* AppBundle; // The BundleInfo for the current app, initialized by coreclr_initialize. static bool AppIsBundle() { LIMITED_METHOD_CONTRACT; return AppBundle != nullptr; } @@ -52,6 +53,7 @@ class Bundle private: SString m_path; // The path to single-file executable + SString m_systemPath; // The system path if this needs to be different from the exe path above (otherwise empty) BundleProbe *m_probe; SString m_basePath; // The prefix to denote a path within the bundle diff --git a/src/coreclr/src/vm/bundle.cpp b/src/coreclr/src/vm/bundle.cpp index 3a204deb2cfb5..4e57a4a3fc243 100644 --- a/src/coreclr/src/vm/bundle.cpp +++ b/src/coreclr/src/vm/bundle.cpp @@ -30,13 +30,14 @@ const SString &BundleFileLocation::Path() const return Bundle::AppBundle->Path(); } -Bundle::Bundle(LPCWSTR bundlePath, BundleProbe *probe) +Bundle::Bundle(LPCWSTR bundlePath, LPCWSTR systemPath, BundleProbe *probe) { STANDARD_VM_CONTRACT; _ASSERTE(probe != nullptr); m_path.Set(bundlePath); + m_systemPath.Set(systemPath); m_probe = probe; // The bundle-base path is the directory containing the single-file bundle. diff --git a/src/installer/corehost/cli/hostpolicy/coreclr.cpp b/src/installer/corehost/cli/hostpolicy/coreclr.cpp index d9564ac8fa676..144940629cac0 100644 --- a/src/installer/corehost/cli/hostpolicy/coreclr.cpp +++ b/src/installer/corehost/cli/hostpolicy/coreclr.cpp @@ -148,7 +148,8 @@ namespace _X("APP_NI_PATHS"), _X("RUNTIME_IDENTIFIER"), _X("BUNDLE_PROBE"), - _X("HOSTPOLICY_EMBEDDED") + _X("HOSTPOLICY_EMBEDDED"), + _X("SYSTEM_PATH") }; static_assert((sizeof(PropertyNameMapping) / sizeof(*PropertyNameMapping)) == static_cast(common_property::Last), "Invalid property count"); diff --git a/src/installer/corehost/cli/hostpolicy/coreclr.h b/src/installer/corehost/cli/hostpolicy/coreclr.h index c086ba56e10b2..9c7f659d89df5 100644 --- a/src/installer/corehost/cli/hostpolicy/coreclr.h +++ b/src/installer/corehost/cli/hostpolicy/coreclr.h @@ -67,6 +67,7 @@ enum class common_property RuntimeIdentifier, BundleProbe, HostPolicyEmbedded, + SystemPath, // Sentinel value - new values should be defined above Last }; diff --git a/src/installer/corehost/cli/hostpolicy/hostpolicy_context.cpp b/src/installer/corehost/cli/hostpolicy/hostpolicy_context.cpp index 05a3b8fb9e2db..0f2464e6ab198 100644 --- a/src/installer/corehost/cli/hostpolicy/hostpolicy_context.cpp +++ b/src/installer/corehost/cli/hostpolicy/hostpolicy_context.cpp @@ -234,15 +234,27 @@ int hostpolicy_context_t::initialize(hostpolicy_init_t &hostpolicy_init, const a if (!coreclr_properties.add(common_property::BundleProbe, ptr_stream.str().c_str())) { - log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::StartUpHooks)); + log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::BundleProbe)); return StatusCode::LibHostDuplicateProperty; } + + // In the case where everything is extracted onto disk, set the system path to the extraction directory + // This is important if the runtime is compiled into the host, in which case it would have no way to detect + // the extraction directory. + if (bundle::runner_t::app()->is_netcoreapp3_compat_mode()) + { + if (!coreclr_properties.add(common_property::SystemPath, app_base.c_str())) + { + log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::SystemPath)); + return StatusCode::LibHostDuplicateProperty; + } + } } #if defined(HOSTPOLICY_EMBEDDED) if (!coreclr_properties.add(common_property::HostPolicyEmbedded, _X("true"))) { - log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::StartUpHooks)); + log_duplicate_property_error(coreclr_property_bag_t::common_property_to_string(common_property::HostPolicyEmbedded)); return StatusCode::LibHostDuplicateProperty; } #endif