Initial commit: Complete open-source Decal rebuild

All 5 phases of the open-source Decal rebuild:

Phase 1: 14 decompiled .NET projects (Interop.*, Adapter, FileService, DecalUtil)
Phase 2: 10 native DLLs rewritten as C# COM servers with matching GUIDs
  - DecalDat, DHS, SpellFilter, DecalInput, DecalNet, DecalFilters
  - Decal.Core, DecalControls, DecalRender, D3DService
Phase 3: C++ shims for Inject.DLL (D3D9 hooking) and LauncherHook.DLL
Phase 4: DenAgent WinForms tray application
Phase 5: WiX installer and build script

25 C# projects building with 0 errors.
Native C++ projects require VS 2022 + Windows SDK (x86).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
erik 2026-02-08 18:27:56 +01:00
commit d1442e3747
1382 changed files with 170725 additions and 0 deletions

View file

@ -0,0 +1,282 @@
// DirectDrawHook.cpp : Implementation of CDirectDrawHook
#include "stdafx.h"
#include "Inject.h"
#include "DirectDrawHook.h"
#include "MaterialHook.h"
#include "DirectDrawSurfaceHook.h"
#include "Manager.h"
//#include <fstream>
/////////////////////////////////////////////////////////////////////////////
// CDirectDrawHook
void CDirectDrawHook::setObject( IDirectDraw *pDD )
{
m_pDD = pDD;
m_pDD->QueryInterface( IID_IDirectDraw2, reinterpret_cast< void ** >( &m_pDD2 ) );
m_pDD->QueryInterface( IID_IDirectDraw4, reinterpret_cast< void ** >( &m_pDD4 ) );
m_pDD->QueryInterface( IID_IDirect3D, reinterpret_cast< void ** >( &m_pD3D ) );
m_pDD->QueryInterface( IID_IDirect3D2, reinterpret_cast< void ** >( &m_pD3D2 ) );
m_pDD->QueryInterface( IID_IDirect3D3, reinterpret_cast< void ** >( &m_pD3D3 ) );
cManager::_p->setDirectDraw( m_pDD4, m_pD3D3, NULL);
}
STDMETHODIMP CDirectDrawHook::SetCooperativeLevel(HWND p1, DWORD p2)
{
cManager::_p->setWindow( p1 );
return m_pDD->SetCooperativeLevel( p1, p2 );
}
STDMETHODIMP CDirectDrawHook::SetDisplayMode(DWORD p1, DWORD p2, DWORD p3)
{
return m_pDD->SetDisplayMode( p1, p2, p3 );
}
HRESULT (__stdcall *pfnOldUnlock)(IDirectDrawSurface4 *pDDS, LPRECT rc);
HRESULT __stdcall myUnlock ( IDirectDrawSurface4 *pDDS, LPRECT rc)
{
HRESULT hRes = pfnOldUnlock(pDDS, rc);
if(rc==NULL)
cManager::_p->draw2D();
//MessageBox(0, _bstr_t(" left: ") + _bstr_t((long)rc->left) + _bstr_t(" top: ") + _bstr_t((long)rc->top) + _bstr_t(" right: ") + _bstr_t((long)rc->right) + _bstr_t(" bottom: ") + _bstr_t((long)rc->bottom), "Asd", 0);
return hRes;
}
STDMETHODIMP CDirectDrawHook::CreateSurface(LPDDSURFACEDESC2 p1, LPDIRECTDRAWSURFACE4 FAR *ppDDS, IUnknown FAR *p3)
{
static bool bGotPrimary=false;
static sc=0;
//static std::ofstream ass("c:\\acl.txt", std::ios::binary);
//ass << "Flags: " << p1->dwFlags << " dwCaps: " << p1->ddsCaps.dwCaps << " Width: " << p1->dwWidth << " Height: " << p1->dwHeight << "\r\n";
if((cManager::_p->getSoftwareMode()))// && (!bGotPrimary))
{
/*CComPtr< IDirectDrawSurface4 > pDDS;
HRESULT hRes = m_pDD4->CreateSurface( p1, &pDDS, p3 );
if( FAILED( hRes ) )
return hRes;
if(!(p1->ddsCaps.dwCaps & (DDSCAPS_PRIMARYSURFACE)))// | DDSCAPS_COMPLEX)))
{
pDDS->QueryInterface(IID_IDirectDrawSurface4, reinterpret_cast< void ** >(ppDDS));
return hRes;
}
m_nSurfaceCount++;
if(m_nSurfaceCount==1)//!=4)
cManager::_p->setDirectDraw(m_pDD4, NULL, pDDS);
CComObject< CDirectDrawSurfaceHook > *pHook;
CComObject< CDirectDrawSurfaceHook >::CreateInstance( &pHook );
pHook->setObject( pDDS );
pHook->setSurfaceNum( m_nSurfaceCount );
pHook->QueryInterface( IID_IDirectDrawSurface4, reinterpret_cast< void ** >( ppDDS ) );
*/
CComPtr< IDirectDrawSurface4 > pDDS;
HRESULT hRes = m_pDD4->CreateSurface( p1, &pDDS, p3 );
if( FAILED( hRes ) )
return hRes;
// Get the configured width from the registry
/* DWORD dwConfiguredWidth;
{
RECT rc;
::GetClientRect( cManager::_p->m_hMain, &rc );
dwConfiguredWidth = rc.right - rc.left;
}*/
/*if( p1->dwWidth < ( dwConfiguredWidth - 330 ) )
{
}
else*/
if(p1->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)// && (p1->dwHeight==362) && (p1->dwWidth==300))//(p1->ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN)
{
//MessageBox(0, _bstr_t("Width: ") + _bstr_t((long)p1->dwWidth) + _bstr_t(" Height: ") + _bstr_t((long)p1->dwHeight), "asd", 0);
sc++;
if((!bGotPrimary) && (sc==2))
{
sc=0;
HRESULT (__stdcall *&pfnUnlock)(IDirectDrawSurface4 *pDDS, LPRECT rc) = reinterpret_cast< HRESULT (__stdcall**)(IDirectDrawSurface4 *pDDS, LPRECT rc) > ( *reinterpret_cast< DWORD * > ( pDDS.p ) )[ 32 ];
pfnOldUnlock = *pfnUnlock;
pfnUnlock = myUnlock;
//if((p1->dwHeight>=362) && (p1->dwWidth>=300))
//{
// cManager::_p->SurfaceList.push_back(pDDS);
//MessageBox(0, _bstr_t(CSC), "asd", 0);
//557 or 333
//}
//if(CSC==1)
//{
/* CComObject< CDirectDrawSurfaceHook > *pHook;
CComObject< CDirectDrawSurfaceHook >::CreateInstance( &pHook );
pHook->setObject( pDDS );*/
bGotPrimary=true;
//if(!bGotPrimary)
//{
cManager::_p->setDirectDraw(m_pDD4, NULL, pDDS);
cManager::_p->setSurface(NULL);
//}
}
}
//pHook->QueryInterface( IID_IDirectDrawSurface4, reinterpret_cast< void ** >( ppDDS ) );
// return hRes;
//}
/* pHook->QueryInterface(IID_IDirectDrawSurface4, reinterpret_cast< void ** >(ppDDS));
}
else*/
pDDS->QueryInterface(IID_IDirectDrawSurface4, reinterpret_cast< void ** >(ppDDS));
m_pPrimary = pDDS.p;
return hRes;
}
else
return m_pDD4->CreateSurface(p1, ppDDS, p3);
}
STDMETHODIMP CDirectDrawHook::SetDisplayMode(DWORD p1, DWORD p2, DWORD p3, DWORD p4, DWORD p5)
{
return m_pDD2->SetDisplayMode( p1, p2, p3, p4, p5 );
}
STDMETHODIMP CDirectDrawHook::CreateMaterial(LPDIRECT3DMATERIAL *p1,IUnknown *p2)
{
CComPtr< IDirect3DMaterial > pMat;
HRESULT hRes = m_pD3D->CreateMaterial( &pMat, p2 );
if( FAILED( hRes ) )
return hRes;
CComObject< CMaterialHook > *pHook;
CComObject< CMaterialHook >::CreateInstance( &pHook );
pHook->setObject( pMat, m_pDevice2, m_pDevice3 );
pHook->QueryInterface( IID_IDirect3DMaterial, reinterpret_cast< void ** >( p1 ) );
return hRes;
}
STDMETHODIMP CDirectDrawHook::CreateMaterial(LPDIRECT3DMATERIAL2*p1,IUnknown*p2)
{
CComPtr< IDirect3DMaterial2 > pMat;
HRESULT hRes = m_pD3D2->CreateMaterial( &pMat, p2 );
if( FAILED( hRes ) )
return hRes;
CComObject< CMaterialHook > *pHook;
CComObject< CMaterialHook >::CreateInstance( &pHook );
pHook->setObject( pMat, m_pDevice2, m_pDevice3 );
pHook->QueryInterface( IID_IDirect3DMaterial2, reinterpret_cast< void ** >( p1 ) );
return hRes;
}
STDMETHODIMP CDirectDrawHook::CreateMaterial(LPDIRECT3DMATERIAL3*p1,LPUNKNOWN p2)
{
CComPtr< IDirect3DMaterial3 > pMat;
HRESULT hRes = m_pD3D3->CreateMaterial( &pMat, p2 );
if( FAILED( hRes ) )
return hRes;
CComObject< CMaterialHook > *pHook;
CComObject< CMaterialHook >::CreateInstance( &pHook );
pHook->setObject( pMat, m_pDevice2, m_pDevice3 );
pHook->QueryInterface( IID_IDirect3DMaterial3, reinterpret_cast< void ** >( p1 ) );
return hRes;
}
STDMETHODIMP CDirectDrawHook::CreateDevice( REFCLSID cls,LPDIRECTDRAWSURFACE pDDS,LPDIRECT3DDEVICE2 *ppD3D )
{
CComPtr< IDirect3DDevice2 > pD3D;
HRESULT hRes = m_pD3D2->CreateDevice( cls, pDDS, &pD3D );
if( FAILED( hRes ) )
{
::MessageBox (NULL, "2COULDN'T CreateDevice IN D3D HOOK", "ERROR", MB_OK);
return hRes;
}
CComObject< CDirect3DHook > *pHook;
CComObject< CDirect3DHook >::CreateInstance( &pHook );
pHook->setObject( pD3D );
pHook->QueryInterface( IID_IDirect3DDevice2, reinterpret_cast< void ** >( ppD3D ) );
m_pDevice2 = *ppD3D;
return hRes;
}
STDMETHODIMP CDirectDrawHook::CreateDevice(REFCLSID cls,LPDIRECTDRAWSURFACE4 pDDS,LPDIRECT3DDEVICE3* ppD3D,LPUNKNOWN pUnk)
{
CComPtr< IDirect3DDevice3 > pD3D;
HRESULT hRes = m_pD3D3->CreateDevice( cls, pDDS, &pD3D, pUnk );
if( FAILED( hRes ) )
{
::MessageBox (NULL, "3COULDN'T CreateDevice IN D3D HOOK", "ERROR", MB_OK);
return hRes;
}
// Ok, figure out if this is the "primary" 3d device
DDSURFACEDESC2 ddsd;
ddsd.dwSize = sizeof( DDSURFACEDESC2 );
pDDS->GetSurfaceDesc( &ddsd );
// Get the configured width from the registry
DWORD dwConfiguredWidth;
{
RECT rc;
::GetClientRect( cManager::_p->m_hMain, &rc );
dwConfiguredWidth = rc.right - rc.left;
}
if( ddsd.dwWidth < ( dwConfiguredWidth - 330 ) )
{
// This is a secondary 3ddevice - do not hook it
return pD3D->QueryInterface( IID_IDirect3DDevice3, reinterpret_cast< void ** >( ppD3D ) );
}
// Ok, we're past the wrong device, get to the right device
cManager::_p->setSurface( pD3D );
CComObject< CDirect3DHook > *pHook;
CComObject< CDirect3DHook >::CreateInstance( &pHook );
pHook->setObject( pD3D );
pHook->QueryInterface( IID_IDirect3DDevice3, reinterpret_cast< void ** >( ppD3D ) );
m_pDevice3 = *ppD3D;
return hRes;
}

View file

@ -0,0 +1,277 @@
// DirectDrawHook.h : Declaration of the CDirectDrawHook
#ifndef __DIRECTDRAWHOOK_H_
#define __DIRECTDRAWHOOK_H_
#include "resource.h" // main symbols
#include "Direct3DHook.h"
/////////////////////////////////////////////////////////////////////////////
// CDirectDrawHook
class ATL_NO_VTABLE CDirectDrawHook :
public CComObjectRootEx<CComMultiThreadModel>,
public IDirectDraw,
public IDirectDraw2,
public IDirectDraw4,
public IDirect3D,
public IDirect3D2,
public IDirect3D3
{
public:
CDirectDrawHook()
: m_pDevice2( NULL ),
m_pDevice3( NULL ), m_nSurfaceCount( 0 )
{
}
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CDirectDrawHook)
COM_INTERFACE_ENTRY_IID(IID_IDirectDraw, IDirectDraw)
COM_INTERFACE_ENTRY_IID(IID_IDirectDraw2, IDirectDraw2)
COM_INTERFACE_ENTRY_IID(IID_IDirectDraw4, IDirectDraw4)
COM_INTERFACE_ENTRY_IID(IID_IDirect3D, IDirect3D)
COM_INTERFACE_ENTRY_IID(IID_IDirect3D2, IDirect3D2)
COM_INTERFACE_ENTRY_IID(IID_IDirect3D3, IDirect3D3)
END_COM_MAP()
void setObject( IDirectDraw *pDD );
CComPtr< IDirectDraw > m_pDD;
CComPtr< IDirectDraw2 > m_pDD2;
CComPtr< IDirectDraw4 > m_pDD4;
CComPtr< IDirect3D > m_pD3D;
CComPtr< IDirect3D2 > m_pD3D2;
CComPtr< IDirect3D3 > m_pD3D3;
IDirect3DDevice2 *m_pDevice2;
IDirect3DDevice3 *m_pDevice3;
IDirectDrawSurface4 *m_pPrimary;
long m_nSurfaceCount;
public:
// IDirectDraw Methods
STDMETHOD(Compact)()
{
return m_pDD->Compact();
}
STDMETHOD(CreateClipper)(DWORD p1, LPDIRECTDRAWCLIPPER FAR *p2, IUnknown FAR *p3 )
{
return m_pDD->CreateClipper( p1, p2, p3 );
}
STDMETHOD(CreatePalette)(DWORD p1, LPPALETTEENTRY p2, LPDIRECTDRAWPALETTE FAR*p3, IUnknown FAR *p4 )
{
return m_pDD->CreatePalette( p1, p2, p3, p4 );
}
STDMETHOD(CreateSurface)(LPDDSURFACEDESC p1, LPDIRECTDRAWSURFACE FAR *p2, IUnknown FAR *p3 )
{
return m_pDD->CreateSurface( p1, p2, p3 );
}
STDMETHOD(DuplicateSurface)( LPDIRECTDRAWSURFACE p1, LPDIRECTDRAWSURFACE FAR *p2 )
{
return m_pDD->DuplicateSurface( p1, p2 );
}
STDMETHOD(EnumDisplayModes)( DWORD p1, LPDDSURFACEDESC p2, LPVOID p3, LPDDENUMMODESCALLBACK p4 )
{
return m_pDD->EnumDisplayModes( p1, p2, p3, p4 );
}
STDMETHOD(EnumSurfaces)(DWORD p1, LPDDSURFACEDESC p2, LPVOID p3, LPDDENUMSURFACESCALLBACK p4 )
{
return m_pDD->EnumSurfaces( p1, p2, p3, p4 );
}
STDMETHOD(FlipToGDISurface)()
{
return m_pDD4->FlipToGDISurface();
}
STDMETHOD(GetCaps)( LPDDCAPS p1, LPDDCAPS p2 )
{
return m_pDD4->GetCaps( p1, p2 );
}
STDMETHOD(GetDisplayMode)( LPDDSURFACEDESC p1 )
{
return m_pDD->GetDisplayMode( p1 );
}
STDMETHOD(GetFourCCCodes)(LPDWORD p1, LPDWORD p2 )
{
return m_pDD->GetFourCCCodes( p1, p2 );
}
STDMETHOD(GetGDISurface)(LPDIRECTDRAWSURFACE FAR *p1)
{
return m_pDD->GetGDISurface( p1 );
}
STDMETHOD(GetMonitorFrequency)(LPDWORD p1)
{
return m_pDD->GetMonitorFrequency( p1 );
}
STDMETHOD(GetScanLine)(LPDWORD p1)
{
return m_pDD->GetScanLine( p1 );
}
STDMETHOD(GetVerticalBlankStatus)(LPBOOL p1 )
{
return m_pDD->GetVerticalBlankStatus( p1 );
}
STDMETHOD(Initialize)(GUID FAR *p1)
{
return m_pDD->Initialize( p1 );
}
STDMETHOD(RestoreDisplayMode)()
{
return m_pDD->RestoreDisplayMode();
}
STDMETHOD(SetCooperativeLevel)(HWND p1, DWORD p2);
STDMETHOD(SetDisplayMode)(DWORD p1, DWORD p2, DWORD p3);
STDMETHOD(WaitForVerticalBlank)(DWORD p1, HANDLE p2 )
{
return m_pDD->WaitForVerticalBlank( p1, p2 );
}
/*** Added in the v2 interface ***/
STDMETHOD(GetAvailableVidMem)(LPDDSCAPS p1, LPDWORD p2, LPDWORD p3)
{
return m_pDD2->GetAvailableVidMem( p1, p2, p3 );
}
/*** Added in the V4 Interface ***/
STDMETHOD(GetAvailableVidMem)(LPDDSCAPS2 p1, LPDWORD p2, LPDWORD p3)
{
return m_pDD4->GetAvailableVidMem( p1, p2, p3 );
}
STDMETHOD(CreateSurface)(LPDDSURFACEDESC2 p1, LPDIRECTDRAWSURFACE4 FAR *p2, IUnknown FAR *p3);
STDMETHOD(DuplicateSurface)( LPDIRECTDRAWSURFACE4 p1, LPDIRECTDRAWSURFACE4 FAR *p2 )
{
return m_pDD4->DuplicateSurface( p1, p2 );
}
STDMETHOD(EnumDisplayModes)( DWORD p1, LPDDSURFACEDESC2 p2, LPVOID p3, LPDDENUMMODESCALLBACK2 p4 )
{
return m_pDD4->EnumDisplayModes( p1, p2, p3, p4 );
}
STDMETHOD(EnumSurfaces)(DWORD p1, LPDDSURFACEDESC2 p2, LPVOID p3, LPDDENUMSURFACESCALLBACK2 p4 )
{
return m_pDD4->EnumSurfaces( p1, p2, p3, p4 );
}
STDMETHOD(GetDisplayMode)( LPDDSURFACEDESC2 p1 )
{
return m_pDD4->GetDisplayMode( p1 );
}
STDMETHOD(GetGDISurface)(LPDIRECTDRAWSURFACE4 FAR *p1)
{
return m_pDD4->GetGDISurface( p1 );
}
STDMETHOD(GetSurfaceFromDC) (HDC p1, LPDIRECTDRAWSURFACE4 *p2)
{
return m_pDD4->GetSurfaceFromDC( p1, p2 );
}
STDMETHOD(RestoreAllSurfaces)()
{
return m_pDD4->RestoreAllSurfaces();
}
STDMETHOD(TestCooperativeLevel)()
{
return m_pDD4->TestCooperativeLevel();
}
STDMETHOD(GetDeviceIdentifier)(LPDDDEVICEIDENTIFIER p1, DWORD p2 )
{
return m_pDD4->GetDeviceIdentifier( p1, p2 );
}
// Methods for the IDirect3D Interface
STDMETHOD(Initialize)(REFCLSID p1)
{
return m_pD3D->Initialize( p1 );
}
STDMETHOD(EnumDevices)(LPD3DENUMDEVICESCALLBACK p1,LPVOID p2)
{
return m_pD3D->EnumDevices( p1, p2 );
}
STDMETHOD(CreateLight)(LPDIRECT3DLIGHT*p1,IUnknown*p2)
{
return m_pD3D->CreateLight( p1, p2 );
}
STDMETHOD(CreateMaterial)(LPDIRECT3DMATERIAL *p1,IUnknown *p2);
STDMETHOD(CreateViewport)(LPDIRECT3DVIEWPORT*p1,IUnknown*p2)
{
return m_pD3D->CreateViewport( p1, p2 );
}
STDMETHOD(FindDevice)(LPD3DFINDDEVICESEARCH p1,LPD3DFINDDEVICERESULT p2)
{
return m_pD3D->FindDevice( p1, p2 );
}
// Methods for the IDirect3D2 Interface
STDMETHOD(SetDisplayMode)(DWORD p1, DWORD p2, DWORD p3, DWORD p4, DWORD p5);
STDMETHOD(CreateMaterial)(LPDIRECT3DMATERIAL2*p1,IUnknown*p2);
STDMETHOD(CreateViewport)(LPDIRECT3DVIEWPORT2*p1,IUnknown*p2)
{
return m_pD3D2->CreateViewport( p1, p2 );
}
STDMETHOD(CreateDevice)(REFCLSID cls,LPDIRECTDRAWSURFACE pDDS,LPDIRECT3DDEVICE2 *ppD3D);
// Methods for the IDirect3D3 Interface
STDMETHOD(CreateMaterial)(LPDIRECT3DMATERIAL3*p1,LPUNKNOWN p2);
STDMETHOD(CreateViewport)(LPDIRECT3DVIEWPORT3*p1,LPUNKNOWN p2)
{
return m_pD3D3->CreateViewport( p1, p2 );
}
STDMETHOD(CreateDevice)(REFCLSID cls,LPDIRECTDRAWSURFACE4 pDDS,LPDIRECT3DDEVICE3* ppD3D,LPUNKNOWN pUnk);
STDMETHOD(CreateVertexBuffer)(LPD3DVERTEXBUFFERDESC p1,LPDIRECT3DVERTEXBUFFER*p2,DWORD p3,LPUNKNOWN p4)
{
return m_pD3D3->CreateVertexBuffer( p1, p2, p3, p4 );
}
STDMETHOD(EnumZBufferFormats)(REFCLSID p1,LPD3DENUMPIXELFORMATSCALLBACK p2,LPVOID p3)
{
return m_pD3D3->EnumZBufferFormats( p1, p2, p3 );
}
STDMETHOD(EvictManagedTextures)()
{
return m_pD3D3->EvictManagedTextures();
}
};
#endif //__DIRECTDRAWHOOK_H_

