|
|
//+-------------------------------------------------------------------------
//
// 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"
/*********************************************************************/ /** 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; IActivationSecurityInfo* pIActSecInfo = NULL; BOOL IsGetPersist = FALSE; DWORD destCtx; IInstanceInfo* pInstanceInfo = NULL; int nRetries = 0; IComClassInfo* pComClassInfo = NULL; *ppActOut = NULL;
// Fill up ActParams for Generic Activation Path
pActParams->pAuthInfo = NULL; pActParams->pProcess = 0; pActParams->pToken = 0;
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;
rethr = pActPropsIn->QueryInterface(IID_IActivationSecurityInfo, (LPVOID*)&pIActSecInfo); if (FAILED(rethr)) goto exit_Activation;
pInstantiationInfo = pActPropsIn->GetInstantiationInfo(); if (pInstantiationInfo == NULL) { rethr = E_OUTOFMEMORY; goto exit_Activation; } pActParams->pInstantiationInfo = pInstantiationInfo;
if (pActParams->RemoteActivation) { pActParams->pProcess = NULL; // no CProcess for remote clients
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); if (FAILED(rethr)) goto exit_Activation;
// Check local security
pActParams->pProcess = CheckLocalSecurity(pActParams->hRpc, (PHPROCESS)pPrivScmInfo->ProcessSignature, TRUE); // *not* passed as a context handle
if (!pActParams->pProcess) { rethr = E_ACCESSDENIED; goto exit_Activation; } pActParams->pEnvBlock = pPrivScmInfo->pEnvBlock; pActParams->EnvBlockLength = pPrivScmInfo->EnvBlockLength; pActParams->pwszWinstaDesktop = pPrivScmInfo->pwszWinstaDesktop; pActParams->Apartment = pPrivScmInfo->Apartment; COSERVERINFO *pServerInfo; // Retrieve the COSERVERINFO (originally from the client) and
// save a copy. Then we free the COAUTHINFO part of the actprops
// so that we don't accidently send it anywhere else.
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; } }
// Make sure caller has not set a COAUTHIDENTITY
COAUTHIDENTITY* pAuthIdentBogus; rethr = pIActSecInfo->GetAuthIdentity(&pAuthIdentBogus); if (FAILED(rethr)) goto exit_Activation; if (pAuthIdentBogus != NULL) { // since we have never set this field on any MSFT platform (and
// never will), this means we have a caller who is playing games
rethr = E_ACCESSDENIED; ASSERT(!"pAuthIdentBogus was non-NULL"); goto exit_Activation; }
// 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); ASSERT(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); ASSERT(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; }
ASSERT(pActParams->MsgType == GETPERSISTENTINSTANCE); } else { ASSERT(pActParams->MsgType != GETPERSISTENTINSTANCE); if (pActParams->MsgType == GETCLASSOBJECT) pActParams->Mode = MODE_GET_CLASS_OBJECT;
#ifdef DFSACTIVATION
pActParams->FileWasOpened = FALSE; #endif
}
rethr = pInstantiationInfo->GetClsid(&pActParams->Clsid); ASSERT(SUCCEEDED(rethr)); if (pActParams->RemoteActivation) pActParams->ClsContext = CLSCTX_LOCAL_SERVER; else { rethr = pInstantiationInfo->GetClsctx(&pActParams->ClsContext); ASSERT(SUCCEEDED(rethr)); }
rethr = pInstantiationInfo->GetRequestedIIDs( &pActParams->Interfaces, &pActParams->pIIDs); ASSERT(SUCCEEDED(rethr)); /* only one requested interface allowed for GetClassObject */ if ((pActParams->MsgType == GETCLASSOBJECT) && (pActParams->Interfaces != 1)) { rethr = E_INVALIDARG; goto exit_Activation; }
pActParams->ORPCthis->flags = ORPCF_LOCAL; pActParams->Localthis->dwFlags = LOCALF_NONE; pActParams->ORPCthat->flags = 0; pActParams->ORPCthat->extensions = NULL;
//
// Get a CToken for all callers. Only allow unsecure for
// remote clients.
//
RPC_STATUS status; status = LookupOrCreateTokenForRPCClient(pActParams->hRpc, pActParams->RemoteActivation, &pActParams->pToken, &pActParams->UnsecureActivation); if (status != RPC_S_OK) { rethr = HRESULT_FROM_WIN32(status); goto exit_Activation; }
// UNDONE: figure out if this is still necessary for correct
// rot lookups.
if (pActParams->UnsecureActivation) { pActParams->pwszWinstaDesktop = L""; } ASSERT(pActParams->pToken);
// Look up the (per-user) classinfo here before
// the partition activators run.
if (!pActParams->UnsecureActivation) { 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) { HRESULT temphr = pActPropsIn->SetClassInfo(pComClassInfo); pComClassInfo->Release(); pComClassInfo=NULL; if (FAILED(temphr)) { rethr = temphr; goto exit_Activation; } } // 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 (HRESULT_FROM_WIN32(ERROR_RETRY) == rethr) { ASSERT(!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 (pIActSecInfo) pIActSecInfo->Release(); if (pActParams->pInstanceInfo) pActParams->pInstanceInfo->Release(); if (pActParams->pAuthInfo) SecurityInfo::freeCOAUTHINFO(pActParams->pAuthInfo); if (pActParams->pToken) pActParams->pToken->Release(); if (pActParams->pProcess) ReleaseProcess(pActParams->pProcess); if (pComClassInfo) { pComClassInfo->Release(); } return rethr; }
#if DBG == 1
LONG ActivationExceptionFilter( DWORD lCode, LPEXCEPTION_POINTERS lpep ) { ASSERT(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); ASSERT(pActParams != NULL);
// This could have already been set in the lb rerouting case
pActParams->activatedRemote = FALSE;
if (pActParams->RemoteActivation) { ASSERT(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(); ASSERT(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
ASSERT(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); // COM+ 31260, don't free pActParams->pIIDs since it is owned by ActPropsIn
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; }
|