1093 lines
24 KiB
C++
1093 lines
24 KiB
C++
//---------------------------------------------------------------------------
|
|
//
|
|
// File: myproxy.cxx
|
|
//
|
|
// Purpose: Sample implementation of wrappers to allow simultaneous
|
|
// hand-crafted and MILD-generated stubs.
|
|
//
|
|
// History: 12-11-95 Rickhi Created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
#include <ole2.h>
|
|
#include <stddef.h> // offsetof
|
|
#include <icube.h> // 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;
|
|
}
|