Каким образом правильно работать с неизвестными COM Объектами в С++

Тема в разделе "WASM.WIN32", создана пользователем wertyman, 13 дек 2006.

  1. wertyman

    wertyman Member

    Публикаций:
    0
    Регистрация:
    13 дек 2006
    Сообщения:
    74
    Добрый день..
    Такая проблемка, есть исходник написанный на MASM который работает с COM объектом, неизвестного интерфейса, все структуры и GUIDы там указаны и все работает чудно, пытаюсь перевести исходник на С++ получаю грабли с вызовом методов из объекта :dntknw:
    В масме за это отвечает макрос coinvoke, весьма по хитрому работает, ну сам алгоритм я понял, а вот как он делает вызов через структуру интерфейса понять не могу :dntknw:

    Вот код на масме
    Код (Text):
    1.  IBackgroundCopyManager     STRUCT DWORD
    2.     IBackgroundCopyManager_QueryInterface       comethod3       ?
    3.     IBackgroundCopyManager_AddRef           comethod1       ?
    4.     IBackgroundCopyManager_Release                  comethod1       ?
    5.     IBackgroundCopyManager_CreateJob        comethod5       ?
    6.     IBackgroundCopyManager_GetJob           comethod3       ?
    7.     IBackgroundCopyManager_EnumJobs     comethod3       ?
    8.     IBackgroundCopyManager_GetErrorDescription  comethod4       ?
    9.  IBackgroundCopyManager     ENDS
    10. ; -----
    11. invoke  CoCreateInstance, ADDR CLSID_BackgroundCopyManager, NULL, CLSCTX_ALL, ADDR IDD_IBackgroundCopyManager, ADDR pbcm
    12. ; -----
    13. coinvoke pbcm, IBackgroundCopyManager, CreateJob, OFFSET szDspName, NULL, ADDR JobId, ADDR pbcj
    На С++ пытаюсь сделать так
    Код (Text):
    1. typedef struct _IBackgroundCopyManager {
    2.     PROC QueryInterface;
    3.     PROC AddRef;
    4.     PROC Release;
    5.     PROC CreateJob;
    6.     PROC GetJob;
    7.     PROC EnumJobs;
    8.     PROC GetErrorDescription;
    9. } IBackgroundCopyManager, *PIBackgroundCopyManager;
    10.  
    11. HRESULT hRes = CoCreateInstance(CLSID_BackgroundCopyManager, NULL, CLSCTX_ALL, IDD_IBackgroundCopyManager, (void**)&pbcm);
    12. PROC addr = 0;
    13. addr = pbcm->CreateJob;
    14. _asm {
    15.     lea ecx, pbcj;
    16.     push ecx;
    17.     lea ecx, gJobId;
    18.     push ecx;
    19.     push 0;    
    20.     push offset[szJobName];
    21.     call dword ptr[addr];
    22. }
    нифига понять не могу :wall: структура заполняется вроде данными и вроде верными, одно смущает, что некоторые адреса там из самой длл КОМпонента, а некоторые из моего процесса...

     
  2. EvilsInterrupt

    EvilsInterrupt Постигающий азы дзена

    Публикаций:
    0
    Регистрация:
    28 окт 2003
    Сообщения:
    2.428
    Адрес:
    Russia
    wertyman
    На rsdn.ru есть статейка как реверсить COM-сервера, там как раз на с++
     
  3. TheRawGod

    TheRawGod New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    71
    Ну, к слову, 2 интерфейса этого самого объекта вполне известны, исходя из Вашего кода: IUnknown и IBackgroundCopyManager.
    Первое что пришло в глову - это МСДН. IBackgroundCopyManager там вполне описан, в Platform SDK, используется для BITS сервисов или что-то там такое:)

    Bits.h
    Bits.idl <---!!!
    Bits.lib
    QmgrPrxy.dll
    IID_IBackgroundCopyManager == 5CE34C0D-0DC9-4C1F-897C-DAA1B78CEE7C

    Есть ли необходимость изобретать велосипед и описывать интерфейс самому, раз мы можем взять родную idl-ку для него и скомпилировав ее, получить отличное описание интерфейса?
     
  4. P_F

    P_F New Member

    Публикаций:
    0
    Регистрация:
    27 мар 2006
    Сообщения:
    116
    Адрес:
    Russia
  5. EvilsInterrupt

    EvilsInterrupt Постигающий азы дзена

    Публикаций:
    0
    Регистрация:
    28 окт 2003
    Сообщения:
    2.428
    Адрес:
    Russia
    TheRawGod
    Ты прав, есть такая возможность! вот токо название забыл!
    Как вспомню, это сообщение отредактирую. :)
     
  6. censored

    censored New Member

    Публикаций:
    0
    Регистрация:
    5 июл 2005
    Сообщения:
    1.615
    Адрес:
    деревня "Анонимные Прокси"
    wertyman
    Код (Text):
    1. #include <windows.h>
    2. #include <objbase.h>
    3. #include <bits.h>
    4. #pragma hdrstop
    5. #pragma comment(lib, "bits.lib")
    6.  
    7. int main() {
    8.   HRESULT hr;
    9.   IBackgroundCopyManager * bcm;
    10.   IBackgroundCopyJob * bcj;
    11.   GUID jobid;
    12.  
    13.   CoInitialize(NULL);
    14.  
    15.   hr = CoCreateInstance(CLSID_BackgroundCopyManager, 0, CLSCTX_ALL,
    16.     IID_IBackgroundCopyManager, (LPVOID *)&bcm);
    17.   if (hr==S_OK) {
    18.     hr = bcm->CreateJob(L"asdf", BG_JOB_TYPE_DOWNLOAD /*0*/,
    19.       &jobid, &bcj);
    20.     if (hr==S_OK) {
    21.       hr = bcj->AddFile(L"http://localhost/notepad.exe", L"c:\\temp\\calc.exe");
    22.       if (hr==S_OK) {
    23.         BG_JOB_STATE state;
    24.         bcj->Resume();
    25.         do {
    26.           Sleep(100);
    27.           hr = bcj->GetState(&state);
    28.         } while (state!=BG_JOB_STATE_TRANSFERRED);
    29.         WinExec("c:\\temp\\calc.exe", SW_SHOW);
    30.       }
    31.       bcj->Release();
    32.     }
    33.     bcm->Release();
    34.   }
    35.  
    36.   CoUninitialize();
    37. }
     
  7. wertyman

    wertyman Member

    Публикаций:
    0
    Регистрация:
    13 дек 2006
    Сообщения:
    74
    да да, все это читал и смотрел, просто создалось впечатление, что код от этого станет громоздким и сам бинарник то же... т.к. посмотрел если на масме это возможно было реализовать без всяких дополнительных заголовков и т.п. то почему бы на сях так же не сделать ?

    То же читал, нифига не вышло :dntknw: Там показано как вызывать QueryInterface, а он у меня нормально вызывается по своему...

    censored
    спасибо, это аналог исходника на масме только с хенедерами сишными :)

    Значит сделать это так же тупо как на масме не получится или просто не стоит заморачиваться ?
     
  8. TheRawGod

    TheRawGod New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    71
    wertyman
    та дело в том, что скомпилировав idl-ку, получится header, в котором будет описание этого интерфейса, которое точно будет нормально работат с QueryInterface. Его и заюзать.
    Не вижу, от чего тут может "разбухнуть" бинарик.

    А еще интересно, зачем они предлагают линковаться к либе / ддл-ке.

    EvilsInterrupt,
    название в студию! :)
     
  9. Freeman

    Freeman New Member

    Публикаций:
    0
    Регистрация:
    10 фев 2005
    Сообщения:
    1.385
    Адрес:
    Ukraine
    хитрый интерфейс. :)
     
  10. EvilsInterrupt

    EvilsInterrupt Постигающий азы дзена

    Публикаций:
    0
    Регистрация:
    28 окт 2003
    Сообщения:
    2.428
    Адрес:
    Russia
     
  11. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Тема не совсем корректно названа - объект-то известный. И заголовочные файлы к нему есть.
     
  12. TheRawGod

    TheRawGod New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    71
    Та и пример кода, если разобраться, на С, а не на С++ :)
     
  13. wertyman

    wertyman Member

    Публикаций:
    0
    Регистрация:
    13 дек 2006
    Сообщения:
    74
    Ну да, нашел хедеры и либу и сделал как советовали... действительно не сильно разбух :)
    Но все равно из принципа было интересно почему он не хотел работать по моему способу :dntknw:
     
  14. TheRawGod

    TheRawGod New Member

    Публикаций:
    0
    Регистрация:
    6 июл 2003
    Сообщения:
    71
    wertyman
    А вот ради интереса, если убрать либу, т.е. не прилинковывать ее, а все остальное оставить, то оно ругается? Если да, то на что именно?
    Заранее спасибо! :)

    А почему Ваш вариант не работет - надо глянуть вовнутрь bits.h и посмотреть, чем объявление интерфейса в нем отличается от Вашего:)
    Вы определили у себя переменные, в которые планировали поместить указатели на функции, а QueryInterface заполняет vtable Вашей структуры, т.е. таблицу указателей на функции, а это немного другое:)
    Насколько я могу судить на скорую руку, глядя в bits.h, vtable - таблица указателей, которую Вы пытались заполнить, является первым элементом структуры интерфейса. Этот адрес разименовывается и по нему заполняется таблица адресов на функции. Посмотрите как выглядит "C style interface" Вашего интерфейса в bits.h.
    Кроме того, первым в самой vtable идет также функция (макрос BEGIN_INTERFACE). Отсюда и следует, что Вы заполняли просто не совсем то, что предполагали:)

    Внимательно просмотрите bits.h на предмет различий в описаниях Вашего интерфейса и описания, полученного после компиляции .idl файла и все должно стать на свои места.