📄 type.cpp
字号:
#include "pch.h"
#include "util.h"
#include "main.h"
#include "type.h"
#include "doc.h"
#include "debug.h"
#include "record.h"
Type::Type ( )
{
m_pfnUserDecoder = NULL ;
}
Type::~Type ( )
{
}
// display name to a string
void Type::Present ( CString& str )
{
int i , n = m_arParam.GetSize ( ) ;
str = m_strName + " - " ;
for ( i = 0 ; i < n ; i++ )
{
ParamType& pt = m_arParam [ i ] ;
str += pt.m_pType->m_strName ;
for ( DWORD j = 0 ; j < pt.m_dwPointerDepth ; j++ )
{
str += '*' ;
}
str += ' ' ;
}
CString s ; s.Format ( "%d" , m_dwLength ) ;
str += s ;
}
// construct a ParamBlock for a parameter tree
ParamBlock* Type::Construct ( CDebugControl* pDebugControl ,
LPVOID lpAddress , DWORD dwPointer )
{
ParamBlock* p = new ParamBlock ;
ParamBlock* p2 ;
LPVOID addr ;
BOOL ret ;
DWORD i , j , n ;
p->m_pBlock = new BYTE [ p->m_dwSize = m_dwLength ] ;
p->m_bFunction = m_bFunction ;
p->m_bStruct = m_bStruct ;
ret = pDebugControl->ReadBlock ( lpAddress , p->m_pBlock , m_dwLength ) ;
p->m_strMsg = m_strName ;
for ( i = 0 ; i < dwPointer ; i++ )
p->m_strMsg += '*' ;
if ( ret == FALSE )
{
CString s ; s.Format ( IDS_INVALID_POINTER ) ;
p->m_strMsg += s ;
return p ;
}
// construct type name
if ( ret == TRUE && ( m_bStruct == TRUE || m_bFunction == TRUE ) )
{
n = m_arParam.GetSize ( ) ;
i = ( m_bFunction == TRUE ? 1 : 0 ) ;
for ( ; i < n ; i++ )
{
ParamType* pp = &m_arParam [ i ] ;
if ( pp->m_dwPointerDepth == 0 ) // base type refetch
{
p2 = pp->m_pType->Construct ( pDebugControl , lpAddress , pp->m_dwPointerDepth ) ;
p->m_arStruct.Add ( p2 ) ;
lpAddress = ( LPVOID ) ( ( DWORD ) lpAddress + pp->m_pType->m_dwLength ) ;
}
else // index pointer
{
addr = lpAddress ;
for ( j = pp->m_dwPointerDepth ; j > 0 ; j-- )
addr = ( LPVOID ) pDebugControl->ReadDWord ( addr ) ;
p2 = pp->m_pType->Construct ( pDebugControl , addr , pp->m_dwPointerDepth ) ;
p->m_arStruct.Add ( p2 ) ;
lpAddress = ( LPVOID ) ( ( DWORD ) lpAddress + 4 ) ;
}
}
return p ;
}
CString s ;
p->m_strMsg += " - " ;
// decode type
if ( m_pfnUserDecoder != NULL ) // use user-decoder
{
CHAR buf [ MAX_PATH ] ;
ZeroMemory ( buf , MAX_PATH ) ;
if ( m_pfnUserDecoder ( lpAddress , buf ) == TRUE )
{
p->m_strMsg += buf ;
return p ;
}
}
for ( i = 0 ; i < p->m_dwSize ; i++ )
{
s.Format ( "%02X" , p->m_pBlock [ i ] ) ;
p->m_strMsg += s ;
if ( i != p->m_dwSize - 1 )
p->m_strMsg += ' ' ;
}
return p ;
}
int Type::GetLength ( )
{
if ( m_bStruct == FALSE && m_bFunction == FALSE )
return m_dwLength ;
int s = 0 , i = ( m_bStruct == TRUE ? 0 : 1 ) , n = m_arParam.GetSize ( ) ;
for ( ; i < n ; i++ )
{
ParamType* p = &m_arParam [ i ] ;
if ( p->m_dwPointerDepth > 0 ) s += 4 ;
else s += p->m_pType->GetLength ( ) ;
}
return m_dwLength = s ;
}
TypeSet::TypeSet ( )
{
}
TypeSet::~TypeSet ( )
{
Dispose ( ) ;
}
void TypeSet::Dispose ( )
{
RELEASE_PTR_ARRAY ( m_arType , Type ) ;
m_mapType.RemoveAll ( ) ;
}
void TypeSet::GetAllLength ( )
{
int i , n = m_arType.GetSize ( ) ;
for ( i = 0 ; i < n ; i++ )
{
Type* p = ( Type* ) m_arType [ i ] ;
p->GetLength ( ) ;
}
}
// query a type
Type* TypeSet::Query ( const CString& strName )
{
Type* p ;
int i , n = m_arType.GetSize ( ) ;
for ( i = 0 ; i < n ; i++ )
{
p = ( Type* ) m_arType [ i ] ;
if ( p->m_strName.Compare ( strName ) == 0 )
return p ;
}
p = new Type ;
p->m_dwLength = 4 ;
p->m_strName = strName ;
p->m_bFunction = FALSE ;
p->m_bStruct = FALSE ;
m_arType.Add ( p ) ;
m_mapType [ strName ] = p ;
return p ;
}
void TypeSet::Append ( TypeSet* pTypeSet )
{
int i , n = pTypeSet->m_arType.GetSize ( ) ;
for ( i = 0 ; i < n ; i++ )
{
Type* p = ( Type* ) pTypeSet->m_arType [ i ] ;
Type* p2 = Query ( p->m_strName ) ;
*p2 = *p ;
}
}
CTypeManager::CTypeManager ( )
{
}
CTypeManager::~CTypeManager ( )
{
Dispose ( ) ;
}
void CTypeManager::AttachTo ( CDebugControl* pDebugControl )
{
m_pDebugControl = pDebugControl ;
}
// load type information from a gammar-file
void CTypeManager::LoadType ( CPtrArray& ar )
{
CPtrArray ar2 ;
LoadCommonType ( ar2 ) ;
CString pn ;
Hooked* ph ;
TypeSet* pt ;
LPVOID p ;
int i , j , n , n2 ;
n = ar.GetSize ( ) ;
for ( i = 0 ; i < n ; i++ )
{
ph = ( Hooked* ) ar [ i ] ;
CString fn , path ;
xSplitPathName ( ph->m_strExportPathName , fn , path ) ;
// set the default file name
pn = m_pDebugControl->m_pDancerDoc->m_strPath ; pn += fn ; pn += ".txt" ;
if ( xIsFileExisting ( pn ) == FALSE )
{
pn = ph->m_strExportPathName ;
pn += ".txt" ;
}
pn.MakeUpper ( ) ;
if ( m_mapTypeSet.Lookup ( pn , p ) == FALSE )
{
pt = new TypeSet ;
pt->m_strPathName = pn ;
n2 = ar2.GetSize ( ) ;
for ( j = 0 ; j < n2 ; j++ )
{
TypeSet* pt2 = ( TypeSet* ) ar2 [ j ] ;
pt->Append ( pt2 ) ;
}
LoadType ( pt ) ;
m_arTypeSet.Add ( pt ) ;
m_mapTypeSet [ pn ] = pt ;
}
else
{
pt = ( TypeSet* ) p ;
}
if ( ph->m_bHasName == TRUE ) // only for function has name
{
LPVOID p2 ;
if ( pt->m_mapType.Lookup ( ph->m_strFunction , p2 ) == TRUE )
{
ph->m_pType = ( Type* ) p2 ;
}
else
{
ph->m_pType = NULL ;
}
}
else ph->m_pType = NULL ;
}
}
void CTypeManager::Dispose ( )
{
RELEASE_PTR_ARRAY ( m_arTypeSet , TypeSet ) ;
}
// start parsing
void CTypeManager::LoadType ( TypeSet* pTypeSet )
{
FILE* fp = fopen ( pTypeSet->m_strPathName , "r" ) ;
if ( fp == NULL ) return ;
// open and load
int size = _filelength ( fp->_file ) + 1;
char* buf = new char [ size ] ;
memset ( buf , 0 , size ) ;
fread ( buf , 1, size , fp ) ;
fclose ( fp ) ;
RemoveComment ( buf ) ;
int n = Parse ( pTypeSet , buf ) ;
if ( n != -1 )
{
int i , col = 1 , line = 1 ;
for ( i = 0 ; i < n ; i++ )
{
if ( buf [ i ] == '\n' )
{
line++ ;
col = 1 ;
}
else col++ ;
}
col-- ;
// show error message
CString msg ;
msg.Format ( IDS_MSG_SYNTAX_ERROR , pTypeSet->m_strPathName , line , col ) ;
m_pDebugControl->m_pDancerDoc->m_pRecordManager->AddExtraMsg ( msg , 2 ) ;
pTypeSet->Dispose ( ) ;
}
pTypeSet->GetAllLength ( ) ;
#ifdef _DEBUG
pTypeSet->Dump ( ) ;
#endif
}
// get a token
BOOL CTypeManager::GetToken ( char* buf , int& p , Token& t )
{
while ( buf [ p ] && IsWhitespace ( buf [ p ] ) ) p++ ;
if ( buf [ p ] == 0 ) return FALSE ; // end of file
char c = buf [ p ] ;
t.m_dwNum = 0 ;
t.m_dwType = UNKNOWN ;
t.m_strName.Empty ( ) ;
if ( isdigit ( c ) )
{
do {
t.m_dwNum *= 10 ;
t.m_dwNum += ( c - '0' ) ;
c = buf [ ++p ] ;
} while ( isdigit ( c ) ) ;
t.m_dwType = NUM ;
}
else if ( IsNondigit ( c ) )
{
do {
t.m_strName += c ;
c = buf [ ++p ] ;
} while ( IsNondigit ( c ) ) ;
t.m_dwType = ID ;
}
else
{
if ( c == '*' ) t.m_dwType = POINTER ;
else if ( c == ',' ) t.m_dwType = COMMA ;
else if ( c == ';' ) t.m_dwType = SEMICOLON ;
else if ( c == '{' ) t.m_dwType = LB ;
else if ( c == '}' ) t.m_dwType = RB ;
else if ( c == '(' ) t.m_dwType = LS ;
else if ( c == ')' ) t.m_dwType = RS ;
else if ( c == '=' ) t.m_dwType = EQ ;
p++ ;
}
return TRUE ;
}
// two helper
BOOL CTypeManager::IsWhitespace ( int c )
{
return c == ' ' || c == '\t' || c == '\n' || c == '\r' ;
}
BOOL CTypeManager::IsNondigit ( int c )
{
return c == '_' || c == '@' || c == '?' ||
( c >= 'a' && c <= 'z' ) ||
( c >= 'A' && c <= 'Z' ) ||
( c >= '0' && c <= '8' ) ;
}
// delete all comment in file
void CTypeManager::RemoveComment ( char* buf )
{
int p = 0 , inc = 0 ;
char c ;
while ( c = buf [ p ] )
{
if ( inc == 0 )
{
if ( c == '/' && buf [ p + 1 ] == '*' )
{
buf [ p ] = buf [ p + 1 ] = ' ';
inc = 1 ;
}
}
else
{
if ( c == '*' && buf [ p + 1 ] == '/' )
{
buf [ p + 1 ] = ' ' ;
inc = 0 ;
}
if ( IsWhitespace ( c ) == FALSE )
buf [ p ] = ' ' ;
}
p++ ;
}
}
// a DFA driver
int CTypeManager::Parse ( TypeSet* pTypeSet , char* buf )
{
Token t ;
Type *pp , *ptp ;
ParamType pt ;
int p = 0 , st = 0 ;
DWORD ch ;
while ( GetToken ( buf , p , t ) )
{
switch ( st )
{
case 0:
pp = new Type ;
pp->m_arParam.RemoveAll ( ) ;
pp->m_dwLength = 0 ;
pp->m_bFunction = FALSE ;
pp->m_bStruct = FALSE ;
pp->m_strName.Empty ( ) ;
pp->m_pfnUserDecoder = NULL ;
if ( t.m_dwType == ID )
{
ptp = pTypeSet->Query ( t.m_strName ) ;
st = 1 ;
}
else return p ;
break ;
case 1:
if ( t.m_dwType == POINTER )
{
pt.m_pType = ptp ;
pt.m_dwPointerDepth = 1 ;
st = 2 ;
}
else if ( t.m_dwType == ID )
{
pt.m_pType = ptp ;
pt.m_dwPointerDepth = 0 ;
pp->m_strName = t.m_strName ;
pp->m_bFunction = TRUE ;
pp->m_arParam.Add ( pt ) ;
st = 9 ;
}
else if ( t.m_dwType == EQ )
{
pp->m_strName = ptp->m_strName ;
st = 3 ;
}
else return p ;
break ;
case 2:
if ( t.m_dwType == POINTER )
{
pt.m_dwPointerDepth++ ;
}
else if ( t.m_dwType == ID )
{
pp->m_strName = t.m_strName ;
pp->m_arParam.Add ( pt ) ;
st = 9 ;
}
else return p ;
break ;
case 3:
if ( t.m_dwType == LB )
{
pp->m_bStruct = TRUE ;
ch = RB ;
st = 4 ;
}
else if ( t.m_dwType == NUM )
{
pp->m_dwLength = t.m_dwNum ;
st = 5 ;
}
else return p ;
break ;
case 4:
if ( t.m_dwType == ID )
{
pt.m_pType = pTypeSet->Query ( t.m_strName ) ;
pt.m_dwPointerDepth = 0 ;
st = 6 ;
}
else if ( t.m_dwType == ch )
{
st = 8 ;
}
else return p ;
break ;
case 5:
if ( t.m_dwType == SEMICOLON )
{
Type* pp2 = pTypeSet->Query ( pp->m_strName ) ;
*pp2 = *pp ;
delete pp ;
st = 0 ;
}
else return p ;
break ;
case 6:
if ( t.m_dwType == POINTER )
{
pt.m_dwPointerDepth++ ;
}
else if ( t.m_dwType == COMMA )
{
pp->m_arParam.Add ( pt ) ;
st = 7 ;
}
else if ( t.m_dwType == ch )
{
pp->m_arParam.Add ( pt ) ;
st = 8 ;
}
else return p ;
break ;
case 7:
if ( t.m_dwType == ID )
{
pt.m_pType = pTypeSet->Query ( t.m_strName ) ;
pt.m_dwPointerDepth = 0 ;
st = 6 ;
}
else return p ;
break ;
case 8:
if ( t.m_dwType == SEMICOLON )
{
Type* pp2 = pTypeSet->Query ( pp->m_strName ) ;
*pp2 = *pp ;
delete pp ;
st = 0 ;
}
else return p ;
break ;
case 9:
if ( t.m_dwType == LS )
{
pp->m_bFunction = TRUE ;
ch = RS ;
st = 4 ;
}
else return p ;
break ;
}
}
if ( st != 0 ) return p ;
return -1 ;
}
// load type all type set has
void CTypeManager::LoadCommonType ( CPtrArray& ar )
{
CMainApp* p = ( CMainApp* ) AfxGetApp ( ) ;
TypeSet* pt ;
ar.RemoveAll ( ) ;
int i , n = p->m_appOption.m_arTypeFile.GetSize ( ) ;
for ( i = 0; i < n ; i++ )
{
CString& pn = p->m_appOption.m_arTypeFile [ i ] ;
pt = new TypeSet ;
pt->m_strPathName = pn ;
LoadType ( pt ) ;
ar.Add ( pt ) ;
m_arTypeSet.Add ( pt ) ;
}
}
// load user-decoder in my space
void CTypeManager::LoadDecoder ( )
{
CMainApp* p = ( CMainApp* ) AfxGetApp ( ) ;
int i , n = p->m_appOption.m_arDecoder.GetSize ( ) ;
for ( i = 0; i < n ; i++ )
{
LoadDecoder ( p->m_appOption.m_arDecoder [ i ] ) ;
}
}
void CTypeManager::LoadDecoder ( const CString& strPathName )
{
HMODULE hm ;
hm = LoadLibrary ( strPathName ) ;
if ( hm == NULL )
{
CString msg ;
msg.Format ( IDS_EXTRA_LOAD_PROCESSOR , strPathName ) ;
m_pDebugControl->m_pDancerDoc->m_pRecordManager->AddExtraMsg ( msg , 1 ) ;
return ;
}
RoutineEntry re ;
// call LoadRoutine
re.m_hControl = ( HANDLE ) m_pDebugControl ;
re.m_pfnOutputString = CDebugControl::_OutputString ;
re.m_pfnReadByte = CDebugControl::_ReadByte ;
re.m_pfnReadWord = CDebugControl::_ReadWord ;
re.m_pfnReadDWord = CDebugControl::_ReadDWord ;
re.m_pfnReadBlock = CDebugControl::_ReadBlock ;
re.m_pfnRegisterDecoder = CDebugControl::_RegisterDecoder ;
re.m_pfnReadString = CDebugControl::_ReadString ;
re.m_pfnReadStringW = CDebugControl::_ReadStringW ;
LPPROC_LOAD_ROUTINE pfn = ( LPPROC_LOAD_ROUTINE )
GetProcAddress ( hm , "LoadRoutine" ) ;
if ( pfn == NULL )
{
pfn = ( LPPROC_LOAD_ROUTINE )
GetProcAddress ( hm , "_LoadRoutine@4" ) ;
if ( pfn == NULL )
{
FreeLibrary ( hm ) ;
CString msg ;
msg.Format ( IDS_EXTRA_LOAD_PROCESSOR , strPathName ) ;
m_pDebugControl->m_pDancerDoc->m_pRecordManager->AddExtraMsg ( msg , 1 ) ;
return ;
}
}
pfn ( &re ) ;
m_arDecoder.Add ( hm ) ;
m_arModName.Add ( strPathName ) ;
CString msg ;
msg.Format ( IDS_EXTRA_LOAD_PROCESSOR_DONE , strPathName ) ;
m_pDebugControl->m_pDancerDoc->m_pRecordManager->AddExtraMsg ( msg , 0 ) ;
}
// unload from my space
void CTypeManager::UnloadDecoder ( )
{
int i , n = m_arDecoder.GetSize ( ) ;
for ( i = 0 ; i < n ; i++ )
{
HMODULE hm = ( HMODULE ) m_arDecoder [ i ] ;
LPPROC_UNLOAD_ROUTINE pfn = ( LPPROC_UNLOAD_ROUTINE )
GetProcAddress ( hm , "UnloadRoutine" ) ;
if ( pfn == NULL ) // try to call UnloadRoutine
{
pfn = ( LPPROC_UNLOAD_ROUTINE )
GetProcAddress ( hm , "_UnloadRoutine@0" ) ;
}
if ( pfn != NULL ) pfn ( ) ;
FreeLibrary ( hm ) ;
CString msg ;
msg.Format ( IDS_EXTRA_UNLOAD_PROCESSOR , m_arModName [ i ] ) ;
m_pDebugControl->m_pDancerDoc->m_pRecordManager->AddExtraMsg ( msg , 0 ) ;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -