/////////////////////////////////////////////////////////////
//
// CProxyDirect3DVertexBuffer::Lock
//
// If lock is writable, tell manager that range content will change
//
/////////////////////////////////////////////////////////////
HRESULT CProxyDirect3DVertexBuffer::Lock ( UINT OffsetToLock, UINT SizeToLock, void** ppbData, DWORD Flags )
{
    m_stats.iLockedCount++;

    if ( ( Flags & D3DLOCK_READONLY ) == 0 )
    {
        CAdditionalVertexStreamManager::GetSingleton ()->OnVertexBufferRangeInvalidated ( m_pOriginal, OffsetToLock, SizeToLock );
        CVertexStreamBoundingBoxManager::GetSingleton ()->OnVertexBufferRangeInvalidated ( m_pOriginal, OffsetToLock, SizeToLock );
    }

    *ppbData = NULL;
    HRESULT hr = m_pOriginal->Lock ( OffsetToLock, SizeToLock, ppbData, Flags );

    if( FAILED( hr ) )
    {
        SString strMessage( "Lock VertexBuffer fail: hr:%x Length:%x Usage:%x FVF:%x Pool:%x OffsetToLock:%x SizeToLock:%x Flags:%x"
                                                        , hr, m_iMemUsed, m_dwUsage, m_dwFVF, m_pool, OffsetToLock, SizeToLock, Flags );
        WriteDebugEvent( strMessage );
        AddReportLog( 8620, strMessage );
        CCore::GetSingleton ().LogEvent ( 620, "Lock VertexBuffer", "", strMessage );
    }
    else
    if ( *ppbData == NULL )
    {
        SString strMessage( "Lock VertexBuffer result NULL: hr:%x Length:%x Usage:%x FVF:%x Pool:%x OffsetToLock:%x SizeToLock:%x Flags:%x"
                                                        , hr, m_iMemUsed, m_dwUsage, m_dwFVF, m_pool, OffsetToLock, SizeToLock, Flags );
        WriteDebugEvent( strMessage );
        AddReportLog( 8621, strMessage );
        CCore::GetSingleton ().LogEvent ( 621, "Lock VertexBuffer NULL", "", strMessage );
    }
    return hr;
}
////////////////////////////////////////////////
//
// CreateDeviceSecondCallCheck
//
// Check for, and handle subsequent calls to create device
// Know to occur with RTSSHooks.dll (EVGA Precision X on screen display)
//
////////////////////////////////////////////////
bool CreateDeviceSecondCallCheck(HRESULT& hOutResult, IDirect3D9* pDirect3D, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags,
                                 D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface)
{
    static uint uiCreateCount = 0;

    // Also check for invalid size
    if (pPresentationParameters->BackBufferWidth == 0)
    {
        WriteDebugEvent(SString(" Passing through call #%d to CreateDevice because size is invalid", uiCreateCount));
        return true;
    }

    // Also check for calls from other threads
    if (!IsMainThread())
    {
        SString strMessage(" Passing through call #%d to CreateDevice because not main thread", uiCreateCount);
        WriteDebugEvent(strMessage);
        AddReportLog(8627, strMessage);
        return true;
    }

    if (++uiCreateCount == 1)
        return false;
    WriteDebugEvent(SString(" Passing through call #%d to CreateDevice", uiCreateCount));
    hOutResult = pDirect3D->CreateDevice(Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface);
    return true;
}
/////////////////////////////////////////////////////////////
//
// CProxyDirect3DIndexBuffer::Lock
//
// For stats
//
/////////////////////////////////////////////////////////////
HRESULT CProxyDirect3DIndexBuffer::Lock(UINT OffsetToLock, UINT SizeToLock, void** ppbData, DWORD Flags)
{
    m_stats.iLockedCount++;

    *ppbData = NULL;
    HRESULT hr = m_pOriginal->Lock(OffsetToLock, SizeToLock, ppbData, Flags);

    if (FAILED(hr))
    {
        SString strMessage("Lock IndexBuffer fail: hr:%x Length:%x Usage:%x Format:%x Pool:%x OffsetToLock:%x SizeToLock:%x Flags:%x", hr, m_iMemUsed,
                           m_dwUsage, m_format, m_pool, OffsetToLock, SizeToLock, Flags);
        WriteDebugEvent(strMessage);
        AddReportLog(8625, strMessage);
        CCore::GetSingleton().LogEvent(625, "Lock IndexBuffer", "", strMessage);
    }
    else if (*ppbData == NULL)
    {
        SString strMessage("Lock IndexBuffer result NULL: hr:%x Length:%x Usage:%x Format:%x Pool:%x OffsetToLock:%x SizeToLock:%x Flags:%x", hr, m_iMemUsed,
                           m_dwUsage, m_format, m_pool, OffsetToLock, SizeToLock, Flags);
        WriteDebugEvent(strMessage);
        AddReportLog(8626, strMessage);
        CCore::GetSingleton().LogEvent(626, "Lock IndexBuffer NULL", "", strMessage);
    }
    return hr;
}
Exemple #4
0
int WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, PVOID pvNothing)
{
    CFilePathTranslator     FileTranslator;
    std::string             WorkingDirectory;

    if ( dwReason == DLL_PROCESS_ATTACH )
    {
        WriteDebugEvent( SString( "DLL_PROCESS_ATTACH %08x", pvNothing ) );
        if ( IsGTAProcess() )
        {
            WriteDebugEvent( SString( "ModuleFileName: %s", *GetLaunchPathFilename() ) );

            AddUtf8FileHooks();

            // Set low frag heap for XP
            ULONG heapInfo = 2 ;
            HeapSetInformation( GetProcessHeap(), HeapCompatibilityInformation, &heapInfo, sizeof( heapInfo ) );

            FileTranslator.GetGTARootDirectory ( WorkingDirectory );
            SetCurrentDirectory ( WorkingDirectory.c_str ( ) );

            // For dll searches, this call replaces the current directory entry and turns off 'SafeDllSearchMode'
            // Meaning it will search the supplied path before the system and windows directory.
            // http://msdn.microsoft.com/en-us/library/ms682586%28VS.85%29.aspx
            SetDllDirectory( CalcMTASAPath ( "MTA" ) );

            g_pCore = new CCore;

            FileTranslator.GetGTARootDirectory ( WorkingDirectory );
            SetCurrentDirectory ( WorkingDirectory.c_str ( ) );
        }
    } 
    else if (dwReason == DLL_PROCESS_DETACH)
    {
        WriteDebugEvent( SString( "DLL_PROCESS_DETACH %08x", pvNothing ) );
        if ( IsGTAProcess () )
        {
            RemoveUtf8FileHooks();

            AddReportLog( 7102, "Core - PROCESS_DETACH" );
            // For now, TerminateProcess if any destruction is attempted (or we'll crash)
            TerminateProcess ( GetCurrentProcess (), 0 );

            if ( g_pCore )
            {
                delete g_pCore;
                g_pCore = NULL;
            }
        }
    }

    return TRUE;
}
/////////////////////////////////////////////////////////////
//
// CDirect3DEvents9::CreateTexture
//
//
//
/////////////////////////////////////////////////////////////
HRESULT CDirect3DEvents9::CreateTexture ( IDirect3DDevice9 *pDevice, UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture9** ppTexture, HANDLE* pSharedHandle )
{
    HRESULT hr;

    for ( uint i = 0 ; i < 2 ; i++ )
    {
        hr = pDevice->CreateTexture ( Width, Height, Levels, Usage, Format, Pool, ppTexture, pSharedHandle );
        if( SUCCEEDED( hr ) )
            break;

        if ( hr != D3DERR_OUTOFVIDEOMEMORY || i > 0 )
        {
            SString strMessage( "CreateTexture fail: hr:%x W:%x H:%x L:%x Usage:%x Format:%x Pool:%x", hr, Width, Height, Levels, Usage, Format, Pool );
            WriteDebugEvent( strMessage );
            AddReportLog( 8612, strMessage );
            CCore::GetSingleton ().LogEvent ( 612, "CreateTexture", "", strMessage );
            return hr;
        }

        pDevice->EvictManagedResources ();
    }

    // Create proxy so we can track when it's finished with
    *ppTexture = new CProxyDirect3DTexture ( pDevice, *ppTexture, Width, Height, Levels, Usage, Format, Pool );
    return hr;
}
/////////////////////////////////////////////////////////////
//
// CDirect3DEvents9::CreateIndexBuffer
//
//
//
/////////////////////////////////////////////////////////////
HRESULT CDirect3DEvents9::CreateIndexBuffer ( IDirect3DDevice9 *pDevice, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9** ppIndexBuffer, HANDLE* pSharedHandle )
{
    HRESULT hr;

    for ( uint i = 0 ; i < 2 ; i++ )
    {
        hr = pDevice->CreateIndexBuffer ( Length, Usage, Format, Pool, ppIndexBuffer, pSharedHandle );
        if( SUCCEEDED( hr ) )
            break;

        if ( hr != D3DERR_OUTOFVIDEOMEMORY || i > 0 )
        {
            SString strMessage( "CreateIndexBuffer fail: hr:%x Length:%x Usage:%x Format:%x Pool:%x", hr, Length, Usage, Format, Pool );
            WriteDebugEvent( strMessage );
            AddReportLog( 8611, strMessage );
            CCore::GetSingleton ().LogEvent ( 611, "CreateIndexBuffer", "", strMessage );
            return hr;
        }

        pDevice->EvictManagedResources ();
    }

    // Create proxy so we can track when it's finished with
    *ppIndexBuffer = new CProxyDirect3DIndexBuffer ( pDevice, *ppIndexBuffer, Length, Usage, Format, Pool );
    return hr;
}
/////////////////////////////////////////////////////////////
//
// CDirect3DEvents9::CreateVertexBuffer
//
// Creates a proxy object for the new vertex buffer
//
/////////////////////////////////////////////////////////////
HRESULT CDirect3DEvents9::CreateVertexBuffer ( IDirect3DDevice9 *pDevice, UINT Length,DWORD Usage,DWORD FVF,D3DPOOL Pool,IDirect3DVertexBuffer9** ppVertexBuffer,HANDLE* pSharedHandle )
{
    HRESULT hr;

    // We may have to look at the contents to generate normals (Not needed for dynamic buffers)
    if ( ( Usage & D3DUSAGE_DYNAMIC ) == 0 )
        Usage &= -1 - D3DUSAGE_WRITEONLY;

    for ( uint i = 0 ; i < 2 ; i++ )
    {
        hr = pDevice->CreateVertexBuffer ( Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle );
        if( SUCCEEDED( hr ) )
            break;

        if ( hr != D3DERR_OUTOFVIDEOMEMORY || i > 0 )
        {
            SString strMessage( "CreateVertexBuffer fail: hr:%x Length:%x Usage:%x FVF:%x Pool:%x", hr, Length, Usage, FVF, Pool );
            WriteDebugEvent( strMessage );
            AddReportLog( 8610, strMessage );
            CCore::GetSingleton ().LogEvent ( 610, "CreateVertexBuffer", "", strMessage );
            return hr;
        }

        pDevice->EvictManagedResources ();
    }

    // Create proxy
    *ppVertexBuffer = new CProxyDirect3DVertexBuffer ( pDevice, *ppVertexBuffer, Length, Usage, FVF, Pool );
    return hr;
}
//////////////////////////////////////////////////////////
//
// GetPatchRequirementAltModules
//
// Return true if checksum for some dlls will cause problems
//
//////////////////////////////////////////////////////////
bool GetPatchRequirementAltModules( void )
{
    // Only do file check once per launch
    static bool bDone = false;
    static bool bMismatch = false;

    if ( !bDone )
    {
        SString strGTAPath = GetGTAPath();
        if ( !strGTAPath.empty() )
        {
            struct {
                const char* szMd5;
                const char* szFilename;
            } fileList[] = { { "309D860FC8137E5FE9E7056C33B4B8BE", "eax.dll" },
                             { "0602F672BA595716E64EC4040E6DE376", "ogg.dll" },
                             { "2840F08DD9753A5B13C60D6D1C165C9A", "vorbis.dll" },
                             { "2B7B803311D2B228F065C45D13E1AEB2", "vorbisfile.dll" } };

            for ( uint i = 0 ; i < NUMELMS( fileList ) ; i++ )
            {
                SString strPathFilename = PathJoin( strGTAPath, fileList[i].szFilename );
                SString strMd5 = CMD5Hasher::CalculateHexString( strPathFilename );
                if ( strMd5.CompareI( fileList[i].szMd5 ) == false )
                    bMismatch = true;
            }
        }
        bDone = true;

        if ( bMismatch )
            WriteDebugEvent( "PatchRequirementAltModules: Need to use alt modules" );
    }
    return bMismatch;
}
CProxyDirectInput8::CProxyDirectInput8(IDirectInput8* pDevice)
{
    WriteDebugEvent(SString("CProxyDirectInput8::CProxyDirectInput8 %08x", this));

    // Initalize our local variable.
    m_pDevice = pDevice;
}
CDirectInputHookManager::~CDirectInputHookManager()
{
    WriteDebugEvent("CDirectInputHookManager::~CDirectInputHookManager");

    // Delete our hook object.
    SAFE_DELETE(m_pDirectInputHook8);
}
ULONG   CProxyDirect3DDevice9::Release                        ( VOID )
{
    ULONG       ulResult;
    IUnknown *  pDestroyedDevice;

    // Check to see if we should destroy ourself
    if ( --m_dwRefCount == 0 )
    {
        WriteDebugEvent ( "Releasing IDirect3DDevice9 Proxy..." );

		// Call event handler
		CDirect3DEvents9::OnDirect3DDeviceDestroy ( m_pDevice );

        // Save device so we can destroy it after.
        pDestroyedDevice = m_pDevice;

        // Destroy...
        delete this;

		// Release device...
        ulResult = pDestroyedDevice->Release ( );

		return ulResult;
    }
	
	ulResult = m_pDevice->Release ( );

    return ulResult;
}
HRESULT CProxyDirect3DDevice9::Reset                          ( D3DPRESENT_PARAMETERS* pPresentationParameters )
{
	WriteDebugEvent ( "CProxyDirect3DDevice9::Reset" );

    GetVideoModeManager ()->PreReset ( pPresentationParameters );

    HRESULT hResult;

    // Call our event handler.
    CDirect3DEvents9::OnInvalidate ( m_pDevice );

    // Call the real reset routine.
    hResult = m_pDevice->Reset ( pPresentationParameters );

    GetVideoModeManager ()->PostReset ( pPresentationParameters );

    // Update our data.
    m_pData->StoreViewport ( 0, 0, 
                            pPresentationParameters->BackBufferWidth,
                            pPresentationParameters->BackBufferHeight );


    // Call our event handler.
    CDirect3DEvents9::OnRestore ( m_pDevice );

    return hResult;   
}
Exemple #13
0
CProxyDirect3D8::~CProxyDirect3D8 ( )
{
    WriteDebugEvent ( "CProxyDirect3D8::~CProxyDirect3D8" );
    m_pDevice       = NULL;
    m_dwRefCount    = 1;

}
CSetCursorPosHook::CSetCursorPosHook ( void ) 
{
    WriteDebugEvent ( "CSetCursorPosHook::CSetCursorPosHook" );

    m_bCanCall          = true;
    m_pfnSetCursorPos   = NULL;
}
ULONG   CProxyDirectInput8::Release ( VOID )
{
    ULONG       ulRefCount;
    IUnknown *  pDestroyedDevice;

    // Determine if we should self destruct
    if ( m_dwRefCount-- == 0 )
    {
        WriteDebugEvent ( "Releasing IDirectInput8 Proxy..." );

        // Save device so we can destroy it after.
        pDestroyedDevice = m_pDevice;

        delete this;

        // Call the release routine and get the refcount.
        ulRefCount = pDestroyedDevice->Release ( );

        return ulRefCount;
    }

    // Call the release routine and get the refcount.
    ulRefCount = m_pDevice->Release ( );
    
    return ulRefCount;
}
CDirectInputHookManager::CDirectInputHookManager()
{
    WriteDebugEvent("CDirectInputHookManager::CDirectInputHookManager");

    // Initialize our member variables.
    m_pDirectInputHook8 = NULL;
}
CDirect3DHook9::CDirect3DHook9 (  )
{
    WriteDebugEvent ( "CDirect3DHook9::CDirect3DHook9" );

    m_pfnDirect3DCreate9 = NULL;
    m_bDirect3DCreate9Suspended = false;
}
CProxyDirectInput8::CProxyDirectInput8 ( IDirectInput8* pDevice )
{
    WriteDebugEvent ( "CProxyDirectInput8::CProxyDirectInput8" );

    // Initalize our local variable.
    m_pDevice       = pDevice;
    m_dwRefCount    = 0;
}
CMessageLoopHook::CMessageLoopHook ( )
{
    WriteDebugEvent ( "CMessageLoopHook::CMessageLoopHook" );
    m_HookedWindowProc      = NULL;
    m_HookedWindowHandle    = NULL;
    m_bRefreshMsgQueueEnabled = true;
    m_MovementDummyWindow   = NULL;
}
CProxyDirect3D9::CProxyDirect3D9 ( IDirect3D9* pInterface )
{
    WriteDebugEvent ( "CProxyDirect3D9::CProxyDirect3D9" );
    m_pDevice       = pInterface;

	// Give ourself a matching refcount.
	pInterface->AddRef ( );
	m_dwRefCount = pInterface->Release ( );
}
CSetCursorPosHook::~CSetCursorPosHook ( void ) 
{
    WriteDebugEvent ( "CSetCursorPosHook::~CSetCursorPosHook" );

    if ( m_pfnSetCursorPos != NULL )
    {
        RemoveHook ( );
    }
}
////////////////////////////////////////////////
//
// CreateDeviceSecondCallCheck
//
// Check for, and handle subsequent calls to create device
// Know to occur with RTSSHooks.dll (EVGA Precision X on screen display)
//
////////////////////////////////////////////////
bool CreateDeviceSecondCallCheck( HRESULT& hOutResult, IDirect3D9* pDirect3D, UINT Adapter, D3DDEVTYPE DeviceType, HWND hFocusWindow, DWORD BehaviorFlags, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DDevice9** ppReturnedDeviceInterface )
{
    static uint uiCreateCount = 0;
    if ( ++uiCreateCount == 1 )
        return false;
    WriteDebugEvent ( SString ( " Passing through call #%d to CreateDevice", uiCreateCount ) );
    hOutResult = pDirect3D->CreateDevice ( Adapter, DeviceType, hFocusWindow, BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface );
    return true;
}
bool CDirect3DHook9::RemoveHook ( )
{
    if ( UsingAltD3DSetup() )
        return true;

    m_bDirect3DCreate9Suspended = true;
    WriteDebugEvent ( "Direct3D9 hook suspended." );
    return true;
}
// Proxy constructor and destructor.
CProxyDirect3DDevice9::CProxyDirect3DDevice9(IDirect3DDevice9* pDevice)
{
    WriteDebugEvent(SString("CProxyDirect3DDevice9::CProxyDirect3DDevice9 %08x", this));

    // Set our wrapped device.
    m_pDevice = pDevice;

    // Get CDirect3DData pointer.
    m_pData = CDirect3DData::GetSingletonPtr();

    g_pProxyDevice = this;
    g_pDeviceState = &DeviceState;
    pDevice->GetDeviceCaps(&g_pDeviceState->DeviceCaps);

    //
    // Get video card installed memory
    //
    D3DDEVICE_CREATION_PARAMETERS creationParameters;
    m_pDevice->GetCreationParameters(&creationParameters);
    int iAdapter = creationParameters.AdapterOrdinal;

    IDirect3D9* pD3D9 = CProxyDirect3D9::StaticGetDirect3D();
    if (!pD3D9)
        m_pDevice->GetDirect3D(&pD3D9);

    D3DADAPTER_IDENTIFIER9 adaptIdent;
    ZeroMemory(&adaptIdent, sizeof(D3DADAPTER_IDENTIFIER9));
    pD3D9->GetAdapterIdentifier(iAdapter, 0, &adaptIdent);

    int iVideoCardMemoryKBTotal = GetWMIVideoAdapterMemorySize(adaptIdent.DeviceName) / 1024;

    // Just incase, fallback to using texture memory stats
    if (iVideoCardMemoryKBTotal < 16)
        iVideoCardMemoryKBTotal = m_pDevice->GetAvailableTextureMem() / 1024;

    g_pDeviceState->AdapterState.InstalledMemoryKB = iVideoCardMemoryKBTotal;

    //
    // Get video card name
    //
    g_pDeviceState->AdapterState.Name = adaptIdent.Description;

    //
    // Get max anisotropic setting
    //
    g_pDeviceState->AdapterState.MaxAnisotropicSetting = 0;

    // Make sure device can do anisotropic minification and trilinear filtering
    if ((g_pDeviceState->DeviceCaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC) &&
        (g_pDeviceState->DeviceCaps.TextureFilterCaps & D3DPTFILTERCAPS_MIPFLINEAR))
    {
        int iLevel = std::max<int>(1, g_pDeviceState->DeviceCaps.MaxAnisotropy);
        // Convert level 1/2/4/8/16 into setting 0/1/2/3/4
        while (iLevel >>= 1)
            g_pDeviceState->AdapterState.MaxAnisotropicSetting++;
    }
Exemple #25
0
int WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, PVOID pvNothing)
{
    CFilePathTranslator     FileTranslator;
    std::string             WorkingDirectory;

    if ( dwReason == DLL_PROCESS_ATTACH )
    {
        WriteDebugEvent( SString( "DLL_PROCESS_ATTACH %08x", pvNothing ) );
        if ( IsRealDeal () )
        {
            FileTranslator.GetGTARootDirectory ( WorkingDirectory );
            SetCurrentDirectory ( WorkingDirectory.c_str ( ) );

            // For dll searches, this call replaces the current directory entry and turns off 'SafeDllSearchMode'
            // Meaning it will search the supplied path before the system and windows directory.
            // http://msdn.microsoft.com/en-us/library/ms682586%28VS.85%29.aspx
            SetDllDirectory( CalcMTASAPath ( "MTA" ) );

            g_pCore = new CCore;

            FileTranslator.GetGTARootDirectory ( WorkingDirectory );
            SetCurrentDirectory ( WorkingDirectory.c_str ( ) );
        }
    } 
    else if (dwReason == DLL_PROCESS_DETACH)
    {
        WriteDebugEvent( SString( "DLL_PROCESS_DETACH %08x", pvNothing ) );
        if ( IsRealDeal () )
        {
            // For now, TerminateProcess if any destruction is attempted (or we'll crash)
            TerminateProcess ( GetCurrentProcess (), 0 );

            if ( g_pCore )
            {
                delete g_pCore;
                g_pCore = NULL;
            }
        }
    }

    return TRUE;
}
ULONG CProxyDirectInput8::Release(VOID)
{
    // Call original function
    ULONG ulRefCount = m_pDevice->Release();
    if (ulRefCount == 0)
    {
        WriteDebugEvent("Releasing IDirectInput8 Proxy...");
        delete this;
    }
    return ulRefCount;
}
Exemple #27
0
//
// Returns true if dll has been loaded with GTA.
//
bool IsRealDeal ( void )
{
    // Get current module full path
    char szBuffer[64000];
    GetModuleFileName ( NULL, szBuffer, sizeof(szBuffer) - 1 );
    WriteDebugEvent( SString( "ModuleFileName: %s", szBuffer ) );
    if ( SStringX( szBuffer ).EndsWithI( "gta_sa.exe" )
        || SStringX( szBuffer ).EndsWithI( "proxy_sa.exe" ) )
        return true;
    return false;
}
bool CDirect3DHook9::ApplyHook ( )
{
    if ( UsingAltD3DSetup() )
        return true;

    // Hook Direct3DCreate9.
    if ( !m_pfnDirect3DCreate9 )
    {
        m_pfnDirect3DCreate9 = reinterpret_cast < pDirect3DCreate > ( DetourFunction ( DetourFindFunction ( "D3D9.DLL", "Direct3DCreate9" ), 
                                                                      reinterpret_cast < PBYTE > ( API_Direct3DCreate9 ) ) );

        WriteDebugEvent ( SString( "Direct3D9 hook applied %08x", m_pfnDirect3DCreate9 ) );
    }
    else
    {
        WriteDebugEvent ( "Direct3D9 hook resumed." );
        m_bDirect3DCreate9Suspended = false;
    }
    return true;
}
void CDirect3DEvents9::OnInvalidate ( IDirect3DDevice9 *pDevice )
{
    WriteDebugEvent ( "CDirect3DEvents9::OnInvalidate" );

    // Invalidate the VMR9 Manager
    //CVideoManager::GetSingleton ().OnLostDevice ();

    // Notify gui
    CLocalGUI::GetSingleton().Invalidate ();

    CGraphics::GetSingleton ().OnDeviceInvalidate ( pDevice );
}
void DebugInfoXmlWriter::WriteDebugEventList(const std::vector<DebugEvent>& vecDebugEvents)
{
   m_spWriter->WriteStartElement(_T("debug-event-list"));
   CString cszText; cszText.Format(_T("%u"), vecDebugEvents.size());
   m_spWriter->WriteAttributeString(_T("event-count"), cszText);
   m_spWriter->WriteStartElementEnd();

   for (size_t i=0,iMax=vecDebugEvents.size(); i<iMax; i++)
      WriteDebugEvent(i, vecDebugEvents[i]);

   m_spWriter->WriteEndElement();
}