659 lines
13 KiB
Plaintext
659 lines
13 KiB
Plaintext
|
|
|||
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1995 Microsoft Corporation
|
|||
|
|
|||
|
Module Name
|
|||
|
|
|||
|
wcall.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Windows version: diplay system calls
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Mark Enstrom (marke) 13-Dec-1995
|
|||
|
|
|||
|
Enviornment:
|
|||
|
|
|||
|
User Mode
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#include <nt.h>
|
|||
|
#include <ntrtl.h>
|
|||
|
#include <nturtl.h>
|
|||
|
#include <windows.h>
|
|||
|
#include <commdlg.h>
|
|||
|
#include <assert.h>
|
|||
|
#include <stdio.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <string.h>
|
|||
|
#include <ctype.h>
|
|||
|
#include "wcall.h"
|
|||
|
#include "resource.h"
|
|||
|
|
|||
|
WCALL_CONTEXT wCxt;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
int PASCAL
|
|||
|
WinMain(
|
|||
|
HINSTANCE hInst,
|
|||
|
HINSTANCE hPrev,
|
|||
|
LPSTR szCmdLine,
|
|||
|
int cmdShow
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Process messages.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hWnd - window hande
|
|||
|
msg - type of message
|
|||
|
wParam - additional information
|
|||
|
lParam - additional information
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
status of operation
|
|||
|
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
02-17-91 Initial code
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
{
|
|||
|
MSG msg;
|
|||
|
WNDCLASS wc;
|
|||
|
|
|||
|
wCxt.hInstMain = hInst;
|
|||
|
|
|||
|
//
|
|||
|
// Create (if no prev instance) and Register the class
|
|||
|
//
|
|||
|
|
|||
|
if (!hPrev)
|
|||
|
{
|
|||
|
wc.hCursor = LoadCursor((HINSTANCE)NULL, IDC_ARROW);
|
|||
|
wc.hIcon = (HICON)NULL;
|
|||
|
wc.lpszMenuName = MAKEINTRESOURCE(IDR_WCALL_MENU);
|
|||
|
wc.lpszClassName = "wcallClass";
|
|||
|
wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
|
|||
|
wc.hInstance = hInst;
|
|||
|
wc.style = CS_OWNDC;
|
|||
|
wc.lpfnWndProc = WndProc;
|
|||
|
wc.cbWndExtra = 0;
|
|||
|
wc.cbClsExtra = 0;
|
|||
|
|
|||
|
if (!RegisterClass(&wc))
|
|||
|
{
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Create and show the main window
|
|||
|
//
|
|||
|
|
|||
|
wCxt.hWndMain = CreateWindow ("wcallClass",
|
|||
|
"System Call Count",
|
|||
|
WS_OVERLAPPEDWINDOW,
|
|||
|
50,
|
|||
|
50,
|
|||
|
450,
|
|||
|
350,
|
|||
|
(HWND)NULL,
|
|||
|
(HMENU)NULL,
|
|||
|
(HINSTANCE)hInst,
|
|||
|
(LPSTR)NULL
|
|||
|
);
|
|||
|
|
|||
|
if (wCxt.hWndMain == NULL)
|
|||
|
{
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Show the window
|
|||
|
//
|
|||
|
|
|||
|
ShowWindow(wCxt.hWndMain,cmdShow);
|
|||
|
UpdateWindow(wCxt.hWndMain);
|
|||
|
SetFocus(wCxt.hWndMain);
|
|||
|
|
|||
|
//
|
|||
|
// Main message loop
|
|||
|
//
|
|||
|
|
|||
|
while (GetMessage(&msg,(HWND)NULL,0,0))
|
|||
|
{
|
|||
|
TranslateMessage(&msg);
|
|||
|
DispatchMessage(&msg);
|
|||
|
}
|
|||
|
|
|||
|
return msg.wParam;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
LONG FAR
|
|||
|
PASCAL WndProc(
|
|||
|
HWND hWnd,
|
|||
|
unsigned msg,
|
|||
|
UINT wParam,
|
|||
|
LONG lParam)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Windows Proc
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
hWnd - window hande
|
|||
|
msg - type of message
|
|||
|
wParam - additional information
|
|||
|
lParam - additional information
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
standard
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
switch (msg) {
|
|||
|
|
|||
|
case WM_CREATE:
|
|||
|
{
|
|||
|
//
|
|||
|
// mark as no current data
|
|||
|
//
|
|||
|
|
|||
|
wCxt.NumberOfCounts = 0;
|
|||
|
|
|||
|
|
|||
|
DialogBox(wCxt.hInstMain, (LPSTR)IDD_RESULTS, hWnd, (DLGPROC)ResultsDlgProc);
|
|||
|
|
|||
|
SendMessage(hWnd,WM_CLOSE,0,0L);
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case WM_COMMAND:
|
|||
|
{
|
|||
|
|
|||
|
switch (LOWORD(wParam)){
|
|||
|
case IDM_EXIT:
|
|||
|
{
|
|||
|
SendMessage(hWnd,WM_CLOSE,0,0L);
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
//
|
|||
|
// sample system call counts and save as
|
|||
|
// the base counts for future calls to
|
|||
|
// GET_CURRENT
|
|||
|
//
|
|||
|
|
|||
|
case IDM_SAVE_CALLS:
|
|||
|
{
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// read system call counts, then subtract from
|
|||
|
// the baseline value and display highest values
|
|||
|
//
|
|||
|
|
|||
|
case IDM_GET_CURRENT:
|
|||
|
{
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case WM_PAINT:
|
|||
|
{
|
|||
|
PAINTSTRUCT ps;
|
|||
|
HDC hDC = BeginPaint(hWnd,&ps);
|
|||
|
EndPaint(hWnd,&ps);
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case WM_DESTROY:
|
|||
|
PostQuitMessage(0);
|
|||
|
break;
|
|||
|
default:
|
|||
|
|
|||
|
//
|
|||
|
// Passes message on if unproccessed
|
|||
|
//
|
|||
|
|
|||
|
return (DefWindowProc(hWnd, msg, wParam, lParam));
|
|||
|
}
|
|||
|
|
|||
|
return ((LONG)NULL);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Save results to file
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
none
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
none
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
void WriteResults(HFILE hFile)
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
SaveResults()
|
|||
|
{
|
|||
|
static OPENFILENAME ofn;
|
|||
|
static char szFilename[80];
|
|||
|
char szT[80];
|
|||
|
int i, hfile;
|
|||
|
FILE *fpOut;
|
|||
|
|
|||
|
for (i = 0; i < sizeof(ofn); i++)
|
|||
|
{
|
|||
|
//
|
|||
|
// clear out the OPENFILENAME struct
|
|||
|
//
|
|||
|
|
|||
|
((char *)&ofn)[i] = 0;
|
|||
|
}
|
|||
|
|
|||
|
ofn.lStructSize = sizeof(ofn);
|
|||
|
ofn.hwndOwner = wCxt.hWndMain;
|
|||
|
ofn.hInstance = wCxt.hInstMain;
|
|||
|
|
|||
|
ofn.lpstrFilter = "SysCall (*.log)\0*.log;\0All Files\0*.*\0\0";
|
|||
|
ofn.lpstrCustomFilter = NULL;
|
|||
|
ofn.nMaxCustFilter = 0;
|
|||
|
ofn.nFilterIndex = 0;
|
|||
|
ofn.lpstrFileTitle = NULL;
|
|||
|
ofn.nMaxFileTitle = 0;
|
|||
|
ofn.lpstrInitialDir = "C:\\";
|
|||
|
ofn.Flags = 0;
|
|||
|
ofn.lpstrDefExt = NULL;
|
|||
|
ofn.lCustData = 0;
|
|||
|
ofn.lpfnHook = NULL;
|
|||
|
ofn.lpTemplateName = NULL;
|
|||
|
|
|||
|
lstrcpy(szFilename, "syscall.log");
|
|||
|
|
|||
|
ofn.lpstrFile = szFilename;
|
|||
|
ofn.nMaxFile = sizeof(szFilename);
|
|||
|
ofn.lpstrTitle = "Save As";
|
|||
|
|
|||
|
if (!GetSaveFileName(&ofn))
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
fpOut = fopen(szFilename, "w+");
|
|||
|
|
|||
|
if (fpOut)
|
|||
|
{
|
|||
|
ULONG ix;
|
|||
|
|
|||
|
for (ix = 0; ix < TOP_CALLS; ix++)
|
|||
|
{
|
|||
|
//
|
|||
|
// stop if count is 0
|
|||
|
//
|
|||
|
|
|||
|
if (wCxt.CallData[wCxt.Index[ix]] == 0)
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
fprintf(fpOut,"%8ld %s\n",
|
|||
|
wCxt.CallData[wCxt.Index[ix]],
|
|||
|
CallTable[wCxt.Index[ix]]);
|
|||
|
}
|
|||
|
|
|||
|
fclose(fpOut);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
APIENTRY
|
|||
|
ResultsDlgProc(
|
|||
|
HWND hwnd,
|
|||
|
UINT msg,
|
|||
|
UINT wParam,
|
|||
|
LONG lParam)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Show results (Interactive Mode Dialog)
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
Std dlg
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
Status
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
ULONG ix;
|
|||
|
char szT[80];
|
|||
|
BOOL fResults;
|
|||
|
int aiT[2];
|
|||
|
|
|||
|
switch (msg) {
|
|||
|
case WM_INITDIALOG:
|
|||
|
{
|
|||
|
LONG NumCounts;
|
|||
|
|
|||
|
aiT[0] = 40;
|
|||
|
aiT[1] = 140;
|
|||
|
SendDlgItemMessage(hwnd, IDC_RESULTSLIST, LB_SETTABSTOPS, 2,
|
|||
|
(LONG)(LPSTR)aiT);
|
|||
|
//
|
|||
|
// get initial kmode call count
|
|||
|
//
|
|||
|
|
|||
|
NumCounts = ReadCallCountInfo(
|
|||
|
(PSYSTEM_CALL_COUNT_INFORMATION)&wCxt.CountBuffer1);
|
|||
|
|
|||
|
if (NumCounts > 0)
|
|||
|
{
|
|||
|
wCxt.NumberOfCounts = NumCounts;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
MessageBox(NULL,"ReadCallCountInfo failed","Error",MB_OK);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case WM_COMMAND:
|
|||
|
switch (LOWORD(wParam)) {
|
|||
|
case IDOK:
|
|||
|
EndDialog(hwnd, 0);
|
|||
|
break;
|
|||
|
|
|||
|
case IDM_SAVERESULTS:
|
|||
|
SaveResults();
|
|||
|
break;
|
|||
|
|
|||
|
case IDM_RESTART:
|
|||
|
{
|
|||
|
int ix;
|
|||
|
|
|||
|
//
|
|||
|
// Gat call counts
|
|||
|
//
|
|||
|
|
|||
|
LONG NumCounts = ReadCallCountInfo(
|
|||
|
(PSYSTEM_CALL_COUNT_INFORMATION)&wCxt.CountBuffer1);
|
|||
|
|
|||
|
if (NumCounts > 0)
|
|||
|
{
|
|||
|
wCxt.NumberOfCounts = NumCounts;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
MessageBox(NULL,"ReadCallCountInfo failed","Error",MB_OK);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Delete old strings
|
|||
|
//
|
|||
|
|
|||
|
for (ix = 0; ix < TOP_CALLS; ix++)
|
|||
|
{
|
|||
|
SendDlgItemMessage(hwnd, IDC_RESULTSLIST, LB_DELETESTRING,0,0);
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case IDM_SAMPLE:
|
|||
|
if (wCxt.NumberOfCounts > 0)
|
|||
|
{
|
|||
|
|
|||
|
int ix;
|
|||
|
|
|||
|
LONG NumberOfCounts = ReadCallCountInfo(
|
|||
|
(PSYSTEM_CALL_COUNT_INFORMATION)&wCxt.CountBuffer2);
|
|||
|
|
|||
|
if (NumberOfCounts == wCxt.NumberOfCounts)
|
|||
|
{
|
|||
|
//
|
|||
|
// Compute number of system calls for each service, the total
|
|||
|
// number of system calls, and the total time for each serviced.
|
|||
|
//
|
|||
|
|
|||
|
ULONG TotalSystemCalls = 0;
|
|||
|
ULONG i;
|
|||
|
|
|||
|
PULONG CallCountTable[2];
|
|||
|
|
|||
|
PULONG CurrentCallCountTable;
|
|||
|
PSYSTEM_CALL_COUNT_INFORMATION CallCountInfo[2];
|
|||
|
|
|||
|
PULONG PreviousCallCountTable;
|
|||
|
|
|||
|
CallCountInfo[0] = (PVOID)wCxt.CountBuffer1;
|
|||
|
CallCountInfo[1] = (PVOID)wCxt.CountBuffer2;
|
|||
|
CallCountTable[0] = (PULONG)(CallCountInfo[0] + 1) + NUMBER_SERVICE_TABLES;
|
|||
|
CallCountTable[1] = (PULONG)(CallCountInfo[1] + 1) + NUMBER_SERVICE_TABLES;
|
|||
|
|
|||
|
PreviousCallCountTable = CallCountTable[0];
|
|||
|
CurrentCallCountTable = CallCountTable[1];
|
|||
|
|
|||
|
|
|||
|
for (i = 0; i < NumberOfCounts; i += 1) {
|
|||
|
wCxt.CallData[i] = CurrentCallCountTable[i] - PreviousCallCountTable[i];
|
|||
|
TotalSystemCalls += wCxt.CallData[i];
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Sort the system call data.
|
|||
|
//
|
|||
|
|
|||
|
SortUlongData(NumberOfCounts, &wCxt.Index[0],&wCxt.CallData[0]);
|
|||
|
|
|||
|
//
|
|||
|
// Delete old strings
|
|||
|
//
|
|||
|
|
|||
|
for (ix = 0; ix < TOP_CALLS; ix++)
|
|||
|
{
|
|||
|
SendDlgItemMessage(hwnd, IDC_RESULTSLIST, LB_DELETESTRING,0,0);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// display new strings
|
|||
|
//
|
|||
|
|
|||
|
for (ix = 0; ix < TOP_CALLS; ix++)
|
|||
|
{
|
|||
|
//
|
|||
|
// stop if count is 0
|
|||
|
//
|
|||
|
|
|||
|
if (wCxt.CallData[wCxt.Index[ix]] == 0)
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
sprintf(szT,"%8ld %s",
|
|||
|
wCxt.CallData[wCxt.Index[ix]],
|
|||
|
CallTable[wCxt.Index[ix]]);
|
|||
|
|
|||
|
SendDlgItemMessage(hwnd, IDC_RESULTSLIST, LB_ADDSTRING, 0,
|
|||
|
(LONG)(LPSTR)szT);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
MessageBox(NULL,"ReadCallCountInfo returned different number of counts than initial sample","Error",MB_OK);
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Read system call count info into buffer and return number of counts
|
|||
|
|
|||
|
Arguments
|
|||
|
|
|||
|
pCurrentCallCountInfo - buffer for results (BUFFER_SIZE)
|
|||
|
|
|||
|
Return Value
|
|||
|
|
|||
|
Number of counts or negative status value on error
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
int
|
|||
|
ReadCallCountInfo(
|
|||
|
PSYSTEM_CALL_COUNT_INFORMATION pCurrentCallCountInfo
|
|||
|
)
|
|||
|
{
|
|||
|
KPRIORITY SetBasePriority;
|
|||
|
NTSTATUS status;
|
|||
|
PULONG p;
|
|||
|
ULONG i;
|
|||
|
int NumberOfCounts;
|
|||
|
|
|||
|
SetBasePriority = (KPRIORITY)12;
|
|||
|
|
|||
|
NtSetInformationProcess(
|
|||
|
NtCurrentProcess(),
|
|||
|
ProcessBasePriority,
|
|||
|
(PVOID) &SetBasePriority,
|
|||
|
sizeof(SetBasePriority)
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Query system information and get the initial call count data.
|
|||
|
//
|
|||
|
|
|||
|
status = NtQuerySystemInformation(SystemCallCountInformation,
|
|||
|
(PVOID)pCurrentCallCountInfo,
|
|||
|
BUFFER_SIZE * sizeof(ULONG),
|
|||
|
NULL);
|
|||
|
|
|||
|
if (NT_SUCCESS(status) == FALSE){
|
|||
|
return(-1);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Make sure that the number of tables reported by the kernel matches
|
|||
|
// our list.
|
|||
|
//
|
|||
|
|
|||
|
if (pCurrentCallCountInfo->NumberOfTables != NUMBER_SERVICE_TABLES) {
|
|||
|
return(-2);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Make sure call count information is available for base services.
|
|||
|
//
|
|||
|
|
|||
|
p = (PULONG)(pCurrentCallCountInfo + 1);
|
|||
|
|
|||
|
if (p[0] == 0) {
|
|||
|
return(-3);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If there is a hole in the count information (i.e., one set of services
|
|||
|
// doesn't have counting enabled, but a subsequent one does, then our
|
|||
|
// indexes will be off, and we'll display the wrong service names.
|
|||
|
//
|
|||
|
|
|||
|
for ( i = 2; i < NUMBER_SERVICE_TABLES; i++ ) {
|
|||
|
if ((p[i] != 0) && (p[i-1] == 0)) {
|
|||
|
return(-4);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Determine number of counts and return
|
|||
|
//
|
|||
|
|
|||
|
NumberOfCounts = (pCurrentCallCountInfo->Length
|
|||
|
- sizeof(SYSTEM_CALL_COUNT_INFORMATION)
|
|||
|
- NUMBER_SERVICE_TABLES * sizeof(ULONG)) / sizeof(ULONG);
|
|||
|
|
|||
|
return(NumberOfCounts);
|
|||
|
}
|