Анализ кода ATL COM-компонента. Функции глобальной точки входа

   
На этом шаге мы рассмотрим содержимое файла EncodeServer.cpp.

   
На вкладке ClassView рабочей области есть узел Globals, развернув который, Вы увидите несколько
глобальных функций (с префиксом Dll) и один глобальный объект _Module.


Рис.1. Вкладка ClassView

   
Эти элементы находятся файле EncodeServer.cpp, они добавлены в проект мастером ATL COM AppWizard
для предоставления функций точки входа, экспортируемых из DLL и вызываемых из СОМ и других системных
утилит. Вот какой код находится в файле EncodeServer.cpp:

#include "stdafx.h"
#include "resource.h"
#include <initguid.h>
#include "EncodeServer.h"

#include "EncodeServer_i.c"
#include "Encoder.h"


CComModule _Module;

BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_Encoder, CEncoder)
END_OBJECT_MAP()

/////////////////////////////////////////////////////////////////////////////
// Точка входа в DLL

extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
{
    if (dwReason == DLL_PROCESS_ATTACH)
    {
        _Module.Init(ObjectMap, hInstance, &LIBID_ENCODESERVERLib);
        DisableThreadLibraryCalls(hInstance);
    }
    else if (dwReason == DLL_PROCESS_DETACH)
        _Module.Term();
    return TRUE;    // ok
}

/////////////////////////////////////////////////////////////////////////////
// Здесь проверяем, может ли OLE выгрузить нашу DLL 

STDAPI DllCanUnloadNow(void)
{
    return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
}

/////////////////////////////////////////////////////////////////////////////
// Возвращает фабрику классов для создания объекта нужного типа

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
    return _Module.GetClassObject(rclsid, riid, ppv);
}

/////////////////////////////////////////////////////////////////////////////
// DllRegisterServer помещает записи в реестр
// (регистрирует сервер) 

STDAPI DllRegisterServer(void)
{
    // registers object, typelib and all interfaces in typelib
    return _Module.RegisterServer(TRUE);
}

/////////////////////////////////////////////////////////////////////////////
// DllUnregisterServer удаляет записи из реестра
//  (удаляет регистрационную запись сервера)

STDAPI DllUnregisterServer(void)
{
    return _Module.UnregisterServer(TRUE);
}

   
В первой половине файла находится объявление объекта _Module класса CComModule. В классе
CComModule реализован модуль СОМ-сервера, позволяющий клиенту запрашивать его компоненты.
ССоmModule поддерживает как внешние модули, так и модули, встраиваемые в процесс. Внешние серверы
(расположенные в ЕХЕ-файлах) используют объект, реализующий особые функции приложения и являющийся
производным от CComModule.

   
Экземпляр класса CComModule имеет таблицу, называемую картой объекта (object map), которая
хранит набор определений объекта. Внутренние механизмы карты объекта создают и поддерживают массив структур
_ATL_OBJMAP_ENTRY, которые содержат информацию, используемую каркасом для:

  • создания объектов с помощью фабрики классов;
  • создания взаимосвязи между клиентом и корневым объектом компонента;
  • управления существованием объектов класса в памяти;
  • создания и удаления описания объектов в реестре.

   
Макрос OBJECT_ENTRY помещается в карте каждого СОМ-объекта данной DLL. Ему передаются
два параметра. Первый из них - это GUID, уникальный идентификатор СОМ-объекта, а второй -
имя реализующего его класса. На основе этих сведений макрос создает для указанного объекта соответствующую запись
_ATL_OBJMAP_ENTRY.

   
При загрузке DLL в ответ на клиентский запрос СОМ вызывает функцию DllGetClassObject(), которая
в свою очередь для вызова фабрики классов указанного объекта обращается к ССоmModule::GetClassObject() - функции
базового класса, находящейся в глобальном объекте _Module. CComModule::GetClassObject() обращается к
таблице в карте объекта и получает указатель на метод CreateInstance() фабрики классов. С помощью этого
указателя GetClassObject() создает СОМ-объект, выполняет его функцию QueryInterface() и возвращает в СОМ указатель на интерфейс.

   
В серверах, находящихся в ЕХЕ-файлах, Dll-функции не реализованы; вместо этого при запуске вызывается
СОМ-функция CoRegisterClassObject() для каждой реализованной в ней фабрики классов. Указатели на
фабрики классов кэшируются во внутренней таблице. Функции DllRegisterServer() и DllUnregisterServer() реализуют
саморегистрирующийся СОМ-объект, встраиваемый в процесс. Программы типа консольной утилиты
RegSvr32.exe способны вызывать их для добавления в реестр или удаления из него сведений о СОМ-объекте.
Информацию о том, какие действия нужно предпринять - добавить или удалить записи, ЕХЕ-серверы получают из параметров
командной строки: RegServer или UnregServer соответственно. И ЕХЕ, и DLL в конце
концов обращаются к функциям CComModule::RegisterServer() и CComModule::UnregisterServer(). Задача этих функций -
регистрация или дерегистрация всех объявленных в карте объектов на основе информации из сценария реестра.

   
На следующем шаге мы рассмотрим сценарий реестра.



Вы можете оставить комментарий, или Трекбэк с вашего сайта.

Оставить комментарий