summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSwaroop Sridhar <Swaroop.Sridhar@microsoft.com>2019-01-18 09:24:41 -0800
committerGitHub <noreply@github.com>2019-01-18 09:24:41 -0800
commit732f892665343e84d04eea4478eccb459b385f55 (patch)
treea76fa9e8df71b776e414a0e73079974cf849d02b /src
parentec53bfdc54cf1b79730561c4a7f3c744090a400c (diff)
downloadcoreclr-732f892665343e84d04eea4478eccb459b385f55.tar.gz
coreclr-732f892665343e84d04eea4478eccb459b385f55.tar.bz2
coreclr-732f892665343e84d04eea4478eccb459b385f55.zip
Add Per-assembly Load Native Library callbacks (#21555)
Add Per-assembly Load Native Library callbacks This Change implements the Native Library resolution Call-backs proposed in https://github.com/dotnet/corefx/issues/32015
Diffstat (limited to 'src')
-rw-r--r--src/System.Private.CoreLib/Resources/Strings.resx5
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.cs91
-rw-r--r--src/vm/callhelpers.h1
-rw-r--r--src/vm/dllimport.cpp203
-rw-r--r--src/vm/dllimport.h9
-rw-r--r--src/vm/interoputil.cpp8
-rw-r--r--src/vm/interoputil.h6
-rw-r--r--src/vm/metasig.h1
-rw-r--r--src/vm/mscorlib.h2
9 files changed, 256 insertions, 70 deletions
diff --git a/src/System.Private.CoreLib/Resources/Strings.resx b/src/System.Private.CoreLib/Resources/Strings.resx
index 906ca365ea..c89f9428b4 100644
--- a/src/System.Private.CoreLib/Resources/Strings.resx
+++ b/src/System.Private.CoreLib/Resources/Strings.resx
@@ -2428,7 +2428,10 @@
<data name="InvalidOperation_CannotImportGlobalFromDifferentModule" xml:space="preserve">
<value>Unable to import a global method or field from a different module.</value>
</data>
- <data name="InvalidOperation_CannotRemoveLastFromEmptyCollection" xml:space="preserve">
+ <data name="InvalidOperation_CannotRegisterSecondResolver" xml:space="preserve">
+ <value>A resolver is already set for the assembly.</value>
+ </data>
+ <data name="InvalidOperation_CannotRemoveLastFromEmptyCollection" xml:space="preserve">
<value>Cannot remove the last element from an empty collection.</value>
</data>
<data name="InvalidOperation_CannotRestoreUnsupressedFlow" xml:space="preserve">
diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.cs
index 38712ac1b7..00b78d5c2c 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.cs
+++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.cs
@@ -9,10 +9,26 @@ using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using Win32Native = Microsoft.Win32.Win32Native;
using System.Diagnostics;
+using System.Threading;
namespace System.Runtime.InteropServices
{
/// <summary>
+ /// A delegate used to resolve native libraries via callback.
+ /// </summary>
+ /// <param name="libraryName">The native library to resolve</param>
+ /// <param name="assembly">The assembly requesting the resolution</param>
+ /// <param name="searchPath">
+ /// The DllImportSearchPathsAttribute on the PInvoke, if any.
+ /// Otherwise, the DllImportSearchPathsAttribute on the assembly, if any.
+ /// Otherwise null.
+ /// </param>
+ /// <returns>The handle for the loaded native library on success, null on failure</returns>
+ public delegate IntPtr DllImportResolver(string libraryName,
+ Assembly assembly,
+ DllImportSearchPath? searchPath);
+
+ /// <summary>
/// APIs for managing Native Libraries
/// </summary>
public static partial class NativeLibrary
@@ -58,7 +74,9 @@ namespace System.Runtime.InteropServices
/// Otherwise, the flags specified by the DefaultDllImportSearchPaths attribute on the
/// calling assembly (if any) are used.
/// This LoadLibrary() method does not invoke the managed call-backs for native library resolution:
+ /// * The per-assembly registered callback
/// * AssemblyLoadContext.LoadUnmanagedDll()
+ /// * AssemblyLoadContext.ResolvingUnmanagedDllEvent
/// </summary>
/// <param name="libraryName">The name of the native library to be loaded</param>
/// <param name="assembly">The assembly loading the native library</param>
@@ -117,7 +135,6 @@ namespace System.Runtime.InteropServices
/// No action if the input handle is null.
/// </summary>
/// <param name="handle">The native library handle to be freed</param>
- /// <exception cref="System.InvalidOperationException">If the operation fails</exception>
public static void Free(IntPtr handle)
{
FreeLib(handle);
@@ -161,6 +178,78 @@ namespace System.Runtime.InteropServices
return address != IntPtr.Zero;
}
+ /// <summary>
+ /// Map from assembly to native-library resolver.
+ /// Interop specific fields and properties are generally not added to Assembly class.
+ /// Therefore, this table uses weak assembly pointers to indirectly achieve
+ /// similar behavior.
+ /// </summary>
+ private static ConditionalWeakTable<Assembly, DllImportResolver> s_nativeDllResolveMap = null;
+
+ /// <summary>
+ /// Set a callback for resolving native library imports from an assembly.
+ /// This per-assembly resolver is the first attempt to resolve native library loads
+ /// initiated by this assembly.
+ ///
+ /// Only one resolver can be registered per assembly.
+ /// Trying to register a second resolver fails with InvalidOperationException.
+ /// </summary>
+ /// <param name="assembly">The assembly for which the resolver is registered</param>
+ /// <param name="resolver">The resolver callback to register</param>
+ /// <exception cref="System.ArgumentNullException">If assembly or resolver is null</exception>
+ /// <exception cref="System.ArgumentException">If a resolver is already set for this assembly</exception>
+ public static void SetDllImportResolver(Assembly assembly, DllImportResolver resolver)
+ {
+ if (assembly == null)
+ throw new ArgumentNullException(nameof(assembly));
+ if (resolver == null)
+ throw new ArgumentNullException(nameof(resolver));
+ if (!(assembly is RuntimeAssembly))
+ throw new ArgumentException(SR.Argument_MustBeRuntimeAssembly);
+
+ if (s_nativeDllResolveMap == null)
+ {
+ Interlocked.CompareExchange(ref s_nativeDllResolveMap,
+ new ConditionalWeakTable<Assembly, DllImportResolver>(), null);
+ }
+
+ try
+ {
+ s_nativeDllResolveMap.Add(assembly, resolver);
+ }
+ catch (ArgumentException)
+ {
+ // ConditionalWealTable throws ArgumentException if the Key already exists
+ throw new InvalidOperationException(SR.InvalidOperation_CannotRegisterSecondResolver);
+ }
+ }
+
+ /// <summary>
+ /// The helper function that calls the per-assembly native-library resolver
+ /// if one is registered for this assembly.
+ /// </summary>
+ /// <param name="libraryName">The native library to load</param>
+ /// <param name="assembly">The assembly trying load the native library</param>
+ /// <param name="hasDllImportSearchPathFlags">If the pInvoke has DefaultDllImportSearchPathAttribute</param>
+ /// <param name="dllImportSearchPathFlags">If hasdllImportSearchPathFlags is true, the flags in
+ /// DefaultDllImportSearchPathAttribute; meaningless otherwise </param>
+ /// <returns>The handle for the loaded library on success. Null on failure.</returns>
+ internal static IntPtr LoadLibraryCallbackStub(string libraryName, Assembly assembly,
+ bool hasDllImportSearchPathFlags, uint dllImportSearchPathFlags)
+ {
+ if (s_nativeDllResolveMap == null)
+ {
+ return IntPtr.Zero;
+ }
+
+ if (!s_nativeDllResolveMap.TryGetValue(assembly, out DllImportResolver resolver))
+ {
+ return IntPtr.Zero;
+ }
+
+ return resolver(libraryName, assembly, hasDllImportSearchPathFlags ? (DllImportSearchPath?)dllImportSearchPathFlags : null);
+ }
+
/// External functions that implement the NativeLibrary interface
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
diff --git a/src/vm/callhelpers.h b/src/vm/callhelpers.h
index bcd553dcc8..032cec43ce 100644
--- a/src/vm/callhelpers.h
+++ b/src/vm/callhelpers.h
@@ -566,6 +566,7 @@ enum DispatchCallSimpleFlags
#define STRINGREF_TO_ARGHOLDER(x) (LPVOID)STRINGREFToObject(x)
#define PTR_TO_ARGHOLDER(x) (LPVOID)x
#define DWORD_TO_ARGHOLDER(x) (LPVOID)(SIZE_T)x
+#define BOOL_TO_ARGHOLDER(x) DWORD_TO_ARGHOLDER(!!(x))
#define INIT_VARIABLES(count) \
DWORD __numArgs = count; \
diff --git a/src/vm/dllimport.cpp b/src/vm/dllimport.cpp
index 37cfda9775..18e77d8490 100644
--- a/src/vm/dllimport.cpp
+++ b/src/vm/dllimport.cpp
@@ -51,11 +51,6 @@
#include "clr/fs/path.h"
using namespace clr::fs;
-// The Bit 0x2 has different semantics in DllImportSearchPath and LoadLibraryExA flags.
-// In DllImportSearchPath enum, bit 0x2 represents SearchAssemblyDirectory -- which is performed by CLR.
-// Unlike other bits in this enum, this bit shouldn't be directly passed on to LoadLibrary()
-#define DLLIMPORTSEARCHPATH_ASSEMBLYDIRECTORY 0x2
-
// remove when we get an updated SDK
#define LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR 0x00000100
#define LOAD_LIBRARY_SEARCH_DEFAULT_DIRS 0x00001000
@@ -6127,6 +6122,57 @@ bool NDirect::s_fSecureLoadLibrarySupported = false;
#define PLATFORM_SHARED_LIB_PREFIX_W W("")
#endif // !FEATURE_PAL
+// The Bit 0x2 has different semantics in DllImportSearchPath and LoadLibraryExA flags.
+// In DllImportSearchPath enum, bit 0x2 represents SearchAssemblyDirectory -- which is performed by CLR.
+// Unlike other bits in this enum, this bit shouldn't be directly passed on to LoadLibrary()
+#define DLLIMPORTSEARCHPATH_ASSEMBLYDIRECTORY 0x2
+
+// DllImportSearchPathFlags is a special enumeration, whose values are tied closely with LoadLibrary flags.
+// There is no "default" value DllImportSearchPathFlags. In the absence of DllImportSearchPath attribute,
+// CoreCLR's LoadLibrary implementation uses the following defaults.
+// Other implementations of LoadLibrary callbacks/events are free to use other default conventions.
+void GetDefaultDllImportSearchPathFlags(DWORD *dllImportSearchPathFlags, BOOL *searchAssemblyDirectory)
+{
+ STANDARD_VM_CONTRACT;
+
+ *searchAssemblyDirectory = TRUE;
+ *dllImportSearchPathFlags = 0;
+}
+
+// If a module has the DefaultDllImportSearchPathsAttribute, get DllImportSearchPathFlags from it, and return true.
+// Otherwise, get CoreCLR's default value for DllImportSearchPathFlags, and return false.
+BOOL GetDllImportSearchPathFlags(Module *pModule, DWORD *dllImportSearchPathFlags, BOOL *searchAssemblyDirectory)
+{
+ STANDARD_VM_CONTRACT;
+
+ if (pModule->HasDefaultDllImportSearchPathsAttribute())
+ {
+ *dllImportSearchPathFlags = pModule->DefaultDllImportSearchPathsAttributeCachedValue();
+ *searchAssemblyDirectory = pModule->DllImportSearchAssemblyDirectory();
+ return TRUE;
+ }
+
+ GetDefaultDllImportSearchPathFlags(dllImportSearchPathFlags, searchAssemblyDirectory);
+ return FALSE;
+}
+
+// If a pInvoke has the DefaultDllImportSearchPathsAttribute, get DllImportSearchPathFlags from it, and returns true.
+// Otherwise, if the containing assembly has the DefaultDllImportSearchPathsAttribute, get DllImportSearchPathFlags from it, and returns true.
+// Otherwise, get CoreCLR's default value for DllImportSearchPathFlags, and return false.
+BOOL GetDllImportSearchPathFlags(NDirectMethodDesc * pMD, DWORD *dllImportSearchPathFlags, BOOL *searchAssemblyDirectory)
+{
+ STANDARD_VM_CONTRACT;
+
+ if (pMD->HasDefaultDllImportSearchPathsAttribute())
+ {
+ *dllImportSearchPathFlags = pMD->DefaultDllImportSearchPathsAttributeCachedValue();
+ *searchAssemblyDirectory = pMD->DllImportSearchAssemblyDirectory();
+ return TRUE;
+ }
+
+ return GetDllImportSearchPathFlags(pMD->GetModule(), dllImportSearchPathFlags, searchAssemblyDirectory);
+}
+
// static
NATIVE_LIBRARY_HANDLE NDirect::LoadLibraryFromPath(LPCWSTR libraryPath, BOOL throwOnError)
{
@@ -6151,7 +6197,7 @@ NATIVE_LIBRARY_HANDLE NDirect::LoadLibraryFromPath(LPCWSTR libraryPath, BOOL thr
// static
NATIVE_LIBRARY_HANDLE NDirect::LoadLibraryByName(LPCWSTR libraryName, Assembly *callingAssembly,
- BOOL hasDllImportSearchFlag, DWORD dllImportSearchFlag,
+ BOOL hasDllImportSearchFlags, DWORD dllImportSearchFlags,
BOOL throwOnError)
{
CONTRACTL
@@ -6164,30 +6210,26 @@ NATIVE_LIBRARY_HANDLE NDirect::LoadLibraryByName(LPCWSTR libraryName, Assembly *
LoadLibErrorTracker errorTracker;
- // First checks if a default DllImportSearchPathFlag was passed in, if so, use that value.
- // Otherwise checks if the assembly has the DefaultDllImportSearchPathsAttribute attribute. If so, use that value.
- BOOL searchAssemblyDirectory = TRUE;
- DWORD dllImportSearchPathFlag = 0;
+ // 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 searchAssemblyDirectory;
+ DWORD dllImportSearchPathFlags;
- if (hasDllImportSearchFlag)
+ if (hasDllImportSearchFlags)
{
- dllImportSearchPathFlag = dllImportSearchFlag & ~DLLIMPORTSEARCHPATH_ASSEMBLYDIRECTORY;
- searchAssemblyDirectory = dllImportSearchFlag & DLLIMPORTSEARCHPATH_ASSEMBLYDIRECTORY;
+ dllImportSearchPathFlags = dllImportSearchFlags & ~DLLIMPORTSEARCHPATH_ASSEMBLYDIRECTORY;
+ searchAssemblyDirectory = dllImportSearchFlags & DLLIMPORTSEARCHPATH_ASSEMBLYDIRECTORY;
}
- else
+ else
{
- Module * pModule = callingAssembly->GetManifestModule();
-
- if (pModule->HasDefaultDllImportSearchPathsAttribute())
- {
- dllImportSearchPathFlag = pModule->DefaultDllImportSearchPathsAttributeCachedValue();
- searchAssemblyDirectory = pModule->DllImportSearchAssemblyDirectory();
- }
+ GetDllImportSearchPathFlags(callingAssembly->GetManifestModule(),
+ &dllImportSearchPathFlags, &searchAssemblyDirectory);
}
NATIVE_LIBRARY_HANDLE hmod =
- LoadLibraryModuleBySearch(callingAssembly, searchAssemblyDirectory, dllImportSearchPathFlag, &errorTracker, libraryName);
+ LoadLibraryModuleBySearch(callingAssembly, searchAssemblyDirectory, dllImportSearchPathFlags, &errorTracker, libraryName);
if (throwOnError && (hmod == nullptr))
{
@@ -6203,29 +6245,13 @@ NATIVE_LIBRARY_HANDLE NDirect::LoadLibraryModuleBySearch(NDirectMethodDesc * pMD
{
STANDARD_VM_CONTRACT;
- // First checks if the method has DefaultDllImportSearchPathsAttribute. If so, use that value.
- // Otherwise checks if the assembly has the attribute. If so, use that value.
- BOOL searchAssemblyDirectory = TRUE;
- DWORD dllImportSearchPathFlag = 0;
+ BOOL searchAssemblyDirectory;
+ DWORD dllImportSearchPathFlags;
- if (pMD->HasDefaultDllImportSearchPathsAttribute())
- {
- dllImportSearchPathFlag = pMD->DefaultDllImportSearchPathsAttributeCachedValue();
- searchAssemblyDirectory = pMD->DllImportSearchAssemblyDirectory();
- }
- else
- {
- Module * pModule = pMD->GetModule();
-
- if (pModule->HasDefaultDllImportSearchPathsAttribute())
- {
- dllImportSearchPathFlag = pModule->DefaultDllImportSearchPathsAttributeCachedValue();
- searchAssemblyDirectory = pModule->DllImportSearchAssemblyDirectory();
- }
- }
+ GetDllImportSearchPathFlags(pMD, &dllImportSearchPathFlags, &searchAssemblyDirectory);
Assembly* pAssembly = pMD->GetMethodTable()->GetAssembly();
- return LoadLibraryModuleBySearch(pAssembly, searchAssemblyDirectory, dllImportSearchPathFlag, pErrorTracker, wszLibName);
+ return LoadLibraryModuleBySearch(pAssembly, searchAssemblyDirectory, dllImportSearchPathFlags, pErrorTracker, wszLibName);
}
// static
@@ -6274,6 +6300,17 @@ INT_PTR NDirect::GetNativeLibraryExport(NATIVE_LIBRARY_HANDLE handle, LPCWSTR sy
return address;
}
+#ifndef PLATFORM_UNIX
+BOOL IsWindowsAPISet(PCWSTR wszLibName)
+{
+ STANDARD_VM_CONTRACT;
+
+ // This is replicating quick check from the OS implementation of api sets.
+ return SString::_wcsnicmp(wszLibName, W("api-"), 4) == 0 ||
+ SString::_wcsnicmp(wszLibName, W("ext-"), 4) == 0;
+}
+#endif // !PLATFORM_UNIX
+
// static
NATIVE_LIBRARY_HANDLE NDirect::LoadLibraryModuleViaHost(NDirectMethodDesc * pMD, PCWSTR wszLibName)
{
@@ -6282,13 +6319,12 @@ NATIVE_LIBRARY_HANDLE NDirect::LoadLibraryModuleViaHost(NDirectMethodDesc * pMD,
//Check if we need to provide the host a chance to provide the unmanaged dll
#ifndef PLATFORM_UNIX
- // Prevent Overriding of Windows API sets.
- // This is replicating quick check from the OS implementation of api sets.
- if (SString::_wcsnicmp(wszLibName, W("api-"), 4) == 0 || SString::_wcsnicmp(wszLibName, W("ext-"), 4) == 0)
+ if (IsWindowsAPISet(wszLibName))
{
+ // Prevent Overriding of Windows API sets.
return NULL;
}
-#endif
+#endif // !PLATFORM_UNIX
NATIVE_LIBRARY_HANDLE hmod = NULL;
AppDomain* pDomain = GetAppDomain();
@@ -6438,6 +6474,51 @@ NATIVE_LIBRARY_HANDLE NDirect::LoadLibraryModuleViaEvent(NDirectMethodDesc * pMD
return hmod;
}
+NATIVE_LIBRARY_HANDLE NDirect::LoadLibraryModuleViaCallback(NDirectMethodDesc * pMD, LPCWSTR wszLibName)
+{
+ STANDARD_VM_CONTRACT;
+
+ if (pMD->GetModule()->IsSystem())
+ {
+ // Don't attempt to callback on Corelib itself.
+ // The LoadLibrary callback stub is managed code that requires CoreLib
+ return NULL;
+ }
+
+ DWORD dllImportSearchPathFlags;
+ BOOL searchAssemblyDirectory;
+ BOOL hasDllImportSearchPathFlags = GetDllImportSearchPathFlags(pMD, &dllImportSearchPathFlags, &searchAssemblyDirectory);
+ dllImportSearchPathFlags |= searchAssemblyDirectory ? DLLIMPORTSEARCHPATH_ASSEMBLYDIRECTORY : 0;
+
+ Assembly* pAssembly = pMD->GetMethodTable()->GetAssembly();
+ NATIVE_LIBRARY_HANDLE handle = NULL;
+
+ GCX_COOP();
+
+ struct {
+ STRINGREF libNameRef;
+ OBJECTREF assemblyRef;
+ } gc = { NULL, NULL };
+
+ GCPROTECT_BEGIN(gc);
+
+ gc.libNameRef = StringObject::NewString(wszLibName);
+ gc.assemblyRef = pAssembly->GetExposedObject();
+
+ PREPARE_NONVIRTUAL_CALLSITE(METHOD__NATIVELIBRARY__LOADLIBRARYCALLBACKSTUB);
+ DECLARE_ARGHOLDER_ARRAY(args, 4);
+ args[ARGNUM_0] = STRINGREF_TO_ARGHOLDER(gc.libNameRef);
+ args[ARGNUM_1] = OBJECTREF_TO_ARGHOLDER(gc.assemblyRef);
+ args[ARGNUM_2] = BOOL_TO_ARGHOLDER(hasDllImportSearchPathFlags);
+ args[ARGNUM_3] = DWORD_TO_ARGHOLDER(dllImportSearchPathFlags);
+
+ // Make the call
+ CALL_MANAGED_METHOD(handle, NATIVE_LIBRARY_HANDLE, args);
+ GCPROTECT_END();
+
+ return handle;
+}
+
// Try to load the module alongside the assembly where the PInvoke was declared.
NATIVE_LIBRARY_HANDLE NDirect::LoadFromPInvokeAssemblyDirectory(Assembly *pAssembly, LPCWSTR libName, DWORD flags, LoadLibErrorTracker *pErrorTracker)
{
@@ -6461,11 +6542,12 @@ NATIVE_LIBRARY_HANDLE NDirect::LoadFromPInvokeAssemblyDirectory(Assembly *pAssem
}
// Try to load the module from the native DLL search directories
-NATIVE_LIBRARY_HANDLE NDirect::LoadFromNativeDllSearchDirectories(AppDomain* pDomain, LPCWSTR libName, DWORD flags, LoadLibErrorTracker *pErrorTracker)
+NATIVE_LIBRARY_HANDLE NDirect::LoadFromNativeDllSearchDirectories(LPCWSTR libName, DWORD flags, LoadLibErrorTracker *pErrorTracker)
{
STANDARD_VM_CONTRACT;
NATIVE_LIBRARY_HANDLE hmod = NULL;
+ AppDomain* pDomain = GetAppDomain();
if (pDomain->HasNativeDllSearchDirectories())
{
@@ -6587,7 +6669,7 @@ static void DetermineLibNameVariations(const WCHAR** libNameVariations, int* num
// Search for the library and variants of its name in probing directories.
//static
NATIVE_LIBRARY_HANDLE NDirect::LoadLibraryModuleBySearch(Assembly *callingAssembly,
- BOOL searchAssemblyDirectory, DWORD dllImportSearchPathFlag,
+ BOOL searchAssemblyDirectory, DWORD dllImportSearchPathFlags,
LoadLibErrorTracker * pErrorTracker, LPCWSTR wszLibName)
{
STANDARD_VM_CONTRACT;
@@ -6597,7 +6679,7 @@ NATIVE_LIBRARY_HANDLE NDirect::LoadLibraryModuleBySearch(Assembly *callingAssemb
#if defined(FEATURE_CORESYSTEM) && !defined(PLATFORM_UNIX)
// Try to go straight to System32 for Windows API sets. This is replicating quick check from
// the OS implementation of api sets.
- if (SString::_wcsnicmp(wszLibName, W("api-"), 4) == 0 || SString::_wcsnicmp(wszLibName, W("ext-"), 4) == 0)
+ if (IsWindowsAPISet(wszLibName))
{
hmod = LocalLoadLibraryHelper(wszLibName, LOAD_LIBRARY_SEARCH_SYSTEM32, pErrorTracker);
if (hmod != NULL)
@@ -6625,7 +6707,7 @@ NATIVE_LIBRARY_HANDLE NDirect::LoadLibraryModuleBySearch(Assembly *callingAssemb
currLibNameVariation.Printf(prefixSuffixCombinations[i], PLATFORM_SHARED_LIB_PREFIX_W, wszLibName, PLATFORM_SHARED_LIB_SUFFIX_W);
// NATIVE_DLL_SEARCH_DIRECTORIES set by host is considered well known path
- hmod = LoadFromNativeDllSearchDirectories(pDomain, currLibNameVariation, loadWithAlteredPathFlags, pErrorTracker);
+ hmod = LoadFromNativeDllSearchDirectories(currLibNameVariation, loadWithAlteredPathFlags, pErrorTracker);
if (hmod != NULL)
{
return hmod;
@@ -6634,11 +6716,11 @@ NATIVE_LIBRARY_HANDLE NDirect::LoadLibraryModuleBySearch(Assembly *callingAssemb
if (!libNameIsRelativePath)
{
DWORD flags = loadWithAlteredPathFlags;
- if ((dllImportSearchPathFlag & LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) != 0)
+ if ((dllImportSearchPathFlags & LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) != 0)
{
// LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR is the only flag affecting absolute path. Don't OR the flags
// unconditionally as all absolute path P/Invokes could then lose LOAD_WITH_ALTERED_SEARCH_PATH.
- flags |= dllImportSearchPathFlag;
+ flags |= dllImportSearchPathFlags;
}
hmod = LocalLoadLibraryHelper(currLibNameVariation, flags, pErrorTracker);
@@ -6649,14 +6731,14 @@ NATIVE_LIBRARY_HANDLE NDirect::LoadLibraryModuleBySearch(Assembly *callingAssemb
}
else if ((callingAssembly != nullptr) && searchAssemblyDirectory)
{
- hmod = LoadFromPInvokeAssemblyDirectory(callingAssembly, currLibNameVariation, loadWithAlteredPathFlags | dllImportSearchPathFlag, pErrorTracker);
+ hmod = LoadFromPInvokeAssemblyDirectory(callingAssembly, currLibNameVariation, loadWithAlteredPathFlags | dllImportSearchPathFlags, pErrorTracker);
if (hmod != NULL)
{
return hmod;
}
}
- hmod = LocalLoadLibraryHelper(currLibNameVariation, dllImportSearchPathFlag, pErrorTracker);
+ hmod = LocalLoadLibraryHelper(currLibNameVariation, dllImportSearchPathFlags, pErrorTracker);
if (hmod != NULL)
{
return hmod;
@@ -6686,7 +6768,7 @@ NATIVE_LIBRARY_HANDLE NDirect::LoadLibraryModuleBySearch(Assembly *callingAssemb
Assembly *pAssembly = spec.LoadAssembly(FILE_LOADED);
Module *pModule = pAssembly->FindModuleByName(szLibName);
- hmod = LocalLoadLibraryHelper(pModule->GetPath(), loadWithAlteredPathFlags | dllImportSearchPathFlag, pErrorTracker);
+ hmod = LocalLoadLibraryHelper(pModule->GetPath(), loadWithAlteredPathFlags | dllImportSearchPathFlags, pErrorTracker);
}
}
@@ -6707,11 +6789,18 @@ HINSTANCE NDirect::LoadLibraryModule(NDirectMethodDesc * pMD, LoadLibErrorTracke
if ( !name || !*name )
return NULL;
- ModuleHandleHolder hmod;
-
PREFIX_ASSUME( name != NULL );
MAKE_WIDEPTR_FROMUTF8( wszLibName, name );
+ ModuleHandleHolder hmod = LoadLibraryModuleViaCallback(pMD, wszLibName);
+ if (hmod != NULL)
+ {
+#ifdef FEATURE_PAL
+ hmod = PAL_RegisterLibraryDirect(hmod, wszLibName);
+#endif // FEATURE_PAL
+ return hmod.Extract();
+ }
+
AppDomain* pDomain = GetAppDomain();
// AssemblyLoadContext is not supported in AppX mode and thus,
diff --git a/src/vm/dllimport.h b/src/vm/dllimport.h
index 1203803b9a..b88d339a84 100644
--- a/src/vm/dllimport.h
+++ b/src/vm/dllimport.h
@@ -76,7 +76,7 @@ public:
static LPVOID NDirectGetEntryPoint(NDirectMethodDesc *pMD, HINSTANCE hMod);
static NATIVE_LIBRARY_HANDLE LoadLibraryFromPath(LPCWSTR libraryPath, BOOL throwOnError);
static NATIVE_LIBRARY_HANDLE LoadLibraryByName(LPCWSTR name, Assembly *callingAssembly,
- BOOL hasDllImportSearchPathFlag, DWORD dllImportSearchPathFlag,
+ BOOL hasDllImportSearchPathFlags, DWORD dllImportSearchPathFlags,
BOOL throwOnError);
static HINSTANCE LoadLibraryModule(NDirectMethodDesc * pMD, LoadLibErrorTracker *pErrorTracker);
static void FreeNativeLibrary(NATIVE_LIBRARY_HANDLE handle);
@@ -122,12 +122,13 @@ public:
private:
NDirect() {LIMITED_METHOD_CONTRACT;}; // prevent "new"'s on this class
- static NATIVE_LIBRARY_HANDLE LoadFromNativeDllSearchDirectories(AppDomain* pDomain, LPCWSTR libName, DWORD flags, LoadLibErrorTracker *pErrorTracker);
+ static NATIVE_LIBRARY_HANDLE LoadFromNativeDllSearchDirectories(LPCWSTR libName, DWORD flags, LoadLibErrorTracker *pErrorTracker);
static NATIVE_LIBRARY_HANDLE LoadFromPInvokeAssemblyDirectory(Assembly *pAssembly, LPCWSTR libName, DWORD flags, LoadLibErrorTracker *pErrorTracker);
static NATIVE_LIBRARY_HANDLE LoadLibraryModuleViaHost(NDirectMethodDesc * pMD, LPCWSTR wszLibName);
static NATIVE_LIBRARY_HANDLE LoadLibraryModuleViaEvent(NDirectMethodDesc * pMD, LPCWSTR wszLibName);
- static NATIVE_LIBRARY_HANDLE LoadLibraryModuleBySearch(NDirectMethodDesc * pMD, LoadLibErrorTracker * pErrorTracker, const wchar_t* wszLibName);
- static NATIVE_LIBRARY_HANDLE LoadLibraryModuleBySearch(Assembly *callingAssembly, BOOL searchAssemblyDirectory, DWORD dllImportSearchPathFlag, LoadLibErrorTracker * pErrorTracker, const wchar_t* wszLibName);
+ static NATIVE_LIBRARY_HANDLE LoadLibraryModuleViaCallback(NDirectMethodDesc * pMD, LPCWSTR wszLibName);
+ static NATIVE_LIBRARY_HANDLE LoadLibraryModuleBySearch(NDirectMethodDesc * pMD, LoadLibErrorTracker * pErrorTracker, LPCWSTR wszLibName);
+ static NATIVE_LIBRARY_HANDLE LoadLibraryModuleBySearch(Assembly *callingAssembly, BOOL searchAssemblyDirectory, DWORD dllImportSearchPathFlags, LoadLibErrorTracker * pErrorTracker, LPCWSTR wszLibName);
#if !defined(FEATURE_PAL)
// Indicates if the OS supports the new secure LoadLibraryEx flags introduced in KB2533623
diff --git a/src/vm/interoputil.cpp b/src/vm/interoputil.cpp
index b84670ba3a..c70154d39c 100644
--- a/src/vm/interoputil.cpp
+++ b/src/vm/interoputil.cpp
@@ -897,9 +897,9 @@ void FillExceptionData(
#endif // CROSSGEN_COMPILE
//---------------------------------------------------------------------------
-//returns true if pImport has DefaultDllImportSearchPathsAttribute
-//if true, also returns dllImportSearchPathFlag and searchAssemblyDirectory values.
-BOOL GetDefaultDllImportSearchPathsAttributeValue(IMDInternalImport *pImport, mdToken token, DWORD * pDllImportSearchPathFlag)
+// If pImport has the DefaultDllImportSearchPathsAttribute,
+// set the value of the attribute in pDlImportSearchPathFlags and return true.
+BOOL GetDefaultDllImportSearchPathsAttributeValue(IMDInternalImport *pImport, mdToken token, DWORD * pDllImportSearchPathFlags)
{
CONTRACTL
{
@@ -929,7 +929,7 @@ BOOL GetDefaultDllImportSearchPathsAttributeValue(IMDInternalImport *pImport, md
args[0].InitEnum(SERIALIZATION_TYPE_U4, (ULONG)0);
ParseKnownCaArgs(ca, args, lengthof(args));
- *pDllImportSearchPathFlag = args[0].val.u4;
+ *pDllImportSearchPathFlags = args[0].val.u4;
return TRUE;
}
diff --git a/src/vm/interoputil.h b/src/vm/interoputil.h
index 91f6828c49..872848b9df 100644
--- a/src/vm/interoputil.h
+++ b/src/vm/interoputil.h
@@ -136,9 +136,9 @@ void FillExceptionData(
_In_opt_ IRestrictedErrorInfo* pRestrictedErrorInfo);
//---------------------------------------------------------------------------
-//returns true if pImport has DefaultDllImportSearchPathsAttribute
-//if true, also returns dllImportSearchPathFlag and searchAssemblyDirectory values.
-BOOL GetDefaultDllImportSearchPathsAttributeValue(IMDInternalImport *pImport, mdToken token, DWORD * pDlImportSearchPathFlag);
+// If pImport has the DefaultDllImportSearchPathsAttribute,
+// set the value of the attribute in pDlImportSearchPathFlags and return true.
+BOOL GetDefaultDllImportSearchPathsAttributeValue(IMDInternalImport *pImport, mdToken token, DWORD * pDlImportSearchPathFlags);
//---------------------------------------------------------------------------
// Returns the index of the LCID parameter if one exists and -1 otherwise.
diff --git a/src/vm/metasig.h b/src/vm/metasig.h
index cfa844012e..cbac116bd3 100644
--- a/src/vm/metasig.h
+++ b/src/vm/metasig.h
@@ -552,6 +552,7 @@ DEFINE_METASIG_T(IM(RefGuid_OutIntPtr_RetCustomQueryInterfaceResult, r(g(GUID))
DEFINE_METASIG_T(SM(IntPtr_AssemblyName_RetAssemblyBase, I C(ASSEMBLY_NAME), C(ASSEMBLYBASE)))
DEFINE_METASIG_T(SM(Str_AssemblyBase_IntPtr_RetIntPtr, s C(ASSEMBLYBASE) I, I))
+DEFINE_METASIG_T(SM(Str_AssemblyBase_Bool_UInt_RetIntPtr, s C(ASSEMBLYBASE) F K, I))
// ThreadPool
DEFINE_METASIG(SM(Obj_Bool_RetVoid, j F, v))
diff --git a/src/vm/mscorlib.h b/src/vm/mscorlib.h
index 7c5802a8b7..94acf84f58 100644
--- a/src/vm/mscorlib.h
+++ b/src/vm/mscorlib.h
@@ -493,6 +493,8 @@ DEFINE_METHOD(MARSHAL, GET_DELEGATE_FOR_FUNCTION_POINTER, GetDelega
DEFINE_METHOD(MARSHAL, ALLOC_CO_TASK_MEM, AllocCoTaskMem, SM_Int_RetIntPtr)
DEFINE_FIELD(MARSHAL, SYSTEM_MAX_DBCS_CHAR_SIZE, SystemMaxDBCSCharSize)
+DEFINE_CLASS(NATIVELIBRARY, Interop, NativeLibrary)
+DEFINE_METHOD(NATIVELIBRARY, LOADLIBRARYCALLBACKSTUB, LoadLibraryCallbackStub, SM_Str_AssemblyBase_Bool_UInt_RetIntPtr)
DEFINE_CLASS(MEMBER, Reflection, MemberInfo)