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

VxWorks

开发平台:

C/C++

  1. /* SCM - Service Control Manager */
  2. /* Copyright (c) 1999 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 02u,03jan02,nel  Remove usage of alloca.
  7. 02t,17dec01,nel  Add include symbol for diab build.
  8. 02s,06aug01,dbs  remove instance-creation from SCM
  9. 02r,03aug01,dbs  remove usage of Thread class
  10. 02q,01aug01,dbs  fix channel-auth for unix only
  11. 02p,24jul01,dbs  fix ping-set add/del order, tidy up and comment
  12. 02o,18jul01,dbs  clean up stray printfs
  13. 02n,13jul01,dbs  fix up includes
  14. 02m,14mar01,nel  SPR#35873. Modify code to search for first good address in
  15.                  dual string array passed as part of marshaling an interface.
  16. 02l,02mar01,nel  SPR#35589. Add code to make Oxid addresses unique to prevent
  17.                  clash with other targets.
  18. 02k,20sep00,nel  ensure SCM closes down properly.
  19. 02j,22aug00,nel  Add assert to catch case where SCM hasn't been init and
  20.                  request of ObjectExporter is received.
  21. 02i,10aug00,nel  Win2K patch.
  22. 02h,07jun00,nel  Remove static c'tor dependency.
  23. 02g,15feb00,dbs  add global SCM interface functions
  24. 02f,20aug99,aim  make nextOID MT safe
  25. 02e,19aug99,aim  fix MLK
  26. 02d,19aug99,aim  change assert to VXDCOM_ASSERT
  27. 02c,18aug99,dbs  improve resilience by use of RC-ptr to ObjExp
  28. 02b,17aug99,aim  added Object Exporter project resources
  29. 02a,17aug99,dbs  protect remote-SCM list against threads
  30. 01z,05aug99,dbs  add sanity checks in CreateInstance()
  31. 01y,02aug99,dbs  remove stray printf
  32. 01x,26jul99,dbs  fix case where all QIs fail in successful activation
  33. 01w,26jul99,dbs  move marshaling into exporter
  34. 01v,22jul99,dbs  re-use remote SCM connections
  35. 01u,20jul99,dbs  make sure all out-args of RemoteActivation are zeroed when
  36.                  call fails
  37. 01t,16jul99,aim  serverAddress functionality moved to base class
  38. 01s,15jul99,dbs  check for local-machine activation
  39. 01r,15jul99,dbs  ensure proper HRESULTs are returned
  40. 01q,13jul99,aim  syslog api changes
  41. 01p,12jul99,aim  added timers
  42. 01o,09jul99,dbs  implement ping functionality in SCM now
  43. 01n,08jul99,dbs  clean up remote-SCM connection after activation
  44. 01m,07jul99,dbs  init next-setid in SCM ctor
  45. 01l,07jul99,dbs  only marshal resulting ptrs if activation succeeded
  46. 01k,07jul99,aim  change from RpcBinding to RpcIfClient
  47. 01j,06jul99,dbs  check return-value of remote-activation
  48. 01i,06jul99,dbs  simplify activation mechanism
  49. 01h,06jul99,dbs  make SCM create ObjectExporter at startup
  50. 01g,30jun99,aim  fixed mod history
  51. 01f,30jun99,aim  rework for error reporting
  52. 01e,28jun99,dbs  remove defaultInstance method
  53. 01d,25jun99,dbs  use channel-ID to determine channel authn status
  54. 01c,18jun99,aim  resolverAddress return ObjectExporters address
  55. 01b,08jun99,aim  rework
  56. 01a,27may99,aim  created
  57. */
  58. #include "SCM.h"
  59. #include "Reactor.h"
  60. #include "INETSockAddr.h"
  61. #include "ObjectExporter.h"
  62. #include "Syslog.h"
  63. #include "orpcLib.h"
  64. #include "private/comMisc.h"
  65. #include "StdProxy.h"
  66. #include "RpcIfClient.h"
  67. #include "TimeValue.h"
  68. #include "taskLib.h"
  69. /* Include symbol for diab */
  70. extern "C" int include_vxdcom_SCM (void)
  71.     {
  72.     return 0;
  73.     }
  74. EXTERN_C const VXDCOM_STUB_DISPTBL IRemoteActivation_vxstub_disptbl;
  75. EXTERN_C const VXDCOM_STUB_DISPTBL IOXIDResolver_vxstub_disptbl;
  76. EXTERN_C const VXDCOM_STUB_DISPTBL ISystemActivator_vxstub_disptbl;
  77. // SCM statics
  78. SCM* SCM::s_theSCM = 0;
  79. //////////////////////////////////////////////////////////////////////////
  80. //
  81. // SCM destructor
  82. //
  83. SCM::~SCM ()
  84.     {
  85.     COM_ASSERT (s_theSCM == this);
  86.     ObjectExporterPtr pObjectExporter = objectExporter ();
  87.     pObjectExporter->AddRef ();
  88.     if (pObjectExporter)
  89. {
  90. // Force the exporter to release all exported objects
  91. pObjectExporter->objectUnregisterAll ();
  92. // Remove it from our map...
  93. oxidUnregister (pObjectExporter->oxid ());
  94. }
  95.     pObjectExporter->Release ();    
  96.     s_theSCM = 0;
  97.     cout << "SCM : closed down" << endl;
  98.     }
  99. //////////////////////////////////////////////////////////////////////////
  100. //
  101. SCM::SCM (Reactor* r, NTLMSSP* ssp)
  102.   : RpcIfServer (r, &m_dispatcher),
  103.     m_mutex (),
  104.     m_exporters (),
  105.     m_oidSets (),
  106.     m_nextSetid (0),
  107.     m_dispatchTable (),
  108.     m_dispatcher (&m_dispatchTable),
  109.     m_ssp (ssp)
  110.     {
  111.     COM_ASSERT(s_theSCM == 0);
  112.     s_theSCM = this;
  113.     
  114.     // Initialise OXID (Object Exporter ID). We factor this node's IP
  115.     // address into the OXID to make sure it has some chance of being
  116.     // unique, even among similar nodes. This code should really be
  117.     // part of the 'network addressing' classes, but that requires
  118.     // some deeper rework in future...
  119.     char hostname [64];
  120.     long adr = -1;
  121.     if (gethostname (hostname, sizeof (hostname)) == 0)
  122.         {
  123. #ifdef VXDCOM_PLATFORM_VXWORKS
  124. adr = ::hostGetByName (hostname);
  125. #else
  126. hostent* hp = ::gethostbyname (hostname);
  127. if (hp != 0)
  128.             adr = (long) hp->h_addr;
  129. #endif
  130.         }
  131.     // If we got some valid IP address, 
  132.     if (adr != -1)
  133.         // Use the host IP address to weight the initial OXID value...
  134.         m_nextOxid = ((LONGLONG) adr) << 32;
  135.     else
  136.         // Make some feeble attempt to randomize it...
  137.         m_nextOxid = ::time (0);
  138.     // Initialise the next available OID (Object ID), using the
  139.     // IP-factored OXID value, plus the thread ID...
  140.     m_nextOid = m_nextOxid + ::taskIdSelf ();
  141.     }
  142. ////////////////////////////////////////////////////////////////////////////
  143. //
  144. // returns the string indicating the address of the IOXIDResolver
  145. // interface.
  146. HRESULT SCM::addressBinding (BSTR* pbsResAddr)
  147.     {
  148.     if (rpcAddressFormat (pbsResAddr, 0 /* no portNumber */) < 0)
  149. return E_FAIL;
  150.     else
  151. return S_OK;
  152.     }
  153. //////////////////////////////////////////////////////////////////////////
  154. //
  155. // theSCM - returns the one and only instance
  156. //
  157. SCM* SCM::theSCM ()
  158.     {
  159.     return s_theSCM;
  160.     }
  161. //////////////////////////////////////////////////////////////////////////
  162. //
  163. // registerStdInterfaces - add DCE interfaces to tables
  164. //
  165. void SCM::registerStdInterfaces ()
  166.     {
  167.     m_dispatchTable.dceInterfaceRegister
  168. (IID_IRemoteActivation,
  169.  &IRemoteActivation_vxstub_disptbl);
  170.     m_dispatchTable.dceInterfaceRegister
  171. (IID_IOXIDResolver,
  172.  &IOXIDResolver_vxstub_disptbl);
  173.     m_dispatchTable.dceInterfaceRegister
  174. (IID_ISystemActivator,
  175.  &ISystemActivator_vxstub_disptbl);
  176.     }
  177. //////////////////////////////////////////////////////////////////////////
  178. //
  179. NTLMSSP* SCM::ssp ()
  180.     {
  181.     if (s_theSCM)
  182. return s_theSCM->m_ssp;
  183.     return 0;
  184.     }
  185. //////////////////////////////////////////////////////////////////////////
  186. //
  187. // startService - initiate a SCM service in the current task
  188. //
  189. int SCM::startService ()
  190.     {
  191.     INETSockAddr addr(VXDCOM_SCM_ENDPOINT);
  192.     Reactor r;
  193.     NTLMSSP ssp;
  194.     SCM scm (&r, &ssp);
  195.     SCM::PingTimer pingTimer;
  196.     int result = scm.init (addr);
  197.     if (result == 0)
  198. {
  199. scm.reactorGet()->timerAdd (&pingTimer, TimeValue (5));
  200. S_INFO (LOG_SCM, "SCM bound to " << addr << " fd=" << scm.handleGet ());
  201. result = scm.reactorGet()->run ();
  202. }
  203.     
  204.     return result;
  205.     }
  206. //////////////////////////////////////////////////////////////////////////
  207. //
  208. // init - initialize the SCM
  209. //
  210. int SCM::init (INETSockAddr& addr)
  211.     {
  212.     registerStdInterfaces ();
  213.     int result = open (addr, reactorGet(), 1 /* reuse addr */);
  214.     if (result == 0)
  215. {
  216. if ((result = hostAddrGet (addr)) == 0)
  217.     {
  218.     // Now create the one-and-only object exporter
  219.     ObjectExporter* pExp=0;
  220.     HRESULT hr = newObjectExporter (&pExp);
  221.     if (SUCCEEDED (hr))
  222. {
  223. oxidRegister (pExp->oxid (), pExp);
  224. hr = pExp->init ();
  225. if (FAILED (hr))
  226.     {
  227.     result = hr;
  228.     }
  229. }
  230.     }
  231. }
  232.     else
  233.         {
  234. S_ERR (LOG_SCM|LOG_ERRNO, "cannot bind to " << addr);
  235. }
  236.     return result;
  237.     }
  238. //////////////////////////////////////////////////////////////////////////
  239. //
  240. // stopService - terminate the SCM instance by closing down reactor
  241. //
  242. int SCM::stopService ()
  243.     {
  244.     if (s_theSCM)
  245. {
  246. s_theSCM->reactorGet()->eventLoopEnd ();
  247. s_theSCM->close ();
  248. }
  249.     return 0;
  250.     }
  251. //////////////////////////////////////////////////////////////////////////
  252. //
  253. // GetNextOid - return the next OID (Object ID) value
  254. //
  255. HRESULT SCM::GetNextOid (OID* pOid)
  256.     {
  257.     VxCritSec cs (m_mutex);
  258.     *pOid = ++m_nextOid;
  259.     return S_OK;
  260.     }
  261. //////////////////////////////////////////////////////////////////////////
  262. //
  263. // nextOXID - return the next OXID (Object eXporter ID) value
  264. //
  265. OXID SCM::nextOXID ()
  266.     {
  267.     VxCritSec cs (m_mutex);
  268.     return ++m_nextOxid;
  269.     }
  270. //////////////////////////////////////////////////////////////////////////
  271. //
  272. // nextOID - return the next OID (Object ID) value
  273. //
  274. OID SCM::nextOid ()
  275.     {
  276.     OID o;
  277.     this->GetNextOid (&o);
  278.     return o;
  279.     }
  280. ////////////////////////////////////////////////////////////////////////////
  281. //
  282. // SCM::objectExporter -- returns the object exporter for the
  283. // current context, i.e. the task within which the call is made. In
  284. // future this may be PD-dependent, etc, but for now, it simply
  285. // returns the one and only exporter. Note that it *doesn't* add a
  286. // reference for it...
  287. //
  288. ObjectExporter* SCM::objectExporter ()
  289.     {
  290.     SCM* scm = theSCM ();
  291.     ObjectExporter* pExp = 0;
  292.     // enter critical section
  293.     VxCritSec critSec (scm->m_mutex);
  294.     if (scm->m_exporters.size () == 0)
  295. pExp = 0;
  296.     else
  297. pExp = (* (scm->m_exporters.begin ())).second;
  298.     COM_ASSERT(pExp != NULL);
  299.     return pExp;
  300.     }
  301. //////////////////////////////////////////////////////////////////////////
  302. //
  303. // newObjectExporter -- utility to create an instance of the 
  304. // ObjectExporter. This is a COM object, so is dealt with as such...
  305. //
  306. HRESULT SCM::newObjectExporter (ObjectExporter** ppObjExp)
  307.     {
  308.     HRESULT hr = S_OK;
  309.     
  310.     // Create an instance of Object Exporter, with one ref...
  311.     ObjectExporterPtr pOX = new ObjectExporter (reactorGet(),
  312.                                                nextOXID ());
  313.     // Did we get one?
  314.     if (! pOX)
  315.         return E_OUTOFMEMORY;
  316.     
  317.     // Open it on the required local endpoint...
  318.     INETSockAddr addr (g_vxdcomObjectExporterPortNumber);
  319.     if (pOX->open (addr, reactorGet(), 1) < 0)
  320.         {
  321.         // Cannot bind to loca endpoint...
  322.         pOX->Release ();
  323.         pOX = 0;
  324.         hr = MAKE_HRESULT (SEVERITY_ERROR,
  325.                            FACILITY_RPC,
  326.                            RPC_S_CANT_CREATE_ENDPOINT);
  327.         }
  328.     else
  329.         {
  330.         // Make sure we got an endpoint?
  331.         if (pOX->hostAddrGet (addr) < 0)
  332.             {
  333.             pOX->Release ();
  334.             pOX = 0;
  335.             hr = E_UNEXPECTED;
  336.             }
  337.         else
  338.             {
  339.             // Success!
  340.             S_INFO (LOG_SCM, "ObjectExporter bound to "
  341.                     << addr
  342.                     << " fd="
  343.                     << pOX->handleGet ());
  344.             }
  345.         }
  346.     if (ppObjExp)
  347.         *ppObjExp = pOX;
  348.     
  349.     return hr;        
  350.     }
  351. //////////////////////////////////////////////////////////////////////////
  352. //
  353. // SCM::RemoteActivation -- called by external DCE clients to activate
  354. // an instance of an object-class on this machine.
  355. //
  356. HRESULT SCM::RemoteActivation
  357.     (
  358.     int channelId, // channel
  359.     ORPCTHIS* pOrpcThis, // housekeeping
  360.     ORPCTHAT* pOrpcThat, // returned housekeeping
  361.     GUID* pClsid, // CLSID to activate
  362.     OLECHAR* pwszObjName, // NULL
  363.     MInterfacePointer* pObjStorage, // NULL
  364.     DWORD clientImpLevel, // security
  365.     DWORD mode, // all-1's == get-class-obj
  366.     DWORD nInterfaces, // num of interfaces
  367.     IID* pIIDs, // size_is (nItfs)
  368.     USHORT cReqProtseqs, // num of protseqs
  369.     USHORT arReqProtseqs[],// array of protseqs
  370.     OXID* pOxid, // returned OXID
  371.     DUALSTRINGARRAY** ppdsaOxidBindings,// returned bindings
  372.     IPID* pIpidRemUnknown,// returned IPID
  373.     DWORD* pAuthnHint, // returned security info
  374.     COMVERSION* pSvrVersion, // returned server version
  375.     HRESULT* phr, // returned activation result
  376.     MInterfacePointer** ppItfData, // returned interface(s)
  377.     HRESULT* pResults // returned results per i/f
  378.     )
  379.     {
  380.     // Preset default out-args...
  381.     pOrpcThat->flags = 1;
  382.     pOrpcThat->extensions = 0;
  383.     pSvrVersion->MinorVersion = 2;
  384.     pSvrVersion->MajorVersion = 5;
  385.     *pAuthnHint = ssp()->authnLevel ();
  386.     
  387.     // First check with the authentication service that this
  388.     // channel-ID is allowed to activate objects...
  389. #ifndef VXDCOM_PLATFORM_SOLARIS
  390.     HRESULT hrChannel = E_ACCESSDENIED;
  391.     NTLMSSP* pssp = ssp ();
  392.     if (pssp)
  393. hrChannel = pssp->channelStatusGet (channelId);
  394. #else    
  395.     HRESULT hrChannel = S_OK;
  396. #endif
  397.     if (FAILED (hrChannel))
  398. {
  399. // Set out-args to NULL...
  400. *pOxid = 0;
  401. *ppdsaOxidBindings = 0;
  402. *pIpidRemUnknown = GUID_NULL;
  403. for (DWORD n=0; n < nInterfaces; ++n)
  404.     {
  405.     pResults [n] = E_FAIL;
  406.     ppItfData [n] = 0;
  407.     }
  408. *phr = hrChannel;
  409. return S_OK;
  410. }
  411.     
  412.     // allocate space for MULTI_QI array
  413.     MULTI_QI* mqi = new MULTI_QI [nInterfaces];
  414.     if (0 == mqi) return E_OUTOFMEMORY;
  415.     
  416.     for (DWORD j=0; j < nInterfaces; ++j)
  417. {
  418. // fill MQI array with input arguments...
  419. mqi [j].pIID = &pIIDs [j];
  420. mqi [j].pItf = 0;
  421. mqi [j].hr = S_OK;
  422. // initialise output-array elements to NULL
  423. ppItfData [j] = 0;
  424. }
  425.     // Now activate the requested object/class -- first we need to
  426.     // know the current object-exporter so we can discover its
  427.     // IRemUnknown IPID and OXID value...
  428.     ObjectExporter* pExp = objectExporter ();
  429.     *pOxid = pExp->oxid ();
  430.     *pIpidRemUnknown = pExp->ipidRemUnknown ();
  431.     HRESULT hrActivation = instanceCreate (mode,
  432.    *pClsid,
  433.    nInterfaces,
  434.    mqi);
  435.     // Check that the entire activation was successful, i.e. all
  436.     // marshaling worked...
  437.     DUALSTRINGARRAY* pdsa = 0;
  438.     
  439.     if (SUCCEEDED (hrActivation))
  440. {
  441. // Now marshal each of the resulting interface pointers, and
  442. // output the HRESULTs. We also need to release the local
  443. // reference from each interface-ptr before it is exported. At
  444. // least one of the MQIs must have succeeded or else we return
  445. // E_NOINTERFACE as the hrActivation...
  446. bool allFailed = true;
  447. bool someFailed = false;
  448. for (DWORD k=0; k < nInterfaces; ++k)
  449.     {
  450.     // Marshal each individual interface ptr, or else fail it
  451.     // with the appropriate error-code...
  452.     
  453.     HRESULT hrm = mqiMarshal (*pClsid, mqi [k], &ppItfData [k]);
  454.     if (FAILED (hrm))
  455. pResults [k] = hrm;
  456.     else
  457. pResults [k] = mqi [k].hr;
  458.     // Fail the overall result if any individual interface
  459.     // failed to be marshaled, otherwise release the local ref
  460.     // as the interface has now been remoted successfully...
  461.     if (SUCCEEDED (pResults [k]))
  462. {
  463. allFailed = false;
  464. mqi [k].pItf->Release ();
  465. }
  466.     else
  467. {
  468. someFailed = true;
  469. hrActivation = mqi [k].hr;
  470. }
  471.     }
  472. // Decide on result -- if all failed that must take priority...
  473. if (someFailed)
  474.     hrActivation = CO_S_NOTALLINTERFACES;
  475. if (allFailed)
  476.     hrActivation = E_NOINTERFACE;
  477. if (SUCCEEDED (hrActivation))
  478.     {     
  479.     // Find the address and endpoint of the exporter that is
  480.     // exporting the object that has just been marshaled
  481.     BSTR bsSvrAddr;
  482.     hrActivation = pExp->addressBinding (&bsSvrAddr);
  483.     if (SUCCEEDED (hrActivation))
  484. {
  485. const OLECHAR wszSecInfo [] = { 0x0A, 0xFFFF, 0 };
  486. // Allocate memory to hold the DSA, allowing some
  487. // leeway at the end (16 bytes)...
  488. const DWORD dsaLen = sizeof (DUALSTRINGARRAY) + 
  489.      (2 * SysStringLen (bsSvrAddr)) +
  490.      (2 * vxcom_wcslen (wszSecInfo)) +
  491.      16;
  492.     
  493. pdsa = (DUALSTRINGARRAY*) CoTaskMemAlloc (dsaLen);
  494. if (pdsa)
  495.     {
  496.     // Format the DSA...
  497.     hrActivation = orpcDSAFormat (pdsa,
  498.   dsaLen,
  499.   bsSvrAddr,
  500.   wszSecInfo);
  501.     }
  502. else
  503.     // Memory ran out?
  504.     hrActivation = E_OUTOFMEMORY;
  505.     
  506. SysFreeString (bsSvrAddr);
  507. }
  508.     }
  509. }
  510.     
  511.     // Activation HRESULT is an out-arg...
  512.     *phr = hrActivation;
  513.     *ppdsaOxidBindings = pdsa;
  514.     // free up the mqi structure allocated on the heap
  515.     delete []mqi;
  516.     // This function always returns S_OK...
  517.     return S_OK;
  518.     }
  519. //////////////////////////////////////////////////////////////////////////
  520. //
  521. // SCM::mqiMarshal -- marshals a single MULTI_QI entry into an
  522. // MInterfacePointer structure...
  523. //
  524. HRESULT SCM::mqiMarshal
  525.     (
  526.     REFCLSID clsid, // class ID of containing object
  527.     const MULTI_QI& mqi, // MULTI_QI structure
  528.     MInterfacePointer** ppMIP // output is marshaled ptr
  529.     )
  530.     {
  531.     // Check the MQI contains a valid result...
  532.     if (FAILED (mqi.hr))
  533. {
  534. *ppMIP = 0;
  535. return mqi.hr;
  536. }
  537.     
  538.     // Create a stream...
  539.     IStream* pStrm=0;
  540.     HRESULT hr = VxRWMemStream::CreateInstance (0,
  541. IID_IStream,
  542. (void**) &pStrm);
  543.     if (SUCCEEDED (hr))
  544. {
  545. // Marshal interface-ptr into stream - we use the object
  546. // exporter to do this...
  547. ObjectExporter* pExp = objectExporter ();
  548. COM_ASSERT (pExp);
  549. hr = pExp->objectMarshal (clsid,
  550.   pStrm,
  551.   *(mqi.pIID),
  552.   mqi.pItf,
  553.   MSHCTX_DIFFERENTMACHINE,
  554.   0,
  555.   MSHLFLAGS_NORMAL,
  556.   0);
  557. // Now convert the marshaled packet into a MInterfacePointer...
  558. if (SUCCEEDED (hr))
  559.     {
  560.     ISimpleStream* pss=0;
  561.     hr = pStrm->QueryInterface (IID_ISimpleStream,
  562. (void**) &pss);
  563.     if (SUCCEEDED (hr))
  564. {
  565. size_t strmSize = pss->size ();
  566. pss->locationSet (0);
  567. MInterfacePointer* mip
  568.     = (MInterfacePointer*) CoTaskMemAlloc (sizeof
  569.    (MInterfacePointer) +
  570.    strmSize);
  571. if (mip)
  572.     {
  573.     mip->ulCntData = strmSize;
  574.     pss->extract (mip->abData, strmSize);
  575.     pStrm->Release ();
  576.     }
  577. else
  578.     hr = E_OUTOFMEMORY;
  579. *ppMIP = mip;
  580. }
  581.     }
  582. pStrm->Release ();
  583. }
  584.     return hr;
  585.     }
  586. ////////////////////////////////////////////////////////////////////////////
  587. //
  588. // IndirectActivation - activate remote server on behalf of local client
  589. //
  590. //
  591. HRESULT SCM::IndirectActivation
  592.     (
  593.     LPWSTR              pwszServerName, // PROTSEQ + server name 
  594.     REFGUID clsid,          // CLSID to activate
  595.     DWORD mode,           // all-1's == get-class-obj
  596.     DWORD nItfs,          // num of interfaces
  597.     IID* iids,           // array of IIDs
  598.     MInterfacePointer** ppItfData, // returned interface(s)
  599.     HRESULT* pResults // returned results per i/f
  600.     )
  601.     {
  602.     // Create a string-binding representing the remote SCM...
  603.     RpcStringBinding sbRemoteScm (pwszServerName+1,
  604.   pwszServerName[0],
  605.   VXDCOM_SCM_ENDPOINT);
  606.     // Prepare for RemoteActivation call...
  607.     ORPCTHIS orpcThis;
  608.     ORPCTHAT orpcThat;
  609.     OXID oxid;
  610.     IPID ipidRemUnknown;
  611.     HRESULT hrActivation;
  612.     DUALSTRINGARRAY* pdsaOxidBinding = 0;
  613.     USHORT arProtseqs [] = { pwszServerName[0] };
  614.     COMVERSION serverVersion;
  615.     DWORD               authnHint;
  616.     // Initialise in-args...
  617.     orpcThis.version.MajorVersion = 5;
  618.     orpcThis.version.MinorVersion = 1;
  619.     orpcThis.flags = 0;
  620.     orpcThis.reserved1 = 0;
  621.     orpcThis.causality = CLSID_NULL;
  622.     orpcThis.extensions = 0;
  623.     // Get an RPC binding handle to the SCM on the machine where the
  624.     // object (or rather its class-object) lives. We don't need to
  625.     // free the binding handle later as it belongs to the RemoteSCM
  626.     // object itself. First we look to see if we already have a
  627.     // connection to that remote SCM...
  628.  
  629.     SPRemoteSCM& pscm = m_remoteScmTable [sbRemoteScm];
  630.     if (! pscm)
  631.         pscm = new RemoteSCM (sbRemoteScm);
  632.  
  633.     IOrpcClientChannelPtr pClient = pscm->connectionGet ();
  634.     // Request activation - note that this function is defined to
  635.     // always return S_OK even if some of the internal activation
  636.     // results are failures...
  637.     HRESULT hr = IRemoteActivation_RemoteActivation_vxproxy
  638.         (pClient, // Client handle
  639.          &orpcThis, // ORPCTHIS
  640.          &orpcThat, // [out] ORPCTHAT
  641.          (CLSID*)&clsid, // CLSID
  642.          0, // pwszObjName
  643.          0, // pObjStorage
  644.          0, // imp level
  645.          mode,                          // class-mode?
  646.          nItfs,                         // num itfs
  647.          iids,                          // IIDs
  648.          1,                             // num protseqs
  649.          arProtseqs,                    // array of protseqs
  650.          &oxid,                         // [out] oxid
  651.          &pdsaOxidBinding, // [out] string binding
  652.          &ipidRemUnknown, // [out] ipid of rem-unknown
  653.          &authnHint,                    // [out] auth hint
  654.          &serverVersion, // [out] server version
  655.          &hrActivation,                 // [out] activation result
  656.          ppItfData, // [out] resulting interfaces
  657.          pResults); // [out] results for each QI
  658.     // Check results...
  659.     if (FAILED (hr))
  660.         return hr;
  661.     if (FAILED (hrActivation))
  662.         return hrActivation;
  663.     if (! pdsaOxidBinding)
  664.         return E_FAIL;
  665.     // Now we have discovered the OXID-resolution for the OXID that is
  666.     // exporting the newly-created object, we need to tell the SCM
  667.     // about it...
  668.     oxidBindingUpdate (oxid,
  669.                        sbRemoteScm,
  670.                        ipidRemUnknown, 
  671.                        RpcStringBinding (pdsaOxidBinding));
  672.     return S_OK;
  673.     }
  674. ////////////////////////////////////////////////////////////////////////////
  675. //
  676. // instanceCreate -- creates an instance of a class, marshals its
  677. // interface(s), and returns the whole lot in one go! This is used by
  678. // the SCM to create instances in response to external requests via
  679. // the IRemoteActivation interface.
  680. //
  681. HRESULT SCM::instanceCreate
  682.     (
  683.     DWORD mode, // get-class-obj?
  684.     REFCLSID clsid, // CLSID to create
  685.     DWORD nInterfaces, // num i/f's to return
  686.     MULTI_QI* mqi // resulting itf ptrs
  687.     )
  688.     {
  689.     // First create a class-factory object...
  690.     cout << "In SCM::instanceCreate" << endl;
  691.     
  692.     IUnknown* punk=0;
  693.     IClassFactory* pCF;
  694.     HRESULT hr = comClassObjectGet (clsid,
  695.                                     CLSCTX_INPROC_SERVER,
  696.                                     "",
  697.                                     IID_IClassFactory,
  698.                                     (void**) &pCF);
  699.     if (FAILED (hr))
  700.         {
  701.         cout << "no class object" << endl;
  702.         return hr;
  703.         }
  704.     // If we are being called in CLASS-MODE then just return the
  705.     // class-factory pointer, otherwise create an instance and QI
  706.     // it for all requested interfaces...
  707.     if (mode == MODE_GET_CLASS_OBJECT)
  708.         {
  709.         punk = pCF;
  710.         }
  711.     else
  712.         {
  713.         // Create an instance of the class...
  714.         hr = pCF->CreateInstance (0,
  715.                                   IID_IUnknown,
  716.                                   (void**) &punk);
  717.         pCF->Release();
  718.         }
  719.         
  720.     // Now QI for each of the requested interfaces...
  721.     if (SUCCEEDED (hr))
  722.         {
  723.         for (ULONG n=0; n < nInterfaces; ++n)
  724.             {
  725.             mqi[n].hr = punk->QueryInterface (*(mqi[n].pIID),
  726.                                               (void**) &mqi[n].pItf);
  727.             if (FAILED (mqi[n].hr))
  728.                 hr = CO_S_NOTALLINTERFACES;
  729.             }
  730.         punk->Release ();
  731.         }
  732.     else
  733.         cout << "class-factory failed" << endl;
  734.     
  735.     return hr;
  736.     }
  737. //////////////////////////////////////////////////////////////////////////
  738. //
  739. // oxidBindingUpdate -- update our table of OXID-resolver and
  740. // RemoteOxid entries...
  741. //
  742. void SCM::oxidBindingUpdate
  743.     (
  744.     OXID oxid,
  745.     const RpcStringBinding& sbRemoteScm,
  746.     REFIPID ipidRemUnk,
  747.     const RpcStringBinding& sbRemoteOxid
  748.     )
  749.     {
  750.     // See if we already know about a remote SCM at this address...
  751.     SPRemoteSCM& rscm = m_remoteScmTable [sbRemoteScm];
  752.     // If not, make a new one...
  753.     if (! rscm)
  754. rscm = new RemoteSCM (sbRemoteScm);
  755.     // Now update its knowledge of this OXID...
  756.     rscm->oxidBindingUpdate (oxid, ipidRemUnk, sbRemoteOxid);
  757.     }
  758. //////////////////////////////////////////////////////////////////////////
  759. //
  760. // oxidResolve -- given an OXID and a string-binding to the remote
  761. // machine on which the OXID is known to exist, return the address of
  762. // the actual remote Object Exporter. The 'resAddr' may contain the
  763. // port-number 135, or may omit it...
  764. //
  765. HRESULT SCM::oxidResolve
  766.     (
  767.     OXID oxid,
  768.     const RpcStringBinding& resAddr,
  769.     SPRemoteOxid& remOxid
  770.     )
  771.     {
  772.     // Create string-binding to remote SCM/OxidResolver, with explicit
  773.     // port-number...
  774.     RpcStringBinding sbor (resAddr.ipAddress (),
  775.    resAddr.protocolSequence (),
  776.    VXDCOM_SCM_ENDPOINT);
  777.     // If we don't already have a RemoteSCM object representing that
  778.     // network address, then create one...
  779.     SPRemoteSCM rscm = 0;
  780.     {
  781.     VxCritSec cs1 (m_mutex);
  782.     REMOTESCMMAP::const_iterator s = m_remoteScmTable.find (sbor);
  783.     if (s == m_remoteScmTable.end ())
  784. {
  785. rscm = new RemoteSCM (sbor);
  786. m_remoteScmTable [sbor] = rscm;
  787. }
  788.     else
  789. rscm = (*s).second;
  790.     }
  791.     // Now see if it knows about the specific OXID...
  792.     if (! rscm->oxidBindingLookup (oxid, remOxid))
  793. {
  794. IPID ipidRemUnk;
  795. DWORD authnHint;
  796. DUALSTRINGARRAY* pdsa=0;
  797. OLECHAR arProtseqs [] = { NCACN_IP_TCP };
  798. HRESULT hr = S_OK;
  799. // Need to remotely query the OXID-resolver for the answer...
  800.         IOrpcClientChannelPtr pChannel = new RpcIfClient (resAddr);
  801.     
  802. // Find the (remote) server, given the OXID and the string-
  803. // binding for the resolver - this will be cached and
  804. // re-used in future if the same OXID recurs...
  805. hr = IOXIDResolver_ResolveOxid_vxproxy (pChannel,
  806. &oxid,
  807. 1,
  808. arProtseqs,
  809. &pdsa,
  810. &ipidRemUnk,
  811. &authnHint);
  812. // Only S_OK is valid as a 'good' result, anything else may be
  813. // a warning that the method failed somehow...
  814. if (hr == S_OK)
  815.     {
  816.             // Now we have all the info, we need to record it...
  817.             oxidBindingUpdate (oxid,
  818.                                sbor,
  819.                                ipidRemUnk, 
  820.                                RpcStringBinding (pdsa));
  821.             }
  822.                 
  823. // Tidy up
  824. if (pdsa)
  825.             CoTaskMemFree (pdsa);
  826. }
  827.     
  828.     // Return the new binding...
  829.     if (! rscm->oxidBindingLookup (oxid, remOxid))
  830. return OR_INVALID_OXID;
  831.     
  832.     return S_OK;
  833.     }
  834. //////////////////////////////////////////////////////////////////////////
  835. //
  836. // SCM::SimplePing -- ping all the objects whose OIDs are in the set
  837. // indicated by 'setid'...
  838. //
  839. HRESULT SCM::SimplePing
  840.     (
  841.     SETID setid // [in] set ID
  842.     )
  843.     {
  844.     TRACE_CALL;
  845.     
  846.     S_INFO (LOG_SCM, "SimplePing()");
  847.     // enter critical section
  848.     VxCritSec critSec (m_mutex);
  849.     // Find the appropriate set...
  850.     OIDSETMAP::iterator i = m_oidSets.find (setid);
  851.     if (i == m_oidSets.end ())
  852. return OR_INVALID_SET;
  853.     HRESULT hr = S_OK;
  854.     // Iterate over all OIDs in this set...
  855.     OIDSET& oidset = (*i).second;
  856.     for (OIDSET::iterator o = oidset.begin(); o != oidset.end (); ++o)
  857. {
  858. OID oid = (*o);
  859.         bool pinged = false;
  860. // Ping the exporter associated with this OID - we don't know
  861. // which one it is so try them all until we hit one
  862. for (OXIDMAP::iterator j = m_exporters.begin ();
  863.      j != m_exporters.end ();
  864.      ++j)
  865.     {
  866.     ObjectExporterPtr pExp = (*j).second;
  867.     COM_ASSERT (pExp != 0);
  868.     if (pExp && pExp->oidPing (oid) == S_OK)
  869.         {
  870.                 pinged = true;
  871.                 break;
  872.                 }
  873.     }
  874.             if (! pinged)
  875.                 hr = OR_INVALID_OID;
  876. }
  877.     
  878.     return hr;
  879.     }
  880. //////////////////////////////////////////////////////////////////////////
  881. //
  882. // SCM::ComplexPing -- add/remove some OIDs from the ping-set
  883. // indicated by the received SETID, which may also be zero menaing
  884. // 'create a new set'...
  885. //
  886. HRESULT SCM::ComplexPing
  887.     (
  888.     SETID* pSetid, // [in,out] set ID
  889.     USHORT SeqNum, // [in] sequence number
  890.     USHORT cAddToSet, // [in]
  891.     USHORT cDelFromSet, // [in]
  892.     OID AddToSet [], // [in]
  893.     OID DelFromSet [], // [in]
  894.     USHORT* pPingBackoffFactor // [out]
  895.     )
  896.     {
  897.     TRACE_CALL;
  898.     S_INFO (LOG_SCM, "ComplexPing()");
  899.     
  900.     SETID setid = *pSetid;
  901.     // enter critical section
  902.     VxCritSec critSec (m_mutex);
  903.     
  904.     // Are we being asked to create a new set?
  905.     if (setid == 0)
  906. {
  907. // Yes we are -- make a new entry in the sets table...
  908. setid = ++m_nextSetid;
  909. m_oidSets [setid] = OIDSET ();
  910. }
  911.     
  912.     // Make sure we have the entry now...
  913.     OIDSETMAP::iterator i = m_oidSets.find (setid);
  914.     if (i == m_oidSets.end ())
  915. return OR_INVALID_SET;
  916. HRESULT hr = S_OK;
  917.     // Delete some OIDs from the set...
  918.     for (unsigned int d=0; d < cDelFromSet; ++d)
  919. (*i).second.erase (DelFromSet [d]);
  920.     // Add some OIDs to the set...
  921.     for (unsigned int a=0; a < cAddToSet; ++a)
  922. {
  923. OID oid = AddToSet [a];
  924. // Add the OID to the set...
  925. (*i).second.insert (oid);
  926. bool pinged = false;
  927. // Ping the exporter associated with this OID - we don't know
  928. // which one it is so try them all until we hit one
  929. for (OXIDMAP::iterator j = m_exporters.begin ();
  930.      j != m_exporters.end ();
  931.      ++j)
  932.     {
  933.     ObjectExporterPtr pExp = (*j).second;
  934.     COM_ASSERT (pExp);
  935.             if (pExp && SUCCEEDED (pExp->oidPing (oid)))
  936.                 {
  937.                 pinged = true;
  938.                 break;
  939.                 }
  940.             }
  941.             if (! pinged)
  942.                 hr = OR_INVALID_OID;
  943. }
  944.     
  945.     // Update the SETID value...
  946.     *pSetid = setid;
  947.     return hr;
  948.     }
  949. //////////////////////////////////////////////////////////////////////////
  950. //
  951. // SCM::ResolveOxid2 -- given an OXID, return the string-binding
  952. // indicating how to connect to the Object Exporter represented by
  953. // that OXID value...
  954. //
  955. HRESULT SCM::ResolveOxid2
  956.     (
  957.     OXID oxid, // [in] OXID to resolve
  958.     USHORT cReqProtseqs, // [in] num of protseqs
  959.     USHORT arReqProtseqs[],// [in] array of protseqs
  960.     DUALSTRINGARRAY** ppdsaOxidBindings,// [out] bindings
  961.     IPID* pipidRemUnknown,// [out] IPID
  962.     DWORD* pAuthHint, // [out] security info
  963.     COMVERSION* pComVersion // [out] COM version
  964.     )
  965.     {
  966.     TRACE_CALL;
  967.     ObjectExporterPtr pExp;
  968.     DUALSTRINGARRAY* pdsa=0;
  969.     OLECHAR wszSecInfo [] = { 0x0A, 0xFFFF, 0 };
  970.     HRESULT hr = S_OK;
  971.     // Enumerate all object-exporters and see if any have the OXID
  972.     // value given...
  973.     if (cReqProtseqs)
  974. {
  975. VxCritSec critSec (m_mutex);
  976. OXIDMAP::iterator i = m_exporters.begin ();
  977. while (i != m_exporters.end ())
  978.     {
  979.     pExp = (*i).second;
  980.     if (pExp && pExp->oxid () == oxid)
  981. {
  982. pExp->AddRef ();
  983. break;
  984. }
  985.     else
  986. pExp = 0;
  987.     }
  988. }
  989.     
  990.     if (pExp)
  991. {
  992. // Get info we need from exporter...
  993. *pipidRemUnknown = pExp->ipidRemUnknown ();
  994. BSTR bsSvrAddr;
  995. HRESULT hrAddr = pExp->addressBinding (&bsSvrAddr);
  996. pExp->Release ();
  997. // Create DSA...
  998. if (SUCCEEDED (hrAddr))
  999.     {
  1000.     // Allocate memory to hold the DSA...
  1001.     const DWORD dsaLen = sizeof (DUALSTRINGARRAY) + 
  1002.  (2 * SysStringLen (bsSvrAddr)) +
  1003.  (2 * vxcom_wcslen (wszSecInfo)) +
  1004.  16;
  1005.     pdsa = (DUALSTRINGARRAY*) CoTaskMemAlloc (dsaLen);
  1006.     if (pdsa)
  1007. // Format the DSA...
  1008. hr = orpcDSAFormat (pdsa, dsaLen, bsSvrAddr, wszSecInfo);
  1009.     else
  1010. // Memory ran out?
  1011. hr = E_OUTOFMEMORY;
  1012.     SysFreeString (bsSvrAddr);
  1013.     }
  1014. else
  1015.     hr = E_OUTOFMEMORY;
  1016. }
  1017.     else
  1018. {
  1019. *pipidRemUnknown = GUID_NULL;
  1020. hr = OR_INVALID_OXID;
  1021. }
  1022.     *ppdsaOxidBindings = pdsa;
  1023.     pComVersion->MajorVersion = 5;
  1024.     pComVersion->MinorVersion = 2;
  1025.     *pAuthHint = 1;
  1026.     return hr;
  1027.     }
  1028.     
  1029. //////////////////////////////////////////////////////////////////////////
  1030. //
  1031. // SCM::oxidRegister -- register an ObjectExporter (by its OXID
  1032. // value) with the SCM...
  1033. //
  1034. void SCM::oxidRegister (OXID oxid, ObjectExporter* pexp)
  1035.     {
  1036.     VxCritSec cs (m_mutex);
  1037.     m_exporters [oxid] = pexp;
  1038.     }
  1039. //////////////////////////////////////////////////////////////////////////
  1040. //
  1041. // SCM::oxidUnregister -- unregister an ObjectExporter (by its OXID
  1042. // value) from the SCM...
  1043. //
  1044. void SCM::oxidUnregister (OXID oxid)
  1045.     {
  1046.     VxCritSec cs (m_mutex);
  1047.     m_exporters.erase (oxid);
  1048.     }
  1049. //////////////////////////////////////////////////////////////////////////
  1050. //
  1051. // SCM::tick -- it is now 'nSecs' since this function was last
  1052. // called, so we need to prod all the exporters to timeout their
  1053. // objects. Rather than locking the 'm_exporters' table for a long
  1054. // time, we cache all the OXID values first, then unlock the table and
  1055. // individually tick() each exporter. Finally, we tick() all the
  1056. // RemoteSCM objects...
  1057. //
  1058. void SCM::tick (size_t nSecs)
  1059.     {
  1060.     OXID oxids [MAX_EXPORTERS];
  1061.     size_t nOxids=0;
  1062.     // Cache all OXID values
  1063.     if (nSecs)
  1064. {
  1065. VxCritSec cs1 (m_mutex);
  1066. for (OXIDMAP::iterator i = m_exporters.begin ();
  1067.      i != m_exporters.end ();
  1068.      ++i)
  1069.     {
  1070.     oxids [nOxids++] = (*i).second->oxid ();
  1071.     }
  1072. }
  1073.     // Now ask each exporter to perform its timeouts...
  1074.     for (size_t n=0; n < nOxids; ++n)
  1075. {
  1076. ObjectExporterPtr pExp = m_exporters [ oxids[n] ];
  1077. if (pExp)
  1078.     pExp->tick (nSecs);
  1079. }
  1080.     // Timeout each of the RemoteSCM objects...
  1081.     {
  1082.     VxCritSec cs2 (m_mutex);
  1083.     for (REMOTESCMMAP::iterator s = m_remoteScmTable.begin ();
  1084.  s != m_remoteScmTable.end ();
  1085.  ++s)
  1086. {
  1087. (*s).second->pingTick (nSecs);
  1088. }
  1089.     }
  1090.     
  1091.     }
  1092. //////////////////////////////////////////////////////////////////////////
  1093. //
  1094. void SCM::oidAdd (const RpcStringBinding& resAddr, OID oid)
  1095.     {
  1096.     REMOTESCMMAP::iterator i = m_remoteScmTable.find (resAddr);
  1097.     if (i != m_remoteScmTable.end ())
  1098.         (*i).second->oidAdd (oid);
  1099.     }
  1100. //////////////////////////////////////////////////////////////////////////
  1101. //
  1102. void SCM::oidDel (const RpcStringBinding& resAddr, OID oid)
  1103.     {
  1104.     REMOTESCMMAP::iterator i = m_remoteScmTable.find (resAddr);
  1105.     if (i != m_remoteScmTable.end ())
  1106.         (*i).second->oidDel (oid);
  1107.     }
  1108. int
  1109. SCM::PingTimer::handleTimeout
  1110.     (
  1111.     const TimeValue& timerValue
  1112.     )
  1113.     {
  1114.     S_DEBUG (LOG_SCM, "SCM::PingTimer::handleTimeout: " << timerValue);
  1115.     SCM* scm = SCM::theSCM ();
  1116.     if (scm)
  1117. scm->tick (timerValue.sec ());
  1118.     return scm ? 0 : -1;
  1119.     }
  1120. //////////////////////////////////////////////////////////////////////////
  1121. //
  1122. // Global IRemoteActivation, IOXIDResolver and IPrivateSCM
  1123. // functions. They simply defer to the equivalent methods in the SCM.
  1124. //
  1125. HRESULT RemoteActivation
  1126.     (
  1127.     void* channelId,
  1128.     ORPCTHIS* pORPCthis,
  1129.     ORPCTHAT* pORPCthat,
  1130.     GUID* pClsid,
  1131.     WCHAR* pwszObjectName,
  1132.     MInterfacePointer* pObjectStorage,
  1133.     DWORD clientImpLevel,
  1134.     DWORD mode,
  1135.     DWORD nItfs,
  1136.     IID* pIIDs,
  1137.     unsigned short cReqProtseqs,
  1138.     USHORT* reqProtseqs,
  1139.     OXID* pOxid,
  1140.     DUALSTRINGARRAY** ppdsaOxidBindings,
  1141.     IPID* pipidRemUnknown,
  1142.     DWORD* pAuthnHint,
  1143.     COMVERSION* pServerVersion,
  1144.     HRESULT* phr,
  1145.     MInterfacePointer** ppInterfaceData,
  1146.     HRESULT* pResults
  1147.     )
  1148.     {
  1149.     SCM* pscm = SCM::theSCM ();
  1150.     return pscm->RemoteActivation ((int) channelId,
  1151.    pORPCthis,
  1152.    pORPCthat,
  1153.    pClsid,
  1154.    pwszObjectName,
  1155.    pObjectStorage,
  1156.    clientImpLevel,
  1157.    mode,
  1158.    nItfs,
  1159.    pIIDs,
  1160.    cReqProtseqs,
  1161.    reqProtseqs,
  1162.    pOxid,
  1163.    ppdsaOxidBindings,
  1164.    pipidRemUnknown,
  1165.    pAuthnHint,
  1166.    pServerVersion,
  1167.    phr,
  1168.    ppInterfaceData,
  1169.    pResults);
  1170.     }
  1171. HRESULT ResolveOxid
  1172.     (
  1173.     void* pvRpcChannel,
  1174.     OXID* pOxid,
  1175.     unsigned short cRequestedProtseqs,
  1176.     unsigned short* arRequestedProtseqs,
  1177.     DUALSTRINGARRAY** ppdsaOxidBindings,
  1178.     IPID* pipidRemUnknown,
  1179.     DWORD* pAuthnHint
  1180.     )
  1181.     {
  1182.     SCM* pscm = SCM::theSCM ();
  1183.     COMVERSION dummy;
  1184.     return pscm->ResolveOxid2 (*pOxid,
  1185.        cRequestedProtseqs,
  1186.        arRequestedProtseqs,
  1187.        ppdsaOxidBindings,
  1188.        pipidRemUnknown,
  1189.        pAuthnHint,
  1190.        &dummy);
  1191.     }
  1192. HRESULT SimplePing (void* pvRpcChannel, SETID* pSetId)
  1193.     {
  1194.     SCM* pscm = SCM::theSCM ();
  1195.     return pscm->SimplePing (*pSetId);
  1196.     }
  1197. HRESULT ComplexPing
  1198.     (
  1199.     void* pvRpcChannel,
  1200.     SETID* pSetId,
  1201.     unsigned short SequenceNum,
  1202.     unsigned short cAddToSet,
  1203.     unsigned short cDelFromSet,
  1204.     OID* AddToSet,
  1205.     OID* DelFromSet,
  1206.     unsigned short* pPingBackoffFactor
  1207.     )
  1208.     {
  1209.     SCM* pscm = SCM::theSCM ();
  1210.     return pscm->ComplexPing (pSetId,
  1211.       SequenceNum,
  1212.       cAddToSet,
  1213.       cDelFromSet,
  1214.       AddToSet,
  1215.       DelFromSet,
  1216.       pPingBackoffFactor);
  1217.     }
  1218. HRESULT ServerAlive (void* pvRpcChannel)
  1219.     {
  1220.     return S_OK;
  1221.     }
  1222. HRESULT ADummyMethod (void * pvRpcChannel)
  1223.     {
  1224.     return S_OK;
  1225.     }
  1226. HRESULT ResolveOxid2
  1227.     (
  1228.     void* pvRpcChannel,
  1229.     OXID* pOxid,
  1230.     unsigned short cRequestedProtseqs,
  1231.     unsigned short* arRequestedProtseqs,
  1232.     DUALSTRINGARRAY** ppdsaOxidBindings,
  1233.     IPID* pipidRemUnknown,
  1234.     DWORD* pAuthnHint,
  1235.     COMVERSION* pComVersion
  1236.     )
  1237.     {
  1238.     SCM* pscm = SCM::theSCM ();
  1239.     return pscm->ResolveOxid2 (*pOxid,
  1240.        cRequestedProtseqs,
  1241.        arRequestedProtseqs,
  1242.        ppdsaOxidBindings,
  1243.        pipidRemUnknown,
  1244.        pAuthnHint,
  1245.        pComVersion);
  1246.     }
  1247. #if 0
  1248. HRESULT IndirectActivation
  1249.     (
  1250.     LPWSTR              pwszServerName, // PROTSEQ + server name 
  1251.     REFGUID clsid, // CLSID to activate
  1252.     DWORD mode, // all-1's == get-class-obj
  1253.     DWORD nItfs, // num of interfaces
  1254.     IID* pIIDs, // array of IIDs
  1255.     HRESULT* phr, // returned activation result
  1256.     MInterfacePointer** ppItfData, // returned interface(s)
  1257.     HRESULT* pResults // returned results per i/f
  1258.     )
  1259.     {
  1260.     SCM* pscm = SCM::theSCM ();
  1261.     return pscm->IndirectActivation (pwszServername,
  1262.                                      clsid,
  1263.                                      mode,
  1264.                                      nItfs,
  1265.                                      pIIDs,
  1266.                                      phr,
  1267.                                      ppItfData,
  1268.                                      pResults);
  1269.     }
  1270. HRESULT AddOid (OID oid)
  1271.     {
  1272.     SCM* pscm = SCM::theSCM ();
  1273.     return pscm->AddOid (oid);
  1274.     }
  1275. HRESULT DelOid (OID oid)
  1276.     {
  1277.     SCM* pscm = SCM::theSCM ();
  1278.     return pscm->DelOid (oid);
  1279.     }
  1280. HRESULT GetNextOid (OID* pOid)
  1281.     {
  1282.     SCM* pscm = SCM::theSCM ();
  1283.     return pscm->GetNextOid (pOid);
  1284.     }
  1285. HRESULT GetOxidResolverBinding
  1286.     (
  1287.     USHORT                  cProtseqs,
  1288.     USHORT                  arProtseqs[],
  1289.     DUALSTRINGARRAY**       ppdsaBindings
  1290.     )
  1291.     {
  1292.     SCM* pscm = SCM::theSCM ();
  1293.     return pscm->GetOxidResolverBinding (cProtseqs,
  1294.                                          arProtseqs,
  1295.                                          ppdsaBindings);
  1296.     }
  1297. #endif