Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

COM interfaces should have attributed with [ComImport] #198

Closed
weltkante opened this issue Mar 16, 2021 · 1 comment · Fixed by #212
Closed

COM interfaces should have attributed with [ComImport] #198

weltkante opened this issue Mar 16, 2021 · 1 comment · Fixed by #212
Assignees
Labels
bug Something isn't working

Comments

@weltkante
Copy link

Something strange is going on with the new interface generation, the interfaces mostly work even though they have no ComImport attribute (which they are supposed to have but for some reason basic operations work anyways)

My quick and dirty trick for testing CCWs in the classic marshaler is to use Marshal.GetIUnknownForObject and Marshal.GetComInterfaceForObject and then call into the vtable, faking a native caller. However for the new interface generation GetComInterfaceForObject complains and throws an exception, since there is no ComImport attribute on the interface. Copy/pasting the generated source and adding ComImport makes it work and I can call into the vtable as expected.

Now I know this is just a quick and dirty test and I want to explore this some more, I had similar errors in the past when doing handwritten projections so the problem might not be restricted to the Marshal helper function. However for today I'm running out of time since my usual IDataObject scenario I use for exploring COM interactions doesn't work at all in the new generator, so I'm leaving this just as a note and will come back to it over the next days and see if I can build an actual repro that doesn't rely on manually calling Marshal helper functions.

@weltkante
Copy link
Author

weltkante commented Mar 18, 2021

Had to search a bit to find another candidate than my usual IDataObject that isn't a ton of effort to implement, but here's an example that doesn't work without [ComImport] attribute. From what I know marking interfaces with ComImport is a requirement and not optional. I suspect all CCWs are unable to be queried for interfaces (i.e. the fact that Marshal.GetComInterfaceForObject throws is not a superficial check in the helper API but a core behavior of the runtime, and all queries for specific interfaces will probably fail if they aren't marked as ComImport.)

static class Program
{
    [STAThread]
    static void Main()
    {
        Application.OleRequired();
        PInvoke.CoRegisterClassObject(typeof(CustomObject).GUID, new CustomFactory(), (uint)CLSCTX.CLSCTX_INPROC_SERVER, (uint)REGCLS.REGCLS_MULTIPLEUSE, out var cookie).ThrowOnFailure();
        PInvoke.CoCreateInstance(typeof(CustomObject).GUID, null, (uint)CLSCTX.CLSCTX_INPROC_SERVER, typeof(CustomObject).GUID, out var obj).ThrowOnFailure();
        Debug.Assert(obj is CustomObject);
    }
}

[ComVisible(true)]
[Guid("7E9C7DDD-CB25-4D98-AECB-5BCD3D66C935")]
class CustomFactory : IClassFactory
{
    public unsafe void CreateInstance([MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, Guid* riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppvObject)
    {
        // being lazy here to prove the point, this is not a good implementation
        if (riid is null || *riid != typeof(CustomObject).GUID)
            throw new NotSupportedException();

        ppvObject = new CustomObject();
    }

    public void LockServer(BOOL fLock)
    {
        // being lazy here to prove the point, this is not a good implementation
    }
}

[ComVisible(true)]
[Guid("C680720D-AB01-4A89-88A4-6C241CF60B07")]
class CustomObject
{
}

[edit] I realized after I made that repro that I'm using the CustomObject class GUID as if it were an interface GUID, which is not really correct, but thats trivially fixable and doesn't change behavior of the repro. The point of failure is registering the class factory, not creating the instance.

@AArnott AArnott added the bug Something isn't working label Mar 18, 2021
@AArnott AArnott self-assigned this Mar 18, 2021
@AArnott AArnott changed the title Interfaces not fully marshalable COM interfaces should have attributed with [ComImport] Mar 18, 2021
AArnott added a commit that referenced this issue Mar 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants