491 lines
13 KiB
C++
491 lines
13 KiB
C++
|
//--------------------------------------------------------------
|
|||
|
//
|
|||
|
// File: hook.cxx
|
|||
|
//
|
|||
|
// Contents: Test channel hooks
|
|||
|
//
|
|||
|
//---------------------------------------------------------------
|
|||
|
|
|||
|
#include <windows.h>
|
|||
|
#include <stdio.h>
|
|||
|
#include <sys/types.h>
|
|||
|
#include <sys/stat.h>
|
|||
|
#include <errno.h>
|
|||
|
#include <io.h>
|
|||
|
#include <malloc.h>
|
|||
|
|
|||
|
#include <ole2.h>
|
|||
|
#include <coguid.h>
|
|||
|
#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;
|
|||
|
}
|
|||
|
|