📄 stdstub.cpp
字号:
/* StdStub.cpp - COM/DCOM StdStub class implementation *//*modification history--------------------02f,17dec01,nel Add include symbol for StdStub.02e,31jul01,dbs import full T2 changes for stublet refcounts02d,13jul01,dbs fix up includes02c,20sep00,nel Add changes made in T2 since branch.02b,28feb00,dbs add fake stub disp table for IUnknown02a,02aug99,dbs return correct err code when no stublet01z,27jul99,drm Returning CLSID from interfaceInfoGet().01y,09jul99,dbs change to new ObjectExporter naming01x,08jul99,dbs remove print statements01w,29jun99,dbs no longer need to unregister StdStub in dtor01v,28jun99,dbs make Relase() return refs so deletion can be done by OX01u,17jun99,aim uses new SCM01t,10jun99,dbs remove op new and delete01s,08jun99,dbs remove use of mtmap01r,04jun99,dbs change GuidMap to mtmap01q,03jun99,dbs no return value from mutex lock01p,02jun99,dbs inherit from RpcDispatchTable01o,26may99,dbs fix remote ref-count for IUnknown stublet01n,25may99,dbs fix stublet refcount for IUnknown stublet01m,24may99,dbs ask SCM for local object exporter01l,18may99,dbs change to new marshaling architecture01k,11may99,dbs fix pure-virtual call problem01j,11may99,dbs simplify stub remoting architecture01i,07may99,dbs fix method calls to exporter01h,29apr99,dbs fix -Wall warnings01g,28apr99,dbs use COM_MEM_ALLOC for all classes01f,26apr99,aim added TRACE_CALL01e,26apr99,dbs remove class-specific debug code01d,26apr99,dbs add mem-pool to StubInfo class01c,23apr99,dbs add mem-pool to class01b,22apr99,dbs tidy up potential leaks01a,20apr99,dbs created during Grand Renaming*//* DESCRIPTION: StdStub -- */#include "StdStub.h"#include "Stublet.h"#include "SCM.h"#include "orpcLib.h"#include "PSFactory.h"/* Include symbol for diab */extern "C" int include_vxdcom_StdStub (void) { return 0; }////////////////////////////////////////////////////////////////////////////// VxStdStub::VxStdStub -- default ctor...//VxStdStub::VxStdStub () : m_pUnkServer (0), m_oid (0) { }////////////////////////////////////////////////////////////////////////////// VxStdStub destructor --//VxStdStub::~VxStdStub () { TRACE_CALL; // Release all the stublets associated with this instance of // VxStdStub... VxCritSec cs (m_mutex); STUBLETMAP::iterator i = m_stublets.begin (); while (i != m_stublets.end ()) { VxStublet* pStublet = (*i).second; if (pStublet) delete pStublet; ++i; } // Release the server object we are representing if (m_pUnkServer) m_pUnkServer->Release (); }////////////////////////////////////////////////////////////////////////////ULONG VxStdStub::AddRef (ULONG n, REFIPID ipid) { TRACE_CALL; VxCritSec cs (m_mutex); STUBLETMAP::const_iterator i = m_stublets.find (ipid); if (i != m_stublets.end ()) { VxStublet* pStublet = (*i).second; pStublet->addRefs (n); } return n; }////////////////////////////////////////////////////////////////////////////ULONG VxStdStub::Release (ULONG n, REFIPID ipid) { TRACE_CALL; ULONG nRefs=1; // Only take action if we have some refs to release... if (n) { VxCritSec cs (m_mutex); STUBLETMAP::const_iterator i = m_stublets.find (ipid); if (i != m_stublets.end ()) { VxStublet* pStublet = (*i).second; pStublet->relRefs (n); } // Now add up remote refs, and destroy stub if zero... nRefs = 0; for (i = m_stublets.begin (); i != m_stublets.end (); ++i) { VxStublet* pStublet = (*i).second; nRefs += pStublet->refs (); } } return nRefs; }////////////////////////////////////////////////////////////////////////////// interfaceAdd -- adds an interface-stub (a 'stublet') for the// given IID on the stubbed object, and adds 'nRefs' remote references// for it. Returns the IPID of the interface if requested.//// As objects typically re-use one of their interfaces as their// IUnknown we must always check the interface-ptr to see if an IPID// for it already exists (IPID values are repeatable, given an OID// value and an interface pointer) - if not we make a new entry.//// Also, there is no interface-stub (stublet) for the IUnknown interface// as the StdStub provides this functionality, so IUnknown is treated// as a special case here.//// Note the this StdStub object keeps one reference to the main// IUnknown of the server object in m_pUnkServer, and each stublet// also keeps one reference to the particular interface it is// representing, so even an object with only one interface will have 2// references to it when being remoted - one by the StdStub and one by// the stublet for its primary interface.//HRESULT VxStdStub::interfaceAdd ( REFIID iid, DWORD nRefs, IPID* pIpidNew ) { TRACE_CALL; HRESULT hr = S_OK; VxStublet* pStublet=0; VxStublet* pStubletTmp=0; // First, we must generate a unique IPID for this interface-ptr... IUnknown* pOther; hr = m_pUnkServer->QueryInterface (iid, (void**) &pOther); if (FAILED (hr)) return hr; // Using the other interface-ptr, we can create a // unique IPID value... IPID ipid = orpcIpidCreate (pOther, m_oid); // See if we already have a Stublet for this interface - we need // to look in the per-IPID first, as that is the unique case... { VxCritSec cs (m_mutex); STUBLETMAP::const_iterator i = m_stublets.find (ipid); if (i != m_stublets.end ()) { // there is already a stublet for this interface pStublet = (*i).second; // If it is a stublet for IUnknown, we need to convert it to // the new interface ID so it can dispatch methods beyond the // basic 3 methods of IUnknown. The simplest way of achieving // this is to erase it and make a new stublet... if (pStublet->iid () == IID_IUnknown) { // Save the remote refs we already had on the IUnknown ptr // of the server-object... pStubletTmp = pStublet; nRefs += pStubletTmp->refs (); // erase the table-entries m_stublets.erase (ipid); m_interfaces.erase (IID_IUnknown); // make sure we re-create the stublet... pStublet = 0; } } // Now create a new stublet if required... if (pStublet == 0) { // We don't have a stublet, so we must create one. We don't // release the one reference we got through QI since this will // be held by the stublet itself, and released when the object // is destroyed... VxPSFactory* pPSFactory = VxPSFactory::theInstance (); pStublet = pPSFactory->CreateStublet (pOther, iid, ipid); if (pStublet) { VxCritSec cs2 (m_mutex); m_stublets [ipid] = pStublet; } else hr = E_NOINTERFACE; } } // Common operations - add references to the stublet, and make // sure it has an entry in the per-interface table... if (pStublet) { VxCritSec cs3 (m_mutex); // make IID-related entry m_interfaces [iid] = pStublet; // add new remote-refs pStublet->addRefs (nRefs); // return the IPID value if (pIpidNew) *pIpidNew = pStublet->ipid (); } // Get rid of the old stublet (if we had one)... if (pStubletTmp) delete pStubletTmp; // Release the other interface pointer, as the stublet will // maintain its own reference to the interface... pOther->Release (); return hr; }////////////////////////////////////////////////////////////////////////////// VxStdStub::interfaceInfoGet -- get the interface pointer and// stub-function pointer for the given IPID value from its appropriate// stublet...//HRESULT VxStdStub::interfaceInfoGet ( REFIID /*riid*/, REFIPID ipid, ULONG opnum, IUnknown** ppunk, PFN_ORPC_STUB* ppfn, CLSID & classid ) { TRACE_CALL; VxStublet* pStublet = 0; HRESULT hr = S_OK; // Make sure its one of our IPIDs -- look for per-stublet info, // based on IPID... { VxCritSec cs (m_mutex); STUBLETMAP::const_iterator i = m_stublets.find (ipid); if (i == m_stublets.end ()) hr = RPC_E_INVALID_IPID; else pStublet = (*i).second; } // Now find the interface ptr if (pStublet && SUCCEEDED (hr)) hr = pStublet->stubInfoGet (opnum, ppunk, ppfn); classid = GUID_NULL; return hr; }////////////////////////////////////////////////////////////////////////////// VxStdStub::supportsInterface -- determine whether this stub object// supports the given interface (by IID)...//bool VxStdStub::supportsInterface (REFIID riid) { TRACE_CALL; VxCritSec cs (m_mutex); STUBLETMAP::const_iterator i = m_interfaces.find (riid); return (i != m_interfaces.end ()); }////////////////////////////////////////////////////////////////////////////// VxStdStub::adopt -- adopt a server-object to be 'exported'. If we// haven't already got its IUnknown then we find it now, and thus hold// one reference to it via m_pUnkServer. This reference will be// released when this StdStub is destroyed...//void VxStdStub::adopt (IUnknown* punk, OID oid) { if (! m_pUnkServer) { punk->QueryInterface (IID_IUnknown, (void**) &m_pUnkServer); m_oid = oid; } }////////////////////////////////////////////////////////////////////////////// Vtbl and stub dispatch-table for IUnknown -- these are never used,// they are just here to fit into the same architecture as all the// other _ps files. PSfactory requires them in order to be able to// return a Facelet for IUnknown...//const PFN_ORPC_STUB IUnknown_vxstub_functbl [] = { 0,0,0, };const VXDCOM_STUB_DISPTBL IUnknown_vxstub_disptbl = { 3, IUnknown_vxstub_functbl };const int IUnknown_vxproxy_vtbl=0;VXDCOM_PS_AUTOREGISTER(IUnknown);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -