summaryrefslogtreecommitdiff
path: root/utils/mdmpRipper
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /utils/mdmpRipper
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'utils/mdmpRipper')
-rw-r--r--utils/mdmpRipper/CDbgOutput.cpp86
-rw-r--r--utils/mdmpRipper/CDbgOutput.h35
-rw-r--r--utils/mdmpRipper/CMDDetailPanel.cpp40
-rw-r--r--utils/mdmpRipper/CMDDetailPanel.h31
-rw-r--r--utils/mdmpRipper/CMDErrorPanel.cpp139
-rw-r--r--utils/mdmpRipper/CMDErrorPanel.h40
-rw-r--r--utils/mdmpRipper/CMDModulePanel.cpp539
-rw-r--r--utils/mdmpRipper/CMDModulePanel.h67
-rw-r--r--utils/mdmpRipper/CMDRipperMain.cpp272
-rw-r--r--utils/mdmpRipper/CMDRipperMain.h83
-rw-r--r--utils/mdmpRipper/CMiniDumpObject.cpp246
-rw-r--r--utils/mdmpRipper/CMiniDumpObject.h63
-rw-r--r--utils/mdmpRipper/dbgeng.libbin0 -> 2144 bytes
-rw-r--r--utils/mdmpRipper/icon2.icobin0 -> 2238 bytes
-rw-r--r--utils/mdmpRipper/icon_mdmpRipper.icobin0 -> 2238 bytes
-rw-r--r--utils/mdmpRipper/main.cpp252
-rw-r--r--utils/mdmpRipper/mdmpRipper.h33
-rw-r--r--utils/mdmpRipper/mdmpRipper.rc73
-rw-r--r--utils/mdmpRipper/mdmpRipperPanel.cpp151
-rw-r--r--utils/mdmpRipper/mdmpripper.vpc68
-rw-r--r--utils/mdmpRipper/steamwebConnection.cpp83
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, &currentModule.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
new file mode 100644
index 0000000..9ec4a51
--- /dev/null
+++ b/utils/mdmpRipper/dbgeng.lib
Binary files differ
diff --git a/utils/mdmpRipper/icon2.ico b/utils/mdmpRipper/icon2.ico
new file mode 100644
index 0000000..0aa500f
--- /dev/null
+++ b/utils/mdmpRipper/icon2.ico
Binary files differ
diff --git a/utils/mdmpRipper/icon_mdmpRipper.ico b/utils/mdmpRipper/icon_mdmpRipper.ico
new file mode 100644
index 0000000..0aa500f
--- /dev/null
+++ b/utils/mdmpRipper/icon_mdmpRipper.ico
Binary files differ
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