Skip to content

Commit 09f16de

Browse files
authored
Fix using .NET COM server with dynamic keyword (port of #48037) (#48481)
1 parent 9cbdbc5 commit 09f16de

File tree

6 files changed

+94
-8
lines changed

6 files changed

+94
-8
lines changed

src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/ComRuntimeHelpers.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,25 +103,29 @@ internal static string GetNameOfType(ComTypes.ITypeInfo typeInfo)
103103
}
104104

105105
/// <summary>
106-
/// Look for typeinfo using IDispatch.GetTypeInfo
106+
/// Look for type info using IDispatch.GetTypeInfo
107107
/// </summary>
108108
/// <param name="dispatch">IDispatch object</param>
109109
/// <remarks>
110-
/// Some COM objects just dont expose typeinfo. In these cases, this method will return null.
111-
/// Some COM objects do intend to expose typeinfo, but may not be able to do so if the type-library is not properly
112-
/// registered. This will be considered as acceptable or as an error condition depending on throwIfMissingExpectedTypeInfo
110+
/// Some COM objects just don't expose type info. In these cases, this method will return null.
111+
/// Some COM objects do intend to expose type info, but may not be able to do so if the type library
112+
/// is not properly registered. This will be considered an error.
113113
/// </remarks>
114114
/// <returns>Type info</returns>
115115
internal static ComTypes.ITypeInfo GetITypeInfoFromIDispatch(IDispatch dispatch)
116116
{
117117
int hresult = dispatch.TryGetTypeInfoCount(out uint typeCount);
118-
Marshal.ThrowExceptionForHR(hresult);
119-
Debug.Assert(typeCount <= 1);
120118
if (typeCount == 0)
121119
{
120+
// COM objects should return a type count of 0 to indicate that type info is not exposed.
121+
// Some COM objects may return a non-success HRESULT when type info is not supported, so
122+
// we only check the count and not the HRESULT in this case.
122123
return null;
123124
}
124125

126+
Marshal.ThrowExceptionForHR(hresult);
127+
Debug.Assert(typeCount == 1);
128+
125129
IntPtr typeInfoPtr;
126130
hresult = dispatch.TryGetTypeInfo(0, 0, out typeInfoPtr);
127131
if (!ComHresults.IsSuccess(hresult))

src/tests/Interop/COM/Dynamic/App.manifest

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
33
<assemblyIdentity
4-
type="win32"
4+
type="win32"
55
name="COMDynamicTest"
66
version="1.0.0.0" />
77

88
<dependency>
99
<dependentAssembly>
10-
<!-- RegFree COM -->
10+
<!-- RegFree COM to activate managed server -->
11+
<assemblyIdentity
12+
type="win32"
13+
name="CoreShim.X"
14+
version="1.0.0.0"/>
15+
</dependentAssembly>
16+
</dependency>
17+
<dependency>
18+
<dependentAssembly>
19+
<!-- RegFree COM to activate native server-->
1120
<assemblyIdentity
1221
type="win32"
1322
name="DynamicTestServer.X"
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
3+
4+
<assemblyIdentity
5+
type="win32"
6+
name="CoreShim.X"
7+
version="1.0.0.0" />
8+
9+
<file name="CoreShim.dll">
10+
<!-- ConsumeNETServerTesting -->
11+
<comClass
12+
clsid="{DE4ACF53-5957-4D31-8BE2-EA6C80683246}"
13+
threadingModel="Both" />
14+
</file>
15+
16+
</assembly>

src/tests/Interop/COM/Dynamic/Dynamic.csproj

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
<CLRTestTargetUnsupported Condition="'$(TargetsWindows)' != 'true'">true</CLRTestTargetUnsupported>
99
<!-- This test would require the runincontext.exe to include App.manifest describing the COM interfaces -->
1010
<UnloadabilityIncompatible>true</UnloadabilityIncompatible>
11+
<CLRTestScriptLocalCoreShim>true</CLRTestScriptLocalCoreShim>
12+
<RequiresMockHostPolicy>true</RequiresMockHostPolicy>
1113
<!-- This test is very slow under some GCStress variations, especially with COMPlus_HeapVerify=1, so disable it under GCStress to avoid test timeouts in the CI.
1214
Issue: https://github.com/dotnet/runtime/issues/39584
1315
-->
@@ -18,11 +20,23 @@
1820
<Compile Include="CollectionTest.cs" />
1921
<Compile Include="EventTest.cs" />
2022
<Compile Include="ParametersTest.cs" />
23+
<Compile Include="NETServerTest.cs" />
2124
<Compile Include="Program.cs" />
2225
<Compile Include="ServerGuids.cs" />
26+
<Compile Include="../ServerContracts/ServerGuids.cs" />
27+
</ItemGroup>
28+
<ItemGroup>
29+
<None Include="CoreShim.X.manifest">
30+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
31+
</None>
2332
</ItemGroup>
2433
<ItemGroup>
2534
<ProjectReference Include="Server/CMakeLists.txt" />
2635
<ProjectReference Include="$(TestSourceDir)Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj" />
36+
<ProjectReference Include="../NETServer/NETServer.csproj">
37+
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
38+
<OutputItemType>Content</OutputItemType>
39+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
40+
</ProjectReference>
2741
</ItemGroup>
2842
</Project>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace Dynamic
5+
{
6+
using System;
7+
using System.Runtime.InteropServices;
8+
using TestLibrary;
9+
10+
internal class NETServerTest
11+
{
12+
public void Run()
13+
{
14+
Console.WriteLine($"Running {nameof(NETServerTest)}");
15+
16+
// Initialize CoreShim and hostpolicymock
17+
HostPolicyMock.Initialize(Environment.CurrentDirectory, null);
18+
Environment.SetEnvironmentVariable("CORESHIM_COMACT_ASSEMBLYNAME", "NETServer");
19+
Environment.SetEnvironmentVariable("CORESHIM_COMACT_TYPENAME", "ConsumeNETServerTesting");
20+
21+
using (HostPolicyMock.Mock_corehost_resolve_component_dependencies(
22+
0,
23+
string.Empty,
24+
string.Empty,
25+
string.Empty))
26+
{
27+
Type t = Type.GetTypeFromCLSID(Guid.Parse(Server.Contract.Guids.ConsumeNETServerTesting));
28+
dynamic obj = Activator.CreateInstance(t);
29+
30+
try
31+
{
32+
Assert.IsTrue(obj.EqualByCCW(obj));
33+
Assert.IsTrue(obj.NotEqualByRCW(obj));
34+
}
35+
finally
36+
{
37+
obj.ReleaseResources();
38+
}
39+
}
40+
}
41+
}
42+
}

src/tests/Interop/COM/Dynamic/Program.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ static int Main(string[] doNotUse)
2222
new CollectionTest().Run();
2323
new EventTest().Run();
2424
new ParametersTest().Run();
25+
new NETServerTest().Run();
2526
}
2627
catch (Exception e)
2728
{

0 commit comments

Comments
 (0)