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 ); |
|
}
|
|
|