[default.source] дуальные интерфейсы и позднее связывание
От: SloNN  
Дата: 24.04.03 08:22
Оценка:
Вопрос в следующем:
мне нужно написать объект, который бы перехватывал обычные event'ы через IConnectionPoint и запускал бы их на переданном мне IDispatch. Я загружаю tlb, вычитываю оттуда нужный мне интерфейс, выполняю advise на объекте-источнике событий. Но возникает проблема: если посмотреть в код метода advise в ATL реализации, то там есть такой кусок:


    hRes = pUnkSink->QueryInterface(iid, (void**)&p);
    if (SUCCEEDED(hRes))
    {
        pT->Lock();
        *pdwCookie = m_vec.Add(p);
        hRes = (*pdwCookie != NULL) ? S_OK : CONNECT_E_ADVISELIMIT;
        pT->Unlock();
        if (hRes != S_OK)
            p->Release();
    }
    else if (hRes == E_NOINTERFACE)
        hRes = CONNECT_E_CANNOTCONNECT;
    if (FAILED(hRes))
        *pdwCookie = 0;


где iid — CLSID интерфейса-источника событий (для определенности дальше я буду его называть IID_Event), для которого я говорю advise.
Т.е получается, что ATL делает дополнительную проверку и проверяет, действительно ли переданный ему указатель на интерфейс поддерживает интерфейс-источник событий (IID_Event).

И вроде бы все хорошо, но я ( и другие языки, поддерживающие позднее связывание) не могу в QueryInterface ответить, что я поддерживаю на двоичном уровне IID_Event. Я могу честно ответить, что я поддерживаю IUnknown и IDispatch.
Дальше если посмотреть исходники запуска событий в ATL будет все равно видно, что события вызываются через IDispatch.
Т.е. я могу формально подправить QueryInterface и добавить туда строчку, что я поддерживаю IID_Event, но если вдруг объект-источник событий решит вызвать через указатель методы IID_Event напрямую, не через IDispatch, то тут же получит ошибку доступа к памяти.

Я поискал по интернету, но наткнулся лишь на одну статью с borland'a, где они решают похожую задачу, так там они действительно в QueryInterface объявляют о поддержке IID_Event, но возвращают просто указатель на IDispatch.

Может быть есть какие-нибудь соглашения о вызове методов на [default,source] интерфейсах?
Или нужна какая-нибудь дополнительная обработка?
Re: [default.source] дуальные интерфейсы и позднее связывани
От: Plutonia Experiment Беларусь http://blogs.rsdn.org/ikemefula
Дата: 24.04.03 08:41
Оценка:
Здравствуйте, SloNN, Вы писали:

Это большой недостаток коннекшн поинтов. Обычно используется диспинтерфейс.
Обойти можно, но есть много телодвижений.
Обычно все исходящие интерфейсы являются наследниками от IDispatch.
Если есть диспатч — работай с ним. Если нет — работай напрямую.
Все это можно выяснить из конкретного интерфейса.

Обычно эта ответственность лежит на сервере.
IE, например, проверяет на IDispatch.

Ну и нужно делать дуальный интерфейс, если в IID_Event засовываешь в QueryInterface.



SNN>Вопрос в следующем:

SNN>Т.е. я могу формально подправить QueryInterface и добавить туда строчку, что я поддерживаю IID_Event, но если вдруг объект-источник событий решит вызвать через указатель методы IID_Event напрямую, не через IDispatch, то тут же получит ошибку доступа к памяти.

SNN>Я поискал по интернету, но наткнулся лишь на одну статью с borland'a, где они решают похожую задачу, так там они действительно в QueryInterface объявляют о поддержке IID_Event, но возвращают просто указатель на IDispatch.


SNN>Может быть есть какие-нибудь соглашения о вызове методов на [default,source] интерфейсах?

SNN>Или нужна какая-нибудь дополнительная обработка?
Re: [default.source] дуальные интерфейсы и позднее связывани
От: AlexanderK Россия  
Дата: 24.04.03 08:42
Оценка:
Здравствуйте, SloNN, Вы писали:

