text: #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 );
  }
  