COM

Тема в разделе "WASM.WIN32", создана пользователем cresta, 21 авг 2004.

  1. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Создаю окно для com-объекта. При помощи ATL.DLL получаю сам объект и вставляю в это онко. Объект отображается, но вот никак не могу добраться до его функций. IUnknown получил, а как определить смещения ф-ций - не знаю. Попробовал таким путём:

    При помощи утилиты COM Browser получил описание интерфейса объекта (на примере mediaplayer'a). Примерно такого содержания:
    Код (Text):
    1. Interface Dispatch DirectFrameMediaPlayer
    2.     Member Get CurrentPosition<&H403>() As Double
    3.     Member Let CurrentPosition<&H403>()   'Parameter Type As Double
    4.     Member Get Duration<&H3EB>() As Double
    5.     Member Get ImageSourceWidth<&H3E9>() As Long
    6.     Member Get ImageSourceHeight<&H3EA>() As Long
    7.  


    Значения <&H3E9>,<&H3EA>,<&H3EB> смещениями относительно IUnknown адресов вызываемых функций не должны быть, т.к. разница меж ними менее дворда. Наугад попробовал вызывать ф-ции по этим смещениям - программа вылетает.

    Может кто знает, как получить адреса функций и методов объекта?
     
  2. volodya

    volodya wasm.ru

    Публикаций:
    0
    Регистрация:
    22 апр 2003
    Сообщения:
    1.169
    Может кто знает, как получить адреса функций и методов объекта?



    Все зависит от того, используется ли раннее связывание или позднее связывание. Подробнее тут:



    http://www.wasm.ru/article.php?article=msi
     
  3. zed_0xff

    zed_0xff New Member

    Публикаций:
    0
    Регистрация:
    13 май 2004
    Сообщения:
    29
    Если ты имеешь _именно_ IUnknown, то сделай ему QueryInterface с REFIID'ом того интерфейса, который ты хочешь. Он тебе на это, если все хорошо, отдаст указатель на область памяти, где в свою очередь первым двордом будет лежать указатель на его vtbl.

    Далее, vtbl - это массив указателей на методы класса. Там стандартно идет так:

    QueryInterface()

    AddRef()

    Release()

    а вот дальше пошли методы, специфичные для конкретного класса. Для стандартных интерфейсов в *.h от визуал студии есть эти таблицы. Например вот для IDispatch:
    Код (Text):
    1.     typedef struct IDispatchVtbl
    2.     {
    3.         BEGIN_INTERFACE
    4.  
    5.         HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
    6.             IDispatch * This,
    7.             /* [in] */ REFIID riid,
    8.             /* [iid_is][out] */ void **ppvObject);
    9.  
    10.         ULONG ( STDMETHODCALLTYPE *AddRef )(
    11.             IDispatch * This);
    12.  
    13.         ULONG ( STDMETHODCALLTYPE *Release )(
    14.             IDispatch * This);
    15.  
    16.         HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )(
    17.             IDispatch * This,
    18.             /* [out] */ UINT *pctinfo);
    19.  
    20.         HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )(
    21.             IDispatch * This,
    22.             /* [in] */ UINT iTInfo,
    23.             /* [in] */ LCID lcid,
    24.             /* [out] */ ITypeInfo **ppTInfo);
    25.  
    26.         HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )(
    27.             IDispatch * This,
    28.             /* [in] */ REFIID riid,
    29.             /* [size_is][in] */ LPOLESTR *rgszNames,
    30.             /* [in] */ UINT cNames,
    31.             /* [in] */ LCID lcid,
    32.             /* [size_is][out] */ DISPID *rgDispId);
    33.  
    34.         /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )(
    35.             IDispatch * This,
    36.             /* [in] */ DISPID dispIdMember,
    37.             /* [in] */ REFIID riid,
    38.             /* [in] */ LCID lcid,
    39.             /* [in] */ WORD wFlags,
    40.             /* [out][in] */ DISPPARAMS *pDispParams,
    41.             /* [out] */ VARIANT *pVarResult,
    42.             /* [out] */ EXCEPINFO *pExcepInfo,
    43.             /* [out] */ UINT *puArgErr);
    44.  
    45.         END_INTERFACE
    46.     } IDispatchVtbl;
    (файл OAIdl.h).

    Для нестандартных интерфейсов можно попробовать их ИДой расковырять, к ней палгин есть для КОМ-объектов специальный..
     
  4. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    zed_0xff



    Так QueryInterface получается обязательно нужно вызывать? Сразу после получения IUnknown. Либо не сразу, но перед первым вызовом метода. ОК, попробую.
     
  5. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Ещё уточню: значит, я запрашиваю QueryInterface с REFIID'ом (это для всего com-объекта в целом), получаю указатель на указатель на таблицу. После этого ещё раз запрашиваю QueryInterface по первому адресу этой таблицы, но теперь уже для конкретного интерфейса. Если до сих пор я правильно понял, то второй запрос нужно делать уже с ID конкретного интерфейса, т.к. их может быть несколько. И обязательно ли делать Release после каждого вызова функции\метода? Может только при окончании работы с интерфейсом?

    О том чтобы расковырять интерфейс: я тут нарыл утилиту COMView, она делает 4 стандартных инклюда + два для конкретного объекта. На асме. Правда, там такое количество макросов :-\ Если вдруг кому надо, она лежит на http://www.japheth.de
     
  6. zed_0xff

    zed_0xff New Member

    Публикаций:
    0
    Регистрация:
    13 май 2004
    Сообщения:
    29
    cresta

    допустим мы имеем IUnknown* pUnk
    Код (Text):
    1.  
    2. mov ebx, pUnk ; ebx = адрес IUnknown
    3. mov ebx, [ebx]; ebx = адрес vtbl для IUnknown
    4. mov ebx, [ebx]; ebx = адрес QueryInterface() для IUnknown
    5. push offset pWantedInterface
    6. push offset IID_WantedInterface
    7. push pUnk
    8. call ebx
    9. mov ebx, [pWantedInterface]
    10. or ebx,ebx
    11. jnz all_ok
    12.  
    13. push 1
    14. call ExitProcess
    15.  
    16. all_ok:
    17. ; ebx = указатель на экземпляр искомого объекта
    18. mov ebx, [ebx] ; теперь на его vtbl
    19. add ebx,4*4 ; если мы хотим вызвать 4-ю по порядку функцию
    20. mov ebx,[ebx] ; получаем ее адрес
    21. push arg2 ; аргументы, опять же по вкусу
    22. push arg1
    23. push [pWantedInterface]
    24. call ebx
    25.  
    26. ...............
    27.  
    28.  ; сюда придет указатель на искомый ифейс:
    29. pWantedInterface: dd 0
    30.  
    31.  ; а это IID нужного интерфейса, цифры подставить по вкусу :)
    32. IID_WantedInterface:
    33.   dd 12345678h
    34.   dw 1234h, 1234h
    35.   db 12h, 12h, 12h, 12h, 12h, 12h, 12h, 12h
    36.  




    вроде все.
     
  7. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Ага, теперь всё видно :)

    Спасибо.
     
  8. zed_0xff

    zed_0xff New Member

    Публикаций:
    0
    Регистрация:
    13 май 2004
    Сообщения:
    29
    Угу. пжалста. Просто как раз совсем недавно проект один сделал, там всяко на голом си с ком-объектами извращался... :)
     
  9. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Да я в Си ни в зуб ногой, а все примеры обычно на ём написаны. А ассемблерный как-то всё просто и понятно. Потому сразу и не допёр :dntknw:(