Basic .NET client tests (#18843)
authorAaron Robinson <arobins@microsoft.com>
Thu, 19 Jul 2018 00:52:02 +0000 (17:52 -0700)
committerGitHub <noreply@github.com>
Thu, 19 Jul 2018 00:52:02 +0000 (17:52 -0700)
- Add support for a testing primitive marshalling with a native COM server
and .NET client. This uses RegFree COM for activation.
- Remove ClassicCOM tests
- Bring back tests for activation via reflection

36 files changed:
tests/CMakeLists.txt
tests/src/Interop/CMakeLists.txt
tests/src/Interop/COM/NETClients/Primitives/App.manifest [new file with mode: 0644]
tests/src/Interop/COM/NETClients/Primitives/ArrayTests.cs [new file with mode: 0644]
tests/src/Interop/COM/NETClients/Primitives/ErrorTests.cs [new file with mode: 0644]
tests/src/Interop/COM/NETClients/Primitives/NETClientPrimitives.csproj [new file with mode: 0644]
tests/src/Interop/COM/NETClients/Primitives/NumericTests.cs [new file with mode: 0644]
tests/src/Interop/COM/NETClients/Primitives/Program.cs [new file with mode: 0644]
tests/src/Interop/COM/NETClients/Primitives/StringTests.cs [new file with mode: 0644]
tests/src/Interop/COM/NETServer/ImportedTypes.cs [moved from tests/src/Interop/ClassicCOM/COMLib2.cs with 97% similarity]
tests/src/Interop/COM/NETServer/NETServer.csproj [moved from tests/src/Interop/ClassicCOM/COMLib2.csproj with 92% similarity]
tests/src/Interop/COM/NativeServer/ArrayTesting.h [new file with mode: 0644]
tests/src/Interop/COM/NativeServer/CMakeLists.txt [new file with mode: 0644]
tests/src/Interop/COM/NativeServer/COMNativeServer.X.manifest [new file with mode: 0644]
tests/src/Interop/COM/NativeServer/ComHelpers.h [new file with mode: 0644]
tests/src/Interop/COM/NativeServer/ErrorMarshalTesting.h [new file with mode: 0644]
tests/src/Interop/COM/NativeServer/Exports.def [new file with mode: 0644]
tests/src/Interop/COM/NativeServer/NumericTesting.h [new file with mode: 0644]
tests/src/Interop/COM/NativeServer/Servers.cpp [new file with mode: 0644]
tests/src/Interop/COM/NativeServer/Servers.h [new file with mode: 0644]
tests/src/Interop/COM/NativeServer/StringTesting.h [new file with mode: 0644]
tests/src/Interop/COM/NativeServer/stdafx.cpp [new file with mode: 0644]
tests/src/Interop/COM/NativeServer/stdafx.h [new file with mode: 0644]
tests/src/Interop/COM/Reflection/Reflection.cs [new file with mode: 0644]
tests/src/Interop/COM/Reflection/Reflection.csproj [moved from tests/src/Interop/ClassicCOM/ClassicCOMUnitTest.csproj with 73% similarity]
tests/src/Interop/COM/ServerContracts/Primitives.cs [new file with mode: 0644]
tests/src/Interop/COM/ServerContracts/PrimitivesNativeServer.cs [new file with mode: 0644]
tests/src/Interop/COM/ServerContracts/Server.Contracts.tlh [new file with mode: 0644]
tests/src/Interop/COM/ServerContracts/Server.Contracts.tli [new file with mode: 0644]
tests/src/Interop/COM/ServerContracts/readme.md [new file with mode: 0644]
tests/src/Interop/ClassicCOM/CMakeLists.txt [deleted file]
tests/src/Interop/ClassicCOM/COMLib.cs [deleted file]
tests/src/Interop/ClassicCOM/COMLib.csproj [deleted file]
tests/src/Interop/ClassicCOM/ClassicCOMNative.cpp [deleted file]
tests/src/Interop/ClassicCOM/ClassicCOMUnitTest.cs [deleted file]
tests/testsUnsupportedOutsideWindows.txt

index 078d9b8..e667e59 100644 (file)
@@ -36,7 +36,21 @@ endif()
 # Compile options
 
 if (WIN32)
-    add_compile_options(-wd4100 -wd4514 -wd4668 -wd4710 -wd4711 -wd4820)
+    # 4100 - unreferenced formal parameter
+    # 4514 - unreferenced inline function has been removed
+    # 4625 - copy constructor was implicitly defined as deleted because a base class copy constructor is inaccessible or deleted
+    # 4626 - assignment operator was implicitly defined as deleted because a base class assignment operator is inaccessible or deleted
+    # 4668 - 'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives'
+    # 4710 - function not inlined
+    # 4711 - 'function' selected for inline expansion
+    # 4774 - format string expected in argument number is not a string literal
+    # 4820 - bytes padding added after construct 'member_name'
+    # 5025 - move assignment operator was implicitly defined as deleted
+    # 5026 - move constructor was implicitly defined as deleted
+    # 5027 - move assignment operator was implicitly defined as deleted
+    # 5039 - pointer or reference to potentially throwing function passed to extern C function under -EHc. Undefined behavior may occur if this function throws an exception.
+    add_compile_options(-wd4100 -wd4514 -wd4625 -wd4626 -wd4668 -wd4710 -wd4711 -wd4774 -wd4820 -wd5025 -wd5026 -wd5027 -wd5039)
+    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
 endif()
 
 if(CLR_CMAKE_PLATFORM_UNIX)
index 8780010..04ec8aa 100644 (file)
@@ -1,10 +1,10 @@
 
 if(WIN32)
-       if(CLR_CMAKE_HOST_ARCH STREQUAL arm)
-           list(APPEND LINK_LIBRARIES_ADDITIONAL
-               ole32.lib
-           )
-       endif(CLR_CMAKE_HOST_ARCH STREQUAL arm)
+    if(CLR_CMAKE_HOST_ARCH STREQUAL arm)
+        list(APPEND LINK_LIBRARIES_ADDITIONAL
+            ole32.lib
+        )
+    endif(CLR_CMAKE_HOST_ARCH STREQUAL arm)
 endif(WIN32)
 
 include_directories(common)
@@ -26,7 +26,10 @@ add_subdirectory(StringMarshalling/UTF8)
 add_subdirectory(MarshalAPI/FunctionPointer)
 add_subdirectory(MarshalAPI/IUnknown)
 add_subdirectory(SizeConst)
-add_subdirectory(ClassicCOM)
 add_subdirectory(DllImportAttribute/ExeFile)
 add_subdirectory(DllImportAttribute/FileNameContainDot)
 add_subdirectory(DllImportAttribute/Simple)
+
+if(WIN32)
+    add_subdirectory(COM/NativeServer)
+endif(WIN32)
diff --git a/tests/src/Interop/COM/NETClients/Primitives/App.manifest b/tests/src/Interop/COM/NETClients/Primitives/App.manifest
new file mode 100644 (file)
index 0000000..37b4f65
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
+  <assemblyIdentity
+    type="win32" 
+    name="NetPrimitivesClient"
+    version="1.0.0.0" />
+
+  <dependency>
+    <dependentAssembly>
+      <!-- RegFree COM -->
+      <assemblyIdentity
+          type="win32"
+          name="COMNativeServer.X"
+          version="1.0.0.0"/>
+    </dependentAssembly>
+  </dependency>
+
+</assembly>
diff --git a/tests/src/Interop/COM/NETClients/Primitives/ArrayTests.cs b/tests/src/Interop/COM/NETClients/Primitives/ArrayTests.cs
new file mode 100644 (file)
index 0000000..1881263
--- /dev/null
@@ -0,0 +1,168 @@
+// 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 NetClient
+{
+    using CoreFXTestLibrary;
+    using System;
+    using System.Collections.Generic;
+    using System.Linq;
+
+    class ArrayTests
+    {
+        static private readonly IEnumerable<int> BaseData = Enumerable.Range(0, 10);
+
+        private readonly Server.Contract.Servers.ArrayTesting server;
+        private readonly double expectedMean;
+
+        public ArrayTests()
+        {
+            this.server = (Server.Contract.Servers.ArrayTesting)new Server.Contract.Servers.ArrayTestingClass();
+
+            double acc = 0.0;
+            int[] rawData = BaseData.ToArray();
+            foreach (var d in rawData)
+            {
+                acc += d;
+            }
+
+            expectedMean = acc / rawData.Length;
+        }
+
+        public void Run()
+        {
+            this.Marshal_ByteArray();
+            this.Marshal_ShortArray();
+            this.Marshal_UShortArray();
+            this.Marshal_IntArray();
+            this.Marshal_UIntArray();
+            this.Marshal_LongArray();
+            this.Marshal_ULongArray();
+            this.Marshal_FloatArray();
+            this.Marshal_DoubleArray();
+        }
+
+        static private bool EqualByBound(double expected, double actual)
+        {
+            double low = expected - 0.00001;
+            double high = expected + 0.00001;
+            double eps = Math.Abs(expected - actual);
+            bool isEqual = eps < double.Epsilon || (low < actual && actual < high);
+            if (!isEqual)
+            {
+                Console.WriteLine($"{expected}  {actual}");
+            }
+
+            return isEqual;
+        }
+
+        private void Marshal_ByteArray()
+        {
+            int len;
+            byte[] data = BaseData.Select(i => (byte)i).ToArray();
+
+            Console.WriteLine($"{data.GetType().Name} marshalling");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_Byte_LP_PreLen(data.Length, data)), $"Mean_Byte_LP_PreLen");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_Byte_LP_PostLen(data, data.Length)), $"Mean_Byte_LP_PostLen");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_Byte_SafeArray_OutLen(data, out len)), $"Mean_Byte_SafeArray_OutLen");
+            Assert.AreEqual(data.Length, len);
+        }
+
+        private void Marshal_ShortArray()
+        {
+            int len;
+            short[] data = BaseData.Select(i => (short)i).ToArray();
+
+            Console.WriteLine($"{data.GetType().Name} marshalling");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_Short_LP_PreLen(data.Length, data)), $"Mean_Short_LP_PreLen");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_Short_LP_PostLen(data, data.Length)), $"Mean_Short_LP_PostLen");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_Short_SafeArray_OutLen(data, out len)), $"Mean_Short_SafeArray_OutLen");
+            Assert.AreEqual(data.Length, len);
+        }
+
+        private void Marshal_UShortArray()
+        {
+            int len;
+            ushort[] data = BaseData.Select(i => (ushort)i).ToArray();
+
+            Console.WriteLine($"{data.GetType().Name} marshalling");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_UShort_LP_PreLen(data.Length, data)), $"Mean_UShort_LP_PreLen");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_UShort_LP_PostLen(data, data.Length)), $"Mean_UShort_LP_PostLen");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_UShort_SafeArray_OutLen(data, out len)), $"Mean_UShort_SafeArray_OutLen");
+            Assert.AreEqual(data.Length, len);
+        }
+
+        private void Marshal_IntArray()
+        {
+            int len;
+            int[] data = BaseData.Select(i => i).ToArray();
+
+            Console.WriteLine($"{data.GetType().Name} marshalling");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_Int_LP_PreLen(data.Length, data)), $"Mean_Int_LP_PreLen");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_Int_LP_PostLen(data, data.Length)), $"Mean_Int_LP_PostLen");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_Int_SafeArray_OutLen(data, out len)), $"Mean_Int_SafeArray_OutLen");
+            Assert.AreEqual(data.Length, len);
+        }
+
+        private void Marshal_UIntArray()
+        {
+            int len;
+            uint[] data = BaseData.Select(i => (uint)i).ToArray();
+
+            Console.WriteLine($"{data.GetType().Name} marshalling");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_UInt_LP_PreLen(data.Length, data)), $"Mean_UInt_LP_PreLen");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_UInt_LP_PostLen(data, data.Length)), $"Mean_UInt_LP_PostLen");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_UInt_SafeArray_OutLen(data, out len)), $"Mean_UInt_SafeArray_OutLen");
+            Assert.AreEqual(data.Length, len);
+        }
+
+        private void Marshal_LongArray()
+        {
+            int len;
+            long[] data = BaseData.Select(i => (long)i).ToArray();
+
+            Console.WriteLine($"{data.GetType().Name} marshalling");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_Long_LP_PreLen(data.Length, data)), $"Mean_Long_LP_PreLen");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_Long_LP_PostLen(data, data.Length)), $"Mean_Long_LP_PostLen");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_Long_SafeArray_OutLen(data, out len)), $"Mean_Long_SafeArray_OutLen");
+            Assert.AreEqual(data.Length, len);
+        }
+
+        private void Marshal_ULongArray()
+        {
+            int len;
+            ulong[] data = BaseData.Select(i => (ulong)i).ToArray();
+
+            Console.WriteLine($"{data.GetType().Name} marshalling");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_ULong_LP_PreLen(data.Length, data)), $"Mean_ULong_LP_PreLen");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_ULong_LP_PostLen(data, data.Length)), $"Mean_ULong_LP_PostLen");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_ULong_SafeArray_OutLen(data, out len)), $"Mean_ULong_SafeArray_OutLen");
+            Assert.AreEqual(data.Length, len);
+        }
+
+        private void Marshal_FloatArray()
+        {
+            int len;
+            float[] data = BaseData.Select(i => (float)i).ToArray();
+
+            Console.WriteLine($"{data.GetType().Name} marshalling");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_Float_LP_PreLen(data.Length, data)), $"Mean_Float_LP_PreLen");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_Float_LP_PostLen(data, data.Length)), $"Mean_Float_LP_PostLen");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_Float_SafeArray_OutLen(data, out len)), $"Mean_Float_SafeArray_OutLen");
+            Assert.AreEqual(data.Length, len);
+        }
+
+        private void Marshal_DoubleArray()
+        {
+            int len;
+            double[] data = BaseData.Select(i => (double)i).ToArray();
+
+            Console.WriteLine($"{data.GetType().Name} marshalling");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_Double_LP_PreLen(data.Length, data)), $"Mean_Double_LP_PreLen");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_Double_LP_PostLen(data, data.Length)), $"Mean_Double_LP_PostLen");
+            Assert.IsTrue(EqualByBound(expectedMean, this.server.Mean_Double_SafeArray_OutLen(data, out len)), $"Mean_Double_SafeArray_OutLen");
+            Assert.AreEqual(data.Length, len);
+        }
+    }
+}
diff --git a/tests/src/Interop/COM/NETClients/Primitives/ErrorTests.cs b/tests/src/Interop/COM/NETClients/Primitives/ErrorTests.cs
new file mode 100644 (file)
index 0000000..9694333
--- /dev/null
@@ -0,0 +1,60 @@
+// 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 NetClient
+{
+    using CoreFXTestLibrary;
+    using System;
+    using System.Runtime.InteropServices;
+
+    class ErrorTests
+    {
+        private readonly Server.Contract.Servers.ErrorMarshalTesting server;
+        public ErrorTests()
+        {
+            this.server = (Server.Contract.Servers.ErrorMarshalTesting)new Server.Contract.Servers.ErrorMarshalTestingClass();
+        }
+
+        public void Run()
+        {
+            this.VerifyExpectedException();
+            this.VerifyReturnHResult();
+        }
+
+        private void VerifyExpectedException()
+        {
+            Console.WriteLine($"Verify expected exception from HRESULT");
+
+            Assert.Throws<NotImplementedException>(() => { this.server.Throw_HResult(unchecked((int)0x80004001)); });
+            Assert.Throws<NullReferenceException>(() => { this.server.Throw_HResult(unchecked((int)0x80004003)); });
+            Assert.Throws<UnauthorizedAccessException>(() => { this.server.Throw_HResult(unchecked((int)0x80070005)); });
+            Assert.Throws<OutOfMemoryException>(() => { this.server.Throw_HResult(unchecked((int)0x8007000E)); });
+            Assert.Throws<ArgumentException>(() => { this.server.Throw_HResult(unchecked((int)0x80070057)); });
+            Assert.Throws<COMException>(() => { this.server.Throw_HResult(unchecked((int)0x8000ffff)); });
+            Assert.Throws<COMException>(() => { this.server.Throw_HResult(unchecked((int)-1)); });
+        }
+
+        private void VerifyReturnHResult()
+        {
+            Console.WriteLine($"Verify preserved function signature");
+
+            var hrs = new[]
+            {
+                    unchecked((int)0x80004001),
+                    unchecked((int)0x80004003),
+                    unchecked((int)0x80070005),
+                    unchecked((int)0x80070057),
+                    unchecked((int)0x8000ffff),
+                    -1,
+                    1,
+                    2
+                };
+
+            foreach (var hr in hrs)
+            {
+                Assert.AreEqual(hr, this.server.Return_As_HResult(hr));
+            }
+        }
+    }
+}
diff --git a/tests/src/Interop/COM/NETClients/Primitives/NETClientPrimitives.csproj b/tests/src/Interop/COM/NETClients/Primitives/NETClientPrimitives.csproj
new file mode 100644 (file)
index 0000000..0bb40d7
--- /dev/null
@@ -0,0 +1,36 @@
+<?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" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <AssemblyName>NETClientPrimitives</AssemblyName>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{85C57688-DA98-4DE3-AC9B-526E4747434C}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <ProjectTypeGuids>{209912F9-0DA1-4184-9CC1-8D583BAF4A28};{87799F5D-CEBD-499D-BDBA-B2C6105CD766}</ProjectTypeGuids>
+    <ApplicationManifest>App.manifest</ApplicationManifest>
+  </PropertyGroup>
+  <PropertyGroup>
+    <DisableProjectBuild Condition="'$(TargetsWindows)' != 'true'">true</DisableProjectBuild>
+  </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="Program.cs" />
+    <Compile Include="ArrayTests.cs" />
+    <Compile Include="ErrorTests.cs" />
+    <Compile Include="NumericTests.cs" />
+    <Compile Include="StringTests.cs" />
+    <Compile Include="../../ServerContracts/Primitives.cs" />
+    <Compile Include="../../ServerContracts/PrimitivesNativeServer.cs" />
+    <Compile Include="../../../common/Assertion.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="../../NativeServer/CMakeLists.txt" />
+  </ItemGroup>
+  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/tests/src/Interop/COM/NETClients/Primitives/NumericTests.cs b/tests/src/Interop/COM/NETClients/Primitives/NumericTests.cs
new file mode 100644 (file)
index 0000000..cff69ec
--- /dev/null
@@ -0,0 +1,193 @@
+// 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 NetClient
+{
+    using CoreFXTestLibrary;
+    using System;
+
+    class NumericTests
+    {
+        private readonly int seed;
+        private readonly Random rng;
+        private readonly Server.Contract.Servers.NumericTesting server;
+
+        public NumericTests(int seed = 37)
+        {
+            this.seed = seed;
+            Console.WriteLine($"Numeric RNG seed: {this.seed}");
+
+            this.rng = new Random(this.seed);
+            this.server = (Server.Contract.Servers.NumericTesting)new Server.Contract.Servers.NumericTestingClass();
+        }
+
+        public void Run()
+        {
+            int a = this.rng.Next();
+            int b = this.rng.Next();
+
+            this.Marshal_Byte((byte)a, (byte)b);
+            this.Marshal_Short((short)a, (short)b);
+            this.Marshal_UShort((ushort)a, (ushort)b);
+            this.Marshal_Int(a, b);
+            this.Marshal_UInt((uint)a, (uint)b);
+            this.Marshal_Long(a, b);
+            this.Marshal_ULong((ulong)a, (ulong)b);
+
+            this.Marshal_Float(a / 100f, b / 100f);
+            this.Marshal_Double(a / 100.0, b / 100.0);
+        }
+
+        static private bool EqualByBound(float expected, float actual)
+        {
+            float low = expected - 0.0001f;
+            float high = expected + 0.0001f;
+            float eps = Math.Abs(expected - actual);
+            return eps < float.Epsilon || (low < actual && actual < high);
+        }
+
+        static private bool EqualByBound(double expected, double actual)
+        {
+            double low = expected - 0.00001;
+            double high = expected + 0.00001;
+            double eps = Math.Abs(expected - actual);
+            return eps < double.Epsilon || (low < actual && actual < high);
+        }
+
+        private void Marshal_Byte(byte a, byte b)
+        {
+            var expected = (byte)(a + b);
+            Console.WriteLine($"{expected.GetType().Name} test invariant: {a} + {b} = {expected}");
+            Assert.AreEqual(expected, this.server.Add_Byte(a, b));
+
+            var c = byte.MaxValue;
+            this.server.Add_Byte_Ref(a, b, ref c);
+            Assert.AreEqual(expected, c);
+
+            c = 0;
+            this.server.Add_Byte_Out(a, b, out c);
+            Assert.AreEqual(expected, c);
+        }
+
+        private void Marshal_Short(short a, short b)
+        {
+            var expected = (short)(a + b);
+            Console.WriteLine($"{expected.GetType().Name} test invariant: {a} + {b} = {expected}");
+            Assert.AreEqual(expected, this.server.Add_Short(a, b));
+
+            var c = short.MaxValue;
+            this.server.Add_Short_Ref(a, b, ref c);
+            Assert.AreEqual(expected, c);
+
+            c = 0;
+            this.server.Add_Short_Out(a, b, out c);
+            Assert.AreEqual(expected, c);
+        }
+
+        private void Marshal_UShort(ushort a, ushort b)
+        {
+            var expected = (ushort)(a + b);
+            Console.WriteLine($"{expected.GetType().Name} test invariant: {a} + {b} = {expected}");
+            Assert.AreEqual(expected, this.server.Add_UShort(a, b));
+
+            var c = ushort.MaxValue;
+            this.server.Add_UShort_Ref(a, b, ref c);
+            Assert.AreEqual(expected, c);
+
+            c = 0;
+            this.server.Add_UShort_Out(a, b, out c);
+            Assert.AreEqual(expected, c);
+        }
+
+        private void Marshal_Int(int a, int b)
+        {
+            var expected = a + b;
+            Console.WriteLine($"{expected.GetType().Name} test invariant: {a} + {b} = {expected}");
+            Assert.AreEqual(expected, this.server.Add_Int(a, b));
+
+            var c = int.MaxValue;
+            this.server.Add_Int_Ref(a, b, ref c);
+            Assert.AreEqual(expected, c);
+
+            c = 0;
+            this.server.Add_Int_Out(a, b, out c);
+            Assert.AreEqual(expected, c);
+        }
+
+        private void Marshal_UInt(uint a, uint b)
+        {
+            var expected = a + b;
+            Console.WriteLine($"{expected.GetType().Name} test invariant: {a} + {b} = {expected}");
+            Assert.AreEqual(expected, this.server.Add_UInt(a, b));
+
+            var c = uint.MaxValue;
+            this.server.Add_UInt_Ref(a, b, ref c);
+            Assert.AreEqual(expected, c);
+
+            c = 0;
+            this.server.Add_UInt_Out(a, b, out c);
+            Assert.AreEqual(expected, c);
+        }
+
+        private void Marshal_Long(long a, long b)
+        {
+            var expected = a + b;
+            Console.WriteLine($"{expected.GetType().Name} test invariant: {a} + {b} = {expected}");
+            Assert.AreEqual(expected, this.server.Add_Long(a, b));
+
+            var c = long.MaxValue;
+            this.server.Add_Long_Ref(a, b, ref c);
+            Assert.AreEqual(expected, c);
+
+            c = 0;
+            this.server.Add_Long_Out(a, b, out c);
+            Assert.AreEqual(expected, c);
+        }
+
+        private void Marshal_ULong(ulong a, ulong b)
+        {
+            var expected = a + b;
+            Console.WriteLine($"{expected.GetType().Name} test invariant: {a} + {b} = {expected}");
+            Assert.AreEqual(expected, this.server.Add_ULong(a, b));
+
+            var c = ulong.MaxValue;
+            this.server.Add_ULong_Ref(a, b, ref c);
+            Assert.AreEqual(expected, c);
+
+            c = 0;
+            this.server.Add_ULong_Out(a, b, out c);
+            Assert.AreEqual(expected, c);
+        }
+
+        private void Marshal_Float(float a, float b)
+        {
+            var expected = a + b;
+            Console.WriteLine($"{expected.GetType().Name} test invariant: {a} + {b} = {expected}");
+            Assert.IsTrue(EqualByBound(expected, this.server.Add_Float(a, b)), $"Add_Float: {this.server.Add_Float(a, b)}");
+
+            var c = float.MaxValue;
+            this.server.Add_Float_Ref(a, b, ref c);
+            Assert.IsTrue(EqualByBound(expected, c), "Add_Float_Ref");
+
+            c = 0;
+            this.server.Add_Float_Out(a, b, out c);
+            Assert.IsTrue(EqualByBound(expected, c), "Add_Float_Out");
+        }
+
+        private void Marshal_Double(double a, double b)
+        {
+            var expected = a + b;
+            Console.WriteLine($"{expected.GetType().Name} test invariant: {a} + {b} = {expected}");
+            Assert.IsTrue(EqualByBound(expected, this.server.Add_Double(a, b)));
+
+            var c = double.MaxValue;
+            this.server.Add_Double_Ref(a, b, ref c);
+            Assert.IsTrue(EqualByBound(expected, c));
+
+            c = 0;
+            this.server.Add_Double_Out(a, b, out c);
+            Assert.IsTrue(EqualByBound(expected, c));
+        }
+    }
+}
diff --git a/tests/src/Interop/COM/NETClients/Primitives/Program.cs b/tests/src/Interop/COM/NETClients/Primitives/Program.cs
new file mode 100644 (file)
index 0000000..4d76417
--- /dev/null
@@ -0,0 +1,29 @@
+// 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 NetClient
+{
+    using System;
+
+    class Program
+    {
+        static int Main(string[] doNotUse)
+        {
+            try
+            {
+                new NumericTests().Run();
+                new ArrayTests().Run();
+                new StringTests().Run();
+                new ErrorTests().Run();
+            }
+            catch (Exception e)
+            {
+                Console.WriteLine($"Test Failure: {e.Message}\n{e.StackTrace}");
+                return 101;
+            }
+
+            return 100;
+        }
+    }
+}
diff --git a/tests/src/Interop/COM/NETClients/Primitives/StringTests.cs b/tests/src/Interop/COM/NETClients/Primitives/StringTests.cs
new file mode 100644 (file)
index 0000000..ab5271f
--- /dev/null
@@ -0,0 +1,272 @@
+// 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 NetClient
+{
+    using CoreFXTestLibrary;
+    using System;
+    using System.Collections.Generic;
+    using System.Linq;
+    using System.Text;
+    using System.Runtime.InteropServices;
+
+    class StringTests
+    {
+        private readonly Server.Contract.Servers.StringTesting server;
+
+        private readonly IEnumerable<Tuple<string, string>> addPairs = new Tuple<string, string>[]
+        {
+            Tuple.Create("", ""),
+            Tuple.Create("", "def"),
+            Tuple.Create("abc", ""),
+            Tuple.Create("abc", "def"),
+            Tuple.Create("", "结合"),
+            Tuple.Create("结合", ""),
+            Tuple.Create("a", "结合"),
+            Tuple.Create("结合", "a"),
+            Tuple.Create("结合", "结合"),
+
+            // String marshalling is optimized where strings shorter than MAX_PATH are
+            // allocated on the stack. Longer strings have memory allocated for them.
+            Tuple.Create("123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901", "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901")
+        };
+
+        private readonly IEnumerable<string> reversableStrings = new string[]
+        {
+            "",
+            "a",
+            "abc",
+            "reversable string",
+            "Unicode 相反 Unicode",
+
+            // Long string optimization validation
+            "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901"
+        };
+
+        public StringTests()
+        {
+            this.server = (Server.Contract.Servers.StringTesting)new Server.Contract.Servers.StringTestingClass();
+        }
+
+        public void Run()
+        {
+            this.Marshal_LPString();
+            this.Marshal_LPWString();
+            this.Marshal_BStrString();
+        }
+
+        static private string Reverse(string s)
+        {
+            var chars = s.ToCharArray();
+            Array.Reverse(chars);
+            return new string(chars);
+        }
+
+        static private bool AllAscii(string s)
+        {
+            const int MaxAscii = 0x7f;
+            return s.ToCharArray().All(c => c <= MaxAscii);
+        }
+
+        private void Marshal_LPString()
+        {
+            Console.WriteLine($"Marshal strings as { UnmanagedType.LPStr }");
+            foreach (var p in addPairs)
+            {
+                if (!AllAscii(p.Item1) || !AllAscii(p.Item2))
+                {
+                    // LPStr doesn't support non-ascii characters
+                    continue;
+                }
+
+                string expected = p.Item1 + p.Item2;
+                string actual = this.server.Add_LPStr(p.Item1, p.Item2);
+                Assert.AreEqual(expected, actual, "Add_String_LPStr (simple)");
+            }
+
+            foreach (var s in reversableStrings)
+            {
+                if (!AllAscii(s))
+                {
+                    // LPStr doesn't support non-ascii characters
+                    continue;
+                }
+
+                string local = s;
+                string expected = Reverse(local);
+
+                string actual = this.server.Reverse_LPStr(local);
+                Assert.AreEqual(expected, actual);
+
+                actual = this.server.Reverse_LPStr_Ref(ref local);
+                Assert.AreEqual(expected, actual);
+                Assert.AreEqual(expected, local);
+
+                local = s;
+                actual = this.server.Reverse_LPStr_InRef(ref local);
+                Assert.AreEqual(expected, actual);
+                Assert.AreEqual(s, local);
+
+                this.server.Reverse_LPStr_Out(local, out actual);
+                Assert.AreEqual(expected, actual);
+
+                actual = local;
+                this.server.Reverse_LPStr_OutAttr(local, actual); // No-op for strings
+                Assert.AreEqual(local, actual);
+            }
+
+            foreach (var s in reversableStrings)
+            {
+                if (!AllAscii(s))
+                {
+                    // LPStr doesn't support non-ascii characters
+                    continue;
+                }
+
+                var local = new StringBuilder(s);
+                string expected = Reverse(local.ToString());
+
+                StringBuilder actual = this.server.Reverse_SB_LPStr(local);
+                Assert.AreEqual(expected, actual.ToString());
+                Assert.AreEqual(expected, local.ToString());
+
+                local = new StringBuilder(s);
+                actual = this.server.Reverse_SB_LPStr_Ref(ref local);
+                Assert.AreEqual(expected, actual.ToString());
+                Assert.AreEqual(expected, local.ToString());
+
+                local = new StringBuilder(s);
+                actual = this.server.Reverse_SB_LPStr_InRef(ref local);
+                Assert.AreEqual(expected, actual.ToString());
+
+                // Palindromes are _always_ equal
+                if (!string.Equals(s, expected))
+                {
+                    Assert.AreNotEqual(expected, local.ToString());
+                }
+
+                local = new StringBuilder(s);
+                actual = new StringBuilder();
+                this.server.Reverse_SB_LPStr_Out(local, out actual);
+                Assert.AreEqual(expected, actual.ToString());
+                Assert.AreEqual(expected, local.ToString());
+
+                local = new StringBuilder(s);
+                actual = new StringBuilder(s.Length);
+                this.server.Reverse_SB_LPStr_OutAttr(local, actual);
+                Assert.AreEqual(expected, actual.ToString());
+                Assert.AreEqual(expected, local.ToString());
+            }
+        }
+
+        private void Marshal_LPWString()
+        {
+            Console.WriteLine($"Marshal strings as { UnmanagedType.LPWStr }");
+            foreach (var p in addPairs)
+            {
+                string expected = p.Item1 + p.Item2;
+                string actual = this.server.Add_LPWStr(p.Item1, p.Item2);
+                Assert.AreEqual(expected, actual, "Add_String_LPWStr (simple)");
+            }
+
+            foreach (var s in reversableStrings)
+            {
+                string local = s;
+                string expected = Reverse(local);
+
+                string actual = this.server.Reverse_LPWStr(local);
+                Assert.AreEqual(expected, actual);
+
+                actual = this.server.Reverse_LPWStr_Ref(ref local);
+                Assert.AreEqual(expected, actual);
+                Assert.AreEqual(expected, local);
+
+                local = s;
+                actual = this.server.Reverse_LPWStr_InRef(ref local);
+                Assert.AreEqual(expected, actual);
+                Assert.AreEqual(s, local);
+
+                this.server.Reverse_LPWStr_Out(local, out actual);
+                Assert.AreEqual(expected, actual);
+
+                actual = local;
+                this.server.Reverse_LPWStr_OutAttr(local, actual); // No-op for strings
+                Assert.AreEqual(local, actual);
+            }
+
+            foreach (var s in reversableStrings)
+            {
+                var local = new StringBuilder(s);
+                string expected = Reverse(local.ToString());
+
+                StringBuilder actual = this.server.Reverse_SB_LPWStr(local);
+                Assert.AreEqual(expected, actual.ToString());
+                Assert.AreEqual(expected, local.ToString());
+
+                local = new StringBuilder(s);
+                actual = this.server.Reverse_SB_LPWStr_Ref(ref local);
+                Assert.AreEqual(expected, actual.ToString());
+                Assert.AreEqual(expected, local.ToString());
+
+                local = new StringBuilder(s);
+                actual = this.server.Reverse_SB_LPWStr_InRef(ref local);
+                Assert.AreEqual(expected, actual.ToString());
+
+                // Palindromes are _always_ equal
+                if (!string.Equals(s, expected))
+                {
+                    Assert.AreNotEqual(expected, local.ToString());
+                }
+
+                local = new StringBuilder(s);
+                actual = new StringBuilder();
+                this.server.Reverse_SB_LPWStr_Out(local, out actual);
+                Assert.AreEqual(expected, actual.ToString());
+                Assert.AreEqual(expected, local.ToString());
+
+                local = new StringBuilder(s);
+                actual = new StringBuilder(s.Length);
+                this.server.Reverse_SB_LPWStr_OutAttr(local, actual);
+                Assert.AreEqual(expected, actual.ToString());
+                Assert.AreEqual(expected, local.ToString());
+            }
+        }
+
+        private void Marshal_BStrString()
+        {
+            Console.WriteLine($"Marshal strings as { UnmanagedType.BStr }");
+            foreach (var p in addPairs)
+            {
+                string expected = p.Item1 + p.Item2;
+                string actual = this.server.Add_BStr(p.Item1, p.Item2);
+                Assert.AreEqual(expected, actual, "Add_String_BStr (simple)");
+            }
+
+            foreach (var s in reversableStrings)
+            {
+                string local = s;
+                string expected = Reverse(local);
+
+                string actual = this.server.Reverse_BStr(local);
+                Assert.AreEqual(expected, actual);
+
+                actual = this.server.Reverse_BStr_Ref(ref local);
+                Assert.AreEqual(expected, actual);
+                Assert.AreEqual(expected, local);
+
+                local = s;
+                actual = this.server.Reverse_BStr_InRef(ref local);
+                Assert.AreEqual(expected, actual);
+                Assert.AreEqual(s, local);
+
+                this.server.Reverse_BStr_Out(local, out actual);
+                Assert.AreEqual(expected, actual);
+
+                actual = local;
+                this.server.Reverse_BStr_OutAttr(local, actual); // No-op for strings
+                Assert.AreEqual(local, actual);
+            }
+        }
+    }
+}
similarity index 97%
rename from tests/src/Interop/ClassicCOM/COMLib2.cs
rename to tests/src/Interop/COM/NETServer/ImportedTypes.cs
index 8f0ec78..a8d6e19 100644 (file)
@@ -7,7 +7,7 @@ using System.Text;
 using System.Security;
 using System.Runtime.InteropServices;
 
