From 5848876564fe7e064a90a6c6a8aef2872543c070 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Mon, 10 Sep 2018 17:24:49 -0700 Subject: [PATCH] Basic implementation for testing of COM activation of a .NET class (dotnet/coreclr#19760) * Rough outline of managed implementation for COM activation in SPCL * Add property for finding interop common Add property to exclude default assertion file Display exe ExeLaunchProgram class is going to launch * Add a native client for the NETServer Consume the ExeLauncherProgram.cs file as a wrapper for the native test * Update COM Server contracts to use 'int' instead of 'long' * Complete symmetric testing coverage for .NET server and native client. * Block EXE launch from running on non-Windows machines * Disable COM testing in helix since it has issues on Windows Nano and there is no way to determine that is the platform. * Update tests based on CLSID mapping manifest approach. Commit migrated from https://github.com/dotnet/coreclr/commit/fc3378095f04946815e627a5ab70b528a898abe6 --- src/coreclr/build-test.cmd | 6 +- .../System.Private.CoreLib.csproj | 1 + .../System/Runtime/InteropServices/ComActivator.cs | 261 +++++++++++++ .../src/System/Runtime/InteropServices/Marshal.cs | 7 +- src/coreclr/src/coreclr/hosts/CMakeLists.txt | 1 + .../src/coreclr/hosts/coreshim/CMakeLists.txt | 25 ++ .../src/coreclr/hosts/coreshim/ComActivation.cpp | 91 +++++ .../src/coreclr/hosts/coreshim/CoreShim.cpp | 293 ++++++++++++++ src/coreclr/src/coreclr/hosts/coreshim/CoreShim.h | 179 +++++++++ src/coreclr/src/coreclr/hosts/coreshim/Exports.def | 3 + src/coreclr/tests/issues.targets | 14 +- .../tests/src/CLRTest.Execute.Batch.targets | 6 + src/coreclr/tests/src/Interop/CMakeLists.txt | 1 + .../src/Interop/COM/Activator/Activator.csproj | 29 ++ .../tests/src/Interop/COM/Activator/Program.cs | 67 ++++ .../src/Interop/COM/NETServer/ArrayTesting.cs | 241 ++++++++++++ .../Interop/COM/NETServer/ErrorMarshalTesting.cs | 28 ++ .../src/Interop/COM/NETServer/NETServer.csproj | 16 +- .../src/Interop/COM/NETServer/NumericTesting.cs | 193 ++++++++++ .../src/Interop/COM/NETServer/StringTesting.cs | 191 ++++++++++ .../Interop/COM/NativeClients/Primitives.csproj | 17 + .../COM/NativeClients/Primitives/App.manifest | 17 + .../COM/NativeClients/Primitives/ArrayTests.cpp | 318 ++++++++++++++++ .../COM/NativeClients/Primitives/CMakeLists.txt | 23 ++ .../COM/NativeClients/Primitives/Client.cpp | 45 +++ .../COM/NativeClients/Primitives/ClientTests.h | 70 ++++ .../NativeClients/Primitives/CoreShim.X.manifest | 28 ++ .../COM/NativeClients/Primitives/ErrorTests.cpp | 68 ++++ .../COM/NativeClients/Primitives/NumericTests.cpp | 227 +++++++++++ .../COM/NativeClients/Primitives/StringTests.cpp | 422 +++++++++++++++++++++ .../src/Interop/COM/NativeServer/ArrayTesting.h | 64 ++-- .../Interop/COM/NativeServer/ErrorMarshalTesting.h | 7 +- .../src/Interop/COM/NativeServer/NumericTesting.h | 36 +- .../tests/src/Interop/COM/NativeServer/Servers.h | 24 ++ .../src/Interop/COM/ServerContracts/Primitives.cs | 38 +- .../COM/ServerContracts/Server.Contracts.tlh | 204 +++++----- .../COM/ServerContracts/Server.Contracts.tli | 72 ++-- .../tests/src/Interop/Interop.settings.targets | 3 +- .../tests/src/Interop/common/ExeLauncherProgram.cs | 69 ++++ src/coreclr/tests/src/Interop/common/xplatform.h | 23 ++ 40 files changed, 3196 insertions(+), 232 deletions(-) create mode 100644 src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComActivator.cs create mode 100644 src/coreclr/src/coreclr/hosts/coreshim/CMakeLists.txt create mode 100644 src/coreclr/src/coreclr/hosts/coreshim/ComActivation.cpp create mode 100644 src/coreclr/src/coreclr/hosts/coreshim/CoreShim.cpp create mode 100644 src/coreclr/src/coreclr/hosts/coreshim/CoreShim.h create mode 100644 src/coreclr/src/coreclr/hosts/coreshim/Exports.def create mode 100644 src/coreclr/tests/src/Interop/COM/Activator/Activator.csproj create mode 100644 src/coreclr/tests/src/Interop/COM/Activator/Program.cs create mode 100644 src/coreclr/tests/src/Interop/COM/NETServer/ArrayTesting.cs create mode 100644 src/coreclr/tests/src/Interop/COM/NETServer/ErrorMarshalTesting.cs create mode 100644 src/coreclr/tests/src/Interop/COM/NETServer/NumericTesting.cs create mode 100644 src/coreclr/tests/src/Interop/COM/NETServer/StringTesting.cs create mode 100644 src/coreclr/tests/src/Interop/COM/NativeClients/Primitives.csproj create mode 100644 src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/App.manifest create mode 100644 src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/ArrayTests.cpp create mode 100644 src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/CMakeLists.txt create mode 100644 src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/Client.cpp create mode 100644 src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/ClientTests.h create mode 100644 src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/CoreShim.X.manifest create mode 100644 src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/ErrorTests.cpp create mode 100644 src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/NumericTests.cpp create mode 100644 src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/StringTests.cpp create mode 100644 src/coreclr/tests/src/Interop/common/ExeLauncherProgram.cs diff --git a/src/coreclr/build-test.cmd b/src/coreclr/build-test.cmd index 361a3f8..c0f45b1 100644 --- a/src/coreclr/build-test.cmd +++ b/src/coreclr/build-test.cmd @@ -324,7 +324,8 @@ for /l %%G in (1, 1, %__BuildLoopCount%) do ( set __MsbuildErr=/flp2:ErrorsOnly;LogFile="%__BuildErr%";Append=!__AppendToLog! set TestBuildSlice=%%G - call %__DotnetHost% msbuild %__ProjectDir%\tests\build.proj !__MsbuildLog! !__MsbuildWrn! !__MsbuildErr! %__msbuildArgs% %__BuildAgainstPackagesMsbuildArg% !__PriorityMsbuildArg! %__UnprocessedBuildArgs% + echo Running: msbuild %__ProjectDir%\tests\build.proj !__MsbuildLog! !__MsbuildWrn! !__MsbuildErr! %__msbuildArgs% %__BuildAgainstPackagesMsbuildArg% !__PriorityMsbuildArg! %__UnprocessedBuildArgs% + call msbuild %__ProjectDir%\tests\build.proj !__MsbuildLog! !__MsbuildWrn! !__MsbuildErr! %__msbuildArgs% %__BuildAgainstPackagesMsbuildArg% !__PriorityMsbuildArg! %__UnprocessedBuildArgs% if errorlevel 1 ( echo %__MsgPrefix%Error: build failed. Refer to the build log files for details: @@ -342,7 +343,8 @@ for /l %%G in (1, 1, %__BuildLoopCount%) do ( REM Check that we've built about as many tests as we expect. This is primarily intended to prevent accidental changes that cause us to build REM drastically fewer Pri-1 tests than expected. echo %__MsgPrefix%Check the managed tests build -call %__DotnetHost% msbuild %__ProjectDir%\tests\runtest.proj /t:CheckTestBuild /p:CLRTestPriorityToBuild=%__Priority% %__msbuildArgs% %__unprocessedBuildArgs% +echo Running: msbuild %__ProjectDir%\tests\runtest.proj /t:CheckTestBuild /p:CLRTestPriorityToBuild=%__Priority% %__msbuildArgs% %__unprocessedBuildArgs% +call msbuild %__ProjectDir%\tests\runtest.proj /t:CheckTestBuild /p:CLRTestPriorityToBuild=%__Priority% %__msbuildArgs% %__unprocessedBuildArgs% if errorlevel 1 ( echo %__MsgPrefix%Error: build failed. exit /b 1 diff --git a/src/coreclr/src/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/src/System.Private.CoreLib/System.Private.CoreLib.csproj index 30b5b2b..74f04d8 100644 --- a/src/coreclr/src/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/coreclr/src/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -158,6 +158,7 @@ + diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComActivator.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComActivator.cs new file mode 100644 index 0000000..785e9ac --- /dev/null +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComActivator.cs @@ -0,0 +1,261 @@ +// 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.Diagnostics; +using System.IO; +using System.Reflection; + +namespace System.Runtime.InteropServices +{ + [ComImport] + [ComVisible(false)] + [Guid("00000001-0000-0000-C000-000000000046")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IClassFactory + { + void CreateInstance( + [MarshalAs(UnmanagedType.Interface)] object pUnkOuter, + ref Guid riid, + [MarshalAs(UnmanagedType.Interface)] out object ppvObject); + + void LockServer([MarshalAs(UnmanagedType.Bool)] bool fLock); + } + + [StructLayout(LayoutKind.Sequential)] + internal struct LICINFO + { + public int cbLicInfo; + + [MarshalAs(UnmanagedType.Bool)] + public bool fRuntimeKeyAvail; + + [MarshalAs(UnmanagedType.Bool)] + public bool fLicVerified; + } + + [ComImport] + [ComVisible(false)] + [Guid("B196B28F-BAB4-101A-B69C-00AA00341D07")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + internal interface IClassFactory2 : IClassFactory + { + new void CreateInstance( + [MarshalAs(UnmanagedType.Interface)] object pUnkOuter, + ref Guid riid, + [MarshalAs(UnmanagedType.Interface)] out object ppvObject); + + new void LockServer([MarshalAs(UnmanagedType.Bool)] bool fLock); + + void GetLicInfo(ref LICINFO pLicInfo); + + void RequestLicKey( + int dwReserved, + [MarshalAs(UnmanagedType.BStr)] out string pBstrKey); + + void CreateInstanceLic( + [MarshalAs(UnmanagedType.Interface)] object pUnkOuter, + [MarshalAs(UnmanagedType.Interface)] object pUnkReserved, + ref Guid riid, + [MarshalAs(UnmanagedType.BStr)] string bstrKey, + [MarshalAs(UnmanagedType.Interface)] out object ppvObject); + } + + [StructLayout(LayoutKind.Sequential)] + public struct ComActivationContext + { + public Guid ClassId; + public Guid InterfaceId; + public string AssemblyName; + public string TypeName; + } + + [StructLayout(LayoutKind.Sequential)] + public struct ComActivationContextInternal + { + public Guid ClassId; + public Guid InterfaceId; + public IntPtr AssemblyNameBuffer; + public IntPtr TypeNameBuffer; + public IntPtr ClassFactoryDest; + } + + public static class ComActivator + { + /// + /// Entry point for unmanaged COM activation API from managed code + /// + /// Reference to a instance + public static object GetClassFactoryForType(ComActivationContext cxt) + { + if (cxt.InterfaceId != typeof(IClassFactory).GUID + && cxt.InterfaceId != typeof(IClassFactory2).GUID) + { + throw new NotSupportedException(); + } + + Type classType = FindClassType(cxt.ClassId, cxt.AssemblyName, cxt.TypeName); + return new BasicClassFactory(cxt.ClassId, classType); + } + + /// + /// Internal entry point for unmanaged COM activation API from native code + /// + /// Reference to a instance + public static int GetClassFactoryForTypeInternal(ref ComActivationContextInternal cxtInt) + { + if (IsLoggingEnabled()) + { + Log( +$@"{nameof(GetClassFactoryForTypeInternal)} arguments: + {cxtInt.ClassId} + {cxtInt.InterfaceId} + 0x{cxtInt.AssemblyNameBuffer.ToInt64():x} + 0x{cxtInt.TypeNameBuffer.ToInt64():x} + 0x{cxtInt.ClassFactoryDest.ToInt64():x}"); + } + + try + { + var cxt = new ComActivationContext() + { + ClassId = cxtInt.ClassId, + InterfaceId = cxtInt.InterfaceId, + AssemblyName = Marshal.PtrToStringUTF8(cxtInt.AssemblyNameBuffer), + TypeName = Marshal.PtrToStringUTF8(cxtInt.TypeNameBuffer) + }; + + object cf = GetClassFactoryForType(cxt); + IntPtr nativeIUnknown = Marshal.GetIUnknownForObject(cf); + Marshal.WriteIntPtr(cxtInt.ClassFactoryDest, nativeIUnknown); + } + catch (Exception e) + { + return e.HResult; + } + + return 0; + } + + private static bool IsLoggingEnabled() + { +#if COM_ACTIVATOR_DEBUG + return true; +#else + return false; +#endif + } + + private static void Log(string fmt, params object[] args) + { + // [TODO] Use FrameworkEventSource in release builds + + Debug.WriteLine(fmt, args); + } + + private static Type FindClassType(Guid clsid, string assemblyName, string typeName) + { + try + { + Assembly assem = Assembly.LoadFrom(assemblyName); + Type t = assem.GetType(typeName); + if (t != null) + { + return t; + } + } + catch (Exception e) + { + if (IsLoggingEnabled()) + { + Log($"COM Activation of {clsid} failed. {e}"); + } + } + + const int CLASS_E_CLASSNOTAVAILABLE = unchecked((int)0x80040111); + throw new COMException(string.Empty, CLASS_E_CLASSNOTAVAILABLE); + } + + [ComVisible(true)] + internal class BasicClassFactory : IClassFactory2 + { + private readonly Guid classId; + private readonly Type classType; + + public BasicClassFactory(Guid clsid, Type classType) + { + this.classId = clsid; + this.classType = classType; + } + + public void CreateInstance( + [MarshalAs(UnmanagedType.Interface)] object pUnkOuter, + ref Guid riid, + [MarshalAs(UnmanagedType.Interface)] out object ppvObject) + { + if (riid != Marshal.IID_IUnknown) + { + bool found = false; + + // Verify the class implements the desired interface + foreach (Type i in this.classType.GetInterfaces()) + { + if (i.GUID == riid) + { + found = true; + break; + } + } + + if (!found) + { + // E_NOINTERFACE + throw new InvalidCastException(); + } + } + + ppvObject = Activator.CreateInstance(this.classType); + if (pUnkOuter != null) + { + try + { + IntPtr outerPtr = Marshal.GetIUnknownForObject(pUnkOuter); + IntPtr innerPtr = Marshal.CreateAggregatedObject(outerPtr, ppvObject); + ppvObject = Marshal.GetObjectForIUnknown(innerPtr); + } + finally + { + // Decrement the above 'Marshal.GetIUnknownForObject()' + Marshal.ReleaseComObject(pUnkOuter); + } + } + } + + public void LockServer([MarshalAs(UnmanagedType.Bool)] bool fLock) + { + // nop + } + + public void GetLicInfo(ref LICINFO pLicInfo) + { + throw new NotImplementedException(); + } + + public void RequestLicKey(int dwReserved, [MarshalAs(UnmanagedType.BStr)] out string pBstrKey) + { + throw new NotImplementedException(); + } + + public void CreateInstanceLic( + [MarshalAs(UnmanagedType.Interface)] object pUnkOuter, + [MarshalAs(UnmanagedType.Interface)] object pUnkReserved, + ref Guid riid, + [MarshalAs(UnmanagedType.BStr)] string bstrKey, + [MarshalAs(UnmanagedType.Interface)] out object ppvObject) + { + throw new NotImplementedException(); + } + } + } +} diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs index e214f1e..c4c65da 100644 --- a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs +++ b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs @@ -28,14 +28,15 @@ namespace System.Runtime.InteropServices /// public static partial class Marshal { +#if FEATURE_COMINTEROP + internal static Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046"); +#endif //FEATURE_COMINTEROP + private const int LMEM_FIXED = 0; private const int LMEM_MOVEABLE = 2; #if !FEATURE_PAL private const long HiWordMask = unchecked((long)0xffffffffffff0000L); #endif //!FEATURE_PAL -#if FEATURE_COMINTEROP - private static Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046"); -#endif //FEATURE_COMINTEROP // Win32 has the concept of Atoms, where a pointer can either be a pointer // or an int. If it's less than 64K, this is guaranteed to NOT be a diff --git a/src/coreclr/src/coreclr/hosts/CMakeLists.txt b/src/coreclr/src/coreclr/hosts/CMakeLists.txt index bb425b9..c27ba16 100644 --- a/src/coreclr/src/coreclr/hosts/CMakeLists.txt +++ b/src/coreclr/src/coreclr/hosts/CMakeLists.txt @@ -3,6 +3,7 @@ include_directories(inc) if(WIN32) add_subdirectory(corerun) add_subdirectory(coreconsole) + add_subdirectory(coreshim) else(WIN32) add_subdirectory(unixcoreruncommon) add_subdirectory(unixcorerun) diff --git a/src/coreclr/src/coreclr/hosts/coreshim/CMakeLists.txt b/src/coreclr/src/coreclr/hosts/coreshim/CMakeLists.txt new file mode 100644 index 0000000..828b91c --- /dev/null +++ b/src/coreclr/src/coreclr/hosts/coreshim/CMakeLists.txt @@ -0,0 +1,25 @@ +project (CoreShim) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CoreShim_SOURCES + CoreShim.cpp + ComActivation.cpp + Exports.def) + +add_library_clr(CoreShim + SHARED + ${CoreShim_SOURCES} +) + +target_link_libraries(CoreShim + utilcodestaticnohost + advapi32.lib + oleaut32.lib + uuid.lib + user32.lib + ${STATIC_MT_CRT_LIB} + ${STATIC_MT_VCRT_LIB} +) + +install_clr(CoreShim) \ No newline at end of file diff --git a/src/coreclr/src/coreclr/hosts/coreshim/ComActivation.cpp b/src/coreclr/src/coreclr/hosts/coreshim/ComActivation.cpp new file mode 100644 index 0000000..5df1d00 --- /dev/null +++ b/src/coreclr/src/coreclr/hosts/coreshim/ComActivation.cpp @@ -0,0 +1,91 @@ +// 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 "CoreShim.h" + +#include + +namespace +{ + HRESULT InitializeCoreClr(_In_ coreclr* inst) + { + assert(inst != nullptr); + + HRESULT hr; + + std::string tpaList; + RETURN_IF_FAILED(coreclr::CreateTpaList(tpaList)); + + const char *keys[] = + { + "APP_PATHS", + "TRUSTED_PLATFORM_ASSEMBLIES", + }; + + // [TODO] Support UNICODE app path + char wd[MAX_PATH]; + (void)::GetCurrentDirectoryA(ARRAYSIZE(wd), wd); + + const char *values[] = + { + wd, + tpaList.c_str(), + }; + + static_assert(ARRAYSIZE(keys) == ARRAYSIZE(values), "key/values pairs should match in length"); + + return inst->Initialize(ARRAYSIZE(keys), keys, values, "COMAct"); + } +} + +STDAPI DllGetClassObject( + _In_ REFCLSID rclsid, + _In_ REFIID riid, + _Outptr_ LPVOID FAR* ppv) +{ + HRESULT hr; + + coreclr *inst; + RETURN_IF_FAILED(coreclr::GetCoreClrInstance(&inst)); + + if (hr == S_OK) + RETURN_IF_FAILED(InitializeCoreClr(inst)); + + using GetClassFactoryForTypeInternal_ptr = HRESULT(*)(void *); + GetClassFactoryForTypeInternal_ptr GetClassFactoryForTypeInternal; + RETURN_IF_FAILED(inst->CreateDelegate( + "System.Private.CoreLib", + "System.Runtime.InteropServices.ComActivator", + "GetClassFactoryForTypeInternal", (void**)&GetClassFactoryForTypeInternal)); + + // Get assembly and type for activation + std::string assemblyName; + RETURN_IF_FAILED(Utility::TryGetEnvVar(COMACT_ASSEMBLYNAME_ENVVAR, assemblyName)); + + std::string typeName; + RETURN_IF_FAILED(Utility::TryGetEnvVar(COMACT_TYPENAME_ENVVAR, typeName)); + + IUnknown *ccw = nullptr; + + struct ComActivationContext + { + GUID ClassId; + GUID InterfaceId; + const void *AssemblyName; + const void *TypeName; + void **ClassFactoryDest; + } comCxt{ rclsid, riid, assemblyName.data(), typeName.data(), (void**)&ccw }; + + RETURN_IF_FAILED(GetClassFactoryForTypeInternal(&comCxt)); + assert(ccw != nullptr); + + hr = ccw->QueryInterface(riid, ppv); + ccw->Release(); + return hr; +} + +STDAPI DllCanUnloadNow(void) +{ + return S_FALSE; +} diff --git a/src/coreclr/src/coreclr/hosts/coreshim/CoreShim.cpp b/src/coreclr/src/coreclr/hosts/coreshim/CoreShim.cpp new file mode 100644 index 0000000..497c10e --- /dev/null +++ b/src/coreclr/src/coreclr/hosts/coreshim/CoreShim.cpp @@ -0,0 +1,293 @@ +// 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 "CoreShim.h" + +#include +#include +#include +#include + +namespace +{ + struct PathBuffer + { + PathBuffer() + : DefBuffer{} + , Buf{ DefBuffer } + , Len{ ARRAYSIZE(DefBuffer) } + { } + + void SetLength(_In_ DWORD len) + { + if (len > Len) + { + Buf = BigBuffer.data(); + Len = static_cast(BigBuffer.size()); + } + } + + void ExpandBuffer(_In_ DWORD factor = 2) + { + SetLength(Len * factor); + } + + operator DWORD() + { + return Len; + } + + operator WCHAR *() + { + return Buf; + } + + WCHAR DefBuffer[MAX_PATH]; + std::vector BigBuffer; + + WCHAR *Buf; + DWORD Len; + }; + + std::string GetExePath() + { + PathBuffer buffer; + DWORD len = ::GetModuleFileNameW(nullptr, buffer, buffer); + while (::GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + buffer.ExpandBuffer(); + len = ::GetModuleFileNameW(nullptr, buffer, buffer); + } + + return std::string{ buffer.Buf, buffer.Buf + len }; + } + + std::wstring GetEnvVar(_In_z_ const WCHAR *env) + { + DWORD len = ::GetEnvironmentVariableW(env, nullptr, 0); + if (len == 0) + throw __HRESULT_FROM_WIN32(ERROR_ENVVAR_NOT_FOUND); + + PathBuffer buffer; + buffer.SetLength(len); + (void)::GetEnvironmentVariableW(env, buffer, buffer); + + return static_cast(buffer.Buf); + } + + coreclr *s_CoreClrInstance; +} + +namespace Utility +{ + HRESULT TryGetEnvVar(_In_z_ const WCHAR *env, _Inout_ std::string &envVar) + { + try + { + std::wstring envVarLocal = GetEnvVar(env); + envVar = { std::begin(envVarLocal), std::end(envVarLocal) }; + } + catch (HRESULT hr) + { + return hr; + } + + return S_OK; + } +} + +HRESULT coreclr::GetCoreClrInstance(_Outptr_ coreclr **instance, _In_opt_z_ const WCHAR *path) +{ + if (s_CoreClrInstance != nullptr) + { + *instance = s_CoreClrInstance; + return S_FALSE; + } + + try + { + std::wstring pathLocal; + if (path == nullptr) + { + pathLocal = GetEnvVar(W("CORE_ROOT")); + } + else + { + pathLocal = { path }; + } + + pathLocal.append(W("\\coreclr.dll")); + + AutoModule hmod = ::LoadLibraryExW(pathLocal.c_str() , nullptr, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS); + if (hmod == nullptr) + return HRESULT_FROM_WIN32(::GetLastError()); + + s_CoreClrInstance = new coreclr{ std::move(hmod) }; + } + catch (HRESULT hr) + { + return hr; + } + catch (const std::bad_alloc&) + { + return E_OUTOFMEMORY; + } + + *instance = s_CoreClrInstance; + return S_OK; +} + +HRESULT coreclr::CreateTpaList(_Inout_ std::string &tpaList, _In_opt_z_ const WCHAR *dir) +{ + assert(tpaList.empty()); + + // Represents priority order + static const WCHAR * const tpaExtensions[] = + { + W(".ni.dll"), + W(".dll"), + W(".ni.exe"), + W(".exe"), + }; + + try + { + std::wstring w_dirLocal; + if (dir == nullptr) + { + w_dirLocal = GetEnvVar(W("CORE_ROOT")); + } + else + { + w_dirLocal = { dir }; + } + + std::string dirLocal{ std::begin(w_dirLocal), std::end(w_dirLocal) }; + w_dirLocal.append(W("\\*")); + + std::set addedAssemblies; + std::stringstream tpaStream; + + // Walk the directory for each extension separately so assembly types + // are discovered in priority order - see above. + for (int extIndex = 0; extIndex < ARRAYSIZE(tpaExtensions); extIndex++) + { + const WCHAR* ext = tpaExtensions[extIndex]; + size_t extLength = ::wcslen(ext); + + WIN32_FIND_DATAW ffd; + AutoFindFile sh = ::FindFirstFileW(w_dirLocal.c_str(), &ffd); + if (sh == nullptr) + break; + + // For all entries in the directory + do + { + // Only examine non-directory entries + if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + std::wstring filename{ ffd.cFileName }; + + // Check if the extension matches + int extPos = static_cast(filename.length() - extLength); + if ((extPos <= 0) || (filename.compare(extPos, extLength, ext) != 0)) + { + continue; + } + + std::wstring filenameWithoutExt{ filename.substr(0, extPos) }; + + // Only one type of a particular assembly instance should be inserted + // See extension list above. + if (addedAssemblies.find(filenameWithoutExt) == std::end(addedAssemblies)) + { + addedAssemblies.insert(std::move(filenameWithoutExt)); + + // [TODO] Properly convert to UTF-8 + std::string filename_utf8{ std::begin(filename), std::end(filename) }; + tpaStream << dirLocal << "\\" << filename_utf8 << ";"; + } + } + } while (::FindNextFileW(sh, &ffd) != FALSE); + } + + tpaList = tpaStream.str(); + } + catch (HRESULT hr) + { + return hr; + } + catch (const std::bad_alloc&) + { + return E_OUTOFMEMORY; + } + + return S_OK; +} + +coreclr::coreclr(_Inout_ AutoModule hmod) + : _hmod{ std::move(hmod) } + , _clrInst{ nullptr } + , _appDomainId{ std::numeric_limits::max() } +{ + _initialize = (decltype(_initialize))::GetProcAddress(_hmod, "coreclr_initialize"); + assert(_initialize != nullptr); + + _create_delegate = (decltype(_create_delegate))::GetProcAddress(_hmod, "coreclr_create_delegate"); + assert(_create_delegate != nullptr); + + _shutdown = (decltype(_shutdown))::GetProcAddress(_hmod, "coreclr_shutdown"); + assert(_shutdown != nullptr); +} + +coreclr::~coreclr() +{ + if (_clrInst != nullptr) + { + HRESULT hr = _shutdown(_clrInst, _appDomainId); + assert(SUCCEEDED(hr)); + (void)hr; + } +} + +HRESULT coreclr::Initialize( + _In_ int propertyCount, + _In_reads_(propertCount) const char **keys, + _In_reads_(propertCount) const char **values, + _In_opt_z_ const char *appDomainName) +{ + if (_clrInst != nullptr) + return __HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS); + + if (appDomainName == nullptr) + appDomainName = "CoreShim"; + + HRESULT hr; + try + { + const std::string exePath = GetExePath(); + RETURN_IF_FAILED(_initialize(exePath.c_str(), appDomainName, propertyCount, keys, values, &_clrInst, &_appDomainId)); + } + catch (const std::bad_alloc&) + { + return E_OUTOFMEMORY; + } + + return S_OK; +} + +HRESULT coreclr::CreateDelegate( + _In_z_ const char *assembly, + _In_z_ const char *type, + _In_z_ const char *method, + _Out_ void **del) +{ + if (_clrInst == nullptr) + return E_NOT_VALID_STATE; + + HRESULT hr; + RETURN_IF_FAILED(_create_delegate(_clrInst, _appDomainId, assembly, type, method, del)); + + return S_OK; +} diff --git a/src/coreclr/src/coreclr/hosts/coreshim/CoreShim.h b/src/coreclr/src/coreclr/hosts/coreshim/CoreShim.h new file mode 100644 index 0000000..dd5e9d1 --- /dev/null +++ b/src/coreclr/src/coreclr/hosts/coreshim/CoreShim.h @@ -0,0 +1,179 @@ +// 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. + +#ifndef _CORESHIM_H_ +#define _CORESHIM_H_ + +// Platform +#define NOMINMAX +#include +#include + +// Standard library +#include +#include +#include +#include + +// CoreCLR +#include +#include + +#define WCHAR wchar_t + +#define RETURN_IF_FAILED(exp) { hr = (exp); if (FAILED(hr)) { assert(false && #exp); return hr; } } + +template +< + typename T, + T DEFAULT, + void(*RELEASE)(T) +> +struct AutoClass +{ + T c; + + AutoClass() : c{ DEFAULT } + { } + + AutoClass(_Inout_ T t) : c{ t } + { } + + AutoClass(_In_ const AutoClass&) = delete; + AutoClass& operator=(_In_ const AutoClass&) = delete; + + AutoClass(_Inout_ AutoClass &&other) + : c{ other.Detach() } + { } + + AutoClass& operator=(_Inout_ AutoClass &&other) + { + Attach(other.Detach()); + } + + ~AutoClass() + { + Attach(DEFAULT); + } + + operator T() + { + return c; + } + + T* operator &() + { + return &c; + } + + void Attach(_In_opt_ T cm) + { + RELEASE(c); + c = cm; + } + + T Detach() + { + T tmp = c; + c = DEFAULT; + return tmp; + } +}; + +inline void ReleaseHandle(_In_ HANDLE h) +{ + if (h != nullptr && h != INVALID_HANDLE_VALUE) + ::CloseHandle(h); +} + +using AutoHandle = AutoClass; + +inline void ReleaseFindFile(_In_ HANDLE h) +{ + if (h != nullptr) + ::FindClose(h); +} + +using AutoFindFile = AutoClass; + +inline void ReleaseModule(_In_ HMODULE m) +{ + if (m != nullptr) + ::FreeLibrary(m); +} + +using AutoModule = AutoClass; + +namespace Utility +{ + /// + /// Get the supplied environment variable. + /// + HRESULT TryGetEnvVar(_In_z_ const WCHAR *env, _Inout_ std::string &envVar); +} + +// CoreShim environment variables used to indicate what assembly/type tuple +// to load during COM activation. +#define COMACT_ASSEMBLYNAME_ENVVAR W("CORESHIM_COMACT_ASSEMBLYNAME") +#define COMACT_TYPENAME_ENVVAR W("CORESHIM_COMACT_TYPENAME") + +// CoreCLR class to handle lifetime and provide a simpler API surface +class coreclr +{ +public: // static + /// + /// Get a CoreCLR instance + /// + /// S_OK if newly created and needs initialization, S_FALSE if already exists and no initialization needed, otherwise an error code + /// + /// If a CoreCLR instance has already been created, the existing instance is returned. + /// If the is not supplied, the 'CORE_ROOT' environment variable is used. + /// + static HRESULT GetCoreClrInstance(_Outptr_ coreclr **instance, _In_opt_z_ const WCHAR *path = nullptr); + + /// + /// Populate the supplied string with a delimited string of TPA assemblies in from the supplied directory path. + /// + /// + /// If is not supplied, the 'CORE_ROOT' environment variable is used. + /// + static HRESULT CreateTpaList(_Inout_ std::string &tpaList, _In_opt_z_ const WCHAR *dir = nullptr); + +public: + coreclr(_Inout_ AutoModule hmod); + + coreclr(_In_ const coreclr &) = delete; + coreclr& operator=(_In_ const coreclr &) = delete; + + coreclr(_Inout_ coreclr &&) = delete; + coreclr& operator=(_Inout_ coreclr &&) = delete; + + ~coreclr(); + + // See exported function 'coreclr_initialize' from coreclr library + HRESULT Initialize( + _In_ int propertyCount, + _In_reads_(propertyCount) const char **keys, + _In_reads_(propertyCount) const char **values, + _In_opt_z_ const char *appDomainName = nullptr); + + // See exported function 'coreclr_create_delegate' from coreclr library + HRESULT CreateDelegate( + _In_z_ const char *assembly, + _In_z_ const char *type, + _In_z_ const char *method, + _Out_ void **del); + +private: + AutoModule _hmod; + + void *_clrInst; + uint32_t _appDomainId; + + coreclr_initialize_ptr _initialize; + coreclr_create_delegate_ptr _create_delegate; + coreclr_shutdown_ptr _shutdown; +}; + +#endif /* _CORESHIM_H_ */ diff --git a/src/coreclr/src/coreclr/hosts/coreshim/Exports.def b/src/coreclr/src/coreclr/hosts/coreshim/Exports.def new file mode 100644 index 0000000..fbdded0 --- /dev/null +++ b/src/coreclr/src/coreclr/hosts/coreshim/Exports.def @@ -0,0 +1,3 @@ +EXPORTS + DllGetClassObject PRIVATE + DllCanUnloadNow PRIVATE \ No newline at end of file diff --git a/src/coreclr/tests/issues.targets b/src/coreclr/tests/issues.targets index 2a34642..68f7472 100644 --- a/src/coreclr/tests/issues.targets +++ b/src/coreclr/tests/issues.targets @@ -47,7 +47,11 @@ 11408 - + + + 19164 + + 19164 @@ -671,11 +675,6 @@ Varargs supported on this platform - - - - Fails on Windows.Nano - @@ -786,6 +785,9 @@ by design Windows only + + by design Windows only + needs triage diff --git a/src/coreclr/tests/src/CLRTest.Execute.Batch.targets b/src/coreclr/tests/src/CLRTest.Execute.Batch.targets index 4407010..1b1d36e 100644 --- a/src/coreclr/tests/src/CLRTest.Execute.Batch.targets +++ b/src/coreclr/tests/src/CLRTest.Execute.Batch.targets @@ -253,6 +253,11 @@ if defined DoLink ( <_CLRTestRunFile Condition="'$(CLRTestIsHosted)'=='true'">"%CORE_ROOT%\corerun.exe" + + + + + + Debug + AnyCPU + Activator + 2.0 + Exe + true + + + true + true + + + + + + + + + + + + + + diff --git a/src/coreclr/tests/src/Interop/COM/Activator/Program.cs b/src/coreclr/tests/src/Interop/COM/Activator/Program.cs new file mode 100644 index 0000000..117d55f --- /dev/null +++ b/src/coreclr/tests/src/Interop/COM/Activator/Program.cs @@ -0,0 +1,67 @@ +// 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 Activator +{ + using System; + using System.Runtime.InteropServices; + + using CoreFXTestLibrary; + + using Console = Internal.Console; + + class Program + { + static void InvalidInterfaceRequest() + { + Assert.Throws( + () => + { + var notIClassFactory = new Guid("ED53F949-63E4-43B5-A13D-5655478AADD5"); + var cxt = new ComActivationContext() + { + InterfaceId = notIClassFactory + }; + ComActivator.GetClassFactoryForType(cxt); + }, + "Non-IClassFactory request should fail"); + } + + static void ClassNotRegistered() + { + COMException e = Assert.Throws( + () => + { + var CLSID_NotRegistered = new Guid("328FF83E-3F6C-4BE9-A742-752562032925"); // Random GUID + var IID_IClassFactory = new Guid("00000001-0000-0000-C000-000000000046"); + var cxt = new ComActivationContext() + { + ClassId = CLSID_NotRegistered, + InterfaceId = IID_IClassFactory + }; + ComActivator.GetClassFactoryForType(cxt); + }, + "Class should not be found"); + + const int CLASS_E_CLASSNOTAVAILABLE = unchecked((int)0x80040111); + Assert.AreEqual(CLASS_E_CLASSNOTAVAILABLE, e.HResult, "Unexpected HRESULT"); + } + + static int Main(string[] doNotUse) + { + try + { + InvalidInterfaceRequest(); + ClassNotRegistered(); + } + catch (Exception e) + { + Console.WriteLine($"Test Failure: {e}"); + return 101; + } + + return 100; + } + } +} diff --git a/src/coreclr/tests/src/Interop/COM/NETServer/ArrayTesting.cs b/src/coreclr/tests/src/Interop/COM/NETServer/ArrayTesting.cs new file mode 100644 index 0000000..3cdd5d1 --- /dev/null +++ b/src/coreclr/tests/src/Interop/COM/NETServer/ArrayTesting.cs @@ -0,0 +1,241 @@ +// 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.Runtime.InteropServices; + +#pragma warning disable 618 // Must test deprecated features + +[ComVisible(true)] +[Guid(Server.Contract.Guids.ArrayTesting)] +public class ArrayTesting : Server.Contract.IArrayTesting +{ + private static double Mean(byte[] d) + { + double t = 0.0; + foreach (var b in d) + { + t += b; + } + return (t / d.Length); + } + private static double Mean(short[] d) + { + double t = 0.0; + foreach (var b in d) + { + t += b; + } + return (t / d.Length); + } + private static double Mean(ushort[] d) + { + double t = 0.0; + foreach (var b in d) + { + t += b; + } + return (t / d.Length); + } + private static double Mean(int[] d) + { + double t = 0.0; + foreach (var b in d) + { + t += b; + } + return (t / d.Length); + } + private static double Mean(uint[] d) + { + double t = 0.0; + foreach (var b in d) + { + t += b; + } + return (t / d.Length); + } + private static double Mean(long[] d) + { + double t = 0.0; + foreach (var b in d) + { + t += b; + } + return (t / d.Length); + } + private static double Mean(ulong[] d) + { + double t = 0.0; + foreach (var b in d) + { + t += b; + } + return (t / d.Length); + } + private static double Mean(float[] d) + { + double t = 0.0; + foreach (var b in d) + { + t += b; + } + return (t / d.Length); + } + private static double Mean(double[] d) + { + double t = 0.0; + foreach (var b in d) + { + t += b; + } + return (t / d.Length); + } + + public double Mean_Byte_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] byte[] d) + { + return Mean(d); + } + + public double Mean_Short_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] short[] d) + { + return Mean(d); + } + + public double Mean_UShort_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] ushort[] d) + { + return Mean(d); + } + + public double Mean_Int_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] int[] d) + { + return Mean(d); + } + + public double Mean_UInt_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] uint[] d) + { + return Mean(d); + } + + public double Mean_Long_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] long[] d) + { + return Mean(d); + } + + public double Mean_ULong_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] ulong[] d) + { + return Mean(d); + } + + public double Mean_Float_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] float[] d) + { + return Mean(d); + } + + public double Mean_Double_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] double[] d) + { + return Mean(d); + } + + public double Mean_Byte_LP_PostLen([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] byte[] d, int len) + { + return Mean(d); + } + + public double Mean_Short_LP_PostLen([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] short[] d, int len) + { + return Mean(d); + } + + public double Mean_UShort_LP_PostLen([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] ushort[] d, int len) + { + return Mean(d); + } + + public double Mean_Int_LP_PostLen([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] int[] d, int len) + { + return Mean(d); + } + + public double Mean_UInt_LP_PostLen([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] uint[] d, int len) + { + return Mean(d); + } + + public double Mean_Long_LP_PostLen([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] long[] d, int len) + { + return Mean(d); + } + + public double Mean_ULong_LP_PostLen([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] ulong[] d, int len) + { + return Mean(d); + } + + public double Mean_Float_LP_PostLen([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] float[] d, int len) + { + return Mean(d); + } + + public double Mean_Double_LP_PostLen([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] double[] d, int len) + { + return Mean(d); + } + + public double Mean_Byte_SafeArray_OutLen([MarshalAs(UnmanagedType.SafeArray)] byte[] d, out int len) + { + len = d.Length; + return Mean(d); + } + + public double Mean_Short_SafeArray_OutLen([MarshalAs(UnmanagedType.SafeArray)] short[] d, out int len) + { + len = d.Length; + return Mean(d); + } + + public double Mean_UShort_SafeArray_OutLen([MarshalAs(UnmanagedType.SafeArray)] ushort[] d, out int len) + { + len = d.Length; + return Mean(d); + } + + public double Mean_Int_SafeArray_OutLen([MarshalAs(UnmanagedType.SafeArray)] int[] d, out int len) + { + len = d.Length; + return Mean(d); + } + + public double Mean_UInt_SafeArray_OutLen([MarshalAs(UnmanagedType.SafeArray)] uint[] d, out int len) + { + len = d.Length; + return Mean(d); + } + + public double Mean_Long_SafeArray_OutLen([MarshalAs(UnmanagedType.SafeArray)] long[] d, out int len) + { + len = d.Length; + return Mean(d); + } + + public double Mean_ULong_SafeArray_OutLen([MarshalAs(UnmanagedType.SafeArray)] ulong[] d, out int len) + { + len = d.Length; + return Mean(d); + } + + public double Mean_Float_SafeArray_OutLen([MarshalAs(UnmanagedType.SafeArray)] float[] d, out int len) + { + len = d.Length; + return Mean(d); + } + + public double Mean_Double_SafeArray_OutLen([MarshalAs(UnmanagedType.SafeArray)] double[] d, out int len) + { + len = d.Length; + return Mean(d); + } +} + +#pragma warning restore 618 // Must test deprecated features \ No newline at end of file diff --git a/src/coreclr/tests/src/Interop/COM/NETServer/ErrorMarshalTesting.cs b/src/coreclr/tests/src/Interop/COM/NETServer/ErrorMarshalTesting.cs new file mode 100644 index 0000000..6bd104f --- /dev/null +++ b/src/coreclr/tests/src/Interop/COM/NETServer/ErrorMarshalTesting.cs @@ -0,0 +1,28 @@ +// 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.Runtime.InteropServices; + +[ComVisible(true)] +[Guid(Server.Contract.Guids.ErrorMarshalTesting)] +public class ErrorMarshalTesting : Server.Contract.IErrorMarshalTesting +{ + public void Throw_HResult(int hresultToReturn) + { + // This GetExceptionForHR call is needed to 'eat' the IErrorInfo put to TLS by + // any previous exception on this thread. If this isn't done, calls can return + // previous exception objects that have occurred. + Marshal.GetExceptionForHR(hresultToReturn); + + Exception e = Marshal.GetExceptionForHR(hresultToReturn); + throw e; + } + + [PreserveSig] + public int Return_As_HResult(int hresultToReturn) + { + return hresultToReturn; + } +} \ No newline at end of file diff --git a/src/coreclr/tests/src/Interop/COM/NETServer/NETServer.csproj b/src/coreclr/tests/src/Interop/COM/NETServer/NETServer.csproj index 214bb25..0610fca 100644 --- a/src/coreclr/tests/src/Interop/COM/NETServer/NETServer.csproj +++ b/src/coreclr/tests/src/Interop/COM/NETServer/NETServer.csproj @@ -1,6 +1,7 @@ + Debug AnyCPU @@ -9,8 +10,6 @@ {C04AB564-CC61-499D-9F4C-AA1A9FDE42C9} library {4948E98A-ECFC-4988-851E-68E1ADD2DD5A};{B850CC46-E8FB-4569-A28D-423F81E8A861} - ..\..\ - $(DefineConstants);STATIC @@ -18,16 +17,13 @@ - - False - - - + + + + + - - - \ No newline at end of file diff --git a/src/coreclr/tests/src/Interop/COM/NETServer/NumericTesting.cs b/src/coreclr/tests/src/Interop/COM/NETServer/NumericTesting.cs new file mode 100644 index 0000000..c6b1163 --- /dev/null +++ b/src/coreclr/tests/src/Interop/COM/NETServer/NumericTesting.cs @@ -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. + +using System; +using System.Runtime.InteropServices; + +#pragma warning disable 618 // Must test deprecated features + +[ComVisible(true)] +[Guid(Server.Contract.Guids.NumericTesting)] +public class NumericTesting : Server.Contract.INumericTesting +{ + public byte Add_Byte(byte a, byte b) + { + return (byte)(a + b); + } + + public short Add_Short(short a, short b) + { + return (short)(a + b); + } + + public ushort Add_UShort(ushort a, ushort b) + { + return (ushort)(a + b); + } + + public int Add_Int(int a, int b) + { + return a + b; + } + + public uint Add_UInt(uint a, uint b) + { + return a + b; + } + + public long Add_Long(long a, long b) + { + return a + b; + } + + public ulong Add_ULong(ulong a, ulong b) + { + return a + b; + } + + public float Add_Float(float a, float b) + { + return a + b; + } + + public double Add_Double(double a, double b) + { + return a + b; + } + + public void Add_Byte_Ref(byte a, byte b, ref byte c) + { + if (c != byte.MaxValue) + { + throw new Exception(); + } + + c = (byte)(a + b); + } + + public void Add_Short_Ref(short a, short b, ref short c) + { + if (c != short.MaxValue) + { + throw new Exception(); + } + + c = (short)(a + b); + } + + public void Add_UShort_Ref(ushort a, ushort b, ref ushort c) + { + if (c != ushort.MaxValue) + { + throw new Exception(); + } + + c = (ushort)(a + b); + } + + public void Add_Int_Ref(int a, int b, ref int c) + { + if (c != int.MaxValue) + { + throw new Exception(); + } + + c = a + b; + } + + public void Add_UInt_Ref(uint a, uint b, ref uint c) + { + if (c != uint.MaxValue) + { + throw new Exception(); + } + + c = a + b; + } + + public void Add_Long_Ref(long a, long b, ref long c) + { + if (c != long.MaxValue) + { + throw new Exception(); + } + + c = a + b; + } + + public void Add_ULong_Ref(ulong a, ulong b, ref ulong c) + { + if (c != ulong.MaxValue) + { + throw new Exception(); + } + + c = a + b; + } + + public void Add_Float_Ref(float a, float b, ref float c) + { + if (c != float.MaxValue) + { + throw new Exception(); + } + + c = a + b; + } + + public void Add_Double_Ref(double a, double b, ref double c) + { + if (c != double.MaxValue) + { + throw new Exception(); + } + + c = a + b; + } + + public void Add_Byte_Out(byte a, byte b, out byte c) + { + c = (byte)(a + b); + } + + public void Add_Short_Out(short a, short b, out short c) + { + c = (short)(a + b); + } + + public void Add_UShort_Out(ushort a, ushort b, out ushort c) + { + c = (ushort)(a + b); + } + + public void Add_Int_Out(int a, int b, out int c) + { + c = a + b; + } + + public void Add_UInt_Out(uint a, uint b, out uint c) + { + c = a + b; + } + + public void Add_Long_Out(long a, long b, out long c) + { + c = a + b; + } + + public void Add_ULong_Out(ulong a, ulong b, out ulong c) + { + c = a + b; + } + + public void Add_Float_Out(float a, float b, out float c) + { + c = a + b; + } + + public void Add_Double_Out(double a, double b, out double c) + { + c = a + b; + } +} \ No newline at end of file diff --git a/src/coreclr/tests/src/Interop/COM/NETServer/StringTesting.cs b/src/coreclr/tests/src/Interop/COM/NETServer/StringTesting.cs new file mode 100644 index 0000000..3a510f5 --- /dev/null +++ b/src/coreclr/tests/src/Interop/COM/NETServer/StringTesting.cs @@ -0,0 +1,191 @@ +// 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.Runtime.InteropServices; + +#pragma warning disable 618 // Must test deprecated features + +[ComVisible(true)] +[Guid(Server.Contract.Guids.StringTesting)] +public class StringTesting : Server.Contract.IStringTesting +{ + private static string Reverse(string s) + { + var chars = s.ToCharArray(); + Array.Reverse(chars); + return new string(chars); + } + + [return: MarshalAs(UnmanagedType.LPStr)] + public string Add_LPStr( + [MarshalAs(UnmanagedType.LPStr)] string a, + [MarshalAs(UnmanagedType.LPStr)] string b) + { + return a + b; + } + + [return: MarshalAs(UnmanagedType.LPWStr)] + public string Add_LPWStr( + [MarshalAs(UnmanagedType.LPWStr)] string a, + [MarshalAs(UnmanagedType.LPWStr)] string b) + { + return a + b; + } + + [return: MarshalAs(UnmanagedType.BStr)] + public string Add_BStr( + [MarshalAs(UnmanagedType.BStr)] string a, + [MarshalAs(UnmanagedType.BStr)] string b) + { + return a + b; + } + + // LPStr + + [return: MarshalAs(UnmanagedType.LPStr)] + public string Reverse_LPStr([MarshalAs(UnmanagedType.LPStr)] string a) + { + return Reverse(a); + } + + [return: MarshalAs(UnmanagedType.LPStr)] + public string Reverse_LPStr_Ref([MarshalAs(UnmanagedType.LPStr)] ref string a) + { + return Reverse(a); + } + + [return: MarshalAs(UnmanagedType.LPStr)] + public string Reverse_LPStr_InRef([In][MarshalAs(UnmanagedType.LPStr)] ref string a) + { + return Reverse(a); + } + + public void Reverse_LPStr_Out([MarshalAs(UnmanagedType.LPStr)] string a, [MarshalAs(UnmanagedType.LPStr)] out string b) + { + b = Reverse(a); + } + + public void Reverse_LPStr_OutAttr([MarshalAs(UnmanagedType.LPStr)] string a, [Out][MarshalAs(UnmanagedType.LPStr)] string b) + { + b = Reverse(a); + } + + [return: MarshalAs(UnmanagedType.LPStr)] + public StringBuilder Reverse_SB_LPStr([MarshalAs(UnmanagedType.LPStr)] StringBuilder a) + { + return new StringBuilder(Reverse(a.ToString())); + } + + [return: MarshalAs(UnmanagedType.LPStr)] + public StringBuilder Reverse_SB_LPStr_Ref([MarshalAs(UnmanagedType.LPStr)] ref StringBuilder a) + { + return new StringBuilder(Reverse(a.ToString())); + } + + [return: MarshalAs(UnmanagedType.LPStr)] + public StringBuilder Reverse_SB_LPStr_InRef([In][MarshalAs(UnmanagedType.LPStr)] ref StringBuilder a) + { + return new StringBuilder(Reverse(a.ToString())); + } + + public void Reverse_SB_LPStr_Out([MarshalAs(UnmanagedType.LPStr)] StringBuilder a, [MarshalAs(UnmanagedType.LPStr)] out StringBuilder b) + { + b = new StringBuilder(Reverse(a.ToString())); + } + + public void Reverse_SB_LPStr_OutAttr([MarshalAs(UnmanagedType.LPStr)] StringBuilder a, [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder b) + { + b.Append(Reverse(a.ToString())); + } + + // LPWStr + + [return: MarshalAs(UnmanagedType.LPWStr)] + public string Reverse_LPWStr([MarshalAs(UnmanagedType.LPWStr)] string a) + { + return Reverse(a); + } + + [return: MarshalAs(UnmanagedType.LPWStr)] + public string Reverse_LPWStr_Ref([MarshalAs(UnmanagedType.LPWStr)] ref string a) + { + return Reverse(a); + } + + [return: MarshalAs(UnmanagedType.LPWStr)] + public string Reverse_LPWStr_InRef([In][MarshalAs(UnmanagedType.LPWStr)] ref string a) + { + return Reverse(a); + } + + public void Reverse_LPWStr_Out([MarshalAs(UnmanagedType.LPWStr)] string a, [MarshalAs(UnmanagedType.LPWStr)] out string b) + { + b = Reverse(a); + } + + public void Reverse_LPWStr_OutAttr([MarshalAs(UnmanagedType.LPWStr)] string a, [Out][MarshalAs(UnmanagedType.LPWStr)] string b) + { + b = Reverse(a); + } + + [return: MarshalAs(UnmanagedType.LPWStr)] + public StringBuilder Reverse_SB_LPWStr([MarshalAs(UnmanagedType.LPWStr)] StringBuilder a) + { + return new StringBuilder(Reverse(a.ToString())); + } + + [return: MarshalAs(UnmanagedType.LPWStr)] + public StringBuilder Reverse_SB_LPWStr_Ref([MarshalAs(UnmanagedType.LPWStr)] ref StringBuilder a) + { + return new StringBuilder(Reverse(a.ToString())); + } + + [return: MarshalAs(UnmanagedType.LPWStr)] + public StringBuilder Reverse_SB_LPWStr_InRef([In][MarshalAs(UnmanagedType.LPWStr)] ref StringBuilder a) + { + return new StringBuilder(Reverse(a.ToString())); + } + + public void Reverse_SB_LPWStr_Out([MarshalAs(UnmanagedType.LPWStr)] StringBuilder a, [MarshalAs(UnmanagedType.LPWStr)] out StringBuilder b) + { + b = new StringBuilder(Reverse(a.ToString())); + } + + public void Reverse_SB_LPWStr_OutAttr([MarshalAs(UnmanagedType.LPWStr)] StringBuilder a, [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder b) + { + b.Append(Reverse(a.ToString())); + } + + // BSTR + + [return: MarshalAs(UnmanagedType.BStr)] + public string Reverse_BStr([MarshalAs(UnmanagedType.BStr)] string a) + { + return Reverse(a); + } + + [return: MarshalAs(UnmanagedType.BStr)] + public string Reverse_BStr_Ref([MarshalAs(UnmanagedType.BStr)] ref string a) + { + return Reverse(a); + } + + [return: MarshalAs(UnmanagedType.BStr)] + public string Reverse_BStr_InRef([In][MarshalAs(UnmanagedType.BStr)] ref string a) + { + return Reverse(a); + } + + public void Reverse_BStr_Out([MarshalAs(UnmanagedType.BStr)] string a, [MarshalAs(UnmanagedType.BStr)] out string b) + { + b = Reverse(a); + } + + public void Reverse_BStr_OutAttr([MarshalAs(UnmanagedType.BStr)] string a, [Out][MarshalAs(UnmanagedType.BStr)] string b) + { + b = Reverse(a); + } +} \ No newline at end of file diff --git a/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives.csproj b/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives.csproj new file mode 100644 index 0000000..b1bc0e6 --- /dev/null +++ b/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives.csproj @@ -0,0 +1,17 @@ + + + + + + true + true + + + + + + + + + + \ No newline at end of file diff --git a/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/App.manifest b/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/App.manifest new file mode 100644 index 0000000..ed66508 --- /dev/null +++ b/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/App.manifest @@ -0,0 +1,17 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/ArrayTests.cpp b/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/ArrayTests.cpp new file mode 100644 index 0000000..5b54a14 --- /dev/null +++ b/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/ArrayTests.cpp @@ -0,0 +1,318 @@ +// 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 "ClientTests.h" +#include +#include + +namespace +{ + bool EqualByBound(double expected, double actual) + { + double low = expected - 0.00001; + double high = expected + 0.00001; + double eps = std::fabs(expected - actual); + bool isEqual = eps < std::numeric_limits::epsilon() || (low < actual && actual < high); + return isEqual; + } + + template + std::vector Convert(_In_ const std::vector &in) + { + std::vector out; + for (auto i : in) + out.push_back((T)i); + return out; + } + + template + VARTYPE ToSafeArrayType(); + template<> + VARTYPE ToSafeArrayType() { return VT_UI1; } + template<> + VARTYPE ToSafeArrayType() { return VT_I2; } + template<> + VARTYPE ToSafeArrayType() { return VT_UI2; } + template<> + VARTYPE ToSafeArrayType() { return VT_I4; } + template<> + VARTYPE ToSafeArrayType() { return VT_UI4; } + template<> + VARTYPE ToSafeArrayType() { return VT_I8; } + template<> + VARTYPE ToSafeArrayType() { return VT_UI8; } + template<> + VARTYPE ToSafeArrayType() { return VT_R4; } + template<> + VARTYPE ToSafeArrayType() { return VT_R8; } + + template + class SafeArraySmartPtr + { + public: + SafeArraySmartPtr(_In_ const std::vector &in) + : _safeArray{} + , _elementCount{ static_cast(in.size()) } + { + SAFEARRAYBOUND saBound; + saBound.lLbound = 0; + saBound.cElements = static_cast(in.size()); + + _safeArray = ::SafeArrayCreate(ToSafeArrayType(), 1, &saBound); + assert(_safeArray != nullptr); + + std::memcpy(static_cast(_safeArray->pvData), in.data(), sizeof(T) * in.size()); + } + + ~SafeArraySmartPtr() + { + ::SafeArrayDestroy(_safeArray); + } + + int Length() const + { + return _elementCount; + } + + operator SAFEARRAY *() + { + return _safeArray; + } + + private: + int _elementCount; + SAFEARRAY *_safeArray; + }; + + void ByteArray(_In_ IArrayTesting *arrayTesting, _In_ const std::vector &baseData, _In_ double expectedMean) + { + HRESULT hr; + auto data = Convert(baseData); + + ::printf("Byte[] marshalling\n"); + + double actual; + THROW_IF_FAILED(arrayTesting->raw_Mean_Byte_LP_PreLen(static_cast(baseData.size()), data.data(), &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + + actual = 0.0; + THROW_IF_FAILED(arrayTesting->raw_Mean_Byte_LP_PostLen(data.data(), static_cast(baseData.size()), &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + + actual = 0.0; + int len; + SafeArraySmartPtr saData{ data }; + THROW_IF_FAILED(arrayTesting->raw_Mean_Byte_SafeArray_OutLen(saData, &len, &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + THROW_FAIL_IF_FALSE(len == saData.Length()); + } + + void ShortArray(_In_ IArrayTesting *arrayTesting, _In_ const std::vector &baseData, _In_ double expectedMean) + { + HRESULT hr; + auto data = Convert(baseData); + + ::printf("Short[] marshalling\n"); + + double actual; + THROW_IF_FAILED(arrayTesting->raw_Mean_Short_LP_PreLen(static_cast(baseData.size()), data.data(), &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + + actual = 0.0; + THROW_IF_FAILED(arrayTesting->raw_Mean_Short_LP_PostLen(data.data(), static_cast(baseData.size()), &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + + actual = 0.0; + int len; + SafeArraySmartPtr saData{ data }; + THROW_IF_FAILED(arrayTesting->raw_Mean_Short_SafeArray_OutLen(saData, &len, &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + THROW_FAIL_IF_FALSE(len == saData.Length()); + } + + void UShortArray(_In_ IArrayTesting *arrayTesting, _In_ const std::vector &baseData, _In_ double expectedMean) + { + HRESULT hr; + auto data = Convert(baseData); + + ::printf("UShort[] marshalling\n"); + + double actual; + THROW_IF_FAILED(arrayTesting->raw_Mean_UShort_LP_PreLen(static_cast(baseData.size()), data.data(), &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + + actual = 0.0; + THROW_IF_FAILED(arrayTesting->raw_Mean_UShort_LP_PostLen(data.data(), static_cast(baseData.size()), &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + + actual = 0.0; + int len; + SafeArraySmartPtr saData{ data }; + THROW_IF_FAILED(arrayTesting->raw_Mean_UShort_SafeArray_OutLen(saData, &len, &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + THROW_FAIL_IF_FALSE(len == saData.Length()); + } + + void IntArray(_In_ IArrayTesting *arrayTesting, _In_ const std::vector &baseData, _In_ double expectedMean) + { + HRESULT hr; + auto data = Convert(baseData); + + ::printf("Int[] marshalling\n"); + + double actual; + THROW_IF_FAILED(arrayTesting->raw_Mean_Int_LP_PreLen(static_cast(baseData.size()), data.data(), &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + + actual = 0.0; + THROW_IF_FAILED(arrayTesting->raw_Mean_Int_LP_PostLen(data.data(), static_cast(baseData.size()), &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + + actual = 0.0; + int len; + SafeArraySmartPtr saData{ data }; + THROW_IF_FAILED(arrayTesting->raw_Mean_Int_SafeArray_OutLen(saData, &len, &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + THROW_FAIL_IF_FALSE(len == saData.Length()); + } + + void UIntArray(_In_ IArrayTesting *arrayTesting, _In_ const std::vector &baseData, _In_ double expectedMean) + { + HRESULT hr; + auto data = Convert(baseData); + + ::printf("UInt[] marshalling\n"); + + double actual; + THROW_IF_FAILED(arrayTesting->raw_Mean_UInt_LP_PreLen(static_cast(baseData.size()), data.data(), &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + + actual = 0.0; + THROW_IF_FAILED(arrayTesting->raw_Mean_UInt_LP_PostLen(data.data(), static_cast(baseData.size()), &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + + actual = 0.0; + int len; + SafeArraySmartPtr saData{ data }; + THROW_IF_FAILED(arrayTesting->raw_Mean_UInt_SafeArray_OutLen(saData, &len, &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + THROW_FAIL_IF_FALSE(len == saData.Length()); + } + + void LongArray(_In_ IArrayTesting *arrayTesting, _In_ const std::vector &baseData, _In_ double expectedMean) + { + HRESULT hr; + auto data = Convert(baseData); + + ::printf("Long[] marshalling\n"); + + double actual; + THROW_IF_FAILED(arrayTesting->raw_Mean_Long_LP_PreLen(static_cast(baseData.size()), data.data(), &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + + actual = 0.0; + THROW_IF_FAILED(arrayTesting->raw_Mean_Long_LP_PostLen(data.data(), static_cast(baseData.size()), &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + + actual = 0.0; + int len; + SafeArraySmartPtr saData{ data }; + THROW_IF_FAILED(arrayTesting->raw_Mean_Long_SafeArray_OutLen(saData, &len, &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + THROW_FAIL_IF_FALSE(len == saData.Length()); + } + + void ULongArray(_In_ IArrayTesting *arrayTesting, _In_ const std::vector &baseData, _In_ double expectedMean) + { + HRESULT hr; + auto data = Convert(baseData); + + ::printf("ULong[] marshalling\n"); + + double actual; + THROW_IF_FAILED(arrayTesting->raw_Mean_ULong_LP_PreLen(static_cast(baseData.size()), data.data(), &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + + actual = 0.0; + THROW_IF_FAILED(arrayTesting->raw_Mean_ULong_LP_PostLen(data.data(), static_cast(baseData.size()), &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + + actual = 0.0; + int len; + SafeArraySmartPtr saData{ data }; + THROW_IF_FAILED(arrayTesting->raw_Mean_ULong_SafeArray_OutLen(saData, &len, &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + THROW_FAIL_IF_FALSE(len == saData.Length()); + } + + void FloatArray(_In_ IArrayTesting *arrayTesting, _In_ const std::vector &baseData, _In_ double expectedMean) + { + HRESULT hr; + auto data = Convert(baseData); + + ::printf("Float[] marshalling\n"); + + double actual; + THROW_IF_FAILED(arrayTesting->raw_Mean_Float_LP_PreLen(static_cast(baseData.size()), data.data(), &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + + actual = 0.0; + THROW_IF_FAILED(arrayTesting->raw_Mean_Float_LP_PostLen(data.data(), static_cast(baseData.size()), &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + + actual = 0.0; + int len; + SafeArraySmartPtr saData{ data }; + THROW_IF_FAILED(arrayTesting->raw_Mean_Float_SafeArray_OutLen(saData, &len, &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + THROW_FAIL_IF_FALSE(len == saData.Length()); + } + + void DoubleArray(_In_ IArrayTesting *arrayTesting, _In_ const std::vector &baseData, _In_ double expectedMean) + { + HRESULT hr; + auto data = Convert(baseData); + + ::printf("Double[] marshalling\n"); + + double actual; + THROW_IF_FAILED(arrayTesting->raw_Mean_Double_LP_PreLen(static_cast(baseData.size()), data.data(), &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + + actual = 0.0; + THROW_IF_FAILED(arrayTesting->raw_Mean_Double_LP_PostLen(data.data(), static_cast(baseData.size()), &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + + actual = 0.0; + int len; + SafeArraySmartPtr saData{ data }; + THROW_IF_FAILED(arrayTesting->raw_Mean_Double_SafeArray_OutLen(saData, &len, &actual)); + THROW_FAIL_IF_FALSE(EqualByBound(expectedMean, actual)); + THROW_FAIL_IF_FALSE(len == saData.Length()); + } +} + +void Run_ArrayTests() +{ + HRESULT hr; + + CoreShimComActivation csact{ W("NETServer.dll"), W("ArrayTesting") }; + + ComSmartPtr arrayTesting; + THROW_IF_FAILED(::CoCreateInstance(CLSID_ArrayTesting, nullptr, CLSCTX_INPROC, IID_IArrayTesting, (void**)&arrayTesting)); + + std::vector baseData(10); + std::iota(std::begin(baseData), std::end(baseData), 0); + double mean = std::accumulate(std::begin(baseData), std::end(baseData), 0.0) / baseData.size(); + + ByteArray(arrayTesting, baseData, mean); + ShortArray(arrayTesting, baseData, mean); + UShortArray(arrayTesting, baseData, mean); + IntArray(arrayTesting, baseData, mean); + UIntArray(arrayTesting, baseData, mean); + LongArray(arrayTesting, baseData, mean); + ULongArray(arrayTesting, baseData, mean); + FloatArray(arrayTesting, baseData, mean); + DoubleArray(arrayTesting, baseData, mean); +} diff --git a/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/CMakeLists.txt b/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/CMakeLists.txt new file mode 100644 index 0000000..b2b2fb0 --- /dev/null +++ b/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required (VERSION 2.6) + +project (COMClientPrimitives) +include_directories( ${INC_PLATFORM_DIR} ) +include_directories( "../../ServerContracts" ) +include_directories( "../../NativeServer" ) +set(SOURCES + Client.cpp + NumericTests.cpp + ArrayTests.cpp + StringTests.cpp + ErrorTests.cpp + App.manifest) + +# add the executable +add_executable (COMClientPrimitives ${SOURCES}) +target_link_libraries(COMClientPrimitives ${LINK_LIBRARIES_ADDITIONAL}) + +# Copy CoreShim manifest to project output +file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/$/CoreShim.X.manifest INPUT ${CMAKE_CURRENT_SOURCE_DIR}/CoreShim.X.manifest) + +# add the install targets +install (TARGETS COMClientPrimitives DESTINATION bin) diff --git a/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/Client.cpp b/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/Client.cpp new file mode 100644 index 0000000..bfb32c5 --- /dev/null +++ b/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/Client.cpp @@ -0,0 +1,45 @@ +// 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 "ClientTests.h" + +template +struct ComInit +{ + const HRESULT Result; + + ComInit() + : Result{ ::CoInitializeEx(nullptr, TM) } + { } + + ~ComInit() + { + if (SUCCEEDED(Result)) + ::CoUninitialize(); + } +}; + +using ComMTA = ComInit; + +int __cdecl main() +{ + ComMTA init; + if (FAILED(init.Result)) + return -1; + + try + { + Run_NumericTests(); + Run_ArrayTests(); + Run_StringTests(); + Run_ErrorTests(); + } + catch (HRESULT hr) + { + ::printf("Test Failure: 0x%08x\n", hr); + return 101; + } + + return 100; +} diff --git a/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/ClientTests.h b/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/ClientTests.h new file mode 100644 index 0000000..029ed02 --- /dev/null +++ b/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/ClientTests.h @@ -0,0 +1,70 @@ +// 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 +#include +#include + +#define COM_CLIENT +#include + +#define THROW_IF_FAILED(exp) { hr = exp; if (FAILED(hr)) { ::printf("FAILURE: 0x%08x = %s\n", hr, #exp); throw hr; } } +#define THROW_FAIL_IF_FALSE(exp) { if (!(exp)) { ::printf("FALSE: %s\n", #exp); throw E_FAIL; } } + +template +struct ComSmartPtr +{ + ComSmartPtr() + : p{} + { } + + ComSmartPtr(_In_ const ComSmartPtr &) = delete; + ComSmartPtr(_Inout_ ComSmartPtr &&) = delete; + + ComSmartPtr& operator=(_In_ const ComSmartPtr &) = delete; + ComSmartPtr& operator=(_Inout_ ComSmartPtr &&) = delete; + + ~ComSmartPtr() + { + if (p != nullptr) + p->Release(); + } + + operator T*() + { + return p; + } + + T** operator&() + { + return &p; + } + + T* operator->() + { + return p; + } + + void Attach(_In_opt_ T *t) + { + if (p != nullptr) + p->Release(); + + p = t; + } + + T *Detach() + { + T *tmp = p; + p = nullptr; + return tmp; + } + + T *p; +}; + +void Run_NumericTests(); +void Run_ArrayTests(); +void Run_StringTests(); +void Run_ErrorTests(); diff --git a/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/CoreShim.X.manifest b/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/CoreShim.X.manifest new file mode 100644 index 0000000..1dba8e0 --- /dev/null +++ b/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/CoreShim.X.manifest @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + diff --git a/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/ErrorTests.cpp b/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/ErrorTests.cpp new file mode 100644 index 0000000..9f0af22 --- /dev/null +++ b/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/ErrorTests.cpp @@ -0,0 +1,68 @@ +// 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 "ClientTests.h" + +namespace +{ + void VerifyExpectedException(_In_ IErrorMarshalTesting *et) + { + ::printf("Verify expected exception from HRESULT\n"); + + HRESULT hrs[] = + { + E_NOTIMPL, + E_POINTER, + E_ACCESSDENIED, + E_OUTOFMEMORY, + E_INVALIDARG, + E_UNEXPECTED, + HRESULT{-1} + }; + + for (int i = 0; i < ARRAYSIZE(hrs); ++i) + { + HRESULT hr = hrs[i]; + HRESULT hrMaybe = et->raw_Throw_HResult(hr); + THROW_FAIL_IF_FALSE(hr == hrMaybe); + } + } + + void VerifyReturnHResult(_In_ IErrorMarshalTesting *et) + { + ::printf("Verify preserved function signature\n"); + + HRESULT hrs[] = + { + E_NOTIMPL, + E_POINTER, + E_ACCESSDENIED, + E_INVALIDARG, + E_UNEXPECTED, + HRESULT{-1}, + S_FALSE, + HRESULT{2} + }; + + for (int i = 0; i < ARRAYSIZE(hrs); ++i) + { + HRESULT hr = hrs[i]; + HRESULT hrMaybe = et->Return_As_HResult(hr); + THROW_FAIL_IF_FALSE(hr == hrMaybe); + } + } +} + +void Run_ErrorTests() +{ + HRESULT hr; + + CoreShimComActivation csact{ W("NETServer.dll"), W("ErrorMarshalTesting") }; + + ComSmartPtr errorMarshal; + THROW_IF_FAILED(::CoCreateInstance(CLSID_ErrorMarshalTesting, nullptr, CLSCTX_INPROC, IID_IErrorMarshalTesting, (void**)&errorMarshal)); + + VerifyExpectedException(errorMarshal); + VerifyReturnHResult(errorMarshal); +} diff --git a/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/NumericTests.cpp b/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/NumericTests.cpp new file mode 100644 index 0000000..68ae4f4 --- /dev/null +++ b/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/NumericTests.cpp @@ -0,0 +1,227 @@ +// 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 "ClientTests.h" +#include +#include + +namespace +{ + void MarshalByte(_In_ INumericTesting *numericTesting, _In_ byte a, _In_ byte b) + { + HRESULT hr; + + byte expected = a + b; + ::printf("Byte test invariant: %d + %d = %d\n", a, b, expected); + + byte c; + THROW_IF_FAILED(numericTesting->raw_Add_Byte(a, b, &c)); + THROW_FAIL_IF_FALSE(expected == c); + + c = std::numeric_limits::max(); + THROW_IF_FAILED(numericTesting->raw_Add_Byte_Ref(a, b, &c)); + THROW_FAIL_IF_FALSE(expected == c); + + c = 0; + THROW_IF_FAILED(numericTesting->raw_Add_Byte_Out(a, b, &c)); + THROW_FAIL_IF_FALSE(expected == c); + } + + void MarshalShort(_In_ INumericTesting *numericTesting, _In_ int16_t a, _In_ int16_t b) + { + HRESULT hr; + + int16_t expected = a + b; + ::printf("Short test invariant: %d + %d = %d\n", a, b, expected); + + int16_t c; + THROW_IF_FAILED(numericTesting->raw_Add_Short(a, b, &c)); + THROW_FAIL_IF_FALSE(expected == c); + + c = std::numeric_limits::max(); + THROW_IF_FAILED(numericTesting->raw_Add_Short_Ref(a, b, &c)); + THROW_FAIL_IF_FALSE(expected == c); + + c = 0; + THROW_IF_FAILED(numericTesting->raw_Add_Short_Out(a, b, &c)); + THROW_FAIL_IF_FALSE(expected == c); + } + + void MarshalUShort(_In_ INumericTesting *numericTesting, _In_ uint16_t a, _In_ uint16_t b) + { + HRESULT hr; + + uint16_t expected = a + b; + ::printf("UShort test invariant: %u + %u = %u\n", a, b, expected); + + uint16_t c; + THROW_IF_FAILED(numericTesting->raw_Add_UShort(a, b, &c)); + THROW_FAIL_IF_FALSE(expected == c); + + c = std::numeric_limits::max(); + THROW_IF_FAILED(numericTesting->raw_Add_UShort_Ref(a, b, &c)); + THROW_FAIL_IF_FALSE(expected == c); + + c = 0; + THROW_IF_FAILED(numericTesting->raw_Add_UShort_Out(a, b, &c)); + THROW_FAIL_IF_FALSE(expected == c); + } + + void MarshalInt(_In_ INumericTesting *numericTesting, _In_ int32_t a, _In_ int32_t b) + { + HRESULT hr; + + int32_t expected = a + b; + ::printf("Int test invariant: %d + %d = %d\n", a, b, expected); + + int32_t c; + THROW_IF_FAILED(numericTesting->raw_Add_Int(a, b, &c)); + THROW_FAIL_IF_FALSE(expected == c); + + c = std::numeric_limits::max(); + THROW_IF_FAILED(numericTesting->raw_Add_Int_Ref(a, b, &c)); + THROW_FAIL_IF_FALSE(expected == c); + + c = 0; + THROW_IF_FAILED(numericTesting->raw_Add_Int_Out(a, b, &c)); + THROW_FAIL_IF_FALSE(expected == c); + } + + void MarshalUInt(_In_ INumericTesting *numericTesting, _In_ uint32_t a, _In_ uint32_t b) + { + HRESULT hr; + + uint32_t expected = a + b; + ::printf("UInt test invariant: %u + %u = %u\n", a, b, expected); + + uint32_t c; + THROW_IF_FAILED(numericTesting->raw_Add_UInt(a, b, &c)); + THROW_FAIL_IF_FALSE(expected == c); + + c = std::numeric_limits::max(); + THROW_IF_FAILED(numericTesting->raw_Add_UInt_Ref(a, b, &c)); + THROW_FAIL_IF_FALSE(expected == c); + + c = 0; + THROW_IF_FAILED(numericTesting->raw_Add_UInt_Out(a, b, &c)); + THROW_FAIL_IF_FALSE(expected == c); + } + + void MarshalLong(_In_ INumericTesting *numericTesting, _In_ int64_t a, _In_ int64_t b) + { + HRESULT hr; + + int64_t expected = a + b; + ::printf("Long test invariant: %lld + %lld = %lld\n", a, b, expected); + + int64_t c; + THROW_IF_FAILED(numericTesting->raw_Add_Long(a, b, &c)); + THROW_FAIL_IF_FALSE(expected == c); + + c = std::numeric_limits::max(); + THROW_IF_FAILED(numericTesting->raw_Add_Long_Ref(a, b, &c)); + THROW_FAIL_IF_FALSE(expected == c); + + c = 0; + THROW_IF_FAILED(numericTesting->raw_Add_Long_Out(a, b, &c)); + THROW_FAIL_IF_FALSE(expected == c); + } + + void MarshalULong(_In_ INumericTesting *numericTesting, _In_ uint64_t a, _In_ uint64_t b) + { + HRESULT hr; + + uint64_t expected = a + b; + ::printf("ULong test invariant: %llu + %llu = %llu\n", a, b, expected); + + uint64_t c; + THROW_IF_FAILED(numericTesting->raw_Add_ULong(a, b, &c)); + THROW_FAIL_IF_FALSE(expected == c); + + c = std::numeric_limits::max(); + THROW_IF_FAILED(numericTesting->raw_Add_ULong_Ref(a, b, &c)); + THROW_FAIL_IF_FALSE(expected == c); + + c = 0; + THROW_IF_FAILED(numericTesting->raw_Add_ULong_Out(a, b, &c)); + THROW_FAIL_IF_FALSE(expected == c); + } + + template + bool EqualByBound(_In_ T expected, _In_ T actual) + { + T low = expected - (T)0.0001; + T high = expected + (T)0.0001; + T eps = std::abs(expected - actual); + return (eps < std::numeric_limits::epsilon() || (low < actual && actual < high)); + } + + void MarshalFloat(_In_ INumericTesting *numericTesting, _In_ float a, _In_ float b) + { + HRESULT hr; + + float expected = a + b; + ::printf("Float test invariant: %f + %f = %f\n", a, b, expected); + + float c; + THROW_IF_FAILED(numericTesting->raw_Add_Float(a, b, &c)); + THROW_FAIL_IF_FALSE(EqualByBound(expected, c)); + + c = std::numeric_limits::max(); + THROW_IF_FAILED(numericTesting->raw_Add_Float_Ref(a, b, &c)); + THROW_FAIL_IF_FALSE(EqualByBound(expected, c)); + + c = 0; + THROW_IF_FAILED(numericTesting->raw_Add_Float_Out(a, b, &c)); + THROW_FAIL_IF_FALSE(EqualByBound(expected, c)); + } + + void MarshalDouble(_In_ INumericTesting *numericTesting, _In_ double a, _In_ double b) + { + HRESULT hr; + + double expected = a + b; + ::printf("Double test invariant: %f + %f = %f\n", a, b, expected); + + double c; + THROW_IF_FAILED(numericTesting->raw_Add_Double(a, b, &c)); + THROW_FAIL_IF_FALSE(EqualByBound(expected, c)); + + c = std::numeric_limits::max(); + THROW_IF_FAILED(numericTesting->raw_Add_Double_Ref(a, b, &c)); + THROW_FAIL_IF_FALSE(EqualByBound(expected, c)); + + c = 0; + THROW_IF_FAILED(numericTesting->raw_Add_Double_Out(a, b, &c)); + THROW_FAIL_IF_FALSE(EqualByBound(expected, c)); + } +} + +void Run_NumericTests() +{ + HRESULT hr; + + CoreShimComActivation csact{ W("NETServer.dll"), W("NumericTesting") }; + + ComSmartPtr numericTesting; + THROW_IF_FAILED(::CoCreateInstance(CLSID_NumericTesting, nullptr, CLSCTX_INPROC, IID_INumericTesting, (void**)&numericTesting)); + + int seed = 37; + ::srand(seed); + + ::printf("Numeric RNG seed: %d\n", seed); + + int a = ::rand(); + int b = ::rand(); + + MarshalByte(numericTesting, (byte)a, (byte)b); + MarshalShort(numericTesting, (int16_t)a, (int16_t)b); + MarshalUShort(numericTesting, (uint16_t)a, (uint16_t)b); + MarshalInt(numericTesting, a, b); + MarshalUInt(numericTesting, (uint32_t)a, (uint32_t)b); + MarshalLong(numericTesting, (int64_t)a, (int64_t)b); + MarshalULong(numericTesting, (uint64_t)a, (uint64_t)b); + MarshalFloat(numericTesting, (float)a / 100.f, (float)b / 100.f); + MarshalDouble(numericTesting, (double)a / 100.0, (double)b / 100.0); +} diff --git a/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/StringTests.cpp b/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/StringTests.cpp new file mode 100644 index 0000000..a9dad99 --- /dev/null +++ b/src/coreclr/tests/src/Interop/COM/NativeClients/Primitives/StringTests.cpp @@ -0,0 +1,422 @@ +// 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 "ClientTests.h" +#include +#include + +namespace +{ + template + < + typename CT, + void*(*STR_ALLOC)(size_t), + void(*STR_FREE)(void*) + > + class AnyStr + { + public: + AnyStr() : _lenBytes{ 0 } , _str{ nullptr } + { } + + explicit AnyStr(_In_z_ const char *str) + : _lenBytes{ (::strlen(str) + 1) * sizeof(CT) } + { + _str = (CT *)STR_ALLOC(_lenBytes); + CT *strLocal = _str; + + while (*str) + { + // [TODO] handle UTF8 + *strLocal = static_cast(*str++); + strLocal++; + } + *strLocal = CT{ '\0' }; + } + + // Concat strings + AnyStr(_In_ const AnyStr &l, _In_ const AnyStr &r) + : _lenBytes{ l._lenBytes + r._lenBytes - sizeof(CT) } // Remove duplicate null + { + _str = (CT *)STR_ALLOC(_lenBytes); + CT *strLocal = _str; + std::memcpy(strLocal, l._str, l._lenBytes - sizeof(CT)); // Ignore null + + size_t l_len = l.Length(); + std::memcpy(strLocal + l_len, r._str, r._lenBytes); + } + + AnyStr(_In_ const AnyStr &other) + : _lenBytes{ other._lenBytes } + , _str{ (CT *)STR_ALLOC(other._lenBytes) } + { + std::memcpy(_str, other._str, _lenBytes); + } + + AnyStr& operator=(_In_ const AnyStr &other) + { + AnyStr old{ std::move(*this) }; + AnyStr otherCopy{ other }; + (*this) = std::move(otherCopy); + return (*this); + } + + AnyStr(_Inout_ AnyStr &&other) + : _lenBytes{ other._lenBytes } + , _str{ other._str } + { + other._str = nullptr; + } + + AnyStr& operator=(_Inout_ AnyStr &&other) + { + AnyStr tmp{ std::move(*this) }; + _lenBytes = other._lenBytes; + _str = other._str; + other._str = nullptr; + return (*this); + } + + ~AnyStr() + { + if (_str != nullptr) + STR_FREE(_str); + } + + operator CT*() + { + return _str; + } + + operator const CT*() const + { + return _str; + } + + CT** operator &() + { + return &_str; + } + + bool operator==(_In_ const AnyStr &other) const + { + return EqualTo(other._str); + } + + bool operator!=(_In_ const AnyStr &other) const + { + return !(*this == other); + } + + void Attach(_In_z_ CT *data) + { + AnyStr tmp{ std::move(*this) }; + + CT *dataIter = data; + int len = 1; // Include 1 for null + while (*dataIter++) + ++len; + + _str = data; + _lenBytes = len * sizeof(CT); + } + + // String length _not_ including null + size_t Length() const + { + if (_lenBytes == 0) + return 0; + + return (_lenBytes - sizeof(CT)) / sizeof(CT); + } + + // String length including null in bytes + size_t LengthByte() const + { + return _lenBytes; + } + + bool AllAscii() const + { + const CT *c = _str; + const CT MaxAscii = (CT)0x7f; + while (*c) + { + if ((*c++) > MaxAscii) + return false; + } + + return true; + } + + bool EqualTo(_In_z_ const CT *str) const + { + const CT *tmp = str; + int len = 1; // Include 1 for null + while (*tmp++) + ++len; + + if (_lenBytes != (sizeof(CT) * len)) + return false; + + return (0 == std::memcmp(_str, str, _lenBytes)); + } + + HRESULT Reverse(_Inout_ AnyStr &res) const + { + AnyStr tmp{}; + + if (_lenBytes > 0) + { + tmp._lenBytes = _lenBytes; + tmp._str = (CT *)STR_ALLOC(_lenBytes); + if (tmp._str == nullptr) + return E_OUTOFMEMORY; + + ::memcpy(tmp._str, _str, _lenBytes); + std::reverse(tmp._str, tmp._str + Length()); + } + + res = std::move(tmp); + return S_OK; + } + + private: + size_t _lenBytes; + CT *_str; + }; + + // BSTR string + using BStr = AnyStr; + + // Wide string + using WStr = AnyStr; + + // Narrow string + using NStr = AnyStr; + + template + std::vector> GetAddPairs() + { + std::vector> pairs; + + pairs.push_back({ STR{ "" }, STR{ "" } }); + pairs.push_back({ STR{ "" }, STR{ "def" } }); + pairs.push_back({ STR{ "abc" }, STR{ "" } }); + pairs.push_back({ STR{ "abc" }, STR{ "def" } }); + + // String marshalling is optimized where strings shorter than MAX_PATH are + // allocated on the stack. Longer strings have memory allocated for them. + pairs.push_back({ + STR{ "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901" }, + STR{ "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901" } + }); + + return pairs; + } + + template + std::vector GetReversableStrings() + { + std::vector rev; + + rev.push_back(STR{ "" }); + rev.push_back(STR{ "a" }); + rev.push_back(STR{ "abc" }); + rev.push_back(STR{ "reversable string" }); + + // Long string optimization validation + rev.push_back(STR{ "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901" }); + + return rev; + } + + void Marshal_LPString(_In_ IStringTesting* stringTesting) + { + ::printf("Marshal strings as LPStr\n"); + + HRESULT hr; + + auto pairs = GetAddPairs(); + for (auto &p : pairs) + { + if (!p.first.AllAscii() || !p.second.AllAscii()) + { + // LPStr doesn't support non-ascii characters + continue; + } + + LPSTR tmp; + NStr expected{ p.first, p.second }; + THROW_IF_FAILED(stringTesting->raw_Add_LPStr(p.first, p.second, &tmp)); + + NStr actual; + actual.Attach(tmp); + THROW_FAIL_IF_FALSE(expected.EqualTo(actual)); + } + + auto reversable = GetReversableStrings(); + for (const auto &r : reversable) + { + if (!r.AllAscii()) + { + // LPStr doesn't support non-ascii characters + continue; + } + + LPSTR tmp; + NStr local{ r }; + + NStr actual; + NStr expected; + THROW_IF_FAILED(r.Reverse(expected)); + + THROW_IF_FAILED(stringTesting->raw_Reverse_LPStr(local, &tmp)); + actual.Attach(tmp); + THROW_FAIL_IF_FALSE(expected == actual); + + THROW_IF_FAILED(stringTesting->raw_Reverse_LPStr_Ref(&local, &tmp)); + actual.Attach(tmp); + THROW_FAIL_IF_FALSE(expected == actual); + THROW_FAIL_IF_FALSE(r == local); // Local should not be changed + + local = r; + THROW_IF_FAILED(stringTesting->raw_Reverse_LPStr_InRef(&local, &tmp)); + actual.Attach(tmp); + THROW_FAIL_IF_FALSE(expected == actual); + THROW_FAIL_IF_FALSE(r == local); // Local should not be changed + + THROW_IF_FAILED(stringTesting->raw_Reverse_LPStr_Out(local, &tmp)); + actual.Attach(tmp); + THROW_FAIL_IF_FALSE(expected == actual); + + actual = local; + tmp = actual; + THROW_IF_FAILED(stringTesting->raw_Reverse_LPStr_OutAttr(local, tmp)); // No-op for strings + THROW_FAIL_IF_FALSE(local == actual); + } + } + + void Marshal_LPWString(_In_ IStringTesting* stringTesting) + { + ::printf("Marshal strings as LPWStr\n"); + + HRESULT hr; + + auto pairs = GetAddPairs(); + for (auto &p : pairs) + { + LPWSTR tmp; + WStr expected{ p.first, p.second }; + THROW_IF_FAILED(stringTesting->raw_Add_LPWStr(p.first, p.second, &tmp)); + + WStr actual; + actual.Attach(tmp); + THROW_FAIL_IF_FALSE(expected.EqualTo(actual)); + } + + auto reversable = GetReversableStrings(); + for (const auto &r : reversable) + { + LPWSTR tmp; + WStr local{ r }; + + WStr actual; + WStr expected; + THROW_IF_FAILED(r.Reverse(expected)); + + THROW_IF_FAILED(stringTesting->raw_Reverse_LPWStr(local, &tmp)); + actual.Attach(tmp); + THROW_FAIL_IF_FALSE(expected == actual); + + THROW_IF_FAILED(stringTesting->raw_Reverse_LPWStr_Ref(&local, &tmp)); + actual.Attach(tmp); + THROW_FAIL_IF_FALSE(expected == actual); + THROW_FAIL_IF_FALSE(r == local); // Local should not be changed + + local = r; + THROW_IF_FAILED(stringTesting->raw_Reverse_LPWStr_InRef(&local, &tmp)); + actual.Attach(tmp); + THROW_FAIL_IF_FALSE(expected == actual); + THROW_FAIL_IF_FALSE(r == local); // Local should not be changed + + THROW_IF_FAILED(stringTesting->raw_Reverse_LPWStr_Out(local, &tmp)); + actual.Attach(tmp); + THROW_FAIL_IF_FALSE(expected == actual); + + actual = local; + tmp = actual; + THROW_IF_FAILED(stringTesting->raw_Reverse_LPWStr_OutAttr(local, tmp)); // No-op for strings + THROW_FAIL_IF_FALSE(local == actual); + } + } + + void Marshal_BStrString(_In_ IStringTesting* stringTesting) + { + ::printf("Marshal strings as BStr\n"); + + HRESULT hr; + + auto pairs = GetAddPairs(); + for (auto &p : pairs) + { + BSTR tmp; + BStr expected{ p.first, p.second }; + THROW_IF_FAILED(stringTesting->raw_Add_BStr(p.first, p.second, &tmp)); + + BStr actual; + actual.Attach(tmp); + THROW_FAIL_IF_FALSE(expected.EqualTo(actual)); + } + + auto reversable = GetReversableStrings(); + for (const auto &r : reversable) + { + BSTR tmp; + BStr local{ r }; + + BStr actual; + BStr expected; + THROW_IF_FAILED(r.Reverse(expected)); + + THROW_IF_FAILED(stringTesting->raw_Reverse_BStr(local, &tmp)); + actual.Attach(tmp); + THROW_FAIL_IF_FALSE(expected == actual); + + THROW_IF_FAILED(stringTesting->raw_Reverse_BStr_Ref(&local, &tmp)); + actual.Attach(tmp); + THROW_FAIL_IF_FALSE(expected == actual); + THROW_FAIL_IF_FALSE(r == local); // Local should not be changed + + local = r; + THROW_IF_FAILED(stringTesting->raw_Reverse_BStr_InRef(&local, &tmp)); + actual.Attach(tmp); + THROW_FAIL_IF_FALSE(expected == actual); + THROW_FAIL_IF_FALSE(r == local); // Local should not be changed + + THROW_IF_FAILED(stringTesting->raw_Reverse_BStr_Out(local, &tmp)); + actual.Attach(tmp); + THROW_FAIL_IF_FALSE(expected == actual); + + actual = local; + tmp = actual; + THROW_IF_FAILED(stringTesting->raw_Reverse_BStr_OutAttr(local, tmp)); // No-op for strings + THROW_FAIL_IF_FALSE(local == actual); + } + } +} + +void Run_StringTests() +{ + HRESULT hr; + + CoreShimComActivation csact{ W("NETServer.dll"), W("StringTesting") }; + + ComSmartPtr stringTesting; + THROW_IF_FAILED(::CoCreateInstance(CLSID_StringTesting, nullptr, CLSCTX_INPROC, IID_IStringTesting, (void**)&stringTesting)); + + Marshal_LPString(stringTesting); + Marshal_LPWString(stringTesting); + Marshal_BStrString(stringTesting); +} diff --git a/src/coreclr/tests/src/Interop/COM/NativeServer/ArrayTesting.h b/src/coreclr/tests/src/Interop/COM/NativeServer/ArrayTesting.h index 6939762..27d0239 100644 --- a/src/coreclr/tests/src/Interop/COM/NativeServer/ArrayTesting.h +++ b/src/coreclr/tests/src/Interop/COM/NativeServer/ArrayTesting.h @@ -20,7 +20,7 @@ private: return (t / l); } template - HRESULT Mean(SAFEARRAY *d, long *l, double *r) + HRESULT Mean(SAFEARRAY *d, int *l, double *r) { HRESULT hr; @@ -74,7 +74,7 @@ private: public: // IArrayTesting DEF_RAWFUNC(Mean_Byte_LP_PreLen)( - /*[in]*/ long len, + /*[in]*/ int len, /*[in]*/ unsigned char * d, /*[out,retval]*/ double * pRetVal) { @@ -84,7 +84,7 @@ public: // IArrayTesting return S_OK; } DEF_RAWFUNC(Mean_Short_LP_PreLen)( - /*[in]*/ long len, + /*[in]*/ int len, /*[in]*/ short * d, /*[out,retval]*/ double * pRetVal) { @@ -94,7 +94,7 @@ public: // IArrayTesting return S_OK; } DEF_RAWFUNC(Mean_UShort_LP_PreLen)( - /*[in]*/ long len, + /*[in]*/ int len, /*[in]*/ unsigned short * d, /*[out,retval]*/ double * pRetVal) { @@ -104,8 +104,8 @@ public: // IArrayTesting return S_OK; } DEF_RAWFUNC(Mean_Int_LP_PreLen)( - /*[in]*/ long len, - /*[in]*/ long * d, + /*[in]*/ int len, + /*[in]*/ int * d, /*[out,retval]*/ double * pRetVal) { if (pRetVal == nullptr) @@ -114,8 +114,8 @@ public: // IArrayTesting return S_OK; } DEF_RAWFUNC(Mean_UInt_LP_PreLen)( - /*[in]*/ long len, - /*[in]*/ unsigned long * d, + /*[in]*/ int len, + /*[in]*/ unsigned int * d, /*[out,retval]*/ double * pRetVal) { if (pRetVal == nullptr) @@ -124,7 +124,7 @@ public: // IArrayTesting return S_OK; } DEF_RAWFUNC(Mean_Long_LP_PreLen)( - /*[in]*/ long len, + /*[in]*/ int len, /*[in]*/ __int64 * d, /*[out,retval]*/ double * pRetVal) { @@ -134,7 +134,7 @@ public: // IArrayTesting return S_OK; } DEF_RAWFUNC(Mean_ULong_LP_PreLen)( - /*[in]*/ long len, + /*[in]*/ int len, /*[in]*/ unsigned __int64 * d, /*[out,retval]*/ double * pRetVal) { @@ -144,7 +144,7 @@ public: // IArrayTesting return S_OK; } DEF_RAWFUNC(Mean_Float_LP_PreLen)( - /*[in]*/ long len, + /*[in]*/ int len, /*[in]*/ float * d, /*[out,retval]*/ double * pRetVal) { @@ -154,7 +154,7 @@ public: // IArrayTesting return S_OK; } DEF_RAWFUNC(Mean_Double_LP_PreLen)( - /*[in]*/ long len, + /*[in]*/ int len, /*[in]*/ double * d, /*[out,retval]*/ double * pRetVal) { @@ -165,7 +165,7 @@ public: // IArrayTesting } DEF_RAWFUNC(Mean_Byte_LP_PostLen)( /*[in]*/ unsigned char * d, - /*[in]*/ long len, + /*[in]*/ int len, /*[out,retval]*/ double * pRetVal) { if (pRetVal == nullptr) @@ -175,7 +175,7 @@ public: // IArrayTesting } DEF_RAWFUNC(Mean_Short_LP_PostLen)( /*[in]*/ short * d, - /*[in]*/ long len, + /*[in]*/ int len, /*[out,retval]*/ double * pRetVal) { if (pRetVal == nullptr) @@ -185,7 +185,7 @@ public: // IArrayTesting } DEF_RAWFUNC(Mean_UShort_LP_PostLen)( /*[in]*/ unsigned short * d, - /*[in]*/ long len, + /*[in]*/ int len, /*[out,retval]*/ double * pRetVal) { if (pRetVal == nullptr) @@ -194,8 +194,8 @@ public: // IArrayTesting return S_OK; } DEF_RAWFUNC(Mean_Int_LP_PostLen)( - /*[in]*/ long * d, - /*[in]*/ long len, + /*[in]*/ int * d, + /*[in]*/ int len, /*[out,retval]*/ double * pRetVal) { if (pRetVal == nullptr) @@ -204,8 +204,8 @@ public: // IArrayTesting return S_OK; } DEF_RAWFUNC(Mean_UInt_LP_PostLen)( - /*[in]*/ unsigned long * d, - /*[in]*/ long len, + /*[in]*/ unsigned int * d, + /*[in]*/ int len, /*[out,retval]*/ double * pRetVal) { if (pRetVal == nullptr) @@ -215,7 +215,7 @@ public: // IArrayTesting } DEF_RAWFUNC(Mean_Long_LP_PostLen)( /*[in]*/ __int64 * d, - /*[in]*/ long len, + /*[in]*/ int len, /*[out,retval]*/ double * pRetVal) { if (pRetVal == nullptr) @@ -225,7 +225,7 @@ public: // IArrayTesting } DEF_RAWFUNC(Mean_ULong_LP_PostLen)( /*[in]*/ unsigned __int64 * d, - /*[in]*/ long len, + /*[in]*/ int len, /*[out,retval]*/ double * pRetVal) { if (pRetVal == nullptr) @@ -235,7 +235,7 @@ public: // IArrayTesting } DEF_RAWFUNC(Mean_Float_LP_PostLen)( /*[in]*/ float * d, - /*[in]*/ long len, + /*[in]*/ int len, /*[out,retval]*/ double * pRetVal) { if (pRetVal == nullptr) @@ -245,7 +245,7 @@ public: // IArrayTesting } DEF_RAWFUNC(Mean_Double_LP_PostLen)( /*[in]*/ double * d, - /*[in]*/ long len, + /*[in]*/ int len, /*[out,retval]*/ double * pRetVal) { if (pRetVal == nullptr) @@ -255,7 +255,7 @@ public: // IArrayTesting } DEF_RAWFUNC(Mean_Byte_SafeArray_OutLen)( /*[in]*/ SAFEARRAY * d, - /*[out]*/ long * len, + /*[out]*/ int * len, /*[out,retval]*/ double * pRetVal) { if (pRetVal == nullptr) @@ -264,7 +264,7 @@ public: // IArrayTesting } DEF_RAWFUNC(Mean_Short_SafeArray_OutLen)( /*[in]*/ SAFEARRAY * d, - /*[out]*/ long * len, + /*[out]*/ int * len, /*[out,retval]*/ double * pRetVal) { if (pRetVal == nullptr) @@ -273,7 +273,7 @@ public: // IArrayTesting } DEF_RAWFUNC(Mean_UShort_SafeArray_OutLen)( /*[in]*/ SAFEARRAY * d, - /*[out]*/ long * len, + /*[out]*/ int * len, /*[out,retval]*/ double * pRetVal) { if (pRetVal == nullptr) @@ -282,7 +282,7 @@ public: // IArrayTesting } DEF_RAWFUNC(Mean_Int_SafeArray_OutLen)( /*[in]*/ SAFEARRAY * d, - /*[out]*/ long * len, + /*[out]*/ int * len, /*[out,retval]*/ double * pRetVal) { if (pRetVal == nullptr) @@ -291,7 +291,7 @@ public: // IArrayTesting } DEF_RAWFUNC(Mean_UInt_SafeArray_OutLen)( /*[in]*/ SAFEARRAY * d, - /*[out]*/ long * len, + /*[out]*/ int * len, /*[out,retval]*/ double * pRetVal) { if (pRetVal == nullptr) @@ -300,7 +300,7 @@ public: // IArrayTesting } DEF_RAWFUNC(Mean_Long_SafeArray_OutLen)( /*[in]*/ SAFEARRAY * d, - /*[out]*/ long * len, + /*[out]*/ int * len, /*[out,retval]*/ double * pRetVal) { if (pRetVal == nullptr) @@ -309,7 +309,7 @@ public: // IArrayTesting } DEF_RAWFUNC(Mean_ULong_SafeArray_OutLen)( /*[in]*/ SAFEARRAY * d, - /*[out]*/ long * len, + /*[out]*/ int * len, /*[out,retval]*/ double * pRetVal) { if (pRetVal == nullptr) @@ -318,7 +318,7 @@ public: // IArrayTesting } DEF_RAWFUNC(Mean_Float_SafeArray_OutLen)( /*[in]*/ SAFEARRAY * d, - /*[out]*/ long * len, + /*[out]*/ int * len, /*[out,retval]*/ double * pRetVal) { if (pRetVal == nullptr) @@ -327,7 +327,7 @@ public: // IArrayTesting } DEF_RAWFUNC(Mean_Double_SafeArray_OutLen)( /*[in]*/ SAFEARRAY * d, - /*[out]*/ long * len, + /*[out]*/ int * len, /*[out,retval]*/ double * pRetVal) { if (pRetVal == nullptr) diff --git a/src/coreclr/tests/src/Interop/COM/NativeServer/ErrorMarshalTesting.h b/src/coreclr/tests/src/Interop/COM/NativeServer/ErrorMarshalTesting.h index 6dd7649..2b1276c9 100644 --- a/src/coreclr/tests/src/Interop/COM/NativeServer/ErrorMarshalTesting.h +++ b/src/coreclr/tests/src/Interop/COM/NativeServer/ErrorMarshalTesting.h @@ -10,12 +10,13 @@ class ErrorMarshalTesting : public UnknownImpl, public IErrorMarshalTesting { public: // IErrorMarshalTesting DEF_RAWFUNC(Throw_HResult)( - /*[in]*/ long hresultToReturn) + /*[in]*/ int hresultToReturn) { return HRESULT{ hresultToReturn }; } - long STDMETHODCALLTYPE Return_As_HResult( - /*[in]*/ long hresultToReturn) + + int STDMETHODCALLTYPE Return_As_HResult( + /*[in]*/ int hresultToReturn) { return hresultToReturn; } diff --git a/src/coreclr/tests/src/Interop/COM/NativeServer/NumericTesting.h b/src/coreclr/tests/src/Interop/COM/NativeServer/NumericTesting.h index 555a38d..1f4acf9 100644 --- a/src/coreclr/tests/src/Interop/COM/NativeServer/NumericTesting.h +++ b/src/coreclr/tests/src/Interop/COM/NativeServer/NumericTesting.h @@ -36,17 +36,17 @@ public: return S_OK; } DEF_RAWFUNC(Add_Int)( - /*[in]*/ long a, - /*[in]*/ long b, - /*[out,retval]*/ long * pRetVal) + /*[in]*/ int a, + /*[in]*/ int b, + /*[out,retval]*/ int * pRetVal) { *pRetVal = a + b; return S_OK; } DEF_RAWFUNC(Add_UInt)( - /*[in]*/ unsigned long a, - /*[in]*/ unsigned long b, - /*[out,retval]*/ unsigned long * pRetVal) + /*[in]*/ unsigned int a, + /*[in]*/ unsigned int b, + /*[out,retval]*/ unsigned int * pRetVal) { *pRetVal = a + b; return S_OK; @@ -114,9 +114,9 @@ public: return S_OK; } DEF_RAWFUNC(Add_Int_Ref)( - /*[in]*/ long a, - /*[in]*/ long b, - /*[in,out]*/ long * c) + /*[in]*/ int a, + /*[in]*/ int b, + /*[in,out]*/ int * c) { if (*c != std::numeric_limits::type>::max()) return E_UNEXPECTED; @@ -124,9 +124,9 @@ public: return S_OK; } DEF_RAWFUNC(Add_UInt_Ref)( - /*[in]*/ unsigned long a, - /*[in]*/ unsigned long b, - /*[in,out]*/ unsigned long * c) + /*[in]*/ unsigned int a, + /*[in]*/ unsigned int b, + /*[in,out]*/ unsigned int * c) { if (*c != std::numeric_limits::type>::max()) return E_UNEXPECTED; @@ -198,17 +198,17 @@ public: return S_OK; } DEF_RAWFUNC(Add_Int_Out)( - /*[in]*/ long a, - /*[in]*/ long b, - /*[out]*/ long * c) + /*[in]*/ int a, + /*[in]*/ int b, + /*[out]*/ int * c) { *c = a + b; return S_OK; } DEF_RAWFUNC(Add_UInt_Out)( - /*[in]*/ unsigned long a, - /*[in]*/ unsigned long b, - /*[out]*/ unsigned long * c) + /*[in]*/ unsigned int a, + /*[in]*/ unsigned int b, + /*[out]*/ unsigned int * c) { *c = a + b; return S_OK; diff --git a/src/coreclr/tests/src/Interop/COM/NativeServer/Servers.h b/src/coreclr/tests/src/Interop/COM/NativeServer/Servers.h index bcfdbe2..4f279e0 100644 --- a/src/coreclr/tests/src/Interop/COM/NativeServer/Servers.h +++ b/src/coreclr/tests/src/Interop/COM/NativeServer/Servers.h @@ -5,6 +5,7 @@ #pragma once #include +#include //#import "Server.Contract.tlb" no_namespace #include @@ -25,6 +26,29 @@ class DECLSPEC_UUID("71CF5C45-106C-4B32-B418-43A463C6041F") ErrorMarshalTesting; #define IID_IStringTesting __uuidof(IStringTesting) #define IID_IErrorMarshalTesting __uuidof(IErrorMarshalTesting) +// Class used for COM activation when using CoreShim +struct CoreShimComActivation +{ + CoreShimComActivation(_In_z_ const WCHAR *assemblyName, _In_z_ const WCHAR *typeName) + { + assert(assemblyName && typeName); + Set(assemblyName, typeName); + } + + ~CoreShimComActivation() + { + Set(nullptr, nullptr); + } + +private: + void Set(_In_opt_z_ const WCHAR *assemblyName, _In_opt_z_ const WCHAR *typeName) + { + // See CoreShim.h for usage of environment variables + ::SetEnvironmentVariableW(W("CORESHIM_COMACT_ASSEMBLYNAME"), assemblyName); + ::SetEnvironmentVariableW(W("CORESHIM_COMACT_TYPENAME"), typeName); + } +}; + #ifndef COM_CLIENT #include "ComHelpers.h" diff --git a/src/coreclr/tests/src/Interop/COM/ServerContracts/Primitives.cs b/src/coreclr/tests/src/Interop/COM/ServerContracts/Primitives.cs index cc6a303..0714047 100644 --- a/src/coreclr/tests/src/Interop/COM/ServerContracts/Primitives.cs +++ b/src/coreclr/tests/src/Interop/COM/ServerContracts/Primitives.cs @@ -51,25 +51,25 @@ namespace Server.Contract [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_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] byte[] d); + double Mean_Short_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] short[] d); + double Mean_UShort_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] ushort[] d); + double Mean_Int_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] int[] d); + double Mean_UInt_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] uint[] d); + double Mean_Long_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] long[] d); + double Mean_ULong_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] ulong[] d); + double Mean_Float_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] float[] d); + double Mean_Double_LP_PreLen(int len, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] double[] d); + + double Mean_Byte_LP_PostLen([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] byte[] d, int len); + double Mean_Short_LP_PostLen([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] short[] d, int len); + double Mean_UShort_LP_PostLen([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] ushort[] d, int len); + double Mean_Int_LP_PostLen([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] int[] d, int len); + double Mean_UInt_LP_PostLen([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] uint[] d, int len); + double Mean_Long_LP_PostLen([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] long[] d, int len); + double Mean_ULong_LP_PostLen([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] ulong[] d, int len); + double Mean_Float_LP_PostLen([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] float[] d, int len); + double Mean_Double_LP_PostLen([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] 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); diff --git a/src/coreclr/tests/src/Interop/COM/ServerContracts/Server.Contracts.tlh b/src/coreclr/tests/src/Interop/COM/ServerContracts/Server.Contracts.tlh index 9bc826d..412d352 100644 --- a/src/coreclr/tests/src/Interop/COM/ServerContracts/Server.Contracts.tlh +++ b/src/coreclr/tests/src/Interop/COM/ServerContracts/Server.Contracts.tlh @@ -49,12 +49,12 @@ INumericTesting : IUnknown 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 ); + int Add_Int ( + int a, + int b ); + unsigned int Add_UInt ( + unsigned int a, + unsigned int b ); __int64 Add_Long ( __int64 a, __int64 b ); @@ -80,13 +80,13 @@ INumericTesting : IUnknown unsigned short b, unsigned short * c ); HRESULT Add_Int_Ref ( - long a, - long b, - long * c ); + int a, + int b, + int * c ); HRESULT Add_UInt_Ref ( - unsigned long a, - unsigned long b, - unsigned long * c ); + unsigned int a, + unsigned int b, + unsigned int * c ); HRESULT Add_Long_Ref ( __int64 a, __int64 b, @@ -116,13 +116,13 @@ INumericTesting : IUnknown unsigned short b, unsigned short * c ); HRESULT Add_Int_Out ( - long a, - long b, - long * c ); + int a, + int b, + int * c ); HRESULT Add_UInt_Out ( - unsigned long a, - unsigned long b, - unsigned long * c ); + unsigned int a, + unsigned int b, + unsigned int * c ); HRESULT Add_Long_Out ( __int64 a, __int64 b, @@ -157,13 +157,13 @@ INumericTesting : IUnknown /*[in]*/ unsigned short b, /*[out,retval]*/ unsigned short * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Add_Int ( - /*[in]*/ long a, - /*[in]*/ long b, - /*[out,retval]*/ long * pRetVal ) = 0; + /*[in]*/ int a, + /*[in]*/ int b, + /*[out,retval]*/ int * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Add_UInt ( - /*[in]*/ unsigned long a, - /*[in]*/ unsigned long b, - /*[out,retval]*/ unsigned long * pRetVal ) = 0; + /*[in]*/ unsigned int a, + /*[in]*/ unsigned int b, + /*[out,retval]*/ unsigned int * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Add_Long ( /*[in]*/ __int64 a, /*[in]*/ __int64 b, @@ -193,13 +193,13 @@ INumericTesting : IUnknown /*[in]*/ unsigned short b, /*[in,out]*/ unsigned short * c ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Add_Int_Ref ( - /*[in]*/ long a, - /*[in]*/ long b, - /*[in,out]*/ long * c ) = 0; + /*[in]*/ int a, + /*[in]*/ int b, + /*[in,out]*/ int * c ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Add_UInt_Ref ( - /*[in]*/ unsigned long a, - /*[in]*/ unsigned long b, - /*[in,out]*/ unsigned long * c ) = 0; + /*[in]*/ unsigned int a, + /*[in]*/ unsigned int b, + /*[in,out]*/ unsigned int * c ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Add_Long_Ref ( /*[in]*/ __int64 a, /*[in]*/ __int64 b, @@ -229,13 +229,13 @@ INumericTesting : IUnknown /*[in]*/ unsigned short b, /*[out]*/ unsigned short * c ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Add_Int_Out ( - /*[in]*/ long a, - /*[in]*/ long b, - /*[out]*/ long * c ) = 0; + /*[in]*/ int a, + /*[in]*/ int b, + /*[out]*/ int * c ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Add_UInt_Out ( - /*[in]*/ unsigned long a, - /*[in]*/ unsigned long b, - /*[out]*/ unsigned long * c ) = 0; + /*[in]*/ unsigned int a, + /*[in]*/ unsigned int b, + /*[out]*/ unsigned int * c ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Add_Long_Out ( /*[in]*/ __int64 a, /*[in]*/ __int64 b, @@ -262,198 +262,198 @@ IArrayTesting : IUnknown // double Mean_Byte_LP_PreLen ( - long len, + int len, unsigned char * d ); double Mean_Short_LP_PreLen ( - long len, + int len, short * d ); double Mean_UShort_LP_PreLen ( - long len, + int len, unsigned short * d ); double Mean_Int_LP_PreLen ( - long len, - long * d ); + int len, + int * d ); double Mean_UInt_LP_PreLen ( - long len, - unsigned long * d ); + int len, + unsigned int * d ); double Mean_Long_LP_PreLen ( - long len, + int len, __int64 * d ); double Mean_ULong_LP_PreLen ( - long len, + int len, unsigned __int64 * d ); double Mean_Float_LP_PreLen ( - long len, + int len, float * d ); double Mean_Double_LP_PreLen ( - long len, + int len, double * d ); double Mean_Byte_LP_PostLen ( unsigned char * d, - long len ); + int len ); double Mean_Short_LP_PostLen ( short * d, - long len ); + int len ); double Mean_UShort_LP_PostLen ( unsigned short * d, - long len ); + int len ); double Mean_Int_LP_PostLen ( - long * d, - long len ); + int * d, + int len ); double Mean_UInt_LP_PostLen ( - unsigned long * d, - long len ); + unsigned int * d, + int len ); double Mean_Long_LP_PostLen ( __int64 * d, - long len ); + int len ); double Mean_ULong_LP_PostLen ( unsigned __int64 * d, - long len ); + int len ); double Mean_Float_LP_PostLen ( float * d, - long len ); + int len ); double Mean_Double_LP_PostLen ( double * d, - long len ); + int len ); double Mean_Byte_SafeArray_OutLen ( SAFEARRAY * d, - long * len ); + int * len ); double Mean_Short_SafeArray_OutLen ( SAFEARRAY * d, - long * len ); + int * len ); double Mean_UShort_SafeArray_OutLen ( SAFEARRAY * d, - long * len ); + int * len ); double Mean_Int_SafeArray_OutLen ( SAFEARRAY * d, - long * len ); + int * len ); double Mean_UInt_SafeArray_OutLen ( SAFEARRAY * d, - long * len ); + int * len ); double Mean_Long_SafeArray_OutLen ( SAFEARRAY * d, - long * len ); + int * len ); double Mean_ULong_SafeArray_OutLen ( SAFEARRAY * d, - long * len ); + int * len ); double Mean_Float_SafeArray_OutLen ( SAFEARRAY * d, - long * len ); + int * len ); double Mean_Double_SafeArray_OutLen ( SAFEARRAY * d, - long * len ); + int * len ); // // Raw methods provided by interface // virtual HRESULT STDMETHODCALLTYPE raw_Mean_Byte_LP_PreLen ( - /*[in]*/ long len, + /*[in]*/ int len, /*[in]*/ unsigned char * d, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_Short_LP_PreLen ( - /*[in]*/ long len, + /*[in]*/ int len, /*[in]*/ short * d, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_UShort_LP_PreLen ( - /*[in]*/ long len, + /*[in]*/ int len, /*[in]*/ unsigned short * d, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_Int_LP_PreLen ( - /*[in]*/ long len, - /*[in]*/ long * d, + /*[in]*/ int len, + /*[in]*/ int * d, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_UInt_LP_PreLen ( - /*[in]*/ long len, - /*[in]*/ unsigned long * d, + /*[in]*/ int len, + /*[in]*/ unsigned int * d, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_Long_LP_PreLen ( - /*[in]*/ long len, + /*[in]*/ int len, /*[in]*/ __int64 * d, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_ULong_LP_PreLen ( - /*[in]*/ long len, + /*[in]*/ int len, /*[in]*/ unsigned __int64 * d, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_Float_LP_PreLen ( - /*[in]*/ long len, + /*[in]*/ int len, /*[in]*/ float * d, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_Double_LP_PreLen ( - /*[in]*/ long len, + /*[in]*/ int len, /*[in]*/ double * d, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_Byte_LP_PostLen ( /*[in]*/ unsigned char * d, - /*[in]*/ long len, + /*[in]*/ int len, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_Short_LP_PostLen ( /*[in]*/ short * d, - /*[in]*/ long len, + /*[in]*/ int len, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_UShort_LP_PostLen ( /*[in]*/ unsigned short * d, - /*[in]*/ long len, + /*[in]*/ int len, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_Int_LP_PostLen ( - /*[in]*/ long * d, - /*[in]*/ long len, + /*[in]*/ int * d, + /*[in]*/ int len, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_UInt_LP_PostLen ( - /*[in]*/ unsigned long * d, - /*[in]*/ long len, + /*[in]*/ unsigned int * d, + /*[in]*/ int len, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_Long_LP_PostLen ( /*[in]*/ __int64 * d, - /*[in]*/ long len, + /*[in]*/ int len, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_ULong_LP_PostLen ( /*[in]*/ unsigned __int64 * d, - /*[in]*/ long len, + /*[in]*/ int len, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_Float_LP_PostLen ( /*[in]*/ float * d, - /*[in]*/ long len, + /*[in]*/ int len, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_Double_LP_PostLen ( /*[in]*/ double * d, - /*[in]*/ long len, + /*[in]*/ int len, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_Byte_SafeArray_OutLen ( /*[in]*/ SAFEARRAY * d, - /*[out]*/ long * len, + /*[out]*/ int * len, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_Short_SafeArray_OutLen ( /*[in]*/ SAFEARRAY * d, - /*[out]*/ long * len, + /*[out]*/ int * len, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_UShort_SafeArray_OutLen ( /*[in]*/ SAFEARRAY * d, - /*[out]*/ long * len, + /*[out]*/ int * len, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_Int_SafeArray_OutLen ( /*[in]*/ SAFEARRAY * d, - /*[out]*/ long * len, + /*[out]*/ int * len, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_UInt_SafeArray_OutLen ( /*[in]*/ SAFEARRAY * d, - /*[out]*/ long * len, + /*[out]*/ int * len, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_Long_SafeArray_OutLen ( /*[in]*/ SAFEARRAY * d, - /*[out]*/ long * len, + /*[out]*/ int * len, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_ULong_SafeArray_OutLen ( /*[in]*/ SAFEARRAY * d, - /*[out]*/ long * len, + /*[out]*/ int * len, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_Float_SafeArray_OutLen ( /*[in]*/ SAFEARRAY * d, - /*[out]*/ long * len, + /*[out]*/ int * len, /*[out,retval]*/ double * pRetVal ) = 0; virtual HRESULT STDMETHODCALLTYPE raw_Mean_Double_SafeArray_OutLen ( /*[in]*/ SAFEARRAY * d, - /*[out]*/ long * len, + /*[out]*/ int * len, /*[out,retval]*/ double * pRetVal ) = 0; }; @@ -635,16 +635,16 @@ IErrorMarshalTesting : IUnknown // HRESULT Throw_HResult ( - long hresultToReturn ); + int hresultToReturn ); // // Raw methods provided by interface // virtual HRESULT STDMETHODCALLTYPE raw_Throw_HResult ( - /*[in]*/ long hresultToReturn ) = 0; - virtual long STDMETHODCALLTYPE Return_As_HResult ( - /*[in]*/ long hresultToReturn ) = 0; + /*[in]*/ int hresultToReturn ) = 0; + virtual int STDMETHODCALLTYPE Return_As_HResult ( + /*[in]*/ int hresultToReturn ) = 0; }; // diff --git a/src/coreclr/tests/src/Interop/COM/ServerContracts/Server.Contracts.tli b/src/coreclr/tests/src/Interop/COM/ServerContracts/Server.Contracts.tli index a419c65..94046af 100644 --- a/src/coreclr/tests/src/Interop/COM/ServerContracts/Server.Contracts.tli +++ b/src/coreclr/tests/src/Interop/COM/ServerContracts/Server.Contracts.tli @@ -27,15 +27,15 @@ inline unsigned short INumericTesting::Add_UShort ( unsigned short a, unsigned s return _result; } -inline long INumericTesting::Add_Int ( long a, long b ) { - long _result = 0; +inline int INumericTesting::Add_Int ( int a, int b ) { + int _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; +inline unsigned int INumericTesting::Add_UInt ( unsigned int a, unsigned int b ) { + unsigned int _result = 0; HRESULT _hr = raw_Add_UInt(a, b, &_result); if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); return _result; @@ -87,13 +87,13 @@ inline HRESULT INumericTesting::Add_UShort_Ref ( unsigned short a, unsigned shor return _hr; } -inline HRESULT INumericTesting::Add_Int_Ref ( long a, long b, long * c ) { +inline HRESULT INumericTesting::Add_Int_Ref ( int a, int b, int * 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 ) { +inline HRESULT INumericTesting::Add_UInt_Ref ( unsigned int a, unsigned int b, unsigned int * c ) { HRESULT _hr = raw_Add_UInt_Ref(a, b, c); if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); return _hr; @@ -141,13 +141,13 @@ inline HRESULT INumericTesting::Add_UShort_Out ( unsigned short a, unsigned shor return _hr; } -inline HRESULT INumericTesting::Add_Int_Out ( long a, long b, long * c ) { +inline HRESULT INumericTesting::Add_Int_Out ( int a, int b, int * 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 ) { +inline HRESULT INumericTesting::Add_UInt_Out ( unsigned int a, unsigned int b, unsigned int * c ) { HRESULT _hr = raw_Add_UInt_Out(a, b, c); if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); return _hr; @@ -181,189 +181,189 @@ inline HRESULT INumericTesting::Add_Double_Out ( double a, double b, double * c // interface IArrayTesting wrapper method implementations // -inline double IArrayTesting::Mean_Byte_LP_PreLen ( long len, unsigned char * d ) { +inline double IArrayTesting::Mean_Byte_LP_PreLen ( int 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 ) { +inline double IArrayTesting::Mean_Short_LP_PreLen ( int 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 ) { +inline double IArrayTesting::Mean_UShort_LP_PreLen ( int 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 ) { +inline double IArrayTesting::Mean_Int_LP_PreLen ( int len, int * 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 ) { +inline double IArrayTesting::Mean_UInt_LP_PreLen ( int len, unsigned int * 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 ) { +inline double IArrayTesting::Mean_Long_LP_PreLen ( int 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 ) { +inline double IArrayTesting::Mean_ULong_LP_PreLen ( int 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 ) { +inline double IArrayTesting::Mean_Float_LP_PreLen ( int 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 ) { +inline double IArrayTesting::Mean_Double_LP_PreLen ( int 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 ) { +inline double IArrayTesting::Mean_Byte_LP_PostLen ( unsigned char * d, int 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 ) { +inline double IArrayTesting::Mean_Short_LP_PostLen ( short * d, int 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 ) { +inline double IArrayTesting::Mean_UShort_LP_PostLen ( unsigned short * d, int 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 ) { +inline double IArrayTesting::Mean_Int_LP_PostLen ( int * d, int 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 ) { +inline double IArrayTesting::Mean_UInt_LP_PostLen ( unsigned int * d, int 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 ) { +inline double IArrayTesting::Mean_Long_LP_PostLen ( __int64 * d, int 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 ) { +inline double IArrayTesting::Mean_ULong_LP_PostLen ( unsigned __int64 * d, int 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 ) { +inline double IArrayTesting::Mean_Float_LP_PostLen ( float * d, int 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 ) { +inline double IArrayTesting::Mean_Double_LP_PostLen ( double * d, int 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 ) { +inline double IArrayTesting::Mean_Byte_SafeArray_OutLen ( SAFEARRAY * d, int * 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 ) { +inline double IArrayTesting::Mean_Short_SafeArray_OutLen ( SAFEARRAY * d, int * 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 ) { +inline double IArrayTesting::Mean_UShort_SafeArray_OutLen ( SAFEARRAY * d, int * 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 ) { +inline double IArrayTesting::Mean_Int_SafeArray_OutLen ( SAFEARRAY * d, int * 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 ) { +inline double IArrayTesting::Mean_UInt_SafeArray_OutLen ( SAFEARRAY * d, int * 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 ) { +inline double IArrayTesting::Mean_Long_SafeArray_OutLen ( SAFEARRAY * d, int * 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 ) { +inline double IArrayTesting::Mean_ULong_SafeArray_OutLen ( SAFEARRAY * d, int * 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 ) { +inline double IArrayTesting::Mean_Float_SafeArray_OutLen ( SAFEARRAY * d, int * 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 ) { +inline double IArrayTesting::Mean_Double_SafeArray_OutLen ( SAFEARRAY * d, int * len ) { double _result = 0; HRESULT _hr = raw_Mean_Double_SafeArray_OutLen(d, len, &_result); if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); @@ -564,7 +564,7 @@ inline HRESULT IStringTesting::Reverse_BStr_OutAttr ( _bstr_t a, _bstr_t b ) { // interface IErrorMarshalTesting wrapper method implementations // -inline HRESULT IErrorMarshalTesting::Throw_HResult ( long hresultToReturn ) { +inline HRESULT IErrorMarshalTesting::Throw_HResult ( int hresultToReturn ) { HRESULT _hr = raw_Throw_HResult(hresultToReturn); if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this)); return _hr; diff --git a/src/coreclr/tests/src/Interop/Interop.settings.targets b/src/coreclr/tests/src/Interop/Interop.settings.targets index 50e37af..df05c15 100644 --- a/src/coreclr/tests/src/Interop/Interop.settings.targets +++ b/src/coreclr/tests/src/Interop/Interop.settings.targets @@ -1,6 +1,7 @@ + $(MSBuildThisFileDirectory)common/ @@ -9,6 +10,6 @@ - + diff --git a/src/coreclr/tests/src/Interop/common/ExeLauncherProgram.cs b/src/coreclr/tests/src/Interop/common/ExeLauncherProgram.cs new file mode 100644 index 0000000..7f643f3 --- /dev/null +++ b/src/coreclr/tests/src/Interop/common/ExeLauncherProgram.cs @@ -0,0 +1,69 @@ +// 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.Diagnostics; +using System.IO; +using System.Reflection; + +/// +/// This class is used for creating a test that has an entry point +/// that is not the test itself. For example a test that starts from +/// a native exe instead of a managed entry point. +/// +public class Program +{ + static int Main(string[] noArgs) + { + if (Environment.OSVersion.Platform != PlatformID.Win32NT) + { + Console.WriteLine($"Exe launcher only supported on Windows environments..."); + return 100; + } + + string workingDir = Environment.CurrentDirectory; + Console.WriteLine($"Searching for exe to launch in {workingDir}..."); + + Assembly thisAssem = Assembly.GetEntryAssembly(); + string startExe = string.Empty; + foreach (string exeMaybe in Directory.EnumerateFiles(workingDir, "*.exe")) + { + // This entry point is _not_ an option + if (exeMaybe.Equals(thisAssem.Location, StringComparison.OrdinalIgnoreCase)) + { + continue; + } + + startExe = exeMaybe; + break; + } + + if (string.IsNullOrEmpty(startExe)) + { + throw new Exception("Unable to find start EXE"); + } + + var startInfo = new ProcessStartInfo() + { + FileName = startExe, + + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true + }; + + Console.WriteLine($"Launching '{startExe}'..."); + using (Process p = Process.Start(startInfo)) + { + p.OutputDataReceived += (_, args) => Console.WriteLine(args.Data); + p.BeginOutputReadLine(); + + p.ErrorDataReceived += (_, args) => Console.Error.WriteLine(args.Data); + p.BeginErrorReadLine(); + + p.WaitForExit(); + return p.ExitCode; + } + } +} \ No newline at end of file diff --git a/src/coreclr/tests/src/Interop/common/xplatform.h b/src/coreclr/tests/src/Interop/common/xplatform.h index e0b939e..94a693e 100644 --- a/src/coreclr/tests/src/Interop/common/xplatform.h +++ b/src/coreclr/tests/src/Interop/common/xplatform.h @@ -36,6 +36,7 @@ // include #ifdef _WIN32 + #define NOMINMAX #include #include @@ -95,6 +96,28 @@ inline void CoreClrFree(void *p) #endif } +inline void *CoreClrBstrAlloc(size_t cb) +{ +#ifdef _WIN32 + // A null is automatically applied in the SysAllocStringByteLen API. + // Remove a single OLECHAR for the implied null. + // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/api/oleauto/nf-oleauto-sysallocstringbytelen + if (cb >= sizeof(OLECHAR)) + cb -= sizeof(OLECHAR); + + return ::SysAllocStringByteLen(nullptr, static_cast(cb)); +#else + return nullptr; +#endif +} + +inline void CoreClrBstrFree(void *p) +{ +#ifdef _WIN32 + return ::SysFreeString((BSTR)p); +#endif +} + // redirected types not-windows only #ifndef _WIN32 -- 2.7.4