|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1996.
//
// File: defhndlr.cpp
//
// Contents: Implementation of the default handler
//
// Classes: CDefObject (see defhndlr.h)
//
// Functions: OleCreateDefaultHandler
// OleCreateEmbeddingHelper
//
//
// History: dd-mmm-yy Author Comment
//
// 11-17-95 JohannP (Johann Posch) Architectural change:
// Default handler will talk to a handler object
// on the server site (ServerHandler). The serverhandler
// communicates with the default handler via the
// clientsitehandler. See document: "The Ole Server Handler".
//
// 06-Sep-95 davidwor modified SetHostNames to avoid atoms
// 01-Feb-95 t-ScottH add Dump method to CDefObject
// add DumpCDefObject API
// add DHFlag to indicate aggregation
// initialize m_cConnections in constructor
// 09-Jan-95 t-scotth changed VDATETHREAD to accept a pointer
// 15-Nov-94 alexgo optimized, removed excess BOOLS and
// now use multiple inheritance
// 01-Aug-94 alexgo added object stabilization
// 16-Jan-94 alexgo fixed bug in control flow for
// advises
// 11-Jan-94 alexgo added VDATEHEAP macro to every function
// and method.
// 10-Dec-93 alexgo added call tracing, ran through
// tab filter program to eliminate
// whitespace
// 30-Nov-93 alexgo fixed bug with cache aggregation
// 22-Nov-93 alexgo removed overloaded == for GUIDs
// 09-Nov-93 ChrisWe changed COleCache::Update to
// COleCache::UpdateCache, and COleCache::Discard to
// COleCache::DiscardCache, which do the same as the
// originals, but without the indirect function call
// 02-Nov-93 alexgo 32bit port
// srinik 09/15/92 Removed code for giving cfOwnerLink data through
// GetData() method
// srinik 09/11/92 Removed IOleCache implementation, as a result of
// removing voncache.cpp, and moving IViewObject
// implementation into olecache.cpp.
// SriniK 06/04/92 Fixed problems in IPersistStorage methods
// 04-Mar-92 srinik created
//
//--------------------------------------------------------------------------
#include <le2int.h>
#include <scode.h>
#include <objerror.h>
#include <olerem.h>
#include "defhndlr.h"
#include "defutil.h"
#include "ole1cls.h"
#ifdef _DEBUG
#include <dbgdump.h>
#endif // _DEBUG
#include <ole2int.h>
#include <stdid.hxx> // CStdIdentity
#include <ipidtbl.hxx> // IpidTable.
#include <aggid.hxx> // COM outer object
#include "xmit.hxx"
#ifdef SERVER_HANDLER
#include "srvhndlr.h"
#include "clthndlr.h"
#endif // SERVER_HANDLER
ASSERTDATA
/*
* IMPLEMENTATION of CDefObject * */
FARINTERNAL_(LPUNKNOWN) CreateDdeProxy(IUnknown FAR* pUnkOuter, REFCLSID rclsid);
//+-------------------------------------------------------------------------
//
// Function: CreateRemoteHandler
//
// Arguments: [rclsid] -- clsid of the remote object
// [pUnkOuter] -- the controlling unknown
// [iid] -- requested interface ID
// [ppv] -- pointer to hold the returned interface
//
// Returns: HRESULT
//
// History: dd-mmm-yy Author Comment
// 10-Jan-96 Gopalk Rewritten
//--------------------------------------------------------------------------
static INTERNAL CreateRemoteHandler(REFCLSID rclsid, IUnknown *pUnkOuter, REFIID iid, void **ppv, DWORD flags, BOOL *fComOuterObject, BOOL *fOle1Server) { LEDebugOut((DEB_ITRACE, "%p _IN CreateRemoteHandler (%p, %p, %p, %p, %p)\n", 0 /* this */, rclsid, pUnkOuter, iid, ppv, fComOuterObject));
// Validation checks
VDATEHEAP();
// Local variables
HRESULT hresult = NOERROR;
// Initialize fComOuterObject and fOle1Server
*fComOuterObject = FALSE; *fOle1Server = FALSE;
// Check if the server is a OLE 1.0 object
if(CoIsOle1Class(rclsid)) { IUnknown* pUnk; COleTls Tls;
// Set fComOuterObject to TRUE
*fOle1Server = TRUE;
// Check if the container disabled OLE1 functinality
if(Tls->dwFlags & OLETLS_DISABLE_OLE1DDE) { // Container is not interested in talking to OLE1 servers.
// Fail the call
hresult = CO_E_OLE1DDE_DISABLED; }
else { LEDebugOut((DEB_ITRACE, "%p CreateRemoteHandler calling CreateDdeProxy(%p, %p)\n", 0 /* this */, pUnkOuter, rclsid));
pUnk = CreateDdeProxy(pUnkOuter, rclsid);
if(pUnk) { hresult = pUnk->QueryInterface(iid, ppv); pUnk->Release(); } else { hresult = E_OUTOFMEMORY; } }
} else { // Check for COM outer object
CStdIdentity *pStdId;
Win4Assert(pUnkOuter); // We do not want to QI a generic pUnkOuter for IID_IStdIdentity. Hence
// we QI only if we put the pUnkOuter, either during OleCreateEmbeddingHelper
// or during unmarshaling (CDefClassFactory::CreateInstance).
// The DH_APICREATE flag is used to distinguish between the two cases.
if ( flags & DH_COM_OUTEROBJECT || ( !(flags & DH_COM_OUTEROBJECT)&&!(flags & DH_APICREATE) )) { hresult = pUnkOuter->QueryInterface(IID_IStdIdentity, (void **)&pStdId); if(SUCCEEDED(hresult)) { // Obtain the inner IUnknown on the COM outer object
*ppv = pStdId->GetInternalUnk(); ((IUnknown *) *ppv)->AddRef();
// Inform the COM outer object that it is dealing with Default
// Handler so that it enables access to IProxyManager methods
pStdId->UpdateFlags(STDID_CLIENT_DEFHANDLER);
// Release the StdId
pStdId->Release();
// Set fComOuterObject to TRUE
*fComOuterObject = TRUE; } } else { // Create StdIdentity
hresult = CreateIdentityHandler(pUnkOuter, STDID_CLIENT_DEFHANDLER, NULL, GetCurrentApartmentId(), iid, ppv); } }
LEDebugOut((DEB_ITRACE, "%p OUT CreateRemoteHandler(%lx)\n", 0 /* this */, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Function: OleCreateDefaultHandler
//
// Synopsis: API to create the default handler. Simply calls
// OleCreateEmbeddingHelper with more arguments
//
// Arguments: [clsid] -- the clsid of the remote exe
// [pUnkOuter] -- the controlling unknown (so we can
// be aggregated)
// [iid] -- the requested interface
// [ppv] -- where to put a pointer to the default
// handler
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 10-Dec-93 alexgo added call tracing
// 02-Nov-93 alexgo 32bit port
// 10-Jan-97 Gopalk Simplified
//--------------------------------------------------------------------------
#pragma SEG(OleCreateDefaultHandler)
STDAPI OleCreateDefaultHandler(REFCLSID clsid, IUnknown *pUnkOuter, REFIID iid, void **ppv) { OLETRACEIN((API_OleCreateDefaultHandler, PARAMFMT("clsid=%I, pUnkOuter=%p, iid=%I, ppv=%p"), &clsid, pUnkOuter, &iid, ppv)); LEDebugOut((DEB_TRACE, "%p _IN OleCreateDefaultHandler(%p, %p, %p, %p)\n", 0 /* this */, clsid, pUnkOuter, iid, ppv));
// validation checks
VDATEHEAP();
// Local variable
HRESULT hresult;
// Call OleCreateEmbeddingHelper with the right parameters
hresult = OleCreateEmbeddingHelper(clsid, pUnkOuter, EMBDHLP_INPROC_HANDLER | EMBDHLP_CREATENOW, NULL, iid, ppv);
LEDebugOut((DEB_TRACE, "%p OUT OleCreateDefaultHandler(%lx)\n", 0 /* this */, hresult));
OLETRACEOUT((API_OleCreateDefaultHandler, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Function: OleCreateEmbeddingHelper
//
// Synopsis: Creates an instance of CDefObject (the default handler)
// Called by OleCreateDefaultHandler
//
// Arguments: [clsid] -- Server class id
// [pUnkOuter] -- Controlling unkown for aggregation
// [flags] -- Indiacte an inproc handler or
// helper for an inproc server. The inproc
// server case is useful for self embedding
// [pCF] -- Server's class factory for inproc server
// [iid] -- Requested interface
// [ppv] -- pointer to hold the returned interface
//
// Returns: HRESULT
//
// History: dd-mmm-yy Author Comment
// 10-Jan-96 Gopalk Rewritten
//--------------------------------------------------------------------------
#pragma SEG(OleCreateEmbeddingHelper)
STDAPI OleCreateEmbeddingHelper(REFCLSID clsid, IUnknown *pUnkOuter, DWORD flags, IClassFactory *pCF, REFIID iid, void **ppv) { OLETRACEIN((API_OleCreateEmbeddingHelper, PARAMFMT("clsid=%I, pUnkOuter=%p, flags=%x, pCF=%p, iid=%I, ppv=%p"), &clsid, pUnkOuter, flags, pCF, &iid, ppv)); LEDebugOut((DEB_TRACE, "%p _IN OleCreateEmbeddingHelper(%p, %p, %lu, %p, %p, %p)\n", 0 /* this */, clsid, pUnkOuter, flags, pCF, iid, ppv));
// Local variables
HRESULT hresult = NOERROR; IUnknown *pUnk;
// Validation checks
VDATEHEAP();
// Initialize the out parameter
if(IsValidPtrOut(ppv, sizeof(void *))) *ppv = NULL; else hresult = E_INVALIDARG;
if(hresult == NOERROR) { // Check that only allowed flags are set
if(flags & ~(EMBDHLP_INPROC_SERVER|EMBDHLP_DELAYCREATE)) { hresult = E_INVALIDARG; } // Ensure that aggregation rules are being followed
else if(pUnkOuter && (iid!=IID_IUnknown || !IsValidInterface(pUnkOuter))) { hresult = E_INVALIDARG; } else { // Check whether Inproc Server or Inproc Handler is requested
if(flags & EMBDHLP_INPROC_SERVER) { // InProc server requested
if(!pCF || !IsValidInterface(pCF)) { // Inproc Server should be given a class factory
hresult = E_INVALIDARG; } } else { // InProc Handler requested
if(pCF || (flags & EMBDHLP_DELAYCREATE)) { // InProc Handler should not be given a class factory
hresult = E_INVALIDARG; } } } }
// Create the Default object
if(hresult == NOERROR) { // We add the DH_APICREATE flag so that during CreateRemoteHandler we can
// distinguish between creation through APIs v/s creation through unmarshaling.
// Warning: Be careful! Do not use bits used by the EMBDHLP_xxx flags (ole2.h)
pUnk = CDefObject::Create(pUnkOuter, clsid, flags|DH_APICREATE, pCF); if(pUnk) { // Check if IUnknown was requested
if(IsEqualIID(iid, IID_IUnknown)) { *ppv = pUnk; } else { // QI for the desired interface
hresult = pUnk->QueryInterface(iid, ppv); // Fixup the reference count
pUnk->Release(); } } else { hresult = E_OUTOFMEMORY; } }
LEDebugOut((DEB_TRACE, "%p OUT OleCreateEmbeddingHelper(%lx)\n", 0 /* this */, hresult)); OLETRACEOUT((API_OleCreateEmbeddingHelper, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::Create, static
//
// Synopsis: Static function used internally to create CDefObject
//
// Arguments: [pUnkOuter] -- Controlling unkown
// [clsid] -- Server clsid
// [flags] -- creation flags
// [pCF] -- pointer to server object class factory for
// inproc server
//
// Returns: pointer to the CDefObject's IUnkown interface
//
// History: dd-mmm-yy Author Comment
// 10-Jan-96 Gopalk Rewritten
// 07-Oct-98 SteveSw Fix bug in "new CAggID" failure case
//--------------------------------------------------------------------------
IUnknown *CDefObject::Create(IUnknown *pUnkOuter, REFCLSID clsid, DWORD flags, IClassFactory *pCF) { // Validation checks
VDATEHEAP();
// Local variables
CDefObject *pDefObj = NULL; CAggId *pAID = NULL; HRESULT error = S_OK;
// If the outer object is absent, create the standard
// COM outer object to take care of race conditions
// during unmarshaling. If the outer object is present,
// we can only hope that either it handles the race
// conditions (Unmarshaled handler case) or that
// they are not encountered
if(!(flags & EMBDHLP_INPROC_SERVER) && !pUnkOuter && !CoIsOle1Class(clsid)) { IUnknown *pUnkInternal = NULL;
// Create the COM outer object
pAID = new CAggId(clsid, error); if(SUCCEEDED(error) && pAID != NULL) { pUnkOuter = (IUnknown *) pAID; flags |= DH_COM_OUTEROBJECT; } else { // Release aggid if it was created
if(pAID) pAID->Release(); return NULL; } }
// Create the Default Handler
pDefObj = new CDefObject(pUnkOuter); if(!pDefObj) { // If COM outer object was created earlier, release it now
if(flags & DH_COM_OUTEROBJECT) pAID->Release();
return NULL; }
// Make our ref count equal to 1
pDefObj->m_Unknown.AddRef();
// Check if COM outer object was created earlier
if(flags & DH_COM_OUTEROBJECT) { // Set handler on the COM outer object
error = pAID->SetHandler(&pDefObj->m_Unknown); // As OID has not yet been assigned to StdIdentity
// of AggId, no other thread can get a pointer to it
// and consequently, the above call should never fail
Win4Assert(error == NOERROR);
// Fix the reference count
pDefObj->m_Unknown.Release();
// Return if something has gone wrong
if(error != NOERROR) { pAID->Release(); return NULL; } }
// Initialize member variables
pDefObj->m_clsidServer = clsid; pDefObj->m_clsidBits = CLSID_NULL;
#ifdef SERVER_HANDLER
pDefObj->m_clsidUser = CLSID_NULL; pDefObj->m_ContentMiscStatusUser = 0; #endif // SERVER_HANDLER
if(pCF) { pDefObj->m_pCFDelegate = pCF; pCF->AddRef(); }
// Update flags
if(!(flags & EMBDHLP_INPROC_SERVER)) pDefObj->m_flags |= DH_INPROC_HANDLER; if(flags & DH_COM_OUTEROBJECT) pDefObj->m_flags |= DH_COM_OUTEROBJECT; if (flags & DH_APICREATE) pDefObj->m_flags |= DH_APICREATE;
if(IsEqualCLSID(clsid, CLSID_StaticMetafile) || IsEqualCLSID(clsid, CLSID_StaticDib) || IsEqualCLSID(clsid, CLSID_Picture_EnhMetafile)) pDefObj->m_flags |= DH_STATIC;
// Create sub objects starting with Ole Cache
pDefObj->m_pCOleCache = new COleCache(pDefObj->m_pUnkOuter, clsid); if(pDefObj->m_pCOleCache) { // Create DataAdvise Cache
error = CDataAdviseCache::CreateDataAdviseCache(&pDefObj->m_pDataAdvCache); if(error == NOERROR) { // Check flags and create the inner object if requested
if(flags & EMBDHLP_DELAYCREATE) { Win4Assert(pCF); Win4Assert(flags & EMBDHLP_INPROC_SERVER); Win4Assert(pDefObj->m_pUnkDelegate == NULL); Win4Assert(pDefObj->m_pProxyMgr == NULL); Win4Assert(pDefObj->GetRefCount() == 1); pDefObj->m_flags |= DH_DELAY_CREATE; return &pDefObj->m_Unknown; } else { error = pDefObj->CreateDelegate(); if(error == NOERROR) { Win4Assert(pDefObj->GetRefCount() == 1); if(flags & DH_COM_OUTEROBJECT) return (IUnknown *)pAID; else return &pDefObj->m_Unknown; } } } }
// Something has gone wrong. Release the outer object
// which will in turn release sub objects
Win4Assert(pDefObj->GetRefCount() == 1); if(flags & DH_COM_OUTEROBJECT) pAID->Release(); else pDefObj->m_Unknown.Release();
return NULL; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::CDefObject
//
// Synopsis: constructor, sets member variables to NULL
//
// Effects:
//
// Arguments: [pUnkOuter] -- the controlling unkown
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: none
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 02-Nov-93 alexgo 32bit port
// 10-Jan-97 Gopalk Intialize CRefExportCount
//--------------------------------------------------------------------------
CDefObject::CDefObject (IUnknown *pUnkOuter) : CRefExportCount(pUnkOuter) { VDATEHEAP();
if (!pUnkOuter) { pUnkOuter = &m_Unknown; }
//m_clsidServer
//m_clsidBits are set in ::Create
m_cConnections = 0; m_pCFDelegate = NULL; m_pUnkDelegate = NULL; m_pUnkOuter = pUnkOuter; m_pProxyMgr = NULL;
m_pCOleCache = NULL; m_pOAHolder = NULL; m_dwConnOle = 0L;
m_pAppClientSite = NULL; m_pStg = NULL;
m_pDataAdvCache = NULL; m_flags = DH_INIT_NEW; m_dwObjFlags = 0;
m_pHostNames = NULL; m_ibCntrObj = 0; m_pOleDelegate = NULL; m_pDataDelegate = NULL; m_pPSDelegate = NULL;
#ifdef SERVER_HANDLER
m_pEmbSrvHndlrWrapper = NULL; m_pRunClientSite = NULL; #endif // SERVER_HANDLER
// Initialize member variables used for caching MiscStatus bits
m_ContentSRVMSHResult = 0xFFFFFFFF; m_ContentSRVMSBits = 0; m_ContentREGMSHResult = 0xFFFFFFFF; m_ContentREGMSBits = 0;
// Initialize member variables used for caching MiscStatus bits
m_ContentSRVMSHResult = 0xFFFFFFFF; m_ContentSRVMSBits = 0; m_ContentREGMSHResult = 0xFFFFFFFF; m_ContentREGMSBits = 0;
#if DBG==1
if (pUnkOuter != &m_Unknown) { m_flags |= DH_AGGREGATED; } #endif
}
//+-------------------------------------------------------------------------
//
// Member: CDefObject::CleanupFn, private, virtual
//
// Synopsis: This function is called by CRefExportCount when the object
// enters zombie state
//
// Arguments: None
//
// History: dd-mmm-yy Author Comment
// 10-Jan-07 Gopalk Creation
//--------------------------------------------------------------------------
void CDefObject::CleanupFn(void) { LEDebugOut((DEB_ITRACE, "%p _IN CDefObject::CleanupFn()\n", this));
// Validation check
VDATEHEAP();
// Ensure that the server is stopped thereby releasing all references on
// it
Stop();
// Release all cached pointers following aggregation rules. For local
// server case, the following calls simply release proxies maintained
// by the proxy manager as they have already been disconnected above
if(m_pProxyMgr) { m_pUnkOuter->AddRef(); SafeReleaseAndNULL((IUnknown **)&m_pProxyMgr); } if(m_pDataDelegate) { m_pUnkOuter->AddRef(); SafeReleaseAndNULL((IUnknown **)&m_pDataDelegate); } if(m_pOleDelegate) { m_pUnkOuter->AddRef(); SafeReleaseAndNULL((IUnknown **)&m_pOleDelegate); } if(m_pPSDelegate) { m_pUnkOuter->AddRef(); SafeReleaseAndNULL((IUnknown **)&m_pPSDelegate); }
// Release server handler
#ifdef SERVER_HANDLER
if (m_pEmbSrvHndlrWrapper){ CEmbServerWrapper* pWrapper = m_pEmbSrvHndlrWrapper; m_pEmbSrvHndlrWrapper = NULL; pWrapper->m_Unknown.Release(); } #endif // SERVER_HANDLER
// Release the inner objects
if(m_pUnkDelegate) { SafeReleaseAndNULL((IUnknown **)&m_pUnkDelegate); } if(m_pCFDelegate) { SafeReleaseAndNULL((IUnknown **)&m_pCFDelegate); } if(m_pCOleCache) { COleCache *pcache = m_pCOleCache; m_pCOleCache = NULL; pcache->m_UnkPrivate.Release(); } if(m_pOAHolder) { SafeReleaseAndNULL((IUnknown **)&m_pOAHolder); } if (m_pDataAdvCache) { LPDATAADVCACHE pcacheTemp = m_pDataAdvCache; m_pDataAdvCache = NULL; delete pcacheTemp; }
// Release container side objects
if(m_pAppClientSite) { SafeReleaseAndNULL((IUnknown **)&m_pAppClientSite); } if(m_pStg) { SafeReleaseAndNULL((IUnknown **)&m_pStg); } if(m_pHostNames) { PrivMemFree(m_pHostNames); m_pHostNames = NULL; }
// Set DH_CLEANEDUP flag
m_flags |= DH_CLEANEDUP;
LEDebugOut((DEB_ITRACE, "%p OUT CDefObject::CleanupFn()\n", this));
return; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::~CDefObject
//
// Synopsis: Destructor
//
// Arguments: None
//
// History: dd-mmm-yy Author Comment
// 10-Jan-07 Gopalk Rewritten
//--------------------------------------------------------------------------
#pragma SEG(CDefObject_dtor)
CDefObject::~CDefObject(void) { VDATEHEAP();
Win4Assert(m_flags & DH_CLEANEDUP); Win4Assert(m_pUnkDelegate == NULL); Win4Assert(m_pCFDelegate == NULL); Win4Assert(m_pProxyMgr == NULL); Win4Assert(m_pCOleCache == NULL); Win4Assert(m_pOAHolder == NULL); Win4Assert(m_pAppClientSite == NULL); Win4Assert(m_pHostNames == NULL); Win4Assert(m_pStg == NULL); Win4Assert(m_pDataAdvCache == NULL); }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::CreateDelegate, private
//
// Synopsis: Creates either a remote handler or a user supplied delegate
// The remote handler must support IProxyManager
//
// Returns: HRESULT
//
// History: dd-mmm-yy Author Comment
// 10-Jan-07 Gopalk Rewritten
//--------------------------------------------------------------------------
INTERNAL CDefObject::CreateDelegate(void) { LEDebugOut((DEB_TRACE, "%p _IN CDefObject::CreateDelegate()\n", this));
// Validation checks
VDATEHEAP();
// Local variables
HRESULT hresult = NOERROR; BOOL fComOuterObject, fOle1Server;
// Check if inner object has not yet been created
if(!m_pUnkDelegate) { // Check for the class factory for the inner object
if(m_pCFDelegate) { // Create the inner object using its class factory
Win4Assert(!(m_flags & DH_INPROC_HANDLER)); Win4Assert(!(m_flags & DH_COM_OUTEROBJECT)); hresult = m_pCFDelegate->CreateInstance(m_pUnkOuter, IID_IUnknown, (void **) &m_pUnkDelegate);
// Assert that COM rules have been followed for out parameters
AssertOutPtrIface(hresult, m_pUnkDelegate);
// Release class factory if inner object has been
// successfully created
if(hresult == NOERROR) { m_pCFDelegate->Release(); m_pCFDelegate = NULL; } else { // Win4Assert(!"CreateInstance failed"); // LeSuite Covers this case.
}
} else { // Create the COM/DDE Proxy Manager
// Note that the proxy manager is intialized to obtain strong
// references when the server is run. The conatiner can
// modify this behavior by calling either
// OleSetConatinedObject or IRunnableObject::LockRunning
Win4Assert(m_flags & DH_INPROC_HANDLER); hresult = CreateRemoteHandler(m_clsidServer, m_pUnkOuter, IID_IUnknown, (void **) &m_pUnkDelegate, m_flags, &fComOuterObject, &fOle1Server);
// Assert that COM rules have been followed for out parameters
AssertOutPtrIface(hresult, m_pUnkDelegate); if(hresult == NOERROR) { // Determine if the Default Handler is being created due to
// unmarshaling and update flags
if(m_flags & DH_COM_OUTEROBJECT) { Win4Assert(fComOuterObject); } else if(fComOuterObject) { // DEFHANDLER obtained by unmarshaling.
// This happens on the linking container side
m_flags |= DH_UNMARSHALED;
// Output a debug warning.
LEDebugOut((DEB_WARN, "DEFHANDLER obtained by unmarshaling\n")); } if(fOle1Server) { // OLE 1.0 Server
m_flags |= DH_OLE1SERVER;
// Output a debug warning.
LEDebugOut((DEB_WARN, "OLE 1.0 Server\n")); }
// Obtain the IProxyManager interface
hresult = m_pUnkDelegate->QueryInterface(IID_IProxyManager, (void **) &m_pProxyMgr); // Follow aggregation rules for caching interface
// pointers on inner objects
if(hresult == NOERROR) { Win4Assert(m_pProxyMgr); m_pUnkOuter->Release(); } else { Win4Assert(!"Default handler failed to obtain Proxy Manager"); Win4Assert(!m_pProxyMgr); m_pProxyMgr = NULL; } } else { Win4Assert(!"CreateRemoteHandler Failed"); } }
// Cleanup if something has gone wrong
if(hresult != NOERROR) { if(m_pUnkDelegate) m_pUnkDelegate->Release(); m_pUnkDelegate = NULL; }
}
// DEFHANDLER either has proxy manager as the inner object
// for out of proc server objects or actual server as the
// inner object for inproc server objects.
// Assert that this is TRUE
Win4Assert((m_pProxyMgr != NULL) == !!(m_flags & DH_INPROC_HANDLER));
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::CreateDelegate(%lx)\n", this , hresult));
return hresult; }
//+----------------------------------------------------------------------------
//
// Member:
// CDefObject::CPrivUnknown::AddRef, private
//
// Synopsis:
// implements IUnknown::AddRef
//
// Arguments:
// none
//
// Returns:
// the parent object's reference count
//
// History:
// Gopalk Rewritten Jan 20, 97
//-----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CDefObject::CPrivUnknown::AddRef( void ) { LEDebugOut((DEB_TRACE, "%p _IN CDefObject::CPrivUnknown::AddRef()\n", this));
// Validation check
VDATEHEAP();
// Local variables
CDefObject *pDefObject = GETPPARENT(this, CDefObject, m_Unknown); ULONG cRefs;
// Addref the parent object
cRefs = pDefObject->SafeAddRef();
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::CPrivUnknown::AddRef(%lu)\n", this, cRefs));
return cRefs; }
//+----------------------------------------------------------------------------
//
// Member:
// CDefObject::CPrivUnknown::Release, private
//
// Synopsis:
// implements IUnknown::Release
//
// Arguments:
// none
//
// Returns:
// the parent object's reference count
//
// History:
// Gopalk Rewritten Jan 20, 97
//-----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CDefObject::CPrivUnknown::Release( void ) { LEDebugOut((DEB_TRACE, "%p _IN CDefObject::CPrivUnknown::Release()\n", this));
// Validation check
VDATEHEAP();
// Local variables
CDefObject *pDefObject = GETPPARENT(this, CDefObject, m_Unknown); ULONG cRefs;
// Release parent object
cRefs = pDefObject->SafeRelease();
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::CPrivUnknown::Release(%lu)\n", this, cRefs));
return cRefs; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::CPrivUnknown::QueryInterface
//
// Synopsis: Returns a pointer to one of the supported interfaces.
//
// Effects:
//
// Arguments: [iid] -- the requested interface ID
// [ppv] -- where to put the iface pointer
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 03-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::CPrivUnknown::QueryInterface(REFIID iid, LPLPVOID ppv) { CDefObject * pDefObject = GETPPARENT(this, CDefObject, m_Unknown); HRESULT hresult;
VDATEHEAP();
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::CUnknownImpl::QueryInterface " "( %p , %p )\n", pDefObject, iid, ppv));
CRefStabilize stabilize(pDefObject);
if (IsEqualIID(iid, IID_IUnknown)) { *ppv = (void FAR *)this; } else if (IsEqualIID(iid, IID_IOleObject)) { *ppv = (void FAR *)(IOleObject *)pDefObject; } else if (IsEqualIID(iid, IID_IDataObject)) { *ppv = (void FAR *)(IDataObject *)pDefObject; } else if (IsEqualIID(iid, IID_IRunnableObject)) { *ppv = (void FAR *)(IRunnableObject *)pDefObject; } else if (IsEqualIID(iid, IID_IPersist) || IsEqualIID(iid, IID_IPersistStorage)) { *ppv = (void FAR *)(IPersistStorage *)pDefObject; } else if( IsEqualIID(iid, IID_IViewObject) || IsEqualIID(iid, IID_IViewObject2) || IsEqualIID(iid, IID_IOleCache) || IsEqualIID(iid, IID_IOleCache2) ) { // m_pCOleCache is a pointer to the *public* IUnknown
// (we want the private one)
hresult = pDefObject->m_pCOleCache->m_UnkPrivate.QueryInterface( iid, ppv);
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::CUnknownImpl::QueryInterface " "( %lx ) [ %p ]\n", pDefObject, hresult, (ppv) ? *ppv : 0 ));
return hresult; } else if( !(pDefObject->m_flags & DH_INPROC_HANDLER) && IsEqualIID(iid, IID_IExternalConnection) ) { // only allow IExternalConnection if inproc server. We
// know we are an inproc server if we are *not* an inproc
// handler (cute, huh? ;-)
*ppv = (void FAR *)(IExternalConnection *)pDefObject; } else if( IsEqualIID(iid, IID_IOleLink) ) { // this prevents a remote call for
// a query which will almost always fail; the remote call
// interfered with server notification messages.
*ppv = NULL;
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::CUnknownImpl::QueryInterface " "( %lx ) [ %p ]\n", pDefObject, E_NOINTERFACE, 0));
return E_NOINTERFACE; } else if( IsEqualIID(iid, IID_IInternalUnknown) ) { // this interface is private between the handler and the
// remoting layer and is never exposed by handlers.
*ppv = NULL; return E_NOINTERFACE; } else if( pDefObject->CreateDelegate() == NOERROR) {
hresult = pDefObject->m_pUnkDelegate->QueryInterface( iid, ppv);
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::CUnknownImpl::QueryInterface " "( %lx ) [ %p ]\n", pDefObject, hresult, (ppv) ? *ppv : 0 ));
return hresult; } else { // no delegate and couldn't create one
*ppv = NULL;
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::CUnkownImpl::QueryInterface " "( %lx ) [ %p ]\n", pDefObject, CO_E_OBJNOTCONNECTED, 0 ));
return CO_E_OBJNOTCONNECTED; }
// this indirection is important since there are different
// implementationsof AddRef (this unk and the others).
((IUnknown FAR*) *ppv)->AddRef();
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::CUnknownImpl::QueryInterface " "( %lx ) [ %p ]\n", pDefObject, NOERROR, *ppv));
return NOERROR; }
/*
* IMPLEMENTATION of IUnknown methods */
//+-------------------------------------------------------------------------
//
// Member: CDefObject::QueryInterface
//
// Synopsis: QI's to the controlling IUnknown
//
// Effects:
//
// Arguments: [riid] -- the interface ID
// [ppv] -- where to put it
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IUnknown
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 15-Nov-94 alexgo author
//
// Notes: We do *not* need to stabilize this method as only
// one outgoing call is made and we do not use the
// 'this' pointer afterwards
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::QueryInterface( REFIID riid, void **ppv ) { HRESULT hresult;
VDATEHEAP(); VDATETHREAD(this);
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::QueryInterface ( %lx , " "%p )\n", this, riid, ppv));
Assert(m_pUnkOuter);
hresult = m_pUnkOuter->QueryInterface(riid, ppv);
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::QueryInterface ( %lx ) " "[ %p ]\n", this, hresult, *ppv));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::AddRef
//
// Synopsis: delegates AddRef to the controlling IUnknown
//
// Effects:
//
// Arguments: void
//
// Requires:
//
// Returns: ULONG -- the new reference count
//
// Signals:
//
// Modifies:
//
// Derivation: IUnknown
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 15-Nov-94 alexgo author
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CDefObject::AddRef( void ) { ULONG crefs;;
VDATEHEAP();
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::AddRef ( )\n", this));
Assert(m_pUnkOuter);
crefs = m_pUnkOuter->AddRef();
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::AddRef ( %ld ) ", this, crefs));
return crefs; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::Release
//
// Synopsis: delegates Release to the controlling IUnknown
//
// Effects:
//
// Arguments: void
//
// Requires:
//
// Returns: ULONG -- the new reference count
//
// Signals:
//
// Modifies:
//
// Derivation: IUnknown
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 15-Nov-94 alexgo author
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CDefObject::Release( void ) { ULONG crefs;;
VDATEHEAP();
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::Release ( )\n", this));
Assert(m_pUnkOuter);
crefs = m_pUnkOuter->Release();
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::Release ( %ld ) ", this, crefs));
return crefs; }
/*
* IMPLEMENTATION of CDataObjectImpl methods */
//+-------------------------------------------------------------------------
//
// Member: CDefObject::GetDataDelegate
//
// Synopsis: Calls DuCacheDelegate (a glorified QueryInterface)
// for the IDataObject interface on the def handler's
// delegate
//
// Effects:
//
// Arguments: void
//
// Requires:
//
// Returns: IDataObject *
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 04-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
INTERNAL_(IDataObject FAR*) CDefObject::GetDataDelegate(void) { VDATEHEAP();
if( IsZombie() ) { return NULL; }
if (m_pDataDelegate) { return m_pDataDelegate; }
return (IDataObject FAR*)DuCacheDelegate( &m_pUnkDelegate, IID_IDataObject, (LPLPVOID) &m_pDataDelegate, m_pUnkOuter); }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::GetData
//
// Synopsis: calls IDO->GetData on the cache, if that fails, then the
// call is delegated
//
// Effects: Space for the data is allocated; caller is responsible for
// freeing.
//
// Arguments: [pformatetcIn] -- format of the data to get
// [pmedium] -- the medium to transmit the data
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IDataObject
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 05-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::GetData( LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium ) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::GetData ( %p , %p )\n", this, pformatetcIn, pmedium));
VDATEPTROUT( pmedium, STGMEDIUM ); VDATEREADPTRIN( pformatetcIn, FORMATETC );
CRefStabilize stabilize(this);
if (!HasValidLINDEX(pformatetcIn)) { return DV_E_LINDEX; }
pmedium->tymed = TYMED_NULL; pmedium->pUnkForRelease = NULL;
Assert(m_pCOleCache != NULL);
hresult = m_pCOleCache->m_Data.GetData(pformatetcIn, pmedium);
if( hresult != NOERROR ) { if( IsRunning() && GetDataDelegate() ) { hresult = m_pDataDelegate->GetData(pformatetcIn, pmedium); AssertOutStgmedium(hresult, pmedium); } else { hresult = OLE_E_NOTRUNNING; } }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetData ( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::GetDataHere
//
// Synopsis: Gets data and puts it into the medium specified in pmedium
//
// Effects:
//
// Arguments: [pformatetcIn] -- the format of the data
// [pmedium] -- the medium to put the data in
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IDataObject
//
// Algorithm: Tries the cache first, if that fails, calls GetDataHere
// on the delegate.
//
// History: dd-mmm-yy Author Comment
// 05-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::GetDataHere( LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium ) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::GetDataHere " "( %p , %p )\n", this, pformatetcIn, pmedium));
VDATEREADPTRIN( pformatetcIn, FORMATETC ); VDATEREADPTRIN( pmedium, STGMEDIUM );
CRefStabilize stabilize(this);
if (!HasValidLINDEX(pformatetcIn)) { return DV_E_LINDEX; }
Assert((m_pCOleCache) != NULL);
hresult = m_pCOleCache->m_Data.GetDataHere(pformatetcIn, pmedium);
if( hresult != NOERROR) { if( IsRunning() && GetDataDelegate() ) { hresult = m_pDataDelegate->GetDataHere(pformatetcIn, pmedium); } else { hresult = OLE_E_NOTRUNNING; } }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetDataHere " "( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::QueryGetData
//
// Synopsis: Determines whether or not a GetData call with [pformatetcIn]
// would succeed.
//
// Effects:
//
// Arguments: [pformatetcIn] -- the format of the data
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IDataObject
//
// Algorithm: Tries the cache first, then the delegate.
//
// History: dd-mmm-yy Author Comment
// 05-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::QueryGetData( LPFORMATETC pformatetcIn ) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::QueryGetData " "( %p )\n", this, pformatetcIn));
VDATEREADPTRIN( pformatetcIn, FORMATETC );
CRefStabilize stabilize(this);
if (!HasValidLINDEX(pformatetcIn)) { return DV_E_LINDEX; }
Assert((m_pCOleCache) != NULL);
hresult = m_pCOleCache->m_Data.QueryGetData(pformatetcIn);
if( hresult != NOERROR ) { if( IsRunning() && GetDataDelegate() ) { hresult = m_pDataDelegate->QueryGetData(pformatetcIn); } else { hresult = OLE_E_NOTRUNNING; } }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::QueryGetData " "( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::GetCanonicalFormatEtc
//
// Synopsis: Calls IDO->GetCanonicalFormatEtc on the delegate
//
// Effects:
//
// Arguments: [pformatetc] -- the reqested format
// [pformatetcOut] -- the canonical format
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IDataObject
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 05-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::GetCanonicalFormatEtc( LPFORMATETC pformatetc, LPFORMATETC pformatetcOut) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::GetCanonicalFormatEtc " "( %p , %p )\n", this, pformatetc, pformatetcOut));
VDATEPTROUT( pformatetcOut, FORMATETC ); VDATEREADPTRIN( pformatetc, FORMATETC );
CRefStabilize stabilize(this);
pformatetcOut->ptd = NULL; pformatetcOut->tymed = TYMED_NULL;
if (!HasValidLINDEX(pformatetc)) { return DV_E_LINDEX; }
if( IsRunning() && GetDataDelegate() ) { hresult = m_pDataDelegate->GetCanonicalFormatEtc( pformatetc, pformatetcOut); } else { hresult = OLE_E_NOTRUNNING; }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetCanonicalFormatEtc " "( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::SetData
//
// Synopsis: Calls IDO->SetData on the handler's delegate
//
// Effects:
//
// Arguments: [pformatetc] -- the format of the data
// [pmedium] -- the data's transmision medium
// [fRelease] -- if the delegate should release
// the data
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IDataObject
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 05-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::SetData( LPFORMATETC pformatetc, LPSTGMEDIUM pmedium, BOOL fRelease) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::SetData " "( %p , %p , %ld )\n", this, pformatetc, pmedium, fRelease));
VDATEREADPTRIN( pformatetc, FORMATETC ); VDATEREADPTRIN( pmedium, STGMEDIUM );
CRefStabilize stabilize(this);
if (!HasValidLINDEX(pformatetc)) { return DV_E_LINDEX; }
if( IsRunning() && GetDataDelegate() ) { hresult = m_pDataDelegate->SetData(pformatetc, pmedium, fRelease); } else { hresult = OLE_E_NOTRUNNING; }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::SetData " "( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::EnumFormatEtc
//
// Synopsis: Enumerates the formats available from an object
//
// Effects:
//
// Arguments: [dwDirection] -- indicates which set of formats are
// desired (i.e. those that can be set or
// those that can be retrieved via GetData)
// [ppenumFormatEtc] -- where to put the pointer to the
// enumerator
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm: Tries the delegate (if available). If the delegate is
// is not currently connected (or if it returns OLE_E_USEREG),
// then we attempt to build the enumerator from the reg database
//
// History: dd-mmm-yy Author Comment
// 05-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::EnumFormatEtc( DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::EnumFormatEtc ( %lu , %p )\n", this, dwDirection, ppenumFormatEtc));
VDATEPTROUT(ppenumFormatEtc, LPVOID);
CRefStabilize stabilize(this);
*ppenumFormatEtc = NULL;
if( IsRunning() && GetDataDelegate() ) { hresult = m_pDataDelegate->EnumFormatEtc (dwDirection, ppenumFormatEtc);
if (!GET_FROM_REGDB(hresult)) { LEDebugOut((DEB_TRACE, "%p OUT CDefObject::CDataObject::EnumFormatEtc " "( %lx ) [ %p ]\n", this, hresult, ppenumFormatEtc));
return hresult; } } // Not running, or object wants to use reg db anyway
hresult = OleRegEnumFormatEtc (m_clsidServer, dwDirection, ppenumFormatEtc);
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::EnumFormatEtc " "( %lx ) [ %p ]\n", this, hresult, ppenumFormatEtc));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::DAdvise
//
// Synopsis: Sets up a data advise connection
//
// Effects:
//
// Arguments: [pFormatetc] -- format to be advise'd on
// [advf] -- advise flags
// [pAdvSink] -- advise sink (whom to notify)
// [pdwConnection] -- where to put the connection ID
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IDataObject
//
// Algorithm: calls Advise on the DataAdvise cache
//
// History: dd-mmm-yy Author Comment
// 05-Nov-93 alexgo 32bit port
//
// Notes:
// We should set up an data advise holder and add the entries to
// it. We should also create a new data advise sink and register
// it with server when it is run. On receiving OnDataChange
// notifications, the advise sink would turn around and send
// OnDataChange notifications to registered client advise sinks
// This should improve run time performance and also facilitates
// better cleanup when server crashes through CoDisconnectObject
// on the advise sink registered with the server. Gopalk
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::DAdvise(FORMATETC *pFormatetc, DWORD advf, IAdviseSink * pAdvSink, DWORD * pdwConnection) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::DAdvise " "( %p , %lu , %p , %p )\n", this, pFormatetc, advf, pAdvSink, pdwConnection));
VDATEREADPTRIN( pFormatetc, FORMATETC ); VDATEIFACE( pAdvSink );
CRefStabilize stabilize(this);
IDataObject * pDataDelegate = NULL;
if( pdwConnection ) { VDATEPTROUT( pdwConnection, DWORD ); *pdwConnection = NULL; }
if( !HasValidLINDEX(pFormatetc) ) { return DV_E_LINDEX; }
if( IsRunning() ) { pDataDelegate = GetDataDelegate(); }
// setting up advises' changes state. Don't do this if we
// are in a zombie state
if( IsZombie() == FALSE ) { hresult = m_pDataAdvCache->Advise(pDataDelegate, pFormatetc, advf, pAdvSink, pdwConnection); } else { hresult = CO_E_RELEASED; }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::DAdvise " "( %lx ) [ %lu ]\n", this, hresult, (pdwConnection) ? *pdwConnection : 0));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::DUnadvise
//
// Synopsis: Tears down a data advise connection
//
// Effects:
//
// Arguments: [dwConnection] -- the advise connection to remove
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IDataObject
//
// Algorithm: delegates to the DataAdvise cache
//
// History: dd-mmm-yy Author Comment
// 05-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::DUnadvise(DWORD dwConnection) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::DUnadvise ( %lu )\n", this, dwConnection));
CRefStabilize stabilize(this);
IDataObject * pDataDelegate = NULL;
if( IsRunning() ) { pDataDelegate = GetDataDelegate(); }
hresult = m_pDataAdvCache->Unadvise(pDataDelegate, dwConnection);
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::DUnadvise " "( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::EnumDAdvise
//
// Synopsis: Enumerates advise connection (delegates to data advise cache)
//
// Effects:
//
// Arguments: [ppenumAdvise] -- where to put a pointer to the enumerator
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IDataObject
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 05-Nov-93 alexgo 32bit port
//
// Notes: We do NOT need to stabilize this method, as we make
// no outgoing calls (EnumAdvise on the data advise cache
// just allocates an advise enumerator which we implement)
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::EnumDAdvise( LPENUMSTATDATA * ppenumAdvise ) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::EnumDAdvise " "( %p )\n", this, ppenumAdvise));
VDATEPTROUT( ppenumAdvise, LPENUMSTATDATA ); *ppenumAdvise = NULL;
hresult = m_pDataAdvCache->EnumAdvise (ppenumAdvise);
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::EnumDAdvise " "( %lx ) [ %p ]\n", this, hresult, *ppenumAdvise));
return hresult; }
/*
* IMPLEMENTATION of COleObjectImpl methods * */
//+-------------------------------------------------------------------------
//
// Member: CDefObject::COleObjectImpl::GetOleDelegate
//
// Synopsis: Gets the IID_IOleObject interface from the delegate
//
// Effects:
//
// Arguments: void
//
// Requires:
//
// Returns: IOleObject *
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 05-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
INTERNAL_(IOleObject FAR*) CDefObject::GetOleDelegate(void) { VDATEHEAP();
if( IsZombie() ) { return NULL; }
return (IOleObject FAR*)DuCacheDelegate(&m_pUnkDelegate, IID_IOleObject, (LPLPVOID) &m_pOleDelegate, m_pUnkOuter); }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::COleObjectImpl::SetClientSite
//
// Synopsis: Sets the client site for the object
//
// Effects:
//
// Arguments: [pClientSite] -- pointer to the client site
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOleObject
//
// Algorithm: If running, set the client site in the server, if not
// running (or successfully set the server client site),
// save it in the handler as well
//
// History: dd-mmm-yy Author Comment
// 05-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::SetClientSite(IOleClientSite * pClientSite) { VDATEHEAP(); VDATETHREAD(this); HRESULT hresult = S_OK; IOleObject * pOleDelegate; BOOL fIsRunning;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::SetClientSite " "( %p )\n", this, pClientSite));
CRefStabilize stabilize(this);
#if DBG==1
// In Debug builds, assert that the clientsite is in the same
// apartment. This assert is harmless but shows the deficiency
// of the current design in loading INPROC servers
CStdIdentity* pStdId = NULL;
// QI for IStdIdentity
if(pClientSite && pClientSite->QueryInterface(IID_IStdIdentity, (void **)&pStdId) == NOERROR) { // Assert that DefHandler and ClientSite not in the same apartment
LEDebugOut((DEB_WARN,"Performance Alert: Default Handler and " "ClientSite not in the same apartment. " "You can avoid this performance problem " "by making the Server Dll apartment aware"));
// Release the StdIdentity as it succeded
pStdId->Release(); } #endif
fIsRunning=IsRunning();
if( (fIsRunning) && (pOleDelegate = GetOleDelegate()) != NULL) { #ifdef SERVER_HANDLER
if (m_pEmbSrvHndlrWrapper) { // Todo: Need to handle case ClientSite is the Wrapped one like DoVerb.
// Win4Assert(0 && "SetClientSite while running");
hresult = m_pEmbSrvHndlrWrapper->SetClientSite(pClientSite); } else #endif // SERVER_HANDLER
{ hresult = pOleDelegate->SetClientSite(pClientSite); }
if( hresult != NOERROR ) { goto errRtn; } }
// we shouldn't set the client site if we are in a zombie state;
// it's possible that we're zombied and have already gotten
// to the point in our destructor where we release the client
// site. Resetting it here would cause an unbalanced addref.
if( IsZombie() == FALSE ) { BOOL fLockedContainer = m_flags & DH_LOCKED_CONTAINER;
fIsRunning=IsRunning(); // I am chicken, maybe running state has changed!
hresult = DuSetClientSite(fIsRunning, pClientSite, &m_pAppClientSite, &fLockedContainer);
if(fLockedContainer) m_flags |= DH_LOCKED_CONTAINER; else m_flags &= ~DH_LOCKED_CONTAINER;
#if DBG==1
// In debug builds, update DH_LOCKFAILED flag
if(fIsRunning) { if(fLockedContainer) m_flags &= ~DH_LOCKFAILED; else m_flags |= DH_LOCKFAILED; } #endif
}
errRtn:
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::SetClientSite " "( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::GetClientSite
//
// Synopsis: returns the client site of the object
//
// Effects:
//
// Arguments: [ppClientSite] -- where to put the client site pointer
//
// Requires:
//
// Returns: NOERROR
//
// Signals:
//
// Modifies:
//
// Derivation: IOleObject
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 05-Nov-93 alexgo 32bit port
//
// Notes: We do NOT need to stabilize this call. The client
// site addref should simply addref the client site on this
// thread.
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::GetClientSite( IOleClientSite ** ppClientSite) { VDATEHEAP(); VDATETHREAD(this);
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::GetClientSite " "( %p )\n", this, ppClientSite));
VDATEPTROUT(ppClientSite, IOleClientSite *);
*ppClientSite = m_pAppClientSite; if( *ppClientSite ) { (*ppClientSite)->AddRef(); }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetClientSite " "( %lx ) [ %p ]\n", this, NOERROR, *ppClientSite));
return NOERROR; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::SetHostNames
//
// Synopsis: Sets the name that may appear in an object's window
//
// Effects: Turns the strings into atoms
//
// Arguments: [szContainerApp] -- name of the container
// [szContainerObj] -- name of the object
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOleObject
//
// Algorithm: turns the strings into atoms, calls IOO->SetHostNames
// on the delegate
//
// History: dd-mmm-yy Author Comment
// 05-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::SetHostNames( LPCOLESTR szContainerApp, LPCOLESTR szContainerObj) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult = NOERROR; OLECHAR szNull[] = OLESTR(""); DWORD cbApp, cbObj;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::SetHostNames " "( \"%ws\" , \"%ws\" )\n", this, szContainerApp, szContainerObj));
VDATEPTRIN( (LPVOID)szContainerApp, char );
CRefStabilize stabilize(this);
if( (m_flags & DH_STATIC) ) { hresult = OLE_E_STATIC; goto errRtn; }
// Make sure both arguments point to a valid string; this
// simplifies the code that follows.
if (!szContainerApp) { szContainerApp = szNull; } if (!szContainerObj) { szContainerObj = szNull; }
cbApp = (_xstrlen(szContainerApp) + 1) * sizeof(OLECHAR); cbObj = (_xstrlen(szContainerObj) + 1) * sizeof(OLECHAR); m_ibCntrObj = cbApp;
if (m_pHostNames) { PrivMemFree(m_pHostNames); }
m_pHostNames = (char *)PrivMemAlloc(cbApp+cbObj);
// Store the two strings in the m_pHostNames pointer.
if (m_pHostNames) { memcpy(m_pHostNames, szContainerApp, cbApp); memcpy(m_pHostNames + cbApp, szContainerObj, cbObj); }
if( IsRunning() && GetOleDelegate() ) { hresult = m_pOleDelegate->SetHostNames(szContainerApp, szContainerObj); }
errRtn:
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::SetHostNames " "( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::Close
//
// Synopsis: calls Close on the delegate and does cleanup
//
// Arguments: [dwFlags] -- close flags
//
// Returns: HRESULT
//
// History: dd-mmm-yy Author Comment
// 10-Jan-96 Gopalk Rewritten
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::Close(DWORD dwFlags) { LEDebugOut((DEB_TRACE, "%p _IN CDefObject::Close(%lu)\n", this, dwFlags));
// Validation checks
VDATEHEAP(); VDATETHREAD(this);
// Local variables
HRESULT hresult = NOERROR; CRefStabilize stabilize(this);
// Check if the server is running
if(IsRunning()) { // Call IOleObject::Close on the server
if(m_pOleDelegate || GetOleDelegate()) { hresult = m_pOleDelegate->Close(dwFlags); if(SUCCEEDED(hresult)) { // Discard cache if requested
if(dwFlags == OLECLOSE_NOSAVE) m_pCOleCache->DiscardCache(DISCARDCACHE_NOSAVE); } }
// Do not rely on server calling IAdviseSink::OnClose and
// stop the running server
Stop(); } else { // Check the save flags
if (dwFlags != OLECLOSE_NOSAVE) { Win4Assert(dwFlags == OLECLOSE_SAVEIFDIRTY);
// Call IOleClientSite::SaveObject if dirty
if(IsDirty()==NOERROR && m_pAppClientSite) hresult = m_pAppClientSite->SaveObject(); } }
// Assert that the container is not locked
Win4Assert(!(m_flags & DH_LOCKED_CONTAINER) && !(m_flags & DH_LOCKFAILED));
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::Close(%lx)\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::SetMoniker
//
// Synopsis: Gives a moniker to the embedding (usually called by the
// container)
//
// Effects:
//
// Arguments: [dwWhichMoniker] -- flags to indicate the type of
// moniker
// [pmk] -- the moniker
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOleObject
//
// Algorithm: delegates to the server object
//
// History: dd-mmm-yy Author Comment
// 07-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::SetMoniker( DWORD dwWhichMoniker, LPMONIKER pmk ) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult = NOERROR;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::SetMoniker " "( %lu , %p )\n", this, dwWhichMoniker, pmk));
VDATEIFACE( pmk );
CRefStabilize stabilize(this);
if( IsRunning() && GetOleDelegate() ) { hresult = m_pOleDelegate->SetMoniker(dwWhichMoniker, pmk); } // else case: return NOERROR
// this is not an error since we will call SetMoniker in Run().
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::COleObjectImpl::SetMoniker " "( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::COleObjectImpl::GetMoniker
//
// Synopsis: Calls the client site to get the object's moniker
//
// Effects:
//
// Arguments: [dwAssign] -- controls whether a moniker should be
// assigned if not already present
// [dwWhichMoniker] -- the moniker type to get
// [ppmk] -- where to put a pointer to the moniker
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOleObject
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 07-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::GetMoniker( DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER FAR* ppmk) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::GetMoniker " "( %lu , %lu , %p )\n", this, dwAssign, dwWhichMoniker, ppmk));
VDATEPTROUT( ppmk, LPMONIKER );
CRefStabilize stabilize(this);
*ppmk = NULL;
// the moniker is always accessible via the client site
if( m_pAppClientSite) { hresult = m_pAppClientSite->GetMoniker(dwAssign, dwWhichMoniker, ppmk); } else { // not running and no client site
hresult = E_UNSPEC; }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetMoniker " "( %lx ) [ %p ]\n", this, hresult, *ppmk));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::InitFromData
//
// Synopsis: Initializes the object from the data in [pDataObject]
//
// Effects:
//
// Arguments: [pDataObject] -- the data
// [fCreation] -- TRUE on creation, FALSE for data transfer
// [dwReserved] -- unused
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOleObject
//
// Algorithm: delegates to the server
//
// History: dd-mmm-yy Author Comment
// 07-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::InitFromData(LPDATAOBJECT pDataObject, BOOL fCreation, DWORD dwReserved) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::InitFromData " "( %p , %ld , %lu )\n", this, pDataObject, fCreation, dwReserved ));
if( pDataObject ) { VDATEIFACE(pDataObject); }
CRefStabilize stabilize(this);
if( IsRunning() && GetOleDelegate() ) { hresult = m_pOleDelegate->InitFromData(pDataObject, fCreation, dwReserved); } else { hresult = OLE_E_NOTRUNNING; }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::InitFromData " "( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::GetClipboardData
//
// Synopsis: Retrieves a data object that could be passed to the clipboard
//
// Effects:
//
// Arguments: [dwReserverd] -- unused
// [ppDataObject] -- where to put the pointer to the data object
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOleObject
//
// Algorithm: delegates to the server
//
// History: dd-mmm-yy Author Comment
// 07-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::GetClipboardData( DWORD dwReserved, LPDATAOBJECT * ppDataObject) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::GetClipboardData " "( %lu , %p )\n", this, dwReserved, ppDataObject));
VDATEPTROUT( ppDataObject, LPDATAOBJECT );
CRefStabilize stabilize(this);
*ppDataObject = NULL;
if( IsRunning() && GetOleDelegate() ) { hresult = m_pOleDelegate->GetClipboardData (dwReserved, ppDataObject); } else { hresult = OLE_E_NOTRUNNING; }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetClipboardData " "( %lx ) [ %p ]\n", this, hresult, *ppDataObject));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::DoVerb
//
// Synopsis: Calls a verb on the object (such as Edit)
//
// Effects: The object may launch its app, go in place, etc
//
// Arguments: [iVerb] -- the verb number
// [lpmsg] -- the windows message that caused the verb
// to be invoked
// [pActiveSite] -- the client site in which the verb was
// invoked
// [lindex] -- reserved
// [hwndParent] -- the document window (containing the object)
// [lprcPosRect] -- the object's bounding rectangle
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOleObject
//
// Algorithm: delegates to the server (launching it if necessary)
//
// History: dd-mmm-yy Author Comment
// 07-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::DoVerb( LONG iVerb, LPMSG lpmsg, LPOLECLIENTSITE pActiveSite, LONG lindex, HWND hwndParent, const RECT * lprcPosRect) { VDATEHEAP(); VDATETHREAD(this);
BOOL bStartedNow = FALSE; HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::DoVerb " "( %ld , %p , %p , %ld , %lx , %p )\n", this, iVerb, lpmsg, pActiveSite, lindex, hwndParent, lprcPosRect));
if( lpmsg ) { VDATEPTRIN( lpmsg, MSG ); }
if (pActiveSite) { VDATEIFACE( pActiveSite ); }
if( lprcPosRect ) { VDATEPTRIN(lprcPosRect, RECT); }
CRefStabilize stabilize(this);
if (lindex != 0 && lindex != -1) { hresult = DV_E_LINDEX; goto errRtn; }
if (!IsRunning()) { if( FAILED(hresult = Run(NULL)) ) { goto errRtn; } bStartedNow = TRUE; }
#ifdef SERVER_HANDLER
if (m_pEmbSrvHndlrWrapper) { LPOLECLIENTSITE pOleClientSite = NULL; BOOL fUseRunClientSite = FALSE;
// Marshal the ClientSite based on if same ClientSite passed in Run
if ( m_pRunClientSite && (m_pRunClientSite == pActiveSite)) { pOleClientSite = NULL; fUseRunClientSite = TRUE;
} else { pOleClientSite = pActiveSite; fUseRunClientSite = FALSE;
}
// Todo: Can prefetch information to pass along to ClientSiteHandler.
hresult = m_pEmbSrvHndlrWrapper->DoVerb(iVerb, lpmsg, fUseRunClientSite, pOleClientSite, lindex, hwndParent, lprcPosRect); } else #endif // SERVER_HANDLER
{ if( !GetOleDelegate() ) { hresult = E_NOINTERFACE; } else { hresult = m_pOleDelegate->DoVerb(iVerb, lpmsg, pActiveSite, lindex, hwndParent, lprcPosRect); } }
if (FAILED(hresult) && bStartedNow) { Close(OLECLOSE_NOSAVE); }
errRtn: LEDebugOut((DEB_TRACE, "%p OUT CDefObject::DoVerb " "( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::EnumVerbs
//
// Synopsis: Enumerates the verbs that an object supports
//
// Effects:
//
// Arguments: [ppenumOleVerb] -- where to put the verb enumerator
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOleObject
//
// Algorithm: delegates to the cache (if running), otherwise looks it up
// in the registration database
//
// History: dd-mmm-yy Author Comment
// 07-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::EnumVerbs( IEnumOLEVERB ** ppenumOleVerb) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::EnumVerbs " "( %p )\n", this, ppenumOleVerb));
VDATEPTROUT( ppenumOleVerb, IEnumOLEVERB FAR );
CRefStabilize stabilize(this);
*ppenumOleVerb = NULL;
if( IsRunning() && GetOleDelegate() ) {
hresult = m_pOleDelegate->EnumVerbs (ppenumOleVerb);
if (!GET_FROM_REGDB(hresult)) { goto errRtn; } } // Not running, or object deferred to us, so interrogate reg db
hresult = OleRegEnumVerbs( m_clsidServer, ppenumOleVerb);
errRtn: LEDebugOut((DEB_TRACE, "%p OUT CDefObject::EnumVerbs " "( %lx ) [ %p ]\n", this, hresult, *ppenumOleVerb));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::Update
//
// Synopsis: Brings any caches or views up-to-date
//
// Effects: may launch the server (if not already running)
//
// Arguments: void
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOleObject
//
// Algorithm: delegates to the server, launching it if it is not
// already running
//
// History: dd-mmm-yy Author Comment
// 07-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::Update( void ) { VDATEHEAP(); VDATETHREAD(this);
BOOL bStartedNow = FALSE; HRESULT hresult = NOERROR; HRESULT hrLock;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::Update ( )\n", this ));
CRefStabilize stabilize(this);
if( (m_flags & DH_STATIC) ) { hresult = OLE_E_STATIC; goto errRtn; }
if (!IsRunning()) { if( FAILED(hresult = Run(NULL))) { goto errRtn; } bStartedNow = TRUE; }
// as a convenience to the server, we make the connection strong
// for the duration of the update; thus, if lock container (of
// embedings of this server) is done with co lock obj external,
// nothing special need be done.
hrLock = LockRunning(TRUE, FALSE);
if( GetOleDelegate() ) { hresult = m_pOleDelegate->Update(); }
if (hresult == NOERROR) { m_flags &= ~DH_INIT_NEW;
if (bStartedNow) { hresult = m_pCOleCache->UpdateCache( GetDataDelegate(), UPDFCACHE_ALLBUTNODATACACHE, NULL); } else { // already running...
// normal caches would have got updated as a result
// of SendOnDataChange of the object.
hresult = m_pCOleCache->UpdateCache( GetDataDelegate(), UPDFCACHE_IFBLANKORONSAVECACHE, NULL); } }
// balance lock above; do not release on last unlock; i.e., siliently
// restore to the state before this routine was called.
if( hrLock == NOERROR ) { LockRunning(FALSE, FALSE); }
if( bStartedNow ) { Close(OLECLOSE_SAVEIFDIRTY); }
errRtn:
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::Update " "( %lx )\n", this, hresult ));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::IsUpToDate
//
// Synopsis: returns whether or not the embedding is up-to-date
//
// Effects:
//
// Arguments: void
//
// Requires:
//
// Returns: HRESULT (NOERROR == is up to date)
//
// Signals:
//
// Modifies:
//
// Derivation: IOleObject
//
// Algorithm: delegates to the server if it is running
//
// History: dd-mmm-yy Author Comment
// 07-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::IsUpToDate(void) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::IsUpToDate ( )\n", this));
CRefStabilize stabilize(this);
if( (m_flags & DH_STATIC) ) { hresult = NOERROR; } else if( IsRunning() && GetOleDelegate() ) { // if running currently, propogate call; else fail
hresult = m_pOleDelegate->IsUpToDate(); } else { hresult = OLE_E_NOTRUNNING; }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::IsUpToDate " "( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::SetExtent
//
// Synopsis: Set's the size boundaries on an object
//
// Effects:
//
// Arguments: [dwDrawAspect] -- the drawing aspect (such as ICON, etc)
// [lpsizel] -- the new size (in HIMETRIC)
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOleObject
//
// Algorithm: delegates to the server if running
//
// History: dd-mmm-yy Author Comment
// 07-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::SetExtent( DWORD dwDrawAspect, LPSIZEL lpsizel ) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::SetExtent " "( %lu , %p )\n", this, dwDrawAspect, lpsizel));
VDATEPTRIN( lpsizel, SIZEL );
CRefStabilize stabilize(this);
if( (m_flags & DH_STATIC) ) { hresult = OLE_E_STATIC; } else if( IsRunning() && GetOleDelegate() ) { hresult = m_pOleDelegate->SetExtent(dwDrawAspect, lpsizel); } else { hresult = OLE_E_NOTRUNNING; }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::SetExtent " "( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::GetExtent
//
// Synopsis: Retrieve the size of the object
//
// Effects:
//
// Arguments: [dwDrawAspect] -- the drawing aspect (such as icon)
// [lpsizel] -- where to put the size
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOleObject
//
// Algorithm: Tries the server first, the the cache if that fails
//
// History: dd-mmm-yy Author Comment
// 07-Nov-93 alexgo 32bit port
//
// Notes: Hacks for bogus WordArt2.0 app.
// REVIEW32: We may want to take them out for 32bit
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::GetExtent( DWORD dwDrawAspect, LPSIZEL lpsizel ) { VDATEHEAP(); VDATETHREAD(this);
VDATEPTROUT(lpsizel, SIZEL);
HRESULT hresult = NOERROR; BOOL fNoDelegate = TRUE;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::GetExtent " "( %lu , %p )\n", this, dwDrawAspect, lpsizel));
CRefStabilize stabilize(this);
lpsizel->cx = 0; lpsizel->cy = 0;
// if server is running try to get extents from the server
if( IsRunning() && GetOleDelegate() ) { fNoDelegate = FALSE; hresult = m_pOleDelegate->GetExtent(dwDrawAspect, lpsizel); }
// if there is error or object is not running or WordArt2 returns zero
// extents, then get extents from Cache
if (hresult != NOERROR || fNoDelegate || (0==lpsizel->cx && 0==lpsizel->cy)) { // Otherwise try to get extents from cache
Assert(m_pCOleCache != NULL); hresult = m_pCOleCache->GetExtent(dwDrawAspect, lpsizel); }
// WordArt2.0 is giving negative extents!!
if (SUCCEEDED(hresult)) { lpsizel->cx = LONG_ABS(lpsizel->cx); lpsizel->cy = LONG_ABS(lpsizel->cy); }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetExtent " "( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::Advise
//
// Synopsis: Sets up an advise connection for things like close, save,
// rename, etc.
//
// Effects: Creates an OleAdviseHolder
//
// Arguments: [pAdvSink] -- whom to advise
// [pdwConnection] -- where to put the connection ID
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOleObject
//
// Algorithm: delegates to the server and creates a an OleAdviseHolder
// if one doesn't already exist
//
// History: dd-mmm-yy Author Comment
// 07-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::Advise(IAdviseSink *pAdvSink, DWORD *pdwConnection) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::Advise " "( %p , %p )\n", this, pAdvSink, pdwConnection));
VDATEIFACE( pAdvSink ); VDATEPTROUT( pdwConnection, DWORD );
CRefStabilize stabilize(this);
*pdwConnection = NULL;
if( (m_flags & DH_STATIC) ) { hresult = OLE_E_STATIC; goto errRtn; }
// if defhndlr got running without going through run, setup advise.
// The call to run (via ProxyMgr::Connect) always comes before any
// other method call in the default handler. Thus it is safe to
// assume that there is no earlier point by which this advise (or any
// other of the calls) should have been done.
if( IsRunning() && m_dwConnOle == 0L && GetOleDelegate() ) { if( IsZombie() ) { hresult = CO_E_RELEASED; goto errRtn; }
// delegate to the server
hresult = m_pOleDelegate->Advise((IAdviseSink *)&m_AdviseSink, &m_dwConnOle);
if( hresult != NOERROR ) { goto errRtn; } }
// if we are in a zombie state, we shouldn't go allocate more
// memory.
if( IsZombie() ) { hresult = CO_E_RELEASED; }
if( m_pOAHolder == NULL ) { hresult = CreateOleAdviseHolder((IOleAdviseHolder **)&m_pOAHolder); if( hresult != NOERROR ) { goto errRtn; } }
// stuff the advise notification in our advise holder
hresult = m_pOAHolder->Advise(pAdvSink, pdwConnection);
errRtn:
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::Advise " "( %lx ) [ %lu ]\n", this, hresult, (pdwConnection)? *pdwConnection : 0));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::COleObjectImpl::Unadvise
//
// Synopsis: Tears down an advise connection
//
// Effects:
//
// Arguments: [dwConnection] -- the connection to destroy
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOleObject
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 07-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::Unadvise(DWORD dwConnection) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::Unadvise " "( %lu )\n", this, dwConnection));
CRefStabilize stabilize(this);
if( m_pOAHolder == NULL ) { // no one registered
hresult = OLE_E_NOCONNECTION; } else { hresult = m_pOAHolder->Unadvise(dwConnection); }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::Unadvise " "( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::EnumAdvise
//
// Synopsis: Enumerate the advises currently established
//
// Effects:
//
// Arguments: [ppenumAdvise] -- where to put the advise enumerator
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOleObject
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 07-Nov-93 alexgo 32bit port
//
// Notes: We do NOT need to stabilize because EnumAdvise only
// allocates some memory for an enumerator and returns.
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::EnumAdvise( LPENUMSTATDATA *ppenumAdvise ) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::EnumAdvise " "( *p )\n", this, ppenumAdvise));
VDATEPTROUT( ppenumAdvise, LPENUMSTATDATA ); *ppenumAdvise = NULL;
if( m_pOAHolder == NULL ) { // no one registered
hresult = E_UNSPEC; } else { hresult = m_pOAHolder->EnumAdvise(ppenumAdvise); }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::EnumAdvise " "( %lx ) [ %p ]\n", this, hresult, *ppenumAdvise));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::GetMiscStatus
//
// Synopsis: Get misc status bits, such as OLEMISC_ONLYICONIC
//
// Effects:
//
// Arguments: [dwAspect] -- the drawing aspect we're concerned about
// [pdwStatus] -- where to put the status bits
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOleObject
//
// Algorithm: Delegates to the server. If not there, or if it returns
// OLE_E_USEREG, then lookup in the registration database
//
// History: dd-mmm-yy Author Comment
// 07-Nov-93 alexgo 32bit port
// 20-Nov-96 Gopalk Cache MiscStatus bits
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::GetMiscStatus( DWORD dwAspect, DWORD *pdwStatus) { LEDebugOut((DEB_TRACE, "%p _IN CDefObject::GetMiscStatus(%lu, %p)\n", this, dwAspect, pdwStatus));
// Validation checks
VDATEHEAP(); VDATETHREAD(this); VDATEPTROUT(pdwStatus, DWORD);
// Local variables
HRESULT hresult;
// Stabilize
CRefStabilize stabilize(this);
// Initialize
*pdwStatus = 0; hresult = OLE_S_USEREG;
if(IsRunning()) { #ifdef SERVER_HANDLER
if(m_pEmbSrvHndlrWrapper && (DVASPECT_CONTENT == dwAspect)) { *pdwStatus = m_ContentMiscStatusUser; hresult = m_hresultContentMiscStatus; } else #endif // SERVER_HANDLER
if(GetOleDelegate()) { // Check if MiscStatus bits have been cached for this instance
// of server for DVASPECT_CONTENT
if(m_ContentSRVMSHResult != 0xFFFFFFFF && dwAspect == DVASPECT_CONTENT) { *pdwStatus = m_ContentSRVMSBits; hresult = m_ContentSRVMSHResult; } else { // Ask the running server
hresult = m_pOleDelegate->GetMiscStatus(dwAspect, pdwStatus);
// Cache the server MiscStatus bits for DVASPECT_CONTENT
if(dwAspect == DVASPECT_CONTENT) { m_ContentSRVMSBits = *pdwStatus; m_ContentSRVMSHResult = hresult; } } } }
// Check if we have to obtain MiscStatus bits from the registry
if (GET_FROM_REGDB(hresult)) { // Check if registry MiscStatus bits have been cached for DVASPECT_CONTENT
if(m_ContentREGMSHResult != 0xFFFFFFFF && dwAspect == DVASPECT_CONTENT) { *pdwStatus = m_ContentREGMSBits; hresult = m_ContentREGMSHResult; } else { // Hit the registry
hresult = OleRegGetMiscStatus (m_clsidServer, dwAspect, pdwStatus); if(hresult == NOERROR) { // Update the MiscStatus flags
if((m_flags & DH_STATIC)) (*pdwStatus) |= (OLEMISC_STATIC | OLEMISC_CANTLINKINSIDE); else if(CoIsOle1Class(m_clsidServer)) (*pdwStatus) |= OLEMISC_CANTLINKINSIDE;
// Cache the registry MiscStatus bits for DVASPECT_CONTENT
if(dwAspect == DVASPECT_CONTENT) { m_ContentREGMSBits = *pdwStatus; m_ContentREGMSHResult = hresult; } } } }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetMiscStatus(%lx) [%lx]\n", this, hresult, *pdwStatus)); return hresult; } //+-------------------------------------------------------------------------
//
// Member: CDefObject::SetColorScheme
//
// Synopsis: Sets the palette for an object
//
// Effects:
//
// Arguments: [lpLogpal] -- the palette
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOleObject
//
// Algorithm: Delegates to the server
//
// History: dd-mmm-yy Author Comment
// 07-Nov-93 alexgo 32bit
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::SetColorScheme( LPLOGPALETTE lpLogpal ) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::SetColorScheme " "( %p )\n", this, lpLogpal));
CRefStabilize stabilize(this);
if( (m_flags & DH_STATIC) ) { hresult = OLE_E_STATIC; } else if( lpLogpal == NULL || lpLogpal->palNumEntries == NULL) { hresult = E_INVALIDARG; } else if( IsRunning() && GetOleDelegate() ) { hresult = m_pOleDelegate->SetColorScheme (lpLogpal); } else { hresult = OLE_E_NOTRUNNING; }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::SetColorScheme " "( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::GetUserClassID
//
// Synopsis: Retrieves the class ID for the object
//
// Effects:
//
// Arguments: [pClassID] -- where to put the class ID
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOleObject
//
// Algorithm: Delegates to the server, or if not running (or if it
// fails the delegated call), then we attempt
// to get the class id from the storage.
//
// History: dd-mmm-yy Author Comment
// 07-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::GetUserClassID( CLSID *pClassID ) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::GetUserClassID " "( %p )\n", this, pClassID));
VDATEPTROUT(pClassID, CLSID);
CRefStabilize stabilize(this);
if( IsRunning() ) { #ifdef SERVER_HANDLER
if (m_pEmbSrvHndlrWrapper ) { *pClassID = m_clsidUser; hresult = m_hresultClsidUser; goto errRtn;
} else #endif // SERVER_HANDLER
if ( GetOleDelegate() ) { hresult = m_pOleDelegate->GetUserClassID(pClassID); // success! We don't have to figure it out ourselves, so
// skip to the end and exit
if (hresult == NOERROR ) { goto errRtn; } } }
if( !IsEqualCLSID(m_clsidServer, CLSID_NULL) ) { *pClassID = m_clsidServer; hresult = NOERROR; } else { hresult = GetClassBits(pClassID); }
errRtn:
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetUserClassID " "( %lx ) [ %p ]\n", this, hresult, pClassID));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::GetUserType
//
// Synopsis: Gets a descriptive string about the object for the user
//
// Effects:
//
// Arguments: [dwFromOfType] -- whether to get a short/long/etc version
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOleObject
//
// Algorithm: Delegates to the server, failing that, trys the registration
// database, failing that, tries to read from the storage
//
// History: dd-mmm-yy Author Comment
// 07-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::GetUserType( DWORD dwFormOfType, LPOLESTR *ppszUserType) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::GetUserType " "( %lu , %p )\n", this, dwFormOfType, ppszUserType));
VDATEPTROUT(ppszUserType, LPOLESTR);
CRefStabilize stabilize(this);
*ppszUserType = NULL;
if( IsRunning() && GetOleDelegate() ) { hresult = m_pOleDelegate->GetUserType (dwFormOfType, ppszUserType);
if (!GET_FROM_REGDB(hresult)) { goto errRtn; } }
if( (hresult = OleRegGetUserType( m_clsidServer, dwFormOfType, ppszUserType)) == NOERROR) { goto errRtn; }
// Try reading from storage
// This really ugly bit of 16bit code tries to read the user type
// from the storage. If that fails, then we look in the registry
if( NULL == m_pStg || NOERROR != (hresult = ReadFmtUserTypeStg(m_pStg, NULL, ppszUserType)) || NULL == *ppszUserType ) { OLECHAR sz[256]; long cb = sizeof(sz);// ReqQueryValue expects
// a *byte* count
*ppszUserType = UtDupString ( (ERROR_SUCCESS == RegQueryValue (HKEY_CLASSES_ROOT, OLESTR("Software\\Microsoft\\OLE2\\UnknownUserType"), sz, &cb)) ? (LPCOLESTR)sz : OLESTR("Unknown"));
if (NULL != *ppszUserType) { hresult = NOERROR; } else { hresult = E_OUTOFMEMORY; } }
errRtn:
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetUserType " "( %lx ) [ %p ]\n", this, hresult, *ppszUserType));
return hresult; }
/*
* IMPLEMENTATION of CROImpl methods * * We never delegate to the server. This is by design. */
//+-------------------------------------------------------------------------
//
// Member: CDefObject::GetRunningClass
//
// Synopsis: Get the class id of the server
//
// Effects:
//
// Arguments: [lpClsid] -- where to put the class id
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IRunnableObject
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 07-Nov-93 alexgo 32bit port
//
// Notes: We do not need to stabilize this call as no outgoing
// calls are made.
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::GetRunningClass(LPCLSID lpClsid) { VDATEHEAP(); VDATETHREAD(this);
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::GetRunningClass " "( %p )\n", this, lpClsid));
VDATEPTROUT(lpClsid, CLSID);
*lpClsid = m_clsidServer;
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetRunningClass " "( %lx ) [ %p ]\n", this, NOERROR, lpClsid));
return NOERROR; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::Run
//
// Synopsis: Sets the object running (if it isn't already)
//
// Effects: may launch the server
//
// Arguments: [pbc] -- the bind context (unused)
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IRunnableObject
//
// Algorithm: If already running, return. Otherwise, get the proxy
// manager to create the server. Initialize the storage
// and caches, and set the host name for the server's window.
//
// History: dd-mmm-yy Author Comment
// 07-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::Run(LPBINDCTX pbc) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult; IDataObject FAR* pDataDelegate = NULL; IOleObject FAR* pOleDelegate = NULL; IPersistStorage FAR* pPStgDelegate = NULL; IMoniker FAR* pmk = NULL; BOOL fLockedContainer; DWORD dwMiscStatus;
// NOTE: ignore pbc for now
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::Run ( %p )\n", this, pbc));
CRefStabilize stabilize(this);
if( IsRunning() ) { hresult = S_OK; // just return the error code
goto errRtn2; }
if( (m_flags & DH_STATIC) ) { hresult = OLE_E_STATIC; goto errRtn2; }
if( IsZombie() ) { hresult = CO_E_RELEASED; goto errRtn2; }
if( FAILED(hresult = CreateDelegate()) ) { // just return the error code
goto errRtn2; }
if (m_pProxyMgr != NULL) {
#ifdef SERVER_HANDLER
IServerHandler *pSrvHndl = NULL;
hresult = m_pProxyMgr->CreateServerWithEmbHandler(m_clsidServer, CLSCTX_LOCAL_SERVER | CLSCTX_ESERVER_HANDLER , IID_IServerHandler,(void **) &pSrvHndl,NULL); if(FAILED(hresult)) Win4Assert(NULL == pSrvHndl); #else
hresult = m_pProxyMgr->CreateServer(m_clsidServer, CLSCTX_LOCAL_SERVER, NULL); #endif // SERVER_HANDLER
if (FAILED(hresult)) { goto errRtn; }
// if there is a serverHandler, create a wrapper object for handling standard interfaces
#ifdef SERVER_HANDLER
if (pSrvHndl) { m_pEmbSrvHndlrWrapper = CreateEmbServerWrapper(m_pUnkOuter,pSrvHndl); pSrvHndl->Release(); } else { m_pEmbSrvHndlrWrapper = NULL; } #endif // SERVER_HANDLER
}
// NOTE: the lock state of the proxy mgr is not changed; it remembers
// the state and sets up the connection correctly.
// server is running; normally this coincides with locking the
// container, but we keep a separate flag since locking the container
// may fail.
m_flags |= DH_FORCED_RUNNING;
// Lock the container
fLockedContainer = m_flags & DH_LOCKED_CONTAINER;
DuLockContainer(m_pAppClientSite, TRUE, &fLockedContainer );
if( fLockedContainer ) { m_flags |= DH_LOCKED_CONTAINER; } else { m_flags &= ~DH_LOCKED_CONTAINER; }
#if DBG==1
// In debug builds, update DH_LOCKFAILED flag
if(fLockedContainer) m_flags &= ~DH_LOCKFAILED; else m_flags |= DH_LOCKFAILED; #endif
#ifdef SERVER_HANDLER
if (m_pEmbSrvHndlrWrapper) { MInterfacePointer *pIRDClientSite = NULL; CStdIdentity *pStdid = NULL; CClientSiteHandler *pClientSiteHandler = NULL; GUID riid = IID_IOleClientSite; //Reference to the identifier of the interface
BOOL fHasIPSite = FALSE; IUnknown *pUnk = NULL; //Pointer to the interface to be marshaled
CXmitRpcStream Stm;
if (m_pAppClientSite) {
// Only wrap ClientSite if there is not an existing Identity.
if (NOERROR != LookupIDFromUnk(m_pAppClientSite, GetCurrentApartmentId(),0,&pStdid)) { Assert(NULL == pClientSiteHandler);
hresult = CreateClientSiteHandler(m_pAppClientSite,&pClientSiteHandler,&fHasIPSite);
riid = IID_IClientSiteHandler; pUnk = (IUnknown *) (IClientSiteHandler *) pClientSiteHandler; } else { riid = IID_IOleClientSite; pUnk = (IUnknown *) (IOleClientSite*) m_pAppClientSite; pUnk->AddRef(); }
hresult = CoMarshalInterface(&Stm,riid, pUnk, MSHCTX_DIFFERENTMACHINE, NULL, MSHLFLAGS_NORMAL);
if (SUCCEEDED(hresult)) { Stm.AssignSerializedInterface((InterfaceData **) &pIRDClientSite); }
m_pRunClientSite = m_pAppClientSite; // Remember ClientSite on Run.
}
Assert(m_dwConnOle == 0L);
hresult = m_pEmbSrvHndlrWrapper->Run(m_flags, riid, pIRDClientSite, fHasIPSite, (LPOLESTR)m_pHostNames, (LPOLESTR)(m_pHostNames + m_ibCntrObj), (IStorage *) m_pStg, (IAdviseSink *) &m_AdviseSink, &m_dwConnOle, &m_hresultClsidUser, &m_clsidUser, &m_hresultContentMiscStatus, &m_ContentMiscStatusUser );
if (pIRDClientSite) CoTaskMemFree(pIRDClientSite);
if (pStdid) pStdid->Release();
if (pUnk) pUnk->Release();
// !!! Make sure on error don't set up Cache.
if (NOERROR != hresult) { goto errRtn; }
// set up any cached interfaces
// !!!!!TODO: Not All LeSuite Linking Tests Pass when Cache DataObject through ServerHandler.
if (!m_pDataDelegate) { if (NOERROR == m_pEmbSrvHndlrWrapper->m_Unknown.QueryInterface(IID_IDataObject,(void **) &m_pDataDelegate)) { m_pUnkOuter->Release(); } }
} else #endif // SERVER_HANDLER
{ // Check if we have client site
if(m_pAppClientSite) { // Clear the cached MiscStatus bits
m_ContentSRVMSBits = 0; m_ContentSRVMSHResult = 0xFFFFFFFF;
// Get MiscStatus bits from the running server
hresult = GetMiscStatus(DVASPECT_CONTENT, &dwMiscStatus);
// Set the client site first if OLEMISC_SETCLIENTSITEFIRST bit is set
if(hresult == NOERROR && (dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST) && (pOleDelegate = GetOleDelegate())) hresult = pOleDelegate->SetClientSite(m_pAppClientSite); else if(hresult != NOERROR) { hresult = NOERROR; dwMiscStatus = 0; } } if(hresult != NOERROR) goto errRtn;
if( pPStgDelegate = GetPSDelegate() ) { if( m_pStg) { if( (m_flags & DH_INIT_NEW) ) { hresult = pPStgDelegate->InitNew(m_pStg); } else { hresult = pPStgDelegate->Load(m_pStg); } if (hresult != NOERROR) { // this will cause us to stop the
// the server we just launced
goto errRtn; } } }
if(pOleDelegate || (pOleDelegate = GetOleDelegate())) { // REVIEW MM1: what are we supposed to do in case of failure
if(m_pAppClientSite && !(dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)) { pOleDelegate->SetClientSite(m_pAppClientSite); }
if (m_pHostNames) { if (hresult = pOleDelegate->SetHostNames((LPOLESTR)m_pHostNames, (LPOLESTR)(m_pHostNames + m_ibCntrObj)) != NOERROR) { goto errRtn; } }
// set single ole advise (we multiplex)
Assert(m_dwConnOle == 0L);
if ((hresult = pOleDelegate->Advise((IAdviseSink *)&m_AdviseSink, &m_dwConnOle)) != NOERROR) { goto errRtn; }
if(m_pAppClientSite != NULL && m_pAppClientSite->GetMoniker (OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_OBJREL, &pmk) == NOERROR) { AssertOutPtrIface(NOERROR, pmk); pOleDelegate->SetMoniker(OLEWHICHMK_OBJREL, pmk); pmk->Release(); }
}
}
Win4Assert(NOERROR == hresult);
if( pDataDelegate = GetDataDelegate() ) { // inform cache that we are running
Assert(m_pCOleCache != NULL);
m_pCOleCache->OnRun(pDataDelegate);
// Enumerate all the advises we stored while we were either not
// running or running the previous time, and send them to the
// now-running object.
m_pDataAdvCache->EnumAndAdvise(pDataDelegate, TRUE); }
errRtn: if(hresult == NOERROR) { // Clear the cached MiscStatus bits if not cleared before
#ifdef SERVER_HANDLER
if(m_pEmbSrvHndlrWrapper) { m_ContentSRVMSBits = 0; m_ContentSRVMSHResult = 0xFFFFFFFF; } else #endif // SERVER_HANDLER
if(!m_pAppClientSite) { m_ContentSRVMSBits = 0; m_ContentSRVMSHResult = 0xFFFFFFFF; } } else { // Stop the running object
Stop();
// Assert that the container is not locked
Win4Assert(!(m_flags & DH_LOCKED_CONTAINER) && !(m_flags & DH_LOCKFAILED)); }
errRtn2:
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::Run " "( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::Stop
//
// Synopsis: Undoes some of Run() (stops the server)...internal function
//
// Effects:
//
// Arguments: void
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm: unadvise connections (if any), stop the cache, disconnect
// from the proxy manager and unlock the container
//
// History: dd-mmm-yy Author Comment
// 07-Nov-93 alexgo 32bit port
//
// Notes:
//
// undo effects of Run(); some of this work is done also in IsRunning
// when we detect we are not running (in case the server crashed).
//--------------------------------------------------------------------------
INTERNAL CDefObject::Stop (void) { BOOL fLockedContainer;
VDATEHEAP();
LEDebugOut((DEB_ITRACE, "%p _IN CDefObject::CROImpl::Stop " "( )\n", this));
CRefStabilize stabilize(this);
if( !IsRunning() ) { // NOTE: ISRUNNING below does some of this cleanup
goto errRtn; // return NOERROR
}
// NOTE: we cleanup connections which point directly back to us;
// connections which point back to the app (e.g, the clientsite and
// data advise) are left alone; an app must know how to use
// CoDisconnectObject if deterministic shutdown is desired.
if( m_dwConnOle != 0L && GetOleDelegate() ) { m_pOleDelegate->Unadvise(m_dwConnOle); m_dwConnOle = 0L; }
if( m_pDataDelegate ) { m_pDataAdvCache->EnumAndAdvise(m_pDataDelegate, FALSE); }
// inform cache that we are not running (Undoes advise)
Assert(m_pCOleCache != NULL); m_pCOleCache->OnStop();
#ifdef SERVER_HANDLER
if (m_pEmbSrvHndlrWrapper) { CEmbServerWrapper *pSrvHndlr = m_pEmbSrvHndlrWrapper;
m_pEmbSrvHndlrWrapper = NULL; m_pRunClientSite = NULL;
// need to release any interfaces the Handler Wraps
if(m_pDataDelegate) { m_pUnkOuter->AddRef(); SafeReleaseAndNULL((IUnknown **)&m_pDataDelegate); }
// NULL out m_pSrvHndl before Release since out call could case re-entrance.
pSrvHndlr->m_Unknown.Release(); } #endif // SERVER_HANDLER
#if DBG==1
// In debug builds, set DH_WILLUNLOCK flag
m_flags |= DH_WILLUNLOCK; #endif
// Reset DH_FORCED_RUNNING flag and disconnect proxy manager
m_flags &= ~DH_FORCED_RUNNING; if(m_pProxyMgr) m_pProxyMgr->Disconnect();
// Unlock the container site
fLockedContainer = (m_flags & DH_LOCKED_CONTAINER); if(fLockedContainer) { m_flags &= ~DH_LOCKED_CONTAINER; DuLockContainer(m_pAppClientSite, FALSE, &fLockedContainer); } Win4Assert(!fLockedContainer); #if DBG==1
// In debug builds, reset the DH_LOCKFAILED and DH_WILLUNLOCK flags
m_flags &= ~DH_LOCKFAILED; m_flags &= ~DH_WILLUNLOCK; #endif
errRtn: LEDebugOut((DEB_ITRACE, "%p OUT CDefObject::Stop " "( %lx )\n", this, NOERROR ));
return NOERROR; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::IsRunning
//
// Arguments: None
//
// Returns: BOOL
//
// Derivation: IRunnableObject
//
// Notes: Detects if the local server has crashed and does cleanup
// so that the user can activate the embedding in the same
// session.
//
// History: dd-mmm-yy Author Comment
// 06-Dec-96 Gopalk Rewritten
//--------------------------------------------------------------------------
STDMETHODIMP_(BOOL) CDefObject::IsRunning(void) { LEDebugOut((DEB_TRACE, "%p _IN CDefObject::IsRunning()\n", this));
// Validation checks
VDATEHEAP(); VDATETHREAD(this);
// Local variable
BOOL fReturn = FALSE; HRESULT hStatus;
CRefStabilize stabilize(this);
// Check if the inner object has been created
if(m_pUnkDelegate) { // DEFHANDLER either has proxy manager as the inner object
// for out of proc server objects or actual server as the
// inner object for inproc server objects.
// Assert that this is TRUE
Win4Assert((m_pProxyMgr != NULL) == !!(m_flags & DH_INPROC_HANDLER)); if(m_pProxyMgr) { // Out of proc server object.
// Check with the proxy manager whether it is connected to the
// server object. We cannot rely on the DH_FORCED_RUNNING flag
// to indicate run status because the DEFHANDLER could have been
// marshaled from the embedding conatiner and unmarshaled in the
// link container. The DEFHANDLER created by unmarshaling in the
// link container is always in the running state due to the
// requirement that IOleItemContainer::GetObject is required to
// put the embedding in running state when its bind speed
// parameter permits, else it is supposed to return
// MK_E_EXCEEDEDDEADLINE. Further, CoMarshalInterface fails
// if the the proxy manager is not connected
fReturn = m_pProxyMgr->IsConnected(); if(fReturn) { // The proxymanager is connected to the server object
// Check the status of connection with the server object
hStatus = m_pProxyMgr->GetConnectionStatus(); if(hStatus != S_OK) { // Either Server object called CoDisconnectObject or
// its apartment crashed or unitialized breaking the
// external connection to the objects in that apartment
// Clean up the state
Win4Assert(!"Local Server crashed or disconnected");
// Reset flags
m_flags &= ~DH_FORCED_RUNNING;
// Reset advise connection and recover the references
// placed by the server on the handler advise sink
m_dwConnOle = 0L; CoDisconnectObject((IUnknown *) &m_AdviseSink, 0);
// Inform cache that the local server crashed
if(m_pCOleCache) m_pCOleCache->OnCrash();
// Inform and cleanup data advice cache
m_pDataAdvCache->EnumAndAdvise(NULL, FALSE);
// Unlock the container if it is was locked
BOOL fCurLock = !!(m_flags & DH_LOCKED_CONTAINER);
if(fCurLock) { DuLockContainer(m_pAppClientSite, FALSE, &fCurLock); m_flags &= ~DH_LOCKED_CONTAINER; } Win4Assert(!fCurLock); #if DBG==1
// In debug builds, reset DH_LOCKFAILED flag
m_flags &= ~DH_LOCKFAILED; #endif
// Inform ProxyManager to disconnect
m_pProxyMgr->Disconnect();
// Reset fReturn
fReturn = FALSE; } } } else { // Inproc server object.
// COM supports self embedding by allowing separate class
// objects to be registered for instatiating INPROC_SERVER
// and LOCAL_SERVER objects. Apps typically ask the Default
// handler to aggregate their INPROC_SERVER objects by
// using OleCreateEmbeddingHelper api so that embedding
// interfaces like IViewObject are supported. But this
// creates problem for self linking because link moniker
// binds to inproc servers in preference to local servers.
// As the inproc server object obtained from the INPROC_SERVER
// class factory is the default handler, it will not delegate
// method calls to the actual server object unless it thinks that
// the local object is running. Below we check if we are dealing
// with an embedded object using the assumption that embedded objects
// are initialized through IStorage. The above assumption is
// questionable but we are helpless.
if (!(m_flags & DH_EMBEDDING) || (m_flags & DH_FORCED_RUNNING)) fReturn = TRUE; } } else Win4Assert((m_flags & DH_DELAY_CREATE) && m_pCFDelegate != NULL);
// Sanity checks
if(fReturn) { if(m_flags & DH_FORCED_RUNNING) { Win4Assert((m_flags & DH_LOCKED_CONTAINER) || (m_flags & DH_LOCKFAILED)); Win4Assert(!(m_flags & DH_UNMARSHALED)); } else if(m_pProxyMgr) { Win4Assert(!m_pAppClientSite); Win4Assert(!m_pStg); Win4Assert(!(m_flags & DH_LOCKED_CONTAINER)); Win4Assert(!(m_flags & DH_LOCKFAILED)); Win4Assert(m_flags & DH_UNMARSHALED); Win4Assert(!(m_flags & DH_EMBEDDING)); } } else { if(!(m_flags & DH_OLE1SERVER)) { // DDE IProxyManager::IsConnected returns FLASE until
// either IPersistStorage::Load or IPersistStorage::InitNew
// is called on it
Win4Assert(!(m_flags & DH_FORCED_RUNNING)); Win4Assert((m_flags & DH_WILLUNLOCK) || !(m_flags & DH_LOCKED_CONTAINER)); Win4Assert((m_flags & DH_WILLUNLOCK) || !(m_flags & DH_LOCKFAILED)); } }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::IsRunning(%lu)\n", this, fReturn));
return fReturn; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::SetContainedObject
//
// Synopsis: sets the embedding status of an object
//
// Effects:
//
// Arguments: [fContained] -- TRUE indicates we are an embedding/
// FALSE otherwise
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IRunnableObject
//
// Algorithm: Sets flags, if we are an improc handler, we will call
// IRunnableObject->LockRunning(FALSE) to unlock ourselves
//
// History: dd-mmm-yy Author Comment
// 08-Nov-93 alexgo 32bit port
//
// Notes:
// note that this is a contained object; this unlocks
// connection to the server
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::SetContainedObject(BOOL fContained) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult = NOERROR;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::SetContainedObject " "( %lu )\n", this, fContained));
CRefStabilize stabilize(this);
if( !!(m_flags & DH_CONTAINED_OBJECT) != !!fContained) { // not contained in the same way as desired;
// for inproc handler, [un]lock connection
// for inproc server, just remember flag
if( (m_flags & DH_INPROC_HANDLER) ) { hresult = LockRunning(!fContained, FALSE); }
if (hresult == NOERROR) { // the !! ensure exactly 0 or 1 will be stored in
// m_fContainedObject
if( fContained ) { m_flags |= DH_CONTAINED_OBJECT; } else { m_flags &= ~DH_CONTAINED_OBJECT; } } }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::SetContainedObject " "( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::LockRunning
//
// Synopsis: Locks or unlocks the object
//
// Effects:
//
// Arguments: [fLock] -- TRUE, then lock, unlock if FALSE
// [fLastUnlockCloses] -- shut down if unlocking the last
// lock
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IRunnableObject
//
// Algorithm: If we are an improc server, call CoLockObjectExternal,
// otherwise have the proxy manager lock us down.
//
// History: dd-mmm-yy Author Comment
// 08-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::LockRunning(BOOL fLock, BOOL fLastUnlockCloses) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::LockRunning " "( %lu , %lu )\n", this, fLock, fLastUnlockCloses ));
CRefStabilize stabilize(this);
// else map to lock connection
if( !(m_flags & DH_INPROC_HANDLER) ) { // inproc server: use CoLockObjExternal; will close down
// if invisible via new IExternalConnection interface.
Assert(m_pProxyMgr == NULL); hresult = CoLockObjectExternal((IUnknown *)(IOleObject *)this, fLock, fLastUnlockCloses); } else if( m_pUnkDelegate == NULL ) { // NOTE: this really shouldn't happen at present
// since we currently disallow delay create with
// inproc handler. In fact, the LockConnection below
// is one of the reasons why we must have the
// proxymgr upfront. In the future we could force
// the creation of the delegate here.
Assert( (m_flags & DH_DELAY_CREATE) && m_pCFDelegate != NULL); hresult = NOERROR; } else { Assert(m_pProxyMgr != NULL);
hresult = m_pProxyMgr->LockConnection(fLock, fLastUnlockCloses); }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::LockRunning " "( %lx )\n", this, hresult));
return hresult; }
/*
* IMPLEMENTATION of CECImpl methods * */
//+-------------------------------------------------------------------------
//
// Member: CDefObject::AddConnection
//
// Synopsis: Adds an external connection
//
// Effects:
//
// Arguments: [extconn] -- the type of connection (such as
// EXTCONN_STRONG)
// [reserved] -- unused
//
// Requires:
//
// Returns: DWORD -- the number of strong connections
//
// Signals:
//
// Modifies:
//
// Derivation: IExternalConnection
//
// Algorithm: keeps track of strong connections
//
// History: dd-mmm-yy Author Comment
// 08-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP_(DWORD) CDefObject::AddConnection(DWORD extconn, DWORD reserved) { VDATEHEAP();
//
// VDATETHREAD contains a 'return HRESULT' but this procedure expects to
// return a DWORD. Avoid the warning.
#if ( _MSC_VER >= 800 )
#pragma warning( disable : 4245 )
#endif
VDATETHREAD(this); #if ( _MSC_VER >= 800 )
#pragma warning( default : 4245 )
#endif
DWORD dwConn;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::AddConnection " "( %lu , %lu )\n", this, extconn, reserved));
Assert( !(m_flags & DH_INPROC_HANDLER) );
dwConn = extconn&EXTCONN_STRONG ? ++m_cConnections : 0;
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::AddConnection " "( %lu )\n", this, dwConn));
return dwConn; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::ReleaseConnection
//
// Synopsis: Releases external connection, potentially calling IOO->Close
//
// Effects:
//
// Arguments: [extconn] -- the type of connection
// [reserved] -- unused
// [fLastReleaseCloses] -- call IOO->Close if its the last
// release
//
// Requires:
//
// Returns:
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 08-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP_(DWORD) CDefObject::ReleaseConnection(DWORD extconn, DWORD reserved, BOOL fLastReleaseCloses) { VDATEHEAP();
//
// VDATETHREAD contains a 'return HRESULT' but this procedure expects to
// return a DWORD. Avoid the warning.
#if ( _MSC_VER >= 800 )
#pragma warning( disable : 4245 )
#endif
VDATETHREAD(this); #if ( _MSC_VER >= 800 )
#pragma warning( default : 4245 )
#endif
DWORD dwConn;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::ReleaseConnection " "( %lu , %lu , %lu )\n", this, extconn, reserved, fLastReleaseCloses));
CRefStabilize stabilize(this);
// must be an embedding helper
Assert( !(m_flags & DH_INPROC_HANDLER) );
if( (extconn & EXTCONN_STRONG) && --m_cConnections == 0 && fLastReleaseCloses) { // REVIEW: might want this to be close save if dirty.
Close(OLECLOSE_NOSAVE); }
dwConn = (extconn & EXTCONN_STRONG) ? m_cConnections : 0;
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::ReleaseConnection " "( %lu )\n", this, dwConn));
return dwConn; }
/*
* * IMPLEMENTATION of CAdvSinkImpl methods * */
//
// NOTE: Advise Sink is a nested object of Default Handler that is exported
// for achieving some of its functionality. This introduces some lifetime
// complications. Can its lifetime be controlled by the server object to
// which it exported its Advise Sink? Ideally, only its client should
// control its lifetime alone, but it should also honor the ref counts
// placed on it by the server object by entering into a zombie state
// to prevent AV's on the incoming calls to the Advise Sink. All needed
// logic is coded into the new class "CRefExportCount" which manages
// the ref and export counts in a thread safe manner and invokes
// appropriate methods during the object's lifetime. Any server objects
// that export nested objects to other server objects should derive from
// "CRefExportCount" class and call its methods to manage their lifetime
// as exemplified in this Default Handler implementation.
//
// Gopalk Jan 10, 97
//
//+-------------------------------------------------------------------------
//
// Member: CDefObject::CAdvSinkImpl::QueryInterface
//
// Synopsis: Only supports IUnknown and IAdviseSink
//
// Arguments: [iid] -- Interface requested
// [ppvObj] -- pointer to hold returned interface
//
// Returns: HRESULT
//
// History: dd-mmm-yy Author Comment
// 10-Jan-96 Gopalk Rewritten
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::CAdvSinkImpl::QueryInterface(REFIID iid, void **ppv) { LEDebugOut((DEB_TRACE,"%p _IN CDefObject::CAdvSinkImpl::QueryInterface()\n", this));
// Validation check
VDATEHEAP();
// Local variables
HRESULT hresult = NOERROR;
if(IsValidPtrOut(ppv, sizeof(void *))) { if(IsEqualIID(iid, IID_IUnknown)) { *ppv = (void *)(IUnknown *) this; } else if(IsEqualIID(iid, IID_IAdviseSink)) { *ppv = (void *)(IAdviseSink *) this; } else { *ppv = NULL; hresult = E_NOINTERFACE; } } else hresult = E_INVALIDARG;
if(hresult == NOERROR) ((IUnknown *) *ppv)->AddRef();
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::CAdvSinkImpl::QueryInterface(%lx)\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::CAdvSinkImpl::AddRef
//
// Synopsis: Increments export count
//
// Returns: ULONG; New export count
//
// History: dd-mmm-yy Author Comment
// 10-Jan-96 Gopalk Rewritten
//--------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CDefObject::CAdvSinkImpl::AddRef( void ) { LEDebugOut((DEB_TRACE, "%p _IN CDefObject::CAdvSinkImpl::AddRef()\n", this));
// Validation check
VDATEHEAP();
// Local variables
CDefObject *pDefObject = GETPPARENT(this, CDefObject, m_AdviseSink); ULONG cExportCount;
// Increment export count
cExportCount = pDefObject->IncrementExportCount();
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::CAdvSinkImpl::AddRef(%ld)\n", this, cExportCount));
return cExportCount; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::CAdvSinkImpl::Release
//
// Synopsis: Decerement export count and potentially destroy the object
//
// Returns: ULONG; New export count
//
// History: dd-mmm-yy Author Comment
// 10-Jan-96 Gopalk Rewritten
//--------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CDefObject::CAdvSinkImpl::Release ( void ) { LEDebugOut((DEB_TRACE, "%p _IN CDefObject::CAdvSinkImpl::Release()\n", this));
// Validation check
VDATEHEAP();
// Local variables
CDefObject *pDefObject = GETPPARENT(this, CDefObject, m_AdviseSink); ULONG cExportCount;
// Decrement export count.
cExportCount = pDefObject->DecrementExportCount();
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::CAdvSinkImpl::Release(%ld)\n", this, cExportCount));
return cExportCount; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::CAdvSinkImpl::OnDataChange
//
// Synopsis: Function to notify on data change
//
// Effects: Never called
//
// Arguments: [pFormatetc] -- format of the data
// [pStgmed] -- data medium
//
// Requires:
//
// Returns: void
//
// Signals:
//
// Modifies:
//
// Derivation: IAdviseSink
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 08-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP_(void) CDefObject::CAdvSinkImpl::OnDataChange( FORMATETC *pFormatetc, STGMEDIUM *pStgmed) { VDATEHEAP();
VOID_VDATEPTRIN( pFormatetc, FORMATETC ); VOID_VDATEPTRIN( pStgmed, STGMEDIUM );
Assert(FALSE); // never received
}
//+-------------------------------------------------------------------------
//
// Member: CDefObject::CAdvSinkImpl::OnViewChange
//
// Synopsis: notification of view changes
//
// Effects: never called
//
// Arguments: [aspects]
// [lindex]
//
// Requires:
//
// Returns: void
//
// Signals:
//
// Modifies:
//
// Derivation: IAdviseSink
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 08-Nov-93 alexgo 32bit port
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP_(void) CDefObject::CAdvSinkImpl::OnViewChange (DWORD aspects, LONG lindex) { VDATEHEAP();
Assert(FALSE); // never received
}
//+-------------------------------------------------------------------------
//
// Member: CDefObject::CAdvSinkImpl::OnRename
//
// Synopsis: Notification of name change. Turns around and informs its
// advise sinks
//
// Arguments: [pmk] -- New name (moniker)
//
// History: dd-mmm-yy Author Comment
// 10-Jan-96 Gopalk Rewritten
//--------------------------------------------------------------------------
STDMETHODIMP_(void) CDefObject::CAdvSinkImpl::OnRename(IMoniker *pmk) { LEDebugOut((DEB_TRACE, "%p _IN CDefObject::CAdvSinkImpl::OnRename(%p)\n", this, pmk));
// Validation check
VDATEHEAP();
// Local variable
CDefObject *pDefObject = GETPPARENT(this, CDefObject, m_AdviseSink);
if(IsValidInterface(pmk)) { if(!pDefObject->IsZombie()) { // Stabilize
CRefStabilize stabilize(pDefObject);
if(pDefObject->m_pOAHolder != NULL) pDefObject->m_pOAHolder->SendOnRename(pmk); } else LEDebugOut((DEB_WARN, "OnRename() method invoked on zombied " "Default Handler")); }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::CAdvSinkImpl::OnRename()\n", this)); }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::CAdvSinkImpl::OnSave
//
// Synopsis: Notification of save. Turns around and informs its
// advise sinks
//
// Arguments: None
//
// History: dd-mmm-yy Author Comment
// 10-Jan-96 Gopalk Rewritten
//--------------------------------------------------------------------------
STDMETHODIMP_(void) CDefObject::CAdvSinkImpl::OnSave(void) { LEDebugOut((DEB_TRACE, "%p _IN CDefObject::CAdvSinkImpl::OnSave()\n", this));
// Validation check
VDATEHEAP();
// Local variable
CDefObject *pDefObject = GETPPARENT(this, CDefObject, m_AdviseSink);
if(!pDefObject->IsZombie()) { // Stabilize
CRefStabilize stabilize(pDefObject);
if(pDefObject->m_pOAHolder != NULL) pDefObject->m_pOAHolder->SendOnSave(); } else LEDebugOut((DEB_WARN,"OnSave() method invoked on zombied Default Handler"));
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::CAdvSinkImpl::OnSave()\n", this)); }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::CAdvSinkImpl::OnClose
//
// Synopsis: notification of the object close. Turns around and informs its
// advise sinks
//
// Arguments: None
//
// History: dd-mmm-yy Author Comment
// 10-Jan-96 Gopalk Rewritten
//--------------------------------------------------------------------------
STDMETHODIMP_(void) CDefObject::CAdvSinkImpl::OnClose( void ) { LEDebugOut((DEB_TRACE, "%p _IN CDefObject::CAdvSinkImpl::OnClose()\n", this));
// Validation check
VDATEHEAP();
// Local variables
CDefObject *pDefObject = GETPPARENT(this, CDefObject, m_AdviseSink);
if(!pDefObject->IsZombie()) { // Stabilize
CRefStabilize stabilize(pDefObject);
// Check if container has registered any of its own advise sinks
if(pDefObject->m_pOAHolder) { // Inform the container advise sinks. Note that this can result
// in additional outgoing calls and consequently, OnClose()
// method is designed to be not asyncronous
pDefObject->m_pOAHolder->SendOnClose(); }
// Do not rely on container calling close. Stop the running server
pDefObject->Stop(); } else LEDebugOut((DEB_WARN,"OnClose() method invoked on zombied Default Handler"));
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::CAdvSinkImpl::OnClose()\n", pDefObject));
return; }
/*
* IMPLEMENTATION of CPersistStgImpl methods * */
//+-------------------------------------------------------------------------
//
// Member: CDefObject::GetPSDelegate
//
// Synopsis: retrieves the IPersistStorage interface from the delegate
//
// Effects:
//
// Arguments: void
//
// Requires:
//
// Returns: IPersistStorage *
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 08-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
INTERNAL_(IPersistStorage *) CDefObject::GetPSDelegate(void) { VDATEHEAP();
if( IsZombie() ) { return NULL; }
return (IPersistStorage FAR*)DuCacheDelegate( &m_pUnkDelegate, IID_IPersistStorage, (LPLPVOID) &m_pPSDelegate, m_pUnkOuter); }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::GetClassID
//
// Synopsis: Retrieves the class ID of the object
//
// Effects:
//
// Arguments: [pClassID] -- where to put the class ID
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IPersistStorage
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 08-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::GetClassID (CLSID *pClassID) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::GetClassID " "( %p )\n", this, pClassID));
VDATEPTROUT(pClassID, CLSID );
hresult = GetClassBits(pClassID);
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::GetClassID " "( %lx ) [ %p ]\n", this, hresult, pClassID));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::IsDirty
//
// Synopsis: Returns whether or not the object needs to be saved
//
// Effects:
//
// Arguments: void
//
// Requires:
//
// Returns: HRESULT -- NOERROR means the object *is* dirty
//
// Signals:
//
// Modifies:
//
// Derivation: IPersistStorage
//
// Algorithm: if the server is running, delegate. If the server is
// clean (or not present), ask the cache
//
// History: dd-mmm-yy Author Comment
// 08-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::IsDirty( void ) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult = S_FALSE;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::IsDirty ( )\n", this));
CRefStabilize stabilize(this);
// if server is running, it holds definitive dirty flag
if( IsRunning() && GetPSDelegate() ) { if ( FAILED(hresult = m_pPSDelegate->IsDirty()) ) { goto errRtn; } }
if (hresult == S_FALSE) { Assert(m_pCOleCache != NULL); hresult = m_pCOleCache->IsDirty(); }
errRtn:
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::IsDirty " "( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::InitNew
//
// Synopsis: Create a new object with the given storage
//
// Effects:
//
// Arguments: [pstg] -- the storage for the new object
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IPersistStorage
//
// Algorithm: Delegates to the server and to the cache. Writes
// Ole private data to the storage.
//
// History: dd-mmm-yy Author Comment
// 08-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::InitNew( IStorage *pstg ) { VDATEHEAP(); VDATETHREAD(this);
VDATEIFACE( pstg );
HRESULT hresult;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::InitNew ( %p )\n", this, pstg));
CRefStabilize stabilize(this);
if( m_pStg ) { hresult = CO_E_ALREADYINITIALIZED; goto errRtn; }
m_flags |= DH_EMBEDDING;
if( IsRunning() && GetPSDelegate() && (hresult = m_pPSDelegate->InitNew(pstg)) != NOERROR) { goto errRtn; }
m_flags |= DH_INIT_NEW;
// if we're in a zombie state, don't change the storage!
if( IsZombie() ) { hresult = CO_E_RELEASED; goto errRtn; }
Assert(m_pCOleCache != NULL); if ((hresult = m_pCOleCache->InitNew(pstg)) != NOERROR) { goto errRtn; }
// remember the storage pointer
(m_pStg = pstg)->AddRef();
// go ahead and write the Ole stream now
WriteOleStg(pstg, (IOleObject *)this, NULL, NULL);
errRtn: LEDebugOut((DEB_TRACE, "%p OUT CDefObject::InitNew " "( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::Load
//
// Synopsis: Loads object data from the given storage
//
// Effects:
//
// Arguments: [pstg] -- the storage for the object's data
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IPeristStorage
//
// Algorithm: Reads ole-private data (or creates if not there), delegates
// to the server and the cache.
//
// History: dd-mmm-yy Author Comment
// 08-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::Load (IStorage *pstg) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult; DWORD dwOptUpdate;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::Load ( %p )\n", this, pstg));
VDATEIFACE( pstg );
CRefStabilize stabilize(this);
if( m_pStg ) { hresult = CO_E_ALREADYINITIALIZED; goto errRtn; }
m_flags |= DH_EMBEDDING;
// NOTE: we can get the moniker from container, so no need to get
// it here
hresult = ReadOleStg (pstg, &m_dwObjFlags, &dwOptUpdate, NULL, NULL, NULL);
if (hresult == NOERROR) { if (m_dwObjFlags & OBJFLAGS_CONVERT) { if( DoConversionIfSpecialClass(pstg) != NOERROR ) { hresult = OLE_E_CANTCONVERT; goto errRtn; } }
Assert (dwOptUpdate == NULL);
} else if (hresult == STG_E_FILENOTFOUND) { // it is OK if the Ole stream doesn't exist.
hresult = NOERROR;
// go ahead and write the Ole stream now
WriteOleStg(pstg, (IOleObject *)this, NULL, NULL); } else { goto errRtn; }
// if running, tell server to load from pstg
if( IsRunning() && GetPSDelegate() && (hresult = m_pPSDelegate->Load(pstg)) != NOERROR) { goto errRtn; }
// if we're in a zombie state, don't addref' the storage!
if( IsZombie() ) { hresult = CO_E_RELEASED; goto errRtn; }
// now load cache from pstg
Assert(m_pCOleCache != NULL); if(m_dwObjFlags & OBJFLAGS_CACHEEMPTY) { hresult = m_pCOleCache->Load(pstg, TRUE); if(hresult != NOERROR) goto errRtn; } else { hresult = m_pCOleCache->Load(pstg); if(hresult != NOERROR) goto errRtn; }
m_flags &= ~DH_INIT_NEW; // clear init new flag
// remember the storage pointer
(m_pStg = pstg)->AddRef();
errRtn: LEDebugOut((DEB_TRACE, "%p OUT CDefObject::Load " "( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::Save
//
// Synopsis: Saves the object to the given storage
//
// Effects:
//
// Arguments: [pstgSave] -- storage in which to save
// [fSameAsLoad] -- FALSE indicates a SaveAs operation
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IPersistStorage
//
// Algorithm: Saves ole-private data, delegates to the server and then
// to the cache
//
// History: dd-mmm-yy Author Comment
// 08-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::Save( IStorage *pstgSave, BOOL fSameAsLoad) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult = NOERROR;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::Save " "( %p , %lu )\n", this, pstgSave, fSameAsLoad ));
VDATEIFACE( pstgSave );
CRefStabilize stabilize(this);
Assert(m_pCOleCache != NULL);
if( IsRunning() && GetPSDelegate() ) {
DWORD grfUpdf = UPDFCACHE_IFBLANK; DWORD ObjFlags = 0; HRESULT error;
#ifdef NEVER
// We would have liked to have done this check as an
// optimization, but WordArt2 does not give the right answer
// (bug 3504) so we can't.
if (m_pPStgDelegate->IsDirty() == NOERROR) #endif
grfUpdf |= UPDFCACHE_ONSAVECACHE;
// next save server data
if (hresult = m_pPSDelegate->Save(pstgSave, fSameAsLoad)) { goto errRtn; }
// Update any blank cached presentations
m_pCOleCache->UpdateCache(GetDataDelegate(), grfUpdf, NULL);
// Save cache
hresult = m_pCOleCache->Save(pstgSave, fSameAsLoad);
// Write the Ole stream after obtaining cache status
if(m_pCOleCache->IsEmpty()) ObjFlags |= OBJFLAGS_CACHEEMPTY; error = WriteOleStgEx(pstgSave, (IOleObject *)this, NULL, ObjFlags, NULL);
// Remember the cache status if Ole stream was successfully written and
// fSameAsLoad is TRUE
if(error==NOERROR && fSameAsLoad) m_dwObjFlags |= ObjFlags; } else { // Save the cache
if ((hresult = m_pCOleCache->Save(m_pStg,TRUE)) != NOERROR) { goto errRtn; }
// Check to see if Ole Stream needs to be written
if((!!(m_dwObjFlags & OBJFLAGS_CACHEEMPTY)) != m_pCOleCache->IsEmpty()) { DWORD ObjFlags = 0; HRESULT error;
// Write the Ole stream after obtaining cache status
if(m_pCOleCache->IsEmpty()) ObjFlags |= OBJFLAGS_CACHEEMPTY; error = WriteOleStgEx(m_pStg, (IOleObject *)this, NULL, ObjFlags, NULL);
// Remember the cache status if Ole stream was successfully written
if(error==NOERROR) m_dwObjFlags |= ObjFlags; }
// By now we are sure that object's current state has got
// saved into its storage.
AssertSz(m_pStg, "Object doesn't have storage");
// Is saving the existing storage when fSameAsLoad is FLASE correct?
// To me it seems wrong. Gopalk
// It is not being fixed fearing some regression in apps
if (!fSameAsLoad) { hresult = m_pStg->CopyTo(NULL, NULL, NULL, pstgSave); } }
errRtn: if (hresult == NOERROR) { if( fSameAsLoad ) { m_flags |= DH_SAME_AS_LOAD; // gets used in SaveCompleted
m_flags &= ~DH_INIT_NEW; } else { m_flags &= ~DH_SAME_AS_LOAD; } }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::Save " "( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::SaveCompleted
//
// Synopsis: called when the save is completed
//
// Effects:
//
// Arguments: [pstgNew] -- the new storage for the object
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IPersistStorage
//
// Algorithm: delegates to the server and the cache.
//
// History: dd-mmm-yy Author Comment
// 08-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::SaveCompleted( IStorage *pstgNew ) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult = NOERROR;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::SaveCompleted " "( %p )\n", this, pstgNew));
if( pstgNew ) { VDATEIFACE(pstgNew); }
CRefStabilize stabilize(this);
if( IsRunning() && GetPSDelegate() ) { hresult = m_pPSDelegate->SaveCompleted(pstgNew); }
// we don't save the new storage if we're in a zombie state!
if( hresult == NOERROR && pstgNew && !IsZombie() ) { if( m_pStg ) { m_pStg->Release(); }
m_pStg = pstgNew; pstgNew->AddRef(); }
// let the cache know that the save is completed, so that it can
// clear its dirty flag in Save or SaveAs situation, as well as
// remember the new storage pointer if a new one is given
Assert(m_pCOleCache != NULL);
if( (m_flags & DH_SAME_AS_LOAD) || pstgNew) { // clear init-new and same-as-load flags
m_flags &= ~(DH_SAME_AS_LOAD | DH_INIT_NEW); }
m_pCOleCache->SaveCompleted(pstgNew);
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::SaveCompleted ( %lx )\n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::HandsOffStorage
//
// Synopsis: Forces the server to release a storage (for low-mem reasons,
// etc).
//
// Effects:
//
// Arguments: void
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IPersistStorage
//
// Algorithm: Delegates to the server and the cache
//
// History: dd-mmm-yy Author Comment
// 08-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CDefObject::HandsOffStorage(void) { VDATEHEAP(); VDATETHREAD(this);
HRESULT hresult = NOERROR;
LEDebugOut((DEB_TRACE, "%p _IN CDefObject::HandsOffStorage ( )\n", this));
CRefStabilize stabilize(this);
if( IsRunning() && GetPSDelegate() ) { hresult = m_pPSDelegate->HandsOffStorage(); }
if (hresult == NOERROR) { if( m_pStg ) { m_pStg->Release(); m_pStg = NULL; }
Assert(m_pCOleCache != NULL); m_pCOleCache->HandsOffStorage(); }
LEDebugOut((DEB_TRACE, "%p OUT CDefObject::HandsOffStorage ( %lx )\n", this, hresult));
return hresult; }
/*
* Default handler private functions */
//+-------------------------------------------------------------------------
//
// Member: CDefObject::GetClassBits
//
// Synopsis: Gets a class id for the object
//
// Effects:
//
// Arguments: [pClsidBits] -- where to put the class id
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm: Tries the server, then the storage, and finally the
// clsid we were created with
//
// History: dd-mmm-yy Author Comment
// 08-Nov-93 alexgo 32bit port
//
// Notes:
//
// always gets a clsid and returns NOERROR; the clsid may be m_clsidServer
// under certain conditions (e.g., no compobj stream).
//
//--------------------------------------------------------------------------
INTERNAL CDefObject::GetClassBits(CLSID FAR* pClsidBits) { VDATEHEAP();
// alway try server first; this allows the server to respond
if( IsRunning() && GetPSDelegate() ) { if( m_pPSDelegate->GetClassID(pClsidBits) == NOERROR ) { m_clsidBits = *pClsidBits; return NOERROR; } }
// not running, no ps or error: use previously cached value
if( !IsEqualCLSID(m_clsidBits, CLSID_NULL) ) { *pClsidBits = m_clsidBits; return NOERROR; }
// not running, no ps or error and no clsidBits yet: read from stg
// if not static object.
if( !(m_flags & DH_STATIC) ) { if (m_pStg && ReadClassStg(m_pStg, pClsidBits) == NOERROR) { m_clsidBits = *pClsidBits; return NOERROR; } }
// no contact with server and can't get from storage; don't set
// m_clsidBits so if we get a storage or the serve becomes running,
// we get the right one
*pClsidBits = m_clsidServer; return NOERROR; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::DoConversionIfSpecialClass
//
// Synopsis: Convert old data formats.
//
// Effects:
//
// Arguments: [pstg] -- the storage with the data
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm: see notes...
//
// History: dd-mmm-yy Author Comment
// 08-Nov-93 alexgo 32bit port
//
// Notes: this is not yet functional for 32bit OLE
//
// If the class is CLSID_StaticDib/CLSID_StaticMetafile and the old
// format is "PBrush"/"MSDraw" the data must be in the OLE10_NATIVESTREAM.
// Move the data into the CONTENTS stream
//
// If the class is CLSID_PBrush/CLSID_MSDraw and the old format is
// metafile/DIB then data must be in the CONTENTS stream. Move the data
// from the CONTENTS stream to the OLE10_NATIVESTREAM"
//
//--------------------------------------------------------------------------
INTERNAL CDefObject::DoConversionIfSpecialClass(LPSTORAGE pstg) { VDATEHEAP();
LEDebugOut((DEB_ITRACE, "%p _IN CDefObject::DoConversionIfSpecialClass (" " %p )\n", this, pstg));
HRESULT hresult; UINT uiStatus;
/*** Handle the static object case ***/
if( (m_flags & DH_STATIC) ) { if ((hresult = Ut10NativeStmToContentsStm(pstg, m_clsidServer, TRUE /* fDeleteContentStm*/)) == NOERROR) #ifdef OLD
UtRemoveExtraOlePresStreams(pstg, 0 /*iStart*/); #endif
goto errRtn;
}
/*** Handle the PBrush & MSDraw case ***/
// Conversion is not a frequent operation. So, it is better to do the
// CLSID comparison here when it is necessary than doing comparison
// upfront and remember a flag
// if the class is not one of the following two then the object server
// will do the necessary conversion.
{ CLSID clsid = CLSID_NULL;
// Get the real CLSID from the storage. This is necessary because we
// may be a PBrush object being "treated as".
ReadClassStg(pstg, &clsid);
// if the real CLSID is not PaintBrush or the known CLSID is not MSDRAW
// head out.
if( clsid != CLSID_PBrush && m_clsidServer != CLSID_MSDraw ) { hresult = NOERROR; goto exitRtn; }
// if the real CLSID is not paintbrush, then set clsid to the clsid to
// the known clsid.
if (clsid != CLSID_PBrush) { clsid = m_clsidServer; }
//
hresult = UtContentsStmTo10NativeStm(pstg, clsid, TRUE /* fDeleteContentStm*/, &uiStatus); } // if OLE10_NATIVE_STREAM exists then assume success
if (!(uiStatus & CONVERT_NODESTINATION)) hresult = NOERROR;
if (hresult != NOERROR) { // May be the static object data is in OlePres stream. If so,
// first convert that to contents stream and then try again
// In OLE2.0 first release static object were written to
// OlePres000 stream.
hresult = UtOlePresStmToContentsStm(pstg, OLE_PRESENTATION_STREAM, TRUE /*fDeletePresStm*/, &uiStatus);
if (hresult == NOERROR) hresult = UtContentsStmTo10NativeStm(pstg, m_clsidServer, TRUE /* fDeleteContentStm*/, &uiStatus); }
errRtn: if (hresult == NOERROR) // conversion is successful, turn the bit off
SetConvertStg(pstg, FALSE);
exitRtn: LEDebugOut((DEB_TRACE, "%p OUT CDefObject::DoConversionIfSpecialClass " "( %lx ) \n", this, hresult));
return hresult; }
//+-------------------------------------------------------------------------
//
// Member: CDefObject::Dump, public (_DEBUG only)
//
// Synopsis: return a string containing the contents of the data members
//
// Effects:
//
// Arguments: [ppszDump] - an out pointer to a null terminated character array
// [ulFlag] - flag determining prefix of all newlines of the
// out character array (default is 0 - no prefix)
// [nIndentLevel] - will add a indent prefix after the other prefix
// for ALL newlines (including those with no prefix)
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies: [ppszDump] - argument
//
// Derivation:
//
// Algorithm: use dbgstream to create a string containing information on the
// content of data structures
//
// History: dd-mmm-yy Author Comment
// 01-Feb-95 t-ScottH author
//
// Notes:
//
//--------------------------------------------------------------------------
#ifdef _DEBUG
HRESULT CDefObject::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel) { int i; char *pszPrefix; char *pszCSafeRefCount; char *pszCThreadCheck; char *pszOAHolder; char *pszCLSID; char *pszCOleCache; char *pszDAC; LPOLESTR pszName; dbgstream dstrPrefix; dbgstream dstrDump(5000);
// determine prefix of newlines
if ( ulFlag & DEB_VERBOSE ) { dstrPrefix << this << " _VB "; }
// determine indentation prefix for all newlines
for (i = 0; i < nIndentLevel; i++) { dstrPrefix << DUMPTAB; }
pszPrefix = dstrPrefix.str();
// put data members in stream
pszCThreadCheck = DumpCThreadCheck((CThreadCheck *)this, ulFlag, nIndentLevel + 1); dstrDump << pszPrefix << "CThreadCheck:" << endl; dstrDump << pszCThreadCheck; CoTaskMemFree(pszCThreadCheck);
// only vtable pointers (plus we don't get the right address in debugger extensions)
// dstrDump << pszPrefix << "&IUnknown = " << &m_Unknown << endl;
// dstrDump << pszPrefix << "&IAdviseSink = " << &m_AdviseSink << endl;
dstrDump << pszPrefix << "pIOleObject Delegate = " << m_pOleDelegate << endl;
dstrDump << pszPrefix << "pIDataObject Delegate = " << m_pDataDelegate << endl;
dstrDump << pszPrefix << "pIPersistStorage Delegate = " << m_pPSDelegate << endl;
dstrDump << pszPrefix << "Count of Strong Connection= " << m_cConnections << endl;
dstrDump << pszPrefix << "pIUnknown pUnkOuter = "; if (m_flags & DH_AGGREGATED) { dstrDump << "AGGREGATED (" << m_pUnkOuter << ")" << endl; } else { dstrDump << "NO AGGREGATION (" << m_pUnkOuter << ")" << endl; }
pszCLSID = DumpCLSID(m_clsidServer); dstrDump << pszPrefix << "Server CLSID = " << pszCLSID << endl; CoTaskMemFree(pszCLSID);
pszCLSID = DumpCLSID(m_clsidBits); dstrDump << pszPrefix << "Persistent CLSID = " << pszCLSID << endl; CoTaskMemFree(pszCLSID);
dstrDump << pszPrefix << "Handler flags = "; if (m_flags & DH_SAME_AS_LOAD) { dstrDump << "DH_SAME_AS_LOAD "; } if (m_flags & DH_CONTAINED_OBJECT) { dstrDump << "DH_CONTAINED_OBJECT "; } if (m_flags & DH_LOCKED_CONTAINER) { dstrDump << "DH_LOCKED_CONTAINER "; } if (m_flags & DH_FORCED_RUNNING) { dstrDump << "DH_FORCED_RUNNING "; } if (m_flags & DH_EMBEDDING) { dstrDump << "DH_EMBEDDING "; } if (m_flags & DH_INIT_NEW) { dstrDump << "DH_INIT_NEW "; } if (m_flags & DH_STATIC) { dstrDump << "DH_STATIC "; } if (m_flags & DH_INPROC_HANDLER) { dstrDump << "DH_INPROC_HANDLER "; } if (m_flags & DH_DELAY_CREATE) { dstrDump << "DH_DELAY_CREATE "; } if (m_flags & DH_AGGREGATED) { dstrDump << "DH_AGGREGATED "; } // if none of the flags are set...
if ( !( (m_flags & DH_SAME_AS_LOAD) | (m_flags & DH_CONTAINED_OBJECT) | (m_flags & DH_LOCKED_CONTAINER) | (m_flags & DH_FORCED_RUNNING) | (m_flags & DH_EMBEDDING) | (m_flags & DH_INIT_NEW) | (m_flags & DH_STATIC) | (m_flags & DH_INPROC_HANDLER) | (m_flags & DH_DELAY_CREATE) | (m_flags & DH_AGGREGATED))) { dstrDump << "No FLAGS SET!"; } dstrDump << "(" << LongToPtr(m_flags) << ")" << endl;
dstrDump << pszPrefix << "pIClassFactory Delegate = " << m_pCFDelegate << endl;
dstrDump << pszPrefix << "pIUnknown Delegate = " << m_pUnkDelegate << endl;
dstrDump << pszPrefix << "pIProxyManager = " << m_pProxyMgr << endl;
if (m_pCOleCache != NULL) { // pszCOleCache = DumpCOleCache(m_pCOleCache, ulFlag, nIndentLevel + 1);
dstrDump << pszPrefix << "COleCache: " << endl; // dstrDump << pszCOleCache;
// CoTaskMemFree(pszCOleCache);
} else { dstrDump << pszPrefix << "pCOleCache = " << m_pCOleCache << endl; }
if (m_pOAHolder != NULL) { pszOAHolder = DumpCOAHolder(m_pOAHolder, ulFlag, nIndentLevel + 1); dstrDump << pszPrefix << "COAHolder: " << endl; dstrDump << pszOAHolder; CoTaskMemFree(pszOAHolder); } else { dstrDump << pszPrefix << "pIOleAdviseHolder = " << m_pOAHolder << endl; }
dstrDump << pszPrefix << "OLE Connection Advise ID = " << m_dwConnOle << endl;
dstrDump << pszPrefix << "pIOleClientSite = " << m_pAppClientSite << endl;
dstrDump << pszPrefix << "pIStorage = " << m_pStg << endl;
pszName = (LPOLESTR)m_pHostNames; dstrDump << pszPrefix << "Application Name = " << pszName << endl;
pszName = (LPOLESTR)(m_pHostNames + m_ibCntrObj); dstrDump << pszPrefix << "Document Name = " << pszName << endl;
if (m_pDataAdvCache != NULL) { pszDAC = DumpCDataAdviseCache(m_pDataAdvCache, ulFlag, nIndentLevel + 1); dstrDump << pszPrefix << "CDataAdviseCache: " << endl; dstrDump << pszDAC; CoTaskMemFree(pszDAC); } else { dstrDump << pszPrefix << "pCDataAdviseCache = " << m_pDataAdvCache << endl; }
// cleanup and provide pointer to character array
*ppszDump = dstrDump.str();
if (*ppszDump == NULL) { *ppszDump = UtDupStringA(szDumpErrorMessage); }
CoTaskMemFree(pszPrefix);
return NOERROR; }
#endif // _DEBUG
//+-------------------------------------------------------------------------
//
// Function: DumpCDefObject, public (_DEBUG only)
//
// Synopsis: calls the CDefObject::Dump method, takes care of errors and
// returns the zero terminated string
//
// Effects:
//
// Arguments: [pDO] - pointer to CDefObject
// [ulFlag] - flag determining prefix of all newlines of the
// out character array (default is 0 - no prefix)
// [nIndentLevel] - will add a indent prefix after the other prefix
// for ALL newlines (including those with no prefix)
//
// Requires:
//
// Returns: character array of structure dump or error (null terminated)
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 01-Feb-95 t-ScottH author
//
// Notes:
//
//--------------------------------------------------------------------------
#ifdef _DEBUG
char *DumpCDefObject(CDefObject *pDO, ULONG ulFlag, int nIndentLevel) { HRESULT hresult; char *pszDump;
if (pDO == NULL) { return UtDupStringA(szDumpBadPtr); }
hresult = pDO->Dump(&pszDump, ulFlag, nIndentLevel);
if (hresult != NOERROR) { CoTaskMemFree(pszDump);
return DumpHRESULT(hresult); }
return pszDump; }
#endif // _DEBUG
|