Необходимо реализовать интерфейс, которій наследует IDispatch и IObjectWithSite. Возможно ли на masm?
Если это возможно на си, то почему нельзя на масме? Некоторые даже ActiveX на асме написали, что уж говорить о BHO
Ну пусть не в примерах. Слово IObjectWithSite встречается только в \masm32\com\include\bandobj.inc. Даже не знаю, как подступиться к этому на масме. В соседней ветке уже почти выяснил, как это написать на С++, но важен размер, потому необходимо переписать на масм. Помогите, кто знает, плз!!
nobodyzzz IObjectWithSite и IDispatch - это вообще разные интерфейсы IObjectWithSite как и все СОМ интерфейсы, унаследоавн он IUnknown. К 3-м методам которого он добавляет 2 своих.
Кто-то может пояснить, как вообще на масме это все делается? Смотрю пример MyCom2. Практически ничего не понятно. Можна пошагово расписать, как в этом примере IMyCom2 наследует IDispatch, и как к нему добавить наследование IObjectWithSite?
Прочитал. Не понятно, как создать интерфейс, который наследует более одного интерфейса. Вот, что уже написал: Код (Text): _vtIObjectWithSite MACRO CastName:REQ _vtIUnknown CastName &CastName&_SetSite comethod2 ? &CastName&_GetSite comethod3 ? ENDM IObjectWithSite STRUC _vtIObjectWithSite IObjectWithSite IObjectWithSite ENDS vtIDispatch IDispatch < QueryInterface_MC, \ AddRef_MC, \ Release_MC, \ GetTypeInfoCount, \ GetTypeInfo, \ GetIDsOfNames, \ Invoke_ \ > vtIObjectWithSite IObjectWithSite < QueryInterface_MC, \ AddRef_MC, \ Release_MC, \ SetSite, \ GetSite \ > Правильно ли это? Есть две таблицы функций? Как тогда реализовать IClassFactory::CreateInstance?
Как угодно, в принципе - всё равно кастинг (приведение типов) будет через QueryInterface и ты можешь этим управлять. А вообще, в VC - это две vtbl, одна за другой. Смотришь на IID и возвращаешь нужный объект.
Ну вот так например можна? Код (Text): MyComObject STRUCT ; this_ ; interface object lpVtblIDispatch DWORD 0 lpVtblIObjectWithSite DWORD 0 ; object data nRefCount DWORD 1 MyComObject ENDS ... CreateMyComObject PROC LOCAL pNewObject:DWORD invoke CoTaskMemAlloc, sizeof MyComObject mov pNewObject, eax .IF (eax != NULL) mov edx, pNewObject mov (MyComObject PTR [edx]).lpVtblIDispatch, OFFSET [b]vtIDispatch[/b] mov (MyComObject PTR [edx]).lpVtblIObjectWithSite, OFFSET [b]vtIObjectWithSite[/b] mov (MyComObject PTR [edx]).nRefCount, 1 .ENDIF mov eax, pNewObject ret CreateMyComObject endp Тогда что нужно вернуть в QueryInterface_MC, если запрашивается IObjectWithSite? Просто смещение таблицы ее функций? А как тогда будет работать AddRef|Release? Непонятно, как реализовать счетчик. Люди добрые, ну пару строчек примера напишите, пожалуйста!!
Правильно, просто смещение таблицы функций этого интерфейса. AddRef / Release / QueryInterface реализованы все один раз. Все vtable содержат ссылки на одну и ту же реализацию. Можно, в принципе, и не один раз, как угодно можно выворачиваться (если зачем-то нужно). Да вот, даже в одном из Ваших постов выше Вы использовали, например, AddRef_MC и для IObjectWithState, и для IDispatch.
Ну вот смотрите. Код (Text): MyComObject STRUCT ; this_ lpVtblIDispatch DWORD 0 lpVtblIObjectWithSite DWORD 0 nRefCount DWORD 1 MyComObject ENDS если при запросе IObjectDispatch я верну lpVtblIObjectWithSite из QueryInterface_MC, то this_ при вызове AddRef_MC будет указывать на экземпляр MyComObject, смещенный на 4 байта, соответственно, счетчик будет находиться за пределами обьекта. Вот чего я не понимаю. Ведь счетчик-то общий и для IDispatch и для IObjectWithSite.
Счетчик должен быть либо "корректно" размещен относительно AddRef_MC, либо указатель на него должен быть туда передан. Если не нужны выверты, то используется первый случай. Т.е. реализация AddRef_MC у нас одна, в самом классе объекта, значит this при заходе в нее будет указывать именно на объект. То, что QueryInterface вернет указатель на vtable одного из интерфесов совсем не значит, что внутри реализации методов этого интерфеса при их вызове this будет указывать на этот же vtable This указывает на объект, в котором реализована функция этот this используящая. А так как все методы в Вашем случае реализованы на MyComObject, то все ссылки будут "правильными". Последний абзац можно упрощенно резюмировать так: "откуда" бы Вы не зашли в AddRef_MC, this внутри него будет ссылаться на объект, в котором AddRef_MC реализован.
Вот кусок кода из QueryInterface_MC Код (Text): invoke IsEqualGUID, pRIID, addr IID_IObjectWithSite .IF eax == TRUE mov eax, this_ mov eax, (MyComObject PTR [eax]).lpVtblIObjectWithSite ???????????????? правильно mov edx, ppv mov [ edx ], eax invoke AddRef_MC, this_ ; inc the ref count for the new pointer *we* created mov eax, S_OK ; and signal all is well jmp return .ENDIF в таком виде бразуер падает после первого же запроса IID_IObjectWithSite. Если закоментить помеченную строку, то грузиться все нормально, но SetSite и GetSite не вызываются. Запросов на IID_IDispatch вообще не поступает. Если поменять местами lpVtblIObjectWithSite и lpVtblIDispatch в обьявлении MyComObject, то начинает работать, вызывается и SetSite и GetSite.
psu Сделай два разных объекта, по QI возвращай нужный. Или пиши вручную объект, без макросов - чем возиться и гадать, как же извернуться и сделать две v-table.