You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
246 lines
7.2 KiB
246 lines
7.2 KiB
//========= 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 );
|
|
}
|