summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSwaroop Sridhar <Swaroop.Sridhar@microsoft.com>2018-11-12 11:56:18 -0800
committerJan Vorlicek <janvorli@microsoft.com>2018-11-12 20:56:18 +0100
commit214c3b62d889b2ff57425ab3f4ce70adf7503be6 (patch)
tree6e58e67bf9a78bd0ade030d615bf57cbc3959baa
parent853a01279327163b099fdd70d1c04d8aaf61f772 (diff)
downloadcoreclr-214c3b62d889b2ff57425ab3f4ce70adf7503be6.tar.gz
coreclr-214c3b62d889b2ff57425ab3f4ce70adf7503be6.tar.bz2
coreclr-214c3b62d889b2ff57425ab3f4ce70adf7503be6.zip
LoadLibrary refactoring (#20841)
* Refactor LoadLibrary Methods This change refactors the code in DllImport in preparation for implementing the new NativeLibrary API here: dotnet/corefx#32015 The two main changes are: 1) A change in the semantics of the internal LoadLibrary helper functions. When a native library is loaded, there are two categories of callers expecting different return values: External callers like AssemblyNative::InternalLoadUnmanagedDllFromPath() and the upcoming System.Runtime.Interop.Marshall.LoadLibrary() need the raw system handle Internal callers like LoadLibraryModule() need the PAL registered handle This change modifies the internal LoadLibraryModule* methods to work in terms of native system handles, so that external callers can obrain them directly. Methods requiring PAL-handles can register them explicitly. There is no change in external signature of DllImport class, or the native Dll cache in AppDomain class. 2) Differentiate HMODULE and NATIVE_LIBRARY_HANDLE This change defines NATIVE_LIBRARY_HANDLE type to represent raw system handles to native libraries that are not registered with the PAL (On Unix systems). The types on PAL and DlImport methods are adjusted to make this semantic distinction explicit. * Fix loading LibC via PAL_LoadLibraryDirect()
-rw-r--r--src/inc/palclr_win.h6
-rw-r--r--src/pal/inc/pal.h7
-rw-r--r--src/pal/src/loader/module.cpp89
-rw-r--r--src/vm/assemblynative.cpp2
-rw-r--r--src/vm/dllimport.cpp327
-rw-r--r--src/vm/dllimport.h10
6 files changed, 237 insertions, 204 deletions
diff --git a/src/inc/palclr_win.h b/src/inc/palclr_win.h
index 372f467cbd..c04e0ab8bd 100644
--- a/src/inc/palclr_win.h
+++ b/src/inc/palclr_win.h
@@ -142,4 +142,10 @@
#define WIN_PAL_ENDTRY_NAKED_DBG
#endif // defined(ENABLE_CONTRACTS_IMPL) && !defined(JIT64_BUILD)
+#if !defined (FEATURE_PAL)
+// Native system libray handle.
+// In Windows, NATIVE_LIBRARY_HANDLE is the same as HMODULE.
+typedef HMODULE NATIVE_LIBRARY_HANDLE;
+#endif // !FEATURE_PAL
+
#endif // __PALCLR_WIN_H__
diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h
index c4a1d64a29..45989998e8 100644
--- a/src/pal/inc/pal.h
+++ b/src/pal/inc/pal.h
@@ -68,6 +68,11 @@ extern "C" {
#include <pal_error.h>
#include <pal_mstypes.h>
+// Native system libray handle.
+// On Unix systems, NATIVE_LIBRARY_HANDLE type represents a library handle not registered with the PAL.
+// To get a HMODULE on Unix, call PAL_RegisterLibraryDirect() on a NATIVE_LIBRARY_HANDLE.
+typedef void * NATIVE_LIBRARY_HANDLE;
+
/******************* Processor-specific glue *****************************/
#ifndef _MSC_VER
@@ -2590,7 +2595,7 @@ LoadLibraryExW(
IN DWORD dwFlags);
PALIMPORT
-void *
+NATIVE_LIBRARY_HANDLE
PALAPI
PAL_LoadLibraryDirect(
IN LPCWSTR lpLibFileName);
diff --git a/src/pal/src/loader/module.cpp b/src/pal/src/loader/module.cpp
index 16bca0f929..04e41c38e5 100644
--- a/src/pal/src/loader/module.cpp
+++ b/src/pal/src/loader/module.cpp
@@ -103,10 +103,10 @@ static bool LOADConvertLibraryPathWideStringToMultibyteString(
INT *multibyteLibraryPathLengthRef);
static BOOL LOADValidateModule(MODSTRUCT *module);
static LPWSTR LOADGetModuleFileName(MODSTRUCT *module);
-static MODSTRUCT *LOADAddModule(void *dl_handle, LPCSTR libraryNameOrPath);
-static void *LOADLoadLibraryDirect(LPCSTR libraryNameOrPath);
+static MODSTRUCT *LOADAddModule(NATIVE_LIBRARY_HANDLE dl_handle, LPCSTR libraryNameOrPath);
+static NATIVE_LIBRARY_HANDLE LOADLoadLibraryDirect(LPCSTR libraryNameOrPath);
static BOOL LOADFreeLibrary(MODSTRUCT *module, BOOL fCallDllMain);
-static HMODULE LOADRegisterLibraryDirect(void *dl_handle, LPCSTR libraryNameOrPath, BOOL fDynamic);
+static HMODULE LOADRegisterLibraryDirect(NATIVE_LIBRARY_HANDLE dl_handle, LPCSTR libraryNameOrPath, BOOL fDynamic);
static HMODULE LOADLoadLibrary(LPCSTR shortAsciiName, BOOL fDynamic);
static BOOL LOADCallDllMainSafe(MODSTRUCT *module, DWORD dwReason, LPVOID lpReserved);
@@ -556,6 +556,33 @@ done:
return retval;
}
+LPCSTR FixLibCName(LPCSTR shortAsciiName)
+{
+ // Check whether we have been requested to load 'libc'. If that's the case, then:
+ // * For Linux, use the full name of the library that is defined in <gnu/lib-names.h> by the
+ // LIBC_SO constant. The problem is that calling dlopen("libc.so") will fail for libc even
+ // though it works for other libraries. The reason is that libc.so is just linker script
+ // (i.e. a test file).
+ // As a result, we have to use the full name (i.e. lib.so.6) that is defined by LIBC_SO.
+ // * For macOS, use constant value absolute path "/usr/lib/libc.dylib".
+ // * For FreeBSD, use constant value "libc.so.7".
+ // * For rest of Unices, use constant value "libc.so".
+ if (strcmp(shortAsciiName, LIBC_NAME_WITHOUT_EXTENSION) == 0)
+ {
+#if defined(__APPLE__)
+ return "/usr/lib/libc.dylib";
+#elif defined(__FreeBSD__)
+ return "libc.so.7";
+#elif defined(LIBC_SO)
+ return LIBC_SO;
+#else
+ return "libc.so";
+#endif
+ }
+
+ return shortAsciiName;
+}
+
/*
Function:
PAL_LoadLibraryDirect
@@ -564,15 +591,16 @@ Function:
Returns the system handle to the loaded library, or nullptr upon failure (error is set via SetLastError()).
*/
-void *
+NATIVE_LIBRARY_HANDLE
PALAPI
PAL_LoadLibraryDirect(
IN LPCWSTR lpLibFileName)
{
PathCharString pathstr;
CHAR * lpstr = nullptr;
+ LPCSTR lpcstr = nullptr;
INT name_length;
- void *dl_handle = nullptr;
+ NATIVE_LIBRARY_HANDLE dl_handle = nullptr;
PERF_ENTRY(LoadLibraryDirect);
ENTRY("LoadLibraryDirect (lpLibFileName=%p (%S)) \n",
@@ -597,8 +625,9 @@ PAL_LoadLibraryDirect(
/* do the Dos/Unix conversion on our own copy of the name */
FILEDosToUnixPathA(lpstr);
pathstr.CloseBuffer(name_length);
+ lpcstr = FixLibCName(lpstr);
- dl_handle = LOADLoadLibraryDirect(lpstr);
+ dl_handle = LOADLoadLibraryDirect(lpcstr);
done:
LOGEXIT("LoadLibraryDirect returns HMODULE %p\n", dl_handle);
@@ -617,7 +646,7 @@ Function:
HMODULE
PALAPI
PAL_RegisterLibraryDirect(
- IN void *dl_handle,
+ IN NATIVE_LIBRARY_HANDLE dl_handle,
IN LPCWSTR lpLibFileName)
{
PathCharString pathstr;
@@ -651,7 +680,7 @@ PAL_RegisterLibraryDirect(
/* let LOADRegisterLibraryDirect call SetLastError in case of failure */
LockModuleList();
- hModule = LOADRegisterLibraryDirect((void *)dl_handle, lpstr, true /* fDynamic */);
+ hModule = LOADRegisterLibraryDirect(dl_handle, lpstr, true /* fDynamic */);
UnlockModuleList();
done:
@@ -684,7 +713,7 @@ PAL_RegisterModule(
LockModuleList();
- void *dl_handle = LOADLoadLibraryDirect(lpLibFileName);
+ NATIVE_LIBRARY_HANDLE dl_handle = LOADLoadLibraryDirect(lpLibFileName);
if (dl_handle)
{
// This only creates/adds the module handle and doesn't call DllMain
@@ -1395,12 +1424,12 @@ Parameters:
Return value:
System handle to the loaded library, or nullptr upon failure (error is set via SetLastError()).
*/
-static void *LOADLoadLibraryDirect(LPCSTR libraryNameOrPath)
+static NATIVE_LIBRARY_HANDLE LOADLoadLibraryDirect(LPCSTR libraryNameOrPath)
{
_ASSERTE(libraryNameOrPath != nullptr);
_ASSERTE(libraryNameOrPath[0] != '\0');
- void *dl_handle = dlopen(libraryNameOrPath, RTLD_LAZY);
+ NATIVE_LIBRARY_HANDLE dl_handle = dlopen(libraryNameOrPath, RTLD_LAZY);
if (dl_handle == nullptr)
{
SetLastError(ERROR_MOD_NOT_FOUND);
@@ -1420,7 +1449,7 @@ Function :
Allocate and initialize a new MODSTRUCT structure
Parameters :
- void *dl_handle : handle returned by dl_open, goes in MODSTRUCT::dl_handle
+ NATIVE_LIBRARY_HANDLE dl_handle : handle returned by dl_open, goes in MODSTRUCT::dl_handle
char *name : name of new module. after conversion to widechar,
goes in MODSTRUCT::lib_name
@@ -1432,7 +1461,7 @@ Notes :
'name' is used to initialize MODSTRUCT::lib_name. The other member is set to NULL
In case of failure (in malloc or MBToWC), this function sets LastError.
--*/
-static MODSTRUCT *LOADAllocModule(void *dl_handle, LPCSTR name)
+static MODSTRUCT *LOADAllocModule(NATIVE_LIBRARY_HANDLE dl_handle, LPCSTR name)
{
MODSTRUCT *module;
LPWSTR wide_name;
@@ -1485,13 +1514,13 @@ Function:
Registers a system handle to a loaded library with the module list.
Parameters:
- void *dl_handle: System handle to the loaded library.
+ NATIVE_LIBRARY_HANDLE dl_handle: System handle to the loaded library.
LPCSTR libraryNameOrPath: The library that was loaded.
Return value:
PAL handle to the loaded library, or nullptr upon failure (error is set via SetLastError()).
*/
-static MODSTRUCT *LOADAddModule(void *dl_handle, LPCSTR libraryNameOrPath)
+static MODSTRUCT *LOADAddModule(NATIVE_LIBRARY_HANDLE dl_handle, LPCSTR libraryNameOrPath)
{
_ASSERTE(dl_handle != nullptr);
_ASSERTE(libraryNameOrPath != nullptr);
@@ -1555,14 +1584,14 @@ Function:
Registers a system handle to a loaded library with the module list.
Parameters:
- void *dl_handle: System handle to the loaded library.
+ NATIVE_LIBRARY_HANDLE dl_handle: System handle to the loaded library.
LPCSTR libraryNameOrPath: The library that was loaded.
BOOL fDynamic: TRUE if dynamic load through LoadLibrary, FALSE if static load through RegisterLibrary.
Return value:
PAL handle to the loaded library, or nullptr upon failure (error is set via SetLastError()).
*/
-static HMODULE LOADRegisterLibraryDirect(void *dl_handle, LPCSTR libraryNameOrPath, BOOL fDynamic)
+static HMODULE LOADRegisterLibraryDirect(NATIVE_LIBRARY_HANDLE dl_handle, LPCSTR libraryNameOrPath, BOOL fDynamic)
{
MODSTRUCT *module = LOADAddModule(dl_handle, libraryNameOrPath);
if (module == nullptr)
@@ -1631,30 +1660,10 @@ Return value :
static HMODULE LOADLoadLibrary(LPCSTR shortAsciiName, BOOL fDynamic)
{
HMODULE module = nullptr;
- void *dl_handle = nullptr;
-
- // Check whether we have been requested to load 'libc'. If that's the case, then:
- // * For Linux, use the full name of the library that is defined in <gnu/lib-names.h> by the
- // LIBC_SO constant. The problem is that calling dlopen("libc.so") will fail for libc even
- // though it works for other libraries. The reason is that libc.so is just linker script
- // (i.e. a test file).
- // As a result, we have to use the full name (i.e. lib.so.6) that is defined by LIBC_SO.
- // * For macOS, use constant value absolute path "/usr/lib/libc.dylib".
- // * For FreeBSD, use constant value "libc.so.7".
- // * For rest of Unices, use constant value "libc.so".
- if (strcmp(shortAsciiName, LIBC_NAME_WITHOUT_EXTENSION) == 0)
- {
-#if defined(__APPLE__)
- shortAsciiName = "/usr/lib/libc.dylib";
-#elif defined(__FreeBSD__)
- shortAsciiName = "libc.so.7";
-#elif defined(LIBC_SO)
- shortAsciiName = LIBC_SO;
-#else
- shortAsciiName = "libc.so";
-#endif
- }
+ NATIVE_LIBRARY_HANDLE dl_handle = nullptr;
+ shortAsciiName = FixLibCName(shortAsciiName);
+
LockModuleList();
dl_handle = LOADLoadLibraryDirect(shortAsciiName);
diff --git a/src/vm/assemblynative.cpp b/src/vm/assemblynative.cpp
index 89e6768c33..117507e7e8 100644
--- a/src/vm/assemblynative.cpp
+++ b/src/vm/assemblynative.cpp
@@ -310,7 +310,7 @@ INT_PTR QCALLTYPE AssemblyNative::InternalLoadUnmanagedDllFromPath(LPCWSTR unman
{
QCALL_CONTRACT;
- HMODULE moduleHandle = nullptr;
+ NATIVE_LIBRARY_HANDLE moduleHandle = nullptr;
BEGIN_QCALL;
diff --git a/src/vm/dllimport.cpp b/src/vm/dllimport.cpp
index acb356a42b..9ad41c55c8 100644
--- a/src/vm/dllimport.cpp
+++ b/src/vm/dllimport.cpp
@@ -2941,7 +2941,7 @@ PInvokeStaticSigInfo::PInvokeStaticSigInfo(MethodDesc* pMD, ThrowOnError throwOn
HRESULT hRESULT = pMT->GetMDImport()->GetCustomAttributeByName(
pMT->GetCl(), g_UnmanagedFunctionPointerAttribute, (const VOID **)(&pData), (ULONG *)&cData);
IfFailThrow(hRESULT);
- if(cData != 0)
+ if (cData != 0)
{
CustomAttributeParser ca(pData, cData);
@@ -6069,12 +6069,16 @@ private:
SString m_message;
}; // class LoadLibErrorTracker
-// Local helper function for the LoadLibraryModule function below
-static HMODULE LocalLoadLibraryHelper( LPCWSTR name, DWORD flags, LoadLibErrorTracker *pErrorTracker )
+// Local helper function to load a library.
+// Load the library directly. On Unix systems, don't register it yet with PAL.
+// * External callers like AssemblyNative::InternalLoadUnmanagedDllFromPath() and the upcoming
+// System.Runtime.Interop.Marshall.LoadLibrary() need the raw system handle
+// * Internal callers like LoadLibraryModule() can convert this handle to a HMODULE via PAL APIs on Unix
+static NATIVE_LIBRARY_HANDLE LocalLoadLibraryHelper( LPCWSTR name, DWORD flags, LoadLibErrorTracker *pErrorTracker )
{
STANDARD_VM_CONTRACT;
- HMODULE hmod = NULL;
+ NATIVE_LIBRARY_HANDLE hmod = NULL;
#ifndef FEATURE_PAL
@@ -6085,7 +6089,7 @@ static HMODULE LocalLoadLibraryHelper( LPCWSTR name, DWORD flags, LoadLibErrorTr
)
{
hmod = CLRLoadLibraryEx(name, NULL, flags & 0xFFFFFF00);
- if(hmod != NULL)
+ if (hmod != NULL)
{
return hmod;
}
@@ -6101,7 +6105,7 @@ static HMODULE LocalLoadLibraryHelper( LPCWSTR name, DWORD flags, LoadLibErrorTr
hmod = CLRLoadLibraryEx(name, NULL, flags & 0xFF);
#else // !FEATURE_PAL
- hmod = CLRLoadLibrary(name);
+ hmod = PAL_LoadLibraryDirect(name);
#endif // !FEATURE_PAL
if (hmod == NULL)
@@ -6112,27 +6116,6 @@ static HMODULE LocalLoadLibraryHelper( LPCWSTR name, DWORD flags, LoadLibErrorTr
return hmod;
}
-// Local helper function for the LoadLibraryFromPath function below
-static HMODULE LocalLoadLibraryDirectHelper(LPCWSTR name, DWORD flags, LoadLibErrorTracker *pErrorTracker)
-{
- STANDARD_VM_CONTRACT;
-
-#ifndef FEATURE_PAL
- return LocalLoadLibraryHelper(name, flags, pErrorTracker);
-#else // !FEATURE_PAL
- // Load the library directly, and don't register it yet with PAL. The system library handle is required here, not the PAL
- // handle. The system library handle is registered with PAL to get a PAL handle in LoadLibraryModuleViaHost().
- HMODULE hmod = PAL_LoadLibraryDirect(name);
-
- if (hmod == NULL)
- {
- pErrorTracker->TrackErrorCode();
- }
-
- return hmod;
-#endif // !FEATURE_PAL
-}
-
#if !defined(FEATURE_PAL)
bool NDirect::s_fSecureLoadLibrarySupported = false;
#endif
@@ -6149,23 +6132,23 @@ bool NDirect::s_fSecureLoadLibrarySupported = false;
#endif // !FEATURE_PAL
// static
-HMODULE NDirect::LoadLibraryFromPath(LPCWSTR libraryPath)
+NATIVE_LIBRARY_HANDLE NDirect::LoadLibraryFromPath(LPCWSTR libraryPath)
{
STANDARD_VM_CONTRACT;
LoadLibErrorTracker errorTracker;
- const HMODULE systemModuleHandle =
- LocalLoadLibraryDirectHelper(libraryPath, GetLoadWithAlteredSearchPathFlag(), &errorTracker);
- if (systemModuleHandle == nullptr)
+ const NATIVE_LIBRARY_HANDLE hmod =
+ LocalLoadLibraryHelper(libraryPath, GetLoadWithAlteredSearchPathFlag(), &errorTracker);
+ if (hmod == nullptr)
{
SString libraryPathSString(libraryPath);
errorTracker.Throw(libraryPathSString);
}
- return systemModuleHandle;
+ return hmod;
}
/* static */
-HMODULE NDirect::LoadLibraryModuleViaHost(NDirectMethodDesc * pMD, AppDomain* pDomain, const wchar_t* wszLibName)
+NATIVE_LIBRARY_HANDLE NDirect::LoadLibraryModuleViaHost(NDirectMethodDesc * pMD, AppDomain* pDomain, const wchar_t* wszLibName)
{
STANDARD_VM_CONTRACT;
//Dynamic Pinvoke Support:
@@ -6243,23 +6226,15 @@ HMODULE NDirect::LoadLibraryModuleViaHost(NDirectMethodDesc * pMD, AppDomain* pD
GCPROTECT_END();
-#ifdef FEATURE_PAL
- if (hmod != nullptr)
- {
- // Register the system library handle with PAL and get a PAL library handle
- hmod = PAL_RegisterLibraryDirect(hmod, wszLibName);
- }
-#endif // FEATURE_PAL
-
- return (HMODULE)hmod;
+ return (NATIVE_LIBRARY_HANDLE)hmod;
}
// Try to load the module alongside the assembly where the PInvoke was declared.
-HMODULE NDirect::LoadFromPInvokeAssemblyDirectory(Assembly *pAssembly, LPCWSTR libName, DWORD flags, LoadLibErrorTracker *pErrorTracker)
+NATIVE_LIBRARY_HANDLE NDirect::LoadFromPInvokeAssemblyDirectory(Assembly *pAssembly, LPCWSTR libName, DWORD flags, LoadLibErrorTracker *pErrorTracker)
{
STANDARD_VM_CONTRACT;
- HMODULE hmod = NULL;
+ NATIVE_LIBRARY_HANDLE hmod = NULL;
SString path = pAssembly->GetManifestFile()->GetPath();
@@ -6277,11 +6252,11 @@ HMODULE NDirect::LoadFromPInvokeAssemblyDirectory(Assembly *pAssembly, LPCWSTR l
}
// Try to load the module from the native DLL search directories
-HMODULE NDirect::LoadFromNativeDllSearchDirectories(AppDomain* pDomain, LPCWSTR libName, DWORD flags, LoadLibErrorTracker *pErrorTracker)
+NATIVE_LIBRARY_HANDLE NDirect::LoadFromNativeDllSearchDirectories(AppDomain* pDomain, LPCWSTR libName, DWORD flags, LoadLibErrorTracker *pErrorTracker)
{
STANDARD_VM_CONTRACT;
- HMODULE hmod = NULL;
+ NATIVE_LIBRARY_HANDLE hmod = NULL;
if (pDomain->HasNativeDllSearchDirectories())
{
@@ -6400,69 +6375,28 @@ static void DetermineLibNameVariations(const WCHAR** libNameVariations, int* num
}
#endif // FEATURE_PAL
-HINSTANCE NDirect::LoadLibraryModule(NDirectMethodDesc * pMD, LoadLibErrorTracker * pErrorTracker)
+// Search for the library and variants of its name in probing directories.
+NATIVE_LIBRARY_HANDLE NDirect::LoadLibraryModuleBySearch(NDirectMethodDesc * pMD, LoadLibErrorTracker * pErrorTracker, const wchar_t* wszLibName)
{
- CONTRACTL
- {
- STANDARD_VM_CHECK;
- PRECONDITION( CheckPointer( pMD ) );
- }
- CONTRACTL_END;
-
- LPCUTF8 name = pMD->GetLibName();
- if ( !name || !*name )
- return NULL;
-
- ModuleHandleHolder hmod;
-
- DWORD loadWithAlteredPathFlags = GetLoadWithAlteredSearchPathFlag();
-
- PREFIX_ASSUME( name != NULL );
- MAKE_WIDEPTR_FROMUTF8( wszLibName, name );
-
+ STANDARD_VM_CONTRACT;
+
+ NATIVE_LIBRARY_HANDLE hmod = NULL;
AppDomain* pDomain = GetAppDomain();
- // AssemblyLoadContext is not supported in AppX mode and thus,
- // we should not perform PInvoke resolution via it when operating in
- // AppX mode.
- if (!AppX::IsAppXProcess())
- {
- hmod = LoadLibraryModuleViaHost(pMD, pDomain, wszLibName);
- }
-
-
- if(hmod == NULL)
- {
- hmod = pDomain->FindUnmanagedImageInCache(wszLibName);
- }
-
- if(hmod != NULL)
- {
- return hmod.Extract();
- }
-
-#ifdef FEATURE_PAL
- // In the PAL version of CoreCLR, the CLR module itself exports the functionality
- // that the Windows version obtains from kernel32 and friends. In order to avoid
- // picking up the wrong instance, we perform this redirection first.
- // This is also true for CoreSystem builds, where mscorlib p/invokes are forwarded through coreclr
- // itself so we can control CoreSystem library/API name re-mapping from one central location.
- if (SString::_wcsicmp(wszLibName, MAIN_CLR_MODULE_NAME_W) == 0)
- hmod = GetCLRModule();
-#endif // FEATURE_PAL
-
#if defined(FEATURE_CORESYSTEM) && !defined(PLATFORM_UNIX)
- if (hmod == NULL)
+ // 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)
{
- // 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)
+ hmod = LocalLoadLibraryHelper(wszLibName, LOAD_LIBRARY_SEARCH_SYSTEM32, pErrorTracker);
+ if (hmod != NULL)
{
- hmod = LocalLoadLibraryHelper(wszLibName, LOAD_LIBRARY_SEARCH_SYSTEM32, pErrorTracker);
+ return hmod;
}
}
#endif // FEATURE_CORESYSTEM && !FEATURE_PAL
+ DWORD loadWithAlteredPathFlags = GetLoadWithAlteredSearchPathFlag();
bool libNameIsRelativePath = Path::IsRelative(wszLibName);
DWORD dllImportSearchPathFlag = 0;
// P/Invokes are often declared with variations on the actual library name.
@@ -6473,99 +6407,178 @@ HINSTANCE NDirect::LoadLibraryModule(NDirectMethodDesc * pMD, LoadLibErrorTracke
const WCHAR* prefixSuffixCombinations[MaxVariationCount] = {};
int numberOfVariations = COUNTOF(prefixSuffixCombinations);
DetermineLibNameVariations(prefixSuffixCombinations, &numberOfVariations, wszLibName, libNameIsRelativePath);
- for (int i = 0; hmod == NULL && i < numberOfVariations; i++)
+ for (int i = 0; i < numberOfVariations; i++)
{
SString currLibNameVariation;
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);
+ if (hmod != NULL)
+ {
+ return hmod;
+ }
+ // First checks if the method has DefaultDllImportSearchPathsAttribute. If method has the attribute
+ // then dllImportSearchPathFlag is set to its value.
+ // Otherwise checks if the assembly has the attribute.
+ // If assembly has the attribute then flag is set to its value.
BOOL searchAssemblyDirectory = TRUE;
- if (hmod == NULL)
+ BOOL attributeIsFound = FALSE;
+
+ if (pMD->HasDefaultDllImportSearchPathsAttribute())
+ {
+ dllImportSearchPathFlag = pMD->DefaultDllImportSearchPathsAttributeCachedValue();
+ searchAssemblyDirectory = pMD->DllImportSearchAssemblyDirectory();
+ attributeIsFound = TRUE;
+ }
+ else
{
- // First checks if the method has DefaultDllImportSearchPathsAttribute. If method has the attribute
- // then dllImportSearchPathFlag is set to its value.
- // Otherwise checks if the assembly has the attribute.
- // If assembly has the attribute then flag ise set to its value.
- BOOL attributeIsFound = FALSE;
+ Module * pModule = pMD->GetModule();
- if (pMD->HasDefaultDllImportSearchPathsAttribute())
+ if (pModule->HasDefaultDllImportSearchPathsAttribute())
{
- dllImportSearchPathFlag = pMD->DefaultDllImportSearchPathsAttributeCachedValue();
- searchAssemblyDirectory = pMD->DllImportSearchAssemblyDirectory();
+ dllImportSearchPathFlag = pModule->DefaultDllImportSearchPathsAttributeCachedValue();
+ searchAssemblyDirectory = pModule->DllImportSearchAssemblyDirectory();
attributeIsFound = TRUE;
}
- else
- {
- Module * pModule = pMD->GetModule();
+ }
- if(pModule->HasDefaultDllImportSearchPathsAttribute())
- {
- dllImportSearchPathFlag = pModule->DefaultDllImportSearchPathsAttributeCachedValue();
- searchAssemblyDirectory = pModule->DllImportSearchAssemblyDirectory();
- attributeIsFound = TRUE;
- }
+ if (!libNameIsRelativePath)
+ {
+ DWORD flags = loadWithAlteredPathFlags;
+ if ((dllImportSearchPathFlag & 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;
}
- if (!libNameIsRelativePath)
+ hmod = LocalLoadLibraryHelper(currLibNameVariation, flags, pErrorTracker);
+ if (hmod != NULL)
{
- DWORD flags = loadWithAlteredPathFlags;
- if ((dllImportSearchPathFlag & 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;
- }
-
- hmod = LocalLoadLibraryHelper(currLibNameVariation, flags, pErrorTracker);
+ return hmod;
}
- else if (searchAssemblyDirectory)
+ }
+ else if (searchAssemblyDirectory)
+ {
+ Assembly* pAssembly = pMD->GetMethodTable()->GetAssembly();
+ hmod = LoadFromPInvokeAssemblyDirectory(pAssembly, currLibNameVariation, loadWithAlteredPathFlags | dllImportSearchPathFlag, pErrorTracker);
+ if (hmod != NULL)
{
- Assembly* pAssembly = pMD->GetMethodTable()->GetAssembly();
- hmod = LoadFromPInvokeAssemblyDirectory(pAssembly, currLibNameVariation, loadWithAlteredPathFlags | dllImportSearchPathFlag, pErrorTracker);
+ return hmod;
}
}
- // This call searches the application directory instead of the location for the library.
- if (hmod == NULL)
+ hmod = LocalLoadLibraryHelper(currLibNameVariation, dllImportSearchPathFlag, pErrorTracker);
+ if (hmod != NULL)
{
- hmod = LocalLoadLibraryHelper(currLibNameVariation, dllImportSearchPathFlag, pErrorTracker);
+ return hmod;
}
}
// This may be an assembly name
- if (!hmod)
+ // Format is "fileName, assemblyDisplayName"
+ MAKE_UTF8PTR_FROMWIDE(szLibName, wszLibName);
+ char *szComma = strchr(szLibName, ',');
+ if (szComma)
{
- // Format is "fileName, assemblyDisplayName"
- MAKE_UTF8PTR_FROMWIDE(szLibName, wszLibName);
- char *szComma = strchr(szLibName, ',');
- if (szComma)
- {
- *szComma = '\0';
- while (COMCharacter::nativeIsWhiteSpace(*(++szComma)));
+ *szComma = '\0';
+ // Trim white spaces
+ while (COMCharacter::nativeIsWhiteSpace(*(++szComma)));
- AssemblySpec spec;
- if (SUCCEEDED(spec.Init(szComma)))
+ AssemblySpec spec;
+ if (SUCCEEDED(spec.Init(szComma)))
+ {
+ // Need to perform case insensitive hashing.
+ CQuickBytes qbLC;
{
- // Need to perform case insensitive hashing.
- CQuickBytes qbLC;
- {
- UTF8_TO_LOWER_CASE(szLibName, qbLC);
- szLibName = (LPUTF8) qbLC.Ptr();
- }
+ UTF8_TO_LOWER_CASE(szLibName, qbLC);
+ szLibName = (LPUTF8) qbLC.Ptr();
+ }
- Assembly *pAssembly = spec.LoadAssembly(FILE_LOADED);
- Module *pModule = pAssembly->FindModuleByName(szLibName);
+ Assembly *pAssembly = spec.LoadAssembly(FILE_LOADED);
+ Module *pModule = pAssembly->FindModuleByName(szLibName);
- hmod = LocalLoadLibraryHelper(pModule->GetPath(), loadWithAlteredPathFlags | dllImportSearchPathFlag, pErrorTracker);
- }
+ hmod = LocalLoadLibraryHelper(pModule->GetPath(), loadWithAlteredPathFlags | dllImportSearchPathFlag, pErrorTracker);
}
}
- // After all this, if we have a handle add it to the cache.
- if (hmod)
+ return hmod;
+}
+
+// This Method returns an instance of the PAL-Registered handle
+HINSTANCE NDirect::LoadLibraryModule(NDirectMethodDesc * pMD, LoadLibErrorTracker * pErrorTracker)
+{
+ CONTRACTL
+ {
+ STANDARD_VM_CHECK;
+ PRECONDITION( CheckPointer( pMD ) );
+ }
+ CONTRACTL_END;
+
+ LPCUTF8 name = pMD->GetLibName();
+ if ( !name || !*name )
+ return NULL;
+
+ ModuleHandleHolder hmod;
+
+ PREFIX_ASSUME( name != NULL );
+ MAKE_WIDEPTR_FROMUTF8( wszLibName, name );
+
+ AppDomain* pDomain = GetAppDomain();
+
+ // AssemblyLoadContext is not supported in AppX mode and thus,
+ // we should not perform PInvoke resolution via it when operating in
+ // AppX mode.
+ if (!AppX::IsAppXProcess())
+ {
+ hmod = LoadLibraryModuleViaHost(pMD, pDomain, wszLibName);
+ if (hmod != NULL)
+ {
+#ifdef FEATURE_PAL
+ // Register the system library handle with PAL and get a PAL library handle
+ hmod = PAL_RegisterLibraryDirect(hmod, wszLibName);
+#endif // FEATURE_PAL
+ return hmod.Extract();
+ }
+ }
+
+ hmod = pDomain->FindUnmanagedImageInCache(wszLibName);
+ if (hmod != NULL)
+ {
+ // AppDomain caches the PAL_registered handles
+ // So, no need to PAL_Register the handle obtained from the cache
+ return hmod.Extract();
+ }
+
+#ifdef FEATURE_PAL
+ // In the PAL version of CoreCLR, the CLR module itself exports the functionality
+ // that the Windows version obtains from kernel32 and friends. In order to avoid
+ // picking up the wrong instance, we perform this redirection first.
+ // This is also true for CoreSystem builds, where mscorlib p/invokes are forwarded through coreclr
+ // itself so we can control CoreSystem library/API name re-mapping from one central location.
+ if (SString::_wcsicmp(wszLibName, MAIN_CLR_MODULE_NAME_W) == 0)
+ {
+ hmod = GetCLRModule();
+ }
+#endif // FEATURE_PAL
+
+ if (hmod == NULL)
+ {
+ hmod = LoadLibraryModuleBySearch(pMD, pErrorTracker, wszLibName);
+ if (hmod != NULL)
+ {
+#ifdef FEATURE_PAL
+ // Register the system library handle with PAL and get a PAL library handle
+ hmod = PAL_RegisterLibraryDirect(hmod, wszLibName);
+#endif // FEATURE_PAL
+ }
+ }
+
+ if (hmod != NULL)
{
+ // If we have a handle add it to the cache.
pDomain->AddUnmanagedImageToCache(wszLibName, hmod);
}
@@ -6655,7 +6668,7 @@ VOID NDirect::NDirectLink(NDirectMethodDesc *pMD)
}
WCHAR wszEPName[50];
- if(WszMultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pMD->GetEntrypointName(), -1, wszEPName, sizeof(wszEPName)/sizeof(WCHAR)) == 0)
+ if (WszMultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pMD->GetEntrypointName(), -1, wszEPName, sizeof(wszEPName)/sizeof(WCHAR)) == 0)
{
wszEPName[0] = W('?');
wszEPName[1] = W('\0');
diff --git a/src/vm/dllimport.h b/src/vm/dllimport.h
index a3842fca16..05336b43c6 100644
--- a/src/vm/dllimport.h
+++ b/src/vm/dllimport.h
@@ -77,7 +77,7 @@ public:
static HRESULT HasNAT_LAttribute(IMDInternalImport *pInternalImport, mdToken token, DWORD dwMemberAttrs);
static LPVOID NDirectGetEntryPoint(NDirectMethodDesc *pMD, HINSTANCE hMod);
- static HMODULE LoadLibraryFromPath(LPCWSTR libraryPath);
+ static NATIVE_LIBRARY_HANDLE LoadLibraryFromPath(LPCWSTR libraryPath);
static HINSTANCE LoadLibraryModule(NDirectMethodDesc * pMD, LoadLibErrorTracker *pErrorTracker);
@@ -121,10 +121,10 @@ public:
private:
NDirect() {LIMITED_METHOD_CONTRACT;}; // prevent "new"'s on this class
- static HMODULE LoadFromNativeDllSearchDirectories(AppDomain* pDomain, LPCWSTR libName, DWORD flags, LoadLibErrorTracker *pErrorTracker);
- static HMODULE LoadFromPInvokeAssemblyDirectory(Assembly *pAssembly, LPCWSTR libName, DWORD flags, LoadLibErrorTracker *pErrorTracker);
-
- static HMODULE LoadLibraryModuleViaHost(NDirectMethodDesc * pMD, AppDomain* pDomain, const wchar_t* wszLibName);
+ static NATIVE_LIBRARY_HANDLE LoadFromNativeDllSearchDirectories(AppDomain* pDomain, 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, AppDomain* pDomain, const wchar_t* wszLibName);
+ static NATIVE_LIBRARY_HANDLE LoadLibraryModuleBySearch(NDirectMethodDesc * pMD, LoadLibErrorTracker * pErrorTracker, const wchar_t* wszLibName);
#if !defined(FEATURE_PAL)
// Indicates if the OS supports the new secure LoadLibraryEx flags introduced in KB2533623