StdStub.cpp
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:10k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* StdStub.cpp - COM/DCOM StdStub class implementation */
  2. /*
  3. modification history
  4. --------------------
  5. 02f,17dec01,nel  Add include symbol for StdStub.
  6. 02e,31jul01,dbs  import full T2 changes for stublet refcounts
  7. 02d,13jul01,dbs  fix up includes
  8. 02c,20sep00,nel  Add changes made in T2 since branch.
  9. 02b,28feb00,dbs  add fake stub disp table for IUnknown
  10. 02a,02aug99,dbs  return correct err code when no stublet
  11. 01z,27jul99,drm  Returning CLSID from interfaceInfoGet().
  12. 01y,09jul99,dbs  change to new ObjectExporter naming
  13. 01x,08jul99,dbs  remove print statements
  14. 01w,29jun99,dbs  no longer need to unregister StdStub in dtor
  15. 01v,28jun99,dbs  make Relase() return refs so deletion can be done by OX
  16. 01u,17jun99,aim  uses new SCM
  17. 01t,10jun99,dbs  remove op new and delete
  18. 01s,08jun99,dbs  remove use of mtmap
  19. 01r,04jun99,dbs  change GuidMap to mtmap
  20. 01q,03jun99,dbs  no return value from mutex lock
  21. 01p,02jun99,dbs  inherit from RpcDispatchTable
  22. 01o,26may99,dbs  fix remote ref-count for IUnknown stublet
  23. 01n,25may99,dbs  fix stublet refcount for IUnknown stublet
  24. 01m,24may99,dbs  ask SCM for local object exporter
  25. 01l,18may99,dbs  change to new marshaling architecture
  26. 01k,11may99,dbs  fix pure-virtual call problem
  27. 01j,11may99,dbs  simplify stub remoting architecture
  28. 01i,07may99,dbs  fix method calls to exporter
  29. 01h,29apr99,dbs  fix -Wall warnings
  30. 01g,28apr99,dbs  use COM_MEM_ALLOC for all classes
  31. 01f,26apr99,aim  added TRACE_CALL
  32. 01e,26apr99,dbs  remove class-specific debug code
  33. 01d,26apr99,dbs  add mem-pool to StubInfo class
  34. 01c,23apr99,dbs  add mem-pool to class
  35. 01b,22apr99,dbs  tidy up potential leaks
  36. 01a,20apr99,dbs  created during Grand Renaming
  37. */
  38. /*
  39.   DESCRIPTION:
  40.   StdStub -- 
  41. */
  42. #include "StdStub.h"
  43. #include "Stublet.h"
  44. #include "SCM.h"
  45. #include "orpcLib.h"
  46. #include "PSFactory.h"
  47. /* Include symbol for diab */
  48. extern "C" int include_vxdcom_StdStub (void)
  49.     {
  50.     return 0;
  51.     }
  52. //////////////////////////////////////////////////////////////////////////
  53. //
  54. // VxStdStub::VxStdStub -- default ctor...
  55. //
  56. VxStdStub::VxStdStub () : m_pUnkServer (0), m_oid (0)
  57.     {
  58.     }
  59. //////////////////////////////////////////////////////////////////////////
  60. //
  61. // VxStdStub destructor --
  62. //
  63. VxStdStub::~VxStdStub ()
  64.     {
  65.     TRACE_CALL;
  66.     // Release all the stublets associated with this instance of
  67.     // VxStdStub...
  68.     VxCritSec cs (m_mutex);
  69.     STUBLETMAP::iterator i = m_stublets.begin ();
  70.     while (i != m_stublets.end ())
  71. {
  72. VxStublet* pStublet = (*i).second;
  73. if (pStublet)
  74.     delete pStublet;
  75. ++i;
  76. }
  77.     
  78.     // Release the server object we are representing
  79.     if (m_pUnkServer)
  80.         m_pUnkServer->Release ();
  81.     }
  82. //////////////////////////////////////////////////////////////////////////
  83. //
  84. ULONG VxStdStub::AddRef (ULONG n, REFIPID ipid)
  85.     {
  86.     TRACE_CALL;
  87.     VxCritSec cs (m_mutex);
  88.     STUBLETMAP::const_iterator i = m_stublets.find (ipid);
  89.     if (i != m_stublets.end ())
  90. {
  91. VxStublet* pStublet = (*i).second;
  92. pStublet->addRefs (n);
  93. }
  94.     
  95.     return n;
  96.     }
  97. //////////////////////////////////////////////////////////////////////////
  98. //
  99. ULONG VxStdStub::Release (ULONG n, REFIPID ipid)
  100.     {
  101.     TRACE_CALL;
  102.     ULONG nRefs=1;
  103.     // Only take action if we have some refs to release...
  104.     if (n)
  105. {
  106. VxCritSec cs (m_mutex);
  107.     
  108. STUBLETMAP::const_iterator i = m_stublets.find (ipid);
  109. if (i != m_stublets.end ())
  110.     {
  111.     VxStublet* pStublet = (*i).second;
  112.     pStublet->relRefs (n);
  113.     }
  114. // Now add up remote refs, and destroy stub if zero...
  115. nRefs = 0;
  116. for (i = m_stublets.begin (); i != m_stublets.end (); ++i)
  117.     {
  118.     VxStublet* pStublet = (*i).second;
  119.     nRefs += pStublet->refs ();
  120.     }
  121. }
  122.     
  123.     return nRefs;
  124.     }
  125. //////////////////////////////////////////////////////////////////////////
  126. //
  127. // interfaceAdd -- adds an interface-stub (a 'stublet') for the
  128. // given IID on the stubbed object, and adds 'nRefs' remote references
  129. // for it. Returns the IPID of the interface if requested.
  130. //
  131. // As objects typically re-use one of their interfaces as their
  132. // IUnknown we must always check the interface-ptr to see if an IPID
  133. // for it already exists (IPID values are repeatable, given an OID
  134. // value and an interface pointer) - if not we make a new entry.
  135. //
  136. // Also, there is no interface-stub (stublet) for the IUnknown interface
  137. // as the StdStub provides this functionality, so IUnknown is treated
  138. // as a special case here.
  139. //
  140. // Note the this StdStub object keeps one reference to the main
  141. // IUnknown of the server object in m_pUnkServer, and each stublet
  142. // also keeps one reference to the particular interface it is
  143. // representing, so even an object with only one interface will have 2
  144. // references to it when being remoted - one by the StdStub and one by
  145. // the stublet for its primary interface.
  146. //
  147. HRESULT VxStdStub::interfaceAdd
  148.     (
  149.     REFIID      iid,
  150.     DWORD       nRefs,
  151.     IPID*       pIpidNew
  152.     )
  153.     {
  154.     TRACE_CALL;
  155.     HRESULT hr = S_OK;
  156.     VxStublet* pStublet=0;
  157.     VxStublet* pStubletTmp=0;
  158.     
  159.     // First, we must generate a unique IPID for this interface-ptr...
  160.     IUnknown* pOther;
  161.     hr = m_pUnkServer->QueryInterface (iid, (void**) &pOther);
  162.     if (FAILED (hr))
  163. return hr;
  164.     
  165.     // Using the other interface-ptr, we can create a
  166.     // unique IPID value...
  167.     IPID ipid = orpcIpidCreate (pOther, m_oid);
  168.     // See if we already have a Stublet for this interface - we need
  169.     // to look in the per-IPID first, as that is the unique case...
  170.     
  171.     {
  172.     VxCritSec cs (m_mutex);
  173.     STUBLETMAP::const_iterator i = m_stublets.find (ipid);
  174.     if (i != m_stublets.end ())
  175. {
  176. // there is already a stublet for this interface
  177. pStublet = (*i).second;
  178. // If it is a stublet for IUnknown, we need to convert it to
  179. // the new interface ID so it can dispatch methods beyond the
  180. // basic 3 methods of IUnknown. The simplest way of achieving
  181. // this is to erase it and make a new stublet...
  182. if (pStublet->iid () == IID_IUnknown)
  183.     {
  184.     // Save the remote refs we already had on the IUnknown ptr
  185.     // of the server-object...
  186.     pStubletTmp = pStublet;
  187.     nRefs += pStubletTmp->refs ();
  188.     // erase the table-entries
  189.     m_stublets.erase (ipid);
  190.     m_interfaces.erase (IID_IUnknown);
  191.     // make sure we re-create the stublet...
  192.     pStublet = 0;
  193.     }
  194. }
  195.     // Now create a new stublet if required...
  196.     if (pStublet == 0)
  197. {
  198. // We don't have a stublet, so we must create one. We don't
  199. // release the one reference we got through QI since this will
  200. // be held by the stublet itself, and released when the object
  201. // is destroyed...
  202. VxPSFactory* pPSFactory = VxPSFactory::theInstance ();
  203. pStublet = pPSFactory->CreateStublet (pOther,
  204.       iid,
  205.       ipid);
  206. if (pStublet)
  207.     {
  208.     VxCritSec cs2 (m_mutex);
  209.     m_stublets [ipid] = pStublet;
  210.     }
  211. else
  212.     hr = E_NOINTERFACE;
  213. }
  214.     }
  215.     // Common operations - add references to the stublet, and make
  216.     // sure it has an entry in the per-interface table...
  217.     if (pStublet)
  218. {
  219. VxCritSec cs3 (m_mutex);
  220. // make IID-related entry
  221. m_interfaces [iid] = pStublet;
  222. // add new remote-refs
  223. pStublet->addRefs (nRefs);
  224.     
  225. // return the IPID value
  226. if (pIpidNew)
  227.     *pIpidNew = pStublet->ipid ();
  228. }
  229.     // Get rid of the old stublet (if we had one)...
  230.     if (pStubletTmp)
  231. delete pStubletTmp;
  232.     
  233.     // Release the other interface pointer, as the stublet will
  234.     // maintain its own reference to the interface...
  235.     pOther->Release ();
  236.     
  237.     return hr;
  238.     }
  239. //////////////////////////////////////////////////////////////////////////
  240. //
  241. // VxStdStub::interfaceInfoGet -- get the interface pointer and
  242. // stub-function pointer for the given IPID value from its appropriate
  243. // stublet...
  244. //
  245. HRESULT VxStdStub::interfaceInfoGet
  246.     (
  247.     REFIID              /*riid*/,
  248.     REFIPID ipid,
  249.     ULONG opnum,
  250.     IUnknown** ppunk,
  251.     PFN_ORPC_STUB* ppfn,
  252.     CLSID & classid
  253.     )
  254.     {
  255.     TRACE_CALL;
  256.     VxStublet* pStublet = 0;
  257.     HRESULT hr = S_OK;
  258.     // Make sure its one of our IPIDs --  look for per-stublet info,
  259.     // based on IPID...
  260.     {    
  261.     VxCritSec cs (m_mutex);
  262.     
  263.     STUBLETMAP::const_iterator i = m_stublets.find (ipid);
  264.     if (i == m_stublets.end ())
  265. hr = RPC_E_INVALID_IPID;
  266.     else
  267. pStublet = (*i).second;
  268.     }
  269.     
  270.     // Now find the interface ptr
  271.     if (pStublet && SUCCEEDED (hr))
  272. hr = pStublet->stubInfoGet (opnum, ppunk, ppfn);
  273.     classid = GUID_NULL;
  274.     return hr;
  275.     }
  276. //////////////////////////////////////////////////////////////////////////
  277. //
  278. // VxStdStub::supportsInterface -- determine whether this stub object
  279. // supports the given interface (by IID)...
  280. //
  281. bool VxStdStub::supportsInterface (REFIID riid)
  282.     {
  283.     TRACE_CALL;
  284.     VxCritSec cs (m_mutex);
  285.     STUBLETMAP::const_iterator i = m_interfaces.find (riid);
  286.     return (i != m_interfaces.end ());
  287.     }
  288. //////////////////////////////////////////////////////////////////////////
  289. //
  290. // VxStdStub::adopt -- adopt a server-object to be 'exported'. If we
  291. // haven't already got its IUnknown then we find it now, and thus hold
  292. // one reference to it via m_pUnkServer. This reference will be
  293. // released when this StdStub is destroyed...
  294. //
  295. void VxStdStub::adopt (IUnknown* punk, OID oid)
  296.     {
  297.     if (! m_pUnkServer)
  298.         {
  299.         punk->QueryInterface (IID_IUnknown,
  300.   (void**) &m_pUnkServer);
  301.         m_oid = oid;
  302.         }
  303.     }
  304. //////////////////////////////////////////////////////////////////////////
  305. //
  306. // Vtbl and stub dispatch-table for IUnknown -- these are never used,
  307. // they are just here to fit into the same architecture as all the
  308. // other _ps files. PSfactory requires them in order to be able to
  309. // return a Facelet for IUnknown...
  310. //
  311. const PFN_ORPC_STUB IUnknown_vxstub_functbl [] = 
  312.     { 
  313.     0,0,0,
  314.     };
  315. const VXDCOM_STUB_DISPTBL IUnknown_vxstub_disptbl = 
  316.     {
  317.     3, 
  318.     IUnknown_vxstub_functbl
  319.     };
  320. const int IUnknown_vxproxy_vtbl=0;
  321. VXDCOM_PS_AUTOREGISTER(IUnknown);