📄 crashfinderdoc.cpp
字号:
/*----------------------------------------------------------------------
"Debugging Applications" (Microsoft Press)
Copyright (c) 1997-2000 John Robbins -- All rights reserved.
With excellent updates from Scott Bloom, Ching Ming Kwok,
Jeff Shanholtz, and Pablo Presedo!
----------------------------------------------------------------------*/
#include "stdafx.h"
#include "CrashFinder.h"
#include "CrashFinderDoc.h"
#include "CommonRoutines.h"
#include "SymbolEngine.h"
#include "FindView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE [] = __FILE__ ;
#endif
IMPLEMENT_DYNCREATE ( CCrashFinderDoc , CDocument )
BEGIN_MESSAGE_MAP ( CCrashFinderDoc , CDocument )
//{{AFX_MSG_MAP(CCrashFinderDoc)
ON_COMMAND ( ID_EDIT_FIND_CRASH , OnEditFindCrash )
ON_COMMAND ( ID_EDIT_ADD_IMAGE , OnEditAddImage )
ON_COMMAND ( ID_EDIT_REMOVE_IMAGE , OnEditRemoveImage )
ON_COMMAND ( ID_EDIT_IMAGE_PROPERTIES , OnEditImageProperties )
ON_UPDATE_COMMAND_UI ( ID_EDIT_REMOVE_IMAGE , OnUpdateEditRemoveImage )
ON_UPDATE_COMMAND_UI ( ID_EDIT_IMAGE_PROPERTIES , OnUpdateEditImageProperties )
//}}AFX_MSG_MAP
END_MESSAGE_MAP ( )
CCrashFinderDoc :: CCrashFinderDoc ( )
: CDocument ( ) ,
m_cDataArray ( ) ,
m_cSymEng ( )
{
ASSERT ( this ) ;
m_pcTreeControl = NULL ;
m_pcTreeView = NULL ;
m_pFormView = NULL ;
m_pEditControl = NULL ;
}
CCrashFinderDoc :: ~CCrashFinderDoc ( )
{
ASSERT ( this ) ;
}
BOOL CCrashFinderDoc :: OnNewDocument ( )
{
ASSERT ( this ) ;
// Go get a drink....
CWaitCursor cWait ;
if ( ( TRUE == SharedInitialization ( ) ) &&
( TRUE == CDocument::OnNewDocument ( ) ) )
{
// Let the user start adding binaries immediately.
if ( TRUE == AddAnImage ( ) )
{
// Force the selection to the first item, if possible.
HTREEITEM hItem = m_pcTreeControl->GetRootItem ( ) ;
if ( NULL != hItem )
{
m_pcTreeControl->SelectItem ( hItem ) ;
}
return ( TRUE ) ;
}
}
return ( FALSE ) ;
}
BOOL CCrashFinderDoc :: OnOpenDocument ( LPCTSTR lpszPathName )
{
ASSERT ( this ) ;
// Go get a drink....
CWaitCursor cWait ;
if ( ( TRUE == SharedInitialization ( ) ) &&
( TRUE == CDocument::OnOpenDocument ( lpszPathName ) ) )
{
return ( TRUE ) ;
}
return ( FALSE ) ;
}
void CCrashFinderDoc :: OnCloseDocument ( )
{
ASSERT ( this ) ;
int iCount = m_cDataArray.GetSize ( ) ;
for ( int i = 0 ; i < iCount ; i++ )
{
CBinaryImage * pImage = (CBinaryImage *)m_cDataArray[ i ] ;
ASSERT ( NULL != pImage ) ;
delete pImage ;
}
// Clean out the image list I set earlier, if the tree control is a
// valid window.
if ( TRUE == ::IsWindow ( m_pcTreeControl->m_hWnd ) )
{
CImageList * pImageList =
m_pcTreeControl->GetImageList(TVSIL_NORMAL);
if ( NULL != pImageList )
{
pImageList->DeleteImageList ( ) ;
delete pImageList ;
}
}
// Clean up the symbol engine.
BOOL bRet = m_cSymEng.SymCleanup ( ) ;
if ( FALSE == bRet )
{
ASSERT ( TRUE == bRet ) ;
TRACE ( "m_cSymEng.SymCleanup FAILED!!!\n" ) ;
}
// Now that I have done my cleanup, let the main framework do it's
// cleanup.
CDocument::OnCloseDocument ( ) ;
}
BOOL CCrashFinderDoc :: SharedInitialization ( void )
{
// BIG NOTE!
// This function is called BEFORE the main framework functions for
// document creation and loading. Only things that rely on the
// views can be done here. Don't try and access any of the
// document data as it is not valid yet.
ASSERT ( this ) ;
// Loop through the views looking for the one with the tree view.
// if there are no tree views, then initialization must fail.
POSITION pos = GetFirstViewPosition ( ) ;
while ( NULL != pos )
{
CView * pView = GetNextView ( pos ) ;
ASSERT ( NULL != pView ) ;
if ( TRUE == pView->IsKindOf ( RUNTIME_CLASS ( CTreeView ) ) )
{
m_pcTreeView = (CTreeView*)pView ;
m_pcTreeControl = &m_pcTreeView->GetTreeCtrl ( ) ;
ASSERT ( NULL != m_pcTreeControl ) ;
if ( NULL == m_pcTreeControl )
{
return ( FALSE ) ;
}
}
if ( TRUE == pView->IsKindOf ( RUNTIME_CLASS ( CFormView ) ) )
{
m_pFormView = (CFindView*)pView ;
m_pEditControl = m_pFormView->GetHexEditControl ( ) ;
}
}
ASSERT ( NULL != m_pcTreeControl ) ;
if ( NULL == m_pcTreeControl )
{
return ( FALSE ) ;
}
ASSERT ( NULL != m_pFormView ) ;
ASSERT ( NULL != m_pEditControl ) ;
// Initialize the tree control and get back the font used.
m_cTreeDisplay.InitializeTreeControl ( m_pcTreeControl ,
&m_cSymEng ) ;
// Finally, initialize the symbol engine.
return ( InitializeSymbolEngine ( m_cSymEng ) ) ;
}
BOOL CCrashFinderDoc :: LoadAndShowImage ( CBinaryImage * pImage ,
BOOL bModifiesDoc ,
BOOL bIgnoreDups )
{
// Check the assumptions from outside the function.
ASSERT ( this ) ;
ASSERT ( NULL != m_pcTreeControl ) ;
// A string that can be used for any user messages
CString sMsg ;
// The state for the tree graphic
int iState = STATE_NOTVALID ;
// A Boolean return value holder
BOOL bRet ;
// Make sure the parameter is good.
ASSERT ( NULL != pImage ) ;
if ( NULL == pImage )
{
// Nothing much can happen with a bad pointer.
return ( FALSE ) ;
}
// Check to see whether this image is valid. If it is, make sure
// that it isn't already in the list and that it doesn't have
// a conflicting load address. If it isn't a valid image, I add
// it anyway because it isn't good form just to throw out user
// data. If the image is bad, I just show it with the invalid
// bitmap and don't load it into the symbol engine.
if ( TRUE == pImage->IsValidImage ( ) )
{
// Here I walk through the items in the data array so that I can
// look for three problem conditions:
// 1. The binary image is already in the list. If so, I can
// only abort.
// 2. The binary is going to load at an address that's already
// in the list. If that's the case, I'll display the
// Properties dialog box for the binary image so that its
// load address can be changed before adding it to the list.
// 3. The project already includes an EXE image, and pImage is
// also an executable.
// I always start out assuming that the data in pImage is valid.
// Call me an optimist!
BOOL bValid = TRUE ;
int iCount = m_cDataArray.GetSize ( ) ;
for ( int i = 0 ; i < iCount ; i++ )
{
CBinaryImage * pTemp = (CBinaryImage *)m_cDataArray[ i ] ;
ASSERT ( NULL != pTemp ) ;
if ( NULL == pTemp )
{
// Not much can happen with a bad pointer!
return ( FALSE ) ;
}
// Do these two CString values match?
if ( pImage->GetFullName ( ) == pTemp->GetFullName ( ) )
{
if ( FALSE == bIgnoreDups )
{
// Tell the user!!
sMsg.FormatMessage ( IDS_DUPLICATEFILE ,
pTemp->GetFullName ( ) ) ;
AfxMessageBox ( sMsg ) ;
}
return ( FALSE ) ;
}
// If the current image from the data structure isn't
// valid, I'm up a creek. Although I can check
// duplicate names above, it's hard to check load
// addresses and EXE characteristics. If pTemp isn't valid,
// I have to skip these checks. Skipping them can lead
// to problems, but since pTemp is marked in the list as
// invalid, it's up to the user to reset the properties.
if ( TRUE == pTemp->IsValidImage ( FALSE ) )
{
// Check that I don't add two EXEs to the project.
if ( 0 == ( IMAGE_FILE_DLL &
pTemp->GetCharacteristics ( ) ) )
{
if ( 0 == ( IMAGE_FILE_DLL &
pImage->GetCharacteristics ( ) ) )
{
// Tell the user!!
sMsg.FormatMessage ( IDS_EXEALREADYINPROJECT ,
pImage->GetFullName ( ) ,
pTemp->GetFullName ( ) ) ;
AfxMessageBox ( sMsg ) ;
// Trying to load two images marked as EXEs will
// automatically have the data thrown out for
// pImage.
return ( FALSE ) ;
}
}
// Check for load address conflicts.
if ( pImage->GetLoadAddress ( ) ==
pTemp->GetLoadAddress( ) )
{
sMsg.FormatMessage ( IDS_DUPLICATELOADADDR ,
pImage->GetFullName ( ) ,
pTemp->GetFullName ( ) ) ;
if ( IDYES == AfxMessageBox ( sMsg , MB_YESNO ) )
{
// The user wants to change the properties by
// hand.
pImage->SetProperties ( ) ;
// Check that the load address really did
// change and that it doesn't now conflict with
// another binary.
int iIndex ;
if ( TRUE ==
IsConflictingLoadAddress (
pImage->GetLoadAddress(),
iIndex ))
{
sMsg.FormatMessage
( IDS_DUPLICATELOADADDRFINAL ,
pImage->GetFullName ( ) ,
((CBinaryImage*)m_cDataArray[iIndex])->GetFullName());
AfxMessageBox ( sMsg ) ;
// The data in pImage isn't valid, so go
// ahead and exit the loop.
bValid = FALSE ;
break ;
}
}
else
{
// The data in pImage isn't valid, so go
// ahead and exit the loop.
bValid = FALSE ;
pImage->SetBinaryError ( eAddressConflict ) ;
break ;
}
}
}
}
if ( TRUE == bValid )
{
// This image is good (at least up to the symbol load).
iState = STATE_VALIDATED ;
}
else
{
iState = STATE_NOTVALID ;
}
}
else
{
// This image isn't valid.
iState = STATE_NOTVALID ;
}
if ( STATE_VALIDATED == iState )
{
// Try to load this image into the symbol engine.
bRet =
m_cSymEng.SymLoadModule(NULL ,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -