diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/mdmpRipper | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'utils/mdmpRipper')
21 files changed, 2301 insertions, 0 deletions
diff --git a/utils/mdmpRipper/CDbgOutput.cpp b/utils/mdmpRipper/CDbgOutput.cpp new file mode 100644 index 0000000..f4e5ebb --- /dev/null +++ b/utils/mdmpRipper/CDbgOutput.cpp @@ -0,0 +1,86 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +/* CDbgOutput.cpp + +*****************************************************************************/ +#define WIN32_LEAN_AND_MEAN +#define STRICT +#include <windows.h> +#include <dbghelp.h> +#include <dbgeng.h> + +#include "vgui/IVGui.h" +#include "vgui/IPanel.h" +#include "tier1/KeyValues.h" +#include "vgui_controls/Frame.h" + +#include "CMDRipperMain.h" + +#include "CDbgOutput.h" + +using namespace vgui; + + +CDbgOutput::CDbgOutput() +{ + m_iRefCount = 0; + m_Target = 0; +} + + +CDbgOutput::~CDbgOutput() +{ +} + + +STDMETHODIMP CDbgOutput::QueryInterface( THIS_ IN REFIID InterfaceId, + OUT PVOID* Interface) +{ + *Interface = NULL; + + if ( IsEqualIID( InterfaceId, __uuidof( IUnknown ) ) || + IsEqualIID( InterfaceId, __uuidof( IDebugOutputCallbacks ) ) ) + { + *Interface = ( IDebugOutputCallbacks * )this; + AddRef( ); + return S_OK; + } + else + { + return E_NOINTERFACE; + } +} + + +STDMETHODIMP_( ULONG )CDbgOutput::AddRef( THIS ) +{ + return ( ++m_iRefCount ); +} + + +STDMETHODIMP_( ULONG )CDbgOutput::Release( THIS ) +{ + return ( --m_iRefCount ); +} + + +STDMETHODIMP CDbgOutput::Output( THIS_ IN ULONG Mask, IN PCSTR Text ) +{ + if (Text) + { + KeyValues *pkv = new KeyValues( "DebugOutput", "iMask", Mask ); + pkv->SetString( "pszDebugText", Text ); + + ivgui()->DPrintf( "CDbgOutput::Output() about to post [%s]", Text ); + g_pCMDRipperMain->PostMessage( m_Target, pkv ); + } + + return S_OK; +} + + +void CDbgOutput::SetOutputPanel( vgui::VPANEL Target ) +{ + m_Target = Target; +} + +/* CDbgOutput.cpp */ diff --git a/utils/mdmpRipper/CDbgOutput.h b/utils/mdmpRipper/CDbgOutput.h new file mode 100644 index 0000000..050f6bb --- /dev/null +++ b/utils/mdmpRipper/CDbgOutput.h @@ -0,0 +1,35 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +/* CDbgOutput.h + +*****************************************************************************/ +#ifndef CDBGOUTPUT_H +# define CDBGOUTPUT_H + + +class CDbgOutput : public IDebugOutputCallbacks +{ +public: + // Ctor/dtor + CDbgOutput(); + ~CDbgOutput(); + + // IUnknown. + STDMETHOD( QueryInterface )( THIS_ IN REFIID InterfaceId, + OUT PVOID* Interface ); + STDMETHOD_( ULONG, AddRef )( THIS ); + STDMETHOD_( ULONG, Release )( THIS ); + + // IDebugOutputCallbacks. + STDMETHOD( Output )( THIS_ IN ULONG Mask, IN PCSTR Text ); + + void SetOutputPanel( vgui::VPANEL Target ); + +private: + int m_iRefCount; + vgui::VPANEL m_Target; +}; + + +#endif /* CDBGOUTPUT_H */ + +/* CDbgOutput.h */ diff --git a/utils/mdmpRipper/CMDDetailPanel.cpp b/utils/mdmpRipper/CMDDetailPanel.cpp new file mode 100644 index 0000000..b76a290 --- /dev/null +++ b/utils/mdmpRipper/CMDDetailPanel.cpp @@ -0,0 +1,40 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +#include "vgui_controls/HTML.h" +#include "CMDDetailPanel.h" + +using namespace vgui; + +CMDDetailPanel::CMDDetailPanel( vgui::Panel *pParent, const char *pName ) : + BaseClass( pParent, pName, true ) +{ + SetParent( pParent ); + m_pDetailWindow = new vgui::HTML(this, "Details"); + m_pDetailWindow->SetParent( this ); + m_pDetailWindow->SetSize( 770, 475 ); + LoadControlSettings( "MDDetailPanel.res" ); + m_pDetailWindow->OpenURL( "about:blank" ); +} + +void CMDDetailPanel::OpenURL( const char *url ) +{ + m_pDetailWindow->OpenURL( "about:blank" ); + m_pDetailWindow->OpenURL( url ); + m_pDetailWindow->SetVisible( true ); +} + + +void CMDDetailPanel::OnCommand( const char *pCommand ) +{ + if ( !Q_strcmp( pCommand, "Close" ) ) + { + Close(); + } +} + +void CMDDetailPanel::Close() +{ + m_pDetailWindow->SetVisible( false ); + SetVisible( false ); + KeyValues *kv = new KeyValues( "Refresh" ); + this->PostActionSignal( kv ); +} diff --git a/utils/mdmpRipper/CMDDetailPanel.h b/utils/mdmpRipper/CMDDetailPanel.h new file mode 100644 index 0000000..ad82269 --- /dev/null +++ b/utils/mdmpRipper/CMDDetailPanel.h @@ -0,0 +1,31 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +#include "mdmpRipper.h" +#include "vgui_controls/MessageMap.h" +#include "vgui_controls/MenuBar.h" +#include "vgui_controls/Menu.h" +#include "tier1/KeyValues.h" +#include "vgui/ISurface.h" +#include "vgui_controls/EditablePanel.h" +#include "vgui_controls/HTML.h" + +#ifndef MDDETAILPANEL_H +#define MDDETAILPANEL_H + +#ifdef _WIN32 +#pragma once +#endif + +using namespace vgui; + +class CMDDetailPanel : public vgui::EditablePanel +{ + vgui::HTML *m_pDetailWindow; + DECLARE_CLASS_SIMPLE( CMDDetailPanel, vgui::EditablePanel ); +public: + CMDDetailPanel( vgui::Panel *pParent, const char *pName ); + virtual void OpenURL( const char *url ); + virtual void OnCommand( const char *pCommand ); + virtual void Close(); +}; + +#endif // MDDETAILPANEL_H diff --git a/utils/mdmpRipper/CMDErrorPanel.cpp b/utils/mdmpRipper/CMDErrorPanel.cpp new file mode 100644 index 0000000..cc123ec --- /dev/null +++ b/utils/mdmpRipper/CMDErrorPanel.cpp @@ -0,0 +1,139 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +//#include <windows.h> +#include "mdmpRipper.h" +#include "vgui_controls/MessageMap.h" +#include "vgui_controls/MenuBar.h" +#include "vgui_controls/Menu.h" +#include "vgui_controls/TextEntry.h" +#include "vgui/ISurface.h" +#include "vgui_controls/Frame.h" +#include "CMDErrorPanel.h" +#include "vgui_controls/ListPanel.h" +#include "KeyValues.h" +#include "vgui/ISystem.h" +#include "CMDDetailPanel.h" + +using namespace vgui; + +CMDErrorPanel::CMDErrorPanel( vgui::Panel *pParent, const char *pName ) : + BaseClass( pParent, pName ) +{ + SetParent( pParent ); + m_pTokenList = new ListPanel(this, "ErrorList"); + m_pTokenList->AddColumnHeader(0, "errorid", "Error ID", 100, 0); + m_pTokenList->AddColumnHeader(1, "module", "Module Name", 200, 0); + m_pTokenList->AddColumnHeader(2, "count", "Count", 100, 0); + m_pTokenList->AddColumnHeader(3, "minidumps", "Minidump Count", 100, 0); + + m_pMaxResults = new vgui::TextEntry( this, "maxResults" ); + m_pQueryCounts = new vgui::TextEntry( this, "numCrashes" ); + + m_pMaxResults->SetText( "100" ); + m_pQueryCounts->SetText( "10000" ); + + LoadControlSettings( "MDErrorPanel.res" ); +} + +void CMDErrorPanel::OnCommand( const char *pCommand ) +{ + if ( !Q_strcmp( pCommand, "Close" ) ) + { + Close(); + } + if ( !Q_strcmp( pCommand, "CheckModules" ) ) + { + CheckModules(); + } + if ( !Q_strcmp( pCommand, "NewQuery" ) ) + { + NewQuery(); + } + if ( !Q_strcmp( pCommand, "Download" ) ) + { + DownloadMinidumps(); + } + if ( !Q_strcmp( pCommand, "Details" ) ) + { + DetailScreen(); + } +} + +void CMDErrorPanel::Close() +{ + if ( this ) + { + m_pTokenList->DeleteAllItems(); + SetVisible( false ); + KeyValues *kv = new KeyValues( "Refresh" ); + this->PostActionSignal( kv ); + } +} + +void CMDErrorPanel::CheckModules() +{ + char sql[255] = ""; + extern void getMiniDumpHandles( char *pszQuery, const char *errorid, CUtlVector<HANDLE> *pMiniDumpHandles ); + + + int selectedIndex = m_pTokenList->GetSelectedItem( 0 ); + void *kv = m_pTokenList->GetItem( selectedIndex ); + if ( kv ) + { + strcat( sql, "select MinidumpFilePath from minidumps where ErrorID=" ); + strcat( sql, ((KeyValues *)kv)->GetString( "errorid", "" ) ); + strcat( sql, " order by MinidumpFilePath desc limit " ); + strcat( sql, ((KeyValues *)kv)->GetString( "minidumps", "" ) ); + strcat( sql, ";" ); + getMiniDumpHandles( sql, ((KeyValues *)kv)->GetString( "errorid", "" ), &m_MiniDumpHandles ); + KeyValues *kv = new KeyValues( "Compare", "handlePointer", (int)(&m_MiniDumpHandles) ); + this->PostActionSignal( kv ); + } +} + +void CMDErrorPanel::NewQuery() +{ + m_pTokenList->DeleteAllItems(); + extern void errorsToListPanel( vgui::ListPanel *pTokenList, char* pszQuery ); + char sql[255] = ""; + char temp[10]; + strcat( sql, "select errorid, module, count, minidumpsonhand from error_types where processed=0 and minidumpsonhand > 0 and count > " ); + m_pQueryCounts->GetText( temp, 10 ); + strcat( sql, temp ); + strcat( sql, " limit " ); + m_pMaxResults->GetText( temp, 10 ); + strcat( sql, temp ); + strcat( sql, ";" ); + errorsToListPanel( m_pTokenList, sql ); + Repaint(); +} + +void CMDErrorPanel::DownloadMinidumps() +{ + int selectedIndex = m_pTokenList->GetSelectedItem( 0 ); + void *kv = m_pTokenList->GetItem( selectedIndex ); + if ( kv ) + { + char command[1024] = ""; + + strcat( command, ((KeyValues *)kv)->GetString( "errorid", "" )); + strcat( command, " minidumpSaves" ); + ::_spawnl( _P_WAIT, ".\\minidump.bat", "minidump.bat ", command, NULL ); + } +} + +void CMDErrorPanel::DetailScreen() +{ + int selectedIndex = m_pTokenList->GetSelectedItem( 0 ); + void *kv = m_pTokenList->GetItem( selectedIndex ); + if ( kv ) + { + KeyValues *kvPost = new KeyValues( "Detail", "errorID", ((KeyValues *)kv)->GetString( "errorid", "" ) ); + this->PostActionSignal( kvPost ); + } +} + + + + + + diff --git a/utils/mdmpRipper/CMDErrorPanel.h b/utils/mdmpRipper/CMDErrorPanel.h new file mode 100644 index 0000000..66503a3 --- /dev/null +++ b/utils/mdmpRipper/CMDErrorPanel.h @@ -0,0 +1,40 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +#include "mdmpRipper.h" +#include "vgui_controls/MessageMap.h" +#include "vgui_controls/MenuBar.h" +#include "vgui_controls/Menu.h" +#include "tier1/KeyValues.h" +#include "vgui/ISurface.h" +#include "vgui_controls/Frame.h" +#include "CMDDetailPanel.h" + +#ifndef MDERRORPANEL_H +#define MDERRORPANEL_H + +#ifdef _WIN32 +#pragma once +#endif + +using namespace vgui; + +class CMDErrorPanel : public vgui::EditablePanel +{ + DECLARE_CLASS_SIMPLE( CMDErrorPanel, vgui::EditablePanel ); + + vgui::ListPanel *m_pTokenList; + vgui::TextEntry *m_pMaxResults; + vgui::TextEntry *m_pQueryCounts; + + CUtlVector<HANDLE> m_MiniDumpHandles; + +public: + CMDErrorPanel( vgui::Panel *pParent, const char *pName ); + virtual void OnCommand( const char *pCommand ); + virtual void Close(); + void DownloadMinidumps(); + void CheckModules(); + void NewQuery(); + void DetailScreen(); +}; + +#endif // MDERRORPANEL_H diff --git a/utils/mdmpRipper/CMDModulePanel.cpp b/utils/mdmpRipper/CMDModulePanel.cpp new file mode 100644 index 0000000..396f735 --- /dev/null +++ b/utils/mdmpRipper/CMDModulePanel.cpp @@ -0,0 +1,539 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +#include <windows.h> +#include "mdmpRipper.h" +#include <vgui/IVGui.h> +#include "vgui_controls/MessageMap.h" +#include "vgui_controls/MenuBar.h" +#include "vgui_controls/Menu.h" +#include "vgui_controls/MessageBox.h" +#include "tier1/KeyValues.h" +#include "vgui/ISurface.h" +#include <vgui/ILocalize.h> +#include "vgui_controls/Frame.h" +#include "CMDModulePanel.h" +#include "vgui_controls/ListPanel.h" +#include <vgui_controls/RichText.h> +#include "KeyValues.h" +#include "vgui/ISystem.h" +#include "vgui_controls/FileOpenDialog.h" +#include "isqlwrapper.h" +#include "CMDRipperMain.h" + +extern ISQLWrapper *g_pSqlWrapper; + +using namespace vgui; + + + +CMDModulePanel::CMDModulePanel( vgui::Panel *pParent, const char *pName ) : + BaseClass( pParent, pName, true ) +{ + m_pTokenList = new ListPanel(this, "ModuleList"); + m_pTokenList->AddColumnHeader(0, "name", "Module Name", 600, 0); + m_pTokenList->AddColumnHeader(1, "version", "Version", 100, 0); + m_pTokenList->AddColumnHeader(2, "count", "Count", 86, 0); + m_pTokenList->AddActionSignalTarget( this ); + + m_pAnalyzeText = new RichText(this, "AnalyzeText"); + m_pAnalyzeText->SetVerticalScrollbar(true); + LoadControlSettings( "MDModulePanel.res" ); + m_pAnalyzeText->InsertString("Initializing...\n"); + + InitializeDebugEngine(); + LoadKnownModules(); + + m_hThread = NULL; + +// SetTitleBarVisible( false ); +// SetSizeable( false ); + + + //SETUP_PANEL( this ); +} + +CMDModulePanel::~CMDModulePanel( void ) +{ + ReleaseDebugEngine( ); +} + +void CMDModulePanel::OnKeyCodeTyped( KeyCode code ) +{ + switch ( code ) + { + case KEY_G: + UpdateKnownDB( "GOOD" ); + break; + case KEY_B: + UpdateKnownDB( "BAD" ); + break; + case KEY_U: + UpdateKnownDB( "UNKNOWN" ); + break; + case KEY_F: + ModuleLookUp(); + break; + } +} + +void CMDModulePanel::OnCommand( const char *pCommand ) +{ + if ( !Q_strcmp( pCommand, "Close" ) ) + { + //we want to close + Close(); + } + if ( !Q_strcmp( pCommand, "ModuleLookUp" ) ) + { + ModuleLookUp(); + } + if ( !Q_strcmp( pCommand, "SetGood" ) ) + { + UpdateKnownDB( "GOOD" ); + } + if ( !Q_strcmp( pCommand, "SetBad" ) ) + { + UpdateKnownDB( "BAD" ); + } + if ( !Q_strcmp( pCommand, "SetUnknown" ) ) + { + UpdateKnownDB( "UNKNOWN" ); + } +} + +void CMDModulePanel::Close() +{ + if ( this ) + { + m_pTokenList->DeleteAllItems(); + m_MiniDumpList.RemoveAll(); + m_knownModuleList.RemoveAll(); + m_pAnalyzeText->SetText(""); + SetVisible( false ); + KeyValues *kv = new KeyValues( "Refresh" ); + this->PostActionSignal( kv ); + } +} + +void CMDModulePanel::Create( CUtlVector<CMiniDumpObject *> *pMiniDump ) +{ + LoadKnownModules(); + + for ( int i = 0; i < pMiniDump->Count(); i++ ) + { + pMiniDump->Element(i)->PopulateListPanel( m_pTokenList, true ); + } +} + +void CMDModulePanel::Create( const char *filename ) +{ + if ( g_pFullFileSystem->FileExists( filename ) ) + { + LoadKnownModules(); + + CMiniDumpObject *newMDObj = new CMiniDumpObject( filename, &m_knownModuleList ); + m_MiniDumpList.AddToTail( newMDObj ); + newMDObj->PopulateListPanel( m_pTokenList, false ); + + AnalyzeDumpFile( filename ); + } +} + +void CMDModulePanel::ModuleLookUp() +{ + int selectedIndex = m_pTokenList->GetSelectedItem( 0 ); + void *kv = m_pTokenList->GetItem( selectedIndex ); + if ( kv ) + { + const char *val = ((KeyValues *)kv)->GetString( "name", "" ); + if ( val ) + { + const char *moduleName = strrchr( val, '\\' ) + 1; + char google[1024] = ""; + sprintf( google, "http://www.google.com/search?hl=en&q=%s", moduleName); + KeyValues *kvPost = new KeyValues( "ModuleLookUp", "url", google ); + this->PostActionSignal( kvPost ); + } + } +} + +void SeparateVersion( const char *version, char *v1buf, char *v2buf, char *v3buf, char *v4buf ) +{ + const char *endV1 = strchr( version, '.' )+1; + const char *endV2 = strchr( endV1+1, '.' )+1; + const char *endV3 = strchr( endV2+1, '.' )+1; + _mbsnbcpy( (unsigned char *)v1buf, (const unsigned char*)version, endV1 - version ); + v1buf[endV1 - version - 1] = 0; + _mbsnbcpy( (unsigned char *)v2buf, (const unsigned char*)endV1, endV2 - endV1 ); + v2buf[endV2 - endV1 - 1] = 0; + _mbsnbcpy( (unsigned char *)v3buf, (const unsigned char*)endV2, endV3 - endV2 ); + v3buf[endV3 - endV2 - 1] = 0; + strcpy( v4buf, endV3 ); +} + +void SetKeyValueColor( char *type, KeyValues *kv, bool knownVersion ) +{ + int colorValue = 255; + if( !knownVersion ) + colorValue = 155; + + if ( !Q_strcmp( "GOOD", type ) ) + { + ((KeyValues *)kv)->SetColor( "cellcolor", Color(0,colorValue,0,255)); + } + else if ( !Q_strcmp( "BAD", type ) ) + { + ((KeyValues *)kv)->SetColor( "cellcolor", Color(colorValue,0,0,255)); + } + else + { + ((KeyValues *)kv)->SetColor( "cellcolor", Color(255,255,0,255)); + } +} + +void CMDModulePanel::UpdateKnownDB( char *type ) +{ + int selectedIndex = m_pTokenList->GetSelectedItem( 0 ); + void *kv = m_pTokenList->GetItem( selectedIndex ); + char v1buf[10]; + char v2buf[10]; + char v3buf[10]; + char v4buf[10]; + char name[65]; + char keybuf[10]; + if ( kv ) + { + SetKeyValueColor( type, (KeyValues *)kv, true ); + int key = ((KeyValues *)kv)->GetInt( "key" ); + itoa( key, keybuf, 10 ); + strcpy( name, strrchr(((KeyValues *)kv)->GetString( "name" ), '\\')+1); + SeparateVersion( ((KeyValues *)kv)->GetString("version"), v1buf, v2buf, v3buf, v4buf ); + if ( key == 0 ) + { + //as far as we know, this is a non-existant module. + if ( !Q_strcmp( type, "UNKNOWN" ) ) + { + return; + } + else + { + char query[1024]; + sprintf( query, "select * from knownmodules where name = \"%s\" and version1 = %s and version2 = %s and version3 = %s and version4 = %s;", + name, v1buf, v2buf, v3buf, v4buf ); + IResultSet *results = g_pSqlWrapper->PResultSetQuery( query ); // do the query + if ( !results ) + { + return; + } + + int numResults = results->GetCSQLRow(); + if ( numResults > 0 ) + { + //there is an entry... get our module list up to date with this entry + + const ISQLRow *row = results->PSQLRowNextResult(); + Assert( row != NULL ); + int realKey = row->NData(0); + const char *realType = row->PchData(6); + g_pSqlWrapper->FreeResult(); + + ((KeyValues *)kv)->SetInt( "key", realKey ); + + if ( !Q_strcmp( realType, type ) ) + { + //this user was out of sync with the database. It doesn't actually need updating. + return; + } + else + { + char update[1024]; + sprintf( update, "update knownmodules set type=\"%s\" where id = %i;", type, realKey); + g_pSqlWrapper->BInsert( update ); + } + } + else + { + g_pSqlWrapper->FreeResult(); + //it isn't in there. Let's add it. + char update[1024]; + sprintf( update, "insert into knownmodules set name = \"%s\", version1 = %s, version2 = %s, version3 = %s, version4 = %s, type = \"%s\";", + name, v1buf, v2buf, v3buf, v4buf, type); + g_pSqlWrapper->BInsert( update ); + results = g_pSqlWrapper->PResultSetQuery( query ); // do the query + int numResults = results->GetCSQLRow(); + if ( numResults > 0 ) + { + const ISQLRow *row = results->PSQLRowNextResult(); + Assert( row != NULL ); + int realKey = row->NData(0); + ((KeyValues *)kv)->SetInt( "key", realKey ); + } + g_pSqlWrapper->FreeResult(); + } + } + } + else + { + char query[1024]; + sprintf( query, "select * from knownmodules where id = %i;", + key); + IResultSet *results = g_pSqlWrapper->PResultSetQuery( query ); // do the query + + int numResults = results->GetCSQLRow(); + if ( numResults > 0 ) + { + //there is an entry... update it with the new info... + + const ISQLRow *row = results->PSQLRowNextResult(); + Assert( row != NULL ); + Assert( numResults == 1 ); + Assert( !Q_stricmp( name, row->PchData(1) ) && atoi( v1buf ) == row->NData(2) && atoi( v2buf ) == row->NData(3) && + atoi( v3buf ) == row->NData(4) && atoi( v4buf ) == row->NData(5) ); + int realKey = row->NData(0); + const char *realType = row->PchData(6); + g_pSqlWrapper->FreeResult(); + + if ( !Q_strcmp( realType, type ) ) + { + //we don't need to update... it is already updated already + return; + } + + char update[1024]; + sprintf( update, "update knownmodules set type=\"%s\" where id = %i;", type, realKey); + g_pSqlWrapper->BInsert( update ); + + } + else + { + //the module entry was mis-keyed. First, check for an existing entry of this module. + char query[1024]; + sprintf( query, "select * from knownmodules where name = \"%s\" and version1 = %s and version2 = %s and version3 = %s and version4 = %s;", + name, v1buf, v2buf, v3buf, v4buf ); + IResultSet *results = g_pSqlWrapper->PResultSetQuery( query ); // do the query + + int numResults = results->GetCSQLRow(); + if ( numResults > 0 ) + { + //there is an existing entry. Update its type and update the key for this keyvalue; + const ISQLRow *row = results->PSQLRowNextResult(); + int realKey = row->NData(0); + ((KeyValues *)kv)->SetInt( "key", realKey ); + g_pSqlWrapper->FreeResult(); + char update[1024]; + sprintf( update, "update knownmodules set type=\"%s\" where id = %i;", type, realKey); + g_pSqlWrapper->BInsert( update ); + } + else + { + g_pSqlWrapper->FreeResult(); + //no exisiting entry. Insert it. + char update[1024]; + sprintf( update, "insert into knownmodules set name = \"%s\", version1 = %s, version2 = %s, version3 = %s, version4 = %s, type = \"%s\";", + name, v1buf, v2buf, v3buf, v4buf, type); + g_pSqlWrapper->BInsert( update ); + results = g_pSqlWrapper->PResultSetQuery( query ); // do the query + int numResults = results->GetCSQLRow(); + if ( numResults > 0 ) + { + const ISQLRow *row = results->PSQLRowNextResult(); + Assert( row != NULL ); + int realKey = row->NData(0); + ((KeyValues *)kv)->SetInt( "key", realKey ); + } + g_pSqlWrapper->FreeResult(); + } + } + } + } +} + + +void CMDModulePanel::OnCompare( KeyValues *data ) +{ + LoadKnownModules(); + + CUtlVector<HANDLE> *pMiniDumpHandles = (CUtlVector<HANDLE> *)(void *)data->GetInt( "handlePointer" ); + + + DWORD error; + int returnValue = 0; + for( int i = 0; i < pMiniDumpHandles->Count(); i++ ) + { + m_MiniDumpList.AddToTail( new CMiniDumpObject( pMiniDumpHandles->Element( i ), &m_knownModuleList ) ); + returnValue = CloseHandle( pMiniDumpHandles->Element( i ) ); + error = GetLastError(); + } + Create( &m_MiniDumpList ); + SetVisible( true ); + MoveToFront(); + + pMiniDumpHandles->RemoveAll(); + system("rmdir c:\\minidumptool /s/q"); +} + + +void CMDModulePanel::OnDbgOutput( int iMask, const char *pszDebugText) +{ + if ( m_pAnalyzeText && pszDebugText ) + { + m_pAnalyzeText->InsertString( pszDebugText ); + } +} + + +DWORD WINAPI CMDModulePanel::StaticAnalyzeThread( LPVOID lParam ) +{ + CMDModulePanel *pClass = (CMDModulePanel *)lParam; + if ( pClass ) + { + pClass->AnalyzeThread( ); + } + + return ( 0 ); +} + +void CMDModulePanel::LoadKnownModules() +{ + if ( m_knownModuleList.Count() > 0 ) + return; + + char rgchQueryBuf[ 1024 ] = "SELECT * from knownmodules;"; + IResultSet *results = g_pSqlWrapper->PResultSetQuery( rgchQueryBuf ); + + if ( !results ) + { + ivgui()->DPrintf( "LoadKnownModules() results are NULL" ); + VGUIMessageBox( GetParent(), "Error", "Unable to retrieve known modules from database" ); + return; + } + + for ( int i = 0; i < results->GetCSQLRow(); i++ ) + { + module newModule; + const ISQLRow *row = results->PSQLRowNextResult(); + Assert( row != NULL ); + newModule.key = row->NData(0); + strcpy( newModule.name, row->PchData(1)); + newModule.versionInfo.v1 = row->NData(2); + newModule.versionInfo.v2 = row->NData(3); + newModule.versionInfo.v3 = row->NData(4); + newModule.versionInfo.v4 = row->NData(5); + if ( !Q_strcmp( row->PchData(6), "GOOD" ) ) + { + newModule.myType = GOOD; + } + else if ( !Q_strcmp( row->PchData(6), "BAD" ) ) + { + newModule.myType = BAD; + } + else + { + newModule.myType = UNKNOWN; + } + m_knownModuleList.AddToTail( newModule ); + } + + g_pSqlWrapper->FreeResult(); +} + + +void CMDModulePanel::InitializeDebugEngine( void ) +{ + // Start things off by getting an initial interface from + // the engine. This can be any engine interface but is + // generally IDebugClient as the client interface is + // where sessions are started. + if ( S_OK == DebugCreate( __uuidof ( IDebugClient ), + (void**)&m_pDbgClient ) ) + { + m_pDbgClient->QueryInterface( __uuidof ( IDebugControl ), + ( void** )&m_pDbgControl ); + m_pDbgClient->QueryInterface( __uuidof ( IDebugSymbols2 ), + ( void** )&m_pDbgSymbols ); + + // Set out Panel to receive the debug outputs from the engine + m_cDbgOutput.SetOutputPanel( GetVPanel() ); + + // Install output callbacks so we get any output that the + // later calls produce. + m_pDbgClient->SetOutputCallbacks(&m_cDbgOutput); + + if ( m_pDbgSymbols ) + { + // Make sure we have a symbol path to use + char szSymbolSrv[ 512 ] = { 0 }; + ExpandEnvironmentStrings( "%_NT_SYMBOL_PATH%", szSymbolSrv, sizeof (szSymbolSrv) ); + if ( !Q_stricmp( "%_NT_SYMBOL_PATH%", szSymbolSrv ) ) + { + ivgui()->DPrintf( "Setting symbol server" ); + Q_strcpy( szSymbolSrv, "SRV*c:\\localsymbols*\\\\perforce\\symbols*http://msdl.microsoft.com/download/symbols" ); + m_pDbgSymbols->SetSymbolPath( szSymbolSrv ); + } + m_pDbgSymbols->AddSymbolOptions(SYMOPT_LOAD_LINES); + } + } +} + +void CMDModulePanel::ReleaseDebugEngine( void ) +{ + // Clean up any resources. + if ( m_pDbgSymbols != NULL ) + { + m_pDbgSymbols->Release( ); + } + + if ( m_pDbgControl != NULL ) + { + m_pDbgControl->Release( ); + } + + if ( m_pDbgClient != NULL ) + { + // We don't want to see any output from the shutdown. + m_pDbgClient->SetOutputCallbacks( NULL ); + + m_pDbgClient->EndSession( DEBUG_END_PASSIVE ); + + m_pDbgClient->Release( ); + } +} + + +void CMDModulePanel::AnalyzeDumpFile( const char *pszDumpFile ) +{ + if (m_pDbgClient && m_pDbgControl) + { + char szBuf[ 256 ] = { 0 }; + Q_snprintf( szBuf, sizeof ( szBuf ), "About to open [%s].\n", pszDumpFile ); + m_pAnalyzeText->InsertString( szBuf ); + + // Everything's set up so open the dump file. + m_pDbgClient->OpenDumpFile(pszDumpFile); + + // Finish initialization by waiting for the event that + // caused the dump. This will return immediately as the + // dump file is considered to be at its event. + m_pDbgControl->WaitForEvent(DEBUG_WAIT_DEFAULT, INFINITE); + + DWORD dwThreadId = 0; + m_hThread = CreateThread( NULL, 0, StaticAnalyzeThread, (LPVOID)this, 0, &dwThreadId ); + } +} + + +DWORD CMDModulePanel::AnalyzeThread( void ) +{ + if ( m_pDbgControl ) + { + // Tell the debug engine to analyze the current dump file + m_pDbgControl->Execute( DEBUG_OUTCTL_THIS_CLIENT, + "!analyze -v", + DEBUG_EXECUTE_DEFAULT); + } + + CloseHandle( m_hThread ); + m_pAnalyzeText->InsertString( "Finished analyzing minidump file.\n" ); + + return ( 0 ); +} + diff --git a/utils/mdmpRipper/CMDModulePanel.h b/utils/mdmpRipper/CMDModulePanel.h new file mode 100644 index 0000000..21ab2e4 --- /dev/null +++ b/utils/mdmpRipper/CMDModulePanel.h @@ -0,0 +1,67 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +#include <dbghelp.h> +#include <dbgeng.h> + +#include "mdmpRipper.h" +#include "vgui_controls/MessageMap.h" +#include "vgui_controls/MenuBar.h" +#include "vgui_controls/Menu.h" +#include "tier1/KeyValues.h" +#include "vgui/ISurface.h" +#include "vgui_controls/Frame.h" +#include "CMiniDumpObject.h" +#include "CDbgOutput.h" + +#ifndef MDMODULEPANEL_H +#define MDMODULEPANEL_H + +#ifdef _WIN32 +#pragma once +#endif + +using namespace vgui; + + +class CMDModulePanel : public vgui::EditablePanel +{ + DECLARE_CLASS_SIMPLE( CMDModulePanel, vgui::EditablePanel ); +public: + CMDModulePanel( vgui::Panel *pParent, const char *pName ); + ~CMDModulePanel( ); + + virtual void OnCommand( const char *pCommand ); + virtual void Close(); + void OnKeyCodeTyped( KeyCode code ); + virtual void Create( const char *filename ); + virtual void Create( CUtlVector<CMiniDumpObject *> *ptr ); + + void UpdateKnownDB( char *type ); + void ModuleLookUp(); + + static DWORD WINAPI StaticAnalyzeThread( LPVOID lParam ); + +private: + MESSAGE_FUNC_PARAMS( OnCompare, "compare", data ); + MESSAGE_FUNC_INT_CHARPTR( OnDbgOutput, "DebugOutput", iMask, pszDebugText ); + + void LoadKnownModules(); + + void InitializeDebugEngine( void ); + void ReleaseDebugEngine( void ); + void AnalyzeDumpFile( const char *pszDumpFile ); + DWORD AnalyzeThread( void ); + + vgui::ListPanel *m_pTokenList; + vgui::RichText *m_pAnalyzeText; + CUtlVector<CMiniDumpObject *> m_MiniDumpList; + CUtlVector<module> m_knownModuleList; + + HANDLE m_hThread; + IDebugClient *m_pDbgClient; + IDebugControl *m_pDbgControl; + IDebugSymbols2 *m_pDbgSymbols; + CDbgOutput m_cDbgOutput; +}; + + +#endif // MDMODULEPANEL_H
\ No newline at end of file diff --git a/utils/mdmpRipper/CMDRipperMain.cpp b/utils/mdmpRipper/CMDRipperMain.cpp new file mode 100644 index 0000000..0275454 --- /dev/null +++ b/utils/mdmpRipper/CMDRipperMain.cpp @@ -0,0 +1,272 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Dialog for selecting game configurations +// +//=====================================================================================// + +#include <windows.h> + +#include <vgui/IVGui.h> +#include <vgui/IInput.h> +#include <vgui/ISystem.h> +#include <vgui_controls/ComboBox.h> +#include <vgui_controls/MessageBox.h> +#include <vgui_controls/FileOpenDialog.h> +#include <KeyValues.h> +#include "CMDErrorPanel.h" +#include "CMDModulePanel.h" +#include "isqlwrapper.h" +#include "CMDRipperMain.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/memdbgon.h> + +using namespace vgui; + +CMDRipperMain *g_pCMDRipperMain = NULL; +extern ISQLWrapper *g_pSqlWrapper; + +class CModalPreserveMessageBox : public vgui::MessageBox +{ +public: + CModalPreserveMessageBox(const char *title, const char *text, vgui::Panel *parent) + : vgui::MessageBox( title, text, parent ) + { + m_PrevAppFocusPanel = vgui::input()->GetAppModalSurface(); + } + + ~CModalPreserveMessageBox() + { + vgui::input()->SetAppModalSurface( m_PrevAppFocusPanel ); + } + +public: + vgui::VPANEL m_PrevAppFocusPanel; +}; + +//----------------------------------------------------------------------------- +// Purpose: Utility function to pop up a VGUI message box +//----------------------------------------------------------------------------- +void VGUIMessageBox( vgui::Panel *pParent, const char *pTitle, const char *pMsg, ... ) +{ + char msg[4096]; + va_list marker; + va_start( marker, pMsg ); + Q_vsnprintf( msg, sizeof( msg ), pMsg, marker ); + va_end( marker ); + + vgui::MessageBox *dlg = new CModalPreserveMessageBox( pTitle, msg, pParent ); + dlg->DoModal(); + dlg->Activate(); + dlg->RequestFocus(); +} + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- +CMDRipperMain::CMDRipperMain( Panel *parent, const char *name ) : BaseClass( parent, name ), m_bChanged( false ) +{ + Assert( !g_pCMDRipperMain ); + g_pCMDRipperMain = this; + + Sys_LoadInterface( "sqlwrapper", INTERFACEVERSION_ISQLWRAPPER, &hSQLWrapper, (void **)&sqlWrapperFactory ); + Assert( hSQLWrapper != NULL ); + Assert( sqlWrapperFactory != NULL ); + + sqlWrapper = sqlWrapperFactory->Create( "cserr", "steamweb-sql", "root", "" ); + if ( !sqlWrapper ) + { + ivgui()->DPrintf( "SQLWrapper is NULL" ); + } + Assert( sqlWrapper != NULL ); + g_pSqlWrapper = sqlWrapper; + + SetSize(800, 600); + SetMinimumSize(500, 200); + + SetMinimizeButtonVisible( true ); + + m_pMenuBar = new vgui::MenuBar( this, "Main Menu Bar" ); + m_pMenuBar->SetPos( 5, 26 ); + m_pMenuBar->SetSize( 690, 28 ); + + Menu *pFileMenu = new Menu(NULL, "File"); + pFileMenu->AddMenuItem( "&Open", new KeyValues( "Open" ), this ); + m_pMenuBar->AddMenu( "&File", pFileMenu ); + + Menu *pErrorMenu = new Menu(NULL, "Error"); + pErrorMenu->AddMenuItem( "&Error", new KeyValues("Error"), this); + m_pMenuBar->AddMenu( "&Error", pErrorMenu ); + + m_pErrorPanel = new CMDErrorPanel( this, "MDError Panel" ); + m_pErrorPanel->AddActionSignalTarget( this ); + + m_pModulePanel = new CMDModulePanel( this, "MDModule Panel" ); + m_pModulePanel->AddActionSignalTarget( this ); + + m_pErrorPanel->AddActionSignalTarget( m_pModulePanel ); + + m_pDetailPanel = new CMDDetailPanel( this, "MDDetail Panel" ); + m_pErrorPanel->AddActionSignalTarget( this ); + + LoadControlSettings( "MDRipperMain.res" ); + + m_pErrorPanel->SetVisible( false ); + m_pModulePanel->SetVisible( false ); + m_pDetailPanel->SetVisible( false ); +} + +//----------------------------------------------------------------------------- +// Destructor +//----------------------------------------------------------------------------- +CMDRipperMain::~CMDRipperMain() +{ + g_pCMDRipperMain = NULL; +} + + + +//----------------------------------------------------------------------------- +// Purpose: Kills the whole app on close +//----------------------------------------------------------------------------- +void CMDRipperMain::OnClose( void ) +{ + BaseClass::OnClose(); + ivgui()->Stop(); + + sqlWrapper->FreeResult(); + sqlWrapperFactory->Free( sqlWrapper ); + Sys_UnloadModule( hSQLWrapper ); +} + +/* +//----------------------------------------------------------------------------- +// Purpose: Select the item from the list (updating the environment variable as well) +// Input : index - item to select +//----------------------------------------------------------------------------- +void CMDRipperMain::SetGlobalConfig( const char *modDir ) +{ + // Set our environment variable + SetVConfigRegistrySetting( GAMEDIR_TOKEN, modDir ); +} +*/ + +//----------------------------------------------------------------------------- +// Purpose: Parse commands coming in from the VGUI dialog +//----------------------------------------------------------------------------- +void CMDRipperMain::OnCommand( const char *command ) +{ + if ( Q_stricmp( command, "Open" ) == 0 ) + { + OnOpen(); + } + else if ( Q_stricmp( command, "Error" ) == 0 ) + { + OnError(); + } + BaseClass::OnCommand( command ); +} + + +bool CMDRipperMain::RequestInfo( KeyValues *outputData ) +{ + const char * szName = outputData->GetName(); + if ( !Q_stricmp( szName, "DragDrop" )) + { + bool bAccept = false; + + if ( !Q_stricmp( outputData->GetString( "type" ), "Files" ) ) + { + // Make sure we only get .mdmp files + KeyValues *pFiles = outputData->FindKey( "list", false ); + if ( pFiles ) + { + const char *pszFile = pFiles->GetString( "0" ); + const char *pszExtension = Q_strrchr( pszFile, '.' ); + if ( pszExtension ) + { + if ( !Q_stricmp( pszExtension, ".mdmp" ) ) + { + outputData->SetPtr( "AcceptPanel", ( Panel * )this ); + bAccept = true; + } + } + } + } + + return ( bAccept ); + } + + return ( BaseClass::RequestInfo( outputData ) ); +} + + +void CMDRipperMain::OnOpen() +{ + FileOpenDialog *pFileDialog = new FileOpenDialog ( this, "File Open", true); + pFileDialog->AddActionSignalTarget(this); + pFileDialog->AddFilter( "*.mdmp", "MiniDumps", true ); + pFileDialog->DoModal( true ); +} + +void CMDRipperMain::OnError() +{ + m_pErrorPanel->NewQuery(); + m_pErrorPanel->SetVisible( true ); + m_pErrorPanel->MoveToFront(); + Repaint(); +} + +void CMDRipperMain::OnFileSelected( const char *filename ) +{ + m_pModulePanel->Create( filename ); + m_pModulePanel->SetVisible( true ); + Repaint(); +} + +void CMDRipperMain::OnDetail( KeyValues *data ) +{ + char URL[1024] = ""; + strcat( URL, "http://steamweb/cserr_detailsnograph.php?errorid=" ); + strcat( URL, data->GetString( "errorID" ) ); + m_pDetailPanel->OpenURL( URL ); + m_pDetailPanel->SetVisible( true ); + m_pDetailPanel->MoveToFront(); + Repaint(); +} + +void CMDRipperMain::OnRefresh() +{ + Repaint(); +} + +void CMDRipperMain::OnLookUp( KeyValues *data ) +{ + m_pDetailPanel->OpenURL( data->GetString( "url" ) ); + m_pDetailPanel->SetVisible( true ); + m_pDetailPanel->MoveToFront(); + Repaint(); +} + + +void CMDRipperMain::OnDragDrop( KeyValues *pData ) +{ + KeyValues *pFiles = pData->FindKey( "list", false ); + if ( pFiles ) + { + DWORD dwIndex = 0; + const char *pszFile = NULL; + char szIndex[ 64 ] = { 0 }; + + do + { + Q_snprintf( szIndex, sizeof ( szIndex ), "%d", dwIndex ); + pszFile = pFiles->GetString( szIndex ); + ivgui()->DPrintf( "Got file [%s]", pszFile ); + OnFileSelected( pszFile ); + dwIndex++; + } + while ( g_pFullFileSystem->FileExists( pszFile ) ); + } + +}
\ No newline at end of file diff --git a/utils/mdmpRipper/CMDRipperMain.h b/utils/mdmpRipper/CMDRipperMain.h new file mode 100644 index 0000000..0ab62e0 --- /dev/null +++ b/utils/mdmpRipper/CMDRipperMain.h @@ -0,0 +1,83 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef MDRIPPERMAIN_H +#define MDRIPPERMAIN_H +#ifdef _WIN32 +#pragma once +#endif + +#include <vgui_controls/Frame.h> +#include <vgui_controls/ImageList.h> +#include <vgui_controls/SectionedListPanel.h> +#include <vgui_controls/PHandle.h> +#include <vgui_controls/MenuBar.h> +#include <FileSystem.h> +#include "vgui/mousecode.h" +#include "vgui/IScheme.h" +#include "CMDErrorPanel.h" +#include "CMDModulePanel.h" +#include "CMDDetailPanel.h" +#include "isqlwrapper.h" + +using namespace vgui; + + +void VGUIMessageBox( vgui::Panel *pParent, const char *pTitle, PRINTF_FORMAT_STRING const char *pMsg, ... ); + +//----------------------------------------------------------------------------- +// Purpose: Main dialog for media browser +//----------------------------------------------------------------------------- +class CMDRipperMain : public Frame +{ + DECLARE_CLASS_SIMPLE( CMDRipperMain, Frame ); + +public: + + CMDRipperMain(Panel *parent, const char *name); + virtual ~CMDRipperMain(); + ISQLWrapper *GetSqlWrapper() { return sqlWrapper; } + +protected: + + virtual void OnClose(); + virtual void OnCommand( const char *command ); + virtual bool RequestInfo( KeyValues *outputData ); + +private: + + void SetGlobalConfig( const char *modDir ); + + vgui::ComboBox *m_pConfigCombo; + bool m_bChanged; + vgui::MenuBar *m_pMenuBar; + vgui::Panel *m_pClientArea; + CMDErrorPanel *m_pErrorPanel; + CMDModulePanel *m_pModulePanel; + CMDDetailPanel *m_pDetailPanel; + + MESSAGE_FUNC( OnOpen, "Open" ); + MESSAGE_FUNC( OnError, "Error" ); + MESSAGE_FUNC( OnRefresh, "refresh" ); + MESSAGE_FUNC_PARAMS( OnDetail, "detail", data ); + MESSAGE_FUNC_CHARPTR( OnFileSelected, "FileSelected", fullpath ); + MESSAGE_FUNC_PARAMS( OnLookUp, "ModuleLookUp", url ); + MESSAGE_FUNC_PARAMS( OnDragDrop, "DragDrop", pData ); + + CSysModule *hSQLWrapper; + ISQLWrapperFactory *sqlWrapperFactory; + ISQLWrapper *sqlWrapper; + + +// MESSAGE_FUNC( OnManageSelect, "ManageSelect" ); +// MESSAGE_FUNC( OnAddSelect, "AddSelect" ); +}; + + +extern CMDRipperMain *g_pCMDRipperMain; + + +#endif // MDRIPPERMAIN_H diff --git a/utils/mdmpRipper/CMiniDumpObject.cpp b/utils/mdmpRipper/CMiniDumpObject.cpp new file mode 100644 index 0000000..0d064da --- /dev/null +++ b/utils/mdmpRipper/CMiniDumpObject.cpp @@ -0,0 +1,246 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +#include <windows.h> +#include "tier1/strtools.h" +#include <conio.h> +#include "utlvector.h" +#include <Dbghelp.h> +#include "isqlwrapper.h" +#include "CMiniDumpObject.h" + +extern ISQLWrapper *g_pSqlWrapper; + +CMiniDumpObject::CMiniDumpObject( const char *pszFilename, CUtlVector<module> *pKnownModuleList ) +{ + InitFromFilename( pszFilename, pKnownModuleList ); +} + +CMiniDumpObject::CMiniDumpObject( HANDLE pMiniDumpHandle, CUtlVector<module> *pKnownModuleList ) +{ + InitFromHandle( pMiniDumpHandle, pKnownModuleList ); +} + +void CMiniDumpObject::Init( HANDLE pszFileMap, CUtlVector<module> *pKnownModuleList ) +{ + PMINIDUMP_DIRECTORY miniDumpDir; + PVOID pOutput; + ULONG ulSize; + + if ( !pszFileMap ) + return; + PVOID pMiniDump = MapViewOfFile( pszFileMap, FILE_MAP_READ, 0, 0, 0 ); + + MiniDumpReadDumpStream( pMiniDump, ModuleListStream, &miniDumpDir, &pOutput, &ulSize ); + + int numberOfModules = ((int *)pOutput)[0]; + MINIDUMP_MODULE *pModules = (MINIDUMP_MODULE *)((byte *)pOutput + sizeof(int)); + + for ( int i = 0; i < numberOfModules; i++ ) + { + MINIDUMP_MODULE *pCurrentModule = (pModules + i); + module *newModule = new module; + newModule->key = 0; + newModule->knownVersion = false; + int offset = pCurrentModule->ModuleNameRva; + int nSizeOfName = *(int *)((byte *)pMiniDump + offset); + char nameBuf[1024]; + char *pszName = (char *)(byte *)pMiniDump + offset + sizeof(int); + int j = 0; + for ( j = 0; j < nSizeOfName/2; j++ ) + { + nameBuf[j] = *(pszName + j*2); + } + nameBuf[j] = 0; + strcpy( newModule->name, nameBuf ); + newModule->versionInfo = GetVersionStruct(&pCurrentModule->VersionInfo); + bool added = false; + + for ( int j = 0; j < pKnownModuleList->Count(); j++ ) + { + if ( !Q_stricmp( strrchr( nameBuf, '\\' )+1, pKnownModuleList->Element( j ).name ) ) + { + newModule->myType = pKnownModuleList->Element( j ).myType; + + if ( newModule->versionInfo == pKnownModuleList->Element(j).versionInfo ) + { + newModule->key = pKnownModuleList->Element( j ).key; + newModule->knownVersion = true; + } + else + { + newModule->knownVersion = false; + } + } + if ( newModule->knownVersion ) + break; + } + switch ( newModule->myType ) + { + case GOOD: + m_goodModuleList.AddToTail( *newModule ); + added = true; + break; + case BAD: + m_badModuleList.AddToTail( *newModule ); + added = true; + break; + default: + m_unknownModuleList.AddToTail( *newModule ); + added = true; + break; + } + if ( !added ) + { + newModule->key = 0; + newModule->myType = UNKNOWN; + m_unknownModuleList.AddToTail( *newModule ); + } + } + UnmapViewOfFile( pMiniDump ); +} + +void CMiniDumpObject::InitFromHandle( HANDLE pMiniDumpHandle, CUtlVector<module> *pKnownModuleList ) +{ + if ( INVALID_HANDLE_VALUE != pMiniDumpHandle ) + { + DWORD dwNumRead = 0; + char szMdmp[ 5 ] = { 0 }; + if ( ReadFile( pMiniDumpHandle, (LPVOID)szMdmp, 4, &dwNumRead, NULL ) ) + { + if ( !Q_strcmp( "MDMP", szMdmp )) + { + HANDLE hFileMap = CreateFileMapping( pMiniDumpHandle, NULL, PAGE_READONLY, 0, 0, NULL ); + Init( hFileMap, pKnownModuleList ); + } + } + } +} + +void CMiniDumpObject::InitFromFilename( const char *pszFilename, CUtlVector<module> *pKnownModuleList ) +{ + HANDLE hFile = CreateFile(pszFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + InitFromHandle( hFile, pKnownModuleList ); +} + +void CMiniDumpObject::GetVersionString( char *pszOutput, version *pVersionInfo ) +{ + char firstHighVer[10]; + char firstLowVer[10]; + char secondHighVer[10]; + char secondLowVer[10]; + + int firstHigh = pVersionInfo->v1; + int secondHigh = pVersionInfo->v2; + int firstLow = pVersionInfo->v3; + int secondLow = pVersionInfo->v4; + + itoa( firstHigh, firstHighVer, 10 ); + itoa( firstLow, firstLowVer, 10 ); + itoa( secondHigh, secondHighVer, 10 ); + itoa( secondLow, secondLowVer, 10 ); + + strcat( pszOutput, firstHighVer ); + strcat( pszOutput, "." ); + strcat( pszOutput, secondHighVer ); + strcat( pszOutput, "." ); + strcat( pszOutput, firstLowVer ); + strcat( pszOutput, "." ); + strcat( pszOutput, secondLowVer ); +} + +version CMiniDumpObject::GetVersionStruct( VS_FIXEDFILEINFO *pVersionInfo ) +{ + version returnVersion; + int highVal = pVersionInfo->dwFileVersionMS; + int lowVal = pVersionInfo->dwFileVersionLS; + returnVersion.v1 = highVal >> 16; + returnVersion.v2 = (highVal << 16)>>16; + returnVersion.v3 = lowVal >> 16; + returnVersion.v4 = (lowVal << 16)>>16; + + return returnVersion; +} + +int CMiniDumpObject::ModuleListToListPanel( vgui::ListPanel *pTokenList, CUtlVector<module> *pModuleList, bool bCumulative, int startingModule) +{ + char keyNameBuf[1024] = "module"; + char modNumBuf[4] = ""; + int moduleNumber = startingModule; + + for ( int i = 0; i < pModuleList->Count(); i++ ) + { + char version[20] = ""; + moduleNumber++; + itoa( moduleNumber, modNumBuf, 10 ); + strcat( keyNameBuf, modNumBuf ); + module currentModule = pModuleList->Element(i); + GetVersionString( version, ¤tModule.versionInfo ); + bool bRepeat = false; + + if ( bCumulative ) + { + int tokenCount = pTokenList->GetItemCount(); + for ( int j = 0; j < tokenCount; j++ ) + { + KeyValues *kv = pTokenList->GetItem( j ); + const char *moduleName = strrchr( kv->GetString( "name" ), '\\' ); + const char *secondModuleName = strrchr( currentModule.name, '\\' ); + const char *checksum = kv->GetString( "checksum" ); + + if ( !stricmp( moduleName, secondModuleName ) && !strcmp( kv->GetString( "version" ), version ) ) + { + int count = kv->GetInt( "count" ); + int key = kv->GetInt( "key" ); + KeyValues *newKv = new KeyValues( keyNameBuf, "name", kv->GetString("name"), "checksum", checksum ); + newKv->SetString( "version", version ); + newKv->SetInt( "count", count+1 ); + newKv->SetInt( "key", key ); + newKv->SetColor( "cellcolor", kv->GetColor( "cellcolor" ) ); + pTokenList->RemoveItem( j ); + pTokenList->AddItem( newKv, j, false, false ); + bRepeat = true; + break; + } + } + } + + if ( !bRepeat ) + { + KeyValues *kv = new KeyValues( keyNameBuf, "name", currentModule.name); + kv->SetString( "version", version ); + kv->SetInt( "key", currentModule.key ); + if ( bCumulative ) + { + kv->SetInt( "count", 1 ); + } + int colorValue = 255; + if ( !currentModule.knownVersion ) + colorValue = 155; + switch ( currentModule.myType ) + { + case GOOD: + kv->SetColor( "cellcolor", Color(0,colorValue,0,255)); + break; + case BAD: + kv->SetColor( "cellcolor", Color(colorValue,0,0,255)); + break; + default: + kv->SetColor( "cellcolor", Color(255,255,0,255)); + break; + } + pTokenList->AddItem( kv, i, false, false ); + bRepeat = false; + } + strcpy( keyNameBuf, "module"); + } + return moduleNumber; +} + + +void CMiniDumpObject::PopulateListPanel( vgui::ListPanel *pTokenList, bool bCumulative ) +{ + int nextModuleNumber = 0; + nextModuleNumber = ModuleListToListPanel( pTokenList, &m_goodModuleList, bCumulative, nextModuleNumber ); + nextModuleNumber = ModuleListToListPanel( pTokenList, &m_unknownModuleList, bCumulative, nextModuleNumber ); + nextModuleNumber = ModuleListToListPanel( pTokenList, &m_badModuleList, bCumulative, nextModuleNumber); + ModuleListToListPanel( pTokenList, &m_badChecksumList, bCumulative, nextModuleNumber ); +} diff --git a/utils/mdmpRipper/CMiniDumpObject.h b/utils/mdmpRipper/CMiniDumpObject.h new file mode 100644 index 0000000..7fca952 --- /dev/null +++ b/utils/mdmpRipper/CMiniDumpObject.h @@ -0,0 +1,63 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +#include <windows.h> +#include "tier1/strtools.h" +#include <conio.h> +#include "utlvector.h" +#include <Dbghelp.h> +#include "vgui_controls/ListPanel.h" +#include "KeyValues.h" + +enum moduleType +{ + GOOD, + BAD, + UNKNOWN +}; + +struct version +{ + int v1, v2, v3, v4; + bool operator == (version version2){ return v1==version2.v1 && v2==version2.v2 && v3==version2.v3 && v4==version2.v4; } +}; + +struct module +{ + int key; + char name[1024]; + moduleType myType; + version versionInfo; + bool knownVersion; +}; + +class CMiniDumpObject +{ +public: + //CMiniDumpObject( char *pszFilename, char *pszKnownFilename ); + CMiniDumpObject( const char *pszFilename, CUtlVector<module> *pKnownModuleList ); + CMiniDumpObject( HANDLE pMiniDumpHandle, CUtlVector<module> *pKnownModuleList ); + + void AddToBadList( MINIDUMP_MODULE module ); + void AddToGoodList( MINIDUMP_MODULE module ); + void AddToUnknownList( MINIDUMP_MODULE module ); + void PopulateListPanel( vgui::ListPanel *pTokenList, bool bCumulative ); + inline const char *GetName() + { + return m_pszMiniDumpFileName; + } + +private: + void Init( HANDLE pFileMap, CUtlVector<module> *pKnownModuleList ); + void InitFromFilename( const char *pszFilename, CUtlVector<module> *pKnownModuleList ); + void InitFromHandle( HANDLE pMiniDumpHandle, CUtlVector<module> *pKnownModuleList ); + int ModuleListToListPanel( vgui::ListPanel *pTokenList, CUtlVector<module> *pModuleList, bool bCumulative, int startingModule); + void GetVersionString( char *pszOutput, version *pVersionInfo ); + version GetVersionStruct( VS_FIXEDFILEINFO *pVersionInfo ); + void LoadKnownModules(); + + CUtlVector<module> m_goodModuleList; + CUtlVector<module> m_badModuleList; + CUtlVector<module> m_unknownModuleList; + CUtlVector<module> m_badChecksumList; + char m_pszMiniDumpFileName[1024]; + +};
\ No newline at end of file diff --git a/utils/mdmpRipper/dbgeng.lib b/utils/mdmpRipper/dbgeng.lib Binary files differnew file mode 100644 index 0000000..9ec4a51 --- /dev/null +++ b/utils/mdmpRipper/dbgeng.lib diff --git a/utils/mdmpRipper/icon2.ico b/utils/mdmpRipper/icon2.ico Binary files differnew file mode 100644 index 0000000..0aa500f --- /dev/null +++ b/utils/mdmpRipper/icon2.ico diff --git a/utils/mdmpRipper/icon_mdmpRipper.ico b/utils/mdmpRipper/icon_mdmpRipper.ico Binary files differnew file mode 100644 index 0000000..0aa500f --- /dev/null +++ b/utils/mdmpRipper/icon_mdmpRipper.ico diff --git a/utils/mdmpRipper/main.cpp b/utils/mdmpRipper/main.cpp new file mode 100644 index 0000000..c1e1d72 --- /dev/null +++ b/utils/mdmpRipper/main.cpp @@ -0,0 +1,252 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Configuration utility +// +//===========================================================================// + +#include <windows.h> +#include <io.h> +#include <stdio.h> + +#include <vgui/ILocalize.h> +#include <vgui/ISurface.h> +#include <vgui/IVGui.h> +#include <vgui_controls/Panel.h> +#include "appframework/tier3app.h" +#include "inputsystem/iinputsystem.h" +#include "tier0/icommandline.h" +#include "filesystem_init.h" +#include "CMDRipperMain.h" +#include "isqlwrapper.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/memdbgon.h> + +#define MDRIPPER_MAIN_PATH_ID "MAIN" +#define MDRIPPER_WRITE_PATH "DEFAULT_WRITE_PATH" + +CMDRipperMain *g_pMainFrame = 0; +ISQLWrapper *g_pSqlWrapper; + +// Dummy window +static WNDCLASS staticWndclass = { NULL }; +static ATOM staticWndclassAtom = 0; +static HWND staticHwnd = 0; + +// List of our game configs, as read from the gameconfig.txt file +//CGameConfigManager g_ConfigManager; +//CUtlVector<CGameConfig *> g_Configs; +HANDLE g_dwChangeHandle = NULL; + + +//----------------------------------------------------------------------------- +// Purpose: +// Output : const char +//----------------------------------------------------------------------------- +const char *GetBaseDirectory( void ) +{ + static char path[MAX_PATH] = {0}; + if ( path[0] == 0 ) + { + GetModuleFileName( (HMODULE)GetAppInstance(), path, sizeof( path ) ); + Q_StripLastDir( path, sizeof( path ) ); // Get rid of the filename. + Q_StripTrailingSlash( path ); + } + return path; +} + + +//----------------------------------------------------------------------------- +// Purpose: Message handler for dummy app +//----------------------------------------------------------------------------- +static LRESULT CALLBACK messageProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) +{ + // See if we've gotten a VPROJECT change + if ( msg == WM_SETTINGCHANGE ) + { + if ( g_pMainFrame != NULL ) + { + // Reset the list and pop an error if they've chosen something we don't understand + //g_pMainFrame->PopulateConfigList(); + } + } + + return ::DefWindowProc(hwnd,msg,wparam,lparam); +} + +//----------------------------------------------------------------------------- +// Purpose: Creates a dummy window that handles windows messages +//----------------------------------------------------------------------------- +void CreateMessageWindow( void ) +{ + // Make and register a very simple window class + memset(&staticWndclass, 0, sizeof(staticWndclass)); + staticWndclass.style = 0; + staticWndclass.lpfnWndProc = messageProc; + staticWndclass.hInstance = GetModuleHandle(NULL); + staticWndclass.lpszClassName = "minidumpRipper_Window"; + staticWndclassAtom = ::RegisterClass( &staticWndclass ); + + // Create an empty window just for message handling + staticHwnd = CreateWindowEx(0, "minidumpRipper_Window", "Hidden Window", 0, 0, 0, 1, 1, NULL, NULL, GetModuleHandle(NULL), NULL); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void ShutdownMessageWindow( void ) +{ + // Kill our windows instance + ::DestroyWindow( staticHwnd ); + ::UnregisterClass("minidumpRipper_Window", ::GetModuleHandle(NULL)); +} + + +//----------------------------------------------------------------------------- +// Purpose: Setup all our VGUI info +//----------------------------------------------------------------------------- +bool InitializeVGUI( void ) +{ + vgui::ivgui()->SetSleep(false); + + // Init the surface + vgui::Panel *pPanel = new vgui::Panel( NULL, "TopPanel" ); + pPanel->SetVisible(true); + + vgui::surface()->SetEmbeddedPanel(pPanel->GetVPanel()); + + // load the scheme + vgui::scheme()->LoadSchemeFromFile( "resource/sourcescheme.res", NULL ); + + // localization + g_pVGuiLocalize->AddFile( "resource/platform_%language%.txt" ); + g_pVGuiLocalize->AddFile( "resource/vgui_%language%.txt" ); + g_pVGuiLocalize->AddFile( "mdmpRipper_english.txt" ); + + // Start vgui + vgui::ivgui()->Start(); + + // add our main window + g_pMainFrame = new CMDRipperMain( pPanel, "CMDRipperMain" ); + + // show main window + g_pMainFrame->MoveToCenterOfScreen(); + g_pMainFrame->Activate(); + g_pMainFrame->SetSizeable( true ); + g_pMainFrame->SetMenuButtonVisible( true ); + + g_pSqlWrapper = g_pMainFrame->GetSqlWrapper(); + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Stop VGUI +//----------------------------------------------------------------------------- +void ShutdownVGUI( void ) +{ + delete g_pMainFrame; +} + + +//----------------------------------------------------------------------------- +// The application object +//----------------------------------------------------------------------------- +class CMDRipperApp : public CVguiSteamApp +{ + typedef CVguiSteamApp BaseClass; + +public: + // Methods of IApplication + virtual bool Create(); + virtual bool PreInit(); + virtual int Main(); + virtual void PostShutdown(); + virtual void Destroy() {} +}; + +DEFINE_WINDOWED_STEAM_APPLICATION_OBJECT( CMDRipperApp ); + + +//----------------------------------------------------------------------------- +// The application object +//----------------------------------------------------------------------------- +bool CMDRipperApp::Create() +{ + AppSystemInfo_t appSystems[] = + { + { "inputsystem.dll", INPUTSYSTEM_INTERFACE_VERSION }, + { "vgui2.dll", VGUI_IVGUI_INTERFACE_VERSION }, + { "", "" } // Required to terminate the list + }; + + return AddSystems( appSystems ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Entry point +//----------------------------------------------------------------------------- +bool CMDRipperApp::PreInit() +{ + if ( !BaseClass::PreInit() ) + return false; + + // Create a window to capture messages + CreateMessageWindow(); + + FileSystem_SetErrorMode( FS_ERRORMODE_AUTO ); + + // We only want to use the gameinfo.txt that is in the bin\vconfig directory. + char dirName[MAX_PATH]; + Q_strncpy( dirName, GetBaseDirectory(), sizeof( dirName ) ); + Q_AppendSlash( dirName, sizeof( dirName ) ); + Q_strncat( dirName, "minidumpRipper", sizeof( dirName ), COPY_ALL_CHARACTERS ); + + if ( !BaseClass::SetupSearchPaths( dirName, true, true ) ) + { + ::MessageBox( NULL, "Error", "Unable to initialize file system\n", MB_OK ); + return false; + } + + // the "base dir" so we can scan mod name + g_pFullFileSystem->AddSearchPath(GetBaseDirectory(), MDRIPPER_MAIN_PATH_ID); + + // the main platform dir + g_pFullFileSystem->AddSearchPath("platform","PLATFORM", PATH_ADD_TO_HEAD); + g_pFullFileSystem->AddSearchPath(".\\minidumpRipper\\",MDRIPPER_WRITE_PATH, PATH_ADD_TO_HEAD); + + return true; +} + + +void CMDRipperApp::PostShutdown() +{ + // Stop our message window + ShutdownMessageWindow(); + + BaseClass::PostShutdown(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Entry point +//----------------------------------------------------------------------------- +int CMDRipperApp::Main() +{ + // Run app frame loop + if ( !InitializeVGUI() ) + return 0; + + // Run the app + while (vgui::ivgui()->IsRunning()) + { + Sleep( 10 ); + vgui::ivgui()->RunFrame(); + } + + ShutdownVGUI(); + + return 1; +} diff --git a/utils/mdmpRipper/mdmpRipper.h b/utils/mdmpRipper/mdmpRipper.h new file mode 100644 index 0000000..7f34e5e --- /dev/null +++ b/utils/mdmpRipper/mdmpRipper.h @@ -0,0 +1,33 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#ifndef ELEMENTVIEWER_H +#define ELEMENTVIEWER_H +#ifdef _WIN32 +#pragma once +#endif + + +namespace vgui +{ + class ISurface; + class IVGui; + class IPanel; +} + +class IFileSystem; +//class IMaterialSystem; +class IMatSystemSurface; + +/* +extern IFileSystem *g_pFileSystem; +extern IMaterialSystem *g_pMaterialSystem; +extern IMatSystemSurface *g_pMatSystemSurface; +extern vgui::ISurface *g_pVGuiSurface; +extern vgui::IVGui *g_pVGui; +extern vgui::IPanel *g_pVGuiPanel; +*/ +#endif // ELEMENTVIEWER_H diff --git a/utils/mdmpRipper/mdmpRipper.rc b/utils/mdmpRipper/mdmpRipper.rc new file mode 100644 index 0000000..a31bafe --- /dev/null +++ b/utils/mdmpRipper/mdmpRipper.rc @@ -0,0 +1,73 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON "icon_mdmpRipper.ico" +IDI_ICON2 ICON "icon2.ico" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/utils/mdmpRipper/mdmpRipperPanel.cpp b/utils/mdmpRipper/mdmpRipperPanel.cpp new file mode 100644 index 0000000..b39b8b3 --- /dev/null +++ b/utils/mdmpRipper/mdmpRipperPanel.cpp @@ -0,0 +1,151 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "mdmpRipper.h" +#include "vgui_controls/MessageMap.h" +#include "vgui_controls/MenuBar.h" +#include "vgui_controls/Menu.h" +#include "tier1/KeyValues.h" +#include "vgui/ISurface.h" +#include "vgui_controls/Frame.h" +#include "vgui_controls/FileOpenDialog.h" +#include "vgui_controls/MenuButton.h" +#include "CMDModulePanel.h" +#include "CMDErrorPanel.h" + + +using namespace vgui; + +//----------------------------------------------------------------------------- +// Test panel +//----------------------------------------------------------------------------- +class CVGuiTestPanel : public vgui::Panel +{ + DECLARE_CLASS_SIMPLE( CVGuiTestPanel, vgui::Panel ); + +public: + CVGuiTestPanel( vgui::Panel *pParent, const char *pName ); + + virtual void PerformLayout(); + +private: + MESSAGE_FUNC( OnOpen, "Open" ); + MESSAGE_FUNC( OnError, "Error" ); + MESSAGE_FUNC_PARAMS( OnCompare, "compare", data ); + MESSAGE_FUNC_CHARPTR( OnFileSelected, "FileSelected", fullpath ); + + void CVGuiTestPanel::MiniDumpCompare( CUtlVector<HANDLE> *pMiniDumpHandles ); + + vgui::MenuBar *m_pMenuBar; + vgui::Panel *m_pClientArea; + +// void OnFileSelected( const char * filename ); +}; + + +//----------------------------------------------------------------------------- +// Class factory +//----------------------------------------------------------------------------- +vgui::Panel *CreateVGuiTestPanel( const char *pName ) +{ + CVGuiTestPanel *pVGuiTestPanel = new CVGuiTestPanel( NULL, pName ); +// pVGuiTestPanel->SetParent( g_pVGuiSurface->GetEmbeddedPanel() ); + return pVGuiTestPanel; +} + + +//----------------------------------------------------------------------------- +// Constructor +//----------------------------------------------------------------------------- +CVGuiTestPanel::CVGuiTestPanel( vgui::Panel *pParent, const char *pName ) : BaseClass( NULL, pName ) +{ + + // Create the menu bar + m_pMenuBar = new vgui::MenuBar( this, "Main Menu Bar" ); + m_pMenuBar->SetSize( 10, 28 ); + + // Create a test menu + Menu *pFileMenu = new Menu(NULL, "File"); + pFileMenu->AddMenuItem( "&Open", new KeyValues( "Open" ), this ); + m_pMenuBar->AddMenu( "&File", pFileMenu ); + + Menu *pErrorMenu = new Menu(NULL, "Error"); + pErrorMenu->AddMenuItem( "&Error", new KeyValues("Error"), this); + m_pMenuBar->AddMenu( "&Error", pErrorMenu ); + + MenuButton *pCloseButton = new vgui::MenuButton( this, "Close", "X" ); + m_pMenuBar->AddButton( pCloseButton ); + + // Area below the menu bar + m_pClientArea = new vgui::Panel( this, "VGuiTest Client Area "); +} + + +//----------------------------------------------------------------------------- +// Test menu button +//----------------------------------------------------------------------------- +void CVGuiTestPanel::OnOpen() +{ + FileOpenDialog *pFileDialog = new FileOpenDialog ( this, "File Open", true); + pFileDialog->AddActionSignalTarget(this); + pFileDialog->AddFilter( "*.mdmp", "MiniDumps", true ); + pFileDialog->DoModal( false ); +} + +void CVGuiTestPanel::OnError() +{ + CMDErrorPanel *pPanel = new CMDErrorPanel( this, "MDError Panel" ); + pPanel->Create(); + pPanel->AddActionSignalTarget( this ); + pPanel->DoModal(); +} + + +//----------------------------------------------------------------------------- +// The editor panel should always fill the space... +//----------------------------------------------------------------------------- +void CVGuiTestPanel::PerformLayout() +{ + // Make the editor panel fill the space + int iWidth, iHeight; + + vgui::VPANEL parent = GetParent() ? GetParent()->GetVPanel() : vgui::surface()->GetEmbeddedPanel(); + vgui::ipanel()->GetSize( parent, iWidth, iHeight ); + SetSize( iWidth, iHeight ); + m_pMenuBar->SetSize( iWidth, 28 ); + + // Make the client area also fill the space not used by the menu bar + int iTemp, iMenuHeight; + m_pMenuBar->GetSize( iTemp, iMenuHeight ); + m_pClientArea->SetPos( 0, iMenuHeight ); + m_pClientArea->SetSize( iWidth, iHeight - iMenuHeight ); +} + +void CVGuiTestPanel::OnCompare( KeyValues *data ) +{ + int test = data->GetInt( "handlePointer" ); + CUtlVector<HANDLE> *pMiniDumpHandles = (CUtlVector<HANDLE> *)(void *)test; + CUtlVector<CMiniDumpObject *> miniDumps; + + for( int i = 0; i < pMiniDumpHandles->Count(); i++ ) + { + miniDumps.AddToTail( new CMiniDumpObject( pMiniDumpHandles->Element( i ) ) ); + } + CMDModulePanel *pPanel = new CMDModulePanel( this, "MDModule Panel" ); + pPanel->Create( &miniDumps ); + pPanel->DoModal(); + miniDumps.RemoveAll(); + pMiniDumpHandles->RemoveAll(); +} + +void CVGuiTestPanel::OnFileSelected( const char *filename ) +{ + CMDModulePanel *pPanel = new CMDModulePanel( this, "MDModule Panel" ); + pPanel->Create( filename ); + pPanel->DoModal(); +} + diff --git a/utils/mdmpRipper/mdmpripper.vpc b/utils/mdmpRipper/mdmpripper.vpc new file mode 100644 index 0000000..ccfe226 --- /dev/null +++ b/utils/mdmpRipper/mdmpripper.vpc @@ -0,0 +1,68 @@ +//----------------------------------------------------------------------------- +// MDMPRIPPER.VPC +// +// Project Script +//----------------------------------------------------------------------------- + +$Macro SRCDIR "..\.." +$Macro OUTBINDIR "$SRCDIR\..\game\bin" + +$Include "$SRCDIR\vpc_scripts\source_exe_con_win32_base.vpc" + +$Configuration +{ + $Compiler + { + $AdditionalIncludeDirectories "$BASE,$SRCDIR\vgui2\include,$SRCDIR\vgui2\controls,$SRCDIR\utils\common" + $EnableC++Exceptions "Yes (/EHsc)" + } + + $Linker + { + $AdditionalDependencies "$BASE dbgeng.lib shlwapi.lib comctl32.lib odbc32.lib odbccp32.lib Rpcrt4.lib dbghelp.lib sqlwrapper.lib" + } +} + +$Project "MdmpRipper" +{ + $Folder "Source Files" + { + $File "CDbgOutput.cpp" + $File "CMDDetailPanel.cpp" + $File "CMDErrorPanel.cpp" + $File "CMDModulePanel.cpp" + $File "CMDRipperMain.cpp" + $File "CMiniDumpObject.cpp" + $File "main.cpp" + $File "steamwebConnection.cpp" + $File "$SRCDIR\public\vgui_controls\vgui_controls.cpp" + } + + $Folder "Header Files" + { + $File "CDbgOutput.h" + $File "CMDDetailPanel.h" + $File "CMDErrorPanel.h" + $File "CMDModulePanel.h" + $File "CMDRipperMain.h" + $File "CMiniDumpObject.h" + $File "..\common\filesystem_tools.h" + $File "mdmpRipper.h" + } + + $Folder "Resource Files" + { + $File "icon2.ico" + $File "icon_mdmpRipper.ico" + $File "mdmpRipper.rc" + } + + $Folder "Link Libraries" + { + $DynamicFile "$SRCDIR\lib\public\appframework.lib" + $DynamicFile "$SRCDIR\lib\public\matsys_controls.lib" + $DynamicFile "$SRCDIR\lib\public\tier2.lib" + $DynamicFile "$SRCDIR\lib\public\tier3.lib" + $DynamicFile "$SRCDIR\lib\public\vgui_controls.lib" + } +} diff --git a/utils/mdmpRipper/steamwebConnection.cpp b/utils/mdmpRipper/steamwebConnection.cpp new file mode 100644 index 0000000..6ee7255 --- /dev/null +++ b/utils/mdmpRipper/steamwebConnection.cpp @@ -0,0 +1,83 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +#include <windows.h> +//#include <conio.h> +#include "vgui_controls/ListPanel.h" +#include "KeyValues.h" +#include "isqlwrapper.h" +#include "vgui/ISystem.h" + +#include "tier0/memdbgon.h" + +using namespace vgui; + +extern ISQLWrapper *g_pSqlWrapper; + +void getMiniDumpHandles( char* pszQuery, const char *errorid, CUtlVector<HANDLE> *pMiniDumpHandles ) +{ + char rgchQueryBuf[ 1024 ]; + + Q_snprintf( rgchQueryBuf, sizeof(rgchQueryBuf), pszQuery ); + IResultSet *results = g_pSqlWrapper->PResultSetQuery( rgchQueryBuf ); // do the query + Assert( results != NULL ); + + char command[1024] = ""; + + strcat( command, errorid ); + strcat( command, " minidumptool" ); + ::_spawnl( _P_WAIT, ".\\minidump.bat", "minidump.bat ", command, NULL ); + + char path[1024] = ""; + char *pathTraverse; + char newPath[1024] = ""; + for ( int i = 0; i < results->GetCSQLRow(); i++ ) + { + const ISQLRow *row = results->PSQLRowNextResult(); + Assert( row != NULL ); + strcpy( path, row->PchData(0) ); + pathTraverse = strchr( path, '/' ) + 1; + pathTraverse = strchr( pathTraverse, '/' ) + 1; + pathTraverse = strchr( pathTraverse, '/' ) + 1; + pathTraverse = strchr( pathTraverse, '/' ); + strcat( newPath, "c:/minidumptool" ); + strcat( newPath, pathTraverse ); + HANDLE hFile = CreateFile(newPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + pMiniDumpHandles->AddToTail( hFile ); + newPath[0] = 0; + } + g_pSqlWrapper->FreeResult(); +} +void errorsToListPanel( vgui::ListPanel *pTokenList, char* pszQuery ) +{ + char rgchQueryBuf[ 1024 ]; + + Q_snprintf( rgchQueryBuf, sizeof(rgchQueryBuf), pszQuery ); + IResultSet *results = g_pSqlWrapper->PResultSetQuery( rgchQueryBuf ); // do the query + Assert( results != NULL ); + + int errorid; + char errorbuf[128]; + char module[128]; + int count; + int minidumps; + char keyNameBuf[1024] = "module"; + char modNumBuf[4] = ""; + for ( int i = 0; i < results->GetCSQLRow(); i++ ) + { + const ISQLRow *row = results->PSQLRowNextResult(); + itoa( i, modNumBuf, 10 ); + strcat( keyNameBuf, modNumBuf ); + + errorid = row->NData(0); + itoa( errorid, errorbuf, 10 ); + strcpy( module, row->PchData(1) ); + count = row->NData(2); + minidumps = row->NData(3); + + KeyValues *kv = new KeyValues( keyNameBuf, "errorid", errorbuf, "module", module ); + kv->SetInt( "count", count ); + kv->SetInt( "minidumps", minidumps ); + pTokenList->AddItem(kv, i, false, false); + } + g_pSqlWrapper->FreeResult(); +}
\ No newline at end of file |