Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

417 lines
7.0 KiB

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
napdump.c
Module Description:
Dump Nt Api Profiling data.
This is a perverted derivative of teh apfdump.* utility.
Environment:
Windows command line.
Author:
Russ Blake (russbl) 25-Apr-1991
Revision History:
--*/
#include <excpt.h>
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#undef NULL
#include <stdio.h>
#include <string.h>
#include <direct.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <io.h>
#include <conio.h>
#include <errno.h>
#include <process.h>
#include <ctype.h>
#include <windows.h>
#include <tools.h>
#define MICROSEC_FACTOR 1000000
#define MAX_TIME 0x7fffffffL
//
// Dump switches and defaults
//
BOOLEAN Dump = TRUE; // if not dumping,
// then clearing
CHAR DumpFileName[256] = "ntdll.nap"; // default name
CHAR OutputRecord[132];
CHAR *rgstrUsage[] = {
"Usage: napdump [ {/c | filename } ]",
" Default - data dumped to file named ntdll.nap",
" /c - clear data already collected",
" filename - dump data to filename",
0};
FILE *DumpFile;
ULONG ApiCount;
NAPDATA *ApiProfilingData;
PCHAR *ApiNames;
PLARGE_INTEGER CounterFreq;
/*++
Usage takes a variable number of strings, terminated by zero,
e.g. Usage ("first ", "second ", 0);
--*/
void
Usage (
CHAR *p,
...
)
{
CHAR **rgstr;
rgstr = &p;
if (*rgstr) {
fprintf (stderr, "TC: ");
while (*rgstr)
fprintf(stderr, "%s", *rgstr++);
fprintf(stderr, "\n");
}
rgstr = rgstrUsage;
while (*rgstr)
fprintf(stderr, "%s\n", *rgstr++);
exit (1);
}
/*++
ExtractTime()
Extract a time from a large integer, converting it to microseconds
--*/
VOID
ExtractTime (
PLARGE_INTEGER RealTime,
LARGE_INTEGER Time,
LONG Overhead,
ULONG Count
)
{
LARGE_INTEGER ElapsedTime;
LARGE_INTEGER OverheadTime;
ElapsedTime = RtlExtendedIntegerMultiply (Time, MICROSEC_FACTOR);
ElapsedTime = RtlExtendedLargeIntegerDivide (ElapsedTime,
CounterFreq->LowPart,
NULL);
OverheadTime.HighPart = 0;
OverheadTime.LowPart = Count * Overhead;
*RealTime = RtlLargeIntegerSubtract(ElapsedTime, OverheadTime);
}
/*++
AdjustTime
This routine is called to convert long times to smaller times
expressed as multiples of 1024 (= 1K).
--*/
VOID
AdjustTime (
PLARGE_INTEGER Time,
PCHAR Kchar
)
{
if (Time->HighPart != 0) {
if (Time->HighPart>>10 > 0) {
fprintf(DumpFile,
"*** Unexpected timer overflow: %ld \t %lu ***\n",
Time->HighPart,
Time->LowPart);
Time->HighPart = 0;
Time->LowPart = 0;
*Kchar = '?';
} else if (Time->HighPart>>10 < 0) {
fprintf(DumpFile,
"*** Unexpected timer underflow: %ld \t %lu ***\n",
Time->HighPart,
Time->LowPart);
Time->HighPart = 0;
Time->LowPart = 0;
*Kchar = '?';
} else {
Time->LowPart = ((ULONG)(Time->HighPart))<<22 +
Time->LowPart>>10;
*Kchar = 'K';
}
} else {
*Kchar = ' ';
}
}
/*++
Main Routine
--*/
VOID
main (c, v)
int c;
CHAR *v[];
{
ULONG Api;
CHAR *p;
LONG Overhead;
struct {
LONG TotalTime;
LONG FirstTime;
LONG MaxTime;
LONG MinTime;
} ProfData;
LARGE_INTEGER OverheadTime;
LARGE_INTEGER TotalTime;
LARGE_INTEGER PerCallTime;
LARGE_INTEGER FirstTime;
LARGE_INTEGER MaxTime;
LARGE_INTEGER MinTime;
CHAR TotalSuffix;
CHAR PerCallSuffix;
CHAR FirstSuffix;
CHAR MaxSuffix;
CHAR MinSuffix;
SHIFT(c,v);
while (c && fSwitChr (*v[0])) {
p = v[0];
SHIFT(c,v);
while (*++p) {
switch (*p) {
case 'c':
Dump = FALSE;
break;
case '?':
case 'h':
case 'H':
Usage(0);
break;
default:
Usage("Invalid switch - ", p, 0);
}
}
}
if (c > 1) {
Usage("Too many parameters - ", p, 0);
}
if (c == 1) {
strcpy(DumpFileName, v[0]);
}
if (!Dump) {
NapPause();
NapClearData();
NapResume();
}
else {
//
// Stop recording
//
NapPause();
DumpFile = fopen(DumpFileName, "w");
if (!DumpFile) {
Usage("Unable to open output file %s\n", DumpFileName);
}
NapGetApiCount(&ApiCount);
ApiProfilingData = (NAPDATA *) malloc((ApiCount+1) * sizeof(NAPDATA));
NapRetrieveData(ApiProfilingData, &ApiNames, &CounterFreq);
ExtractTime(&OverheadTime, ApiProfilingData[0].MinTime, 0, 0);
//
// Now dump the data; start with the header info
//
fprintf(DumpFile,
"%s: Api profile of nt service routines.\n",
DumpFileName);
fprintf(DumpFile, "All times are in microseconds.\n");
fprintf(DumpFile,
"All times (except Calibration) corrected "
"by %lu microseconds/call.\n",
OverheadTime.LowPart);
fprintf(DumpFile,
"(Note: First Time not included in Max or Min Times)\n\n\n");
fprintf(DumpFile,
"%-32s\t%10s\t%10s\t%10s\t%10s\t%10s\t%10s\t\n\n",
"API Name",
"Num Calls",
"Total Time",
"Time/Call",
"First Time",
"Max Time",
"Min Time");
//
// Dump the data for each api that got used
//
//
// The Calibration Counters (Api = 0) should not be adjusted for
// overhead.
// Note: this is repaired for all api at the end of the for loop.
//
Overhead = 0;
for (Api = 0; Api <= ApiCount; Api++) {
if (ApiProfilingData[Api].Calls >= 1) {
ExtractTime(&TotalTime,
ApiProfilingData[Api].TotalTime,
Overhead,
ApiProfilingData[Api].Calls);
ExtractTime(&FirstTime,
ApiProfilingData[Api].FirstTime,
Overhead, 1);
AdjustTime(&TotalTime,&TotalSuffix);
PerCallTime.HighPart = 0;
PerCallTime.LowPart = TotalTime.LowPart /
ApiProfilingData[Api].Calls;
PerCallSuffix = TotalSuffix;
AdjustTime(&FirstTime,&FirstSuffix);
if (ApiProfilingData[Api].Calls > 1) {
ExtractTime(&MaxTime,
ApiProfilingData[Api].MaxTime,
Overhead, 1);
ExtractTime(&MinTime,
ApiProfilingData[Api].MinTime,
Overhead, 1);
AdjustTime(&MaxTime,&MaxSuffix);
AdjustTime(&MinTime,&MinSuffix);
fprintf(DumpFile,
"%-32s\t%10lu\t%10lu%1c\t%10lu%1c\t%10lu%1c"
"\t%10lu%1c\t%10lu%1c\n",
ApiNames[Api],
ApiProfilingData[Api].Calls,
TotalTime.LowPart,
TotalSuffix,
PerCallTime.LowPart,
PerCallSuffix,
FirstTime.LowPart,
FirstSuffix,
MaxTime.LowPart,
MaxSuffix,
MinTime.LowPart,
MinSuffix);
}
else if (ApiProfilingData[Api].Calls == 1) {
fprintf(DumpFile,
"%-32s\t%10lu\t%10lu%1c\t%10lu%1c\t%10lu%1c"
"\t%10s\t%10s\n",
ApiNames[Api],
ApiProfilingData[Api].Calls,
TotalTime.LowPart,
TotalSuffix,
PerCallTime.LowPart,
PerCallSuffix,
FirstTime.LowPart,
FirstSuffix,
"n/a",
"n/a");
}
}
Overhead = OverheadTime.LowPart;
}
//
// Start collecting data again
//
free(ApiProfilingData);
NapResume();
fclose(DumpFile);
}
}