Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit f1933b7

Browse files
Move Native Library APIs to NativeLibrary class
Move APIs that manipulate native libraries from System.Runtime.InteropServices.Marshal class to the new System.Runtime.InteropServices.NativeLibrary class. In API review: #32015, The LoadLibrary APIs were originally Approved to live in System.Runtime.InteropServices.Marshal class. However, recently the decision was changed such that the APIs are in a new NativeLibrary class.
1 parent 88eb93a commit f1933b7

16 files changed

+689
-625
lines changed

src/System.Private.CoreLib/System.Private.CoreLib.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@
288288
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\InvalidComObjectException.cs" />
289289
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\InvalidOleVariantTypeException.cs" />
290290
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\Marshal.cs" />
291+
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\NativeLibrary.cs" />
291292
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\NonPortable.cs" Condition="'$(FeatureCominterop)' != 'true'" />
292293
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\PInvokeMap.cs" />
293294
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\PInvokeMarshal.cs" />

src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs

-159
Original file line numberDiff line numberDiff line change
@@ -1788,164 +1788,5 @@ public static unsafe void ZeroFreeGlobalAllocUnicode(IntPtr s)
17881788
RuntimeImports.RhZeroMemory(s, (UIntPtr)(string.wcslen((char*)s) * 2));
17891789
FreeHGlobal(s);
17901790
}
1791-
1792-
/// APIs for managing Native Libraries
1793-
1794-
/// <summary>
1795-
/// NativeLibrary Loader: Simple API
1796-
/// This method is a wrapper around OS loader, using "default" flags.
1797-
/// </summary>
1798-
/// <param name="libraryPath">The name of the native library to be loaded</param>
1799-
/// <returns>The handle for the loaded native library</returns>
1800-
/// <exception cref="System.ArgumentNullException">If libraryPath is null</exception>
1801-
/// <exception cref="System.DllNotFoundException ">If the library can't be found.</exception>
1802-
/// <exception cref="System.BadImageFormatException">If the library is not valid.</exception>
1803-
public static IntPtr LoadLibrary(string libraryPath)
1804-
{
1805-
if (libraryPath == null)
1806-
throw new ArgumentNullException(nameof(libraryPath));
1807-
1808-
return LoadLibraryFromPath(libraryPath, throwOnError: true);
1809-
}
1810-
1811-
/// <summary>
1812-
/// NativeLibrary Loader: Simple API that doesn't throw
1813-
/// </summary>
1814-
/// <param name="libraryPath">The name of the native library to be loaded</param>
1815-
/// <param name="handle">The out-parameter for the loaded native library handle</param>
1816-
/// <returns>True on successful load, false otherwise</returns>
1817-
/// <exception cref="System.ArgumentNullException">If libraryPath is null</exception>
1818-
public static bool TryLoadLibrary(string libraryPath, out IntPtr handle)
1819-
{
1820-
if (libraryPath == null)
1821-
throw new ArgumentNullException(nameof(libraryPath));
1822-
1823-
handle = LoadLibraryFromPath(libraryPath, throwOnError: false);
1824-
return handle != IntPtr.Zero;
1825-
}
1826-
1827-
/// <summary>
1828-
/// NativeLibrary Loader: High-level API
1829-
/// Given a library name, this function searches specific paths based on the
1830-
/// runtime configuration, input parameters, and attributes of the calling assembly.
1831-
/// If DllImportSearchPath parameter is non-null, the flags in this enumeration are used.
1832-
/// Otherwise, the flags specified by the DefaultDllImportSearchPaths attribute on the
1833-
/// calling assembly (if any) are used.
1834-
/// This LoadLibrary() method does not invoke the managed call-backs for native library resolution:
1835-
/// * AssemblyLoadContext.LoadUnmanagedDll()
1836-
/// </summary>
1837-
/// <param name="libraryName">The name of the native library to be loaded</param>
1838-
/// <param name="assembly">The assembly loading the native library</param>
1839-
/// <param name="searchPath">The search path</param>
1840-
/// <returns>The handle for the loaded library</returns>
1841-
/// <exception cref="System.ArgumentNullException">If libraryPath or assembly is null</exception>
1842-
/// <exception cref="System.ArgumentException">If assembly is not a RuntimeAssembly</exception>
1843-
/// <exception cref="System.DllNotFoundException ">If the library can't be found.</exception>
1844-
/// <exception cref="System.BadImageFormatException">If the library is not valid.</exception>
1845-
public static IntPtr LoadLibrary(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
1846-
{
1847-
if (libraryName == null)
1848-
throw new ArgumentNullException(nameof(libraryName));
1849-
if (assembly == null)
1850-
throw new ArgumentNullException(nameof(assembly));
1851-
if (!(assembly is RuntimeAssembly))
1852-
throw new ArgumentException(SR.Argument_MustBeRuntimeAssembly);
1853-
1854-
return LoadLibraryByName(libraryName,
1855-
((RuntimeAssembly)assembly).GetNativeHandle(),
1856-
searchPath.HasValue,
1857-
(uint) searchPath.GetValueOrDefault(),
1858-
throwOnError: true);
1859-
}
1860-
1861-
/// <summary>
1862-
/// NativeLibrary Loader: High-level API that doesn't throw.
1863-
/// </summary>
1864-
/// <param name="libraryName">The name of the native library to be loaded</param>
1865-
/// <param name="searchPath">The search path</param>
1866-
/// <param name="assembly">The assembly loading the native library</param>
1867-
/// <param name="handle">The out-parameter for the loaded native library handle</param>
1868-
/// <returns>True on successful load, false otherwise</returns>
1869-
/// <exception cref="System.ArgumentNullException">If libraryPath or assembly is null</exception>
1870-
/// <exception cref="System.ArgumentException">If assembly is not a RuntimeAssembly</exception>
1871-
public static bool TryLoadLibrary(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, out IntPtr handle)
1872-
{
1873-
if (libraryName == null)
1874-
throw new ArgumentNullException(nameof(libraryName));
1875-
if (assembly == null)
1876-
throw new ArgumentNullException(nameof(assembly));
1877-
if (!(assembly is RuntimeAssembly))
1878-
throw new ArgumentException(SR.Argument_MustBeRuntimeAssembly);
1879-
1880-
handle = LoadLibraryByName(libraryName,
1881-
((RuntimeAssembly)assembly).GetNativeHandle(),
1882-
searchPath.HasValue,
1883-
(uint) searchPath.GetValueOrDefault(),
1884-
throwOnError: false);
1885-
return handle != IntPtr.Zero;
1886-
}
1887-
1888-
/// <summary>
1889-
/// Free a loaded library
1890-
/// Given a library handle, free it.
1891-
/// No action if the input handle is null.
1892-
/// </summary>
1893-
/// <param name="handle">The native library handle to be freed</param>
1894-
/// <exception cref="System.InvalidOperationException">If the operation fails</exception>
1895-
public static void FreeLibrary(IntPtr handle)
1896-
{
1897-
FreeNativeLibrary(handle);
1898-
}
1899-
1900-
/// <summary>
1901-
/// Get the address of an exported Symbol
1902-
/// This is a simple wrapper around OS calls, and does not perform any name mangling.
1903-
/// </summary>
1904-
/// <param name="handle">The native library handle</param>
1905-
/// <param name="name">The name of the exported symbol</param>
1906-
/// <returns>The address of the symbol</returns>
1907-
/// <exception cref="System.ArgumentNullException">If handle or name is null</exception>
1908-
/// <exception cref="System.EntryPointNotFoundException">If the symbol is not found</exception>
1909-
public static IntPtr GetLibraryExport(IntPtr handle, string name)
1910-
{
1911-
if (handle == IntPtr.Zero)
1912-
throw new ArgumentNullException(nameof(handle));
1913-
if (name == null)
1914-
throw new ArgumentNullException(nameof(name));
1915-
1916-
return GetNativeLibraryExport(handle, name, throwOnError: true);
1917-
}
1918-
1919-
/// <summary>
1920-
/// Get the address of an exported Symbol, but do not throw
1921-
/// </summary>
1922-
/// <param name="handle">The native library handle</param>
1923-
/// <param name="name">The name of the exported symbol</param>
1924-
/// <param name="address"> The out-parameter for the symbol address, if it exists</param>
1925-
/// <returns>True on success, false otherwise</returns>
1926-
/// <exception cref="System.ArgumentNullException">If handle or name is null</exception>
1927-
public static bool TryGetLibraryExport(IntPtr handle, string name, out IntPtr address)
1928-
{
1929-
if (handle == IntPtr.Zero)
1930-
throw new ArgumentNullException(nameof(handle));
1931-
if (name == null)
1932-
throw new ArgumentNullException(nameof(name));
1933-
1934-
address = GetNativeLibraryExport(handle, name, throwOnError: false);
1935-
return address != IntPtr.Zero;
1936-
}
1937-
1938-
/// External functions that implement the NativeLibrary interface
1939-
1940-
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
1941-
internal static extern IntPtr LoadLibraryFromPath(string libraryName, bool throwOnError);
1942-
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
1943-
internal static extern IntPtr LoadLibraryByName(string libraryName, RuntimeAssembly callingAssembly,
1944-
bool hasDllImportSearchPathFlag, uint dllImportSearchPathFlag,
1945-
bool throwOnError);
1946-
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
1947-
internal static extern void FreeNativeLibrary(IntPtr handle);
1948-
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
1949-
internal static extern IntPtr GetNativeLibraryExport(IntPtr handle, string symbolName, bool throwOnError);
19501791
}
19511792
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Collections.Generic;
6+
using System.Reflection;
7+
using System.Reflection.Emit;
8+
using System.Runtime.CompilerServices;
9+
using System.Runtime.ConstrainedExecution;
10+
using Win32Native = Microsoft.Win32.Win32Native;
11+
using System.Diagnostics;
12+
13+
namespace System.Runtime.InteropServices
14+
{
15+
/// <summary>
16+
/// APIs for managing Native Libraries
17+
/// </summary>
18+
public static partial class NativeLibrary
19+
{
20+
/// <summary>
21+
/// NativeLibrary Loader: Simple API
22+
/// This method is a wrapper around OS loader, using "default" flags.
23+
/// </summary>
24+
/// <param name="libraryPath">The name of the native library to be loaded</param>
25+
/// <returns>The handle for the loaded native library</returns>
26+
/// <exception cref="System.ArgumentNullException">If libraryPath is null</exception>
27+
/// <exception cref="System.DllNotFoundException ">If the library can't be found.</exception>
28+
/// <exception cref="System.BadImageFormatException">If the library is not valid.</exception>
29+
public static IntPtr Load(string libraryPath)
30+
{
31+
if (libraryPath == null)
32+
throw new ArgumentNullException(nameof(libraryPath));
33+
34+
return LoadFromPath(libraryPath, throwOnError: true);
35+
}
36+
37+
/// <summary>
38+
/// NativeLibrary Loader: Simple API that doesn't throw
39+
/// </summary>
40+
/// <param name="libraryPath">The name of the native library to be loaded</param>
41+
/// <param name="handle">The out-parameter for the loaded native library handle</param>
42+
/// <returns>True on successful load, false otherwise</returns>
43+
/// <exception cref="System.ArgumentNullException">If libraryPath is null</exception>
44+
public static bool TryLoad(string libraryPath, out IntPtr handle)
45+
{
46+
if (libraryPath == null)
47+
throw new ArgumentNullException(nameof(libraryPath));
48+
49+
handle = LoadFromPath(libraryPath, throwOnError: false);
50+
return handle != IntPtr.Zero;
51+
}
52+
53+
/// <summary>
54+
/// NativeLibrary Loader: High-level API
55+
/// Given a library name, this function searches specific paths based on the
56+
/// runtime configuration, input parameters, and attributes of the calling assembly.
57+
/// If DllImportSearchPath parameter is non-null, the flags in this enumeration are used.
58+
/// Otherwise, the flags specified by the DefaultDllImportSearchPaths attribute on the
59+
/// calling assembly (if any) are used.
60+
/// This LoadLibrary() method does not invoke the managed call-backs for native library resolution:
61+
/// * AssemblyLoadContext.LoadUnmanagedDll()
62+
/// </summary>
63+
/// <param name="libraryName">The name of the native library to be loaded</param>
64+
/// <param name="assembly">The assembly loading the native library</param>
65+
/// <param name="searchPath">The search path</param>
66+
/// <returns>The handle for the loaded library</returns>
67+
/// <exception cref="System.ArgumentNullException">If libraryPath or assembly is null</exception>
68+
/// <exception cref="System.ArgumentException">If assembly is not a RuntimeAssembly</exception>
69+
/// <exception cref="System.DllNotFoundException ">If the library can't be found.</exception>
70+
/// <exception cref="System.BadImageFormatException">If the library is not valid.</exception>
71+
public static IntPtr Load(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
72+
{
73+
if (libraryName == null)
74+
throw new ArgumentNullException(nameof(libraryName));
75+
if (assembly == null)
76+
throw new ArgumentNullException(nameof(assembly));
77+
if (!(assembly is RuntimeAssembly))
78+
throw new ArgumentException(SR.Argument_MustBeRuntimeAssembly);
79+
80+
return LoadByName(libraryName,
81+
((RuntimeAssembly)assembly).GetNativeHandle(),
82+
searchPath.HasValue,
83+
(uint) searchPath.GetValueOrDefault(),
84+
throwOnError: true);
85+
}
86+
87+
/// <summary>
88+
/// NativeLibrary Loader: High-level API that doesn't throw.
89+
/// </summary>
90+
/// <param name="libraryName">The name of the native library to be loaded</param>
91+
/// <param name="searchPath">The search path</param>
92+
/// <param name="assembly">The assembly loading the native library</param>
93+
/// <param name="handle">The out-parameter for the loaded native library handle</param>
94+
/// <returns>True on successful load, false otherwise</returns>
95+
/// <exception cref="System.ArgumentNullException">If libraryPath or assembly is null</exception>
96+
/// <exception cref="System.ArgumentException">If assembly is not a RuntimeAssembly</exception>
97+
public static bool TryLoad(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, out IntPtr handle)
98+
{
99+
if (libraryName == null)
100+
throw new ArgumentNullException(nameof(libraryName));
101+
if (assembly == null)
102+
throw new ArgumentNullException(nameof(assembly));
103+
if (!(assembly is RuntimeAssembly))
104+
throw new ArgumentException(SR.Argument_MustBeRuntimeAssembly);
105+
106+
handle = LoadByName(libraryName,
107+
((RuntimeAssembly)assembly).GetNativeHandle(),
108+
searchPath.HasValue,
109+
(uint) searchPath.GetValueOrDefault(),
110+
throwOnError: false);
111+
return handle != IntPtr.Zero;
112+
}
113+
114+
/// <summary>
115+
/// Free a loaded library
116+
/// Given a library handle, free it.
117+
/// No action if the input handle is null.
118+
/// </summary>
119+
/// <param name="handle">The native library handle to be freed</param>
120+
/// <exception cref="System.InvalidOperationException">If the operation fails</exception>
121+
public static void Free(IntPtr handle)
122+
{
123+
FreeLib(handle);
124+
}
125+
126+
/// <summary>
127+
/// Get the address of an exported Symbol
128+
/// This is a simple wrapper around OS calls, and does not perform any name mangling.
129+
/// </summary>
130+
/// <param name="handle">The native library handle</param>
131+
/// <param name="name">The name of the exported symbol</param>
132+
/// <returns>The address of the symbol</returns>
133+
/// <exception cref="System.ArgumentNullException">If handle or name is null</exception>
134+
/// <exception cref="System.EntryPointNotFoundException">If the symbol is not found</exception>
135+
public static IntPtr GetExport(IntPtr handle, string name)
136+
{
137+
if (handle == IntPtr.Zero)
138+
throw new ArgumentNullException(nameof(handle));
139+
if (name == null)
140+
throw new ArgumentNullException(nameof(name));
141+
142+
return GetSymbol(handle, name, throwOnError: true);
143+
}
144+
145+
/// <summary>
146+
/// Get the address of an exported Symbol, but do not throw
147+
/// </summary>
148+
/// <param name="handle">The native library handle</param>
149+
/// <param name="name">The name of the exported symbol</param>
150+
/// <param name="address"> The out-parameter for the symbol address, if it exists</param>
151+
/// <returns>True on success, false otherwise</returns>
152+
/// <exception cref="System.ArgumentNullException">If handle or name is null</exception>
153+
public static bool TryGetExport(IntPtr handle, string name, out IntPtr address)
154+
{
155+
if (handle == IntPtr.Zero)
156+
throw new ArgumentNullException(nameof(handle));
157+
if (name == null)
158+
throw new ArgumentNullException(nameof(name));
159+
160+
address = GetSymbol(handle, name, throwOnError: false);
161+
return address != IntPtr.Zero;
162+
}
163+
164+
/// External functions that implement the NativeLibrary interface
165+
166+
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
167+
internal static extern IntPtr LoadFromPath(string libraryName, bool throwOnError);
168+
169+
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
170+
internal static extern IntPtr LoadByName(string libraryName, RuntimeAssembly callingAssembly,
171+
bool hasDllImportSearchPathFlag, uint dllImportSearchPathFlag,
172+
bool throwOnError);
173+
174+
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
175+
internal static extern void FreeLib(IntPtr handle);
176+
177+
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
178+
internal static extern IntPtr GetSymbol(IntPtr handle, string symbolName, bool throwOnError);
179+
}
180+
}

src/vm/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ set(VM_SOURCES_WKS
355355
multicorejitplayer.cpp # Condition="'$(FeatureMulticoreJIT)' == 'true'
356356
nativeeventsource.cpp
357357
nativeoverlapped.cpp
358+
nativelibrarynative.cpp
358359
objectlist.cpp
359360
olevariant.cpp
360361
pendingload.cpp
@@ -473,6 +474,7 @@ set(VM_HEADERS_WKS
473474
multicorejitimpl.h
474475
nativeeventsource.h
475476
nativeoverlapped.h
477+
nativelibrarynative.h
476478
objectlist.h
477479
olevariant.h
478480
pendingload.h

0 commit comments

Comments
 (0)