#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 ) { }