Одна интересная разновидность управления маркером и window-станцией серверного процесса относится к службам NT. Напомним, что наличие именованной величины LocalService заставляет SCM использовать для запуска серверного процесса NT Service Control Manager вместо CreateProcess или CreateProcessAsUser. При запуске серверных процессов как сервисов NT COM не контролирует, с каким принципалом запускается этот процесс просто потому, что это жестко запрограммировано в конфигурации соответствующей запущенной службы NT. В этом случае COM игнорирует именованную величину RunAs, чтобы убедиться, что случайные процессы не могут имитировать вызовы CoRegisterClassObject. Наличие именованной величины LocalService требует, чтобы вызывающая программа выполнялась как сервис NT. Если сам этот сервис сконфигурирован на запуск как встроенная учетная запись SYSTEM, то серверный процесс либо запустит интерактивную window– станцию, либо будет запущена заранее определенная window-станция, совместно используемая всеми сервисами NT в качестве SYSTEM (это зависит от того, как именно сконфигурирован сервис NT). Если вместо этого сервис NT сконфигурирован для выполнения как отдельная учетная запись пользователя, то NT Service Control Manager будет всегда запускать сервис NT под новой window– станцией, специфической для данного серверного процесса.
Одно общее соображение в пользу реализации сервера COM как сервиса NT заключается в том, что только сервисы NT способны выполняться со встроенной учетной записью SYSTEM. Эта учетная запись обыкновенно имеет больший доступ к таким локальным ресурсам, как файлы и ключи реестра. Кроме того, эта учетная запись часто является единственной, которая может выступать как часть доверительной компьютерной базы (trusted computing base) и использовать низкоуровневые службы защиты, доступ к которым был бы опасен из обычных пользовательских учетных записей. К сожалению, хотя учетная запись SYSTEM воистину всемогуща в локальной системе, она полностью бессильна для доступа к защищенным удаленным ресурсам, в том числе к удаленным файловым системам и к удаленным объектам COM. Это обстоятельство делает учетную запись SYSTEM отчасти менее полезной для построения распределенных систем, чем можно было бы ожидать. Вне зависимости от того, используется ли сервер как сервис NT или в качестве традиционного процесса Win32, принято создавать отдельную учетную запись пользователя для каждого приложения COM, которое имеет полные полномочия для доступа в сеть.
Где мы находимся?
В данной главе рассматривались вопросы, относящиеся к выделению классов в отдельные серверные процессы. COM поддерживает запуск серверных процессов на основе запросов на активацию. Эти серверные процессы должны саморегистрироваться с помощью библиотеки COM, используя CoRegisterClassObject для того, чтобы обеспечить доступ к объектам своего класса со стороны внешних клиентов. Архитектура системы безопасности COM тесно связана с собственной моделью безопасности операционной системы и основывается на трех различных понятиях. Целостность и аутентичность сообщений ORPC, которыми обмениваются клиент и объект, обеспечивается аутентификацией. Контроль доступа выявляет, какие принципалы защиты могут иметь доступ к объектам, экспортированным из данного процесса. Управление маркерами отслеживает, какие полномочия используются для запуска серверных процессов и выполнения методов объекта.
Разное
IChapter *pc = 0;
HRESULT hr = CoGetObject(OLESTR(«Chapter:7»), О,
IID_IChapter, (void**)&pc);
if (SUCCEEDED(hr)) {
hr = pc->IncludeAllTopicsNotCoveredYet();
pc->Release(); }
В предыдущей главе были представлены основы модели программирования СОМ и архитектуры удаленного доступа. Различные интерфейсы и методики СОМ рассматриваются на протяжении всей книги. Однако осталось несколько вопросов, не связанных ни с какой определенной главой, о которых следует рассказать подробно. Вместо того чтобы просто втиснуть эти вопросы в другие главы, которые были скомпонованы рационально или даже превышали разумные размеры, я отвел данную главу под хранилище для «маленьких» тем, которые не всегда подходят к другим частям книги. За исключением вводных разделов об указателях, управлении памятью и массивах, ни одна из этих тем не является жизненно необходимой для создания эффективных распределенных систем с СОМ. Помните об этом и расслабьтесь, в то время как ваши глаза будут скользить вдоль строк этой главы.
Основы указателей
СОМ, подобно DCE (Distributed Computing Environment – среда распределенных вычислений), ведет свое начало от языка программирования С. Хотя лишь немногие разработчики используют С для создания или использования компонентов СОМ, именно от С СОМ унаследовала синтаксис для своего языка определений интерфейсов (Interface Definition Language – IDL). Одной из наиболее сложных проблем при разработке и использовании интерфейсов является управление указателями. Рассмотрим такое простое определение метода IDL:
HRESULT f([in] const short *ps);
Если бы вызывающая программа должна была запустить этот метод так:
short s = 10;
HRESULT hr = p->f(&s);
то величину 10 следовало бы послать объекту. Если бы этому методу нужно было выйти за границы апартамента, то интерфейсный заместитель был бы обязан разыменовать указатель и передать величину 10 в сообщение ORPC-запроса.
Следующий клиентский код, хотя и написан целиком в традициях С, представляет собой более интересный случай:
HRESULT hr = p->f(0);
// pass a null pointer
// передаем нулевой указатель
Если вызывающий поток выполняется в апартаменте объекта, то заместителя нет и нулевой указатель будет передан прямо объекту. Но что если объект расположен в другом апартаменте и заместитель используется? Что в точности должен передать интерфейсный заместитель, чтобы показать, что был послан нулевой указатель? Кроме того, означает ли это, что интерфейсные заместители и заглушки должны проверять каждый указатель, не является ли он нулевым? Оказывается, бывают ситуации, в которых указатель никогда не должен быть нулевым, и другие ситуации, когда нулевые указатели, наоборот, чрезвычайно полезны как начальные значения. В последнем случае факт передачи нулевого указателя интерфейсному заместителю должен быть продублирован интерфейсной заглушкой в апартаменте объекта.