|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1995.
//
// File:
// dscmif.cxx
//
// Contents:
// Entry points for remote activation SCM interface.
//
// Functions:
// SCMActivatorGetClassObject
// SCMActivatorCreateInstance
//
// History: SatishT 2/10/98 Rewrote for use with ISCMActivator
// History: Vinaykr 3/1/98 Modified To Add Activation Properties,
// SCM Stage handling and Remote handling
//
//--------------------------------------------------------------------------
#include "act.hxx"
// forward defn
HRESULT GetClassInfoFromClsid(REFCLSID rclsid, IComClassInfo **ppClassInfo);
/*********************************************************************/ /** Entry point for local GetClassObject activation requests **/ /*********************************************************************/ HRESULT SCMActivatorGetClassObject( IN handle_t hRpc, IN ORPCTHIS * ORPCthis, IN LOCALTHIS * LOCALthis, OUT ORPCTHAT * ORPCthat, IN MInterfacePointer * pInActProperties, OUT MInterfacePointer ** ppOutActProperties ) { ACTIVATION_PARAMS ActParams;
if (ORPCthis == NULL || LOCALthis == NULL || ORPCthat == NULL) return E_INVALIDARG;
memset(&ActParams, 0, sizeof(ActParams)); ActParams.MsgType = GETCLASSOBJECT; ActParams.hRpc = hRpc; ActParams.ORPCthis = ORPCthis; ActParams.Localthis = LOCALthis; ActParams.ORPCthat = ORPCthat; ActParams.oldActivationCall = FALSE;
return PerformScmStage(CLIENT_MACHINE_STAGE, &ActParams, pInActProperties, ppOutActProperties); }
/*********************************************************************/ /** Entry point for local CreateInstance activation requests **/ /*********************************************************************/ HRESULT SCMActivatorCreateInstance( IN handle_t hRpc, IN ORPCTHIS * ORPCthis, IN LOCALTHIS * LOCALthis, OUT ORPCTHAT * ORPCthat, IN MInterfacePointer * pUnkOuter, IN MInterfacePointer * pInActProperties, OUT MInterfacePointer ** ppOutActProperties ) { ACTIVATION_PARAMS ActParams;
if (ORPCthis == NULL || LOCALthis == NULL || ORPCthat == NULL) return E_INVALIDARG;
memset(&ActParams, 0, sizeof(ActParams)); ActParams.MsgType = CREATEINSTANCE; ActParams.hRpc = hRpc; ActParams.ORPCthis = ORPCthis; ActParams.Localthis = LOCALthis; ActParams.ORPCthat = ORPCthat; ActParams.oldActivationCall = FALSE;
return PerformScmStage(CLIENT_MACHINE_STAGE, &ActParams, pInActProperties, ppOutActProperties); }
/*********************************************************************/ /** Dummy IUnknown functions **/ /*********************************************************************/ HRESULT DummyQueryInterfaceISCMActivator( IN handle_t rpc, IN ORPCTHIS * ORPCthis, IN LOCALTHIS * localthis, OUT ORPCTHAT * ORPCthat, IN DWORD dummy ) { CairoleDebugOut((DEB_ERROR, "SystemActivator Dummy function should never be called!\n")); ORPCthat->flags = 0; ORPCthat->extensions = NULL; return E_FAIL; }
/*********************************************************************/ /** Dummy IUnknown functions **/ /*********************************************************************/ HRESULT DummyAddRefISCMActivator( IN handle_t rpc, IN ORPCTHIS * ORPCthis, IN LOCALTHIS * LOCALthis, OUT ORPCTHAT * ORPCthat, IN DWORD dummy ) { CairoleDebugOut((DEB_ERROR, "SystemActivator Dummy function should never be called!\n")); ORPCthat->flags = 0; ORPCthat->extensions = NULL; return E_FAIL; }
/*********************************************************************/ /** Dummy IUnknown functions **/ /*********************************************************************/ HRESULT DummyReleaseISCMActivator( IN handle_t rpc, IN ORPCTHIS * ORPCthis, IN LOCALTHIS * localthis, OUT ORPCTHAT * ORPCthat, IN DWORD dummy ) { CairoleDebugOut((DEB_ERROR, "SystemActivator Dummy function should never be called!\n")); ORPCthat->flags = 0; ORPCthat->extensions = NULL; return E_FAIL; }
/*
ActivateFromPropertiesPreamble
Does various stuff, loads custom activators, delegates.
*/ HRESULT ActivateFromPropertiesPreamble( ActivationPropertiesIn *pActPropsIn, IActivationPropertiesOut **ppActOut, PACTIVATION_PARAMS pActParams ) { HRESULT rethr; ILegacyInfo * pLegacyInfo = NULL; InstantiationInfo * pInstantiationInfo = NULL; IServerLocationInfo* pISLInfo = NULL; ISpecialSystemProperties* pISSP = NULL; BOOL IsGetPersist = FALSE; DWORD destCtx; IInstanceInfo *pInstanceInfo = NULL; BOOL bTookRefOnCProcess = FALSE; int nRetries = 0; IComClassInfo* pComClassInfo = NULL; *ppActOut = NULL;
// Fill up ActParams for Generic Activation Path
pActParams->pAuthInfo = NULL;
rethr = pActPropsIn->QueryInterface(IID_IScmRequestInfo, (LPVOID*)&pActParams->pInScmResolverInfo); if (FAILED(rethr)) goto exit_Activation;
rethr = pActPropsIn->QueryInterface(IID_ILegacyInfo, (LPVOID*)&pLegacyInfo);
if (FAILED(rethr)) goto exit_Activation;
pInstantiationInfo = pActPropsIn->GetInstantiationInfo(); ASSERT(pInstantiationInfo != NULL);
pActParams->pInstantiationInfo = pInstantiationInfo;
if (pActParams->RemoteActivation) { pActParams->ProcessSignature = 0; pActParams->pEnvBlock = NULL; pActParams->pwszWinstaDesktop = NULL; pActParams->Apartment = FALSE; pActParams->pAuthInfo = 0; pActParams->pwszServer = NULL; } else { PRIV_SCM_INFO *pPrivScmInfo;
rethr = pActParams->pInScmResolverInfo->GetScmInfo(&pPrivScmInfo); ASSERT(SUCCEEDED(rethr)); if (FAILED(rethr)) goto exit_Activation; CheckLocalCall( pActParams->hRpc ); pActParams->RemoteActivation = FALSE; pActParams->ProcessSignature = (PVOID)pPrivScmInfo->ProcessSignature; pActParams->pEnvBlock = pPrivScmInfo->pEnvBlock; pActParams->EnvBlockLength = pPrivScmInfo->EnvBlockLength; pActParams->pwszWinstaDesktop = pPrivScmInfo->pwszWinstaDesktop; pActParams->Apartment = pPrivScmInfo->Apartment; COSERVERINFO *pServerInfo; rethr = pLegacyInfo->GetCOSERVERINFO(&pServerInfo); ASSERT(SUCCEEDED(rethr)); if (FAILED(rethr)) goto exit_Activation; if (pServerInfo) {
rethr = CopyAuthInfo(pServerInfo->pAuthInfo, &pActParams->pAuthInfo); SecurityInfo::freeCOAUTHINFO(pServerInfo->pAuthInfo); pServerInfo->pAuthInfo = NULL;
if (FAILED(rethr)) goto exit_Activation; } }
pActParams->pProcess = 0; pActParams->pToken = 0; // Make sure process request info is set to defaults before calling any custom activators
if (pActPropsIn->QueryInterface(IID_IServerLocationInfo, (void**)&pISLInfo) == S_OK) { HRESULT hr; hr = pISLInfo->SetProcess(0, PRT_IGNORE); Win4Assert(hr == S_OK); pISLInfo->Release(); }
// Remember if client was impersonating or not
if (pActPropsIn->QueryInterface(IID_ISpecialSystemProperties, (void**)&pISSP) == S_OK) { HRESULT hr; hr = pISSP->GetClientImpersonating(&pActParams->bClientImpersonating); Win4Assert(hr == S_OK); pISSP->Release(); }
// QI will only work if persistent activation is happening
if (pActPropsIn->QueryInterface(IID_IInstanceInfo, (LPVOID*)&pInstanceInfo) == S_OK)
{ pActParams->pInstanceInfo = pInstanceInfo;
// The only case where msgtype will already be GETPERSISTENTINSTANCE
// is during an incoming nt4 client remote activation(see remactif)
if (pActParams->MsgType == CREATEINSTANCE) { pActParams->MsgType = GETPERSISTENTINSTANCE; WCHAR *pwszObjectName; pInstanceInfo->GetFile(&pwszObjectName, &pActParams->Mode); if (pActParams->RemoteActivation) { WCHAR *pwszObjectName2; rethr = GetServerPath( pwszObjectName, &pwszObjectName2 ); if (pwszObjectName != pwszObjectName2) { pInstanceInfo->SetFile(pwszObjectName2, pActParams->Mode); pInstanceInfo->GetFile(&pActParams->pwszPath, &pActParams->Mode); MIDL_user_free(pwszObjectName2); } } else { pActParams->pwszPath = pwszObjectName; }
if ( FAILED(rethr) ) goto exit_Activation;
pInstanceInfo->GetStorageIFD(&pActParams->pIFDStorage); IsGetPersist = TRUE; }
Win4Assert(pActParams->MsgType == GETPERSISTENTINSTANCE); } else { Win4Assert(pActParams->MsgType != GETPERSISTENTINSTANCE); if (pActParams->MsgType == GETCLASSOBJECT) pActParams->Mode = MODE_GET_CLASS_OBJECT;
#ifdef DFSACTIVATION
pActParams->FileWasOpened = FALSE; #endif
}
rethr = pInstantiationInfo->GetClsid(&pActParams->Clsid);
if (pActParams->RemoteActivation) pActParams->ClsContext = CLSCTX_LOCAL_SERVER; else rethr = pInstantiationInfo->GetClsctx(&pActParams->ClsContext);
ASSERT(!FAILED(rethr));
rethr = pInstantiationInfo->GetRequestedIIDs( &pActParams->Interfaces, &pActParams->pIIDs);
/* only one requested interface allowed for GetClassObject */ if ((pActParams->MsgType == GETCLASSOBJECT) && (pActParams->Interfaces != 1)) { rethr = E_INVALIDARG; goto exit_Activation; }
pActParams->UnsecureActivation = FALSE; pActParams->ORPCthis->flags = ORPCF_LOCAL; pActParams->Localthis->dwFlags = LOCALF_NONE; pActParams->ORPCthat->flags = 0; pActParams->ORPCthat->extensions = NULL;
//
// Get a CProcess for local callers.
//
if ( ! pActParams->RemoteActivation ) { //
// A local activation passes the "magic" signature from CRpcResolver.
// Because ORPC calls cannot have context handles, the signature
// is just a pointer to the process object.
//
pActParams->pProcess = ReferenceProcess( pActParams->ProcessSignature, TRUE );
if ( ! pActParams->pProcess ) { rethr = E_ACCESSDENIED; goto exit_Activation; } bTookRefOnCProcess = TRUE; }
//
// Get a CToken for all callers.
//
RPC_STATUS Status; Status = LookupOrCreateToken( pActParams->hRpc, FALSE, &pActParams->pToken );
//
// ERROR_ACCESS_DENIED is returned if RpcImpersonateClient fails.
// We will take this to mean that the remote activation is coming
// in unsecure. In this case we have no Token object and must do
// permission checks manually. We set the winsta/desktop to an
// empty string to distinguish this case during some ROT lookups.
//
// Unsecure remote clients can only connect to services or RunAs
// servers.
//
if ( Status == ERROR_ACCESS_DENIED ) { pActParams->pToken = 0; pActParams->pwszWinstaDesktop = L""; pActParams->UnsecureActivation = TRUE; Status = RPC_S_OK; }
if ( Status != RPC_S_OK ) { rethr = HRESULT_FROM_WIN32(Status); goto exit_Activation; }
// Look up the (per-user) classinfo here before
// the partition activators run.
if (pActParams->pToken) { pActPropsIn->SetClientToken(pActParams->pToken->GetToken()); if (!(pActParams->ClsContext & CLSCTX_INPROC_SERVER)) { rethr = gpCatalogSCM->GetClassInfo ( pActParams->ClsContext, pActParams->pToken, pActParams->Clsid, IID_IComClassInfo, (void**) &pComClassInfo ); } } else rethr = gpCatalog->GetClassInfo ( pActParams->Clsid, IID_IComClassInfo, (void**) &pComClassInfo ); // catalog will return S_FALSE if the class is not
// registered.
if ( pComClassInfo == NULL || rethr != S_OK ) rethr = REGDB_E_CLASSNOTREG;
// Careful here: the lookup above may have failed registration info
// for a local server activation, but we need to keep going since the
// activation may still end up being sent to a remote machine.
if (FAILED(rethr) && rethr != REGDB_E_CLASSNOTREG) goto exit_Activation;
if (pComClassInfo) { pActPropsIn->SetClassInfo(pComClassInfo); pComClassInfo->Release();pComClassInfo=NULL; } // Set Activation Params "Local Blob"
pActPropsIn->SetLocalBlob((void*)pActParams); pActParams->pActPropsIn = pActPropsIn;
RETRY_ACTIVATION: //
// Set the stage. For now, all scm-level activators must be
// SERVER_MACHINE_STAGE activators, since more work needs to be
// done to properly define the semantic/other differences
// between "client" and "server" scm activators.
//
rethr = pActPropsIn->SetStageAndIndex(SERVER_MACHINE_STAGE, 0); if (FAILED (rethr)) goto exit_Activation;
// Delegate onwards....
if (pActParams->MsgType == GETCLASSOBJECT) rethr = pActPropsIn->DelegateGetClassObject(ppActOut); else rethr = pActPropsIn->DelegateCreateInstance(NULL, ppActOut); // Sajia - support for partitions
// If the delegated activation returns ERROR_RETRY,
// we walk the chain again, but AT MOST ONCE.
if (ERROR_RETRY == rethr) { Win4Assert(!nRetries); if (!nRetries) { nRetries++; goto RETRY_ACTIVATION; } } exit_Activation:
if (IsGetPersist) { if ( pActParams->pIFDROT ) MIDL_user_free( pActParams->pIFDROT ); }
if (pActParams->pInScmResolverInfo) pActParams->pInScmResolverInfo->Release(); if (pLegacyInfo) pLegacyInfo->Release(); if (pActParams->pInstanceInfo) pActParams->pInstanceInfo->Release(); if (pActParams->pAuthInfo) FreeAuthInfo(pActParams->pAuthInfo); if (pActParams->pToken) pActParams->pToken->Release(); if (bTookRefOnCProcess) { ASSERT(pActParams->pProcess); ReleaseProcess(pActParams->pProcess); } if (pComClassInfo) { pComClassInfo->Release(); } return rethr; }
#if DBG == 1
LONG ActivationExceptionFilter( DWORD lCode, LPEXCEPTION_POINTERS lpep ) { Win4Assert(NULL && "Unexpected exception thrown"); return TRUE; } #endif
/*********************************************************************/ /** Real Work of SCM Activation begins here After Custom Activators **/ /** have been called. This will be called during all activations **/ /** occuring in the SCM, local and remote **/ /*********************************************************************/ HRESULT ActivateFromProperties( IActivationPropertiesIn *pActIn, IActivationPropertiesOut **ppActOut ) { HRESULT rethr; REMOTE_REQUEST_SCM_INFO * pScmRequestInfo=NULL; IScmReplyInfo * pOutScmResolverInfo = NULL; DWORD destCtx; REMOTE_REPLY_SCM_INFO *pScmReplyInfo=NULL; PRIV_RESOLVER_INFO *pPrivActOutInfo=NULL; ActivationPropertiesIn *pActPropsIn=NULL; WCHAR * pwszDummy;
*ppActOut = NULL;
// Get Activation Params "Local Blob"
rethr = pActIn->QueryInterface(CLSID_ActivationPropertiesIn, (void**)&pActPropsIn); PACTIVATION_PARAMS pActParams; pActPropsIn->GetLocalBlob((void**)&pActParams); Win4Assert(pActParams != NULL);
// This could have already been set in the lb rerouting case
pActParams->activatedRemote = FALSE;
if (pActParams->RemoteActivation) { Win4Assert(pActParams->pInScmResolverInfo); rethr = pActParams->pInScmResolverInfo->GetRemoteRequestInfo(&pScmRequestInfo); if (pScmRequestInfo == NULL) { if (SUCCEEDED(rethr)) rethr = E_FAIL; goto exit_Activation; }
pScmReplyInfo = (REMOTE_REPLY_SCM_INFO*) MIDL_user_allocate(sizeof(REMOTE_REPLY_SCM_INFO));
if (pScmReplyInfo == NULL) { rethr = E_OUTOFMEMORY; goto exit_Activation; }
memset(pScmReplyInfo, 0, sizeof(REMOTE_REPLY_SCM_INFO));
pActParams->pOxidServer = &pScmReplyInfo->Oxid;
//
// The following OR fields are not used while servicing a
// remote activation.
//
pActParams->ppServerORBindings = (DUALSTRINGARRAY **)NULL; pActParams->pOxidInfo = NULL; pActParams->pLocalMidOfRemote = NULL; pActParams->pDllServerModel = NULL; pActParams->ppwszDllServer = &pwszDummy; } else { pPrivActOutInfo = (PRIV_RESOLVER_INFO*) MIDL_user_allocate(sizeof(PRIV_RESOLVER_INFO));
if (pPrivActOutInfo == NULL) { rethr = E_OUTOFMEMORY; goto exit_Activation; }
memset(pPrivActOutInfo, 0, sizeof(PRIV_RESOLVER_INFO));
pActParams->pFoundInROT = &pPrivActOutInfo->FoundInROT; pActParams->pOxidServer = &pPrivActOutInfo->OxidServer; pActParams->ppServerORBindings = &pPrivActOutInfo->pServerORBindings; *pActParams->ppServerORBindings = 0; pActParams->pOxidInfo = &pPrivActOutInfo->OxidInfo; pActParams->pOxidInfo->psa = 0; pActParams->pLocalMidOfRemote = &pPrivActOutInfo->LocalMidOfRemote; pActParams->pDllServerModel = &pPrivActOutInfo->DllServerModel; pActParams->ppwszDllServer = &pPrivActOutInfo->pwszDllServer; }
{ IServerLocationInfo *pServerLocationInfo = NULL; pServerLocationInfo = pActPropsIn->GetServerLocationInfo(); Win4Assert(pServerLocationInfo != NULL); pServerLocationInfo->GetRemoteServerName(&pActParams->pwszServer); }
pActPropsIn->GetClassInfo(IID_IComClassInfo, (void**)&pActParams->pComClassInfo); pActParams->ProtseqId = 0; *pActParams->pOxidServer = 0; *pActParams->ppwszDllServer = 0;
RpcTryExcept { // Generic SCM Activation Path
rethr = Activation( pActParams ); }
#if DBG == 1
RpcExcept(ActivationExceptionFilter(GetExceptionCode(), GetExceptionInformation()) ) #else
RpcExcept(TRUE) #endif
{ rethr = HRESULT_FROM_WIN32(RpcExceptionCode()); }
RpcEndExcept
if (rethr != S_OK) goto exit_ActWithoutResolvingInfo;
if (pActParams->activatedRemote) { // if did remote activation for an incoming one
// just exit
if (pActParams->RemoteActivation) { *ppActOut = pActParams->pActPropsOut; goto exit_ActWithoutResolvingInfo; }
if(!pActParams->IsLocalOxid) { //Set Tid/Pid to 0 for remote server
Win4Assert(pActParams->pOxidInfo); pActParams->pOxidInfo->dwTid = 0; pActParams->pOxidInfo->dwPid = 0; } }
ActivationPropertiesOut *pActPropsOut;
pActPropsOut = pActParams->pActPropsOut;
if (pActPropsOut == NULL) { rethr = pActPropsIn->GetReturnActivationProperties(&pActPropsOut);
if (FAILED(rethr)) goto exit_ActWithoutResolvingInfo;
rethr = pActPropsOut->SetMarshalledResults(pActParams->Interfaces, pActParams->pIIDs, pActParams->pResults, pActParams->ppIFD); MIDL_user_free(pActParams->pIIDs); MIDL_user_free(pActParams->pResults); MIDL_user_free(pActParams->ppIFD);
if (FAILED(rethr)) goto exit_ActWithoutResolvingInfo;
pActParams->pActPropsOut = pActPropsOut; }
rethr = pActPropsOut->QueryInterface( IID_IScmReplyInfo, (LPVOID*)&pOutScmResolverInfo );
if (FAILED(rethr)) goto exit_ActWithoutResolvingInfo;
if (pActParams->RemoteActivation) { RPC_STATUS sc; if (*pActParams->pOxidServer != 0) { sc = _ResolveOxid2(pActParams->hRpc, pActParams->pOxidServer, pScmRequestInfo->cRequestedProtseqs, pScmRequestInfo->pRequestedProtseqs, &pScmReplyInfo->pdsaOxidBindings, &pScmReplyInfo->ipidRemUnknown, &pScmReplyInfo->authnHint, &pScmReplyInfo->serverVersion ); rethr = HRESULT_FROM_WIN32(sc); } pOutScmResolverInfo->SetRemoteReplyInfo(pScmReplyInfo); } else pOutScmResolverInfo->SetResolverInfo(pPrivActOutInfo);
pOutScmResolverInfo->Release();
*ppActOut = pActPropsOut;
exit_Activation: if (pActParams->pComClassInfo) { pActParams->pComClassInfo->Release(); } return rethr;
// Go here if ActivationPropertiesOut is not created
exit_ActWithoutResolvingInfo: MIDL_user_free(pScmReplyInfo); MIDL_user_free(pPrivActOutInfo); goto exit_Activation; }
//
// GetClassInfoFromClsid
//
// On success, returns a IComClassInfo for the requested class
//
// FUTURE: this function is basically a duplicate of one linked into
// ole32. We should find a way to centralize all of this catalog
// stuff and do away with this funky "this function is just here to
// satisfy the linker" crud.
//
HRESULT GetClassInfoFromClsid(REFCLSID rclsid, IComClassInfo **ppClassInfo) { HRESULT hr = InitializeCatalogIfNecessary(); if ( FAILED(hr) ) { return hr; } else { // get the information object for the requested class
// this may translate the CLSID via TreatAs and other mappings
hr = gpCatalog->GetClassInfo(rclsid, IID_IComClassInfo, (void**)ppClassInfo); } return hr; }
//This should never be called. It is mainly to link with actprops which
//uses it to load persistent objects and should only do so in a server.
HRESULT LoadPersistentObject(IUnknown *punk, IInstanceInfo *pInstanceInfo) { return E_NOTIMPL; }
//This should never be called. It is mainly to link with actprops which
//uses it for marshalling of returns
void *GetDestCtxPtr(COMVERSION *pComVersion) { return NULL; }
//
// These should never be called. It is mainly to link with actprops which
// uses it creating contexts
//
HRESULT CObjectContextCF_CreateInstance(IUnknown *pUnkOuter, REFIID riid, void** ppv) { return E_NOTIMPL; }
HRESULT CObjectContext::QueryInterface(REFIID riid, void **ppv) { return E_NOTIMPL; }
ULONG CObjectContext::AddRef() { return E_NOTIMPL; }
ULONG CObjectContext::Release() { return E_NOTIMPL; }
HRESULT CObjectContext::InternalQueryInterface(REFIID riid, void **ppv) { return E_NOTIMPL; }
ULONG CObjectContext::InternalAddRef() { return E_NOTIMPL; }
ULONG CObjectContext::InternalRelease() { return E_NOTIMPL; }
|