Создаю окно для com-объекта. При помощи ATL.DLL получаю сам объект и вставляю в это онко. Объект отображается, но вот никак не могу добраться до его функций. IUnknown получил, а как определить смещения ф-ций - не знаю. Попробовал таким путём: При помощи утилиты COM Browser получил описание интерфейса объекта (на примере mediaplayer'a). Примерно такого содержания: Код (Text): 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 адресов вызываемых функций не должны быть, т.к. разница меж ними менее дворда. Наугад попробовал вызывать ф-ции по этим смещениям - программа вылетает. Может кто знает, как получить адреса функций и методов объекта?
Может кто знает, как получить адреса функций и методов объекта? Все зависит от того, используется ли раннее связывание или позднее связывание. Подробнее тут: http://www.wasm.ru/article.php?article=msi
Если ты имеешь _именно_ IUnknown, то сделай ему QueryInterface с REFIID'ом того интерфейса, который ты хочешь. Он тебе на это, если все хорошо, отдаст указатель на область памяти, где в свою очередь первым двордом будет лежать указатель на его vtbl. Далее, vtbl - это массив указателей на методы класса. Там стандартно идет так: QueryInterface() AddRef() Release() а вот дальше пошли методы, специфичные для конкретного класса. Для стандартных интерфейсов в *.h от визуал студии есть эти таблицы. Например вот для IDispatch: Код (Text): 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). Для нестандартных интерфейсов можно попробовать их ИДой расковырять, к ней палгин есть для КОМ-объектов специальный..
zed_0xff Так QueryInterface получается обязательно нужно вызывать? Сразу после получения IUnknown. Либо не сразу, но перед первым вызовом метода. ОК, попробую.
Ещё уточню: значит, я запрашиваю QueryInterface с REFIID'ом (это для всего com-объекта в целом), получаю указатель на указатель на таблицу. После этого ещё раз запрашиваю QueryInterface по первому адресу этой таблицы, но теперь уже для конкретного интерфейса. Если до сих пор я правильно понял, то второй запрос нужно делать уже с ID конкретного интерфейса, т.к. их может быть несколько. И обязательно ли делать Release после каждого вызова функции\метода? Может только при окончании работы с интерфейсом? О том чтобы расковырять интерфейс: я тут нарыл утилиту COMView, она делает 4 стандартных инклюда + два для конкретного объекта. На асме. Правда, там такое количество макросов :-\ Если вдруг кому надо, она лежит на http://www.japheth.de
cresta допустим мы имеем IUnknown* pUnk Код (Text): 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 вроде все.
Угу. пжалста. Просто как раз совсем недавно проект один сделал, там всяко на голом си с ком-объектами извращался...
Да я в Си ни в зуб ногой, а все примеры обычно на ём написаны. А ассемблерный как-то всё просто и понятно. Потому сразу и не допёр (