This mostly completes support for the attribute. Our algorithm differs a bit from CoreCLR right now, so we don't support the legacy behavior flag since it makes less since in the context of our algorithm, but this should be good enough for most cases.
DLLIMPORTSEARCHPATH_SAFE_DIRECTORIES = 0x1000,
DLLIMPORTSEARCHPATH_ASSEMBLY_DIRECTORY = 0x2, // search the assembly directory first regardless of platform, not passed on to LoadLibraryEx
} DllImportSearchPath;
-//static const int DLLIMPORTSEARCHPATH_LOADLIBRARY_FLAG_MASK = DLLIMPORTSEARCHPATH_USE_DLL_DIRECTORY_FOR_DEPENDENCIES | DLLIMPORTSEARCHPATH_APPLICATION_DIRECTORY |
-// DLLIMPORTSEARCHPATH_USER_DIRECTORIES | DLLIMPORTSEARCHPATH_SYSTEM32 | DLLIMPORTSEARCHPATH_SAFE_DIRECTORIES;
+#ifdef HOST_WIN32
+static const int DLLIMPORTSEARCHPATH_LOADLIBRARY_FLAG_MASK = DLLIMPORTSEARCHPATH_USE_DLL_DIRECTORY_FOR_DEPENDENCIES | DLLIMPORTSEARCHPATH_APPLICATION_DIRECTORY |
+ DLLIMPORTSEARCHPATH_USER_DIRECTORIES | DLLIMPORTSEARCHPATH_SYSTEM32 | DLLIMPORTSEARCHPATH_SAFE_DIRECTORIES;
+#endif
// This lock may be taken within an ALC lock, and should never be the other way around.
static MonoCoopMutex native_library_module_lock;
return g_hash_table_contains (native_library_module_blocklist, module);
}
+static int
+convert_dllimport_flags (int flags)
+{
+#ifdef HOST_WIN32
+ return flags & DLLIMPORTSEARCHPATH_LOADLIBRARY_FLAG_MASK;
+#else
+ // DllImportSearchPath is Windows-only, other than DLLIMPORTSEARCHPATH_ASSEMBLY_DIRECTORY
+ return 0;
+#endif
+}
+
static MonoDl *
-netcore_probe_for_module_variations (const char *mdirname, const char *file_name)
+netcore_probe_for_module_variations (const char *mdirname, const char *file_name, int raw_flags)
{
void *iter = NULL;
char *full_name;
MonoDl *module = NULL;
- // This does not actually mirror CoreCLR's algorithm; if that becomes a problem, potentially use theirs
// FIXME: this appears to search *.dylib twice for some reason
while ((full_name = mono_dl_build_path (mdirname, file_name, &iter)) && module == NULL) {
char *error_msg;
- module = mono_dl_open (full_name, MONO_DL_LAZY, &error_msg);
+ module = mono_dl_open_full (full_name, MONO_DL_LAZY, raw_flags, &error_msg);
if (!module) {
mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "DllImport error loading library '%s': '%s'.", full_name, error_msg);
g_free (error_msg);
netcore_probe_for_module (MonoImage *image, const char *file_name, int flags)
{
MonoDl *module = NULL;
+ int lflags = convert_dllimport_flags (flags);
+
+ // TODO: this algorithm doesn't quite match CoreCLR, so respecting DLLIMPORTSEARCHPATH_LEGACY_BEHAVIOR makes little sense
+ // If the difference becomes a problem, overhaul this algorithm to match theirs exactly
// Try without any path additions
- module = netcore_probe_for_module_variations (NULL, file_name);
+ module = netcore_probe_for_module_variations (NULL, file_name, lflags);
// Check the NATIVE_DLL_SEARCH_DIRECTORIES
for (int i = 0; i < pinvoke_search_directories_count && module == NULL; ++i)
- module = netcore_probe_for_module_variations (pinvoke_search_directories[i], file_name);
+ module = netcore_probe_for_module_variations (pinvoke_search_directories[i], file_name, lflags);
// Check the assembly directory if the search flag is set and the image exists
if (flags & DLLIMPORTSEARCHPATH_ASSEMBLY_DIRECTORY && image != NULL && module == NULL) {
char *mdirname = g_path_get_dirname (image->filename);
if (mdirname)
- module = netcore_probe_for_module_variations (mdirname, file_name);
+ module = netcore_probe_for_module_variations (mdirname, file_name, lflags);
g_free (mdirname);
}
}
int
-mono_dl_convert_flags (int flags)
+mono_dl_convert_flags (int mono_flags, int native_flags)
{
- int lflags = 0;
+ int lflags = native_flags;
#ifdef ENABLE_NETCORE
// Specifying both will default to LOCAL
- if (flags & MONO_DL_GLOBAL && !(flags & MONO_DL_LOCAL))
+ if (mono_flags & MONO_DL_GLOBAL && !(mono_flags & MONO_DL_LOCAL))
lflags |= RTLD_GLOBAL;
else
lflags |= RTLD_LOCAL;
#else
- lflags = flags & MONO_DL_LOCAL ? RTLD_LOCAL : RTLD_GLOBAL;
+ lflags = mono_flags & MONO_DL_LOCAL ? RTLD_LOCAL : RTLD_GLOBAL;
#endif
- if (flags & MONO_DL_LAZY)
+ if (mono_flags & MONO_DL_LAZY)
lflags |= RTLD_LAZY;
else
lflags |= RTLD_NOW;
return g_strdup ("");
}
-
+// Copied from mono-dl-posix.c
int
-mono_dl_convert_flags (int flags)
+mono_dl_convert_flags (int mono_flags, int native_flags)
{
- int lflags = 0;
+ int lflags = native_flags;
#ifdef ENABLE_NETCORE
// Specifying both will default to LOCAL
- if (flags & MONO_DL_LOCAL)
- lflags |= RTLD_LOCAL;
- else if (flags & MONO_DL_GLOBAL)
+ if (mono_flags & MONO_DL_GLOBAL && !(mono_flags & MONO_DL_LOCAL))
lflags |= RTLD_GLOBAL;
+ else
+ lflags |= RTLD_LOCAL;
#else
- lflags = flags & MONO_DL_LOCAL ? RTLD_LOCAL : RTLD_GLOBAL;
+ lflags = mono_flags & MONO_DL_LOCAL ? RTLD_LOCAL : RTLD_GLOBAL;
#endif
- if (flags & MONO_DL_LAZY)
+ if (mono_flags & MONO_DL_LAZY)
lflags |= RTLD_LAZY;
else
lflags |= RTLD_NOW;
guint32 last_error = 0;
#if HAVE_API_SUPPORT_WIN32_LOAD_LIBRARY
- hModule = LoadLibraryW (file_utf16);
+ hModule = LoadLibraryExW (file_utf16, NULL, flags);
#elif HAVE_API_SUPPORT_WIN32_LOAD_PACKAGED_LIBRARY
hModule = LoadPackagedLibrary (file_utf16, NULL);
#else
}
int
-mono_dl_convert_flags (int flags)
+mono_dl_convert_flags (int mono_flags, int native_flags)
{
- return 0;
+ // Mono flags are not applicable on Windows
+ return native_flags;
}
#if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
MonoDl*
mono_dl_open (const char *name, int flags, char **error_msg)
{
+ return mono_dl_open_full (name, flags, 0, error_msg);
+}
+
+MonoDl *
+mono_dl_open_full (const char *name, int mono_flags, int native_flags, char **error_msg)
+{
MonoDl *module;
void *lib;
MonoDlFallbackHandler *dl_fallback = NULL;
- int lflags = mono_dl_convert_flags (flags);
+ int lflags = mono_dl_convert_flags (mono_flags, native_flags);
char *found_name;
if (error_msg)
MonoDl* mono_dl_open_runtime_lib (const char *lib_name, int flags, char **error_msg);
-MonoDl* mono_dl_open_self (char **error_msg);
+MonoDl *
+mono_dl_open_self (char **error_msg);
+// This converts the MONO_DL_* enum to native flags, combines it with the other flags passed, and resolves some inconsistencies
+MonoDl *
+mono_dl_open_full (const char *name, int mono_flags, int native_flags, char **error_msg);
//Platform API for mono_dl
void* mono_dl_open_file (const char *file, int flags);
void mono_dl_close_handle (MonoDl *module);
void* mono_dl_lookup_symbol (MonoDl *module, const char *name);
-int mono_dl_convert_flags (int flags);
+int mono_dl_convert_flags (int mono_flags, int native_flags);
char* mono_dl_current_error_string (void);
int mono_dl_get_executable_path (char *buf, int buflen);
const char* mono_dl_get_system_dir (void);