c ++ - Krydsession aktivering. Session moniker ignoreres

Indlæg af Hanne Mølgaard Plasc

Problem



Der er to konti på min Windows pc: \ A1 og \ SYSTEM. Mit testprojekt består af tre applikationer:



  1. Server.exe - out-of-proc com-server. implementerer objektet Q

  2. Service.exe - ud af proc com-tjenesten. implementerer objektet T

  3. Client.exe - et klientprogram



Min arbejdsgang er vist nedenfor:



  1. Jeg logger ind på \ A1. Jeg starter 'Client.exe'.

  2. Klienten opretter en forekomst af objektet 'T'

  3. Klienten kalder en metode, siger 'T.ActivateQ', som instanserer 'Q'.



Jeg har til hensigt at gøre Service.exe til at oprette en forekomst af 'Q' i kontoen \ A1, selvom Service.exe ligger under \ SYSTEM-kontoen.


Som angivet i denne artikel har Windows indbygget funktionalitet til at gøre denne type aktivering kaldet 'Session-to-Session activation'. Det gennemføres ved hjælp af Session Moniker ('Session:! Clsid:'). [6]


På den baggrund har jeg konfigureret 'Server.exe' til at køre som 'Interaktiv bruger' via dcomcnfg.
Så har jeg implementeret funktionen '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));
}


og jeg bruger det i tjenesten:


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;
    }
}


Men der sker ikke noget. Jeg mener, at tjenesten altid starter serveren i sessionen 0, som svarer til \ SYSTEM-kontoen.


Klientens sikkerhedsindstillinger:


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-fil:


HKLM
{
    NoRemove Software
    {
        NoRemove Classes
        {
            NoRemove AppID
            {
                ForceRemove '\%APPID\%' = s 'Test Server'
                {
                    val RunAs = s 'Interactive User'
                }
            }
        }
    }
}


Gør jeg noget galt?


UPDATE
Jeg har endelig fundet en løsning. Registreringsskriptet for klassen 'Q' manglede AppID-feltet:


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

        }
    }
}

Bedste reference