windows-nt/Source/XPSP1/NT/sdktools/debuggers/excepmon/emshell/readlogsdlg.cpp
2020-09-26 16:20:57 +08:00

1021 lines
32 KiB
C++

// ReadLogsDlg.cpp : implementation file
//
#include "stdafx.h"
#include "emshell.h"
#include "ReadLogsDlg.h"
#include "EmShell.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern BSTR CopyBSTR( LPBYTE pb, ULONG cb );
const char* gslCarriageReturn = "\r";
const TCHAR* gtcFileOpenFlags = _T("w+b");
const TCHAR* gtcTempFilenameSeed = _T("ems");
const char* gslFirstChance = "first chance";
const char* gslCode = " - code";
const char* gslKV = "> kv";
const char* gslChildEBP = "ChildEBP";
const char* gslPrompt = ">";
const char* gslUEIP = "> u eip";
const char* gslSemiColon = ":";
const char* gslReadLogsAV = "READLOGS_AV";
const char* gslReadLogsDB = "READLOGS_DB";
const char* gslTildaStarKV = "~*kv";
const char* gslBangLocks = "!locks";
const char* gslIDColon = "id: ";
const char* gslCritSecText = "CritSec ";
const char gslSpace = ' ';
const char* gslOwningThread = "OwningThread";
const char* gslPeriod = ".";
const char* gslWaitForSingleObject = "WaitForSingleObject";
const char* gslWaitForMultipleObjects = "WaitForMultipleObjects";
const char* gslWaitForCriticalSection = "WaitForCriticalSection";
/////////////////////////////////////////////////////////////////////////////
// CReadLogsDlg dialog
CReadLogsDlg::CReadLogsDlg(PEmObject pEmObj, IEmManager *pEmMgr, CWnd* pParent /*=NULL*/)
: CDialog(CReadLogsDlg::IDD, pParent)
{
_ASSERTE( pEmObj != NULL );
_ASSERTE( pEmMgr != NULL );
m_pEmObject = pEmObj;
m_pIEmManager = pEmMgr;
m_bAdvancedWindow = FALSE;
m_pLogFile = NULL;
//{{AFX_DATA_INIT(CReadLogsDlg)
m_csCompleteLog = _T("");
m_strExceptionType = _T("");
m_strExceptionLocation = _T("");
m_strFailingInstruction = _T("");
//}}AFX_DATA_INIT
}
void CReadLogsDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CReadLogsDlg)
DDX_Control(pDX, IDC_STATIC_EXCEPINFO, m_ctlStaticExcepInfo);
DDX_Control(pDX, IDC_STATIC_HANGINFO, m_staticHangInfo);
DDX_Control(pDX, IDC_STATIC_FAILING_INSTRUCTION, m_ctlStaticFailingInstruction);
DDX_Control(pDX, IDC_STATIC_EXCEPTION_LOCATION, m_ctlStaticExceptionLocation);
DDX_Control(pDX, IDC_STATIC_EXCEPTION_TYPE, m_ctlStaticExceptionType);
DDX_Control(pDX, IDC_STATIC_CALL_STACK, m_ctlStaticCallStack);
DDX_Control(pDX, IDC_EDIT_FAILING_INSTRUCTION, m_ctlEditFailingInstruction);
DDX_Control(pDX, IDC_EDIT_EXCEPTION_TYPE, m_ctlEditExceptionType);
DDX_Control(pDX, IDC_EDIT_EXCEPTION_LOCATION, m_ctlEditExceptionLocation);
DDX_Control(pDX, IDC_LIST_CALL_STACK, m_ctlListControl);
DDX_Control(pDX, IDC_ADVANCED, m_ctrlAdvancedBtn);
DDX_Control(pDX, IDC_EDIT_READLOGS, m_ctrlCompleteReadLog);
DDX_Text(pDX, IDC_EDIT_READLOGS, m_csCompleteLog);
DDX_Text(pDX, IDC_EDIT_EXCEPTION_TYPE, m_strExceptionType);
DDX_Text(pDX, IDC_EDIT_EXCEPTION_LOCATION, m_strExceptionLocation);
DDX_Text(pDX, IDC_EDIT_FAILING_INSTRUCTION, m_strFailingInstruction);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CReadLogsDlg, CDialog)
//{{AFX_MSG_MAP(CReadLogsDlg)
ON_BN_CLICKED(IDC_ADVANCED, OnAdvanced)
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CReadLogsDlg message handlers
BOOL CReadLogsDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
HRESULT hr = E_FAIL;
ULONG lRead = 0L;
size_t tWritten = 0;
BSTR bstrEmObj = NULL;
TCHAR szTempDirPath[MAX_PATH] = {0};
TCHAR szTempFileName[MAX_PATH] = {0};
char lpszLogData[ISTREAM_BUFFER_SIZE];
do {
CWaitCursor wait;
if( !m_pEmObject || !m_pIEmManager ) break;
bstrEmObj = CopyBSTR( (LPBYTE) m_pEmObject, sizeof EmObject );
//Load the read logs stream from the manager
hr = m_pIEmManager->GetEmFileInterface( bstrEmObj, (IStream **)&m_pIEmStream );
if( FAILED(hr) ) break;
SysFreeString( bstrEmObj );
//Get the temporary system path
if ( 0 == GetTempPath( MAX_PATH, szTempDirPath ) ) break;
//Create a temp filename
GetTempFileName( szTempDirPath, gtcTempFilenameSeed, 0, szTempFileName);
m_pTempLogFileName = szTempFileName;
//Create a temp file in the system temp directory
m_pLogFile = _tfopen( m_pTempLogFileName, gtcFileOpenFlags );
if ( m_pLogFile == NULL ) break;
//Check the second line, if it's not either READLOGS_AV OR READLOGS_DB, cancel
for (int i = 1; i < 2; i++) {
hr = m_pIEmStream->Read( (void *)lpszLogData, ISTREAM_BUFFER_SIZE, &lRead );
if ( lRead == 0 || FAILED( hr ) ) break;
m_csCompleteLog += lpszLogData;
tWritten = fwrite( lpszLogData, sizeof( char ), lRead, m_pLogFile );
if ( tWritten == 0 ) {
hr = E_FAIL;
break;
}
if ( i == 1) {
//Check to see which version of the dlg we should be showing
if ( strstr( lpszLogData, gslReadLogsAV ) )
m_eReadLogType = ReadLogsType_Exception;
else if ( strstr( lpszLogData, gslReadLogsDB ) )
m_eReadLogType = ReadLogsType_Hang;
else
m_eReadLogType = ReadLogsType_None;
}
} while ( FALSE );
if ( FAILED( hr) ) break;
//Continue to read the log into the temp file
do {
hr = m_pIEmStream->Read( (void *)lpszLogData, ISTREAM_BUFFER_SIZE, &lRead );
if ( lRead == 0 || FAILED( hr ) ) break;
m_csCompleteLog += lpszLogData;
tWritten = fwrite( lpszLogData, sizeof( char ), lRead, m_pLogFile );
if ( tWritten == 0 ) {
hr = E_FAIL;
break;
}
} while (TRUE);
if ( FAILED( hr ) ) break;
//Flush the data to the file.
fflush( m_pLogFile );
switch ( m_eReadLogType ) {
case ReadLogsType_Exception:
ParseAndInitExceptionView();
break;
case ReadLogsType_Hang:
ParseAndInitHangView();
break;
case ReadLogsType_None:
ParseAndInitNoneView();
break;
default:
break;
}
UpdateData(FALSE);
} while ( FALSE );
SysFreeString( bstrEmObj );
if (m_pIEmStream) m_pIEmStream->Release();
//
// a-mando
//
ShowAppropriateControls();
ResizeAndReposControl();
// a-mando
SetDialogSize(FALSE);
if( FAILED(hr) ) {
//Show msg box
((CEmshellApp*)AfxGetApp())->DisplayErrMsgFromHR(hr);
return FALSE;
}
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CReadLogsDlg::SetDialogSize(BOOL bAdvanced)
{
CRect rtCompleteLog,
rtDlg;
GetWindowRect( &rtDlg );
m_ctrlCompleteReadLog.GetWindowRect( &rtCompleteLog );
rtDlg.bottom = rtCompleteLog.top;
if( bAdvanced ) {
rtDlg.bottom = rtCompleteLog.bottom + DLG_PIXEL_EXTEND_SIZE;
m_ctrlCompleteReadLog.ShowWindow(SW_SHOW);
}
MoveWindow(rtDlg);
}
void CReadLogsDlg::OnAdvanced()
{
CString csTemp;
// TODO: Add your control notification handler code here
if( !m_bAdvancedWindow )
{
SetDialogSize( TRUE );
m_bAdvancedWindow = TRUE;
csTemp.LoadString( IDS_READLOGS_ADVOPEN );
m_ctrlAdvancedBtn.SetWindowText( csTemp );
}
else
{
SetDialogSize(FALSE);
m_bAdvancedWindow = FALSE;
csTemp.LoadString( IDS_READLOGS_ADVCLOSE );
m_ctrlAdvancedBtn.SetWindowText( csTemp );
}
}
CReadLogsDlg::~CReadLogsDlg()
{
POSITION pos = NULL;
CString key;
CString* pVal = NULL;
ASSERT( m_pLogFile == NULL );
}
void CReadLogsDlg::ParseAndInitHangView()
{
//Show the controls for this view
//Hide the controls for this view
//Build map of critical sections
BuildCriticalSectionsMap();
//Build map of thread ID's
BuildThreadIDMap();
//Set the file cursor to the beginning of the logfile
ProcessKvThreadBlocks();
}
//
// a-mando
//
void CReadLogsDlg::ShowAppropriateControls()
{
//Enable the controls based on what view is selected
switch ( m_eReadLogType ) {
case ReadLogsType_None:
case ReadLogsType_Exception:
m_ctlStaticExcepInfo.ShowWindow(SW_SHOW);
m_staticHangInfo.ShowWindow(SW_HIDE);
m_ctlStaticFailingInstruction.ShowWindow(SW_SHOW);
m_ctlStaticExceptionLocation.ShowWindow(SW_SHOW);
m_ctlStaticExceptionType.ShowWindow(SW_SHOW);
m_ctlStaticCallStack.ShowWindow(SW_SHOW);
m_ctlEditFailingInstruction.ShowWindow(SW_SHOW);
m_ctlEditExceptionType.ShowWindow(SW_SHOW);
m_ctlEditExceptionLocation.ShowWindow(SW_SHOW);
m_ctlListControl.ShowWindow(SW_SHOW);
break;
case ReadLogsType_Hang:
m_staticHangInfo.ShowWindow(SW_SHOW);
//Disable all the controls except for the m_ctlHangListControl
break;
}
}
// a-mando
void CReadLogsDlg::ParseAndInitNoneView()
{
//Show the controls for this view
//Hide the controls for this view
}
void CReadLogsDlg::ParseAndInitExceptionView()
{
char szBuffer[MAX_TEMP_BUFFER_SIZE] = {0};
TCHAR szTmpBuffer[MAX_TEMP_BUFFER_SIZE] = {0};
char* pszOffset = NULL;
long lLastLineOffset = 0L;
char szException[MAX_TEMP_BUFFER_SIZE] = {0};
BOOL bFound = FALSE;
//Show the controls for this view
//Hide the controls for this view
do {
//Set the file cursor to the beginning of the logfile
fseek( m_pLogFile, 0, SEEK_SET );
do {
//Search through each line looking for the "(first chance)" text
pszOffset = fgets( szBuffer, MAX_TEMP_BUFFER_SIZE, m_pLogFile );
if ( pszOffset == NULL ) break;
pszOffset = strstr( szBuffer, gslFirstChance );
if ( pszOffset == 0 ) continue;
//Get the current byte offset. Note this is the next line, not the first chance line
lLastLineOffset = ftell( m_pLogFile );
if ( lLastLineOffset == -1L ) break;
//Store off the line just matched
strcpy( szException, szBuffer );
bFound = TRUE;
} while ( TRUE );
if ( !bFound ) break;
//Parse the szException for the readable exception text
//Get the position of the word "code", and then only get the string up to that point
pszOffset = strstr( szException, gslCode );
if ( pszOffset != NULL ) //a-kjaw, bug ID: 296028
*pszOffset = '\0';
//Store off szException to the dialog control
m_strExceptionType = szException;
bFound = FALSE; //Reset
//Handle ~KV
//Set the file pointer back to the last exception position or break if there is a problem
do {
if ( fseek( m_pLogFile, lLastLineOffset, SEEK_SET ) ) break;
do {
//Search through each line looking for the "> kv" text
pszOffset = fgets( szBuffer, MAX_TEMP_BUFFER_SIZE, m_pLogFile );
if ( pszOffset == NULL ) break;
pszOffset = strstr( szBuffer, gslKV );
if ( pszOffset == 0 ) continue;
bFound = TRUE;
break;
} while ( TRUE );
if ( !bFound ) break;
bFound = FALSE; //Reset
do {
//Search through each line looking for the "ChildEBP" text
pszOffset = fgets( szBuffer, MAX_TEMP_BUFFER_SIZE, m_pLogFile );
if ( pszOffset == NULL ) break;
pszOffset = strstr( szBuffer, gslChildEBP );
if ( pszOffset == 0 ) continue;
bFound = TRUE;
break;
} while ( TRUE );
if ( !bFound ) break;
bFound = FALSE; //Reset
do {
//Search through each line getting the call stack strings and
//populating the list control with them
pszOffset = fgets( szBuffer, MAX_TEMP_BUFFER_SIZE, m_pLogFile );
if ( pszOffset == NULL ) break;
pszOffset = strstr( szBuffer, gslPrompt );
if ( pszOffset != 0 ) break;
pszOffset = strstr( szBuffer, gslCarriageReturn );
*pszOffset = 0;
//Get the string from offset 45 on and insert into list control
mbstowcs( szTmpBuffer, szBuffer + sizeof( char[45] ), MAX_TEMP_BUFFER_SIZE );
m_ctlListControl.AddString( szTmpBuffer );
} while ( TRUE );
} while ( FALSE );
//Handle u eip
do {
if ( fseek( m_pLogFile, lLastLineOffset, SEEK_SET ) ) break;
do {
//Search through each line looking for the "> u eip" text
pszOffset = fgets( szBuffer, MAX_TEMP_BUFFER_SIZE, m_pLogFile );
if ( pszOffset == NULL ) break;
pszOffset = strstr( szBuffer, gslUEIP );
if ( pszOffset == 0 ) continue;
bFound = TRUE;
break;
} while ( TRUE );
if ( !bFound ) break;
bFound = FALSE; //Reset
//Get the first item in the list control
m_ctlListControl.GetText( 0, m_strExceptionLocation );
do {
//Get the immediate next line and stuff it into the failing instruction
pszOffset = fgets( szBuffer, MAX_TEMP_BUFFER_SIZE, m_pLogFile );
if ( pszOffset == NULL ) break;
//If the line has a semicolon, skip it.
pszOffset = strstr( szBuffer, gslSemiColon );
if ( pszOffset != NULL ) {
pszOffset = fgets( szBuffer, MAX_TEMP_BUFFER_SIZE, m_pLogFile );
}
pszOffset = strstr( szBuffer, gslCarriageReturn );
*pszOffset = 0;
m_strFailingInstruction = szBuffer + sizeof( char[26] );
bFound = TRUE;
break;
} while ( TRUE );
} while ( FALSE );
} while ( FALSE );
if ( !bFound ) {
//We didn't find an exception, error to the user
}
}
void CReadLogsDlg::OnDestroy()
{
CDialog::OnDestroy();
// TODO: Add your message handler code here
//Release the handle to the file
if ( m_pLogFile ) {
fclose( m_pLogFile );
m_pLogFile = NULL;
DeleteFile( m_pTempLogFileName );
}
}
void CReadLogsDlg::BuildCriticalSectionsMap()
{
BOOL bFound = FALSE;
char *pszOffset = NULL;
char *pszTempOffset = NULL;
char szBuffer[MAX_TEMP_BUFFER_SIZE] = {0};
CString csAddress;
CString *pcsOwningThread = NULL;
do {
//Set the file cursor to the beginning of the logfile
fseek( m_pLogFile, 0, SEEK_SET );
do {
//Search through each line looking for the "!Locks" command
pszOffset = fgets( szBuffer, MAX_TEMP_BUFFER_SIZE, m_pLogFile );
if ( pszOffset == NULL ) break;
pszOffset = strstr( szBuffer, gslBangLocks );
if ( pszOffset == NULL ) continue;
bFound = TRUE;
break;
} while ( TRUE );
if ( !bFound ) break;
bFound = FALSE;
//We're now at the !Locks area of the log file
do {
//We are now poised to extract the critical section address and the internal thread ID
do {
//Search through the block looking for the "CritSec" text or the "> " prompt
pszOffset = fgets( szBuffer, MAX_TEMP_BUFFER_SIZE, m_pLogFile );
if ( pszOffset == NULL ) break;
pszOffset = strstr( szBuffer, gslCritSecText );
//If "CritSec" is not in the string, look for the prompt
if ( pszOffset == NULL ) {
pszOffset = strstr( szBuffer, gslPrompt );
//If the prompt is not in the string, continue
if ( pszOffset == NULL ) {
continue;
}
else break;
}
pszOffset = strstr( szBuffer, gslCarriageReturn );
if( pszOffset != NULL ) // a-mando, bug ID: 296029
*pszOffset = '\0';
//We have a "CritSec", get the address from the right most edge
pszOffset = strrchr( szBuffer, gslSpace );
if ( pszOffset == NULL ) break;
csAddress = pszOffset + 1;
csAddress.MakeLower();
bFound = TRUE;
break;
} while ( TRUE );
if ( !bFound ) break;
bFound = FALSE;
do {
//Search through the block looking for the "OwningThread" text or the "> " prompt
pszOffset = fgets( szBuffer, MAX_TEMP_BUFFER_SIZE, m_pLogFile );
if ( pszOffset == NULL ) break;
pszOffset = strstr( szBuffer, gslOwningThread );
//If "OwningThread" is not in the string, look for the prompt
if ( pszOffset == NULL ) {
pszOffset = strstr( szBuffer, gslPrompt );
//If the prompt is not in the string, continue
if ( pszOffset == NULL ) {
continue;
}
else break;
}
//We have an "OwningThread", get the internal thread ID from the right most edge
pszOffset = strrchr( szBuffer, gslSpace );
if ( pszOffset == NULL ) break;
pszTempOffset = strstr( pszOffset, gslCarriageReturn );
if ( pszTempOffset != NULL ) *pszTempOffset = '\0';
CString pcsOwningThread = pszOffset + 1 ;
//Add the address and owning thread to the critical section map
m_mapCriticalSection.SetAt( csAddress, (CString&) pcsOwningThread );
bFound = TRUE;
break;
} while ( TRUE );
if ( !bFound ) break;
bFound = FALSE;
} while ( TRUE );
if ( !bFound ) break;
bFound = FALSE;
} while ( FALSE );
}
void CReadLogsDlg::BuildThreadIDMap()
{
BOOL bFound = FALSE;
char *pszStartOffset = NULL;
char *pszEndOffset = NULL;
char szBuffer[MAX_TEMP_BUFFER_SIZE] = {0};
CString* pcsThreadVal = NULL;
CString csThreadKey;
do {
//Set the file cursor to the beginning of the logfile
fseek( m_pLogFile, 0, SEEK_SET );
do {
//Search through each line looking for the "~*kv" command
pszStartOffset = fgets( szBuffer, MAX_TEMP_BUFFER_SIZE, m_pLogFile );
if ( pszStartOffset == NULL ) break;
pszStartOffset = strstr( szBuffer, gslTildaStarKV );
if ( pszStartOffset == NULL ) continue;
bFound = TRUE;
break;
} while ( TRUE );
if ( !bFound ) break;
bFound = FALSE;
//We're now at the ~*kv area of the log file
do {
//We are now poised to extract the critical section address and the internal thread ID
do {
//Search through the block looking for the "id: " text or the "> " prompt
pszStartOffset = fgets( szBuffer, MAX_TEMP_BUFFER_SIZE, m_pLogFile );
if ( pszStartOffset == NULL ) break;
pszStartOffset = strstr( szBuffer, gslIDColon );
//If "id: " is not in the string, look for the prompt
if ( pszStartOffset == NULL ) {
pszStartOffset = strstr( szBuffer, gslPrompt );
//If the prompt is not in the string, continue
if ( pszStartOffset == NULL ) {
continue;
}
else break;
}
//We have an "id: ", get the internal thread ID and ordered thread ID
CString pcsThreadVal = GetThreadID( szBuffer );
csThreadKey = GetThreadNumber( szBuffer );
csThreadKey.MakeLower();
m_mapThreadID.SetAt( csThreadKey, (CString&) pcsThreadVal );
bFound = TRUE;
break;
} while ( TRUE );
if ( !bFound ) break;
bFound = FALSE;
} while ( TRUE );
if ( !bFound ) break;
bFound = FALSE;
}while ( FALSE );
}
char* CReadLogsDlg::GetThreadID( char* szBuffer )
{
char *pszStartOffset = NULL;
char *pszEndOffset = NULL;
do {
pszStartOffset = strstr( szBuffer, gslPeriod );
if ( pszStartOffset == NULL ) break;
if ( pszStartOffset == szBuffer ) {
szBuffer++;
continue;
}
pszStartOffset++;
//increment 1 past the period we're sitting on. Unless it's the first one we're encountering
pszEndOffset = strchr( pszStartOffset, gslSpace );
if ( pszEndOffset == NULL ) break;
*pszEndOffset = '\0';
break;
} while ( TRUE );
return pszStartOffset;
}
char* CReadLogsDlg::GetThreadNumber( char* szBuffer )
{
char *pszStartOffset = NULL;
char *pszEndOffset = NULL;
//Look for the first occurance of a numeric number
pszStartOffset = szBuffer;
for ( ; (!isdigit( *pszStartOffset ) || *pszStartOffset == '.') && *pszStartOffset != '\0'; ) {
pszStartOffset++;
}
pszEndOffset = strchr( pszStartOffset, gslSpace );
*pszEndOffset = '\0';
return pszStartOffset;
}
void CReadLogsDlg::GetFirstParameter( char* szBuffer, CString &str )
{
char* token = NULL;
//Tokenize the buffer and get the 3rd token and set to str
token = strtok( szBuffer, &gslSpace );
for ( int i = 1; i < 3 && token != NULL; i++)
{
/* Get next token: */
token = strtok( NULL, &gslSpace );
}
str = token;
}
void CReadLogsDlg::GetSecondParameter( char* szBuffer, CString &str )
{
char* token = NULL;
//Tokenize the buffer and get the 3rd token and set to str
token = strtok( szBuffer, &gslSpace );
for ( int i = 1; i < 4 && token != NULL; i++)
{
/* Get next token: */
token = strtok( NULL, &gslSpace );
}
str = token;
}
void CReadLogsDlg::GetThirdParameter( char* szBuffer, CString &str )
{
char* token = NULL;
//Tokenize the buffer and get the 3rd token and set to str
token = strtok( szBuffer, &gslSpace );
for ( int i = 1; i < 5 && token != NULL; i++)
{
/* Get next token: */
token = strtok( NULL, &gslSpace );
}
str = token;
}
void CReadLogsDlg::ProcessKvThreadBlocks()
{
BOOL bFound = FALSE;
char *pszStartOffset = NULL;
char *pszEndOffset = NULL;
char szBuffer[MAX_TEMP_BUFFER_SIZE] = {0};
char szOriginalBuffer[MAX_TEMP_BUFFER_SIZE] = {0};
CString csThreadID;
CString csThreadNumber;
CString csOutput;
CString csFirstParameter;
CString csSecondParameter;
CString csThirdParameter;
CString csOwningThread;
do {
//Set the file cursor to the beginning of the logfile
fseek( m_pLogFile, 0, SEEK_SET );
do {
//Search through each line looking for the "~*kv" command
pszStartOffset = fgets( szBuffer, MAX_TEMP_BUFFER_SIZE, m_pLogFile );
if ( pszStartOffset == NULL ) break;
pszStartOffset = strstr( szBuffer, gslTildaStarKV );
if ( pszStartOffset == NULL ) continue;
bFound = TRUE;
break;
} while ( TRUE );
if ( !bFound ) break;
bFound = FALSE;
//We're now at the ~*kv area of the log file
do {
//We are now poised to handle determining output string for thread states
do {
//Search through the block looking for the "id: " text or the "> " prompt
pszStartOffset = fgets( szBuffer, MAX_TEMP_BUFFER_SIZE, m_pLogFile );
if ( pszStartOffset == NULL ) break;
//Let's keep a copy of the original around
strcpy( szOriginalBuffer, szBuffer );
pszStartOffset = strstr( szBuffer, gslIDColon );
//If "id: " is not in the string, look for the prompt
if ( pszStartOffset == NULL ) {
pszStartOffset = strstr( szBuffer, gslPrompt );
//If the prompt is not in the string, continue
if ( pszStartOffset == NULL ) {
continue;
}
else break;
}
csThreadNumber = GetThreadNumber( szBuffer );
strcpy( szBuffer, szOriginalBuffer );
csThreadID = GetThreadID( szBuffer );
strcpy( szBuffer, szOriginalBuffer );
//Search through the block looking for the "ChildEBP" text or the "> " prompt
pszStartOffset = fgets( szBuffer, MAX_TEMP_BUFFER_SIZE, m_pLogFile );
if ( pszStartOffset == NULL ) break;
//Let's keep a copy of the original around
strcpy( szOriginalBuffer, szBuffer );
pszStartOffset = strstr( szBuffer, gslChildEBP );
//If "ChildEBP" is not in the string, look for the prompt
if ( pszStartOffset == NULL ) {
pszStartOffset = strstr( szBuffer, gslPrompt );
//If the prompt is not in the string, continue
if ( pszStartOffset == NULL ) {
continue;
}
else break;
}
//We have found the "ChildEBP", so skip it! hahahahaa (what a waste)
pszStartOffset = fgets( szBuffer, MAX_TEMP_BUFFER_SIZE, m_pLogFile );
if ( pszStartOffset == NULL ) break;
//Let's keep a copy of the original around
strcpy( szOriginalBuffer, szBuffer );
if ( strstr( szBuffer, gslWaitForSingleObject ) ) {
//Get the next line and look for WaitForCriticalSection
pszStartOffset = fgets( szBuffer, MAX_TEMP_BUFFER_SIZE, m_pLogFile );
if ( pszStartOffset == NULL ) break;
//Let's keep a copy of the original around
strcpy( szOriginalBuffer, szBuffer );
pszStartOffset = strstr( szBuffer, gslWaitForCriticalSection );
//If "WaitForCriticalSection" is not in the string, look for the prompt
if ( pszStartOffset == NULL ) {
pszStartOffset = strstr( szBuffer, gslPrompt );
//If the prompt is not in the string, continue
if ( pszStartOffset == NULL ) {
GetFirstParameter( szBuffer, csFirstParameter );
strcpy( szBuffer, szOriginalBuffer );
csOutput.Format( _T("Thread %s is in a WaitForSingleObject() call on object %s"), csThreadNumber, csFirstParameter );
bFound = TRUE;
break;
}
else break;
}
//"WaitForCriticalSection" is in the string,
//Get the 5th token (3rd parameter) and look it up in the critical section map
GetThirdParameter( szBuffer, csThirdParameter );
strcpy( szBuffer, szOriginalBuffer );
csThirdParameter.MakeLower();
BOOL bFoundInMap = m_mapCriticalSection.Lookup( csThirdParameter, (CString&) csOwningThread );
//If not found in map,
if ( !bFoundInMap ) {
csOutput.Format( _T("Thread %s id: %s is in WaitForCriticalSection() call on object %s"), csThreadNumber, csThreadID, csThirdParameter );
bFound = TRUE;
break;
}
else {
csOutput.Format( _T("Thread %s id: %s is in WaitForCriticalSection() call on object %s. Thread %s is the owning thread."), csThreadNumber, csThreadID, csThirdParameter, csOwningThread);
bFound = TRUE;
break;
}
}
else if ( strstr( szBuffer, gslWaitForMultipleObjects ) ) {
GetFirstParameter( szBuffer, csFirstParameter );
strcpy( szBuffer, szOriginalBuffer );
GetSecondParameter( szBuffer, csSecondParameter );
strcpy( szBuffer, szOriginalBuffer );
csOutput.Format( _T("Thread %s id: %s is in a WaitForMultipleObjects() call on %s objects at address %s"), csThreadNumber, csThreadID, csFirstParameter, csSecondParameter );
bFound = TRUE;
break;
}
else {
csOutput.Format( _T("Thread %s is not in a known wait state"), csThreadNumber );
bFound = TRUE;
break;
}
if ( !bFound ) break;
bFound = FALSE;
} while ( TRUE );
if ( !bFound ) break;
bFound = FALSE;
//Output the text to the list control
m_ctlListControl.AddString( csOutput );
} while ( TRUE );
if ( !bFound ) break;
bFound = FALSE;
} while ( TRUE );
}
//
// a-mando
//
void CReadLogsDlg::ResizeAndReposControl()
{
CRect rtListCtrl,
rtHangInfo,
rtDlg;
GetWindowRect( &rtDlg );
m_staticHangInfo.GetWindowRect( &rtHangInfo );
m_ctlListControl.GetWindowRect( &rtListCtrl );
ScreenToClient( &rtDlg );
ScreenToClient( &rtHangInfo );
ScreenToClient( &rtListCtrl );
switch ( m_eReadLogType ) {
case ReadLogsType_Exception:
break;
case ReadLogsType_Hang:
m_staticHangInfo.ShowWindow(SW_SHOW);
rtListCtrl.left = rtDlg.left + DLG_PIXEL_EXTEND_SIZE;
rtListCtrl.top = rtHangInfo.bottom + DLG_PIXEL_EXTEND_SIZE;
m_ctlListControl.MoveWindow(&rtListCtrl);
m_ctlListControl.ShowWindow(SW_SHOW);
break;
case ReadLogsType_None:
//Disable all the controls
break;
}
}
// a-mando