|
|
| Посл.отвђт | Сообщенiе |
|
|
Дата: Авг 21, 2004 17:27:06 Создаю окно для com-объекта. При помощи ATL.DLL получаю сам объект и вставляю в это онко. Объект отображается, но вот никак не могу добраться до его функций. IUnknown получил, а как определить смещения ф-ций - не знаю. Попробовал таким путём: При помощи утилиты COM Browser получил описание интерфейса объекта (на примере mediaplayer'a). Примерно такого содержания: Interface Dispatch DirectFrameMediaPlayer
Member Get CurrentPosition<&H403>() As Double
Member Let CurrentPosition<&H403>() 'Parameter Type As Double
Member Get Duration<&H3EB>() As Double
Member Get ImageSourceWidth<&H3E9>() As Long
Member Get ImageSourceHeight<&H3EA>() As Long
Значения <&H3E9>,<&H3EA>,<&H3EB> смещениями относительно IUnknown адресов вызываемых функций не должны быть, т.к. разница меж ними менее дворда. Наугад попробовал вызывать ф-ции по этим смещениям - программа вылетает. Может кто знает, как получить адреса функций и методов объекта? |
|
|
Дата: Авг 21, 2004 19:46:41 Может кто знает, как получить адреса функций и методов объекта? Все зависит от того, используется ли раннее связывание или позднее связывание. Подробнее тут: http://www.wasm.ru/article.php?article=msi |
|
|
Дата: Авг 22, 2004 21:48:47 Если ты имеешь _именно_ IUnknown, то сделай ему QueryInterface с REFIID'ом того интерфейса, который ты хочешь. Он тебе на это, если все хорошо, отдаст указатель на область памяти, где в свою очередь первым двордом будет лежать указатель на его vtbl. Далее, vtbl - это массив указателей на методы класса. Там стандартно идет так: QueryInterface() AddRef() Release() а вот дальше пошли методы, специфичные для конкретного класса. Для стандартных интерфейсов в *.h от визуал студии есть эти таблицы. Например вот для IDispatch: typedef struct IDispatchVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
IDispatch * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
IDispatch * This);
ULONG ( STDMETHODCALLTYPE *Release )(
IDispatch * This);
HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )(
IDispatch * This,
/* [out] */ UINT *pctinfo);
HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )(
IDispatch * This,
/* [in] */ UINT iTInfo,
/* [in] */ LCID lcid,
/* [out] */ ITypeInfo **ppTInfo);
HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )(
IDispatch * This,
/* [in] */ REFIID riid,
/* [size_is][in] */ LPOLESTR *rgszNames,
/* [in] */ UINT cNames,
/* [in] */ LCID lcid,
/* [size_is][out] */ DISPID *rgDispId);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )(
IDispatch * This,
/* [in] */ DISPID dispIdMember,
/* [in] */ REFIID riid,
/* [in] */ LCID lcid,
/* [in] */ WORD wFlags,
/* [out][in] */ DISPPARAMS *pDispParams,
/* [out] */ VARIANT *pVarResult,
/* [out] */ EXCEPINFO *pExcepInfo,
/* [out] */ UINT *puArgErr);
END_INTERFACE
} IDispatchVtbl; (файл OAIdl.h).
Для нестандартных интерфейсов можно попробовать их ИДой расковырять, к ней палгин есть для КОМ-объектов специальный.. |
|
|
Дата: Авг 23, 2004 17:03:26 zed_0xff Так QueryInterface получается обязательно нужно вызывать? Сразу после получения IUnknown. Либо не сразу, но перед первым вызовом метода. ОК, попробую. |
|
|
Дата: Авг 23, 2004 17:24:43 · Поправил: cresta Ещё уточню: значит, я запрашиваю QueryInterface с REFIID'ом (это для всего com-объекта в целом), получаю указатель на указатель на таблицу. После этого ещё раз запрашиваю QueryInterface по первому адресу этой таблицы, но теперь уже для конкретного интерфейса. Если до сих пор я правильно понял, то второй запрос нужно делать уже с ID конкретного интерфейса, т.к. их может быть несколько. И обязательно ли делать Release после каждого вызова функции\метода? Может только при окончании работы с интерфейсом? О том чтобы расковырять интерфейс: я тут нарыл утилиту COMView, она делает 4 стандартных инклюда + два для конкретного объекта. На асме. Правда, там такое количество макросов :-\ Если вдруг кому надо, она лежит на http://www.japheth.de |
|
|
Дата: Авг 23, 2004 20:57:47 cresta допустим мы имеем IUnknown* pUnk mov ebx, pUnk ; ebx = адрес IUnknown mov ebx, [ebx]; ebx = адрес vtbl для IUnknown mov ebx, [ebx]; ebx = адрес QueryInterface() для IUnknown push offset pWantedInterface push offset IID_WantedInterface push pUnk call ebx mov ebx, [pWantedInterface] or ebx,ebx jnz all_ok push 1 call ExitProcess all_ok: ; ebx = указатель на экземпляр искомого объекта mov ebx, [ebx] ; теперь на его vtbl add ebx,4*4 ; если мы хотим вызвать 4-ю по порядку функцию mov ebx,[ebx] ; получаем ее адрес push arg2 ; аргументы, опять же по вкусу push arg1 push [pWantedInterface] call ebx ............... ; сюда придет указатель на искомый ифейс: pWantedInterface: dd 0 ; а это IID нужного интерфейса, цифры подставить по вкусу :) IID_WantedInterface: dd 12345678h dw 1234h, 1234h db 12h, 12h, 12h, 12h, 12h, 12h, 12h, 12h вроде все. |
|
|
Дата: Авг 23, 2004 21:41:51 Ага, теперь всё видно :) Спасибо. |
|
|
Дата: Авг 23, 2004 22:21:27 Угу. пжалста. Просто как раз совсем недавно проект один сделал, там всяко на голом си с ком-объектами извращался... :) |
|
|
Дата: Авг 24, 2004 00:51:47 Да я в Си ни в зуб ногой, а все примеры обычно на ём написаны. А ассемблерный как-то всё просто и понятно. Потому сразу и не допёр :(( |
|
Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.044 |