Архитектура COM.

Тема в разделе "WASM.WIN32", создана пользователем Booster, 5 мар 2007.

  1. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Приветствую всех васмовцев.
    Хочу маленько пообсуждать COM.
    Вот код который генерирует VS2003, для доcтупа к функции.
    Код (Text):
    1. p_inputDeviceJoystick->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE|DISCL_FOREGROUND);
    2. 0047E0F2  mov         esi,esp
    3. 0047E0F4  push        5    
    4. 0047E0F6  mov         eax,dword ptr [hWnd]
    5. 0047E0F9  push        eax  
    6. 0047E0FA  mov         ecx,dword ptr [this]
    7. 0047E0FD  mov         edx,dword ptr [ecx+14Ch]
    8. 0047E103  mov         eax,dword ptr [this]
    9. 0047E106  mov         ecx,dword ptr [eax+14Ch]
    10. 0047E10C  mov         edx,dword ptr [edx]
    11. 0047E10E  push        ecx  
    12. 0047E10F  call        dword ptr [edx+34h]
    13. 0047E112  cmp         esi,esp
    14. 0047E114  call        @ILT+13660(__RTC_CheckEsp) (47A561h)
    Сразу бросается в глаза то что edx и ecx инициализируются очень смешно.
    Код (Text):
    1. 0047E0FA  mov         ecx,dword ptr [this]
    2. 0047E0FD  mov         edx,dword ptr [ecx+14Ch]
    3. 0047E103  mov         eax,dword ptr [this]
    4. 0047E106  mov         ecx,dword ptr [eax+14Ch]
    Почему не mov ecx, edx? Ну да ладно оставим это на совести разработчиков компилятора.
    Обращает на себя внимание строка:
    В статье многоуважаемого мной Aquila "Как получить доступ к COM-объекту, используя ассемблер", по всей видимости вкралась ошибка.
    Код (Text):
    1. ; получаем указатель на объект
    2. mov eax, ppv
    3. ; и используем его, чтобы найти структуру интерфейса
    4. mov edx, [eax]
    5.  
    6. ; загоняем параметры функции в стек
    7. push OFFSET ppv2
    8. push OFFSET IID_ISomeOtherInterface
    9. push dword ppv
    10.  
    11. ; а затем вызываем этот метод
    12. call dword ptr [eax + 0]
    Наверное он всё же имел ввиду call dword ptr [edx + 0], а не eax.
    Ну да ладно, меня же больше интересует первая строка из этого.
    Код (Text):
    1. 0047E10E  push        ecx  
    2. 0047E10F  call        dword ptr [edx+34h]
    Для чего нужно передавать указатель на объект в вызов Com метода.
    Мои соображения таковы: Указатель на объект который возвращается например CoCreateInstance, это область памяти переменных объекта, так называемый указатель на this объекта класса. Перавая переменная в этой области, это указатель на vtbl. Причём vtbl всех объектов определённого класса одна и таже. И соответственно местоположение кода идентично. Это и логично ведь код у всех экземпляров одного класса идентичен, и не зачем для каждого экземпляра создавать отдельный участок памяти для него. А вот область памяти переменных у каждого экземпляра своя. Вообщем может кому-то это может показаться очевидным, но это нужно чётко себе представлять когда делается перехват методов объекта. Получается что перехватив функцию в vtbl одного экземпляра, мы автоматически перехватываем во всех экземплярах этого класса. Я этого по началу не понимал, и пытался перехватывать во всех экземплярах, что вело к ошибкам. Но ведь есть ещё понятие интерфейса, и похоже что функции во всех vtbl одного интерфейса, ссылаются на один и тот же код. То есть экземпляр IUnknown один не только для экземпляров одного класса, но и для экземпляров всех других классов, или я не прав? Ещё есть когда интефейс один, но реализаций может быть много, например в DInput функции CreateDevice передаётся GUID устройства. И вроде получаем интерфейс один, но реализаций несколько, а может и не нет, тут у меня ясности пока нет.
    Интересно что скажут знатоки COM Aquila, Roustem, и другие по этому интересному вопросу.
     
  2. AsmGuru62

    AsmGuru62 Member

    Публикаций:
    0
    Регистрация:
    12 сен 2002
    Сообщения:
    689
    Адрес:
    Toronto
    Вообще-то если смотреть на генерацию кода - надо смотреть на оптимизированный код. Присутствие __RTC_CheckEsp говорит, что код скомпилирован в DEBUG режиме.

    Про COM: в теории, каждый COM интерфейс имеет свою реализацию. Это значит, что реализаций должно быть столько сколько есть COM интерфейсов. Надо посмотреть в отладчике виртуальные таблицы для разных интерфейсов - какие адреса там проставлены в первых трёх DWORD-ах.
     
  3. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    AsmGuru62[/b
    Да, тут я поспешил с оценкой, в DEBUG наверно лучше такой код.

    То есть реализация IUnknown всегда одна? Но как тогда быть с интерфейсом объекта возращаемого CreateDevice. Интерфейс то один, а устройств несколько, зависит только от передаваемого функции CreateDevice гуида устройства. Не ужели по стандарту нужно код всех устройств пихать в одну реализацию? Похоже что так и сделано.
     
  4. JohnSmith

    JohnSmith New Member

    Публикаций:
    0
    Регистрация:
    11 янв 2007
    Сообщения:
    41
    мне кажется некоторые вопросы от недостатка теории.

    я очень советую: "Дейл Роджерсон - Основы COM" в сети есть пдфка на русском.
    очень все по полочкам разобрано.