View file

@ -0,0 +1,313 @@
// Panel.cpp : Implementation of cPanel
#include "stdafx.h"
#include "Inject.h"
#include "Panel.h"
/////////////////////////////////////////////////////////////////////////////
// cPanel
enum ePanelChildren
{
eViewFirst = 1000
};
cPanel::cPanel()
: m_nIcon( 0 ),
m_nIconModule( 0 ),
m_nActiveView( -1 ),
m_bDragging( false )
{
}
void cPanel::hideView()
{
m_pSite->Invalidate();
if( m_nActiveView == -1 )
// No active view currently
return;
CComPtr< ILayerSite > pActive;
m_pSite->get_Child( m_nActiveView, ePositionByID, &pActive );
static RECT rcHide = { 0, 0, 0, 0 };
pActive->put_Position( &rcHide );
if( m_pSink.p != NULL )
m_pSink->PanelDeactivate( m_nActiveView );
m_nActiveView = -1;
}
void cPanel::onCreate()
{
CComPtr< IPluginSite > pPlugin;
m_pSite->get_PluginSite( &pPlugin );
pPlugin->LoadBitmapPortal( 0x0600126F, &m_pBackground );
pPlugin->LoadBitmapPortal( 0x06001277, &m_pBorder );
pPlugin->CreateFont( _bstr_t( _T( "Times New Roman" ) ), 15, eFontBold, &m_pTitle );
CComPtr< IButton > pRollup;
HRESULT hRes = ::CoCreateInstance( CLSID_Button, NULL, CLSCTX_INPROC_SERVER, IID_IButton,
reinterpret_cast< void ** >( &pRollup ) );
_ASSERTE( SUCCEEDED( hRes ) );
CComPtr< ILayer > pBtnLayer;
pRollup->QueryInterface( &pBtnLayer );
LayerParams lp = { 1, { 180 - 16, 0, 180, 16 }, eRenderClipped };
m_pSite->CreateChild( &lp, pBtnLayer );
pRollup->put_Matte( RGB( 0, 0, 0 ) );
pRollup->SetImages( 0, 0x0600113C, 0x0600113B );
ICommandEventsImpl< BUTTON_CLOSE, cPanel >::advise( pRollup );
m_pSite->put_Transparent( VARIANT_FALSE );
}
void cPanel::onDestroy()
{
m_pBorder.Release();
m_pBackground.Release();
m_pTitle.Release();
}
STDMETHODIMP cPanel::Render( ICanvas *pCanvas )
{
RECT rc;
m_pSite->get_Position( &rc );
SIZE szBorder;
m_pBorder->get_Size( &szBorder );
// Draw the background
RECT rc_pat = { 0, 0, rc.right - rc.left, rc.bottom - rc.top };
static POINT pt_pat = { 0, 0 };
m_pBackground->PatBlt( pCanvas, &rc_pat, &pt_pat );
// Draw the borders
RECT rc_border_top = { 0, 0, rc.right - rc.left, szBorder.cy },
rc_border_bottom = { 0, rc.bottom - rc.top - szBorder.cy,
rc.right - rc.left, rc.bottom - rc.top };
pCanvas->Fill( &rc_border_top, RGB( 0, 0, 0 ) );
m_pBorder->PatBlt( pCanvas, &rc_border_top, &pt_pat );
pCanvas->Fill( &rc_border_bottom, RGB( 0, 0, 0 ) );
m_pBorder->PatBlt( pCanvas, &rc_border_bottom, &pt_pat );
// Draw the title text
if( m_strTitle.length() > 0 )
{
POINT ptText = { 24, szBorder.cy + 5 };
m_pTitle->DrawText( &ptText, m_strTitle, 0, pCanvas );
}
if( m_nIcon != 0 )
{
CComPtr< IPluginSite > pPlugin;
m_pSite->get_PluginSite( &pPlugin );
CComPtr< IIconCache > pIconCache;
static SIZE szIcon = { 16, 16 };
pPlugin->GetIconCache( &szIcon, &pIconCache );
static POINT pt = { 4, szBorder.cy + 4 };
pIconCache->DrawIcon( &pt, m_nIcon, m_nIconModule, pCanvas );
}
_ASSERTE( _CrtCheckMemory( ) );
return S_OK;
}
STDMETHODIMP cPanel::Reformat()
{
// Reset the size
CComPtr< IPluginSite > pPlugin;
m_pSite->get_PluginSite( &pPlugin );
SIZE szScreen;
pPlugin->GetScreenSize( &szScreen );
RECT rc = { m_nLeft, m_nTop, m_nWidth+m_nLeft, m_nHeight+m_nTop };
m_pSite->put_Position( &rc );
RECT rcCloseBtn = { m_nWidth - 16, 0, m_nWidth, 16 };
CComPtr< ILayerSite > pCloseBtnLS;
m_pSite->get_Child(1, ePositionByID, &pCloseBtnLS);
pCloseBtnLS->put_Position(&rcCloseBtn);
if( m_nActiveView != -1 )
{
// Position the active view
SIZE szBorder;
m_pBorder->get_Size( &szBorder );
CComPtr< ILayerSite > pActive;
m_pSite->get_Child( m_nActiveView, ePositionByID, &pActive );
RECT rcChild = { 0, 24 + szBorder.cy, m_nWidth, m_nHeight - szBorder.cy };
pActive->put_Position( &rcChild );
}
return S_OK;
}
STDMETHODIMP cPanel::AddView(long nViewID, ILayer *pLayer)
{
_ASSERTE( pLayer != NULL );
LayerParams p = { nViewID, { 0, 0, 0, 0 }, eRenderClipped };
// Set up the layer - note that it is not visible
return m_pSite->CreateChild( &p, pLayer );
}
STDMETHODIMP cPanel::ActivateView(long nViewID, ViewParams *pParams)
{
// Hide the current view by resizing to 0,0
hideView();
m_strTitle = pParams->label;
m_nIcon = pParams->icon;
m_nIconModule = pParams->iconLibrary;
m_nWidth = pParams->width;
m_nTop = pParams->top;
m_nHeight = pParams->height;
m_nLeft = pParams->left;
#ifdef _DEBUG
// Make sure the child exists
CComPtr< ILayerSite > pChildSite;
_ASSERTE( SUCCEEDED( m_pSite->get_Child( nViewID, ePositionByID, &pChildSite ) ) );
#endif
// Locate the child
m_nActiveView = nViewID;
// Trick it into reformatting next frame
static RECT rcBig = { 0, 0, 1, 1 };
m_pSite->put_Position( &rcBig );
return S_OK;
}
STDMETHODIMP cPanel::RemoveView(long nViewID)
{
if( nViewID == m_nActiveView )
// If this is the current view, run and hide
Deactivate();
CComPtr< ILayerSite > pChildSite;
HRESULT hRes = m_pSite->get_Child( nViewID, ePositionByID, &pChildSite );
_ASSERTE( SUCCEEDED( hRes ) );
pChildSite->Destroy();
return S_OK;
}
void cPanel::onCloseAccepted(long nID)
{
// We should only be getting commands from the button
_ASSERTE( nID == 1 );
Deactivate();
}
STDMETHODIMP cPanel::get_ActiveView(long *pVal)
{
_ASSERTE( pVal != NULL );
*pVal = m_nActiveView;
return S_OK;
}
STDMETHODIMP cPanel::LoadView(long nViewID, IView *pView, IUnknown *pSchema)
{
_ASSERTE( pView != NULL );
_ASSERTE( pSchema != NULL );
long nAssigned;
// Set up the layer - note that it is not visible
return pView->LoadControl( m_pSite, nViewID, pSchema, &nAssigned );
}
STDMETHODIMP cPanel::Deactivate()
{
if( m_nActiveView == -1 )
// No active view currently
return S_OK;
// Hide the current view by resizing to 0,0
hideView();
// Hide the entire panel
static RECT rcHide = { 0, 0, 0, 0 };
m_pSite->put_Position( &rcHide );
m_nActiveView = -1;
return S_OK;
}
STDMETHODIMP cPanel::putref_Sink(IPanelSink *newVal)
{
m_pSink = newVal;
return S_OK;
}
STDMETHODIMP cPanel::MouseEnter(MouseState *)
{
return S_OK;
}
STDMETHODIMP cPanel::MouseExit(MouseState *)
{
return S_OK;
}
STDMETHODIMP cPanel::MouseDown(MouseState *pMS)
{
if((pMS->screen.x>=m_nLeft) && (pMS->screen.x<=m_nLeft+m_nWidth-16) && (pMS->screen.y-28>=m_nTop) && (pMS->screen.y-28<=m_nTop+28))
{
m_DeltaX = pMS->screen.x-m_nLeft;
m_DeltaY = pMS->screen.y-m_nTop-28;
m_bDragging = true;
}
return S_OK;
}
STDMETHODIMP cPanel::MouseUp(MouseState *)
{
m_bDragging = false;
return S_OK;
}
STDMETHODIMP cPanel::MouseMove(MouseState *pMS)
{
if(m_bDragging)
{
m_nLeft = pMS->screen.x-m_DeltaX;
m_nTop = pMS->screen.y-m_DeltaY-28;
static RECT rcBig = { 0, 0, 1, 1 };
m_pSite->put_Position( &rcBig );
}
return S_OK;
}
STDMETHODIMP cPanel::MouseEvent(long nMsg, long wParam, long lParam)
{
return S_OK;
}

View file

@ -0,0 +1,88 @@
// Panel.h : Declaration of the cPanel
#ifndef __PANEL_H_
#define __PANEL_H_
#include "resource.h" // main symbols
#include "SinkImpl.h"
#define BUTTON_CLOSE 1
/////////////////////////////////////////////////////////////////////////////
// cPanel
class ATL_NO_VTABLE cPanel :
public CComObjectRootEx<CComMultiThreadModel>,
public ILayerRenderImpl,
public ILayerImpl< cPanel >,
public ILayerMouseImpl,
public ICommandEventsImpl< BUTTON_CLOSE, cPanel >,
public cNoEventsImpl,
public IPanel
{
public:
cPanel();
_bstr_t m_strTitle;
long m_nIcon, m_nIconModule;
long m_nActiveView;
CComPtr< IImageCache > m_pBorder;
CComPtr< IImageCache > m_pBackground;
CComPtr< IFontCache > m_pTitle;
CComPtr< IPanelSink > m_pSink;
long m_nTop;
long m_nLeft;
long m_nHeight;
long m_nWidth;
long m_DeltaX;
long m_DeltaY;
bool m_bDragging;
void hideView();
void onCreate();
void onDestroy();
BEGIN_COM_MAP(cPanel)
COM_INTERFACE_ENTRY(ILayer)
COM_INTERFACE_ENTRY(ILayerRender)
COM_INTERFACE_ENTRY(IPanel)
COM_INTERFACE_ENTRY(ILayerMouse)
END_COM_MAP()
BEGIN_SINK_MAP( cPanel )
SINK_ENTRY_EX( BUTTON_CLOSE, DIID_ICommandEvents, DISPID_ACCEPTED, onCloseAccepted )
END_SINK_MAP()
// IPanel
public:
STDMETHOD(LoadView)(long nPlugin, IView *pView, IUnknown *pSchema);
STDMETHOD(get_ActiveView)(/*[out, retval]*/ long *pVal);
STDMETHOD(AddView)(long nPluginID, ILayer *pLayer);
STDMETHOD(RemoveView)(long nID);
STDMETHOD(ActivateView)(long nViewID, ViewParams *pParams);
STDMETHOD(Deactivate)();
STDMETHOD(putref_Sink)(/*[in]*/ IPanelSink* newVal);
// ILayerRender Methods
STDMETHOD(Render)(ICanvas *);
STDMETHOD(Reformat)();
// ICommandEvents Methods
void __stdcall onCloseAccepted(long nID);
// ILayerMouse Methods
STDMETHOD(MouseEnter)(struct MouseState *);
STDMETHOD(MouseExit)(struct MouseState *);
STDMETHOD(MouseDown)(struct MouseState *pMS);
STDMETHOD(MouseUp)(struct MouseState *);
STDMETHOD(MouseMove)(struct MouseState *pMS);
STDMETHOD(MouseEvent)(long nMsg, long wParam, long lParam);
};
#endif //__PANEL_H_

View file

@ -0,0 +1,191 @@
// RootLayer.cpp : Implementation of cRootLayer
#include "stdafx.h"
#include "Inject.h"
#include "RootLayer.h"
#include "BarLayer.h"
#include "Panel.h"
#include "View.h"
enum eChildIDs
{
eChildBars,
eChildPanel
};
/////////////////////////////////////////////////////////////////////////////
// cRootLayer
void cRootLayer::addView( cView *pView, ILayer *pRoot )
{
m_views.push_back( pView );
ViewParams vp = { pView->m_nIcon, pView->m_nIconModule, pView->m_strTitle, pView->m_nLeft, pView->m_nTop, pView->m_nWidth, pView->m_nHeight };
// Next, make the bar entry
m_pBars->AddBar( pView->m_nViewID, &vp );
// Last, make the view entry
m_pPanel->AddView( pView->m_nViewID, pRoot );
}
void cRootLayer::removeView( cView *pView )
{
for( cViewList::iterator i = m_views.begin(); i != m_views.end(); ++ i )
{
if( *i == pView )
{
m_views.erase( i );
break;
}
}
}
void cRootLayer::onCreate()
{
LayerParams lpBars = { eChildBars, { 0, 0, 1, 1 }, 0 };
CComObject< cBarLayer > *pBars;
CComObject< cBarLayer >::CreateInstance( &pBars );
m_pBars = pBars;
m_pSite->CreateChild( &lpBars, pBars );
LayerParams lpPanel = { eChildPanel, { 0, 0, 0, 0 }, 0 };
CComObject< cPanel > *pPanel;
CComObject< cPanel >::CreateInstance( &pPanel );
m_pPanel = pPanel;
m_pSite->CreateChild( &lpPanel, pPanel );
m_pPanel->putref_Sink( this );
}
void cRootLayer::onDestroy()
{
m_pBars.Release();
m_pPanel.Release();
}
STDMETHODIMP cRootLayer::CreateView(ViewParams *pParams, ILayer *pLayer, IView **ppView)
{
// First create the view object
CComObject< cView > *pView;
CComObject< cView >::CreateInstance( &pView );
pView->m_pRoot = this;
pView->m_nViewID = m_nNextViewID ++;
pView->m_strTitle = pParams->label;
pView->m_nIcon = pParams->icon;
pView->m_nIconModule = pParams->iconLibrary;
pView->m_nLeft = pParams->left;
pView->m_nTop = pParams->top;
pView->m_nWidth = pParams->width;
pView->m_nHeight = pParams->height;
addView( pView, pLayer );
*ppView = pView;
pView->AddRef();
return S_OK;
}
STDMETHODIMP cRootLayer::SelectBar(long nID)
{
// We are given the Bar ID, find the matching view
for( cViewList::iterator i = m_views.begin(); i != m_views.end(); ++ i )
{
if( ( *i )->m_nViewID == nID )
{
long nPrevActive;
m_pPanel->get_ActiveView( &nPrevActive );
if( nPrevActive != nID )
{
ViewParams p = { ( *i )->m_nIcon, ( *i )->m_nIconModule, ( *i )->m_strTitle, ( *i )->m_nLeft, ( *i )->m_nTop, ( *i )->m_nWidth, ( *i )->m_nHeight };
m_pPanel->ActivateView( ( *i )->m_nViewID, &p );
( *i )->Fire_Activate();
}
else
{
( *i )->Deactivate();
}
return S_OK;
}
}
// Invalid return value
return E_INVALIDARG;
}
STDMETHODIMP cRootLayer::LoadView(BSTR strXML, IView **ppView)
{
CComObject< cView > *pView;
CComObject< cView >::CreateInstance( &pView );
CComPtr< IUnknown > pRootControl;
pView->m_pRoot = this;
pView->m_nViewID = m_nNextViewID ++;
pView->loadSchema( strXML, &pRootControl );
ViewParams vp = { pView->m_nIcon, pView->m_nIconModule, pView->m_strTitle, pView->m_nLeft, pView->m_nTop, pView->m_nWidth, pView->m_nHeight };
m_views.push_back( pView );
*ppView = pView;
pView->AddRef();
// Next, make the bar entry
m_pBars->AddBar( pView->m_nViewID, &vp );
// Last, create all the controls
m_pPanel->LoadView( pView->m_nViewID, pView, pRootControl );
return S_OK;
}
STDMETHODIMP cRootLayer::PanelDeactivate(long nViewID)
{
// Find the view of our desires and fire it's hide message
for( cViewList::iterator i = m_views.begin(); i != m_views.end(); ++ i )
{
if( ( *i )->m_nViewID == nViewID )
( *i )->Fire_Deactivate();
}
return S_OK;
}
STDMETHODIMP cRootLayer::LoadViewObject(IUnknown *pSchema, IView **ppView)
{
CComObject< cView > *pView;
CComObject< cView >::CreateInstance( &pView );
CComPtr< IUnknown > pRootControl;
pView->m_pRoot = this;
pView->m_nViewID = m_nNextViewID ++;
pView->loadSchemaObject( pSchema, &pRootControl );
ViewParams vp = { pView->m_nIcon, pView->m_nIconModule, pView->m_strTitle, pView->m_nLeft, pView->m_nTop, pView->m_nWidth, pView->m_nHeight };
m_views.push_back( pView );
*ppView = pView;
pView->AddRef();
// Next, make the bar entry
m_pBars->AddBar( pView->m_nViewID, &vp );
// Last, create all the controls
m_pPanel->LoadView( pView->m_nViewID, pView, pRootControl );
return S_OK;
}

View file

@ -0,0 +1,61 @@
// RootLayer.h : Declaration of the cRootLayer
#ifndef __ROOTLAYER_H_
#define __ROOTLAYER_H_
#include "resource.h" // main symbols
// This special layer implements no sinks, it is merely a container
// layer for the bar manager and the window manager - it server no other purpose
// than to forward event on and avoid redundant looping in the manager object.
#include "SinkImpl.h"
class cView;
/////////////////////////////////////////////////////////////////////////////
// cRootLayer
class ATL_NO_VTABLE cRootLayer :
public CComObjectRootEx<CComMultiThreadModel>,
public ILayerImpl< cRootLayer >,
public IPanelSink,
public cNoEventsImpl,
public IRootLayer
{
public:
cRootLayer()
: m_nNextViewID( 1000 )
{
}
CComPtr< IBarManager > m_pBars;
CComPtr< IPanel > m_pPanel;
typedef std::list< cView * > cViewList;
cViewList m_views;
long m_nNextViewID;
void addView( cView *pView, ILayer *pRootLayer );
void removeView( cView *pView );
void onCreate();
void onDestroy();
BEGIN_COM_MAP(cRootLayer)
COM_INTERFACE_ENTRY(IPanelSink)
COM_INTERFACE_ENTRY(IRootLayer)
COM_INTERFACE_ENTRY(ILayer)
END_COM_MAP()
public:
// IRootLayer Methods
STDMETHOD(CreateView)(ViewParams *pParams, ILayer *pLayer, /*[out, retval]*/ IView **ppView);
STDMETHOD(SelectBar)(long nID);
STDMETHOD(LoadView)(BSTR strXML, /*[out, retval]*/ IView **ppView);
STDMETHOD(LoadViewObject)(IUnknown *pSchema, /*[out, retval]*/ IView **ppView);
// IPanelSink Methods
STDMETHOD(PanelDeactivate)( long nViewID );
};
#endif //__ROOTLAYER_H_

