Переход анимации между действиями с использованием FLAG_ACTIVITY_CLEAR_TOP

Есть ли в C # способ получить доступ к таблице виртуальных методов COM-объекта для получения адреса функции?

7
задан Peter Mortensen 4 September 2010 в 10:41
поделиться

4 ответа

После долгого поиска и объединения различных частичных решений я понял, как это сделать.

Сначала вам нужно определить компонентный класс COM для объекта, к которому вы пытаетесь получить доступ:

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

Затем вам нужно создать экземпляр COM-объекта. Есть несколько способов сделать это. Поскольку меня интересовал DirectSound, я использовал:

[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);

Поскольку у меня теперь был мой COM-объект, я мог использовать предложение Ганса Marshal.GetComInterfaceForObject () :

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

В качестве дополнительного бонуса вы затем можно выполнить итерацию по функциям vtable следующим образом:

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());
}

Дополнительное чтение / ссылки:

8
ответ дан 7 December 2019 в 01:14
поделиться

Вы не можете извлечь указатель на собственный интерфейс из RCW. Но вы можете вызвать Marshal.GetComInterfaceForObject (), это должно быть хорошо, если вы запрашиваете правильный интерфейс. Оттуда вы можете Marshal.ReadIntPtr (), чтобы получить записи v-таблицы. Смещение 0 - это QueryInterface, 4 - это AddRef, 8 - это Release, 12 - это первый метод интерфейса и т. Д. Удвойте это значение для кода x64. Marshal.GetComSlotForMethodInfo () - это вариант.

На самом деле для вызова метода требуется Marshal.GetDelegateForFunctionPointer (), вам необходимо объявить делегат с точной подписью метода интерфейса COM. Это будет не подпись, которую он имеет при обычном вызове этого метода, это подпись [PreserveSig]. Другими словами, функция, которая возвращает HRESULT и аргумент ref, если она возвращает значение.

Возможностей взорвать вашу программу предостаточно.


После обновления: вам потребуются Marshal.GetFunctionPointerForDelegate и Marshal.WriteIntPtr для исправления записи слота v-таблицы.

2
ответ дан 7 December 2019 в 01:14
поделиться

Вы уверены, что спрашиваете о C #?

Вам не нужно чтобы получить адреса функций в C #, независимо от того, является ли метод виртуальным или нет. Вы можете создать экземпляр делегата , который содержит управляемую ссылку на метод. Если вы создаете экземпляр делегата с помощью виртуального метода, тогда метод будет вызываться виртуально, т.е. он вызовет наиболее производное переопределение.

В C # нет необходимости читать внутренние компоненты системы, такие как необработанная vtable.

0
ответ дан 7 December 2019 в 01:14
поделиться

Самое близкое, что я могу придумать, это Marshal.GetFunctionPointerForDelegate, хотя это по крайней мере один уровень от неуправляемого метода COM (поскольку вызов COM будет обернут в делегат .NET).

Для чего вам нужна эта информация?

0
ответ дан 7 December 2019 в 01:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: