summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorAaron Robinson <arobins@microsoft.com>2019-03-01 22:53:42 -0800
committerGitHub <noreply@github.com>2019-03-01 22:53:42 -0800
commit9e66e140f09b32694b32b98c34d8948bdf3608a3 (patch)
tree889cd9899cb7ff7c3141475db7df48342aeaf773 /tests
parent42bc2de2c63fe0c95a582e642ff97b2fe0d4bb7e (diff)
downloadcoreclr-9e66e140f09b32694b32b98c34d8948bdf3608a3.tar.gz
coreclr-9e66e140f09b32694b32b98c34d8948bdf3608a3.tar.bz2
coreclr-9e66e140f09b32694b32b98c34d8948bdf3608a3.zip
Support IClassFactory2 - LicenseManager use in COM activation (#22846)
* Implement IClassFactory2 * Add test support for IClassFactory2 * Add support for testing RCW activation via IClassFactory2
Diffstat (limited to 'tests')
-rw-r--r--tests/issues.targets6
-rw-r--r--tests/src/Interop/CMakeLists.txt1
-rw-r--r--tests/src/Interop/COM/NETClients/Licensing/App.manifest18
-rw-r--r--tests/src/Interop/COM/NETClients/Licensing/NETClientLicense.csproj42
-rw-r--r--tests/src/Interop/COM/NETClients/Licensing/Program.cs147
-rw-r--r--tests/src/Interop/COM/NETServer/LicenseTesting.cs77
-rw-r--r--tests/src/Interop/COM/NETServer/NETServer.csproj1
-rw-r--r--tests/src/Interop/COM/NativeClients/Licensing.csproj23
-rw-r--r--tests/src/Interop/COM/NativeClients/Licensing/App.manifest17
-rw-r--r--tests/src/Interop/COM/NativeClients/Licensing/CMakeLists.txt19
-rw-r--r--tests/src/Interop/COM/NativeClients/Licensing/CoreShim.X.manifest16
-rw-r--r--tests/src/Interop/COM/NativeClients/Licensing/LicenseTests.cpp150
-rw-r--r--tests/src/Interop/COM/NativeServer/COMNativeServer.X.manifest5
-rw-r--r--tests/src/Interop/COM/NativeServer/LicenseTesting.h77
-rw-r--r--tests/src/Interop/COM/NativeServer/Servers.cpp3
-rw-r--r--tests/src/Interop/COM/NativeServer/Servers.h4
-rw-r--r--tests/src/Interop/COM/ServerContracts/NativeServers.cs19
-rw-r--r--tests/src/Interop/COM/ServerContracts/Server.Contracts.cs13
-rw-r--r--tests/src/Interop/COM/ServerContracts/Server.Contracts.h13
-rw-r--r--tests/src/Interop/COM/ServerContracts/ServerGuids.cs1
-rw-r--r--tests/src/Interop/common/ComHelpers.h100
21 files changed, 752 insertions, 0 deletions
diff --git a/tests/issues.targets b/tests/issues.targets
index a575498576..020caf07b6 100644
--- a/tests/issues.targets
+++ b/tests/issues.targets
@@ -299,12 +299,18 @@
<ExcludeList Include="$(XunitTestBinBase)/Interop/COM/NativeClients/Primitives/*">
<Issue>20682</Issue>
</ExcludeList>
+ <ExcludeList Include="$(XunitTestBinBase)/Interop/COM/NativeClients/Licensing/*">
+ <Issue>20682</Issue>
+ </ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/Interop/COM/NETClients/IDispatch/NETClientIDispatch/*">
<Issue>20682</Issue>
</ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/Interop/COM/NETClients/Aggregation/NETClientAggregation/*">
<Issue>20682</Issue>
</ExcludeList>
+ <ExcludeList Include="$(XunitTestBinBase)/Interop/COM/NETClients/Licensing/NETClientLicense/*">
+ <Issue>20682</Issue>
+ </ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/Interop/COM/NETClients/Events/NETClientEvents/*">
<Issue>22784</Issue>
</ExcludeList>
diff --git a/tests/src/Interop/CMakeLists.txt b/tests/src/Interop/CMakeLists.txt
index 106ef1f58e..66124deb93 100644
--- a/tests/src/Interop/CMakeLists.txt
+++ b/tests/src/Interop/CMakeLists.txt
@@ -81,6 +81,7 @@ if(WIN32)
add_subdirectory(ArrayMarshalling/SafeArray)
add_subdirectory(COM/NativeServer)
add_subdirectory(COM/NativeClients/Primitives)
+ add_subdirectory(COM/NativeClients/Licensing)
add_subdirectory(IJW/FakeMscoree)
# IJW isn't supported on ARM64
diff --git a/tests/src/Interop/COM/NETClients/Licensing/App.manifest b/tests/src/Interop/COM/NETClients/Licensing/App.manifest
new file mode 100644
index 0000000000..c0181f3827
--- /dev/null
+++ b/tests/src/Interop/COM/NETClients/Licensing/App.manifest
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
+ <assemblyIdentity
+ type="win32"
+ name="NetClientLicensing"
+ version="1.0.0.0" />
+
+ <dependency>
+ <dependentAssembly>
+ <!-- RegFree COM -->
+ <assemblyIdentity
+ type="win32"
+ name="COMNativeServer.X"
+ version="1.0.0.0"/>
+ </dependentAssembly>
+ </dependency>
+
+</assembly>
diff --git a/tests/src/Interop/COM/NETClients/Licensing/NETClientLicense.csproj b/tests/src/Interop/COM/NETClients/Licensing/NETClientLicense.csproj
new file mode 100644
index 0000000000..52154225c4
--- /dev/null
+++ b/tests/src/Interop/COM/NETClients/Licensing/NETClientLicense.csproj
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <AssemblyName>NETClientLicense</AssemblyName>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{85C57688-DA98-4DE3-AC9B-526E4747434C}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <ProjectTypeGuids>{209912F9-0DA1-4184-9CC1-8D583BAF4A28};{87799F5D-CEBD-499D-BDBA-B2C6105CD766}</ProjectTypeGuids>
+ <ApplicationManifest>App.manifest</ApplicationManifest>
+
+ <!-- Blocked on ILAsm supporting embedding resources. See https://github.com/dotnet/coreclr/issues/20819 -->
+ <IlrtTestKind>BuildOnly</IlrtTestKind>
+
+ <!-- Blocked on CrossGen.exe supporting embedding resources. See https://github.com/dotnet/coreclr/issues/21006 -->
+ <CrossGenTest>false</CrossGenTest>
+
+ <!-- Test unsupported outside of windows -->
+ <TestUnsupportedOutsideWindows>true</TestUnsupportedOutsideWindows>
+ <DisableProjectBuild Condition="'$(TargetsUnix)' == 'true'">true</DisableProjectBuild>
+ <!-- This test would require the runincontext.exe to include App.manifest describing the COM interfaces -->
+ <UnloadabilityIncompatible>true</UnloadabilityIncompatible>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="Program.cs" />
+ <Compile Include="../../ServerContracts/NativeServers.cs" />
+ <Compile Include="../../ServerContracts/Server.Contracts.cs" />
+ <Compile Include="../../ServerContracts/ServerGuids.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="../../NativeServer/CMakeLists.txt" />
+ <ProjectReference Include="../../../../Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/tests/src/Interop/COM/NETClients/Licensing/Program.cs b/tests/src/Interop/COM/NETClients/Licensing/Program.cs
new file mode 100644
index 0000000000..68ac88184d
--- /dev/null
+++ b/tests/src/Interop/COM/NETClients/Licensing/Program.cs
@@ -0,0 +1,147 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace NetClient
+{
+ using System;
+ using System.Collections.Generic;
+ using System.ComponentModel;
+ using System.Reflection;
+ using System.Runtime.InteropServices;
+
+ using TestLibrary;
+ using Server.Contract;
+ using Server.Contract.Servers;
+
+ class Program
+ {
+ static readonly string DefaultLicKey = "__MOCK_LICENSE_KEY__";
+ static void ActivateLicensedObject()
+ {
+ Console.WriteLine($"Calling {nameof(ActivateLicensedObject)}...");
+
+ // Validate activation
+ var licenseTesting = (LicenseTesting)new LicenseTestingClass();
+
+ // Validate license denial
+ licenseTesting.SetNextDenyLicense(true);
+ try
+ {
+ var tmp = (LicenseTesting)new LicenseTestingClass();
+ Assert.Fail("Activation of licensed class should fail");
+ }
+ catch (COMException e)
+ {
+ const int CLASS_E_NOTLICENSED = unchecked((int)0x80040112);
+ Assert.AreEqual(CLASS_E_NOTLICENSED, e.HResult);
+ }
+ finally
+ {
+ licenseTesting.SetNextDenyLicense(false);
+ }
+ }
+
+ class MockLicenseContext : LicenseContext
+ {
+ private readonly Type _type;
+ private string _key;
+
+ public MockLicenseContext(Type type, LicenseUsageMode mode)
+ {
+ UsageMode = mode;
+ _type = type;
+ }
+
+ public override LicenseUsageMode UsageMode { get; }
+
+ public override string GetSavedLicenseKey(Type type, Assembly resourceAssembly)
+ {
+ if (type == _type)
+ {
+ return _key;
+ }
+
+ return null;
+ }
+
+ public override void SetSavedLicenseKey(Type type, string key)
+ {
+ if (type == _type)
+ {
+ _key = key;
+ }
+ }
+ }
+
+ static void ActivateUnderDesigntimeContext()
+ {
+ Console.WriteLine($"Calling {nameof(ActivateUnderDesigntimeContext)}...");
+
+ LicenseContext prev = LicenseManager.CurrentContext;
+ try
+ {
+ string licKey = "__TEST__";
+ LicenseManager.CurrentContext = new MockLicenseContext(typeof(LicenseTestingClass), LicenseUsageMode.Designtime);
+ LicenseManager.CurrentContext.SetSavedLicenseKey(typeof(LicenseTestingClass), licKey);
+
+ var licenseTesting = (LicenseTesting)new LicenseTestingClass();
+
+ // During design time the IClassFactory::CreateInstance will be called - no license
+ Assert.AreEqual(null, licenseTesting.GetLicense());
+
+ // Verify the value retrieved from the IClassFactory2::RequestLicKey was what was set
+ Assert.AreEqual(DefaultLicKey, LicenseManager.CurrentContext.GetSavedLicenseKey(typeof(LicenseTestingClass), resourceAssembly: null));
+ }
+ finally
+ {
+ LicenseManager.CurrentContext = prev;
+ }
+ }
+
+ static void ActivateUnderRuntimeContext()
+ {
+ Console.WriteLine($"Calling {nameof(ActivateUnderRuntimeContext)}...");
+
+ LicenseContext prev = LicenseManager.CurrentContext;
+ try
+ {
+ string licKey = "__TEST__";
+ LicenseManager.CurrentContext = new MockLicenseContext(typeof(LicenseTestingClass), LicenseUsageMode.Runtime);
+ LicenseManager.CurrentContext.SetSavedLicenseKey(typeof(LicenseTestingClass), licKey);
+
+ var licenseTesting = (LicenseTesting)new LicenseTestingClass();
+
+ // During runtime the IClassFactory::CreateInstance2 will be called with license from context
+ Assert.AreEqual(licKey, licenseTesting.GetLicense());
+ }
+ finally
+ {
+ LicenseManager.CurrentContext = prev;
+ }
+ }
+
+ static int Main(string[] doNotUse)
+ {
+ // RegFree COM is not supported on Windows Nano
+ if (Utilities.IsWindowsNanoServer)
+ {
+ return 100;
+ }
+
+ try
+ {
+ ActivateLicensedObject();
+ ActivateUnderDesigntimeContext();
+ ActivateUnderRuntimeContext();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine($"Test Failure: {e}");
+ return 101;
+ }
+
+ return 100;
+ }
+ }
+}
diff --git a/tests/src/Interop/COM/NETServer/LicenseTesting.cs b/tests/src/Interop/COM/NETServer/LicenseTesting.cs
new file mode 100644
index 0000000000..e55ad8ac66
--- /dev/null
+++ b/tests/src/Interop/COM/NETServer/LicenseTesting.cs
@@ -0,0 +1,77 @@
+// 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.ComponentModel;
+using System.Runtime.InteropServices;
+
+[ComVisible(true)]
+[Guid(Server.Contract.Guids.LicenseTesting)]
+[LicenseProvider(typeof(MockLicenseProvider))]
+public class LicenseTesting : Server.Contract.ILicenseTesting
+{
+ public LicenseTesting()
+ {
+ LicenseManager.Validate(typeof(LicenseTesting), this);
+ }
+
+ public string LicenseUsed { get; set; }
+
+ void Server.Contract.ILicenseTesting.SetNextDenyLicense(bool denyLicense)
+ {
+ MockLicenseProvider.DenyLicense = denyLicense;
+ }
+
+ void Server.Contract.ILicenseTesting.SetNextLicense(string lic)
+ {
+ MockLicenseProvider.License = lic;
+ }
+
+ string Server.Contract.ILicenseTesting.GetLicense()
+ {
+ return LicenseUsed;
+ }
+}
+
+public class MockLicenseProvider : LicenseProvider
+{
+ public static bool DenyLicense { get; set; }
+ public static string License { get; set; }
+
+ public override License GetLicense(LicenseContext context, Type type, object instance, bool allowExceptions)
+ {
+ if (DenyLicense)
+ {
+ if (allowExceptions)
+ {
+ throw new LicenseException(type);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ if (type != typeof(LicenseTesting))
+ {
+ throw new Exception();
+ }
+
+ var lic = new MockLicense();
+
+ if (instance != null)
+ {
+ ((LicenseTesting)instance).LicenseUsed = lic.LicenseKey;
+ }
+
+ return lic;
+ }
+
+ private class MockLicense : License
+ {
+ public override string LicenseKey => MockLicenseProvider.License ?? "__MOCK_LICENSE_KEY__";
+
+ public override void Dispose () { }
+ }
+}
diff --git a/tests/src/Interop/COM/NETServer/NETServer.csproj b/tests/src/Interop/COM/NETServer/NETServer.csproj
index 3548ea1bf1..aa4e791a6c 100644
--- a/tests/src/Interop/COM/NETServer/NETServer.csproj
+++ b/tests/src/Interop/COM/NETServer/NETServer.csproj
@@ -23,6 +23,7 @@
<Compile Include="StringTesting.cs" />
<Compile Include="ErrorMarshalTesting.cs" />
<Compile Include="ColorTesting.cs" />
+ <Compile Include="LicenseTesting.cs" />
<Compile Include="../ServerContracts/Server.Contracts.cs" />
<Compile Include="../ServerContracts/ServerGuids.cs" />
</ItemGroup>
diff --git a/tests/src/Interop/COM/NativeClients/Licensing.csproj b/tests/src/Interop/COM/NativeClients/Licensing.csproj
new file mode 100644
index 0000000000..dba48db706
--- /dev/null
+++ b/tests/src/Interop/COM/NativeClients/Licensing.csproj
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Interop.settings.targets))\Interop.settings.targets" />
+ <PropertyGroup>
+ <IgnoreCoreCLRTestLibraryDependency>true</IgnoreCoreCLRTestLibraryDependency>
+ <CLRTestScriptLocalCoreShim>true</CLRTestScriptLocalCoreShim>
+
+ <TestUnsupportedOutsideWindows>true</TestUnsupportedOutsideWindows>
+ <DisableProjectBuild Condition="'$(TargetsUnix)' == 'true'">true</DisableProjectBuild>
+ <DefineConstants>BLOCK_WINDOWS_NANO</DefineConstants>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="$(InteropCommonDir)ExeLauncherProgram.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="Licensing/CMakeLists.txt" />
+ <ProjectReference Include="../NetServer/NetServer.csproj" />
+ <ProjectReference Include="../../../Common/hostpolicymock/CMakeLists.txt" />
+ <ProjectReference Include="../../../Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project> \ No newline at end of file
diff --git a/tests/src/Interop/COM/NativeClients/Licensing/App.manifest b/tests/src/Interop/COM/NativeClients/Licensing/App.manifest
new file mode 100644
index 0000000000..613f8bf63b
--- /dev/null
+++ b/tests/src/Interop/COM/NativeClients/Licensing/App.manifest
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+ <assemblyIdentity
+ type="win32"
+ name="COMClientLicensing"
+ version="1.0.0.0"/>
+
+ <dependency>
+ <dependentAssembly>
+ <!-- RegFree COM - CoreCLR Shim -->
+ <assemblyIdentity
+ type="win32"
+ name="CoreShim.X"
+ version="1.0.0.0"/>
+ </dependentAssembly>
+ </dependency>
+</assembly> \ No newline at end of file
diff --git a/tests/src/Interop/COM/NativeClients/Licensing/CMakeLists.txt b/tests/src/Interop/COM/NativeClients/Licensing/CMakeLists.txt
new file mode 100644
index 0000000000..237b614268
--- /dev/null
+++ b/tests/src/Interop/COM/NativeClients/Licensing/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required (VERSION 2.6)
+
+project (COMClientLicensing)
+include_directories( ${INC_PLATFORM_DIR} )
+include_directories( "../../ServerContracts" )
+include_directories( "../../NativeServer" )
+set(SOURCES
+ LicenseTests.cpp
+ App.manifest)
+
+# add the executable
+add_executable (COMClientLicensing ${SOURCES})
+target_link_libraries(COMClientLicensing ${LINK_LIBRARIES_ADDITIONAL})
+
+# Copy CoreShim manifest to project output
+file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/CoreShim.X.manifest INPUT ${CMAKE_CURRENT_SOURCE_DIR}/CoreShim.X.manifest)
+
+# add the install targets
+install (TARGETS COMClientLicensing DESTINATION bin)
diff --git a/tests/src/Interop/COM/NativeClients/Licensing/CoreShim.X.manifest b/tests/src/Interop/COM/NativeClients/Licensing/CoreShim.X.manifest
new file mode 100644
index 0000000000..27479e25ea
--- /dev/null
+++ b/tests/src/Interop/COM/NativeClients/Licensing/CoreShim.X.manifest
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+
+<assemblyIdentity
+ type="win32"
+ name="CoreShim.X"
+ version="1.0.0.0" />
+
+<file name="CoreShim.dll">
+ <!-- LicenseTesting -->
+ <comClass
+ clsid="{66DB7882-E2B0-471D-92C7-B2B52A0EA535}"
+ threadingModel="Both" />
+</file>
+
+</assembly>
diff --git a/tests/src/Interop/COM/NativeClients/Licensing/LicenseTests.cpp b/tests/src/Interop/COM/NativeClients/Licensing/LicenseTests.cpp
new file mode 100644
index 0000000000..8fbff01121
--- /dev/null
+++ b/tests/src/Interop/COM/NativeClients/Licensing/LicenseTests.cpp
@@ -0,0 +1,150 @@
+// 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 <xplatform.h>
+#include <cassert>
+#include <Server.Contracts.h>
+
+// COM headers
+#include <objbase.h>
+#include <combaseapi.h>
+
+#define COM_CLIENT
+#include <Servers.h>
+
+#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<COINIT TM>
+struct ComInit
+{
+ const HRESULT Result;
+
+ ComInit()
+ : Result{ ::CoInitializeEx(nullptr, TM) }
+ { }
+
+ ~ComInit()
+ {
+ if (SUCCEEDED(Result))
+ ::CoUninitialize();
+ }
+};
+
+using ComMTA = ComInit<COINIT_MULTITHREADED>;
+
+void ActivateViaCoCreateInstance();
+void ActivateViaCoGetClassObject();
+
+int __cdecl main()
+{
+ ComMTA init;
+ if (FAILED(init.Result))
+ return -1;
+
+ try
+ {
+ CoreShimComActivation csact{ W("NETServer"), W("LicenseTesting") };
+
+ ActivateViaCoCreateInstance();
+ ActivateViaCoGetClassObject();
+ }
+ catch (HRESULT hr)
+ {
+ ::printf("Test Failure: 0x%08x\n", hr);
+ return 101;
+ }
+
+ return 100;
+}
+
+void ActivateViaCoCreateInstance()
+{
+ ::printf("License test through CoCreateInstance...\n");
+
+ HRESULT hr;
+
+ ILicenseTesting *licenseTesting;
+ THROW_IF_FAILED(::CoCreateInstance(CLSID_LicenseTesting, nullptr, CLSCTX_INPROC, IID_ILicenseTesting, (void**)&licenseTesting));
+ THROW_IF_FAILED(licenseTesting->SetNextDenyLicense(VARIANT_TRUE));
+
+ ILicenseTesting *failToCreate = nullptr;
+ hr = ::CoCreateInstance(CLSID_LicenseTesting, nullptr, CLSCTX_INPROC, IID_ILicenseTesting, (void**)&failToCreate);
+ if (hr != CLASS_E_NOTLICENSED || failToCreate != nullptr)
+ {
+ ::printf("Should fail to activate without license: %#08x\n", hr);
+ throw E_FAIL;
+ }
+
+ // Reset the environment
+ licenseTesting->SetNextDenyLicense(VARIANT_FALSE);
+ licenseTesting->Release();
+}
+
+void ActivateViaCoGetClassObject()
+{
+ ::printf("License test through CoGetClassObject...\n");
+
+ HRESULT hr;
+
+ IClassFactory2 *factory;
+ THROW_IF_FAILED(::CoGetClassObject(CLSID_LicenseTesting, CLSCTX_INPROC, nullptr, IID_IClassFactory2, (void**)&factory));
+
+ // Validate license info
+ LICINFO info;
+ THROW_IF_FAILED(factory->GetLicInfo(&info));
+ THROW_FAIL_IF_FALSE(info.fLicVerified != FALSE);
+ THROW_FAIL_IF_FALSE(info.fRuntimeKeyAvail == FALSE); // Have not populated the cache
+
+ // Initialize to default key.
+ LPCOLESTR key = W("__MOCK_LICENSE_KEY__");
+
+ // Validate license key
+ BSTR lic;
+ THROW_IF_FAILED(factory->RequestLicKey(0, &lic));
+ THROW_FAIL_IF_FALSE(::CompareStringOrdinal(lic, -1, key, -1, FALSE) == CSTR_EQUAL);
+
+ // Create instance
+ IUnknown *test;
+ THROW_IF_FAILED(factory->CreateInstanceLic(nullptr, nullptr, IID_IUnknown, lic, (void**)&test));
+ CoreClrBStrFree(lic);
+
+ ILicenseTesting *licenseTesting;
+ THROW_IF_FAILED(test->QueryInterface(&licenseTesting));
+ test->Release();
+
+ // Validate license key used
+ BSTR licMaybe;
+ THROW_IF_FAILED(licenseTesting->GetLicense(&licMaybe));
+ THROW_FAIL_IF_FALSE(::CompareStringOrdinal(licMaybe, -1, key, -1, FALSE) == CSTR_EQUAL);
+ CoreClrBStrFree(licMaybe);
+ licMaybe = nullptr;
+
+ // Set new license key
+ key = W("__TEST__");
+ THROW_IF_FAILED(licenseTesting->SetNextLicense(key));
+
+ // Free previous instance
+ licenseTesting->Release();
+
+ // Create instance and validate key used
+ THROW_IF_FAILED(factory->RequestLicKey(0, &lic));
+ THROW_FAIL_IF_FALSE(::CompareStringOrdinal(lic, -1, key, -1, FALSE) == CSTR_EQUAL);
+
+ test = nullptr;
+ THROW_IF_FAILED(factory->CreateInstanceLic(nullptr, nullptr, IID_IUnknown, lic, (void**)&test));
+ CoreClrBStrFree(lic);
+
+ licenseTesting = nullptr;
+ THROW_IF_FAILED(test->QueryInterface(&licenseTesting));
+ test->Release();
+
+ // Validate license key used
+ THROW_IF_FAILED(licenseTesting->GetLicense(&licMaybe));
+ THROW_FAIL_IF_FALSE(::CompareStringOrdinal(licMaybe, -1, key, -1, FALSE) == CSTR_EQUAL);
+ CoreClrBStrFree(licMaybe);
+
+ licenseTesting->Release();
+ factory->Release();
+}
diff --git a/tests/src/Interop/COM/NativeServer/COMNativeServer.X.manifest b/tests/src/Interop/COM/NativeServer/COMNativeServer.X.manifest
index 4509ee9d65..3c67514b47 100644
--- a/tests/src/Interop/COM/NativeServer/COMNativeServer.X.manifest
+++ b/tests/src/Interop/COM/NativeServer/COMNativeServer.X.manifest
@@ -46,6 +46,11 @@
<comClass
clsid="{C222F472-DA5A-4FC6-9321-92F4F7053A65}"
threadingModel="Both" />
+
+ <!-- LicenseTesting -->
+ <comClass
+ clsid="{66DB7882-E2B0-471D-92C7-B2B52A0EA535}"
+ threadingModel="Both" />
</file>
</assembly>
diff --git a/tests/src/Interop/COM/NativeServer/LicenseTesting.h b/tests/src/Interop/COM/NativeServer/LicenseTesting.h
new file mode 100644
index 0000000000..b0c058e668
--- /dev/null
+++ b/tests/src/Interop/COM/NativeServer/LicenseTesting.h
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#pragma once
+
+#include <xplatform.h>
+#include "Servers.h"
+
+class LicenseTesting : public UnknownImpl, public ILicenseTesting
+{
+private: // static
+ static bool s_DenyLicense;
+ static BSTR s_License;
+
+public: // static
+ static HRESULT RequestLicKey(BSTR *key)
+ {
+ LPCOLESTR lic = s_License;
+ if (lic == nullptr)
+ lic = W("__MOCK_LICENSE_KEY__");
+
+ *key = TP_SysAllocString(lic);
+ return S_OK;
+ }
+
+private:
+ BSTR _lic;
+
+public:
+ LicenseTesting(_In_opt_ BSTR lic)
+ : _lic{ lic }
+ {
+ if (s_DenyLicense)
+ throw CLASS_E_NOTLICENSED;
+ }
+
+ ~LicenseTesting()
+ {
+ CoreClrBStrFree(_lic);
+ }
+
+public: // ILicenseTesting
+ DEF_FUNC(SetNextDenyLicense)(_In_ VARIANT_BOOL denyLicense)
+ {
+ s_DenyLicense = (denyLicense == VARIANT_FALSE) ? false : true;
+ return S_OK;
+ }
+
+ DEF_FUNC(GetLicense)(_Out_ BSTR *lic)
+ {
+ *lic = TP_SysAllocString(_lic);
+ return S_OK;
+ }
+
+ DEF_FUNC(SetNextLicense)(_In_z_ LPCOLESTR lic)
+ {
+ if (s_License != nullptr)
+ CoreClrBStrFree(s_License);
+
+ s_License = TP_SysAllocString(lic);
+ return S_OK;
+ }
+
+public: // IUnknown
+ STDMETHOD(QueryInterface)(
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject)
+ {
+ return DoQueryInterface(riid, ppvObject, static_cast<ILicenseTesting *>(this));
+ }
+
+ DEFINE_REF_COUNTING();
+};
+
+bool LicenseTesting::s_DenyLicense = false;
+BSTR LicenseTesting::s_License = nullptr;
diff --git a/tests/src/Interop/COM/NativeServer/Servers.cpp b/tests/src/Interop/COM/NativeServer/Servers.cpp
index 3bf7072f81..8cf7802088 100644
--- a/tests/src/Interop/COM/NativeServer/Servers.cpp
+++ b/tests/src/Interop/COM/NativeServer/Servers.cpp
@@ -214,5 +214,8 @@ STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Out_ LPVOID FA
if (rclsid == __uuidof(ColorTesting))
return ClassFactoryBasic<ColorTesting>::Create(riid, ppv);
+ if (rclsid == __uuidof(LicenseTesting))
+ return ClassFactoryLicense<LicenseTesting>::Create(riid, ppv);
+
return CLASS_E_CLASSNOTAVAILABLE;
}
diff --git a/tests/src/Interop/COM/NativeServer/Servers.h b/tests/src/Interop/COM/NativeServer/Servers.h
index 7a2a1ff6a7..61f16ca13a 100644
--- a/tests/src/Interop/COM/NativeServer/Servers.h
+++ b/tests/src/Interop/COM/NativeServer/Servers.h
@@ -18,6 +18,7 @@ class DECLSPEC_UUID("0F8ACD0C-ECE0-4F2A-BD1B-6BFCA93A0726") DispatchTesting;
class DECLSPEC_UUID("4DBD9B61-E372-499F-84DE-EFC70AA8A009") EventTesting;
class DECLSPEC_UUID("4CEFE36D-F377-4B6E-8C34-819A8BB9CB04") AggregationTesting;
class DECLSPEC_UUID("C222F472-DA5A-4FC6-9321-92F4F7053A65") ColorTesting;
+class DECLSPEC_UUID("66DB7882-E2B0-471D-92C7-B2B52A0EA535") LicenseTesting;
#define CLSID_NumericTesting __uuidof(NumericTesting)
#define CLSID_ArrayTesting __uuidof(ArrayTesting)
@@ -27,6 +28,7 @@ class DECLSPEC_UUID("C222F472-DA5A-4FC6-9321-92F4F7053A65") ColorTesting;
#define CLSID_EventTesting __uuidof(EventTesting)
#define CLSID_AggregationTesting __uuidof(AggregationTesting)
#define CLSID_ColorTesting __uuidof(ColorTesting)
+#define CLSID_LicenseTesting __uuidof(LicenseTesting)
#define IID_INumericTesting __uuidof(INumericTesting)
#define IID_IArrayTesting __uuidof(IArrayTesting)
@@ -37,6 +39,7 @@ class DECLSPEC_UUID("C222F472-DA5A-4FC6-9321-92F4F7053A65") ColorTesting;
#define IID_IEventTesting __uuidof(IEventTesting)
#define IID_IAggregationTesting __uuidof(IAggregationTesting)
#define IID_IColorTesting __uuidof(IColorTesting)
+#define IID_ILicenseTesting __uuidof(ILicenseTesting)
// Class used for COM activation when using CoreShim
struct CoreShimComActivation
@@ -74,4 +77,5 @@ private:
#include "EventTesting.h"
#include "AggregationTesting.h"
#include "ColorTesting.h"
+ #include "LicenseTesting.h"
#endif
diff --git a/tests/src/Interop/COM/ServerContracts/NativeServers.cs b/tests/src/Interop/COM/ServerContracts/NativeServers.cs
index e868345328..0a14e4fdca 100644
--- a/tests/src/Interop/COM/ServerContracts/NativeServers.cs
+++ b/tests/src/Interop/COM/ServerContracts/NativeServers.cs
@@ -142,6 +142,25 @@ namespace Server.Contract.Servers
internal class ColorTestingClass
{
}
+
+ /// <summary>
+ /// Managed definition of CoClass
+ /// </summary>
+ [ComImport]
+ [CoClass(typeof(LicenseTestingClass))]
+ [Guid("6C9E230E-411F-4219-ABFD-E71F2B84FD50")]
+ internal interface LicenseTesting : Server.Contract.ILicenseTesting
+ {
+ }
+
+ /// <summary>
+ /// Managed activation for CoClass
+ /// </summary>
+ [ComImport]
+ [Guid(Server.Contract.Guids.LicenseTesting)]
+ internal class LicenseTestingClass
+ {
+ }
}
#pragma warning restore 618 // Must test deprecated features
diff --git a/tests/src/Interop/COM/ServerContracts/Server.Contracts.cs b/tests/src/Interop/COM/ServerContracts/Server.Contracts.cs
index f401c48176..9c2e680ed7 100644
--- a/tests/src/Interop/COM/ServerContracts/Server.Contracts.cs
+++ b/tests/src/Interop/COM/ServerContracts/Server.Contracts.cs
@@ -273,6 +273,19 @@ namespace Server.Contract
bool AreColorsEqual(Color managed, int native);
Color GetRed();
}
+
+ [ComVisible(true)]
+ [Guid("6C9E230E-411F-4219-ABFD-E71F2B84FD50")]
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ public interface ILicenseTesting
+ {
+ void SetNextDenyLicense([MarshalAs(UnmanagedType.VariantBool)] bool denyLicense);
+
+ [return: MarshalAs(UnmanagedType.BStr)]
+ string GetLicense();
+
+ void SetNextLicense([MarshalAs(UnmanagedType.LPWStr)] string lic);
+ }
}
#pragma warning restore 618 // Must test deprecated features
diff --git a/tests/src/Interop/COM/ServerContracts/Server.Contracts.h b/tests/src/Interop/COM/ServerContracts/Server.Contracts.h
index 25025679e6..1db14e4676 100644
--- a/tests/src/Interop/COM/ServerContracts/Server.Contracts.h
+++ b/tests/src/Interop/COM/ServerContracts/Server.Contracts.h
@@ -25,6 +25,8 @@ struct __declspec(uuid("98cc27f0-d521-4f79-8b63-e980e3a92974"))
/* interface */ IAggregationTesting;
struct __declspec(uuid("E6D72BA7-0936-4396-8A69-3B76DA1108DA"))
/* interface */ IColorTesting;
+struct __declspec(uuid("6C9E230E-411F-4219-ABFD-E71F2B84FD50"))
+/* interface */ ILicenseTesting;
//
// Smart pointer typedef declarations
@@ -38,6 +40,7 @@ _COM_SMARTPTR_TYPEDEF(IDispatchTesting, __uuidof(IDispatchTesting));
_COM_SMARTPTR_TYPEDEF(IEventTesting, __uuidof(IEventTesting));
_COM_SMARTPTR_TYPEDEF(IAggregationTesting, __uuidof(IAggregationTesting));
_COM_SMARTPTR_TYPEDEF(IColorTesting, __uuidof(IColorTesting));
+_COM_SMARTPTR_TYPEDEF(ILicenseTesting, __uuidof(ILicenseTesting));
//
// Type library items
@@ -486,4 +489,14 @@ IColorTesting : public IUnknown
_Out_ _Ret_ OLE_COLOR* color) = 0;
};
+struct __declspec(uuid("6C9E230E-411F-4219-ABFD-E71F2B84FD50"))
+ILicenseTesting : IUnknown
+{
+ virtual HRESULT STDMETHODCALLTYPE SetNextDenyLicense(_In_ VARIANT_BOOL denyLicense) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetLicense(_Out_ BSTR *lic) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE SetNextLicense(_In_z_ LPCOLESTR lic) = 0;
+};
+
#pragma pack(pop)
diff --git a/tests/src/Interop/COM/ServerContracts/ServerGuids.cs b/tests/src/Interop/COM/ServerContracts/ServerGuids.cs
index 1269e6ab91..2ebeed8840 100644
--- a/tests/src/Interop/COM/ServerContracts/ServerGuids.cs
+++ b/tests/src/Interop/COM/ServerContracts/ServerGuids.cs
@@ -17,5 +17,6 @@ namespace Server.Contract
public const string EventTesting = "4DBD9B61-E372-499F-84DE-EFC70AA8A009";
public const string AggregationTesting = "4CEFE36D-F377-4B6E-8C34-819A8BB9CB04";
public const string ColorTesting = "C222F472-DA5A-4FC6-9321-92F4F7053A65";
+ public const string LicenseTesting = "66DB7882-E2B0-471D-92C7-B2B52A0EA535";
}
}
diff --git a/tests/src/Interop/common/ComHelpers.h b/tests/src/Interop/common/ComHelpers.h
index c4d9e6cbdb..aa3e43b569 100644
--- a/tests/src/Interop/common/ComHelpers.h
+++ b/tests/src/Interop/common/ComHelpers.h
@@ -231,3 +231,103 @@ public: // IUnknown
DEFINE_REF_COUNTING();
};
+
+// Templated class factory
+// Supplied type must have the following properties to use this template:
+// 1) Have a static method with the following signature:
+// - HRESULT RequestLicKey(BSTR *key);
+// 2) Have a constructor that takes an optional BSTR value as the key
+template<typename T>
+class ClassFactoryLicense : public UnknownImpl, public IClassFactory2
+{
+public: // static
+ static HRESULT Create(_In_ REFIID riid, _Outptr_ LPVOID FAR* ppv)
+ {
+ try
+ {
+ auto cf = new ClassFactoryLicense();
+ HRESULT hr = cf->QueryInterface(riid, ppv);
+ cf->Release();
+ return hr;
+ }
+ catch (const std::bad_alloc&)
+ {
+ return E_OUTOFMEMORY;
+ }
+ }
+
+public: // IClassFactory
+ STDMETHOD(CreateInstance)(
+ _In_opt_ IUnknown *pUnkOuter,
+ _In_ REFIID riid,
+ _COM_Outptr_ void **ppvObject)
+ {
+ return CreateInstanceLic(pUnkOuter, nullptr, riid, nullptr, ppvObject);
+ }
+
+ STDMETHOD(LockServer)(/* [in] */ BOOL fLock)
+ {
+ assert(false && "Not impl");
+ return E_NOTIMPL;
+ }
+
+public: // IClassFactory2
+ STDMETHOD(GetLicInfo)(
+ /* [out][in] */ __RPC__inout LICINFO *pLicInfo)
+ {
+ // The CLR does not call this function and as such,
+ // returns an error. Note that this is explicitly illegal
+ // in a proper implementation of IClassFactory2.
+ return E_UNEXPECTED;
+ }
+
+ STDMETHOD(RequestLicKey)(
+ /* [in] */ DWORD dwReserved,
+ /* [out] */ __RPC__deref_out_opt BSTR *pBstrKey)
+ {
+ if (dwReserved != 0)
+ return E_UNEXPECTED;
+
+ return T::RequestLicKey(pBstrKey);
+ }
+
+ STDMETHOD(CreateInstanceLic)(
+ /* [annotation][in] */ _In_opt_ IUnknown *pUnkOuter,
+ /* [annotation][in] */ _Reserved_ IUnknown *pUnkReserved,
+ /* [annotation][in] */ __RPC__in REFIID riid,
+ /* [annotation][in] */ __RPC__in BSTR bstrKey,
+ /* [annotation][iid_is][out] */ __RPC__deref_out_opt PVOID *ppvObj)
+ {
+ if (pUnkOuter != nullptr)
+ return CLASS_E_NOAGGREGATION;
+
+ if (pUnkReserved != nullptr)
+ return E_UNEXPECTED;
+
+ try
+ {
+ auto ti = new T(bstrKey);
+ HRESULT hr = ti->QueryInterface(riid, ppvObj);
+ ti->Release();
+ return hr;
+ }
+ catch (HRESULT hr)
+ {
+ return hr;
+ }
+ catch (const std::bad_alloc&)
+ {
+ return E_OUTOFMEMORY;
+ }
+ }
+
+public: // IUnknown
+ STDMETHOD(QueryInterface)(
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject)
+ {
+ return DoQueryInterface(riid, ppvObject, static_cast<IClassFactory *>(this), static_cast<IClassFactory2 *>(this));
+ }
+
+ DEFINE_REF_COUNTING();
+};