View file

@ -0,0 +1,410 @@
// View.cpp : Implementation of cView
#include "stdafx.h"
#include "Inject.h"
#include "View.h"
#include "RootLayer.h"
#include "Manager.h"
#include "InjectApi.h"
/////////////////////////////////////////////////////////////////////////////
// cView
cView::~cView()
{
m_pRoot->m_pBars->RemoveBar( m_nViewID );
m_pRoot->m_pPanel->RemoveView( m_nViewID );
m_pRoot->removeView( this );
}
void cView::loadSchema( BSTR strSchema, IUnknown **ppRootControl )
{
USES_CONVERSION;
_ASSERTE( strSchema != NULL );
// Create a new XML document and load this up
MSXML::IXMLDOMDocumentPtr pDoc;
pDoc.CreateInstance( __uuidof( MSXML::DOMDocument ), NULL, CLSCTX_INPROC_SERVER );
VARIANT_BOOL bSuccess;
if( strSchema[ 0 ] == OLESTR( '<' ) )
bSuccess = pDoc->loadXML( strSchema );
else
{
// Load from a file source
pDoc->async = VARIANT_FALSE;
TCHAR szPath[ MAX_PATH ];
bSuccess = pDoc->load( ::InjectMapPath( eInjectPathAgent, OLE2T( strSchema ), szPath ) );
}
if( !bSuccess )
{
USES_CONVERSION;
// The document failed to load, get the error info for posterity
MSXML::IXMLDOMParseErrorPtr pErr = pDoc->parseError;
long nCode = pErr->errorCode;
long nFilePos = pErr->filepos;
long nLine = pErr->line;
long nLinePos = pErr->linepos;
_bstr_t strReason = pErr->reason;
_bstr_t strText = pErr->srcText;
TCHAR szError[ 1024 ];
::_stprintf( szError, _T( "0x%08X (%i, %i): %s" ),
nCode, nLine, nLinePos, OLE2T( strReason ) );
::MessageBox( cManager::_p->m_hMain, szError, _T( "XML Parse Error" ), MB_ICONERROR | MB_OK );
// Give the user a chance to break and look at this lovely info
_ASSERTE( FALSE );
return;
}
// Get the root element and check it out
loadSchemaObject( pDoc->documentElement, ppRootControl );
}
void cView::loadSchemaObject( IUnknown *pObject, IUnknown **ppRootControl )
{
MSXML::IXMLDOMElementPtr pRoot = pObject;
_ASSERTE( pRoot->tagName == _bstr_t( _T( "view" ) ) );
// Get the view parameters
_variant_t vIconModule = pRoot->getAttribute( _T( "iconlibrary" ) ),
vIcon = pRoot->getAttribute( _T( "icon" ) ),
vTitle = pRoot->getAttribute( _T( "title" ) ),
vLeft = pRoot->getAttribute( _T( "left" ) ),
vTop = pRoot->getAttribute( _T( "top" ) ),
vWidth = pRoot->getAttribute( _T( "width" ) ),
vHeight = pRoot->getAttribute( _T( "height" ) );
// We *must* have a title
_ASSERTE( vTitle.vt == VT_BSTR );
// Fill this into a view param
_ASSERTE( vIcon.vt != VT_NULL );
m_nIcon = ( vIcon.vt != VT_NULL ) ? static_cast< long >( vIcon ) + 0x06000000 : 0;
if( vIconModule.vt == VT_BSTR )
cManager::_p->LoadResourceModule( vIconModule.bstrVal, &m_nIconModule );
else
m_nIconModule = 0;
if(vLeft.vt == VT_NULL)
m_nLeft = 0;
else
m_nLeft = static_cast< long >(vLeft);
if(vTop.vt == VT_NULL)
m_nTop = 70;
else
m_nTop = static_cast< long >(vTop);
if(vWidth.vt == VT_NULL)
m_nWidth = 180;
else
m_nWidth = static_cast< long >(vWidth);
if(vHeight.vt == VT_NULL)
{
SIZE szScreen;
cManager::_p->GetScreenSize( &szScreen );
m_nHeight = szScreen.cy/2;
}
else
m_nHeight = static_cast< long >(vHeight);
m_strTitle = vTitle.bstrVal;
// The properly made schema should have a single control child
MSXML::IXMLDOMElementPtr pControl = pRoot->selectSingleNode( _T( "control" ) );
_ASSERTE( pControl.GetInterfacePtr() != NULL );
pControl->QueryInterface( ppRootControl );
}
STDMETHODIMP cView::get_Control(BSTR strName, IControl **pVal)
{
_ASSERTE( strName != NULL );
_ASSERTE( pVal != NULL );
// Search for a matching control name
for( cNamedControlList::iterator i = m_controls.begin(); i != m_controls.end(); ++ i )
{
if( i->m_strName == _bstr_t( strName ) )
{
*pVal = i->m_pControl;
( *pVal )->AddRef();
return S_OK;
}
}
// The name was not found
return E_INVALIDARG;
}
STDMETHODIMP cView::putref_Control(BSTR strName, IControl *newVal)
{
_ASSERTE( strName != NULL );
// First look for a matching name
for( cNamedControlList::iterator i = m_controls.begin(); i != m_controls.end(); ++ i )
{
if( i->m_strName == _bstr_t( strName ) )
{
if( newVal == NULL )
m_controls.erase( i );
else
i->m_pControl = newVal;
return S_OK;
}
}
if( newVal == NULL )
// No value to set
return S_OK;
// Add in a new record
cNamedControl nc;
nc.m_strName = strName;
nc.m_pControl = newVal;
m_controls.push_back( nc );
return S_OK;
}
STDMETHODIMP cView::LoadControl(ILayerSite *pParent, long nID, IUnknown *pSource, long *pAssignedID)
{
// Usual parameter validation
_ASSERTE( pParent != NULL );
_ASSERTE( pSource != NULL );
_ASSERTE( pAssignedID != NULL );
MSXML::IXMLDOMElementPtr pElement = pSource;
// Make sure we're starting from the correct tag name
_ASSERTE( pElement->tagName == _bstr_t( _T( "control" ) ) );
// Get the progid and make an instance
_variant_t strProgID = pElement->getAttribute( _T( "progid" ) );
_ASSERTE( strProgID.vt == VT_BSTR );
CLSID clsid;
HRESULT hRes = ::CLSIDFromProgID( strProgID.bstrVal, &clsid );
_ASSERTE( SUCCEEDED( hRes ) );
CComPtr< ILayer > pChildLayer;
hRes = ::CoCreateInstance( clsid, NULL, CLSCTX_INPROC_SERVER, IID_ILayer,
reinterpret_cast< void ** >( &pChildLayer ) );
_ASSERTE( SUCCEEDED( hRes ) );
// Get some position metrics - note, these are optional and will be
// loaded with 0s - this is for cases when the control is formatted
// entirely by the parent
_variant_t vLeft = pElement->getAttribute( _T( "left" ) ),
vTop = pElement->getAttribute( _T( "top" ) ),
vWidth = pElement->getAttribute( _T( "width" ) ),
vHeight = pElement->getAttribute( _T( "height" ) ),
vUnclipped = pElement->getAttribute( _T( "unclipped" ) ),
vID = pElement->getAttribute( _T( "ID" ) );
long nRealID = ( vID.vt == VT_NULL ) ? nID : static_cast< long >( vID );
*pAssignedID = nRealID;
POINT pt = { ( vLeft.vt != VT_NULL ) ? static_cast< long >( vLeft ) : 0,
( vTop.vt != VT_NULL ) ? static_cast< long >( vTop ) : 0 };
LayerParams lp = { nRealID, { pt.x, pt.y, pt.x + ( ( vWidth.vt != VT_NULL ) ? static_cast< long >( vWidth ) : 0 ),
pt.y + ( ( vHeight.vt != VT_NULL ) ? static_cast< long >( vHeight ) : 0 ) },
( vUnclipped.vt != VT_NULL ) ? 0 : eRenderClipped };
pParent->CreateChild( &lp, pChildLayer );
// Check if this child is named
_variant_t vName = pElement->getAttribute( _T( "name" ) );
if( vName.vt == VT_BSTR )
{
// Add the named control
CComPtr< IControl > pControl;
pChildLayer->QueryInterface( &pControl );
putref_Control( vName.bstrVal, pControl );
}
// Ok, the child is made - trick it into loading it's own parameters
CComPtr< ILayerSchema > pSchema;
if( SUCCEEDED( pChildLayer->QueryInterface( &pSchema ) ) )
pSchema->SchemaLoad( this, pSource );
return S_OK;
}
STDMETHODIMP cView::LoadSchema(BSTR strXMLSchema)
{
long nPreviousView;
m_pRoot->m_pPanel->get_ActiveView( &nPreviousView );
m_pRoot->m_pPanel->RemoveView( m_nViewID );
CComPtr< IUnknown > pRootControl;
loadSchema( strXMLSchema, &pRootControl );
// Set the bar params
ViewParams vp = { m_nIcon, m_nIconModule, m_strTitle, m_nLeft, m_nTop, m_nWidth, m_nHeight };
m_pRoot->m_pBars->put_Bar( m_nViewID, &vp );
// Last, create all the controls
m_pRoot->m_pPanel->LoadView( m_nViewID, this, pRootControl );
if( nPreviousView == m_nViewID )
// Reactivate the view
m_pRoot->SelectBar( m_nViewID );
return S_OK;
}
STDMETHODIMP cView::get_Title(BSTR *pVal)
{
USES_CONVERSION;
*pVal = OLE2BSTR( m_strTitle );
return S_OK;
}
STDMETHODIMP cView::put_Title(BSTR newVal)
{
_ASSERTE( newVal != NULL );
m_strTitle = newVal;
long nActiveView;
m_pRoot->m_pPanel->get_ActiveView( &nActiveView );
ViewParams vp = { m_nIcon, m_nIconModule, m_strTitle, m_nLeft, m_nTop, m_nWidth, m_nHeight };
m_pRoot->m_pBars->put_Bar( m_nViewID, &vp );
// if( nActiveView == m_nViewID )
// Reload the view
// m_pRoot->SelectBar( m_nViewID );
return S_OK;
}
STDMETHODIMP cView::Alert()
{
return S_OK;
}
STDMETHODIMP cView::SetIcon(long icon, VARIANT iconlibrary)
{
USES_CONVERSION;
m_nIcon = icon;
switch( iconlibrary.vt )
{
case VT_ERROR:
case VT_EMPTY:
case VT_NULL:
m_nIconModule = 0;
break;
case VT_BSTR:
m_nIconModule = reinterpret_cast< long >( ::GetModuleHandle( OLE2T( iconlibrary.bstrVal ) ) );
break;
default:
// Try and convert everything else to a number
try
{
_variant_t v = iconlibrary;
m_nIconModule = v;
}
catch( ... )
{
m_nIconModule = 0;
return E_INVALIDARG;
}
break;
}
long nActiveView;
m_pRoot->m_pPanel->get_ActiveView( &nActiveView );
ViewParams vp = { m_nIcon, m_nIconModule, m_strTitle, m_nLeft, m_nTop, m_nWidth, m_nHeight};
m_pRoot->m_pBars->put_Bar( m_nViewID, &vp );
if( nActiveView == m_nViewID )
// Reload the view
m_pRoot->SelectBar( m_nViewID );
return S_OK;
}
STDMETHODIMP cView::Activate()
{
long nActiveView;
m_pRoot->m_pPanel->get_ActiveView( &nActiveView );
if (nActiveView != m_nViewID)
{
m_pRoot->SelectBar( m_nViewID );
}
return S_OK;
}
STDMETHODIMP cView::Deactivate()
{
m_pRoot->m_pPanel->Deactivate();
if(cManager::_p->m_pKeyboard!=NULL)
{
cManager::_p->m_pKeyboard->sendKeyboardEndCapture( VARIANT_TRUE );
cManager::_p->m_pKeyboard=NULL;
}
return S_OK;
}
STDMETHODIMP cView::put_Position(LPRECT pVal)
{
long nActiveView;
m_pRoot->m_pPanel->get_ActiveView( &nActiveView );
if( nActiveView == m_nViewID )
{
m_nLeft = pVal->left;
m_nTop = pVal->top;
m_nWidth = pVal->right;
m_nHeight = pVal->bottom;
ViewParams vp = {m_nIcon, m_nIconModule, m_strTitle, m_nLeft, m_nTop, m_nWidth, m_nHeight};
m_pRoot->m_pPanel->ActivateView(m_nViewID, &vp );
Fire_Activate();
}
return S_OK;
}
STDMETHODIMP cView::get_Position(LPRECT pVal)
{
pVal->left = m_nLeft;
pVal->top = m_nTop;
pVal->right = m_nWidth;
pVal->bottom = m_nHeight;
return S_OK;
}

View file

@ -0,0 +1,81 @@
// View.h : Declaration of the cView
#ifndef __VIEW_H_
#define __VIEW_H_
#include "resource.h" // main symbols
#include "InjectCP.h"
#include "SinkImpl.h"
class cRootLayer;
/////////////////////////////////////////////////////////////////////////////
// cView
class ATL_NO_VTABLE cView :
public CComObjectRootEx<CComMultiThreadModel>,
public IConnectionPointContainerImpl<cView>,
public IProvideClassInfo2Impl< &CLSID_View, &IID_IViewDisp, &LIBID_DecalPlugins >,
public IDispatchImpl< IView, &IID_IViewDisp, &LIBID_DecalPlugins >,
public CProxyIViewEvents< cView >
{
public:
cView()
{
}
~cView();
cRootLayer *m_pRoot;
_bstr_t m_strTitle;
long m_nIcon;
long m_nIconModule;
long m_nViewID;
long m_nWidth;
long m_nHeight;
long m_nTop;
long m_nLeft;
// Named controls
struct cNamedControl
{
_bstr_t m_strName;
CComPtr< IControl > m_pControl;
};
typedef std::list< cNamedControl > cNamedControlList;
cNamedControlList m_controls;
void loadSchema( BSTR strText, IUnknown **ppRootControl );
void loadSchemaObject( IUnknown *pObject, IUnknown **ppRootControl );
BEGIN_COM_MAP(cView)
COM_INTERFACE_ENTRY(IView)
COM_INTERFACE_ENTRY(IViewDisp)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IProvideClassInfo)
COM_INTERFACE_ENTRY(IProvideClassInfo2)
COM_INTERFACE_ENTRY(IConnectionPointContainer)
COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
END_COM_MAP()
BEGIN_CONNECTION_POINT_MAP(cView)
CONNECTION_POINT_ENTRY(DIID_IViewEvents)
END_CONNECTION_POINT_MAP()
public:
// IView Methods
STDMETHOD(SetIcon)(long icon, /*[optional]*/ VARIANT iconlibrary);
STDMETHOD(Activate)();
STDMETHOD(Alert)();
STDMETHOD(get_Title)(/*[out, retval]*/ BSTR *pVal);
STDMETHOD(put_Title)(/*[in]*/ BSTR newVal);
STDMETHOD(LoadSchema)(BSTR strXMLSchema);
STDMETHOD(LoadControl)(ILayerSite *pParent, long nID, IUnknown *pSource, long *pAssignedID);
STDMETHOD(get_Control)(BSTR strName, /*[out, retval]*/ IControl * *pVal);
STDMETHOD(putref_Control)(BSTR strName, /*[in]*/ IControl * newVal);
STDMETHOD(Deactivate)();
STDMETHOD(put_Position)(/*[in]*/ LPRECT pVal);
STDMETHOD(get_Position)(/*[out, retval]*/ LPRECT pVal);
};
#endif //__VIEW_H_

View file

@ -0,0 +1,91 @@
// EventsImpl.h
// Declaration of helper class for implementing plugins
#ifndef _EVENTSIMPL_H_
#define _EVENTSIMPL_H_
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
template< UINT nID, class cImpl, const IID *pIID, const GUID *pLIBID >
class IControlEventsImpl
: public IDispEventImpl< nID, cImpl, pIID, pLIBID, 1, 0 >
{
protected:
void advise( IUnknown *pUnk )
{
HRESULT hRes = DispEventAdvise( pUnk );
_ASSERTE( SUCCEEDED( hRes ) );
}
void unadvise( IUnknown *pUnk )
{
HRESULT hRes = DispEventUnadvise( pUnk );
_ASSERTE( SUCCEEDED( hRes ) );
}
};
#define DISPID_DESTROY 1
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
template< UINT nID, class cImpl >
class ICommandEventsImpl
: public IControlEventsImpl< nID, cImpl, &DIID_ICommandEvents, &LIBID_DecalPlugins >
{
};
#define DISPID_HIT 2
#define DISPID_UNHIT 3
#define DISPID_ACCEPTED 4
#define DISPID_CANCELED 5
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
template< UINT nID, class cImpl >
class IPagerEventsImpl
: public IControlEventsImpl< nID, cImpl, &DIID_IPagerEvents, &LIBID_DecalPlugins >
{
};
#define DISPID_CHANGE 6
#define DISPID_GETNEXTPOSITION 7
#define DISPID_UPDATE_POSITION 6
#define DISPID_GET_NEXT_POSITION 7
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
template< UINT nID, class cImpl >
class IViewEventsImpl
: public IControlEventsImpl< nID, cImpl, &DIID_IViewEvents, &LIBID_DecalPlugins >
{
};
#define DISPID_ACTIVATE 8
#define DISPID_DEACTIVATE 9
#define DISPID_SIZE 13
#define DISPID_SIZING 14
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
template< UINT nID, class cImpl >
class IInputEventsImpl
: public IControlEventsImpl< nID, cImpl, &DIID_IInputEvents, &LIBID_DecalPlugins >
{
};
#define DISPID_BEGIN 10
#define DISPID_END 11
#define DISPID_PAUSE 12
#endif // _EVENTSIMPL_H_

Binary file not shown.

8563
Native/Inject/Attic/Inject.h Normal file

File diff suppressed because it is too large Load diff

Binary file not shown.

View file

@ -0,0 +1,71 @@
<html>
<body>
<pre>
<h1>Build Log</h1>
<h3>
--------------------Configuration: Inject - Win32 Release MinDependency--------------------
</h3>
<h3>Command Lines</h3>
Creating temporary file "C:\DOCUME~1\AARONP~1\LOCALS~1\Temp\RSP5AC.tmp" with contents
[
/nologo /MD /W3 /GX /Zd /O1 /D "INJECT_IMPL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /Fp"ReleaseMinDependency/Inject.pch" /Yu"stdafx.h" /Fo"ReleaseMinDependency/" /Fd"ReleaseMinDependency/" /FD /c
"E:\Decal\Source\Inject\Canvas.cpp"
]
Creating command line "cl.exe @C:\DOCUME~1\AARONP~1\LOCALS~1\Temp\RSP5AC.tmp"
Creating temporary file "C:\DOCUME~1\AARONP~1\LOCALS~1\Temp\RSP5AD.tmp" with contents
[
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ddraw.lib winmm.lib ws2_32.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"..\Release/Inject.pdb" /debug /machine:I386 /def:".\Inject.def" /out:"..\Release/Inject.dll" /implib:"..\Release/Inject.lib" /pdbtype:sept
.\ReleaseMinDependency\BarLayer.obj
.\ReleaseMinDependency\Button.obj
.\ReleaseMinDependency\Canvas.obj
.\ReleaseMinDependency\DatFile.obj
.\ReleaseMinDependency\Direct3DHook.obj
.\ReleaseMinDependency\DirectDrawHook.obj
.\ReleaseMinDependency\DirectDrawSurfaceHook.obj
.\ReleaseMinDependency\FontCache.obj
.\ReleaseMinDependency\Guids.obj
.\ReleaseMinDependency\IconCache.obj
.\ReleaseMinDependency\Image.obj
.\ReleaseMinDependency\Inject.obj
.\ReleaseMinDependency\InputBuffer.obj
.\ReleaseMinDependency\LayerSite.obj
.\ReleaseMinDependency\Manager.obj
.\ReleaseMinDependency\MaterialHook.obj
.\ReleaseMinDependency\Message.obj
.\ReleaseMinDependency\MessageLoaders.obj
.\ReleaseMinDependency\MessageParsers.obj
.\ReleaseMinDependency\MessageStruct.obj
.\ReleaseMinDependency\MessageVector.obj
.\ReleaseMinDependency\Pager.obj
.\ReleaseMinDependency\Panel.obj
.\ReleaseMinDependency\ProtocolStack.obj
.\ReleaseMinDependency\RootLayer.obj
.\ReleaseMinDependency\SimpleBar.obj
.\ReleaseMinDependency\SinkImpl.obj
.\ReleaseMinDependency\SolidImage.obj
.\ReleaseMinDependency\StdAfx.obj
.\ReleaseMinDependency\View.obj
.\ReleaseMinDependency\Inject.res
]
Creating command line "link.exe @C:\DOCUME~1\AARONP~1\LOCALS~1\Temp\RSP5AD.tmp"
Creating temporary file "C:\DOCUME~1\AARONP~1\LOCALS~1\Temp\RSP5AE.bat" with contents
[
@echo off
regsvr32 /s /c "\Decal\Source\Release\Inject.dll"
echo regsvr32 exec. time > ".\..\Release\regsvr32.trg"
]
Creating command line "C:\DOCUME~1\AARONP~1\LOCALS~1\Temp\RSP5AE.bat"
Compiling...
Canvas.cpp
Linking...
Creating library ..\Release/Inject.lib and object ..\Release/Inject.exp
<h3>Output Window</h3>
Performing registration
<h3>Results</h3>
Inject.dll - 0 error(s), 0 warning(s)
</pre>
</body>
</html>

Binary file not shown.

View file

@ -0,0 +1,448 @@
#pragma warning( disable: 4049 ) /* more than 64k source lines */
/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */
/* link this file in with the server and any clients */
/* File created by MIDL compiler version 5.03.0280 */
/* at Sat Aug 18 01:06:36 2001
*/
/* Compiler settings for E:\Decal\Source\Inject\Inject.idl:
Oicf (OptLev=i2), W1, Zp8, env=Win32 (32b run), ms_ext, c_ext
error checks: allocation ref bounds_check enum stub_data
VC __declspec() decoration level:
__declspec(uuid()), __declspec(selectany), __declspec(novtable)
DECLSPEC_UUID(), MIDL_INTERFACE()
*/
//@@MIDL_FILE_HEADING( )
#if !defined(_M_IA64) && !defined(_M_AXP64)
#ifdef __cplusplus
extern "C"{
#endif
#include <rpc.h>
#include <rpcndr.h>
#ifdef _MIDL_USE_GUIDDEF_
#ifndef INITGUID
#define INITGUID
#include <guiddef.h>
#undef INITGUID
#else
#include <guiddef.h>
#endif
#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8)
#else // !_MIDL_USE_GUIDDEF_
#ifndef __IID_DEFINED__
#define __IID_DEFINED__
typedef struct _IID
{
unsigned long x;
unsigned short s1;
unsigned short s2;
unsigned char c[8];
} IID;
#endif // __IID_DEFINED__
#ifndef CLSID_DEFINED
#define CLSID_DEFINED
typedef IID CLSID;
#endif // CLSID_DEFINED
#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
#endif !_MIDL_USE_GUIDDEF_
MIDL_DEFINE_GUID(IID, IID_IManager,0xBC63C4A7,0xBE01,0x400D,0x90,0x8D,0x07,0x47,0xB0,0x6C,0x80,0x62);
MIDL_DEFINE_GUID(IID, IID_IPluginSite,0x702D3901,0xC13A,0x448e,0x88,0x71,0xEC,0xDC,0x8B,0xC8,0xD0,0x79);
MIDL_DEFINE_GUID(IID, IID_IPluginSink,0xD216BA6C,0xD328,0x4765,0xB4,0x0A,0x9B,0xC5,0x7C,0x96,0xF7,0x5E);
MIDL_DEFINE_GUID(IID, IID_IPlugin,0xBA3E677F,0x8E44,0x4829,0x98,0x2E,0x58,0xBB,0xBC,0x5C,0x5F,0x9B);
MIDL_DEFINE_GUID(IID, IID_IControl,0x996B377C,0x1953,0x4db1,0xAA,0xC1,0x15,0x7F,0x72,0x59,0x2D,0x3E);
MIDL_DEFINE_GUID(IID, DIID_IControlEvents,0x2FEBCBC3,0x488C,0x444f,0xAD,0x08,0x5D,0x30,0x97,0xD2,0xD1,0xED);
MIDL_DEFINE_GUID(IID, IID_ILayer,0x0D63504F,0xDEEF,0x4a2d,0x97,0x42,0x28,0xDD,0x1B,0xAD,0xDA,0x7C);
MIDL_DEFINE_GUID(IID, IID_ILayerRender,0xD1C71B85,0x62C2,0x42a3,0xAE,0x2E,0x4B,0xF5,0xA6,0xBE,0x17,0x84);
MIDL_DEFINE_GUID(IID, IID_ILayerSite,0x5B7E9D99,0xBB3A,0x475D,0x84,0x2D,0x43,0xEB,0xEA,0x82,0x84,0xEA);
MIDL_DEFINE_GUID(IID, IID_IBarManager,0xE4CCDC92,0x8658,0x4caa,0x89,0x55,0xFB,0x89,0x1D,0x5B,0xDC,0xF7);
MIDL_DEFINE_GUID(IID, IID_IIconCache,0xDEDCD5AA,0xF6CA,0x4DA5,0xA6,0x57,0xE8,0x2F,0x12,0x6A,0xBB,0xCD);
MIDL_DEFINE_GUID(IID, IID_IImageCacheDisp,0xF88548BC,0xD11E,0x4ac2,0x9A,0x27,0x36,0x07,0x00,0x4D,0x35,0x9F);
MIDL_DEFINE_GUID(IID, IID_IImageCache,0xBE566CEC,0x6881,0x481C,0xA1,0x46,0x9F,0x5A,0x32,0x57,0x6B,0xE6);
MIDL_DEFINE_GUID(IID, IID_IFontCacheDisp,0x9394E96D,0x2B29,0x4c29,0xAF,0x3E,0xDB,0x5C,0x47,0x61,0x22,0xDB);
MIDL_DEFINE_GUID(IID, IID_IFontCache,0x12ECCB0F,0x36A6,0x451C,0xB0,0x86,0x13,0x06,0xB7,0x4A,0xAE,0xC2);
MIDL_DEFINE_GUID(IID, IID_ISimpleBar,0x4A2D87CD,0xBFB4,0x4723,0xB9,0x59,0xFF,0xF3,0xFD,0xD4,0x92,0x78);
MIDL_DEFINE_GUID(IID, IID_ILayerMouse,0x5014E0B2,0x9156,0x412c,0x94,0x6D,0x9D,0x4B,0xAA,0x9F,0x4C,0x51);
MIDL_DEFINE_GUID(IID, IID_ILayerSchema,0x829E0FB2,0xD0B5,0x4814,0xBC,0xF9,0x6E,0xCF,0xA0,0x6C,0x9A,0xED);
MIDL_DEFINE_GUID(IID, IID_IButton,0x0F5765A4,0x9F83,0x4077,0x88,0x84,0x6C,0xBD,0xDC,0xE3,0x48,0xF7);
MIDL_DEFINE_GUID(IID, DIID_ICommandEvents,0xF029D3A1,0x29AF,0x45ef,0x92,0x7E,0x72,0x9F,0xED,0xD8,0x74,0x03);
MIDL_DEFINE_GUID(IID, IID_IPager,0xBD9FC464,0xC0D8,0x4823,0x82,0x55,0xE8,0x18,0xF8,0x83,0x6B,0x08);
MIDL_DEFINE_GUID(IID, DIID_IPagerEvents,0x7499EB61,0x6992,0x4e21,0x8A,0x55,0xCF,0x44,0xD4,0x4C,0x0A,0x07);
MIDL_DEFINE_GUID(IID, IID_IPanel,0x2B52B5CB,0x9E10,0x4238,0x8F,0x62,0xA5,0x01,0x40,0x6E,0x3E,0xAB);
MIDL_DEFINE_GUID(IID, IID_IPanelSink,0x85D70924,0x917D,0x41bb,0x99,0x5D,0xC4,0x0E,0x6A,0xB2,0x1C,0x71);
MIDL_DEFINE_GUID(IID, IID_ICanvas,0x9241862D,0xBA71,0x4317,0x81,0x66,0x3A,0x3E,0x61,0xCE,0x3E,0x5F);
MIDL_DEFINE_GUID(IID, IID_IViewDisp,0xF3B54A0C,0x61B9,0x4B7A,0x9F,0xD8,0x82,0xB0,0x47,0x7F,0xB7,0xD9);
MIDL_DEFINE_GUID(IID, IID_IView,0xA2AE18B7,0x85C9,0x451c,0x8C,0xC3,0xD0,0xFF,0xE6,0xB8,0x6E,0xEB);
MIDL_DEFINE_GUID(IID, DIID_IViewEvents,0x4B7B19D5,0x61A2,0x4ab0,0x8B,0x1B,0x38,0x1A,0x30,0x3A,0x93,0x7F);
MIDL_DEFINE_GUID(IID, IID_IRootLayer,0xD3006096,0xB293,0x47f5,0x93,0x77,0xC1,0x2D,0xEF,0x5C,0x1D,0x34);
MIDL_DEFINE_GUID(IID, IID_IMessageMember,0x05D14E34,0x0A23,0x4A9F,0x95,0xCF,0x9D,0xB2,0x4B,0x3C,0xFB,0x9F);
MIDL_DEFINE_GUID(IID, IID_IMessage,0x23EE0804,0xEAC7,0x493B,0xBB,0x9D,0x22,0x98,0xFD,0x44,0xFF,0xA1);
MIDL_DEFINE_GUID(IID, IID_INetworkFilter,0xEEB0BE9E,0x46BD,0x493F,0x97,0xE2,0x33,0x06,0x70,0xC0,0x9F,0x59);
MIDL_DEFINE_GUID(IID, IID_ILayerKeyboard,0x7500929F,0x4251,0x4373,0xB9,0x78,0x28,0x6A,0x8A,0x8B,0xEC,0xED);
MIDL_DEFINE_GUID(IID, IID_ILayerPopup,0x22072A97,0xE5E6,0x4d91,0xA3,0x44,0x80,0x72,0x35,0xBF,0xA5,0xD8);
MIDL_DEFINE_GUID(IID, IID_ILayerTimer,0x5D6B8A1B,0x321A,0x479f,0x93,0x47,0x55,0x72,0x5B,0xDA,0x3D,0xA9);
MIDL_DEFINE_GUID(IID, IID_IWindowsMessageSink,0xA68BE455,0xC241,0x49c5,0x9F,0x8A,0x07,0x0E,0x4C,0xBE,0x43,0x0F);
MIDL_DEFINE_GUID(IID, IID_IBrushImage,0x50CDFD25,0x4F3B,0x4412,0x96,0xBE,0x94,0x7A,0x6C,0x7B,0x93,0xA2);
MIDL_DEFINE_GUID(IID, IID_IInputBuffer,0x634D74B8,0xAFED,0x4710,0x82,0xC9,0xB5,0x30,0x32,0x6E,0x1A,0xFA);
MIDL_DEFINE_GUID(IID, DIID_IInputEvents,0xBD33BADC,0xF909,0x4eb6,0xAD,0x15,0xB1,0x56,0x9B,0x58,0x89,0x8B);
MIDL_DEFINE_GUID(IID, IID_IInputNotify,0xE288C465,0x2DD6,0x4fcd,0x95,0xE2,0x5B,0xBC,0x1A,0x1D,0x2D,0x32);
MIDL_DEFINE_GUID(IID, LIBID_DecalPlugins,0x3559E08B,0x827E,0x4DFE,0x9D,0x33,0x35,0x67,0x24,0x68,0x49,0xCC);
MIDL_DEFINE_GUID(CLSID, CLSID_Canvas,0x91892F16,0x31A3,0x4E23,0x9C,0xFD,0x89,0xA5,0xA5,0x17,0x4A,0x59);
MIDL_DEFINE_GUID(CLSID, CLSID_PluginSite,0xB2FBD583,0xB64C,0x4dfc,0xBA,0xAA,0x34,0xB8,0xC2,0x14,0x82,0xF8);
MIDL_DEFINE_GUID(CLSID, CLSID_Layer,0x6FEA2219,0x7438,0x4f76,0x81,0x65,0xC4,0x7A,0xA0,0x60,0xD8,0x11);
MIDL_DEFINE_GUID(CLSID, CLSID_View,0x19BF46E4,0x5CB8,0x4CFC,0xA1,0x7A,0x8E,0x66,0x73,0xE6,0x0A,0xBF);
MIDL_DEFINE_GUID(CLSID, CLSID_Button,0xC22BF2FC,0xF144,0x4d17,0x9C,0x12,0xA3,0x44,0xF9,0x80,0xBB,0x17);
MIDL_DEFINE_GUID(CLSID, CLSID_Pager,0xC79E2F76,0x06F8,0x4cd0,0xA6,0x13,0x48,0x29,0x23,0x7D,0x29,0x7D);
MIDL_DEFINE_GUID(CLSID, CLSID_BrushImage,0x918C0333,0x5714,0x4C8D,0xA9,0x5C,0x2C,0x13,0x7B,0x76,0xD3,0x64);
MIDL_DEFINE_GUID(CLSID, CLSID_InputBuffer,0x2F91FC21,0x4D89,0x4B64,0x94,0xAE,0xA1,0x24,0xD5,0x45,0x63,0xAE);
#undef MIDL_DEFINE_GUID
#ifdef __cplusplus
}
#endif
#endif /* !defined(_M_IA64) && !defined(_M_AXP64)*/
#pragma warning( disable: 4049 ) /* more than 64k source lines */
/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */
/* link this file in with the server and any clients */
/* File created by MIDL compiler version 5.03.0280 */
/* at Sat Aug 18 01:06:36 2001
*/
/* Compiler settings for E:\Decal\Source\Inject\Inject.idl:
Oicf (OptLev=i2), W1, Zp8, env=Win64 (32b run,appending), ms_ext, c_ext, robust
error checks: allocation ref bounds_check enum stub_data
VC __declspec() decoration level:
__declspec(uuid()), __declspec(selectany), __declspec(novtable)
DECLSPEC_UUID(), MIDL_INTERFACE()
*/
//@@MIDL_FILE_HEADING( )
#if defined(_M_IA64) || defined(_M_AXP64)
#ifdef __cplusplus
extern "C"{
#endif
#include <rpc.h>
#include <rpcndr.h>
#ifdef _MIDL_USE_GUIDDEF_
#ifndef INITGUID
#define INITGUID
#include <guiddef.h>
#undef INITGUID
#else
#include <guiddef.h>
#endif
#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8)
#else // !_MIDL_USE_GUIDDEF_
#ifndef __IID_DEFINED__
#define __IID_DEFINED__
typedef struct _IID
{
unsigned long x;
unsigned short s1;
unsigned short s2;
unsigned char c[8];
} IID;
#endif // __IID_DEFINED__
#ifndef CLSID_DEFINED
#define CLSID_DEFINED
typedef IID CLSID;
#endif // CLSID_DEFINED
#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
#endif !_MIDL_USE_GUIDDEF_
MIDL_DEFINE_GUID(IID, IID_IManager,0xBC63C4A7,0xBE01,0x400D,0x90,0x8D,0x07,0x47,0xB0,0x6C,0x80,0x62);
MIDL_DEFINE_GUID(IID, IID_IPluginSite,0x702D3901,0xC13A,0x448e,0x88,0x71,0xEC,0xDC,0x8B,0xC8,0xD0,0x79);
MIDL_DEFINE_GUID(IID, IID_IPluginSink,0xD216BA6C,0xD328,0x4765,0xB4,0x0A,0x9B,0xC5,0x7C,0x96,0xF7,0x5E);
MIDL_DEFINE_GUID(IID, IID_IPlugin,0xBA3E677F,0x8E44,0x4829,0x98,0x2E,0x58,0xBB,0xBC,0x5C,0x5F,0x9B);
MIDL_DEFINE_GUID(IID, IID_IControl,0x996B377C,0x1953,0x4db1,0xAA,0xC1,0x15,0x7F,0x72,0x59,0x2D,0x3E);
MIDL_DEFINE_GUID(IID, DIID_IControlEvents,0x2FEBCBC3,0x488C,0x444f,0xAD,0x08,0x5D,0x30,0x97,0xD2,0xD1,0xED);
MIDL_DEFINE_GUID(IID, IID_ILayer,0x0D63504F,0xDEEF,0x4a2d,0x97,0x42,0x28,0xDD,0x1B,0xAD,0xDA,0x7C);
MIDL_DEFINE_GUID(IID, IID_ILayerRender,0xD1C71B85,0x62C2,0x42a3,0xAE,0x2E,0x4B,0xF5,0xA6,0xBE,0x17,0x84);
MIDL_DEFINE_GUID(IID, IID_ILayerSite,0x5B7E9D99,0xBB3A,0x475D,0x84,0x2D,0x43,0xEB,0xEA,0x82,0x84,0xEA);
MIDL_DEFINE_GUID(IID, IID_IBarManager,0xE4CCDC92,0x8658,0x4caa,0x89,0x55,0xFB,0x89,0x1D,0x5B,0xDC,0xF7);
MIDL_DEFINE_GUID(IID, IID_IIconCache,0xDEDCD5AA,0xF6CA,0x4DA5,0xA6,0x57,0xE8,0x2F,0x12,0x6A,0xBB,0xCD);
MIDL_DEFINE_GUID(IID, IID_IImageCacheDisp,0xF88548BC,0xD11E,0x4ac2,0x9A,0x27,0x36,0x07,0x00,0x4D,0x35,0x9F);
MIDL_DEFINE_GUID(IID, IID_IImageCache,0xBE566CEC,0x6881,0x481C,0xA1,0x46,0x9F,0x5A,0x32,0x57,0x6B,0xE6);
MIDL_DEFINE_GUID(IID, IID_IFontCacheDisp,0x9394E96D,0x2B29,0x4c29,0xAF,0x3E,0xDB,0x5C,0x47,0x61,0x22,0xDB);
MIDL_DEFINE_GUID(IID, IID_IFontCache,0x12ECCB0F,0x36A6,0x451C,0xB0,0x86,0x13,0x06,0xB7,0x4A,0xAE,0xC2);
MIDL_DEFINE_GUID(IID, IID_ISimpleBar,0x4A2D87CD,0xBFB4,0x4723,0xB9,0x59,0xFF,0xF3,0xFD,0xD4,0x92,0x78);
MIDL_DEFINE_GUID(IID, IID_ILayerMouse,0x5014E0B2,0x9156,0x412c,0x94,0x6D,0x9D,0x4B,0xAA,0x9F,0x4C,0x51);
MIDL_DEFINE_GUID(IID, IID_ILayerSchema,0x829E0FB2,0xD0B5,0x4814,0xBC,0xF9,0x6E,0xCF,0xA0,0x6C,0x9A,0xED);
MIDL_DEFINE_GUID(IID, IID_IButton,0x0F5765A4,0x9F83,0x4077,0x88,0x84,0x6C,0xBD,0xDC,0xE3,0x48,0xF7);
MIDL_DEFINE_GUID(IID, DIID_ICommandEvents,0xF029D3A1,0x29AF,0x45ef,0x92,0x7E,0x72,0x9F,0xED,0xD8,0x74,0x03);
MIDL_DEFINE_GUID(IID, IID_IPager,0xBD9FC464,0xC0D8,0x4823,0x82,0x55,0xE8,0x18,0xF8,0x83,0x6B,0x08);
MIDL_DEFINE_GUID(IID, DIID_IPagerEvents,0x7499EB61,0x6992,0x4e21,0x8A,0x55,0xCF,0x44,0xD4,0x4C,0x0A,0x07);
MIDL_DEFINE_GUID(IID, IID_IPanel,0x2B52B5CB,0x9E10,0x4238,0x8F,0x62,0xA5,0x01,0x40,0x6E,0x3E,0xAB);
MIDL_DEFINE_GUID(IID, IID_IPanelSink,0x85D70924,0x917D,0x41bb,0x99,0x5D,0xC4,0x0E,0x6A,0xB2,0x1C,0x71);
MIDL_DEFINE_GUID(IID, IID_ICanvas,0x9241862D,0xBA71,0x4317,0x81,0x66,0x3A,0x3E,0x61,0xCE,0x3E,0x5F);
MIDL_DEFINE_GUID(IID, IID_IViewDisp,0xF3B54A0C,0x61B9,0x4B7A,0x9F,0xD8,0x82,0xB0,0x47,0x7F,0xB7,0xD9);
MIDL_DEFINE_GUID(IID, IID_IView,0xA2AE18B7,0x85C9,0x451c,0x8C,0xC3,0xD0,0xFF,0xE6,0xB8,0x6E,0xEB);
MIDL_DEFINE_GUID(IID, DIID_IViewEvents,0x4B7B19D5,0x61A2,0x4ab0,0x8B,0x1B,0x38,0x1A,0x30,0x3A,0x93,0x7F);
MIDL_DEFINE_GUID(IID, IID_IRootLayer,0xD3006096,0xB293,0x47f5,0x93,0x77,0xC1,0x2D,0xEF,0x5C,0x1D,0x34);
MIDL_DEFINE_GUID(IID, IID_IMessageMember,0x05D14E34,0x0A23,0x4A9F,0x95,0xCF,0x9D,0xB2,0x4B,0x3C,0xFB,0x9F);
MIDL_DEFINE_GUID(IID, IID_IMessage,0x23EE0804,0xEAC7,0x493B,0xBB,0x9D,0x22,0x98,0xFD,0x44,0xFF,0xA1);
MIDL_DEFINE_GUID(IID, IID_INetworkFilter,0xEEB0BE9E,0x46BD,0x493F,0x97,0xE2,0x33,0x06,0x70,0xC0,0x9F,0x59);
MIDL_DEFINE_GUID(IID, IID_ILayerKeyboard,0x7500929F,0x4251,0x4373,0xB9,0x78,0x28,0x6A,0x8A,0x8B,0xEC,0xED);
MIDL_DEFINE_GUID(IID, IID_ILayerPopup,0x22072A97,0xE5E6,0x4d91,0xA3,0x44,0x80,0x72,0x35,0xBF,0xA5,0xD8);
MIDL_DEFINE_GUID(IID, IID_ILayerTimer,0x5D6B8A1B,0x321A,0x479f,0x93,0x47,0x55,0x72,0x5B,0xDA,0x3D,0xA9);
MIDL_DEFINE_GUID(IID, IID_IWindowsMessageSink,0xA68BE455,0xC241,0x49c5,0x9F,0x8A,0x07,0x0E,0x4C,0xBE,0x43,0x0F);
MIDL_DEFINE_GUID(IID, IID_IBrushImage,0x50CDFD25,0x4F3B,0x4412,0x96,0xBE,0x94,0x7A,0x6C,0x7B,0x93,0xA2);
MIDL_DEFINE_GUID(IID, IID_IInputBuffer,0x634D74B8,0xAFED,0x4710,0x82,0xC9,0xB5,0x30,0x32,0x6E,0x1A,0xFA);
MIDL_DEFINE_GUID(IID, DIID_IInputEvents,0xBD33BADC,0xF909,0x4eb6,0xAD,0x15,0xB1,0x56,0x9B,0x58,0x89,0x8B);
MIDL_DEFINE_GUID(IID, IID_IInputNotify,0xE288C465,0x2DD6,0x4fcd,0x95,0xE2,0x5B,0xBC,0x1A,0x1D,0x2D,0x32);
MIDL_DEFINE_GUID(IID, LIBID_DecalPlugins,0x3559E08B,0x827E,0x4DFE,0x9D,0x33,0x35,0x67,0x24,0x68,0x49,0xCC);
MIDL_DEFINE_GUID(CLSID, CLSID_Canvas,0x91892F16,0x31A3,0x4E23,0x9C,0xFD,0x89,0xA5,0xA5,0x17,0x4A,0x59);
MIDL_DEFINE_GUID(CLSID, CLSID_PluginSite,0xB2FBD583,0xB64C,0x4dfc,0xBA,0xAA,0x34,0xB8,0xC2,0x14,0x82,0xF8);
MIDL_DEFINE_GUID(CLSID, CLSID_Layer,0x6FEA2219,0x7438,0x4f76,0x81,0x65,0xC4,0x7A,0xA0,0x60,0xD8,0x11);
MIDL_DEFINE_GUID(CLSID, CLSID_View,0x19BF46E4,0x5CB8,0x4CFC,0xA1,0x7A,0x8E,0x66,0x73,0xE6,0x0A,0xBF);
MIDL_DEFINE_GUID(CLSID, CLSID_Button,0xC22BF2FC,0xF144,0x4d17,0x9C,0x12,0xA3,0x44,0xF9,0x80,0xBB,0x17);
MIDL_DEFINE_GUID(CLSID, CLSID_Pager,0xC79E2F76,0x06F8,0x4cd0,0xA6,0x13,0x48,0x29,0x23,0x7D,0x29,0x7D);
MIDL_DEFINE_GUID(CLSID, CLSID_BrushImage,0x918C0333,0x5714,0x4C8D,0xA9,0x5C,0x2C,0x13,0x7B,0x76,0xD3,0x64);
MIDL_DEFINE_GUID(CLSID, CLSID_InputBuffer,0x2F91FC21,0x4D89,0x4B64,0x94,0xAE,0xA1,0x24,0xD5,0x45,0x63,0xAE);
#undef MIDL_DEFINE_GUID
#ifdef __cplusplus
}
#endif
#endif /* defined(_M_IA64) || defined(_M_AXP64)*/

