- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Интернет-журнал 'Домашняя лаборатория', 2007 №6 - Вязовский
Шрифт:
Интервал:
Закладка:
{
*ppv = (IUnknown*)this;
}
else if(riid == IID_IClassFactory)
{
*ppv = (IdassFactory*) this;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
(IUnknown*)(*ppv)) — >AddRef();
return S OK;
}
//IClassFactory
STDMETHODIMP CoJournaiFactory::Createlnstance(
LPUNKNOWN pUnkOuter, REFIID riid, void** ppv)
{
if(pUnkOuter!= NULL)
{
return СLASS_E_NOAGGREGATION;
}
CoJournal* pJournalObj = NULL;
HRESULT hr;
pJournalObj = new CoJournal;
hr = pJournalObj — > QueryInterface(riid, ppv);
if (FAILED(hr))
delete pJournalObj;
return hr;
}
STDMETHODIMP CoJournalFactory::LockServer(BOOL fLock)
{
if (fLock)
++g_lockCount;
else
--g_lockCount;
return S OK;
}
Заканчивая разговор о фабрике класса нужно заметить, что для нее не нужно задавать GUID.
Сервер в процессе клиента
Итак, для активации некоторого СОМ объекта необходимо создать фабрику класса для соответствующего класса и получить указатель на интерфейс IClassFactory. Далее, используя этот интерфейс, можно создать любое число экземпляров этого кокласса и получить указатели на любые реализуемые коклассом интерфейсы. Но как создать фабрику класса?
Все, что достаточно знать клиенту о коклассе, это его глобальный идентификатор (GUID). Зная этот идентификатор, клиент может воспользоваться функцией CoGetClassObject, которая заставит менеджер управления сервисом найти и загрузить нужный сервер (в котором "живет" нужный кокласс), активизировать фабрику класса для этого кокласса и возвратить клиенту указатель на интерфейс IClassFactory.
Всю необходимую информацию менеджер получает из реестра системы. Подробнее это будет обсуждаться далее, пока достаточно заметить, что реестр представляет собой специальную базу данных, используя которую, в частности, по глобальному идентификатору кокласса можно узнать тип сервера, в котором этот кокласс "живет" (сервер в процессе клиента, сервер в другом процессе на этой же машине или сервер на удаленной машине), путь к серверу (для серверов на данной машине) или путь к удаленной машине (для сервера на удаленной машине).
Далее работа менеджера зависит от типа сервера.
Пока мы строим сервер в процессе клиента, реализуемый в виде dll. Для этого, при работе в Visual C++, можно создать пустое рабочее пространство проекта Win32 DLL с именем PubInPrосServer. В этом проекте нужно создать (или перенести созданные в другом месте) классы CoBook, CoJournal, CoBookFactory, СоJournalFactory. Там же ДОЛЖНЫ находиться файлы с определениями интерфейсов IPub, IBook, IJournal, файл с GUID для всех интерфейсов и коклассов iid.h и (как советует Э.Трельсен в книге [3]) следующий файл iid.cpp
// iid.cpp: гарантирует автоматический вызов <initguid.h>
// перед "iid.h"
#include <windows.h>
#include <initguid.h>
#include "iid.h"
Теперь нужно создать файл, имя которого совпадает с именем проекта — PublnProcServer.cpp:
#include "CoBookFactory.h"
#include "CoJournalFactory.h"
ULONG g_lockCount = 0;
ULONG g_objCount = 0;
STDAPI DllCanUnloadNow()
{
if (g_lockCount == 0 && g_objCount == 0)
return S_OK;
else
return S_FALSE;
}
STDAPI DllGetClassObject(REFCLSID rclsid,
REFIID riid, void** ppv)
{
HRESULT hr;
CoBookFactory* pBookFact = NULL;
CoJournaiFactory* pJournalFact = NULL;
if (rclsid == CLSID_CoBook)
{
pBookFact = new CoBookFactory;
hr = pBookFact —> QueryInterface(riid, ppv);
if (FAILED(hr))
delete pBookFact;
return hr;
}
else if (rclsid == CLSID_CoJournal)
{
pJournalFact = new CoJournaiFactory;
hr = pJournalFact->QueryInterface(riid, ppv);
if (FAILED(hr))
delete pJournalFact;
return hr;
}
else
return СLASS_E_CLASSNOTAVAILABLE;
}
В файле PubInProcServer.cpp определяются и инициализируются нулем две глобальные переменные g_lockCount, g_objCount — соответственно счетчики числа блокировок сервера в памяти и числа активных объектов.
Далее дается реализация двух экспортируемых из dll функций — DllGetClassObject и DllCanUnioadNow. Используя первую, менеджер управления сервисом (из СОМ) сможет активизировать фабрику класса запрашиваемого кокласса и получить указатель на интерфейс ICiassFactory соответствующей фабрики класса. Вторая функция используется менеджером на этапе принятия решения об удалении сервера из памяти.
Рассмотрим подробнее реализацию функции DllGetClassObject.
Эта функция получает в качестве аргументов ссылку на GUID нужного кокласса, ссылку на желаемый интерфейс фабрики класса этого кокласса (обычно IID_IClassFactory) и в качестве выходного параметра возвращает указатель на запрашиваемый интерфейс. Возвращаемое функцией значение типа HRESULT говорит об успехе или неудаче операции. В последнем случае можно выяснить причину неудачи. Дня проверки успешности операции можно использовать определенные в СОМ макроопределения SUCCEEDED() и FAILED(), анализирующие старший бит возвращенного значения типа HRESULT.
Реализация функции DllCanUnioadNow тривиальна.
Обычно dll Сервер Экспортирует еще две функции: DllRegisterServer и DllUnregisterServer. Эти функиции должны обеспечить саморегистрацию сервера в реестре. В данном курсе этот вопрос не рассматривается, и регистрация разрабатываемого сервера будет проведена вручную с помощью редактора реестра.
Далее надо включить в проект стандартный DEF-файл PubInProcServer.def, который перечисляет экспортируемые функции:
LIBRARY "PUBINPROCSERVER"
EXPORTS
DllGetClassObject @1 PRIVATE
DllCanUnloadNow @2 PRIVATE
Здесь название библиотеки должно совпадать с названием проекта, private используется для того, чтобы компоновщик не поместил имена этих функций в библиотеку импорта, т. к. они будут использоваться только СОМ.
Регистрация сервера в реестре
Теперь сервер готов, но для его использования необходимо внести некоторые данные в реестр системы. Сделаем это, используя редактор реестра — regedit.ехе. Для внесения минимальной информации о сервере внесем в реестр следующие данные:
• CLSID и соответствующие ProgID и путь к серверу
Программный идентификатор (ProgID) используется некоторыми программами как некоторая замена CLSID (требуется только локальная уникальность). Формат для ProgID
имя_сервера. имя_кокласса. Для CoBook это PuInProcServer.CoBook.
Под ключом HKEY_CLASSES_ROOT нужно найти ключ CLSID и под ним создать раздел {49F00760-7238-11d5-98C7-000001223694}. Это CLSID для кокласса CoBook. Для задания соответствующего ProgID следует для данного раздела создать подраздел с именем ProgID и в качестве значения для параметра по умолчанию взять PubInProcServer.CoBook.
Аналогично, под ключом HKEY_CLASSES_ROOT CLSID нужно еще создать раздел {49F00761-7238-11d5-98C7-000001223694}. Это CLSID ДЛЯ кокласса