На сколько мне известно, default source интерфейсы обычно объявляются как dispinterface. В этом случае можно смело возвращать S_OK на запрос IID_Event.

Вроде бы есть соглашение, что методы source интерфейса [применительно к ActiveX объектам] вызываются только через IDispatch. В принципе, можно поэкспериментировать на VB (VBA): создать объект с дуальным source интерфейсом и генерировать события напрямую. Сам не проверял, но полагаю, что VB поплохеет.
Чтобы хорошо работать, надо получать от этого удовольствие! (c) Michael Schumacher

Re[2]: [default.source] дуальные интерфейсы и позднее связыв
От: SloNN  
Дата: 24.04.03 08:47
Оценка:
Здравствуйте, AlexanderK, Вы писали:

AK>Здравствуйте, SloNN, Вы писали:


AK>На сколько мне известно, default source интерфейсы обычно объявляются как dispinterface. В этом случае можно смело возвращать S_OK на запрос IID_Event.


AK>Вроде бы есть соглашение, что методы source интерфейса [применительно к ActiveX объектам] вызываются только через IDispatch. В принципе, можно поэкспериментировать на VB (VBA): создать объект с дуальным source интерфейсом и генерировать события напрямую. Сам не проверял, но полагаю, что VB поплохеет.


Я проверял, падает, и IE падает тоже .
Хорошо, тогда буду честно заявлять о поддержке IID_Event.
Спасибо.
Re[3]: [default.source] дуальные интерфейсы и позднее связыв
От: AlexanderK Россия  
Дата: 24.04.03 08:56
Оценка:
Здравствуйте, SloNN, Вы писали:

SNN>Я проверял, падает, и IE падает тоже .

SNN>Хорошо, тогда буду честно заявлять о поддержке IID_Event.
SNN>Спасибо.

В общем случае реализовать программно произвольный интерфейс сложновато да и смысла особого не имеет, особенно при условии, что MS этого не делает
Чтобы хорошо работать, надо получать от этого удовольствие! (c) Michael Schumacher

Re[2]: [default.source] дуальные интерфейсы и позднее связыв
От: SloNN  
Дата: 24.04.03 09:04
Оценка:
Здравствуйте, Plutonia Experiment, Вы писали:

Да, я забыл сказать с самого начала, что интерфейс, на котором я перехватываю события — дуальный.
Когда я загружаю tlb, я проверяю на то, что интерфейс, на котором нужно перехватывать события — дуальный, только тогда начинаю делать advise на нем.


PE>Это большой недостаток коннекшн поинтов. Обычно используется диспинтерфейс.

PE>Обойти можно, но есть много телодвижений.

Если не секрет — то как? У меня был только один вариант, что сделать перехват native вызовов к интерфейсу типа того, как сделано в ATL _QIThunk( ставя свои обработчики на первые 1024 метода интерфейса) и переделывает его в вызовы диспатча, но мне показалось это каким-то корявым.


PE>Обычно все исходящие интерфейсы являются наследниками от IDispatch.

PE>Если есть диспатч — работай с ним. Если нет — работай напрямую.
PE>Все это можно выяснить из конкретного интерфейса.

PE>Обычно эта ответственность лежит на сервере.

PE>IE, например, проверяет на IDispatch.

Да, я видел, но только не совсем понял зачем он это делает? Был у меня, конечно, вариант, что он просто делает запрос к IDispatch и отвечает в QueryInterface S_OK на IID_Event, если IID_Event дуальный интерфейс и я поддержал IDispatch.

PE>Ну и нужно делать дуальный интерфейс, если в IID_Event засовываешь в QueryInterface.
Re: [default.source] дуальные интерфейсы и позднее связывани
От: Tom Россия http://www.RSDN.ru
Дата: 24.04.03 09:48
Оценка:
1. Если я правильно тебя понял, то проблемма у тебя с этим IID_Event. Обьесни пожалуйсто что означает это по подробнее:

И вроде бы все хорошо, но я ( и другие языки, поддерживающие позднее связывание) не могу в QueryInterface ответить, что я поддерживаю на двоичном уровне IID_Event.


2. Для конекшнпоинтов который производные от IDispatch можно пользовать IID_IDispatch. Обычно работает. Так что этого вполне достаточно:

Я могу честно ответить, что я поддерживаю IUnknown и IDispatch.

... << RSDN@Home 1.0 beta 6a >>
Народная мудрось
всем все никому ничего(с).
Re: [default.source] дуальные интерфейсы и позднее связывани
От: Vi2 Удмуртия http://www.adem.ru
Дата: 24.04.03 10:24
Оценка:
Здравствуйте, SloNN, Вы писали:

SNN>Может быть есть какие-нибудь соглашения о вызове методов на [default,source] интерфейсах?
SNN>Или нужна какая-нибудь дополнительная обработка?

Соглашений, отличных от существующих в СОМе, нет. Хорошая дискуссия была ранее в этоим форуме (и как раз по дуальному событийному интерфейсу).

1 момент. Событийный интерфейс — это обычный СОМ интерфейс, в котором сервер вызывает объект клиента, т.е. меняется местами: сервер становится клиентом, а клиент — сервером.

2 момент. Сервер (на то он и сервер) уже написан, если рассматривать со стороны клиента, который имеет желание подцепиться к серверу. Поэтому однозначно сервер использует либо диспатч-вызовы (причем сразу по Invoke, без GetIDsOfNames) либо vtable-вызовы.

Если сервер написан с диспатч-вызовами, то Скрипты подсоединяются к событиям через запрос IProvideClassInfo или IProvideClassInfo2 на объекте. Через который они получают информацию о IID событийного интерфейса, который и удовлетворяют в QueryInterface. Неправда, что они это не умеют. Они прекрасно запрашивают QueryInterface на нужные интерфейсы и тогда, когда им надо. Юзеру они не дают таких средств, но это другое дело.

Если Скрипт определяет, что событийный интерфейс — это дуальный или custom, то вполне возможно, что Скрипт отвергнет такое подсоединение, если не может реализовать свой синк. Что и делает, например, VB для дуального интерфейса. Или же попытается подсоединиться через свой диспинтерфейс синка с последующим вылетом.


Поэтому, что заставило тебя использовать дуальные событийные интерфейсы? Можно ли их перевести в обычные дисп-интерфейсы?

Если ты позиционируешь свой объект между сервером событий и получателем, то ты и должен реализовать как свое подключение к существующему серверу, так и клиентское подключение к своему объекту. Если я правильно понял твою модель.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[2]: [default.source] дуальные интерфейсы и позднее связыв
От: SloNN  
Дата: 24.04.03 12:03
Оценка:
Здравствуйте, Vi2, Вы писали:

SNN>Может быть есть какие-нибудь соглашения о вызове методов на [default,source] интерфейсах?
SNN>Или нужна какая-нибудь дополнительная обработка?



Vi2>Если сервер написан с диспатч-вызовами, то Скрипты подсоединяются к событиям через запрос IProvideClassInfo или IProvideClassInfo2 на объекте. Через который они получают информацию о IID событийного интерфейса, который и удовлетворяют в QueryInterface. Неправда, что они это не умеют. Они прекрасно запрашивают QueryInterface на нужные интерфейсы и тогда, когда им надо. Юзеру они не дают таких средств, но это другое дело.


Я не совсем понял выделенного текста.
Я имел в виду, что у меня есть модель:




То есть у меня есть мой объект, реализующий IActiveScript, при этом сразу оговорюсь, что вносить туда изменения, чтобы добавить туда поддержку ActiveX-event'ов нельзя.
Насколько я знаю, нет способа из такого jscript файла ловить event'ы на объектах, созданных через new ActiveXObject().
Поэтому нужен некоторый объект-прокси, который будет жить между IActiveScript и внешним объектом и маршалить event'ы от ActiveX в jscript.

