Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,35 @@ 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)
{
hmod = Interop.Kernel32.LoadLibraryEx(libraryName, IntPtr.Zero, (int)((uint)flags & 0xFFFFFF00));
if (hmod != IntPtr.Zero)
{
return hmod;
goto exit;
}

int lastError = Marshal.GetLastWin32Error();
int lastError = Marshal.GetLastPInvokeError();
if (lastError != Interop.Errors.ERROR_INVALID_PARAMETER)
{
errorTracker.TrackErrorCode(lastError);
return hmod;
goto exit;
}
}

hmod = Interop.Kernel32.LoadLibraryEx(libraryName, IntPtr.Zero, flags & 0xFF);
if (hmod == IntPtr.Zero)
{
errorTracker.TrackErrorCode(Marshal.GetLastWin32Error());
errorTracker.TrackErrorCode(Marshal.GetLastPInvokeError());
}

exit:
if (set)
{
Interop.Kernel32.SetThreadErrorMode(prev, out _);
}

return hmod;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,12 @@ internal static IntPtr LoadBySearch(Assembly callingAssembly, bool searchAssembl
else if ((callingAssembly != null) && searchAssemblyDirectory)
{
// Try to load the module alongside the assembly where the PInvoke was declared.
// This only makes sense in dynamic scenarios (JIT/interpreter), so leaving this out for now.
// For PInvokes where the DllImportSearchPath.AssemblyDirectory is specified, look next to the application.
ret = LoadLibraryHelper(Path.Combine(AppContext.BaseDirectory, currLibNameVariation), loadWithAlteredPathFlags | dllImportSearchPathFlags, ref errorTracker);
if (ret != IntPtr.Zero)
{
return ret;
}
}

ret = LoadLibraryHelper(currLibNameVariation, dllImportSearchPathFlags, ref errorTracker);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ internal static partial bool SetThreadErrorMode(
uint dwNewMode,
out uint lpOldMode);

internal const uint SEM_FAILCRITICALERRORS = 1;
internal const int SEM_FAILCRITICALERRORS = 0x00000001;
internal const int SEM_NOOPENFILEERRORBOX = 0x00008000;
}
}
22 changes: 22 additions & 0 deletions src/tests/Interop/DllImportSearchPaths/DllImportSearchPathsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ public static void AssemblyDirectory_Found()
Assert.Equal(3, sum);
}

[ConditionalFact(typeof(TestLibrary.Utilities), nameof(TestLibrary.Utilities.IsNativeAot))]
public static void AssemblyDirectoryAot_Found()
{
int sum = NativeLibraryPInvokeAot.Sum(1, 2);
Assert.Equal(3, sum);
}

[Fact]
[PlatformSpecific(TestPlatforms.Windows)]
public static void AssemblyDirectory_Fallback_Found()
Expand Down Expand Up @@ -70,3 +77,18 @@ public static int Sum(int a, int b)
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)]
static extern int NativeSum(int arg1, int arg2);
}

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

// For NativeAOT, validate the case where the native library is next to the AOT application.
// The passing of DllImportSearchPath.System32 is done to ensure on Windows the runtime won't fallback
// and try to search the application directory by default.
[DllImport(NativeLibraryToLoad.Name + "-in-native")]
[DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory | DllImportSearchPath.System32)]
static extern int NativeSum(int arg1, int arg2);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,24 @@

<Target Name="SetUpSubdirectoryNative" AfterTargets="CopyNativeProjectBinaries">
<ItemGroup>
<_FilesToMove Include="$(OutDir)/libNativeLibrary.*" />
<_FilesToMove Include="$(OutDir)/NativeLibrary.*" />
<NativeLibrariesToMove Include="$(OutDir)/libNativeLibrary.*" />
<NativeLibrariesToMove Include="$(OutDir)/NativeLibrary.*" />
</ItemGroup>
<Move SourceFiles="@(_FilesToMove)" DestinationFiles="@(_FilesToMove -> '$(LibrarySubdirectory)/%(Filename)%(Extension)')"/>
<Move SourceFiles="@(NativeLibrariesToMove)" DestinationFiles="@(NativeLibrariesToMove -> '$(LibrarySubdirectory)/%(Filename)%(Extension)')"/>
</Target>

<Target Name="SetUpSubdirectoryManaged" AfterTargets="Build">
<ItemGroup>
<_FilesToCopy Include="$(OutDir)/$(TargetName).dll" />
<AssembliesToCopy Include="$(OutDir)/$(TargetName).dll" />
</ItemGroup>
<Copy SourceFiles="@(_FilesToCopy)" DestinationFiles="@(_FilesToCopy -> '$(LibrarySubdirectory)/%(Filename)%(Extension)')"/>
<Copy SourceFiles="@(AssembliesToCopy)" DestinationFiles="@(AssembliesToCopy -> '$(LibrarySubdirectory)/%(Filename)%(Extension)')"/>
</Target>

