Windows2003-3790/com/ole32/dcomss/olescm/activate.cxx
2020-09-30 16:53:55 +02:00

1059 lines
35 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// activate.cxx
//
// Main dcom activation service routines.
//
// History: VinayKr Created
// 06-Nov-98 TarunA Changed remote/local activation logic
//
//--------------------------------------------------------------------------
#include "act.hxx"
HRESULT GetProcessInfoFromActProps(IActivationPropertiesIn* pActPropsIn, DWORD* ppid, DWORD* pdwProcessReqType);
LPWSTR GetOrigSrvrName( PACTIVATION_PARAMS pActParams );
// Global counter
LONG gThreadToken = 0;
//-------------------------------------------------------------------------
//
// CalculateActParamsClassInfo
//
// Re-calculate the classinfo in the ACTIVATION_PARAMS structure.
//
//-------------------------------------------------------------------------
HRESULT
CalculateActParamsClassInfo(
IN OUT PACTIVATION_PARAMS pActParams
)
{
IComClassInfo *pComClassInfo = NULL;
HRESULT hr = S_OK;
if (pActParams->pToken)
{
//
// I'm a little worried about this. Why do we do this?
//
if (!(pActParams->ClsContext & CLSCTX_INPROC_SERVER))
{
hr = gpCatalogSCM->GetClassInfo ( pActParams->ClsContext,
pActParams->pToken,
pActParams->Clsid,
IID_IComClassInfo,
(void**) &pComClassInfo );
}
}
else
hr = gpCatalog->GetClassInfo ( pActParams->Clsid,
IID_IComClassInfo,
(void**) &pComClassInfo );
if (SUCCEEDED(hr) && (pComClassInfo))
{
if (pActParams->pComClassInfo)
pActParams->pComClassInfo->Release();
// Copy the reference, do not release.
pActParams->pComClassInfo = pComClassInfo;
if (pActParams->pActPropsIn)
hr = pActParams->pActPropsIn->SetClassInfo(pComClassInfo);
}
if (hr == REGDB_E_CLASSNOTREG)
{
// It's OK for us to have no registration information.
hr = S_OK;
}
return hr;
}
LONG ActivationExceptionFilter(LPEXCEPTION_POINTERS lpep)
{
ASSERT(NULL && "Unexpected exception thrown");
return EXCEPTION_EXECUTE_HANDLER;
}
//-------------------------------------------------------------------------
//
// Activation
//
// Main entry point for both local and remote activations.
//
//-------------------------------------------------------------------------
HRESULT
Activation(
IN OUT PACTIVATION_PARAMS pActParams
)
{
CServerTableEntry* pServerTableEntry = NULL;
CClsidData* pClsidData = NULL;
CServerListEntry* pServerListEntry;
CNamedObject* pLaunchMutex = NULL;
HRESULT hr;
RPC_STATUS Status;
BOOL bStatus;
BOOL bFirstTime = TRUE;
CToken* pTkn;
// NT #294385
// If REMOTE_SERVER is set, and LOCAL_SERVER is not,
// and we have a server name, and the server name is us,
// then we need to turn the LOCAL_SERVER flag on
if ( (CLSCTX_REMOTE_SERVER == (pActParams->ClsContext & ( CLSCTX_REMOTE_SERVER | CLSCTX_LOCAL_SERVER ))) &&
pActParams->pwszServer != NULL &&
gpMachineName->Compare (pActParams->pwszServer) )
{
pActParams->ClsContext |= CLSCTX_LOCAL_SERVER;
#ifdef _WIN64
// On Win64, this might change the classinfo.
hr = CalculateActParamsClassInfo(pActParams);
if (FAILED(hr))
goto ActivationDone;
#endif
}
#ifdef SECURITY_DBG
{
WCHAR dbgwszUser[MAX_PATH];
if ( pActParams->pToken != NULL )
{
pActParams->pToken->Impersonate();
ULONG cchSize = MAX_PATH;
GetUserName( dbgwszUser, &cchSize );
pActParams->pToken->Revert();
}
else
{
lstrcpyW( dbgwszUser, L"Anonymous" );
}
}
#endif
if ( pActParams->pwszServer )
{
//
// Some apps may unnecessarily put slashes before their
// server names. We'll allow this and strip them off.
//
if ( pActParams->pwszServer[0] == L'\\' &&
pActParams->pwszServer[1] == L'\\' )
pActParams->pwszServer += 2;
if ( 0 == *pActParams->pwszServer )
{
hr = CO_E_BAD_SERVER_NAME;
goto ActivationDone;
}
if ( ! gpMachineName->Compare( pActParams->pwszServer ) )
{
//
// When a client specifies a remote server name we go straight to the
// source, there is no need to check local configuration information.
//
// The CLSCTX_REMOTE_SERVER bit does not need to be specified by the
// client, it is implied.
//
//
// the remote activation call will null out the pointer in the ActivationPropertiesIn
// object which caused the memory that pActParams->pwszServer is pointing to to be
// freed. We need this name later on to pass to the oxid resoluton phase, so
// we copy it to some memory on the stack
//
WCHAR *pszTemp = (WCHAR *)_alloca( ( lstrlenW(pActParams->pwszServer) + 1 ) * sizeof(WCHAR) );
lstrcpyW(pszTemp, pActParams->pwszServer);
hr = RemoteActivationCall( pActParams, pActParams->pwszServer );
pActParams->pwszServer = pszTemp;
goto ActivationDone;
}
}
//
// First search for a running object.
//
if ( pActParams->pwszPath )
{
//
// This call returns TRUE if we found a ROT object and are now done.
// When handling a remote activation it's possible we'll find a ROT
// object, but we still need to continue in this case to get a remote
// marshalled interface.
//
if ( LookupObjectInROT( pActParams, &hr ) )
goto ActivationDone;
}
//
// Try to get a CClsidData using the supplied pComClassInfo
//
pTkn = pActParams->RemoteActivation ? NULL : pActParams->pToken;
hr = LookupClsidData( pActParams->Clsid,
pActParams->pComClassInfo,
pTkn,
LOAD_NORMAL,
&pClsidData );
if (hr == REGDB_E_CLASSNOTREG)
{
ASSERT(!pClsidData);
// No registration info for this clsid. If the client is interested
// in a local server activation, we still need to check the class
// table in case of unsolicited registrations. For COM+ components
// we should never get here.
if(pActParams->ClsContext & CLSCTX_LOCAL_SERVER)
{
pServerTableEntry = gpClassTable->Lookup(pActParams->Clsid);
if (pServerTableEntry)
{
// Somebody on the machine registered a classfac for this
// clsid; give it a shot:
bStatus = pServerTableEntry->CallRunningServer( pActParams,
0,
0,
NULL,
&hr);
if (bStatus)
goto ActivationDone;
}
}
//
// As a last resort we always try an atstorage activation.
//
ActivateAtStorage( pActParams, NULL, &hr );
goto ActivationDone;
}
else if (FAILED(hr))
goto ActivationDone;
ASSERT(pClsidData && "Registration lookup succeeded but returned nothing");
//
// If this is a remote activation, make sure that the ClassInfo we got
// can be activated.
//
if (pActParams->RemoteActivation)
{
hr = pClsidData->IsEnabledRemote();
if (FAILED(hr))
{
// Log it to the event log.
if (hr == CO_E_CLASS_DISABLED)
LogComPlusRemoteDisabled(pActParams->ClsContext, pActParams->Clsid);
goto ActivationDone;
}
}
// Look up an appropriate table entry if the client is interested in a
// local activation
if(pActParams->ClsContext & CLSCTX_LOCAL_SERVER)
{
if (pClsidData->DllHostOrComPlusProcess())
{
GUID* pAppidGuid = pClsidData->AppidGuid();
ASSERT(pAppidGuid);
pServerTableEntry = gpProcessTable->Lookup(*pAppidGuid);
}
else
pServerTableEntry = gpClassTable->Lookup( pActParams->Clsid );
}
if ( !pServerTableEntry )
{
// At this point we have the class data but no running servers. If the
// client wants remote activation only then go straight to do a remote activation
// NOTE We '&' with flags CLSCTX_REMOTE_SERVER | CLSCTX_LOCAL_SERVER to
// filter out any other bits like CLSCTX_INPROC etc
if( (pActParams->ClsContext & (CLSCTX_REMOTE_SERVER | CLSCTX_LOCAL_SERVER)) == CLSCTX_REMOTE_SERVER)
{
// This call returns TRUE if a remote ActivateAtStorage call was
// made, whether successful or not.
if ( ActivateAtStorage( pActParams, pClsidData, &hr ) )
goto ActivationDone;
else
goto ActivationDoneLocal;
}
// Figure out which table to create the table entry in
if (pClsidData->DllHostOrComPlusProcess())
{
GUID* pAppidGuid = pClsidData->AppidGuid();
ASSERT(pAppidGuid);
pServerTableEntry = gpProcessTable->Create(*pAppidGuid);
}
else
pServerTableEntry = gpClassTable->Create(pActParams->Clsid);
if (!pServerTableEntry)
{
hr = E_OUTOFMEMORY;
goto ActivationDone;
}
}
ASSERT(pServerTableEntry);
hr = GetProcessInfoFromActProps(pActParams->pActPropsIn, &(pActParams->dwPID), &(pActParams->dwProcessReqType));
if (FAILED(hr))
goto ActivationDone;
for (;;)
{
//
// Now check for a running server for the CLSID
// NOTE: The fact that we reached here implies that the client wants at least a
// local activation
//
CairoleDebugOut((DEB_SCM, "Calling ServerTableEntry at 0x%p\n", pServerTableEntry));
// We reach here only when we are interested in at least a local activation
ASSERT(pActParams->ClsContext & CLSCTX_LOCAL_SERVER);
// We always try to use an existing running server, unless a custom
// activator has told us specifically to create a new server.
if (pActParams->dwProcessReqType != PRT_CREATE_NEW)
{
bStatus = pServerTableEntry->CallRunningServer( pActParams,
0,
0,
pClsidData,
&hr);
if ( bStatus )
goto ActivationDone;
else
{
if (pActParams->dwProcessReqType == PRT_USE_THIS_ONLY)
{
// A custom activator specified a specific server which was not
// found. No need to continue further.
hr = E_UNEXPECTED; // REVIEW for better error code!
goto ActivationDone;
}
else if(pActParams->dwProcessReqType == PRT_USE_THIS)
{
// A custom activator hinted at a specific process, which was not
// found. Eg, the process in question was killed, died, etc. Although
// this should not happen much in the normal case, it would be nice if
// we could somehow save the client from getting an error. So what we
// do is re-try the activation using any compatible server. If it works
// great, if not then we're done (we won't start a new server).
// note we're only resetting the pertinent flags in the actparams struct,
// not the actprops object, but everybody downstream from here only looks
// at the actparams so this is okay.
pActParams->dwProcessReqType = PRT_IGNORE;
pActParams->dwPID = 0;
bStatus = pServerTableEntry->CallRunningServer( pActParams,
0,
0,
pClsidData,
&hr);
goto ActivationDone;
}
// else { keep going }
}
}
if (bFirstTime)
{
bFirstTime = FALSE;
//
// Try to do at-storage first
//
if (ActivateAtStorage(pActParams, pClsidData, &hr))
goto ActivationDone;
// Try a remote activation if
// (1a) Class is configured to be activated remotely
// AND
// (1b) Client will accept a remote activation
// OR
// (2)SERVERTYPE_NONE
if( (((pClsidData->GetAcceptableContext() & (CLSCTX_REMOTE_SERVER | CLSCTX_LOCAL_SERVER)) == CLSCTX_REMOTE_SERVER)
&&
(pActParams->ClsContext & CLSCTX_REMOTE_SERVER))
||
(pClsidData->ServerType() == SERVERTYPE_NONE) )
goto ActivationDoneLocal;
}
if ( ! pLaunchMutex )
{
pLaunchMutex = pClsidData->ServerLaunchMutex();
if (!pLaunchMutex)
{
hr = E_OUTOFMEMORY;
goto ActivationDone;
}
}
else
WaitForSingleObject( pLaunchMutex->Handle(), INFINITE );
// At this point we now hold the launch mutex
// If we've been told explicitly to launch a new server process, then
// there's no reason to check for one already running.
if (pActParams->dwProcessReqType != PRT_CREATE_NEW)
{
// If server exists, release launch mutex and try
// to call server
BOOL fExists;
hr = pServerTableEntry->ServerExists(pActParams, &fExists);
if (hr != S_OK)
{
ReleaseMutex( pLaunchMutex->Handle() );
goto ActivationDone;
}
if (fExists)
{
ReleaseMutex( pLaunchMutex->Handle() );
continue;
}
}
ASSERT(pActParams->dwProcessReqType == PRT_IGNORE ||
pActParams->dwProcessReqType == PRT_CREATE_NEW);
RpcTryExcept
{
LONG lLaunchThreadToken;
//
// This returns when the server has registered the requested CLSID or
// we give up.
//
CairoleDebugOut((DEB_SCM, "Starting ServerTableEntry at 0x%p\n", pServerTableEntry));
// Grab a non-zero token for the launch that we will
// use to associate the server with on the call
do {
lLaunchThreadToken = InterlockedIncrement(&gThreadToken);
}
while (lLaunchThreadToken == 0);
// Use the token to launch
// Note that StartServerAndWait could reset the token
// to zero in some cases.
hr = pServerTableEntry->StartServerAndWait( pActParams,
pClsidData,
lLaunchThreadToken);
// Now call the server with the LaunchMutex held but
// with the threadtoken to guarantee first access to
// the class in the server we launched. This takes
// care of SINGLEUSE as well as transient error cases.
if (SUCCEEDED(hr))
{
// NOTE: if the server we just launched was an "extra" one (ie, on
// behalf of some custom activator), it's not guaranteed that this
// activation will use the just-launched server. It may get an old one.
bStatus = pServerTableEntry->CallRunningServer(pActParams,
0,
lLaunchThreadToken,
pClsidData,
&hr);
if (!bStatus)
hr = CO_E_SERVER_EXEC_FAILURE;
}
}
RpcExcept(ActivationExceptionFilter(GetExceptionInformation()))
{
Status = RpcExceptionCode();
hr = HRESULT_FROM_WIN32(Status);
}
RpcEndExcept
ReleaseMutex( pLaunchMutex->Handle() );
break;
}// end for(;;)
goto ActivationDone;
ActivationDoneLocal:
hr = REGDB_E_CLASSNOTREG;
//
// Server name will only be non-null if its our machine name.
//
if ( !pActParams->pwszServer &&
pClsidData->RemoteServerNames() )
{
//
// the remote activation call will null out the pointer in the ActivationPropertiesIn
// object which caused the memory that pActParams->pwszServer is pointing to to be
// freed. We need this name later on to pass to the oxid resoluton phase, so
// we copy it to some memory on the stack
//
// We don't care here since pActParams->pwszServer==NULL if we are here.
if (!ActivateRemote( pActParams, pClsidData, &hr ))
{
hr = (CLSCTX_REMOTE_SERVER == pActParams->ClsContext) ?
CO_E_CANT_REMOTE : REGDB_E_CLASSNOTREG;
}
}
ActivationDone:
if (pLaunchMutex)
pLaunchMutex->Release();
// Registry data is not cached in any way.
if ( pClsidData )
delete pClsidData;
if ( pServerTableEntry )
pServerTableEntry->Release();
// Don't need to resolve if we're return an inproc server.
if ( (S_OK == hr) && ! *pActParams->ppwszDllServer )
hr = ResolveORInfo( pActParams);
if (pActParams->ulMarshaledTargetInfoLength)
{
MIDL_user_free(pActParams->pMarshaledTargetInfo);
}
return hr;
}
//-------------------------------------------------------------------------
//
// ResolveORInfo
//
// On the server side of a remote activation, gets the OXID in the
// marshalled interface pointer.
//
// For a client side activation (local or remote), calls revolve OXID.
//
//-------------------------------------------------------------------------
HRESULT
ResolveORInfo(
IN OUT PACTIVATION_PARAMS pActParams
)
{
MInterfacePointer * pIFD;
OBJREF * pObjRef;
STDOBJREF * pStdObjRef;
DUALSTRINGARRAY * pORBindings;
DWORD DataSize;
RPC_STATUS sc;
DWORD n;
BOOL ActivatedRemote = pActParams->activatedRemote;
// Don't resolve if we are servicing a remote activation and
// we also did a remote activation(i.e LB router)
if (pActParams->RemoteActivation && ActivatedRemote)
return S_OK;
//
// This routine probes the interface data returned from the server's
// OLE during a successfull activation, but we're still going to
// protect ourself from bogus data.
//
if (pActParams->pActPropsOut)
{
HRESULT hr;
pActParams->pIIDs = 0;
pActParams->pResults = 0;
pActParams->ppIFD = 0;
hr = pActParams->pActPropsOut->GetMarshalledResults(&pActParams->Interfaces,
&pActParams->pIIDs,
&pActParams->pResults,
&pActParams->ppIFD);
if (hr != S_OK)
return hr;
}
pIFD = 0;
for ( n = 0; n < pActParams->Interfaces; n++ )
{
pIFD = pActParams->ppIFD[n];
if ( pIFD )
break;
}
ASSERT( pIFD );
if ( pIFD->ulCntData < 2*sizeof(ULONG) )
{
ASSERT( !"Bad interface data returned from server" );
return S_OK;
}
pObjRef = (OBJREF *)pIFD->abData;
if ( (pObjRef->signature != OBJREF_SIGNATURE) ||
(pObjRef->flags & ~(OBJREF_STANDARD | OBJREF_HANDLER |
OBJREF_CUSTOM | OBJREF_EXTENDED)) ||
(pObjRef->flags == 0) )
{
ASSERT( !"Bad interface data returned from server" );
return S_OK;
}
// No OR info sent back for custom marshalled interfaces.
if ( pObjRef->flags == OBJREF_CUSTOM )
return S_OK;
DataSize = 2*sizeof(ULONG) + sizeof(GUID);
pStdObjRef = (STDOBJREF *)(pIFD->abData + DataSize);
DataSize += sizeof(STDOBJREF);
if ( pObjRef->flags == OBJREF_HANDLER )
DataSize += sizeof(CLSID);
else if( pObjRef->flags == OBJREF_EXTENDED)
DataSize += sizeof(DWORD);
pORBindings = (DUALSTRINGARRAY *)(pIFD->abData + DataSize);
DataSize += 2 * sizeof(USHORT);
if ( pIFD->ulCntData < DataSize )
{
ASSERT( !"Bad interface data returned from server" );
return S_OK;
}
// If we activated the server on this machine, we need the OXID of the server.
if ( ! ActivatedRemote )
*pActParams->pOxidServer = *((OXID UNALIGNED *)&pStdObjRef->oxid);
//
// If we're servicing a remote activation, all we need is the server's OXID.
// The client will call ResolveClientOXID from its ResolveORInfo.
//
if ( pActParams->RemoteActivation )
return S_OK;
DataSize += pORBindings->wNumEntries * sizeof(USHORT);
if ( (pIFD->ulCntData < DataSize) ||
(pORBindings->wNumEntries != 0 &&
(pORBindings->wSecurityOffset >= pORBindings->wNumEntries)) )
{
ASSERT( !"Bad interface data returned from server" );
// Bug 658576 - don't send back a non-zero oxid if
// server bindings are empty or corrupt.
*pActParams->pOxidServer = 0;
return S_OK;
}
//
// If empty OR bindings were supplied then the server and client are
// both local to this machine, so use the local OR bindings.
//
if (pORBindings->wNumEntries == 0)
{
sc = CopyMyOrBindings(pActParams->ppServerORBindings, NULL);
if (sc != RPC_S_OK)
return HRESULT_FROM_WIN32(sc);
}
else
{
//
// This was a local activation so use our string bindings for the OR
// binding string.
//
*pActParams->ppServerORBindings = (DUALSTRINGARRAY *)
MIDL_user_allocate( sizeof(DUALSTRINGARRAY) +
pORBindings->wNumEntries*sizeof(USHORT) );
if ( ! *pActParams->ppServerORBindings )
return E_OUTOFMEMORY;
dsaCopy( *pActParams->ppServerORBindings, pORBindings );
}
//
// If we did a remote activation then we already have the server's OXID and
// OR string bindings from the RemoteActivation call and pieces of the OXID
// info have been filled in.
//
// Could we optimize this at all for the local case?
USHORT usAuthnSvc;
sc = ResolveClientOXID( pActParams->hRpc,
pActParams->pOxidServer,
*pActParams->ppServerORBindings,
pActParams->Apartment,
pActParams->ProtseqId,
pActParams->pwszServer,
pActParams->pOxidInfo,
pActParams->pLocalMidOfRemote,
pActParams->UnsecureActivation,
pActParams->AuthnSvc,
pActParams->ulMarshaledTargetInfoLength,
pActParams->pMarshaledTargetInfo,
&pActParams->IsLocalOxid,
NULL,
NULL,
&usAuthnSvc);
return HRESULT_FROM_WIN32(sc);
}
//-------------------------------------------------------------------------
//
// ActivateAtStorage
//
// If the given CLSID is marked with ActivateAtStorage, do a remote
// activation to the machine where the path points.
//
// Returns TRUE if a remote activation was tried or a wierd error was
// encoutered. Returns FALSE if the CLSID is not marked with
// ActivateAtStorage or the file path is determined to be local.
//
//-------------------------------------------------------------------------
BOOL
ActivateAtStorage(
IN OUT ACTIVATION_PARAMS * pActParams,
IN CClsidData * pClsidData,
OUT HRESULT * phr
)
{
//
// See if we need to do a remote ActivateAtStorage activation. If
// a server name is given, then we either made a remote activation
// already or the server name is for the local machine in which case
// ActivateAtStorage is ignored.
LPWSTR pwszOrigSrvrName=NULL;
pwszOrigSrvrName = GetOrigSrvrName(pActParams);
if ( pActParams->RemoteActivation ||
pActParams->pwszServer ||
pwszOrigSrvrName ||
!pActParams->pwszPath )
return FALSE;
// Note that if we have no information at all for a CLSID, we try a
// atstorage activation. Part of initial dcom spec.
//
if ( pClsidData && ! pClsidData->ActivateAtStorage() )
return FALSE;
HRESULT hr;
WCHAR wszMachineName[MAX_COMPUTERNAME_LENGTH+1];
//
#ifdef DFSACTIVATION
//
// This is for DFS support. If the file hasn't been opened yet, we must
// open it before trying to resolve the DFS pathname in GetMachineName.
// This is just how DFS works. FindFirstFile results in the fewest number
// of network packets.
//
if ( ! pActParams->FileWasOpened )
{
HANDLE hFile;
WIN32_FIND_DATA Data;
if (pActParams->pToken != NULL)
pActParams->pToken->Impersonate();
hFile = FindFirstFile( pActParams->pwszPath, &Data );
if ( hFile != INVALID_HANDLE_VALUE )
(void) FindClose( hFile );
if (pActParams->pToken != NULL)
pActParams->pToken->Revert();
if ( INVALID_HANDLE_VALUE == hFile )
{
*phr = CO_E_BAD_PATH;
return TRUE;
}
}
#endif
hr = GetMachineName(
pActParams->pwszPath,
wszMachineName
#ifdef DFSACTIVATION
,TRUE
#endif
);
if ( hr == S_FALSE )
{
// We couldn't get the machine name, path must be local.
return FALSE;
}
else if ( hr != S_OK )
{
// We got an error while trying to find the UNC machine name.
*phr = hr;
return TRUE;
}
if ( gpMachineName->Compare( wszMachineName ) )
return FALSE;
*phr = RemoteActivationCall( pActParams, wszMachineName );
return TRUE;
}
//-------------------------------------------------------------------------
//
// ActivateRemote
//
// Does a remote activation based off of the RemoteServerName registry key
// for the given CLSID.
//
// Returns TRUE if a remote activation was tried, FALSE if not.
//
//-------------------------------------------------------------------------
BOOL
ActivateRemote(
IN OUT ACTIVATION_PARAMS * pActParams,
IN CClsidData * pClsidData,
OUT HRESULT * phr
)
{
WCHAR * pwszServerName;
BOOL bBadServerName;
BOOL bMyServerName;
*phr = S_OK;
//
// The CClsidData class puts the remote server name(s) into a REG_MULTI_SZ
// format.
//
pwszServerName = pClsidData->RemoteServerNames();
// jsimmons 3/11/00 prefix bug fix. We would crash below if RemoteServerNames
// returned NULL (which is possible). The only caller of this function checks
// that before calling us, though. However, it doesn't hurt to make sure.
if (!pwszServerName)
{
ASSERT(0);
*phr = E_UNEXPECTED;
return FALSE;
}
bBadServerName = TRUE;
bMyServerName = TRUE;
for ( ; *pwszServerName; pwszServerName += lstrlenW(pwszServerName) + 1 )
{
if ( pwszServerName[0] == L'\\' && pwszServerName[1] == L'\\' )
pwszServerName += 2;
while ( *pwszServerName &&
(*pwszServerName == L' ' || *pwszServerName == L'\t') )
pwszServerName++;
if ( pwszServerName[0] == L'\0' )
continue;
bBadServerName = FALSE;
if ( gpMachineName->Compare( pwszServerName ) )
continue;
bMyServerName = FALSE;
*phr = RemoteActivationCall( pActParams, pwszServerName );
if ( S_OK == *phr )
break;
}
if ( bBadServerName || bMyServerName )
return FALSE;
return TRUE;
}
//-------------------------------------------------------------------------
//
// LookupObjectInROT
//
// Looks for an object (file path in this activation) in the Running Object
// Table.
//
// Returns TRUE if we found the object in the ROT and can pass its
// marshalled interface pointer directly back to the client.
//
//-------------------------------------------------------------------------
BOOL
LookupObjectInROT(
IN PACTIVATION_PARAMS pActParams,
OUT HRESULT * phr )
{
SCMREGKEY Key;
MNKEQBUF * pMnkEqBuf;
BYTE Buffer[sizeof(DWORD)+ROT_COMPARE_MAX];
pMnkEqBuf = (MNKEQBUF *) Buffer;
*phr = CreateFileMonikerComparisonBuffer(
pActParams->pwszPath,
&pMnkEqBuf->abEqData[0],
ROT_COMPARE_MAX,
&pMnkEqBuf->cdwSize );
if ( *phr != S_OK )
return FALSE;
*phr = gpscmrot->GetObject(
pActParams->pToken,
pActParams->pProcess ? pActParams->pProcess->WinstaDesktop() : NULL,
0,
pMnkEqBuf,
&Key,
(InterfaceData **)&pActParams->pIFDROT );
if ( *phr != S_OK )
return FALSE;
//
// If our activation call is from a local client and for a single
// interface then we can return success. Otherwise we return failure
// because we must call the server either to get more interface
// pointers or because we are servicing a remote activation and must get
// a normal marshalled interface pointer rather than the table marshalled
// interface pointer sitting in the ROT.
//
if ( ! pActParams->RemoteActivation && (1 == pActParams->Interfaces) )
{
// Return the marshaled interface from the ROT to the caller.
pActParams->ppIFD = (MInterfacePointer **)
MIDL_user_allocate(sizeof(MInterfacePointer *));
pActParams->pResults = (HRESULT*) MIDL_user_allocate(sizeof(HRESULT));
if ((pActParams->ppIFD==NULL) || (pActParams->pResults==NULL))
{
MIDL_user_free(pActParams->ppIFD);
MIDL_user_free(pActParams->pResults);
*phr = E_OUTOFMEMORY;
return FALSE;
}
*pActParams->ppIFD = pActParams->pIFDROT;
pActParams->pResults[0] = S_OK;
// So we remember not to clean up the buffer
pActParams->pIFDROT = NULL;
// Let caller know that we got this from the ROT so
// if it doesn't work they should try again.
pActParams->FoundInROT = TRUE;
*pActParams->pFoundInROT = TRUE;
return TRUE;
}
//
// REVIEW REVIEW. Can we return success if the ROT object was marshalled
// strong? Do we really have to call the server if the object was
// marshalled weak? Is the resulting race condition any worse then for a
// normal activation?
//
//
// We can't use a tabled marshalled interface pointer to send back to a
// remote client, so we return failure here, but keep the ROT interface
// data in pIFDROT.
//
return FALSE;
}
//+---------------------------------------------------------------------------
//
// Get the COSERVERINFO supplied by the client. We'll use this to decide
// whether we want to do remote ActivateAtStorage.
//
//+---------------------------------------------------------------------------
LPWSTR GetOrigSrvrName(
PACTIVATION_PARAMS pActParams
)
{
LPWSTR pwszOrigSrvrName = NULL;
if (pActParams->pActPropsIn)
{
SecurityInfo* pLegacyInfo = pActParams->pActPropsIn->GetSecurityInfo();
if (pLegacyInfo)
{
COSERVERINFO* pServerInfo = NULL;
pLegacyInfo->GetCOSERVERINFO(&pServerInfo);
if (pServerInfo)
{
pwszOrigSrvrName = pServerInfo->pwszName;
}
}
}
return pwszOrigSrvrName;
}
//
// Helper function. ppid and pdwProcessReqType may be NULL if caller does not care about them.
//
HRESULT GetProcessInfoFromActProps(IActivationPropertiesIn* pActPropsIn, DWORD* ppid, DWORD* pdwProcessReqType)
{
HRESULT hr = E_INVALIDARG;
ASSERT(pActPropsIn);
if (pActPropsIn != NULL)
{
IServerLocationInfo *pSLInfo = NULL;
hr = pActPropsIn->QueryInterface(IID_IServerLocationInfo, (void**) &pSLInfo);
ASSERT(SUCCEEDED(hr) && pSLInfo);
if (SUCCEEDED(hr) && pSLInfo != NULL)
{
DWORD dwPRT;
DWORD dwPid;
hr = pSLInfo->GetProcess(&dwPid, &dwPRT);
ASSERT(SUCCEEDED(hr));
ASSERT(dwPRT == PRT_IGNORE ||
dwPRT == PRT_CREATE_NEW ||
dwPRT == PRT_USE_THIS ||
dwPRT == PRT_USE_THIS_ONLY);
if (SUCCEEDED(hr))
{
if (ppid)
*ppid = dwPid;
if (pdwProcessReqType)
*pdwProcessReqType = dwPRT;
}
pSLInfo->Release();
pSLInfo = NULL;
}
}
return hr;
}