// get security settings for interface proxy pProxy
// получаем установки защиты для интерфейсного заместителя
pProxy HRESULT CoQueryProxyBlanket([in] IUnknown *pProxy, [out] DWORD *pAuthnSvc, [out] DWORD *pAuthzSvc, [out] OLECHAR **pServerPrincName, [out] DWORD *pAuthnLevel, [out] DWORD *pImpLevel, [out] void **pAuthInfo, [out] DWORD *Capabilities);
// change security settings for interface proxy pProxy
// изменяем установки защиты для интерфейсного заместителя
pProxy HRESULT CoSetProxyBlanket([in] IUnknown *pProxy, [in] DWORD AuthnSvc, [in] DWORD AuthzSvc, [in] OLECHAR *pServerPrincName, [in] DWORD AuthnLevel, [in] DWORD ImpLevel, [in] void *pAuthInfo, [in] DWORD Capabilities);
// duplicate an interface proxy
// копируем интерфейсный заместитель
HRESULT CoCopyProxy([in] IUnknown *pProxy, [out] IUnknown **ppCopy);
Следующий код представляет собой модифицированную версию предыдущей функции, где используются эти удобные процедуры:
HRESULT DupeAndEncrypt(IApe *pApe, IАре *ArpSecretApe) {
rpSecretApe = 0; HRESULT hr = СоСоруProxy(pApe, (IUnknown**)&rpSecretApe);
if (SUCCEEDED(hr))
hr = CoSetProxyBlanket(rpSecretApe, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, 0, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IDENTIFY, 0, EOAC_NONE);
return hr;
}
Первая версия несколько эффективнее, так как для нахождения интерфейса IClientSecurity в ней использован только один вызов QueryInterface . Для последней версии требуется меньше кода, поэтому и вероятность ошибок в ней меньше.
Важно отметить, что методы IClientSecurity могут применяться только в тех интерфейсах, которые используют интерфейсные заместители. Это означает, что те интерфейсы, которые реализованы локально администратором заместителей (например, IMultiQI , IClientSecurity ), не могут использоваться с методами IClientSecurity . Интерфейс IUnknown – это особый случай. IUnknown фактически является локальным интерфейсом, реализованным администратором заместителей. Однако администратору заместителей часто требуется связаться с апартаментом сервера для запроса новых интерфейсов и для освобождения ресурсов, хранящихся в соответствующем администраторе заглушек. Эта связь осуществляется через закрытый интерфейс IRemUnknown , который реализуется библиотекой COM отдельно внутри каждого апартамента. Разработчики могут контролировать полную защиту, использованную для этих вызовов IRemUnknown путем передачи реализации IUnknown администратора заместителей в IClientSecurity::SetBlanket (подобно интерфейсному заместителю, администратор заместителей использует общие для процесса автоматические установки защиты в случае, если функция SetBlanket не вызывается) [3] .Поскольку все интерфейсные заместители агрегированы администратором заместителей, то это, в сущности, означает, что вызовы IClientSecurity::SetBlanket на какой-либо определенный интерфейсный заместитель не влияют на функции QueryInterface , AddRef и Release . Скорее, на них влияют установки, примененные к реализации IUnknown администратором заместителей. Для того чтобы получить указатель на реализацию IUnknown администратором заместителей, можно просто запросить с помощью QueryInterface интерфейсный заместитель для IID_IUnknown . Следующий фрагмент кода демонстрирует эту технологию, отключая защиту как для интерфейсного заместителя, так и для его администратора заместителей:
void TurnOffAllSecurity(IApe *pApe) {
IUnknown *pUnkProxyManager = 0;
// get a pointer to the proxy manager
// получаем указатель на администратор заместителей
HRESULT hr = pApe->QueryInterface(IID_IUnknown, (void**)&pUnkProxyManager);
assert(SUCCEEDED(hr));
// set blanket for proxy manager
// устанавливаем защиту для администратора заместителей
hr = CoSetProxyBlanket(pUnkProxyManager, RPC_C_AUTHN_NONE, RPC_C_AUTHZ_NONE, О, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_ANONYMOUS, 0, EOAC_NONE);
assert(SUCCEEDED(hr));
// set blanket for interface proxy
// устанавливаем защиту для интерфейсного заместителя
hr = CoSetProxyBlanket(pApe, RPC_C_AUTHN_NONE, RPC_C_AUTHZ_NONE, 0, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_ANONYMOUS, 0, EOAC_NONE);
assert(SUCCEEDED(hr));
// release temporary pointer to proxy manager
// освобождаем временный указатель на администратор заместителей
pUnkProxyManager->Release();
}
Хотя представляется возможным установить и запросить защиту для администратора заместителей, невозможно скопировать администратор заместителей с помощью IClientSecurity::CopyProxy , так как это нарушило бы правила идентификации COM.
Когда ORPC-запрос направляется интерфейсной заглушке, COM создает объект контекста вызова ( call context object ), представляющий различные аспекты вызова, в том числе установки защиты того интерфейсного заместителя, который отправил этот запрос. COM связывает этот контекстный объект с потоком, который будет выполнять вызов метода. Библиотека COM выставляет API-функцию CoGetCallContext , позволяющую реализациям метода получить контекст для текущего вызова метода:
HRESULT CoGetCallContext ([in] REFIID riid, [out, iid_is(riid)] void **ppv);
В Windows NT 4.0 единственным интерфейсом, доступным для контекстного объекта вызова, является интерфейс IServerSecurity :
Читать дальше