· Начало · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.WIN32 —› Работа с СОМ на асме

Посл.отвђт Сообщен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 интерфейса копирования не надо.“
Гм… А Борланд делает…

В общем, кажется, разобрался. Код заработал.

Спасибо всем отвечавшим!