|
|
//+-------------------------------------------------------------------------
//
// 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 <ole2int.h>
#include <actprops.hxx>
#include <stdidx.h>
//---------------------------------------------------------------------------
// 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!"); } // NOTE: We leave them NULL otherwise, callers must check. Note that this condition should not occur
// because we are either 1) in RPCSS, in which case it shouldn't be doing the marshalling, or
// 2) We are being called from ole32
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() { //-------------------------------------------------------------------
// 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 = NULL; 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
//---------------------------------------------------------------
HRESULT hr; handle_t handle = NULL; pSer->GetSerializationHandle((void*) &handle); _unSerHeader.pclsid = 0; _unSerHeader.pSizes = 0; _unSerHeader.opaqueData = 0; CustomHeader_Decode(handle, &_unSerHeader); hr = pSer->IncrementPosition(_unSerHeader.headerSize); if (FAILED(hr)) return hr; hr = pSer->GetCopy(&_pUnSer); if (FAILED(hr)) return hr; hr = pSer->Commit(); if (FAILED(hr)) return hr; _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 = (DWORD) 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);
if (SUCCEEDED(hr)) { dwClsCtx &= (dwAcceptableClsCtx | (CLSCTX_PS_DLL | CLSCTX_LOCAL_SERVER));
} }
InstantiationInfo* pii = GetInstantiationInfo(); if (pii) return pii->SetClsctx(dwClsCtx); else return E_OUTOFMEMORY;
}
STDMETHODIMP ActivationPropertiesIn::SetActivationFlags (IN DWORD actvflags) { InstantiationInfo* pii = GetInstantiationInfo(); if (pii) return pii->SetActivationFlags(actvflags); else return E_OUTOFMEMORY;
// 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);
if(SUCCEEDED(hr)) { InstantiationInfo* pii = GetInstantiationInfo(); if (pii) pii->SetClsid(*pclsid); else hr = E_OUTOFMEMORY; }
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) { GetPersistInfo(); Win4Assert(_pPersist != NULL); return _pPersist->SetFile(wszFileName, dwMode); }
//---------------------------------------------------------------------------
// Methods for IActivationPropertiesIn
//---------------------------------------------------------------------------
STDMETHODIMP ActivationPropertiesIn::GetClsctx(OUT DWORD *pdwClsctx) { InstantiationInfo* pii = GetInstantiationInfo(); if (pii) return pii->GetClsctx(pdwClsctx); else return E_OUTOFMEMORY; }
STDMETHODIMP ActivationPropertiesIn::AddRequestedIIDs(IN DWORD cIfs, IN IID *pIID) { InstantiationInfo* pii = GetInstantiationInfo(); if (pii) return pii->AddRequestedIIDs(cIfs, pIID); else return E_OUTOFMEMORY; }
STDMETHODIMP ActivationPropertiesIn::GetRequestedIIDs(OUT DWORD *pcIfs, OUT IID **ppIID) { InstantiationInfo* pii = GetInstantiationInfo(); if (pii) return pii->GetRequestedIIDs(pcIfs, ppIID); else return E_OUTOFMEMORY; }
STDMETHODIMP ActivationPropertiesIn::GetActivationID(OUT GUID *pActivationID) { *pActivationID = GUID_NULL; // currently unused and not supported
return E_NOTIMPL; }
STDMETHODIMP ActivationPropertiesIn::GetActivationFlags(OUT DWORD *pactvflags) { InstantiationInfo* pii = GetInstantiationInfo(); if (pii) return pii->GetActivationFlags(pactvflags); else return E_OUTOFMEMORY;
// 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 (HRESULT_FROM_WIN32(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 = HRESULT_FROM_WIN32(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 (HRESULT_FROM_WIN32(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 = HRESULT_FROM_WIN32(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(*ppSer == NULL) return E_OUTOFMEMORY; 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) { if (!ppv) return E_POINTER; *ppv = NULL; HRESULT hr = ActivationProperties::UnmarshalInterface(pStm, riid,ppv);
if (hr != S_OK) return hr;
CLSID clsid;
hr = GetClsid(&clsid); // this will cause unmarshal of the InstantiationInfo, to get us the Clsid.
if (FAILED(hr)) goto Cleanup;
Win4Assert(clsid != GUID_NULL); // sanity check in checked builds
hr = GetClassInfoFromClsid(clsid, &_pClassInfo);
if ((hr == S_OK) && _pClassInfo) { _pClassInfo->Lock(); }
_delegated=TRUE; //assume unmarshalling imples that delegation happened
Cleanup: if (FAILED(hr) && (*ppv)) { IUnknown* pUnk = (IUnknown*)*ppv; pUnk->Release(); *ppv = NULL; }
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) { 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<cIfs; i++) { //---------------------------------------------------------------
// If no umarshalled result then we have to have a pUnk
//---------------------------------------------------------------
if (!_pOutSer->_ppvObj) { Win4Assert(_pOutSer->_pUnk!=NULL);
if (_fBrokenRefCount && (i == 0)) {
pMultiQi[i].pItf = _pOutSer->_pUnk; pMultiQi[i].hr = S_OK; } else { 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
//-----------------------------------------------------------------------
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<i;j++) { if ((_pOutSer->_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++; } }
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(*ppSer == NULL) return E_OUTOFMEMORY; 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 = NULL; 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 = NULL; 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 = NULL; hr = pSer->GetSizingHandle((void*) &handle);
if (FAILED(hr)) return hr;
_size = (DWORD) 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) { 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 = 0;
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); }
|