21230
Native/Inject/Attic/Inject_p.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,345 @@
// Message.cpp : Implementation of cMessage
#include "stdafx.h"
#include "Inject.h"
#include "Message.h"
#include "InjectApi.h"
#include "MessageLoaders.h"
#include "MessageParsers.h"
// m_pParent noahb
cMessage::cFieldList::iterator cMessage::cLoadContext::lookupField( cMessage::cMessageElement *pElement )
{
for( cLoadContext *pContext = this; pContext != NULL; pContext = pContext->m_pParent )
{
for( cFieldList::iterator i = m_pMessage->m_fields.begin() + m_dwOffset; i != m_pMessage->m_fields.end(); i += i->m_nOwns )
{
if( i->m_pSchema == pElement )
return i;
}
}
return m_pMessage->m_fields.end();
}
void cMessage::cMessageSchema::loadSchema( DWORD dwSchema )
{
TCHAR szQuery[ 255 ];
::_stprintf( szQuery, _T( "/schema/messages/message[@type='%04X']" ), dwSchema );
MSXML::IXMLDOMElementPtr pMessage = (*g_pXML)->selectSingleNode( szQuery );
if( pMessage.GetInterfacePtr() == NULL )
// Nothing here, so we create a valid but empty message
return;
cElementParser::cContext c( &m_members );
c.parseChildren( pMessage );
}
MSXML::IXMLDOMDocumentPtr * cMessage::g_pXML;
cMessage::cMessageSchemaMap cMessage::g_schema;
void cMessage::init()
{
// Load the schema
TCHAR szPath[ MAX_PATH ];
::InjectMapPath( eInjectPathAgent, _T( "messages.xml" ), szPath );
g_pXML = new MSXML::IXMLDOMDocumentPtr;
(*g_pXML).CreateInstance( __uuidof( MSXML::DOMDocument ) );
(*g_pXML)->load( szPath );
// Initialize our schema helper objects
cFieldLoader::init();
cElementParser::init();
#ifdef _DEBUG
// Load all of the message type
USES_CONVERSION;
MSXML::IXMLDOMNodeListPtr pAllMessages = (*g_pXML)->selectNodes( _T( "/schema/messages/message" ) );
for( MSXML::IXMLDOMElementPtr pMessage = pAllMessages->nextNode(); pMessage.GetInterfacePtr() != NULL; pMessage = pAllMessages->nextNode() )
{
_variant_t vType = pMessage->getAttribute( _T( "type" ) );
if( vType.vt != VT_BSTR )
{
_ASSERTE( FALSE );
continue;
}
// Get the ID from the message
long nID;
if( ::_stscanf( OLE2T( vType.bstrVal ), _T( "%X" ), &nID ) != 1 )
{
_ASSERTE( FALSE );
continue;
}
cMessageSchema ms;
ms.loadSchema( nID );
}
#endif
}
void cMessage::term()
{
g_schema.clear();
cElementParser::term();
cFieldLoader::term();
if( (*g_pXML).GetInterfacePtr() != NULL )
{
(*g_pXML).Release();
delete g_pXML;
}
}
/////////////////////////////////////////////////////////////////////////////
// cMessage
cMessage::cMessage()
: m_nType( 0 ),
m_pStartCrack( NULL ),
m_pEndCrack( NULL ),
m_pEndData( NULL ),
m_pSchema( NULL )
{
}
cMessage::cFieldList::iterator cMessage::getFieldFromElement( cMessageElement *pElement )
{
for( cFieldList::iterator i = m_fields.begin(); i != m_fields.end(); i += i->m_nOwns )
{
cMessageElement *pSchema = i->m_pSchema;
if( pSchema == pElement )
break;
}
return i;
}
void cMessage::crackMessage( BYTE *pBody, DWORD dwSize )
{
m_pStartCrack = pBody;
m_pEndData = pBody + dwSize + sizeof( DWORD );
m_nType = *reinterpret_cast< long * >( pBody );
m_fields.clear();
m_pEndCrack = m_pStartCrack + sizeof( long );
// First look up the message to see if it's already decoded
cMessageSchemaMap::iterator i_schema = g_schema.find( m_nType );
if( i_schema == g_schema.end() )
{
// Make a new one
m_pSchema = new cMessageSchema;
m_pSchema->loadSchema( m_nType );
g_schema.insert( cMessageSchemaMap::value_type( m_nType, std::auto_ptr< cMessageSchema >( m_pSchema ) ) );
}
else
m_pSchema = i_schema->second.get();
// At this point we have "a" schema of some quality
// set up the cursors
// Crack all fields right awway - testing mostly
cLoadContext context( this );
m_icracked = m_pSchema->m_members.begin();
while( m_icracked != m_pSchema->m_members.end() )
{
if( !m_icracked->get()->load( context ) )
{
// Failure to load the data, abort
m_icracked = m_pSchema->m_members.end();
break;
}
// Carry on to the next field
++ m_icracked;
}
}
void cMessage::crackAll()
{
cLoadContext context( this );
while( m_icracked != m_pSchema->m_members.end() )
{
if( !m_icracked->get()->load( context ) )
{
// Failure to load the data, abort
m_icracked = m_pSchema->m_members.end();
break;
}
// Carry on to the next field
++ m_icracked;
}
}
bool cMessage::crackMember( cFieldList::iterator i )
{
if( i != m_fields.end() )
// We aren't at the end yet
return true;
if( m_icracked == m_pSchema->m_members.end() )
// At the end now
return false;
// Attempt to crack the next field
cLoadContext context( this );
while( m_icracked != m_pSchema->m_members.end() )
{
if( !m_icracked->get()->load( context ) )
{
// Failure to load the data, abort
m_icracked = m_pSchema->m_members.end();
break;
}
// Carry on to the next field
++ m_icracked;
if( i != m_fields.end() )
return true;
}
return false;
}
STDMETHODIMP cMessage::get_Type(long *pVal)
{
_ASSERTE( pVal != NULL );
*pVal = *reinterpret_cast< long * >( m_pStartCrack );
return S_OK;
}
STDMETHODIMP cMessage::get_Data(VARIANT *pVal)
{
long nSize = m_pEndData - m_pStartCrack;
if( nSize == 0 )
{
// Special case, this message is entirely cracked - return NULL
pVal->vt = VT_NULL;
pVal->intVal = 0;
return S_OK;
}
// We've got some data to share
SAFEARRAYBOUND sab = { nSize, 0 };
SAFEARRAY *pArray = ::SafeArrayCreate( VT_UI1, 1, &sab );
::SafeArrayAllocData( pArray );
LPVOID pvData;
::SafeArrayAccessData( pArray, &pvData );
::memcpy( pvData, m_pStartCrack, nSize );
::SafeArrayUnaccessData( pArray );
pVal->vt = VT_ARRAY | VT_UI1;
pVal->parray = pArray;
return S_OK;
}
STDMETHODIMP cMessage::get_Member(VARIANT vName, VARIANT *pVal)
{
::VariantInit (pVal);
if( vName.vt == VT_BSTR )
{
_bstr_t bstrName = vName;
// Iterate over the fields and return our match - in this loop we'll do incremental
// cracking, so it's a little messy. When we hit the end, we look to see if there are
// more uncracked fields
int nFieldCount = m_fields.size();
for( int nField = 0; nField != nFieldCount; nField += m_fields[ nField ].m_nOwns )
{
if( m_fields[ nField ].m_pSchema->m_strName == bstrName )
{
m_fields[ nField ].m_pSchema->getValue( this, m_fields.begin() + nField, pVal );
return S_OK;
}
}
pVal->vt = VT_EMPTY;
return S_OK;
}
// Attempt to convert it into an index
HRESULT hRes = ::VariantChangeType( &vName, &vName, 0, VT_I4 );
if( FAILED( hRes ) )
{
_ASSERTE( FALSE );
return hRes;
}
// Check if the value is in range
long nIndex = vName.lVal;
if( nIndex < 0 )
{
_ASSERTE( nIndex >= 0 );
return E_INVALIDARG;
}
// Now, one problem is we aren't exactly sure how big the array is, so we have to walk
// through the fields, skipping appropriately
for( cFieldList::iterator i = m_fields.begin(); crackMember( i ); i += i->m_nOwns, -- nIndex )
{
if( nIndex == 0 )
{
// We've found the index - extract the value
i->m_pSchema->getValue( this, i, pVal );
return S_OK;
}
}
// The index was too high
_ASSERTE( FALSE );
return E_INVALIDARG;
}
STDMETHODIMP cMessage::get_MemberName(long nIndex, BSTR *pVal)
{
_ASSERTE( nIndex >= 0 );
_ASSERTE( pVal != NULL );
USES_CONVERSION;
for( cFieldList::iterator i = m_fields.begin(); crackMember( i ); i += i->m_nOwns, -- nIndex )
{
if( nIndex == 0 )
{
// We've found the index - extract the value
*pVal = OLE2BSTR( i->m_pSchema->m_strName );
return S_OK;
}
}
// The index was too high
return E_INVALIDARG;
}
STDMETHODIMP cMessage::get_Count(long *pVal)
{
_ASSERTE( pVal != NULL );
// We must crack them all to get a count
crackAll();
*pVal = 0;
for( cFieldList::iterator i = m_fields.begin(); i != m_fields.end(); i += i->m_nOwns, ++ ( *pVal ) );
return S_OK;
}

View file

@ -0,0 +1,148 @@
// Message.h : Declaration of the cMessage
#ifndef __MESSAGE_H_
#define __MESSAGE_H_
#include <map>
#include "resource.h" // main symbols
/////////////////////////////////////////////////////////////////////////////
// cMessage
class ATL_NO_VTABLE cMessage :
public CComObjectRootEx<CComMultiThreadModel>,
public IDispatchImpl< IMessage, &IID_IMessage, &LIBID_DecalPlugins >
{
public:
class cMessageElement;
class cField
{
public:
cMessageElement *m_pSchema;
void *m_pvData;
int m_nOwns;
CComPtr< IDispatch > m_pDisp;
};
typedef std::deque< cField > cFieldList;
class cLoadContext
{
cMessage *m_pMessage;
DWORD m_dwOffset;
cLoadContext *m_pParent;
public:
cLoadContext( cMessage *pMessage )
: m_pMessage( pMessage ),
m_dwOffset( 0 ),
m_pParent( NULL )
{
}
cLoadContext( cLoadContext *pParent )
: m_pMessage( pParent->m_pMessage ),
m_dwOffset( m_pMessage->m_fields.size() ),
m_pParent( pParent )
{
}
cFieldList::iterator lookupField( cMessageElement *pElement );
DWORD addField( cMessageElement *pElement, void *pvData )
{
cField f;
f.m_pSchema = pElement;
f.m_pvData = pvData;
f.m_nOwns = 1;
m_pMessage->m_fields.push_back( f );
return m_pMessage->m_fields.size();
}
void groupField( DWORD dwIndex )
{
m_pMessage->m_fields[ dwIndex - 1 ].m_nOwns += m_pMessage->m_fields.size() - dwIndex;
}
cMessage *getMessage()
{
return m_pMessage;
}
};
class cMessageElement
{
public:
_bstr_t m_strName;
virtual ~cMessageElement()
{
}
// Decodes from the current point and returns
// the pointer advanced by a certain number of offsets
virtual bool load( cLoadContext &context ) = 0;
virtual void getValue( cMessage *pMsg, cFieldList::iterator i, LPVARIANT pDest ) = 0;
virtual long getNumber( cFieldList::iterator i )
{
// Default implementation fails
_ASSERTE( FALSE );
return 0;
}
};
typedef std::vector< std::auto_ptr< cMessageElement > > cElementList;
class cMessageSchema
{
public:
cElementList m_members;
void loadSchema( DWORD dwSchema );
bool parseChildren( cElementList &list, MSXML::IXMLDOMElementPtr &pElement );
};
typedef std::map< DWORD, std::auto_ptr< cMessageSchema > > cMessageSchemaMap;
static MSXML::IXMLDOMDocumentPtr * g_pXML;
static cMessageSchemaMap g_schema;
static void init();
static void term();
cMessage();
cFieldList m_fields;
long m_nType;
cMessageSchema *m_pSchema;
cElementList::iterator m_icracked;
cFieldList::iterator getFieldFromElement( cMessageElement *pElement );
BYTE *m_pStartCrack,
*m_pEndCrack,
*m_pEndData;
void crackMessage( BYTE *pBody, DWORD dwSize );
void crackAll();
bool crackMember( cFieldList::iterator i );
BEGIN_COM_MAP(cMessage)
COM_INTERFACE_ENTRY(IMessage)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()
// IMessage
public:
STDMETHOD(get_Count)(/*[out, retval]*/ long *pVal);
STDMETHOD(get_MemberName)(long nIndex, /*[out, retval]*/ BSTR *pVal);
STDMETHOD(get_Member)(VARIANT vIndex, /*[out, retval]*/ VARIANT *pVal);
STDMETHOD(get_Data)(/*[out, retval]*/ VARIANT *pVal);
STDMETHOD(get_Type)(/*[out, retval]*/ long *pVal);
};
#endif //__MESSAGE_H_

View file

@ -0,0 +1,196 @@
// MessageLoaders.cpp
// Implementation of message loaders for various data types
#include "StdAfx.h"
#include "MessageLoaders.h"
// The boatload of decoding classes
template< class ValueT >
class cVariantLoader
: public cFieldLoader
{
public:
virtual void *skip( void *pData )
{
return reinterpret_cast< BYTE * >( pData ) + sizeof( ValueT );
}
virtual void *align( void *pData, void *pStart )
{
size_t nOffset = reinterpret_cast< BYTE * >( pData ) - reinterpret_cast< BYTE * >( pStart );
if( ( nOffset % sizeof( ValueT ) ) == 0 )
return pData;
return ( reinterpret_cast< BYTE * >( pStart ) + nOffset + sizeof( ValueT ) - ( nOffset % sizeof( ValueT ) ) );
}
virtual bool testValue( void *pData, void *pEnd )
{
return ( ( reinterpret_cast< BYTE * >( pData ) + sizeof( ValueT ) ) <= reinterpret_cast< BYTE * >( pEnd ) );
}
ValueT &valueOf( void *pvData )
{
return *reinterpret_cast< ValueT * >( pvData );
}
};
class cByteLoader
: public cVariantLoader< BYTE >
{
public:
virtual void getValue( void *pvData, LPVARIANT pDest )
{
pDest->vt = VT_UI1;
pDest->bVal = valueOf( pvData );
}
virtual long getNumber( void *pvData )
{
return valueOf( pvData );
}
};
class cShortLoader
: public cVariantLoader< short >
{
public:
virtual void getValue( void *pvData, LPVARIANT pDest )
{
pDest->vt = VT_I2;
pDest->iVal = valueOf( pvData );
}
virtual long getNumber( void *pvData )
{
return valueOf( pvData );
}
};
class cLongLoader
: public cVariantLoader< long >
{
public:
virtual void getValue( void *pvData, LPVARIANT pDest )
{
pDest->vt = VT_I4;
pDest->lVal = valueOf( pvData );
}
virtual long getNumber( void *pvData )
{
return valueOf( pvData );
}
};
class cFloatLoader
: public cVariantLoader< float >
{
public:
virtual void getValue( void *pvData, LPVARIANT pDest )
{
pDest->vt = VT_R4;
pDest->fltVal = valueOf( pvData );
}
};
class cDoubleLoader
: public cVariantLoader< double >
{
public:
virtual void getValue( void *pvData, LPVARIANT pDest )
{
pDest->vt = VT_R8;
pDest->dblVal = valueOf( pvData );
}
};
class cStringLoader
: public cFieldLoader
{
public:
virtual void *skip( void *pvData )
{
WORD wLength = *reinterpret_cast< WORD * >( pvData ) + sizeof( WORD );
if( ( wLength % sizeof( DWORD ) ) != 0 )
wLength += sizeof( DWORD ) - ( wLength % sizeof( DWORD ) );
return reinterpret_cast< BYTE * >( pvData ) + wLength;
}
virtual void *align( void *pvData, void * )
{
// Error, this is not a valid alignment type
_ASSERTE( FALSE );
return pvData;
}
virtual bool testValue( void *pvData, void *pvEnd )
{
WORD wLength = *reinterpret_cast< WORD * >( pvData ) + sizeof( WORD ),
wField = wLength;
if( ( wField % sizeof( DWORD ) ) != 0 )
wField += sizeof( DWORD ) - ( wField % sizeof( DWORD ) );
// It fits inside the packet, so our field isn't too big
if( ( reinterpret_cast< BYTE * >( pvData ) + wField ) > reinterpret_cast< BYTE * >( pvEnd ) )
return false;
if( *( reinterpret_cast< char * >( pvData ) + wLength - 1 ) != '\0' )
// This string is not NULL terminated
return false;
// Anything else just makes the string ugly, but won't lead to a memory
// overrun, so let them play
return true;
}
virtual void getValue( void *pvData, LPVARIANT pDest )
{
USES_CONVERSION;
pDest->vt = VT_BSTR;
pDest->bstrVal = A2BSTR( reinterpret_cast< char * >( reinterpret_cast< BYTE * >( pvData ) + sizeof( WORD ) ) );
}
};
long cFieldLoader::getNumber( void *pvData )
{
// This default implementation does not support this conversion
_ASSERTE( FALSE );
return 0;
}
cFieldLoader *cFieldLoader::lookup( const _bstr_t &strName )
{
cFieldLoaderMap::iterator i = g_primitives.find( strName );
if( i == g_primitives.end() )
return NULL;
return i->second.get();
}
void cFieldLoader::init()
{
addLoader( _T( "BYTE" ), new cByteLoader );
addLoader( _T( "WORD" ), new cShortLoader );
addLoader( _T( "DWORD" ), new cLongLoader );
addLoader( _T( "float" ), new cFloatLoader );
addLoader( _T( "double" ), new cDoubleLoader );
addLoader( _T( "String" ), new cStringLoader );
}
void cFieldLoader::term()
{
g_primitives.clear();
}
void cFieldLoader::addLoader( LPCTSTR szName, cFieldLoader *pLoader )
{
g_primitives.insert( cFieldLoaderMap::value_type( szName, std::auto_ptr< cFieldLoader >( pLoader ) ) );
}
cFieldLoader::cFieldLoaderMap cFieldLoader::g_primitives;

