跨会话激活。会话名字对象无视

时间:2012-03-09 08:30:49

标签: c++ windows com

我的Windows PC上有两个帐户:\ A1和\ SYSTEM。我的测试项目包含三个应用程序:

  1. Server.exe - 进程外com服务器。实现对象 Q
  2. Service.exe - 进程过期服务。实现对象 T
  3. Client.exe - 客户端应用程序
  4. 我的工作流程如下所示:

    1. 我登录了\ A1。我启动了' Client.exe'。
    2. 客户端创建对象的实例' T'
    3. 客户端调用了一些方法,例如T.ActivateQ',它实例化了Q'。
    4. 我的目的是让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
      
              }
          }
      }
      

0 个答案:

没有答案