Skip to content

Conversation

@jkoritzinsky
Copy link
Member

@jkoritzinsky jkoritzinsky commented Dec 4, 2025

We need to invoke the method on the exact IDispatch pointer that's returned to ensure that members on that dispatch interface will be resolved. The default IDispatch pointer will only resolve members for its corresponding interface.

Fixes #122175

Regression introduced in #104406

Test helper code adapted from #122195 (can be consolidated in the future).

…ing IDispatch pointer, not on the canonical one
Copilot AI review requested due to automatic review settings December 4, 2025 22:49
@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @dotnet/interop-contrib
See info in area-owners.md if you want to be subscribed.

Copilot finished reviewing on behalf of jkoritzinsky December 4, 2025 22:52
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a bug where dispatch interface members were being invoked on the canonical IDispatch pointer instead of the interface-specific IDispatch pointer. This caused issues when a .NET object with a custom default interface (via ComDefaultInterfaceAttribute) exposed multiple IDispatch interfaces - only the default interface's members were resolvable.

Key changes:

  • Modified COM interop dispatch invocation to use the interface-specific IDispatch pointer while still validating IDispatch support via QueryInterface
  • Added test infrastructure for in-process COM activation
  • Added test case demonstrating the fix for non-default IDispatch interfaces

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
src/coreclr/vm/interoputil.cpp Core fix: extracts and uses interface-specific IDispatch pointer for method invocation instead of canonical pointer
src/tests/Interop/common/ComActivationHelpers.cs New test helper providing COM class registration and activation infrastructure
src/tests/Interop/COM/NETClients/ConsumeNETServer/Program.cs Added test case validating IDispatch invocation on non-default interface, reorganized using directives, renamed TestEntryPoint to ConsumeNETServerTests
src/tests/Interop/COM/NETClients/ConsumeNETServer/ConsumeNETServer.csproj Added reference to ComActivationHelpers.cs

Copy link
Member

@AaronRobinsonMSFT AaronRobinsonMSFT left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! We should also backport this to .NET 10. I don't think it needs to go further back.

@jkoritzinsky
Copy link
Member Author

@AaronRobinsonMSFT any more feedback or is this good to go?

@jkoritzinsky
Copy link
Member Author

/backport to release/10.0

@github-actions
Copy link
Contributor

github-actions bot commented Dec 5, 2025

Started backporting to release/10.0 (link to workflow run)

Copy link
Member

@AaronRobinsonMSFT AaronRobinsonMSFT left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@jkoritzinsky jkoritzinsky merged commit 2c91165 into dotnet:main Dec 5, 2025
101 of 105 checks passed
@jkoritzinsky jkoritzinsky deleted the specific-idispatch branch December 5, 2025 17:58
steveisok pushed a commit that referenced this pull request Dec 6, 2025
…ce's corresponding IDispatch pointer, not on the canonical one (#122229)

Backport of #122200 to release/10.0

/cc @jkoritzinsky

## Customer Impact

- [X] Customer reported
- [ ] Found internally

[Select one or both of the boxes. Describe how this issue impacts
customers, citing the expected and actual behaviors and scope of the
issue. If customer-reported, provide the issue number.]

Method call on an IDispatch-based ComImport interface fails to call the
target COM method if the target COM object is a .NET object exposed to
COM that uses the ClassDefaultInterfaceAttribute; instead, an exception
is thrown.

## Regression

- [X] Yes
- [ ] No

[If yes, specify when the regression was introduced. Provide the PR or
commit if known.]

Introduced in .NET 9

#104406

## Testing

[How was the fix verified? How was the issue missed previously? What
tests were added?]

Added a unit test to validate the scenario and validated that the repro
no longer fails.

## Risk

[High/Medium/Low. Justify the indication by mentioning how risks were
measured and addressed.]

Low. Reverts the incorrectly functioning part of the regressing PR to
the .NET 8 code path.

**IMPORTANT**: If this backport is for a servicing release, please
verify that:

- For .NET 8 and .NET 9: The PR target branch is `release/X.0-staging`,
not `release/X.0`.
- For .NET 10+: The PR target branch is `release/X.0` (no `-staging`
suffix).

## Package authoring no longer needed in .NET 9

**IMPORTANT**: Starting with .NET 9, you no longer need to edit a NuGet
package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older
versions.

---------

Co-authored-by: Jeremy Koritzinsky <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DISP_E_UNKNOWNNAME for non-default interface members

2 participants