На рисунке я изобразил примерную диаграмму того, что должно быть: т.е сначала я получаю IUnknown(IDispatch) на объект, чьи event'ы мне надо перехватывать, после этого я опрашиваю QueryInterface( IProvideClassInfo2 ) от этого объекта, чтобы получить ссылку на ITypeLib из него и вытащить [default,source] дуальный интерфейс и в конце говорю объекту Advise( proxy ) на этот интерфейс, он мне отвечает QueryInterface( IID_Event ). Вот должен ли я в этом QueryInterface на запрос IID_Event отвечать S_OK или E_NOINTERFACE?

При этом объекты, которые нужно создать из скрипта могут быть любые.


Vi2>Если Скрипт определяет, что событийный интерфейс — это дуальный или custom, то вполне возможно, что Скрипт отвергнет такое подсоединение, если не может реализовать свой синк. Что и делает, например, VB для дуального интерфейса. Или же попытается подсоединиться через свой диспинтерфейс синка с последующим вылетом.


Vi2>Поэтому, что заставило тебя использовать дуальные событийные интерфейсы? Можно ли их перевести в обычные дисп-интерфейсы?


Нет, не могу, это чужие компоненты.

Vi2>Если ты позиционируешь свой объект между сервером событий и получателем, то ты и должен реализовать как свое подключение к существующему серверу, так и клиентское подключение к своему объекту. Если я правильно понял твою модель.


Да, я ее даже нарисовал.
Re[3]: успешный QI и правильный синк-объект
От: Vi2 Удмуртия http://www.adem.ru
Дата: 25.04.03 04:01
Оценка:
Здравствуйте, SloNN, Вы писали:

SNN>То есть у меня есть мой объект, реализующий IActiveScript, при этом сразу оговорюсь, что вносить туда изменения, чтобы добавить туда поддержку ActiveX-event'ов нельзя.
SNN>Насколько я знаю, нет способа из такого jscript файла ловить event'ы на объектах, созданных через new ActiveXObject().
SNN>Поэтому нужен некоторый объект-прокси, который будет жить между IActiveScript и внешним объектом и маршалить event'ы от ActiveX в jscript.

Я имел в виду IActiveScript::AddNamedItem("имя", ...|SCRIPTITEM_ISSOURCE ) с подключением объекта с именем "имя" через хост IActiveScriptSite::GetItemInfo. Как скрипт будет выбирать подпрограммы события (скорее всего, стратегия такая — перебирая методы, определенные у себя, и найденные как "имя_fff" или "имя::fff" и т.п. будет обработчиком) или ему нужно помогать в этом через IActiveScriptParse::AddScriptlet — я точно не знаю.

Поиск на форуме есть — ищи, найдешь массу информации. Не знаю, насколько полезной, но...
Еще по поводу ActiveScript'инга и событий
Автор: Vladik
Дата: 26.02.02

Подключиться к событиям из VBScript
Автор: Vladik
Дата: 03.01.02

Отчёт о дуальных событийных интерфейсах
Автор: Tom
Дата: 24.10.02

Автоматизация работы с использованием Windows Scripting Host
Автор(ы):
Дата: 25.04.2001


SNN>На рисунке я изобразил примерную диаграмму того, что должно быть: т.е сначала я получаю IUnknown(IDispatch) на объект, чьи event'ы мне надо перехватывать, после этого я опрашиваю QueryInterface( IProvideClassInfo2 ) от этого объекта, чтобы получить ссылку на ITypeLib из него и вытащить [default,source] дуальный интерфейс и в конце говорю объекту Advise( proxy ) на этот интерфейс, он мне отвечает QueryInterface( IID_Event ). Вот должен ли я в этом QueryInterface на запрос IID_Event отвечать S_OK или E_NOINTERFACE?
SNN>При этом объекты, которые нужно создать из скрипта могут быть любые.

Подсоединиться к событиям можно только по определенному IID интерфейса, который сервер объявил своим событийным интерфейсом. Так что ты просто обязан не просто ответить S_OK, но и сделать sink, который правильно обработает любые запросы по этому интерфейсу. Впрочем, ты можешь его ограничить только диспатч-частью, рискуя сознательно.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.