У кого і як домогтися отримання COM-об'єкта
Можливо, що на даному етапі це поки і не дуже цікаво, але я хочу повторити свої слова - точне знання філософії взаємодії об'єктів, знання засобів і інструментів, які використовуються на різних етапах цього процесу неминуче. В COM немає можливості "перекомпіліровать все" або запустити відладчик і спостерігати будь-яку частину вашої програми - частина програмного комплексу становитимуть "чужі" об'єкти, з якими ви будете поводитися так само, як і зі своїми. А з'ясувати "що у них всередині" і щось "підправити" ви не зможете, вам залишиться покладатися тільки на точне дотримання протоколу взаємодії.
Для цього нам знадобиться знання деяких подробиць "DLL естроенія". Раніше йшлося про те, що операційна система якимось стандартним чином звертається до модуля, іменованого COM-сервер, і спонукає його видати посилання на COM-об'єкт. Питання, на який хочеться отримати відповідь - як?
Якщо звернутися до технічних подробиць, то ви, мабуть, чули, що DLL - не просто шматок коду. Усередині DLL існують спеціальні таблиці, які описують функції, "зовнішні" з точки зору кордону цієї DLL. Перша таблиця називається IMPORTS - це функції, які потрібні DLL. але які в самій DLL не реалізовані. Друга таблиця називається EXPORTS. вона описує функції, які реалізовані в DLL і пропонуються всім бажаючим.
У постачання Visual Studio існує дуже корисний інструмент дослідження довічних файлів - програма dumpbin.exe. Вона розташовується в каталозі ". \ Program Files \ Microsoft Visual Studio \ VC98 \ Bin" і управляється інтерфейсом командного рядка. Призначення цієї програми - видавати вміст таблиць, що містяться в довічних файлах в человекочітаемом вигляді. Використовуємо її в застосуванні до свідомо COM-сервер, виявленому нами в минулій статті - до DAO350.DLL, який на моїй машині розташовується в каталозі "C: \ Program Files \ Common Files \ Microsoft Shared \ DAO".
Запустимо dumpbin наступною командою з командного рядка:
dumpbin.exe / EXPORTS C: \ Program Files \ Common Files \ Microsoft Shared \ DAO \ DAO350.DLL> tttt.txt
Перепризначення виведення dumpbin в файл tttt.txt зроблено зручності заради. За замовчуванням програма виводить на консоль, а мені хочеться отримати висновок так, щоб його можна було досліджувати і після її завершення. Подивимося, що ми в цей файл отримали. А отримали ми ось (з невеликими скороченнями) що:
Microsoft (R) COFF Binary File Dumper Version 6.00.8447
Dump of file DAO350.DLL
Section contains the following exports for DAO350.dll
Це в точності те, що ми хотіли - таблиця EXPORTS. У цій DLL всього п'ять експортованих функцій! Забігаючи вперед скажу - всі вони використовуються виключно для функціонування COM. тобто перед нами чистий COM-сервер, що не призначений робити нічого більше.
І з цих п'яти функцій зараз мова йде лише про одну - DllGetClassObject. Вона - та сама функція, викликаючи яку система повідомляє серверу посилання на який об'єкт він повинен виготовити і надати системі. Звернення до MSDN дає наступний прототип цієї функції:
Але ось звідки береться аргумент riid і що він означає? І сам це питання і відповідь на нього старанно обходилися з початку нашого викладу, а між тим компонентне програмування взагалі-то починається з відповіді на це питання. riid є ідентифікатор інтерфейсу. У пункті п'ятому нашого філософського викладу стояло - "як взаємодіяти між собою об'єкти і самі знають.". Насправді, в COM об'єкти взаємодіють один з одним за допомогою інтерфейсів і - ніяк інакше.