//--------------------------------------------------------------------------- // // File: myproxy.cxx // // Purpose: Sample implementation of wrappers to allow simultaneous // hand-crafted and MILD-generated stubs. // // History: 12-11-95 Rickhi Created // //--------------------------------------------------------------------------- #include #include // offsetof #include // custom interface ICube, IID_ICube // flag set in rpcFlags field of RPCOLEMESSAGE if the call is from a // non-NDR client. #define RPCFLG_NON_NDR 0x80000000UL DEFINE_OLEGUID(IID_INonNDRStub, 0x0000013DL, 0, 0); DEFINE_OLEGUID(CLSID_MyProxy, 0x0000013EL, 0, 0); // IID that the proxy querys the channel for to see if the server // has an NDR or NON NDR stub. const GUID IID_INonNDRStub = {0x0000013d,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; // class id of my custom proxy dll const GUID CLSID_MyProxy = {0x0000013e,0x0001,0x0008,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; // class id of the MIDL generated proxy dll const GUID CLSID_CubeProxy = {0x00000138,0x0001,0x0008,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; #define GETPPARENT(pmemb, struc, membname) (\ (struc FAR *)(((char FAR *)(pmemb))-offsetof(struc, membname))) //--------------------------------------------------------------------------- // // Class: CPSFactory // // Purpose: ProxyStub Class Factory // // Notes: fill in the CreateProxy and CreateStub methods for // other custom interfaces supported by this DLL. // //--------------------------------------------------------------------------- class CPSFactory : public IPSFactoryBuffer { public: // no ctor or dtor needed. DllGetClassObject returns a static // instance of this class. STDMETHOD(QueryInterface)(REFIID riid, void **ppv); STDMETHOD_(ULONG, AddRef)(void); STDMETHOD_(ULONG, Release)(void); STDMETHOD(CreateProxy)(IUnknown *pUnkOuter, REFIID riid, IRpcProxyBuffer **ppProxy, void **ppv); STDMETHOD(CreateStub)(REFIID riid, IUnknown *pUnkObj, IRpcStubBuffer **ppStub); }; //--------------------------------------------------------------------------- // // Class: CStubWrapper // // Purpose: Wrapper object for stubs. // // Notes: This class can wrap any stub object regardless of // the interface the stub is for. // //--------------------------------------------------------------------------- class CStubWrapper : public IRpcStubBuffer { public: CStubWrapper(IUnknown *pUnkObj, REFIID riid); STDMETHOD(QueryInterface)(REFIID riid, void **ppv); STDMETHOD_(ULONG, AddRef)(void); STDMETHOD_(ULONG, Release)(void); STDMETHOD(Connect)(IUnknown *pUnkObj); STDMETHOD_(void, Disconnect)(void); STDMETHOD(Invoke)(RPCOLEMESSAGE *pMsg, IRpcChannelBuffer *pChnl); STDMETHOD_(IRpcStubBuffer *, IsIIDSupported)(REFIID riid); STDMETHOD_(ULONG, CountRefs)(void); STDMETHOD(DebugServerQueryInterface)(void **ppv); STDMETHOD_(void, DebugServerRelease)(void *pv); private: ~CStubWrapper(void); ULONG _cRefs; IUnknown * _pUnkObj; IRpcStubBuffer *_pHCStub; IRpcStubBuffer *_pMIDLStub; IID _iid; }; //--------------------------------------------------------------------------- // // Class: CCubesStub // // Purpose: Hand-Crafted stub object for interface ICube. // // Notes: Replace this with your exisitng 32bit hand-crafted stubs. // //--------------------------------------------------------------------------- class CCubesStub : public IRpcStubBuffer { public: CCubesStub(IUnknown *pUnkObj); STDMETHOD(QueryInterface)(REFIID riid, void **ppv); STDMETHOD_(ULONG, AddRef)(void); STDMETHOD_(ULONG, Release)(void); STDMETHOD(Connect)(IUnknown *pUnkObj); STDMETHOD_(void, Disconnect)(void); STDMETHOD(Invoke)(RPCOLEMESSAGE *pMsg, IRpcChannelBuffer *pChnl); STDMETHOD_(IRpcStubBuffer *, IsIIDSupported)(REFIID riid); STDMETHOD_(ULONG, CountRefs)(void); STDMETHOD(DebugServerQueryInterface)(void **ppv); STDMETHOD_(void, DebugServerRelease)(void *pv); private: ~CCubesStub(void); ULONG _cRefs; IUnknown * _pUnkObj; }; //--------------------------------------------------------------------------- // // Class: CInternalUnk // // Purpose: Internal proxy class that implements IRpcProxyBuffer // // Notes: This could use some work. Perhaps dont make it an internal // class, but derive the other proxy classes from it, allowing // common code. // //--------------------------------------------------------------------------- #define DECLARE_INTERNAL_PROXY() \ class CInternalUnk : public IRpcProxyBuffer \ { \ public: \ STDMETHOD(QueryInterface)(REFIID riid, void **ppvObj); \ STDMETHOD_(ULONG,AddRef)(void) ; \ STDMETHOD_(ULONG,Release)(void); \ STDMETHOD(Connect)(IRpcChannelBuffer *pChnl); \ STDMETHOD_(void, Disconnect)(void); \ }; \ friend CInternalUnk; \ CInternalUnk _InternalUnk; //--------------------------------------------------------------------------- // // Class: CProxyWrapper // // Purpose: Wrapper object for itnerface proxies. // // Notes: the routines in this class simply delegate to the // real proxy or the internal proxy unknown, or to the // controlling unknown. // //--------------------------------------------------------------------------- class CProxyWrapper : public ICube { public: CProxyWrapper(IUnknown *pUnkOuter, IRpcProxyBuffer **ppProxy); STDMETHOD(QueryInterface)(REFIID riid, void **ppv); STDMETHOD_(ULONG, AddRef)(void); STDMETHOD_(ULONG, Release)(void); // interface specific routines below here STDMETHOD(MoveCube)(ULONG xPos, ULONG yPos); STDMETHOD(GetCubePos)(ULONG *pxPos, ULONG *pyPos); STDMETHOD(Contains)(IBalls *pIFDb); STDMETHOD(SimpleCall)(DWORD pidCaller, DWORD tidCaller, GUID lidCaller); DECLARE_INTERNAL_PROXY() private: ~CProxyWrapper(void); ULONG _cRefs; IUnknown *_pUnkOuter; IRpcProxyBuffer *_pRealProxy; ICube *_pRealIf; }; //--------------------------------------------------------------------------- // // Class: CCubesProxy // // Purpose: Hand-Crafted proxy object for ICube interface. // //--------------------------------------------------------------------------- class CCubesProxy : public ICube { public: CCubesProxy(IUnknown *pUnkOuter, IRpcProxyBuffer **ppProxy); STDMETHOD(QueryInterface)(REFIID riid, void **ppv); STDMETHOD_(ULONG, AddRef)(void); STDMETHOD_(ULONG, Release)(void); // interface specific routines below here STDMETHOD(MoveCube)(ULONG xPos, ULONG yPos); STDMETHOD(GetCubePos)(ULONG *pxPos, ULONG *pyPos); STDMETHOD(Contains)(IBalls *pIFDb); STDMETHOD(SimpleCall)(DWORD pidCaller, DWORD tidCaller, GUID lidCaller); DECLARE_INTERNAL_PROXY() private: ~CCubesProxy(void); ULONG _cRefs; IUnknown *_pUnkOuter; IRpcChannelBuffer *_pChnl; }; //--------------------------------------------------------------------------- // // Function: DllMain // // Purpose: Entry point for the Proxy/Stub Dll // //--------------------------------------------------------------------------- extern "C" BOOL WINAPI DllMain(HANDLE hDll, DWORD dwReason, void *pvReserved) { return TRUE; } //--------------------------------------------------------------------------- // // Function: DllGetClassObject // // Purpose: Entry point to return proxy/stub class factory // //--------------------------------------------------------------------------- // static instance of the class factory CPSFactory gPSFactory; STDAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **ppv) { if (IsEqualCLSID(clsid, CLSID_MyProxy)) { *ppv = (void *)(IClassFactory *)&gPSFactory; return S_OK; } return E_UNEXPECTED; } //--------------------------------------------------------------------------- // // Function: DllCanUnloadNow // // Purpose: Entry point to determine if DLL is unloadable. // //--------------------------------------------------------------------------- STDAPI DllCanUnloadNow(void) { return FALSE; } //--------------------------------------------------------------------------- // // Function: GetMIDLPSFactory // // Purpose: Function for getting the MIDL generated PSFactoryBuffer // for the test interface. // //--------------------------------------------------------------------------- HRESULT GetMIDLPSFactory(REFIID riid, IPSFactoryBuffer **ppIPSF) { *ppIPSF = NULL; // load the dll and get the PS class object return CoGetClassObject(CLSID_CubeProxy, CLSCTX_INPROC_SERVER, // | CLSCTX_PS_DLL, NULL, IID_IPSFactoryBuffer, (void **)ppIPSF); } //--------------------------------------------------------------------------- // // Function: CreateMIDLProxy // // Purpose: Function for creating the MIDL generated proxy // for the test interface. // //--------------------------------------------------------------------------- IUnknown *CreateMIDLProxy(REFIID riid, IUnknown *pUnkOuter, IRpcProxyBuffer **ppProxy) { IUnknown *pRealIf = NULL; IPSFactoryBuffer *pPSFactory = NULL; HRESULT hr = GetMIDLPSFactory(riid, &pPSFactory); if (SUCCEEDED(hr)) { hr = pPSFactory->CreateProxy(pUnkOuter,riid,ppProxy,(void **)&pRealIf); pPSFactory->Release(); } return pRealIf; } //--------------------------------------------------------------------------- // // Function: CreateMIDLStub // // Purpose: Function for creating the MIDL generated stub // for the test interface. // //--------------------------------------------------------------------------- IRpcStubBuffer *CreateMIDLStub(REFIID riid, IUnknown *pUnkOuter) { IRpcStubBuffer *pStub = NULL; IPSFactoryBuffer *pPSFactory = NULL; HRESULT hr = GetMIDLPSFactory(riid, &pPSFactory); if (SUCCEEDED(hr)) { hr = pPSFactory->CreateStub(riid, pUnkOuter, &pStub); pPSFactory->Release(); } return pStub; } //--------------------------------------------------------------------------- // // Implement: CPSFactory // // Purpose: ProxyStub Class Factory // // Notes: just fill in the CreateProxy and CreateStub methods for // your other custom interfaces. // //--------------------------------------------------------------------------- HRESULT CPSFactory::QueryInterface(REFIID riid, void **ppv) { if (IsEqualIID(riid, IID_IPSFactoryBuffer) || IsEqualIID(riid, IID_IUnknown)) { *ppv = (IPSFactoryBuffer *)this; // static object, dont need refcnt return S_OK; } *ppv = NULL; return E_NOINTERFACE; } ULONG CPSFactory::AddRef(void) { // static object, dont need refcnt return 1; } ULONG CPSFactory::Release(void) { // static object, dont need refcnt return 1; } HRESULT CPSFactory::CreateProxy(IUnknown *pUnkOuter, REFIID riid, IRpcProxyBuffer **ppProxy, void **ppv) { // check for supported interfaces if (IsEqualIID(riid, IID_ICube)) { CProxyWrapper *pProxy = new CProxyWrapper(pUnkOuter, ppProxy); if (pProxy) { *ppv = (void *)(ICube *) pProxy; ((IUnknown *)(*ppv))->AddRef(); // AddRef the returned interface return S_OK; } } *ppProxy = NULL; *ppv = NULL; return E_NOINTERFACE; } HRESULT CPSFactory::CreateStub(REFIID riid, IUnknown *pUnkObj, IRpcStubBuffer **ppStub) { // check for supported interfaces if (IsEqualIID(riid, IID_ICube)) { CStubWrapper *pStub = new CStubWrapper(pUnkObj, riid); if (pStub) { *ppStub = (IRpcStubBuffer *) pStub; return S_OK; } } *ppStub = NULL; return E_NOINTERFACE; } //--------------------------------------------------------------------------- // // Implement: CStubWrapper // // Purpose: Wrapper object for stubs. // // Notes: This same class can wrap any stub object regardless of // the interface the stub is for. // //--------------------------------------------------------------------------- CStubWrapper::CStubWrapper(IUnknown *pUnkObj, REFIID riid) : _cRefs(1), _pUnkObj(pUnkObj), _pHCStub(NULL), _pMIDLStub(NULL), _iid(riid) { _pUnkObj->AddRef(); } CStubWrapper::~CStubWrapper(void) { Disconnect(); } HRESULT CStubWrapper::QueryInterface(REFIID riid, void **ppv) { if (IsEqualIID(riid, IID_IRpcStubBuffer) || IsEqualIID(riid, IID_IUnknown)) { *ppv = (IRpcStubBuffer *)this; AddRef(); return S_OK; } *ppv = NULL; return E_NOINTERFACE; } ULONG CStubWrapper::AddRef(void) { InterlockedIncrement((LONG *)&_cRefs); return _cRefs; } ULONG CStubWrapper::Release(void) { ULONG cRefs = _cRefs-1; if (InterlockedDecrement((LONG *)&_cRefs) == 0) { delete this; return 0; } return cRefs; } HRESULT CStubWrapper::Connect(IUnknown *pUnkObj) { if (_pUnkObj) { // already connected, disconnect Disconnect(); } // get the requested interface and hold it. HRESULT hr = pUnkObj->QueryInterface(_iid, (void **)&_pUnkObj); if (FAILED(hr)) { // make sure our ptr is NULL else we might think we're connected _pUnkObj = NULL; } return hr; } void CStubWrapper::Disconnect() { if (_pHCStub) { _pHCStub->Disconnect(); _pHCStub->Release(); _pHCStub = NULL; } if (_pMIDLStub) { _pMIDLStub->Disconnect(); _pMIDLStub->Release(); _pMIDLStub = NULL; } if (_pUnkObj) { _pUnkObj->Release(); _pUnkObj = NULL; } } HRESULT CStubWrapper::Invoke(RPCOLEMESSAGE *pMsg, IRpcChannelBuffer *pChnl) { if (pMsg->rpcFlags & RPCFLG_NON_NDR) { // call is not NDR format, so use the hand-crafted stub. // create the stub if it does not exist yet. if (_pHCStub == NULL) { if ((_pHCStub = new CCubesStub(_pUnkObj)) == NULL) return E_OUTOFMEMORY; } return _pHCStub->Invoke(pMsg, pChnl); } // call is NDR format, so use the MIDL generated stub. // create the stub if it does not exist yet. if (_pMIDLStub == NULL) { _pMIDLStub = CreateMIDLStub(IID_ICube, _pUnkObj); if (_pMIDLStub == NULL) return E_OUTOFMEMORY; } return _pMIDLStub->Invoke(pMsg, pChnl); } IRpcStubBuffer *CStubWrapper::IsIIDSupported(REFIID riid) { if (IsEqualIID(riid, _iid)) { AddRef(); return (IRpcStubBuffer *)this; } return NULL; } ULONG CStubWrapper::CountRefs() { ULONG cRefs = (_pUnkObj) ? 1 : 0; if (_pHCStub) cRefs += _pHCStub->CountRefs(); if (_pMIDLStub) cRefs += _pMIDLStub->CountRefs(); return cRefs; } HRESULT CStubWrapper::DebugServerQueryInterface(void **ppv) { *ppv = (void *)_pUnkObj; return S_OK; } void CStubWrapper::DebugServerRelease(void *pv) { return; } //--------------------------------------------------------------------------- // // Implement: CProxyWrapper // // Purpose: Wrapper object for itnerface proxies. // // Notes: the top several routines are the same for all proxies // but you must change the interface specific routines for // each new interface. // //--------------------------------------------------------------------------- CProxyWrapper::CProxyWrapper(IUnknown *pUnkOuter, IRpcProxyBuffer **ppProxy) : _cRefs(1), _pUnkOuter(pUnkOuter), // don't AddRef _pRealProxy(NULL) { *ppProxy = (IRpcProxyBuffer *)&_InternalUnk; } CProxyWrapper::~CProxyWrapper(void) { if (_pRealProxy) { _InternalUnk.Disconnect(); } } HRESULT CProxyWrapper::CInternalUnk::QueryInterface(REFIID riid, void **ppv) { CProxyWrapper *pProxy = GETPPARENT(this, CProxyWrapper, _InternalUnk); if (IsEqualIID(riid, IID_IRpcProxyBuffer) || IsEqualIID(riid, IID_IUnknown)) { pProxy->AddRef(); *ppv = (IRpcProxyBuffer *)this; return S_OK; } else if (IsEqualIID(riid, IID_ICube)) { *ppv = (ICube *)pProxy; AddRef(); return S_OK; } *ppv = NULL; return E_NOINTERFACE; } ULONG CProxyWrapper::CInternalUnk::AddRef(void) { CProxyWrapper *pProxy = GETPPARENT(this, CProxyWrapper, _InternalUnk); InterlockedIncrement((LONG *)&pProxy->_cRefs); return pProxy->_cRefs; } ULONG CProxyWrapper::CInternalUnk::Release(void) { CProxyWrapper *pProxy = GETPPARENT(this, CProxyWrapper, _InternalUnk); ULONG cRefs = pProxy->_cRefs-1; if (InterlockedDecrement((LONG *)&pProxy->_cRefs) == 0) { delete this; return 0; } return cRefs; } HRESULT CProxyWrapper::CInternalUnk::Connect(IRpcChannelBuffer *pChnl) { CProxyWrapper *pProxy = GETPPARENT(this, CProxyWrapper, _InternalUnk); void *pv; HRESULT hr = pChnl->QueryInterface(IID_INonNDRStub, &pv); if (SUCCEEDED(hr)) { ((IUnknown *)pv)->Release(); // create the hand-crafted proxy pProxy->_pRealIf = new CCubesProxy(pProxy->_pUnkOuter, &pProxy->_pRealProxy); } else { // create the MIDL generated proxy pProxy->_pRealIf = (ICube *) CreateMIDLProxy(IID_ICube, pProxy->_pUnkOuter, &pProxy->_pRealProxy); } if (pProxy->_pRealIf == NULL) return E_OUTOFMEMORY; // since the proxy AddRef'd the punkOuter, we need to release it. pProxy->_pUnkOuter->Release(); // connect the proxy hr = pProxy->_pRealProxy->Connect(pChnl); if (FAILED(hr)) { pProxy->_pRealProxy->Release(); pProxy->_pRealProxy = NULL; } return hr; } void CProxyWrapper::CInternalUnk::Disconnect(void) { CProxyWrapper *pProxy = GETPPARENT(this, CProxyWrapper, _InternalUnk); if (pProxy->_pRealProxy) { pProxy->_pRealProxy->Disconnect(); pProxy->_pRealProxy->Release(); pProxy->_pRealProxy = NULL; } } //--------------------------------------------------------------------------- // // ICube specific proxy wrapper code below here. // //--------------------------------------------------------------------------- HRESULT CProxyWrapper::QueryInterface(REFIID riid, void **ppv) { return _pUnkOuter->QueryInterface(riid, ppv); } ULONG CProxyWrapper::AddRef(void) { return _pUnkOuter->AddRef(); } ULONG CProxyWrapper::Release(void) { return _pUnkOuter->Release(); } HRESULT CProxyWrapper::MoveCube(ULONG xPos, ULONG yPos) { if (_pRealProxy) { return _pRealIf->MoveCube(xPos, yPos); } return CO_E_OBJNOTCONNECTED; } HRESULT CProxyWrapper::GetCubePos(ULONG *pxPos, ULONG *pyPos) { if (_pRealProxy) { return _pRealIf->GetCubePos(pxPos, pyPos); } *pxPos = 0; *pyPos = 0; return CO_E_OBJNOTCONNECTED; } HRESULT CProxyWrapper::Contains(IBalls *pIFDb) { if (_pRealProxy) { return _pRealIf->Contains(pIFDb); } return CO_E_OBJNOTCONNECTED; } HRESULT CProxyWrapper::SimpleCall( DWORD pidCaller, DWORD tidCaller, GUID lidCaller) { return CO_E_OBJNOTCONNECTED; } //--------------------------------------------------------------------------- // // Implement: CCubesProxy // // Purpose: Hand-Crafted proxy object for interface ICube. // // Notes: Replace this with your exisitng 32bit hand-crafted proxies. // //--------------------------------------------------------------------------- CCubesProxy::CCubesProxy(IUnknown *pUnkOuter, IRpcProxyBuffer **ppProxy) : _pUnkOuter(pUnkOuter), _pChnl(NULL) { _pUnkOuter->AddRef(); *ppProxy = (IRpcProxyBuffer *)&_InternalUnk; } CCubesProxy::~CCubesProxy(void) { _InternalUnk.Disconnect(); } HRESULT CCubesProxy::CInternalUnk::QueryInterface(REFIID riid, void **ppv) { if (IsEqualIID(riid, IID_IRpcProxyBuffer) || IsEqualIID(riid, IID_IUnknown)) { CCubesProxy *pProxy = GETPPARENT(this, CCubesProxy, _InternalUnk); pProxy->AddRef(); *ppv = (IRpcProxyBuffer *)this; return S_OK; } *ppv = NULL; return E_NOINTERFACE; } ULONG CCubesProxy::CInternalUnk::AddRef(void) { CCubesProxy *pProxy = GETPPARENT(this, CCubesProxy, _InternalUnk); InterlockedIncrement((LONG *)&pProxy->_cRefs); return pProxy->_cRefs; } ULONG CCubesProxy::CInternalUnk::Release(void) { CCubesProxy *pProxy = GETPPARENT(this, CCubesProxy, _InternalUnk); ULONG cRefs = pProxy->_cRefs-1; if (InterlockedDecrement((LONG *)&pProxy->_cRefs) == 0) { delete this; return 0; } return cRefs; } HRESULT CCubesProxy::CInternalUnk::Connect(IRpcChannelBuffer *pChnl) { Disconnect(); // make sure we are disconnected CCubesProxy *pProxy = GETPPARENT(this, CCubesProxy, _InternalUnk); pProxy->_pChnl = pChnl; // keep the channel ptr pChnl->AddRef(); return S_OK; } void CCubesProxy::CInternalUnk::Disconnect(void) { CCubesProxy *pProxy = GETPPARENT(this, CCubesProxy, _InternalUnk); if (pProxy->_pChnl) { pProxy->_pChnl->Release(); pProxy->_pChnl = NULL; } } //--------------------------------------------------------------------------- // // ICubes Proxy Implementation // //--------------------------------------------------------------------------- HRESULT CCubesProxy::QueryInterface(REFIID riid, void **ppv) { return _pUnkOuter->QueryInterface(riid, ppv); } ULONG CCubesProxy::AddRef(void) { return _pUnkOuter->AddRef(); } ULONG CCubesProxy::Release(void) { return _pUnkOuter->Release(); } HRESULT CCubesProxy::MoveCube(ULONG xPos, ULONG yPos) { // set up the message and get the buffer RPCOLEMESSAGE msg; memset(&msg, 0, sizeof(msg)); msg.iMethod = 3; msg.dataRepresentation = NDR_LOCAL_DATA_REPRESENTATION; msg.cbBuffer = 16; HRESULT hrFromServer; HRESULT hr = _pChnl->GetBuffer(&msg, IID_ICube); if (SUCCEEDED(hr)) { // Marshal the parameters. The string "myproxy" followed by // xPos and yPos values. char *pBuf = (char *)msg.Buffer; strcpy((char *)pBuf, "myproxy"); pBuf += 8; DWORD *dwp = (DWORD *)pBuf; *dwp = xPos; pBuf += 4; dwp = (DWORD *)pBuf; *dwp = yPos; // Send the message and get the reply ULONG ulStatus = 0; hr = _pChnl->SendReceive(&msg, &ulStatus); if (SUCCEEDED(hr)) { // unmarshal the results hrFromServer = (DWORD)(msg.Buffer); } // FreeBuffer hr = _pChnl->FreeBuffer(&msg); } return hr; } HRESULT CCubesProxy::GetCubePos(ULONG *pxPos, ULONG *pyPos) { *pxPos = 0; *pyPos = 0; return E_NOTIMPL; } HRESULT CCubesProxy::Contains(IBalls *pIFDb) { return E_NOTIMPL; } HRESULT CCubesProxy::SimpleCall( DWORD pidCaller, DWORD tidCaller, GUID lidCaller) { return E_NOTIMPL; } //--------------------------------------------------------------------------- // // Implement: CCubesStub // // Purpose: Hand-Crafted stub object for interface ICube. // // Notes: Replace this with your exisitng 32bit hand-crafted stubs. // //--------------------------------------------------------------------------- CCubesStub::CCubesStub(IUnknown *pUnkObj) : _cRefs(1), _pUnkObj(pUnkObj) { _pUnkObj->AddRef(); } CCubesStub::~CCubesStub(void) { Disconnect(); } HRESULT CCubesStub::QueryInterface(REFIID riid, void **ppv) { if (IsEqualIID(riid, IID_IRpcStubBuffer) || IsEqualIID(riid, IID_IUnknown)) { *ppv = (IRpcStubBuffer *)this; } else { *ppv = NULL; return E_NOINTERFACE; } AddRef(); return S_OK; } ULONG CCubesStub::AddRef(void) { InterlockedIncrement((LONG *)&_cRefs); return _cRefs; } ULONG CCubesStub::Release(void) { ULONG cRefs = _cRefs-1; if (InterlockedDecrement((LONG *)&_cRefs) == 0) { delete this; return 0; } return cRefs; } HRESULT CCubesStub::Connect(IUnknown *pUnkObj) { if (_pUnkObj) { // already connected, disconnect Disconnect(); } // get the requested interface and hold it. HRESULT hr = pUnkObj->QueryInterface(IID_ICube, (void **)&_pUnkObj); if (FAILED(hr)) { _pUnkObj = NULL; } return hr; } void CCubesStub::Disconnect() { if (_pUnkObj) { _pUnkObj->Release(); _pUnkObj = NULL; } } HRESULT CCubesStub::Invoke(RPCOLEMESSAGE *pMsg, IRpcChannelBuffer *pChnl) { // Check the method number. if (pMsg->iMethod !=3 || pMsg->cbBuffer != 16) return E_INVALIDARG; // unmarshal the parameters char *pBuf = (char *)pMsg->Buffer; pBuf += 8; DWORD *dwp = (DWORD *)pBuf; ULONG xPos = *dwp; pBuf += 4; dwp = (DWORD *)pBuf; ULONG yPos = *dwp; // call the real object HRESULT hrFromServer = ((ICube *)_pUnkObj)->MoveCube(xPos, yPos); // get a new buffer pMsg->cbBuffer = 4; HRESULT hr = pChnl->GetBuffer(pMsg, IID_ICube); if (SUCCEEDED(hr)) { // marshal the return values pBuf = (char *)pMsg->Buffer; dwp = (DWORD *)pBuf; *dwp = hrFromServer; } return hr; } IRpcStubBuffer *CCubesStub::IsIIDSupported(REFIID riid) { if (IsEqualIID(riid, IID_ICube)) { AddRef(); return (IRpcStubBuffer *)this; } return NULL; } ULONG CCubesStub::CountRefs() { // only keep one reference return 1; } HRESULT CCubesStub::DebugServerQueryInterface(void **ppv) { *ppv = (void *)_pUnkObj; return S_OK; } void CCubesStub::DebugServerRelease(void *pv) { return; }