STDMETHODIMP MyClassObject::CreateInstance(IUnknown *puo, REFIID riid, void **ppv) {
LockModule();
// ensure we don't shut down while in call
// убеждаемся в том, что не прекращаем работу
// во время вызова HRESULT hr;
*ppv = 0;
// shutdown initiated?
// процесс останова запущен?
DWORD dw = WaitForSingleObject(g_heventShutdown, 0);
if (dw == WAIT_OBJECT_0) hr = CO_E_SERVER_STOPPING;
else {
// normal CreateInstance implementation
// нормальная реализация CreateInstance
}
UnlockModule();
return hr;
}
Во время написания этого текста ни одна из коммерческих библиотек классов COM не реализовывала этот способ.
Идентификаторы приложений
В версии COM под Windows NT 4.0 введено понятие приложений COM ( COM applications ). Приложения COM идентифицируются с помощью GUID (называемых в этом контексте AppID – идентификаторы приложения) и представляют серверный процесс для одного или более классов. Каждый CLSID может быть связан с ровно одним идентификатором приложений. Эта связь фиксируется в локальном реестре, использующем именованное значение AppID :
[HKCR\CLSID\{27EE6A4E-DF65-11D0-8C5F-0080C73925BA}] @="Gorilla" AppID="{27EE6A4E-DF65-11D0-8C5F-0080C73925BA}"
Все классы, принадлежащие к одному и тому же приложению COM, будут иметь один и тот же AppID , а также будут использовать одни и те же установки удаленной активации и защиты. Эти установки записаны в локальном реестре под ключом HKEY_CLASSES_ROOT\AppID
Подобно CLSID, AppID могут быть зарегистрированы для каждого пользователя под Windows NT версии 5.0 или выше. Поскольку серверы, реализованные до появления Windows NT 4.0, не регистрируют явно свои AppID , инструментальные средства конфигурирования COM (например, DCOMCNFG.EXE , OLEVIEW.EXE ) автоматически создадут новый AppID для этих старых серверов. Чтобы синтезировать AppID для старых серверов, эти программы автоматически добавляют именованное значение AppID ко всем CLSID , экспортируемым определенным локальным сервером. При добавлении этих именованных значений DCOMCNFG или OLEVIEW просто использует в качестве AppID первый встреченный CLSID для данного сервера. Те приложения, которые были разработаны после выпуска Windows NT 4.0, могут (и будут) использовать для своих AppID особый GUID .
Большинством установок AppID можно управлять с помощью программы DCOMCNFG.EXE , которая является стандартным компонентом Windows NT 4.0 или выше. DCOMCNFG.EXE предоставляет администраторам удобный для использования интерфейс для контроля установок удаленного доступа и защиты. Более мощный инструмент, OLEVIEW.EXE , осуществляет большинство функциональных возможностей DCOMCNFG.EXE и, кроме того, обеспечивает очень «COM-центрический» ( COM-centric ) взгляд на реестр. Обе эти программы интуитивно понятны при использовании и обе являются существенными для разработок с использованием COM.
Простейшим установочным параметром AppID является RemoteServerName . Эта именованная величина показывает, какую хост-машину следует использовать для удаленных запросов на активацию, если в них явно не указано с помощью COSERVERINFO удаленное хост-имя. Рассмотрим следующие установки реестра:
[HKCR\AppID\{27EE6A4D-DF65-11d0-8C5F-0080C73925BA}] @="Аре Server" RemoteServerName="www.apes.com"
[HKCR\AppID\{27EE6A4E-DF65-11d0-8C5F-0080C73925BA}] @="Gorilla" AppID={27EE6A4D-DF65-11d0-8C5F-0080C73925BA}
[HKCR\AppID\{27EE6A4F-DF65-11d0-8C5F-0080C73925BA}] @="Chimp" AppID={27EE6A4D-DF65-11d0-8C5F-0080C73925BA}
Если клиент осуществляет такой запрос на активацию:
IApeClass *рас = 0;
HRESULT hr = CoGetClassObject(CLSID_Chimp, CLSCTX_REMOTE_SERVER, 0, IID_IApeClass, (void**)&pac);
то SCM со стороны клиента направит этот запрос в SCM на www.apes.com , где этот запрос будет рассмотрен как локальный активационный запрос. Отметим, что если клиент предоставляет явное хост-имя:
IApeClass *рас = 0;
COSERVERINFO csi;
ZeroMemory(&csi, sizeof(csi));
csi.pwszName = OLESTR( www.dogs.com);
HRESULT hr = CoGetClassObject(CLSID_Chimp, CLSCTX_REMOTE_SERVER, &csi, IID_IApeClass, (void**)&pac);
то установка RemoteServerName игнорируется и запрос направляется в www.apes.com .
Чаще встречается ситуация, когда клиенты не указывают явно свои предпочтения относительно хост-имени и месторасположения. Рассмотрим следующий вызов CoGetClassObject
IApeClass *pac = 0;
HRESULT hr = CoGetClassObject(CLSID_Chimp, CLSCTX_ALL, 0, IID_IApeClass, (void*)&pac);
Поскольку не указано никакого хост-имени, то SCM сначала будет искать в локальном реестре следующий ключ:
[HKCR\AppID\{27EE6A4F-DF65-11d0-8C5F-0080C7392SBA}]
Если этот ключ локально не доступен, COM обратится к хранилищу класса ( class store ) под Windows NT 5.0, если оно доступно. Если с этой точки зрения ключ реестра доступен, то вслед за этим SCM будет искать подключ InpocServer32 :
HKCR\CLSID\{27EE6A4F-DF65-11d0-8C5F-0080C73925BA}\InprocServer32] @="C:\somefile.dll"
Если этот ключ найден, класс будет активирован путем загрузки той DLL, которая указана в реестре. В противном случае SCM ищет подключ InprocHandler32 :
Читать дальше