View file

@ -0,0 +1,30 @@
// MessageLoaders.h
// Declaration of Primitive Data Type loaders for encoded message data
#ifndef __MESSAGELOADERS_H
#define __MESSAGELOADERS_H
#include <map>
class cFieldLoader
{
public:
virtual void *skip(void *) = 0;
virtual void *align(void *pData, void *pStart) = 0;
virtual bool testValue(void *pData, void *pEnd) = 0;
virtual void getValue( void *, LPVARIANT pDest ) = 0;
virtual long getNumber( void *pvData );
static cFieldLoader *lookup( const _bstr_t &strName );
static void init();
static void term();
private:
static void addLoader( LPCTSTR szName, cFieldLoader *pLoader );
typedef std::map< _bstr_t, std::auto_ptr< cFieldLoader > > cFieldLoaderMap;
static cFieldLoaderMap g_primitives;
};
#endif

View file

@ -0,0 +1,701 @@
// MessageParsers.cpp
// Implementation of parsers and runtime objects for parsing message data
#include "StdAfx.h"
#include "Inject.h"
#include "MessageParsers.h"
#include "MessageLoaders.h"
#include "MessageStruct.h"
#include "MessageVector.h"
class cStructElement
: public cMessage::cMessageElement
{
public:
cMessage::cElementList m_members;
virtual bool load( cMessage::cLoadContext &context )
{
// Walk through the list of members and have them load
int nIndex = context.addField( this, NULL );
for( cMessage::cElementList::iterator i = m_members.begin(); i != m_members.end(); ++ i )
{
if( !i->get()->load( cMessage::cLoadContext( &context ) ) )
return false;
}
// Update the field count
context.groupField( nIndex );
return true;
}
virtual void getValue( cMessage *pMessage, cMessage::cFieldList::iterator i, LPVARIANT pDest )
{
if( i->m_pDisp.p == NULL )
{
// Create the vector object
CComObject< cMessageStruct > *pVecDisp;
CComObject< cMessageStruct >::CreateInstance( &pVecDisp );
pVecDisp->init( pMessage, ( i - pMessage->m_fields.begin() ) );
i->m_pDisp = pVecDisp;
}
else
i->m_pDisp->Reset();
pDest->vt = VT_DISPATCH;
pDest->pdispVal = i->m_pDisp;
pDest->pdispVal->AddRef();
}
};
class cFieldParser
: public cElementParser
{
public:
class cFieldElement
: public cMessage::cMessageElement
{
public:
cFieldLoader *m_pLoader;
virtual bool load( cMessage::cLoadContext &context )
{
if( !m_pLoader->testValue( context.getMessage()->m_pEndCrack, context.getMessage()->m_pEndData ) )
{
// The element failed, this will usually indicate bad schema
_ASSERTE( FALSE );
return false;
}
context.addField( this, context.getMessage()->m_pEndCrack );
context.getMessage()->m_pEndCrack = reinterpret_cast< BYTE * >( m_pLoader->skip( context.getMessage()->m_pEndCrack ) );
return true;
}
virtual void getValue( cMessage *, cMessage::cFieldList::iterator i, LPVARIANT pDest )
{
m_pLoader->getValue( i->m_pvData, pDest );
}
virtual long getNumber( cMessage::cFieldList::iterator i )
{
return m_pLoader->getNumber( i->m_pvData );
}
};
// Strings
static _bstr_t g_strType;
static _bstr_t g_strName;
virtual cMessage::cMessageElement *parse( cContext &context, MSXML::IXMLDOMElementPtr &pElement )
{
// Locate the data type in the list
_variant_t strDataType = pElement->getAttribute( g_strType );
if( strDataType.vt != VT_BSTR )
{
// Schema error
_ASSERTE( strDataType.vt == VT_BSTR );
return NULL;
}
_bstr_t bstrDataType = strDataType;
cFieldLoader *pField = cFieldLoader::lookup( bstrDataType );
if( pField == NULL )
return parseStruct( context, pElement, bstrDataType );
_variant_t strName = pElement->getAttribute( g_strName );
if( strName.vt != VT_BSTR )
{
_ASSERTE( strName.vt == VT_BSTR );
return NULL;
}
cFieldElement *pFieldElement = new cFieldElement;
pFieldElement->m_strName = strName;
pFieldElement->m_pLoader = pField;
return pFieldElement;
}
cMessage::cMessageElement *parseStruct( cContext &context, MSXML::IXMLDOMElementPtr &pElement, const _bstr_t &strType )
{
// Locate the data type in the list
_variant_t strName = pElement->getAttribute( cFieldParser::g_strName );
if( strName.vt != VT_BSTR )
{
// Schema error
_ASSERTE( strName.vt == VT_BSTR );
return NULL;
}
// We have the field name, now look up data type schema
USES_CONVERSION;
TCHAR szQuery[ 255 ];
::_stprintf( szQuery, _T( "/schema/datatypes/type[@name='%s']" ),
OLE2T( strType ) );
MSXML::IXMLDOMElementPtr pStruct = pElement->ownerDocument->selectSingleNode( szQuery );
if( pStruct.GetInterfacePtr() == NULL )
{
// Could not cross reference the structure
_ASSERTE( pStruct.GetInterfacePtr() != NULL );
return NULL;
}
std::auto_ptr< cStructElement > pStructElement( new cStructElement() );
pStructElement->m_strName = strName;
if( context.parseChildren( pStructElement->m_members, pStruct ) )
return pStructElement.release();
return NULL;
}
};
_bstr_t cFieldParser::g_strType( _T( "type" ) );
_bstr_t cFieldParser::g_strName( _T( "name" ) );
class cMaskParser
: public cElementParser
{
public:
class cMaskElement
: public cMessage::cMessageElement
{
public:
cMessage::cMessageElement *m_pValue;
class cMask
{
public:
DWORD m_dwValue;
DWORD m_dwFirstChild,
m_dwLastChild;
};
typedef std::vector< cMask > cMaskMap;
cMaskMap m_masks;
cMessage::cElementList m_members;
virtual bool load( cMessage::cLoadContext &context )
{
// First, look for our value element in the message
cMessage::cFieldList::iterator iField = context.lookupField( m_pValue );
if( iField == context.getMessage()->m_fields.end() )
{
// Could not find a mask source - most likely a bad name of some kind
_ASSERTE( FALSE );
return false;
}
_ASSERT( iField->m_pSchema == m_pValue );
long nMaskValue = iField->m_pSchema->getNumber( iField );
// Walk through the mask values and load all of the fields in range
for( cMaskMap::iterator i = m_masks.begin(); i != m_masks.end(); ++ i )
{
if( ( nMaskValue & i->m_dwValue ) == 0 )
continue;
// This is a valid mask load up all teh fields in range
cMessage::cElementList::iterator m_end = m_members.begin() + i->m_dwLastChild;
for( cMessage::cElementList::iterator j = m_members.begin() + i->m_dwFirstChild; j != m_end; ++ j )
{
if( !j->get()->load( context ) )
return false;
}
}
return true;
}
virtual void getValue( cMessage *, cMessage::cFieldList::iterator, LPVARIANT )
{
// This element should never insert itself into the message list
_ASSERTE( FALSE );
}
};
static _bstr_t g_strMask;
static _bstr_t g_strValue;
virtual cMessage::cMessageElement *parse( cContext &context, MSXML::IXMLDOMElementPtr &pElement )
{
_variant_t vName = pElement->getAttribute( cFieldParser::g_strName );
if( vName.vt != VT_BSTR )
{
// It must have the name field
_ASSERTE( vName.vt == VT_BSTR );
return NULL;
}
// Find a matching element in the schema
cMessage::cMessageElement *pName = context.findElement( vName.bstrVal );
if( pName == NULL )
{
// The mask field was not found
_ASSERTE( pName != NULL );
return NULL;
}
// Create the mask element
std::auto_ptr< cMaskElement > pMaskElement( new cMaskElement );
pMaskElement->m_pValue = pName;
// Walk through each of the mask values
USES_CONVERSION;
MSXML::IXMLDOMNodeListPtr pMaskList = pElement->selectNodes( g_strMask );
for( MSXML::IXMLDOMElementPtr pMask = pMaskList->nextNode(); pMask.GetInterfacePtr() != NULL; pMask = pMaskList->nextNode() )
{
_variant_t vValue = pMask->getAttribute( g_strValue );
if( vValue.vt != VT_BSTR )
{
_ASSERTE( vName.vt == VT_BSTR );
return NULL;
}
// Make sure it has the 'hex' prefix
if( vValue.bstrVal[ 0 ] != OLESTR( '0' ) )
{
_ASSERTE( vValue.bstrVal[ 0 ] == OLESTR( '0' ) );
return NULL;
}
if( vValue.bstrVal[ 1 ] != OLESTR( 'x' ) )
{
_ASSERTE( vValue.bstrVal[ 1 ] == OLESTR( 'x' ) );
return NULL;
}
// Attempt to convert the remaining number
long nMaskValue;
if( ::_stscanf( OLE2T( vValue.bstrVal + 2 ), _T( "%X" ), &nMaskValue ) != 1 )
{
// Could not convert value
_ASSERTE( FALSE );
return NULL;
}
long nStartOffset = pMaskElement->m_members.size();
context.parseChildren( pMaskElement->m_members, pMask );
cMaskElement::cMask mask = { nMaskValue, nStartOffset, pMaskElement->m_members.size() };
pMaskElement->m_masks.push_back( mask );
}
return pMaskElement.release();
}
};
_bstr_t cMaskParser::g_strMask( _T( "mask" ) );
_bstr_t cMaskParser::g_strValue( _T( "value" ) );
class cVectorParser
: public cElementParser
{
public:
class cVectorElement
: public cMessage::cMessageElement
{
public:
cMessage::cMessageElement *m_pLength;
std::auto_ptr< cMessage::cMessageElement > m_pStruct;
int m_nSkip;
virtual bool load( cMessage::cLoadContext &context )
{
// First, look for our value element in the message
cMessage::cFieldList::iterator iField = context.lookupField( m_pLength );
if( iField == context.getMessage()->m_fields.end() )
{
// Could not find a mask source - most likely a bad name of some kind
_ASSERTE( FALSE );
return NULL;
}
_ASSERT( iField->m_pSchema == m_pLength );
long nLength = iField->m_pSchema->getNumber( iField ) - m_nSkip;
// Insert a record for ourself
DWORD dwIndex = context.addField( this, NULL );
for( int i = 0; i < nLength; ++ i )
{
// Insert a record for the current struct
if( !m_pStruct->load( cMessage::cLoadContext( &context ) ) )
return false;
}
// Update the used field count
context.groupField( dwIndex );
return true;
}
virtual void getValue( cMessage *pMessage, cMessage::cFieldList::iterator i, LPVARIANT pDest )
{
if( i->m_pDisp.p == NULL )
{
// Create the vector object
CComObject< cMessageVector > *pVecDisp;
CComObject< cMessageVector >::CreateInstance( &pVecDisp );
pVecDisp->init( pMessage, ( i - pMessage->m_fields.begin() ) );
i->m_pDisp = pVecDisp;
}
else
i->m_pDisp->Reset();
pDest->vt = VT_DISPATCH;
pDest->pdispVal = i->m_pDisp;
pDest->pdispVal->AddRef();
}
};
static _bstr_t g_strLength,
g_strSkip;
virtual cMessage::cMessageElement *parse( cContext &context, MSXML::IXMLDOMElementPtr &pElement )
{
_variant_t vName = pElement->getAttribute( cFieldParser::g_strName );
if( vName.vt != VT_BSTR )
{
// It must have the name field
_ASSERTE( vName.vt == VT_BSTR );
return NULL;
}
_variant_t vLength = pElement->getAttribute( g_strLength ),
vSkip = pElement->getAttribute( g_strSkip );
if( vLength.vt != VT_BSTR )
{
// It must have the name field
_ASSERTE( vLength.vt == VT_BSTR );
return NULL;
}
long nSkip = 0;
if( vSkip.vt != VT_NULL )
{
try
{
nSkip = vSkip;
}
catch( ... )
{
// Failed to make the conversion
_ASSERT( FALSE );
return NULL;
}
}
cMessage::cMessageElement *pLength = context.findElement( vLength.bstrVal );
if( pLength == NULL )
{
// The mask field was not found
_ASSERTE( pLength != NULL );
return NULL;
}
std::auto_ptr< cStructElement > pStructElement( new cStructElement );
if( !context.parseChildren( pStructElement->m_members, pElement ) )
return NULL;
cVectorElement *pVector = new cVectorElement;
pVector->m_strName = vName;
pVector->m_pLength = pLength;
pVector->m_nSkip = nSkip;
pVector->m_pStruct = std::auto_ptr< cMessage::cMessageElement >( pStructElement.release() );
return pVector;
}
};
_bstr_t cVectorParser::g_strLength( _T( "length" ) );
_bstr_t cVectorParser::g_strSkip( _T( "skip" ) );
class cSwitchParser
: public cElementParser
{
public:
class cSwitchElement
: public cMessage::cMessageElement
{
public:
cMessage::cMessageElement *m_pValue;
class cCase
{
public:
DWORD m_dwValue;
DWORD m_dwFirstChild,
m_dwLastChild;
};
typedef std::vector< cCase > cCaseMap;
cCaseMap m_cases;
cMessage::cElementList m_members;
virtual bool load( cMessage::cLoadContext &context )
{
// First, look for our value element in the message
cMessage::cFieldList::iterator iField = context.lookupField( m_pValue );
if( iField == context.getMessage()->m_fields.end() )
{
// Could not find a mask source - most likely a bad name of some kind
_ASSERTE( FALSE );
return NULL;
}
_ASSERT( iField->m_pSchema == m_pValue );
long nCaseValue = iField->m_pSchema->getNumber( iField );
// Walk through the mask values and load all of the fields in range
for( cCaseMap::iterator i = m_cases.begin(); i != m_cases.end(); ++ i )
{
if( nCaseValue != i->m_dwValue )
continue;
// This is a valid mask load up all teh fields in range
cMessage::cElementList::iterator m_end = m_members.begin() + i->m_dwLastChild;
for( cMessage::cElementList::iterator j = m_members.begin() + i->m_dwFirstChild; j != m_end; ++ j )
{
if( !j->get()->load( context ) )
return false;
}
// For now we short circuit cases
break;
}
return true;
}
virtual void getValue( cMessage *, cMessage::cFieldList::iterator, LPVARIANT )
{
// This element should never insert itself into the message list
_ASSERTE( FALSE );
}
};
static _bstr_t g_strCase;
virtual cMessage::cMessageElement *parse( cContext &context, MSXML::IXMLDOMElementPtr &pElement )
{
_variant_t vName = pElement->getAttribute( cFieldParser::g_strName );
if( vName.vt != VT_BSTR )
{
// It must have the name field
_ASSERTE( vName.vt == VT_BSTR );
return NULL;
}
// Find a matching element in the schema
cMessage::cMessageElement *pName = context.findElement( vName.bstrVal );
if( pName == NULL )
{
// The mask field was not found
_ASSERTE( pName != NULL );
return NULL;
}
// Create the mask element
std::auto_ptr< cSwitchElement > pSwitchElement( new cSwitchElement );
pSwitchElement->m_pValue = pName;
// Walk through each of the mask values
USES_CONVERSION;
MSXML::IXMLDOMNodeListPtr pCaseList = pElement->selectNodes( g_strCase );
for( MSXML::IXMLDOMElementPtr pCase = pCaseList->nextNode(); pCase.GetInterfacePtr() != NULL; pCase = pCaseList->nextNode() )
{
_variant_t vValue = pCase->getAttribute( cMaskParser::g_strValue );
if( vValue.vt != VT_BSTR )
{
_ASSERTE( vName.vt == VT_BSTR );
return NULL;
}
// Make sure it has the 'hex' prefix
if( vValue.bstrVal[ 0 ] != OLESTR( '0' ) )
{
_ASSERTE( vValue.bstrVal[ 0 ] == OLESTR( '0' ) );
return NULL;
}
if( vValue.bstrVal[ 1 ] != OLESTR( 'x' ) )
{
_ASSERTE( vValue.bstrVal[ 1 ] == OLESTR( 'x' ) );
return NULL;
}
// Attempt to convert the remaining number
long nCaseValue;
if( ::_stscanf( OLE2T( vValue.bstrVal + 2 ), _T( "%X" ), &nCaseValue ) != 1 )
{
// Could not convert value
_ASSERTE( FALSE );
return NULL;
}
long nStartOffset = pSwitchElement->m_members.size();
context.parseChildren( pSwitchElement->m_members, pCase );
cSwitchElement::cCase _case = { nCaseValue, nStartOffset, pSwitchElement->m_members.size() };
pSwitchElement->m_cases.push_back( _case );
}
return pSwitchElement.release();
}
};
_bstr_t cSwitchParser::g_strCase( _T( "case" ) );
class cAlignParser
: public cElementParser
{
public:
class cAlignElement
: public cMessage::cMessageElement
{
public:
cFieldLoader *m_pLoader;
virtual bool load( cMessage::cLoadContext &context )
{
void *pAlign = m_pLoader->align( context.getMessage()->m_pEndCrack, context.getMessage()->m_pStartCrack );
if( pAlign > context.getMessage()->m_pEndData )
{
_ASSERTE( FALSE );
return false;
}
context.getMessage()->m_pEndCrack = reinterpret_cast< BYTE * >( pAlign );
return true;
}
virtual void getValue( cMessage *, cMessage::cFieldList::iterator i, LPVARIANT pDest )
{
// This should never associate itself with a field
_ASSERTE( FALSE );
}
};
virtual cMessage::cMessageElement *parse( cContext &context, MSXML::IXMLDOMElementPtr &pElement )
{
// Locate the data type in the list
_variant_t strDataType = pElement->getAttribute( cFieldParser::g_strType );
if( strDataType.vt != VT_BSTR )
{
// Schema error
_ASSERTE( strDataType.vt == VT_BSTR );
return NULL;
}
_bstr_t bstrDataType = strDataType;
cFieldLoader *pField = cFieldLoader::lookup( bstrDataType );
if( pField == NULL )
{
_ASSERTE( FALSE );
return NULL;
}
cAlignElement *pAlignElement = new cAlignElement;
pAlignElement->m_pLoader = pField;
return pAlignElement;
}
};
cMessage::cMessageElement *cElementParser::cContext::findElement( const _bstr_t &strElement )
{
for( cContext *pContext = this; pContext != NULL; pContext = pContext->m_pParent )
{
for( cMessage::cElementList::iterator i = m_pElements->begin() + m_dwStartOffset; i != m_pElements->end(); ++ i )
{
if( i->get()->m_strName == strElement )
return i->get();
}
}
return NULL;
}
bool cElementParser::cContext::parseChildren( MSXML::IXMLDOMElementPtr &pElement )
{
MSXML::IXMLDOMNodeListPtr pChildList = pElement->selectNodes( g_strAll );
for( MSXML::IXMLDOMElementPtr pChild = pChildList->nextNode(); pChild.GetInterfacePtr() != NULL; pChild = pChildList->nextNode() )
{
_bstr_t strElementName = pChild->tagName;
cElementParser *pParser = cElementParser::lookup( strElementName );
if( pParser == NULL )
{
// Could not find a parse for this element type
_ASSERTE( FALSE );
return false;
}
cMessage::cMessageElement *pElement = pParser->parse( *this, pChild );
if( pElement == NULL )
return false;
m_pElements->push_back( cMessage::cElementList::value_type( pElement ) );
}
return true;
}
_bstr_t cElementParser::cContext::g_strAll( _T( "*" ) );
bool cElementParser::cContext::parseChildren( cMessage::cElementList &elements, MSXML::IXMLDOMElementPtr &pElement )
{
cContext c( &elements, this );
return c.parseChildren( pElement );
}
cElementParser *cElementParser::lookup( const _bstr_t &strElement )
{
cElementParserMap::iterator i = g_parsers.find( strElement );
if( i == g_parsers.end() )
return NULL;
return i->second.get();
}
void cElementParser::init()
{
addParser( _T( "field" ), new cFieldParser );
addParser( _T( "maskmap" ), new cMaskParser );
addParser( _T( "vector" ), new cVectorParser );
addParser( _T( "switch" ), new cSwitchParser );
addParser( _T( "align" ), new cAlignParser );
}
void cElementParser::term()
{
g_parsers.clear();
}
void cElementParser::addParser( LPCTSTR szName, cElementParser *pParser )
{
g_parsers.insert( cElementParserMap::value_type( szName, std::auto_ptr< cElementParser >( pParser ) ) );
}
cElementParser::cElementParserMap cElementParser::g_parsers;

