📄 scm.cpp
字号:
/* SCM - Service Control Manager *//* Copyright (c) 1999 Wind River Systems, Inc. *//*modification history--------------------02u,03jan02,nel Remove usage of alloca.02t,17dec01,nel Add include symbol for diab build.02s,06aug01,dbs remove instance-creation from SCM02r,03aug01,dbs remove usage of Thread class02q,01aug01,dbs fix channel-auth for unix only02p,24jul01,dbs fix ping-set add/del order, tidy up and comment02o,18jul01,dbs clean up stray printfs02n,13jul01,dbs fix up includes02m,14mar01,nel SPR#35873. Modify code to search for first good address in dual string array passed as part of marshaling an interface.02l,02mar01,nel SPR#35589. Add code to make Oxid addresses unique to prevent clash with other targets.02k,20sep00,nel ensure SCM closes down properly.02j,22aug00,nel Add assert to catch case where SCM hasn't been init and request of ObjectExporter is received.02i,10aug00,nel Win2K patch.02h,07jun00,nel Remove static c'tor dependency.02g,15feb00,dbs add global SCM interface functions02f,20aug99,aim make nextOID MT safe02e,19aug99,aim fix MLK02d,19aug99,aim change assert to VXDCOM_ASSERT02c,18aug99,dbs improve resilience by use of RC-ptr to ObjExp02b,17aug99,aim added Object Exporter project resources02a,17aug99,dbs protect remote-SCM list against threads01z,05aug99,dbs add sanity checks in CreateInstance()01y,02aug99,dbs remove stray printf01x,26jul99,dbs fix case where all QIs fail in successful activation01w,26jul99,dbs move marshaling into exporter01v,22jul99,dbs re-use remote SCM connections01u,20jul99,dbs make sure all out-args of RemoteActivation are zeroed when call fails01t,16jul99,aim serverAddress functionality moved to base class01s,15jul99,dbs check for local-machine activation01r,15jul99,dbs ensure proper HRESULTs are returned01q,13jul99,aim syslog api changes01p,12jul99,aim added timers01o,09jul99,dbs implement ping functionality in SCM now01n,08jul99,dbs clean up remote-SCM connection after activation01m,07jul99,dbs init next-setid in SCM ctor01l,07jul99,dbs only marshal resulting ptrs if activation succeeded01k,07jul99,aim change from RpcBinding to RpcIfClient01j,06jul99,dbs check return-value of remote-activation01i,06jul99,dbs simplify activation mechanism01h,06jul99,dbs make SCM create ObjectExporter at startup01g,30jun99,aim fixed mod history01f,30jun99,aim rework for error reporting01e,28jun99,dbs remove defaultInstance method01d,25jun99,dbs use channel-ID to determine channel authn status01c,18jun99,aim resolverAddress return ObjectExporters address01b,08jun99,aim rework01a,27may99,aim created*/#include "SCM.h"#include "Reactor.h"#include "INETSockAddr.h"#include "ObjectExporter.h"#include "Syslog.h"#include "orpcLib.h"#include "private/comMisc.h"#include "StdProxy.h"#include "RpcIfClient.h"#include "TimeValue.h"#include "taskLib.h"/* Include symbol for diab */extern "C" int include_vxdcom_SCM (void) { return 0; }EXTERN_C const VXDCOM_STUB_DISPTBL IRemoteActivation_vxstub_disptbl;EXTERN_C const VXDCOM_STUB_DISPTBL IOXIDResolver_vxstub_disptbl;EXTERN_C const VXDCOM_STUB_DISPTBL ISystemActivator_vxstub_disptbl;// SCM staticsSCM* SCM::s_theSCM = 0;////////////////////////////////////////////////////////////////////////////// SCM destructor//SCM::~SCM () { COM_ASSERT (s_theSCM == this); ObjectExporterPtr pObjectExporter = objectExporter (); pObjectExporter->AddRef (); if (pObjectExporter) { // Force the exporter to release all exported objects pObjectExporter->objectUnregisterAll (); // Remove it from our map... oxidUnregister (pObjectExporter->oxid ()); } pObjectExporter->Release (); s_theSCM = 0; cout << "SCM : closed down" << endl; }////////////////////////////////////////////////////////////////////////////SCM::SCM (Reactor* r, NTLMSSP* ssp) : RpcIfServer (r, &m_dispatcher), m_mutex (), m_exporters (), m_oidSets (), m_nextSetid (0), m_dispatchTable (), m_dispatcher (&m_dispatchTable), m_ssp (ssp) { COM_ASSERT(s_theSCM == 0); s_theSCM = this; // Initialise OXID (Object Exporter ID). We factor this node's IP // address into the OXID to make sure it has some chance of being // unique, even among similar nodes. This code should really be // part of the 'network addressing' classes, but that requires // some deeper rework in future... char hostname [64]; long adr = -1; if (gethostname (hostname, sizeof (hostname)) == 0) {#ifdef VXDCOM_PLATFORM_VXWORKS adr = ::hostGetByName (hostname);#else hostent* hp = ::gethostbyname (hostname); if (hp != 0) adr = (long) hp->h_addr;#endif } // If we got some valid IP address, if (adr != -1) // Use the host IP address to weight the initial OXID value... m_nextOxid = ((LONGLONG) adr) << 32; else // Make some feeble attempt to randomize it... m_nextOxid = ::time (0); // Initialise the next available OID (Object ID), using the // IP-factored OXID value, plus the thread ID... m_nextOid = m_nextOxid + ::taskIdSelf (); }//////////////////////////////////////////////////////////////////////////////// returns the string indicating the address of the IOXIDResolver// interface.HRESULT SCM::addressBinding (BSTR* pbsResAddr) { if (rpcAddressFormat (pbsResAddr, 0 /* no portNumber */) < 0) return E_FAIL; else return S_OK; }////////////////////////////////////////////////////////////////////////////// theSCM - returns the one and only instance//SCM* SCM::theSCM () { return s_theSCM; }////////////////////////////////////////////////////////////////////////////// registerStdInterfaces - add DCE interfaces to tables//void SCM::registerStdInterfaces () { m_dispatchTable.dceInterfaceRegister (IID_IRemoteActivation, &IRemoteActivation_vxstub_disptbl); m_dispatchTable.dceInterfaceRegister (IID_IOXIDResolver, &IOXIDResolver_vxstub_disptbl); m_dispatchTable.dceInterfaceRegister (IID_ISystemActivator, &ISystemActivator_vxstub_disptbl); }////////////////////////////////////////////////////////////////////////////NTLMSSP* SCM::ssp () { if (s_theSCM) return s_theSCM->m_ssp; return 0; }////////////////////////////////////////////////////////////////////////////// startService - initiate a SCM service in the current task//int SCM::startService () { INETSockAddr addr(VXDCOM_SCM_ENDPOINT); Reactor r; NTLMSSP ssp; SCM scm (&r, &ssp); SCM::PingTimer pingTimer; int result = scm.init (addr); if (result == 0) { scm.reactorGet()->timerAdd (&pingTimer, TimeValue (5)); S_INFO (LOG_SCM, "SCM bound to " << addr << " fd=" << scm.handleGet ()); result = scm.reactorGet()->run (); } return result; }////////////////////////////////////////////////////////////////////////////// init - initialize the SCM//int SCM::init (INETSockAddr& addr) { registerStdInterfaces (); int result = open (addr, reactorGet(), 1 /* reuse addr */); if (result == 0) { if ((result = hostAddrGet (addr)) == 0) { // Now create the one-and-only object exporter ObjectExporter* pExp=0; HRESULT hr = newObjectExporter (&pExp); if (SUCCEEDED (hr)) { oxidRegister (pExp->oxid (), pExp); hr = pExp->init (); if (FAILED (hr)) { result = hr; } } } } else { S_ERR (LOG_SCM|LOG_ERRNO, "cannot bind to " << addr); } return result; }////////////////////////////////////////////////////////////////////////////// stopService - terminate the SCM instance by closing down reactor//int SCM::stopService () { if (s_theSCM) { s_theSCM->reactorGet()->eventLoopEnd (); s_theSCM->close (); } return 0; }////////////////////////////////////////////////////////////////////////////// GetNextOid - return the next OID (Object ID) value//HRESULT SCM::GetNextOid (OID* pOid) { VxCritSec cs (m_mutex); *pOid = ++m_nextOid; return S_OK; }////////////////////////////////////////////////////////////////////////////// nextOXID - return the next OXID (Object eXporter ID) value//OXID SCM::nextOXID () { VxCritSec cs (m_mutex); return ++m_nextOxid; }////////////////////////////////////////////////////////////////////////////// nextOID - return the next OID (Object ID) value//OID SCM::nextOid () { OID o; this->GetNextOid (&o); return o; }//////////////////////////////////////////////////////////////////////////////// SCM::objectExporter -- returns the object exporter for the// current context, i.e. the task within which the call is made. In// future this may be PD-dependent, etc, but for now, it simply// returns the one and only exporter. Note that it *doesn't* add a// reference for it...//ObjectExporter* SCM::objectExporter () { SCM* scm = theSCM (); ObjectExporter* pExp = 0; // enter critical section VxCritSec critSec (scm->m_mutex); if (scm->m_exporters.size () == 0) pExp = 0; else pExp = (* (scm->m_exporters.begin ())).second; COM_ASSERT(pExp != NULL); return pExp; }////////////////////////////////////////////////////////////////////////////// newObjectExporter -- utility to create an instance of the // ObjectExporter. This is a COM object, so is dealt with as such...//HRESULT SCM::newObjectExporter (ObjectExporter** ppObjExp) { HRESULT hr = S_OK; // Create an instance of Object Exporter, with one ref... ObjectExporterPtr pOX = new ObjectExporter (reactorGet(), nextOXID ()); // Did we get one? if (! pOX) return E_OUTOFMEMORY; // Open it on the required local endpoint... INETSockAddr addr (g_vxdcomObjectExporterPortNumber); if (pOX->open (addr, reactorGet(), 1) < 0) { // Cannot bind to loca endpoint... pOX->Release (); pOX = 0; hr = MAKE_HRESULT (SEVERITY_ERROR, FACILITY_RPC, RPC_S_CANT_CREATE_ENDPOINT); } else { // Make sure we got an endpoint? if (pOX->hostAddrGet (addr) < 0) { pOX->Release (); pOX = 0; hr = E_UNEXPECTED; } else { // Success! S_INFO (LOG_SCM, "ObjectExporter bound to " << addr << " fd=" << pOX->handleGet ()); } } if (ppObjExp) *ppObjExp = pOX; return hr; }////////////////////////////////////////////////////////////////////////////// SCM::RemoteActivation -- called by external DCE clients to activate// an instance of an object-class on this machine.//HRESULT SCM::RemoteActivation ( int channelId, // channel ORPCTHIS* pOrpcThis, // housekeeping ORPCTHAT* pOrpcThat, // returned housekeeping GUID* pClsid, // CLSID to activate OLECHAR* pwszObjName, // NULL MInterfacePointer* pObjStorage, // NULL DWORD clientImpLevel, // security DWORD mode, // all-1's == get-class-obj DWORD nInterfaces, // num of interfaces IID* pIIDs, // size_is (nItfs) USHORT cReqProtseqs, // num of protseqs USHORT arReqProtseqs[],// array of protseqs OXID* pOxid, // returned OXID DUALSTRINGARRAY** ppdsaOxidBindings,// returned bindings IPID* pIpidRemUnknown,// returned IPID DWORD* pAuthnHint, // returned security info COMVERSION* pSvrVersion, // returned server version HRESULT* phr, // returned activation result MInterfacePointer** ppItfData, // returned interface(s) HRESULT* pResults // returned results per i/f ) { // Preset default out-args... pOrpcThat->flags = 1; pOrpcThat->extensions = 0; pSvrVersion->MinorVersion = 2; pSvrVersion->MajorVersion = 5; *pAuthnHint = ssp()->authnLevel (); // First check with the authentication service that this // channel-ID is allowed to activate objects...#ifndef VXDCOM_PLATFORM_SOLARIS HRESULT hrChannel = E_ACCESSDENIED; NTLMSSP* pssp = ssp (); if (pssp) hrChannel = pssp->channelStatusGet (channelId);#else HRESULT hrChannel = S_OK;#endif if (FAILED (hrChannel)) { // Set out-args to NULL... *pOxid = 0; *ppdsaOxidBindings = 0; *pIpidRemUnknown = GUID_NULL; for (DWORD n=0; n < nInterfaces; ++n) { pResults [n] = E_FAIL; ppItfData [n] = 0; } *phr = hrChannel; return S_OK; } // allocate space for MULTI_QI array MULTI_QI* mqi = new MULTI_QI [nInterfaces]; if (0 == mqi) return E_OUTOFMEMORY; for (DWORD j=0; j < nInterfaces; ++j) { // fill MQI array with input arguments... mqi [j].pIID = &pIIDs [j]; mqi [j].pItf = 0; mqi [j].hr = S_OK; // initialise output-array elements to NULL ppItfData [j] = 0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -