diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
index c12d6c854ac0c0..440163552ef3d4 100644
--- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
+++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
@@ -222,7 +222,6 @@
-
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.CoreCLR.cs
deleted file mode 100644
index f407b366021f89..00000000000000
--- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.CoreCLR.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Reflection;
-using System.Runtime.CompilerServices;
-
-namespace System.Runtime.InteropServices
-{
- public static partial class NativeLibrary
- {
- internal static IntPtr LoadLibraryByName(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, bool throwOnError)
- {
- RuntimeAssembly rtAsm = (RuntimeAssembly)assembly;
- return LoadByName(libraryName,
- new QCallAssembly(ref rtAsm),
- searchPath.HasValue,
- (uint)searchPath.GetValueOrDefault(),
- throwOnError);
- }
-
- /// External functions that implement the NativeLibrary interface
-
- [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "NativeLibrary_LoadFromPath", StringMarshalling = StringMarshalling.Utf16)]
- internal static partial IntPtr LoadFromPath(string libraryName, [MarshalAs(UnmanagedType.Bool)] bool throwOnError);
-
- [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "NativeLibrary_LoadByName", StringMarshalling = StringMarshalling.Utf16)]
- internal static partial IntPtr LoadByName(string libraryName, QCallAssembly callingAssembly,
- [MarshalAs(UnmanagedType.Bool)] bool hasDllImportSearchPathFlag, uint dllImportSearchPathFlag,
- [MarshalAs(UnmanagedType.Bool)] bool throwOnError);
-
- [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "NativeLibrary_FreeLib")]
- internal static partial void FreeLib(IntPtr handle);
-
- [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "NativeLibrary_GetSymbol", StringMarshalling = StringMarshalling.Utf16)]
- internal static partial IntPtr GetSymbol(IntPtr handle, string symbolName, [MarshalAs(UnmanagedType.Bool)] bool throwOnError);
- }
-}
diff --git a/src/coreclr/dlls/mscorrc/mscorrc.rc b/src/coreclr/dlls/mscorrc/mscorrc.rc
index 0fed12722a1139..abd530f5836d37 100644
--- a/src/coreclr/dlls/mscorrc/mscorrc.rc
+++ b/src/coreclr/dlls/mscorrc/mscorrc.rc
@@ -164,8 +164,6 @@ BEGIN
IDS_EE_NDIRECT_LOADLIB_MAC "Unable to load shared library '%1' or one of its dependencies. In order to help diagnose loading problems, consider setting the DYLD_PRINT_LIBRARIES environment variable: %2"
IDS_EE_NDIRECT_GETPROCADDRESS_WIN "Unable to find an entry point named '%2' in DLL '%1'."
IDS_EE_NDIRECT_GETPROCADDRESS_UNIX "Unable to find an entry point named '%2' in shared library '%1'."
- IDS_EE_NDIRECT_GETPROCADDR_WIN_DLL "Unable to find an entry point named '%1' in DLL."
- IDS_EE_NDIRECT_GETPROCADDR_UNIX_SO "Unable to find an entry point named '%1' in shared library."
IDS_EE_NDIRECT_GETPROCADDRESS_NONAME "A library name must be specified in a DllImport attribute applied to non-IJW methods."
IDS_EE_NDIRECT_DISABLEDMARSHAL_SETLASTERROR "Setting SetLastError to 'true' is not supported when runtime marshalling is disabled."
IDS_EE_NDIRECT_DISABLEDMARSHAL_LCID "The LCIDConversionAttribute is not supported when runtime marshalling is disabled."
diff --git a/src/coreclr/dlls/mscorrc/resource.h b/src/coreclr/dlls/mscorrc/resource.h
index f7ae1dea4a6259..f3621378343c9a 100644
--- a/src/coreclr/dlls/mscorrc/resource.h
+++ b/src/coreclr/dlls/mscorrc/resource.h
@@ -514,8 +514,6 @@
#define IDS_EE_CANNOT_SET_INITONLY_STATIC_FIELD 0x2643
-#define IDS_EE_NDIRECT_GETPROCADDR_WIN_DLL 0x2644
-#define IDS_EE_NDIRECT_GETPROCADDR_UNIX_SO 0x2645
#define IDS_EE_BADMARSHAL_STRING_OUT 0x2646
#define IDS_EE_BADMARSHAL_COPYCTORRESTRICTION 0x2647
#define IDS_EE_BADMARSHAL_DELEGATE_TLB_INTERFACE 0x2649
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj
index 6dd8b1dbe9fa54..76d3de6266ab27 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj
@@ -202,7 +202,6 @@
-
@@ -252,7 +251,6 @@
-
System\Runtime\InteropServices\BuiltInVariantExtensions.cs
@@ -282,9 +280,6 @@
Interop\Windows\OleAut32\Interop.VariantClear.cs
-
- Interop\Windows\Kernel32\Interop.DynamicLoad.cs
-
@@ -293,7 +288,6 @@
-
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.cs
deleted file mode 100644
index db2174deef1dc2..00000000000000
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.cs
+++ /dev/null
@@ -1,154 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.IO;
-using System.Reflection;
-
-using LibraryNameVariation = System.Runtime.Loader.LibraryNameVariation;
-
-namespace System.Runtime.InteropServices
-{
- public static partial class NativeLibrary
- {
- // Not a public API. We expose this so that it's possible to bypass the codepath that tries to read search path
- // from custom attributes.
- internal static bool TryLoad(string libraryName, Assembly assembly, DllImportSearchPath searchPath, out IntPtr handle)
- {
- handle = LoadLibraryByName(libraryName,
- assembly,
- userSpecifiedSearchFlags: true,
- searchPath,
- throwOnError: false);
- return handle != IntPtr.Zero;
- }
-
- internal static IntPtr LoadLibraryByName(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, bool throwOnError)
- {
- // First checks if a default dllImportSearchPathFlags was passed in, if so, use that value.
- // Otherwise checks if the assembly has the DefaultDllImportSearchPathsAttribute attribute.
- // If so, use that value.
- bool userSpecifiedSearchFlags = searchPath.HasValue;
- if (!userSpecifiedSearchFlags)
- {
- searchPath = GetDllImportSearchPath(assembly, out userSpecifiedSearchFlags);
- }
- return LoadLibraryByName(libraryName, assembly, userSpecifiedSearchFlags, searchPath!.Value, throwOnError);
- }
-
- private static IntPtr LoadLibraryByName(string libraryName, Assembly assembly, bool userSpecifiedSearchFlags, DllImportSearchPath searchPath, bool throwOnError)
- {
- int searchPathFlags = (int)(searchPath & ~DllImportSearchPath.AssemblyDirectory);
- bool searchAssemblyDirectory = (searchPath & DllImportSearchPath.AssemblyDirectory) != 0;
-
- LoadLibErrorTracker errorTracker = default;
- IntPtr ret = LoadBySearch(assembly, userSpecifiedSearchFlags, searchAssemblyDirectory, searchPathFlags, ref errorTracker, libraryName);
- if (throwOnError && ret == IntPtr.Zero)
- {
- errorTracker.Throw(libraryName);
- }
-
- return ret;
- }
-
- private static DllImportSearchPath GetDllImportSearchPath(Assembly callingAssembly, out bool userSpecifiedSearchFlags)
- {
- foreach (CustomAttributeData cad in callingAssembly.CustomAttributes)
- {
- if (cad.AttributeType == typeof(DefaultDllImportSearchPathsAttribute))
- {
- userSpecifiedSearchFlags = true;
- return (DllImportSearchPath)cad.ConstructorArguments[0].Value!;
- }
- }
-
- userSpecifiedSearchFlags = false;
- return DllImportSearchPath.AssemblyDirectory;
- }
-
- internal static IntPtr LoadBySearch(Assembly callingAssembly, bool userSpecifiedSearchFlags, bool searchAssemblyDirectory, int dllImportSearchPathFlags, ref LoadLibErrorTracker errorTracker, string libraryName)
- {
- IntPtr ret;
-
- int loadWithAlteredPathFlags = LoadWithAlteredSearchPathFlag;
- const int loadLibrarySearchFlags = (int)DllImportSearchPath.UseDllDirectoryForDependencies
- | (int)DllImportSearchPath.ApplicationDirectory
- | (int)DllImportSearchPath.UserDirectories
- | (int)DllImportSearchPath.System32
- | (int)DllImportSearchPath.SafeDirectories;
- bool libNameIsRelativePath = !Path.IsPathFullyQualified(libraryName);
-
- // P/Invokes are often declared with variations on the actual library name.
- // For example, it's common to leave off the extension/suffix of the library
- // even if it has one, or to leave off a prefix like "lib" even if it has one
- // (both of these are typically done to smooth over cross-platform differences).
- // We try to dlopen with such variations on the original.
- foreach (LibraryNameVariation libraryNameVariation in LibraryNameVariation.DetermineLibraryNameVariations(libraryName, libNameIsRelativePath))
- {
- string currLibNameVariation = libraryNameVariation.Prefix + libraryName + libraryNameVariation.Suffix;
-
- if (!libNameIsRelativePath)
- {
- // LOAD_WITH_ALTERED_SEARCH_PATH is incompatible with LOAD_LIBRARY_SEARCH flags. Remove those flags if they are set.
- int flags = loadWithAlteredPathFlags | (dllImportSearchPathFlags & ~loadLibrarySearchFlags);
- ret = LoadLibraryHelper(currLibNameVariation, flags, ref errorTracker);
- if (ret != IntPtr.Zero)
- {
- return ret;
- }
- }
- else if ((callingAssembly != null) && searchAssemblyDirectory)
- {
- // LOAD_WITH_ALTERED_SEARCH_PATH is incompatible with LOAD_LIBRARY_SEARCH flags. Remove those flags if they are set.
- int flags = loadWithAlteredPathFlags | (dllImportSearchPathFlags & ~loadLibrarySearchFlags);
-
- // Try to load the module alongside the assembly where the PInvoke was declared.
- // For PInvokes where the DllImportSearchPath.AssemblyDirectory is specified, look next to the application.
- ret = LoadLibraryHelper(Path.Combine(AppContext.BaseDirectory, currLibNameVariation), flags, ref errorTracker);
- if (ret != IntPtr.Zero)
- {
- return ret;
- }
- }
-
- // Internally, search path flags and whether or not to search the assembly directory are
- // tracked separately. However, on the API level, DllImportSearchPath represents them both.
- // When unspecified, the default is to search the assembly directory and all OS defaults,
- // which maps to searchAssemblyDirectory being true and dllImportSearchPathFlags being 0.
- // When a user specifies DllImportSearchPath.AssemblyDirectory, searchAssemblyDirectory is
- // true, dllImportSearchPathFlags is 0, and the desired logic is to only search the assembly
- // directory (handled above), so we avoid doing any additional load search in that case.
- if (!userSpecifiedSearchFlags || !searchAssemblyDirectory || dllImportSearchPathFlags != 0)
- {
- ret = LoadLibraryHelper(currLibNameVariation, dllImportSearchPathFlags, ref errorTracker);
- if (ret != IntPtr.Zero)
- {
- return ret;
- }
- }
- }
-
- return IntPtr.Zero;
- }
-
- private static IntPtr LoadFromPath(string libraryName, bool throwOnError)
- {
- LoadLibErrorTracker errorTracker = default;
- IntPtr ret = LoadLibraryHelper(libraryName, LoadWithAlteredSearchPathFlag, ref errorTracker);
- if (throwOnError && ret == IntPtr.Zero)
- {
- errorTracker.Throw(libraryName);
- }
-
- return ret;
- }
-
- private static unsafe IntPtr GetSymbol(IntPtr handle, string symbolName, bool throwOnError)
- {
- IntPtr ret = GetSymbolOrNull(handle, symbolName);
- if (throwOnError && ret == IntPtr.Zero)
- throw new EntryPointNotFoundException(SR.Format(SR.Arg_EntryPointNotFoundExceptionParameterizedNoLibrary, symbolName));
-
- return ret;
- }
- }
-}
diff --git a/src/coreclr/vm/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt
index f574bb1f14eefc..5fbcb4ac6da73a 100644
--- a/src/coreclr/vm/CMakeLists.txt
+++ b/src/coreclr/vm/CMakeLists.txt
@@ -354,7 +354,6 @@ set(VM_SOURCES_WKS
multicorejitplayer.cpp # Condition="'$(FeatureMulticoreJIT)' == 'true'
nativeeventsource.cpp
nativelibrary.cpp
- nativelibrarynative.cpp
olevariant.cpp
pendingload.cpp
pinvokeoverride.cpp
diff --git a/src/coreclr/vm/corelib.cpp b/src/coreclr/vm/corelib.cpp
index 9e89019b200780..676c266d3416a9 100644
--- a/src/coreclr/vm/corelib.cpp
+++ b/src/coreclr/vm/corelib.cpp
@@ -23,7 +23,6 @@
#include "clrconfignative.h"
#include "commodule.h"
#include "marshalnative.h"
-#include "nativelibrarynative.h"
#include "system.h"
#include "comutilnative.h"
#include "comsynchronizable.h"
diff --git a/src/coreclr/vm/corhost.cpp b/src/coreclr/vm/corhost.cpp
index 4f1c5afdd4bc1b..e625ae15369547 100644
--- a/src/coreclr/vm/corhost.cpp
+++ b/src/coreclr/vm/corhost.cpp
@@ -37,6 +37,9 @@
#endif // !TARGET_UNIX
#include "nativelibrary.h"
+#ifdef TARGET_UNIX
+#include "dlfcn.h"
+#endif
#ifndef DACCESS_COMPILE
@@ -644,7 +647,7 @@ HRESULT CorHost2::CreateAppDomainWithManager(
// Preload the libSystem.Native.so/dylib to detect possible problems with loading it early
EX_TRY
{
- NativeLibrary::LoadLibraryByName(W("libSystem.Native"), SystemDomain::SystemAssembly(), FALSE, 0, TRUE);
+ NativeLibrary::LoadFromAssemblyDirectory(W("libSystem.Native") PAL_SHLIB_SUFFIX_W, SystemDomain::SystemAssembly());
}
EX_HOOK
{
diff --git a/src/coreclr/vm/nativelibrary.cpp b/src/coreclr/vm/nativelibrary.cpp
index dec0e92964cd8f..3fe2b1f8c762d9 100644
--- a/src/coreclr/vm/nativelibrary.cpp
+++ b/src/coreclr/vm/nativelibrary.cpp
@@ -242,70 +242,6 @@ namespace
}
}
-// static
-NATIVE_LIBRARY_HANDLE NativeLibrary::LoadLibraryFromPath(LPCWSTR libraryPath, BOOL throwOnError)
-{
- CONTRACTL
- {
- STANDARD_VM_CHECK;
- PRECONDITION(CheckPointer(libraryPath));
- }
- CONTRACTL_END;
-
- LoadLibErrorTracker errorTracker;
- const NATIVE_LIBRARY_HANDLE hmod =
- LocalLoadLibraryHelper(libraryPath, GetLoadWithAlteredSearchPathFlag(), &errorTracker);
-
- if (throwOnError && (hmod == nullptr))
- {
- SString libraryPathSString(libraryPath);
- errorTracker.Throw(libraryPathSString);
- }
- return hmod;
-}
-
-// static
-void NativeLibrary::FreeNativeLibrary(NATIVE_LIBRARY_HANDLE handle)
-{
- STANDARD_VM_CONTRACT;
- _ASSERTE(handle != NULL);
-
-#ifndef TARGET_UNIX
- BOOL retVal = FreeLibrary(handle);
-#else // !TARGET_UNIX
- BOOL retVal = PAL_FreeLibraryDirect(handle);
-#endif // !TARGET_UNIX
-
- if (retVal == 0)
- COMPlusThrow(kInvalidOperationException, W("Arg_InvalidOperationException"));
-}
-
-//static
-INT_PTR NativeLibrary::GetNativeLibraryExport(NATIVE_LIBRARY_HANDLE handle, LPCWSTR symbolName, BOOL throwOnError)
-{
- CONTRACTL
- {
- STANDARD_VM_CHECK;
- PRECONDITION(CheckPointer(handle));
- PRECONDITION(CheckPointer(symbolName));
- }
- CONTRACTL_END;
-
- MAKE_UTF8PTR_FROMWIDE(lpstr, symbolName);
-
-#ifndef TARGET_UNIX
- INT_PTR address = reinterpret_cast(GetProcAddress((HMODULE)handle, lpstr));
- if ((address == 0) && throwOnError)
- COMPlusThrow(kEntryPointNotFoundException, IDS_EE_NDIRECT_GETPROCADDR_WIN_DLL, symbolName);
-#else // !TARGET_UNIX
- INT_PTR address = reinterpret_cast(PAL_GetProcAddressDirect(handle, lpstr));
- if ((address == 0) && throwOnError)
- COMPlusThrow(kEntryPointNotFoundException, IDS_EE_NDIRECT_GETPROCADDR_UNIX_SO, symbolName);
-#endif // !TARGET_UNIX
-
- return address;
-}
-
namespace
{
#ifndef TARGET_UNIX
@@ -771,9 +707,7 @@ namespace
}
// static
-NATIVE_LIBRARY_HANDLE NativeLibrary::LoadLibraryByName(LPCWSTR libraryName, Assembly *callingAssembly,
- BOOL hasDllImportSearchFlags, DWORD dllImportSearchFlags,
- BOOL throwOnError)
+NATIVE_LIBRARY_HANDLE NativeLibrary::LoadFromAssemblyDirectory(LPCWSTR libraryName, Assembly *callingAssembly)
{
CONTRACTL
{
@@ -785,43 +719,13 @@ NATIVE_LIBRARY_HANDLE NativeLibrary::LoadLibraryByName(LPCWSTR libraryName, Asse
NATIVE_LIBRARY_HANDLE hmod = nullptr;
- // Resolve using the AssemblyLoadContext.LoadUnmanagedDll implementation
- hmod = LoadNativeLibraryViaAssemblyLoadContext(callingAssembly, libraryName);
- if (hmod != nullptr)
- return hmod;
-
- // Check if a default dllImportSearchPathFlags was passed in. If so, use that value.
- // Otherwise, check if the assembly has the DefaultDllImportSearchPathsAttribute attribute.
- // If so, use that value.
- BOOL searchAssemblyDirectory;
- DWORD dllImportSearchPathFlags;
- if (hasDllImportSearchFlags)
- {
- dllImportSearchPathFlags = dllImportSearchFlags & ~DLLIMPORTSEARCHPATH_ASSEMBLYDIRECTORY;
- searchAssemblyDirectory = dllImportSearchFlags & DLLIMPORTSEARCHPATH_ASSEMBLYDIRECTORY;
-
- }
- else
- {
- hasDllImportSearchFlags = GetDllImportSearchPathFlags(callingAssembly->GetModule(),
- &dllImportSearchPathFlags, &searchAssemblyDirectory);
- }
-
LoadLibErrorTracker errorTracker;
- hmod = LoadNativeLibraryBySearch(callingAssembly, hasDllImportSearchFlags, searchAssemblyDirectory, dllImportSearchPathFlags, &errorTracker, libraryName);
- if (hmod != nullptr)
- return hmod;
-
- // Resolve using the AssemblyLoadContext.ResolvingUnmanagedDll event
- hmod = LoadNativeLibraryViaAssemblyLoadContextEvent(callingAssembly, libraryName);
+ hmod = LoadFromPInvokeAssemblyDirectory(callingAssembly, libraryName, 0, &errorTracker);
if (hmod != nullptr)
return hmod;
- if (throwOnError)
- {
- SString libraryPathSString(libraryName);
- errorTracker.Throw(libraryPathSString);
- }
+ SString libraryPathSString(libraryName);
+ errorTracker.Throw(libraryPathSString);
return hmod;
}
diff --git a/src/coreclr/vm/nativelibrary.h b/src/coreclr/vm/nativelibrary.h
index 0745a5a3e41b03..61ea651daec9ce 100644
--- a/src/coreclr/vm/nativelibrary.h
+++ b/src/coreclr/vm/nativelibrary.h
@@ -9,13 +9,7 @@
class NativeLibrary
{
public:
- static NATIVE_LIBRARY_HANDLE LoadLibraryFromPath(LPCWSTR libraryPath, BOOL throwOnError);
- static NATIVE_LIBRARY_HANDLE LoadLibraryByName(LPCWSTR name, Assembly *callingAssembly,
- BOOL hasDllImportSearchPathFlags, DWORD dllImportSearchPathFlags,
- BOOL throwOnError);
- static void FreeNativeLibrary(NATIVE_LIBRARY_HANDLE handle);
- static INT_PTR GetNativeLibraryExport(NATIVE_LIBRARY_HANDLE handle, LPCWSTR symbolName, BOOL throwOnError);
-
+ static NATIVE_LIBRARY_HANDLE LoadFromAssemblyDirectory(LPCWSTR libraryName, Assembly *callingAssembly);
static NATIVE_LIBRARY_HANDLE LoadLibraryFromMethodDesc(PInvokeMethodDesc *pMD);
};
diff --git a/src/coreclr/vm/nativelibrarynative.cpp b/src/coreclr/vm/nativelibrarynative.cpp
deleted file mode 100644
index 780871eff3f725..00000000000000
--- a/src/coreclr/vm/nativelibrarynative.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-//
-// File: NativeLibraryNative.cpp
-//
-
-#include "common.h"
-#include "nativelibrary.h"
-#include "nativelibrarynative.h"
-
-// static
-extern "C" INT_PTR QCALLTYPE NativeLibrary_LoadFromPath(LPCWSTR path, BOOL throwOnError)
-{
- QCALL_CONTRACT;
-
- NATIVE_LIBRARY_HANDLE handle = nullptr;
-
- BEGIN_QCALL;
-
- handle = NativeLibrary::LoadLibraryFromPath(path, throwOnError);
-
- END_QCALL;
-
- return reinterpret_cast(handle);
-}
-
-// static
-extern "C" INT_PTR QCALLTYPE NativeLibrary_LoadByName(LPCWSTR name, QCall::AssemblyHandle callingAssembly,
- BOOL hasDllImportSearchPathFlag, DWORD dllImportSearchPathFlag,
- BOOL throwOnError)
-{
- QCALL_CONTRACT;
-
- NATIVE_LIBRARY_HANDLE handle = nullptr;
-
- BEGIN_QCALL;
-
- handle = NativeLibrary::LoadLibraryByName(name, callingAssembly, hasDllImportSearchPathFlag, dllImportSearchPathFlag, throwOnError);
-
- END_QCALL;
-
- return reinterpret_cast(handle);
-}
-
-// static
-extern "C" void QCALLTYPE NativeLibrary_FreeLib(INT_PTR handle)
-{
- QCALL_CONTRACT;
-
- BEGIN_QCALL;
-
- NativeLibrary::FreeNativeLibrary((NATIVE_LIBRARY_HANDLE) handle);
-
- END_QCALL;
-}
-
-//static
-extern "C" INT_PTR QCALLTYPE NativeLibrary_GetSymbol(INT_PTR handle, LPCWSTR symbolName, BOOL throwOnError)
-{
- QCALL_CONTRACT;
-
- INT_PTR address = 0;
-
- BEGIN_QCALL;
-
- address = NativeLibrary::GetNativeLibraryExport((NATIVE_LIBRARY_HANDLE)handle, symbolName, throwOnError);
-
- END_QCALL;
-
- return address;
-}
diff --git a/src/coreclr/vm/nativelibrarynative.h b/src/coreclr/vm/nativelibrarynative.h
deleted file mode 100644
index 6ace9ae0be58b3..00000000000000
--- a/src/coreclr/vm/nativelibrarynative.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-//
-// File: NativeLibraryNative.h
-//
-//
-// QCall's for the NativeLibrary class
-//
-
-#ifndef __NATIVELIBRARYNATIVE_H__
-#define __NATIVELIBRARYNATIVE_H__
-
-extern "C" INT_PTR QCALLTYPE NativeLibrary_LoadFromPath(LPCWSTR path, BOOL throwOnError);
-extern "C" INT_PTR QCALLTYPE NativeLibrary_LoadByName(LPCWSTR name, QCall::AssemblyHandle callingAssembly,
- BOOL hasDllImportSearchPathFlag, DWORD dllImportSearchPathFlag,
- BOOL throwOnError);
-extern "C" void QCALLTYPE NativeLibrary_FreeLib(INT_PTR handle);
-extern "C" INT_PTR QCALLTYPE NativeLibrary_GetSymbol(INT_PTR handle, LPCWSTR symbolName, BOOL throwOnError);
-
-#endif // __NATIVELIBRARYNATIVE_H__
diff --git a/src/coreclr/vm/qcallentrypoints.cpp b/src/coreclr/vm/qcallentrypoints.cpp
index 11e57f6663e15c..f801ab33053ef9 100644
--- a/src/coreclr/vm/qcallentrypoints.cpp
+++ b/src/coreclr/vm/qcallentrypoints.cpp
@@ -18,7 +18,6 @@
#include "clrconfignative.h"
#include "commodule.h"
#include "marshalnative.h"
-#include "nativelibrarynative.h"
#include "system.h"
#include "comutilnative.h"
#include "comsynchronizable.h"
@@ -393,10 +392,6 @@ static const Entry s_QCall[] =
DllImportEntry(MngdSafeArrayMarshaler_ClearNative)
DllImportEntry(Variant_ConvertValueTypeToRecord)
#endif // FEATURE_COMINTEROP
- DllImportEntry(NativeLibrary_LoadFromPath)
- DllImportEntry(NativeLibrary_LoadByName)
- DllImportEntry(NativeLibrary_FreeLib)
- DllImportEntry(NativeLibrary_GetSymbol)
DllImportEntry(GetTypeLoadExceptionMessage)
DllImportEntry(GetFileLoadExceptionMessage)
DllImportEntry(FileLoadException_GetMessageForHR)
diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadErrorMode.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadErrorMode.cs
index c27e92419943dd..416e7b84c4be2d 100644
--- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadErrorMode.cs
+++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadErrorMode.cs
@@ -15,6 +15,5 @@ internal static partial bool SetThreadErrorMode(
out uint lpOldMode);
internal const int SEM_FAILCRITICALERRORS = 0x00000001;
- internal const int SEM_NOOPENFILEERRORBOX = 0x00008000;
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
index 3383f70a0b4e64..77248567b357b9 100644
--- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
+++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
@@ -1825,6 +1825,9 @@
Common\Interop\Windows\Kernel32\Interop.DeviceIoControl.cs
+
+ Common\Interop\Windows\Kernel32\Interop.DynamicLoad.cs
+
Common\Interop\Windows\Kernel32\Interop.ExpandEnvironmentStrings.cs
@@ -2274,6 +2277,7 @@
+
@@ -2617,6 +2621,7 @@
+
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.Unix.cs
similarity index 93%
rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.Unix.cs
rename to src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.Unix.cs
index 6ef45a24750955..d9e460692dd316 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.Unix.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.Unix.cs
@@ -15,7 +15,7 @@ private static IntPtr LoadLibraryHelper(string libraryName, int _ /*flags*/, ref
if (ret == IntPtr.Zero)
{
string? message = Marshal.PtrToStringUTF8(Interop.Sys.GetLoadLibraryError());
- errorTracker.TrackErrorMessage(message);
+ errorTracker.TrackErrorMessage(message ?? string.Empty);
}
return ret;
@@ -46,7 +46,7 @@ public void Throw(string libraryName)
#endif
}
- public void TrackErrorMessage(string? message)
+ public void TrackErrorMessage(string message)
{
_errorMessage ??= Environment.NewLine;
if (!_errorMessage.Contains(message))
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.Windows.cs
similarity index 77%
rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.Windows.cs
rename to src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.Windows.cs
index bac99a01ed35df..73ab588fdd9128 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.Windows.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.Windows.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
+using System.IO;
namespace System.Runtime.InteropServices
{
@@ -13,37 +14,32 @@ private static IntPtr LoadLibraryHelper(string libraryName, int flags, ref LoadL
{
IntPtr hmod;
- // Disable the OS dialogs when failing to load. This matches CoreCLR.
- uint prev;
- bool set = Interop.Kernel32.SetThreadErrorMode(Interop.Kernel32.SEM_FAILCRITICALERRORS | Interop.Kernel32.SEM_NOOPENFILEERRORBOX, out prev);
- if (((uint)flags & 0xFFFFFF00) != 0)
+ // Disable the OS dialogs when failing to load.
+ using (DisableMediaInsertionPrompt.Create())
{
- hmod = Interop.Kernel32.LoadLibraryEx(libraryName, IntPtr.Zero, (int)((uint)flags & 0xFFFFFF00));
- if (hmod != IntPtr.Zero)
+ if (((uint)flags & 0xFFFFFF00) != 0)
{
- goto exit;
+ hmod = Interop.Kernel32.LoadLibraryEx(libraryName, IntPtr.Zero, (int)((uint)flags & 0xFFFFFF00));
+ if (hmod != IntPtr.Zero)
+ {
+ return hmod;
+ }
+
+ int lastError = Marshal.GetLastPInvokeError();
+ if (lastError != Interop.Errors.ERROR_INVALID_PARAMETER)
+ {
+ errorTracker.TrackErrorCode(lastError);
+ return hmod;
+ }
}
- int lastError = Marshal.GetLastPInvokeError();
- if (lastError != Interop.Errors.ERROR_INVALID_PARAMETER)
+ hmod = Interop.Kernel32.LoadLibraryEx(libraryName, IntPtr.Zero, flags & 0xFF);
+ if (hmod == IntPtr.Zero)
{
- errorTracker.TrackErrorCode(lastError);
- goto exit;
+ errorTracker.TrackErrorCode(Marshal.GetLastPInvokeError());
}
}
- hmod = Interop.Kernel32.LoadLibraryEx(libraryName, IntPtr.Zero, flags & 0xFF);
- if (hmod == IntPtr.Zero)
- {
- errorTracker.TrackErrorCode(Marshal.GetLastPInvokeError());
- }
-
- exit:
- if (set)
- {
- Interop.Kernel32.SetThreadErrorMode(prev, out _);
- }
-
return hmod;
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.cs
index 41321edd86325c..d1e09384e0f0bd 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.cs
@@ -2,8 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.ComponentModel;
+using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
+using System.Runtime.Loader;
using System.Threading;
namespace System.Runtime.InteropServices
@@ -131,6 +133,20 @@ public static bool TryLoad(string libraryName, Assembly assembly, DllImportSearc
return handle != IntPtr.Zero;
}
+#if !MONO
+ // Not a public API. We expose this so that it's possible to bypass the codepath that tries to read search path
+ // from custom attributes.
+ internal static bool TryLoad(string libraryName, Assembly assembly, DllImportSearchPath searchPath, out IntPtr handle)
+ {
+ handle = LoadLibraryByName(libraryName,
+ assembly,
+ userSpecifiedSearchFlags: true,
+ searchPath,
+ throwOnError: false);
+ return handle != IntPtr.Zero;
+ }
+#endif
+
///
/// Free a loaded library
/// Given a library handle, free it.
@@ -264,5 +280,181 @@ public static IntPtr GetMainProgramHandle()
}
return result;
}
+
+#if !MONO
+ internal static IntPtr LoadLibraryByName(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, bool throwOnError)
+ {
+#if !NATIVEAOT
+ // Resolve using the AssemblyLoadContext.LoadUnmanagedDll implementation
+ IntPtr mod = LoadNativeLibraryViaAssemblyLoadContext(assembly, libraryName);
+ if (mod != IntPtr.Zero)
+ return mod;
+#endif
+
+ // First checks if a default dllImportSearchPathFlags was passed in, if so, use that value.
+ // Otherwise checks if the assembly has the DefaultDllImportSearchPathsAttribute attribute.
+ // If so, use that value.
+ bool userSpecifiedSearchFlags = searchPath.HasValue;
+ if (!userSpecifiedSearchFlags)
+ {
+ searchPath = GetDllImportSearchPath(assembly, out userSpecifiedSearchFlags);
+ }
+ return LoadLibraryByName(libraryName, assembly, userSpecifiedSearchFlags, searchPath!.Value, throwOnError);
+ }
+
+ private static IntPtr LoadLibraryByName(string libraryName, Assembly assembly, bool userSpecifiedSearchFlags, DllImportSearchPath searchPath, bool throwOnError)
+ {
+ int searchPathFlags = (int)(searchPath & ~DllImportSearchPath.AssemblyDirectory);
+ bool searchAssemblyDirectory = (searchPath & DllImportSearchPath.AssemblyDirectory) != 0;
+
+ LoadLibErrorTracker errorTracker = default;
+ IntPtr ret = LoadBySearch(assembly, userSpecifiedSearchFlags, searchAssemblyDirectory, searchPathFlags, ref errorTracker, libraryName);
+
+ // Resolve using the AssemblyLoadContext.ResolvingUnmanagedDll event
+ if (ret == IntPtr.Zero)
+ {
+ ret = LoadNativeLibraryViaAssemblyLoadContextEvent(assembly, libraryName);
+ }
+
+ if (throwOnError && ret == IntPtr.Zero)
+ {
+ errorTracker.Throw(libraryName);
+ }
+
+ return ret;
+ }
+
+#if !NATIVEAOT
+ private static IntPtr LoadNativeLibraryViaAssemblyLoadContext(Assembly callingAssembly, string libraryName)
+ {
+#if TARGET_WINDOWS
+ // This is replicating quick check from the OS implementation of api sets.
+ if (libraryName.StartsWithOrdinalIgnoreCase("api-") ||
+ libraryName.StartsWithOrdinalIgnoreCase("ext-"))
+ {
+ // Prevent Overriding of Windows API sets.
+ return IntPtr.Zero;
+ }
+#endif
+ AssemblyLoadContext? alc = AssemblyLoadContext.GetLoadContext(callingAssembly);
+ if (alc is null || alc == AssemblyLoadContext.Default)
+ {
+ // For assemblies bound via default binder, we should use the standard mechanism to make the pinvoke call.
+ return IntPtr.Zero;
+ }
+
+ // Call System.Runtime.Loader.AssemblyLoadContext.LoadUnmanagedDll to give
+ // The custom assembly context a chance to load the unmanaged dll.
+ return alc.InvokeLoadUnmanagedDll(libraryName);
+ }
+#endif
+
+ private static IntPtr LoadNativeLibraryViaAssemblyLoadContextEvent(Assembly callingAssembly, string libraryName)
+ {
+ AssemblyLoadContext? alc = AssemblyLoadContext.GetLoadContext(callingAssembly);
+ return alc?.GetResolvedUnmanagedDll(callingAssembly, libraryName) ?? IntPtr.Zero;
+ }
+
+ private static DllImportSearchPath GetDllImportSearchPath(Assembly callingAssembly, out bool userSpecifiedSearchFlags)
+ {
+ foreach (CustomAttributeData cad in callingAssembly.CustomAttributes)
+ {
+ if (cad.AttributeType == typeof(DefaultDllImportSearchPathsAttribute))
+ {
+ userSpecifiedSearchFlags = true;
+ return (DllImportSearchPath)cad.ConstructorArguments[0].Value!;
+ }
+ }
+
+ userSpecifiedSearchFlags = false;
+ return DllImportSearchPath.AssemblyDirectory;
+ }
+
+ internal static IntPtr LoadBySearch(Assembly callingAssembly, bool userSpecifiedSearchFlags, bool searchAssemblyDirectory, int dllImportSearchPathFlags, ref LoadLibErrorTracker errorTracker, string libraryName)
+ {
+ IntPtr ret;
+
+ int loadWithAlteredPathFlags = LoadWithAlteredSearchPathFlag;
+ const int loadLibrarySearchFlags = (int)DllImportSearchPath.UseDllDirectoryForDependencies
+ | (int)DllImportSearchPath.ApplicationDirectory
+ | (int)DllImportSearchPath.UserDirectories
+ | (int)DllImportSearchPath.System32
+ | (int)DllImportSearchPath.SafeDirectories;
+ bool libNameIsRelativePath = !Path.IsPathFullyQualified(libraryName);
+
+ // P/Invokes are often declared with variations on the actual library name.
+ // For example, it's common to leave off the extension/suffix of the library
+ // even if it has one, or to leave off a prefix like "lib" even if it has one
+ // (both of these are typically done to smooth over cross-platform differences).
+ // We try to dlopen with such variations on the original.
+ foreach (LibraryNameVariation libraryNameVariation in LibraryNameVariation.DetermineLibraryNameVariations(libraryName, libNameIsRelativePath))
+ {
+ string currLibNameVariation = libraryNameVariation.Prefix + libraryName + libraryNameVariation.Suffix;
+
+ if (!libNameIsRelativePath)
+ {
+ // LOAD_WITH_ALTERED_SEARCH_PATH is incompatible with LOAD_LIBRARY_SEARCH flags. Remove those flags if they are set.
+ int flags = loadWithAlteredPathFlags | (dllImportSearchPathFlags & ~loadLibrarySearchFlags);
+ ret = LoadLibraryHelper(currLibNameVariation, flags, ref errorTracker);
+ if (ret != IntPtr.Zero)
+ {
+ return ret;
+ }
+ }
+ else if ((callingAssembly != null) && searchAssemblyDirectory)
+ {
+ // LOAD_WITH_ALTERED_SEARCH_PATH is incompatible with LOAD_LIBRARY_SEARCH flags. Remove those flags if they are set.
+ int flags = loadWithAlteredPathFlags | (dllImportSearchPathFlags & ~loadLibrarySearchFlags);
+
+ // Try to load the module alongside the assembly where the PInvoke was declared.
+ // For PInvokes where the DllImportSearchPath.AssemblyDirectory is specified, look next to the application.
+ ret = LoadLibraryHelper(Path.Combine(AppContext.BaseDirectory, currLibNameVariation), flags, ref errorTracker);
+ if (ret != IntPtr.Zero)
+ {
+ return ret;
+ }
+ }
+
+ // Internally, search path flags and whether or not to search the assembly directory are
+ // tracked separately. However, on the API level, DllImportSearchPath represents them both.
+ // When unspecified, the default is to search the assembly directory and all OS defaults,
+ // which maps to searchAssemblyDirectory being true and dllImportSearchPathFlags being 0.
+ // When a user specifies DllImportSearchPath.AssemblyDirectory, searchAssemblyDirectory is
+ // true, dllImportSearchPathFlags is 0, and the desired logic is to only search the assembly
+ // directory (handled above), so we avoid doing any additional load search in that case.
+ if (!userSpecifiedSearchFlags || !searchAssemblyDirectory || dllImportSearchPathFlags != 0)
+ {
+ ret = LoadLibraryHelper(currLibNameVariation, dllImportSearchPathFlags, ref errorTracker);
+ if (ret != IntPtr.Zero)
+ {
+ return ret;
+ }
+ }
+ }
+
+ return IntPtr.Zero;
+ }
+
+ private static IntPtr LoadFromPath(string libraryName, bool throwOnError)
+ {
+ LoadLibErrorTracker errorTracker = default;
+ IntPtr ret = LoadLibraryHelper(libraryName, LoadWithAlteredSearchPathFlag, ref errorTracker);
+ if (throwOnError && ret == IntPtr.Zero)
+ {
+ errorTracker.Throw(libraryName);
+ }
+
+ return ret;
+ }
+
+ private static unsafe IntPtr GetSymbol(IntPtr handle, string symbolName, bool throwOnError)
+ {
+ IntPtr ret = GetSymbolOrNull(handle, symbolName);
+ if (throwOnError && ret == IntPtr.Zero)
+ throw new EntryPointNotFoundException(SR.Format(SR.Arg_EntryPointNotFoundExceptionParameterizedNoLibrary, symbolName));
+
+ return ret;
+ }
+#endif
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs
index 7816d79a680d6d..79669280df61c7 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs
@@ -789,6 +789,11 @@ internal static void InvokeAssemblyLoadEvent(Assembly assembly)
return asm;
}
+ internal IntPtr InvokeLoadUnmanagedDll(string unmanagedDllName)
+ {
+ return LoadUnmanagedDll(unmanagedDllName);
+ }
+
internal IntPtr GetResolvedUnmanagedDll(Assembly assembly, string unmanagedDllName)
{
// Loop through the event subscribers and return the first non-null native library handle