//-------------------------------------------------------------- // // File: hook.cxx // // Contents: Test channel hooks // //--------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include "hook.h" class CWhichHook : public IWhichHook { public: // Constructor/Destructor CWhichHook(); ~CWhichHook() {}; // IUnknown STDMETHOD (QueryInterface) (REFIID iid, void FAR * FAR * ppv); STDMETHOD_(ULONG,AddRef) ( void ); STDMETHOD_(ULONG,Release) ( void ); // IWhichHook STDMETHOD (Me) ( REFIID riid ); STDMETHOD (Hooked)( REFIID riid ); STDMETHOD (Clear) (); private: DWORD _iRef; static BOOL _f1; static BOOL _f2; }; class CDllHook : public IChannelHook { public: CDllHook( REFGUID ); ~CDllHook() {}; STDMETHOD (QueryInterface) ( REFIID riid, LPVOID FAR* ppvObj); STDMETHOD_(ULONG,AddRef) ( void ); STDMETHOD_(ULONG,Release) ( void ); STDMETHOD_(void,ClientGetSize) ( REFGUID, REFIID, ULONG *DataSize ); STDMETHOD_(void,ClientFillBuffer)( REFGUID, REFIID, ULONG *DataSize, void *DataBuffer ); STDMETHOD_(void,ClientNotify) ( REFGUID, REFIID, ULONG DataSize, void *DataBuffer, DWORD DataRep, HRESULT ); STDMETHOD_(void,ServerNotify) ( REFGUID, REFIID, ULONG DataSize, void *DataBuffer, DWORD DataRep ); STDMETHOD_(void,ServerGetSize) ( REFGUID, REFIID, HRESULT, ULONG *DataSize ); STDMETHOD_(void,ServerFillBuffer)( REFGUID, REFIID, ULONG *DataSize, void *DataBuffer, HRESULT ); private: ULONG _iRef; GUID _extent; CWhichHook _cWhich; }; class CHookCF: public IClassFactory { public: // Constructor/Destructor CHookCF( CLSID ); ~CHookCF() {}; // IUnknown STDMETHOD (QueryInterface) (REFIID iid, void FAR * FAR * ppv); STDMETHOD_(ULONG,AddRef) ( void ); STDMETHOD_(ULONG,Release) ( void ); // IClassFactory STDMETHODIMP CreateInstance( IUnknown FAR* pUnkOuter, REFIID iidInterface, void FAR* FAR* ppv); STDMETHODIMP LockServer(BOOL fLock); private: ULONG _iRef; CLSID _class; }; const CLSID CLSID_Hook1 = {0x60000400, 0x76d7, 0x11cf, {0x9a, 0xf1, 0x00, 0x20, 0xaf, 0x6e, 0x72, 0xf4}}; const CLSID CLSID_Hook2 = {0x60000401, 0x76d7, 0x11cf, {0x9a, 0xf1, 0x00, 0x20, 0xaf, 0x6e, 0x72, 0xf4}}; const CLSID CLSID_WhichHook = {0x60000402, 0x76d7, 0x11cf, {0x9a, 0xf1, 0x00, 0x20, 0xaf, 0x6e, 0x72, 0xf4}}; const IID IID_IWhichHook = {0x60000403, 0x76d7, 0x11cf, {0x9a, 0xf1, 0x00, 0x20, 0xaf, 0x6e, 0x72, 0xf4}}; BOOL CWhichHook::_f1 = FALSE; BOOL CWhichHook::_f2 = FALSE; //+------------------------------------------------------------------------- // // Function: DllCanUnloadNow // // Synopsis: Dll entry point // //-------------------------------------------------------------------------- STDAPI DllCanUnloadNow() { return S_FALSE; } //+------------------------------------------------------------------------- // // Function: DllGetClassObject // // Synopsis: Dll entry point // //-------------------------------------------------------------------------- STDAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **ppv) { CHookCF *pFactory; // Check for IPSFactoryBuffer if ((clsid == CLSID_Hook1 || clsid == CLSID_Hook2 || clsid == CLSID_WhichHook) && iid == IID_IClassFactory) { pFactory = new CHookCF( clsid ); *ppv = pFactory; if (pFactory == NULL) return E_OUTOFMEMORY; else return S_OK; } return E_NOTIMPL; } //+------------------------------------------------------------------- // // Member: CHookCF::AddRef, public // // Synopsis: Adds a reference to an interface // //-------------------------------------------------------------------- STDMETHODIMP_(ULONG) CHookCF::AddRef() { InterlockedIncrement( (long *) &_iRef ); return _iRef; } //+------------------------------------------------------------------- // // Member: CHookCF::CHookCF // // Synopsis: Constructor // //-------------------------------------------------------------------- CHookCF::CHookCF( CLSID clsid ) { _iRef = 1; _class = clsid; } //+------------------------------------------------------------------- // // Member: CHookCF::CreateInstance, public // // Synopsis: Create an instance of the requested class // //-------------------------------------------------------------------- STDMETHODIMP CHookCF::CreateInstance( IUnknown FAR* pUnkOuter, REFIID iidInterface, void FAR* FAR* ppv) { IUnknown *pUnk; HRESULT hr; *ppv = NULL; if (pUnkOuter != NULL) { printf( "Create instance failed, attempted agregation.\n" ); return E_FAIL; } // Create the right class. if (_class == CLSID_WhichHook) pUnk = new CWhichHook(); else pUnk = new CDllHook( _class ); // Query for the requested interface. hr = pUnk->QueryInterface( iidInterface, ppv ); pUnk->Release(); return hr; } //+------------------------------------------------------------------- // // Member: CHookCF::LockServer, public // //-------------------------------------------------------------------- STDMETHODIMP CHookCF::LockServer(BOOL fLock) { return E_FAIL; } //+------------------------------------------------------------------- // // Member: CHookCF::QueryInterface, public // // Synopsis: Returns a pointer to the requested interface. // //-------------------------------------------------------------------- STDMETHODIMP CHookCF::QueryInterface( REFIID riid, LPVOID FAR* ppvObj) { if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory)) *ppvObj = (IClassFactory *) this; else { *ppvObj = NULL; return E_NOINTERFACE; } AddRef(); return S_OK; } //+------------------------------------------------------------------- // // Member: CHookCF::Release, public // // Synopsis: Releases an interface // //-------------------------------------------------------------------- STDMETHODIMP_(ULONG) CHookCF::Release() { ULONG lRef = _iRef - 1; if (InterlockedDecrement( (long*) &_iRef ) == 0) { delete this; return 0; } else return lRef; } //+------------------------------------------------------------------- // // Member: CDllHook::AddRef, public // // Synopsis: Adds a reference to an interface // //-------------------------------------------------------------------- STDMETHODIMP_(ULONG) CDllHook::AddRef() { InterlockedIncrement( (long *) &_iRef ); return _iRef; } //+------------------------------------------------------------------- // // Member: CDllHook::CDllHook, public // // Synopsis: Constructor // //-------------------------------------------------------------------- CDllHook::CDllHook( REFGUID rExtent ) { _iRef = 1; _extent = rExtent; } //+------------------------------------------------------------------- // // Member: CDllHook::QueryInterface, public // // Synopsis: Returns a pointer to the requested interface. // //-------------------------------------------------------------------- STDMETHODIMP CDllHook::QueryInterface( REFIID riid, LPVOID FAR* ppvObj) { if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IChannelHook)) *ppvObj = (IChannelHook *) this; else { *ppvObj = NULL; return E_NOINTERFACE; } AddRef(); return S_OK; } //+------------------------------------------------------------------- // // Member: CDllHook::Release, public // // Synopsis: Releases an interface // //-------------------------------------------------------------------- STDMETHODIMP_(ULONG) CDllHook::Release() { ULONG lRef = _iRef - 1; if (InterlockedDecrement( (long*) &_iRef ) == 0) { delete this; return 0; } else return lRef; } /***************************************************************************/ STDMETHODIMP_(void) CDllHook::ClientGetSize( REFGUID ext, REFIID riid, ULONG *size ) { _cWhich.Me( _extent ); *size = sizeof(DWORD); } /***************************************************************************/ STDMETHODIMP_(void) CDllHook::ClientFillBuffer( REFGUID ext, REFIID riid, ULONG *max, void *buffer ) { _cWhich.Me( _extent ); *max = sizeof(DWORD); if (_extent == CLSID_Hook1) *((DWORD *) buffer) = 'Blue'; else *((DWORD *) buffer) = 'Grn'; } /***************************************************************************/ STDMETHODIMP_(void) CDllHook::ClientNotify( REFGUID ext, REFIID riid, ULONG size, void *buffer, DWORD data_rep, HRESULT result ) { _cWhich.Me( _extent ); } /***************************************************************************/ STDMETHODIMP_(void) CDllHook::ServerNotify( REFGUID ext, REFIID riid, ULONG size, void *buffer, DWORD data_rep ) { _cWhich.Me( _extent ); } /***************************************************************************/ STDMETHODIMP_(void) CDllHook::ServerGetSize( REFGUID ext, REFIID riid, HRESULT hr, ULONG *size ) { _cWhich.Me( _extent ); *size = sizeof(DWORD); } /***************************************************************************/ STDMETHODIMP_(void) CDllHook::ServerFillBuffer( REFGUID ext, REFIID riid, ULONG *max, void *buffer, HRESULT hr ) { _cWhich.Me( _extent ); *max = sizeof(DWORD); if (_extent == CLSID_Hook1) *((DWORD *) buffer) = 'Blue'; else *((DWORD *) buffer) = 'Grn'; } //+------------------------------------------------------------------- // // Member: CWhichHook::AddRef, public // // Synopsis: Adds a reference to an interface // //-------------------------------------------------------------------- STDMETHODIMP_(ULONG) CWhichHook::AddRef() { InterlockedIncrement( (long *) &_iRef ); return _iRef; } //+------------------------------------------------------------------- // // Member: CWhichHook::CWhichHook, public // // Synopsis: Constructor // //-------------------------------------------------------------------- CWhichHook::CWhichHook() { _iRef = 1; } //+------------------------------------------------------------------- // // Member: CWhichHook::QueryInterface, public // // Synopsis: Returns a pointer to the requested interface. // //-------------------------------------------------------------------- STDMETHODIMP CWhichHook::QueryInterface( REFIID riid, LPVOID FAR* ppvObj) { if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IWhichHook)) *ppvObj = (IWhichHook *) this; else { *ppvObj = NULL; return E_NOINTERFACE; } AddRef(); return S_OK; } //+------------------------------------------------------------------- // // Member: CWhichHook::Release, public // // Synopsis: Releases an interface // //-------------------------------------------------------------------- STDMETHODIMP_(ULONG) CWhichHook::Release() { ULONG lRef = _iRef - 1; if (InterlockedDecrement( (long*) &_iRef ) == 0) { delete this; return 0; } else return lRef; } //+------------------------------------------------------------------- // // Member: CWhichHook::Me, public // // Synopsis: Flags a hook as used. // //-------------------------------------------------------------------- STDMETHODIMP CWhichHook::Me( REFIID riid ) { if (riid == CLSID_Hook1) _f1 = TRUE; else if (riid == CLSID_Hook2) _f2 = TRUE; return S_OK; } //+------------------------------------------------------------------- // // Member: CWhichHook::Hooked, public // // Synopsis: Succeeds if the specified hook has been used. // //-------------------------------------------------------------------- STDMETHODIMP CWhichHook::Hooked( REFIID riid ) { if (riid == CLSID_Hook1) return _f1 ? S_OK : E_FAIL; else if (riid == CLSID_Hook2) return _f2 ? S_OK : E_FAIL; return E_INVALIDARG; } //+------------------------------------------------------------------- // // Member: CWhichHook::Clear, public // // Synopsis: Clears the used flags. // //-------------------------------------------------------------------- STDMETHODIMP CWhichHook::Clear() { _f1 = FALSE; _f2 = FALSE; return S_OK; }