// find the class object via CoGetClassObject

// находим объект класса с помощью CoGetClassObject

HRESULT hr = CoGetClassObject(CLSIDGorilla, CLSCTXALL, 0, IIDIApeClass, (void**)&pgc);

if (SUCCEEDED(hr))

{

IApe *pApe = 0;

// use the class object to find an existing gorilla

// используем объект класса для нахождения существующей гориллы

hr = pgc->GetApe(nGorillaID, &pApe);

if (SUCCEEDED(hr))

{

// tell the designated gorilla to eat a banana

// прикажем указанной горилле есть бананы

hr = pApe->EatBanana();

pApe->Release();

}

pgc->Release();

}

return hr;

}

Данный пример использует объект класса для того, чтобы Gorilla нашла именованный объект и проинструктировала его есть бананы. Чтобы этот пример работал, нужно, чтобы какой-нибудь внешний посредник дал вызывающему объекту имя какой-нибудь известной гориллы. Можно построить пример и таким образом, чтобы любая неизвестная горилла могла быть использована для удовлетворения запроса:

HRESULT CreateAGorillaAndEatBanana(void)

{

IApeClass *pgc = 0;

// find the class object via CoGetClassObject

// находим объект класса с помощью CoGetClassObject

HRESULT hr = CoGetClassObject(CLSIDGorilla, CLSCTXALL, 0, IIDIApeClass, (void**)&pgc);

if (SUCCEEDED(hr))

{

IApe *pApe = 0;

// use the class object to create a new gorilla

// используем объект класса для создания новой гориллы

hr = pgc->CreateApe(&pApe);

if (SUCCEEDED(hr))

{

// tell the new gorilla to eat a banana

// прикажем новой горилле есть бананы

hr = pApe->EatBanana();

pApe->Release();

}

pgc->Release();

}

return hr;

}

Отметим, что за исключением специфического использования метода IApeClass, эти примеры идентичны. Поскольку объекты класса могут экспортировать сколь угодно сложные интерфейсы, то их можно использовать для моделирования довольно изощренной стратегии активации, инициализации и размещения объектов.

Классы и серверы

СОМ-сервер – это двоичный файл, содержащий код метода для одного или более СОМ-классов. Сервер может быть упакован или в динамически подключаемую библиотеку (DLL), или в нормальный исполняемый файл. В любом случае за загрузку любого типа сервера автоматически отвечает диспетчер управления сервисами SCM.

Если в запросе на активацию объекта указана внутрипроцессная активация, то вариант сервера на базе DLL должен быть доступен для загрузки в адресном пространстве клиента. Если же в запросе на активацию указаны внепроцессная или внехостовая активация, то для запуска серверного процесса на указанной хост-машине (она может совпадать с машиной клиента) будет использован исполняемый файл. СОМ поддерживает также выполнение DLL-серверов в суррогатных процессах (surrogate processes) с целью разрешить использование внепроцессной и внехостовой активации существующих внутрипроцессных серверов. Подробности того, как суррогатные процессы связаны с внепроцессной и внехостовой активацией, будут изложены в главе 6.

Чтобы клиенты могли активировать объекты, не беспокоясь о том, как упакован сервер или где он инсталлирован, в СОМ предусмотрена конфигурационная база данных, отображающая CLSID на тот сервер, который реализует этот класс. При использовании версий Windows NT 5.0 или выше основным местом расположения этой конфигурационной базы данных является директория NT (NT Directory). Эта директория является рассредоточенной защищенной базой данных, в которой хранится служебная информация об учетных записях пользователей, хост-машинах и прочее. С тем же успехом в директории NT можно хранить информацию и о СОМ-классах. Эта информация записывается в области директории, называемой СОМ Class Store (хранилище СОМ-классов). СОМ использует Class Store для перевода CLSID в файлы реализации (в случае локальных запросов на активацию) или в удаленные хост-имена (в случае удаленных запросов на активацию). Если запрос на активацию для CLSID сделан на данной машине, то в первую очередь опрашивается локальный кэш. Если в локальном кэше нет доступной конфигурационной информации, то СОМ посылает запрос в Class Store о том, чтобы реализация стала доступной из локальной машины. Это может просто означать добавление некоторой информации в локальный кэш, чтобы переадресовать запрос на другую хост-машину, или же это может привести к загрузке реализации класса на локальную машину и к запуску программы инсталляции. В любом случае, если класс зарегистрирован в Class Store, он доступен для запроса на активацию со стороны клиента в рамках ограничений безопасности.

