📄 vxdmon.c
字号:
CloseHandle( fp );
return;
}
/******************************************************************************
*
* FUNCTION: ClickPoint
*
* PURPOSE: Return the point, in window-space coordinates, where the
* cursor was clicked.
*
******************************************************************************/
POINT ClickPoint( HWND hWnd )
{
POINT point;
DWORD dwpos = GetMessagePos();
point.x = LOWORD( dwpos );
point.y = HIWORD( dwpos );
MapWindowPoints( HWND_DESKTOP, hWnd, &point, 1 );
return point;
}
/******************************************************************************
*
* FUNCTION: CreateCallTree
*
* PURPOSE: Open a descendant/ancestor call tree window.
* Uses global variables to determine what type of tree is desired.
******************************************************************************/
void CreateCallTree( HWND hWnd, struct vxdmon_stats * item, BOOL calldown )
{
HWND hCallTree;
// Set global variables indicating contents of new window
CallTreeStat = item;
CallTreeDown = calldown;
// Set name of window
if ( CallTreeDown )
wsprintf( msgbuf, "Services called by %s",
LookupService(((struct vxdmon_stats *) CallTreeStat)->Ordinal)->Name );
else
wsprintf( msgbuf, "Callers of %s",
LookupService(((struct vxdmon_stats *) CallTreeStat)->Ordinal)->Name );
// Create a call-tree window for the service
hCallTree = CreateWindow( calldown ? "VxDMonCallDownClass" : "VxDMonCallUpClass",
msgbuf,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 300, 300,
NULL, NULL, hInst, NULL );
if ( !hCallTree ) {
wsprintf( msgbuf, "Call tree not created: Error %d", GetLastError() );
MessageBox( hWnd, msgbuf, NULL, MB_OK );
}
// Display the window
ShowWindow( hCallTree, SW_SHOWNORMAL );
UpdateWindow( hCallTree );
}
/******************************************************************************
*
* FUNCTION: WriteCallData
*
* PURPOSE: Write the call-tree information to a file
*
******************************************************************************/
void WriteCallData( HANDLE fp, HWND hTree, HTREEITEM hItem, int depth )
{
HTREEITEM Child;
char Line[ 100 ];
DWORD cnt = 0;
TV_ITEM tvi;
int i;
char servicename[64];
// Get the item's name
tvi.hItem = hItem;
tvi.mask = TVIF_TEXT | TVIF_PARAM;
tvi.pszText = servicename;
tvi.cchTextMax = sizeof servicename;
TreeView_GetItem( hTree, &tvi );
// don't print root since its redundant
if ( depth >= 0 ) {
// Print a number of tabs equal to depth
for ( i = 0; i < depth; i++ ) {
wsprintf( Line, "\t");
WriteFile( fp, Line, strlen(Line), &cnt, NULL );
}
// Print the name of the service
wsprintf( Line,"%s\r\n", servicename );
WriteFile( fp, Line, strlen(Line), &cnt, NULL );
}
// If any children exist then recurse on them
for ( Child = TreeView_GetChild( hTree, hItem );
Child != NULL;
Child = TreeView_GetNextSibling( hTree, Child ) )
{
WriteCallData( fp, hTree, Child, depth+1 );
}
return;
}
/******************************************************************************
*
* FUNCTION: SaveCallData
*
* PURPOSE: Write a call tree to an ASCII file.
*
******************************************************************************/
void SaveCallData( HWND hWnd, char * CallFileName, HWND hWndTreeView )
{
SECURITY_ATTRIBUTES security;
HANDLE fp;
char Line[128];
int cnt;
// Open the file
memset( &security, 0, sizeof security );
security.nLength = sizeof security;
fp = CreateFile( CallFileName, GENERIC_WRITE, FILE_SHARE_WRITE,
&security, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if ( fp == INVALID_HANDLE_VALUE ) {
wsprintf( msgbuf, "Can't open \"%s\": Error %d", CallFileName, GetLastError() );
MessageBox( NULL, msgbuf, NULL, MB_OK );
return;
}
// Fetch text from title bar of window
GetWindowText( hWnd, msgbuf, sizeof msgbuf );
// Write title bar to file
wsprintf( Line, "%s:\r\n\n", msgbuf );
WriteFile( fp, Line, strlen(Line), &cnt, NULL );
// Write call tree data to file
WriteCallData( fp, hWndTreeView, TreeView_GetChild(hWndTreeView, 0 ), -1 );
// Close file and exit
CloseHandle( fp );
return;
}
/****************************************************************************
*
* FUNCTION: CallWndProc( HWND, unsigned, WORD, LONG )
*
* PURPOSE: Processes messages for call-tree windows
*
****************************************************************************/
LONG APIENTRY CallWndProc( HWND hWnd, UINT message, UINT wParam, LONG lParam )
{
HWND hWndTreeView; // Handle of the tree window
RECT rc; // rectangle for setting size of window
NM_TREEVIEW * tv;
// Get value of tree window saved during WM_CREATE
hWndTreeView = (HWND) GetWindowLong( hWnd, 0 );
switch ( message ) {
case WM_CREATE:
// Get the size and position of the parent window.
GetClientRect( hWnd, &rc );
// Create the tree view window.
hWndTreeView = CreateWindowEx( 0L, WC_TREEVIEW, "",
WS_VISIBLE | WS_CHILD | WS_BORDER | TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT,
0, 0, rc.right - rc.left, rc.bottom - rc.top - 15,
hWnd, (HMENU)ID_CALLVIEW, hInst, NULL );
if ( hWndTreeView == NULL )
MessageBox( NULL, "Call Tree View not created!", NULL, MB_OK );
// Save the treeview handle for later invocations
SetWindowLong( hWnd, 0, (LONG)hWndTreeView );
// Set image list for tree
TreeView_SetImageList( hWndTreeView, hCallImageList, 0 );
// post hourglass icon
SetCapture(hWnd);
hSaveCursor = SetCursor(hHourGlass);
// Add all callers/callees to tree
AddCallTreeItems( hWndTreeView, TVI_ROOT, CallTreeStat, 0 );
// notify user that operation is done
SetCursor(hSaveCursor);
ReleaseCapture();
break;
case WM_SIZE:
// Move or resize window
MoveWindow( hWndTreeView, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
break;
case WM_NOTIFY:
// Detect double clicks on items
if ( wParam != ID_CALLVIEW )
return 0;
tv = (NM_TREEVIEW *) lParam;
if ( tv->hdr.code == NM_DBLCLK || tv->hdr.code == NM_RDBLCLK ) {
// Have a double click
TV_HITTESTINFO tvhti;
HTREEITEM htiItemClicked;
// Ensure the click was on something interesting
tvhti.pt = ClickPoint( hWndTreeView );
htiItemClicked = TreeView_HitTest( hWndTreeView, &tvhti );
if ( htiItemClicked && tvhti.flags & TVHT_ONITEM ) {
// Create call graph for item clicked on
TV_ITEM Item;
// Determine which service was clicked
Item.mask = TVIF_PARAM;
Item.hItem = htiItemClicked;
if ( ! TreeView_GetItem( hWndTreeView, &Item ) )
return 0;
// Create the window
CreateCallTree( hWnd,
(struct vxdmon_stats *) Item.lParam,
tv->hdr.code == NM_DBLCLK );
}
}
break;
case WM_COMMAND:
switch ( LOWORD( wParam ) ) {
case IDM_ANCESTORS:
case IDM_DESCENDANTS: {
// Create call graph for currently selected item
TV_ITEM Item;
HTREEITEM hItem = TreeView_GetSelection( hWndTreeView );
if ( ! hItem )
return 0;
// Get info about currently select item
Item.mask = TVIF_PARAM;
Item.hItem = hItem;
if ( ! TreeView_GetItem( hWndTreeView, &Item ) )
return 0;
// Create the window
CreateCallTree( hWnd,
(struct vxdmon_stats *) Item.lParam,
LOWORD(wParam) == IDM_DESCENDANTS );
return 0;
}
case IDM_CALLSAVE:
// Save call graph to file
if( GetFileName( hWnd, CallFileName, "Call Graph Files (*.CLL)\0*.CLL\0",
"CLL" ))
SaveCallData( hWnd, CallFileName, hWndTreeView );
return 0;
case IDM_EXIT:
// Close call graph
SendMessage( hWnd, WM_CLOSE, 0, 0 );
return 0;
default:
return DefWindowProc( hWnd, message, wParam, lParam );
}
break;
default:
return DefWindowProc( hWnd, message, wParam, lParam );
}
return 0;
}
/******************************************************************************
*
* FUNCTION: AddCallTreeItems
*
* PURPOSE: Build a call tree based upon contents of statitics buffer.
* We rely on brute force searching of all the data, rather
* than doing anything intelligent.
*
******************************************************************************/
BOOL AddCallTreeItems( HWND hTree, HTREEITEM Parent, struct vxdmon_stats * stats, int depth )
{
DWORD j;
HTREEITEM me;
char * Name = LookupService(stats->Ordinal)->Name;
TV_ITEM tvi;
// Add the given, top-level, item
me = AddOneTreeViewItem( hTree, Parent, TVI_SORT, Name, (DWORD)stats );
// Set image for direction of call
tvi.hItem = me;
tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
tvi.iImage = depth == 0 ? CALL_NONE : CallTreeDown ? CALL_DOWN : CALL_UP;
tvi.iSelectedImage = tvi.iImage;
TreeView_SetItem( hTree, &tvi );
// Check if we appear as our own ancestor
while ( Parent != NULL && Parent != TVI_ROOT ) {
TV_ITEM Item;
Item.mask = TVIF_PARAM;
Item.hItem = Parent;
TreeView_GetItem( hTree, &Item );
if ( Item.lParam == (int)stats )
// We're part of a cycle. Don't recurse on children
return TRUE;
Parent = TreeView_GetParent( hTree, Parent );
}
if ( CallTreeDown ) {
// Add everything item calls
for ( j = 0; j < numStats; ++j ) {
DWORD c;
for ( c = 0; c < CALLER_CNT; ++c ) {
if ( Stats[j].Caller[c] == stats->Ordinal ) {
// Make sure item is not already in tree
HTREEITEM Sibling;
for ( Sibling = TreeView_GetChild( hTree, me );
Sibling != NULL;
Sibling = TreeView_GetNextSibling( hTree, Sibling ) )
{
TV_ITEM tvi;
// Get sibling info
tvi.hItem = Sibling;
tvi.mask = TVIF_PARAM;
TreeView_GetItem( hTree, &tvi );
if ( tvi.lParam == (int) &Stats[j] )
goto duplicate_callee;
}
// Add item to tree
AddCallTreeItems( hTree, me, &Stats[j], depth+1 );
}
}
duplicate_callee:;
}
} else {
// Add everything calling item
for ( j = 0; j < CALLER_CNT; ++j ) {
DWORD child = stats->Caller[j];
if ( child ) {
DWORD c;
// Ensure we haven't already added child
for ( c = 0; c < j; ++c )
if ( stats->Caller[c] == child )
goto duplicate_caller;
// Locate child
for ( c = 0; c < numStats; ++c )
if ( Stats[c].Ordinal == child )
break;
if ( c >= numStats )
continue;
// Recurse on child
AddCallTreeItems( hTree, me, &Stats[c], depth+1 );
}
duplicate_caller:;
}
}
// Initially have tree fully expanded (except first level)
if ( depth != 1 )
TreeView_Expand( hTree, me, TVE_EXPAND );
return TRUE;
}
/***************************************************************************
*
* FUNCTION: HookServices
*
* PURPOSE: Hook/unhook all services marked in selection tree view
*
****************************************************************************/
BOOL HookServices( HWND hTree, HTREEITEM hItem )
{
HTREEITEM Child = TreeView_GetChild( hTree, hItem );
static DWORD NotLoadedOrd = (DWORD) -1;
DWORD nb;
if ( Child ) {
// This is not a leaf item. Recurse on all children.
while ( Child != NULL ) {
HookServices( hTree, Child );
Child = TreeView_GetNextSibling( hTree, Child );
}
} else {
// Leaf item. Tell VxD to hook/unhook it.
TV_ITEM tvi;
struct service * pService;
// Determine current hook state
tvi.hItem = hItem;
tvi.mask = TVIF_IMAGE | TVIF_PARAM;
TreeView_GetItem( hTree, &tvi );
pService = (struct service *) tvi.lParam;
if ( pService->Hooked != (tvi.iImage == HOOK_YES) ) {
// do we already know that vxd is not loaded?
if( NotLoadedOrd == (pService->Ordinal >> 16 )) {
// Reset state of item
SetTreeItemState( hTree, hItem,
pService->Hooked ? HOOK_YES : HOOK_NO, FALSE );
} else {
// try to hook the service
if ( DeviceIoControl( vxd_handle,
pService->Hooked
? VXDMON_unhookservice
: VXDMON_hookservice,
&pService->Ordinal, sizeof(DWORD),
NULL, 0, &nb, NULL ) )
{
// Successfully hooked/unhooked service. Mark as such.
NotLoadedOrd = (DWORD) -1;
pService->Hooked = !pService->Hooked;
} else {
// Hook/unhook failed. Find out why.
DWORD ErrorCode = GetLastError();
char vxdname[ 12 ];
// get VxD name for error message
tvi.hItem = TreeView_GetParent( hTree, hItem );
tvi.mask = TVIF_TEXT | TVIF_PARAM;
tvi.pszText = vxdname;
tvi.cchTextMax = sizeof vxdname;
TreeView_GetItem( hTree, &tvi );
// error because VxD not loaded?
if ( ErrorCode == VXDMON_ERROR_NOSUCHVXD ) {
wsprintf( msgbuf, "\nVxD %s is not loaded\n\n", vxdname );
NotLoadedOrd = pService->Ordinal >> 16;
} else {
// unknown error
wsprintf( msgbuf, "Couldn't %s service\n\n%s:%s\n#0x%08X",
pService->Hooked ? "unhook" : "hook",
vxdname, pService->Name, pService->Ordinal );
}
MessageBox( NULL, msgbuf, NULL, MB_ICONEXCLAMATION );
// Reset state of item to what it was before being selected/deselected
SetTreeItemState( hTree, hItem,
pService->Hooked ? HOOK_YES : HOOK_NO, FALSE );
}
}
}
}
return TRUE;
}
/****************************************************************************
*
* FUNCTION: About
*
* PURPOSE: Processes messages for "About" dialog box
*
****************************************************************************/
BOOL APIENTRY About( HWND hDlg, UINT message, UINT wParam, LONG lParam )
{
switch ( message ) {
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if ( LOWORD( wParam ) == IDOK ) {
EndDialog( hDlg, TRUE );
return TRUE;
}
break;
}
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -