Access COM COM table with C #

Is there a way in C # to access the table of virtual methods of a COM object to get the address of a function?

+7
c # interop com
source share
4 answers

After a lot of searching and building various partial solutions, I figured out how to do it.

First you need to define a COM class for the object you are trying to access:

[ComImport, Guid("..."), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] internal interface ISomeCOMInterface { // Define interface methods here, using PInvoke conversion between types } 

Then you need to instantiate the COM object. There are several ways to do this. Since I was interested in DirectSound, I used:

 [DllImport("dsound.dll", EntryPoint = "DirectSoundCreate", ...] static extern void DirectSoundCreate(IntPtr GUID, [Out, MarshalAs(UnmanagedType.Interface)] out IDirectSound directSound, IntPtr pUnkOuter); IDirectSound directSound; DirectSoundCreate(IntPtr.Zero, out directSound, IntPtr.Zero); 

Since I now had my own COM object, I could use the Hans suggestion Marshal.GetComInterfaceForObject() :

 IntPtr comPtr = Marshal.GetComInterfaceForObject(directSound, typeof(IDirectSound)); IntPtr vTable = Marshal.ReadIntPtr(comPtr); 

As an added bonus, you can iterate through the vtable functions as follows:

 int start = Marshal.GetStartComSlot(typeof(IDirectSound)); int end = Marshal.GetEndComSlot(typeof(IDirectSound)); ComMemberType mType = 0; for (int i = start; i <= end; i++) { System.Reflection.MemberInfo mi = Marshal.GetMethodInfoForComSlot(typeof(IDirectSound), i, ref mType); Console.WriteLine("Method {0} at address 0x{1:X}", mi.Name, Marshal.ReadIntPtr(vTable, i * Marshal.SizeOf(typeof(IntPtr))).ToInt64()); } 

Additional reads / links:

+8
source share

You cannot dig out your own interface pointer from RCW. But you can call Marshal.GetComInterfaceForObject (), it should be fine if you ask for the correct interface. From there, you can Marshal.ReadIntPtr () get the v-table entries. Offset 0 - QueryInterface, 4 - AddRef, 8 - Release, 12 - first interface method, etc. Double for x64 code. Marshal.GetComSlotForMethodInfo () is an option.

Actually the method call requires Marshal.GetDelegateForFunctionPointer (), you need to declare a delegate with the exact signature of the COM interface method. It will not be the signature it has, when you usually call this method, it is the signature [PreserveSig]. In other words, the function returns HRESULT and the argument ref if it returns a value.

The possibilities to bomb your program are numerous.


After the update: you will need Marshal.GetFunctionPointerForDelegate and Marshal.WriteIntPtr to fix the v-table slot entry.

+2
source share

Are you sure you are asking about C #?

You do not need to get the addresses of functions in C #, regardless of whether the method is virtual or not. You can create an instance of a delegate that contains a managed link to this method. If you create an instance of a delegate using a virtual method, the method will be called practically, i.e. It will cause the most derived override.

In C #, there is no need to read internal system elements such as raw vtable.

0
source share

The closest thing I can think of is Marshal.GetFunctionPointerForDelegate , although this is at least one level removed from the unmanaged COM method (since the COM call will be wrapped in a .NET delegate.)

Why do you need this information?

0
source share

All Articles