-namespace COMLib2
+namespace NETServer
 {
     [Guid("00020404-0000-0000-C000-000000000046")]
     [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
@@ -31,4 +31,4 @@ namespace COMLib2
     public class ContextMenu
     {
     }
-}
+}
\ No newline at end of file
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?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" />
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <AssemblyName>COMLib2</AssemblyName>
+    <AssemblyName>NETServer</AssemblyName>
     <SchemaVersion>2.0</SchemaVersion>
     <ProjectGuid>{C04AB564-CC61-499D-9F4C-AA1A9FDE42C9}</ProjectGuid>
     <OutputType>library</OutputType>
     </CodeAnalysisDependentAssemblyPaths>
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="COMLib2.cs" />
+    <Compile Include="ImportedTypes.cs" />
   </ItemGroup>
   <ItemGroup>
     <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
   </ItemGroup>
   <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
+</Project>
\ No newline at end of file
diff --git a/tests/src/Interop/COM/NativeServer/ArrayTesting.h b/tests/src/Interop/COM/NativeServer/ArrayTesting.h
new file mode 100644 (file)
index 0000000..cbf54cf
--- /dev/null
@@ -0,0 +1,347 @@
+// 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.
+
+#pragma once
+
+#include <cstdint>
+#include "Servers.h"
+
+class DECLSPEC_UUID("B99ABE6A-DFF6-440F-BFB6-55179B8FE18E") ArrayTesting : public UnknownImpl, public IArrayTesting
+{
+private:
+    template<typename L, typename D>
+    double Mean(L l, D *d)
+    {
+        double t = 0.0;
+        for (L i = 0; i < l; ++i)
+            t += d[i];
+
+        return (t / l);
+    }
+    template<VARTYPE E>
+    HRESULT Mean(SAFEARRAY *d, long *l, double *r)
+    {
+        HRESULT hr;
+
+        VARTYPE type;
+        RETURN_IF_FAILED(::SafeArrayGetVartype(d, &type));
+
+        if (E != type)
+            return E_UNEXPECTED;
+
+        LONG upperBoundIndex;
+        RETURN_IF_FAILED(::SafeArrayGetUBound(d, 1, &upperBoundIndex));
+
+        // Upper bound is index so add '1'
+        *l = (upperBoundIndex + 1);
+
+        switch (type)
+        {
+        case VT_UI1:
+            *r = Mean(*l, static_cast<unsigned char*>(d->pvData));
+            break;
+        case VT_I2:
+            *r = Mean(*l, static_cast<int16_t*>(d->pvData));
+            break;
+        case VT_UI2:
+            *r = Mean(*l, static_cast<uint16_t*>(d->pvData));
+            break;
+        case VT_I4:
+            *r = Mean(*l, static_cast<int32_t*>(d->pvData));
+            break;
+        case VT_UI4:
+            *r = Mean(*l, static_cast<uint32_t*>(d->pvData));
+            break;
+        case VT_I8:
+            *r = Mean(*l, static_cast<int64_t*>(d->pvData));
+            break;
+        case VT_UI8:
+            *r = Mean(*l, static_cast<uint64_t*>(d->pvData));
+            break;
+        case VT_R4:
+            *r = Mean(*l, static_cast<float*>(d->pvData));
+            break;
+        case VT_R8:
+            *r = Mean(*l, static_cast<double *>(d->pvData));
+            break;
+        default:
+            return E_INVALIDARG;
+        }
+
+        return S_OK;
+    }
+
+public: // IArrayTesting
+    DEF_RAWFUNC(Mean_Byte_LP_PreLen)(
+        /*[in]*/ long len,
+        /*[in]*/ unsigned char * d,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        *pRetVal = Mean(len, d);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Mean_Short_LP_PreLen)(
+        /*[in]*/ long len,
+        /*[in]*/ short * d,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        *pRetVal = Mean(len, d);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Mean_UShort_LP_PreLen)(
+        /*[in]*/ long len,
+        /*[in]*/ unsigned short * d,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        *pRetVal = Mean(len, d);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Mean_Int_LP_PreLen)(
+        /*[in]*/ long len,
+        /*[in]*/ long * d,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        *pRetVal = Mean(len, d);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Mean_UInt_LP_PreLen)(
+        /*[in]*/ long len,
+        /*[in]*/ unsigned long * d,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        *pRetVal = Mean(len, d);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Mean_Long_LP_PreLen)(
+        /*[in]*/ long len,
+        /*[in]*/ __int64 * d,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        *pRetVal = Mean(len, d);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Mean_ULong_LP_PreLen)(
+        /*[in]*/ long len,
+        /*[in]*/ unsigned __int64 * d,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        *pRetVal = Mean(len, d);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Mean_Float_LP_PreLen)(
+        /*[in]*/ long len,
+        /*[in]*/ float * d,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        *pRetVal = Mean(len, d);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Mean_Double_LP_PreLen)(
+        /*[in]*/ long len,
+        /*[in]*/ double * d,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        *pRetVal = Mean(len, d);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Mean_Byte_LP_PostLen)(
+        /*[in]*/ unsigned char * d,
+        /*[in]*/ long len,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        *pRetVal = Mean(len, d);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Mean_Short_LP_PostLen)(
+        /*[in]*/ short * d,
+        /*[in]*/ long len,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        *pRetVal = Mean(len, d);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Mean_UShort_LP_PostLen)(
+        /*[in]*/ unsigned short * d,
+        /*[in]*/ long len,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        *pRetVal = Mean(len, d);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Mean_Int_LP_PostLen)(
+        /*[in]*/ long * d,
+        /*[in]*/ long len,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        *pRetVal = Mean(len, d);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Mean_UInt_LP_PostLen)(
+        /*[in]*/ unsigned long * d,
+        /*[in]*/ long len,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        *pRetVal = Mean(len, d);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Mean_Long_LP_PostLen)(
+        /*[in]*/ __int64 * d,
+        /*[in]*/ long len,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        *pRetVal = Mean(len, d);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Mean_ULong_LP_PostLen)(
+        /*[in]*/ unsigned __int64 * d,
+        /*[in]*/ long len,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        *pRetVal = Mean(len, d);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Mean_Float_LP_PostLen)(
+        /*[in]*/ float * d,
+        /*[in]*/ long len,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        *pRetVal = Mean(len, d);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Mean_Double_LP_PostLen)(
+        /*[in]*/ double * d,
+        /*[in]*/ long len,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        *pRetVal = Mean(len, d);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Mean_Byte_SafeArray_OutLen)(
+        /*[in]*/ SAFEARRAY * d,
+        /*[out]*/ long * len,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        return Mean<VT_UI1>(d, len, pRetVal);
+    }
+    DEF_RAWFUNC(Mean_Short_SafeArray_OutLen)(
+        /*[in]*/ SAFEARRAY * d,
+        /*[out]*/ long * len,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        return Mean<VT_I2>(d, len, pRetVal);
+    }
+    DEF_RAWFUNC(Mean_UShort_SafeArray_OutLen)(
+        /*[in]*/ SAFEARRAY * d,
+        /*[out]*/ long * len,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        return Mean<VT_UI2>(d, len, pRetVal);
+    }
+    DEF_RAWFUNC(Mean_Int_SafeArray_OutLen)(
+        /*[in]*/ SAFEARRAY * d,
+        /*[out]*/ long * len,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        return Mean<VT_I4>(d, len, pRetVal);
+    }
+    DEF_RAWFUNC(Mean_UInt_SafeArray_OutLen)(
+        /*[in]*/ SAFEARRAY * d,
+        /*[out]*/ long * len,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        return Mean<VT_UI4>(d, len, pRetVal);
+    }
+    DEF_RAWFUNC(Mean_Long_SafeArray_OutLen)(
+        /*[in]*/ SAFEARRAY * d,
+        /*[out]*/ long * len,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        return Mean<VT_I8>(d, len, pRetVal);
+    }
+    DEF_RAWFUNC(Mean_ULong_SafeArray_OutLen)(
+        /*[in]*/ SAFEARRAY * d,
+        /*[out]*/ long * len,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        return Mean<VT_UI8>(d, len, pRetVal);
+    }
+    DEF_RAWFUNC(Mean_Float_SafeArray_OutLen)(
+        /*[in]*/ SAFEARRAY * d,
+        /*[out]*/ long * len,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        return Mean<VT_R4>(d, len, pRetVal);
+    }
+    DEF_RAWFUNC(Mean_Double_SafeArray_OutLen)(
+        /*[in]*/ SAFEARRAY * d,
+        /*[out]*/ long * len,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        if (pRetVal == nullptr)
+            return E_POINTER;
+        return Mean<VT_R8>(d, len, pRetVal);
+    }
+
+public: // IUnknown
+    STDMETHOD(QueryInterface)(
+        /* [in] */ REFIID riid,
+        /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject)
+    {
+        return DoQueryInterface<ArrayTesting, IArrayTesting>(this, riid, ppvObject);
+    }
+
+    DEFINE_REF_COUNTING();
+};
diff --git a/tests/src/Interop/COM/NativeServer/CMakeLists.txt b/tests/src/Interop/COM/NativeServer/CMakeLists.txt
new file mode 100644 (file)
index 0000000..368248d
--- /dev/null
@@ -0,0 +1,20 @@
+cmake_minimum_required (VERSION 2.6)
+project (COMNativeServer)
+include_directories( ${INC_PLATFORM_DIR} )
+include_directories( "../ServerContracts" )
+set(SOURCES Servers.cpp stdafx.cpp Exports.def COMNativeServer.X.manifest)
+
+if (WIN32)
+    # 4365 - signed/unsigned mismatch
+    add_compile_options(-wd4365)
+endif()
+
+# add the shared library
+add_library (COMNativeServer SHARED ${SOURCES})
+target_link_libraries(COMNativeServer ${LINK_LIBRARIES_ADDITIONAL})
+
+# Copy manifest file to project output
+file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/COMNativeServer.X.manifest INPUT ${CMAKE_CURRENT_SOURCE_DIR}/COMNativeServer.X.manifest)
+
+# add the install targets
+install (TARGETS COMNativeServer DESTINATION bin)
diff --git a/tests/src/Interop/COM/NativeServer/COMNativeServer.X.manifest b/tests/src/Interop/COM/NativeServer/COMNativeServer.X.manifest
new file mode 100644 (file)
index 0000000..13c36c9
--- /dev/null
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+
+<assemblyIdentity
+  type="win32"
+  name="COMNativeServer.X"
+  version="1.0.0.0" />
+
+<file name = "COMNativeServer.dll">
+  <!-- NumericTesting -->
+  <comClass
+    clsid="{53169A33-E85D-4E3C-B668-24E438D0929B}"
+    threadingModel="Both" />
+
+  <!-- ArrayTesting -->
+  <comClass
+    clsid="{B99ABE6A-DFF6-440F-BFB6-55179B8FE18E}"
+    threadingModel="Both" />
+
+  <!-- StringTesting -->
+  <comClass
+    clsid="{C73C83E8-51A2-47F8-9B5C-4284458E47A6}"
+    threadingModel="Both" />
+
+  <!-- ErrorMarshalTesting -->
+  <comClass
+    clsid="{71CF5C45-106C-4B32-B418-43A463C6041F}"
+    threadingModel="Both" />
+</file>
+
+</assembly>
diff --git a/tests/src/Interop/COM/NativeServer/ComHelpers.h b/tests/src/Interop/COM/NativeServer/ComHelpers.h
new file mode 100644 (file)
index 0000000..651ccc5
--- /dev/null
@@ -0,0 +1,169 @@
+// 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.
+
+#pragma once
+
+#include <Windows.h>
+#include <comdef.h>
+#include <cassert>
+#include <exception>
+#include <type_traits>
+#include <atomic>
+
+// Common macro for working in COM
+#define RETURN_IF_FAILED(exp) { hr = exp; if (FAILED(hr)) { return hr; } }
+
+namespace Internal
+{
+    template<typename C, typename I>
+    HRESULT __QueryInterfaceImpl(
+        /* [in] */ C *obj,
+        /* [in] */ REFIID riid,
+        /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject)
+    {
+        if (riid == __uuidof(I))
+        {
+            *ppvObject = static_cast<I*>(obj);
+        }
+        else if (riid == __uuidof(IUnknown))
+        {
+            *ppvObject = static_cast<IUnknown*>(obj);
+        }
+        else
+        {
+            *ppvObject = nullptr;
+            return E_NOINTERFACE;
+        }
+
+        return S_OK;
+    }
+
+    template<typename C, typename I1, typename I2, typename ...R>
+    HRESULT __QueryInterfaceImpl(
+        /* [in] */ C *obj,
+        /* [in] */ REFIID riid,
+        /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject)
+    {
+        if (riid == __uuidof(I1))
+        {
+            *ppvObject = static_cast<I1*>(obj);
+            return S_OK;
+        }
+
+        return __QueryInterfaceImpl<C, I2, R...>(obj, riid, ppvObject);
+    }
+}
+
+// Implementation of IUnknown operations
+class UnknownImpl
+{
+public:
+    UnknownImpl() = default;
+    virtual ~UnknownImpl() = default;
+
+    UnknownImpl(const UnknownImpl&) = delete;
+    UnknownImpl& operator=(const UnknownImpl&) = delete;
+
+    UnknownImpl(UnknownImpl&&) = default;
+    UnknownImpl& operator=(UnknownImpl&&) = default;
+
+    template<typename C, typename ...I>
+    HRESULT DoQueryInterface(
+        /* [in] */ C *derived,
+        /* [in] */ REFIID riid,
+        /* [iid_is][out] */ _COM_Outptr_ void **ppvObject)
+    {
+        assert(derived != nullptr);
+        if (ppvObject == nullptr)
+            return E_POINTER;
+
+        HRESULT hr = Internal::__QueryInterfaceImpl<C, I...>(derived, riid, ppvObject);
+        if (hr == S_OK)
+            DoAddRef();
+
+        return hr;
+    }
+
+    ULONG DoAddRef()
+    {
+        assert(_refCount > 0);
+        return (++_refCount);
+    }
+
+    ULONG DoRelease()
+    {
+        assert(_refCount > 0);
+        ULONG c = (--_refCount);
+        if (c == 0)
+            delete this;
+        return c;
+    }
+
+private:
+    std::atomic<ULONG> _refCount = 1;
+};
+
+// Marco to use for defining ref counting impls
+#define DEFINE_REF_COUNTING() \
+    STDMETHOD_(ULONG, AddRef)(void) { return UnknownImpl::DoAddRef(); } \
+    STDMETHOD_(ULONG, Release)(void) { return UnknownImpl::DoRelease(); }
+
+// Templated class factory
+template<typename T>
+class ClassFactoryBasic : public UnknownImpl, public IClassFactory
+{
+public: // static
+    static HRESULT Create(_In_ REFIID riid, _Outptr_ LPVOID FAR* ppv)
+    {
+        try
+        {
+            auto cf = new ClassFactoryBasic();
+            HRESULT hr = cf->QueryInterface(riid, ppv);
+            cf->Release();
+            return hr;
+        }
+        catch (const std::bad_alloc&)
+        {
+            return E_OUTOFMEMORY;
+        }
+    }
+
+public: // IClassFactory
+    STDMETHOD(CreateInstance)(
+        _In_opt_  IUnknown *pUnkOuter,
+        _In_  REFIID riid,
+        _COM_Outptr_  void **ppvObject)
+    {
+        if (pUnkOuter != nullptr)
+            return CLASS_E_NOAGGREGATION;
+
+        try
+        {
+            auto ti = new T();
+            HRESULT hr = ti->QueryInterface(riid, ppvObject);
+            ti->Release();
+            return hr;
+        }
+        catch (const std::bad_alloc&)
+        {
+            return E_OUTOFMEMORY;
+        }
+    }
+
+    STDMETHOD(LockServer)(/* [in] */ BOOL fLock)
+    {
+        assert(false && "Not impl");
+        return E_NOTIMPL;
+    }
+
+public: // IUnknown
+    STDMETHOD(QueryInterface)(
+        /* [in] */ REFIID riid,
+        /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject)
+    {
+        return DoQueryInterface<ClassFactoryBasic, IClassFactory>(this, riid, ppvObject);
+    }
+
+    DEFINE_REF_COUNTING();
+};
diff --git a/tests/src/Interop/COM/NativeServer/ErrorMarshalTesting.h b/tests/src/Interop/COM/NativeServer/ErrorMarshalTesting.h
new file mode 100644 (file)
index 0000000..307abe4
--- /dev/null
@@ -0,0 +1,32 @@
+// 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.
+
+#pragma once
+
+#include "Servers.h"
+
+class DECLSPEC_UUID("71CF5C45-106C-4B32-B418-43A463C6041F") ErrorMarshalTesting : public UnknownImpl, public IErrorMarshalTesting
+{
+public: // IErrorMarshalTesting
+    DEF_RAWFUNC(Throw_HResult)(
+        /*[in]*/ long hresultToReturn)
+    {
+        return HRESULT{ hresultToReturn };
+    }
+    long __stdcall Return_As_HResult(
+        /*[in]*/ long hresultToReturn)
+    {
+        return hresultToReturn;
+    }
+
+public: // IUnknown
+    STDMETHOD(QueryInterface)(
+        /* [in] */ REFIID riid,
+        /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject)
+    {
+        return DoQueryInterface<ErrorMarshalTesting, IErrorMarshalTesting>(this, riid, ppvObject);
+    }
+
+    DEFINE_REF_COUNTING();
+};
diff --git a/tests/src/Interop/COM/NativeServer/Exports.def b/tests/src/Interop/COM/NativeServer/Exports.def
new file mode 100644 (file)
index 0000000..2d0de26
--- /dev/null
@@ -0,0 +1,4 @@
+EXPORTS
+    DllGetClassObject   PRIVATE
+    DllRegisterServer   PRIVATE
+    DllUnregisterServer PRIVATE
\ No newline at end of file
diff --git a/tests/src/Interop/COM/NativeServer/NumericTesting.h b/tests/src/Interop/COM/NativeServer/NumericTesting.h
new file mode 100644 (file)
index 0000000..9a80230
--- /dev/null
@@ -0,0 +1,257 @@
+// 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.
+
+#pragma once
+
+#include <type_traits>
+#include "Servers.h"
+
+class DECLSPEC_UUID("53169A33-E85D-4E3C-B668-24E438D0929B") NumericTesting : public UnknownImpl, public INumericTesting
+{
+public:
+    DEF_RAWFUNC(Add_Byte)(
+        /*[in]*/ unsigned char a,
+        /*[in]*/ unsigned char b,
+        /*[out,retval]*/ unsigned char * pRetVal)
+    {
+        *pRetVal = static_cast<unsigned char>(a + b);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_Short)(
+        /*[in]*/ short a,
+        /*[in]*/ short b,
+        /*[out,retval]*/ short * pRetVal)
+    {
+        *pRetVal = static_cast<short>(a + b);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_UShort)(
+        /*[in]*/ unsigned short a,
+        /*[in]*/ unsigned short b,
+        /*[out,retval]*/ unsigned short * pRetVal)
+    {
+        *pRetVal = static_cast<unsigned short>(a + b);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_Int)(
+        /*[in]*/ long a,
+        /*[in]*/ long b,
+        /*[out,retval]*/ long * pRetVal)
+    {
+        *pRetVal = a + b;
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_UInt)(
+        /*[in]*/ unsigned long a,
+        /*[in]*/ unsigned long b,
+        /*[out,retval]*/ unsigned long * pRetVal)
+    {
+        *pRetVal = a + b;
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_Long)(
+        /*[in]*/ __int64 a,
+        /*[in]*/ __int64 b,
+        /*[out,retval]*/ __int64 * pRetVal)
+    {
+        *pRetVal = a + b;
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_ULong)(
+        /*[in]*/ unsigned __int64 a,
+        /*[in]*/ unsigned __int64 b,
+        /*[out,retval]*/ unsigned __int64 * pRetVal)
+    {
+        *pRetVal = a + b;
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_Float)(
+        /*[in]*/ float a,
+        /*[in]*/ float b,
+        /*[out,retval]*/ float * pRetVal)
+    {
+        *pRetVal = a + b;
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_Double)(
+        /*[in]*/ double a,
+        /*[in]*/ double b,
+        /*[out,retval]*/ double * pRetVal)
+    {
+        *pRetVal = a + b;
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_Byte_Ref)(
+        /*[in]*/ unsigned char a,
+        /*[in]*/ unsigned char b,
+        /*[in,out]*/ unsigned char * c)
+    {
+        if (*c != std::numeric_limits<std::remove_reference<decltype(*c)>::type>::max())
+            return E_UNEXPECTED;
+        *c = static_cast<unsigned char>(a + b);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_Short_Ref)(
+        /*[in]*/ short a,
+        /*[in]*/ short b,
+        /*[in,out]*/ short * c)
+    {
+        if (*c != std::numeric_limits<std::remove_reference<decltype(*c)>::type>::max())
+            return E_UNEXPECTED;
+        *c = static_cast<short>(a + b);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_UShort_Ref)(
+        /*[in]*/ unsigned short a,
+        /*[in]*/ unsigned short b,
+        /*[in,out]*/ unsigned short * c)
+    {
+        if (*c != std::numeric_limits<std::remove_reference<decltype(*c)>::type>::max())
+            return E_UNEXPECTED;
+        *c = static_cast<unsigned short>(a + b);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_Int_Ref)(
+        /*[in]*/ long a,
+        /*[in]*/ long b,
+        /*[in,out]*/ long * c)
+    {
+        if (*c != std::numeric_limits<std::remove_reference<decltype(*c)>::type>::max())
+            return E_UNEXPECTED;
+        *c = a + b;
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_UInt_Ref)(
+        /*[in]*/ unsigned long a,
+        /*[in]*/ unsigned long b,
+        /*[in,out]*/ unsigned long * c)
+    {
+        if (*c != std::numeric_limits<std::remove_reference<decltype(*c)>::type>::max())
+            return E_UNEXPECTED;
+        *c = a + b;
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_Long_Ref)(
+        /*[in]*/ __int64 a,
+        /*[in]*/ __int64 b,
+        /*[in,out]*/ __int64 * c)
+    {
+        if (*c != std::numeric_limits<std::remove_reference<decltype(*c)>::type>::max())
+            return E_UNEXPECTED;
+        *c = a + b;
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_ULong_Ref)(
+        /*[in]*/ unsigned __int64 a,
+        /*[in]*/ unsigned __int64 b,
+        /*[in,out]*/ unsigned __int64 * c)
+    {
+        if (*c != std::numeric_limits<std::remove_reference<decltype(*c)>::type>::max())
+            return E_UNEXPECTED;
+        *c = a + b;
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_Float_Ref)(
+        /*[in]*/ float a,
+        /*[in]*/ float b,
+        /*[in,out]*/ float * c)
+    {
+        if (*c != std::numeric_limits<std::remove_reference<decltype(*c)>::type>::max())
+            return E_UNEXPECTED;
+        *c = a + b;
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_Double_Ref)(
+        /*[in]*/ double a,
+        /*[in]*/ double b,
+        /*[in,out]*/ double * c)
+    {
+        if (*c != std::numeric_limits<std::remove_reference<decltype(*c)>::type>::max())
+            return E_UNEXPECTED;
+        *c = a + b;
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_Byte_Out)(
+        /*[in]*/ unsigned char a,
+        /*[in]*/ unsigned char b,
+        /*[out]*/ unsigned char * c)
+    {
+        *c = static_cast<unsigned char>(a + b);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_Short_Out)(
+        /*[in]*/ short a,
+        /*[in]*/ short b,
+        /*[out]*/ short * c)
+    {
+        *c = static_cast<short>(a + b);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_UShort_Out)(
+        /*[in]*/ unsigned short a,
+        /*[in]*/ unsigned short b,
+        /*[out]*/ unsigned short * c)
+    {
+        *c = static_cast<unsigned short>(a + b);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_Int_Out)(
+        /*[in]*/ long a,
+        /*[in]*/ long b,
+        /*[out]*/ long * c)
+    {
+        *c = a + b;
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_UInt_Out)(
+        /*[in]*/ unsigned long a,
+        /*[in]*/ unsigned long b,
+        /*[out]*/ unsigned long * c)
+    {
+        *c = a + b;
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_Long_Out)(
+        /*[in]*/ __int64 a,
+        /*[in]*/ __int64 b,
+        /*[out]*/ __int64 * c)
+    {
+        *c = a + b;
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_ULong_Out)(
+        /*[in]*/ unsigned __int64 a,
+        /*[in]*/ unsigned __int64 b,
+        /*[out]*/ unsigned __int64 * c)
+    {
+        *c = a + b;
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_Float_Out)(
+        /*[in]*/ float a,
+        /*[in]*/ float b,
+        /*[out]*/ float * c)
+    {
+        *c = a + b;
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_Double_Out)(
+        /*[in]*/ double a,
+        /*[in]*/ double b,
+        /*[out]*/ double * c)
+    {
+        *c = a + b;
+        return S_OK;
+    }
+
+public: // IUnknown
+    STDMETHOD(QueryInterface)(
+        /* [in] */ REFIID riid,
+        /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject)
+    {
+        return DoQueryInterface<NumericTesting, INumericTesting>(this, riid, ppvObject);
+    }
+
+    DEFINE_REF_COUNTING();
+};
diff --git a/tests/src/Interop/COM/NativeServer/Servers.cpp b/tests/src/Interop/COM/NativeServer/Servers.cpp
new file mode 100644 (file)
index 0000000..27f0d29
--- /dev/null
@@ -0,0 +1,198 @@
+// 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.
+
+#include "stdafx.h"
+#include "Servers.h"
+
+namespace
+{
+    const WCHAR EntryKeyFmt[] = L"SOFTWARE\\Classes\\CLSID\\%s";
+
+    struct OleStr : public std::unique_ptr<std::remove_pointer<LPOLESTR>::type, decltype(&::CoTaskMemFree)>
+    {
+        OleStr(_In_ LPOLESTR raw)
+            : std::unique_ptr<std::remove_pointer<LPOLESTR>::type, decltype(&::CoTaskMemFree)>(raw, ::CoTaskMemFree)
+        { }
+    };
+
+    struct RegKey : public std::unique_ptr<std::remove_pointer<HKEY>::type, decltype(&::RegCloseKey)>
+    {
+        RegKey(_In_ HKEY raw)
+            : std::unique_ptr<std::remove_pointer<HKEY>::type, decltype(&::RegCloseKey)>(raw, ::RegCloseKey)
+        { }
+    };
+
+    HRESULT RemoveClsid(_In_ REFCLSID clsid)
+    {
+        HRESULT hr;
+
+        LPOLESTR clsidAsStrRaw;
+        RETURN_IF_FAILED(::StringFromCLSID(clsid, &clsidAsStrRaw));
+
+        OleStr clsidAsStr{ clsidAsStrRaw };
+
+        WCHAR regKeyPath[1024];
+        ::swprintf_s(regKeyPath, EntryKeyFmt, clsidAsStr.get());
+
+        LSTATUS res;
+
+        // Handle sub keys
+        {
+            HKEY toDeleteRaw;
+            res = ::RegOpenKeyExW(HKEY_LOCAL_MACHINE, regKeyPath, 0, KEY_READ | KEY_WRITE, &toDeleteRaw);
+            if (ERROR_FILE_NOT_FOUND == res)
+            {
+                return S_OK;
+            }
+            else if (ERROR_SUCCESS != res)
+            {
+                return __HRESULT_FROM_WIN32(res);
+            }
+
+            RegKey toDelete{ toDeleteRaw };
+            res = ::RegDeleteTreeW(toDelete.get(), nullptr);
+            if (ERROR_SUCCESS != res)
+                return __HRESULT_FROM_WIN32(res);
+        }
+
+        res = ::RegDeleteKeyW(HKEY_LOCAL_MACHINE, regKeyPath);
+        if (ERROR_SUCCESS != res)
+            return __HRESULT_FROM_WIN32(res);
+
+        return S_OK;
+    }
+
+    HRESULT RegisterClsid(_In_ REFCLSID clsid, _In_opt_z_ const WCHAR *threadingModel)
+    {
+        HRESULT hr;
+
+        // Remove the CLSID in case it exists and has undesirable settings
+        RETURN_IF_FAILED(RemoveClsid(clsid));
+
+        LPOLESTR clsidAsStrRaw;
+        RETURN_IF_FAILED(::StringFromCLSID(clsid, &clsidAsStrRaw));
+
+        OleStr clsidAsStr{ clsidAsStrRaw };
+
+        WCHAR regKeyClsidPath[1024];
+        ::swprintf_s(regKeyClsidPath, EntryKeyFmt, clsidAsStr.get());
+
+        HKEY regKeyRaw;
+        DWORD disp;
+        LSTATUS res = ::RegCreateKeyExW(
+            HKEY_LOCAL_MACHINE,
+            regKeyClsidPath,
+            0,
+            REG_NONE,
+            REG_OPTION_NON_VOLATILE,
+            (KEY_READ | KEY_WRITE),
+            nullptr,
+            &regKeyRaw,
+            &disp);
+        if (res != ERROR_SUCCESS)
+            return __HRESULT_FROM_WIN32(res);
+
+        RegKey regKey{ regKeyRaw };
+
+        WCHAR regKeyServerPath[1024];
+        ::swprintf_s(regKeyServerPath, L"%s\\InProcServer32", regKeyClsidPath);
+
+        HKEY regServerKeyRaw;
+        res = ::RegCreateKeyExW(
+            HKEY_LOCAL_MACHINE,
+            regKeyServerPath,
+            0,
+            REG_NONE,
+            REG_OPTION_NON_VOLATILE,
+            (KEY_READ | KEY_WRITE),
+            nullptr,
+            &regServerKeyRaw,
+            &disp);
+        if (res != ERROR_SUCCESS)
+            return __HRESULT_FROM_WIN32(res);
+
+        regKey.reset(regServerKeyRaw);
+
+        WCHAR fullPath[MAX_PATH + 1];
+
+        HMODULE mod;
+        if (FALSE == ::GetModuleHandleExW(
+            (GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT),
+            reinterpret_cast<LPCWSTR>(&RegisterClsid),
+            &mod))
+        {
+            return HRESULT_FROM_WIN32(::GetLastError());
+        }
+
+        ::GetModuleFileNameW(mod, fullPath, ARRAYSIZE(fullPath));
+
+        // The default value for the key is the path to the DLL
+        res = ::RegSetValueExW(
+            regKey.get(),
+            nullptr,
+            0,
+            REG_SZ,
+            reinterpret_cast<const BYTE*>(fullPath),
+            static_cast<DWORD>(::wcslen(fullPath) + 1) * sizeof(fullPath[0]));
+        if (res != ERROR_SUCCESS)
+            return __HRESULT_FROM_WIN32(res);
+
+        // Set the threading model if provided
+        if (threadingModel != nullptr)
+        {
+            res = ::RegSetValueExW(
+                regKey.get(),
+                L"ThreadingModel",
+                0,
+                REG_SZ,
+                reinterpret_cast<const BYTE*>(threadingModel),
+                static_cast<DWORD>(::wcslen(threadingModel) + 1) * sizeof(threadingModel[0]));
+            if (res != ERROR_SUCCESS)
+                return __HRESULT_FROM_WIN32(res);
+        }
+
+        return S_OK;
+    }
+}
+
+STDAPI DllRegisterServer(void)
+{
+    HRESULT hr;
+
+    RETURN_IF_FAILED(RegisterClsid(__uuidof(NumericTesting), L"Both"));
+    RETURN_IF_FAILED(RegisterClsid(__uuidof(ArrayTesting), L"Both"));
+    RETURN_IF_FAILED(RegisterClsid(__uuidof(StringTesting), L"Both"));
+    RETURN_IF_FAILED(RegisterClsid(__uuidof(ErrorMarshalTesting), L"Both"));
+
+    return S_OK;
+}
+
+STDAPI DllUnregisterServer(void)
+{
+    HRESULT hr;
+
+    RETURN_IF_FAILED(RemoveClsid(__uuidof(NumericTesting)));
+    RETURN_IF_FAILED(RemoveClsid(__uuidof(ArrayTesting)));
+    RETURN_IF_FAILED(RemoveClsid(__uuidof(StringTesting)));
+    RETURN_IF_FAILED(RemoveClsid(__uuidof(ErrorMarshalTesting)));
+
+    return S_OK;
+}
+
+STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Out_ LPVOID FAR* ppv)
+{
+    if (rclsid == __uuidof(NumericTesting))
+        return ClassFactoryBasic<NumericTesting>::Create(riid, ppv);
+
+    if (rclsid == __uuidof(ArrayTesting))
+        return ClassFactoryBasic<ArrayTesting>::Create(riid, ppv);
+
+    if (rclsid == __uuidof(StringTesting))
+        return ClassFactoryBasic<StringTesting>::Create(riid, ppv);
+
+    if (rclsid == __uuidof(ErrorMarshalTesting))
+        return ClassFactoryBasic<ErrorMarshalTesting>::Create(riid, ppv);
+
+    return CLASS_E_CLASSNOTAVAILABLE;
+}
diff --git a/tests/src/Interop/COM/NativeServer/Servers.h b/tests/src/Interop/COM/NativeServer/Servers.h
new file mode 100644 (file)
index 0000000..5a22e80
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+
+#pragma once
+
+#include "ComHelpers.h"
+
+//#import "Server.Contract.tlb" no_namespace
+#include <Server.Contracts.tlh>
+
+#define DEF_RAWFUNC(n) virtual COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE raw_ ## n
+#define DEF_FUNC(n) virtual COM_DECLSPEC_NOTHROW HRESULT STDMETHODCALLTYPE ## n
+
+#include "NumericTesting.h"
+#include "ArrayTesting.h"
+#include "StringTesting.h"
+#include "ErrorMarshalTesting.h"
diff --git a/tests/src/Interop/COM/NativeServer/StringTesting.h b/tests/src/Interop/COM/NativeServer/StringTesting.h
new file mode 100644 (file)
index 0000000..7589bf2
--- /dev/null
@@ -0,0 +1,321 @@
+// 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.
+
+#pragma once
+
+#include "Servers.h"
+
+class DECLSPEC_UUID("C73C83E8-51A2-47F8-9B5C-4284458E47A6") StringTesting : public UnknownImpl, public IStringTesting
+{
+private:
+    template <typename STRING>
+    bool EqualValue(STRING l, STRING r)
+    {
+        STRING tmp = l;
+        int len = 1; // Include 1 for null
+        while (*tmp++)
+            ++len;
+
+        return (0 == ::memcmp(l, r, len * sizeof(l[0])));
+    }
+
+    template <typename STRING>
+    STRING ReverseInplace(size_t len, STRING s)
+    {
+        std::reverse(s, s + len);
+        return s;
+    }
+
+    template<typename STRING>
+    HRESULT Reverse(STRING str, STRING *res)
+    {
+        STRING tmp = str;
+        size_t len = 0;
+        while (*tmp++)
+            ++len;
+
+        size_t strDataLen = (len + 1) * sizeof(str[0]);
+        auto resLocal = (STRING)::CoTaskMemAlloc(strDataLen);
+        if (resLocal == nullptr)
+            return E_OUTOFMEMORY;
+
+        ::memcpy_s(resLocal, strDataLen, str, strDataLen);
+        *res = ReverseInplace(len, resLocal);
+
+        return S_OK;
+    }
+
+    HRESULT ReverseBstr(BSTR str, BSTR *res)
+    {
+        UINT strDataLen = ::SysStringByteLen(str);
+        BSTR resLocal = ::SysAllocStringByteLen(reinterpret_cast<LPCSTR>(str), strDataLen);
+        if (resLocal == nullptr)
+            return E_OUTOFMEMORY;
+
+        UINT len = ::SysStringLen(str);
+        *res = ReverseInplace(len, resLocal);
+
+        return S_OK;
+    }
+
+public: // IStringTesting
+    DEF_RAWFUNC(Add_LPStr)(
+        /*[in]*/ LPSTR a,
+        /*[in]*/ LPSTR b,
+        /*[out,retval]*/ LPSTR * pRetVal)
+    {
+        if (a == nullptr || b == nullptr)
+            return E_POINTER;
+
+        size_t aLen = ::strlen(a);
+        size_t bLen = ::strlen(b);
+        auto buf = (LPSTR)::CoTaskMemAlloc((aLen + bLen + 1) * sizeof(*b));
+
+        ::strcpy_s(buf, aLen + 1, a);
+        ::strcpy_s(buf + aLen, bLen + 1, b);
+
+        *pRetVal = buf;
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_LPWStr)(
+        /*[in]*/ LPWSTR a,
+        /*[in]*/ LPWSTR b,
+        /*[out,retval]*/ LPWSTR * pRetVal)
+    {
+        if (a == nullptr || b == nullptr)
+            return E_POINTER;
+
+        size_t aLen = ::wcslen(a);
+        size_t bLen = ::wcslen(b);
+        auto buf = (LPWSTR)::CoTaskMemAlloc((aLen + bLen + 1) * sizeof(*b));
+
+        ::wcscpy_s(buf, aLen + 1, a);
+        ::wcscpy_s(buf + aLen, bLen + 1, b);
+
+        *pRetVal = buf;
+        return S_OK;
+    }
+    DEF_RAWFUNC(Add_BStr)(
+        /*[in]*/ BSTR a,
+        /*[in]*/ BSTR b,
+        /*[out,retval]*/ BSTR * pRetVal)
+    {
+        if (a == nullptr || b == nullptr)
+            return E_POINTER;
+
+        UINT aLen = ::SysStringLen(a);
+        UINT bLen = ::SysStringLen(b);
+        BSTR buf = ::SysAllocStringByteLen(nullptr, (aLen + bLen) * sizeof(a[0]));
+
+        ::wcscpy_s(buf, aLen + 1, a);
+        ::wcscpy_s(buf + aLen, bLen + 1, b);
+
+        *pRetVal = buf;
+        return S_OK;
+    }
+    DEF_RAWFUNC(Reverse_LPStr)(
+        /*[in]*/ LPSTR a,
+        /*[out,retval]*/ LPSTR * pRetVal)
+    {
+        return Reverse(a, pRetVal);
+    }
+    DEF_RAWFUNC(Reverse_LPStr_Ref)(
+        /*[in,out]*/ LPSTR * a,
+        /*[out,retval]*/ LPSTR * pRetVal)
+    {
+        HRESULT hr;
+        RETURN_IF_FAILED(Reverse(*a, pRetVal));
+        ReverseInplace(::strlen(*a), *a);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Reverse_LPStr_InRef)(
+        /*[in]*/ LPSTR * a,
+        /*[out,retval]*/ LPSTR * pRetVal)
+    {
+        return Reverse(*a, pRetVal);
+    }
+    DEF_RAWFUNC(Reverse_LPStr_Out)(
+        /*[in]*/ LPSTR a,
+        /*[out]*/ LPSTR * b)
+    {
+        return Reverse(a, b);
+    }
+    DEF_RAWFUNC(Reverse_LPStr_OutAttr)(
+        /*[in]*/ LPSTR a,
+        /*[out]*/ LPSTR b)
+    {
+        ReverseInplace(::strlen(b), b);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Reverse_SB_LPStr)(
+        /*[in,out]*/ LPSTR a,
+        /*[out,retval]*/ LPSTR * pRetVal)
+    {
+        HRESULT hr;
+        RETURN_IF_FAILED(Reverse(a, pRetVal));
+        ReverseInplace(::strlen(a), a);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Reverse_SB_LPStr_Ref)(
+        /*[in,out]*/ LPSTR * a,
+        /*[out,retval]*/ LPSTR * pRetVal)
+    {
+        HRESULT hr;
+        RETURN_IF_FAILED(Reverse(*a, pRetVal));
+        ReverseInplace(::strlen(*a), *a);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Reverse_SB_LPStr_InRef)(
+        /*[in]*/ LPSTR * a,
+        /*[out,retval]*/ LPSTR * pRetVal)
+    {
+        HRESULT hr;
+        RETURN_IF_FAILED(Reverse(*a, pRetVal));
+        ReverseInplace(::strlen(*a), *a);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Reverse_SB_LPStr_Out)(
+        /*[in,out]*/ LPSTR a,
+        /*[out]*/ LPSTR * b)
+    {
+        HRESULT hr;
+        RETURN_IF_FAILED(Reverse(a, b));
+        ReverseInplace(::strlen(a), a);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Reverse_SB_LPStr_OutAttr)(
+        /*[in,out]*/ LPSTR a,
+        /*[out]*/ LPSTR b)
+    {
+        size_t len = ::strlen(a);
+        ReverseInplace(len, a);
+        size_t byteLen = (len + 1) * sizeof(*a);
+        ::memcpy_s(b, byteLen, a, byteLen);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Reverse_LPWStr)(
+        /*[in]*/ LPWSTR a,
+        /*[out,retval]*/ LPWSTR * pRetVal)
+    {
+        return Reverse(a, pRetVal);
+    }
+    DEF_RAWFUNC(Reverse_LPWStr_Ref)(
+        /*[in,out]*/ LPWSTR * a,
+        /*[out,retval]*/ LPWSTR * pRetVal)
+    {
+        HRESULT hr;
+        RETURN_IF_FAILED(Reverse(*a, pRetVal));
+        ReverseInplace(::wcslen(*a), *a);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Reverse_LPWStr_InRef)(
+        /*[in]*/ LPWSTR * a,
+        /*[out,retval]*/ LPWSTR * pRetVal)
+    {
+        return Reverse(*a, pRetVal);
+    }
+    DEF_RAWFUNC(Reverse_LPWStr_Out)(
+        /*[in]*/ LPWSTR a,
+        /*[out]*/ LPWSTR * b)
+    {
+        return Reverse(a, b);
+    }
+    DEF_RAWFUNC(Reverse_LPWStr_OutAttr)(
+        /*[in]*/ LPWSTR a,
+        /*[out]*/ LPWSTR b)
+    {
+        ReverseInplace(::wcslen(b), b);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Reverse_SB_LPWStr)(
+        /*[in,out]*/ LPWSTR a,
+        /*[out,retval]*/ LPWSTR * pRetVal)
+    {
+        HRESULT hr;
+        RETURN_IF_FAILED(Reverse(a, pRetVal));
+        ReverseInplace(::wcslen(a), a);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Reverse_SB_LPWStr_Ref)(
+        /*[in,out]*/ LPWSTR * a,
+        /*[out,retval]*/ LPWSTR * pRetVal)
+    {
+        HRESULT hr;
+        RETURN_IF_FAILED(Reverse(*a, pRetVal));
+        ReverseInplace(::wcslen(*a), *a);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Reverse_SB_LPWStr_InRef)(
+        /*[in]*/ LPWSTR * a,
+        /*[out,retval]*/ LPWSTR * pRetVal)
+    {
+        HRESULT hr;
+        RETURN_IF_FAILED(Reverse(*a, pRetVal));
+        ReverseInplace(::wcslen(*a), *a);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Reverse_SB_LPWStr_Out)(
+        /*[in,out]*/ LPWSTR a,
+        /*[out]*/ LPWSTR * b)
+    {
+        HRESULT hr;
+        RETURN_IF_FAILED(Reverse(a, b));
+        ReverseInplace(::wcslen(a), a);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Reverse_SB_LPWStr_OutAttr)(
+        /*[in,out]*/ LPWSTR a,
+        /*[out]*/ LPWSTR b)
+    {
+        size_t len = ::wcslen(a);
+        ReverseInplace(len, a);
+        size_t byteLen = (len + 1) * sizeof(*a);
+        ::memcpy_s(b, byteLen, a, byteLen);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Reverse_BStr)(
+        /*[in]*/ BSTR a,
+        /*[out,retval]*/ BSTR * pRetVal)
+    {
+        return ReverseBstr(a, pRetVal);
+    }
+    DEF_RAWFUNC(Reverse_BStr_Ref)(
+        /*[in,out]*/ BSTR * a,
+        /*[out,retval]*/ BSTR * pRetVal)
+    {
+        HRESULT hr;
+        RETURN_IF_FAILED(ReverseBstr(*a, pRetVal));
+        ReverseInplace(::SysStringLen(*a), *a);
+        return S_OK;
+    }
+    DEF_RAWFUNC(Reverse_BStr_InRef)(
+        /*[in]*/ BSTR * a,
+        /*[out,retval]*/ BSTR * pRetVal)
+    {
+        return ReverseBstr(*a, pRetVal);
+    }
+    DEF_RAWFUNC(Reverse_BStr_Out)(
+        /*[in]*/ BSTR a,
+        /*[out]*/ BSTR * b)
+    {
+        return ReverseBstr(a, b);
+    }
+    DEF_RAWFUNC(Reverse_BStr_OutAttr)(
+        /*[in]*/ BSTR a,
+        /*[out]*/ BSTR b)
+    {
+        ReverseInplace(::SysStringLen(b), b);
+        return S_OK;
+    }
+
+public: // IUnknown
+    STDMETHOD(QueryInterface)(
+        /* [in] */ REFIID riid,
+        /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject)
+    {
+        return DoQueryInterface<StringTesting, IStringTesting>(this, riid, ppvObject);
+    }
+
+    DEFINE_REF_COUNTING();
+};
diff --git a/tests/src/Interop/COM/NativeServer/stdafx.cpp b/tests/src/Interop/COM/NativeServer/stdafx.cpp
new file mode 100644 (file)
index 0000000..c87158f
--- /dev/null
@@ -0,0 +1,5 @@
+// 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.
+
+#include "stdafx.h"
diff --git a/tests/src/Interop/COM/NativeServer/stdafx.h b/tests/src/Interop/COM/NativeServer/stdafx.h
new file mode 100644 (file)
index 0000000..058ec2e
--- /dev/null
@@ -0,0 +1,15 @@
+// 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.
+
+#pragma once
+
+#define NOMINMAX
+#define WIN32_LEAN_AND_MEAN
+// Windows Header Files
+#include <windows.h>
+
+#include <atomic>
+#include <memory>
+
+
diff --git a/tests/src/Interop/COM/Reflection/Reflection.cs b/tests/src/Interop/COM/Reflection/Reflection.cs
new file mode 100644 (file)
index 0000000..bab341a
--- /dev/null
@@ -0,0 +1,144 @@
+// 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.Text;
+using System.Security;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+public class Reflection
+{
+    /// <summary>
+    /// Reflect load ComImport Types amd enumerate them
+    /// </summary>
+    static bool ReflectionLoad()
+    {
+        try
+        {
+            Console.WriteLine("Scenario: ReflectionLoad");
+            var asm = Assembly.LoadFrom("NETServer.dll");
+            foreach (Type t in asm.GetTypes())
+            {
+                Console.WriteLine(t.Name);
+            }
+
+            return true;
+        }
+        catch (Exception e)
+        {
+            Console.WriteLine($"Caught unexpected exception: {e}");
+            return false;
+        }
+    }
+
+    /// <summary>
+    /// Type.IsCOMObject
+    /// </summary>
+    static bool TypeIsComObject()
+    {
+        try
+        {
+            Console.WriteLine("Scenario: TypeIsComObject");
+            Type classType = typeof(NETServer.ContextMenu);
+            if (!classType.IsCOMObject)
+            {
+                Console.WriteLine("ComImport Class's IsCOMObject should return true");
+                return false;
+            }
+
+            Type interfaceType = typeof(NETServer.IEnumVARIANT);
+            if (interfaceType.IsCOMObject)
+            {
+                Console.WriteLine("ComImport interface's IsCOMObject should return false");
+                return false;
+            }
+
+            return true;
+        }
+        catch (Exception e)
+        {
+            Console.WriteLine($"Caught unexpected exception: {e}");
+            return false;
+        }
+    }
+
+    /// <summary>
+    /// Create COM instance via Activator
+    /// </summary>
+    static bool ActivateCOMType()
+    {
+        try
+        {
+            Console.WriteLine("Scenario: ActivateCOMType");
+            var contextMenu = (NETServer.ContextMenu)Activator.CreateInstance(typeof(NETServer.ContextMenu));
+
+            // Non-Windows should throw PlatformNotSupportedException
+            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+            {
+                return false;
+            }
+            
+            if (contextMenu == null)
+            {
+                Console.WriteLine("ActivateCOMType failed");
+                return false;
+            }
+
+            return true;
+        }
+        catch (TargetInvocationException e)
+        {
+            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && e.InnerException is PlatformNotSupportedException)
+            {
+                return true;
+            }
+            
+            Console.WriteLine($"Caught unexpected {nameof(PlatformNotSupportedException)}: {e}");
+            return false;
+        }
+        catch(COMException e)
+        {
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+            {
+                return true;
+            }
+            
+            Console.WriteLine($"Caught unexpected {nameof(COMException)}: {e}");
+            return false;
+        }
+        catch (Exception e)
+        {
+            Console.WriteLine($"Caught unexpected exception: {e}");
+            return false;
+        }
+    }
+
+    [System.Security.SecuritySafeCritical]
+    static int Main()
+    {
+        int failures = 0;
+        if (!ReflectionLoad())
+        {
+            Console.WriteLine("ReflectionLoad Failed");
+            failures++;
+        }
+
+        if (!TypeIsComObject())
+        {
+            Console.WriteLine("TypeIsComObject Failed");
+            failures++;
+        }
+
+        if (!ActivateCOMType())
+        {
+            Console.WriteLine("ActivateCOMType Failed");
+            failures++;
+        }
+
+        return failures > 0 ? 101 : 100;
+    }
+}
\ No newline at end of file
@@ -1,10 +1,10 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?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" />
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <AssemblyName>ClassicCOMUnitTest</AssemblyName>
+    <AssemblyName>Reflection</AssemblyName>
     <SchemaVersion>2.0</SchemaVersion>
     <ProjectGuid>{85C57688-DA98-4DE3-AC9B-526E4747434C}</ProjectGuid>
     <OutputType>Exe</OutputType>
     </CodeAnalysisDependentAssemblyPaths>
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="ClassicCOMUnitTest.cs" />
+    <Compile Include="Reflection.cs" />
   </ItemGroup>
   <ItemGroup>
-    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
-  </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>
-    <ProjectReference Include="COMLib.csproj">
-      <Project>{5FEE5C46-8DD9-49FA-BDC1-AF22867A0704}</Project>
-      <Name>COMLib</Name>
-    </ProjectReference>
-    <ProjectReference Include="COMLib2.csproj">
+    <ProjectReference Include="..\NETServer\NETServer.csproj">
       <Project>{C04AB564-CC61-499D-9F4C-AA1A9FDE42C9}</Project>
-      <Name>COMLib</Name>
+      <Name>NETServer</Name>
     </ProjectReference>
-    <ProjectReference Include="CMakeLists.txt" />
   </ItemGroup>
   <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
+</Project>
\ No newline at end of file
diff --git a/tests/src/Interop/COM/ServerContracts/Primitives.cs b/tests/src/Interop/COM/ServerContracts/Primitives.cs
new file mode 100644 (file)
index 0000000..cc6a303
--- /dev/null
@@ -0,0 +1,189 @@
+// 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.
+
+#pragma warning disable 618 // Must test deprecated features
+
+namespace Server.Contract
+{
+    using System;
+    using System.Runtime.InteropServices;
+    using System.Text;
+
+    [ComVisible(true)]
+    [Guid("05655A94-A915-4926-815D-A9EA648BAAD9")]
+    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+    public interface INumericTesting
+    {
+        byte Add_Byte(byte a, byte b);
+        short Add_Short(short a, short b);
+        ushort Add_UShort(ushort a, ushort b);
+        int Add_Int(int a, int b);
+        uint Add_UInt(uint a, uint b);
+        long Add_Long(long a, long b);
+        ulong Add_ULong(ulong a, ulong b);
+        float Add_Float(float a, float b);
+        double Add_Double(double a, double b);
+
+        void Add_Byte_Ref(byte a, byte b, ref byte c);
+        void Add_Short_Ref(short a, short b, ref short c);
+        void Add_UShort_Ref(ushort a, ushort b, ref ushort c);
+        void Add_Int_Ref(int a, int b, ref int c);
+        void Add_UInt_Ref(uint a, uint b, ref uint c);
+        void Add_Long_Ref(long a, long b, ref long c);
+        void Add_ULong_Ref(ulong a, ulong b, ref ulong c);
+        void Add_Float_Ref(float a, float b, ref float c);
+        void Add_Double_Ref(double a, double b, ref double c);
+
+        void Add_Byte_Out(byte a, byte b, out byte c);
+        void Add_Short_Out(short a, short b, out short c);
+        void Add_UShort_Out(ushort a, ushort b, out ushort c);
+        void Add_Int_Out(int a, int b, out int c);
+        void Add_UInt_Out(uint a, uint b, out uint c);
+        void Add_Long_Out(long a, long b, out long c);
+        void Add_ULong_Out(ulong a, ulong b, out ulong c);
+        void Add_Float_Out(float a, float b, out float c);
+        void Add_Double_Out(double a, double b, out double c);
+    }
+
+    [ComVisible(true)]
+    [Guid("7731CB31-E063-4CC8-BCD2-D151D6BC8F43")]
+    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+    public interface IArrayTesting
+    {
+        double Mean_Byte_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray)] byte[] d);
+        double Mean_Short_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray)] short[] d);
+        double Mean_UShort_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray)] ushort[] d);
+        double Mean_Int_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray)] int[] d);
+        double Mean_UInt_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray)] uint[] d);
+        double Mean_Long_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray)] long[] d);
+        double Mean_ULong_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray)] ulong[] d);
+        double Mean_Float_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray)] float[] d);
+        double Mean_Double_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray)] double[] d);
+
+        double Mean_Byte_LP_PostLen([MarshalAs(UnmanagedType.LPArray)] byte[] d, int len);
+        double Mean_Short_LP_PostLen([MarshalAs(UnmanagedType.LPArray)] short[] d, int len);
+        double Mean_UShort_LP_PostLen([MarshalAs(UnmanagedType.LPArray)] ushort[] d, int len);
+        double Mean_Int_LP_PostLen([MarshalAs(UnmanagedType.LPArray)] int[] d, int len);
+        double Mean_UInt_LP_PostLen([MarshalAs(UnmanagedType.LPArray)] uint[] d, int len);
+        double Mean_Long_LP_PostLen([MarshalAs(UnmanagedType.LPArray)] long[] d, int len);
+        double Mean_ULong_LP_PostLen([MarshalAs(UnmanagedType.LPArray)] ulong[] d, int len);
+        double Mean_Float_LP_PostLen([MarshalAs(UnmanagedType.LPArray)] float[] d, int len);
+        double Mean_Double_LP_PostLen([MarshalAs(UnmanagedType.LPArray)] double[] d, int len);
+
+        double Mean_Byte_SafeArray_OutLen([MarshalAs(UnmanagedType.SafeArray)] byte[] d, out int len);
+        double Mean_Short_SafeArray_OutLen([MarshalAs(UnmanagedType.SafeArray)] short[] d, out int len);
+        double Mean_UShort_SafeArray_OutLen([MarshalAs(UnmanagedType.SafeArray)] ushort[] d, out int len);
+        double Mean_Int_SafeArray_OutLen([MarshalAs(UnmanagedType.SafeArray)] int[] d, out int len);
+        double Mean_UInt_SafeArray_OutLen([MarshalAs(UnmanagedType.SafeArray)] uint[] d, out int len);
+        double Mean_Long_SafeArray_OutLen([MarshalAs(UnmanagedType.SafeArray)] long[] d, out int len);
+        double Mean_ULong_SafeArray_OutLen([MarshalAs(UnmanagedType.SafeArray)] ulong[] d, out int len);
+        double Mean_Float_SafeArray_OutLen([MarshalAs(UnmanagedType.SafeArray)] float[] d, out int len);
+        double Mean_Double_SafeArray_OutLen([MarshalAs(UnmanagedType.SafeArray)] double[] d, out int len);
+    }
+
+    [ComVisible(true)]
+    [Guid("7044C5C0-C6C6-4713-9294-B4A4E86D58CC")]
+    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+    public interface IStringTesting
+    {
+        [return: MarshalAs(UnmanagedType.LPStr)]
+        string Add_LPStr(
+            [MarshalAs(UnmanagedType.LPStr)] string a,
+            [MarshalAs(UnmanagedType.LPStr)] string b);
+
+        [return: MarshalAs(UnmanagedType.LPWStr)]
+        string Add_LPWStr(
+            [MarshalAs(UnmanagedType.LPWStr)] string a,
+            [MarshalAs(UnmanagedType.LPWStr)] string b);
+
+        [return: MarshalAs(UnmanagedType.BStr)]
+        string Add_BStr(
+            [MarshalAs(UnmanagedType.BStr)] string a,
+            [MarshalAs(UnmanagedType.BStr)] string b);
+
+        // LPStr
+
+        [return: MarshalAs(UnmanagedType.LPStr)]
+        string Reverse_LPStr([MarshalAs(UnmanagedType.LPStr)] string a);
+
+        [return: MarshalAs(UnmanagedType.LPStr)]
+        string Reverse_LPStr_Ref([MarshalAs(UnmanagedType.LPStr)] ref string a);
+
+        [return: MarshalAs(UnmanagedType.LPStr)]
+        string Reverse_LPStr_InRef([In][MarshalAs(UnmanagedType.LPStr)] ref string a);
+
+        void Reverse_LPStr_Out([MarshalAs(UnmanagedType.LPStr)] string a, [MarshalAs(UnmanagedType.LPStr)] out string b);
+
+        void Reverse_LPStr_OutAttr([MarshalAs(UnmanagedType.LPStr)] string a, [Out][MarshalAs(UnmanagedType.LPStr)] string b);
+
+        [return: MarshalAs(UnmanagedType.LPStr)]
+        StringBuilder Reverse_SB_LPStr([MarshalAs(UnmanagedType.LPStr)] StringBuilder a);
+
+        [return: MarshalAs(UnmanagedType.LPStr)]
+        StringBuilder Reverse_SB_LPStr_Ref([MarshalAs(UnmanagedType.LPStr)] ref StringBuilder a);
+
+        [return: MarshalAs(UnmanagedType.LPStr)]
+        StringBuilder Reverse_SB_LPStr_InRef([In][MarshalAs(UnmanagedType.LPStr)] ref StringBuilder a);
+
+        void Reverse_SB_LPStr_Out([MarshalAs(UnmanagedType.LPStr)] StringBuilder a, [MarshalAs(UnmanagedType.LPStr)] out StringBuilder b);
+
+        void Reverse_SB_LPStr_OutAttr([MarshalAs(UnmanagedType.LPStr)] StringBuilder a, [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder b);
+
+        // LPWStr
+
+        [return: MarshalAs(UnmanagedType.LPWStr)]
+        string Reverse_LPWStr([MarshalAs(UnmanagedType.LPWStr)] string a);
+
+        [return: MarshalAs(UnmanagedType.LPWStr)]
+        string Reverse_LPWStr_Ref([MarshalAs(UnmanagedType.LPWStr)] ref string a);
+
+        [return: MarshalAs(UnmanagedType.LPWStr)]
+        string Reverse_LPWStr_InRef([In][MarshalAs(UnmanagedType.LPWStr)] ref string a);
+
+        void Reverse_LPWStr_Out([MarshalAs(UnmanagedType.LPWStr)] string a, [MarshalAs(UnmanagedType.LPWStr)] out string b);
+
+        void Reverse_LPWStr_OutAttr([MarshalAs(UnmanagedType.LPWStr)] string a, [Out][MarshalAs(UnmanagedType.LPWStr)] string b);
+
+        [return: MarshalAs(UnmanagedType.LPWStr)]
+        StringBuilder Reverse_SB_LPWStr([MarshalAs(UnmanagedType.LPWStr)] StringBuilder a);
+
+        [return: MarshalAs(UnmanagedType.LPWStr)]
+        StringBuilder Reverse_SB_LPWStr_Ref([MarshalAs(UnmanagedType.LPWStr)] ref StringBuilder a);
+
+        [return: MarshalAs(UnmanagedType.LPWStr)]
+        StringBuilder Reverse_SB_LPWStr_InRef([In][MarshalAs(UnmanagedType.LPWStr)] ref StringBuilder a);
+
+        void Reverse_SB_LPWStr_Out([MarshalAs(UnmanagedType.LPWStr)] StringBuilder a, [MarshalAs(UnmanagedType.LPWStr)] out StringBuilder b);
+
+        void Reverse_SB_LPWStr_OutAttr([MarshalAs(UnmanagedType.LPWStr)] StringBuilder a, [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder b);
+
+        // BSTR
+
+        [return: MarshalAs(UnmanagedType.BStr)]
+        string Reverse_BStr([MarshalAs(UnmanagedType.BStr)] string a);
+
+        [return: MarshalAs(UnmanagedType.BStr)]
+        string Reverse_BStr_Ref([MarshalAs(UnmanagedType.BStr)] ref string a);
+
+        [return: MarshalAs(UnmanagedType.BStr)]
+        string Reverse_BStr_InRef([In][MarshalAs(UnmanagedType.BStr)] ref string a);
+
+        void Reverse_BStr_Out([MarshalAs(UnmanagedType.BStr)] string a, [MarshalAs(UnmanagedType.BStr)] out string b);
+
+        void Reverse_BStr_OutAttr([MarshalAs(UnmanagedType.BStr)] string a, [Out][MarshalAs(UnmanagedType.BStr)] string b);
+    }
+
+    [ComVisible(true)]
+    [Guid("592386A5-6837-444D-9DE3-250815D18556")]
+    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+    public interface IErrorMarshalTesting
+    {
+        void Throw_HResult(int hresultToReturn);
+
+        [PreserveSig]
+        int Return_As_HResult(int hresultToReturn);
+    }
+}
+
+#pragma warning restore 618 // Must test deprecated features
diff --git a/tests/src/Interop/COM/ServerContracts/PrimitivesNativeServer.cs b/tests/src/Interop/COM/ServerContracts/PrimitivesNativeServer.cs
new file mode 100644 (file)
index 0000000..4e02880
--- /dev/null
@@ -0,0 +1,89 @@
+// 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.
+
+#pragma warning disable IDE1006 // Naming Styles
+
+namespace Server.Contract.Servers
+{
+    using System;
+    using System.Runtime.InteropServices;
+
+    /// <summary>
+    /// Managed definition of CoClass 
+    /// </summary>
+    [ComImport]
+    [CoClass(typeof(NumericTestingClass))]
+    [Guid("05655A94-A915-4926-815D-A9EA648BAAD9")]
+    internal interface NumericTesting : Server.Contract.INumericTesting
+    {
+    }
+
+    /// <summary>
+    /// Managed activation for CoClass
+    /// </summary>
+    [ComImport]
+    [Guid("53169A33-E85D-4E3C-B668-24E438D0929B")]
+    internal class NumericTestingClass
+    {
+    }
+
+    /// <summary>
+    /// Managed definition of CoClass 
+    /// </summary>
+    [ComImport]
+    [CoClass(typeof(ArrayTestingClass))]
+    [Guid("7731CB31-E063-4CC8-BCD2-D151D6BC8F43")]
+    internal interface ArrayTesting : Server.Contract.IArrayTesting
+    {
+    }
+
+    /// <summary>
+    /// Managed activation for CoClass
+    /// </summary>
+    [ComImport]
+    [Guid("B99ABE6A-DFF6-440F-BFB6-55179B8FE18E")]
+    internal class ArrayTestingClass
+    {
+    }
+
+    /// <summary>
+    /// Managed definition of CoClass 
+    /// </summary>
+    [ComImport]
+    [CoClass(typeof(StringTestingClass))]
+    [Guid("7044C5C0-C6C6-4713-9294-B4A4E86D58CC")]
+    internal interface StringTesting : Server.Contract.IStringTesting
+    {
+    }
+
+    /// <summary>
+    /// Managed activation for CoClass
+    /// </summary>
+    [ComImport]
+    [Guid("C73C83E8-51A2-47F8-9B5C-4284458E47A6")]
+    internal class StringTestingClass
+    {
+    }
+
+    /// <summary>
+    /// Managed definition of CoClass 
+    /// </summary>
+    [ComImport]
+    [CoClass(typeof(ErrorMarshalTestingClass))]
+    [Guid("592386A5-6837-444D-9DE3-250815D18556")]
+    internal interface ErrorMarshalTesting : Server.Contract.IErrorMarshalTesting
+    {
+    }
+
+    /// <summary>
+    /// Managed activation for CoClass
+    /// </summary>
+    [ComImport]
+    [Guid("71CF5C45-106C-4B32-B418-43A463C6041F")]
+    internal class ErrorMarshalTestingClass
+    {
+    }
+}
+
+#pragma warning restore IDE1006 // Naming Styles
diff --git a/tests/src/Interop/COM/ServerContracts/Server.Contracts.tlh b/tests/src/Interop/COM/ServerContracts/Server.Contracts.tlh
new file mode 100644 (file)
index 0000000..55597a9
--- /dev/null
@@ -0,0 +1,656 @@
+// Created by Microsoft (R) C/C++ Compiler
+
+#pragma once
+#pragma pack(push, 8)
+
+#include <comdef.h>
+
+//
+// Forward references and typedefs
+//
+
+struct __declspec(uuid("3b973377-8c69-4208-96c1-475da757861c"))
+/* LIBID */ __Server_Contract;
+struct __declspec(uuid("05655a94-a915-4926-815d-a9ea648baad9"))
+/* interface */ INumericTesting;
+struct __declspec(uuid("7731cb31-e063-4cc8-bcd2-d151d6bc8f43"))
+/* interface */ IArrayTesting;
+struct __declspec(uuid("7044c5c0-c6c6-4713-9294-b4a4e86d58cc"))
+/* interface */ IStringTesting;
+struct __declspec(uuid("592386a5-6837-444d-9de3-250815d18556"))
+/* interface */ IErrorMarshalTesting;
+
+//
+// Smart pointer typedef declarations
+//
+
+_COM_SMARTPTR_TYPEDEF(INumericTesting, __uuidof(INumericTesting));
+_COM_SMARTPTR_TYPEDEF(IArrayTesting, __uuidof(IArrayTesting));
+_COM_SMARTPTR_TYPEDEF(IStringTesting, __uuidof(IStringTesting));
+_COM_SMARTPTR_TYPEDEF(IErrorMarshalTesting, __uuidof(IErrorMarshalTesting));
+
+//
+// Type library items
+//
+
+struct __declspec(uuid("05655a94-a915-4926-815d-a9ea648baad9"))
+INumericTesting : IUnknown
+{
+    //
+    // Wrapper methods for error-handling
+    //
+
+    unsigned char Add_Byte (
+        unsigned char a,
+        unsigned char b );
+    short Add_Short (
+        short a,
+        short b );
+    unsigned short Add_UShort (
+        unsigned short a,
+        unsigned short b );
+    long Add_Int (
+        long a,
+        long b );
+    unsigned long Add_UInt (
+        unsigned long a,
+        unsigned long b );
+    __int64 Add_Long (
+        __int64 a,
+        __int64 b );
+    unsigned __int64 Add_ULong (
+        unsigned __int64 a,
+        unsigned __int64 b );
+    float Add_Float (
+        float a,
+        float b );
+    double Add_Double (
+        double a,
+        double b );
+    HRESULT Add_Byte_Ref (
+        unsigned char a,
+        unsigned char b,
+        unsigned char * c );
+    HRESULT Add_Short_Ref (
+        short a,
+        short b,
+        short * c );
+    HRESULT Add_UShort_Ref (
+        unsigned short a,
+        unsigned short b,
+        unsigned short * c );
+    HRESULT Add_Int_Ref (
+        long a,
+        long b,
+        long * c );
+    HRESULT Add_UInt_Ref (
+        unsigned long a,
+        unsigned long b,
+        unsigned long * c );
+    HRESULT Add_Long_Ref (
+        __int64 a,
+        __int64 b,
+        __int64 * c );
+    HRESULT Add_ULong_Ref (
+        unsigned __int64 a,
+        unsigned __int64 b,
+        unsigned __int64 * c );
+    HRESULT Add_Float_Ref (
+        float a,
+        float b,
+        float * c );
+    HRESULT Add_Double_Ref (
+        double a,
+        double b,
+        double * c );
+    HRESULT Add_Byte_Out (
+        unsigned char a,
+        unsigned char b,
+        unsigned char * c );
+    HRESULT Add_Short_Out (
+        short a,
+        short b,
+        short * c );
+    HRESULT Add_UShort_Out (
+        unsigned short a,
+        unsigned short b,
+        unsigned short * c );
+    HRESULT Add_Int_Out (
+        long a,
+        long b,
+        long * c );
+    HRESULT Add_UInt_Out (
+        unsigned long a,
+        unsigned long b,
+        unsigned long * c );
+    HRESULT Add_Long_Out (
+        __int64 a,
+        __int64 b,
+        __int64 * c );
+    HRESULT Add_ULong_Out (
+        unsigned __int64 a,
+        unsigned __int64 b,
+        unsigned __int64 * c );
+    HRESULT Add_Float_Out (
+        float a,
+        float b,
+        float * c );
+    HRESULT Add_Double_Out (
+        double a,
+        double b,
+        double * c );
+
+    //
+    // Raw methods provided by interface
+    //
+
+      virtual HRESULT __stdcall raw_Add_Byte (
+        /*[in]*/ unsigned char a,
+        /*[in]*/ unsigned char b,
+        /*[out,retval]*/ unsigned char * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Add_Short (
+        /*[in]*/ short a,
+        /*[in]*/ short b,
+        /*[out,retval]*/ short * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Add_UShort (
+        /*[in]*/ unsigned short a,
+        /*[in]*/ unsigned short b,
+        /*[out,retval]*/ unsigned short * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Add_Int (
+        /*[in]*/ long a,
+        /*[in]*/ long b,
+        /*[out,retval]*/ long * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Add_UInt (
+        /*[in]*/ unsigned long a,
+        /*[in]*/ unsigned long b,
+        /*[out,retval]*/ unsigned long * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Add_Long (
+        /*[in]*/ __int64 a,
+        /*[in]*/ __int64 b,
+        /*[out,retval]*/ __int64 * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Add_ULong (
+        /*[in]*/ unsigned __int64 a,
+        /*[in]*/ unsigned __int64 b,
+        /*[out,retval]*/ unsigned __int64 * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Add_Float (
+        /*[in]*/ float a,
+        /*[in]*/ float b,
+        /*[out,retval]*/ float * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Add_Double (
+        /*[in]*/ double a,
+        /*[in]*/ double b,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Add_Byte_Ref (
+        /*[in]*/ unsigned char a,
+        /*[in]*/ unsigned char b,
+        /*[in,out]*/ unsigned char * c ) = 0;
+      virtual HRESULT __stdcall raw_Add_Short_Ref (
+        /*[in]*/ short a,
+        /*[in]*/ short b,
+        /*[in,out]*/ short * c ) = 0;
+      virtual HRESULT __stdcall raw_Add_UShort_Ref (
+        /*[in]*/ unsigned short a,
+        /*[in]*/ unsigned short b,
+        /*[in,out]*/ unsigned short * c ) = 0;
+      virtual HRESULT __stdcall raw_Add_Int_Ref (
+        /*[in]*/ long a,
+        /*[in]*/ long b,
+        /*[in,out]*/ long * c ) = 0;
+      virtual HRESULT __stdcall raw_Add_UInt_Ref (
+        /*[in]*/ unsigned long a,
+        /*[in]*/ unsigned long b,
+        /*[in,out]*/ unsigned long * c ) = 0;
+      virtual HRESULT __stdcall raw_Add_Long_Ref (
+        /*[in]*/ __int64 a,
+        /*[in]*/ __int64 b,
+        /*[in,out]*/ __int64 * c ) = 0;
+      virtual HRESULT __stdcall raw_Add_ULong_Ref (
+        /*[in]*/ unsigned __int64 a,
+        /*[in]*/ unsigned __int64 b,
+        /*[in,out]*/ unsigned __int64 * c ) = 0;
+      virtual HRESULT __stdcall raw_Add_Float_Ref (
+        /*[in]*/ float a,
+        /*[in]*/ float b,
+        /*[in,out]*/ float * c ) = 0;
+      virtual HRESULT __stdcall raw_Add_Double_Ref (
+        /*[in]*/ double a,
+        /*[in]*/ double b,
+        /*[in,out]*/ double * c ) = 0;
+      virtual HRESULT __stdcall raw_Add_Byte_Out (
+        /*[in]*/ unsigned char a,
+        /*[in]*/ unsigned char b,
+        /*[out]*/ unsigned char * c ) = 0;
+      virtual HRESULT __stdcall raw_Add_Short_Out (
+        /*[in]*/ short a,
+        /*[in]*/ short b,
+        /*[out]*/ short * c ) = 0;
+      virtual HRESULT __stdcall raw_Add_UShort_Out (
+        /*[in]*/ unsigned short a,
+        /*[in]*/ unsigned short b,
+        /*[out]*/ unsigned short * c ) = 0;
+      virtual HRESULT __stdcall raw_Add_Int_Out (
+        /*[in]*/ long a,
+        /*[in]*/ long b,
+        /*[out]*/ long * c ) = 0;
+      virtual HRESULT __stdcall raw_Add_UInt_Out (
+        /*[in]*/ unsigned long a,
+        /*[in]*/ unsigned long b,
+        /*[out]*/ unsigned long * c ) = 0;
+      virtual HRESULT __stdcall raw_Add_Long_Out (
+        /*[in]*/ __int64 a,
+        /*[in]*/ __int64 b,
+        /*[out]*/ __int64 * c ) = 0;
+      virtual HRESULT __stdcall raw_Add_ULong_Out (
+        /*[in]*/ unsigned __int64 a,
+        /*[in]*/ unsigned __int64 b,
+        /*[out]*/ unsigned __int64 * c ) = 0;
+      virtual HRESULT __stdcall raw_Add_Float_Out (
+        /*[in]*/ float a,
+        /*[in]*/ float b,
+        /*[out]*/ float * c ) = 0;
+      virtual HRESULT __stdcall raw_Add_Double_Out (
+        /*[in]*/ double a,
+        /*[in]*/ double b,
+        /*[out]*/ double * c ) = 0;
+};
+
+struct __declspec(uuid("7731cb31-e063-4cc8-bcd2-d151d6bc8f43"))
+IArrayTesting : IUnknown
+{
+    //
+    // Wrapper methods for error-handling
+    //
+
+    double Mean_Byte_LP_PreLen (
+        long len,
+        unsigned char * d );
+    double Mean_Short_LP_PreLen (
+        long len,
+        short * d );
+    double Mean_UShort_LP_PreLen (
+        long len,
+        unsigned short * d );
+    double Mean_Int_LP_PreLen (
+        long len,
+        long * d );
+    double Mean_UInt_LP_PreLen (
+        long len,
+        unsigned long * d );
+    double Mean_Long_LP_PreLen (
+        long len,
+        __int64 * d );
+    double Mean_ULong_LP_PreLen (
+        long len,
+        unsigned __int64 * d );
+    double Mean_Float_LP_PreLen (
+        long len,
+        float * d );
+    double Mean_Double_LP_PreLen (
+        long len,
+        double * d );
+    double Mean_Byte_LP_PostLen (
+        unsigned char * d,
+        long len );
+    double Mean_Short_LP_PostLen (
+        short * d,
+        long len );
+    double Mean_UShort_LP_PostLen (
+        unsigned short * d,
+        long len );
+    double Mean_Int_LP_PostLen (
+        long * d,
+        long len );
+    double Mean_UInt_LP_PostLen (
+        unsigned long * d,
+        long len );
+    double Mean_Long_LP_PostLen (
+        __int64 * d,
+        long len );
+    double Mean_ULong_LP_PostLen (
+        unsigned __int64 * d,
+        long len );
+    double Mean_Float_LP_PostLen (
+        float * d,
+        long len );
+    double Mean_Double_LP_PostLen (
+        double * d,
+        long len );
+    double Mean_Byte_SafeArray_OutLen (
+        SAFEARRAY * d,
+        long * len );
+    double Mean_Short_SafeArray_OutLen (
+        SAFEARRAY * d,
+        long * len );
+    double Mean_UShort_SafeArray_OutLen (
+        SAFEARRAY * d,
+        long * len );
+    double Mean_Int_SafeArray_OutLen (
+        SAFEARRAY * d,
+        long * len );
+    double Mean_UInt_SafeArray_OutLen (
+        SAFEARRAY * d,
+        long * len );
+    double Mean_Long_SafeArray_OutLen (
+        SAFEARRAY * d,
+        long * len );
+    double Mean_ULong_SafeArray_OutLen (
+        SAFEARRAY * d,
+        long * len );
+    double Mean_Float_SafeArray_OutLen (
+        SAFEARRAY * d,
+        long * len );
+    double Mean_Double_SafeArray_OutLen (
+        SAFEARRAY * d,
+        long * len );
+
+    //
+    // Raw methods provided by interface
+    //
+
+      virtual HRESULT __stdcall raw_Mean_Byte_LP_PreLen (
+        /*[in]*/ long len,
+        /*[in]*/ unsigned char * d,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_Short_LP_PreLen (
+        /*[in]*/ long len,
+        /*[in]*/ short * d,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_UShort_LP_PreLen (
+        /*[in]*/ long len,
+        /*[in]*/ unsigned short * d,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_Int_LP_PreLen (
+        /*[in]*/ long len,
+        /*[in]*/ long * d,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_UInt_LP_PreLen (
+        /*[in]*/ long len,
+        /*[in]*/ unsigned long * d,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_Long_LP_PreLen (
+        /*[in]*/ long len,
+        /*[in]*/ __int64 * d,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_ULong_LP_PreLen (
+        /*[in]*/ long len,
+        /*[in]*/ unsigned __int64 * d,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_Float_LP_PreLen (
+        /*[in]*/ long len,
+        /*[in]*/ float * d,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_Double_LP_PreLen (
+        /*[in]*/ long len,
+        /*[in]*/ double * d,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_Byte_LP_PostLen (
+        /*[in]*/ unsigned char * d,
+        /*[in]*/ long len,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_Short_LP_PostLen (
+        /*[in]*/ short * d,
+        /*[in]*/ long len,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_UShort_LP_PostLen (
+        /*[in]*/ unsigned short * d,
+        /*[in]*/ long len,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_Int_LP_PostLen (
+        /*[in]*/ long * d,
+        /*[in]*/ long len,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_UInt_LP_PostLen (
+        /*[in]*/ unsigned long * d,
+        /*[in]*/ long len,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_Long_LP_PostLen (
+        /*[in]*/ __int64 * d,
+        /*[in]*/ long len,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_ULong_LP_PostLen (
+        /*[in]*/ unsigned __int64 * d,
+        /*[in]*/ long len,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_Float_LP_PostLen (
+        /*[in]*/ float * d,
+        /*[in]*/ long len,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_Double_LP_PostLen (
+        /*[in]*/ double * d,
+        /*[in]*/ long len,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_Byte_SafeArray_OutLen (
+        /*[in]*/ SAFEARRAY * d,
+        /*[out]*/ long * len,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_Short_SafeArray_OutLen (
+        /*[in]*/ SAFEARRAY * d,
+        /*[out]*/ long * len,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_UShort_SafeArray_OutLen (
+        /*[in]*/ SAFEARRAY * d,
+        /*[out]*/ long * len,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_Int_SafeArray_OutLen (
+        /*[in]*/ SAFEARRAY * d,
+        /*[out]*/ long * len,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_UInt_SafeArray_OutLen (
+        /*[in]*/ SAFEARRAY * d,
+        /*[out]*/ long * len,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_Long_SafeArray_OutLen (
+        /*[in]*/ SAFEARRAY * d,
+        /*[out]*/ long * len,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_ULong_SafeArray_OutLen (
+        /*[in]*/ SAFEARRAY * d,
+        /*[out]*/ long * len,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_Float_SafeArray_OutLen (
+        /*[in]*/ SAFEARRAY * d,
+        /*[out]*/ long * len,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Mean_Double_SafeArray_OutLen (
+        /*[in]*/ SAFEARRAY * d,
+        /*[out]*/ long * len,
+        /*[out,retval]*/ double * pRetVal ) = 0;
+};
+
+struct __declspec(uuid("7044c5c0-c6c6-4713-9294-b4a4e86d58cc"))
+IStringTesting : IUnknown
+{
+    //
+    // Wrapper methods for error-handling
+    //
+
+    LPSTR Add_LPStr (
+        LPSTR a,
+        LPSTR b );
+    LPWSTR Add_LPWStr (
+        LPWSTR a,
+        LPWSTR b );
+    _bstr_t Add_BStr (
+        _bstr_t a,
+        _bstr_t b );
+    LPSTR Reverse_LPStr (
+        LPSTR a );
+    LPSTR Reverse_LPStr_Ref (
+        LPSTR * a );
+    LPSTR Reverse_LPStr_InRef (
+        LPSTR * a );
+    HRESULT Reverse_LPStr_Out (
+        LPSTR a,
+        LPSTR * b );
+    HRESULT Reverse_LPStr_OutAttr (
+        LPSTR a,
+        LPSTR b );
+    LPSTR Reverse_SB_LPStr (
+        LPSTR a );
+    LPSTR Reverse_SB_LPStr_Ref (
+        LPSTR * a );
+    LPSTR Reverse_SB_LPStr_InRef (
+        LPSTR * a );
+    HRESULT Reverse_SB_LPStr_Out (
+        LPSTR a,
+        LPSTR * b );
+    HRESULT Reverse_SB_LPStr_OutAttr (
+        LPSTR a,
+        LPSTR b );
+    LPWSTR Reverse_LPWStr (
+        LPWSTR a );
+    LPWSTR Reverse_LPWStr_Ref (
+        LPWSTR * a );
+    LPWSTR Reverse_LPWStr_InRef (
+        LPWSTR * a );
+    HRESULT Reverse_LPWStr_Out (
+        LPWSTR a,
+        LPWSTR * b );
+    HRESULT Reverse_LPWStr_OutAttr (
+        LPWSTR a,
+        LPWSTR b );
+    LPWSTR Reverse_SB_LPWStr (
+        LPWSTR a );
+    LPWSTR Reverse_SB_LPWStr_Ref (
+        LPWSTR * a );
+    LPWSTR Reverse_SB_LPWStr_InRef (
+        LPWSTR * a );
+    HRESULT Reverse_SB_LPWStr_Out (
+        LPWSTR a,
+        LPWSTR * b );
+    HRESULT Reverse_SB_LPWStr_OutAttr (
+        LPWSTR a,
+        LPWSTR b );
+    _bstr_t Reverse_BStr (
+        _bstr_t a );
+    _bstr_t Reverse_BStr_Ref (
+        BSTR * a );
+    _bstr_t Reverse_BStr_InRef (
+        BSTR * a );
+    HRESULT Reverse_BStr_Out (
+        _bstr_t a,
+        BSTR * b );
+    HRESULT Reverse_BStr_OutAttr (
+        _bstr_t a,
+        _bstr_t b );
+
+    //
+    // Raw methods provided by interface
+    //
+
+      virtual HRESULT __stdcall raw_Add_LPStr (
+        /*[in]*/ LPSTR a,
+        /*[in]*/ LPSTR b,
+        /*[out,retval]*/ LPSTR * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Add_LPWStr (
+        /*[in]*/ LPWSTR a,
+        /*[in]*/ LPWSTR b,
+        /*[out,retval]*/ LPWSTR * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Add_BStr (
+        /*[in]*/ BSTR a,
+        /*[in]*/ BSTR b,
+        /*[out,retval]*/ BSTR * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_LPStr (
+        /*[in]*/ LPSTR a,
+        /*[out,retval]*/ LPSTR * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_LPStr_Ref (
+        /*[in,out]*/ LPSTR * a,
+        /*[out,retval]*/ LPSTR * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_LPStr_InRef (
+        /*[in]*/ LPSTR * a,
+        /*[out,retval]*/ LPSTR * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_LPStr_Out (
+        /*[in]*/ LPSTR a,
+        /*[out]*/ LPSTR * b ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_LPStr_OutAttr (
+        /*[in]*/ LPSTR a,
+        /*[out]*/ LPSTR b ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_SB_LPStr (
+        /*[in,out]*/ LPSTR a,
+        /*[out,retval]*/ LPSTR * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_SB_LPStr_Ref (
+        /*[in,out]*/ LPSTR * a,
+        /*[out,retval]*/ LPSTR * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_SB_LPStr_InRef (
+        /*[in]*/ LPSTR * a,
+        /*[out,retval]*/ LPSTR * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_SB_LPStr_Out (
+        /*[in,out]*/ LPSTR a,
+        /*[out]*/ LPSTR * b ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_SB_LPStr_OutAttr (
+        /*[in,out]*/ LPSTR a,
+        /*[out]*/ LPSTR b ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_LPWStr (
+        /*[in]*/ LPWSTR a,
+        /*[out,retval]*/ LPWSTR * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_LPWStr_Ref (
+        /*[in,out]*/ LPWSTR * a,
+        /*[out,retval]*/ LPWSTR * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_LPWStr_InRef (
+        /*[in]*/ LPWSTR * a,
+        /*[out,retval]*/ LPWSTR * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_LPWStr_Out (
+        /*[in]*/ LPWSTR a,
+        /*[out]*/ LPWSTR * b ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_LPWStr_OutAttr (
+        /*[in]*/ LPWSTR a,
+        /*[out]*/ LPWSTR b ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_SB_LPWStr (
+        /*[in,out]*/ LPWSTR a,
+        /*[out,retval]*/ LPWSTR * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_SB_LPWStr_Ref (
+        /*[in,out]*/ LPWSTR * a,
+        /*[out,retval]*/ LPWSTR * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_SB_LPWStr_InRef (
+        /*[in]*/ LPWSTR * a,
+        /*[out,retval]*/ LPWSTR * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_SB_LPWStr_Out (
+        /*[in,out]*/ LPWSTR a,
+        /*[out]*/ LPWSTR * b ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_SB_LPWStr_OutAttr (
+        /*[in,out]*/ LPWSTR a,
+        /*[out]*/ LPWSTR b ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_BStr (
+        /*[in]*/ BSTR a,
+        /*[out,retval]*/ BSTR * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_BStr_Ref (
+        /*[in,out]*/ BSTR * a,
+        /*[out,retval]*/ BSTR * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_BStr_InRef (
+        /*[in]*/ BSTR * a,
+        /*[out,retval]*/ BSTR * pRetVal ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_BStr_Out (
+        /*[in]*/ BSTR a,
+        /*[out]*/ BSTR * b ) = 0;
+      virtual HRESULT __stdcall raw_Reverse_BStr_OutAttr (
+        /*[in]*/ BSTR a,
+        /*[out]*/ BSTR b ) = 0;
+};
+
+struct __declspec(uuid("592386a5-6837-444d-9de3-250815d18556"))
+IErrorMarshalTesting : IUnknown
+{
+    //
+    // Wrapper methods for error-handling
+    //
+
+    HRESULT Throw_HResult (
+        long hresultToReturn );
+
+    //
+    // Raw methods provided by interface
+    //
+
+      virtual HRESULT __stdcall raw_Throw_HResult (
+        /*[in]*/ long hresultToReturn ) = 0;
+      virtual long __stdcall Return_As_HResult (
+        /*[in]*/ long hresultToReturn ) = 0;
+};
+
+//
+// Wrapper method implementations
+//
+
+#include "Server.Contracts.tli"
+
+#pragma pack(pop)
diff --git a/tests/src/Interop/COM/ServerContracts/Server.Contracts.tli b/tests/src/Interop/COM/ServerContracts/Server.Contracts.tli
new file mode 100644 (file)
index 0000000..a419c65
--- /dev/null
@@ -0,0 +1,571 @@
+// Created by Microsoft (R) C/C++ Compiler
+
+#pragma once
+
+//
+// interface INumericTesting wrapper method implementations
+//
+
+inline unsigned char INumericTesting::Add_Byte ( unsigned char a, unsigned char b ) {
+    unsigned char _result = 0;
+    HRESULT _hr = raw_Add_Byte(a, b, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline short INumericTesting::Add_Short ( short a, short b ) {
+    short _result = 0;
+    HRESULT _hr = raw_Add_Short(a, b, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline unsigned short INumericTesting::Add_UShort ( unsigned short a, unsigned short b ) {
+    unsigned short _result = 0;
+    HRESULT _hr = raw_Add_UShort(a, b, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline long INumericTesting::Add_Int ( long a, long b ) {
+    long _result = 0;
+    HRESULT _hr = raw_Add_Int(a, b, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline unsigned long INumericTesting::Add_UInt ( unsigned long a, unsigned long b ) {
+    unsigned long _result = 0;
+    HRESULT _hr = raw_Add_UInt(a, b, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline __int64 INumericTesting::Add_Long ( __int64 a, __int64 b ) {
+    __int64 _result = 0;
+    HRESULT _hr = raw_Add_Long(a, b, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline unsigned __int64 INumericTesting::Add_ULong ( unsigned __int64 a, unsigned __int64 b ) {
+    unsigned __int64 _result = 0;
+    HRESULT _hr = raw_Add_ULong(a, b, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline float INumericTesting::Add_Float ( float a, float b ) {
+    float _result = 0;
+    HRESULT _hr = raw_Add_Float(a, b, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double INumericTesting::Add_Double ( double a, double b ) {
+    double _result = 0;
+    HRESULT _hr = raw_Add_Double(a, b, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline HRESULT INumericTesting::Add_Byte_Ref ( unsigned char a, unsigned char b, unsigned char * c ) {
+    HRESULT _hr = raw_Add_Byte_Ref(a, b, c);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline HRESULT INumericTesting::Add_Short_Ref ( short a, short b, short * c ) {
+    HRESULT _hr = raw_Add_Short_Ref(a, b, c);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline HRESULT INumericTesting::Add_UShort_Ref ( unsigned short a, unsigned short b, unsigned short * c ) {
+    HRESULT _hr = raw_Add_UShort_Ref(a, b, c);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline HRESULT INumericTesting::Add_Int_Ref ( long a, long b, long * c ) {
+    HRESULT _hr = raw_Add_Int_Ref(a, b, c);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline HRESULT INumericTesting::Add_UInt_Ref ( unsigned long a, unsigned long b, unsigned long * c ) {
+    HRESULT _hr = raw_Add_UInt_Ref(a, b, c);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline HRESULT INumericTesting::Add_Long_Ref ( __int64 a, __int64 b, __int64 * c ) {
+    HRESULT _hr = raw_Add_Long_Ref(a, b, c);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline HRESULT INumericTesting::Add_ULong_Ref ( unsigned __int64 a, unsigned __int64 b, unsigned __int64 * c ) {
+    HRESULT _hr = raw_Add_ULong_Ref(a, b, c);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline HRESULT INumericTesting::Add_Float_Ref ( float a, float b, float * c ) {
+    HRESULT _hr = raw_Add_Float_Ref(a, b, c);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline HRESULT INumericTesting::Add_Double_Ref ( double a, double b, double * c ) {
+    HRESULT _hr = raw_Add_Double_Ref(a, b, c);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline HRESULT INumericTesting::Add_Byte_Out ( unsigned char a, unsigned char b, unsigned char * c ) {
+    HRESULT _hr = raw_Add_Byte_Out(a, b, c);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline HRESULT INumericTesting::Add_Short_Out ( short a, short b, short * c ) {
+    HRESULT _hr = raw_Add_Short_Out(a, b, c);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline HRESULT INumericTesting::Add_UShort_Out ( unsigned short a, unsigned short b, unsigned short * c ) {
+    HRESULT _hr = raw_Add_UShort_Out(a, b, c);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline HRESULT INumericTesting::Add_Int_Out ( long a, long b, long * c ) {
+    HRESULT _hr = raw_Add_Int_Out(a, b, c);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline HRESULT INumericTesting::Add_UInt_Out ( unsigned long a, unsigned long b, unsigned long * c ) {
+    HRESULT _hr = raw_Add_UInt_Out(a, b, c);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline HRESULT INumericTesting::Add_Long_Out ( __int64 a, __int64 b, __int64 * c ) {
+    HRESULT _hr = raw_Add_Long_Out(a, b, c);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline HRESULT INumericTesting::Add_ULong_Out ( unsigned __int64 a, unsigned __int64 b, unsigned __int64 * c ) {
+    HRESULT _hr = raw_Add_ULong_Out(a, b, c);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline HRESULT INumericTesting::Add_Float_Out ( float a, float b, float * c ) {
+    HRESULT _hr = raw_Add_Float_Out(a, b, c);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline HRESULT INumericTesting::Add_Double_Out ( double a, double b, double * c ) {
+    HRESULT _hr = raw_Add_Double_Out(a, b, c);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+//
+// interface IArrayTesting wrapper method implementations
+//
+
+inline double IArrayTesting::Mean_Byte_LP_PreLen ( long len, unsigned char * d ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_Byte_LP_PreLen(len, d, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_Short_LP_PreLen ( long len, short * d ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_Short_LP_PreLen(len, d, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_UShort_LP_PreLen ( long len, unsigned short * d ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_UShort_LP_PreLen(len, d, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_Int_LP_PreLen ( long len, long * d ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_Int_LP_PreLen(len, d, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_UInt_LP_PreLen ( long len, unsigned long * d ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_UInt_LP_PreLen(len, d, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_Long_LP_PreLen ( long len, __int64 * d ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_Long_LP_PreLen(len, d, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_ULong_LP_PreLen ( long len, unsigned __int64 * d ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_ULong_LP_PreLen(len, d, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_Float_LP_PreLen ( long len, float * d ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_Float_LP_PreLen(len, d, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_Double_LP_PreLen ( long len, double * d ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_Double_LP_PreLen(len, d, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_Byte_LP_PostLen ( unsigned char * d, long len ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_Byte_LP_PostLen(d, len, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_Short_LP_PostLen ( short * d, long len ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_Short_LP_PostLen(d, len, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_UShort_LP_PostLen ( unsigned short * d, long len ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_UShort_LP_PostLen(d, len, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_Int_LP_PostLen ( long * d, long len ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_Int_LP_PostLen(d, len, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_UInt_LP_PostLen ( unsigned long * d, long len ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_UInt_LP_PostLen(d, len, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_Long_LP_PostLen ( __int64 * d, long len ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_Long_LP_PostLen(d, len, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_ULong_LP_PostLen ( unsigned __int64 * d, long len ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_ULong_LP_PostLen(d, len, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_Float_LP_PostLen ( float * d, long len ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_Float_LP_PostLen(d, len, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_Double_LP_PostLen ( double * d, long len ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_Double_LP_PostLen(d, len, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_Byte_SafeArray_OutLen ( SAFEARRAY * d, long * len ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_Byte_SafeArray_OutLen(d, len, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_Short_SafeArray_OutLen ( SAFEARRAY * d, long * len ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_Short_SafeArray_OutLen(d, len, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_UShort_SafeArray_OutLen ( SAFEARRAY * d, long * len ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_UShort_SafeArray_OutLen(d, len, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_Int_SafeArray_OutLen ( SAFEARRAY * d, long * len ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_Int_SafeArray_OutLen(d, len, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_UInt_SafeArray_OutLen ( SAFEARRAY * d, long * len ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_UInt_SafeArray_OutLen(d, len, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_Long_SafeArray_OutLen ( SAFEARRAY * d, long * len ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_Long_SafeArray_OutLen(d, len, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_ULong_SafeArray_OutLen ( SAFEARRAY * d, long * len ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_ULong_SafeArray_OutLen(d, len, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_Float_SafeArray_OutLen ( SAFEARRAY * d, long * len ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_Float_SafeArray_OutLen(d, len, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline double IArrayTesting::Mean_Double_SafeArray_OutLen ( SAFEARRAY * d, long * len ) {
+    double _result = 0;
+    HRESULT _hr = raw_Mean_Double_SafeArray_OutLen(d, len, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+//
+// interface IStringTesting wrapper method implementations
+//
+
+inline LPSTR IStringTesting::Add_LPStr ( LPSTR a, LPSTR b ) {
+    LPSTR _result = 0;
+    HRESULT _hr = raw_Add_LPStr(a, b, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline LPWSTR IStringTesting::Add_LPWStr ( LPWSTR a, LPWSTR b ) {
+    LPWSTR _result = 0;
+    HRESULT _hr = raw_Add_LPWStr(a, b, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline _bstr_t IStringTesting::Add_BStr ( _bstr_t a, _bstr_t b ) {
+    BSTR _result = 0;
+    HRESULT _hr = raw_Add_BStr(a, b, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _bstr_t(_result, false);
+}
+
+inline LPSTR IStringTesting::Reverse_LPStr ( LPSTR a ) {
+    LPSTR _result = 0;
+    HRESULT _hr = raw_Reverse_LPStr(a, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline LPSTR IStringTesting::Reverse_LPStr_Ref ( LPSTR * a ) {
+    LPSTR _result = 0;
+    HRESULT _hr = raw_Reverse_LPStr_Ref(a, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline LPSTR IStringTesting::Reverse_LPStr_InRef ( LPSTR * a ) {
+    LPSTR _result = 0;
+    HRESULT _hr = raw_Reverse_LPStr_InRef(a, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline HRESULT IStringTesting::Reverse_LPStr_Out ( LPSTR a, LPSTR * b ) {
+    HRESULT _hr = raw_Reverse_LPStr_Out(a, b);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline HRESULT IStringTesting::Reverse_LPStr_OutAttr ( LPSTR a, LPSTR b ) {
+    HRESULT _hr = raw_Reverse_LPStr_OutAttr(a, b);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline LPSTR IStringTesting::Reverse_SB_LPStr ( LPSTR a ) {
+    LPSTR _result = 0;
+    HRESULT _hr = raw_Reverse_SB_LPStr(a, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline LPSTR IStringTesting::Reverse_SB_LPStr_Ref ( LPSTR * a ) {
+    LPSTR _result = 0;
+    HRESULT _hr = raw_Reverse_SB_LPStr_Ref(a, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline LPSTR IStringTesting::Reverse_SB_LPStr_InRef ( LPSTR * a ) {
+    LPSTR _result = 0;
+    HRESULT _hr = raw_Reverse_SB_LPStr_InRef(a, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline HRESULT IStringTesting::Reverse_SB_LPStr_Out ( LPSTR a, LPSTR * b ) {
+    HRESULT _hr = raw_Reverse_SB_LPStr_Out(a, b);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline HRESULT IStringTesting::Reverse_SB_LPStr_OutAttr ( LPSTR a, LPSTR b ) {
+    HRESULT _hr = raw_Reverse_SB_LPStr_OutAttr(a, b);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline LPWSTR IStringTesting::Reverse_LPWStr ( LPWSTR a ) {
+    LPWSTR _result = 0;
+    HRESULT _hr = raw_Reverse_LPWStr(a, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline LPWSTR IStringTesting::Reverse_LPWStr_Ref ( LPWSTR * a ) {
+    LPWSTR _result = 0;
+    HRESULT _hr = raw_Reverse_LPWStr_Ref(a, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline LPWSTR IStringTesting::Reverse_LPWStr_InRef ( LPWSTR * a ) {
+    LPWSTR _result = 0;
+    HRESULT _hr = raw_Reverse_LPWStr_InRef(a, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline HRESULT IStringTesting::Reverse_LPWStr_Out ( LPWSTR a, LPWSTR * b ) {
+    HRESULT _hr = raw_Reverse_LPWStr_Out(a, b);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline HRESULT IStringTesting::Reverse_LPWStr_OutAttr ( LPWSTR a, LPWSTR b ) {
+    HRESULT _hr = raw_Reverse_LPWStr_OutAttr(a, b);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline LPWSTR IStringTesting::Reverse_SB_LPWStr ( LPWSTR a ) {
+    LPWSTR _result = 0;
+    HRESULT _hr = raw_Reverse_SB_LPWStr(a, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline LPWSTR IStringTesting::Reverse_SB_LPWStr_Ref ( LPWSTR * a ) {
+    LPWSTR _result = 0;
+    HRESULT _hr = raw_Reverse_SB_LPWStr_Ref(a, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline LPWSTR IStringTesting::Reverse_SB_LPWStr_InRef ( LPWSTR * a ) {
+    LPWSTR _result = 0;
+    HRESULT _hr = raw_Reverse_SB_LPWStr_InRef(a, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _result;
+}
+
+inline HRESULT IStringTesting::Reverse_SB_LPWStr_Out ( LPWSTR a, LPWSTR * b ) {
+    HRESULT _hr = raw_Reverse_SB_LPWStr_Out(a, b);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline HRESULT IStringTesting::Reverse_SB_LPWStr_OutAttr ( LPWSTR a, LPWSTR b ) {
+    HRESULT _hr = raw_Reverse_SB_LPWStr_OutAttr(a, b);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline _bstr_t IStringTesting::Reverse_BStr ( _bstr_t a ) {
+    BSTR _result = 0;
+    HRESULT _hr = raw_Reverse_BStr(a, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _bstr_t(_result, false);
+}
+
+inline _bstr_t IStringTesting::Reverse_BStr_Ref ( BSTR * a ) {
+    BSTR _result = 0;
+    HRESULT _hr = raw_Reverse_BStr_Ref(a, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _bstr_t(_result, false);
+}
+
+inline _bstr_t IStringTesting::Reverse_BStr_InRef ( BSTR * a ) {
+    BSTR _result = 0;
+    HRESULT _hr = raw_Reverse_BStr_InRef(a, &_result);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _bstr_t(_result, false);
+}
+
+inline HRESULT IStringTesting::Reverse_BStr_Out ( _bstr_t a, BSTR * b ) {
+    HRESULT _hr = raw_Reverse_BStr_Out(a, b);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+inline HRESULT IStringTesting::Reverse_BStr_OutAttr ( _bstr_t a, _bstr_t b ) {
+    HRESULT _hr = raw_Reverse_BStr_OutAttr(a, b);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
+
+//
+// interface IErrorMarshalTesting wrapper method implementations
+//
+
+inline HRESULT IErrorMarshalTesting::Throw_HResult ( long hresultToReturn ) {
+    HRESULT _hr = raw_Throw_HResult(hresultToReturn);
+    if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
+    return _hr;
+}
diff --git a/tests/src/Interop/COM/ServerContracts/readme.md b/tests/src/Interop/COM/ServerContracts/readme.md
new file mode 100644 (file)
index 0000000..347c7fc
--- /dev/null
@@ -0,0 +1,9 @@
+## Server Contracts
+
+This directory contains the API contracts for the testing of .NET COM interop. The contract is defined in C# to the degree that the [TlbExp.exe](https://docs.microsoft.com/en-us/dotnet/framework/tools/tlbexp-exe-type-library-exporter) tool can be used to generate a TLB that can then be used by the Microsoft VC++ compiler to generate the `tlh` and `tli` files. This is a manual process at the moment, but as more support is added to CoreCLR, this may change.
+
+The process to create a TLB and update the native contracts are as follows:
+
+1) Take the `Primitives.cs` file and create a DLL using a SDK project.
+1) Use the .NET Framework [TlbExp.exe](https://docs.microsoft.com/en-us/dotnet/framework/tools/tlbexp-exe-type-library-exporter) to create a `tlb` based on the DLL previously compiled.
+1) Using the Microsoft VC++ compiler consume the `tlb` using the [`#import`](https://msdn.microsoft.com/en-us/library/8etzzkb6.aspx) directive (See commented out line in `Servers.h`). The compiler will generate two files (`tlh` and `tli`). The files in this directory can then be updated.
\ No newline at end of file
diff --git a/tests/src/Interop/ClassicCOM/CMakeLists.txt b/tests/src/Interop/ClassicCOM/CMakeLists.txt
deleted file mode 100644 (file)
index d3416dd..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-cmake_minimum_required (VERSION 2.6)
-project (ClassicCOMNative)
-include_directories(${INC_PLATFORM_DIR})
-set(SOURCES ClassicCOMNative.cpp)
-
-# add the executable
-add_library (ClassicCOMNative SHARED ${SOURCES})
-target_link_libraries(ClassicCOMNative ${LINK_LIBRARIES_ADDITIONAL}) 
-
-# add the install targets
-install (TARGETS ClassicCOMNative DESTINATION bin)
-
-
diff --git a/tests/src/Interop/ClassicCOM/COMLib.cs b/tests/src/Interop/ClassicCOM/COMLib.cs
deleted file mode 100644 (file)
index fba866c..0000000
+++ /dev/null
@@ -1,34 +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.Text;
-using System.Security;
-using System.Runtime.InteropServices;
-
-public class COMLib
-{
-    [Guid("00020404-0000-0000-C000-000000000046")]
-    [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
-    [ComImport]
-    public interface IEnumVARIANT
-    {
-        [PreserveSig]
-        int Next(int celt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0), Out] object[] rgVar, IntPtr pceltFetched);
-
-        [PreserveSig]
-        int Skip(int celt);
-
-        [PreserveSig]
-        int Reset();
-
-        IEnumVARIANT Clone();
-    }
-
-    [ComImport]
-    [Guid("78A51822-51F4-11D0-8F20-00805F2CD064")]
-    public class ProcessDebugManager
-    {
-    }
-}
diff --git a/tests/src/Interop/ClassicCOM/COMLib.csproj b/tests/src/Interop/ClassicCOM/COMLib.csproj
deleted file mode 100644 (file)
index 1f289d6..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-<?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" />
-  <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <AssemblyName>COMLib</AssemblyName>
-    <SchemaVersion>2.0</SchemaVersion>
-    <ProjectGuid>{5FEE5C46-8DD9-49FA-BDC1-AF22867A0704}</ProjectGuid>
-    <OutputType>library</OutputType>
-    <ProjectTypeGuids>{CDC3DF7E-04B4-4464-9A02-7E2B0FAB586A};{68EC03EE-C9EE-47FD-AA08-A954EB2D9816}</ProjectTypeGuids>
-    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
-    <DefineConstants>$(DefineConstants);STATIC</DefineConstants>
-  </PropertyGroup>
-  <!-- Default configurations to help VS understand the configurations -->
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
-  </PropertyGroup>
-  <ItemGroup>
-    <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
-      <Visible>False</Visible>
-    </CodeAnalysisDependentAssemblyPaths>
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="COMLib.cs" />
-  </ItemGroup>
-  <ItemGroup>
-    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
-  </ItemGroup>
-  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
diff --git a/tests/src/Interop/ClassicCOM/ClassicCOMNative.cpp b/tests/src/Interop/ClassicCOM/ClassicCOMNative.cpp
deleted file mode 100644 (file)
index 962313c..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-//
-
-#include <xplatform.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-extern "C" DLL_EXPORT void PassObjectToNative(void * ptr)
-{
-    // TODO: Add check
-}
-
-extern "C" DLL_EXPORT void PassObjectArrayToNative(void ** pptr)
-{
-    // TODO: Add check
-}
-
-extern "C" DLL_EXPORT void GetObjectFromNative(void ** pptr)
-{
-    *pptr = NULL;
-    // TODO: Add check
-}
-
-extern "C" DLL_EXPORT void GetObjectFromNativeAsRef(void ** pptr)
-{
-    // TODO: Add check
-}
\ No newline at end of file
diff --git a/tests/src/Interop/ClassicCOM/ClassicCOMUnitTest.cs b/tests/src/Interop/ClassicCOM/ClassicCOMUnitTest.cs
deleted file mode 100644 (file)
index 530f02c..0000000
+++ /dev/null
@@ -1,255 +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.
-//
-
-//
-//  Adding tests for Classic COM code coverage
-//
-
-using System;
-using System.Text;
-using System.Security;
-using System.Reflection;
-using System.Runtime.InteropServices;
-using TestLibrary;
-
-public class ClassicCOMUnitTest
-{
-    /// <summary>
-    /// Try to reflect load ComImport Types by enumerate
-    /// </summary>
-    /// <returns></returns>
-    static bool RelectionLoad()
-    {
-        try
-        {
-            Console.WriteLine("Scenario: RelectionLoad");
-            var asm = Assembly.LoadFrom("COMLib.dll");
-            foreach (Type t in asm.GetTypes())
-            {
-                Console.WriteLine(t.Name);
-            }
-
-            return true;
-        }
-        catch (Exception e)
-        {
-            Console.WriteLine("Caught unexpected exception: " + e);
-            return false;
-        }
-    }
-
-    /// <summary>
-    /// Try to test Type.IsCOMObject
-    /// </summary>
-    /// <returns></returns>
-    static bool TypeIsComObject()
-    {
-        try
-        {
-            Console.WriteLine("Scenario: TypeIsComObject");
-            Type classType = typeof(COMLib2.ContextMenu);
-            if (!classType.IsCOMObject)
-            {
-                Console.WriteLine("ComImport Class's IsCOMObject should return true");
-                return false;
-            }
-
-            Type interfaceType = typeof(COMLib2.IEnumVARIANT);
-            if (interfaceType.IsCOMObject)
-            {
-                Console.WriteLine("ComImport interface's IsCOMObject should return false");
-                return false;
-            }
-
-            return true;
-        }
-        catch (Exception e)
-        {
-            Console.WriteLine("Caught unexpected exception: " + e);
-            return false;
-        }
-    }
-
-    /// <summary>
-    /// Try to create COM instance
-    /// </summary>
-    /// <returns></returns>
-    static bool AcivateCOMType()
-    {
-        try
-        {
-            Console.WriteLine("Scenario: AcivateCOMType");
-            COMLib2.ContextMenu contextMenu = (COMLib2.ContextMenu)Activator.CreateInstance(typeof(COMLib2.ContextMenu));
-            
-            // Linux should throw PlatformNotSupportedException
-            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
-            {
-                return false;
-            }
-            
-            if (contextMenu == null)
-            {
-                Console.WriteLine("AcivateCOMType failed");
-                return false;
-            }
-
-            return true;
-        }
-        catch (System.Reflection.TargetInvocationException e)
-        {
-            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && e.InnerException is PlatformNotSupportedException)
-            {
-                return true;
-            }
-            
-            Console.WriteLine("Caught unexpected PlatformNotSupportedException: " + e);
-            return false;
-        }
-        catch(System.Runtime.InteropServices.COMException e)
-        {
-            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
-            {
-                return true;
-            }
-            
-            Console.WriteLine("Caught unexpected COMException: " + e);
-            return false;
-        }
-        catch (Exception e)
-        {
-            Console.WriteLine("Caught unexpected exception: " + e);
-            return false;
-        }
-    }
-
-    [DllImport("ClassicCOMNative.dll")]
-    extern static void PassObjectToNative([In, MarshalAs( UnmanagedType.Interface)] object o);
-    
-    [DllImport("ClassicCOMNative.dll")]
-    extern static void PassObjectArrayToNative([In,Out] object[] o);
-    
-    [DllImport("ClassicCOMNative.dll")]
-    extern static void GetObjectFromNative(out object o);
-    
-    [DllImport("ClassicCOMNative.dll")]
-    extern static void GetObjectFromNativeAsRef(ref object o);
-    
-    /// <summary>
-    /// Try to Marshal COM Type across managed-native boundary
-    /// </summary>
-    /// <returns></returns>
-    static bool MarshalCOMType()
-    {
-        Console.WriteLine("Scenario: MarshalCOMType");
-        try
-        {
-            object o = new object();
-            PassObjectToNative(o);
-        }
-        catch (System.Runtime.InteropServices.MarshalDirectiveException e) 
-        { 
-            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) 
-            { 
-                return true; 
-            } 
-            Console.WriteLine("Caught unexpected MarshalDirectiveException: " + e); 
-            return false; 
-        }
-        catch (Exception e)
-        {
-            Console.WriteLine("Caught unexpected exception in PassObjectToNative: " + e);
-            return false;
-        }
-        
-        try
-        {
-            object [] oa = new object[2];
-            PassObjectArrayToNative(oa);
-        }
-        catch (Exception e)
-        {
-            Console.WriteLine("Caught unexpected exception in GetObjectFromNative: " + e);
-            return false;
-        }
-        
-        
-        try
-        {
-            object o; 
-            GetObjectFromNative(out o);
-        }
-        catch (Exception e)
-        {
-            Console.WriteLine("Caught unexpected exception in GetObjectFromNative: " + e);
-            return false;
-        }
-        
-        try
-        {
-            object o = new object(); 
-            GetObjectFromNativeAsRef(ref o);
-        }
-        catch (Exception e)
-        {
-            Console.WriteLine("Caught unexpected exception in GetObjectFromNativeAsRef: " + e);
-            return false;
-        }
-
-        return true;
-    }
-
-    /// <summary>
-    /// Try to call Marshal API for COM Types
-    /// </summary>
-    /// <returns></returns>
-    static bool MarshalAPI()
-    {
-        Console.WriteLine("Scenario: MarshalAPI");
-        // MarshalAPI
-        if (Marshal.AreComObjectsAvailableForCleanup())
-        {
-            Console.WriteLine("AreComObjectsAvailableForCleanup should return false");
-            return false;
-        }
-        return true;
-    }
-
-    [System.Security.SecuritySafeCritical]
-    static int Main()
-    {
-        int failures = 0;
-        if (!RelectionLoad())
-        {
-            Console.WriteLine("RelectionLoad Failed");
-            failures++;
-        }
-
-        if (!TypeIsComObject())
-        {
-            Console.WriteLine("TypeIsComObject Failed");
-            failures++;
-        }
-
-        if (!AcivateCOMType())
-        {
-            Console.WriteLine("AcivateCOMType Failed");
-            failures++;
-        }
-
-        if (!MarshalCOMType())
-        {
-            Console.WriteLine("MarshalCOMType Failed");
-            failures++;
-        }
-
-        if (!MarshalAPI())
-        {
-            Console.WriteLine("MarshalAPI Failed");
-            failures++;
-        }
-
-        return failures > 0 ? 101 : 100;
-    }
-}
index b285680..d4928b2 100644 (file)
@@ -123,10 +123,12 @@ CoreMangLib/cti/system/reflection/emit/DynMethodJumpStubTests/DynMethodJumpStubT
 CoreMangLib/system/collections/generic/hashset/Regression_Dev10_609271/Regression_Dev10_609271.sh
 CoreMangLib/system/collections/generic/hashset/Regression_Dev10_624201/Regression_Dev10_624201.sh
 GC/Coverage/smalloom/smalloom.sh
+Interop/COM/NETClients/Primitives/NETClientPrimitives/NETClientPrimitives.sh
 Interop/MarshalAPI/GetNativeVariantForObject/GetNativeVariantForObject/GetNativeVariantForObject.sh
 Interop/MarshalAPI/GetObjectForNativeVariant/GetObjectForNativeVariant/GetObjectForNativeVariant.sh
 Interop/MarshalAPI/GetObjectsForNativeVariants/GetObjectsForNativeVariants/GetObjectsForNativeVariants.sh
 Interop/MarshalAPI/IUnknown/IUnknownTest/IUnknownTest.sh
+Interop/SizeConst/SizeConstTest/SizeConstTest.sh
 JIT/Directed/coverage/oldtests/callipinvoke/callipinvoke.sh
 JIT/Directed/coverage/oldtests/Desktop/callipinvoke_il_d/callipinvoke_il_d.sh
 JIT/Directed/coverage/oldtests/Desktop/callipinvoke_il_r/callipinvoke_il_r.sh
@@ -340,5 +342,4 @@ JIT/Regression/VS-ia64-JIT/V2.0-RTM/b286991/b286991/b286991.sh
 managed/Compilation/Compilation/Compilation.sh
 readytorun/r2rdump/R2RDumpTest/R2RDumpTest.sh
 Regressions/coreclr/0584/Test584/Test584.sh
-Interop/SizeConst/SizeConstTest/SizeConstTest.sh
 tracing/eventsource/eventpipeandetw/eventpipeandetw/eventpipeandetw.sh