Программа TraceView и безопасность
Программа TraceSrv полезна сама по себе, но утилита просмотра, которая отображает на экране операторы трассировки, на самом деле улучшает ее. Я написал TraceView на языке Visual Basic, потому что это было довольно просто сделать. Если посмотреть на ее исходный код, то можно убедиться, что ничего особенного в нем нет.
Я попытался сделать TraceView немного более полезной, чем простой редактируемый элемент управления, добавив к ней панель инструментов, панель состояния, поддержку сохранения и восстановления позиции окна, сохранение файлов, поиск вперед и назад, и реализовал для окна возможность всегда оставаться наверху. Чтобы облегчить локализацию программы, все строки сохраняются в файле ресурса. Не буду углубляться в загрузку строк ресурса, но отмечу, что пришлось модифицировать сгенерированную функцию LoadResStrings (переименованную В LoadFormResStrings) так, чтобы она уведомляла пользователя о том, какие элементы ресурса не были загружены. Сначала TraceView работала прекрасно. Однако в ходе проверки различных способов присоединения TraceView к TraceSrv были выявлены некоторые проблемы. Если TraceView и TraceSrv располагались на одной машине, то Trace View могла соединяться с TraceSrv только тогда, когда она выполнялась как служба или как локальный сервер. TraceView могла также соединяться должным образом с TraceSrv, если TraceSrv выполнялась на другой машине как локальный сервер, использующий СОМ+-технологию. Однако когда я пробовал соединять TraceView с TraceSrv, выполняющейся на другой машине как СОМ+-служба, это всегда приводило к отказу, сопровождаемому VB-сообщением об ошибке "Run-time error -2147023071 (80070721) Automation Error" (Ошибка времени выполнения -2147023071 (80070721) Ошибка автоматизации). В файле WINERROR.H идентификатор (ID) этой ошибки выглядит так: RPC_S_SEC_PKG_ERROR, "A ' security package specific error occurred" (Произошла специфическая ошибка пакета защиты).
Этот идентификатор был мне незнаком, а попытавшись найти его в MSDN, я узнал только, что он определен в WINERROR.H и внесен в список приложений с системными ошибками.
Провозившись с этой проблемой несколько дней, я обнаружил, что мог бы добиться соединения VB-программы с удаленной службой TraceSrv лишь в том случае, если бы в объявлении Trace-объекта не использовал ключевое слово withEvents. Указывая ключевое слово withEvents, я всегда получал ошибку RPC_S_SEC_PKG_ERROR и пребывал в недоумении, пока один из друзей не указал мне, что неправильно установлена защита (security) службы TraceSrv.
Вернувшись "к своим баранам" и еще раз посмотрев, что же происходит, я начал кое-что понимать. Ключевое слово withEvents устанавливает интерфейс iconnectionPoint, который сервер использует для вызова клиента — это, по существу, обратный вызов. Чтобы выполнить обратный вызов клиента, сервер должен иметь корректные полномочия доступа. Когда TraceSrv выполняется на той же машине, что и TraceView, то, не зависимо от того, запущена ли она как локальный сервер или как служба, TraceSrv выполняется под тем же пользовательским идентификатором, что и TraceView. Выполнение TraceSrv на одной машине в качестве удаленного СОМ+-сервера, a TraceView — на другой, было успешным потому, что мне повезло. На обеих машинах, работавших под Windows NT Workstation без контроллера домена, я был зарегистрирован в как "John" с одним тем же паролем. Согласно статье Q158508 Knowledge Base ("Часто задаваемые вопросы по СОМ-безопасности") операционная система Windows NT Workstation "возвращается к режиму согласования имен и паролей учетных записей". Если на двух машинах, работающих под Windows NT Workstation, используются одни и те же ASCII-имена, и учетные записи имеют одни те же пароли, то средства защиты DCOM и других ресурсов NT (например, файловой системы) должны работать так, как если бы вы были действительно зарегистрированы ш этих двух машинах с одной и той же учетной записью".
Когда я, зарегистрировавшись на удаленной машине как "Bob", запускал на ней TraceSrv как удаленный сервер, и пытался соединять с ним TraceView на машине клиента, зарегистрировавшись на ней, как "John", я получал ошибку
RPC_S_SEC_PKG_ERROR.
В моем случае выполнение TraceSrv как удаленного сервера на отдельной машине не принимало во внимание каких-либо измеIнений в соединениях.
Запуск удаленного сервера с надлежащей защитой — довольно простая задача: нужно только при входе в систему зарегистрироваться в качестве пользтователя, имеющего сетевые права. Однако для служб Win32 решение этой задачи требует немного больших усилий. По умолчанию такие службы не имеют никаких полномочий безопасности, поэтому TraceSrv и вызывала соответствующую ошибку всякий раз, когда она пыталась что-то делать с интерфейсом iconnectionPoint, который она получала через параметр вызова. Необходимо было сделать так, чтобы клиент сообщил СОМ+-службам уровень безопасности, который они должны разрешать своим собственным интерфейсам. Уровень безопасности для клиентских интерфейсов определяется с помощью функции CoInitializeSecurity, которая должна вызываться немедленно после того, как ваше приложение вызывает Coinitiaiize. В программе TraceView, которая написана на языке Visual Basic, функция CoInitializeSecurity не будет работать. Если вывзов CoInitializeSecurity будет первым в функции sub Main, то вы получите код ошибки 0x80010119 (RPC_E_ TOO_LATE), что означает: "Security must be initialized before any interfaces are marshaled or unmarshaled. It cannot be changed once initialized." (Защита должна быть инициализирована перед маршализацией1или демаршализацией любого интерфейса. После инициализации она не может быть изменена.) Нетрудно видеть, что Visual Basic выполняет маршалинг намного раньше того, как пользовательский код получает вызов.
Маршалинг — передача данных через границы процесса. Здесь речь идет о передаче параметров и возврате результатов при передаче вызова в другое адресное пространство. — Пер.
Обойти это ограничение Visual Basic можно двумя способами. Первый — 1 запустить DCOMCNFG и установить для свойства Default Authentication Level на I вкладке Default Properties значение None. Такое решение подходит для небольшой замкнутой домашней сети, но для крупных реальных сетей разработки это не самое лучшее решение.
Второй подход более приемлем и безопасен: на машине, которая будет выполнять программу TraceSrv, зарегистрируйте ее как службу, запустите Панель управления, и щелкните на значке Services. Выберите элемент TraceSrv (в списке служб) и нажмите кнопку Start Service, а также кнопку Properties, чтобы отобразить диалоговое окно Properties программы TraceSrv. На вкладке Log On в переключателе Log On As выберите переключатель This Account и введите с клавиатуры имя пользователя и пароль для учетной записи, под которой предполагается выполнять TraceSrv. Теперь служба будет способна получить необходимую ей защиту от известной в сети учетной записи. Как указывается в статье из "COM Security Frequently Asked
Questions" (Часто задаваемые вопросы по СОМ-безопасности): "Учетная запись Localsystem является локально очень привилегированной... Однако ее владелец не имеет сетевых привилегий и не может покинуть машину через любые защищенные механизмы NT, включая файловую систему, именованные каналы, DCOM или безопасные RPC1-вызовы". Как только я получил службу, запускающуюся под надлежащей учетной записью, TraceView заработала прекрасно. Для работы с сервером домена можно предусмотреть создание специальной учетной записи, которую можно использовать для запуска инструментов, подобных TraceSrv. Например, можно организовать специальную учетную запись Build, которую ваши сборочные (build) машины будут использовать для отправки почты.