tags:

views:

82

answers:

2

EDIT:

I am attempting to encapsulate a 3rd party com object in .net classes and at the same time fix a bug with it. I was hoping to replace a method in the com object's vtable with a call to my own method which would provide a bug free implementation of the method.

I was trying to test this out on something very basic, but given the answers below i'm on completely the wrong track. By creating a reference to my com object I presume i've created a runtime callable wrapper, is there any way to get a pointer to the real underlying com object?


I'm attempting to access a com object's vtable in memory and getting nowhere.

From what I have read, the first 4 bytes in memory of a com object should be a pointer to the vtableptr, which in turn is a pointer to the vtable.

Although I'm not sure I expect to find my test method at slot 7 in this com object I have tried them all and nothing looks like the address of my function.

If anyone can make the necessary changes to this sample to get it to work (the aim is just to try and invoke the Test method on the Tester class by accessing the com object's vtable and locating the method in whichever row it turns up) I would be very grateful.

I know it is rare that anyone would need to do this, but please accept I do need to do something quite similar and have considered the alternatives

Thanks in advance

[ComVisible(true)]
public class Tester
{
    public void Test()
    {
        MessageBox.Show("Here");
    }

}

public delegate void TestDelegate();

private void main()
{

    Tester t = new Tester();

    GCHandle objectHandle = GCHandle.Alloc(t);

    IntPtr objectPtr = GCHandle.ToIntPtr(objectHandle);

    IntPtr vTable = (IntPtr)Marshal.ReadInt32(objectPtr);

    IntPtr vTablePtr = (IntPtr)Marshal.ReadInt32(vTable);

    IntPtr functionPtr = (IntPtr)Marshal.ReadInt32(vTablePtr, 7 * 4); // 7 may be incorrect but i have tried many different values

    TestDelegate func = (TestDelegate)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(TestDelegate));

    func();

    objectHandle.Free();
}
+2  A: 

You are completely on the wrong track with this. The t object is not a COM interface pointer, it is a .NET object reference. A COM interface pointer (and its v-table) doesn't get created until unmanaged code creates the CCW (COM Callable Wrapper). It has to be unmanaged code, the CLR interop layer doesn't permit managed code to create a CCW.

The only way to keep this thread moving is by explaining why you want to do this.

Hans Passant
Thanks Hans for your explanation, i'm definitely out of my depth here and that has saved me wasting time on something that will never work. I have updated my question with more information in case that means someone can offer advise
Martin Booth
A: 

@Hans has a point. +1.

This is in no form a solution, just an explanation:

If you really want to access a COM object, why not create a simple COM dll and then try to access it?

Interop works two ways:

  1. .NET component calling COM component
  2. COM component calling .NET component

When .NET calls COM it requires Runtime Callable Wrapper (Visual Studio will create that for you) and COM Callable Wrapper (need to decorate .NET members with ComVisible) for the latter.

To access COM object's vtable from .NET, it needs to be a real COM component that you are accessing, otherwise it's just an object reference as @Hans mentioned.

Vivek