|
|
//+-------------------------------------------------------------------------
//
// 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; i<cRequestedProtseqs; i++) pReqInfo->pRequestedProtseqs[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; }
|