Skip to content

[API Proposal]: Support getting IUnknown for ComWrappers RCWs #79679

@JeremyKuhne

Description

@JeremyKuhne

Background and motivation

For COM interop we expect to be able to cast RCWs to arbitrary [ComImport] interfaces. We use this and Type.IsComObject to implement TypeDescriptor functionality.

We can reimplement to support both legacy COM Interop and ComWrapppers if we have the ability to get IUnknown* for any ComWrappers generated RCWs.

Without this support we cannot enable trimming for WinForms without breaking critical features such as drag/drop/cut/paste and accessibility. This also prevents providing COM ComWrappers support with TypeDescriptor (which WinForms owns).

API Proposal

namespace System.Runtime.InteropServices;

public abstract class ComWrappers
{
+    public static bool TryGetComInstance(object obj, out void* unknown);
}

API Usage

public static bool TryCreateComTypeDescriptor(object obj, out ComTypeDescriptor? descriptor)
{
    void* unknown;
    if (obj.GetType().IsCOMObject)
    {
        unknown = (void*)Marshal.GetIUnknownForObject(obj);
    }
    else
    {
        ComWrappers.TryGetComInstance(obj, out unknown);
    }

    return unknown is not null ? new ComTypeDescriptor(unknown) : null;
}

Alternative Designs

One alternative (or addition) is to change all possible Marshal APIs that provide interface pointers to support ComWrappers RCWs:

namespace System.Runtime.InteropServices;

// Existing interface pointer methods
public static class Marshal
{
    public static IntPtr GetComInterfaceForObject(object! o, Type! T);
    public static IntPtr GetComInterfaceForObject(object! o, Type! T, CustomQueryInterfaceMode mode);
    public static IntPtr GetComInterfaceForObject<T, TInterface>([DisallowNull] T o);
    public static IntPtr GetComInterfaceForObjectInContext(object o, Type t);
    public static IntPtr GetIDispatchForObject(object! o);
    public static IntPtr GetIDispatchForObjectInContext(object o);
    public static IntPtr GetIUnknownForObject(object! o);
    public static IntPtr GetIUnknownForObjectInContext(object o);
}

I don't know how plausible this is, but it would make writing consuming code much easier.

Risks

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-approvedAPI was approved in API review, it can be implementedarea-System.Runtime.InteropServicesblockingMarks issues that we want to fast track in order to unblock other important work

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions