|
|
| Посл.отвђт | Сообщенiе |
|
|
Дата: Июл 7, 2004 12:41:17 Правка Пытаюсь использовать некий СОМ-сервер для своих нужд, но не выходит. 1. В TypeLib сервера указано: function ExecuteSync(command: BSTR): ^Result; stdcall; функция возвращает указатель на интерфейс Result. Но когда я пытаюсь вызвать этот метод: invoke SysAllocString,[lpData] mov [lpBStr],eax comcall pICmd,ExecuteSync,eax nop invoke SysFreeString,[lpBStr] то EAX=0, а стек нарушен. Почему так происходит? все остальные методы работают нормально, не нарушая стек. comcall:
macro comcall object,procn,[arg]
{ common
if ~ arg eq
reverse
pushd arg
common
end if
mov eax,[object#.#handle]
push eax
mov eax,[eax]
call [eax+object#.#procn] }
2. В интерфейсе Result объявлено: //Result text or error message. property-get Text: BSTR; stdcall; //True if a MuPAD error occured. property-get IsError: Bool; stdcall; Как это понимать применительно к асму? Что-то мне подсказывает, что в VTable нужно сделать вместо этих свойств методы getText, getIsError. Или я не прав? 3. Как работать с событиями в СОМ? Перекопал RSDN, порылся в книгах - у меня нет материала по данному вопросу. Может, кто подскажет, в какой стороне искать? Есть интерфейс IEventProperty. В сторону его копать? |
|
|
Дата: Июл 9, 2004 11:20:08 Правка 1. Глянул подробнее, как именно портится стек. Он увеличивается на 4, т.е. получается, что методу не хватает 1 аргумента. О`кей, запушил 0. Отладчик стал вылетать в kernel'e, без него прога отрабатывает нормально, но в еах возвращается чтось левое. В аттаче находится делфийский код двух методов этого СОМ-интерфейса: function ExecuteSync(command: BSTR): ^Result; stdcall; function Execute(command: BSTR); stdcall; Что самое интересное, агрументы по Typelib у них одинаковые, но фактически им передаётся 3 и 2 соответственно. Но что должно идти 3-м аргументом в ExecuteSync? 3. На делфийских сайтах нашёл упоминание о IConnectionPointContainer. А есть ли хорошая книга, описывающая премудрости СОМ? 170676873__TKernel.ExecuteSync.txt |
|
|
Дата: Июл 9, 2004 12:48:10 IceStudent Судя по коду, он предназначен только для его использования из программ на делфи. Параметры этим функциям передаются через регистры, edx - указатель на объект, eax - BSTR, ecx - загадочный параметр. Похоже, что это указатель на dword, в котором хранится указатель на dword(а может быть даже и на целый объект которому принадлежит IResult), в который запишется указатель на интерфейс. |
|
|
Дата: Июл 9, 2004 13:00:06 Правка Black_mirror Он - это кто? Кернел? Да нет, сам-то он на сях написан. Да и описание интерфейса сищное. И что самое интересное - объект работает прекрасно в HTML. А на асме - никак :( |
|
|
Дата: Июл 9, 2004 14:04:05 Просто предположение. Приведённый код - какая-то дельфийная обёртка над COM методами [VTable+28h] и [VTable+1Ch], так что копать нужно последние. По определению, COM не принимает аркументы в регистрах - только со стека. К тому же не видно, что бы аргументы со стека как-то использовались.. (возможно только lea edx,[ebp+var_4]) По поводу аргумента ф-ции согласн с Black_mirror - это какой-то указатель, поэтому и вылетает в ядре с нулём. Можно попробовать вадидный адрес или push esp. |
|
|
Дата: Июл 9, 2004 14:15:44 Он - это кто? Кернел? Он - это COM-сервер. И что самое интересное - объект работает прекрасно в HTML Я понял! Весь этот код это для вызова нормального COM-интерфейса из делфи. Попробуй передать в качестве третьего параметра указатель на dword в котором хранится указатель dword(в него по идее и должен записаться указатель на интерфейс). |
|
|
Дата: Июл 11, 2004 11:20:27 Правка Black_mirror Он - это COM-сервер. Кернел - я имел ввиду СОМ-сервер, TKernel. Спасибо! Экспериментировать без поддержки теорией я не стал, т.к. смутило несоответствие документации и реального положения вещей… |
|
|
Дата: Июл 12, 2004 17:25:38 Правка 1. Black_Mirror Похоже, что это указатель на dword, в котором хранится указатель на dword(а может быть даже и на целый объект которому принадлежит IResult), в который запишется указатель на интерфейс. Именно так! Вы были правы. Я перепробовал остальные методы и, кажется, разобрался. Всё дело в том, что СОМ-методы объектов возвращают результат не в регистр EAX, а записывают его в последний аргумент метода. Это справедливо только для функций, у процедур всё как обычно. Также я не уверен, действителен ли такой подход для INPROC-серверов (физически расположенных в DLL), я проверял только на LOCAL-серверах (EXE-файлы). 1.1. И ещё. Если функции возвращают указатель на интерфейс, то его желательно копировать себе, например, так: lpResult dd ? pIResult IResult … ; вызываем функцию ExecuteSync (function ExecuteSync(command: BSTR): ^Result; stdcall;) comcall pICmd,ExecuteSync,eax,lpResult ; копируем интерфейс invoke CopyMemory,pIResult,[lpResult],sizeof.IResult ; читаем свойство IsError (property-get IsError: Bool; stdcall;) comcall pIResult,get_IsError,lpResult push [lpResult] pop [dwIsError] ; читаем свойство text (property-get Text: BSTR; stdcall;) comcall pIResult,get_Text,lpResult ; результат объявлен как BSTR, фактически возвращается указатель на unicode-строку invoke MessageBox,0,[lpResult],szAppName,64 … Я не уверен на 100% насчёт обязательности копирования интерфейса, но во-первых, Делфи это делает, а во-вторых, я пока не нашёл информацию о гарантии целостности памяти, на которую указывает возвращаемые значения. Хотя вызовы осуществляются RPCRT4.dll, и в её памяти находятся как указатели на VTable методов СОМ-объектов, так и указатели на сами объекты. 4. Неизвестно, что возвращается в ЕАХ после вызовов методов. То ли мусор, то ли информация об ошибке (если есть) вызова функции из RPCRT4.dll. 5. Также хотелось бы узнать о "property-set", если таковые имеются. Как работать с ними? Как с обычными процедурами или имеются ньюансы, как в property-get? |
|
|
Дата: Июл 12, 2004 20:03:52 · Поправил: S_T_A_S_ IceStudent imho не совсем корректно говорить про функцийи и процедуры COM интерфейсов. Это всё методы. Поэтому они и не возвращают "обычный" результат в EAX. В EAX возвращается код результата выполнения, выглядит так: #define MAKE_HRESULT(sev,fac,code) \
((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) )
Если sev = 1, то это ошибка (т.е. бит 31=1), подробнее про это есть статьи на сайте. VTable интерфейса копирования не надо. Указатели на интерфейс валидны пока загружена соответствующая dll. Ещё некоторое упрощение, может оказаться полезным: push reg32 ; место под Result comcall pIResult,get_IsError,ESP ; ESP=lpResult pop [dwIsError] Проблемы с property-get думаю появились только из-за того, что исходный пиример на делфи, нет ли сишных заголовков? property-set так же будут передаваться указатели (вроде в COM только указатели и передаются, для совместимости с чем ни попадя) |
|
|
Дата: Июл 14, 2004 18:57:40 Правка S_T_A_S_ В EAX возвращается код результата выполнения Ой! Я совсем забыл об этом :( VTable интерфейса копирования не надо. Гм… А Борланд делает… В общем, кажется, разобрался. Код заработал. Спасибо всем отвечавшим! |