From 3bf9df6b2785fa6d951086978a3e66f49427166a Mon Sep 17 00:00:00 2001 From: FluorescentCIAAfricanAmerican <0934gj3049fk@protonmail.com> Date: Wed, 22 Apr 2020 12:56:21 -0400 Subject: 1 --- utils/mdmpRipper/CMDModulePanel.cpp | 539 ++++++++++++++++++++++++++++++++++++ 1 file changed, 539 insertions(+) create mode 100644 utils/mdmpRipper/CMDModulePanel.cpp (limited to 'utils/mdmpRipper/CMDModulePanel.cpp') 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 +#include "mdmpRipper.h" +#include +#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 +#include "vgui_controls/Frame.h" +#include "CMDModulePanel.h" +#include "vgui_controls/ListPanel.h" +#include +#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 *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 *pMiniDumpHandles = (CUtlVector *)(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 ); +} + -- cgit v1.2.3