Skip to content

Commit

Permalink
Merge pull request #84639 from vseanreesermsft/internal-merge-6.0-202…
Browse files Browse the repository at this point in the history
…3-04-11-1027

Merging internal commits for release/6.0
  • Loading branch information
carlossanlop authored Apr 11, 2023
2 parents 300ceb8 + f40a2d9 commit fcd2831
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,9 @@ static MsQuicApi()
return;
}

if (!NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out IntPtr msQuicHandle))
// Windows ships msquic in the assembly directory. Non-Windows relies an the package being installed on the system.
DllImportSearchPath? searchPath = OperatingSystem.IsWindows() ? DllImportSearchPath.AssemblyDirectory : null;
if (!NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, searchPath, out IntPtr msQuicHandle))
{
// MsQuic library not loaded
return;
Expand Down
25 changes: 18 additions & 7 deletions src/mono/mono/metadata/native-library.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ mono_dllmap_lookup_list (MonoDllMap *dll_map, const char *dll, const char* func,
if (!dll_map)
goto exit;

/*
/*
* we use the first entry we find that matches, since entries from
* the config file are prepended to the list and we document that the
* later entries win.
Expand Down Expand Up @@ -254,7 +254,7 @@ mono_global_dllmap_cleanup (void)
* This function is used to programatically add \c DllImport remapping in either
* a specific assembly, or as a global remapping. This is done by remapping
* references in a \c DllImport attribute from the \p dll library name into the \p tdll
* name. If the \p dll name contains the prefix <code>i:</code>, the comparison of the
* name. If the \p dll name contains the prefix <code>i:</code>, the comparison of the
* library name is done without case sensitivity.
*
* If you pass \p func, this is the name of the \c EntryPoint in a \c DllImport if specified
Expand Down Expand Up @@ -518,8 +518,11 @@ netcore_probe_for_module (MonoImage *image, const char *file_name, int 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
#if defined(HOST_ANDROID)
// On Android, try without any path additions first. It is sensitive to probing that will always miss
// and lookup for some libraries is required to use a relative path
module = netcore_probe_for_module_variations (NULL, file_name, lflags);
#endif

// Check the NATIVE_DLL_SEARCH_DIRECTORIES
for (int i = 0; i < pinvoke_search_directories_count && module == NULL; ++i)
Expand All @@ -533,6 +536,14 @@ netcore_probe_for_module (MonoImage *image, const char *file_name, int flags)
g_free (mdirname);
}

#if !defined(HOST_ANDROID)
// Try without any path additions
if (module == NULL)
{
module = netcore_probe_for_module_variations (NULL, file_name, lflags);
}
#endif

// TODO: Pass remaining flags on to LoadLibraryEx on Windows where appropriate, see https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.dllimportsearchpath?view=netcore-3.1

return module;
Expand Down Expand Up @@ -1048,7 +1059,7 @@ lookup_pinvoke_call_impl (MonoMethod *method, MonoLookupPInvokeStatus *status_ou
mono_custom_attrs_free (cinfo);
}
if (flags < 0)
flags = 0;
flags = DLLIMPORTSEARCHPATH_ASSEMBLY_DIRECTORY;
module = netcore_lookup_native_library (alc, image, new_scope, flags);

if (!module) {
Expand Down Expand Up @@ -1154,7 +1165,7 @@ pinvoke_probe_for_symbol (MonoDl *module, MonoMethodPInvoke *piinfo, const char

#if HOST_WIN32 && HOST_X86
/* Try the stdcall mangled name */
/*
/*
* gcc under windows creates mangled names without the underscore, but MS.NET
* doesn't support it, so we doesn't support it either.
*/
Expand Down Expand Up @@ -1394,7 +1405,7 @@ mono_loader_save_bundled_library (int fd, uint64_t offset, uint64_t size, const
char *file, *buffer, *err, *internal_path;
if (!bundle_save_library_initialized)
bundle_save_library_initialize ();

file = g_build_filename (bundled_dylibrary_directory, destfname, (const char*)NULL);
buffer = g_str_from_file_region (fd, offset, size);
g_file_set_contents (file, buffer, size, NULL);
Expand All @@ -1409,7 +1420,7 @@ mono_loader_save_bundled_library (int fd, uint64_t offset, uint64_t size, const
mono_loader_register_module (internal_path, lib);
g_free (internal_path);
bundle_library_paths = g_slist_append (bundle_library_paths, file);

g_free (buffer);
}

Expand Down
3 changes: 3 additions & 0 deletions src/tests/Common/CoreCLRTestLibrary/Utilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ public static bool Verbose
public static bool IsWindows7 => IsWindows && Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor == 1;
public static bool IsWindowsNanoServer => (!IsWindowsIoTCore && GetInstallationType().Equals("Nano Server", StringComparison.OrdinalIgnoreCase));

private static string _variant = Environment.GetEnvironmentVariable("DOTNET_RUNTIME_VARIANT");
public static bool IsMonoLLVMFULLAOT => _variant == "llvmfullaot";

// Windows 10 October 2018 Update
public static bool IsWindows10Version1809OrGreater =>
IsWindows && GetWindowsVersion() == 10 && GetWindowsMinorVersion() == 0 && GetWindowsBuildNumber() >= 17763;
Expand Down
4 changes: 4 additions & 0 deletions src/tests/Common/testenvironment.proj
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@
<!-- Mono interpreter -->
<_TestEnvFileLine Condition="'$(RuntimeVariant)' == 'monointerpreter'" Include="set MONO_ENV_OPTIONS=--interpreter" />

<_TestEnvFileLine Condition="'$(RuntimeVariant)' != ''" Include="set DOTNET_RUNTIME_VARIANT=$(RuntimeVariant)" />

<!-- CLR interpreter -->
<_TestEnvFileLine Condition="'$(Scenario)' == 'clrinterpreter'" Include="set COMPlus_Interpret=%2A" /> <!-- %2A is asterisk / wildcard -->
<_TestEnvFileLine Condition="'$(Scenario)' == 'clrinterpreter'" Include="set COMPlus_InterpreterHWIntrinsicsIsSupportedFalse=1" />
Expand All @@ -216,6 +218,8 @@
<!-- Mono interpreter -->
<_TestEnvFileLine Condition="'$(RuntimeVariant)' == 'monointerpreter'" Include="export MONO_ENV_OPTIONS=--interpreter" />

<_TestEnvFileLine Condition="'$(RuntimeVariant)' != ''" Include="export DOTNET_RUNTIME_VARIANT=$(RuntimeVariant)" />

<!-- Hack: Use Mono LLVM JIT when JIT-compiling the non-AOT-compiled parts of the runtime tests -->
<_TestEnvFileLine Condition="'$(RuntimeVariant)' == 'llvmaot'" Include="export MONO_ENV_OPTIONS=--llvm" />

Expand Down
79 changes: 79 additions & 0 deletions src/tests/Interop/DllImportSearchPaths/DllImportSearchPathsTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using Xunit;

public class DllImportSearchPathsTest
{
private static string Subdirectory => Path.Combine(NativeLibraryToLoad.GetDirectory(), "subdirectory");

static int Main(string[] args)
{
try
{
AssemblyDirectory_NotFound();
if (!TestLibrary.Utilities.IsMonoLLVMFULLAOT)
AssemblyDirectory_Found();

if (OperatingSystem.IsWindows())
AssemblyDirectory_Fallback_Found();
}
catch (Exception e)
{
Console.WriteLine($"Test Failure: {e}");
return 101;
}

return 100;
}

public static void AssemblyDirectory_NotFound()
{
// Library should not be found in the assembly directory
Assert.Throws<DllNotFoundException>(() => NativeLibraryPInvoke.Sum(1, 2));
}

public static void AssemblyDirectory_Found()
{
// Library should be found in the assembly directory
var assembly = Assembly.LoadFile(Path.Combine(Subdirectory, $"{nameof(DllImportSearchPathsTest)}.dll"));
var type = assembly.GetType(nameof(NativeLibraryPInvoke));
var method = type.GetMethod(nameof(NativeLibraryPInvoke.Sum));

int sum = (int)method.Invoke(null, new object[] { 1, 2 });
Assert.Equal(3, sum);
}

public static void AssemblyDirectory_Fallback_Found()
{
string currentDirectory = Environment.CurrentDirectory;
try
{
Environment.CurrentDirectory = Subdirectory;

// Library should not be found in the assembly directory, but should fall back to the default OS search which includes CWD on Windows
int sum = NativeLibraryPInvoke.Sum(1, 2);
Assert.Equal(3, sum);
}
finally
{
Environment.CurrentDirectory = currentDirectory;
}
}
}

public class NativeLibraryPInvoke
{
public static int Sum(int a, int b)
{
return NativeSum(a, b);
}

[DllImport(NativeLibraryToLoad.Name)]
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
static extern int NativeSum(int arg1, int arg2);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Compile Include="*.cs" />
<Compile Include="../NativeLibrary/NativeLibraryToLoad/NativeLibraryToLoad.cs" />
<ProjectReference Include="../NativeLibrary/NativeLibraryToLoad/CMakeLists.txt" />
</ItemGroup>

<Target Name="SetUpSubdirectory" AfterTargets="CopyNativeProjectBinaries">
<PropertyGroup>
<NativeLibrarySubdirectory>$(OutDir)/subdirectory</NativeLibrarySubdirectory>
<FileNameSuffix>-in-subdirectory</FileNameSuffix>
</PropertyGroup>
<ItemGroup>
<_FilesToCopy Include="$(OutDir)/$(TargetName).dll" />
<_FilesToMove Include="$(OutDir)/libNativeLibrary.*" />
<_FilesToMove Include="$(OutDir)/NativeLibrary.*" />
</ItemGroup>
<Copy SourceFiles="@(_FilesToCopy)" DestinationFiles="@(_FilesToCopy -> '$(NativeLibrarySubdirectory)/%(Filename)%(Extension)')" />
<Move SourceFiles="@(_FilesToMove)" DestinationFiles="@(_FilesToMove -> '$(NativeLibrarySubdirectory)/%(Filename)%(Extension)')" />
</Target>
</Project>
42 changes: 40 additions & 2 deletions src/tests/Interop/NativeLibrary/API/NativeLibraryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,13 +110,22 @@ public static int Main()
if (TestLibrary.Utilities.IsWindows &&
File.Exists(Path.Combine(Environment.SystemDirectory, libName)))
{
// Calls on a valid library from System32 directory
// Library should be found in the system directory
success &= EXPECT(LoadLibraryAdvanced(libName, assembly, DllImportSearchPath.System32));
success &= EXPECT(TryLoadLibraryAdvanced(libName, assembly, DllImportSearchPath.System32));

// Calls on a valid library from application directory
// Library should not be found in the assembly directory and should be found in the system directory
success &= EXPECT(LoadLibraryAdvanced(libName, assembly, DllImportSearchPath.AssemblyDirectory | DllImportSearchPath.System32));
success &= EXPECT(TryLoadLibraryAdvanced(libName, assembly, DllImportSearchPath.AssemblyDirectory | DllImportSearchPath.System32));

// Library should not be found in the assembly directory, but should fall back to the default OS search which includes CWD on Windows
success &= EXPECT(LoadLibraryAdvanced(libName, assembly, DllImportSearchPath.AssemblyDirectory));
success &= EXPECT(TryLoadLibraryAdvanced(libName, assembly, DllImportSearchPath.AssemblyDirectory));

// Library should not be found in application directory
success &= EXPECT(LoadLibraryAdvanced(libName, assembly, DllImportSearchPath.ApplicationDirectory), TestResult.DllNotFound);
success &= EXPECT(TryLoadLibraryAdvanced(libName, assembly, DllImportSearchPath.ApplicationDirectory), TestResult.ReturnFailure);

}

// Calls with null libName input
Expand All @@ -134,6 +143,35 @@ public static int Main()
success &= EXPECT(LoadLibraryAdvanced(libName, assembly, DllImportSearchPath.AssemblyDirectory), TestResult.DllNotFound);
success &= EXPECT(TryLoadLibraryAdvanced(libName, assembly, DllImportSearchPath.AssemblyDirectory), TestResult.ReturnFailure);

string suffix = "-in-subdirectory";
libName = $"{NativeLibraryToLoad.Name}{suffix}";
string subdirectory = Path.Combine(testBinDir, "subdirectory");

if (!TestLibrary.Utilities.IsMonoLLVMFULLAOT)
{
// Library should be found in the assembly directory
Assembly assemblyInSubdirectory = Assembly.LoadFile(Path.Combine(subdirectory, $"{Path.GetFileNameWithoutExtension(assembly.Location)}{suffix}.dll"));
EXPECT(LoadLibraryAdvanced(libName, assemblyInSubdirectory, DllImportSearchPath.AssemblyDirectory));
EXPECT(TryLoadLibraryAdvanced(libName, assemblyInSubdirectory, DllImportSearchPath.AssemblyDirectory));
}

if (OperatingSystem.IsWindows())
{
string currentDirectory = Environment.CurrentDirectory;
try
{
Environment.CurrentDirectory = subdirectory;

// Library should not be found in the assembly directory, but should fall back to the default OS search which includes CWD on Windows
EXPECT(LoadLibraryAdvanced(libName, assembly, DllImportSearchPath.AssemblyDirectory));
EXPECT(TryLoadLibraryAdvanced(libName, assembly, DllImportSearchPath.AssemblyDirectory));
}
finally
{
Environment.CurrentDirectory = currentDirectory;
}
}

// -----------------------------------------------
// FreeLibrary Tests
// -----------------------------------------------
Expand Down
13 changes: 13 additions & 0 deletions src/tests/Interop/NativeLibrary/API/NativeLibraryTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,17 @@
<ProjectReference Include="$(TestSourceDir)Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj" />
<ProjectReference Include="../NativeLibraryToLoad/CMakeLists.txt" />
</ItemGroup>

<Target Name="SetUpSubdirectory" AfterTargets="CopyNativeProjectBinaries">
<PropertyGroup>
<NativeLibrarySubdirectory>$(OutDir)/subdirectory</NativeLibrarySubdirectory>
<FileNameSuffix>-in-subdirectory</FileNameSuffix>
</PropertyGroup>
<ItemGroup>
<AssembliesToCopy Include="$(OutDir)/libNativeLibrary.*" />
<AssembliesToCopy Include="$(OutDir)/NativeLibrary.*" />
<AssembliesToCopy Include="$(OutDir)/$(TargetName).dll" />
</ItemGroup>
<Copy SourceFiles="@(AssembliesToCopy)" DestinationFiles="@(AssembliesToCopy -> '$(NativeLibrarySubdirectory)/%(Filename)$(FileNameSuffix)%(Extension)')" />
</Target>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,11 @@ public static string GetFileName()

public static string GetFullPath()
{
Assembly assembly = Assembly.GetExecutingAssembly();
string directory = Path.GetDirectoryName(assembly.Location);
return Path.Combine(directory, GetFileName());
return Path.Combine(GetDirectory(), GetFileName());
}

public static string GetDirectory()
{
return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
}
}

0 comments on commit fcd2831

Please sign in to comment.