View file

@ -0,0 +1,704 @@
// MessageParsers.cpp
// Implementation of parsers and runtime objects for parsing message data
#include "StdAfx.h"
#include "Inject.h"
#include "MessageParsers.h"
#include "MessageLoaders.h"
#include "MessageStruct.h"
#include "MessageVector.h"
class cStructElement
: public cMessage::cMessageElement
{
public:
cMessage::cElementList m_members;
virtual bool load( cMessage::cLoadContext &context )
{
// Walk through the list of members and have them load
int nIndex = context.addField( this, NULL );
for( cMessage::cElementList::iterator i = m_members.begin(); i != m_members.end(); ++ i )
{
if( !i->get()->load( cMessage::cLoadContext( &context ) ) )
return false;
}
// Update the field count
context.groupField( nIndex );
return true;
}
virtual void getValue( cMessage *pMessage, cMessage::cFieldList::iterator i, LPVARIANT pDest )
{
if( i->m_pDisp.p == NULL )
{
// Create the vector object
CComObject< cMessageStruct > *pVecDisp;
CComObject< cMessageStruct >::CreateInstance( &pVecDisp );
pVecDisp->m_pSource = pMessage;
pVecDisp->m_dwStartIndex = ( i - pMessage->m_fields.begin() );
i->m_pDisp = pVecDisp;
}
::VariantInit (pDest);
pDest->vt = VT_DISPATCH;
pDest->pdispVal = i->m_pDisp;
pDest->pdispVal->AddRef();
}
};
class cFieldParser
: public cElementParser
{
public:
class cFieldElement
: public cMessage::cMessageElement
{
public:
cFieldLoader *m_pLoader;
virtual bool load( cMessage::cLoadContext &context )
{
if( !m_pLoader->testValue( context.getMessage()->m_pEndCrack, context.getMessage()->m_pEndData ) )
{
// The element failed, this will usually indicate bad schema
_ASSERTE( FALSE );
return false;
}
context.addField( this, context.getMessage()->m_pEndCrack );
context.getMessage()->m_pEndCrack = reinterpret_cast< BYTE * >( m_pLoader->skip( context.getMessage()->m_pEndCrack ) );
return true;
}
virtual void getValue( cMessage *, cMessage::cFieldList::iterator i, LPVARIANT pDest )
{
m_pLoader->getValue( i->m_pvData, pDest );
}
virtual long getNumber( cMessage::cFieldList::iterator i )
{
return m_pLoader->getNumber( i->m_pvData );
}
};
// Strings
static _bstr_t g_strType;
static _bstr_t g_strName;
virtual cMessage::cMessageElement *parse( cContext &context, MSXML::IXMLDOMElementPtr &pElement )
{
// Locate the data type in the list
_variant_t strDataType = pElement->getAttribute( g_strType );
if( strDataType.vt != VT_BSTR )
{
// Schema error
_ASSERTE( strDataType.vt == VT_BSTR );
return NULL;
}
_bstr_t bstrDataType = strDataType;
cFieldLoader *pField = cFieldLoader::lookup( bstrDataType );
if( pField == NULL )
return parseStruct( context, pElement, bstrDataType );
_variant_t strName = pElement->getAttribute( g_strName );
if( strName.vt != VT_BSTR )
{
_ASSERTE( strName.vt == VT_BSTR );
return NULL;
}
cFieldElement *pFieldElement = new cFieldElement;
pFieldElement->m_strName = strName;
pFieldElement->m_pLoader = pField;
return pFieldElement;
}
cMessage::cMessageElement *parseStruct( cContext &context, MSXML::IXMLDOMElementPtr &pElement, const _bstr_t &strType )
{
// Locate the data type in the list
_variant_t strName = pElement->getAttribute( cFieldParser::g_strName );
if( strName.vt != VT_BSTR )
{
// Schema error
_ASSERTE( strName.vt == VT_BSTR );
return NULL;
}
// We have the field name, now look up data type schema
USES_CONVERSION;
TCHAR szQuery[ 255 ];
::_stprintf( szQuery, _T( "/schema/datatypes/type[@name='%s']" ),
OLE2T( strType ) );
MSXML::IXMLDOMElementPtr pStruct = pElement->ownerDocument->selectSingleNode( szQuery );
if( pStruct.GetInterfacePtr() == NULL )
{
// Could not cross reference the structure
_ASSERTE( pStruct.GetInterfacePtr() != NULL );
return NULL;
}
std::auto_ptr< cStructElement > pStructElement( new cStructElement() );
pStructElement->m_strName = strName;
if( context.parseChildren( pStructElement->m_members, pStruct ) )
return pStructElement.release();
return NULL;
}
};
_bstr_t cFieldParser::g_strType( _T( "type" ) );
_bstr_t cFieldParser::g_strName( _T( "name" ) );
class cMaskParser
: public cElementParser
{
public:
class cMaskElement
: public cMessage::cMessageElement
{
public:
cMessage::cMessageElement *m_pValue;
class cMask
{
public:
DWORD m_dwValue;
DWORD m_dwFirstChild,
m_dwLastChild;
};
typedef std::vector< cMask > cMaskMap;
cMaskMap m_masks;
cMessage::cElementList m_members;
virtual bool load( cMessage::cLoadContext &context )
{
// First, look for our value element in the message
cMessage::cFieldList::iterator iField = context.lookupField( m_pValue );
if( iField == context.getMessage()->m_fields.end() )
{
// Could not find a mask source - most likely a bad name of some kind
_ASSERTE( FALSE );
return false;
}
_ASSERT( iField->m_pSchema == m_pValue );
long nMaskValue = iField->m_pSchema->getNumber( iField );
// Walk through the mask values and load all of the fields in range
for( cMaskMap::iterator i = m_masks.begin(); i != m_masks.end(); ++ i )
{
if( ( nMaskValue & i->m_dwValue ) == 0 )
continue;
// THis is a valid mask load up all teh fields in range
cMessage::cElementList::iterator m_end = m_members.begin() + i->m_dwLastChild;
for( cMessage::cElementList::iterator j = m_members.begin() + i->m_dwFirstChild; j != m_end; ++ j )
{
if( !j->get()->load( context ) )
return false;
}
}
return true;
}
virtual void getValue( cMessage *, cMessage::cFieldList::iterator, LPVARIANT )
{
// This element should never insert itself into the message list
_ASSERTE( FALSE );
}
};
static _bstr_t g_strMask;
static _bstr_t g_strValue;
virtual cMessage::cMessageElement *parse( cContext &context, MSXML::IXMLDOMElementPtr &pElement )
{
_variant_t vName = pElement->getAttribute( cFieldParser::g_strName );
if( vName.vt != VT_BSTR )
{
// It must have the name field
_ASSERTE( vName.vt == VT_BSTR );
return NULL;
}
// Find a matching element in the schema
cMessage::cMessageElement *pName = context.findElement( vName.bstrVal );
if( pName == NULL )
{
// The mask field was not found
_ASSERTE( pName != NULL );
return NULL;
}
// Create the mask element
std::auto_ptr< cMaskElement > pMaskElement( new cMaskElement );
pMaskElement->m_pValue = pName;
// Walk through each of the mask values
USES_CONVERSION;
MSXML::IXMLDOMNodeListPtr pMaskList = pElement->selectNodes( g_strMask );
for( MSXML::IXMLDOMElementPtr pMask = pMaskList->nextNode(); pMask.GetInterfacePtr() != NULL; pMask = pMaskList->nextNode() )
{
_variant_t vValue = pMask->getAttribute( g_strValue );
if( vValue.vt != VT_BSTR )
{
_ASSERTE( vName.vt == VT_BSTR );
return NULL;
}
// Make sure it has the 'hex' prefix
if( vValue.bstrVal[ 0 ] != OLESTR( '0' ) )
{
_ASSERTE( vValue.bstrVal[ 0 ] == OLESTR( '0' ) );
return NULL;
}
if( vValue.bstrVal[ 1 ] != OLESTR( 'x' ) )
{
_ASSERTE( vValue.bstrVal[ 1 ] == OLESTR( 'x' ) );
return NULL;
}
// Attempt to convert the remaining number
long nMaskValue;
if( ::_stscanf( OLE2T( vValue.bstrVal + 2 ), _T( "%X" ), &nMaskValue ) != 1 )
{
// Could not convert value
_ASSERTE( FALSE );
return NULL;
}
long nStartOffset = pMaskElement->m_members.size();
context.parseChildren( pMaskElement->m_members, pMask );
cMaskElement::cMask mask = { nMaskValue, nStartOffset, pMaskElement->m_members.size() };
pMaskElement->m_masks.push_back( mask );
}
return pMaskElement.release();
}
};
_bstr_t cMaskParser::g_strMask( _T( "mask" ) );
_bstr_t cMaskParser::g_strValue( _T( "value" ) );
class cVectorParser
: public cElementParser
{
public:
class cVectorElement
: public cMessage::cMessageElement
{
public:
cMessage::cMessageElement *m_pLength;
std::auto_ptr< cMessage::cMessageElement > m_pStruct;
int m_nSkip;
virtual bool load( cMessage::cLoadContext &context )
{
// First, look for our value element in the message
cMessage::cFieldList::iterator iField = context.lookupField( m_pLength );
if( iField == context.getMessage()->m_fields.end() )
{
// Could not find a mask source - most likely a bad name of some kind
_ASSERTE( FALSE );
return NULL;
}
_ASSERT( iField->m_pSchema == m_pLength );
long nLength = iField->m_pSchema->getNumber( iField ) - m_nSkip;
// Insert a record for ourself
DWORD dwIndex = context.addField( this, NULL );
for( int i = 0; i < nLength; ++ i )
{
// Insert a record for the current struct
if( !m_pStruct->load( cMessage::cLoadContext( &context ) ) )
return false;
}
// Update the used field count
context.groupField( dwIndex );
return true;
}
virtual void getValue( cMessage *pMessage, cMessage::cFieldList::iterator i, LPVARIANT pDest )
{
if( i->m_pDisp.p == NULL )
{
// Create the vector object
CComObject< cMessageVector > *pVecDisp;
CComObject< cMessageVector >::CreateInstance( &pVecDisp );
pVecDisp->m_pSource = pMessage;
pVecDisp->m_dwStartIndex = ( i - pMessage->m_fields.begin() );
i->m_pDisp = pVecDisp;
}
::VariantInit (pDest);
pDest->vt = VT_DISPATCH;
pDest->pdispVal = i->m_pDisp;
pDest->pdispVal->AddRef();
}
};
static _bstr_t g_strLength,
g_strSkip;
virtual cMessage::cMessageElement *parse( cContext &context, MSXML::IXMLDOMElementPtr &pElement )
{
_variant_t vName = pElement->getAttribute( cFieldParser::g_strName );
if( vName.vt != VT_BSTR )
{
// It must have the name field
_ASSERTE( vName.vt == VT_BSTR );
return NULL;
}
_variant_t vLength = pElement->getAttribute( g_strLength ),
vSkip = pElement->getAttribute( g_strSkip );
if( vLength.vt != VT_BSTR )
{
// It must have the name field
_ASSERTE( vLength.vt == VT_BSTR );
return NULL;
}
long nSkip = 0;
if( vSkip.vt != VT_NULL )
{
try
{
nSkip = vSkip;
}
catch( ... )
{
// Failed to make the conversion
_ASSERT( FALSE );
return NULL;
}
}
cMessage::cMessageElement *pLength = context.findElement( vLength.bstrVal );
if( pLength == NULL )
{
// The mask field was not found
_ASSERTE( pLength != NULL );
return NULL;
}
std::auto_ptr< cStructElement > pStructElement( new cStructElement );
if( !context.parseChildren( pStructElement->m_members, pElement ) )
return NULL;
cVectorElement *pVector = new cVectorElement;
pVector->m_strName = vName;
pVector->m_pLength = pLength;
pVector->m_nSkip = nSkip;
pVector->m_pStruct = std::auto_ptr< cMessage::cMessageElement >( pStructElement.release() );
return pVector;
}
};
_bstr_t cVectorParser::g_strLength( _T( "length" ) );
_bstr_t cVectorParser::g_strSkip( _T( "skip" ) );
class cSwitchParser
: public cElementParser
{
public:
class cSwitchElement
: public cMessage::cMessageElement
{
public:
cMessage::cMessageElement *m_pValue;
class cCase
{
public:
DWORD m_dwValue;
DWORD m_dwFirstChild,
m_dwLastChild;
};
typedef std::vector< cCase > cCaseMap;
cCaseMap m_cases;
cMessage::cElementList m_members;
virtual bool load( cMessage::cLoadContext &context )
{
// First, look for our value element in the message
cMessage::cFieldList::iterator iField = context.lookupField( m_pValue );
if( iField == context.getMessage()->m_fields.end() )
{
// Could not find a mask source - most likely a bad name of some kind
_ASSERTE( FALSE );
return NULL;
}
_ASSERT( iField->m_pSchema == m_pValue );
long nCaseValue = iField->m_pSchema->getNumber( iField );
// Walk through the mask values and load all of the fields in range
for( cCaseMap::iterator i = m_cases.begin(); i != m_cases.end(); ++ i )
{
if( nCaseValue != i->m_dwValue )
continue;
// This is a valid mask load up all teh fields in range
cMessage::cElementList::iterator m_end = m_members.begin() + i->m_dwLastChild;
for( cMessage::cElementList::iterator j = m_members.begin() + i->m_dwFirstChild; j != m_end; ++ j )
{
if( !j->get()->load( context ) )
return false;
}
// For now we short circuit cases
break;
}
return true;
}
virtual void getValue( cMessage *, cMessage::cFieldList::iterator, LPVARIANT )
{
// This element should never insert itself into the message list
_ASSERTE( FALSE );
}
};
static _bstr_t g_strCase;
virtual cMessage::cMessageElement *parse( cContext &context, MSXML::IXMLDOMElementPtr &pElement )
{
_variant_t vName = pElement->getAttribute( cFieldParser::g_strName );
if( vName.vt != VT_BSTR )
{
// It must have the name field
_ASSERTE( vName.vt == VT_BSTR );
return NULL;
}
// Find a matching element in the schema
cMessage::cMessageElement *pName = context.findElement( vName.bstrVal );
if( pName == NULL )
{
// The mask field was not found
_ASSERTE( pName != NULL );
return NULL;
}
// Create the mask element
std::auto_ptr< cSwitchElement > pSwitchElement( new cSwitchElement );
pSwitchElement->m_pValue = pName;
// Walk through each of the mask values
USES_CONVERSION;
MSXML::IXMLDOMNodeListPtr pCaseList = pElement->selectNodes( g_strCase );
for( MSXML::IXMLDOMElementPtr pCase = pCaseList->nextNode(); pCase.GetInterfacePtr() != NULL; pCase = pCaseList->nextNode() )
{
_variant_t vValue = pCase->getAttribute( cMaskParser::g_strValue );
if( vValue.vt != VT_BSTR )
{
_ASSERTE( vName.vt == VT_BSTR );
return NULL;
}
// Make sure it has the 'hex' prefix
if( vValue.bstrVal[ 0 ] != OLESTR( '0' ) )
{
_ASSERTE( vValue.bstrVal[ 0 ] == OLESTR( '0' ) );
return NULL;
}
if( vValue.bstrVal[ 1 ] != OLESTR( 'x' ) )
{
_ASSERTE( vValue.bstrVal[ 1 ] == OLESTR( 'x' ) );
return NULL;
}
// Attempt to convert the remaining number
long nCaseValue;
if( ::_stscanf( OLE2T( vValue.bstrVal + 2 ), _T( "%X" ), &nCaseValue ) != 1 )
{
// Could not convert value
_ASSERTE( FALSE );
return NULL;
}
long nStartOffset = pSwitchElement->m_members.size();
context.parseChildren( pSwitchElement->m_members, pCase );
cSwitchElement::cCase _case = { nCaseValue, nStartOffset, pSwitchElement->m_members.size() };
pSwitchElement->m_cases.push_back( _case );
}
return pSwitchElement.release();
}
};
_bstr_t cSwitchParser::g_strCase( _T( "case" ) );
class cAlignParser
: public cElementParser
{
public:
class cAlignElement
: public cMessage::cMessageElement
{
public:
cFieldLoader *m_pLoader;
virtual bool load( cMessage::cLoadContext &context )
{
void *pAlign = m_pLoader->align( context.getMessage()->m_pEndCrack, context.getMessage()->m_pStartCrack );
if( pAlign > context.getMessage()->m_pEndData )
{
_ASSERTE( FALSE );
return false;
}
context.getMessage()->m_pEndCrack = reinterpret_cast< BYTE * >( pAlign );
return true;
}
virtual void getValue( cMessage *, cMessage::cFieldList::iterator i, LPVARIANT pDest )
{
// This should never associate itself with a field
_ASSERTE( FALSE );
}
};
virtual cMessage::cMessageElement *parse( cContext &context, MSXML::IXMLDOMElementPtr &pElement )
{
// Locate the data type in the list
_variant_t strDataType = pElement->getAttribute( cFieldParser::g_strType );
if( strDataType.vt != VT_BSTR )
{
// Schema error
_ASSERTE( strDataType.vt == VT_BSTR );
return NULL;
}
_bstr_t bstrDataType = strDataType;
cFieldLoader *pField = cFieldLoader::lookup( bstrDataType );
if( pField == NULL )
{
_ASSERTE( FALSE );
return NULL;
}
cAlignElement *pAlignElement = new cAlignElement;
pAlignElement->m_pLoader = pField;
return pAlignElement;
}
};
cMessage::cMessageElement *cElementParser::cContext::findElement( const _bstr_t &strElement )
{
for( cContext *pContext = this; pContext != NULL; pContext = pContext->m_pParent )
{
for( cMessage::cElementList::iterator i = m_pElements->begin() + m_dwStartOffset; i != m_pElements->end(); ++ i )
{
if( i->get()->m_strName == strElement )
return i->get();
}
}
return NULL;
}
bool cElementParser::cContext::parseChildren( MSXML::IXMLDOMElementPtr &pElement )
{
MSXML::IXMLDOMNodeListPtr pChildList = pElement->selectNodes( g_strAll );
for( MSXML::IXMLDOMElementPtr pChild = pChildList->nextNode(); pChild.GetInterfacePtr() != NULL; pChild = pChildList->nextNode() )
{
_bstr_t strElementName = pChild->tagName;
cElementParser *pParser = cElementParser::lookup( strElementName );
if( pParser == NULL )
{
// Could not find a parse for this element type
_ASSERTE( FALSE );
return false;
}
cMessage::cMessageElement *pElement = pParser->parse( *this, pChild );
if( pElement == NULL )
return false;
m_pElements->push_back( cMessage::cElementList::value_type( pElement ) );
}
return true;
}
_bstr_t cElementParser::cContext::g_strAll( _T( "*" ) );
bool cElementParser::cContext::parseChildren( cMessage::cElementList &elements, MSXML::IXMLDOMElementPtr &pElement )
{
cContext c( &elements, this );
return c.parseChildren( pElement );
}
cElementParser *cElementParser::lookup( const _bstr_t &strElement )
{
cElementParserMap::iterator i = g_parsers.find( strElement );
if( i == g_parsers.end() )
return NULL;
return i->second.get();
}
void cElementParser::init()
{
addParser( _T( "field" ), new cFieldParser );
addParser( _T( "maskmap" ), new cMaskParser );
addParser( _T( "vector" ), new cVectorParser );
addParser( _T( "switch" ), new cSwitchParser );
addParser( _T( "align" ), new cAlignParser );
}
void cElementParser::term()
{
g_parsers.clear();
}
void cElementParser::addParser( LPCTSTR szName, cElementParser *pParser )
{
g_parsers.insert( cElementParserMap::value_type( szName, std::auto_ptr< cElementParser >( pParser ) ) );
}
cElementParser::cElementParserMap cElementParser::g_parsers;

View file

