dotnet / dotnet/runtime

GeneratedComInterface relies on undefined QueryInterface behavior

Open
#129,181 4 comments 0 reactions 0 assignees View on GitHub
area-System.Runtime.InteropServices
Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Description

### Description

From [official documentation about COM interface inheritance](https://learn.microsoft.com/en-us/windows/win32/com/iunknown-and-interface-inheritance), there's no rule that says "if QI to B succeeds and B inherits from A, then QI to A must succeed."

However, any attempts to call methods located in interface `A` will result in a `QueryInterface` to `A`. The chain goes something like this:
- User has COM object of interface `B`, which inherits from `A`.
- User calls `A.SomeMethod()`
- `SomeMethod()` calls `IUnmanagedVirtualMethodTableProvider.GetVirtualMethodTableInfoForKey`
- `ComObject.GetVirtualMethodTableInfoForKey` calls `LookUpVTableInfo` which performs `QueryInterface`.

In effect, this means `GeneratedComInterface` relies on undefined `QueryInterface` behavior

### Reproduction Steps

```cs
[GeneratedComInterface]
[Guid("")]
interface A
{
void Method();
}

[GeneratedComInterface]
[Guid("
")]
interface B : A;

StrategyBasedComWrappers comWrappers = new();
B b = (B)comWrappers.GetOrCreateObjectForComInstance(...);
Test(b);

void Test(A a)
{
a.Method();
}
```

### Expected behavior

`b.Method()` runs successfully in all spec-compliant implementations of `B`.

### Actual behavior

Potential `System.InvalidCastException` at `b.Method()`, even if the native object implementing `B` is compliant with COM specifications.

### Regression?

_No response_

### Known Workarounds

_No response_

### Configuration

_No response_

### Other information

Apparently, this QI behavior is present in Shell (https://github.com/microsoft/CsWin32/issues/1716) and DirectComposition APIs.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.