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