Is there any way in C# to access a COM object's virtual method table in order to get a function's address?
相关问题
- Sorting 3 numbers without branching [closed]
- Graphics.DrawImage() - Throws out of memory except
- Why am I getting UnauthorizedAccessException on th
- 求获取指定qq 资料的方法
- How to know full paths to DLL's from .csproj f
Are you sure you are asking about C#?
You shouldn’t need to get function addresses in C#, irrespective of whether a method is virtual or not. You can instantiate a delegate, which holds a managed reference to the method. If you instantiate a delegate with a virtual method, then the method will be called virtually, i.e. it will call the most derived override.
There is no need in C# to read system internals like the raw vtable.
You can't dig the native interface pointer out of the RCW. But you can call Marshal.GetComInterfaceForObject(), should be good as long as you ask for the right interface. From there, you can Marshal.ReadIntPtr() to get the v-table entries. Offset 0 is QueryInterface, 4 is AddRef, 8 is Release, 12 is the first interface method, etc. Double that for x64 code. Marshal.GetComSlotForMethodInfo() is an option.
Actually calling the method requires Marshal.GetDelegateForFunctionPointer(), you need to declare the delegate with the exact signature of the COM interface method. That won't be the signature it has when you call this method normally, it is the [PreserveSig] signature. In other words, a function that returns HRESULT and a ref argument if it returns a value.
Opportunities to bomb your program are plentiful.
After update: you need Marshal.GetFunctionPointerForDelegate and Marshal.WriteIntPtr to patch the v-table slot entry.
The closest 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).What do you need this information for?
After a lot of searching and piecing together different partial solutions, I figured out how to do it.
First you need to define the COM coclass for the object you're trying to access:
Next you need to instantiate the COM object. There are a couple of ways to do that. Since I was interested in DirectSound, I used:
Since I now had my COM object, I could then use Hans' suggestion of
Marshal.GetComInterfaceForObject()
:As an added bonus, you can then iterate through the vtable functions like this:
Extra Reading / References: