//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1993. // // File: actprops.cxx // // Contents: Activation Functions used by object servers. // // Functions: Implements classes in Actprops.hxx // // History: 24-Jan-98 Vinaykr Created // 24-Jul-98 CBiks Fixed RAID# 199660. // 14-Sep-98 CBiks Fixed RAID# 214719. // 29-Sep-98 vinaykr Fixed RAID# 169084, // inproc unmarshaller for perf // 14-Sep-98 CBiks Fixed RAID# 151056. // 22-Oct-98 TarunA Fixed RAID# 234750 // //-------------------------------------------------------------------------- #include #include #include //--------------------------------------------------------------------------- // GUIDs need to be declared here since they have to // live in both the SCM and OLE32. //--------------------------------------------------------------------------- // catalog query helper defined in ..\com\objact.cxx HRESULT GetClassInfoFromClsid(REFCLSID rclsid, IComClassInfo **ppClassInfo); CLSID CLSID_Grammatik = {0xc9da6c40,0x83b1,0x11ce, {0x81, 0xac, 0x00, 0x60, 0x8c, 0xb9, 0xf8, 0x3b}}; CLSID CLSID_WonderWare = {0x28dd9320, 0x6f69, 0x11ce, {0x8b, 0x69, 0x00, 0x60, 0x8c, 0xc9, 0x7d, 0x5b}}; CLSID CLSID_WPNatLangTools = {0xe6246810, 0x030f, 0x11cf, {0x88, 0x75, 0x00, 0x60, 0x8c, 0xf5, 0xab, 0x6f}}; CLSID CLSID_Grammatik8 = {0xc0e10005, 0x0201, 0x0180, {0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1, 0xc0, 0xe1}}; InprocActpropsUnmarshaller InprocActpropsUnmarshaller::_InprocActUnmarshaller; CLSID *arBrokenRefCount[] = { &CLSID_Grammatik, &CLSID_WonderWare, &CLSID_WPNatLangTools, &CLSID_Grammatik8 }; // // Marshalling functions. They are here because we cannot link to ole32.dll // if we are in the SCM. // PFN_CORELEASEMARSHALDATA pfnCoReleaseMarshalData = NULL; PFN_COUNMARSHALINTERFACE pfnCoUnmarshalInterface = NULL; PFN_COGETMARSHALSIZEMAX pfnCoGetMarshalSizeMax = NULL; PFN_COMARSHALINTERFACE pfnCoMarshalInterface = NULL; // Resolve the function pointers for marshalling. Call this before you // use any of the above functions, or you WILL crash, ole32 or not. void InitMarshalling(void) { static int init = 0; // Only attempt to initialize once. if (init) return; // Do not load ole32.dll, but if it is loaded then we are linked into it, // and this will work. HMODULE hOle32 = GetModuleHandle(L"ole32.dll"); if (hOle32) { // Get the functions we need. pfnCoGetMarshalSizeMax = (PFN_COGETMARSHALSIZEMAX)GetProcAddress(hOle32, "CoGetMarshalSizeMax"); Win4Assert(pfnCoGetMarshalSizeMax && "Could not get CoGetMarshalSizeMax!"); pfnCoMarshalInterface = (PFN_COMARSHALINTERFACE)GetProcAddress(hOle32, "CoMarshalInterface"); Win4Assert(pfnCoMarshalInterface && "Could not get CoMarshalInterface!"); pfnCoUnmarshalInterface = (PFN_COUNMARSHALINTERFACE)GetProcAddress(hOle32, "CoUnmarshalInterface"); Win4Assert(pfnCoUnmarshalInterface && "Could not get CoUnmarshalInterface!"); pfnCoReleaseMarshalData = (PFN_CORELEASEMARSHALDATA)GetProcAddress(hOle32, "CoReleaseMarshalData"); Win4Assert(pfnCoReleaseMarshalData && "Could not get CoReleaseMarshalData!"); } else { // ole32.dll is not loaded. The functions stay null. If anybody // tries to call them, you will crash. You should not be calling // such functions from the SCM. // // REVIEW: We might want to assert here. Revisit when Jon Schwartz // makes ole32.dll delay load. } init = 1; } //+---------------------------------------------------------------------------- // // Function: IsBrokenRefCount // // Synopsis: Check to see if this clsid is known to have broken reference // counting. // // History: 21-Apr-98 MattSmit Created // //----------------------------------------------------------------------------- BOOL IsBrokenRefCount(CLSID *pClsId) { ULONG i; ULONG len = sizeof(arBrokenRefCount)/sizeof(CLSID*); for (i = 0; i < len; i++) { if (IsEqualIID(*pClsId, *(arBrokenRefCount[i]))) { return TRUE; } } return FALSE; } //--------------------------------------------------------------------------- // Internal Class Factories for Activation Properties //--------------------------------------------------------------------------- HRESULT CActivationPropertiesInCF_CreateInstance(IUnknown *pUnkOuter, REFIID riid, void** ppv) { ActivationPropertiesIn * actin = new ActivationPropertiesIn(); if (actin==NULL) return E_OUTOFMEMORY; HRESULT hr = actin->QueryInterface(riid, ppv); actin->Release(); return hr; } HRESULT CActivationPropertiesOutCF_CreateInstance(IUnknown *pUnkOuter, REFIID riid, void** ppv) { ActivationPropertiesOut * actout = new ActivationPropertiesOut(FALSE /* fBrokenRefCount */ ); if (actout==NULL) return E_OUTOFMEMORY; HRESULT hr = actout->QueryInterface(riid, ppv); actout->Release(); return hr; } HRESULT CInprocActpropsUnmarshallerCF_CreateInstance(IUnknown *pUnkOuter, REFIID riid, void** ppv) { InprocActpropsUnmarshaller *pInst; pInst = InprocActpropsUnmarshaller::GetInstance(); Win4Assert(pInst); return pInst->QueryInterface(riid, ppv); } //--------------------------------------------------------------------------- // ActivationProperties is a helper class for marshalling // different property objects. It implements ISerializableParent // and manages a set of serializable interfaces. // Assumptions are: // a. QI'ing an interface can bring an // instance into existence. // b. It is possible for some interfaces // to never be instantiatable on // an unserialized Actprops object. // This is achieved through GetClass() // c. It is possible for some interfaces // to never be instantiated again // after they are unserialized(at // least once). Achieved by returning // a size of 0 in GetMarshalSizeMax // Used to turn off propagation at a // particular stage. //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // Methods for ActivationProperties //--------------------------------------------------------------------------- ActivationProperties::ActivationProperties() { memset(&_serHeader, 0, sizeof(CustomHeader)); memset(&_unSerHeader, 0, sizeof(CustomHeader)); _ifsIndex = 0; _unSerialized = FALSE; _unSerializedInproc = FALSE; _pUnSer = 0; _serHeader.destCtx = MSHCTX_CROSSCTX; _marshalFlags = MSHLFLAGS_NORMAL; _toDelete = TRUE; _fDestruct = FALSE; _marshalState = NOT_MARSHALLED; _fInprocSerializationRequired = FALSE; } ActivationProperties::~ActivationProperties() { #if 0 // Allocate them as member vars now //------------------------------------------------------------------- // Release all references to property objects held //------------------------------------------------------------------- for (DWORD i=0; i<_ifsIndex; i++) { if (serializableIfsCollection[i]) serializableIfsCollection[i]->Release(); } #endif //------------------------------------------------------------------- // Release reference to unserialized stream //------------------------------------------------------------------- if (_pUnSer) _pUnSer->Release(); //------------------------------------------------------------------- // Release unserialized data //------------------------------------------------------------------- if (_unSerialized) { ActMemFree(_unSerHeader.pclsid); ActMemFree(_unSerHeader.pSizes); } if (_serHeader.cOpaqueData) { for (DWORD i=0; i<_serHeader.cOpaqueData;i++) ActMemFree(_serHeader.opaqueData[i].data); ActMemFree(_serHeader.opaqueData); } } //--------------------------------------------------------------------------- // Methods for IUnknown //--------------------------------------------------------------------------- //----------------------------------------------------------------------- // Assumption is that the Top-level ActivationProperties object // supports interfaces of the objects contained within it. // QI'ing an interface of a property object can bring it into // existence. GetClass is used for this. // When this is unmarshalled, the contained objects are not // unserialized. They are unserialized when QI's for using // UnSerializeCallback(). //----------------------------------------------------------------------- STDMETHODIMP ActivationProperties::QueryInterface( REFIID riid, LPVOID* ppv) { HRESULT hr; //------------------------------------------------------------------- // Check for Top level interfaces //------------------------------------------------------------------- if (IsEqualIID(riid, IID_IUnknown)) *ppv = (IActivationProperties*)this; else if (IsEqualIID(riid, IID_IActivationProperties)) *ppv = (IActivationProperties*)this; else if (IsEqualIID(riid, IID_ISerializableParent)) *ppv = (ISerializableParent*)this; else if (IsEqualIID(riid, IID_IMarshal)) *ppv = (IMarshal*)this; else if (IsEqualIID(riid, IID_IMarshal2)) *ppv = (IMarshal2*)this; else if (IsEqualIID(riid, IID_IGetCatalogObject)) *ppv = (IGetCatalogObject*)this; else if (IsEqualIID(riid, CLSID_ActivationProperties)) { // Don't addref for this one *ppv = (ActivationProperties*)this; return S_OK; } else *ppv = NULL; if (*ppv != NULL) { AddRef(); return S_OK; } //------------------------------------------------------------------- // Check Contained objects //------------------------------------------------------------------- for (DWORD i=0; i<_ifsIndex; i++) if (serializableIfsCollection[i]) if (serializableIfsCollection[i]->SerializableQueryInterface(riid, ppv) == S_OK) return S_OK; //------------------------------------------------------------------- // Check for unserialized objects */ //------------------------------------------------------------------- SerializableProperty *pSer; if (_unSerialized) { if ((hr = UnSerializeCallBack(riid, &pSer)) == S_OK) { if (pSer->SerializableQueryInterface(riid, ppv) == S_OK) return S_OK; } else if (hr != E_FAIL) { *ppv = NULL; return hr; } } //------------------------------------------------------------------- // Check if interface supported here */ //------------------------------------------------------------------- if (GetClass(riid, &pSer, TRUE) == S_OK) { AddSerializableIfs(pSer); HRESULT hr = pSer->SerializableQueryInterface(riid, ppv); Win4Assert(hr==S_OK); return S_OK; } *ppv = NULL; return E_NOINTERFACE; } ULONG ActivationProperties::AddRef(void) { return InterlockedIncrement(&_refCount); } ULONG ActivationProperties::Release(void) { ULONG count; if ((count = InterlockedDecrement(&_refCount)) == 0) { //------------------------------------------------------------------- // Relinquish parent-child relationship and send child off into // the big bad world. //------------------------------------------------------------------- for (DWORD i=0; i<_ifsIndex; i++) if (serializableIfsCollection[i]) { serializableIfsCollection[i]->SetParent(NULL); } return 0; } return count; } //--------------------------------------------------------------------------- // Custom marshalling Methods(IMarshal) */ // Ignore Table marshalling //--------------------------------------------------------------------------- STDMETHODIMP ActivationProperties::MarshalInterface( IStream *pStm, REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags) { HRESULT hr; BOOL fReleaseThis; //------------------------------------------------------------------- // Check to see that requested interface is supported //------------------------------------------------------------------- void *ppv; if (!SUCCEEDED(hr=QueryInterface(riid, &ppv))) { return hr; } else fReleaseThis = TRUE; RpcTryExcept { //------------------------------------------------------------------- // Internal marshalling distance flag already set up by // GetMarshalSizeMax //------------------------------------------------------------------- void *pv; if (MARSHALCTX_WITHIN_PROCESS(dwDestContext)) { pv = (void*)((ActivationProperties*) this); fReleaseThis = FALSE; } else pv = NULL; //------------------------------------------------------------------- // Create Serializer for serialization //------------------------------------------------------------------- Serializer ser(_serHeader.destCtx, dwDestContext, _marshalFlags); hr = ser.InitStream(pStm, _serHeader.totalSize, Serializer::DIRECTION_WRITE, pv); if (FAILED(hr)) { if(fReleaseThis) Release(); return hr; } if ((!pv) || _fInprocSerializationRequired) hr = Serialize(ser); else hr = S_OK; _marshalState = MARSHALLED; } RpcExcept(TRUE) { hr = HRESULT_FROM_WIN32(RpcExceptionCode()); } RpcEndExcept if (fReleaseThis) Release(); return hr; } inline HRESULT ActivationProperties::Serialize(Serializer &ser) { HRESULT hr; //------------------------------------------------------------------- // First encode Generic header //------------------------------------------------------------------- handle_t handle; hr = ser.GetSerializationHandle((void*) &handle); if (FAILED(hr)) return hr; CustomHeader_Encode(handle, &_serHeader); hr = ser.IncrementPosition(_headerSize); if (FAILED(hr)) return hr; DWORD unSerializedPosition=_unSerHeader.headerSize; DWORD totalinc = 0; //------------------------------------------------------------------- // Now serialize all contained objects //------------------------------------------------------------------- for (DWORD i=0; i<_ifsIndex;i++) { if (!_sizeArray[i]) continue; if ((_unSerialized) && (!serializableIfsCollection[i])) { hr = _pUnSer->CopyTo(&ser, unSerializedPosition, _sizeArray[i]); if (FAILED(hr)) return hr; } else { hr = serializableIfsCollection[i]->Serialize(&ser); if (hr != S_OK) return hr; hr = ser.IncrementPosition(_sizeArray[i]); if (FAILED(hr)) return hr; } if (_unSerialized && (i<_unSerHeader.cIfs)) unSerializedPosition += _unSerHeader.pSizes[i]; } //------------------------------------------------------------------- // Commit to stream //------------------------------------------------------------------- return ser.Commit(); } inline HRESULT ActivationProperties::SetupForUnserializing(Serializer *pSer) { //--------------------------------------------------------------- // Read Custom header // Make a copy to hold still unserialized objects for future // Set up state for next serialization //--------------------------------------------------------------- handle_t handle; pSer->GetSerializationHandle((void*) &handle); _unSerHeader.pclsid = 0; _unSerHeader.pSizes = 0; _unSerHeader.opaqueData = 0; CustomHeader_Decode(handle, &_unSerHeader); pSer->IncrementPosition(_unSerHeader.headerSize); HRESULT hr = pSer->GetCopy(&_pUnSer); if (FAILED(hr)) return hr; pSer->Commit(); _unSerialized = TRUE; _ifsIndex = _unSerHeader.cIfs; _serHeader.destCtx = _unSerHeader.destCtx; _serHeader.cOpaqueData = _unSerHeader.cOpaqueData; _serHeader.opaqueData = _unSerHeader.opaqueData; return S_OK; } STDMETHODIMP InprocActpropsUnmarshaller::UnmarshalInterface(IStream *pStm, REFIID riid, void **ppv) { ActivationProperties *pAct = NULL; RpcTryExcept { HRESULT hr; DWORD dwSize; void *pv = NULL; //--------------------------------------------------------------- // Init Serializer for reading from stream //--------------------------------------------------------------- Serializer ser; hr = ser.InitStream(pStm, dwSize, Serializer::DIRECTION_READ, pv); if (!SUCCEEDED(hr)) return hr; pAct = (ActivationProperties*) pv; Win4Assert(pAct); if (!pAct) return(E_UNEXPECTED); //--------------------------------------------------------------- // If we received a pointer, check if any further unserialization // required. If so set up stream inside object pointed to //--------------------------------------------------------------- Win4Assert(pAct->_marshalState != ActivationProperties::UNMARSHALLED); if (dwSize != 0) hr = pAct->SetupForUnserializing(&ser); if (SUCCEEDED(hr)) { if (ppv != NULL) hr = pAct->QueryInterface(riid, ppv); else hr = E_UNEXPECTED; } pAct->_marshalState = ActivationProperties::UNMARSHALLED; pAct->Release(); return hr; } RpcExcept(TRUE) { //--------------------------------------------------------------- // If we get here and have a pAct then we must release it //--------------------------------------------------------------- if (pAct) { pAct->Release(); } return HRESULT_FROM_WIN32(RpcExceptionCode()); } RpcEndExcept // Should never get here ! Win4Assert(0 && "Should never reach here"); return E_UNEXPECTED; } STDMETHODIMP ActivationProperties::UnmarshalInterface(IStream *pStm, REFIID riid, void **ppv) { RpcTryExcept { Win4Assert(_marshalState != UNMARSHALLED); HRESULT hr; DWORD dwSize; void *pv = NULL; //--------------------------------------------------------------- // Init Serializer for reading from stream //--------------------------------------------------------------- Serializer ser; hr = ser.InitStream(pStm, dwSize, Serializer::DIRECTION_READ, pv); if (!SUCCEEDED(hr)) return hr; hr = SetupForUnserializing(&ser); if (FAILED(hr)) return hr; for (DWORD i=0; i<_ifsIndex;i++) serializableIfsCollection[i] = 0; _marshalState = UNMARSHALLED; } RpcExcept(TRUE) { return HRESULT_FROM_WIN32(RpcExceptionCode()); } RpcEndExcept //------------------------------------------------------------------- // Query for requested interface to return //------------------------------------------------------------------- if (ppv != NULL) return QueryInterface(riid, ppv); else return S_OK; } STDMETHODIMP ActivationProperties::GetMarshalSizeMax( REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, DWORD *pSize) { HRESULT hr; //------------------------------------------------------------------- // If already know size, return it //------------------------------------------------------------------- if (_marshalState == SIZED) { *pSize = _size; return S_OK; } else { //--------------------------------------------------------------- // First set internal marshalling distance flag //--------------------------------------------------------------- SetDestCtx(dwDestContext); if (MARSHALCTX_WITHIN_PROCESS(dwDestContext) && (!_fInprocSerializationRequired)) { _size = 0; hr = S_OK; } else { RpcTryExcept { //--------------------------------------------------------------- // Create Serializer for serialization //--------------------------------------------------------------- Serializer ser(_serHeader.destCtx, dwDestContext, _marshalFlags); hr = GetSize(ser, pSize); _size = *pSize; if (!_size) _fInprocSerializationRequired = FALSE; } RpcExcept(TRUE) { hr = HRESULT_FROM_WIN32(RpcExceptionCode()); } RpcEndExcept } } if (SUCCEEDED(hr)) { // Add fixed serializer header size to serialization size _size += Serializer::GetSize(); *pSize = _size; _marshalState = SIZED; } return hr; } inline HRESULT ActivationProperties::GetSize(Serializer &ser, DWORD *pSize) { HRESULT hr; DWORD size = 0; //------------------------------------------------------------------- // Get sizes of contained objects //------------------------------------------------------------------- for (DWORD i=0; i<_ifsIndex;i++) { //--------------------------------------------------------------- // If object was never unserialized then simply use old size //--------------------------------------------------------------- if ((_unSerialized) && (!serializableIfsCollection[i])) { _clsidArray[i] = _unSerHeader.pclsid[i]; _sizeArray[i] = _unSerHeader.pSizes[i]; } else { hr = serializableIfsCollection[i]->GetCLSID(&_clsidArray[i]); Win4Assert(hr==S_OK); hr = serializableIfsCollection[i]->GetSize(&ser, &_sizeArray[i]); if (FAILED(hr)) return hr; _sizeArray[i] = (_sizeArray[i]+7) & ~7; } size += _sizeArray[i]; } //------------------------------------------------------------------- // Set up header for serialization and get its size if we need // to marshal any information(i.e size>0) //------------------------------------------------------------------- if (size) { _serHeader.cIfs = _ifsIndex; _serHeader.pSizes = _sizeArray; _serHeader.pclsid = _clsidArray; handle_t handle; hr = ser.GetSizingHandle((void*) &handle); if (FAILED(hr)) return hr; _headerSize = CustomHeader_AlignSize(handle, &_serHeader); MesHandleFree(handle); _serHeader.headerSize = _headerSize; size += _headerSize; } // return serialization size _serHeader.totalSize = size; *pSize = size; return S_OK; } STDMETHODIMP ActivationProperties::GetUnmarshalClass( REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, CLSID *pCid) { if (MARSHALCTX_WITHIN_PROCESS(dwDestContext)) *pCid = CLSID_InprocActpropsUnmarshaller; else *pCid = _actCLSID; return S_OK; } STDMETHODIMP ActivationProperties::ReleaseMarshalData(IStream *pStm) { return E_NOTIMPL; } STDMETHODIMP ActivationProperties::DisconnectObject(DWORD dwReserved) { return E_NOTIMPL; } //--------------------------------------------------------------------------- // Methods from ISerializableParent //--------------------------------------------------------------------------- //----------------------------------------------------------------------- // Returns serializer pointing to unserialized data for referenced // CLSID //----------------------------------------------------------------------- STDMETHODIMP ActivationProperties::GetUnserialized(REFCLSID clsid, void **ppISer, DWORD *pSize, DWORD *pPos) { if (!_unSerialized) return E_FAIL; DWORD pos = _unSerHeader.headerSize; HRESULT hr; for (DWORD i=0; i<_ifsIndex; i++) { if (IsEqualIID(clsid,_unSerHeader.pclsid[i])) { hr = _pUnSer->SetPosition(pos); if (FAILED (hr)) { return hr; } *pSize = _unSerHeader.pSizes[i]; *ppISer = _pUnSer; *pPos = pos; return S_OK; } pos +=_unSerHeader.pSizes[i]; } return E_FAIL; } //----------------------------------------------------------------------- // Used to do late unserialization via a QueryInterface // returns - // E_NOINTERFACE: implies that this interface can // never be supported here(even if GetClass // returns a valid instance). // Implication is that once a class is // signalled in the activation stream to // not be marshalled by setting its size // to zero, it can never be QI'd again. // E_FAIL: implies that this interface was not // part of the serialized packet(but could // be supported if GetClass succeeds). //----------------------------------------------------------------------- inline HRESULT ActivationProperties::UnSerializeCallBack(REFCLSID clsid, SerializableProperty **ppSer) { HRESULT hr; SerializableProperty *pClass = NULL; BOOL pClassUsed = FALSE; Win4Assert(_unSerialized!=0); //------------------------------------------------------------------- // Position past header //------------------------------------------------------------------- DWORD pos = _unSerHeader.headerSize; CLSID realclsid; //------------------------------------------------------------------- // Check to see if class supported at all //------------------------------------------------------------------- BOOL bZeroSizeOk; if ((hr = GetClass(clsid, &pClass, FALSE, &bZeroSizeOk))==S_OK) pClass->GetCLSID(&realclsid); else return hr; hr = E_FAIL; for (DWORD i=0; i<_unSerHeader.cIfs; i++) { //--------------------------------------------------------------- // Check if contained objects match requested class ID // If so then it may or may not be unserialized. //--------------------------------------------------------------- if (IsEqualIID(realclsid,_unSerHeader.pclsid[i])) { RpcTryExcept { //------------------------------------------------------- // If size is zero for a matched object then it is an // interface that is no longer supported unless we // are told otherwise //------------------------------------------------------- if ((!_unSerHeader.pSizes[i]) && (!bZeroSizeOk)) { hr = E_NOINTERFACE; break; } //------------------------------------------------------- // Set position for serializer for unserializing //------------------------------------------------------- hr = S_OK; hr = _pUnSer->SetPosition(pos); if (FAILED(hr)) { break; } //------------------------------------------------------- // If unserializing add it to our collection and make it // a child and return found object. //------------------------------------------------------- if (serializableIfsCollection[i] == NULL) { SetSerializableIfs(i, pClass); pClassUsed = TRUE; if (FAILED(hr = pClass->UnSerialize(_pUnSer))) { serializableIfsCollection[i] = NULL; pClass->SetParent(NULL); pClassUsed = FALSE; } } else { hr = serializableIfsCollection[i]->UnSerialize(_pUnSer); } if (ppSer) *ppSer = serializableIfsCollection[i]; } RpcExcept(TRUE) { hr = HRESULT_FROM_WIN32(RpcExceptionCode()); } RpcEndExcept // // E_FAIL is not considered catastrophic by caller // But this is a catastrophic condition since we could // not unserialize. // if (hr == E_FAIL) hr = E_UNEXPECTED; break; } //--------------------------------------------------------------- // Increment position for next one //--------------------------------------------------------------- pos +=_unSerHeader.pSizes[i]; } if (pClass != NULL && !pClassUsed) { ReturnClass (clsid, pClass); } return hr; } //----------------------------------------------------------------------- // Do things required to make a child //----------------------------------------------------------------------- inline void ActivationProperties::SetSerializableIfs(DWORD index, SerializableProperty *pSer) { serializableIfsCollection[index]= pSer; pSer->SetParent((ISerializableParent*) this); pSer->Added(); } //----------------------------------------------------------------------- // Add a serializiable object to the collection //----------------------------------------------------------------------- inline void ActivationProperties::AddSerializableIfs(SerializableProperty *pSer) { if (pSer->IsAdded()) return; Win4Assert(_ifsIndex < MAX_ACTARRAY_SIZE); SetSerializableIfs(_ifsIndex, pSer); _ifsIndex++; } //--------------------------------------------------------------------------- // Methods for ActivationPropertiesIn //--------------------------------------------------------------------------- ActivationPropertiesIn::ActivationPropertiesIn() { _customIndex = 0; _cCustomAct = 0; _actCLSID=CLSID_ActivationPropertiesIn; _refCount = 1; _pinst = NULL; _pPersist = NULL; _pContextInfo = NULL; _pServerLocationInfo = NULL; _pSecurityInfo = NULL; _pSpecialProperties = NULL; _pClassInfo = NULL; _customActList = NULL; _delegated = FALSE; _actOut.SetNotDelete(); _pDip = NULL; _clientToken = NULL; _fComplusOnly = FALSE; _fUseSystemIdentity = FALSE; _dwInitialContext = 0; } ActivationPropertiesIn::~ActivationPropertiesIn() { if (_pClassInfo) { _pClassInfo->Unlock(); _pClassInfo->Release(); } } //----------------------------------------------------------------------- // Methods from IUnknown //----------------------------------------------------------------------- STDMETHODIMP ActivationPropertiesIn::QueryInterface( REFIID riid, LPVOID* ppv) { // USE CLSID_ActivationPropertiesIn to get at the real object // Note that this is a hidden contract to be used by COM only and // the object is not AddRef'd as an optimization if (IsEqualIID(riid, CLSID_ActivationPropertiesIn)) { *ppv = (ActivationPropertiesIn*)this; return S_OK; } else if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IActivationPropertiesIn)) *ppv = (IActivationPropertiesIn*)this; else if (IsEqualIID(riid, IID_IPrivActivationPropertiesIn)) *ppv = (IPrivActivationPropertiesIn*)this; else if (IsEqualIID(riid, IID_IInitActivationPropertiesIn)) *ppv = (IInitActivationPropertiesIn*)this; else if (IsEqualIID(riid, IID_IActivationStageInfo)) *ppv = (IActivationStageInfo*)this; else *ppv = NULL; if (*ppv != NULL) { AddRef(); return S_OK; } return ActivationProperties::QueryInterface(riid, ppv); } ULONG ActivationPropertiesIn::AddRef(void) { return ActivationProperties::AddRef(); } ULONG ActivationPropertiesIn::Release(void) { ULONG ret=ActivationProperties::Release(); if (ret==0) { if (_toDelete) delete this; else if (_fDestruct) this->ActivationPropertiesIn::~ActivationPropertiesIn(); } return ret; } //--------------------------------------------------------------------------- // Methods from IInitActivationPropertiesIn //--------------------------------------------------------------------------- STDMETHODIMP ActivationPropertiesIn::SetClsctx (DWORD dwClsCtx) { if (dwClsCtx && _pClassInfo) { DWORD dwAcceptableClsCtx; //Note: hack for VB since it cannot specify CLSCTX_REMOTE_SERVER if (dwClsCtx & CLSCTX_LOCAL_SERVER) dwClsCtx |= CLSCTX_REMOTE_SERVER; // Before we filter the specified class context by the class // info, we remember the original class context. if (_dwInitialContext == 0) _dwInitialContext = dwClsCtx; // Here we figure out the desired ClsCtx // by anding the one in the catalog with the // one requested by the user. // If the GetClassContext() // returns an error, we just go ahead and // use the one the user passed. HRESULT hr = _pClassInfo->GetClassContext( (CLSCTX) dwClsCtx, (CLSCTX*) &dwAcceptableClsCtx); // REVIEW: Continue if Get fails? if (SUCCEEDED(hr)) { dwClsCtx &= (dwAcceptableClsCtx | (CLSCTX_PS_DLL | CLSCTX_LOCAL_SERVER)); #ifdef WX86OLE // The code above filters the acceptable context bits found // with those supplied by the caller. The x86 context bits // might have been found and should be allowed. For example // INPROC_SERVER might have been set and an x86 server found, // which is valid. if ( dwAcceptableClsCtx & CLSCTX_INPROC_SERVERX86 ) { dwClsCtx |= CLSCTX_INPROC_SERVERX86; } if ( dwAcceptableClsCtx & CLSCTX_INPROC_HANDLERX86 ) { dwClsCtx |= CLSCTX_INPROC_HANDLERX86; } #endif } } return GetInstantiationInfo()->SetClsctx(dwClsCtx); } STDMETHODIMP ActivationPropertiesIn::SetActivationFlags (IN DWORD actvflags) { return GetInstantiationInfo()->SetActivationFlags(actvflags); // The following code was the original implementation by CBiks. // This code is no longer executes because we delegate above. // /* HRESULT hr; hr = GetPropertyInfo(IID_IInstantiationInfo, (void**) &_pinst); if (SUCCEEDED(hr)) { Win4Assert(_pinst != NULL); hr = _pinst->SetActivationFlags(actvflags); } return hr; */ } STDMETHODIMP ActivationPropertiesIn::SetClassInfo (IUnknown* pUnkClassInfo) { if (_pClassInfo) { _pClassInfo->Unlock(); _pClassInfo->Release(); _pClassInfo = NULL; } // useful and tests minimal usefulness of the object given HRESULT hr = pUnkClassInfo->QueryInterface(IID_IComClassInfo,(LPVOID*)&_pClassInfo); CLSID *pclsid; if (FAILED(hr)) return hr; _pClassInfo->Lock(); hr = _pClassInfo->GetConfiguredClsid(&pclsid); GetInstantiationInfo()->SetClsid(*pclsid); if (SUCCEEDED(hr) && _dwInitialContext) { // Somebody has specifically set the class // context on this actprops, but has now changed // the IComClassInfo. We need to change our // filtered CLSCTX to match the new ClassInfo. hr = SetClsctx(_dwInitialContext); } return hr; } STDMETHODIMP ActivationPropertiesIn::SetContextInfo ( IContext* pClientContext, IContext* pPrototypeContext) { HRESULT hr; ContextInfo *pactctx= GetContextInfo(); Win4Assert(pactctx != NULL); hr = pactctx->SetClientContext(pClientContext); if (hr != S_OK) return hr; hr = pactctx->SetPrototypeContext(pPrototypeContext); return hr; } STDMETHODIMP ActivationPropertiesIn::SetConstructFromStorage (IStorage* pStorage) { HRESULT hr; GetPersistInfo(); Win4Assert(_pPersist != NULL); // This is an optimization for inproc marshalling. We know // that the storage pointer is the only one that requires // inproc serialization in the ActivationPropertiesIn object. _fInprocSerializationRequired = TRUE; return _pPersist->SetStorage(pStorage); } STDMETHODIMP ActivationPropertiesIn::SetConstructFromFile (WCHAR* wszFileName, DWORD dwMode) { HRESULT hr; GetPersistInfo(); Win4Assert(_pPersist != NULL); return _pPersist->SetFile(wszFileName, dwMode); } //--------------------------------------------------------------------------- // Methods for IActivationPropertiesIn //--------------------------------------------------------------------------- STDMETHODIMP ActivationPropertiesIn::GetClsctx(OUT DWORD *pdwClsctx) { return GetInstantiationInfo()->GetClsctx(pdwClsctx); } STDMETHODIMP ActivationPropertiesIn::AddRequestedIIDs(IN DWORD cIfs, IN IID *pIID) { return GetInstantiationInfo()->AddRequestedIIDs(cIfs, pIID); } STDMETHODIMP ActivationPropertiesIn::GetRequestedIIDs(OUT DWORD *pcIfs, OUT IID **ppIID) { return GetInstantiationInfo()->GetRequestedIIDs(pcIfs, ppIID); } STDMETHODIMP ActivationPropertiesIn::GetActivationID(OUT GUID *pActivationID) { *pActivationID = GUID_NULL; // currently unused and not supported return E_NOTIMPL; } STDMETHODIMP ActivationPropertiesIn::GetActivationFlags(OUT DWORD *pactvflags) { return GetInstantiationInfo()->GetActivationFlags(pactvflags); // The following code was the original implementation by CBiks. // This code is no longer executes because we delegate above. // /* HRESULT hr; hr = GetPropertyInfo(IID_IInstantiationInfo, (void**) &_pinst); if (SUCCEEDED(hr)) { Win4Assert(_pinst != NULL); return _pinst->GetActivationFlags(pactvflags); } return hr; */ } //----------------------------------------------------------------------- // The Following 3 routines should be called at the tail end of the // activation path to get activation properties for return // Only the first one is meant to be pubicly used //----------------------------------------------------------------------- STDMETHODIMP ActivationPropertiesIn::GetReturnActivationProperties( IN IUnknown *pobj, OUT IActivationPropertiesOut **ppActOut) { HRESULT hr; *ppActOut = NULL; //------------------------------------------------------------------- // If no punk then don't return an out object //------------------------------------------------------------------- if (!pobj) { return E_FAIL; } if (_unSerialized) hr = GetPropertyInfo(IID_IInstantiationInfo, (void**) &_pinst); Win4Assert(_pinst != NULL); CLSID clsid; hr = _pinst->GetClsid(&clsid); Win4Assert(hr == S_OK); //------------------------------------------------------------------- // Create Return Object //------------------------------------------------------------------- ActivationPropertiesOut *pout; if (!_unSerialized && !_toDelete && !IsBrokenRefCount(&clsid)) { _actOut.Initialize(); pout = &_actOut; } else { pout = new ActivationPropertiesOut(IsBrokenRefCount(&clsid)); if (pout==NULL) return E_OUTOFMEMORY; } //------------------------------------------------------------------- // Set the marshal and dest context flags for marshalling returns //------------------------------------------------------------------- pout->SetMarshalFlags(_marshalFlags); pout->SetDestCtx(_serHeader.destCtx); //------------------------------------------------------------------- // Check to see if we are handling a persistent instance // NOTE: cannot call GetPeristInfo because we need to QI to // so that this will only cause this interface to exist // if it was ever added to the properties object //------------------------------------------------------------------- if (_unSerialized) hr = GetPropertyInfo(IID_IInstanceInfo, (void**) &_pPersist); if (_pPersist) { hr = LoadPersistentObject(pobj, _pPersist); if (FAILED(hr)) { pout->Release(); return hr; } } //------------------------------------------------------------------- // Set COMVERSION of client for marshalling //------------------------------------------------------------------- Win4Assert(_pinst != NULL); COMVERSION *pVersion; GetInstantiationInfo()->GetClientCOMVersion(&pVersion); pout->SetClientCOMVersion(*pVersion); //------------------------------------------------------------------- // Get IIDs requested and set them for return //------------------------------------------------------------------- DWORD cifs; IID *pIID; hr = _pinst->GetRequestedIIDs(&cifs, &pIID); Win4Assert(hr==S_OK); hr = pout->SetObjectInterfaces(cifs, pIID, pobj); *ppActOut = pout; CleanupLocalState(); return hr; } STDMETHODIMP ActivationPropertiesIn::PrivGetReturnActivationProperties( OUT IPrivActivationPropertiesOut **ppActOut) { //------------------------------------------------------------------- // Create Return Object //------------------------------------------------------------------- ActivationPropertiesOut *pout = new ActivationPropertiesOut(FALSE /* fBrokenRefCount */ ); if (pout==NULL) return E_OUTOFMEMORY; //------------------------------------------------------------------- // Set the marshal and dest context flags for marshalling returns //------------------------------------------------------------------- pout->SetMarshalFlags(_marshalFlags); pout->SetDestCtx(_serHeader.destCtx); *ppActOut = (IPrivActivationPropertiesOut*) pout; CleanupLocalState(); return S_OK; } STDMETHODIMP ActivationPropertiesIn::GetReturnActivationProperties( ActivationPropertiesOut **ppActOut) { //------------------------------------------------------------------- // Create Return Object //------------------------------------------------------------------- *ppActOut = new ActivationPropertiesOut(FALSE /* fBrokenRefCount */ ); if (*ppActOut==NULL) return E_OUTOFMEMORY; //------------------------------------------------------------------- // Set the marshal and dest context flags for marshalling returns //------------------------------------------------------------------- (*ppActOut)->SetMarshalFlags(_marshalFlags); (*ppActOut)->SetDestCtx(_serHeader.destCtx); CleanupLocalState(); return S_OK; } //----------------------------------------------------------------------- // Following two routines are used delegate through a chain of custom // activators. When the chain is exhausted, the COM activator for the // current stage is invoked. //----------------------------------------------------------------------- STDMETHODIMP ActivationPropertiesIn::DelegateGetClassObject( OUT IActivationPropertiesOut **pActPropsOut) { Win4Assert(_customIndex <= _cCustomAct && (LONG) _customIndex >= 0); _delegated=TRUE; if ((_cCustomAct == 0) || (_customIndex == _cCustomAct)) { ISystemActivator *pComAct = GetComActivatorForStage(_stage); return pComAct->GetClassObject(this, pActPropsOut); } _customIndex++; // Sajia - Support for partitions. // a) See if the activator supports IReplaceClassInfo // b) If yes, this is the partition activator.Delegate to it. // If the partition activator switches the classinfo, // it returns ERROR_RETRY. It will not delegate in this case. // Otherwise, it simply delegates down the chain. // c) If it returns ERROR_RETRY, call IReplaceClassInfo->GetClassInfo(). // Switch our class info and return ERROR_RETRY so our caller // knows to restart the activation chain. // IReplaceClassInfo *pReplaceClassInfo = NULL; HRESULT hr = _customActList[_customIndex-1]->QueryInterface(IID_IReplaceClassInfo, (void**)&pReplaceClassInfo); if (SUCCEEDED(hr)) { Win4Assert(pReplaceClassInfo && "QI Error"); // Assert that the partition activator is supported only // in the SCM and Server Process stage and must be the // first activator in the stage. Win4Assert((_customIndex == 1) && (_stage == SERVER_MACHINE_STAGE || _stage == SERVER_PROCESS_STAGE || _stage == CLIENT_CONTEXT_STAGE)); hr = _customActList[_customIndex-1]->GetClassObject(this, pActPropsOut); if (ERROR_RETRY == hr) { CLSID clsid; IUnknown *pClassInfo; hr = GetClsid(&clsid); Win4Assert(SUCCEEDED(hr)); if (SUCCEEDED(hr)) { hr = pReplaceClassInfo->GetClassInfo(clsid, IID_IUnknown, (void**)&pClassInfo); Win4Assert(SUCCEEDED(hr)); if (SUCCEEDED(hr)) { hr = SetClassInfo(pClassInfo); Win4Assert(SUCCEEDED(hr)); pClassInfo->Release(); if (SUCCEEDED(hr)) { hr = ERROR_RETRY; } } } } pReplaceClassInfo->Release(); return hr; } else return _customActList[_customIndex-1]->GetClassObject(this, pActPropsOut); } STDMETHODIMP ActivationPropertiesIn::DelegateCreateInstance( IN IUnknown *pUnkOuter, OUT IActivationPropertiesOut **ppActPropsOut) { Win4Assert(_customIndex <= _cCustomAct && (LONG) _customIndex >= 0); _delegated=TRUE; if ((_cCustomAct == 0) || (_customIndex == _cCustomAct)) { ISystemActivator *pComAct = GetComActivatorForStage(_stage); return pComAct->CreateInstance(pUnkOuter, this, ppActPropsOut); } _customIndex++; // Sajia - Support for partitions. // a) See if the activator supports IReplaceClassInfo // b) If yes, this is the partition activator.Delegate to it. // If the partition activator switches the classinfo, // it returns ERROR_RETRY. It will not delegate in this case. // Otherwise, it simply delegates down the chain. // c) If it returns ERROR_RETRY, call IReplaceClassInfo->GetClassInfo(). // Switch our class info and return ERROR_RETRY so our caller // knows to restart the activation chain. // IReplaceClassInfo *pReplaceClassInfo = NULL; HRESULT hr = _customActList[_customIndex-1]->QueryInterface(IID_IReplaceClassInfo, (void**)&pReplaceClassInfo); if (SUCCEEDED(hr)) { Win4Assert(pReplaceClassInfo && "QI Error"); // Assert that the partition activator is supported only // in the SCM and Server Process stage and must be the // first activator in the stage. Win4Assert((_customIndex == 1) && (_stage == SERVER_MACHINE_STAGE || _stage == SERVER_PROCESS_STAGE || _stage == CLIENT_CONTEXT_STAGE)); hr = _customActList[_customIndex-1]->CreateInstance(pUnkOuter, this, ppActPropsOut); if (ERROR_RETRY == hr) { CLSID clsid; IUnknown *pClassInfo; hr = GetClsid(&clsid); Win4Assert(SUCCEEDED(hr)); if (SUCCEEDED(hr)) { hr = pReplaceClassInfo->GetClassInfo(clsid, IID_IUnknown, (void**)&pClassInfo); Win4Assert(SUCCEEDED(hr)); if (SUCCEEDED(hr)) { hr = SetClassInfo(pClassInfo); Win4Assert(SUCCEEDED(hr)); pClassInfo->Release(); if (SUCCEEDED(hr)) { hr = ERROR_RETRY; } } } } pReplaceClassInfo->Release(); return hr; } else return _customActList[_customIndex-1]->CreateInstance(pUnkOuter, this, ppActPropsOut); } //----------------------------------------------------------------------- // Note that this function could return a NULL Class Factory if an // intercepting custom activator returns an object. //----------------------------------------------------------------------- STDMETHODIMP ActivationPropertiesIn::DelegateCIAndGetCF( IN IUnknown *pUnkOuter, OUT IActivationPropertiesOut **ppActPropsOut, OUT IClassFactory **ppCF) { if (_stage != SERVER_CONTEXT_STAGE) return E_UNEXPECTED; HRESULT hr = DelegateCreateInstance(pUnkOuter, ppActPropsOut); if (FAILED(hr)) return hr; ActivationPropertiesOut *pActOut; hr = (*ppActPropsOut)->QueryInterface(CLSID_ActivationPropertiesOut, (void**) &pActOut); Win4Assert(SUCCEEDED(hr)); *ppCF = pActOut->GetCF(); return S_OK; } //----------------------------------------------------------------------- // Instantiate classes supported by this interfaces given an IID //----------------------------------------------------------------------- HRESULT ActivationPropertiesIn::GetClass(REFIID iid, SerializableProperty **ppSer, BOOL forQI, BOOL *pbZeroSizeOk) { if (pbZeroSizeOk) *pbZeroSizeOk = FALSE; if ((iid == IID_IActivationSecurityInfo) || (iid == IID_ILegacyInfo)) *ppSer = &_securityInfo; else if (iid == IID_IServerLocationInfo) *ppSer = &_serverLocationInfo; else if (iid == IID_IInstantiationInfo) *ppSer = &_instantiationInfo; else if (iid == IID_IActivationContextInfo || iid == IID_IPrivActivationContextInfo) *ppSer = &_contextInfo; else if ((!(_delegated && forQI)) && (iid == IID_IInstanceInfo)) *ppSer = &_instanceInfo; else if (iid == IID_IScmRequestInfo) *ppSer = &_scmRequestInfo; else if (iid == IID_ISpecialSystemProperties) { *ppSer = &_specialProperties; } else if (iid == IID_IOpaqueDataInfo) { *ppSer = new OpaqueDataInfo(); if (pbZeroSizeOk) *pbZeroSizeOk = TRUE; } else return E_NOINTERFACE; return S_OK; } HRESULT ActivationProperties::ReturnClass(REFIID iid, SerializableProperty *pSer) { if (iid == IID_IOpaqueDataInfo) { delete (OpaqueDataInfo*) pSer; return S_OK; } return S_FALSE; } //--------------------------------------------------------------------------- // Methods from IActivationStageInfo //--------------------------------------------------------------------------- STDMETHODIMP ActivationPropertiesIn::SetStageAndIndex(ACTIVATION_STAGE stage, int index) { _stage = stage; _customIndex = index; _cCustomAct = 0; _customActList = NULL; HRESULT hr = E_UNEXPECTED; // JSimmons -- 6/30/99 added this assert: Win4Assert(_pClassInfo && "SetStageAndIndex called and _pClassInfo is not set"); if (_pClassInfo) { hr = _pClassInfo->GetCustomActivatorCount(stage,&_cCustomAct); if (SUCCEEDED (hr) && _cCustomAct) { hr = _pClassInfo->GetCustomActivators(stage,&_customActList); if (FAILED (hr)) { _cCustomAct = 0; _customActList = NULL; } } } return hr; } STDMETHODIMP ActivationPropertiesIn::UnmarshalInterface(IStream *pStm,REFIID riid,void **ppv) { HRESULT hr = ActivationProperties::UnmarshalInterface(pStm, riid,ppv); if (hr != S_OK) return hr; CLSID clsid; GetInstantiationInfo()->GetClsid(&clsid); hr = GetClassInfoFromClsid(clsid, &_pClassInfo); if ((hr == S_OK) && _pClassInfo) { _pClassInfo->Lock(); } _delegated=TRUE; //assume unmarshalling imples that delegation happened return hr; } //--------------------------------------------------------------------------- // Methods for ActivationPropertiesOut //--------------------------------------------------------------------------- ActivationPropertiesOut::ActivationPropertiesOut(BOOL fBrokenRefCount) : _outSer(fBrokenRefCount) { _pOutSer=0; _refCount = 1; _actCLSID=CLSID_ActivationPropertiesOut; _fBrokenRefCount = fBrokenRefCount; _fInprocSerializationRequired = TRUE; } ActivationPropertiesOut::~ActivationPropertiesOut() { } //--------------------------------------------------------------------------- // Methods for IUnknown //--------------------------------------------------------------------------- STDMETHODIMP ActivationPropertiesOut::QueryInterface( REFIID riid, LPVOID* ppv) { // USE CLSID_ActivationPropertiesOut to get at the real object // Note that this is a hidden contract to be used by COM only and // the object is not AddRef'd as an optimization if (IsEqualIID(riid, CLSID_ActivationPropertiesOut)) { *ppv = (ActivationPropertiesOut*)this; return S_OK; } else if (IsEqualIID(riid, IID_IUnknown)) *ppv = (IActivationPropertiesOut*)this; else if (IsEqualIID(riid, IID_IPrivActivationPropertiesOut)) *ppv = (IPrivActivationPropertiesOut*)this; else if (IsEqualIID(riid, IID_IActivationPropertiesOut)) *ppv = (IActivationPropertiesOut*)this; else *ppv = NULL; if (*ppv != NULL) { AddRef(); return S_OK; } return ActivationProperties::QueryInterface(riid, ppv); } ULONG ActivationPropertiesOut::AddRef(void) { return ActivationProperties::AddRef(); } ULONG ActivationPropertiesOut::Release(void) { ULONG ret=ActivationProperties::Release(); if (ret==0) { if (_toDelete) delete this; else if (_fDestruct) this->ActivationPropertiesOut::~ActivationPropertiesOut(); } return ret; } STDMETHODIMP ActivationPropertiesOut::GetActivationID(OUT GUID *pActivationID) { *pActivationID = GUID_NULL; // currently unused and not supported return E_NOTIMPL; } //----------------------------------------------------------------------- // Set Marshalled interface data that are results of activation //----------------------------------------------------------------------- STDMETHODIMP ActivationPropertiesOut::SetMarshalledResults( IN DWORD cIfs, IN IID *pIID, IN HRESULT *pHr, IN MInterfacePointer **ppIntfData) { if (!_pOutSer) { _pOutSer = &_outSer; AddSerializableIfs((SerializableProperty*) _pOutSer); } _pOutSer->_info.cIfs = cIfs; // // Allocate new storage and copy parameters // _pOutSer->_info.piid = (IID*) ActMemAlloc(sizeof(IID)*cIfs); if (_pOutSer->_info.piid == NULL) { _pOutSer->_info.cIfs=0; return E_OUTOFMEMORY; } _pOutSer->_info.ppIntfData = (MInterfacePointer**) ActMemAlloc(sizeof(MInterfacePointer*)*cIfs); if (_pOutSer->_info.ppIntfData == NULL) { _pOutSer->_info.cIfs=0; ActMemFree(_pOutSer->_info.piid); _pOutSer->_info.piid = NULL; return E_OUTOFMEMORY; } _pOutSer->_info.phresults = (HRESULT*) ActMemAlloc(sizeof(HRESULT)*cIfs); if (_pOutSer->_info.phresults == NULL) { _pOutSer->_info.cIfs=0; ActMemFree(_pOutSer->_info.piid); _pOutSer->_info.piid = NULL; ActMemFree(_pOutSer->_info.ppIntfData); _pOutSer->_info.ppIntfData = NULL; return E_OUTOFMEMORY; } for (DWORD i=0; i< cIfs; i++) { _pOutSer->_info.piid[i] = pIID[i]; if (ppIntfData[i]) { // // Use stream cloning to copy marshalled stuff // ActivationStream strm((InterfaceData*) ppIntfData[i]); ActivationStream *newStrm; newStrm = strm.Clone(); if (newStrm == NULL) { _pOutSer->_info.cIfs=0; ActMemFree(_pOutSer->_info.piid); _pOutSer->_info.piid = NULL; ActMemFree(_pOutSer->_info.ppIntfData); _pOutSer->_info.ppIntfData = NULL; ActMemFree(_pOutSer->_info.phresults); _pOutSer->_info.phresults = NULL; return E_OUTOFMEMORY; } newStrm->AssignSerializedInterface( (InterfaceData**)&_pOutSer->_info.ppIntfData[i]); newStrm->Release(); } else _pOutSer->_info.ppIntfData[i] = NULL; _pOutSer->_info.phresults[i] = pHr[i]; } return S_OK; } //----------------------------------------------------------------------- // Get results of activation in marshalled form //----------------------------------------------------------------------- STDMETHODIMP ActivationPropertiesOut::GetMarshalledResults(OUT DWORD *pcIfs, OUT IID **ppIID, OUT HRESULT **ppHr, OUT MInterfacePointer ***pppIntfData) { HRESULT hr; //------------------------------------------------------------------- // If not unserialized we have to unserialize appropriately //------------------------------------------------------------------- if ((!_pOutSer) && (_unSerialized)) { if (!SUCCEEDED(hr = UnSerializeCallBack(CLSID_ActivationPropertiesOut, (SerializableProperty**)&_pOutSer))) return hr; } Win4Assert(_pOutSer != NULL); //------------------------------------------------------------------- // If user passed holders, copy into them otherwise allocate //------------------------------------------------------------------- //------------------------------------------------------------------- // First do IIDs //------------------------------------------------------------------- *pcIfs = _pOutSer->_info.cIfs; DWORD i; if (*ppIID == NULL) *ppIID = _pOutSer->_info.piid; else { IID *pIID = *ppIID; for (i=0;i<_pOutSer->_info.cIfs;i++) pIID[i] = _pOutSer->_info.piid[i]; } //------------------------------------------------------------------- // Do Marshalled results //------------------------------------------------------------------- if (*pppIntfData == NULL) *pppIntfData = _pOutSer->_info.ppIntfData; else { MInterfacePointer **ppIntfData = *pppIntfData; for (i=0;i<_pOutSer->_info.cIfs;i++) { ActivationStream strm((InterfaceData*)_pOutSer->_info.ppIntfData[i]); ActivationStream *newStrm; newStrm = strm.Clone(); if (newStrm==NULL) return E_OUTOFMEMORY; newStrm->AssignSerializedInterface((InterfaceData**)&ppIntfData[i]); newStrm->Release(); } } //------------------------------------------------------------------- // Set error codes and return appropriate one as result // Call suceeds if at least one interface exists //------------------------------------------------------------------- HRESULT rethr = E_NOINTERFACE; if (*ppHr == NULL) { *ppHr = _pOutSer->_info.phresults; for (i=0;i<_pOutSer->_info.cIfs;i++) if (_pOutSer->_info.phresults[i] == S_OK) { rethr = S_OK; break; } } else { HRESULT *phr = *ppHr; for (i=0;i<_pOutSer->_info.cIfs;i++) { phr[i] = _pOutSer->_info.phresults[i]; if (phr[i] == S_OK) rethr = S_OK; } } return rethr; } //----------------------------------------------------------------------- // Set results of activation //----------------------------------------------------------------------- STDMETHODIMP ActivationPropertiesOut::SetObjectInterfaces( IN DWORD cIfs, IN IID *pIID, IN IUnknown *pUnk) { if (!cIfs) return E_FAIL; if (!_pOutSer) { _pOutSer = &_outSer; _pOutSer->_pClientCOMVersion = &_clientCOMVersion; AddSerializableIfs((SerializableProperty*) _pOutSer); } _pOutSer->_info.cIfs = cIfs; if (cIfs > MAX_ACTARRAY_SIZE) { _pOutSer->_info.piid = (IID*) ActMemAlloc(sizeof(IID)*cIfs); if (_pOutSer->_info.piid == NULL) return E_OUTOFMEMORY; } else _pOutSer->_info.piid = _pOutSer->_pIIDs; for (DWORD i=0; i< cIfs; i++) _pOutSer->_info.piid[i] = pIID[i]; _pOutSer->_pUnk = pUnk; if (!_fBrokenRefCount) { pUnk->AddRef(); } _pOutSer->_info.phresults = NULL; return S_OK; } //----------------------------------------------------------------------- // Get results of activation //----------------------------------------------------------------------- STDMETHODIMP ActivationPropertiesOut::GetObjectInterface( IN REFIID riid, IN DWORD actvflags, OUT void **ppv) { //------------------------------------------------------------------- // If not unserialized we have to unserialize appropriately //------------------------------------------------------------------- if (!_pOutSer) { if (_unSerialized) { HRESULT rethr; rethr = UnSerializeCallBack(CLSID_ActivationPropertiesOut, (SerializableProperty**)&_pOutSer); if (FAILED(rethr)) return rethr; } else return E_UNEXPECTED; // We must have a _pOutSer } Win4Assert(_pOutSer); IUnknown *punk = NULL; *ppv = NULL; BOOL fCountedPunk = FALSE; // Indicates whether we hold a reference // to punk and must release it. if (!_pOutSer->_ppvObj) { Win4Assert(_pOutSer->_pUnk!=NULL); punk = _pOutSer->_pUnk; } else for (DWORD i=0; i<_pOutSer->_info.cIfs; i++) { if (IsEqualIID(riid, _pOutSer->_info.piid[i])) { _pOutSer->UnmarshalAtIndex(i); if (_pOutSer->_info.phresults[i] == S_OK) { _fInprocSerializationRequired = TRUE; punk = (IUnknown*) _pOutSer->_ppvObj[i]; *ppv = punk; punk->AddRef(); return S_OK; } } } if (!punk) { if (!IsEqualIID(IID_IUnknown, riid)) { // If we get a punk back here, it will be counted, so we // must release it. HRESULT hr = GetObjectInterface(IID_IUnknown, NULL, (void**) &punk); if (FAILED(hr)) punk = NULL; else fCountedPunk = TRUE; } else for (DWORD i=0; i<_pOutSer->_info.cIfs; i++) { _pOutSer->UnmarshalAtIndex(i); if (_pOutSer->_info.phresults[i] == S_OK) { _fInprocSerializationRequired = TRUE; punk = (IUnknown*) _pOutSer->_ppvObj[i]; } } } if (punk) { // If we're being called by x86 code and the IP is x86 then set the // OleStubInvoked flag to allow MapIFacePtr() to thunk unknown IP // return values as -1 because we're just returning this to x86 // code anyway. #ifdef WX86OLE if ( (actvflags & ACTVFLAGS_WX86_CALLER) && gcwx86.IsN2XProxy(punk) ) { gcwx86.SetStubInvokeFlag((UCHAR)-1); } #endif HRESULT hr = punk->QueryInterface(riid, ppv); // If we hold a reference on the punk, release it. if (fCountedPunk) punk->Release(); return hr; } else return E_NOINTERFACE; } //----------------------------------------------------------------------- // Get results of activation //----------------------------------------------------------------------- STDMETHODIMP ActivationPropertiesOut::GetObjectInterfaces( IN DWORD cIfs, IN DWORD actvflags, IN MULTI_QI *pMultiQi) { HRESULT rethr; //------------------------------------------------------------------- // If not unserialized we have to unserialize appropriately //------------------------------------------------------------------- if (!_pOutSer) { if (_unSerialized) { rethr = UnSerializeCallBack(CLSID_ActivationPropertiesOut, (SerializableProperty**)&_pOutSer); if (FAILED(rethr)) return rethr; } else return E_UNEXPECTED; // We must have a _pOutSer } Win4Assert(_pOutSer); rethr = E_NOINTERFACE; //------------------------------------------------------------------- // Either Interfaces already unmarshalled or marshalling never // took place. // Set error codes and return appropriate one as result //------------------------------------------------------------------- for (DWORD i=0; i_ppvObj) { Win4Assert(_pOutSer->_pUnk!=NULL); if (_fBrokenRefCount && (i == 0)) { pMultiQi[i].pItf = _pOutSer->_pUnk; pMultiQi[i].hr = S_OK; } else { #ifdef WX86OLE // If we're being called by x86 code and the IP is x86 thenset the // OleStubInvoked flag to allow MapIFacePtr() to thunk unknown IP // return values as -1 because we're just returning this tox86 // code anyway. if ( (actvflags & ACTVFLAGS_WX86_CALLER) && gcwx86.IsN2XProxy(_pOutSer->_pUnk) ) { gcwx86.SetStubInvokeFlag((UCHAR)-1); } #endif pMultiQi[i].hr = _pOutSer->_pUnk->QueryInterface(*pMultiQi[i].pIID, (void**) &pMultiQi[i].pItf); } } else //--------------------------------------------------------------- // If IIDs don't match then we're inefficient(order n-square) // anyway so call to get a single interface. //--------------------------------------------------------------- if ((_pOutSer->_info.piid[i] != *pMultiQi[i].pIID)|| (_pOutSer->_info.ppIntfData[i] == NULL)) { pMultiQi[i].hr = GetObjectInterface(*pMultiQi[i].pIID, actvflags, (void**)&pMultiQi[i].pItf); } else //--------------------------------------------------------------- // Common case where we are returning originally requested // IIDs after unmarshalling. //--------------------------------------------------------------- { Win4Assert(!_fBrokenRefCount); Win4Assert(_outSer._info.ppIntfData != NULL); _pOutSer->UnmarshalAtIndex(i); _fInprocSerializationRequired = TRUE; pMultiQi[i].pItf = (IUnknown*) _pOutSer->_ppvObj[i]; pMultiQi[i].hr = _pOutSer->_info.phresults[i]; if (pMultiQi[i].hr == S_OK) ((IUnknown*)_pOutSer->_ppvObj[i])->AddRef(); } //--------------------------------------------------------------- // Call suceeds if at least one interface exists //--------------------------------------------------------------- if (rethr != S_OK) rethr = pMultiQi[i].hr; } return rethr; } //----------------------------------------------------------------------- // Removes requested IIDs: to be used by custom activators // REVIEW: Longer term, having a refcount on the IIDs may make code // more readable and could be more efficient all round. // However, since this method can add on to existing scheme // without change we will punt refcounting IIDs for now. // However, also issue of Marshalling n-times at source vs // marshalling once at source and n-1 times in b/w should be // considered as a tradeoff. // Also if something is unmarshallable in an intermediate // stage but activation does'nt fail, all is not lost. //----------------------------------------------------------------------- STDMETHODIMP ActivationPropertiesOut::RemoveRequestedIIDs( IN DWORD cIfs, IN IID *pIID) { //------------------------------------------------------------------- // If not unserialized we have to unserialize appropriately //------------------------------------------------------------------- if (!_pOutSer) { if (!_unSerialized) return E_INVALIDARG; if (UnSerializeCallBack(CLSID_ActivationPropertiesOut, (SerializableProperty**)&_pOutSer)!= S_OK) return E_FAIL; Win4Assert(_pOutSer != NULL); } // //Assume that we never remove originally requested ones // if ((cIfs > _pOutSer->_info.cIfs) || (cIfs == 0)) return E_INVALIDARG; LONG i,j; DWORD dec = 0; // //First try to do it efficiently assuming //that we always added to end // for (i=_pOutSer->_info.cIfs-1; i>=0 && cIfs; i--) { if (_pOutSer->_info.piid[i]==pIID[cIfs-1]) { // //If we still have interface data then make sure //that we give to duplicate entry if it exists and does'nt //have one. Otherwise free it // if (_pOutSer->_info.ppIntfData) { if (_pOutSer->_info.ppIntfData[i]) { for (j=0;j_info.piid[i]==_pOutSer->_info.piid[j]) && (_pOutSer->_info.ppIntfData[j] == NULL)) { _pOutSer->_info.ppIntfData[j] = _pOutSer->_info.ppIntfData[i]; _pOutSer->_info.ppIntfData[i] = NULL; _pOutSer->_info.phresults[j] = _pOutSer->_info.phresults[i]; Win4Assert(_pOutSer->_info.phresults[j]==S_OK); if (_pOutSer->_ppvObj && _pOutSer->_ppvObj[j]) { ((IUnknown*)_pOutSer->_ppvObj[j])->Release(); _pOutSer->_ppvObj[j] = NULL; } } } // If we did'nt give it away release it if (_pOutSer->_info.ppIntfData[i]) { ReleaseIFD(_pOutSer->_info.ppIntfData[i]); ActMemFree(_pOutSer->_info.ppIntfData[i]); _pOutSer->_info.ppIntfData[i] = NULL; } } else // Release Unmarshalled object if (_pOutSer->_ppvObj && _pOutSer->_ppvObj[i]) { ((IUnknown*)_pOutSer->_ppvObj[i])->Release(); _pOutSer->_ppvObj[i] = NULL; } } _pOutSer->_info.cIfs--; cIfs--; dec++; } else break; } // //Do inefficiently if we still have leftover IIDs // if (cIfs) { IID *newIIDs=NULL; MInterfacePointer **newIFD=NULL; void **newppv = NULL; HRESULT *newhr=NULL; BOOL *pFound = (BOOL*) ActMemAlloc(sizeof(BOOL) * cIfs); if (pFound == NULL) return E_OUTOFMEMORY; DWORD newLen = _pOutSer->_info.cIfs-cIfs; // // Allocate storage for new stuff // if (newLen) { newIIDs = (IID*) ActMemAlloc(sizeof(IID)*newLen); if (_marshalState == UNMARSHALLED) { newIFD = (MInterfacePointer**) ActMemAlloc(sizeof(MInterfacePointer*)* newLen); newppv = (void**) ActMemAlloc(sizeof(IUnknown*)*newLen); newhr = (HRESULT*) ActMemAlloc(sizeof(HRESULT)*newLen); if ((newIIDs==NULL) || (newppv==NULL) || (newIFD==NULL) || (newhr == NULL)) { ActMemFree(newppv); ActMemFree(newIIDs); ActMemFree(newIFD); ActMemFree(newhr); ActMemFree(pFound); return E_OUTOFMEMORY; } } } for (i=0;i<(LONG)cIfs;i++) pFound[i] = FALSE; DWORD newIndex=0; // // Loop trying to establish new arrays // for (i=0;i<(LONG)_pOutSer->_info.cIfs;i++) { BOOL found=FALSE; for (j=0;j<(LONG)cIfs;j++) if (!pFound[j]) { if (_pOutSer->_info.piid[i] == pIID[j]) { found = TRUE; pFound[j] = TRUE; if ((_marshalState == UNMARSHALLED) && (SUCCEEDED(_pOutSer->_info.phresults[i]))) { if (_pOutSer->_info.ppIntfData[i]) { ReleaseIFD(_pOutSer->_info.ppIntfData[i]); ActMemFree(_pOutSer->_info.ppIntfData[i]); _pOutSer->_info.ppIntfData[i] = NULL; } else if (_pOutSer->_ppvObj && _pOutSer->_ppvObj[i]) { ((IUnknown*)_pOutSer->_ppvObj[i])->Release(); _pOutSer->_ppvObj[i] = NULL; } } break; } } // If this was'nt part of passed in array we need to // keep it if ((!found) && newLen) { newIIDs[newIndex] = _pOutSer->_info.piid[i]; if (_marshalState == UNMARSHALLED) { newIFD[newIndex] = _pOutSer->_info.ppIntfData[i]; newppv[newIndex] = _pOutSer->_ppvObj[i]; newhr[newIndex] = _pOutSer->_info.phresults[i]; } newIndex++; } } #if 0 //Assume good behaviour since implementing //This failure case would require more changes //than necessary for a failure that should'nt happen for (i=0;i_info.cIfs += dec; // this will not work // unless we preserve // _ppvObj[k] till here return E_INVALIDARG; } #endif Win4Assert(newIndex == newLen); ActMemFree(pFound); // //Free old ones and set new ones // _pOutSer->_info.cIfs = newLen; if (_pOutSer->_info.piid != _pOutSer->_pIIDs) ActMemFree(_pOutSer->_info.piid); _pOutSer->_info.piid = newIIDs; if (_marshalState == UNMARSHALLED) { ActMemFree(_pOutSer->_info.ppIntfData); _pOutSer->_info.ppIntfData = newIFD; ActMemFree(_pOutSer->_ppvObj); _pOutSer->_ppvObj = newppv; ActMemFree(_pOutSer->_info.phresults); _pOutSer->_info.phresults = newhr; } } return S_OK; } //----------------------------------------------------------------------- // Get classes supported by this interfaces given an IID //----------------------------------------------------------------------- HRESULT ActivationPropertiesOut::GetClass(REFIID iid, SerializableProperty **ppSer, BOOL forQI, BOOL *pbZeroSizeOk) { if (pbZeroSizeOk) *pbZeroSizeOk = FALSE; if (iid == CLSID_ActivationPropertiesOut) *ppSer = &_outSer; else if (iid == IID_IScmReplyInfo) *ppSer = &_scmReplyInfo; else if (iid == IID_IOpaqueDataInfo) { *ppSer = new OpaqueDataInfo(); if (pbZeroSizeOk) *pbZeroSizeOk = TRUE; } else return E_NOINTERFACE; return S_OK; } //--------------------------------------------------------------------------- // Methods for ActivationPropertiesOut::OutSerializer //--------------------------------------------------------------------------- ActivationPropertiesOut::OutSerializer::OutSerializer(BOOL fBrokenRefCount) { memset(&_info, 0, sizeof(PropsOutInfo)); _ppvObj = NULL; _unSerialized=FALSE; _pUnk = NULL; _parent = NULL; _fBrokenRefCount = fBrokenRefCount; _fToReleaseIFD = FALSE; } ActivationPropertiesOut::OutSerializer::~OutSerializer() { //------------------------------------------------------------------- // Free marshalled data //------------------------------------------------------------------- if (_info.ppIntfData) { for (DWORD i=0;i<_info.cIfs;i++) { if ((_info.ppIntfData[i]) && (_fToReleaseIFD)) ReleaseIFD(_info.ppIntfData[i]); ActMemFree(_info.ppIntfData[i]); if (_ppvObj && _ppvObj[i]) ((IUnknown*)_ppvObj[i])->Release(); } ActMemFree(_info.ppIntfData); ActMemFree(_ppvObj); } ActMemFree(_info.phresults); if (_info.piid != _pIIDs) ActMemFree(_info.piid); if (_pUnk && !_fBrokenRefCount) { _pUnk->Release(); } } inline void ActivationPropertiesOut::OutSerializer::UnmarshalAtIndex(DWORD index) { InitMarshalling(); Win4Assert(_info.ppIntfData != NULL); if (_info.ppIntfData[index] && (_info.phresults[index] == S_OK)) { ActivationStream strm((InterfaceData*)_info.ppIntfData[index]); if (IsInterfaceImplementedByProxy(_info.piid[index])) { IUnknown* pUnk = NULL; HRESULT hr; if (pfnCoUnmarshalInterface) { hr = pfnCoUnmarshalInterface(&strm, IID_IUnknown, (void**) &pUnk); } else { hr = HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND); } if (SUCCEEDED(hr)) { _info.phresults[index] = pUnk->QueryInterface (_info.piid[index], &_ppvObj[index]); pUnk->Release(); } else { _info.phresults[index] = hr; _ppvObj[index] = (void*) pUnk; } } else { if (pfnCoUnmarshalInterface) { _info.phresults[index] = pfnCoUnmarshalInterface(&strm, _info.piid[index], &_ppvObj[index]); } else { _info.phresults[index] = HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND); } } if (_info.phresults[index] != S_OK) _ppvObj[index] = NULL; ActMemFree(_info.ppIntfData[index]); _info.ppIntfData[index] = NULL; } } //--------------------------------------------------------------------------- // Methods from IUnknown //--------------------------------------------------------------------------- STDMETHODIMP ActivationPropertiesOut::OutSerializer::QueryInterface( REFIID riid, LPVOID* ppvObj) { if (_parent) return _parent->QueryInterface(riid, ppvObj); else return SerializableQueryInterface(riid, ppvObj); } STDMETHODIMP ActivationPropertiesOut::OutSerializer::SerializableQueryInterface( REFIID riid, LPVOID* ppvObj) { *ppvObj = NULL; return E_NOINTERFACE; } ULONG ActivationPropertiesOut::OutSerializer::AddRef(void) { if (_parent) return _parent->AddRef(); return 1; } ULONG ActivationPropertiesOut::OutSerializer::Release(void) { if (_parent) return _parent->Release(); return 0; } //--------------------------------------------------------------------------- // Methods from ISerializable //--------------------------------------------------------------------------- STDMETHODIMP ActivationPropertiesOut::OutSerializer::Serialize(void *pv) { HRESULT hr; Serializer *pSer = (Serializer*) pv; //------------------------------------------------------------------- // Encode this object //------------------------------------------------------------------- handle_t handle; hr = pSer->GetSerializationHandle((void*) &handle); PropsOutInfo_Encode(handle, &_info); return S_OK; } STDMETHODIMP ActivationPropertiesOut::OutSerializer::UnSerialize(void *pv) { Serializer *pSer = (Serializer*) pv; //------------------------------------------------------------------- // If not unserialized then read header //------------------------------------------------------------------- if (!_unSerialized) { handle_t handle; pSer->GetSerializationHandle((void*) &handle); if (_info.piid) ActMemFree(_info.piid); _info.piid = 0; if (_info.phresults) ActMemFree(_info.phresults); _info.phresults = 0; PropsOutInfo_Decode(handle, &_info); if (_info.ppIntfData) { Win4Assert(_info.cIfs != 0); _ppvObj = (void**) ActMemAlloc(sizeof(IUnknown*)*_info.cIfs); if (_ppvObj == NULL) return E_OUTOFMEMORY; for (DWORD i=0; i<_info.cIfs; i++) _ppvObj[i] = NULL; } else _ppvObj = NULL; } return S_OK; } STDMETHODIMP ActivationPropertiesOut::OutSerializer::GetSize(IN void *pv, OUT DWORD *pdwSize) { Serializer *pSer = (Serializer*) pv; //------------------------------------------------------------------- // Need to marshal interfaces to calculate size //------------------------------------------------------------------- DWORD dwMaxDestCtx; BOOL firstMarshal; DWORD i; HRESULT hr; InitMarshalling(); pSer->GetMaxDestCtx(&dwMaxDestCtx); if (!_info.cIfs) goto EncodeOut; if (_info.ppIntfData == NULL) { _info.ppIntfData = (MInterfacePointer**) ActMemAlloc(sizeof(MInterfacePointer*) * _info.cIfs); if (_info.ppIntfData == NULL) return E_OUTOFMEMORY; for (DWORD i=0; i< _info.cIfs; i++) _info.ppIntfData[i] = NULL; Win4Assert(_info.phresults == NULL); _info.phresults = (HRESULT *) ActMemAlloc(sizeof(HRESULT)*_info.cIfs); if (_info.phresults == NULL) { ActMemFree(_info.ppIntfData); _info.ppIntfData=NULL; return E_OUTOFMEMORY; } firstMarshal = TRUE; } else firstMarshal = FALSE; for (i=0; i< _info.cIfs; i++) { if ((!firstMarshal) && ((_info.ppIntfData[i]) || (FAILED(_info.phresults[i])))) continue; // Stream to put marshaled interface in ActivationStream xrpc; DWORD dwMarshalFlags; pSer->GetMarshalFlags(&dwMarshalFlags); IUnknown *punk; if (firstMarshal) punk = _pUnk; else punk = (IUnknown*) _ppvObj[i]; Win4Assert(punk != NULL); void *pvDestCtx = NULL; if (dwMaxDestCtx == MSHCTX_DIFFERENTMACHINE) { pvDestCtx = GetDestCtxPtr(_pClientCOMVersion); if (pvDestCtx == NULL) { ActMemFree(_info.ppIntfData); _info.ppIntfData=NULL; ActMemFree(_info.phresults); _info.phresults = NULL; return E_OUTOFMEMORY; } } if (pfnCoMarshalInterface) { if (IsInterfaceImplementedByProxy(_info.piid[i])) { hr = pfnCoMarshalInterface(&xrpc, IID_IUnknown, punk, dwMaxDestCtx, pvDestCtx, dwMarshalFlags); } else { hr = pfnCoMarshalInterface(&xrpc, _info.piid[i], punk, dwMaxDestCtx, pvDestCtx, dwMarshalFlags); } } else { hr = HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND); } if (pvDestCtx != NULL) { delete pvDestCtx; pvDestCtx = NULL; } _info.phresults[i] = hr; if (SUCCEEDED(hr)) { xrpc.AssignSerializedInterface( (InterfaceData**)&_info.ppIntfData[i]); } else { _info.ppIntfData[i] = NULL; // If MSHLFLAGS_NOTIFYACTIVATION is set then // it is an error path in the LocalServer case // (CobjServer) and it is possible for the server // to linger around forever unless the LockServer // api is toggled on the class factory if (dwMarshalFlags & MSHLFLAGS_NOTIFYACTIVATION) { Win4Assert(_info.cIfs == 1); IClassFactory *pcf; BOOL fToRelease; if (_info.piid[0] != IID_IClassFactory) { HRESULT hr2; hr2 = punk->QueryInterface(IID_IClassFactory, (void**) &pcf); if (FAILED(hr2)) pcf = NULL; fToRelease = TRUE; } else { pcf = (IClassFactory*)punk; fToRelease = FALSE; } if (pcf) { pcf->LockServer(TRUE); pcf->LockServer(FALSE); if (fToRelease) pcf->Release(); } } } } EncodeOut: DWORD dwCurrDestCtx; pSer->GetCurrDestCtx(&dwCurrDestCtx); // If marshalling within process, set up as though unmarshalled if (MARSHALCTX_WITHIN_PROCESS(dwCurrDestCtx)) { if (_info.ppIntfData) { Win4Assert(_info.cIfs != 0); if (!_ppvObj) _ppvObj = (void**) ActMemAlloc(sizeof(IUnknown*)*_info.cIfs); if (_ppvObj == NULL) { ActMemFree(_info.ppIntfData); _info.ppIntfData=NULL; ActMemFree(_info.phresults); _info.phresults = NULL; return E_OUTOFMEMORY; } for (DWORD i=0; i<_info.cIfs; i++) _ppvObj[i] = NULL; // Release punk since destructor won't get called if (_pUnk) { if (!_fBrokenRefCount) _pUnk->Release(); _pUnk = NULL; } } else _ppvObj = NULL; _size = 0; } else { _fToReleaseIFD = FALSE; //------------------------------------------------------------------- // Get Header size //------------------------------------------------------------------- handle_t handle; hr = pSer->GetSizingHandle((void*) &handle); if (FAILED(hr)) return hr; _size = PropsOutInfo_AlignSize(handle, &_info); MesHandleFree(handle); } *pdwSize = _size; return S_OK; } STDMETHODIMP ActivationPropertiesOut::OutSerializer::GetCLSID(OUT CLSID *pclsid) { *pclsid = CLSID_ActivationPropertiesOut; return S_OK; } //--------------------------------------------------------------------------- // // Function: ActPropsMarshalHelper // // Synopsis: Makes an "on the wire" representation of an ActProps // // Arguments: [pact] - interface to marshal // [riid] - iid to marshal // [ppIRD] - where to put pointer to marshaled data // // Returns: S_OK - object successfully marshaled. // // Algorithm: Marshal the object and then get the pointer to // the marshaled data so we can give it to RPC // //--------------------------------------------------------------------------- HRESULT ActPropsMarshalHelper( IActivationProperties *pact, REFIID riid, DWORD destCtx, DWORD mshlflags, MInterfacePointer **ppIRD) { TRACECALL(TRACE_ACTIVATION, "ActPropsMarshalHelper"); HRESULT hr; // This should'nt really get used by functions // called. If that changes we should really QI IUnknown *punk = (IUnknown *)pact; // Do Marshalling ourselves since this is also // used in the SCM. Code collapsed and copied from // dcomrem for Custom marshalling ULONG dwSize, objrefSize; hr = pact->GetMarshalSizeMax(riid, (void*) punk, destCtx, NULL, mshlflags, &dwSize); if (FAILED(hr)) return hr; objrefSize = dwSize + sizeof(OBJREF); // Stream to put marshaled interface in ActivationStream xrpc(objrefSize); // get the clsid for unmarshaling CLSID UnmarshalCLSID; hr = pact->GetUnmarshalClass(riid, punk, destCtx, NULL, mshlflags, &UnmarshalCLSID); if (FAILED(hr)) return hr; OBJREF objref; objref.signature = OBJREF_SIGNATURE; objref.flags = OBJREF_CUSTOM; objref.iid = riid; objref.u_objref.u_custom.clsid = UnmarshalCLSID; objref.u_objref.u_custom.size = dwSize; // currently we dont write any extensions into the custom // objref. The provision is there so we can do it in the // future, for example, if the unmarshaler does not have the // unmarshal class code available we could to provide a callback // mechanism by putting the OXID, and saResAddr in there. objref.u_objref.u_custom.cbExtension = 0; // write the objref header info into the stream ULONG cbToWrite = PtrToUlong( (LPVOID)( (BYTE *)(&objref.u_objref.u_custom.pData) - (BYTE *)&objref ) ); hr = xrpc.Write(&objref, cbToWrite, NULL); if (FAILED(hr)) return hr; hr = pact->MarshalInterface(&xrpc, riid, punk, destCtx, NULL, mshlflags); if (SUCCEEDED(hr)) xrpc.AssignSerializedInterface((InterfaceData**)ppIRD); return hr; } //--------------------------------------------------------------------------- // // Function: ActPropsUnMarshalHelper // // Synopsis: Unmarshals an Activation Properties given an IFD // // Arguments: [pact] - Object to unmarshal into // [riid] - iid to unmarshal // [pIFP] - pointer to marshaled data // // Returns: S_OK - object successfully unmarshaled. // //--------------------------------------------------------------------------- HRESULT ActPropsUnMarshalHelper( IActivationProperties *pAct, MInterfacePointer *pIFP, REFIID riid, void **ppv ) { HRESULT hr = E_INVALIDARG; if (pIFP && ppv) { ActivationStream Stm((InterfaceData *) pIFP); *ppv = NULL; hr = pAct->UnmarshalInterface(&Stm, riid, ppv); } return hr; } //--------------------------------------------------------------------------- // // Function: GetIFDFromInterface // // Synopsis: Makes an "on the wire" representation of an interface // // Arguments: [punk] - interface to marshal // [riid] - iid to marshal // [ppIRD] - where to put pointer to marshaled data // // Returns: S_OK - object successfully marshaled. // // Algorithm: Marshal the object and then get the pointer to // the marshaled data // //--------------------------------------------------------------------------- HRESULT GetIFDFromInterface( IUnknown *pUnk, REFIID riid, DWORD destCtx, DWORD mshlflags, MInterfacePointer **ppIRD) { DWORD sz; InitMarshalling(); HRESULT rethr; if (pfnCoGetMarshalSizeMax) { rethr = pfnCoGetMarshalSizeMax(&sz, riid , pUnk, destCtx, NULL, mshlflags); } else { rethr = HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND); } if (rethr == S_OK) { ActivationStream stream(sz); if (pfnCoMarshalInterface) { rethr = pfnCoMarshalInterface(&stream, riid , pUnk, destCtx, NULL, mshlflags); } else { rethr = HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND); } if (rethr == S_OK) stream.AssignSerializedInterface((InterfaceData**)ppIRD); else *ppIRD = NULL; } return rethr; } //--------------------------------------------------------------------------- // // Function: ReleaseIFD // // Synopsis: Releases Marshalled Data // // Arguments: [pIRD] - Marshalled Data // // Returns: S_OK - object successfully marshaled. // // Algorithm: Marshal the object and then get the pointer to // the marshaled data // //--------------------------------------------------------------------------- HRESULT ReleaseIFD( MInterfacePointer *pIRD) { InitMarshalling(); if (pIRD == NULL) return S_OK; if (pfnCoReleaseMarshalData == NULL) return HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND); ActivationStream Strm((InterfaceData *) pIRD); return pfnCoReleaseMarshalData(&Strm); }