//========= Copyright Valve Corporation, All rights reserved. ============// #include #include "tier1/strtools.h" #include #include "utlvector.h" #include #include "isqlwrapper.h" #include "CMiniDumpObject.h" extern ISQLWrapper *g_pSqlWrapper; CMiniDumpObject::CMiniDumpObject( const char *pszFilename, CUtlVector *pKnownModuleList ) { InitFromFilename( pszFilename, pKnownModuleList ); } CMiniDumpObject::CMiniDumpObject( HANDLE pMiniDumpHandle, CUtlVector *pKnownModuleList ) { InitFromHandle( pMiniDumpHandle, pKnownModuleList ); } void CMiniDumpObject::Init( HANDLE pszFileMap, CUtlVector *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 *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 *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 *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 ); }