<Target Name="SetUpAOTDirectory" Condition="'$(TestBuildMode)' == 'nativeaot'" AfterTargets="Build">
<ItemGroup>
<NativeLibrariesToCopy Include="$(LibrarySubdirectory)/libNativeLibrary.*" />
<NativeLibrariesToCopy Include="$(LibrarySubdirectory)/NativeLibrary.*" />
</ItemGroup>
<Copy SourceFiles="@(NativeLibrariesToCopy)" DestinationFiles="@(NativeLibrariesToCopy -> '$(NativeOutputPath)/%(Filename)-in-native%(Extension)')" />
</Target>
</Project>
10 changes: 10 additions & 0 deletions src/tests/Interop/NativeLibrary/API/NativeLibraryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,16 @@ public void LoadLibrary_AssemblyDirectory()
EXPECT(TryLoadLibrary_WithAssembly(libName, assemblyInSubdirectory, DllImportSearchPath.AssemblyDirectory));
}

if (TestLibrary.Utilities.IsNativeAot)
{
// For NativeAOT, validate the case where the native library is next to the AOT application.
// The passing of DllImportSearchPath.System32 is done to ensure on Windows the runtime won't fallback
// and try to search the application directory by default.
string libNameAot = $"{NativeLibraryToLoad.Name}-in-native";
EXPECT(LoadLibrary_WithAssembly(libNameAot, assembly, DllImportSearchPath.AssemblyDirectory | DllImportSearchPath.System32));
EXPECT(TryLoadLibrary_WithAssembly(libNameAot, assembly, DllImportSearchPath.AssemblyDirectory | DllImportSearchPath.System32));
}

if (OperatingSystem.IsWindows())
{
string currentDirectory = Environment.CurrentDirectory;
Expand Down
14 changes: 11 additions & 3 deletions src/tests/Interop/NativeLibrary/API/NativeLibraryTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@

<Target Name="SetUpSubdirectoryNative" AfterTargets="CopyNativeProjectBinaries">
<ItemGroup>
<AssembliesToCopy Include="$(OutDir)/libNativeLibrary.*" />
<AssembliesToCopy Include="$(OutDir)/NativeLibrary.*" />
<NativeLibrariesToCopy Include="$(OutDir)/libNativeLibrary.*" />
<NativeLibrariesToCopy Include="$(OutDir)/NativeLibrary.*" />
</ItemGroup>
<Copy SourceFiles="@(AssembliesToCopy)" DestinationFiles="@(AssembliesToCopy -> '$(LibrarySubdirectory)/%(Filename)$(FileNameSuffix)%(Extension)')" />
<Copy SourceFiles="@(NativeLibrariesToCopy)" DestinationFiles="@(NativeLibrariesToCopy -> '$(LibrarySubdirectory)/%(Filename)$(FileNameSuffix)%(Extension)')" />
</Target>

<Target Name="SetUpSubdirectoryManaged" AfterTargets="Build">
Expand All @@ -36,4 +36,12 @@
</ItemGroup>
<Copy SourceFiles="@(AssembliesToCopy)" DestinationFiles="@(AssembliesToCopy -> '$(LibrarySubdirectory)/%(Filename)$(FileNameSuffix)%(Extension)')" />
</Target>

<Target Name="SetUpAOTDirectory" Condition="'$(TestBuildMode)' == 'nativeaot'" AfterTargets="Build">
<ItemGroup>
<NativeLibrariesToCopyAOT Include="$(OutDir)/libNativeLibrary.*" />
<NativeLibrariesToCopyAOT Include="$(OutDir)/NativeLibrary.*" />
</ItemGroup>
<Copy SourceFiles="@(NativeLibrariesToCopyAOT)" DestinationFiles="@(NativeLibrariesToCopyAOT -> '$(NativeOutputPath)/%(Filename)-in-native%(Extension)')" />
</Target>
</Project>
3 changes: 0 additions & 3 deletions src/tests/issues.targets
Original file line number Diff line number Diff line change
Expand Up @@ -778,9 +778,6 @@
<ExcludeList Include="$(XunitTestBinBase)/Interop/MarshalAPI/FunctionPointer/FunctionPtrTest/*">
<Issue>https://github.com/dotnet/runtimelab/issues/164</Issue>
</ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/Interop/NativeLibrary/API/NativeLibraryTests/*">
<Issue>https://github.com/dotnet/runtimelab/issues/165</Issue>
</ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/Interop/NativeLibrary/AssemblyLoadContext/ResolveUnmanagedDllTests/*">
<Issue>https://github.com/dotnet/runtimelab/issues/165</Issue>
</ExcludeList>
Expand Down