Как изучить технологию COM ?

Тема в разделе "WASM.BEGINNERS", создана пользователем M0rg0t, 17 окт 2018.

  1. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.574
    Брался за эту технологию раза 4. Каждый раз мозг вскипает и я отступаю. Как можно осилить эту технологию, при условии, что я не знаю ООП и С++? Свои компоненты я писать не планирую, мне бы просто понять, как юзать те, что уже есть в винде. Ну вот пример
    https://docs.microsoft.com/en-us/wi...core/nf-shobjidl_core-ifileoperation-copyitem

    Делаю копипаст оттуда, собираю
    Код (Text):
    1. cannot convert from 'const CLSID' to 'const IID *const '
    2. too few arguments for call
    3. Release' : is not a member of 'IFileOperation'
    Как такое может быть, что код с мсдн не собирается в 2008 студии? Настройки все по дефолту. Причем последние две ошибки вообще удивили - это какой-то новый компонент, или с версии в версию винды меняется к-тво аргументов и методы объекта? В общем, еще раз попробую, если не пойдет, значит не судьба.
     
  2. CrawlUp

    CrawlUp Member

    Публикаций:
    0
    Регистрация:
    1 фев 2018
    Сообщения:
    90
    Лично я понимаю технологию com с сугубо практической точки зрения, так:
    - объявляешь тип объекта
    - получаешь указатель на этот объект из какой либо функции создания этого объекта, присваиваешь полученный указатель объекту
    - подставляешь к объекту(полученному указателю) методы(т.е. функции) и пользуешься.
    Но это всё в С++, на ассемблере всё немного сложнее.
     
  3. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    860
    Какие заголовки подключены?
    Собираешь в C или C++, поскольку эта ошибка обычно появляется когда собираешь на C (код в мсдн на C++). В C нужно напрямую через виртуальную таблицу вызывать вместе с передачей объекта, также там нет __uuidof:
    Код (C):
    1. HRESULT CopyItem(__in PCWSTR pszSrcItem, __in PCWSTR pszDest, PCWSTR pszNewName)
    2. {
    3.     //
    4.     // Initialize COM as STA.
    5.     //
    6.     HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
    7.     if (SUCCEEDED(hr))
    8.     {
    9.         IFileOperation *pfo;
    10.  
    11.         //
    12.         // Create the IFileOperation interface
    13.         //
    14.         hr = CoCreateInstance(&CLSID_FileOperation,
    15.                               NULL,
    16.                               CLSCTX_ALL,
    17.                               &IID_IFileOperation,
    18.                               &pfo);
    19.         if (SUCCEEDED(hr))
    20.         {
    21.             //
    22.             // Set the operation flags. Turn off all UI from being shown to the
    23.             // user during the operation. This includes error, confirmation,
    24.             // and progress dialogs.
    25.             //
    26.             hr = pfo->lpVtbl->SetOperationFlags(pfo, FOF_NO_UI);
    27.             if (SUCCEEDED(hr))
    28.             {
    29.                 //
    30.                 // Create an IShellItem from the supplied source path.
    31.                 //
    32.                 IShellItem *psiFrom = NULL;
    33.                 hr = SHCreateItemFromParsingName(pszSrcItem,
    34.                                                  NULL,
    35.                                                  &IID_IShellItem,
    36.                                                  &psiFrom);
    37.                 if (SUCCEEDED(hr))
    38.                 {
    39.                     IShellItem *psiTo = NULL;
    40.  
    41.                     if (NULL != pszDest)
    42.                     {
    43.                         //
    44.                         // Create an IShellItem from the supplied
    45.                         // destination path.
    46.                         //
    47.                         hr = SHCreateItemFromParsingName(pszDest,
    48.                                                          NULL,
    49.                                                          &IID_IShellItem,
    50.                                                          &psiTo);
    51.                     }
    52.                  
    53.                     if (SUCCEEDED(hr))
    54.                     {
    55.                         //
    56.                         // Add the operation
    57.                         //
    58.                         hr = pfo->lpVtbl->CopyItem(pfo, psiFrom, psiTo, pszNewName, NULL);
    59.  
    60.                         if (NULL != psiTo)
    61.                         {
    62.                             psiTo->lpVtbl->Release(psiTo);
    63.                         }
    64.                     }
    65.                  
    66.                     psiFrom->lpVtbl->Release(psiFrom);
    67.                 }
    68.              
    69.                 if (SUCCEEDED(hr))
    70.                 {
    71.                     //
    72.                     // Perform the operation to copy the file.
    73.                     //
    74.                     hr = pfo->lpVtbl->PerformOperations(pfo);
    75.                 }      
    76.             }
    77.          
    78.             //
    79.             // Release the IFileOperation interface.
    80.             //
    81.             pfo->lpVtbl->Release(pfo);
    82.         }
    83.  
    84.         CoUninitialize();
    85.     }
    86.     return hr;
    87. }
    88.  
    В COM первым аргументом передается ссылка на объект, а сама таблица методов содержится по этому адресу (указатель на интерфейс). Ты вызываешь метод напрямую - так не пойдет, т.к. тут нет ООП - нужно все делать руками. Получаешь указатель на таблицу методов lpVtbl и затем уже вызываешь нужный метод, передавая первым параметром указатель на объект (интерфейсный указатель).
    Вот еще по теме создание COM библиотеки на чистом C без каких-либо зависимостей и вызов из VB6. Также в той теме есть примеры работы на ассемблере и вообще там целая дискуссия на эту тему.
     
    M0rg0t и TermoSINteZ нравится это.
  4. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.707
    M0rg0t,
    1. WASM.IN "Публикации" "COM и OOP"
    2. Win x64 Tutorial #37f: video-player and Component Object Model
    3. Глава 4. Объектно-ориентированное программирование глава из "Турбо Ассемблер 3.0/tasm/#1-2. Руководство пользователя"
    4. Object-Oriented Programming example (Win32 Asm) статья с сайта AsmGuru62
    5. Reversing Microsoft Visual C++ Part II: Classes, Methods and RTTI статья igorsk
    6. Методы реализации ООП на низком уровне топик на wasm.in
    7. Win32 OOP ASM Source Code Generator 47k Generates Object-Oriented ASM source code for:
      • Base class.
      • Derived class.
    8. Object Oriented Programming In Assembly статья Martyn.Rae
    9. Object-Oriented Programming in Assembly Language статья Randall Hyde
    10. RSDN.ORG COM/DCOM/COM+ Сборник статей
      • Основы
      • Исследования
      • Практика
      • Проблемы
      • COM и Script
     
    calidus, inginegr и M0rg0t нравится это.
  5. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.574
    Почему иногда нужно объявлять эти GUID самому? Вот пример ( взято со статьи Rel )
    Код (Text):
    1. static const GUID IID_IDirectDraw = { 0x6c14db80, 0xa733 , 0x11ce,{ 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60 } };
    хотя есть инклуды
    Код (Text):
    1. #include <ddraw.h>
    2. #include <uuids.h>
    Но все равно пишет ошибку линкера. В чем прикол? или эти инклуды для плюсов?

    Также интересно, почему функция DirectDrawCreate не требует CoInitilize , хотя там создаются СОМ объекты..

    Не могу разобраться в этой бредотехнологии и все, вроде чето получилось и дальше куча вопросов.
     
  6. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.235
    Ну чисто формально GUID - это 16 байт статических константных данных, они должны располагаться в какой-то единице трансляции (объектном файле или библиотеке). Если бы их объявляли в хедере и ты подключал этот хедер в образно в двух сишных файлах, то получал бы ошибку редифинишена. Поэтому например в MinGW есть такой хак, как подключение initguid.h, который говорит компилятору, мол в этом сишном файле объяви эти гуиды, а не объяви ссылку на них.

    Не-не, ты попутал, Рел никогда про директдро не писал.
     
  7. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.574
    Rel, ну ты приводил пример , как объявлять guid, там про дебаг были, но не суть, просто пример;
    в кодеблокс вообще ошибки пишет, там даже не хочу пробовать, если честно. Там многие либы еще с ХР не обновлялись походу.
     
  8. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.235
    А, понял, о чем ты, окей.

    Ну с кодблоксом ты можешь использовать любой компилятор и студийный тоже, с любыми подходящими под компилятор библиотеками.
     
  9. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    860
    Нужно просто знать как работает DEFINE_GUID (секция How does the DEFINE_GUID macro work?)
    Словом если нужно использовать определение из хидера достаточно включить Initguid.h в один из cpp файлов перед хидером. Альтернативно можно использовать определение из статической библиотеки. Для DirectDraw нужно подключать ddraw.lib и dxguid.lib.

    Потому что объект создается не напрямую. В MSDN так и написано:
     
    M0rg0t нравится это.
  10. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.574
    Подскажите, как эмулировать нажатие на кнопку на странице? Представим, что есть хтмл код вида

    Код (Text):
    1. <textarea cols="40" rows="4" id="txtdata" name="send1"></textarea>
    2. <input type="button" id="subm1">
    и JS код, который отслеживает ONCHANGE событие текстового поля и что-то там делает.

    Код (C++):
    1.  
    2.     IDispatch*      pDispatch = NULL;
    3.     hr = WebBrowser->lpVtbl->get_Document(WebBrowser,&pDispatch); // объект браузера
    4.  
    5.     if (FAILED(hr) && !pDispatch)
    6.         ExitProcess(EXIT_FAILURE);
    7.  
    8.     // объект документа
    9.     IHTMLDocument3* pDocument3 = NULL;
    10.     hr = pDispatch->lpVtbl->QueryInterface(pDispatch, &IID_IHTMLDocument3, &pDocument3);
    11.  
    12. //элемент
    13.     IHTMLElement *pElementSend = NULL;
    14.  
    15.  
    16.     //textarea - получаем элемент
    17.     hr = pDocument3->lpVtbl->getElementById(pDocument3, L"txtdata", &pElementSend);
    18.     if (FAILED(hr) && !pElementSend)
    19.         ExitProcess(EXIT_FAILURE);
    20.    
    21. //вписываю туда текст
    22.     hr = pElementSend->lpVtbl->put_innerText(pElementSend, L"data123");
    23.     if (FAILED(hr))
    24.         ExitProcess(EXIT_FAILURE);
    25.  
    26.     IHTMLElement *pButton; //получаю кнопку, нажимаю на нее
    27.     hr = pDocument3->lpVtbl->getElementById(pDocument3, L"subm1", &pButton);
    28.     if (FAILED(hr) && !pButton)
    29.         ExitProcess(EXIT_FAILURE);
    30.     hr = pButton->lpVtbl->click(pButton);
    31.     if (FAILED(hr))
    32.         ExitProcess(EXIT_FAILURE);
    33.  
    Не работает, никаких ошибок нет.тупо не работает. Ес-но вручную в браузере работает.
    ну вот который раз берусь и нет слов, кроме матов в адрес этой наркоманской технологии :dash1:
     
  11. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.952
    Технически работать должно. Если проблема в жаваскрипте, который не со скоростью светы исполняется, то:
    Код (ASM):
    1.                             @@:
    2.                             cominvk iWebBrowser2,get_Busy,addr isBusy
    3.                             test eax,eax
    4.                             .if ~ZERO?
    5.                                 mov [nErrorCode1],5
    6.                                 mov [nErrorCode2],eax
    7.                             .else
    8.                                 .if [isBusy] <> 0
    9.                                     invoke Sleep,10
    10.                                     jmp @B
    11.                                 .endif
    по идее должно помочь.

    Кстати вместо put_innerText такое можно делать:
    Код (ASM):
    1.  
    2.                                                     pushdatanp du 'value'\,0
    3.                                                         invoke SysAllocString,esp
    4.                                                         mov [pValueAttributeName],eax
    5.                                                     popdata
    6.                                                     cominvk iFilenameField,setAttribute,[pValueAttributeName],VT_BSTR,0,[pszuActualRomFilename],0,0
     
    M0rg0t нравится это.
  12. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.574
    f13nd, написал так, вроде верно? Все равно не идет
    Код (C++):
    1.   VARIANT_BOOL vb;
    2.  
    3.    WebBrowser->lpVtbl->get_Busy(WebBrowser, &vb);
    4.  
    5.    while (vb != 0)
    6.    {
    7.      WebBrowser->lpVtbl->get_Busy(WebBrowser, &vb);
    8.    }
    может, дело в ajax ? Т.е. для аякс нужны какие-то особые события, хз. Там по кнопке идет аякс запрос с содержимым, но по идее какая разница.

    спасибо. там фиг поймешь в этом всем. с мсдн убрали большую часть документации как депрекейдет.
     
  13. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.952
    isBusy не VARIANT, это WORD.
    Не знаю, вряд ли. Это же интерфейс для элементов страницы в браузере, уровень выше, чем все особенности ее устройства.
     
  14. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.574
    f13nd, да, все сработало, когда навесил событие и на клик по кнопке.
    видимо, он не реагировал на onchange, ну в яваскрипт, тем более текущем, я не особо силен. Короче, работает все и норм. Спасибо!