source-engine/utils/mdmpRipper/CMiniDumpObject.cpp

247 lines
7.2 KiB
C++
Raw Normal View History

2020-04-22 16:56:21 +00:00
//========= 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 );
}