我的Windows PC上有两个帐户:\ A1和\ SYSTEM。我的测试项目包含三个应用程序:
我的工作流程如下所示:
我的目的是让Service.exe创建一个' Q'的实例。在帐户\ A1中,即使Service.exe位于\ SYSTEM帐户下。
如this文章所述,Windows内置了一种功能,可以进行这种称为“会话到会话激活”的激活。它是通过Session Moniker实现的(" Session:!clsid:")。
鉴于此,我已经配置了“Server.exe'以交互式用户身份运行'通过dcomcnfg。 然后我实现了功能' CoGetClassObjectInSession':
void CoGetClassObjectInSession(DWORD sessionId, Guid const& clsid, void *pvReserved, Guid const& riid, void **ppv)
{
ATL::CComQIPtr<IBindCtx> bindCtxInst;
COMCHK(CreateBindCtx(NULL, &bindCtxInst));
CComQIPtr<IMoniker> classMonikerInst;
COMCHK(::CreateClassMoniker(clsid, &classMonikerInst));
std::wstringstream ss;
ss << L"Session:" << std::dec << sessionId;
ULONG parsed;
ATL::CComQIPtr<IMoniker> sessionMonikerInst;
COMCHK(::MkParseDisplayNameEx(bindCtxInst, ss.str().c_str(), &parsed, &sessionMonikerInst));
ATL::CComQIPtr<IMoniker> classObjectMoniker;
COMCHK(sessionMonikerInst->ComposeWith(classMonikerInst, FALSE, &classObjectMoniker));
ATL::CComPtr<IClassFactory> sessionFactoryInst;
COMCHK(classObjectMoniker->BindToObject(bindCtxInst, NULL, riid, ppv));
}
我在服务中使用它:
HRESULT CMyActivator::Activate()
{
try
{
// Impersonate the client
CComQIPtr<IServerSecurity> ss;
COMCHK(::CoGetCallContext(__uuidof(IServerSecurity), reinterpret_cast<void**>(&ss)));
callctx_impersonation_handle _handle(ss);
ImpersonationScope _imp_scope(_handle);
CComQIPtr<IClassFactory> ppv;
CoGetClassObjectInSession(/*session id for \\A1*/ 1, Guid(__uuidof(Q)), nullptr, Guid(__uuidof(IClassFactory)), reinterpret_cast<void**>(&ppv));
ENSURE(NULL != ppv, "'ppv' should not be null");
return S_OK;
}
catch(std::exception const& ex)
{
return E_FAIL;
}
catch(...)
{
return E_FAIL;
}
}
但没有任何反应。我的意思是服务总是在会话0中启动服务器,该会话对应于\ SYSTEM帐户。
客户的安全设置:
COMCHK(::CoSetProxyBlanket(
activatorQ
, RPC_C_AUTHN_DEFAULT
, RPC_C_AUTHZ_DEFAULT
, NULL
, RPC_C_AUTHN_LEVEL_DEFAULT
, RPC_C_IMP_LEVEL_DELEGATE
, NULL
, EOAC_DYNAMIC_CLOAKING));
Server.rgs文件:
HKLM
{
NoRemove Software
{
NoRemove Classes
{
NoRemove AppID
{
ForceRemove '%APPID%' = s 'Test Server'
{
val RunAs = s 'Interactive User'
}
}
}
}
}
我做错了吗?
更新 我终于找到了解决方案。课程的注册脚本&#39; Q&#39;缺少AppID字段:
HKCR
{
NoRemove CLSID
{
ForceRemove {6FDE856C-F1B2-4466-8435-20F4AEF2C2E1} = s 'SMonClass Class'
{
ForceRemove Programmable
LocalServer32 = s '%MODULE%'
{
val ServerExecutable = s '%MODULE_RAW%'
}
TypeLib = s '{4FA39B0F-5B24-43C6-A5B1-11D8F34277B7}'
Version = s '1.0'
--> val AppID = s '%APPID%'** <-- This line
}
}
}