vcmon.c
来自「磁盘工具」· C语言 代码 · 共 461 行
C
461 行
//======================================================================
//
// VCMON.c - main module for VxD VCMON
//
// Copyright (c) 1996 Mark Russinovich and Bryce Cogswell
//
//======================================================================
#define DEVICE_MAIN
#include "vcmon.h"
#undef DEVICE_MAIN
#include "stats.h"
// this should be set to 1 if you want debug output to Winice or WDEB386
#define DEBUGOUT 0
Declare_Virtual_Device(VCMON)
DefineControlHandler(SYS_DYNAMIC_DEVICE_INIT, OnSysDynamicInit);
DefineControlHandler(SYS_DYNAMIC_DEVICE_EXIT, OnSysDynamicExit);
DefineControlHandler(SYS_CRITICAL_INIT, OnSysCriticalInit);
DefineControlHandler(SYS_CRITICAL_EXIT, OnSysCriticalExit);
DefineControlHandler(W32_DEVICEIOCONTROL, OnW32Deviceiocontrol);
//----------------------------------------------------------------------
//
// LOCKED DATA
//
//----------------------------------------------------------------------
#include LOCKED_DATA_SEGMENT
// statistics
VcmonStatus_s Stats;
DWORD GuiEvent;
TIMEOUTHANDLE GuiTimeoutHandle;
TIMEOUT_THUNK GuiTimeThunk;
// sample rate
DWORD SampleRate = STATSFREQ;
BOOL Connected = FALSE;
BOOL FailConnect = FALSE;
// thunks and original service addresses
PVOID VCacheFindBlockService;
DeviceService_THUNK thunkVCacheFindBlockHook;
PVOID VCacheHoldService;
DeviceService_THUNK thunkVCacheHoldHook;
PVOID VCacheGetStatsService;
DeviceService_THUNK thunkVCacheGetStatsHook;
PVOID PageFileReadWriteService;
DeviceService_THUNK thunkPageFileReadWriteHook;
//----------------------------------------------------------------------
//
// LOCKED CODE
//
//----------------------------------------------------------------------
#include LOCKED_CODE_SEGMENT
#if !DEBUGOUT
//----------------------------------------------------------------------
//
// dprintf
//
// If no debug output is desired, this routine stifles the real dprint
// with a no-op.
//
//----------------------------------------------------------------------
void dprintf(const char *format, ...)
{
}
#endif DEBUGOUT
//----------------------------------------------------------------------
//
// VCMON_Get_Version
//
// Returns our version number.
//
//----------------------------------------------------------------------
DWORD _cdecl VCMON_Get_Version( void )
{
return VCMON_Major << 8 | VCMON_Minor;
}
//----------------------------------------------------------------------
//
// GuiTimeout
//
// At the specified sample Each second we signal the Gui, telling it that there are some new
// statistics ready for it to pick up.
//
//----------------------------------------------------------------------
VOID __stdcall GuiTimeout(VMHANDLE hVM, PCLIENT_STRUCT pcrs,
PVOID RefData, DWORD Extra)
{
DWORD lockable;
// get size of cache
Stats.size = VCache_GetSize(0, &Stats.size ) * 4;
// get amount of free memory
Stats.free = GetFreePageCount( 0, &lockable ) * 4;
// signal the gui
VWIN32_DIOCCompletionRoutine( (DWORD) GuiEvent );
// set-up for next timeout
if( Extra >= SampleRate ) Extra = SampleRate;
GuiTimeoutHandle = Set_Global_Time_Out( SampleRate - Extra, 0,
GuiTimeout, &GuiTimeThunk );
}
//----------------------------------------------------------------------
//
// PageFileReadHook
//
// This hook monitors page faults, distinguishing reads from writes.
//
//----------------------------------------------------------------------
VOID __stdcall PageFileReadWriteHook( PDSFRAME pDS )
{
pagefilecmd_s *pfcmd = (pagefilecmd_s *) pDS->REBX;
if( pfcmd->cmd == READ )
Stats.pagereads++;
else
Stats.pagewrites++;
Call_Previous_Hook_Proc( pDS, &thunkPageFileReadWriteHook );
}
//----------------------------------------------------------------------
//
// VCacheGetStatsHook
//
// VMM calls this routine periodically to determine how many hits
// and misses occur at, or just past, the end of the LRU. See the
// VCache documentation for details.
//
//----------------------------------------------------------------------
VOID __stdcall VCacheGetStatsHook( PDSFRAME pDS )
{
Call_Previous_Hook_Proc( pDS, &thunkVCacheGetStatsHook );
Stats.repmisses += pDS->REBX;
Stats.rephits += pDS->RECX;
dprintf("GetStats: miss:%d hits:%d disc:%d\n", pDS->REBX, pDS->RECX,
pDS->REDI );
}
//----------------------------------------------------------------------
//
// VCacheHoldHook
//
// Hold is called whenever VFAT wants to access the data related
// to a block
//
//----------------------------------------------------------------------
VOID __stdcall VCacheHoldHook( PDSFRAME pDS )
{
dprintf("Hold: %x\n", pDS->RESI );
Call_Previous_Hook_Proc( pDS, &thunkVCacheHoldHook );
Stats.holds++;
}
//----------------------------------------------------------------------
//
// VCacheFindBlockHook
//
// FindBlock is the main routine called to determine whether a block
// is in the cache or not. We break it into two calls: a lookup followed
// by a create if that is requested so that we can distinguis misses
// from creates.
//
//----------------------------------------------------------------------
VOID __stdcall VCacheFindBlockHook( PDSFRAME pDS )
{
BOOL create = FALSE;
DSFRAME saveregs;
dprintf("FindBlock - ");
if( pDS->REAX & VCFB_Create)
dprintf("create ");
if( pDS->REAX & VCFB_MustCreate)
dprintf("Must-Create");
if( pDS->REAX & VCFB_Hold)
dprintf("hold ");
if( pDS->REAX & VCFB_LowPri)
dprintf("low-pri ");
if( pDS->REAX & VCFB_MakeMRU)
dprintf("MRU ");
// if its a create, break it into two calls
if( pDS->REAX & VCFB_Create || pDS->REAX & VCFB_MustCreate ) {
// see if its a hit or a miss before its created
saveregs = *pDS;
pDS->REAX &= ~0xFF;
Call_Previous_Hook_Proc( pDS, &thunkVCacheFindBlockHook );
if( pDS->RESI )
Stats.hits++;
else {
// if it was a miss then a block will be created
create = TRUE;
Stats.misses++;
}
// restore regs and do the call again
*pDS = saveregs;
Call_Previous_Hook_Proc( pDS, &thunkVCacheFindBlockHook );
} else {
// its just a lookup, let it go through
Call_Previous_Hook_Proc( pDS, &thunkVCacheFindBlockHook );
if( pDS->RESI )
Stats.hits++;
else
Stats.misses++;
}
// it it was a create, inc the count if successful
if( pDS->RESI && create )
Stats.new++;
dprintf(": %x\n", pDS->RESI );
}
//----------------------------------------------------------------------
//
// DoHooks
//
// Hook all the routines we need to.
//
//----------------------------------------------------------------------
VOID DoHooks( void )
{
// hook the hold service
VCacheHoldService = Hook_Device_Service(
GetVxDServiceOrdinal(VCache_Hold),
VCacheHoldHook,
&thunkVCacheHoldHook);
// hook the findblock service
VCacheFindBlockService = Hook_Device_Service(
GetVxDServiceOrdinal(VCache_FindBlock),
VCacheFindBlockHook,
&thunkVCacheFindBlockHook);
// hook the getstats
VCacheGetStatsService = Hook_Device_Service(
GetVxDServiceOrdinal(VCache_GetStats),
VCacheGetStatsHook,
&thunkVCacheGetStatsHook);
// hook the pagefile read/write service
PageFileReadWriteService = Hook_Device_Service(
GetVxDServiceOrdinal(VCPageFile_Read_Or_Write),
PageFileReadWriteHook,
&thunkPageFileReadWriteHook);
}
//----------------------------------------------------------------------
//
// DoUnhooks
//
// Unhook the services we hooked.
//
//----------------------------------------------------------------------
VOID DoUnhooks( void )
{
// unhook the hold service
Unhook_Device_Service(GetVxDServiceOrdinal(VCache_Hold),
VCacheHoldHook,
&thunkVCacheHoldHook);
// unhook the findblock service
Unhook_Device_Service(GetVxDServiceOrdinal(VCache_FindBlock),
VCacheFindBlockHook,
&thunkVCacheFindBlockHook);
// unhook the getstats
Unhook_Device_Service(GetVxDServiceOrdinal(VCache_GetStats),
VCacheGetStatsHook,
&thunkVCacheGetStatsHook);
// unhook the pagefile read/write service
Unhook_Device_Service(GetVxDServiceOrdinal(VCPageFile_Read_Or_Write),
PageFileReadWriteHook,
&thunkPageFileReadWriteHook);
}
//----------------------------------------------------------------------
//
// OnSysCriticalInit
//
// Initialization: hook all the routines we need to.
//
//----------------------------------------------------------------------
BOOL OnSysCriticalInit( VMHANDLE hVM, PCHAR CommandTail,
DWORD RealModeReferenceData )
{
DoHooks();
return TRUE;
}
//----------------------------------------------------------------------
//
// OnSysDynamicInit
//
// Initialization: hook all the routines we need to.
//
//----------------------------------------------------------------------
BOOL OnSysDynamicInit( void )
{
DoHooks();
return TRUE;
}
//----------------------------------------------------------------------
//
// OnW32Deviceiocontrol
//
// Entry point for Win32 requests. Two functions are support:
//
// STATUS: called by the gui to register. We fail the call if we
// are already connected. Otherwise we pass back to the
// gui the address of the statistics data structure.
// SETRATE: the user can change the stats sampling frequency. This
// is where the timeout interval is changed to reflect the
// new value.
//
//----------------------------------------------------------------------
DWORD OnW32Deviceiocontrol( PIOCTLPARAMS p )
{
DWORD lockable;
switch ( p->dioc_IOCtlCode ) {
case -1:
if( !FailConnect ) {
// gui is closing
Cancel_Time_Out( GuiTimeoutHandle );
Connected = FALSE;
FailConnect = FALSE;
}
return 0;
case 0:
return 0;
case VCMON_STATUS:
// if already connected, return error
if( Connected ) {
FailConnect = TRUE;
return 1;
}
// get size of cache
Stats.size = VCache_GetSize(0, &Stats.size ) * 4;
// get amount of free memory
Stats.free = GetFreePageCount( 0, &lockable ) * 4;
// Gui is initiating contact
GuiEvent = p->dioc_ovrlp->O_Internal;
*(VOID **) p->dioc_OutBuf = &Stats;
GuiTimeoutHandle = Set_Global_Time_Out( SampleRate, 0,
GuiTimeout, &GuiTimeThunk );
*p->dioc_bytesret = 4;
Connected = TRUE;
return 0;
case VCMON_SETRATE:
// need to reset sample rate
SampleRate = *(PDWORD) p->dioc_InBuf;
// cancel event
Cancel_Time_Out( GuiTimeoutHandle );
GuiTimeoutHandle = Set_Global_Time_Out( SampleRate, 0,
GuiTimeout, &GuiTimeThunk );
return 0;
default:
return 1;
}
}
//----------------------------------------------------------------------
//
// OnSysCriticalExit
//
// Unhook everything we hooked.
//
//----------------------------------------------------------------------
VOID OnSysCriticalExit( void )
{
DoUnhooks();
}
//----------------------------------------------------------------------
//
// OnSysDynamicExit
//
// Unhook everything we hooked.
//
//----------------------------------------------------------------------
BOOL OnSysDynamicExit( void )
{
DoUnhooks();
return TRUE;
}
//----------------------------------------------------------------------
//
// ControlDispatcher
//
// Multiplex VxD control messages.
//
//----------------------------------------------------------------------
BOOL __cdecl ControlDispatcher(
DWORD dwControlMessage,
DWORD EBX,
DWORD EDX,
DWORD ESI,
DWORD EDI,
DWORD ECX)
{
START_CONTROL_DISPATCH
ON_SYS_DYNAMIC_DEVICE_INIT(OnSysDynamicInit);
ON_SYS_DYNAMIC_DEVICE_EXIT(OnSysDynamicExit);
ON_SYS_CRITICAL_INIT(OnSysCriticalInit);
ON_SYS_CRITICAL_EXIT(OnSysCriticalExit);
ON_W32_DEVICEIOCONTROL(OnW32Deviceiocontrol);
END_CONTROL_DISPATCH
return TRUE;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?