mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
658 lines
13 KiB
658 lines
13 KiB
|
|
/*++
|
|
|
|
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);
|
|
}
|