Move Native Library APIs to NativeLibrary class (dotnet/coreclr#21821)
authorSwaroop Sridhar <Swaroop.Sridhar@microsoft.com>
Sun, 6 Jan 2019 00:40:59 +0000 (16:40 -0800)
committerJan Kotas <jkotas@microsoft.com>
Sun, 6 Jan 2019 00:40:59 +0000 (16:40 -0800)
Move APIs that manipulate native libraries from
System.Runtime.InteropServices.Marshal class to the new
System.Runtime.InteropServices.NativeLibrary class.

In API review: dotnet/coreclr#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.

Commit migrated from https://github.com/dotnet/coreclr/commit/110835b1b818b333f27ab76db3f223a03027698a

16 files changed:
src/coreclr/src/System.Private.CoreLib/System.Private.CoreLib.csproj
src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs
src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.cs [new file with mode: 0644]
src/coreclr/src/vm/CMakeLists.txt
src/coreclr/src/vm/ecalllist.h
src/coreclr/src/vm/marshalnative.cpp
src/coreclr/src/vm/marshalnative.h
src/coreclr/src/vm/mscorlib.cpp
src/coreclr/src/vm/nativelibrarynative.cpp [new file with mode: 0644]
src/coreclr/src/vm/nativelibrarynative.h [new file with mode: 0644]
src/coreclr/tests/src/Interop/CMakeLists.txt
src/coreclr/tests/src/Interop/MarshalAPI/NativeLibrary/NativeLibraryTests.cs [deleted file]
src/coreclr/tests/src/Interop/NativeLibrary/CMakeLists.txt [moved from src/coreclr/tests/src/Interop/MarshalAPI/NativeLibrary/CMakeLists.txt with 100% similarity]
src/coreclr/tests/src/Interop/NativeLibrary/NativeLibrary.cpp [moved from src/coreclr/tests/src/Interop/MarshalAPI/NativeLibrary/NativeLibrary.cpp with 100% similarity]
src/coreclr/tests/src/Interop/NativeLibrary/NativeLibraryTests.cs [new file with mode: 0644]
src/coreclr/tests/src/Interop/NativeLibrary/NativeLibraryTests.csproj [moved from src/coreclr/tests/src/Interop/MarshalAPI/NativeLibrary/NativeLibraryTests.csproj with 95% similarity]

index 7528d12..bd9d650 100644 (file)
     <Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\InvalidComObjectException.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\InvalidOleVariantTypeException.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\Marshal.cs" />
+    <Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\NativeLibrary.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\NonPortable.cs" Condition="'$(FeatureCominterop)' != 'true'" />
     <Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\PInvokeMap.cs" />
     <Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\PInvokeMarshal.cs" />
index 594b758..1ac33e0 100644 (file)
@@ -1788,164 +1788,5 @@ namespace System.Runtime.InteropServices
             RuntimeImports.RhZeroMemory(s, (UIntPtr)(string.wcslen((char*)s) * 2));
             FreeHGlobal(s);
         }
-
-        /// APIs for managing Native Libraries 
-
-        /// <summary>
-        /// NativeLibrary Loader: Simple API
-        /// This method is a wrapper around OS loader, using "default" flags.
-        /// </summary>
-        /// <param name="libraryPath">The name of the native library to be loaded</param>
-        /// <returns>The handle for the loaded native library</returns>  
-        /// <exception cref="System.ArgumentNullException">If libraryPath is null</exception>
-        /// <exception cref="System.DllNotFoundException ">If the library can't be found.</exception>
-        /// <exception cref="System.BadImageFormatException">If the library is not valid.</exception>
-        public static IntPtr LoadLibrary(string libraryPath)
-        {
-            if (libraryPath == null)
-                throw new ArgumentNullException(nameof(libraryPath));
-
-            return LoadLibraryFromPath(libraryPath, throwOnError: true);
-        }
-
-        /// <summary>
-        /// NativeLibrary Loader: Simple API that doesn't throw
-        /// </summary>
-        /// <param name="libraryPath">The name of the native library to be loaded</param>
-        /// <param name="handle">The out-parameter for the loaded native library handle</param>
-        /// <returns>True on successful load, false otherwise</returns>  
-        /// <exception cref="System.ArgumentNullException">If libraryPath is null</exception>
-        public static bool TryLoadLibrary(string libraryPath, out IntPtr handle)
-        {
-            if (libraryPath == null)
-                throw new ArgumentNullException(nameof(libraryPath));
-
-            handle = LoadLibraryFromPath(libraryPath, throwOnError: false);
-            return handle != IntPtr.Zero;
-        }
-
-        /// <summary>
-        /// NativeLibrary Loader: High-level API
-        /// Given a library name, this function searches specific paths based on the 
-        /// runtime configuration, input parameters, and attributes of the calling assembly.
-        /// If DllImportSearchPath parameter is non-null, the flags in this enumeration are used.
-        /// Otherwise, the flags specified by the DefaultDllImportSearchPaths attribute on the 
-        /// calling assembly (if any) are used. 
-        /// This LoadLibrary() method does not invoke the managed call-backs for native library resolution: 
-        /// * AssemblyLoadContext.LoadUnmanagedDll()
-        /// </summary>
-        /// <param name="libraryName">The name of the native library to be loaded</param>
-        /// <param name="assembly">The assembly loading the native library</param>
-        /// <param name="searchPath">The search path</param>
-        /// <returns>The handle for the loaded library</returns>  
-        /// <exception cref="System.ArgumentNullException">If libraryPath or assembly is null</exception>
-        /// <exception cref="System.ArgumentException">If assembly is not a RuntimeAssembly</exception>
-        /// <exception cref="System.DllNotFoundException ">If the library can't be found.</exception>
-        /// <exception cref="System.BadImageFormatException">If the library is not valid.</exception>        
-        public static IntPtr LoadLibrary(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
-        {
-            if (libraryName == null)
-                throw new ArgumentNullException(nameof(libraryName));
-            if (assembly == null)
-                throw new ArgumentNullException(nameof(assembly));
-            if (!(assembly is RuntimeAssembly))
-                throw new ArgumentException(SR.Argument_MustBeRuntimeAssembly);
-            
-            return LoadLibraryByName(libraryName, 
-                                     ((RuntimeAssembly)assembly).GetNativeHandle(), 
-                                     searchPath.HasValue, 
-                                     (uint) searchPath.GetValueOrDefault(), 
-                                     throwOnError: true);
-        }
-
-        /// <summary>
-        /// NativeLibrary Loader: High-level API that doesn't throw.
-        /// </summary>
-        /// <param name="libraryName">The name of the native library to be loaded</param>
-        /// <param name="searchPath">The search path</param>
-        /// <param name="assembly">The assembly loading the native library</param>
-        /// <param name="handle">The out-parameter for the loaded native library handle</param>
-        /// <returns>True on successful load, false otherwise</returns>  
-        /// <exception cref="System.ArgumentNullException">If libraryPath or assembly is null</exception>
-        /// <exception cref="System.ArgumentException">If assembly is not a RuntimeAssembly</exception>
-        public static bool TryLoadLibrary(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, out IntPtr handle)
-        {
-            if (libraryName == null)
-                throw new ArgumentNullException(nameof(libraryName));
-            if (assembly == null)
-                throw new ArgumentNullException(nameof(assembly));
-            if (!(assembly is RuntimeAssembly))
-                throw new ArgumentException(SR.Argument_MustBeRuntimeAssembly);
-            
-            handle = LoadLibraryByName(libraryName, 
-                                       ((RuntimeAssembly)assembly).GetNativeHandle(), 
-                                       searchPath.HasValue, 
-                                       (uint) searchPath.GetValueOrDefault(),
-                                       throwOnError: false);
-            return handle != IntPtr.Zero;
-        }
-
-        /// <summary>
-        /// Free a loaded library
-        /// Given a library handle, free it.
-        /// No action if the input handle is null.
-        /// </summary>
-        /// <param name="handle">The native library handle to be freed</param>
-        /// <exception cref="System.InvalidOperationException">If the operation fails</exception>
-        public static void FreeLibrary(IntPtr handle)
-        {
-            FreeNativeLibrary(handle);
-        }
-
-        /// <summary>
-        /// Get the address of an exported Symbol
-        /// This is a simple wrapper around OS calls, and does not perform any name mangling.
-        /// </summary>
-        /// <param name="handle">The native library handle</param>
-        /// <param name="name">The name of the exported symbol</param>
-        /// <returns>The address of the symbol</returns>  
-        /// <exception cref="System.ArgumentNullException">If handle or name is null</exception>
-        /// <exception cref="System.EntryPointNotFoundException">If the symbol is not found</exception>
-        public static IntPtr GetLibraryExport(IntPtr handle, string name)
-        {
-            if (handle == IntPtr.Zero) 
-                throw new ArgumentNullException(nameof(handle));
-            if (name == null)
-                throw new ArgumentNullException(nameof(name));
-
-            return GetNativeLibraryExport(handle, name, throwOnError: true);
-        }
-
-        /// <summary>
-        /// Get the address of an exported Symbol, but do not throw
-        /// </summary>
-        /// <param name="handle">The  native library handle</param>
-        /// <param name="name">The name of the exported symbol</param>
-        /// <param name="address"> The out-parameter for the symbol address, if it exists</param>
-        /// <returns>True on success, false otherwise</returns>  
-        /// <exception cref="System.ArgumentNullException">If handle or name is null</exception>
-        public static bool TryGetLibraryExport(IntPtr handle, string name, out IntPtr address)
-        {
-            if (handle == IntPtr.Zero) 
-                throw new ArgumentNullException(nameof(handle));
-            if (name == null)
-                throw new ArgumentNullException(nameof(name));
-
-            address = GetNativeLibraryExport(handle, name, throwOnError: false);
-            return address != IntPtr.Zero;
-        }
-
-        /// External functions that implement the NativeLibrary interface
-
-        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
-        internal static extern IntPtr LoadLibraryFromPath(string libraryName, bool throwOnError);
-        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
-        internal static extern IntPtr LoadLibraryByName(string libraryName, RuntimeAssembly callingAssembly, 
-                                                        bool hasDllImportSearchPathFlag, uint dllImportSearchPathFlag, 
-                                                        bool throwOnError);
-        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
-        internal static extern void FreeNativeLibrary(IntPtr handle);
-        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
-        internal static extern IntPtr GetNativeLibraryExport(IntPtr handle, string symbolName, bool throwOnError);
     }
 }
diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.cs
new file mode 100644 (file)
index 0000000..38712ac
--- /dev/null
@@ -0,0 +1,180 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.CompilerServices;
+using System.Runtime.ConstrainedExecution;
+using Win32Native = Microsoft.Win32.Win32Native;
+using System.Diagnostics;
+
+namespace System.Runtime.InteropServices
+{
+    /// <summary>
+    /// APIs for managing Native Libraries 
+    /// </summary>
+    public static partial class NativeLibrary
+    {
+        /// <summary>
+        /// NativeLibrary Loader: Simple API
+        /// This method is a wrapper around OS loader, using "default" flags.
+        /// </summary>
+        /// <param name="libraryPath">The name of the native library to be loaded</param>
+        /// <returns>The handle for the loaded native library</returns>  
+        /// <exception cref="System.ArgumentNullException">If libraryPath is null</exception>
+        /// <exception cref="System.DllNotFoundException ">If the library can't be found.</exception>
+        /// <exception cref="System.BadImageFormatException">If the library is not valid.</exception>
+        public static IntPtr Load(string libraryPath)
+        {
+            if (libraryPath == null)
+                throw new ArgumentNullException(nameof(libraryPath));
+
+            return LoadFromPath(libraryPath, throwOnError: true);
+        }
+
+        /// <summary>
+        /// NativeLibrary Loader: Simple API that doesn't throw
+        /// </summary>
+        /// <param name="libraryPath">The name of the native library to be loaded</param>
+        /// <param name="handle">The out-parameter for the loaded native library handle</param>
+        /// <returns>True on successful load, false otherwise</returns>  
+        /// <exception cref="System.ArgumentNullException">If libraryPath is null</exception>
+        public static bool TryLoad(string libraryPath, out IntPtr handle)
+        {
+            if (libraryPath == null)
+                throw new ArgumentNullException(nameof(libraryPath));
+
+            handle = LoadFromPath(libraryPath, throwOnError: false);
+            return handle != IntPtr.Zero;
+        }
+
+        /// <summary>
+        /// NativeLibrary Loader: High-level API
+        /// Given a library name, this function searches specific paths based on the 
+        /// runtime configuration, input parameters, and attributes of the calling assembly.
+        /// If DllImportSearchPath parameter is non-null, the flags in this enumeration are used.
+        /// Otherwise, the flags specified by the DefaultDllImportSearchPaths attribute on the 
+        /// calling assembly (if any) are used. 
+        /// This LoadLibrary() method does not invoke the managed call-backs for native library resolution: 
+        /// * AssemblyLoadContext.LoadUnmanagedDll()
+        /// </summary>
+        /// <param name="libraryName">The name of the native library to be loaded</param>
+        /// <param name="assembly">The assembly loading the native library</param>
+        /// <param name="searchPath">The search path</param>
+        /// <returns>The handle for the loaded library</returns>  
+        /// <exception cref="System.ArgumentNullException">If libraryPath or assembly is null</exception>
+        /// <exception cref="System.ArgumentException">If assembly is not a RuntimeAssembly</exception>
+        /// <exception cref="System.DllNotFoundException ">If the library can't be found.</exception>
+        /// <exception cref="System.BadImageFormatException">If the library is not valid.</exception>        
+        public static IntPtr Load(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
+        {
+            if (libraryName == null)
+                throw new ArgumentNullException(nameof(libraryName));
+            if (assembly == null)
+                throw new ArgumentNullException(nameof(assembly));
+            if (!(assembly is RuntimeAssembly))
+                throw new ArgumentException(SR.Argument_MustBeRuntimeAssembly);
+            
+            return LoadByName(libraryName, 
+                              ((RuntimeAssembly)assembly).GetNativeHandle(), 
+                              searchPath.HasValue, 
+                              (uint) searchPath.GetValueOrDefault(), 
+                              throwOnError: true);
+        }
+
+        /// <summary>
+        /// NativeLibrary Loader: High-level API that doesn't throw.
+        /// </summary>
+        /// <param name="libraryName">The name of the native library to be loaded</param>
+        /// <param name="searchPath">The search path</param>
+        /// <param name="assembly">The assembly loading the native library</param>
+        /// <param name="handle">The out-parameter for the loaded native library handle</param>
+        /// <returns>True on successful load, false otherwise</returns>  
+        /// <exception cref="System.ArgumentNullException">If libraryPath or assembly is null</exception>
+        /// <exception cref="System.ArgumentException">If assembly is not a RuntimeAssembly</exception>
+        public static bool TryLoad(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, out IntPtr handle)
+        {
+            if (libraryName == null)
+                throw new ArgumentNullException(nameof(libraryName));
+            if (assembly == null)
+                throw new ArgumentNullException(nameof(assembly));
+            if (!(assembly is RuntimeAssembly))
+                throw new ArgumentException(SR.Argument_MustBeRuntimeAssembly);
+            
+            handle = LoadByName(libraryName, 
+                                ((RuntimeAssembly)assembly).GetNativeHandle(), 
+                                searchPath.HasValue, 
+                                (uint) searchPath.GetValueOrDefault(),
+                                throwOnError: false);
+            return handle != IntPtr.Zero;
+        }
+
+        /// <summary>
+        /// Free a loaded library
+        /// Given a library handle, free it.
+        /// No action if the input handle is null.
+        /// </summary>
+        /// <param name="handle">The native library handle to be freed</param>
+        /// <exception cref="System.InvalidOperationException">If the operation fails</exception>
+        public static void Free(IntPtr handle)
+        {
+            FreeLib(handle);
+        }
+
+        /// <summary>
+        /// Get the address of an exported Symbol
+        /// This is a simple wrapper around OS calls, and does not perform any name mangling.
+        /// </summary>
+        /// <param name="handle">The native library handle</param>
+        /// <param name="name">The name of the exported symbol</param>
+        /// <returns>The address of the symbol</returns>  
+        /// <exception cref="System.ArgumentNullException">If handle or name is null</exception>
+        /// <exception cref="System.EntryPointNotFoundException">If the symbol is not found</exception>
+        public static IntPtr GetExport(IntPtr handle, string name)
+        {
+            if (handle == IntPtr.Zero) 
+                throw new ArgumentNullException(nameof(handle));
+            if (name == null)
+                throw new ArgumentNullException(nameof(name));
+
+            return GetSymbol(handle, name, throwOnError: true);
+        }
+
+        /// <summary>
+        /// Get the address of an exported Symbol, but do not throw
+        /// </summary>
+        /// <param name="handle">The  native library handle</param>
+        /// <param name="name">The name of the exported symbol</param>
+        /// <param name="address"> The out-parameter for the symbol address, if it exists</param>
+        /// <returns>True on success, false otherwise</returns>  
+        /// <exception cref="System.ArgumentNullException">If handle or name is null</exception>
+        public static bool TryGetExport(IntPtr handle, string name, out IntPtr address)
+        {
+            if (handle == IntPtr.Zero) 
+                throw new ArgumentNullException(nameof(handle));
+            if (name == null)
+                throw new ArgumentNullException(nameof(name));
+
+            address = GetSymbol(handle, name, throwOnError: false);
+            return address != IntPtr.Zero;
+        }
+
+        /// External functions that implement the NativeLibrary interface
+
+        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+        internal static extern IntPtr LoadFromPath(string libraryName, bool throwOnError);
+
+        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+        internal static extern IntPtr LoadByName(string libraryName, RuntimeAssembly callingAssembly,
+                                                 bool hasDllImportSearchPathFlag, uint dllImportSearchPathFlag, 
+                                                 bool throwOnError);
+
+        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+        internal static extern void FreeLib(IntPtr handle);
+
+        [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+        internal static extern IntPtr GetSymbol(IntPtr handle, string symbolName, bool throwOnError);
+    }
+}
index 93ccb83..9bb26d4 100644 (file)
@@ -355,6 +355,7 @@ set(VM_SOURCES_WKS
     multicorejitplayer.cpp # Condition="'$(FeatureMulticoreJIT)' == 'true'
     nativeeventsource.cpp
     nativeoverlapped.cpp
+    nativelibrarynative.cpp
     objectlist.cpp
     olevariant.cpp
     pendingload.cpp
@@ -473,6 +474,7 @@ set(VM_HEADERS_WKS
     multicorejitimpl.h
     nativeeventsource.h
     nativeoverlapped.h
+    nativelibrarynative.h
     objectlist.h
     olevariant.h
     pendingload.h
index 05ced0f..89ed6fa 100644 (file)
@@ -832,11 +832,6 @@ FCFuncStart(gInteropMarshalFuncs)
     FCFuncElement("GetDelegateForFunctionPointerInternal", MarshalNative::GetDelegateForFunctionPointerInternal)
     FCFuncElement("GetFunctionPointerForDelegateInternal", MarshalNative::GetFunctionPointerForDelegateInternal)
 
-    QCFuncElement("LoadLibraryFromPath", MarshalNative::LoadLibraryFromPath)
-    QCFuncElement("LoadLibraryByName", MarshalNative::LoadLibraryByName)
-    QCFuncElement("FreeNativeLibrary", MarshalNative::FreeNativeLibrary)
-    QCFuncElement("GetNativeLibraryExport", MarshalNative::GetNativeLibraryExport)
-
 #ifdef FEATURE_COMINTEROP
     FCFuncElement("GetHRForException", MarshalNative::GetHRForException)
     FCFuncElement("GetHRForException_WinRT", MarshalNative::GetHRForException_WinRT)
@@ -871,6 +866,13 @@ FCFuncStart(gInteropMarshalFuncs)
 #endif // FEATURE_COMINTEROP
 FCFuncEnd()
 
+FCFuncStart(gInteropNativeLibraryFuncs)
+    QCFuncElement("LoadFromPath", NativeLibraryNative::LoadFromPath)
+    QCFuncElement("LoadByName", NativeLibraryNative::LoadByName)
+    QCFuncElement("FreeLib", NativeLibraryNative::FreeLib)
+    QCFuncElement("GetSymbol", NativeLibraryNative::GetSymbol)
+FCFuncEnd()
+
 FCFuncStart(gArrayWithOffsetFuncs)
     FCFuncElement("CalculateCount", MarshalNative::CalculateCount)
 FCFuncEnd()
@@ -1278,6 +1280,7 @@ FCClassElement("MngdSafeArrayMarshaler", "System.StubHelpers", gMngdSafeArrayMar
 FCClassElement("ModuleBuilder", "System.Reflection.Emit", gCOMModuleBuilderFuncs)
 FCClassElement("ModuleHandle", "System", gCOMModuleHandleFuncs)
 FCClassElement("Monitor", "System.Threading", gMonitorFuncs)
+FCClassElement("NativeLibrary", "System.Runtime.InteropServices", gInteropNativeLibraryFuncs)
 #ifdef FEATURE_COMINTEROP
 FCClassElement("OAVariantLib", "Microsoft.Win32", gOAVariantFuncs)
 #endif
index a2cb827..e2b2482 100644 (file)
@@ -923,69 +923,6 @@ FCIMPL1(int, MarshalNative::GetHRForException_WinRT, Object* eUNSAFE)
 }
 FCIMPLEND
 
-// static
-INT_PTR QCALLTYPE MarshalNative::LoadLibraryFromPath(LPCWSTR path, BOOL throwOnError)
-{
-    QCALL_CONTRACT;
-
-    NATIVE_LIBRARY_HANDLE handle = nullptr;
-
-    BEGIN_QCALL;
-
-    handle = NDirect::LoadLibraryFromPath(path, throwOnError);
-
-    END_QCALL;
-
-    return reinterpret_cast<INT_PTR>(handle);
-}
-
-// static
-INT_PTR QCALLTYPE MarshalNative::LoadLibraryByName(LPCWSTR name, QCall::AssemblyHandle callingAssembly, 
-                                                   BOOL hasDllImportSearchPathFlag, DWORD dllImportSearchPathFlag, 
-                                                   BOOL throwOnError)
-{
-    QCALL_CONTRACT;
-
-    NATIVE_LIBRARY_HANDLE handle = nullptr;
-    Assembly *pAssembly = callingAssembly->GetAssembly();
-
-    BEGIN_QCALL;
-
-    handle = NDirect::LoadLibraryByName(name, pAssembly, hasDllImportSearchPathFlag, dllImportSearchPathFlag, throwOnError);
-
-    END_QCALL;
-
-    return reinterpret_cast<INT_PTR>(handle);
-}
-
-// static
-void QCALLTYPE MarshalNative::FreeNativeLibrary(INT_PTR handle)
-{
-    QCALL_CONTRACT;
-
-    BEGIN_QCALL;
-
-    NDirect::FreeNativeLibrary((NATIVE_LIBRARY_HANDLE) handle);
-    
-    END_QCALL;
-}
-
-//static 
-INT_PTR QCALLTYPE MarshalNative::GetNativeLibraryExport(INT_PTR handle, LPCWSTR symbolName, BOOL throwOnError)
-{
-    QCALL_CONTRACT;
-
-    INT_PTR address = NULL;
-    
-    BEGIN_QCALL;
-
-    address = NDirect::GetNativeLibraryExport((NATIVE_LIBRARY_HANDLE)handle, symbolName, throwOnError);
-
-    END_QCALL;
-
-    return address;
-}
-
 #ifdef FEATURE_COMINTEROP
 
 //====================================================================
index ddc8351..85be41a 100644 (file)
@@ -85,17 +85,6 @@ public:
     static FCDECL2(Object*, GetDelegateForFunctionPointerInternal, LPVOID FPtr, ReflectClassBaseObject* refTypeUNSAFE);
     static FCDECL1(LPVOID, GetFunctionPointerForDelegateInternal, Object* refDelegateUNSAFE);
 
-
-    //====================================================================
-    // These methods provide the native callbacks for library loading APIs
-    //====================================================================
-    static INT_PTR QCALLTYPE LoadLibraryFromPath(LPCWSTR path, BOOL throwOnError);
-    static INT_PTR QCALLTYPE LoadLibraryByName(LPCWSTR name, QCall::AssemblyHandle callingAssembly, 
-                                                             BOOL hasDllImportSearchPathFlag, DWORD dllImportSearchPathFlag, 
-                                                             BOOL throwOnError);
-    static void QCALLTYPE FreeNativeLibrary(INT_PTR handle);
-    static INT_PTR QCALLTYPE GetNativeLibraryExport(INT_PTR handle, LPCWSTR symbolName, BOOL throwOnError);
-
 #ifdef FEATURE_COMINTEROP
     //====================================================================
     // map GUID to Type
index 4fa9449..e69cfb8 100644 (file)
@@ -35,6 +35,7 @@
 #include "clrconfignative.h"
 #include "commodule.h"
 #include "marshalnative.h"
+#include "nativelibrarynative.h"
 #include "system.h"
 #include "comutilnative.h"
 #include "comsynchronizable.h"
diff --git a/src/coreclr/src/vm/nativelibrarynative.cpp b/src/coreclr/src/vm/nativelibrarynative.cpp
new file mode 100644 (file)
index 0000000..c5bf24f
--- /dev/null
@@ -0,0 +1,74 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+// 
+// File: NativeLibraryNative.cpp
+//
+
+#include "common.h"
+#include "dllimport.h"
+#include "nativelibrarynative.h"
+
+// static
+INT_PTR QCALLTYPE NativeLibraryNative::LoadFromPath(LPCWSTR path, BOOL throwOnError)
+{
+    QCALL_CONTRACT;
+
+    NATIVE_LIBRARY_HANDLE handle = nullptr;
+
+    BEGIN_QCALL;
+
+    handle = NDirect::LoadLibraryFromPath(path, throwOnError);
+
+    END_QCALL;
+
+    return reinterpret_cast<INT_PTR>(handle);
+}
+
+// static
+INT_PTR QCALLTYPE NativeLibraryNative::LoadByName(LPCWSTR name, QCall::AssemblyHandle callingAssembly,
+                                                         BOOL hasDllImportSearchPathFlag, DWORD dllImportSearchPathFlag, 
+                                                         BOOL throwOnError)
+{
+    QCALL_CONTRACT;
+
+    NATIVE_LIBRARY_HANDLE handle = nullptr;
+    Assembly *pAssembly = callingAssembly->GetAssembly();
+
+    BEGIN_QCALL;
+
+    handle = NDirect::LoadLibraryByName(name, pAssembly, hasDllImportSearchPathFlag, dllImportSearchPathFlag, throwOnError);
+
+    END_QCALL;
+
+    return reinterpret_cast<INT_PTR>(handle);
+}
+
+// static
+void QCALLTYPE NativeLibraryNative::FreeLib(INT_PTR handle)
+{
+    QCALL_CONTRACT;
+
+    BEGIN_QCALL;
+
+    NDirect::FreeNativeLibrary((NATIVE_LIBRARY_HANDLE) handle);
+    
+    END_QCALL;
+}
+
+//static 
+INT_PTR QCALLTYPE NativeLibraryNative::GetSymbol(INT_PTR handle, LPCWSTR symbolName, BOOL throwOnError)
+{
+    QCALL_CONTRACT;
+
+    INT_PTR address = NULL;
+    
+    BEGIN_QCALL;
+
+    address = NDirect::GetNativeLibraryExport((NATIVE_LIBRARY_HANDLE)handle, symbolName, throwOnError);
+
+    END_QCALL;
+
+    return address;
+}
+
diff --git a/src/coreclr/src/vm/nativelibrarynative.h b/src/coreclr/src/vm/nativelibrarynative.h
new file mode 100644 (file)
index 0000000..e22031c
--- /dev/null
@@ -0,0 +1,26 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+// 
+// File: NativeLibraryNative.h
+//
+//
+// QCall's for the NativeLibrary class
+//
+
+#ifndef __NATIVELIBRARYNATIVE_H__
+#define __NATIVELIBRARYNATIVE_H__
+
+class NativeLibraryNative
+{
+public:
+    static INT_PTR QCALLTYPE LoadFromPath(LPCWSTR path, BOOL throwOnError);
+    static INT_PTR QCALLTYPE LoadByName(LPCWSTR name, QCall::AssemblyHandle callingAssembly, 
+                                               BOOL hasDllImportSearchPathFlag, DWORD dllImportSearchPathFlag, 
+                                               BOOL throwOnError);
+    static void QCALLTYPE FreeLib(INT_PTR handle);
+    static INT_PTR QCALLTYPE GetSymbol(INT_PTR handle, LPCWSTR symbolName, BOOL throwOnError);
+
+};
+
+#endif // __NATIVELIBRARYNATIVE_H__
index 5685e79..9e0bf85 100644 (file)
@@ -55,7 +55,7 @@ add_subdirectory(StringMarshalling/AnsiBSTR)
 add_subdirectory(StringMarshalling/VBByRefStr)
 add_subdirectory(MarshalAPI/FunctionPointer)
 add_subdirectory(MarshalAPI/IUnknown)
-add_subdirectory(MarshalAPI/NativeLibrary)
+add_subdirectory(NativeLibrary)
 add_subdirectory(SizeConst)
 add_subdirectory(DllImportAttribute/ExeFile)
 add_subdirectory(DllImportAttribute/FileNameContainDot)
diff --git a/src/coreclr/tests/src/Interop/MarshalAPI/NativeLibrary/NativeLibraryTests.cs b/src/coreclr/tests/src/Interop/MarshalAPI/NativeLibrary/NativeLibraryTests.cs
deleted file mode 100644 (file)
index dfc7335..0000000
+++ /dev/null
@@ -1,385 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-using System;
-using System.IO;
-using System.Reflection;
-using System.Runtime.InteropServices;
-using TestLibrary;
-
-using Console = Internal.Console;
-
-enum TestResult {
-    Success,
-    ReturnFailure,
-    ReturnNull,
-    IncorrectEvaluation,
-    ArgumentNull,
-    ArgumentBad,
-
-    DllNotFound,
-    BadImage,
-    InvalidOperation,
-    EntryPointNotFound,
-    GenericException
-    };
-
-public class NativeLibraryTest
-{
-    static string CurrentTest;
-    static bool Verbose = false;
-    public static int Main()
-    {
-        bool success = true;
-
-        Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
-        string testBinDir = Path.GetDirectoryName(assembly.Location);
-        string libName;
-        IntPtr handle;
-
-        // -----------------------------------------------
-        //         Simple LoadLibrary() API Tests
-        // -----------------------------------------------
-
-        // Calls on correct full-path to native lib
-        libName = Path.Combine(testBinDir, GetNativeLibraryName());
-        success &= EXPECT(LoadLibrarySimple(libName));
-        success &= EXPECT(TryLoadLibrarySimple(libName));
-
-        // Calls on non-existant file
-        libName = Path.Combine(testBinDir, "notfound");
-        success &= EXPECT(LoadLibrarySimple(libName), TestResult.DllNotFound);
-        success &= EXPECT(TryLoadLibrarySimple(libName), TestResult.ReturnFailure);
-
-        // Calls on an invalid file
-        libName = Path.Combine(testBinDir, "NativeLibrary.cpp");
-        success &= EXPECT(LoadLibrarySimple(libName), 
-            (TestLibrary.Utilities.IsWindows) ? TestResult.BadImage : TestResult.DllNotFound);
-        success &= EXPECT(TryLoadLibrarySimple(libName), TestResult.ReturnFailure);
-
-        // Calls on null input
-        libName = null;
-        success &= EXPECT(LoadLibrarySimple(libName), TestResult.ArgumentNull);
-        success &= EXPECT(TryLoadLibrarySimple(libName), TestResult.ArgumentNull);
-
-        // -----------------------------------------------
-        //         Advanced LoadLibrary() API Tests
-        // -----------------------------------------------
-
-        // Advanced LoadLibrary() API Tests
-        // Calls on correct full-path to native lib
-        libName = Path.Combine(testBinDir, GetNativeLibraryName());
-        success &= EXPECT(LoadLibraryAdvanced(libName, assembly, null));
-        success &= EXPECT(TryLoadLibraryAdvanced(libName, assembly, null));
-
-        // Calls on non-existant file
-        libName = Path.Combine(testBinDir, "notfound");
-        success &= EXPECT(LoadLibraryAdvanced(libName, assembly, null), TestResult.DllNotFound);
-        success &= EXPECT(TryLoadLibraryAdvanced(libName, assembly, null), TestResult.ReturnFailure);
-
-        // Calls on an invalid file
-        libName = Path.Combine(testBinDir, "NativeLibrary.cpp");
-        // The VM can only distinguish BadImageFormatException from DllNotFoundException on Windows.
-        success &= EXPECT(LoadLibraryAdvanced(libName, assembly, null), 
-            (TestLibrary.Utilities.IsWindows) ? TestResult.BadImage : TestResult.DllNotFound);
-        success &= EXPECT(TryLoadLibraryAdvanced(libName, assembly, null), TestResult.ReturnFailure);
-
-        // Calls on just Native Library name
-        libName = GetNativeLibraryPlainName();
-        success &= EXPECT(LoadLibraryAdvanced(libName, assembly, null));
-        success &= EXPECT(TryLoadLibraryAdvanced(libName, assembly, null));
-
-        // Calls on Native Library name with correct prefix-suffix
-        libName = GetNativeLibraryName();
-        success &= EXPECT(LoadLibraryAdvanced(libName, assembly, null));
-        success &= EXPECT(TryLoadLibraryAdvanced(libName, assembly, null));
-
-        // Calls on full path without prefix-siffix
-        libName = Path.Combine(testBinDir, GetNativeLibraryPlainName());
-        // DllImport doesn't add a prefix if the name is preceeded by a path specification.
-        // Windows only needs a suffix, but Linux and Mac need both prefix and suffix
-        success &= EXPECT(LoadLibraryAdvanced(libName, assembly, null),
-            (TestLibrary.Utilities.IsWindows) ? TestResult.Success : TestResult.DllNotFound);
-        success &= EXPECT(TryLoadLibraryAdvanced(libName, assembly, null),
-            (TestLibrary.Utilities.IsWindows) ? TestResult.Success : TestResult.ReturnFailure);
-
-        if (TestLibrary.Utilities.IsWindows)
-        {
-            libName = GetWin32LibName();
-
-            // Calls on a valid library from System32 directory
-            success &= EXPECT(LoadLibraryAdvanced(libName, assembly, DllImportSearchPath.System32));
-            success &= EXPECT(TryLoadLibraryAdvanced(libName, assembly, DllImportSearchPath.System32));
-
-            // Calls on a valid library from 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
-        success &= EXPECT(LoadLibraryAdvanced(null, assembly, null), TestResult.ArgumentNull);
-        success &= EXPECT(TryLoadLibraryAdvanced(null, assembly, null), TestResult.ArgumentNull);
-
-        // Calls with null assembly
-        libName = GetNativeLibraryPlainName();
-        success &= EXPECT(LoadLibraryAdvanced(libName, null, null), TestResult.ArgumentNull);
-        success &= EXPECT(TryLoadLibraryAdvanced(libName, null, null), TestResult.ArgumentNull);
-
-        // Ensure that a lib is not picked up from current directory when
-        // a different full-path is specified.
-        libName = Path.Combine(testBinDir, Path.Combine("lib", GetNativeLibraryPlainName()));
-        success &= EXPECT(LoadLibraryAdvanced(libName, assembly, DllImportSearchPath.AssemblyDirectory), TestResult.DllNotFound);
-        success &= EXPECT(TryLoadLibraryAdvanced(libName, assembly, DllImportSearchPath.AssemblyDirectory), TestResult.ReturnFailure);
-
-        // -----------------------------------------------
-        //         FreeLibrary Tests
-        // -----------------------------------------------
-
-        libName = Path.Combine(testBinDir, GetNativeLibraryName());
-        handle = Marshal.LoadLibrary(libName);
-
-        // Valid Free
-        success &= EXPECT(FreeLibrary(handle));
-
-        // Double Free
-        success &= EXPECT(FreeLibrary(handle), TestResult.InvalidOperation);
-
-        // Null Free
-        success &= EXPECT(FreeLibrary(IntPtr.Zero));
-
-        // -----------------------------------------------
-        //         GetLibraryExport Tests
-        // -----------------------------------------------
-        libName = Path.Combine(testBinDir, GetNativeLibraryName());
-        handle = Marshal.LoadLibrary(libName);
-
-        // Valid Call (with some hard-coded name mangling)
-        success &= EXPECT(GetLibraryExport(handle, TestLibrary.Utilities.IsX86 ? "_NativeSum@8" : "NativeSum"));
-        success &= EXPECT(TryGetLibraryExport(handle, TestLibrary.Utilities.IsX86 ? "_NativeSum@8" : "NativeSum"));
-
-        // Call with null handle
-        success &= EXPECT(GetLibraryExport(IntPtr.Zero, "NativeSum"), TestResult.ArgumentNull);
-        success &= EXPECT(TryGetLibraryExport(IntPtr.Zero, "NativeSum"), TestResult.ArgumentNull);
-
-        // Call with null string
-        success &= EXPECT(GetLibraryExport(handle, null), TestResult.ArgumentNull);
-        success &= EXPECT(TryGetLibraryExport(handle, null), TestResult.ArgumentNull);
-
-        // Call with wrong string
-        success &= EXPECT(GetLibraryExport(handle, "NonNativeSum"), TestResult.EntryPointNotFound);
-        success &= EXPECT(TryGetLibraryExport(handle, "NonNativeSum"), TestResult.ReturnFailure);
-
-        Marshal.FreeLibrary(handle);
-
-        return (success) ? 100 : -100;
-    }
-
-    static string GetNativeLibraryPlainName()
-    {
-        return "NativeLibrary";
-    }
-
-    static string GetWin32LibName()
-    {
-        return "msi.dll";
-    }
-
-    static string GetNativeLibraryName()
-    {
-        string baseName = GetNativeLibraryPlainName();
-
-        if (TestLibrary.Utilities.IsWindows)
-        {
-            return baseName + ".dll";
-        }
-        if (TestLibrary.Utilities.IsLinux)
-        {
-            return "lib" + baseName + ".so";
-        }
-        if (TestLibrary.Utilities.IsMacOSX)
-        {
-            return "lib" + baseName + ".dylib";
-        }
-
-        return "ERROR";
-    }
-
-    static bool EXPECT(TestResult actualValue, TestResult expectedValue = TestResult.Success)
-    {
-        if (actualValue == expectedValue)
-        {
-            if (Verbose)
-                Console.WriteLine(String.Format("{0} : {1} : [OK]", CurrentTest, actualValue));
-            return true;
-        }
-        else
-        {
-            Console.WriteLine(String.Format(" {0} : {1} : [FAIL]", CurrentTest, actualValue));
-            return false;
-        }
-    }
-
-    static TestResult Run (Func<TestResult> test)
-    {
-
-        TestResult result;
-
-        try
-        {
-            result = test();
-        }
-        catch (ArgumentNullException e)
-        {
-            return  TestResult.ArgumentNull;
-        }
-        catch (ArgumentException e)
-        {
-            return TestResult.ArgumentBad;
-        }
-        catch (DllNotFoundException e)
-        {
-            return TestResult.DllNotFound;
-        }
-        catch (BadImageFormatException e)
-        {
-            return TestResult.BadImage;
-        }
-        catch (InvalidOperationException e)
-        {
-            return TestResult.InvalidOperation;
-        }
-        catch (EntryPointNotFoundException e)
-        {
-            return TestResult.EntryPointNotFound;
-        }
-        catch (Exception e)
-        {
-            //Console.WriteLine(e.ToString());
-            return TestResult.GenericException;
-        }
-
-        return result;
-    }
-
-    static TestResult LoadLibrarySimple(string libPath)
-    {
-        CurrentTest = String.Format("LoadLibrary({0})", libPath);
-
-        IntPtr handle = IntPtr.Zero;
-
-        TestResult result = Run(() => {
-            handle = Marshal.LoadLibrary(libPath);
-            if (handle == IntPtr.Zero)
-                return  TestResult.ReturnNull;
-            return TestResult.Success;
-        });
-
-        Marshal.FreeLibrary(handle);
-
-        return result;
-    }
-
-    static TestResult TryLoadLibrarySimple(string libPath)
-    {
-        CurrentTest = String.Format("TryLoadLibrary({0})", libPath);
-
-        IntPtr handle = IntPtr.Zero;
-
-        TestResult result = Run(() => {
-            bool success = Marshal.TryLoadLibrary(libPath, out handle);
-            if(!success)
-                return TestResult.ReturnFailure;
-            if (handle == null)
-                return  TestResult.ReturnNull;
-            return TestResult.Success;
-        });
-
-        Marshal.FreeLibrary(handle);
-
-        return result;
-    }
-
-
-    static TestResult LoadLibraryAdvanced(string libName, Assembly assembly, DllImportSearchPath? searchPath)
-    {
-        CurrentTest = String.Format("LoadLibrary({0}, {1}, {2})", libName, assembly, searchPath);
-
-        IntPtr handle = IntPtr.Zero;
-
-        TestResult result = Run(() => {
-            handle = Marshal.LoadLibrary(libName, assembly, searchPath);
-            if (handle == IntPtr.Zero)
-                return  TestResult.ReturnNull;
-            return TestResult.Success;
-        });
-
-        Marshal.FreeLibrary(handle);
-
-        return result;
-    }
-
-    static TestResult TryLoadLibraryAdvanced(string libName, Assembly assembly, DllImportSearchPath? searchPath)
-    {
-        CurrentTest = String.Format("TryLoadLibrary({0}, {1}, {2})", libName, assembly, searchPath);
-
-        IntPtr handle = IntPtr.Zero;
-
-        TestResult result = Run(() => {
-            bool success = Marshal.TryLoadLibrary(libName, assembly, searchPath, out handle);
-            if (!success)
-                return  TestResult.ReturnFailure;
-            if (handle == IntPtr.Zero)
-                return  TestResult.ReturnNull;
-            return TestResult.Success;
-        });
-
-        Marshal.FreeLibrary(handle);
-
-        return result;
-    }
-
-    static TestResult FreeLibrary(IntPtr handle)
-    {
-        CurrentTest = String.Format("FreeLibrary({0})", handle);
-
-        return Run(() => {
-            Marshal.FreeLibrary(handle);
-            return TestResult.Success;
-        });
-    }
-
-    static TestResult GetLibraryExport(IntPtr handle, string name)
-    {
-        CurrentTest = String.Format("GetLibraryExport({0}, {1})", handle, name);
-
-        return Run(() => {
-            IntPtr address = Marshal.GetLibraryExport(handle, name);
-            if (address == null)
-                return  TestResult.ReturnNull;
-            if (RunExportedFunction(address, 1, 1) != 2)
-                return TestResult.IncorrectEvaluation;
-            return TestResult.Success;
-        });
-    }
-
-    static TestResult TryGetLibraryExport(IntPtr handle, string name)
-    {
-        CurrentTest = String.Format("TryGetLibraryExport({0}, {1})", handle, name);
-
-        return Run(() => {
-            IntPtr address = IntPtr.Zero;
-            bool success = Marshal.TryGetLibraryExport(handle, name, out address);
-            if (!success)
-                return  TestResult.ReturnFailure;
-            if (address == null)
-                return  TestResult.ReturnNull;
-            if (RunExportedFunction(address, 1, 1) != 2)
-                return TestResult.IncorrectEvaluation;
-            return TestResult.Success;
-        });
-    }
-    [DllImport("NativeLibrary")]
-    static extern int RunExportedFunction(IntPtr address, int arg1, int arg2);
-}
diff --git a/src/coreclr/tests/src/Interop/NativeLibrary/NativeLibraryTests.cs b/src/coreclr/tests/src/Interop/NativeLibrary/NativeLibraryTests.cs
new file mode 100644 (file)
index 0000000..19eb125
--- /dev/null
@@ -0,0 +1,395 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+using Console = Internal.Console;
+
+enum TestResult {
+    Success,
+    ReturnFailure,
+    ReturnNull,
+    IncorrectEvaluation,
+    ArgumentNull,
+    ArgumentBad,
+    DllNotFound,
+    BadImage,
+    InvalidOperation,
+    EntryPointNotFound,
+    GenericException
+    };
+
+public class NativeLibraryTest
+{
+    static string CurrentTest;
+    static bool Verbose = false;
+    public static int Main()
+    {
+        bool success = true;
+
+        Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
+        string testBinDir = Path.GetDirectoryName(assembly.Location);
+        string libName;
+        IntPtr handle;
+
+        try
+        {
+            // -----------------------------------------------
+            //         Simple LoadLibrary() API Tests
+            // -----------------------------------------------
+
+            // Calls on correct full-path to native lib
+            libName = Path.Combine(testBinDir, GetNativeLibraryName());
+            success &= EXPECT(LoadLibrarySimple(libName));
+            success &= EXPECT(TryLoadLibrarySimple(libName));
+
+            // Calls on non-existant file
+            libName = Path.Combine(testBinDir, "notfound");
+            success &= EXPECT(LoadLibrarySimple(libName), TestResult.DllNotFound);
+            success &= EXPECT(TryLoadLibrarySimple(libName), TestResult.ReturnFailure);
+
+            // Calls on an invalid file
+            libName = Path.Combine(testBinDir, "NativeLibrary.cpp");
+            success &= EXPECT(LoadLibrarySimple(libName),
+                (TestLibrary.Utilities.IsWindows) ? TestResult.BadImage : TestResult.DllNotFound);
+            success &= EXPECT(TryLoadLibrarySimple(libName), TestResult.ReturnFailure);
+
+            // Calls on null input
+            libName = null;
+            success &= EXPECT(LoadLibrarySimple(libName), TestResult.ArgumentNull);
+            success &= EXPECT(TryLoadLibrarySimple(libName), TestResult.ArgumentNull);
+
+            // -----------------------------------------------
+            //         Advanced LoadLibrary() API Tests
+            // -----------------------------------------------
+
+            // Advanced LoadLibrary() API Tests
+            // Calls on correct full-path to native lib
+            libName = Path.Combine(testBinDir, GetNativeLibraryName());
+            success &= EXPECT(LoadLibraryAdvanced(libName, assembly, null));
+            success &= EXPECT(TryLoadLibraryAdvanced(libName, assembly, null));
+
+            // Calls on non-existant file
+            libName = Path.Combine(testBinDir, "notfound");
+            success &= EXPECT(LoadLibraryAdvanced(libName, assembly, null), TestResult.DllNotFound);
+            success &= EXPECT(TryLoadLibraryAdvanced(libName, assembly, null), TestResult.ReturnFailure);
+
+            // Calls on an invalid file
+            libName = Path.Combine(testBinDir, "NativeLibrary.cpp");
+            // The VM can only distinguish BadImageFormatException from DllNotFoundException on Windows.
+            success &= EXPECT(LoadLibraryAdvanced(libName, assembly, null),
+                (TestLibrary.Utilities.IsWindows) ? TestResult.BadImage : TestResult.DllNotFound);
+            success &= EXPECT(TryLoadLibraryAdvanced(libName, assembly, null), TestResult.ReturnFailure);
+
+            // Calls on just Native Library name
+            libName = GetNativeLibraryPlainName();
+            success &= EXPECT(LoadLibraryAdvanced(libName, assembly, null));
+            success &= EXPECT(TryLoadLibraryAdvanced(libName, assembly, null));
+
+            // Calls on Native Library name with correct prefix-suffix
+            libName = GetNativeLibraryName();
+            success &= EXPECT(LoadLibraryAdvanced(libName, assembly, null));
+            success &= EXPECT(TryLoadLibraryAdvanced(libName, assembly, null));
+
+            // Calls on full path without prefix-siffix
+            libName = Path.Combine(testBinDir, GetNativeLibraryPlainName());
+            // DllImport doesn't add a prefix if the name is preceeded by a path specification.
+            // Windows only needs a suffix, but Linux and Mac need both prefix and suffix
+            success &= EXPECT(LoadLibraryAdvanced(libName, assembly, null),
+                (TestLibrary.Utilities.IsWindows) ? TestResult.Success : TestResult.DllNotFound);
+            success &= EXPECT(TryLoadLibraryAdvanced(libName, assembly, null),
+                (TestLibrary.Utilities.IsWindows) ? TestResult.Success : TestResult.ReturnFailure);
+
+            if (TestLibrary.Utilities.IsWindows)
+            {
+                libName = GetWin32LibName();
+
+                // Calls on a valid library from System32 directory
+                success &= EXPECT(LoadLibraryAdvanced(libName, assembly, DllImportSearchPath.System32));
+                success &= EXPECT(TryLoadLibraryAdvanced(libName, assembly, DllImportSearchPath.System32));
+
+                // Calls on a valid library from 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
+            success &= EXPECT(LoadLibraryAdvanced(null, assembly, null), TestResult.ArgumentNull);
+            success &= EXPECT(TryLoadLibraryAdvanced(null, assembly, null), TestResult.ArgumentNull);
+
+            // Calls with null assembly
+            libName = GetNativeLibraryPlainName();
+            success &= EXPECT(LoadLibraryAdvanced(libName, null, null), TestResult.ArgumentNull);
+            success &= EXPECT(TryLoadLibraryAdvanced(libName, null, null), TestResult.ArgumentNull);
+
+            // Ensure that a lib is not picked up from current directory when
+            // a different full-path is specified.
+            libName = Path.Combine(testBinDir, Path.Combine("lib", GetNativeLibraryPlainName()));
+            success &= EXPECT(LoadLibraryAdvanced(libName, assembly, DllImportSearchPath.AssemblyDirectory), TestResult.DllNotFound);
+            success &= EXPECT(TryLoadLibraryAdvanced(libName, assembly, DllImportSearchPath.AssemblyDirectory), TestResult.ReturnFailure);
+
+            // -----------------------------------------------
+            //         FreeLibrary Tests
+            // -----------------------------------------------
+
+            libName = Path.Combine(testBinDir, GetNativeLibraryName());
+            handle = NativeLibrary.Load(libName);
+
+            // Valid Free
+            success &= EXPECT(FreeLibrary(handle));
+
+            // Double Free
+            success &= EXPECT(FreeLibrary(handle), TestResult.InvalidOperation);
+
+            // Null Free
+            success &= EXPECT(FreeLibrary(IntPtr.Zero));
+
+            // -----------------------------------------------
+            //         GetLibraryExport Tests
+            // -----------------------------------------------
+            libName = Path.Combine(testBinDir, GetNativeLibraryName());
+            handle = NativeLibrary.Load(libName);
+
+            // Valid Call (with some hard-coded name mangling)
+            success &= EXPECT(GetLibraryExport(handle, TestLibrary.Utilities.IsX86 ? "_NativeSum@8" : "NativeSum"));
+            success &= EXPECT(TryGetLibraryExport(handle, TestLibrary.Utilities.IsX86 ? "_NativeSum@8" : "NativeSum"));
+
+            // Call with null handle
+            success &= EXPECT(GetLibraryExport(IntPtr.Zero, "NativeSum"), TestResult.ArgumentNull);
+            success &= EXPECT(TryGetLibraryExport(IntPtr.Zero, "NativeSum"), TestResult.ArgumentNull);
+
+            // Call with null string
+            success &= EXPECT(GetLibraryExport(handle, null), TestResult.ArgumentNull);
+            success &= EXPECT(TryGetLibraryExport(handle, null), TestResult.ArgumentNull);
+
+            // Call with wrong string
+            success &= EXPECT(GetLibraryExport(handle, "NonNativeSum"), TestResult.EntryPointNotFound);
+            success &= EXPECT(TryGetLibraryExport(handle, "NonNativeSum"), TestResult.ReturnFailure);
+
+            NativeLibrary.Free(handle);
+        }
+        catch (Exception e)
+        {
+            // Catch any exceptions in NativeLibrary calls directly within this function.
+            // These calls are used to setup the environment for tests that follow, and are not expected to fail.
+            // If they do fail (ex: incorrect build environment) fail with an error code, rather than segmentation fault.
+            Console.WriteLine(String.Format("Unhandled exception {0}", e));
+            success = false;
+        }
+
+        return (success) ? 100 : -100;
+    }
+
+    static string GetNativeLibraryPlainName()
+    {
+        return "NativeLibrary";
+    }
+
+    static string GetWin32LibName()
+    {
+        return "msi.dll";
+    }
+
+    static string GetNativeLibraryName()
+    {
+        string baseName = GetNativeLibraryPlainName();
+
+        if (TestLibrary.Utilities.IsWindows)
+        {
+            return baseName + ".dll";
+        }
+        if (TestLibrary.Utilities.IsLinux)
+        {
+            return "lib" + baseName + ".so";
+        }
+        if (TestLibrary.Utilities.IsMacOSX)
+        {
+            return "lib" + baseName + ".dylib";
+        }
+
+        return "ERROR";
+    }
+
+    static bool EXPECT(TestResult actualValue, TestResult expectedValue = TestResult.Success)
+    {
+        if (actualValue == expectedValue)
+        {
+            if (Verbose)
+                Console.WriteLine(String.Format("{0} : {1} : [OK]", CurrentTest, actualValue));
+            return true;
+        }
+        else
+        {
+            Console.WriteLine(String.Format(" {0} : {1} : [FAIL]", CurrentTest, actualValue));
+            return false;
+        }
+    }
+
+    static TestResult Run (Func<TestResult> test)
+    {
+
+        TestResult result;
+
+        try
+        {
+            result = test();
+        }
+        catch (ArgumentNullException e)
+        {
+            return  TestResult.ArgumentNull;
+        }
+        catch (ArgumentException e)
+        {
+            return TestResult.ArgumentBad;
+        }
+        catch (DllNotFoundException e)
+        {
+            return TestResult.DllNotFound;
+        }
+        catch (BadImageFormatException e)
+        {
+            return TestResult.BadImage;
+        }
+        catch (InvalidOperationException e)
+        {
+            return TestResult.InvalidOperation;
+        }
+        catch (EntryPointNotFoundException e)
+        {
+            return TestResult.EntryPointNotFound;
+        }
+        catch (Exception e)
+        {
+            //Console.WriteLine(e.ToString());
+            return TestResult.GenericException;
+        }
+
+        return result;
+    }
+
+    static TestResult LoadLibrarySimple(string libPath)
+    {
+        CurrentTest = String.Format("LoadLibrary({0})", libPath);
+
+        IntPtr handle = IntPtr.Zero;
+
+        TestResult result = Run(() => {
+            handle = NativeLibrary.Load(libPath);
+            if (handle == IntPtr.Zero)
+                return  TestResult.ReturnNull;
+            return TestResult.Success;
+        });
+
+        NativeLibrary.Free(handle);
+
+        return result;
+    }
+
+    static TestResult TryLoadLibrarySimple(string libPath)
+    {
+        CurrentTest = String.Format("TryLoadLibrary({0})", libPath);
+
+        IntPtr handle = IntPtr.Zero;
+
+        TestResult result = Run(() => {
+            bool success = NativeLibrary.TryLoad(libPath, out handle);
+            if(!success)
+                return TestResult.ReturnFailure;
+            if (handle == null)
+                return  TestResult.ReturnNull;
+            return TestResult.Success;
+        });
+
+        NativeLibrary.Free(handle);
+
+        return result;
+    }
+
+
+    static TestResult LoadLibraryAdvanced(string libName, Assembly assembly, DllImportSearchPath? searchPath)
+    {
+        CurrentTest = String.Format("LoadLibrary({0}, {1}, {2})", libName, assembly, searchPath);
+
+        IntPtr handle = IntPtr.Zero;
+
+        TestResult result = Run(() => {
+            handle = NativeLibrary.Load(libName, assembly, searchPath);
+            if (handle == IntPtr.Zero)
+                return  TestResult.ReturnNull;
+            return TestResult.Success;
+        });
+
+        NativeLibrary.Free(handle);
+
+        return result;
+    }
+
+    static TestResult TryLoadLibraryAdvanced(string libName, Assembly assembly, DllImportSearchPath? searchPath)
+    {
+        CurrentTest = String.Format("TryLoadLibrary({0}, {1}, {2})", libName, assembly, searchPath);
+
+        IntPtr handle = IntPtr.Zero;
+
+        TestResult result = Run(() => {
+            bool success = NativeLibrary.TryLoad(libName, assembly, searchPath, out handle);
+            if (!success)
+                return  TestResult.ReturnFailure;
+            if (handle == IntPtr.Zero)
+                return  TestResult.ReturnNull;
+            return TestResult.Success;
+        });
+
+        NativeLibrary.Free(handle);
+
+        return result;
+    }
+
+    static TestResult FreeLibrary(IntPtr handle)
+    {
+        CurrentTest = String.Format("FreeLibrary({0})", handle);
+
+        return Run(() => {
+            NativeLibrary.Free(handle);
+            return TestResult.Success;
+        });
+    }
+
+    static TestResult GetLibraryExport(IntPtr handle, string name)
+    {
+        CurrentTest = String.Format("GetLibraryExport({0}, {1})", handle, name);
+
+        return Run(() => {
+            IntPtr address = NativeLibrary.GetExport(handle, name);
+            if (address == null)
+                return  TestResult.ReturnNull;
+            if (RunExportedFunction(address, 1, 1) != 2)
+                return TestResult.IncorrectEvaluation;
+            return TestResult.Success;
+        });
+    }
+
+    static TestResult TryGetLibraryExport(IntPtr handle, string name)
+    {
+        CurrentTest = String.Format("TryGetLibraryExport({0}, {1})", handle, name);
+
+        return Run(() => {
+            IntPtr address = IntPtr.Zero;
+            bool success = NativeLibrary.TryGetExport(handle, name, out address);
+            if (!success)
+                return  TestResult.ReturnFailure;
+            if (address == null)
+                return  TestResult.ReturnNull;
+            if (RunExportedFunction(address, 1, 1) != 2)
+                return TestResult.IncorrectEvaluation;
+            return TestResult.Success;
+        });
+    }
+    [DllImport("NativeLibrary")]
+    static extern int RunExportedFunction(IntPtr address, int arg1, int arg2);
+}
@@ -35,7 +35,7 @@
     </None>
   </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="..\..\..\Common\CoreCLRTestLibrary\CoreCLRTestLibrary.csproj">
+    <ProjectReference Include="..\..\Common\CoreCLRTestLibrary\CoreCLRTestLibrary.csproj">
       <Project>{c8c0dc74-fac4-45b1-81fe-70c4808366e0}</Project>
       <Name>CoreCLRTestLibrary</Name>
     </ProjectReference>