Локальный кэш, упоминавшийся при обсуждении Class Store, официально называется системным реестром, или базой конфигурации системы (Registry). Реестр является иерархической базой данных, хранящейся в файлах на каждой машине, которую СОМ использует для преобразования CLSID в имена файлов (в случае локальной активации) или удаленные имена хостов (в случае удаленной активации). До Windows NT 5.0 реестр был единственным местом размещения конфигурационной информации СОМ. Быстрый поиск в реестре может быть осуществлен с помощью иерархических ключей (keys), имена которых представляют собой строки, разделенные обратными косыми чертами. Каждый ключ в реестре может иметь одно или несколько значений, которые могут иметь в своем составе строки, целые значения или двоичные данные. В реализации СОМ на Windows NT 4.0 большая часть ее конфигурационной информации записывается под именем

HKEYLOCALMACHINE\Software\Classes

в то время как большинство программ используют более удобный псевдоним

HKEYCLASSESROOT

Реализация СОМ на Windows NT 5.0 продолжает использовать HKEYCLASSESROOT для установок в рамках всей машины, но также разрешает каждому пользователю назначить свою конфигурацию CLSID для обеспечения большей безопасности и гибкости. Под Windows NT 5.0 СОМ вначале опрашивает

HKEYCURRENTUSER\Software\Classes 

прежде чем опрашивать HKEYCLASSESROOT. Для удобства записи часто используются аббревиатуры HKLM, HKCR и HKCU вместо HKEYLOCALMACHINE, HKEYCLASSESROOT и HKEYCURRENTUSER , соответственно[1]

СОМ хранит информацию, относящуюся к CLSID всех машин, под ключом реестра HKCR\CLSID

В версии Windows NT 5.0 или выше СОМ ищет информацию о классах каждого пользователя под ключом HKCU\Software\Classes\CLSID

Под одним из этих ключей будет сохранен список локальных CLSID, для каждого CLSID – свой подключ. Например, класс Gorilla, использовавшийся ранее в этой главе, мог бы иметь по всей машине запись по подключу[2]:

[HKCR\CLSID\{571F1680-CC83-11d0-8C48-0080C73925BA}]

@="Gorilla"

Для обеспечения локальной активации объектов Gorilla запись для CLSID Gorilla в реестре должна иметь подключ, показывающий, какой файл содержит исполняемый код для методов класса. Если сервер упакован как DLL, то требуется такая запись:

[HKCR\CLSID\{571F1680-CC83-11d0-8C48-0080C73925BA}\InprocServer32]

@="C:\ServerOfTheApes.dll"

Чтобы показать, что код упакован в исполняемом файле, требуется такая запись:

[HKCR\CLSID\{571F1680-CC83-11d0-8C48-0080C73925BA}\LocalServer32]

@="С:\ServerOfTheApes.exe"

Допустимо обеспечивать обе записи и позволить клиенту выбирать местоположение, исходя из требований времени задержки и устойчивости. Для поддержки функции ProgIDFromCLSID необходимо указать такой подключ:

вернуться

1 Эти аббревиатуры не допускаются в исходном коде или в конфигурационных файлах. Они просто дают возможность длинным именам ключей фигурировать в виде одной строки без разделителей в документации или других текстах о СОМ. Читателю следует раскрывать аббревиатуры при чтении вслух или при использовании в исходном коде.

вернуться

2 Приведенный здесь способ записи использует стандартный синтаксис REGEDIT4 . Строки, содержащиеся внутри скобок, соответствуют именам ключей. Пары имя=значение (name = value) под ключом обозначают значения, присвоенные указанному ключу. Необычное имя "@" показывает значение ключа по умолчанию.


Перейти на страницу:
Изменить размер шрифта: