//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1995. // // File: // objexif.cxx // // Contents: // Entry point for remote activation call to SCM/OR. // // Functions: // RemoteActivation // // History: // //-------------------------------------------------------------------------- #include "act.hxx" //+--------------------------------------------------------------------------- // // Function: _RemoteActivation // // Synopsis: Entry point for old style activations from off machine. // Creates new stype activation properties and forwards to // ActivateFromPropertiesPreamble. // //---------------------------------------------------------------------------- error_status_t _RemoteActivation( handle_t hRpc, ORPCTHIS *ORPCthis, ORPCTHAT *ORPCthat, GUID *Clsid, WCHAR *pwszObjectName, MInterfacePointer *pObjectStorage, DWORD ClientImpLevel, DWORD Mode, DWORD Interfaces, IID *pIIDs, unsigned short cRequestedProtseqs, unsigned short aRequestedProtseqs[], OXID *pOxid, DUALSTRINGARRAY **ppdsaOxidBindings, IPID *pipidRemUnknown, DWORD *pAuthnHint, COMVERSION *pServerVersion, HRESULT *phr, MInterfacePointer **ppInterfaceData, HRESULT *pResults ) { RPC_STATUS sc; ACTIVATION_PARAMS ActParams; LOCALTHIS Localthis; WCHAR * pwszDummy; error_status_t rpcerror= RPC_S_OK; IID *newIIDs = 0; DWORD count; DWORD i; IComClassInfo* pClassInfo = NULL; IInitActivationPropertiesIn* pInitActPropsIn = NULL; // check for valid parameters if (ORPCthis == NULL || ORPCthat == NULL || Clsid == NULL || pOxid == NULL || Interfaces == 0 || pIIDs == NULL || ppdsaOxidBindings == NULL || pipidRemUnknown == NULL || pAuthnHint == NULL || pServerVersion == NULL || phr == NULL || ppInterfaceData == NULL || pResults == NULL) { return E_INVALIDARG; } *ppInterfaceData = NULL; *pOxid = 0; *ppdsaOxidBindings = NULL; memset(&ActParams, 0, sizeof(ActParams)); /** Old Functionality **/ Localthis.dwClientThread = 0; Localthis.dwFlags = LOCALF_NONE; ORPCthis->flags |= ORPCF_DYNAMIC_CLOAKING; ORPCthat->flags = 0; ORPCthat->extensions = NULL; // Determine what version to use for the returned interface. Fail // if the client wants a version we don't support. *pServerVersion = ORPCthis->version; *phr = NegotiateDCOMVersion( pServerVersion ); if (*phr != OR_OK) { pServerVersion->MajorVersion = COM_MAJOR_VERSION; pServerVersion->MinorVersion = COM_MINOR_VERSION; return RPC_S_OK; } if ( ! s_fEnableDCOM ) { *phr = E_ACCESSDENIED; return RPC_S_OK; } RegisterAuthInfoIfNecessary(); /** Set up Actparams **/ ActParams.hRpc = hRpc; ActParams.ORPCthis = ORPCthis; ActParams.Localthis = &Localthis; ActParams.ORPCthat = ORPCthat; ActParams.oldActivationCall = TRUE; ActParams.RemoteActivation = TRUE; if ( pwszObjectName || pObjectStorage ) ActParams.MsgType = GETPERSISTENTINSTANCE; else ActParams.MsgType = (Mode == MODE_GET_CLASS_OBJECT) ? GETCLASSOBJECT : CREATEINSTANCE; /** Set up Activation Properties **/ ActivationPropertiesIn * pInActivationProperties=NULL; ActivationPropertiesOut * pOutActivationProperties=NULL; InstantiationInfo * pInstantiationInfo=NULL; IScmRequestInfo * pInScmRequestInfo=NULL; IInstanceInfo *pInstanceInfo=NULL; ISpecialSystemProperties* pISpecialSystemProps = NULL; REMOTE_REQUEST_SCM_INFO *pReqInfo; IScmReplyInfo * pScmReplyInfo = NULL; REMOTE_REPLY_SCM_INFO *pReply; pInActivationProperties = new ActivationPropertiesIn; if (NULL == pInActivationProperties) { *phr = E_OUTOFMEMORY; return RPC_S_OK; } HRESULT hr; // Incoming session id from down-level clients is implicitly INVALID_SESSION_ID; make it so *phr = pInActivationProperties->QueryInterface(IID_ISpecialSystemProperties, (void**)&pISpecialSystemProps); if (FAILED(*phr)) goto exit_oldremote; hr = pISpecialSystemProps->SetSessionId(INVALID_SESSION_ID, FALSE, FALSE); ASSERT(hr == S_OK); // pISpecialSystemProps will be released just before returning pInstantiationInfo = pInActivationProperties->GetInstantiationInfo(); if (pInstantiationInfo == NULL) { *phr = E_OUTOFMEMORY; goto exit_oldremote; } *phr = pInActivationProperties->QueryInterface(IID_IScmRequestInfo, (LPVOID*)&pInScmRequestInfo); if (FAILED(*phr)) goto exit_oldremote; hr = pInstantiationInfo->SetClsid(*Clsid); ASSERT(hr == S_OK); hr = pInstantiationInfo->SetClsctx(CLSCTX_LOCAL_SERVER); ASSERT(hr == S_OK); hr = pInstantiationInfo->SetClientCOMVersion(ORPCthis->version); ASSERT(hr == S_OK); *phr = pInActivationProperties->AddRequestedIIDs(Interfaces,pIIDs); if ( FAILED(*phr) ) goto exit_oldremote; if (ActParams.MsgType == GETPERSISTENTINSTANCE) { *phr = pInActivationProperties->QueryInterface(IID_IInstanceInfo, (LPVOID*)&pInstanceInfo); if (FAILED(*phr)) goto exit_oldremote; if ( pwszObjectName ) { WCHAR *oldName = pwszObjectName; *phr = GetServerPath( pwszObjectName, &pwszObjectName); if ( FAILED(*phr) ) goto exit_oldremote; *phr = pInstanceInfo->SetFile(pwszObjectName, Mode); if ( FAILED(*phr) ) goto exit_oldremote; pInstanceInfo->GetFile(&ActParams.pwszPath, &ActParams.Mode); if (pwszObjectName != oldName) PrivMemFree(pwszObjectName); } else { ActParams.pwszPath = 0; } if (pObjectStorage) { MInterfacePointer* newStorage; newStorage = (MInterfacePointer*) AllocateAndCopy((InterfaceData*)pObjectStorage); if (newStorage) { *phr = pInstanceInfo->SetStorageIFD(newStorage); ActParams.pIFDStorage = pObjectStorage; } else *phr = E_OUTOFMEMORY; } if ( FAILED(*phr) ) goto exit_oldremote; } pReqInfo = (REMOTE_REQUEST_SCM_INFO *)MIDL_user_allocate(sizeof(REMOTE_REQUEST_SCM_INFO)); if (pReqInfo) { memset(pReqInfo, 0, sizeof(REMOTE_REQUEST_SCM_INFO)); pReqInfo->ClientImpLevel = ClientImpLevel; if (pReqInfo->cRequestedProtseqs = cRequestedProtseqs) { pReqInfo->pRequestedProtseqs = (unsigned short*) MIDL_user_allocate(sizeof(unsigned short) * cRequestedProtseqs); if (pReqInfo->pRequestedProtseqs == NULL) { *phr = E_OUTOFMEMORY; MIDL_user_free(pReqInfo); } } } else *phr = E_OUTOFMEMORY; if ( FAILED(*phr) ) goto exit_oldremote; for (i=0; ipRequestedProtseqs[i] = aRequestedProtseqs[i]; pInScmRequestInfo->SetRemoteRequestInfo(pReqInfo); //Set up for marshalling pInActivationProperties->SetDestCtx(MSHCTX_DIFFERENTMACHINE); // // Get/set class info for the requested class; ActivateFromPropertiesPreamble // expects that actpropsin will already have had this done. // *phr = GetClassInfoFromClsid(*Clsid, &pClassInfo); if (FAILED(*phr)) goto exit_oldremote; *phr = pInActivationProperties->QueryInterface(IID_IInitActivationPropertiesIn, (void**)&pInitActPropsIn); if (FAILED(*phr)) goto exit_oldremote; *phr = pInitActPropsIn->SetClassInfo(pClassInfo); if (FAILED(*phr)) goto exit_oldremote; //Mark properties object as having been delegated from by //client which is implicitly true even though it's created here //for first time pInActivationProperties->SetDelegated(); //Delegate through activation properties IActivationPropertiesOut *pActPropsOut; *phr = ActivateFromPropertiesPreamble(pInActivationProperties, &pActPropsOut, &ActParams); pOutActivationProperties = ActParams.pActPropsOut; if ((*phr != S_OK) || (pOutActivationProperties == NULL)) goto exit_oldremote; *phr = pOutActivationProperties->QueryInterface(IID_IScmReplyInfo, (LPVOID*)&pScmReplyInfo); if ( FAILED(*phr) ) goto exit_oldremote; pScmReplyInfo->GetRemoteReplyInfo(&pReply); *pOxid = pReply->Oxid; *ppdsaOxidBindings = pReply->pdsaOxidBindings; pReply->pdsaOxidBindings = NULL; // so it won't be freed twice *pipidRemUnknown = pReply->ipidRemUnknown; *pAuthnHint = pReply->authnHint; // For custom marshalled interfaces the reply is not set. Don't // clear the version number in that case. if (pReply->serverVersion.MajorVersion != 0) *pServerVersion = pReply->serverVersion; *phr = pOutActivationProperties->GetMarshalledResults(&count, &newIIDs, &pResults, &ppInterfaceData); // ******************** // ** Begin fix for NT Bug 312637 // ** April 1, 1999 -- stevesw // ** // ** GetMarshalledResults puts a pointer to an empty MInterfacePointer // ** in the ppInterfaceData array. NT4 expects the values to be NULL. // ** Here we translate from NT5 to NT4 by freeing and nulling out these // ** array values. // ** for (i = 0; i < count; i++ ) { if ( !SUCCEEDED(pResults[i]) || ppInterfaceData[i]->ulCntData < 2*sizeof(ULONG) ) { ActMemFree (ppInterfaceData[i]); ppInterfaceData[i] = NULL; } } // ** // ** End fix for NT Bug 312637 // ******************** pScmReplyInfo->Release(); count = pOutActivationProperties->Release(); ASSERT(count == 0); exit_oldremote: if (pInstanceInfo) pInstanceInfo->Release(); if (pClassInfo) pClassInfo->Release(); if (pInitActPropsIn) pInitActPropsIn->Release(); if (pISpecialSystemProps) { pISpecialSystemProps->Release(); } if (pInScmRequestInfo) { count = pInScmRequestInfo->Release(); ASSERT(count == 1); } if (pInActivationProperties) { count = pInActivationProperties->Release(); ASSERT(count == 0); } return rpcerror; } //+--------------------------------------------------------------------------- // // Function: GetServerPath // // Synopsis: Computes file name of executable with drive name instead of // UNC name. // // Description: This is to work around limitations in NT's current // security/rdr. If we get a UNC path to this machine, // convert it into a drive based path. A server activated as // the client can not open any UNC path file, even if local, // so we make it drive based. // // On Chicago, we neither have this problem nor do we have // the NetGetShareInfo entrypoint in the relevant DLL // //---------------------------------------------------------------------------- HRESULT GetServerPath( WCHAR * pwszPath, WCHAR ** pwszServerPath ) { WCHAR * pwszFinalPath; ASSERT(pwszPath != NULL); ASSERT(pwszServerPath != NULL); pwszFinalPath = pwszPath; *pwszServerPath = pwszPath; if ( (pwszPath[0] == L'\\') && (pwszPath[1] == L'\\') ) { WCHAR wszMachineName[MAX_COMPUTERNAME_LENGTH+1]; WCHAR * pwszShareName; WCHAR * pwszShareEnd; PSHARE_INFO_2 pShareInfo; NET_API_STATUS Status; HRESULT hr; // It's already UNC so this had better succeed. hr = GetMachineName( pwszPath, wszMachineName #ifdef DFSACTIVATION ,FALSE #endif ); if ( FAILED(hr) ) return hr; if ( gpMachineName->Compare( wszMachineName ) ) { pwszShareName = pwszPath + 2; while ( *pwszShareName++ != L'\\' ) ; pwszShareEnd = pwszShareName; while ( *pwszShareEnd != L'\\' ) pwszShareEnd++; // This is OK, we're just munching on the string the RPC stub passed us. *pwszShareEnd = 0; pShareInfo = 0; Status = NetShareGetInfo( NULL, pwszShareName, 2, (LPBYTE *)&pShareInfo ); if ( Status != STATUS_SUCCESS ) return (ULONG) CO_E_BAD_PATH; pwszFinalPath = (WCHAR *) PrivMemAlloc( sizeof(WCHAR) * (MAX_PATH+1) ); if ( ! pwszFinalPath ) { LocalFree( pShareInfo ); return (ULONG) E_OUTOFMEMORY; } lstrcpyW( pwszFinalPath, pShareInfo->shi2_path ); *pwszShareEnd = L'\\'; lstrcatW( pwszFinalPath, pwszShareEnd ); // // Netapi32.dll midl_user_allocate calls LocalAlloc, so use // LocalFree to free up the stuff the stub allocated. // LocalFree( pShareInfo ); } } *pwszServerPath = pwszFinalPath; return S_OK; }