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.
 
 
 
 
 
 

1584 lines
41 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
baseprf.c
Abstract:
This file contains the following:
1. The fernel32 dll entry point and basic interface points.
2. The basic routines to maintain the data structure that is used by the
File I/O Profiler to record all the file I/O activity of a process.
The data structure consists of two linked lists of FileProf_Handle
structs (see baseprf.h). Each FileProf_Handle struct corresponds to
some disk file handle used by the process. There exist two linked lists,
one for the active and one for the inactive handles of the process.
When a disk file is opened by the process, the process obtains an active
handle, and the corresponding FileProf_Handle struct is put in the active
list. When the process closes the handle, the corresponding FileProf_Handle
struct is placed in the inactive list. In addition, there exists a
DUPLICATE FileProf_Handle struct which keeps the
file I/O activity statistics for the handles that are not opened by
the process, but are obtained by duplicating existing handles of other
processes (or itself).
A cache of the last-referenced FileProf_Handle structs is kept to speed-up
the Profiler.
3. The basic accounting routines for the File I/O Profiler
Author:
Revision History:
Jul 92, created by Christos Tsollis (baseprf.c)
--*/
#define UNICODE
#include <stdio.h>
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include "windows.h"
#include "baseprf.h"
#include "syncprf.h"
#include "timing.h"
#define MAX_LONG 0x7FFFFFFFL
#define MEM_ATTR GMEM_DISCARDABLE | GMEM_MOVEABLE
#define MAXFILENAMELEN 13
//
// timer calibration
//
#define NUM_ITRATIONS 2000 // Number of iterations
#define MIN_ACCEPTABLEOVERHEAD 0 // Minimum overhead allowed
#define MODULE_NAME L"fernel32" // The dll name. Originally was
// defined in zwinbase.h
#define AtLeastOneOperation(S) ((S).nNumOfOps != (ULONG) 0)
#define ValidDataForDuplicatedHandles \
(AtLeastOneOperation(phDuplicated->pfHandleData->Overall))
//
// The threads that catch the Dump and Clear data events signalled by the
// apf32dmp.exe
//
HANDLE hWaitingForDumpThread;
HANDLE hWaitingForClearThread;
//
// The handles to the Dump and Clear data events. The handles are created
// whenever a process is attached, and destroyed when the pocess is
// detached by their corresponding threads
//
HANDLE hDumpEvent;
HANDLE hClearEvent;
//
// The handle and the pointer to the shared memory where apf32dmp puts the
// name of the file to keep the dumped data
//
HANDLE hDumpFileMapping;
LPTSTR tszDumpFileName;
//
// The output buffer
//
TCHAR OutBuf[OUTLEN];
//
// Statistics collected for all files
//
PFP_Handle phAllFiles;
ULONG ulNumOfAllCreateOps, ulNumOfAllOpenOps, ulNumOfAllCloseOps, ulNumOfFiles;
//
// Dummy large integer. Used as a dummy argument for DumpDataLinePrint()
//
LARGE_INTEGER liDummy;
void FreeMemoryOfList ( PFP_Handle );
void FreeMemoryOfHandle ( PFP_Handle );
void FreeMemoryOfSList ( PSP_Handle );
void FreeMemoryOfSHandle ( PSP_Handle );
void DumpDataLinePrint ();
void RtlLargeIntegerPrint ();
void FileProfDumpData ();
void FileProfClearData ();
void InitFileProf ();
extern void WriteFileAnsi (HANDLE hFile, LPVOID OutBuf, DWORD cChar, LPDWORD lpcWChar, LPOVERLAPPED lpOVerLapped);
/*++
Dll entry point
--*/
BOOLEAN FBaseMain(
IN PVOID DllHandle,
ULONG Reason,
IN PCONTEXT Context OPTIONAL)
{
static TCHAR szDumpFile[15];
USHORT Type;
void FreeMemoryOfHandle();
// if process is attaching, initialize the dll
if (Reason == DLL_PROCESS_ATTACH) {
GdiSetBatchLimit (1);
FileSyncProfInitDll();
}
else if (Reason == DLL_THREAD_ATTACH) {
GdiSetBatchLimit (1);
}
else if (Reason == DLL_PROCESS_DETACH) {
lstrcpy ((LPTSTR)szDumpFile, MODULE_NAME);
lstrcat ((LPTSTR)szDumpFile, L".end");
FileSyncProfDumpData ((LPTSTR)szDumpFile);
WaitForSingleObject ( hMutex, INFINITE );
FreeMemoryOfList (phInactive);
FreeMemoryOfList (phActive);
FreeMemoryOfHandle (phDuplicated);
phActive = phInactive = phDuplicated = (PFP_Handle) NULL;
ReleaseMutex ( hMutex );
for ( Type = 0; Type < NUMOFSYNC; ) {
WaitForSingleObject ( hSMutex[Type], INFINITE );
FreeMemoryOfSList (phSInactive[Type]);
FreeMemoryOfSList (phSActive[Type]);
FreeMemoryOfSHandle (phSDuplicated[Type]);
phSActive[Type] = phSInactive[Type] = phSDuplicated[Type]
= (PSP_Handle) NULL;
ReleaseMutex ( hSMutex[Type++] );
}
// Clean-up
CloseHandle ( hDumpEvent );
CloseHandle ( hClearEvent );
UnmapViewOfFile ( (LPVOID) tszDumpFileName );
CloseHandle ( hDumpFileMapping );
CloseHandle ( hWaitingForDumpThread );
CloseHandle ( hWaitingForClearThread );
CloseHandle ( hMutex );
for ( Type = 0; Type < NUMOFSYNC; )
CloseHandle ( hSMutex[Type++] );
}
return(TRUE);
}
/*++
FileSyncProfInitDll() is called before calling any profiling api. Called
from within LibMain.
--*/
void FAR PASCAL FileSyncProfInitDll ()
{
DWORD ulInitElapsedTime, ThreadId;
SHORT sTimerHandle;
int i;
// Initialize the File I/O Profiler data
InitFileProf ();
// Initialize the Syncronization Profiler data
InitSyncProf ();
// Create the two threads and events to catch the Dump and Clear data events
// that are signalled by the apf32dmp program
hDumpEvent = CreateEvent ( (LPSECURITY_ATTRIBUTES) NULL, TRUE, FALSE,
L"FileProfDumpEvent" );
hWaitingForDumpThread = CreateThread ( (LPSECURITY_ATTRIBUTES) NULL, 0,
(LPTHREAD_START_ROUTINE) CatchDump, (LPVOID) NULL, (DWORD) 0,
(LPDWORD) &ThreadId );
hClearEvent = CreateEvent ( (LPSECURITY_ATTRIBUTES) NULL, TRUE, FALSE,
L"FileProfClearEvent" );
hWaitingForClearThread = CreateThread ( (LPSECURITY_ATTRIBUTES) NULL, 0,
(LPTHREAD_START_ROUTINE) CatchClear, (LPVOID) NULL, (DWORD) 0,
(LPDWORD) &ThreadId );
//
// Do timer calibration, if not already done.
//
//
// Calibrate time overhead from register save and restore:
// we get the minimum time here, to avoid extra time from
// interrupts etc.
// the tedious approach has two benefits
// - duplicate generated code as accurately as possible
// - pick up timer overhead, that isn't handled correctly
// in timer
// NOTE: The global variable ulTimerOverhead contains the
// timer overhead.
ulTimerOverhead = MAX_LONG;
TimerOpen(&sTimerHandle, MICROSECONDS);
for (i = 0; i < NUM_ITRATIONS; i++) {
TimerInit(sTimerHandle);
ulInitElapsedTime = TimerRead(sTimerHandle);
if ( ( ulInitElapsedTime < ulTimerOverhead ) &&
( ulInitElapsedTime > MIN_ACCEPTABLEOVERHEAD ) )
ulTimerOverhead = ulInitElapsedTime;
}
TimerClose(sTimerHandle);
}
/*++
FileSyncProfClearData() clears all data collected by the Profiler so far
--*/
void FAR PASCAL FileSyncProfClearData ()
{
void FileProfClearData(), SyncProfClearData();
FileProfClearData();
SyncProfClearData();
}
/*++
FileProfClearData() clears all the data collected so far. In particular,
the list of the inactive handles becomes empty, and all the statistics for
the curently active handles are zero-ed.
--*/
void FileProfClearData ()
{
register PFP_Handle phThisFile;
void InitHandle();
WaitForSingleObject ( hMutex, INFINITE );
FreeMemoryOfList(phInactive);
phInactive = (PFP_Handle) NULL;
phThisFile = phActive;
while ( phThisFile != (PFP_Handle) NULL ) {
InitHandle ( phThisFile );
phThisFile = phThisFile->phNext;
}
InitHandle ( phDuplicated );
ReleaseMutex ( hMutex );
}
/*++
FileSyncProfDumpData() dumps the data collected by the profiler so far.
--*/
int FAR PASCAL FileSyncProfDumpData (LPTSTR lpszDumpFile)
{
HANDLE hFile;
HANDLE AllMutex[NUMOFSYNC + 1];
UCHAR Type;
void FileProfDumpData(), SyncProfDumpData();
hFile = CreateFile ((LPCTSTR) lpszDumpFile, GENERIC_WRITE, 0,
(LPSECURITY_ATTRIBUTES) NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
// Failed to open the output file
if (hFile == (HANDLE)-1) {
return 1;
}
for ( Type = 0; Type < NUMOFSYNC; Type++ )
AllMutex[Type] = hSMutex[Type];
AllMutex[NUMOFSYNC] = hMutex;
WaitForMultipleObjects ( NUMOFSYNC + 1, AllMutex, TRUE, INFINITE );
FileProfDumpData ( (HFILE)hFile );
SyncProfDumpData ( (HFILE)hFile );
for ( Type = 0; Type < NUMOFSYNC + 1; Type++ )
ReleaseMutex ( AllMutex[Type] );
CloseHandle(hFile);
return 0;
}
/*++
FileProfDumpData() dumps the data (in verbose mode)
--*/
void FileProfDumpData ( HANDLE hFile )
{
DWORD cChar, cWChar;
register PFP_Handle phThisFile;
HANDLE hToMem;
void VerboseDumpHandleData(), AccumulateAllHandleData(), InitHandle();
void FreeMemoryOfHandle();
PFP_Handle NextHandle();
if ( (phActive == (PFP_Handle) NULL) && (phInactive == (PFP_Handle) NULL)
&& (! (ValidDataForDuplicatedHandles) ) )
return;
// Initialize structure for statistics of all used files
hToMem = GlobalAlloc ( MEM_ATTR, (DWORD) sizeof (FileProf_Handle) );
phAllFiles = (PFP_Handle) GlobalLock ( hToMem );
hToMem = GlobalAlloc ( MEM_ATTR, (DWORD) sizeof (FileProf_FileH) );
phAllFiles->pfHandleData = (PFP_FileH) GlobalLock ( hToMem );
ulNumOfAllCreateOps = ulNumOfAllOpenOps = ulNumOfAllCloseOps = (ULONG) 0;
ulNumOfFiles = (ULONG) 0;
InitHandle ( phAllFiles );
// initialize dummy large integer
liDummy.LowPart = (ULONG) 0;
liDummy.HighPart = (LONG) 0;
// print data table header
cChar = wsprintf ( OutBuf, L" \t\t\t FILE I/O PROFILER OUTPUT\r\n\r\n\r\n\0" );
WriteFileAnsi(hFile, OutBuf, cChar, &cWChar, (LPOVERLAPPED) NULL);
cChar = wsprintf ( OutBuf,
L" \t\t (Note: All times are in microseconds)\r\n\r\n\0");
WriteFileAnsi(hFile, OutBuf, cChar, &cWChar, (LPOVERLAPPED) NULL);
if ( phActive == (PFP_Handle) NULL )
if ( phInactive != (PFP_Handle) NULL )
phThisFile = phInactive;
else
phThisFile = (PFP_Handle) NULL;
else
phThisFile = phActive;
// Dump data for normal files
while ( phThisFile != (PFP_Handle) NULL ) {
VerboseDumpHandleData ( hFile, phThisFile );
AccumulateAllHandleData ( phThisFile );
phThisFile = NextHandle ( phThisFile );
}
// Dump data for duplicated handles
if ( ValidDataForDuplicatedHandles ) {
VerboseDumpHandleData ( hFile, phDuplicated );
AccumulateAllHandleData ( phDuplicated );
}
// Dump accumulated statistics for all files
VerboseDumpHandleData ( hFile, phAllFiles );
FreeMemoryOfHandle ( phAllFiles );
phAllFiles = (PFP_Handle) NULL;
}
/*++
VerboseDumpHandleData () dumps the statistics collected for a particular
handle
--*/
void VerboseDumpHandleData ( HANDLE hFile, PFP_Handle phThisFile )
{
register PFP_FileH pfData = phThisFile->pfHandleData;
register DWORD cChar;
DWORD cWChar;
cChar = wsprintf ( OutBuf, L"\r\n\r\n\r\n-------------------------------------------------------------------------------\r\n\0");
WriteFileAnsi(hFile, OutBuf, cChar, &cWChar, (LPOVERLAPPED) NULL);
// print file name and table header
if ( phThisFile == phAllFiles ) {
cChar = wsprintf ( OutBuf, L"Statistics for all file activity (Number of files used: %lu)\r\n\0", ulNumOfFiles);
WriteFileAnsi(hFile, OutBuf, cChar, &cWChar, (LPOVERLAPPED) NULL);
}
else {
cChar = wsprintf ( OutBuf, L"File: %ts\r\n\0", phThisFile->lpwsPathName );
WriteFileAnsi(hFile, OutBuf, cChar, &cWChar, (LPOVERLAPPED) NULL);
}
cChar = wsprintf ( OutBuf, L"----------+----------+----------+----------+----------+----------+-------------\r\n\0");
WriteFileAnsi(hFile, OutBuf, cChar, &cWChar, (LPOVERLAPPED) NULL);
cChar = wsprintf ( OutBuf, L"Operation | Total |Number of | Average | Total | Mean | Std Dev \r\n\0");
WriteFileAnsi(hFile, OutBuf, cChar, &cWChar, (LPOVERLAPPED) NULL);
cChar = wsprintf ( OutBuf, L" Name | Time |operations| Time | Bytes | Bytes | Bytes \r\n\0");
WriteFileAnsi(hFile, OutBuf, cChar, &cWChar, (LPOVERLAPPED) NULL);
cChar = wsprintf ( OutBuf, L"----------+----------+----------+----------+----------+----------+-------------\r\n\0");
WriteFileAnsi(hFile, OutBuf, cChar, &cWChar, (LPOVERLAPPED) NULL);
DumpDataLinePrint ( hFile, L"Overall ", pfData->Overall.nTimeOfOps, pfData->Overall.nNumOfOps, FALSE, liDummy, liDummy );
if ( (phThisFile != phDuplicated) && (phThisFile != phAllFiles) ) {
DumpDataLinePrint ( hFile, L"Create ", pfData->Createf.nTimeOfOp, (ULONG) 1, FALSE, liDummy, liDummy );
DumpDataLinePrint ( hFile, L"Open ", pfData->Openf.nTimeOfOp, (ULONG) 1, FALSE, liDummy, liDummy );
}
if ( phThisFile == phAllFiles ) {
DumpDataLinePrint ( hFile, L"Create ", pfData->Createf.nTimeOfOp, ulNumOfAllCreateOps, FALSE, liDummy, liDummy );
DumpDataLinePrint ( hFile, L"Open ", pfData->Openf.nTimeOfOp, ulNumOfAllOpenOps, FALSE, liDummy, liDummy );
}
DumpDataLinePrint ( hFile, L"Read ", pfData->Readf.nTimeOfOps, pfData->Readf.nNumOfOps, TRUE, pfData->Readf.nNumOfBytes, pfData->Readf.nSumOfSquareBytes );
DumpDataLinePrint ( hFile, L"Write ", pfData->Writef.nTimeOfOps, pfData->Writef.nNumOfOps, TRUE, pfData->Writef.nNumOfBytes, pfData->Writef.nSumOfSquareBytes );
DumpDataLinePrint ( hFile, L"Flush ", pfData->Flushf.nTimeOfOps, pfData->Flushf.nNumOfOps, FALSE, liDummy, liDummy );
DumpDataLinePrint ( hFile, L"Seek ", pfData->Seekf.nTimeOfOps, pfData->Seekf.nNumOfOps, FALSE, liDummy, liDummy );
DumpDataLinePrint ( hFile, L"Info ", pfData->Infof.nTimeOfOps, pfData->Infof.nNumOfOps, FALSE, liDummy, liDummy );
DumpDataLinePrint ( hFile, L"Lock ", pfData->Lockf.nTimeOfLockOps, pfData->Lockf.nNumOfLockOps, TRUE, pfData->Lockf.nNumOfBytes, pfData->Lockf.nSumOfSquareBytes );
DumpDataLinePrint ( hFile, L"Unlock ", pfData->Lockf.nTimeOfUnlockOps, pfData->Lockf.nNumOfUnlockOps, FALSE, liDummy, liDummy );
DumpDataLinePrint ( hFile, L"Set EOF ", pfData->Seteof.nTimeOfOps, pfData->Seteof.nNumOfOps, FALSE, liDummy, liDummy );
if ( phThisFile == phDuplicated )
DumpDataLinePrint ( hFile, L"Close ", pfData->Closef.nTimeOfOp, pfData->Createf.nTimeOfOp.LowPart, FALSE, liDummy, liDummy );
else if ( phThisFile == phAllFiles )
DumpDataLinePrint ( hFile, L"Close ", pfData->Closef.nTimeOfOp, ulNumOfAllCloseOps, FALSE, liDummy, liDummy );
else
DumpDataLinePrint ( hFile, L"Close ", pfData->Closef.nTimeOfOp, (ULONG) 1, FALSE, liDummy, liDummy );
}
/*++
DumpDataLinePrint () prints a line of data associated with a particular
handle that the profiled process used, and operation (eg ReadFile, OpenFile,
...)
--*/
void DumpDataLinePrint ( HANDLE hFile, LPTSTR NameOfOp, LARGE_INTEGER TimeOfOps,
ULONG NumOfOps, BOOL PrintBytes, LARGE_INTEGER SumOfBytes,
LARGE_INTEGER SumOfSquareBytes)
{
register DWORD cChar;
DWORD cWChar;
LARGE_INTEGER a;
if ( (NumOfOps == (ULONG) 0) || ((NumOfOps == (ULONG) 1) &&
(TimeOfOps.LowPart == (ULONG) 0)))
return;
// Clear output buffer
for ( cChar = 0; cChar < OUTLEN; )
*(OutBuf + (cChar++)) = TEXT(' ');
lstrcpy ( OutBuf, NameOfOp );
OutBuf[10] = TEXT('|');
RtlLargeIntegerPrint ( TimeOfOps, OutBuf + 11 );
OutBuf[21] = TEXT('|');
wsprintf ( OutBuf + 22, L"%10lu", NumOfOps );
OutBuf[32] = TEXT('|');
a.QuadPart = TimeOfOps.QuadPart / NumOfOps ;
wsprintf ( OutBuf + 33, L"%10lu", a.LowPart ) ;
OutBuf[43] = TEXT('|');
if ( PrintBytes )
RtlLargeIntegerPrint ( SumOfBytes, OutBuf + 44 );
else
*(OutBuf + 53) = TEXT('-');
OutBuf[54] = TEXT('|');
if ( PrintBytes ) {
a.QuadPart = SumOfBytes.QuadPart / NumOfOps ;
wsprintf ( OutBuf + 55, L"%10lu", a.LowPart );
}
else {
*(OutBuf + 64) = TEXT('-');
}
OutBuf[65] = TEXT('|');
if ( PrintBytes ) {
a.QuadPart = a.LowPart * a.LowPart ;
a.QuadPart = (SumOfSquareBytes.QuadPart / NumOfOps) - a.QuadPart ;
RtlLargeIntegerPrint ( a, OutBuf + 66 );
}
else
*(OutBuf + 75) = TEXT('-');
OutBuf[76] = TEXT('\r');
OutBuf[77] = TEXT('\n');
OutBuf[78] = TEXT('\0');
WriteFileAnsi ( hFile, OutBuf, 78, &cWChar, (LPOVERLAPPED) NULL );
}
/*++
RtlLargeIntegerPrint() prints a large integer (64 bits) in decimal.
Input: Argument is the large integer to be printed,
lptsBuffer is the buffer that will hold the null-terminated string
that is ready for printing
Output: Nothing.
Note: The routine always puts 10 characters in lptsBuffer. If the Argument
is shorter, blanks are used at the beginning of lptsBuffer. If it's
longer, the Argument is printed in scientific format: x.yyyyyezz.
--*/
void FAR PASCAL RtlLargeIntegerPrint (LARGE_INTEGER Argument, LPTSTR lptsBuffer)
{
LARGE_INTEGER Arg, Temp ;
TCHAR tsTempBuffer[15];
register SHORT i = 0, j = 0;
ULONG Divisor = (ULONG) 10;
ULONG Remainder;
Arg.LowPart = Argument.LowPart;
Arg.HighPart = Argument.HighPart;
if ( Arg.HighPart == 0 ) {
wsprintf ( lptsBuffer, L"%10lu", Arg.LowPart );
return;
}
while ( Arg.HighPart != 0 ) {
Arg.QuadPart = Arg.QuadPart / Divisor ;
Remainder = (ULONG)(Temp.QuadPart - (Arg.QuadPart * Divisor )) ;
*(tsTempBuffer + (i++)) = TEXT('0' + (UCHAR)Remainder);
}
j = wsprintf ( lptsBuffer, L"%lu", Arg.LowPart );
while ( --i >= 0 )
*(lptsBuffer + (j++)) = *(tsTempBuffer + i);
if ( j < 10 ) {
for ( i = 9; j > 0; )
*(lptsBuffer + (i--)) = *(lptsBuffer + (--j));
while ( i >= 0 )
*(lptsBuffer + (i--)) = TEXT(' ');
}
else if ( j > 10 ) {
SHORT k = 5;
for ( i = 6; k > 0; )
*(lptsBuffer + (i--)) = *(lptsBuffer + (k--));
*(lptsBuffer + 1) = TEXT('.');
*(lptsBuffer + 7) = TEXT('e');
wsprintf ( lptsBuffer + 8, L"%2u", j-1 );
}
}
/*++
AccumulateAllHandleData() is used to accumulate the statistics of all
opened (or created) handles into the record pointed to by the phAllFiles
pointer.
--*/
void AccumulateAllHandleData (PFP_Handle phHandle)
{
register PFP_FileH pfAll = phAllFiles->pfHandleData;
register PFP_FileH pfHData = phHandle->pfHandleData;
if ( phHandle != phDuplicated )
ulNumOfFiles++;
pfAll->Overall.nNumOfOps += pfHData->Overall.nNumOfOps;
pfAll->Overall.nTimeOfOps.QuadPart += pfHData->Overall.nTimeOfOps.QuadPart ;
pfAll->Writef.nNumOfOps += pfHData->Writef.nNumOfOps;
pfAll->Writef.nTimeOfOps.QuadPart += pfHData->Writef.nTimeOfOps.QuadPart ;
pfAll->Writef.nNumOfBytes.QuadPart += pfHData->Writef.nNumOfBytes.QuadPart ;
pfAll->Writef.nSumOfSquareBytes.QuadPart +=
pfHData->Writef.nSumOfSquareBytes.QuadPart;
pfAll->Readf.nNumOfOps += pfHData->Readf.nNumOfOps;
pfAll->Readf.nTimeOfOps.QuadPart += pfHData->Readf.nTimeOfOps.QuadPart ;
pfAll->Readf.nNumOfBytes.QuadPart += pfHData->Readf.nNumOfBytes.QuadPart ;
pfAll->Readf.nSumOfSquareBytes.QuadPart +=
pfHData->Readf.nSumOfSquareBytes.QuadPart ;
pfAll->Flushf.nNumOfOps += pfHData->Flushf.nNumOfOps;
pfAll->Flushf.nTimeOfOps.QuadPart += pfHData->Flushf.nTimeOfOps.QuadPart ;
pfAll->Seekf.nNumOfOps += pfHData->Seekf.nNumOfOps;
pfAll->Seekf.nTimeOfOps.QuadPart += pfHData->Seekf.nTimeOfOps.QuadPart ;
pfAll->Infof.nNumOfOps += pfHData->Infof.nNumOfOps;
pfAll->Infof.nTimeOfOps.QuadPart += pfHData->Infof.nTimeOfOps.QuadPart ;
pfAll->Lockf.nNumOfLockOps += pfHData->Lockf.nNumOfLockOps;
pfAll->Lockf.nTimeOfLockOps.QuadPart +=
pfHData->Lockf.nTimeOfLockOps.QuadPart ;
pfAll->Lockf.nNumOfUnlockOps += pfHData->Lockf.nNumOfUnlockOps;
pfAll->Lockf.nTimeOfUnlockOps.QuadPart +=
pfHData->Lockf.nTimeOfUnlockOps.QuadPart ;
pfAll->Lockf.nNumOfBytes.QuadPart += pfHData->Lockf.nNumOfBytes.QuadPart ;
pfAll->Lockf.nSumOfSquareBytes.QuadPart +=
pfHData->Lockf.nSumOfSquareBytes.QuadPart ;
pfAll->Seteof.nNumOfOps += pfHData->Seteof.nNumOfOps;
pfAll->Seteof.nTimeOfOps.QuadPart += pfHData->Seteof.nTimeOfOps.QuadPart ;
if (phHandle != phDuplicated) {
if ( (pfHData->Openf.nTimeOfOp.LowPart) != (ULONG) 0 ) {
ulNumOfAllOpenOps++;
pfAll->Openf.nTimeOfOp.QuadPart += pfHData->Openf.nTimeOfOp.QuadPart ;
}
if ( (pfHData->Createf.nTimeOfOp.LowPart) != (ULONG) 0 ) {
ulNumOfAllCreateOps++;
pfAll->Createf.nTimeOfOp.QuadPart += pfHData->Createf.nTimeOfOp.QuadPart ;
}
if ( (pfHData->Closef.nTimeOfOp.LowPart) != (ULONG) 0 ) {
ulNumOfAllCloseOps++;
pfAll->Closef.nTimeOfOp.QuadPart = pfHData->Closef.nTimeOfOp.QuadPart ;
}
}
else {
ulNumOfAllCloseOps += pfHData->Createf.nTimeOfOp.LowPart;
pfAll->Closef.nTimeOfOp.QuadPart = pfHData->Closef.nTimeOfOp.QuadPart ;
}
}
/*++
InitHandle() initializes a FileProf_Handle struct. In effect, it
initializes the various statistics kept for each disk file handle
used by the process
--*/
void InitHandle (PFP_Handle phHFile)
{
register PFP_FileH pfHData = phHFile->pfHandleData;
if ( phHFile == (PFP_Handle) NULL )
return;
if ( phHFile == phAllFiles ) {
ulNumOfAllCreateOps =
ulNumOfAllOpenOps =
ulNumOfAllCloseOps =
ulNumOfFiles = (ULONG) 0;
}
pfHData->Overall.nNumOfOps =
pfHData->Overall.nTimeOfOps.LowPart =
pfHData->Overall.nTimeOfOps.HighPart =
pfHData->Openf.nTimeOfOp.LowPart =
pfHData->Openf.nTimeOfOp.HighPart =
pfHData->Createf.nTimeOfOp.LowPart =
pfHData->Createf.nTimeOfOp.HighPart =
pfHData->Writef.nNumOfOps =
pfHData->Writef.nTimeOfOps.LowPart =
pfHData->Writef.nTimeOfOps.HighPart =
pfHData->Writef.nNumOfBytes.LowPart =
pfHData->Writef.nNumOfBytes.HighPart =
pfHData->Writef.nSumOfSquareBytes.LowPart =
pfHData->Writef.nSumOfSquareBytes.HighPart =
pfHData->Readf.nNumOfOps =
pfHData->Readf.nTimeOfOps.LowPart =
pfHData->Readf.nTimeOfOps.HighPart =
pfHData->Readf.nNumOfBytes.LowPart =
pfHData->Readf.nNumOfBytes.HighPart =
pfHData->Readf.nSumOfSquareBytes.LowPart =
pfHData->Readf.nSumOfSquareBytes.HighPart =
pfHData->Flushf.nNumOfOps =
pfHData->Flushf.nTimeOfOps.LowPart =
pfHData->Flushf.nTimeOfOps.HighPart =
pfHData->Seekf.nNumOfOps =
pfHData->Seekf.nTimeOfOps.LowPart =
pfHData->Seekf.nTimeOfOps.HighPart =
pfHData->Infof.nNumOfOps =
pfHData->Infof.nTimeOfOps.LowPart =
pfHData->Infof.nTimeOfOps.HighPart =
pfHData->Lockf.nNumOfLockOps =
pfHData->Lockf.nTimeOfLockOps.LowPart =
pfHData->Lockf.nTimeOfLockOps.HighPart =
pfHData->Lockf.nNumOfUnlockOps =
pfHData->Lockf.nTimeOfUnlockOps.LowPart =
pfHData->Lockf.nTimeOfUnlockOps.HighPart =
pfHData->Lockf.nNumOfBytes.LowPart =
pfHData->Lockf.nNumOfBytes.HighPart =
pfHData->Lockf.nSumOfSquareBytes.LowPart =
pfHData->Lockf.nSumOfSquareBytes.HighPart =
pfHData->Seteof.nNumOfOps =
pfHData->Seteof.nTimeOfOps.LowPart =
pfHData->Seteof.nTimeOfOps.HighPart =
pfHData->Closef.nTimeOfOp.LowPart =
pfHData->Closef.nTimeOfOp.HighPart = (ULONG) 0;
}
/*++
InitFileProf() initializes the two linked lists of statistics for
disk file handles kept by the File I/O Profiler.
--*/
void InitFileProf (void)
{
register i;
register HANDLE hToMem;
UINT nChars;
hMutex = CreateMutex ( (LPSECURITY_ATTRIBUTES) NULL, TRUE,
(LPTSTR)NAMEOFMUTEX );
// Allocate space for duplicate handle. phActive points to this space.
hToMem = GlobalAlloc ( MEM_ATTR, (DWORD) sizeof (FileProf_Handle) );
phDuplicated = (PFP_Handle) GlobalLock ( hToMem );
hToMem = GlobalAlloc ( MEM_ATTR, (DWORD) sizeof (FileProf_FileH) );
phDuplicated->pfHandleData = (PFP_FileH) GlobalLock ( hToMem );
hToMem = GlobalAlloc ( MEM_ATTR,
(DWORD)(nChars = (UINT) (sizeof(TCHAR) * (DUPLICATELEN + 1))) );
phDuplicated->lpwsPathName = (LPTSTR) GlobalLock ( hToMem );
lstrcpy (phDuplicated->lpwsPathName, (LPCTSTR)DUPLICATE);
phDuplicated->hHandlef = (HFILE) NULL;
phDuplicated->phNext = (PFP_Handle) NULL;
phActive = (PFP_Handle) NULL;
InitHandle (phDuplicated);
// Initialize inactive list
phInactive = (PFP_Handle) NULL;
// Initialize cache
for ( i = 0; i < USEDHANDLES; )
phCache[i++] = (PFP_Handle) NULL;
ReleaseMutex (hMutex);
}
/*++
AddHandle() allocates space and initializes the statistics of a new disk
file handle. It should be called from the OpenFile, _lopen, CreateFile
and _lcreat apis.
The handle to the file is kept in hFile. The name of the file is pointed
to by the lpwsFileName argument
The routine returns a pointer to the new record created
--*/
PFP_Handle AddHandle (HFILE hFile, LPTSTR lpwsFileName)
{
register i;
register PFP_Handle phNewHandle;
register HANDLE hToMem;
// Allocate space for new handle. phNewHandle points to this space
#ifdef DBGTRACE
printf ("Start AddHandle\r\n");
PrintLists();
PrintCache();
#endif
hToMem = GlobalAlloc ( MEM_ATTR, (DWORD) sizeof (FileProf_Handle) );
phNewHandle = (PFP_Handle) GlobalLock ( hToMem );
hToMem = GlobalAlloc ( MEM_ATTR, (DWORD) sizeof (FileProf_FileH) );
phNewHandle->pfHandleData = (PFP_FileH) GlobalLock ( hToMem );
hToMem = GlobalAlloc ( MEM_ATTR,
(DWORD) (sizeof(TCHAR) * (lstrlen (lpwsFileName) + 1 )));
phNewHandle->lpwsPathName = (LPTSTR) GlobalLock ( hToMem );
lstrcpy ( phNewHandle->lpwsPathName, lpwsFileName );
phNewHandle->hHandlef = hFile;
phNewHandle->phNext = phActive;
phActive = phNewHandle;
for ( i = USEDHANDLES; --i > 0; )
phCache[i] = phCache[i-1];
*phCache = phNewHandle;
InitHandle (phNewHandle);
#ifdef DBGTRACE
PrintLists();
PrintCache();
printf("End AddHandle\r\n");
#endif
return phNewHandle;
}
/*++
DeactivateHandle() transfers a record from the active to the inactive list
If the record for the handle hFile was found among the active handles, it
returns a pointer to the record. Otherwise, it returns a pointer to the
record for the duplicated handles.
--*/
PFP_Handle DeactivateHandle ( HFILE hFile )
{
register PFP_Handle phCurrent, phHandle;
register i = 0;
#ifdef DBGTRACE
printf("Start DeactivateHandle\r\n");
PrintLists();
PrintCache();
#endif
if ( phActive == (PFP_Handle) NULL )
return ( phDuplicated );
if ((phActive->hHandlef)== hFile) {//hFile was the first in the active list
phHandle = phActive;
phActive = phActive->phNext;
}
else { // hFile was not the first in the active list
for ( phCurrent = phActive;
(phCurrent->phNext != (PFP_Handle) NULL) &&
(phCurrent->phNext)->hHandlef != hFile;
phCurrent = phCurrent->phNext ) ;
if ( (phHandle = phCurrent->phNext) == (PFP_Handle) NULL )
return (phDuplicated);
phCurrent->phNext = phHandle->phNext;
}
// Add the record in the inactive list
phHandle->phNext = phInactive;
phInactive = phHandle;
// Delete entry from cache.
while ( (i < USEDHANDLES) && (phCache[i] != (PFP_Handle) NULL) &&
(phCache[i++] != phHandle) ) ;
if ( phCache[i-1] == phHandle ) {
while ( (i < USEDHANDLES) && (phCache[i] != (PFP_Handle) NULL) )
phCache[i-1] = phCache[i++];
phCache[--i] = (PFP_Handle) NULL;
}
#ifdef DBGTRACE
PrintLists();
PrintCache();
printf("End DeactivateHandle\r\n");
#endif
return (phHandle);
}
/*++
FindHandle() searches for a particular disk file handle in the active list
of records.
A pointer to the record corresponding to the handle is returned. If the
handle was not found, a pointer to the record for the duplicated handles
is returned.
--*/
PFP_Handle FindHandle (HFILE hFile)
{
register PFP_Handle *pphCacheEnd, *pphCacheNext;
register PFP_Handle phHNext;
#ifdef DBGTRACE
printf("Start FindHandle\r\n");
PrintLists();
PrintCache();
#endif
if ( ((*phCache)!= (PFP_Handle) NULL) && ((*phCache)->hHandlef == hFile) )
return ( *phCache );
// Search the cache
for ( pphCacheNext = phCache+1, pphCacheEnd = phCache+(USEDHANDLES-1);
(*pphCacheNext != (PFP_Handle) NULL) && pphCacheNext <= pphCacheEnd;
pphCacheNext++)
if ( (*pphCacheNext)->hHandlef == hFile ) {
phHNext = *pphCacheNext;
for ( pphCacheEnd = pphCacheNext--; pphCacheEnd > phCache;
pphCacheEnd = pphCacheNext-- )
*pphCacheEnd = *pphCacheNext;
*phCache = phHNext;
#ifdef DBGTRACE
PrintLists();
PrintCache();
printf("End FindHandle 1\r\n");
#endif
return (phHNext);
}
// If the handle was not found in the cache, search the active list
for ( phHNext=phActive; phHNext!=(PFP_Handle)NULL; phHNext=phHNext->phNext)
if ( phHNext->hHandlef == hFile ) {
pphCacheEnd = phCache + (USEDHANDLES - 1);
if ( (*pphCacheEnd) != (PFP_Handle) NULL )
pphCacheNext = pphCacheEnd - 1;
else {
while ( (pphCacheEnd > phCache) &&
((* (--pphCacheEnd)) == (PFP_Handle) NULL) ) ;
if ( pphCacheEnd > phCache )
pphCacheNext = pphCacheEnd++;
}
for ( ; pphCacheEnd > phCache; pphCacheEnd = pphCacheNext-- )
*pphCacheEnd = *pphCacheNext;
*phCache = phHNext;
#ifdef DBGTRACE
PrintLists();
PrintCache();
printf("End FindHandle 2\r\n");
#endif
return (phHNext);
}
#ifdef DBGTRACE
PrintLists();
PrintCache();
printf("End FindHandle 3\r\n");
#endif
return (phDuplicated);
}
/*++
NextHandle()
Input: A pointer to a record for a handle (phPrevHandle)
Output: A pointer to the next record in the two lists of records. In
particular, the inactive list is considered to follow the
active list.
--*/
PFP_Handle NextHandle (PFP_Handle phPrevHandle)
{
register PFP_Handle phNextHandle;
if ( phPrevHandle == (PFP_Handle) NULL )
return ((PFP_Handle) NULL);
if ( (phNextHandle = phPrevHandle->phNext) != (PFP_Handle) NULL )
return (phNextHandle);
if ( phActive == (PFP_Handle) NULL )
return ((PFP_Handle) NULL);
for ( phNextHandle = phActive; phNextHandle->phNext != (PFP_Handle) NULL;
phNextHandle = phNextHandle->phNext ) ;
if ( phNextHandle == phPrevHandle )
return (phInactive);
return ((PFP_Handle) NULL);
}
/*++
FreeMemoryOfList() frees all the memory allocated to the records for the
handles in the active or the inactive list
--*/
void FreeMemoryOfList (PFP_Handle phHeader)
{
register PFP_Handle phThisHandle = phHeader;
register PFP_Handle phNextHandle;
while ( phThisHandle != (PFP_Handle) NULL ) {
phNextHandle = phThisHandle->phNext;
FreeMemoryOfHandle (phThisHandle);
phThisHandle = phNextHandle;
}
}
/*++
FreeMemoryOfHandle() frees all the memory allocated to keep the data for
a particular handle
--*/
void FreeMemoryOfHandle (PFP_Handle phHandle)
{
register HANDLE hToMem;
if ( phHandle != phAllFiles ) {
hToMem = GlobalHandle ( (LPSTR) (phHandle->lpwsPathName) );
GlobalUnlock ( hToMem );
GlobalFree ( hToMem );
}
hToMem = GlobalHandle ( (LPSTR) (phHandle->pfHandleData) );
GlobalUnlock ( hToMem );
GlobalFree ( hToMem );
hToMem = GlobalHandle ( (LPSTR) phHandle );
GlobalUnlock ( hToMem );
GlobalFree ( hToMem );
}
// The accounting routines now.
/*++
OpenfAccounting() collects the statistics for the OpenFile and _lopen APIs
--*/
BOOL OpenfAccounting (PFP_FileH pfHData, ULONG nTime)
{
LARGE_INTEGER liTime ;
register FileProfOverall *pfpoOverall;
register FileProfOpen *pfpoOpen;
liTime.QuadPart = nTime ;
if ( pfHData == (PFP_FileH) NULL )
return FALSE;
pfpoOverall = &(pfHData->Overall);
pfpoOpen = &(pfHData->Openf);
(pfpoOverall->nNumOfOps)++;
pfpoOverall->nTimeOfOps.QuadPart += liTime.QuadPart ;
pfpoOpen->nTimeOfOp.LowPart = liTime.LowPart;
pfpoOpen->nTimeOfOp.HighPart = liTime.HighPart;
return TRUE;
}
/*++
CreatefAccounting() collects the statistics for the CreateFile and _lcreate
APIs
--*/
BOOL CreatefAccounting (PFP_FileH pfHData, ULONG nTime)
{
LARGE_INTEGER liTime ;
register FileProfOverall *pfpoOverall;
register FileProfCreate *pfpcCreate;
liTime.QuadPart = nTime ;
if ( pfHData == (PFP_FileH) NULL )
return FALSE;
pfpoOverall = &(pfHData->Overall);
pfpcCreate = &(pfHData->Createf);
(pfpoOverall->nNumOfOps)++;
pfpoOverall->nTimeOfOps.QuadPart += liTime.QuadPart ;
pfpcCreate->nTimeOfOp.LowPart = liTime.LowPart;
pfpcCreate->nTimeOfOp.HighPart = liTime.HighPart;
return TRUE;
}
/*++
WritefAccounting() collects the statistics for the WriteFile, WriteFileEx
and _lwrite APIs
--*/
BOOL WritefAccounting (PFP_FileH pfHData, ULONG nTime, ULONG nBytes)
{
LARGE_INTEGER liTime ;
LARGE_INTEGER liBytes ;
register FileProfOverall *pfpoOverall;
register FileProfWrite *pfpwWrite;
liTime.QuadPart = nTime ;
liBytes.QuadPart = nBytes ;
if ( pfHData == (PFP_FileH) NULL )
return FALSE;
pfpoOverall = &(pfHData->Overall);
pfpwWrite = &(pfHData->Writef);
(pfpoOverall->nNumOfOps)++;
pfpoOverall->nTimeOfOps.QuadPart += liTime.QuadPart ;
(pfpwWrite->nNumOfOps)++;
pfpwWrite->nTimeOfOps.QuadPart += liTime.QuadPart ;
pfpwWrite->nNumOfBytes.QuadPart += liBytes.QuadPart ;
liBytes.QuadPart = nBytes * nBytes ;
pfpwWrite->nSumOfSquareBytes.QuadPart += liBytes.QuadPart ;
return TRUE;
}
/*++
ReadfAccounting() collects the statistics for the ReadFile, ReadFileEx
and _lread APIs
--*/
BOOL ReadfAccounting (PFP_FileH pfHData, ULONG nTime, ULONG nBytes)
{
LARGE_INTEGER liTime ;
LARGE_INTEGER liBytes ;
register FileProfOverall *pfpoOverall;
register FileProfRead *pfprRead;
liTime.QuadPart = nTime ;
liBytes.QuadPart = nBytes ;
if ( pfHData == (PFP_FileH) NULL )
return FALSE;
pfpoOverall = &(pfHData->Overall);
pfprRead = &(pfHData->Readf);
(pfpoOverall->nNumOfOps)++;
pfpoOverall->nTimeOfOps.QuadPart += liTime.QuadPart ;
(pfprRead->nNumOfOps)++;
pfprRead->nTimeOfOps.QuadPart += liTime.QuadPart ;
pfprRead->nNumOfBytes.QuadPart += liBytes.QuadPart ;
liBytes.QuadPart = nBytes * nBytes ;
pfprRead->nSumOfSquareBytes.QuadPart += liBytes.QuadPart ;
return TRUE;
}
/*++
FlushfAccounting() collects the statistics for the FlushFileBuffers API
--*/
BOOL FlushfAccounting (PFP_FileH pfHData, ULONG nTime)
{
LARGE_INTEGER liTime ;
register FileProfOverall *pfpoOverall;
register FileProfFlush *pfpfFlush;
liTime.QuadPart = nTime ;
if ( pfHData == (PFP_FileH) NULL )
return FALSE;
pfpoOverall = &(pfHData->Overall);
pfpfFlush = &(pfHData->Flushf);
(pfpoOverall->nNumOfOps)++;
pfpoOverall->nTimeOfOps.QuadPart += liTime.QuadPart ;
(pfpfFlush->nNumOfOps)++;
pfpfFlush->nTimeOfOps.QuadPart += liTime.QuadPart ;
return TRUE;
}
/*++
SeekfAccounting() collects the statistics for the SetFilePointer and
_llseek APIs
--*/
BOOL SeekfAccounting (PFP_FileH pfHData, ULONG nTime)
{
LARGE_INTEGER liTime ;
register FileProfOverall *pfpoOverall;
register FileProfSeek *pfpsSeek;
liTime.QuadPart = nTime ;
if ( pfHData == (PFP_FileH) NULL )
return FALSE;
pfpoOverall = &(pfHData->Overall);
pfpsSeek = &(pfHData->Seekf);
(pfpoOverall->nNumOfOps)++;
pfpoOverall->nTimeOfOps.QuadPart += liTime.QuadPart ;
(pfpsSeek->nNumOfOps)++;
pfpsSeek->nTimeOfOps.QuadPart += liTime.QuadPart ;
return TRUE;
}
/*++
InfofAccounting() collects the statistics for the GetFileType,
GetFileInformationByHandle, GetFileSize, GetFileTime, and SetFileTime APIs
--*/
BOOL InfofAccounting (PFP_FileH pfHData, ULONG nTime)
{
LARGE_INTEGER liTime ;
register FileProfOverall *pfpoOverall;
register FileProfInfo *pfpiInfo;
liTime.QuadPart = nTime ;
if ( pfHData == (PFP_FileH) NULL )
return FALSE;
pfpoOverall = &(pfHData->Overall);
pfpiInfo = &(pfHData->Infof);
(pfpoOverall->nNumOfOps)++;
pfpoOverall->nTimeOfOps.QuadPart += liTime.QuadPart ;
(pfpiInfo->nNumOfOps)++;
pfpiInfo->nTimeOfOps.QuadPart += liTime.QuadPart ;
return TRUE;
}
/*++
LockfAccounting() collects the statistics for the LockFile API
--*/
BOOL LockfAccounting (PFP_FileH pfHData, ULONG nTime, BOOL Success,
LARGE_INTEGER nBytes)
{
LARGE_INTEGER liTime ;
register FileProfOverall *pfpoOverall;
register FileProfLock *pfplLock;
liTime.QuadPart = nTime ;
if ( pfHData == (PFP_FileH) NULL )
return FALSE;
pfpoOverall = &(pfHData->Overall);
pfplLock = &(pfHData->Lockf);
(pfpoOverall->nNumOfOps)++;
pfpoOverall->nTimeOfOps.QuadPart += liTime.QuadPart ;
(pfplLock->nNumOfLockOps)++;
pfplLock->nTimeOfLockOps.QuadPart += liTime.QuadPart ;
if ( Success ) {
pfplLock->nNumOfBytes.QuadPart += nBytes.QuadPart ;
nBytes.QuadPart = nBytes.LowPart * nBytes.LowPart ;
pfplLock->nSumOfSquareBytes.QuadPart += nBytes.QuadPart ;
}
return TRUE;
}
/*++
UnlockfAccounting() collects the statistics for the UnlockFile API
--*/
BOOL UnlockfAccounting (PFP_FileH pfHData, ULONG nTime, BOOL Success )
{
LARGE_INTEGER liTime ;
register FileProfOverall *pfpoOverall;
register FileProfLock *pfplLock;
liTime.QuadPart = nTime ;
if ( pfHData == (PFP_FileH) NULL )
return FALSE;
pfpoOverall = &(pfHData->Overall);
pfplLock = &(pfHData->Lockf);
(pfpoOverall->nNumOfOps)++;
pfpoOverall->nTimeOfOps.QuadPart += liTime.QuadPart ;
(pfplLock->nNumOfUnlockOps)++;
pfplLock->nTimeOfUnlockOps.QuadPart += liTime.QuadPart ;
return TRUE;
}
/*++
SeteofAccounting() collects the statistics for the SetEndOfFile API
--*/
BOOL SeteofAccounting (PFP_FileH pfHData, ULONG nTime)
{
LARGE_INTEGER liTime ;
register FileProfOverall *pfpoOverall;
register FileProfSetEOF *pfpsSeteof;
liTime.QuadPart = nTime ;
if ( pfHData == (PFP_FileH) NULL )
return FALSE;
pfpoOverall = &(pfHData->Overall);
pfpsSeteof = &(pfHData->Seteof);
(pfpoOverall->nNumOfOps)++;
pfpoOverall->nTimeOfOps.QuadPart += liTime.QuadPart ;
(pfpsSeteof->nNumOfOps)++;
pfpsSeteof->nTimeOfOps.QuadPart += liTime.QuadPart ;
return TRUE;
}
/*++
ClosefAccounting() collects the statistics for the CloseHandle and _lclose
APIs
--*/
BOOL ClosefAccounting (PFP_FileH pfHData, ULONG nTime)
{
LARGE_INTEGER liTime ;
register FileProfOverall *pfpoOverall;
register FileProfClose *pfpcClose;
liTime.QuadPart = nTime ;
if ( pfHData == (PFP_FileH) NULL )
return FALSE;
pfpoOverall = &(pfHData->Overall);
pfpcClose = &(pfHData->Closef);
(pfpoOverall->nNumOfOps)++;
pfpoOverall->nTimeOfOps.QuadPart += liTime.QuadPart ;
pfpcClose->nTimeOfOp.QuadPart += liTime.QuadPart ;
return TRUE;
}
TCHAR * FAR PASCAL FileSyncProfGetModuleName ()
{
return MODULE_NAME;
}
/*++
CatchDump() is the routine executed by one of the threads that the
fernel32 dll creates to catch the signals generated by apf32dmp.exe sig-
nalling that the statistics collected by the dll so far need to be dumped
--*/
void CatchDump()
{
hDumpFileMapping = CreateFileMapping ( (HANDLE) 0xFFFFFFFF,
(LPSECURITY_ATTRIBUTES) NULL, PAGE_READWRITE, 0, MAXFILENAMELEN,
L"FileProfDumpFileName" );
tszDumpFileName = (LPTSTR) MapViewOfFile ( hDumpFileMapping, FILE_MAP_READ,
0, 0, MAXFILENAMELEN );
while ( TRUE ) {
WaitForSingleObject ( hDumpEvent, INFINITE );
FileSyncProfDumpData ( tszDumpFileName );
}
}
/*++
CatchClear() is the routine executed by one of the threads that the
fernel32 dll creates to catch the signals generated by apf32dmp.exe
signalling that the statistics collected by the dll so far need to be
cleared
Note: In the case of Dump and Clear, the dump must be done first
--*/
void CatchClear ()
{
while ( TRUE ) {
WaitForSingleObject ( hClearEvent, INFINITE );
if ( WaitForSingleObject ( hDumpEvent, 0 ) == WAIT_TIMEOUT )
Sleep ( 100 ); //ensure that dump happens before clear
else {
SetEvent ( hDumpEvent ); // we reset the event, so set it back
Sleep ( 200 ); // let him do the dump
}
FileSyncProfClearData ();
}
}
#ifdef DBGTRACE
PrintLists ()
{
PFP_Handle pnext;
int i;
printf("THE LISTS\r\n\r\n");
printf("Active list\r\n");
for ( i=0, pnext=phActive; pnext!= (PFP_Handle)NULL; pnext=pnext->phNext)
printf("%d . %s\r\n", i++, pnext->lpwsPathName);
printf("Inactive list\r\n");
for (i=0, pnext=phInactive; pnext!= (PFP_Handle)NULL; pnext=pnext->phNext)
printf("%d . %s\r\n", i++, pnext->lpwsPathName);
// getchar();
}
PrintCache ()
{
int i;
printf("THE CACHE\r\n\r\n");
for ( i=0; i<USEDHANDLES && phCache[i]!= (PFP_Handle)NULL; i++)
printf("%d . %s\r\n", i, phCache[i]->lpwsPathName);
getchar();
}
PrintSLists (UCHAR Type)
{
PSP_Handle pnext;
int i;
printf("THE S LISTS\r\n\r\n");
printf("Active list\r\n");
for ( i=0, pnext=phSActive[Type]; pnext!= (PSP_Handle)NULL; pnext=pnext->phNext)
printf("%d . %s\r\n", i++, pnext->lpwsSyncName);
printf("Inactive list\r\n");
for (i=0, pnext=phSInactive[Type]; pnext!= (PSP_Handle)NULL; pnext=pnext->phNext)
printf("%d . %s\r\n", i++, pnext->lpwsSyncName);
// getchar();
}
PrintSCache ()
{
int i;
printf("THE S CACHE\r\n\r\n");
for ( i=0; i<USEDHANDLES && phSCache[i]!= (PSP_Handle)NULL; i++)
printf("%d . %s\r\n", i, phSCache[i]->lpwsSyncName);
getchar();
}
#endif