@ -0,0 +1,48 @@
// MessageParsers.h
// Declaration of class cMessageParser - base class for parsing the
// XML Schema
#ifndef __MESSAGEPARSERS_H
#define __MESSAGEPARSERS_H
#include "Message.h"
class cElementParser
{
public:
class cContext
{
cContext *m_pParent;
cMessage::cElementList *m_pElements;
DWORD m_dwStartOffset;
public:
cContext( cMessage::cElementList *pElements, cContext *pParent = NULL )
: m_pParent( pParent ),
m_pElements( pElements ),
m_dwStartOffset( pElements->size() )
{
}
cMessage::cMessageElement *findElement( const _bstr_t &strElement );
bool parseChildren( MSXML::IXMLDOMElementPtr &pElement );
bool parseChildren( cMessage::cElementList &elements, MSXML::IXMLDOMElementPtr &pElement );
static _bstr_t g_strAll;
};
virtual cMessage::cMessageElement *parse( cContext &context, MSXML::IXMLDOMElementPtr &pElement ) = 0;
static cElementParser *lookup( const _bstr_t &strElement );
static void init();
static void term();
private:
static void addParser( LPCTSTR szElement, cElementParser *pParser );
typedef std::map< _bstr_t, std::auto_ptr< cElementParser > > cElementParserMap;
static cElementParserMap g_parsers;
};
#endif

View file

@ -0,0 +1,93 @@
// MessageStruct.cpp : Implementation of cMessageStruct
#include "stdafx.h"
#include "Inject.h"
#include "MessageStruct.h"
#include "Message.h"
/////////////////////////////////////////////////////////////////////////////
// cMessageStruct
STDMETHODIMP cMessageStruct::get_Count(long *pVal)
{
_ASSERTE( pVal != NULL );
cMessage::cFieldList::iterator i_begin = m_pSource->m_fields.begin() + m_dwStartIndex;
cMessage::cFieldList::iterator i_end = i_begin + i_begin->m_nOwns;
*pVal = 0;
for( cMessage::cFieldList::iterator i = i_begin + 1; i != i_end; i += i->m_nOwns )
++ ( *pVal );
return S_OK;
}
STDMETHODIMP cMessageStruct::get_MemberName(long Index, BSTR *pVal)
{
_ASSERTE( pVal != NULL );
_ASSERTE( Index >= 0 );
USES_CONVERSION;
cMessage::cFieldList::iterator i_begin = m_pSource->m_fields.begin() + m_dwStartIndex;
cMessage::cFieldList::iterator i_end = i_begin + i_begin->m_nOwns;
for( cMessage::cFieldList::iterator i = i_begin + 1; i != i_end; i += i->m_nOwns, -- Index )
{
if( Index == 0 )
{
*pVal = OLE2BSTR( i->m_pSchema->m_strName );
return S_OK;
}
}
_ASSERTE( FALSE );
return E_INVALIDARG;
}
STDMETHODIMP cMessageStruct::get_Member(VARIANT vIndex, VARIANT *pVal)
{
cMessage::cFieldList::iterator i_begin = m_pSource->m_fields.begin() + m_dwStartIndex;
cMessage::cFieldList::iterator i_end = i_begin + i_begin->m_nOwns;
if( vIndex.vt == VT_BSTR )
{
_bstr_t bstrIndex = vIndex;
for( cMessage::cFieldList::iterator i = i_begin + 1; i != i_end; i += i->m_nOwns )
{
if( bstrIndex == i->m_pSchema->m_strName )
{
i->m_pSchema->getValue( m_pSource, i, pVal );
return S_OK;
}
}
}
HRESULT hRes = ::VariantChangeType( &vIndex, &vIndex, 0, VT_I4 );
if( FAILED( hRes ) )
{
_ASSERTE( FALSE );
return hRes;
}
// Check if the value is in range
long nIndex = vIndex.lVal;
if( nIndex < 0 )
{
_ASSERTE( nIndex >= 0 );
return E_INVALIDARG;
}
for( cMessage::cFieldList::iterator i = i_begin + 1; i != i_end; i += i->m_nOwns, -- nIndex )
{
if( nIndex == 0 )
{
i->m_pSchema->getValue( m_pSource, i, pVal );
return S_OK;
}
}
return S_OK;
}

View file

@ -0,0 +1,36 @@
// MessageStruct.h : Declaration of the cMessageStruct
#ifndef __MESSAGESTRUCT_H_
#define __MESSAGESTRUCT_H_
#include "resource.h" // main symbols
class cMessage;
/////////////////////////////////////////////////////////////////////////////
// cMessageStruct
class ATL_NO_VTABLE cMessageStruct :
public IDispatchImpl<IMessageMember, &IID_IMessageMember, &LIBID_DecalPlugins>,
public CComObjectRootEx<CComMultiThreadModel>
{
public:
cMessageStruct()
{
}
cMessage *m_pSource;
DWORD m_dwStartIndex;
BEGIN_COM_MAP(cMessageStruct)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IMessageMember)
END_COM_MAP()
// IMessageStruct
public:
STDMETHOD(get_Count)(/*[out, retval]*/ long *pVal);
STDMETHOD(get_MemberName)(long Index, /*[out, retval]*/ BSTR *pVal);
STDMETHOD(get_Member)(VARIANT vIndex, /*[out, retval]*/ VARIANT *pVal);
};
#endif //__MESSAGESTRUCT_H_

View file

@ -0,0 +1,26 @@
HKCR
{
Inject.MessageStruct.1 = s 'MessageStruct Class'
{
CLSID = s '{5F1C583E-FDAB-4751-85BA-1178E9360E39}'
}
Inject.MessageStruct = s 'MessageStruct Class'
{
CLSID = s '{5F1C583E-FDAB-4751-85BA-1178E9360E39}'
CurVer = s 'Inject.MessageStruct.1'
}
NoRemove CLSID
{
ForceRemove {5F1C583E-FDAB-4751-85BA-1178E9360E39} = s 'MessageStruct Class'
{
ProgID = s 'Inject.MessageStruct.1'
VersionIndependentProgID = s 'Inject.MessageStruct'
ForceRemove 'Programmable'
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Both'
}
'TypeLib' = s '{3559E08B-827E-4DFE-9D33-3567246849CC}'
}
}
}

View file

@ -0,0 +1,75 @@
// MessageVector.cpp : Implementation of cMessageVector
#include "stdafx.h"
#include "Inject.h"
#include "MessageVector.h"
#include "Message.h"
/////////////////////////////////////////////////////////////////////////////
// cMessageVector
STDMETHODIMP cMessageVector::get_MemberName(long nIndex, BSTR *pVal)
{
_ASSERTE( pVal != NULL );
_ASSERTE( nIndex >= 0 );
USES_CONVERSION;
TCHAR strIndex[ 12 ];
::_stprintf( strIndex, _T( "%i" ), nIndex );
*pVal = T2BSTR( strIndex );
return S_OK;
}
STDMETHODIMP cMessageVector::get_Count(long *pVal)
{
_ASSERTE( pVal != NULL );
cMessage::cFieldList::iterator i_begin = m_pSource->m_fields.begin() + m_dwStartIndex;
cMessage::cFieldList::iterator i_end = i_begin + i_begin->m_nOwns;
*pVal = 0;
for( cMessage::cFieldList::iterator i = i_begin + 1; i != i_end; i += i->m_nOwns )
++ ( *pVal );
return S_OK;
}
STDMETHODIMP cMessageVector::get_Member(VARIANT vIndex, VARIANT *pVal)
{
_ASSERTE( pVal != NULL );
HRESULT hRes = ::VariantChangeType( &vIndex, &vIndex, 0, VT_I4 );
if( FAILED( hRes ) )
{
_ASSERTE( FALSE );
return hRes;
}
// Check if the value is in range
long Index = vIndex.lVal;
if( Index < 0 )
{
_ASSERTE( Index >= 0 );
return E_INVALIDARG;
}
cMessage::cFieldList::iterator i_begin = m_pSource->m_fields.begin() + m_dwStartIndex;
cMessage::cFieldList::iterator i_end = i_begin + i_begin->m_nOwns;
for( cMessage::cFieldList::iterator i = i_begin + 1; i != i_end; i += i->m_nOwns, -- Index )
{
if( Index == 0 )
{
i->m_pSchema->getValue( m_pSource, i, pVal );
return S_OK;
}
}
_ASSERTE( FALSE );
return E_INVALIDARG;
}

View file

@ -0,0 +1,37 @@
// MessageVector.h : Declaration of the cMessageVector
#ifndef __MESSAGEVECTOR_H_
#define __MESSAGEVECTOR_H_
#include "resource.h" // main symbols
#include "Message.h"
class cMessage;
/////////////////////////////////////////////////////////////////////////////
// cMessageVector
class ATL_NO_VTABLE cMessageVector :
public IDispatchImpl<IMessageMember, &IID_IMessageMember, &LIBID_DecalPlugins>,
public CComObjectRootEx<CComMultiThreadModel>
{
public:
cMessageVector()
{
}
cMessage *m_pSource;
DWORD m_dwStartIndex;
BEGIN_COM_MAP(cMessageVector)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IMessageMember)
END_COM_MAP()
// IMessageVector
public:
STDMETHOD(get_Count)(/*[out, retval]*/ long *pVal);
STDMETHOD(get_Member)(VARIANT vIndex, /*[out, retval]*/ VARIANT *pVal);
STDMETHOD(get_MemberName)(long Index, BSTR *pVal);
};
#endif //__MESSAGEVECTOR_H_

View file

@ -0,0 +1,26 @@
HKCR
{
Inject.MessageVector.1 = s 'MessageVector Class'
{
CLSID = s '{7D1D98C1-B850-4B7F-B0DD-CE221F3FD132}'
}
Inject.MessageVector = s 'MessageVector Class'
{
CLSID = s '{7D1D98C1-B850-4B7F-B0DD-CE221F3FD132}'
CurVer = s 'Inject.MessageVector.1'
}
NoRemove CLSID
{
ForceRemove {7D1D98C1-B850-4B7F-B0DD-CE221F3FD132} = s 'MessageVector Class'
{
ProgID = s 'Inject.MessageVector.1'
VersionIndependentProgID = s 'Inject.MessageVector'
ForceRemove 'Programmable'
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Both'
}
'TypeLib' = s '{3559E08B-827E-4DFE-9D33-3567246849CC}'
}
}
}

View file

@ -0,0 +1,210 @@
// ProtocolStack.cpp
// Implementation of class cProtocolStack
#include "stdafx.h"
#include "ProtocolStack.h"
cMessageStack::cMessage::cMessage( BYTE *pbData )
: m_pbData( NULL ),
m_bOwn( false )
{
cMessageHeader *pHeader = reinterpret_cast< cMessageHeader * >( pbData );
if( pHeader->m_wFragmentCount == 1 )
{
// This is the only fragment, we use a direct pointer for dispatching
m_pbData = pbData;
return;
}
// This message has multiple fragments, create a buffer
m_pbData = new BYTE[ calcMessageLength( pbData ) ];
// Two initializers, with
// Copy the header into the new buffer
::memcpy( m_pbData, pbData, sizeof( cMessageHeader ) );
// First calculate the number of fragments we should have
m_FragmentMask.SetSize (pHeader->m_wFragmentCount);
insertFragment( pbData );
}
cMessageStack::cMessage::cMessage( const cMessage &msg )
: m_pbData( msg.m_pbData ),
m_bOwn( msg.m_bOwn )
{
m_FragmentMask = msg.m_FragmentMask;
msg.m_bOwn = false;
}
cMessageStack::cMessage::~cMessage()
{
if( m_bOwn )
delete[] m_pbData;
}
cMessageStack::cMessage &cMessageStack::cMessage::operator= ( const cMessage &msg )
{
if( m_bOwn )
delete[] m_pbData;
m_pbData = msg.m_pbData;
m_FragmentMask = msg.m_FragmentMask;
m_bOwn = msg.m_bOwn;
msg.m_bOwn = false;
return *this;
}
bool cMessageStack::cMessage::fragmentMatch( BYTE *pFragmentStart )
{
cMessageHeader *pThis = getMessageHeader(),
*pOther = reinterpret_cast< cMessageHeader * >( pFragmentStart );
return ( pThis->m_dwObjectID == pOther->m_dwObjectID && pThis->m_dwSequence == pOther->m_dwSequence );
}
#define MESSAGE_BODY 448
void cMessageStack::cMessage::insertFragment( BYTE *pFragmentStart )
{
cMessageHeader *pHeader = reinterpret_cast< cMessageHeader * >( pFragmentStart );
BYTE *pInsertLocation = m_pbData + sizeof( cMessageHeader ) + ( MESSAGE_BODY * pHeader->m_wFragmentIndex );
::memcpy( pInsertLocation, pFragmentStart + sizeof( cMessageHeader ), pHeader->m_wFragmentLength - sizeof( cMessageHeader ) );
m_FragmentMask.GotFragment (pHeader->m_wFragmentIndex);
if( pHeader->m_wFragmentIndex == ( pHeader->m_wFragmentCount - 1 ) )
getMessageHeader()->m_wFragmentLength = ( pHeader->m_wFragmentCount - 1 ) * MESSAGE_BODY + pHeader->m_wFragmentLength;
}
DWORD cMessageStack::cMessage::calcMessageLength( BYTE *pFragmentStart )
{
cMessageHeader *pHeader = reinterpret_cast< cMessageHeader * >( pFragmentStart );
return ( pHeader->m_wFragmentIndex == ( pHeader->m_wFragmentCount - 1 ) ) ?
( pHeader->m_wFragmentCount - 1 ) * MESSAGE_BODY + pHeader->m_wFragmentLength : pHeader->m_wFragmentCount * MESSAGE_BODY + sizeof( cMessageHeader );
}
cMessageStack::cMessageStack()
: m_pCallback( NULL )
{
}
cMessageStack::~cMessageStack()
{
// Make sure we clean up and intermediate steps
stop();
}
void cMessageStack::start( cCallback *pCallback )
{
// Setting this enables messages
m_pCallback = pCallback;
}
void cMessageStack::stop()
{
// Clean out the message list since these will never be matched
m_messages.clear();
m_pCallback = NULL;
}
void cMessageStack::processPacket( DWORD dwLength, BYTE *pbPayload )
{
// First filter based on our status and the message type
if( m_pCallback == NULL )
// We currently only support send or receive type messages
return;
// AC messages must be at least as big as a packet header.+ a message header
if (dwLength < (sizeof (cPacketHeader) + sizeof (cMessageHeader)))
{
return;
}
// Filter non-application messages
cPacketHeader *pHeader = reinterpret_cast< cPacketHeader * >( pbPayload );
if((pHeader->m_wTotalSize) != (dwLength - sizeof(cPacketHeader)))
{
return;
}
DWORD dwOffset = 0;
if (pHeader->m_dwFlags & 0x00100000)
{
// 8 extra header bytes
dwOffset += 8;
}
if (pHeader->m_dwFlags & 0x00200000)
{
// 6 extra header bytes
dwOffset += 6;
}
if (pHeader->m_dwFlags & 0x00400000)
{
// 0 extra header bytes
}
if (pHeader->m_dwFlags & 0x00800000)
{
// 4 extra header bytes
dwOffset += 4;
}
if (dwLength < (dwOffset + sizeof (cMessageHeader)))
{
return;
}
splitPacket( dwLength - dwOffset, pbPayload + dwOffset );
}
void cMessageStack::splitPacket( DWORD dwLength, BYTE *pbPayload )
{
DWORD dwFragLength = 0;
BYTE *i_end_packet = pbPayload + dwLength;
for( BYTE *iFrag = pbPayload + sizeof( cPacketHeader ); iFrag != i_end_packet; iFrag += dwFragLength )
{
dwFragLength = reinterpret_cast< cMessageHeader * >( iFrag )->m_wFragmentLength;
if( dwFragLength == 0 || ( iFrag + dwFragLength ) > i_end_packet )
// We are off the end somehow
return;
// First walk through our cached fragments and see if one will take this fragment
for( cMessageList::iterator i = m_messages.begin(); i != m_messages.end(); ++ i )
{
if( i->fragmentMatch( iFrag ) )
{
i->insertFragment( iFrag );
if( i->isComplete() )
{
// Remove it from the list and dispatch the message
m_pCallback->onMessage( *i );
m_messages.erase( i );
}
break;
}
}
if( i != m_messages.end() )
// The fragment was found in the list
continue;
// Ok, we have a new fragment on our hands - generate the fragment object
cMessage msg( iFrag );
if( msg.isComplete() )
// It's only one piece, dispatch right away
m_pCallback->onMessage( msg );
else
// This requires more parts add it into the queue to wait
m_messages.push_back( msg );
}
}

View file

@ -0,0 +1,159 @@
// ProtocolStack.h
// Declaration of class cProtocolStack
#ifndef __PROTOCOLSTACK_H
#define __PROTOCOLSTACK_H
#include <crtdbg.h> // For assertions
#define DEFAULT_HEADER_SIZE 16
#define FRAGMENT_SIZE 448
#define MAX_FRAGMENT_COUNT 1024
#pragma pack( push, 1 )
// The packet header
struct cPacketHeader
{
DWORD m_dwSequence;
DWORD m_dwFlags;
DWORD m_dwCRC;
WORD m_wUnk1;
WORD m_wUnk2;
WORD m_wTotalSize;
WORD m_wUnk3;
};
#pragma pack( pop )
class FragmentMask
{
public:
FragmentMask () { ::memset (m_mask, 0, sizeof (m_mask)); m_size = 0; }
void SetSize (WORD wSize)
{
_ASSERTE (wSize < MAX_FRAGMENT_COUNT);
m_size = wSize;
::memset (m_mask, 0, sizeof (m_mask));
for (WORD wIndex = 0; wIndex < wSize; ++wIndex)
{
m_mask[wIndex/32] |= (1L << (wIndex % 32));
}
}
void GotFragment (WORD wWhich)
{
_ASSERTE (wWhich < m_size && wWhich >= 0);
m_mask[wWhich/32] &= ~(1 << (wWhich % 32));
}
bool IsComplete ()
{
for (WORD wLoop = 0; wLoop < (FRAGMENT_SIZE/32); ++wLoop)
{
if (m_mask[wLoop])
{
return false;
}
}
return true;
}
private:
DWORD m_mask[FRAGMENT_SIZE/32];
WORD m_size;
};
class cMessageStack
{
public:
#pragma pack( push, 1 )
struct cMessageHeader
{
DWORD m_dwSequence;
DWORD m_dwObjectID;
WORD m_wFragmentCount;
WORD m_wFragmentLength;
WORD m_wFragmentIndex,
m_wUnknown1;
};
#pragma pack( pop )
class cMessage
{
protected:
// DWORD m_dwFragmentsMask;
BYTE *m_pbData;
mutable bool m_bOwn;
mutable FragmentMask m_FragmentMask;
public:
cMessage( BYTE *pbData );
cMessage( const cMessage &msg );
~cMessage();
cMessageHeader *getMessageHeader() const
{
return reinterpret_cast< cMessageHeader * >( m_pbData );
}
cMessage &operator= ( const cMessage &msg );
BYTE *getBody() const
{
return m_pbData + sizeof( cMessageHeader );
}
DWORD getBodyLength() const
{
return getMessageHeader()->m_wFragmentLength - sizeof( cMessageHeader );
}
bool isComplete() const
{
return m_FragmentMask.IsComplete ();
}
DWORD getMessageCode() const
{
return *reinterpret_cast< DWORD * >( m_pbData + sizeof( cMessageHeader ) );
}
bool fragmentMatch( BYTE *pFragmentStart );
void insertFragment( BYTE *pFragmentStart );
static DWORD calcMessageLength( BYTE *pbHeader );
};
// Objects wishing to receive
class cCallback
{
public:
virtual void onMessage( cMessage & ) = 0;
};
private:
typedef std::list< cMessage > cMessageList;
cCallback *m_pCallback;
cMessageList m_messages;
public:
cMessageStack();
~cMessageStack();
void start( cCallback * );
void stop();
void processPacket( DWORD dwLength, BYTE *pbPayload );
private:
void splitPacket( DWORD dwLength, BYTE *pbPayload );
};
#endif

View file

@ -0,0 +1,38 @@
/*********************************************************
DllData file -- generated by MIDL compiler
DO NOT ALTER THIS FILE
This file is regenerated by MIDL on every IDL file compile.
To completely reconstruct this file, delete it and rerun MIDL
on all the IDL files in this DLL, specifying this file for the
/dlldata command line option
*********************************************************/
#define PROXY_DELEGATION
#include <rpcproxy.h>
#ifdef __cplusplus
extern "C" {
#endif
EXTERN_PROXY_FILE( Inject )
PROXYFILE_LIST_START
/* Start of list */
REFERENCE_PROXY_FILE( Inject ),
/* End of list */
PROXYFILE_LIST_END
DLLDATA_ROUTINES( aProxyFileList, GET_DLL_CLSID )
#ifdef __cplusplus
} /*extern "C" */
#endif
/* end of generated dlldata file */