📄 vxdmon.c
字号:
// Update statistics windows
RefreshStatistics( hWnd, hWndListView, SortItem );
return 0;
// Toggle the reset-on-update variable
case IDM_RESETONUPDATE:
ResetStatsOnUpdate = !ResetStatsOnUpdate;
CheckMenuItem( GetMenu( hWnd ), IDM_RESETONUPDATE,
MF_BYCOMMAND | (ResetStatsOnUpdate?MF_CHECKED:MF_UNCHECKED) );
break;
// Read statistics from VxD
case IDM_SAMPLE:
if ( ResetStatsOnUpdate )
statcmd = VXDMON_getzerostats;
else
statcmd = VXDMON_getstats;
// Have VxD fill Stats buffer with information
if ( ! DeviceIoControl( vxd_handle, statcmd,
NULL, 0, &Stats, sizeof Stats,
&numStats, NULL ) )
{
Abort( hWnd, "Couldn't access VxD" );
return TRUE;
}
numStats /= sizeof Stats[0];
// Update statistics windows
RefreshStatistics( hWnd, hWndListView, SortItem );
return 0;
case IDM_ANCESTORS:
case IDM_DESCENDANTS:
// Create call graph for currently selected item
Item.iItem = ListView_GetNextItem( hWndListView, -1, LVNI_ALL|LVNI_SELECTED );
if ( Item.iItem == -1 )
return 0;
Item.iSubItem = 0;
Item.mask = LVIF_PARAM;
if ( ! ListView_GetItem( hWndListView, &Item ) )
return 0;
// Create the window
CreateCallTree( hWnd,
(struct vxdmon_stats *) Item.lParam,
LOWORD(wParam) == IDM_DESCENDANTS );
return 0;
case IDM_SAVEAS:
// Save current selections
if( GotFile = GetFileName( hWnd, szFileName, "VxDMon Files (*.VMN)\0*.VMN\0", "VMN" ))
SaveStatisticsData( hWnd, hWndListView );
break;
case IDM_SAVE:
// Save current selections
if( !GotFile )
GotFile = GetFileName( hWnd, szFileName, "VxDMon Files (*.VMN)\0*.VMN\0", "VMN" );
if( GotFile )
SaveStatisticsData( hWnd, hWndListView );
break;
case IDM_IGNORE:
// Toggle ignore-uncalled-services variable
IgnoreUncalled = !IgnoreUncalled;
CheckMenuItem( GetMenu( hWnd ), IDM_IGNORE,
MF_BYCOMMAND | (!IgnoreUncalled?MF_CHECKED:MF_UNCHECKED) );
// Update statistics windows
RefreshStatistics( hWnd, hWndListView, SortItem );
return 0;
case IDM_OVERHEAD:
// Toggle compensate-for-monitoring-overhead variable
Overhead = !Overhead;
CheckMenuItem( GetMenu( hWnd ), IDM_OVERHEAD,
MF_BYCOMMAND | (Overhead?MF_CHECKED:MF_UNCHECKED) );
// Update statistics windows
RefreshStatistics( hWnd, hWndListView, SortItem );
return 0;
case IDM_EXIT:
// see if we should prompt about saving current hook profile
if( ProfileChanged &&
MessageBox( NULL, "Save current hook profile before exiting?",
"Profile Changed", MB_YESNO ) == IDYES )
SendMessage( hTree, WM_COMMAND, (WPARAM) IDM_SAVE, (LPARAM) 0 );
PostQuitMessage( 0 );
break;
case IDM_HELP:
// Pull up on-line help
WinHelp( hWnd, szHelpFileName, HELP_INDEX, 0L);
break;
case IDM_ABOUT:
// Show the names of the authors
DialogBox( hInst, "AboutBox", hWnd, (DLGPROC)About );
break;
default:
// Default behavior
return DefWindowProc( hWnd, message, wParam, lParam );
}
break;
case WM_SIZE:
// Move or resize the listview
MoveWindow( hWndListView, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE );
break;
case WM_DESTROY:
// see if we should prompt about saving current hook profile
if( ProfileChanged &&
MessageBox( NULL, "Save current hook profile before exiting?",
"Profile Changed", MB_YESNO ) == IDYES)
SendMessage( hTree, WM_COMMAND, (WPARAM) IDM_SAVE, (LPARAM) 0 );
// Exit application
PostQuitMessage( 0 );
break;
default:
// Default behavior
return DefWindowProc( hWnd, message, wParam, lParam );
}
return 0;
}
/******************************************************************************
*
* FUNCTION: RefreshStatistics
*
* PURPOSE: Clear the statistics window and refill it with the current
* contents of the statistics buffer. Does not refresh the
* buffer from the VxD.
*
******************************************************************************/
void RefreshStatistics( HWND hWnd, HWND hWndListView, int SortItem )
{
DWORD row;
DWORD cnt;
// post hourglass icon
SetCapture(hWnd);
hSaveCursor = SetCursor(hHourGlass);
// Draw all listview items from Stats[] data
ListView_DeleteAllItems( hWndListView );
row = 0;
for ( cnt = 0; cnt < numStats; ++cnt ) {
LV_ITEM lvI; // list view item structure
// see if we are ignoring uncalled services
if ( IgnoreUncalled && Stats[cnt].Enter == 0 )
continue;
lvI.mask = LVIF_TEXT | LVIF_PARAM;
lvI.iItem = row;
lvI.iSubItem = 0;
// Add service name to listview
lvI.pszText = ServiceName( Stats[cnt].Ordinal );
lvI.cchTextMax = strlen( lvI.pszText ) + 1;
lvI.lParam = (LPARAM) &Stats[cnt]; // Passed as data to NOTIFY
if ( ListView_InsertItem( hWndListView, &lvI ) == -1 )
Abort( hWnd, "Couldn't add items to list view" );
// Ordinal
sprintf( msgbuf, "0x%08X", Stats[cnt].Ordinal );
ListView_SetItemText( hWndListView, row, 1, msgbuf );
// Entries
sprintf( msgbuf, "%d", Stats[cnt].Enter );
ListView_SetItemText( hWndListView, row, 2, msgbuf );
// Exits
sprintf( msgbuf, "%d", Stats[cnt].Exit );
ListView_SetItemText( hWndListView, row, 3, msgbuf );
// Avg cycles
if ( Stats[cnt].Exit ) {
_int64 n = Stats[cnt].Time / Stats[cnt].Exit;
if ( Overhead ) n -= OverheadCycles;
sprintf( msgbuf, "%I64d", n );
} else {
sprintf( msgbuf, "n/a" );
}
ListView_SetItemText( hWndListView, row, 4, msgbuf );
// Total cycles
sprintf( msgbuf, "%I64d",
Stats[cnt].Time - (Overhead?(_int64)OverheadCycles*Stats[cnt].Enter:0) );
ListView_SetItemText( hWndListView, row, 5, msgbuf );
// move to next row
row++;
}
if ( SortItem != -1 ) {
// The user clicked a column header - sort by this criterion.
ListView_SortItems( hWndListView, ListViewCompareProc,
(LPARAM)SortItem );
}
// notify user that operation is done
SetCursor( hSaveCursor );
ReleaseCapture();
}
/******************************************************************************
*
* FUNCTION: GetFileName
*
* PURPOSE: Generic wrapper for GetSaveFileName function.
*
******************************************************************************/
BOOL GetFileName( HWND hWnd, char *filename, char *filter, char *ext )
{
OPENFILENAME of;
of.lStructSize = sizeof(OPENFILENAME);
of.hwndOwner = (HWND)hWnd;
of.hInstance = (HANDLE)NULL;
of.lpstrFilter = filter;
of.lpstrCustomFilter = (LPSTR)NULL;
of.nMaxCustFilter = 0L;
of.nFilterIndex = 1L;
of.lpstrFile = filename;
of.nMaxFile = 256;
of.lpstrFileTitle = NULL;
of.nMaxFileTitle = 0;
of.lpstrInitialDir = NULL;
of.lpstrTitle = (LPSTR)NULL;
of.Flags = OFN_HIDEREADONLY |
OFN_PATHMUSTEXIST ;
of.nFileOffset = 0;
of.nFileExtension = 0;
of.lpstrDefExt = (LPSTR) ext;
of.lCustData = 0L;
of.lpfnHook = 0L; // Zero eliminates compiler warnings
of.lpTemplateName = (LPSTR)NULL;
return GetSaveFileName ( &of );
}
/******************************************************************************
*
* FUNCTION: SaveStatisticsData
*
* PURPOSE: Writes the contents of the statistics window to a file.
*
******************************************************************************/
void SaveStatisticsData( HWND hWnd, HWND hWndListView )
{
SECURITY_ATTRIBUTES security;
HANDLE fp;
DWORD cnt;
char tmp[64], Line[256];
LV_ITEM pitem;
// Open the output file
memset( &security, 0, sizeof security );
security.nLength = sizeof security;
fp = CreateFile( szFileName, 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", szFileName, GetLastError() );
MessageBox( NULL, msgbuf, NULL, MB_OK );
return;
}
// set up item to use for looping through listview items
pitem.mask = LVIF_TEXT;
pitem.iItem = 0;
pitem.iSubItem = 0;
pitem.pszText = msgbuf;
pitem.cchTextMax= sizeof msgbuf;
// write header
sprintf( msgbuf, "Name" );
sprintf( Line, "%32s\tOrdinal\t\tEntries\tExits\tAvg\tTotal\r\n\n", msgbuf);
WriteFile( fp, Line, strlen(Line), &cnt, NULL );
// Iterate over all services in listview
while ( ListView_GetItem( hWndListView, &pitem ) ) {
// service name
sprintf(Line,"%32s\t", msgbuf );
// ordinal
ListView_GetItemText( hWndListView, pitem.iItem, 1, msgbuf, sizeof msgbuf );
sprintf( tmp, "%s\t", msgbuf );
strcat( Line, tmp );
// entries
ListView_GetItemText( hWndListView, pitem.iItem, 2, msgbuf, sizeof msgbuf );
sprintf( tmp, "%s\t", msgbuf );
strcat( Line, tmp );
// exits
ListView_GetItemText( hWndListView, pitem.iItem, 3, msgbuf, sizeof msgbuf );
sprintf( tmp, "%s\t", msgbuf );
strcat( Line, tmp );
// avg cycles
ListView_GetItemText( hWndListView, pitem.iItem, 4, msgbuf, sizeof msgbuf );
sprintf( tmp, "%s\t", msgbuf );
strcat( Line, tmp );
// total cycles
ListView_GetItemText( hWndListView, pitem.iItem, 5, msgbuf, sizeof msgbuf );
sprintf( tmp, "%s\r\n", msgbuf );
strcat( Line, tmp );
// Write output line to file
WriteFile( fp, Line, strlen(Line), &cnt, NULL );
// Advance to next service
pitem.iItem++;
}
CloseHandle( fp );
return;
}
/****************************************************************************
*
* FUNCTION: CreateListView(HWND)
*
* PURPOSE: Creates the statistics list view window and initializes it
*
****************************************************************************/
HWND CreateListView( HWND hWndParent )
{
HWND hWndList; // handle to list view window
RECT rc; // rectangle for setting size of window
LV_COLUMN lvC; // list view column structure
DWORD j;
static struct {
char * Label; // title of column
DWORD Width; // width of column in pixels
} column[] = {
{ "VxD Service", 150 },
{ "Ordinal", 80 },
{ "Entries", 50 },
{ "Exits", 50 },
{ "Avg Cycles", 80 },
{ "Total Cycles", 80 },
};
// Ensure that the common control DLL is loaded.
InitCommonControls();
// Get the size and position of the parent window.
GetClientRect( hWndParent, &rc );
// Create the list view window
hWndList = CreateWindowEx( 0L, WC_LISTVIEW, "",
WS_VISIBLE | WS_CHILD | WS_BORDER | LVS_REPORT |
WS_EX_CLIENTEDGE, // styles
0, 0, rc.right - rc.left, rc.bottom - rc.top,
hWndParent, (HMENU)ID_LISTVIEW, hInst, NULL );
if ( hWndList == NULL )
return NULL;
// Now initialize the columns you will need.
// Initialize the LV_COLUMN structure.
// The mask specifies that the fmt, width, pszText, and subitem members
// of the structure are valid,
lvC.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvC.fmt = LVCFMT_LEFT; // left-align column
// Add the columns.
for ( j = 0; j < sizeof column/sizeof column[0]; ++j ) {
lvC.iSubItem = j;
lvC.cx = column[j].Width;
lvC.pszText = column[j].Label;
if ( ListView_InsertColumn( hWndList, j, &lvC ) == -1 )
return NULL;
}
return hWndList;
}
/****************************************************************************
*
* FUNCTION: ListViewCompareProc(LPARAM, LPARAM, LPARAM)
*
* PURPOSE: Callback function that sorts the statistics listview based on
* the column clicked.
*
****************************************************************************/
int CALLBACK ListViewCompareProc( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort )
{
struct vxdmon_stats * left = (void *) lParam1;
struct vxdmon_stats * right = (void *) lParam2;
_int64 diff;
if ( left && right ) {
switch ( lParamSort) {
case 0: // VxD Service
return strcmpi( ServiceName( left->Ordinal ), ServiceName( right->Ordinal ) );
case 1: // Ordinal
return left->Ordinal - right->Ordinal;
case 2: // Entries
return right->Enter - left->Enter;
case 3: // Exits
return right->Exit - left->Exit;
case 4: // Avg cycles
if ( left->Enter == 0 || right->Enter == 0 )
return right->Enter - left->Enter;
diff = right->Time/right->Enter - left->Time/left->Enter;
return diff < 0 ? -1 : diff > 0 ? 1 : 0;
case 5: // Total cycles
diff = right->Time - left->Time;
return diff < 0 ? -1 : diff > 0 ? 1 : 0;
default:
return 0;
}
} else {
return 0;
}
}
/******************************************************************************
*
* FUNCTION: SetTreeParentState
*
* PURPOSE: Determine whether a parent node in service selection tree should be marked
* selected, unselected, or partially selected, based on states of child nodes.
*
******************************************************************************/
void SetTreeParentState( HWND hTree, HTREEITEM Parent )
{
UINT State;
TV_ITEM tvi;
HTREEITEM Child;
BOOL allsel, nonesel, partial;
allsel = TRUE;
nonesel = TRUE;
partial = FALSE;
for ( Child = TreeView_GetChild( hTree, Parent );
Child != NULL;
Child = TreeView_GetNextSibling( hTree, Child ) )
{
// if at least one, but not all children are selected, then the parent is partial
tvi.mask = TVIF_IMAGE;
tvi.hItem = Child;
TreeView_GetItem( hTree, &tvi );
switch ( tvi.iImage ) {
case HOOK_YES: nonesel = FALSE; break;
case HOOK_NO: allsel = FALSE; break;
case HOOK_PART: allsel = FALSE; nonesel = FALSE; break;
}
// see if partial condition is satisfied
if( !allsel && !nonesel ) {
partial = TRUE;
break;
}
}
// set parent partial if necessary
if ( partial )
State = HOOK_PART;
else if( allsel )
State = HOOK_YES;
else if( nonesel )
State = HOOK_NO;
tvi.hItem = Parent;
tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
tvi.iImage = State;
tvi.iSelectedImage = State;
TreeView_SetItem( hTree, &tvi );
}
/******************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -