📄 filemon.c
字号:
/*
FILEMON.C -- File monitoring VxD for Windows 95
For Win32 app: CONLDR.C
Stan Mitchell
See Stan Mitchell, "Monitoring Windows 95 File Activity in Ring 0,"
Windows/DOS Developer's Journal, July 1995, pp. 6-24.
Also see ftp://ftp.ora.com/pub/examples/windows/win95.update/regwiz.html
*/
/***** Listing 1 FILEMON.C *****/
#include <string.h>
#define WANTVXDWRAPS
#include <basedef.h>
#include <vmm.h>
#include <debug.h>
#include <vwin32.h>
#include <winerror.h>
#include <vxdwraps.h>
#include <ifs.h>
enum IFSMGR_SERVICES { __UniToBCSPath=0x00400041,
__IFSMgr_InstallFileSystemApiHook=0x00400067,
__IFSMgr_RemoveFileSystemApiHook=0x00400068 };
/* The buffer contains 256 LINEs, the first is reserved */
/* for status, lines 0 through 254 are used for output lines */
#define MAXLINE 254
typedef char LINE[128];
#pragma VxD_LOCKED_DATA_SEG
char* szOp[] = { "Read", "Write", "FndNext", "FcnNext",
"?","?","?","?","?","?", "Seek", "Close", "Commit",
"FLocks", "FTimes", "PipeReq", "HdlInfo", "EnumHdl",
"FndClose", "FcnClose", "?","?","?","?","?","?","?",
"?","?","?", "Conn", "Delete", "Dir", "FAttrib",
"Flush", "DiskInfo", "Open", "Rename", "Search",
"Query", "DisConn", "UNCPipeReq", "Ioctl", "DiskParm",
"FndOpen", "Dasdio" };
ppIFSFileHookFunc ppPrevHook; /* the previous hooker */
HTIMEOUT hTimeOut = 0;
DWORD hVMEvent = 0;
HANDLE hEventRing0 = 0;
HVM hSysVM;
LINE* pLineBuf = NULL; /* buffer for output lines */
DWORD* pdw = NULL;
int nLastLine = -1;
#define DIOC_REQEVENTS 1
#define DIOC_SHUTDOWN 2
#pragma VxD_LOCKED_CODE_SEG
#pragma intrinsic(strcpy,strcat,memcpy)
/* Wrapper for the IFS Mgr Service, UniToBCSPath */
UINT __declspec( naked )
UniToBCSDrvPath( UCHAR* pStr, PathElement* pPth,
UINT maxL, int cSet, int drv ) {
_asm push ebp _asm mov ebp,esp
_asm push ebx
_asm mov ebx,[pStr]
_asm mov eax,[drv]
_asm cmp al,0ffh /* UNC volume? */
_asm jz skipdrv
_asm add al,'@'
_asm mov byte ptr [ebx],al
_asm inc ebx
_asm mov byte ptr [ebx],':'
_asm inc ebx
skipdrv:
_asm push [cSet] /* Arguments pushed */
_asm push [maxL] /* in cdecl order */
_asm push [pPth]
_asm push ebx
VxDCall( UniToBCSPath );
_asm add esp,4*4
_asm pop ebx /* eax returns byte cnt */
_asm leave _asm ret
}
/* Called as System VM Event */
void __declspec( naked ) SetWin32Event( void ) {
_asm push ebp _asm mov ebp,esp
_asm mov eax,[edx]
VxDCall( _VWIN32_SetWin32Event );
hVMEvent = 0;
_asm leave _asm ret
}
#define LPtr(a) (&pLineBuf[idx][a])
#ifdef SHOW_HANDLES
#define AddResHdl(a) _Sprintf(LPtr(a),"{%08lx} ",pir->ir_rh)
#define AddFileHdl(a) _Sprintf(LPtr(a),"[%08lx] ",pir->ir_fh)
#define SkpFileHdl(a) _Sprintf(LPtr(a), "%11s"," ")
#else
#define AddResHdl(a) 0
#define AddFileHdl(a) 0
#define SkpFileHdl(a) 0
#endif
#define AddUniPath(a,n) UniToBCSDrvPath( LPtr(a), pUniPath,\
n, BCS_WANSI, drv)
#define CatStr(s) strcat(pLineBuf[idx],s)
/* The FileSystem Hook Function */
int __cdecl FileHook( pIFSFunc pfn,
int fn, int drv, int res,
int cp, pioreq pir )
{
int retc, idx, i;
PathElement* pUniPath;
unsigned short preOptions;
/* Go ahead and call down the chain to the FSD ...
* we look at the IFSFunc only if it succeeds */
preOptions = pir->ir_options;
retc = (*(*ppPrevHook))( pfn, fn, drv, res, cp, pir );
if ( !hEventRing0 ) return retc;
// Functions which are included in this switch statement
// are not monitored
switch( fn ) {
case IFSFN_FILETIMES: /* "GetFTimes" */
if ( (pir->ir_flags != GET_MODIFY_DATETIME) &&
(pir->ir_flags != GET_LAST_ACCESS_DATETIME) &&
(pir->ir_flags != GET_CREATION_DATETIME) )
break;
case IFSFN_READ: /* "Read" */
case IFSFN_WRITE: /* "Write" */
case IFSFN_SEEK: /* "Seek" */
case IFSFN_CLOSE: /* "Close" */
case IFSFN_FINDCLOSE:
case IFSFN_FCNCLOSE:
case IFSFN_FINDNEXT: /* "Next" */
case IFSFN_FCNNEXT:
return retc;
}
/* Point to the Unicode path components of the file */
pUniPath = pir->ir_ppath->pp_elements;
_asm pushfd
_asm cli
if ( ++nLastLine > MAXLINE ) nLastLine=0;
idx = nLastLine;
_asm popfd
i = _Sprintf( pLineBuf[idx], " %3d %c %10s %c ",
idx, pir->ir_error ? 'e' : ' ', szOp[fn],
res & IFSFH_RES_CFSD ? 'c' : ' ' );
switch( fn )
{
case IFSFN_READ: case IFSFN_WRITE:
i+=AddFileHdl(i); i+=AddResHdl(i);
_Sprintf( LPtr(i), "leng: %08lx %c%c",
pir->ir_length,
(preOptions & R0_SWAPPER_CALL) ? 's' : ' ',
(preOptions & R0_MM_READ_WRITE) ? 'm' : ' ' );
break;
case IFSFN_SEEK: case IFSFN_CLOSE:
case IFSFN_FINDNEXT: case IFSFN_FINDCLOSE:
case IFSFN_FCNNEXT: case IFSFN_FCNCLOSE:
case IFSFN_COMMIT: case IFSFN_ENUMHANDLE:
case IFSFN_FILELOCKS:
i+=AddFileHdl(i); AddResHdl(i);
break;
case IFSFN_IOCTL16DRIVE: case IFSFN_SEARCH:
i+=SkpFileHdl(i); i+=AddResHdl(i);
_Sprintf(LPtr(i),"SubFunction: %04X",pir->ir_flags);
break;
case IFSFN_QUERY:
i+=SkpFileHdl(i); i+=AddResHdl(i);
i+=_Sprintf(LPtr(i),"Level %d ",preOptions);
break;
case IFSFN_DELETE: case IFSFN_FINDOPEN:
case IFSFN_RENAME:
i+=SkpFileHdl(i); i+=AddResHdl(i);
if ( fn == IFSFN_RENAME ) {
i+=AddUniPath(i,45);
pUniPath = pir->ir_ppath2->pp_elements;
if ( drv != 0xff ) i+=2;
CatStr(" -> "); i+=4;
AddUniPath(i,45);
}
else i+=AddUniPath(i,80);
break;
case IFSFN_CONNECT:
i+=SkpFileHdl(i); AddResHdl(i);
switch( pir->ir_flags ) {
case RESTYPE_WILD:
CatStr("wild card"); break;
case RESTYPE_DISK:
CatStr("disk"); break;
case RESTYPE_SPOOL:
CatStr("spooled printer"); break;
case RESTYPE_CHARDEV:
CatStr("char device"); break;
case RESTYPE_IPC:
CatStr("ipc"); break;
}
break;
case IFSFN_FILEATTRIB:
if ( pir->ir_flags == GET_ATTRIBUTES )
memcpy( &pLineBuf[idx][8], "Get", 3 );
else memcpy( &pLineBuf[idx][8], "Set", 3 );
i+=SkpFileHdl(i); i+=AddResHdl(i);
AddUniPath(i,80);
break;
case IFSFN_FILETIMES:
if ( (pir->ir_flags == GET_MODIFY_DATETIME) ||
(pir->ir_flags == GET_LAST_ACCESS_DATETIME) ||
(pir->ir_flags == GET_CREATION_DATETIME) )
memcpy( &pLineBuf[idx][9], "Get", 3 );
else memcpy( &pLineBuf[idx][9], "Set", 3 );
i+=AddFileHdl(i); i+=AddResHdl(i);
break;
case IFSFN_DIR:
if ( pir->ir_flags == CREATE_DIR )
memcpy( &pLineBuf[idx][12], "Mk", 2 );
else if ( pir->ir_flags == DELETE_DIR )
memcpy( &pLineBuf[idx][12], "Rd", 2 );
else if ( pir->ir_flags == CHECK_DIR )
memcpy( &pLineBuf[idx][12], "Ck", 2 );
else memcpy( &pLineBuf[idx][11], "Qry", 3 );
i+=SkpFileHdl(i); i+=AddResHdl(i);
AddUniPath(i,80);
break;
case IFSFN_OPEN:
i+=AddFileHdl(i); i+=AddResHdl(i);
AddUniPath(i,80);
if ( pir->ir_options == ACTION_CREATED )
memcpy( &pLineBuf[idx][11], "Create", 6 );
break;
case IFSFN_DISCONNECT: case IFSFN_FLUSH:
case IFSFN_GETDISKINFO: case IFSFN_GETDISKPARMS:
case IFSFN_DASDIO:
i+=SkpFileHdl(i); AddResHdl(i);
break;
}
_asm pushfd
_asm cli
*pdw = idx; /* last completed line */
_asm popfd
return retc; /* make sure we return what the FSD did */
}
void __declspec( naked ) DisplayFSDEvent( void ) {
_asm push ebp _asm mov ebp,esp
hTimeOut = 0;
if ( hEventRing0 != 0 ) {
_asm mov ebx,[hSysVM]
_asm mov esi,offset SetWin32Event
_asm mov edx,offset hEventRing0
VxDCall( Schedule_VM_Event );
_asm mov [hVMEvent],esi
}
_asm leave _asm ret
}
DWORD __stdcall W32_RequestEvents( DWORD dwDDB,
PDIOCPARAMETERS pD )
{
DWORD* pdwArgs;
if ( pdw == NULL ) { /* First time */
/* Check for valid arguments */
if ( pD->cbInBuffer != sizeof(DWORD)*2 )
return 1;
/* Get the parameters passed by the caller */
pdwArgs = (DWORD*)pD->lpvInBuffer;
/* hEventRing0, the handle to the ring 0 event */
hEventRing0 = (HANDLE)pdwArgs[0];
/* First line reserved for pointers */
pdw = (DWORD*)pdwArgs[1];
*pdw = *(pdw+1) = -1;
/* pLineBuf, circular buffer in which to
* store the file activity events */
pLineBuf = ((LINE*)pdwArgs[1])+1;
if (!_LinPageLock((DWORD)pdw>>12,8,PAGEMAPGLOBAL))
return 1; /* lock failed */
}
hTimeOut = Set_Global_Time_Out( DisplayFSDEvent, 250, 0 );
return 0;
}
DWORD __stdcall
W32_Shutdown( DWORD dwDDB, PDIOCPARAMETERS pD ) {
/* Remove our filesystem API hook */
_asm mov eax,OFFSET FileHook
_asm push eax
VxDCall( IFSMgr_RemoveFileSystemApiHook );
_asm add esp,4
return 0;
}
/* Win32 interface for FileMon */
int __stdcall
CtrlMsg_W32DeviceIoControl( DWORD dwIoCtrlCode, /*ecx*/
DWORD dwDDB, /*ebx*/
DWORD pDIOCParams ) /*esi*/
{
if ( dwIoCtrlCode == DIOC_OPEN ||
dwIoCtrlCode == DIOC_CLOSEHANDLE)
return 0L; /* tell Win32, VxD supports DEVIOCTL */
/* private Win32 API provided by FileMon */
if ( dwIoCtrlCode == DIOC_REQEVENTS )
return W32_RequestEvents(dwDDB,(PDIOCPARAMETERS)pDIOCParams);
if ( dwIoCtrlCode == DIOC_SHUTDOWN )
return W32_Shutdown(dwDDB,(PDIOCPARAMETERS)pDIOCParams);
return ERROR_NOT_SUPPORTED;
}
#pragma VxD_PAGEABLE_CODE_SEG
/* Called when device is unloaded */
int __stdcall CleanUp( void ) {
if (hTimeOut) Cancel_Time_Out(hTimeOut);
if (hVMEvent) { _asm mov ebx,[hSysVM]
_asm mov esi,[hVMEvent]
VxDCall(Cancel_VM_Event);
}
if (hEventRing0) { _asm mov eax,[hEventRing0]
VxDCall(_VWIN32_CloseVxDHandle);
}
_LinPageUnlock((DWORD)pdw>>12,8,PAGEMAPGLOBAL);
return(VXD_SUCCESS);
}
/* Called when device is unloaded by VXDLDR */
int __stdcall CtrlMsg_DynDeviceExit( void ) {
return CleanUp();
}
/* Always called when the system is normally shutting down */
int __stdcall
CtrlMsg_SysVMTerminate( DWORD hSysVMHandle ) {
return CleanUp();
}
#pragma VxD_ICODE_SEG
/* Called when Device is loaded by VXDLDR */
int __stdcall CtrlMsg_DynDeviceInit( void ) {
/* Install the filesystem API hook */
hSysVM = Get_Sys_VM_Handle();
_asm mov eax,OFFSET FileHook
_asm push eax
VxDCall( IFSMgr_InstallFileSystemApiHook );
_asm add esp,4
_asm mov ppPrevHook,eax
return( ppPrevHook == 0 ? VXD_FAILURE
: VXD_SUCCESS );
}
/***************** end of file ******************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -