887 lines
21 KiB
C
887 lines
21 KiB
C
|
#include "pwalker.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include "resource.h"
|
||
|
|
||
|
#define DLG_MSG(hwnd, message, fn) \
|
||
|
case (message): return (BOOL) HANDLE_##message((hwnd), (wParam), (lParam), (fn))
|
||
|
#define WPPS WritePrivateProfileString
|
||
|
#define GPPI GetPrivateProfileInt
|
||
|
#define Clear(x) memset(&x, 0, sizeof(x))
|
||
|
|
||
|
#define DUMP_WINDOW_EXTRA 16
|
||
|
|
||
|
#define GET_DUMP_PROCESS(hwnd) (HANDLE) GetWindowLong(hwnd, 0)
|
||
|
#define GET_DUMP_START(hwnd) GetWindowLong(hwnd, 4)
|
||
|
#define GET_DUMP_END(hwnd) GetWindowLong(hwnd, 8)
|
||
|
#define GET_DUMP_OFFSET(hwnd) GetWindowLong(hwnd, 12)
|
||
|
#define GET_DUMP_CY(hwnd) GetWindowLong(hwnd, 16)
|
||
|
|
||
|
#define SET_DUMP_PROCESS(hwnd, x) SetWindowLong(hwnd, 0, (DWORD) x)
|
||
|
#define SET_DUMP_START(hwnd, x) SetWindowLong(hwnd, 4, x)
|
||
|
#define SET_DUMP_END(hwnd, x) SetWindowLong(hwnd, 8, x)
|
||
|
#define SET_DUMP_OFFSET(hwnd, x) SetWindowLong(hwnd, 12, x)
|
||
|
#define SET_DUMP_CY(hwnd, x) SetWindowLong(hwnd, 16, x)
|
||
|
#define IDC_STATUS 8888
|
||
|
|
||
|
// Type definitions for pointers to call tool help functions.
|
||
|
typedef BOOL (WINAPI *MODULEWALK)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);
|
||
|
typedef BOOL (WINAPI *THREADWALK)(HANDLE hSnapshot, LPTHREADENTRY32 lpte);
|
||
|
typedef BOOL (WINAPI *PROCESSWALK)(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
|
||
|
typedef HANDLE (WINAPI *CREATESNAPSHOT)(DWORD dwFlags, DWORD th32ProcessID);
|
||
|
|
||
|
//
|
||
|
// global variables
|
||
|
//
|
||
|
static CREATESNAPSHOT pCreateToolhelp32Snapshot = NULL;
|
||
|
static MODULEWALK pModule32First = NULL;
|
||
|
static MODULEWALK pModule32Next = NULL;
|
||
|
static PROCESSWALK pProcess32First = NULL;
|
||
|
static PROCESSWALK pProcess32Next = NULL;
|
||
|
static THREADWALK pThread32First = NULL;
|
||
|
static THREADWALK pThread32Next = NULL;
|
||
|
|
||
|
static HINSTANCE ghInstance = NULL;
|
||
|
static HWND ghwndProcesses = NULL;
|
||
|
static HWND ghwndMemory = NULL;
|
||
|
static HWND ghwndStatus = NULL;
|
||
|
static HCURSOR ghWait = NULL;
|
||
|
static BOOL gfToolhelp = FALSE;
|
||
|
static HANDLE ghSnapshot = NULL;
|
||
|
static HANDLE ghTargetProcess = NULL;
|
||
|
static HWND ghwndDump = NULL;
|
||
|
static UINT um_dump = 0;
|
||
|
static DWORD gcyLine = 0;
|
||
|
static char gszIniFile[] = "pwalker.ini";
|
||
|
static char gszPreferences[] = "Preferences";
|
||
|
static char gszDialogX[] = "X";
|
||
|
static char gszDialogY[] = "Y";
|
||
|
static char gszDumpWindowClass[] = "Dump Window";
|
||
|
static char gszDumpX[] = "Dump X";
|
||
|
static char gszDumpY[] = "Dump Y";
|
||
|
static char gszDumpCX[] = "DumpCX";
|
||
|
static char gszDumpCY[] = "DumpCY";
|
||
|
|
||
|
//
|
||
|
// forward functions declarations
|
||
|
//
|
||
|
BOOL CALLBACK main_dlgproc( HWND, UINT, WPARAM, LPARAM );
|
||
|
void main_OnCommand( HWND, UINT, HWND, UINT );
|
||
|
LONG main_OnNotify( HWND, int, LPNMHDR );
|
||
|
BOOL main_OnInitDialog( HWND, HWND, LPARAM );
|
||
|
void main_OnClose( HWND );
|
||
|
void main_OnDestroy( HWND );
|
||
|
BOOL InitToolhelp32 ( void );
|
||
|
void WalkProcesses( void );
|
||
|
void WalkProcess( void );
|
||
|
void DumpProcessMemory( void );
|
||
|
LRESULT CALLBACK dump_wndproc( HWND, UINT, WPARAM, LPARAM );
|
||
|
int ListView_GetFocusItem( HWND );
|
||
|
DWORD ListView_GetItemData( HWND, int );
|
||
|
void __cdecl PrintStatus(LPCSTR, ...);
|
||
|
void SaveSnapshot( HWND );
|
||
|
|
||
|
//
|
||
|
// main
|
||
|
//
|
||
|
int PASCAL
|
||
|
WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR lpCmd, int nShow)
|
||
|
{
|
||
|
//
|
||
|
// init common controls and toolhelp
|
||
|
//
|
||
|
InitCommonControls( );
|
||
|
gfToolhelp = InitToolhelp32( );
|
||
|
um_dump = RegisterWindowMessage( "Dump!" );
|
||
|
ghWait = LoadCursor( NULL, IDC_WAIT );
|
||
|
|
||
|
{
|
||
|
TEXTMETRIC tm;
|
||
|
HDC hDC;
|
||
|
HFONT hFont;
|
||
|
|
||
|
hDC = CreateCompatibleDC( NULL );
|
||
|
hFont = SelectFont( hDC, GetStockFont( ANSI_FIXED_FONT ) );
|
||
|
GetTextMetrics( hDC, &tm );
|
||
|
SelectFont( hDC, hFont );
|
||
|
DeleteDC( hDC );
|
||
|
gcyLine = tm.tmHeight;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// store instance handle (we'll need it later)
|
||
|
//
|
||
|
ghInstance = hInstance;
|
||
|
|
||
|
//
|
||
|
// create main window (all initializations are inside WM_INITDIALOG)
|
||
|
//
|
||
|
DialogBox( hInstance, MAKEINTATOM( IDD_MAIN ), NULL, main_dlgproc );
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// main dialog window proc
|
||
|
//
|
||
|
BOOL CALLBACK
|
||
|
main_dlgproc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
|
||
|
{
|
||
|
switch( message ) {
|
||
|
DLG_MSG( hwnd, WM_COMMAND, main_OnCommand );
|
||
|
DLG_MSG( hwnd, WM_NOTIFY, main_OnNotify );
|
||
|
DLG_MSG( hwnd, WM_INITDIALOG, main_OnInitDialog );
|
||
|
DLG_MSG( hwnd, WM_CLOSE, main_OnClose );
|
||
|
DLG_MSG( hwnd, WM_DESTROY, main_OnDestroy );
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
main_OnCommand( HWND hwnd, UINT id, HWND hCtl, UINT code)
|
||
|
{
|
||
|
switch( id ) {
|
||
|
case IDOK:
|
||
|
if( GetFocus( ) == ghwndProcesses ) {
|
||
|
WalkProcess( );
|
||
|
break;
|
||
|
}
|
||
|
if( GetFocus( ) == ghwndMemory ) {
|
||
|
DumpProcessMemory( );
|
||
|
}
|
||
|
break;
|
||
|
case IDM_UPDATE:
|
||
|
WalkProcesses( );
|
||
|
break;
|
||
|
case IDM_SAVE:
|
||
|
SaveSnapshot( hwnd );
|
||
|
break;
|
||
|
case IDM_EXIT:
|
||
|
PostMessage( hwnd, WM_CLOSE, 0, 0 );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
LONG
|
||
|
main_OnNotify( HWND hwnd, int id, LPNMHDR lpHdr )
|
||
|
{
|
||
|
|
||
|
if( lpHdr->idFrom == IDC_PROCESSES && lpHdr->code == NM_CLICK ) {
|
||
|
WalkProcess( );
|
||
|
}
|
||
|
|
||
|
if( lpHdr->idFrom == IDC_MEMORY && lpHdr->code == NM_CLICK ) {
|
||
|
DumpProcessMemory( );
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// initialize dialog box
|
||
|
//
|
||
|
BOOL
|
||
|
main_OnInitDialog( HWND hwnd, HWND hwndFocus, LPARAM lParam )
|
||
|
{
|
||
|
HICON hIcon;
|
||
|
RECT R, r, rStatus;
|
||
|
int x, y, cx, cy;
|
||
|
LV_COLUMN co;
|
||
|
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
hIcon = LoadIcon( ghInstance, MAKEINTATOM( IDI_MAIN ) );
|
||
|
SendMessage( hwnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon );
|
||
|
|
||
|
// Create the status window.
|
||
|
ghwndStatus = CreateStatusWindow(
|
||
|
WS_VISIBLE | WS_CHILD | WS_BORDER,
|
||
|
" ", hwnd, IDC_STATUS );
|
||
|
SendMessage( ghwndStatus, SB_SIMPLE, TRUE, 0 );
|
||
|
GetWindowRect(ghwndStatus, &rStatus );
|
||
|
|
||
|
//
|
||
|
// position dialog
|
||
|
//
|
||
|
GetWindowRect( hwnd, &r );
|
||
|
GetWindowRect( GetDesktopWindow( ), &R );
|
||
|
x = R.left + ((R.right - R.left) - (r.right - r.left)) / 2;
|
||
|
y = R.top + ((R.bottom - R.top) - (r.bottom - r.top)) / 2;
|
||
|
x = GetPrivateProfileInt( gszPreferences, gszDialogX, x, gszIniFile);
|
||
|
y = GetPrivateProfileInt( gszPreferences, gszDialogY, y, gszIniFile);
|
||
|
cx = r.right - r.left;
|
||
|
cy = r.bottom - r.top + (rStatus.bottom - rStatus.top);
|
||
|
SetWindowPos( hwnd, NULL, x, y, cx, cy, SWP_NOZORDER);
|
||
|
x = rStatus.left;
|
||
|
y = rStatus.top + (rStatus.bottom - rStatus.top);
|
||
|
SetWindowPos( ghwndStatus, 0, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE );
|
||
|
|
||
|
//
|
||
|
// create columns in "Processes" list control
|
||
|
//
|
||
|
ghwndProcesses = GetDlgItem( hwnd, IDC_PROCESSES );
|
||
|
SetWindowFont( ghwndProcesses, GetStockFont( ANSI_FIXED_FONT ), FALSE );
|
||
|
Clear( co );
|
||
|
co.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
|
||
|
co.fmt = LVCFMT_LEFT;
|
||
|
co.cx = 200;
|
||
|
co.pszText = "Process";
|
||
|
ListView_InsertColumn( ghwndProcesses, 0, &co );
|
||
|
co.pszText = "Total Committed";
|
||
|
co.cx = 200;
|
||
|
ListView_InsertColumn( ghwndProcesses, 1, &co );
|
||
|
|
||
|
ghwndMemory = GetDlgItem( hwnd, IDC_MEMORY );
|
||
|
SetWindowFont( ghwndMemory, GetStockFont( ANSI_FIXED_FONT ), FALSE );
|
||
|
|
||
|
co.cx = 100;
|
||
|
co.fmt = LVCFMT_RIGHT;
|
||
|
co.pszText = "Address";
|
||
|
ListView_InsertColumn( ghwndMemory, 0, &co );
|
||
|
|
||
|
co.pszText = "AllocBase";
|
||
|
ListView_InsertColumn( ghwndMemory, 1, &co );
|
||
|
|
||
|
co.pszText = "Size";
|
||
|
ListView_InsertColumn( ghwndMemory, 2, &co );
|
||
|
|
||
|
co.cx = 120;
|
||
|
co.fmt = LVCFMT_LEFT;
|
||
|
co.pszText = "Protection";
|
||
|
ListView_InsertColumn( ghwndMemory, 3, &co );
|
||
|
co.cx = 100;
|
||
|
co.pszText = "Type";
|
||
|
ListView_InsertColumn( ghwndMemory, 4, &co );
|
||
|
|
||
|
FORWARD_WM_COMMAND( hwnd, IDM_UPDATE, 0, 0, PostMessage );
|
||
|
SetFocus( ghwndProcesses );
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// just end dialog
|
||
|
//
|
||
|
void
|
||
|
main_OnClose( HWND hwnd )
|
||
|
{
|
||
|
EndDialog( hwnd, IDOK );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// perform any dialog cleanup
|
||
|
//
|
||
|
void
|
||
|
main_OnDestroy( HWND hwnd )
|
||
|
{
|
||
|
char buf[12];
|
||
|
RECT r;
|
||
|
|
||
|
if( IsWindow( ghwndDump ) ) {
|
||
|
DestroyWindow( ghwndDump );
|
||
|
}
|
||
|
|
||
|
if( gfToolhelp && ghTargetProcess ) {
|
||
|
CloseHandle( ghTargetProcess );
|
||
|
}
|
||
|
|
||
|
if( gfToolhelp && ghSnapshot ) {
|
||
|
CloseHandle( ghSnapshot );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// save dialog position
|
||
|
//
|
||
|
GetWindowRect( hwnd, &r );
|
||
|
wsprintf( buf, "%d", r.left );
|
||
|
WPPS( gszPreferences, gszDialogX, buf, gszIniFile );
|
||
|
wsprintf( buf, "%d", r.top );
|
||
|
WPPS( gszPreferences, gszDialogY, buf, gszIniFile );
|
||
|
|
||
|
}
|
||
|
|
||
|
// Function that initializes tool help functions.
|
||
|
BOOL InitToolhelp32 (void)
|
||
|
{
|
||
|
BOOL bRet = FALSE;
|
||
|
HMODULE hKernel = NULL;
|
||
|
|
||
|
// Obtain the module handle of the kernel to retrieve addresses of
|
||
|
// the tool helper functions.
|
||
|
hKernel = GetModuleHandle("KERNEL32.DLL");
|
||
|
if (hKernel) {
|
||
|
pCreateToolhelp32Snapshot =
|
||
|
(CREATESNAPSHOT)GetProcAddress(hKernel,
|
||
|
"CreateToolhelp32Snapshot");
|
||
|
pModule32First = (MODULEWALK)GetProcAddress(hKernel,
|
||
|
"Module32First");
|
||
|
pModule32Next = (MODULEWALK)GetProcAddress(hKernel,
|
||
|
"Module32Next");
|
||
|
pProcess32First = (PROCESSWALK)GetProcAddress(hKernel,
|
||
|
"Process32First");
|
||
|
pProcess32Next = (PROCESSWALK)GetProcAddress(hKernel,
|
||
|
"Process32Next");
|
||
|
pThread32First = (THREADWALK)GetProcAddress(hKernel,
|
||
|
"Thread32First");
|
||
|
pThread32Next = (THREADWALK)GetProcAddress(hKernel,
|
||
|
"Thread32Next");
|
||
|
// All addresses must be non-NULL to be successful.
|
||
|
// If one of these addresses is NULL, one of
|
||
|
// the needed lists cannot be walked.
|
||
|
bRet = pModule32First && pModule32Next && pProcess32First &&
|
||
|
pProcess32Next && pThread32First && pThread32Next &&
|
||
|
pCreateToolhelp32Snapshot;
|
||
|
} else {
|
||
|
bRet = FALSE; // could not get the module handle of kernel
|
||
|
}
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
WalkProcesses( void )
|
||
|
{
|
||
|
LV_ITEM li;
|
||
|
int item = 0;
|
||
|
DWORD dwTasks;
|
||
|
PROCESSENTRY32 pe;
|
||
|
HLOCAL hTaskList;
|
||
|
char *pszExename;
|
||
|
HCURSOR hCursor = SetCursor( ghWait );
|
||
|
|
||
|
Clear( pe );
|
||
|
pe.dwSize = sizeof( pe );
|
||
|
|
||
|
Clear( li );
|
||
|
li.mask = LVIF_TEXT | LVIF_PARAM;
|
||
|
|
||
|
ListView_DeleteAllItems( ghwndProcesses );
|
||
|
ListView_DeleteAllItems( ghwndMemory );
|
||
|
|
||
|
if( gfToolhelp ) {
|
||
|
if( ghSnapshot ) {
|
||
|
CloseHandle( ghSnapshot );
|
||
|
}
|
||
|
ghSnapshot = pCreateToolhelp32Snapshot( TH32CS_SNAPALL, 0 );
|
||
|
if( !ghSnapshot ) {
|
||
|
goto done;
|
||
|
}
|
||
|
if( pProcess32First( ghSnapshot, &pe ) ) {
|
||
|
do {
|
||
|
pszExename = strrchr( pe.szExeFile, '\\' );
|
||
|
if( pszExename ) {
|
||
|
pszExename++;
|
||
|
}else{
|
||
|
pszExename = pe.szExeFile;
|
||
|
}
|
||
|
li.pszText = pszExename;
|
||
|
li.lParam = pe.th32ProcessID;
|
||
|
ListView_InsertItem( ghwndProcesses, &li );
|
||
|
li.iItem = item++;
|
||
|
} while( pProcess32Next( ghSnapshot, &pe ) );
|
||
|
}
|
||
|
}else{
|
||
|
|
||
|
hTaskList = GetLocalTaskListNt( &dwTasks );
|
||
|
for( li.iItem = 0; li.iItem < (int) dwTasks; li.iItem++ ) {
|
||
|
|
||
|
GetLocalTaskNameNt( hTaskList, li.iItem,
|
||
|
pe.szExeFile, sizeof( pe.szExeFile ) );
|
||
|
pszExename = strrchr( pe.szExeFile, '\\' );
|
||
|
if( pszExename ) {
|
||
|
pszExename++;
|
||
|
}else{
|
||
|
pszExename = pe.szExeFile;
|
||
|
}
|
||
|
li.pszText = pszExename;
|
||
|
li.lParam = GetLocalTaskProcessIdNt( hTaskList, li.iItem);
|
||
|
ListView_InsertItem( ghwndProcesses, &li );
|
||
|
}
|
||
|
FreeLocalTaskListNt( hTaskList );
|
||
|
}
|
||
|
done:
|
||
|
SetFocus( ghwndProcesses );
|
||
|
SetCursor( hCursor );
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
WalkProcess( void )
|
||
|
{
|
||
|
MEMORY_BASIC_INFORMATION bi;
|
||
|
VOID * lpAddress;
|
||
|
LV_ITEM li;
|
||
|
int item;
|
||
|
char buf[32];
|
||
|
DWORD dwProcess;
|
||
|
HCURSOR hCursor = SetCursor( ghWait );
|
||
|
|
||
|
item = ListView_GetFocusItem( ghwndProcesses );
|
||
|
if( ghTargetProcess && gfToolhelp ) {
|
||
|
CloseHandle( ghTargetProcess );
|
||
|
}
|
||
|
dwProcess = ListView_GetItemData( ghwndProcesses, item );
|
||
|
__try {
|
||
|
ghTargetProcess = OpenProcess(
|
||
|
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
|
||
|
FALSE, dwProcess );
|
||
|
} __except( EXCEPTION_EXECUTE_HANDLER ) {
|
||
|
PrintStatus( "Failure to open process %x (%d)",
|
||
|
dwProcess, GetLastError() );
|
||
|
}
|
||
|
|
||
|
SetWindowRedraw( ghwndMemory, FALSE );
|
||
|
|
||
|
Clear( bi );
|
||
|
Clear( li );
|
||
|
lpAddress = NULL;
|
||
|
|
||
|
ListView_DeleteAllItems( ghwndMemory );
|
||
|
|
||
|
__try {
|
||
|
|
||
|
while( VirtualQueryEx( ghTargetProcess, lpAddress, &bi, sizeof( bi ) ) ) {
|
||
|
lpAddress = (PVOID)((DWORD) lpAddress + bi.RegionSize );
|
||
|
if( bi.State != MEM_COMMIT ) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
li.iSubItem = 0;
|
||
|
li.mask = LVIF_TEXT | LVIF_PARAM;
|
||
|
wsprintf( buf, "%08x", bi.BaseAddress );
|
||
|
li.pszText = buf;
|
||
|
li.lParam = (DWORD) bi.BaseAddress;
|
||
|
ListView_InsertItem( ghwndMemory, &li );
|
||
|
|
||
|
li.iSubItem = 1;
|
||
|
li.mask = LVIF_TEXT;
|
||
|
wsprintf( buf, "%08x", bi.AllocationBase );
|
||
|
li.pszText = buf;
|
||
|
ListView_SetItem( ghwndMemory, &li );
|
||
|
|
||
|
li.iSubItem = 2;
|
||
|
wsprintf( buf, "%d", bi.RegionSize );
|
||
|
li.pszText = buf;
|
||
|
ListView_SetItem( ghwndMemory, &li );
|
||
|
|
||
|
li.iSubItem = 3;
|
||
|
buf[0] = '\0';
|
||
|
|
||
|
if( (bi.Protect & PAGE_NOACCESS) == PAGE_NOACCESS ) {
|
||
|
strcat( buf, "NOACCESS " );
|
||
|
}
|
||
|
if( (bi.Protect & PAGE_READONLY) == PAGE_READONLY ) {
|
||
|
strcat( buf, "RO " );
|
||
|
}
|
||
|
if( (bi.Protect & PAGE_READWRITE) == PAGE_READWRITE ) {
|
||
|
strcat( buf, "RW " );
|
||
|
}
|
||
|
if( (bi.Protect & PAGE_WRITECOPY) == PAGE_WRITECOPY ) {
|
||
|
strcat( buf, "WC " );
|
||
|
}
|
||
|
if( (bi.Protect & PAGE_EXECUTE) == PAGE_EXECUTE ) {
|
||
|
strcat( buf, "X " );
|
||
|
}
|
||
|
if( (bi.Protect & PAGE_EXECUTE_READ) == PAGE_EXECUTE_READ ) {
|
||
|
strcat( buf, "XR " );
|
||
|
}
|
||
|
if( (bi.Protect & PAGE_EXECUTE_READWRITE) ==
|
||
|
PAGE_EXECUTE_READWRITE ) {
|
||
|
strcat( buf, "XRW " );
|
||
|
}
|
||
|
if( (bi.Protect & PAGE_EXECUTE_WRITECOPY) ==
|
||
|
PAGE_EXECUTE_WRITECOPY ) {
|
||
|
strcat( buf, "XWC " );
|
||
|
}
|
||
|
if( (bi.Protect & PAGE_GUARD) == PAGE_GUARD ) {
|
||
|
strcat( buf, "Guard " );
|
||
|
}
|
||
|
if( (bi.Protect & PAGE_NOCACHE) == PAGE_NOCACHE ) {
|
||
|
strcat( buf, "Nc " );
|
||
|
}
|
||
|
|
||
|
li.pszText = buf;
|
||
|
ListView_SetItem( ghwndMemory, &li );
|
||
|
|
||
|
|
||
|
li.iSubItem = 4;
|
||
|
switch( bi.Type ) {
|
||
|
case MEM_IMAGE:
|
||
|
li.pszText = "Image";
|
||
|
break;
|
||
|
case MEM_MAPPED:
|
||
|
li.pszText = "Mapped";
|
||
|
break;
|
||
|
case MEM_PRIVATE:
|
||
|
li.pszText = "Private";
|
||
|
break;
|
||
|
default:
|
||
|
li.pszText = "Bogus";
|
||
|
break;
|
||
|
}
|
||
|
ListView_SetItem( ghwndMemory, &li );
|
||
|
|
||
|
li.iItem++;
|
||
|
}
|
||
|
} __except( EXCEPTION_EXECUTE_HANDLER ) {
|
||
|
PrintStatus( "Failure in VirtualQueryEx (%d)", GetLastError() );
|
||
|
}
|
||
|
|
||
|
SetWindowRedraw( ghwndMemory, TRUE );
|
||
|
InvalidateRect( ghwndMemory, NULL, TRUE );
|
||
|
UpdateWindow( ghwndMemory );
|
||
|
SetCursor( hCursor );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
void
|
||
|
DumpProcessMemory( )
|
||
|
{
|
||
|
WNDCLASS wc;
|
||
|
int x,y,cx,cy;
|
||
|
int item;
|
||
|
DWORD dwAddress;
|
||
|
HCURSOR hCursor = SetCursor( ghWait );
|
||
|
|
||
|
item = ListView_GetFocusItem( ghwndMemory );
|
||
|
dwAddress = ListView_GetItemData( ghwndMemory, item );
|
||
|
|
||
|
if( !GetClassInfo( ghInstance, gszDumpWindowClass, &wc ) ) {
|
||
|
Clear( wc );
|
||
|
wc.hInstance = ghInstance;
|
||
|
wc.lpfnWndProc = dump_wndproc;
|
||
|
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
|
||
|
wc.hIcon = LoadIcon( ghInstance, MAKEINTATOM( IDI_DUMP ) );
|
||
|
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
|
||
|
wc.cbWndExtra = DUMP_WINDOW_EXTRA;
|
||
|
wc.lpszClassName = gszDumpWindowClass;
|
||
|
|
||
|
if(!RegisterClass( &wc ) ) {
|
||
|
PrintStatus( "Failure to register dump window class" );
|
||
|
goto done;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( !IsWindow( ghwndDump ) ) {
|
||
|
|
||
|
x = y = cx = cy = CW_USEDEFAULT;
|
||
|
|
||
|
x = GPPI( gszPreferences, gszDumpX, x, gszIniFile );
|
||
|
y = GPPI( gszPreferences, gszDumpY, y, gszIniFile );
|
||
|
cx = GPPI( gszPreferences, gszDumpCX, cx, gszIniFile );
|
||
|
cy = GPPI( gszPreferences, gszDumpCY, cy, gszIniFile );
|
||
|
|
||
|
ghwndDump = CreateWindow( gszDumpWindowClass, "",
|
||
|
WS_OVERLAPPEDWINDOW | WS_VSCROLL,
|
||
|
x, y, cx, cy, NULL, NULL, ghInstance, NULL );
|
||
|
|
||
|
if( ghwndDump ) {
|
||
|
SendMessage( ghwndDump, um_dump,
|
||
|
(WPARAM) ghTargetProcess, (LPARAM) dwAddress );
|
||
|
ShowWindow( ghwndDump, SW_SHOW );
|
||
|
UpdateWindow( ghwndDump );
|
||
|
}else{
|
||
|
PrintStatus( "Error: %d", GetLastError() );
|
||
|
}
|
||
|
}else{
|
||
|
SendMessage( ghwndDump, um_dump,
|
||
|
(WPARAM) ghTargetProcess, (LPARAM) dwAddress );
|
||
|
}
|
||
|
done:
|
||
|
SetCursor( hCursor );
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
dump_OnCreate( HWND hwnd, LPCREATESTRUCT lpCreate )
|
||
|
{
|
||
|
SetScrollRange( hwnd, SB_VERT, 0, 100, FALSE );
|
||
|
SetScrollPos( hwnd, SB_VERT, 0, TRUE );
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
dump_OnDestroy( HWND hwnd )
|
||
|
{
|
||
|
RECT r;
|
||
|
char buf[32];
|
||
|
|
||
|
|
||
|
GetWindowRect( hwnd, &r );
|
||
|
wsprintf( buf, "%d", r.left );
|
||
|
WPPS( gszPreferences, gszDumpX, buf, gszIniFile );
|
||
|
wsprintf( buf, "%d", r.top );
|
||
|
WPPS( gszPreferences, gszDumpY, buf, gszIniFile );
|
||
|
wsprintf( buf, "%d", r.right - r.left );
|
||
|
WPPS( gszPreferences, gszDumpCX, buf, gszIniFile );
|
||
|
wsprintf( buf, "%d", r.bottom - r.top );
|
||
|
WPPS( gszPreferences, gszDumpCY, buf, gszIniFile );
|
||
|
|
||
|
}
|
||
|
|
||
|
void
|
||
|
dump_OnPaint( HWND hwnd )
|
||
|
{
|
||
|
PAINTSTRUCT ps;
|
||
|
HFONT hFont;
|
||
|
RECT r;
|
||
|
int line, byte, nLines;
|
||
|
char buf[1024];
|
||
|
BYTE mem[18];
|
||
|
char *p = buf;
|
||
|
DWORD dwOffset = GET_DUMP_OFFSET( hwnd );
|
||
|
DWORD dwEnd = GET_DUMP_END( hwnd );
|
||
|
DWORD dwRead;
|
||
|
HANDLE hProcess = GET_DUMP_PROCESS( hwnd );
|
||
|
|
||
|
BeginPaint( hwnd, &ps );
|
||
|
hFont = SelectFont( ps.hdc, GetStockObject( ANSI_FIXED_FONT ) );
|
||
|
|
||
|
GetClientRect( hwnd, &r );
|
||
|
nLines = (r.bottom - r.top) / gcyLine;
|
||
|
|
||
|
for( line = 0; line < nLines; line++ ) {
|
||
|
Clear( mem );
|
||
|
|
||
|
__try {
|
||
|
ReadProcessMemory( hProcess, (PVOID) dwOffset, mem, 16, &dwRead );
|
||
|
} __except( EXCEPTION_EXECUTE_HANDLER ) {
|
||
|
strcpy( mem, "????????????????");
|
||
|
}
|
||
|
|
||
|
wsprintf(buf, "%08x ", dwOffset);
|
||
|
|
||
|
p = buf + 9;
|
||
|
for(byte = 0; byte < 16; byte++ ) {
|
||
|
wsprintf( p, "%02x ", mem[byte] );
|
||
|
p += (byte == 7) ? 4 : 3;
|
||
|
}
|
||
|
|
||
|
for( byte = 0; byte < 16; byte++ ) {
|
||
|
if( mem[byte] >= ' ' ) {
|
||
|
p[byte] = mem[byte];
|
||
|
}else{
|
||
|
p[byte] = ' ';
|
||
|
}
|
||
|
}
|
||
|
p[16] = '\0';
|
||
|
|
||
|
TextOut( ps.hdc, 0, line * gcyLine, buf, strlen( buf ) );
|
||
|
|
||
|
dwOffset += 16;
|
||
|
|
||
|
if( dwOffset > dwEnd) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
SelectFont( ps.hdc, hFont );
|
||
|
EndPaint( hwnd, &ps );
|
||
|
}
|
||
|
|
||
|
void
|
||
|
dump_OnVScroll(HWND hwnd, HWND hwndCtl, UINT code, int pos)
|
||
|
{
|
||
|
DWORD dwOffset = GET_DUMP_OFFSET( hwnd );
|
||
|
DWORD dwStart = GET_DUMP_START( hwnd );
|
||
|
DWORD dwEnd = GET_DUMP_END( hwnd );
|
||
|
RECT r, ri;
|
||
|
DWORD cyLines, Line, maxLine, newLine;
|
||
|
|
||
|
GetClientRect( hwnd, &r );
|
||
|
r.bottom -= (r.bottom - r.top) % gcyLine;
|
||
|
cyLines = (r.bottom - r.top) / gcyLine;
|
||
|
|
||
|
Line = (dwOffset - dwStart ) / 16;
|
||
|
maxLine = ( dwEnd - dwStart ) / 16 - cyLines;
|
||
|
|
||
|
switch( code ) {
|
||
|
case SB_TOP:
|
||
|
newLine = 0;
|
||
|
break;
|
||
|
case SB_BOTTOM:
|
||
|
newLine = maxLine;
|
||
|
break;
|
||
|
case SB_PAGEUP:
|
||
|
newLine = max( Line - cyLines + 1, 0 );
|
||
|
break;
|
||
|
case SB_PAGEDOWN:
|
||
|
newLine = min( Line + cyLines - 1, maxLine );
|
||
|
break;
|
||
|
case SB_LINEUP:
|
||
|
newLine = max( 0, Line - 1 );
|
||
|
break;
|
||
|
case SB_LINEDOWN:
|
||
|
newLine = min( Line + 1, maxLine );
|
||
|
break;
|
||
|
case SB_THUMBPOSITION:
|
||
|
case SB_THUMBTRACK:
|
||
|
newLine = MulDiv( pos, maxLine, 100 );
|
||
|
break;
|
||
|
default:
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
SET_DUMP_OFFSET( hwnd, dwStart + newLine * 16 );
|
||
|
|
||
|
pos = MulDiv(newLine, 100, maxLine );
|
||
|
SetScrollPos( hwnd, SB_VERT, pos, TRUE );
|
||
|
ScrollWindowEx( hwnd, 0, ( Line - newLine ) * gcyLine,
|
||
|
NULL, &r, NULL, &ri, SW_INVALIDATE );
|
||
|
InvalidateRect( hwnd, &ri, TRUE );
|
||
|
|
||
|
done:
|
||
|
UpdateWindow( hwnd );
|
||
|
}
|
||
|
|
||
|
void
|
||
|
dump_OnSize( HWND hwnd, int state, int cx, int cy )
|
||
|
{
|
||
|
InvalidateRect( hwnd, NULL, TRUE );
|
||
|
UpdateWindow( hwnd );
|
||
|
}
|
||
|
|
||
|
void
|
||
|
dump_OnKey(HWND hwnd, UINT vk, BOOL fDown, int cRepeat, UINT flags)
|
||
|
{
|
||
|
switch( vk ) {
|
||
|
case VK_DOWN:
|
||
|
FORWARD_WM_VSCROLL( hwnd, NULL, SB_LINEDOWN, 0, PostMessage );
|
||
|
break;
|
||
|
case VK_UP:
|
||
|
FORWARD_WM_VSCROLL( hwnd, NULL, SB_LINEUP, 0, PostMessage );
|
||
|
break;
|
||
|
|
||
|
case VK_PRIOR:
|
||
|
FORWARD_WM_VSCROLL( hwnd, NULL, SB_PAGEUP, 0, PostMessage );
|
||
|
break;
|
||
|
case VK_NEXT:
|
||
|
case ' ':
|
||
|
FORWARD_WM_VSCROLL( hwnd, NULL, SB_PAGEDOWN, 0, PostMessage );
|
||
|
break;
|
||
|
|
||
|
case VK_HOME:
|
||
|
FORWARD_WM_VSCROLL( hwnd, NULL, SB_TOP, 0, PostMessage );
|
||
|
break;
|
||
|
|
||
|
case VK_END:
|
||
|
FORWARD_WM_VSCROLL( hwnd, NULL, SB_BOTTOM, 0, PostMessage );
|
||
|
break;
|
||
|
|
||
|
case VK_ESCAPE:
|
||
|
PostMessage( hwnd, WM_CLOSE, 0, 0 );
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// dump window proc
|
||
|
//
|
||
|
LRESULT CALLBACK
|
||
|
dump_wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
|
||
|
{
|
||
|
switch( message ) {
|
||
|
HANDLE_MSG( hwnd, WM_CREATE, dump_OnCreate );
|
||
|
HANDLE_MSG( hwnd, WM_DESTROY, dump_OnDestroy );
|
||
|
HANDLE_MSG( hwnd, WM_PAINT, dump_OnPaint );
|
||
|
HANDLE_MSG( hwnd, WM_VSCROLL, dump_OnVScroll );
|
||
|
HANDLE_MSG( hwnd, WM_SIZE, dump_OnSize );
|
||
|
HANDLE_MSG( hwnd, WM_KEYDOWN, dump_OnKey );
|
||
|
default:
|
||
|
if( message == um_dump ) {
|
||
|
char buf[80];
|
||
|
MEMORY_BASIC_INFORMATION bi;
|
||
|
HANDLE hProcess = (HANDLE) wParam;
|
||
|
DWORD dwOffset = (DWORD) lParam;
|
||
|
|
||
|
wsprintf( buf, "Process %x at %x", wParam, lParam );
|
||
|
SetWindowText( hwnd, buf );
|
||
|
SetScrollPos( hwnd, SB_VERT, 0, TRUE );
|
||
|
InvalidateRect( hwnd, NULL, TRUE );
|
||
|
|
||
|
Clear( bi );
|
||
|
if(! VirtualQueryEx( hProcess, (PVOID) dwOffset,
|
||
|
&bi, sizeof( bi ) ) ) {
|
||
|
PrintStatus( "Error: %d", GetLastError() );
|
||
|
}
|
||
|
SET_DUMP_PROCESS( hwnd, hProcess );
|
||
|
SET_DUMP_START( hwnd, (DWORD) bi.BaseAddress );
|
||
|
SET_DUMP_END( hwnd, (DWORD) bi.BaseAddress + bi.RegionSize );
|
||
|
SET_DUMP_OFFSET( hwnd, (DWORD) bi.BaseAddress );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return DefWindowProc( hwnd, message, wParam, lParam );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// returns the number of the item which has focus or -1
|
||
|
//
|
||
|
int ListView_GetFocusItem( HWND hwnd )
|
||
|
{
|
||
|
int cItems = ListView_GetItemCount( hwnd );
|
||
|
int item;
|
||
|
|
||
|
for( item = 0; item < cItems; item++ ) {
|
||
|
if( ListView_GetItemState( hwnd, item, LVIS_FOCUSED ) ) {
|
||
|
return item;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// returns .lParam of the specified item or -1
|
||
|
//
|
||
|
DWORD ListView_GetItemData( HWND hwnd, int item)
|
||
|
{
|
||
|
LV_ITEM li;
|
||
|
|
||
|
if( item != -1 ) {
|
||
|
Clear( li );
|
||
|
li.mask = LVIF_PARAM;
|
||
|
li.iItem = item;
|
||
|
|
||
|
if( ListView_GetItem( hwnd, &li ) ) {
|
||
|
return li.lParam;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (DWORD) -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// formats message to status bar
|
||
|
//
|
||
|
void __cdecl
|
||
|
PrintStatus(LPCSTR fmt, ...)
|
||
|
{
|
||
|
char buf[4096];
|
||
|
va_list marker;
|
||
|
|
||
|
va_start( marker, fmt );
|
||
|
wvsprintf( buf, fmt, marker );
|
||
|
va_end( marker );
|
||
|
|
||
|
SendMessage( ghwndStatus, SB_SETTEXT, 0, (LPARAM) buf );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
//
|
||
|
//
|
||
|
void SaveSnapshot( HWND hwnd )
|
||
|
{
|
||
|
}
|