Update COM Activator class (#22317)
authorAaron Robinson <arobins@microsoft.com>
Tue, 12 Feb 2019 16:33:58 +0000 (08:33 -0800)
committerGitHub <noreply@github.com>
Tue, 12 Feb 2019 16:33:58 +0000 (08:33 -0800)
* Update COM Activator to use ALCs

* Update tests to now supply an assembly name rather than an binary "path"
  since the COM activator is now using ALCs.

* Add test for non-rooted assembly path.

* Move the hostpolicy mock project to a Common area
Move hostpolicy mock API to CoreCLR test library

* Add test for COM server isolation

* Move ComActivator class and logic to Internal namespace.

34 files changed:
src/System.Private.CoreLib/System.Private.CoreLib.csproj
src/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.cs [moved from src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComActivator.cs with 69% similarity]
src/coreclr/hosts/coreshim/ComActivation.cpp
src/coreclr/hosts/coreshim/CoreShim.cpp
src/coreclr/hosts/coreshim/CoreShim.h
tests/src/Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj
tests/src/Common/CoreCLRTestLibrary/HostPolicyMock.cs [moved from tests/src/Loader/AssemblyDependencyResolverTests/HostPolicyMock.cs with 90% similarity]
tests/src/Common/CoreCLRTestLibrary/XPlatformUtils.cs [moved from tests/src/Loader/AssemblyDependencyResolverTests/XPlatformUtils.cs with 88% similarity]
tests/src/Common/hostpolicymock/CMakeLists.txt [moved from tests/src/Loader/AssemblyDependencyResolverTests/CMakeLists.txt with 100% similarity]
tests/src/Common/hostpolicymock/HostpolicyMock.cpp [moved from tests/src/Loader/AssemblyDependencyResolverTests/HostpolicyMock.cpp with 86% similarity]
tests/src/Interop/COM/Activator/Activator.csproj
tests/src/Interop/COM/Activator/Program.cs
tests/src/Interop/COM/Activator/Servers/AssemblyA.cs [new file with mode: 0644]
tests/src/Interop/COM/Activator/Servers/AssemblyA.csproj [new file with mode: 0644]
tests/src/Interop/COM/Activator/Servers/AssemblyB.cs [new file with mode: 0644]
tests/src/Interop/COM/Activator/Servers/AssemblyB.csproj [new file with mode: 0644]
tests/src/Interop/COM/Activator/Servers/AssemblyC.cs [new file with mode: 0644]
tests/src/Interop/COM/Activator/Servers/AssemblyC.csproj [new file with mode: 0644]
tests/src/Interop/COM/Activator/Servers/AssemblyContracts.cs [new file with mode: 0644]
tests/src/Interop/COM/Activator/Servers/AssemblyContracts.csproj [new file with mode: 0644]
tests/src/Interop/COM/NativeClients/Primitives.csproj
tests/src/Interop/COM/NativeClients/Primitives/ArrayTests.cpp
tests/src/Interop/COM/NativeClients/Primitives/ColorTests.cpp
tests/src/Interop/COM/NativeClients/Primitives/ErrorTests.cpp
tests/src/Interop/COM/NativeClients/Primitives/NumericTests.cpp
tests/src/Interop/COM/NativeClients/Primitives/StringTests.cpp
tests/src/Interop/ExecInDefAppDom/ExecInDefAppDom.csproj
tests/src/Interop/Interop.settings.targets
tests/src/Interop/NativeCallable/NativeCallableTest.csproj
tests/src/Interop/PInvoke/CustomMarshalers/CustomMarshalersTest.csproj
tests/src/Loader/AssemblyDependencyResolverTests/AssemblyDependencyResolverTests.cs
tests/src/Loader/AssemblyDependencyResolverTests/AssemblyDependencyResolverTests.csproj
tests/src/Loader/AssemblyDependencyResolverTests/InvalidHostingTest.cs
tests/src/Loader/AssemblyDependencyResolverTests/NativeDependencyTests.cs

index 79659fb..62da9c9 100644 (file)
   </ItemGroup>
   <ItemGroup Condition="'$(FeatureCominterop)' == 'true'">
     <Compile Include="$(BclSourcesRoot)\Internal\Runtime\InteropServices\WindowsRuntime\ExceptionSupport.cs" />
+    <Compile Include="$(BclSourcesRoot)\Internal\Runtime\InteropServices\ComActivator.cs" Condition="'$(FeatureCominteropUnmanagedActivation)' == 'true'" />
     <Compile Include="$(BclSourcesRoot)\Microsoft\Win32\OAVariantLib.cs" Condition="'$(FeatureClassicCominterop)' == 'true'" />
     <Compile Include="$(BclSourcesRoot)\System\__ComObject.cs" />
-    <Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComActivator.cs" Condition="'$(FeatureCominteropUnmanagedActivation)' == 'true'" />
     <Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComEventsHelper.cs" Condition="'$(FeatureClassicCominterop)' == 'true'" />
     <Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComEventsInfo.cs" Condition="'$(FeatureClassicCominterop)' == 'true'" />
     <Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComEventsMethod.cs" Condition="'$(FeatureClassicCominterop)' == 'true'" />
@@ -3,17 +3,24 @@
 // See the LICENSE file in the project root for more information.
 
 using System;
+using System.Collections.Generic;
 using System.Diagnostics;
 using System.IO;
 using System.Reflection;
-
-namespace System.Runtime.InteropServices
+using System.Runtime.InteropServices;
+using System.Runtime.Loader;
+
+//
+// Types in this file marked as 'public' are done so only to aid in
+// testing of functionality and should not be considered publicly consumable.
+//
+namespace Internal.Runtime.InteropServices
 {
     [ComImport]
     [ComVisible(false)]
     [Guid("00000001-0000-0000-C000-000000000046")]
     [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
-    internal interface IClassFactory
+    public interface IClassFactory
     {
         void CreateInstance(
             [MarshalAs(UnmanagedType.Interface)] object pUnkOuter,
@@ -67,22 +74,29 @@ namespace System.Runtime.InteropServices
     {
         public Guid ClassId;
         public Guid InterfaceId;
+        public string AssemblyPath;
         public string AssemblyName;
         public string TypeName;
     }
 
     [StructLayout(LayoutKind.Sequential)]
-    public struct ComActivationContextInternal
+    [CLSCompliant(false)]
+    public unsafe struct ComActivationContextInternal
     {
         public Guid ClassId;
         public Guid InterfaceId;
-        public IntPtr AssemblyNameBuffer;
-        public IntPtr TypeNameBuffer;
+        public char* AssemblyPathBuffer;
+        public char* AssemblyNameBuffer;
+        public char* TypeNameBuffer;
         public IntPtr ClassFactoryDest;
     }
 
     public static class ComActivator
     {
+        // Collection of all ALCs used for COM activation. In the event we want to support
+        // unloadable COM server ALCs, this will need to be changed.
+        private static Dictionary<string, AssemblyLoadContext> s_AssemblyLoadContexts = new Dictionary<string, AssemblyLoadContext>(StringComparer.InvariantCultureIgnoreCase);
+
         /// <summary>
         /// Entry point for unmanaged COM activation API from managed code
         /// </summary>
@@ -95,7 +109,12 @@ namespace System.Runtime.InteropServices
                 throw new NotSupportedException();
             }
 
-            Type classType = FindClassType(cxt.ClassId, cxt.AssemblyName, cxt.TypeName);
+            if (!Path.IsPathRooted(cxt.AssemblyPath))
+            {
+                throw new ArgumentException();
+            }
+
+            Type classType = FindClassType(cxt.ClassId, cxt.AssemblyPath, cxt.AssemblyName, cxt.TypeName);
             return new BasicClassFactory(cxt.ClassId, classType);
         }
 
@@ -103,7 +122,8 @@ namespace System.Runtime.InteropServices
         /// Internal entry point for unmanaged COM activation API from native code
         /// </summary>
         /// <param name="cxtInt">Reference to a <see cref="ComActivationContextInternal"/> instance</param>
-        public static int GetClassFactoryForTypeInternal(ref ComActivationContextInternal cxtInt)
+        [CLSCompliant(false)]
+        public unsafe static int GetClassFactoryForTypeInternal(ref ComActivationContextInternal cxtInt)
         {
             if (IsLoggingEnabled())
             {
@@ -111,8 +131,9 @@ namespace System.Runtime.InteropServices
 $@"{nameof(GetClassFactoryForTypeInternal)} arguments:
     {cxtInt.ClassId}
     {cxtInt.InterfaceId}
-    0x{cxtInt.AssemblyNameBuffer.ToInt64():x}
-    0x{cxtInt.TypeNameBuffer.ToInt64():x}
+    0x{(ulong)cxtInt.AssemblyPathBuffer:x}
+    0x{(ulong)cxtInt.AssemblyNameBuffer:x}
+    0x{(ulong)cxtInt.TypeNameBuffer:x}
     0x{cxtInt.ClassFactoryDest.ToInt64():x}");
             }
 
@@ -122,8 +143,9 @@ $@"{nameof(GetClassFactoryForTypeInternal)} arguments:
                 {
                     ClassId = cxtInt.ClassId,
                     InterfaceId = cxtInt.InterfaceId,
-                    AssemblyName = Marshal.PtrToStringUTF8(cxtInt.AssemblyNameBuffer),
-                    TypeName = Marshal.PtrToStringUTF8(cxtInt.TypeNameBuffer)
+                    AssemblyPath = Marshal.PtrToStringUni(new IntPtr(cxtInt.AssemblyPathBuffer)),
+                    AssemblyName = Marshal.PtrToStringUni(new IntPtr(cxtInt.AssemblyNameBuffer)),
+                    TypeName = Marshal.PtrToStringUni(new IntPtr(cxtInt.TypeNameBuffer))
                 };
 
                 object cf = GetClassFactoryForType(cxt);
@@ -154,11 +176,13 @@ $@"{nameof(GetClassFactoryForTypeInternal)} arguments:
             Debug.WriteLine(fmt, args);
          }
 
-        private static Type FindClassType(Guid clsid, string assemblyName, string typeName)
+        private static Type FindClassType(Guid clsid, string assemblyPath, string assemblyName, string typeName)
         {
             try
             {
-                Assembly assem = Assembly.LoadFrom(assemblyName);
+                AssemblyLoadContext alc = GetALC(assemblyPath);
+                var assemblyNameLocal = new AssemblyName(assemblyName);
+                Assembly assem = alc.LoadFromAssemblyName(assemblyNameLocal);
                 Type t = assem.GetType(typeName);
                 if (t != null)
                 {
@@ -177,6 +201,54 @@ $@"{nameof(GetClassFactoryForTypeInternal)} arguments:
             throw new COMException(string.Empty, CLASS_E_CLASSNOTAVAILABLE);
         }
 
+        private static AssemblyLoadContext GetALC(string assemblyPath)
+        {
+            AssemblyLoadContext alc;
+
+            lock (s_AssemblyLoadContexts)
+            {
+                if (!s_AssemblyLoadContexts.TryGetValue(assemblyPath, out alc))
+                {
+                    alc = new ComServerLoadContext(assemblyPath);
+                    s_AssemblyLoadContexts.Add(assemblyPath, alc);
+                }
+            }
+
+            return alc;
+        }
+
+        private class ComServerLoadContext : AssemblyLoadContext
+        {
+            private readonly AssemblyDependencyResolver _resolver;
+
+            public ComServerLoadContext(string comServerAssemblyPath)
+            {
+                _resolver = new AssemblyDependencyResolver(comServerAssemblyPath);
+            }
+
+            protected override Assembly Load(AssemblyName assemblyName)
+            {
+                string assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
+                if (assemblyPath != null)
+                {
+                    return LoadFromAssemblyPath(assemblyPath);
+                }
+
+                return null;
+            }
+
+            protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
+            {
+                string libraryPath = _resolver.ResolveUnmanagedDllToPath(unmanagedDllName);
+                if (libraryPath != null)
+                {
+                    return LoadUnmanagedDllFromPath(libraryPath);
+                }
+
+                return IntPtr.Zero;
+            }
+        }
+
         [ComVisible(true)]
         internal class BasicClassFactory : IClassFactory2
         {
index 5df1d00..6c03be0 100644 (file)
@@ -23,13 +23,12 @@ namespace
             "TRUSTED_PLATFORM_ASSEMBLIES",
         };
 
-        // [TODO] Support UNICODE app path
-        char wd[MAX_PATH];
-        (void)::GetCurrentDirectoryA(ARRAYSIZE(wd), wd);
+        std::string assemblyPath;
+        RETURN_IF_FAILED(Utility::GetCoreShimDirectory(assemblyPath));
 
         const char *values[] =
         {
-            wd,
+            assemblyPath.c_str(),
             tpaList.c_str(),
         };
 
@@ -56,26 +55,33 @@ STDAPI DllGetClassObject(
     GetClassFactoryForTypeInternal_ptr GetClassFactoryForTypeInternal;
     RETURN_IF_FAILED(inst->CreateDelegate(
         "System.Private.CoreLib",
-        "System.Runtime.InteropServices.ComActivator",
+        "Internal.Runtime.InteropServices.ComActivator",
         "GetClassFactoryForTypeInternal", (void**)&GetClassFactoryForTypeInternal));
 
     // Get assembly and type for activation
-    std::string assemblyName;
+    std::wstring assemblyName;
     RETURN_IF_FAILED(Utility::TryGetEnvVar(COMACT_ASSEMBLYNAME_ENVVAR, assemblyName));
 
-    std::string typeName;
+    std::wstring typeName;
     RETURN_IF_FAILED(Utility::TryGetEnvVar(COMACT_TYPENAME_ENVVAR, typeName));
 
+    // Compute the path to the assembly. This should be adjacent to CoreShim (i.e. this library).
+    std::wstring assemblyPath;
+    RETURN_IF_FAILED(Utility::GetCoreShimDirectory(assemblyPath));
+    assemblyPath.append(assemblyName);
+    assemblyPath.append(W(".dll"));
+
     IUnknown *ccw = nullptr;
 
     struct ComActivationContext
     {
         GUID ClassId;
         GUID InterfaceId;
-        const void *AssemblyName;
-        const void *TypeName;
+        const WCHAR *AssemblyPath;
+        const WCHAR *AssemblyName;
+        const WCHAR *TypeName;
         void **ClassFactoryDest;
-    } comCxt{ rclsid, riid, assemblyName.data(), typeName.data(), (void**)&ccw };
+    } comCxt{ rclsid, riid, assemblyPath.data(), assemblyName.data(), typeName.data(), (void**)&ccw };
 
     RETURN_IF_FAILED(GetClassFactoryForTypeInternal(&comCxt));
     assert(ccw != nullptr);
index f055b04..bb6ec8a 100644 (file)
@@ -92,12 +92,11 @@ namespace
 
 namespace Utility
 {
-    HRESULT TryGetEnvVar(_In_z_ const WCHAR *env, _Inout_ std::string &envVar)
+    HRESULT TryGetEnvVar(_In_z_ const WCHAR *env, _Inout_ std::wstring &envVar)
     {
         try
         {
-            std::wstring envVarLocal = GetEnvVar(env);
-            envVar = ConvertWideToUtf8(envVarLocal);
+            envVar = GetEnvVar(env);
         }
         catch (HRESULT hr)
         {
@@ -106,6 +105,49 @@ namespace Utility
 
         return S_OK;
     }
+
+    HRESULT GetCoreShimDirectory(_Inout_ std::wstring &dir)
+    {
+        HMODULE hModule;
+        BOOL res = ::GetModuleHandleExW(
+            GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+            reinterpret_cast<LPCWSTR>(&TryGetEnvVar),
+            &hModule);
+        if (res == FALSE)
+            return HRESULT_FROM_WIN32(::GetLastError());
+
+        std::wstring path;
+        size_t dwModuleFileName = MAX_PATH / 2;
+
+        do
+        {
+            path.resize(dwModuleFileName * 2);
+            dwModuleFileName = GetModuleFileNameW(hModule, (LPWSTR)path.data(), static_cast<DWORD>(path.size()));
+        } while (dwModuleFileName == path.size());
+
+        if (dwModuleFileName == 0)
+            return HRESULT_FROM_WIN32(::GetLastError());
+
+        size_t idx = path.find_last_of(W('\\'));
+        if (idx == std::wstring::npos)
+            return E_UNEXPECTED;
+
+        path.resize(idx + 1);
+        dir = std::move(path);
+        return S_OK;
+    }
+
+    HRESULT GetCoreShimDirectory(_Inout_ std::string &dir)
+    {
+        HRESULT hr;
+
+        std::wstring dir_wide;
+        RETURN_IF_FAILED(GetCoreShimDirectory(dir_wide));
+
+        dir = ConvertWideToUtf8(dir_wide);
+
+        return S_OK;
+    }
 }
 
 HRESULT coreclr::GetCoreClrInstance(_Outptr_ coreclr **instance, _In_opt_z_ const WCHAR *path)
@@ -116,6 +158,42 @@ HRESULT coreclr::GetCoreClrInstance(_Outptr_ coreclr **instance, _In_opt_z_ cons
         return S_FALSE;
     }
 
+    // Since the CoreShim is being loaded, there is a chance the scenario depends on
+    // other aspects of the offical host platform (e.g. hostpolicy). Verify a hostpolicy
+    // is _not_ already loaded and if not, attempt to load a hostpolicy library adjacent
+    // to the coreshim. If there isn't one, just keep going.
+    const WCHAR *hostpolicyName = W("hostpolicy.dll");
+    HMODULE hMod = ::GetModuleHandleW(hostpolicyName);
+    if (hMod == nullptr)
+    {
+        HRESULT hr;
+        std::wstring coreShimPath;
+        RETURN_IF_FAILED(Utility::GetCoreShimDirectory(coreShimPath));
+
+        std::wstring hostpolicyPath{ coreShimPath };
+        hostpolicyPath.append(hostpolicyName);
+
+        // Check if a hostpolicy exists and if it does, load it.
+        if (INVALID_FILE_ATTRIBUTES != ::GetFileAttributesW(hostpolicyPath.c_str()))
+        {
+            hMod = ::LoadLibraryExW(hostpolicyPath.c_str(), nullptr, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
+            if (hMod == nullptr)
+                return E_UNEXPECTED;
+
+            // Initialize the hostpolicy mock to a default state
+            using Set_corehost_resolve_component_dependencies_Values_fn = void(STDMETHODCALLTYPE *)(
+                int returnValue,
+                const WCHAR *assemblyPaths,
+                const WCHAR *nativeSearchPaths,
+                const WCHAR *resourceSearchPaths);
+            auto set_comp_depend_values = (Set_corehost_resolve_component_dependencies_Values_fn)
+                ::GetProcAddress(hMod, "Set_corehost_resolve_component_dependencies_Values");
+
+            assert(set_comp_depend_values != nullptr);
+            set_comp_depend_values(0, W(""), W(""), W(""));
+        }
+    }
+
     try
     {
         std::wstring pathLocal;
index dd5e9d1..d4c8b0a 100644 (file)
@@ -110,7 +110,13 @@ namespace Utility
     /// <summary>
     /// Get the supplied environment variable.
     /// </summary>
-    HRESULT TryGetEnvVar(_In_z_ const WCHAR *env, _Inout_ std::string &envVar);
+    HRESULT TryGetEnvVar(_In_z_ const WCHAR *env, _Inout_ std::wstring &envVar);
+
+    /// <summary>
+    /// Get the CoreShim directory.
+    /// </summary>
+    HRESULT GetCoreShimDirectory(_Inout_ std::string &dir);
+    HRESULT GetCoreShimDirectory(_Inout_ std::wstring &dir);
 }
 
 // CoreShim environment variables used to indicate what assembly/type tuple
index 7e210d0..ea0ee84 100644 (file)
@@ -31,9 +31,8 @@
     <Compile Include="Logging.cs" />
     <Compile Include="TestFramework.cs" />
     <Compile Include="Utilities.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+    <Compile Include="HostPolicyMock.cs" />
+    <Compile Include="XPlatformUtils.cs" />
   </ItemGroup>
   <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
 </Project>
@@ -6,15 +6,15 @@ using System.IO;
 using System.Runtime.InteropServices;
 using System.Runtime.Loader;
 
-namespace AssemblyDependencyResolverTests
+namespace TestLibrary
 {
-    class HostPolicyMock
+    public class HostPolicyMock
     {
-#if WINDOWS
+    #if PLATFORM_WINDOWS
         private const CharSet HostpolicyCharSet = CharSet.Unicode;
-#else
+    #else
         private const CharSet HostpolicyCharSet = CharSet.Ansi;
-#endif
+    #endif
 
         [DllImport("hostpolicy", CharSet = HostpolicyCharSet)]
         private static extern int Set_corehost_resolve_component_dependencies_Values(
@@ -45,24 +45,32 @@ namespace AssemblyDependencyResolverTests
 
         public static string DeleteExistingHostpolicy(string coreRoot)
         {
+#if REFERENCING_SYSTEMPRIVATECORELIB
+            throw new Exception("This API is not supported when compiled referencing SPCL");
+
+#else
             string hostPolicyFileName = XPlatformUtils.GetStandardNativeLibraryFileName("hostpolicy");
             string destinationPath = Path.Combine(coreRoot, hostPolicyFileName);
+
             if (File.Exists(destinationPath))
             {
                 File.Delete(destinationPath);
             }
 
             return destinationPath;
+#endif
         }
 
         public static void Initialize(string testBasePath, string coreRoot)
         {
+#if !REFERENCING_SYSTEMPRIVATECORELIB
             string hostPolicyFileName = XPlatformUtils.GetStandardNativeLibraryFileName("hostpolicy");
             string destinationPath = DeleteExistingHostpolicy(coreRoot);
 
             File.Copy(
                 Path.Combine(testBasePath, hostPolicyFileName),
                 destinationPath);
+#endif
 
             _assemblyDependencyResolverType = typeof(AssemblyDependencyResolver);
 
@@ -72,7 +80,7 @@ namespace AssemblyDependencyResolverTests
             _corehost_error_writer_fnType = _assemblyDependencyResolverType.GetNestedType("corehost_error_writer_fn", System.Reflection.BindingFlags.NonPublic);
         }
 
-        public static MockValues_corehost_resolve_componet_dependencies Mock_corehost_resolve_componet_dependencies(
+        public static MockValues_corehost_resolve_component_dependencies Mock_corehost_resolve_component_dependencies(
             int returnValue,
             string assemblyPaths,
             string nativeSearchPaths,
@@ -84,10 +92,10 @@ namespace AssemblyDependencyResolverTests
                 nativeSearchPaths,
                 resourceSearchPaths);
 
-            return new MockValues_corehost_resolve_componet_dependencies();
+            return new MockValues_corehost_resolve_component_dependencies();
         }
 
-        internal class MockValues_corehost_resolve_componet_dependencies : IDisposable
+        public class MockValues_corehost_resolve_component_dependencies : IDisposable
         {
             private Callback_corehost_resolve_component_dependencies callback;
 
@@ -133,7 +141,7 @@ namespace AssemblyDependencyResolverTests
             return new MockValues_corehost_set_error_writer();
         }
 
-        internal class MockValues_corehost_set_error_writer : IDisposable
+        public class MockValues_corehost_set_error_writer : IDisposable
         {
             public IntPtr LastSetErrorWriterPtr
             {
@@ -1,16 +1,17 @@
 ï»¿// 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.
-namespace AssemblyDependencyResolverTests
+
+namespace TestLibrary
 {
-    class XPlatformUtils
+    public class XPlatformUtils
     {
-#if WINDOWS
+#if PLATFORM_WINDOWS
         public const string NativeLibraryPrefix = "";
         public const string NativeLibrarySuffix = ".dll";
 #else
         public const string NativeLibraryPrefix = "lib";
-#if OSX
+#if PLATFORM_OSX
         public const string NativeLibrarySuffix = ".dylib";
 #else
         public const string NativeLibrarySuffix = ".so";
 typedef wchar_t char_t;
 typedef std::wstring string_t;
 
-#else //!_Win32
+// Only create undecorated exports on Windows x86
+#if defined _X86_
+
+// Define undecorated exports to ease test set up from native code
+#pragma comment(linker, "/export:Set_corehost_resolve_component_dependencies_Callback=_Set_corehost_resolve_component_dependencies_Callback@4")
+#pragma comment(linker, "/export:Set_corehost_resolve_component_dependencies_Values=_Set_corehost_resolve_component_dependencies_Values@16")
+#pragma comment(linker, "/export:Set_corehost_set_error_writer_returnValue=_Set_corehost_set_error_writer_returnValue@4")
+
+#endif
+
+#else //!_WIN32
 
 #if __GNUC__ >= 4
 #define SHARED_API extern "C" __attribute__ ((visibility ("default")))
index 792b8be..b656a5c 100644 (file)
@@ -1,7 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
-  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Interop.settings.targets))\Interop.settings.targets" />
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -14,6 +13,8 @@
     <TestUnsupportedOutsideWindows>true</TestUnsupportedOutsideWindows>
     <DisableProjectBuild Condition="'$(TargetsWindows)' != 'true'">true</DisableProjectBuild>
   </PropertyGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Interop.settings.targets))\Interop.settings.targets" />
+
   <!-- Default configurations to help VS understand the configurations -->
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
   </PropertyGroup>
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\NetServer\NetServer.csproj" />
+    <ProjectReference Include="Servers\AssemblyA.csproj" />
+    <ProjectReference Include="Servers\AssemblyB.csproj" />
+    <ProjectReference Include="Servers\AssemblyC.csproj" />
+    <ProjectReference Include="Servers\AssemblyContracts.csproj" />
+    <ProjectReference Include="../../../Common/hostpolicymock/CMakeLists.txt" />
   </ItemGroup>
   <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+
+  <!-- Set up an isolated directory for the server assemblies -->
+  <Target Name="SetUpIsolatedDirectory"
+          AfterTargets="CopyFilesToOutputDirectory">
+
+    <PropertyGroup>
+      <ServerAssemblyDest>$(OutDir)/Servers</ServerAssemblyDest>
+    </PropertyGroup>
+
+    <ItemGroup>
+      <ServerAssembly Include="$(OutDir)/AssemblyA.*" />
+      <ServerAssembly Include="$(OutDir)/AssemblyB.*" />
+      <ServerAssembly Include="$(OutDir)/AssemblyC.*" />
+    </ItemGroup>
+
+    <Move SourceFiles="@(ServerAssembly)"
+          DestinationFolder="$(ServerAssemblyDest)" />
+  </Target>
+
 </Project>
index 4316736..451ecc7 100644 (file)
@@ -4,7 +4,10 @@
 
 namespace Activator
 {
+    using Internal.Runtime.InteropServices;
+
     using System;
+    using System.IO;
     using System.Runtime.InteropServices;
 
     using TestLibrary;
@@ -15,6 +18,8 @@ namespace Activator
     {
         static void InvalidInterfaceRequest()
         {
+            Console.WriteLine($"Running {nameof(InvalidInterfaceRequest)}...");
+
             Assert.Throws<NotSupportedException>(
                 () =>
                 {
@@ -28,17 +33,36 @@ namespace Activator
                 "Non-IClassFactory request should fail");
         }
 
+        static void NonrootedAssemblyPath()
+        {
+            Console.WriteLine($"Running {nameof(NonrootedAssemblyPath)}...");
+
+            ArgumentException e = Assert.Throws<ArgumentException>(
+                () =>
+                {
+                    var cxt = new ComActivationContext()
+                    {
+                        InterfaceId = typeof(IClassFactory).GUID,
+                        AssemblyPath = "foo.dll"
+                    };
+                    ComActivator.GetClassFactoryForType(cxt);
+                },
+                "Non-root assembly path should not be valid");
+        }
+
         static void ClassNotRegistered()
         {
+            Console.WriteLine($"Running {nameof(ClassNotRegistered)}...");
+
             COMException e = Assert.Throws<COMException>(
                 () =>
                 {
                     var CLSID_NotRegistered = new Guid("328FF83E-3F6C-4BE9-A742-752562032925"); // Random GUID
-                    var IID_IClassFactory = new Guid("00000001-0000-0000-C000-000000000046");
                     var cxt = new ComActivationContext()
                     {
                         ClassId = CLSID_NotRegistered,
-                        InterfaceId = IID_IClassFactory
+                        InterfaceId = typeof(IClassFactory).GUID,
+                        AssemblyPath = @"C:\foo.dll"
                     };
                     ComActivator.GetClassFactoryForType(cxt);
                 },
@@ -48,12 +72,78 @@ namespace Activator
             Assert.AreEqual(CLASS_E_CLASSNOTAVAILABLE, e.HResult, "Unexpected HRESULT");
         }
 
+        static void ValidateAssemblyIsolation()
+        {
+            Console.WriteLine($"Running {nameof(ValidateAssemblyIsolation)}...");
+
+            string assemblySubPath = Path.Combine(Environment.CurrentDirectory, "Servers");
+            string assemblyAPath = Path.Combine(assemblySubPath, "AssemblyA.dll");
+            string assemblyBPath = Path.Combine(assemblySubPath, "AssemblyB.dll");
+            string assemblyCPath = Path.Combine(assemblySubPath, "AssemblyC.dll");
+            string assemblyPaths = $"{assemblyAPath}{Path.PathSeparator}{assemblyBPath}{Path.PathSeparator}{assemblyCPath}";
+
+            HostPolicyMock.Initialize(Environment.CurrentDirectory, null);
+
+            var CLSID_NotUsed = Guid.Empty; // During this phase of activation the GUID is not used.
+            Guid iid = typeof(IGetTypeFromC).GUID;
+            Type typeCFromAssemblyA;
+            Type typeCFromAssemblyB;
+
+            using (HostPolicyMock.Mock_corehost_resolve_component_dependencies(
+                0,
+                assemblyPaths,
+                string.Empty,
+                string.Empty))
+            {
+                var cxt = new ComActivationContext()
+                {
+                    ClassId = CLSID_NotUsed,
+                    InterfaceId = typeof(IClassFactory).GUID,
+                    AssemblyPath = assemblyAPath,
+                    AssemblyName = "AssemblyA",
+                    TypeName = "ClassFromA"
+                };
+
+                var factory = (IClassFactory)ComActivator.GetClassFactoryForType(cxt);
+
+                object svr;
+                factory.CreateInstance(null, ref iid, out svr);
+                typeCFromAssemblyA = (Type)((IGetTypeFromC)svr).GetTypeFromC();
+            }
+
+            using (HostPolicyMock.Mock_corehost_resolve_component_dependencies(
+                0,
+                assemblyPaths,
+                string.Empty,
+                string.Empty))
+            {
+                var cxt = new ComActivationContext()
+                {
+                    ClassId = CLSID_NotUsed,
+                    InterfaceId = typeof(IClassFactory).GUID,
+                    AssemblyPath = assemblyBPath,
+                    AssemblyName = "AssemblyB",
+                    TypeName = "ClassFromB"
+                };
+
+                var factory = (IClassFactory)ComActivator.GetClassFactoryForType(cxt);
+
+                object svr;
+                factory.CreateInstance(null, ref iid, out svr);
+                typeCFromAssemblyB = (Type)((IGetTypeFromC)svr).GetTypeFromC();
+            }
+
+            Assert.AreNotEqual(typeCFromAssemblyA, typeCFromAssemblyB, "Types should be from different AssemblyLoadContexts");
+        }
+
         static int Main(string[] doNotUse)
         {
             try
             {
                 InvalidInterfaceRequest();
                 ClassNotRegistered();
+                NonrootedAssemblyPath();
+                ValidateAssemblyIsolation();
             }
             catch (Exception e)
             {
diff --git a/tests/src/Interop/COM/Activator/Servers/AssemblyA.cs b/tests/src/Interop/COM/Activator/Servers/AssemblyA.cs
new file mode 100644 (file)
index 0000000..606f064
--- /dev/null
@@ -0,0 +1,19 @@
+// 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;
+
+public class ClassFromA : IGetTypeFromC
+{
+    private readonly ClassFromC _fromC;
+    public ClassFromA()
+    {
+        this._fromC = new ClassFromC();
+    }
+    
+    public object GetTypeFromC()
+    {
+        return this._fromC.GetType();
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/COM/Activator/Servers/AssemblyA.csproj b/tests/src/Interop/COM/Activator/Servers/AssemblyA.csproj
new file mode 100644 (file)
index 0000000..b5fbf3b
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Interop.settings.targets))\Interop.settings.targets" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <AssemblyName>AssemblyA</AssemblyName>
+    <SchemaVersion>2.0</SchemaVersion>
+    <OutputType>library</OutputType>
+    <ProjectTypeGuids>{4948E98A-ECFC-4988-851E-68E1ADD2DD5A};{B850CC46-E8FB-4569-A28D-423F81E8A861}</ProjectTypeGuids>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="AssemblyA.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="AssemblyC.csproj" />
+    <ProjectReference Include="AssemblyContracts.csproj" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/tests/src/Interop/COM/Activator/Servers/AssemblyB.cs b/tests/src/Interop/COM/Activator/Servers/AssemblyB.cs
new file mode 100644 (file)
index 0000000..043434d
--- /dev/null
@@ -0,0 +1,19 @@
+// 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;
+
+public class ClassFromB : IGetTypeFromC
+{
+    private readonly ClassFromC _fromC;
+    public ClassFromB()
+    {
+        this._fromC = new ClassFromC();
+    }
+    
+    public object GetTypeFromC()
+    {
+        return this._fromC.GetType();
+    }
+}
\ No newline at end of file
diff --git a/tests/src/Interop/COM/Activator/Servers/AssemblyB.csproj b/tests/src/Interop/COM/Activator/Servers/AssemblyB.csproj
new file mode 100644 (file)
index 0000000..8f0fb0a
--- /dev/null
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Interop.settings.targets))\Interop.settings.targets" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <AssemblyName>AssemblyB</AssemblyName>
+    <SchemaVersion>2.0</SchemaVersion>
+    <OutputType>library</OutputType>
+    <ProjectTypeGuids>{4948E98A-ECFC-4988-851E-68E1ADD2DD5A};{B850CC46-E8FB-4569-A28D-423F81E8A861}</ProjectTypeGuids>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="AssemblyB.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="AssemblyC.csproj" />
+    <ProjectReference Include="AssemblyContracts.csproj" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/tests/src/Interop/COM/Activator/Servers/AssemblyC.cs b/tests/src/Interop/COM/Activator/Servers/AssemblyC.cs
new file mode 100644 (file)
index 0000000..fbb79f6
--- /dev/null
@@ -0,0 +1,9 @@
+// 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;
+
+public class ClassFromC
+{
+}
\ No newline at end of file
diff --git a/tests/src/Interop/COM/Activator/Servers/AssemblyC.csproj b/tests/src/Interop/COM/Activator/Servers/AssemblyC.csproj
new file mode 100644 (file)
index 0000000..8c5a84c
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Interop.settings.targets))\Interop.settings.targets" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <AssemblyName>AssemblyC</AssemblyName>
+    <SchemaVersion>2.0</SchemaVersion>
+    <OutputType>library</OutputType>
+    <ProjectTypeGuids>{4948E98A-ECFC-4988-851E-68E1ADD2DD5A};{B850CC46-E8FB-4569-A28D-423F81E8A861}</ProjectTypeGuids>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="AssemblyC.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/tests/src/Interop/COM/Activator/Servers/AssemblyContracts.cs b/tests/src/Interop/COM/Activator/Servers/AssemblyContracts.cs
new file mode 100644 (file)
index 0000000..deb7b63
--- /dev/null
@@ -0,0 +1,13 @@
+// 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.Runtime.InteropServices;
+
+[Guid("6B002803-4C9B-4E4F-BDA2-46AEFFD8D559")]
+public interface IGetTypeFromC
+{
+    object GetTypeFromC();
+}
\ No newline at end of file
diff --git a/tests/src/Interop/COM/Activator/Servers/AssemblyContracts.csproj b/tests/src/Interop/COM/Activator/Servers/AssemblyContracts.csproj
new file mode 100644 (file)
index 0000000..40cd185
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Interop.settings.targets))\Interop.settings.targets" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <AssemblyName>AssemblyContracts</AssemblyName>
+    <SchemaVersion>2.0</SchemaVersion>
+    <OutputType>library</OutputType>
+    <ProjectTypeGuids>{4948E98A-ECFC-4988-851E-68E1ADD2DD5A};{B850CC46-E8FB-4569-A28D-423F81E8A861}</ProjectTypeGuids>
+  </PropertyGroup>
+  <!-- Default configurations to help VS understand the configurations -->
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="AssemblyContracts.cs" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
index 2aa9343..305f104 100644 (file)
@@ -14,8 +14,9 @@
     <Compile Include="$(InteropCommonDir)ExeLauncherProgram.cs" />
   </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="Primitives/CMakeLists.txt"/>
+    <ProjectReference Include="Primitives/CMakeLists.txt" />
     <ProjectReference Include="../NetServer/NetServer.csproj" />
+    <ProjectReference Include="../../../Common/hostpolicymock/CMakeLists.txt" />
     <ProjectReference Include="../../../Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj" />
   </ItemGroup>
   <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
index 1bbdc10..2e57bb9 100644 (file)
@@ -299,7 +299,7 @@ void Run_ArrayTests()
 {
     HRESULT hr;
 
-    CoreShimComActivation csact{ W("NETServer.dll"), W("ArrayTesting") };
+    CoreShimComActivation csact{ W("NETServer"), W("ArrayTesting") };
 
     ComSmartPtr<IArrayTesting> arrayTesting;
     THROW_IF_FAILED(::CoCreateInstance(CLSID_ArrayTesting, nullptr, CLSCTX_INPROC, IID_IArrayTesting, (void**)&arrayTesting));
index ab95740..9ce8a80 100644 (file)
@@ -34,7 +34,7 @@ void Run_ColorTests()
 {
     HRESULT hr;
 
-    CoreShimComActivation csact{ W("NETServer.dll"), W("ColorTesting") };
+    CoreShimComActivation csact{ W("NETServer"), W("ColorTesting") };
 
     ComSmartPtr<IColorTesting> color;
     THROW_IF_FAILED(::CoCreateInstance(CLSID_ColorTesting, nullptr, CLSCTX_INPROC, IID_IColorTesting, (void**)&color));
index 7e40716..1708aca 100644 (file)
@@ -58,7 +58,7 @@ void Run_ErrorTests()
 {
     HRESULT hr;
 
-    CoreShimComActivation csact{ W("NETServer.dll"), W("ErrorMarshalTesting") };
+    CoreShimComActivation csact{ W("NETServer"), W("ErrorMarshalTesting") };
 
     ComSmartPtr<IErrorMarshalTesting> errorMarshal;
     THROW_IF_FAILED(::CoCreateInstance(CLSID_ErrorMarshalTesting, nullptr, CLSCTX_INPROC, IID_IErrorMarshalTesting, (void**)&errorMarshal));
index a9af956..c951c8c 100644 (file)
@@ -222,7 +222,7 @@ void Run_NumericTests()
 {
     HRESULT hr;
 
-    CoreShimComActivation csact{ W("NETServer.dll"), W("NumericTesting") };
+    CoreShimComActivation csact{ W("NETServer"), W("NumericTesting") };
 
     ComSmartPtr<INumericTesting> numericTesting;
     THROW_IF_FAILED(::CoCreateInstance(CLSID_NumericTesting, nullptr, CLSCTX_INPROC, IID_INumericTesting, (void**)&numericTesting));
index 96a713f..b003130 100644 (file)
@@ -412,7 +412,7 @@ void Run_StringTests()
 {
     HRESULT hr;
 
-    CoreShimComActivation csact{ W("NETServer.dll"), W("StringTesting") };
+    CoreShimComActivation csact{ W("NETServer"), W("StringTesting") };
 
     ComSmartPtr<IStringTesting> stringTesting;
     THROW_IF_FAILED(::CoCreateInstance(CLSID_StringTesting, nullptr, CLSCTX_INPROC, IID_IStringTesting, (void**)&stringTesting));
index 5f17049..7725f2f 100644 (file)
@@ -1,7 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
-  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Interop.settings.targets))\Interop.settings.targets" />
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -14,6 +13,8 @@
     <DefineConstants>$(DefineConstants);STATIC</DefineConstants>
     <ReferenceSystemPrivateCoreLib>true</ReferenceSystemPrivateCoreLib>
   </PropertyGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Interop.settings.targets))\Interop.settings.targets" />
+
   <!-- Default configurations to help VS understand the configurations -->
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"></PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"></PropertyGroup>
index e16b130..fc906f2 100644 (file)
@@ -6,16 +6,22 @@
 
   <!-- Environment properties -->
   <PropertyGroup>
+    <DefineConstants Condition="'$(ReferenceSystemPrivateCoreLib)' == 'true'">$(DefineConstants);REFERENCING_SYSTEMPRIVATECORELIB</DefineConstants>
   </PropertyGroup>
 
-  <!-- Required source files -->
-  <ItemGroup>
-    <ProjectReference 
-      Condition="('$(IgnoreCoreCLRTestLibraryDependency)' != 'true') And ('$(ReferenceSystemPrivateCoreLib)' != 'true')" 
+  <!-- Add the CoreCLRTestLibrary dependency -->
+  <ItemGroup Condition="('$(IgnoreCoreCLRTestLibraryDependency)' != 'true') And ('$(ReferenceSystemPrivateCoreLib)' != 'true')">
+    <ProjectReference
       Include="$(MSBuildThisFileDirectory)\..\Common\CoreCLRTestLibrary\CoreCLRTestLibrary.csproj" />
-    <Compile
-      Condition="('$(IgnoreCoreCLRTestLibraryDependency)' != 'true') And ('$(ReferenceSystemPrivateCoreLib)' == 'true')"
-      Include="$(MSBuildThisFileDirectory)\..\Common\CoreCLRTestLibrary\Assertion.cs" />
+  </ItemGroup>
+
+  <!-- Add the CoreCLRTestLibrary dependency
+       If a target project references System.Private.Corelib, we are unable to reference CoreCLRTestLibrary.
+       Compile in relevant files used for testing interop. -->
+  <ItemGroup Condition="('$(IgnoreCoreCLRTestLibraryDependency)' != 'true') And ('$(ReferenceSystemPrivateCoreLib)' == 'true')">
+    <Compile Include="$(MSBuildThisFileDirectory)\..\Common\CoreCLRTestLibrary\Assertion.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)\..\Common\CoreCLRTestLibrary\HostPolicyMock.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)\..\Common\CoreCLRTestLibrary\XPlatformUtils.cs" />
   </ItemGroup>
 
   <!-- Required debug vcruntime and UCRT dlls -->
index 689e124..59cbe9d 100644 (file)
@@ -1,7 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
-  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Interop.settings.targets))\Interop.settings.targets" />
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -15,6 +14,8 @@
     <ReferenceSystemPrivateCoreLib>true</ReferenceSystemPrivateCoreLib>
     <CLRTestPriority>1</CLRTestPriority>
   </PropertyGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Interop.settings.targets))\Interop.settings.targets" />
+
   <!-- Default configurations to help VS understand the configurations -->
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"></PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"></PropertyGroup>
index f92a778..dd3ac5e 100644 (file)
@@ -1,7 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
-  <Import Project="../../Interop.settings.targets" />
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -19,6 +18,8 @@
     <TestUnsupportedOutsideWindows>true</TestUnsupportedOutsideWindows>
     <DisableProjectBuild Condition="'$(TargetsUnix)' == 'true'">true</DisableProjectBuild>
   </PropertyGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Interop.settings.targets))\Interop.settings.targets" />
+
   <!-- Default configurations to help VS understand the configurations -->
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"></PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"></PropertyGroup>
index 9499bee..3e74a66 100644 (file)
@@ -5,8 +5,11 @@ using System;
 using System.IO;
 using System.Reflection;
 using System.Runtime.Loader;
+using TestLibrary;
 using Xunit;
 
+using Assert = Xunit.Assert;
+
 namespace AssemblyDependencyResolverTests
 {
     class AssemblyDependencyResolverTests : TestBase
@@ -38,8 +41,8 @@ namespace AssemblyDependencyResolverTests
             using (HostPolicyMock.MockValues_corehost_set_error_writer errorWriterMock = 
                 HostPolicyMock.Mock_corehost_set_error_writer())
             {
-                using (HostPolicyMock.MockValues_corehost_resolve_componet_dependencies resolverMock = 
-                    HostPolicyMock.Mock_corehost_resolve_componet_dependencies(
+                using (HostPolicyMock.MockValues_corehost_resolve_component_dependencies resolverMock = 
+                    HostPolicyMock.Mock_corehost_resolve_component_dependencies(
                         134,
                         "",
                         "",
@@ -79,8 +82,8 @@ namespace AssemblyDependencyResolverTests
             using (HostPolicyMock.MockValues_corehost_set_error_writer errorWriterMock =
                 HostPolicyMock.Mock_corehost_set_error_writer(previousWriter))
             {
-                using (HostPolicyMock.MockValues_corehost_resolve_componet_dependencies resolverMock =
-                    HostPolicyMock.Mock_corehost_resolve_componet_dependencies(
+                using (HostPolicyMock.MockValues_corehost_resolve_component_dependencies resolverMock =
+                    HostPolicyMock.Mock_corehost_resolve_component_dependencies(
                         134,
                         "",
                         "",
@@ -108,7 +111,7 @@ namespace AssemblyDependencyResolverTests
             using (HostPolicyMock.MockValues_corehost_set_error_writer errorWriterMock =
                 HostPolicyMock.Mock_corehost_set_error_writer(previousWriter))
             {
-                using (HostPolicyMock.Mock_corehost_resolve_componet_dependencies(
+                using (HostPolicyMock.Mock_corehost_resolve_component_dependencies(
                     0,
                     assemblyDependencyPath,
                     "",
@@ -131,7 +134,7 @@ namespace AssemblyDependencyResolverTests
         {
             // If the reqest is for assembly which is not listed in .deps.json
             // the resolver should return null.
-            using (HostPolicyMock.Mock_corehost_resolve_componet_dependencies(
+            using (HostPolicyMock.Mock_corehost_resolve_component_dependencies(
                 0,
                 "",
                 "",
@@ -148,7 +151,7 @@ namespace AssemblyDependencyResolverTests
         {
             // Even if the .deps.json can resolve the request, if the file is not present
             // the resolution should still return null.
-            using (HostPolicyMock.Mock_corehost_resolve_componet_dependencies(
+            using (HostPolicyMock.Mock_corehost_resolve_component_dependencies(
                 0,
                 Path.Combine(_componentDirectory, "NonExistingAssembly.dll"),
                 "",
@@ -164,7 +167,7 @@ namespace AssemblyDependencyResolverTests
         public void TestSingleResource()
         {
             string enResourcePath = CreateMockAssembly($"en{Path.DirectorySeparatorChar}TestComponent.resources.dll");
-            using (HostPolicyMock.Mock_corehost_resolve_componet_dependencies(
+            using (HostPolicyMock.Mock_corehost_resolve_component_dependencies(
                 0,
                 "",
                 "",
@@ -183,7 +186,7 @@ namespace AssemblyDependencyResolverTests
         {
             string enResourcePath = CreateMockAssembly($"en{Path.DirectorySeparatorChar}TestComponent.resources.dll");
             string csResourcePath = CreateMockAssembly($"cs{Path.DirectorySeparatorChar}TestComponent.resources.dll");
-            using (HostPolicyMock.Mock_corehost_resolve_componet_dependencies(
+            using (HostPolicyMock.Mock_corehost_resolve_component_dependencies(
                 0,
                 "",
                 "",
@@ -205,7 +208,7 @@ namespace AssemblyDependencyResolverTests
         {
             string enResourcePath = CreateMockAssembly($"en{Path.DirectorySeparatorChar}TestComponent.resources.dll");
             string frResourcePath = CreateMockAssembly($"SubComponent{Path.DirectorySeparatorChar}fr{Path.DirectorySeparatorChar}TestComponent.resources.dll");
-            using (HostPolicyMock.Mock_corehost_resolve_componet_dependencies(
+            using (HostPolicyMock.Mock_corehost_resolve_component_dependencies(
                 0,
                 "",
                 "",
@@ -226,7 +229,7 @@ namespace AssemblyDependencyResolverTests
         public void TestAssemblyWithNeutralCulture()
         {
             string neutralAssemblyPath = CreateMockAssembly("NeutralAssembly.dll");
-            using (HostPolicyMock.Mock_corehost_resolve_componet_dependencies(
+            using (HostPolicyMock.Mock_corehost_resolve_component_dependencies(
                 0,
                 neutralAssemblyPath,
                 "",
@@ -245,7 +248,7 @@ namespace AssemblyDependencyResolverTests
         {
             string nativeLibraryPath = CreateMockStandardNativeLibrary("native", "Single");
 
-            using (HostPolicyMock.Mock_corehost_resolve_componet_dependencies(
+            using (HostPolicyMock.Mock_corehost_resolve_component_dependencies(
                 0,
                 "",
                 Path.GetDirectoryName(nativeLibraryPath),
@@ -265,7 +268,7 @@ namespace AssemblyDependencyResolverTests
             string oneNativeLibraryPath = CreateMockStandardNativeLibrary($"native{Path.DirectorySeparatorChar}one", "One");
             string twoNativeLibraryPath = CreateMockStandardNativeLibrary($"native{Path.DirectorySeparatorChar}two", "Two");
 
-            using (HostPolicyMock.Mock_corehost_resolve_componet_dependencies(
+            using (HostPolicyMock.Mock_corehost_resolve_component_dependencies(
                 0,
                 "",
                 $"{Path.GetDirectoryName(oneNativeLibraryPath)}{Path.PathSeparator}{Path.GetDirectoryName(twoNativeLibraryPath)}",
index c8ba654..e2dd0a4 100644 (file)
     <!-- The test fails if ran twice in the same process. In one of the test cases, it expects a hostpolicy to not to be found, but it actually is found in the second pass -->
     <UnloadabilityIncompatible>true</UnloadabilityIncompatible>
   </PropertyGroup>
-  <PropertyGroup>
-    <DefineConstants Condition="$(OSGroup) == 'Windows_NT'">WINDOWS</DefineConstants>
-    <DefineConstants Condition="$(OSGroup) == 'OSX'">OSX</DefineConstants>
-  </PropertyGroup>
   <ItemGroup>
     <Compile Include="AssemblyDependencyResolverTests.cs" />
-    <Compile Include="HostPolicyMock.cs" />
     <Compile Include="InvalidHostingTest.cs" />
     <Compile Include="NativeDependencyTests.cs" />
     <Compile Include="TestBase.cs" />
-    <Compile Include="XPlatformUtils.cs" />
   </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="CMakeLists.txt" />
+    <ProjectReference Include="../../Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj" />
+    <ProjectReference Include="../../Common/hostpolicymock/CMakeLists.txt" />
   </ItemGroup>
   <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
 </Project>
index c51b055..d1fc56e 100644 (file)
@@ -4,8 +4,11 @@
 using System;
 using System.IO;
 using System.Runtime.Loader;
+using TestLibrary;
 using Xunit;
 
+using Assert = Xunit.Assert;
+
 namespace AssemblyDependencyResolverTests
 {
     class InvalidHostingTest : TestBase
index 43e721e..e7ac906 100644 (file)
@@ -5,8 +5,11 @@ using System;
 using System.IO;
 using System.Runtime.InteropServices;
 using System.Runtime.Loader;
+using TestLibrary;
 using Xunit;
 
+using Assert = Xunit.Assert;
+
 namespace AssemblyDependencyResolverTests
 {
     class NativeDependencyTests : TestBase
@@ -258,7 +261,7 @@ namespace AssemblyDependencyResolverTests
             string lookupName,
             OS resolvesOnOSes)
         {
-            using (HostPolicyMock.Mock_corehost_resolve_componet_dependencies(
+            using (HostPolicyMock.Mock_corehost_resolve_component_dependencies(
                 0,
                 "",
                 $"{nativeLibraryPaths}",