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