监控目录(300分)(300分)

  • 主题发起人 主题发起人 anson
  • 开始时间 开始时间
A

anson

Unregistered / Unconfirmed
GUEST, unregistred user!
&nbsp; &nbsp;我有一个目录,远端机器随时向这个目录写文件,我需要实时监控这个目录,<br>一旦有文件copy,move,delete,rename等操作,截获此操作,并提示是否取消此操作。<br>我用FindNextChangeNotification ,FindFirstChangeNotification <br>FindCloseChangeNotification,只能监视它,但不能取消它,请各位大侠帮我一下,<br>分数还可以加。
 
试试shell 钩子
 
与查毒功能差不多<br>
 
写驱动啊,我给你一个显成的代码吧!<br>// 司马华鹏<br>//======================================================================<br>//<br>// FILEMON.c - main module for VxD FILEMON<br>//<br>// Copyright (C) 1996-2000 Mark Russinovich and Bryce Cogswell<br>//<br>//======================================================================<br>#define &nbsp; DEVICE_MAIN<br>#include &nbsp;&lt;vtoolsc.h&gt;<br>#include &nbsp;"../exe/ioctlcmd.h"<br>#include &nbsp;"filemon.h"<br>#undef &nbsp; &nbsp;DEVICE_MAIN<br><br>//----------------------------------------------------------------------<br>// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; G L O B A L &nbsp; D A T A <br>//----------------------------------------------------------------------<br><br>//<br>// Indicates if the GUI wants activity to be logged<br>//<br>BOOLEAN &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FilterOn = FALSE;<br><br>//<br>// Global filter (sent to us by the GUI)<br>//<br>FILTER &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;FilterDef;<br><br>//<br>// Array of process and path filters <br>//<br>ULONG &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NumIncludeFilters = 0;<br>PCHAR &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IncludeFilters[MAXFILTERS];<br>ULONG &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NumExcludeFilters = 0;<br>PCHAR &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ExcludeFilters[MAXFILTERS];<br><br>//<br>// Real service pointers with the hook thunks<br>//<br>ppIFSFileHookFunc &nbsp; &nbsp; &nbsp; PrevIFSHookProc;<br><br>//<br>// Hash table data <br>//<br>PHASH_ENTRY &nbsp; &nbsp; &nbsp; &nbsp;HashTable[NUMHASH];<br><br>//<br>// Buffer data<br>//<br>PLOG_BUF &nbsp; &nbsp; &nbsp; &nbsp;Log = NULL;<br>ULONG &nbsp; &nbsp; &nbsp; &nbsp;Sequence = 0;<br><br>//<br>// Maximum amount of buffers we will grab for buffered unread data<br>//<br>ULONG &nbsp; &nbsp; &nbsp; &nbsp;NumLog = 0;<br>ULONG &nbsp; &nbsp; &nbsp; &nbsp;MaxLog = 5;<br><br>//<br>// Semaphore for critical sections<br>//<br>SEMHANDLE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LogMutex, HashMutex, FilterMutex;<br><br>//<br>// Unknown error string<br>//<br>CHAR &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;errstring[32];<br><br>//----------------------------------------------------------------------<br>// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;F O R W A R D S<br>//----------------------------------------------------------------------<br><br>BOOLEAN<br>ApplyFilters(<br>&nbsp; &nbsp; PCHAR Text<br>&nbsp; &nbsp; );<br><br>//----------------------------------------------------------------------<br>// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; V X D &nbsp;C O N T R O L<br>//----------------------------------------------------------------------<br><br>//<br>// Device declaration<br>//<br>Declare_Virtual_Device(FILEMON)<br><br>//<br>// Message handlers - we only care about dynamic loading and unloading<br>//<br>DefineControlHandler(SYS_DYNAMIC_DEVICE_INIT, OnSysDynamicDeviceInit);<br>DefineControlHandler(SYS_DYNAMIC_DEVICE_EXIT, OnSysDynamicDeviceExit);<br>DefineControlHandler(W32_DEVICEIOCONTROL, OnW32Deviceiocontrol);<br><br><br>//----------------------------------------------------------------------<br>// <br>// ControlDispatcher<br>//<br>// Multiplexes incoming VxD messages from Windows to their handlers.<br>//<br>//----------------------------------------------------------------------<br>BOOL <br>__cdecl ControlDispatcher(<br>&nbsp; &nbsp; DWORD dwControlMessage,<br>&nbsp; &nbsp; DWORD EBX,<br>&nbsp; &nbsp; DWORD EDX,<br>&nbsp; &nbsp; DWORD ESI,<br>&nbsp; &nbsp; DWORD EDI,<br>&nbsp; &nbsp; DWORD ECX<br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; START_CONTROL_DISPATCH<br><br>&nbsp; &nbsp; &nbsp; &nbsp; ON_W32_DEVICEIOCONTROL(OnW32Deviceiocontrol);<br>&nbsp; &nbsp; &nbsp; &nbsp; ON_SYS_DYNAMIC_DEVICE_INIT(OnSysDynamicDeviceInit);<br>&nbsp; &nbsp; &nbsp; &nbsp; ON_SYS_DYNAMIC_DEVICE_EXIT(OnSysDynamicDeviceExit);<br><br>&nbsp; &nbsp; END_CONTROL_DISPATCH<br><br>&nbsp; &nbsp; return TRUE;<br>}<br><br>//----------------------------------------------------------------------<br>// &nbsp; &nbsp; &nbsp;P A T T E R N &nbsp; M A T C H I N G &nbsp; R O U T I N E S<br>//----------------------------------------------------------------------<br><br><br>//----------------------------------------------------------------------<br>//<br>// MatchOkay<br>//<br>// Only thing left after compare is more mask. This routine makes<br>// sure that its a valid wild card ending so that its really a match.<br>//<br>//----------------------------------------------------------------------<br>BOOLEAN <br>MatchOkay( <br>&nbsp; &nbsp; PCHAR Pattern <br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // If pattern isn't empty, it must be a wildcard<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; if( *Pattern &amp;&amp; *Pattern != '*' ) {<br>&nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; return FALSE;<br>&nbsp; &nbsp; }<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Matched<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; return TRUE;<br>}<br><br><br>//----------------------------------------------------------------------<br>//<br>// MatchWithPattern<br>//<br>// Performs nifty wildcard comparison.<br>//<br>//----------------------------------------------------------------------<br>BOOLEAN <br>MatchWithPattern( <br>&nbsp; &nbsp; PCHAR Pattern, <br>&nbsp; &nbsp; PCHAR Name <br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; CHAR &nbsp; upcase;<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // End of pattern?<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; if( !*Pattern ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; return FALSE;<br>&nbsp; &nbsp; }<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // If we hit a wild card, do recursion<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; if( *Pattern == '*' ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; Pattern++;<br><br>&nbsp; &nbsp; &nbsp; &nbsp; while( *Name &amp;&amp; *Pattern ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( *Name &gt;= 'a' &amp;&amp; *Name &lt;= 'z' )<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; upcase = *Name - 'a' + 'A';<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; upcase = *Name;<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // See if this substring matches<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( *Pattern == upcase || *Name == '*' ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( MatchWithPattern( Pattern+1, Name+1 )) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return TRUE;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Try the next substring<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Name++;<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br><br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; // See if match condition was met<br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; return MatchOkay( Pattern );<br>&nbsp; &nbsp; } <br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Do straight compare until we hit a wild card<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; while( *Name &amp;&amp; *Pattern != '*' ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; if( *Name &gt;= 'a' &amp;&amp; *Name &lt;= 'z' )<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; upcase = *Name - 'a' + 'A';<br>&nbsp; &nbsp; &nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; upcase = *Name;<br><br>&nbsp; &nbsp; &nbsp; &nbsp; if( *Pattern == upcase ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Pattern++;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Name++;<br><br>&nbsp; &nbsp; &nbsp; &nbsp; } else {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return FALSE;<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; }<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // If not done, recurse<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; if( *Name ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; return MatchWithPattern( Pattern, Name );<br>&nbsp; &nbsp; }<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Make sure its a match<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; return MatchOkay( Pattern );<br>}<br><br>//----------------------------------------------------------------------<br>// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;B U F F E R &nbsp; M A N A G E M E N T<br>//----------------------------------------------------------------------<br><br>//----------------------------------------------------------------------<br>//<br>// FilemonFreeLog<br>//<br>// Frees all the data output buffers that we have currently allocated.<br>//<br>//----------------------------------------------------------------------<br>VOID <br>FilemonFreeLog(<br>&nbsp; &nbsp; VOID <br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; PLOG_BUF prev;<br>&nbsp; &nbsp; <br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Just traverse the list of allocated output buffers<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; while( Log ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; prev = Log-&gt;Next;<br>&nbsp; &nbsp; &nbsp; &nbsp; PageFree( Log-&gt;Handle, 0 );<br>&nbsp; &nbsp; &nbsp; &nbsp; Log = prev;<br>&nbsp; &nbsp; }<br>} <br><br><br>//----------------------------------------------------------------------<br>//<br>// FilemonNewLog<br>//<br>// Called when the current buffer has filled up. This moves us to the<br>// pre-allocated buffer and then allocates another buffer.<br>//<br>// Returns FALSE if another thread is already allocating a buffer.<br>//<br>//----------------------------------------------------------------------<br>BOOLEAN <br>FilemonNewLog( VOID <br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; PLOG_BUF prev = Log, newLog;<br>&nbsp; &nbsp; static busyAllocating = FALSE;<br>&nbsp; &nbsp; MEMHANDLE hNewLog;<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // If we have maxed out or haven't accessed the current Log<br>&nbsp; &nbsp; // just return.<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; if( MaxLog == NumLog ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; Log-&gt;Len = 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; return TRUE; <br>&nbsp; &nbsp; }<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // If the output buffer we currently are using is empty, just<br>&nbsp; &nbsp; // use it, or if we are busy already allocating a buffer, return<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; if( !Log-&gt;Len || busyAllocating ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; return !busyAllocating;<br>&nbsp; &nbsp; }<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Allocate a new output buffer. Release lock to prevent deadlock<br>&nbsp; &nbsp; // on reentrance (allocating memory can result in file I/O)<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; busyAllocating = TRUE;<br>&nbsp; &nbsp; dprintf("Pageallocate: num:%d/n", NumLog );<br>&nbsp; &nbsp; Signal_Semaphore( LogMutex );<br><br>&nbsp; &nbsp; PageAllocate(LOGBUFPAGES, PG_SYS, 0, 0, 0, 0, NULL, PAGELOCKED, <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(PMEMHANDLE) &amp;hNewLog, (PVOID) &amp;newLog );<br><br>&nbsp; &nbsp; Wait_Semaphore( LogMutex, BLOCK_SVC_INTS );<br>&nbsp; &nbsp; dprintf("Pageallocate done: num:%d/n", NumLog );<br>&nbsp; &nbsp; busyAllocating = FALSE;<br><br>&nbsp; &nbsp; if( newLog ) { <br><br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; // Allocation was successful so add the buffer to the list<br>&nbsp; &nbsp; &nbsp; &nbsp; // of allocated buffers and increment the buffer count.<br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; Log &nbsp; &nbsp; &nbsp; = newLog;<br>&nbsp; &nbsp; &nbsp; &nbsp; Log-&gt;Handle = hNewLog;<br>&nbsp; &nbsp; &nbsp; &nbsp; Log-&gt;Len &nbsp;= 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; Log-&gt;Next = prev;<br>&nbsp; &nbsp; &nbsp; &nbsp; NumLog++;<br><br>&nbsp; &nbsp; } else {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; // The allocation failed - just reuse the current buffer<br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; Log-&gt;Len = 0;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; return TRUE;<br>}<br><br><br>//----------------------------------------------------------------------<br>//<br>// FilemonOldestLog<br>//<br>// Goes through the linked list of storage buffers and returns the <br>// oldest one.<br>//<br>//----------------------------------------------------------------------<br>PLOG_BUF <br>FilemonOldestLog( <br>&nbsp; &nbsp; VOID<br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; PLOG_BUF &nbsp;ptr = Log, prev = NULL;<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Traverse the list<br>&nbsp; &nbsp; // &nbsp; &nbsp;<br>&nbsp; &nbsp; while ( ptr-&gt;Next ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; ptr = (prev = ptr)-&gt;Next;<br>&nbsp; &nbsp; }<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Remove the buffer from the list<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; if ( prev ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; prev-&gt;Next = NULL; &nbsp; &nbsp;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; NumLog--;<br>&nbsp; &nbsp; return ptr;<br>}<br><br><br>//----------------------------------------------------------------------<br>//<br>// FilemonResetLog<br>//<br>// When a GUI is no longer communicating with us, but we can't unload,<br>// we reset the storage buffers.<br>//<br>//----------------------------------------------------------------------<br>VOID <br>FilemonResetLog(<br>&nbsp; &nbsp; VOID<br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; PLOG_BUF &nbsp;current, next;<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Traverse the list of output buffers<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; current = Log-&gt;Next;<br>&nbsp; &nbsp; while( current ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; // Free the buffer<br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; next = current-&gt;Next;<br>&nbsp; &nbsp; &nbsp; &nbsp; PageFree( current-&gt;Handle, 0 );<br>&nbsp; &nbsp; &nbsp; &nbsp; current = next;<br>&nbsp; &nbsp; }<br><br>&nbsp; &nbsp; // <br>&nbsp; &nbsp; // Move the output pointer in the buffer that's being kept<br>&nbsp; &nbsp; // the start of the buffer.<br>&nbsp; &nbsp; // <br>&nbsp; &nbsp; Log-&gt;Len = 0;<br>&nbsp; &nbsp; Log-&gt;Next = NULL;<br>}<br><br><br>//----------------------------------------------------------------------<br>//<br>// LogRecord<br>//<br>// Add a new string to Log, if it fits.<br>//<br>//----------------------------------------------------------------------<br>VOID <br>LogRecord( <br>&nbsp; &nbsp; ULONG time, <br>&nbsp; &nbsp; ULONG datetimelo,<br>&nbsp; &nbsp; ULONG datetimehi,<br>&nbsp; &nbsp; const char *format, <br>&nbsp; &nbsp; ... <br>&nbsp; &nbsp; )<br>{ <br>&nbsp; &nbsp; PENTRY Entry;<br>&nbsp; &nbsp; ULONG len;<br>&nbsp; &nbsp; va_list arg_ptr;<br>&nbsp; &nbsp; static CHAR text[MAXPATHLEN*3];<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // If no filtering is desired, don't bother<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; if( !FilterOn ) {<br>&nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; return;<br>&nbsp; &nbsp; }<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Lock the output buffer.<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; Wait_Semaphore( LogMutex, BLOCK_SVC_INTS );<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Vsprintf to determine length of the buffer<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; _asm cld;<br>&nbsp; &nbsp; va_start( arg_ptr, format );<br>&nbsp; &nbsp; len = vsprintf( text, format, arg_ptr );<br>&nbsp; &nbsp; va_end( arg_ptr );<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Only log it if the text passes the filters<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; if( ApplyFilters( text )) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; // If the current output buffer is near capacity, move to a new<br>&nbsp; &nbsp; &nbsp; &nbsp; // output buffer<br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; if( (ULONG) (Log-&gt;Len + len + sizeof(ENTRY) +1) &gt;= LOGBUFSIZE ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( !FilemonNewLog() ) {<br>&nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Just return if a thread is in the process<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // of allocating a buffer.<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Signal_Semaphore( LogMutex );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; } <br><br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; // Extract the sequence number and Log it<br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; Entry = (void *)(Log-&gt;Data+Log-&gt;Len);<br>&nbsp; &nbsp; &nbsp; &nbsp; Entry-&gt;seq = Sequence++;<br>&nbsp; &nbsp; &nbsp; &nbsp; Entry-&gt;perftime.u.LowPart = time;<br>&nbsp; &nbsp; &nbsp; &nbsp; Entry-&gt;perftime.u.HighPart = 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; Entry-&gt;datetime.u.HighPart = datetimehi;<br>&nbsp; &nbsp; &nbsp; &nbsp; Entry-&gt;datetime.u.LowPart &nbsp;= datetimelo;<br>&nbsp; &nbsp; &nbsp; &nbsp; _asm cld;<br>&nbsp; &nbsp; &nbsp; &nbsp; memcpy( Entry-&gt;text, text, len + 1 );<br>&nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; // Log the length of the string, plus 1 for the terminating<br>&nbsp; &nbsp; &nbsp; &nbsp; // NULL &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; // &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; Log-&gt;Len += (Entry-&gt;text - (PCHAR) Entry) + len + 1;<br>&nbsp; &nbsp; }<br>&nbsp;<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Release the output buffer lock<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; Signal_Semaphore( LogMutex );<br>}<br><br>//----------------------------------------------------------------------<br>// &nbsp; &nbsp; &nbsp; H A S H &nbsp; T A B L E &nbsp; M A N A G E M E N T<br>//----------------------------------------------------------------------<br><br>//----------------------------------------------------------------------<br>//<br>// FilemonHashCleanup<br>//<br>// Called when we are unloading to free any memory that we have <br>// in our possession.<br>//<br>//----------------------------------------------------------------------<br>VOID <br>FilemonHashCleanup(<br>&nbsp; &nbsp; VOID<br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; PHASH_ENTRY hashEntry, nextEntry;<br>&nbsp; &nbsp; ULONG &nbsp; &nbsp;i;<br>&nbsp; <br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Free the hash table entries<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; for( i = 0; i &lt; NUMHASH; i++ ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; hashEntry = HashTable;<br>&nbsp; &nbsp; &nbsp; &nbsp; while( hashEntry ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nextEntry = hashEntry-&gt;Next;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HeapFree( hashEntry, 0 );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; hashEntry = nextEntry;<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; }<br>}<br><br>//----------------------------------------------------------------------<br>//<br>// FilemonLogHash<br>//<br>// Logs the key and associated fullpath in the hash table.<br>//<br>//----------------------------------------------------------------------<br>VOID<br>FilemonLogHash( <br>&nbsp; &nbsp; int Drive, <br>&nbsp; &nbsp; fh_t Filenumber, <br>&nbsp; &nbsp; PCHAR Fullname <br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; PHASH_ENTRY &nbsp; &nbsp; newEntry;<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Allocate a new entry<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; newEntry = HeapAllocate( sizeof(HASH_ENTRY) + strlen(Fullname)+1, 0 );<br>&nbsp; &nbsp; if( !newEntry ) return;<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Initialize the new entry.<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; newEntry-&gt;filenumber = Filenumber;<br>&nbsp; &nbsp; newEntry-&gt;drive &nbsp; &nbsp; &nbsp;= Drive &amp; 0xFF;<br>&nbsp; &nbsp; strcpy( newEntry-&gt;FullName, Fullname );<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Lock the hash table and insert the new entry.<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; Wait_Semaphore( HashMutex, BLOCK_SVC_INTS );<br>&nbsp; &nbsp; newEntry-&gt;Next = HashTable[ HASHOBJECT(Filenumber) ];<br>&nbsp; &nbsp; HashTable[ HASHOBJECT(Filenumber) ] = newEntry; <br>&nbsp; &nbsp; Signal_Semaphore( HashMutex );<br>}<br><br><br>//----------------------------------------------------------------------<br>//<br>// FilemonFreeHashEntry<br>//<br>// When we see a file close, we can free the string we had associated<br>// with the fileobject being closed since we know it won't be used<br>// again.<br>//<br>//----------------------------------------------------------------------<br>VOID <br>FilemonFreeHashEntry( <br>&nbsp; &nbsp; int Drive, <br>&nbsp; &nbsp; fh_t Filenumber <br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; PHASH_ENTRY hashEntry, prevEntry;<br><br>&nbsp; &nbsp; Wait_Semaphore( HashMutex, BLOCK_SVC_INTS );<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Look-up the entry.<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; hashEntry = HashTable[ HASHOBJECT( Filenumber ) ];<br>&nbsp; &nbsp; prevEntry = NULL;<br><br>&nbsp; &nbsp; while( hashEntry &amp;&amp; <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;hashEntry-&gt;filenumber != Filenumber &amp;&amp; <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;hashEntry-&gt;drive != (Drive &amp; 0xFF)) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; prevEntry = hashEntry;<br>&nbsp; &nbsp; &nbsp; &nbsp; hashEntry = hashEntry-&gt;Next;<br>&nbsp; &nbsp; }<br><br>&nbsp; &nbsp; // &nbsp;<br>&nbsp; &nbsp; // If we fall of the hash list without finding what we're looking<br>&nbsp; &nbsp; // for, just return.<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; if( !hashEntry ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; Signal_Semaphore( HashMutex );<br>&nbsp; &nbsp; &nbsp; &nbsp; return;<br>&nbsp; &nbsp; }<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Got it! Remove it from the list<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; if( prevEntry ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; prevEntry-&gt;Next = hashEntry-&gt;Next;<br>&nbsp; &nbsp; } else {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; HashTable[ HASHOBJECT( Filenumber )] = hashEntry-&gt;Next;<br>&nbsp; &nbsp; }<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Free the memory associated with the name of the free entry.<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; HeapFree( hashEntry, 0 );<br>&nbsp; &nbsp; Signal_Semaphore( HashMutex );<br>}<br><br>//----------------------------------------------------------------------<br>// &nbsp; &nbsp;F I L T E R &nbsp;A N D &nbsp;P R O C E S S &nbsp;N A M E &nbsp;R O U T I N E S<br>//----------------------------------------------------------------------<br><br>//----------------------------------------------------------------------<br>//<br>// ErrorString<br>//<br>// Returns the string form of an error code.<br>//<br>//----------------------------------------------------------------------<br>PCHAR <br>ErrorString( <br>&nbsp; &nbsp; DWORD retval <br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; switch( retval ) {<br>&nbsp; &nbsp; case ERROR_INVALID_FUNCTION:<br>&nbsp; &nbsp; &nbsp; &nbsp; return "INVALIDFUNC"; <br>&nbsp; &nbsp; case ERROR_SUCCESS:<br>&nbsp; &nbsp; &nbsp; &nbsp; return "SUCCESS";<br>&nbsp; &nbsp; case ERROR_OUTOFMEMORY:<br>&nbsp; &nbsp; &nbsp; &nbsp; return "OUTOFMEM";<br>&nbsp; &nbsp; case ERROR_ACCESS_DENIED:<br>&nbsp; &nbsp; &nbsp; &nbsp; return "ACCDENIED";<br>&nbsp; &nbsp; case ERROR_PATH_NOT_FOUND:<br>&nbsp; &nbsp; &nbsp; &nbsp; return "NOTFOUND";<br>&nbsp; &nbsp; case ERROR_TOO_MANY_OPEN_FILES:<br>&nbsp; &nbsp; &nbsp; &nbsp; return "TOOMANYOPEN";<br>&nbsp; &nbsp; case ERROR_FILE_NOT_FOUND:<br>&nbsp; &nbsp; &nbsp; &nbsp; return "NOTFOUND";<br>&nbsp; &nbsp; case ERROR_NO_MORE_ITEMS:<br>&nbsp; &nbsp; &nbsp; &nbsp; return "NOMORE";<br>&nbsp; &nbsp; case ERROR_GEN_FAILURE:<br>&nbsp; &nbsp; &nbsp; &nbsp; return "GENFAILURE";<br>&nbsp; &nbsp; case ERROR_MORE_DATA:<br>&nbsp; &nbsp; &nbsp; &nbsp; return "MOREDATA";<br>&nbsp; &nbsp; case ERROR_INVALID_DRIVE:<br>&nbsp; &nbsp; &nbsp; &nbsp; return "INVALIDDRIVE";<br>&nbsp; &nbsp; case ERROR_NOT_SAME_DEVICE:<br>&nbsp; &nbsp; &nbsp; &nbsp; return "DIFFERENTDEVICE";<br>&nbsp; &nbsp; case ERROR_WRITE_PROTECT:<br>&nbsp; &nbsp; &nbsp; &nbsp; return "WRITEPROTECTED";<br>&nbsp; &nbsp; case ERROR_SHARING_VIOLATION:<br>&nbsp; &nbsp; &nbsp; &nbsp; return "SHARING";<br>&nbsp; &nbsp; case ERROR_BAD_UNIT:<br>&nbsp; &nbsp; &nbsp; &nbsp; return "BADUNIT";<br>&nbsp; &nbsp; case ERROR_NOT_READY:<br>&nbsp; &nbsp; &nbsp; &nbsp; return "NOTREADY";<br>&nbsp; &nbsp; case ERROR_NO_MORE_FILES:<br>&nbsp; &nbsp; &nbsp; &nbsp; return "NOMORE";<br>&nbsp; &nbsp; case ERROR_BAD_COMMAND:<br>&nbsp; &nbsp; &nbsp; &nbsp; return "BADCOMMAND";<br>&nbsp; &nbsp; case ERROR_INVALID_HANDLE:<br>&nbsp; &nbsp; &nbsp; &nbsp; return "INVALIDHANDLE";<br>&nbsp; &nbsp; case ERROR_DEV_NOT_EXIST:<br>&nbsp; &nbsp; &nbsp; &nbsp; return "DEVDOESNOTEXIST";<br>&nbsp; &nbsp; default:<br>&nbsp; &nbsp; &nbsp; &nbsp; sprintf(errstring, "0x%x", retval );<br>&nbsp; &nbsp; &nbsp; &nbsp; return errstring;<br>&nbsp; &nbsp; }<br>}<br><br><br>//----------------------------------------------------------------------<br>//<br>// FilemonFreeFilters<br>//<br>// Fress storage we allocated for filter strings.<br>//<br>//----------------------------------------------------------------------<br>VOID <br>FilemonFreeFilters(<br>&nbsp; &nbsp; VOID<br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; ULONG &nbsp; i;<br><br>&nbsp; &nbsp; for( i = 0; i &lt; NumIncludeFilters; i++ ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; HeapFree( IncludeFilters, 0 );<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; for( i = 0; i &lt; NumExcludeFilters; i++ ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; HeapFree( ExcludeFilters, 0 );<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; NumIncludeFilters = 0;<br>&nbsp; &nbsp; NumExcludeFilters = 0;<br>}<br><br><br>//----------------------------------------------------------------------<br>//<br>// MakeFilterArray<br>//<br>// Takes a filter string and splits into components (a component<br>// is seperated with a ';')<br>//<br>//----------------------------------------------------------------------<br>VOID <br>MakeFilterArray( <br>&nbsp; &nbsp; PCHAR FilterString,<br>&nbsp; &nbsp; PCHAR FilterArray[],<br>&nbsp; &nbsp; PULONG NumFilters <br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; PCHAR filterStart;<br>&nbsp; &nbsp; ULONG filterLength;<br>&nbsp; &nbsp; CHAR &nbsp;saveChar;<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Scan through the process filters<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; filterStart = FilterString;<br>&nbsp; &nbsp; while( *filterStart ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; filterLength = 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; while( filterStart[filterLength] &amp;&amp;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;filterStart[filterLength] != ';' ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; filterLength++;<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br><br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; // Ignore zero-length components<br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; if( filterLength ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Conservatively allocate so that we can prepend and append<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // wildcards<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FilterArray[ *NumFilters ] = <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HeapAllocate( filterLength + 1 + 2* sizeof('*'), 0 );<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( FilterArray[ *NumFilters ]) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; saveChar = *(filterStart + filterLength );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *(filterStart + filterLength) = 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf( FilterArray[ *NumFilters ], "%s%s%s",<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*filterStart == '*' ? "" : "*",<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;filterStart,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*(filterStart + filterLength - 1 ) == '*' ? "" : "*" );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *(filterStart + filterLength) = saveChar;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (*NumFilters)++;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; // Are we done?<br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; if( !filterStart[filterLength] ) break;<br><br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; // Move to the next component (skip over ';')<br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; filterStart += filterLength + 1;<br>&nbsp; &nbsp; }<br>}<br><br><br>//----------------------------------------------------------------------<br>//<br>// FilemonUpdateFilters<br>//<br>// Takes a new filter specification and updates the filter<br>// arrays with them.<br>//<br>//----------------------------------------------------------------------<br>VOID <br>FilemonUpdateFilters(<br>&nbsp; &nbsp; VOID<br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Free old filters (if any)<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; Wait_Semaphore( FilterMutex, BLOCK_SVC_INTS );<br>&nbsp; &nbsp; FilemonFreeFilters();<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Create new filter arrays<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; MakeFilterArray( FilterDef.includefilter,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;IncludeFilters, &amp;NumIncludeFilters );<br>&nbsp; &nbsp; MakeFilterArray( FilterDef.excludefilter,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ExcludeFilters, &amp;NumExcludeFilters );<br>&nbsp; &nbsp; Signal_Semaphore( FilterMutex );<br>}<br><br><br>//----------------------------------------------------------------------<br>//<br>// wstrlen<br>//<br>// Determine the length of a wide-character string.<br>//<br>//----------------------------------------------------------------------<br>int <br>wstrlen( <br>&nbsp; &nbsp; unsigned short *unistring <br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; int i = 0;<br>&nbsp; &nbsp; int len = 0;<br>&nbsp; <br>&nbsp; &nbsp; while( unistring[i++] != 0 ) len+=2;<br>&nbsp; &nbsp; return len;<br>}<br><br><br>//----------------------------------------------------------------------<br>//<br>// FilmonGetProcess<br>//<br>// Retrieves the process name.<br>//<br>//----------------------------------------------------------------------<br>PCHAR<br>FilemonGetProcess( <br>&nbsp; &nbsp; PCHAR ProcessName <br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; PVOID &nbsp; &nbsp; &nbsp; CurProc;<br>&nbsp; &nbsp; PVOID &nbsp; &nbsp; &nbsp; ring3proc;<br>&nbsp; &nbsp; char &nbsp; &nbsp; &nbsp; &nbsp;*name;<br>&nbsp; &nbsp; ULONG &nbsp; &nbsp; &nbsp; i;<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Get the ring0 process pointer.<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; CurProc = VWIN32_GetCurrentProcessHandle();<br>&nbsp; <br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Now, map the ring3 PCB <br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; ring3proc = (PVOID) SelectorMapFlat( Get_Sys_VM_Handle(), <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(DWORD) (*(PDWORD) ((char *) CurProc + 0x38)) | 0x7, 0 );<br><br>&nbsp; &nbsp; if( ring3proc == (PVOID) -1 ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; strcpy( ProcessName, "???");<br>&nbsp; &nbsp; } else {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; // copy out the process name (max 8 characters)<br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; name = ((char *)ring3proc) + 0xF2;<br>&nbsp; &nbsp; &nbsp; &nbsp; if( name[0] &gt;= 'A' &amp;&amp; name[0] &lt; 'z' ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; strcpy( ProcessName, name );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ProcessName[8] = 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; } else {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; strcpy( ProcessName, "???" );<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; return ProcessName;<br>}<br><br><br>//----------------------------------------------------------------------<br>//<br>// ApplyFilters<br>//<br>// If the name matches the exclusion mask, we do not log it. Else if<br>// it doesn't match the inclusion mask we do not log it. <br>//<br>//----------------------------------------------------------------------<br>BOOLEAN<br>ApplyFilters( <br>&nbsp; &nbsp; PCHAR Text<br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; ULONG &nbsp; &nbsp;i;<br><br>&nbsp; &nbsp; // &nbsp; <br>&nbsp; &nbsp; // If it matches the exclusion string, do not log it<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; Wait_Semaphore( FilterMutex, BLOCK_SVC_INTS );<br>&nbsp; &nbsp; for( i = 0; i &lt; NumExcludeFilters; i++ ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; if( MatchWithPattern( ExcludeFilters, Text ) ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Signal_Semaphore( FilterMutex );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return FALSE;<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; }<br>&nbsp;<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // If it matches an include filter then log it<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; for( i = 0; i &lt; NumIncludeFilters; i++ ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; if( MatchWithPattern( IncludeFilters, Text )) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Signal_Semaphore( FilterMutex );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return TRUE;<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; }<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // It didn't match any include filters so don't log<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; Signal_Semaphore( FilterMutex );<br>&nbsp; &nbsp; return FALSE;<br>}<br><br>//----------------------------------------------------------------------<br>// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; P A T H &nbsp; P A R S I N G<br>//----------------------------------------------------------------------<br><br>//----------------------------------------------------------------------<br>//<br>// FilemonConvertUnparsedPath<br>//<br>// Converts an unparsed unicode path to ANSI. This is only used for<br>// UNC paths except for the special cases of renames and findopens.<br>//<br>//----------------------------------------------------------------------<br>VOID<br>FilemonConvertUnparsedPath(<br>&nbsp; &nbsp; pioreq pir,<br>&nbsp; &nbsp; PCHAR fullpathname<br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; _QWORD &nbsp;result;<br><br>&nbsp; &nbsp; UniToBCS( fullpathname, pir-&gt;ir_upath, wstrlen( pir-&gt;ir_upath ),<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MAXPATHLEN, BCS_WANSI, &amp;result );<br>&nbsp; &nbsp; fullpathname[ result.ddLower ] = 0;<br>}<br><br><br>//----------------------------------------------------------------------<br>//<br>// FilemonConvertParsedPath<br>// <br>// Converts a parsed unicode path to ANSI.<br>//<br>//----------------------------------------------------------------------<br>VOID<br>FilemonConvertParsedPath(<br>&nbsp; &nbsp; int drive,<br>&nbsp; &nbsp; path_t ppath,<br>&nbsp; &nbsp; int codepage,<br>&nbsp; &nbsp; PCHAR fullpathname <br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; int &nbsp;i = 0;<br>&nbsp; &nbsp; _QWORD &nbsp;result;<br><br>&nbsp; &nbsp; if( drive != 0xFF ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; // Its a volume-based path<br>&nbsp; &nbsp; &nbsp; &nbsp; // <br>&nbsp; &nbsp; &nbsp; &nbsp; fullpathname[0] = drive+'A'-1;<br>&nbsp; &nbsp; &nbsp; &nbsp; fullpathname[1] = ':';<br>&nbsp; &nbsp; &nbsp; &nbsp; i = 2;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; fullpathname = 0;<br>&nbsp; &nbsp; UniToBCSPath( &amp;fullpathname, ppath-&gt;pp_elements, <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MAXPATHLEN-1, codepage, &amp;result );<br>&nbsp; &nbsp; fullpathname[ i + result.ddLower ] = 0;<br>}<br><br><br>//----------------------------------------------------------------------<br>//<br>// FilemonConvertMixedPath<br>//<br>// This converts a mix of unparsed and parsed paths to ANSI. The <br>// unparsed path is used for server/share, whereas the parsed<br>// path is used for the directory/file. Only UNC rename and findopen <br>// use this.<br>// <br>//----------------------------------------------------------------------<br>VOID<br>FilemonConvertMixedPath(<br>&nbsp; &nbsp; pioreq pir,<br>&nbsp; &nbsp; path_t ppath,<br>&nbsp; &nbsp; int codepage,<br>&nbsp; &nbsp; PCHAR fullpathname<br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; int &nbsp; &nbsp; i, slashes;<br>&nbsp; &nbsp; _QWORD &nbsp;result;<br><br>&nbsp; &nbsp; UniToBCS( fullpathname, pir-&gt;ir_upath, wstrlen( pir-&gt;ir_upath ), MAXPATHLEN-1,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; codepage, &amp;result );<br>&nbsp; &nbsp; fullpathname[ result.ddLower ] = 0;<br><br>&nbsp; &nbsp; slashes = 0;<br>&nbsp; &nbsp; for( i = 0; i &lt; result.ddLower; i++ ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; // We find the 4th slash: //Server/share/...<br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; if( fullpathname == '//' &amp;&amp; ++slashes == 4 ) break;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; if( slashes == 4 ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; FilemonConvertParsedPath( 0xFF, ppath, codepage, &amp;fullpathname);<br>&nbsp; &nbsp; }<br>}<br><br><br>//----------------------------------------------------------------------<br>//<br>// FilemonConvertPath<br>//<br>// Converts a unicode path name to ANSI.<br>//<br>//----------------------------------------------------------------------<br>PCHAR <br>FilemonConvertPath( <br>&nbsp; &nbsp; CONVERT_TYPE converttype,<br>&nbsp; &nbsp; int drive, <br>&nbsp; &nbsp; pioreq pir,<br>&nbsp; &nbsp; int codepage,<br>&nbsp; &nbsp; PCHAR fullpathname <br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; if( drive != 0xFF ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; // Its a volume-based path<br>&nbsp; &nbsp; &nbsp; &nbsp; // <br>&nbsp; &nbsp; &nbsp; &nbsp; switch( converttype ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; case CONVERT_RENAME_TARGET:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FilemonConvertParsedPath( drive, pir-&gt;ir_ppath2, codepage, fullpathname );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br><br>&nbsp; &nbsp; &nbsp; &nbsp; default:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FilemonConvertParsedPath( drive, pir-&gt;ir_ppath, codepage, fullpathname );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br><br>&nbsp; &nbsp; } else {<br>&nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; // Its a UNC path. The parsed path doesn't include the<br>&nbsp; &nbsp; &nbsp; &nbsp; // server/share, so we get that from the unparsed path.<br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; switch( converttype ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; case CONVERT_STANDARD:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FilemonConvertUnparsedPath( pir, fullpathname );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br><br>&nbsp; &nbsp; &nbsp; &nbsp; case CONVERT_FINDOPEN:<br>&nbsp; &nbsp; &nbsp; &nbsp; case CONVERT_RENAME_SOURCE:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FilemonConvertMixedPath( pir, pir-&gt;ir_ppath, codepage, fullpathname );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br><br>&nbsp; &nbsp; &nbsp; &nbsp; case CONVERT_RENAME_TARGET:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FilemonConvertMixedPath( pir, pir-&gt;ir_ppath2, codepage, fullpathname );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; return fullpathname;<br>}<br><br><br>//----------------------------------------------------------------------<br>//<br>// FilemonGetFullPath<br>//<br>// Returns the full pathname of a file, if we can obtain one, else<br>// returns a handle.<br>//<br>//----------------------------------------------------------------------<br>PCHAR <br>FilemonGetFullPath( &nbsp;<br>&nbsp; &nbsp; fh_t filenumber, <br>&nbsp; &nbsp; PCHAR fullname,<br>&nbsp; &nbsp; int Drive, <br>&nbsp; &nbsp; int ResType, <br>&nbsp; &nbsp; int CodePage, <br>&nbsp; &nbsp; pioreq pir <br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; PHASH_ENTRY hashEntry;<br>&nbsp; &nbsp; pIFSFunc &nbsp; &nbsp; &nbsp; &nbsp;enumFunc;<br>&nbsp; &nbsp; ifsreq &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ifsr;<br>&nbsp; &nbsp; path_t &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;uniFullName;<br>&nbsp; &nbsp; int &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; retval;<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // See if we find the key in the hash table.<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; Wait_Semaphore( HashMutex, BLOCK_SVC_INTS );<br><br>&nbsp; &nbsp; hashEntry = HashTable[ HASHOBJECT( filenumber ) ];<br><br>&nbsp; &nbsp; while( hashEntry &amp;&amp; <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;hashEntry-&gt;filenumber != filenumber &amp;&amp;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;hashEntry-&gt;drive != (Drive &amp; 0xFF)) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; hashEntry = hashEntry-&gt;Next;<br>&nbsp; &nbsp; }<br><br>&nbsp; &nbsp; Signal_Semaphore( HashMutex );<br><br>&nbsp; &nbsp; fullname[0] = 0;<br>&nbsp; &nbsp; if( hashEntry ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; strcpy( fullname, hashEntry-&gt;FullName );<br><br>&nbsp; &nbsp; } else {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; // File name isn't in the table, so ask the<br>&nbsp; &nbsp; &nbsp; &nbsp; // underlying file system<br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; sprintf( fullname, "0x%X", filenumber );<br><br>&nbsp; &nbsp; &nbsp; &nbsp; uniFullName = IFSMgr_GetHeap( MAXPATHLEN * sizeof(WCHAR) + sizeof( path_t));<br>&nbsp; &nbsp; &nbsp; &nbsp; if( uniFullName ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Send a query file name request<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; memcpy( &amp;ifsr, pir, sizeof( ifsreq ));<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ifsr.ifsir.ir_flags = ENUMH_GETFILENAME;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ifsr.ifsir.ir_ppath = uniFullName;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; enumFunc = ifsr.ifs_hndl-&gt;hf_misc-&gt;hm_func[HM_ENUMHANDLE];<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; retval = (*PrevIFSHookProc)(enumFunc, IFSFN_ENUMHANDLE, <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Drive, ResType, CodePage, <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (pioreq) &amp;ifsr);<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( retval == ERROR_SUCCESS ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FilemonConvertParsedPath( Drive, uniFullName, CodePage, fullname );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FilemonLogHash( Drive, filenumber, fullname );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; IFSMgr_RetHeap( (void *) uniFullName );<br>&nbsp; &nbsp; &nbsp; &nbsp; } <br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; return fullname;<br>}<br><br><br>//----------------------------------------------------------------------<br>// &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; H O O K &nbsp; R O U T I N E<br>//----------------------------------------------------------------------<br><br>//----------------------------------------------------------------------<br>//<br>// FilemonHookProc<br>//<br>// All (most) IFS functions come through this routine for us to look<br>// at.<br>//<br>//----------------------------------------------------------------------<br>#pragma optimize("", off)<br>int <br>_cdecl <br>FilemonHookProc(<br>&nbsp; &nbsp; pIFSFunc pfn, <br>&nbsp; &nbsp; int fn, <br>&nbsp; &nbsp; int Drive, <br>&nbsp; &nbsp; int ResType,<br>&nbsp; &nbsp; int CodePage,<br>&nbsp; &nbsp; pioreq pir<br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; int &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;retval;<br>&nbsp; &nbsp; char &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fullpathname[MAXPATHLEN];<br>&nbsp; &nbsp; char &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; processname[64];<br>&nbsp; &nbsp; char &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data[MAXPATHLEN];<br>&nbsp; &nbsp; char &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; drivestring[4];<br>&nbsp; &nbsp; ifsreq &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; origifsr;<br>&nbsp; &nbsp; pioreq &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; origir;<br>&nbsp; &nbsp; _WIN32_FIND_DATA &nbsp; *finddata;<br>&nbsp; &nbsp; struct srch_entry &nbsp;*search;<br>&nbsp; &nbsp; BOOLEAN &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;log;<br>&nbsp; &nbsp; _QWORD &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result;<br>&nbsp; &nbsp; DWORD &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;timelo, timehi;<br>&nbsp; &nbsp; DWORD &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;timelo1, timehi1;<br>&nbsp; &nbsp; DWORD &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;dostime, dosdate;<br>&nbsp; &nbsp; DWORD &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;datetimelo, datetimehi;<br>&nbsp; &nbsp; int &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;i, j;<br><br>&nbsp; &nbsp; // <br>&nbsp; &nbsp; // Inititlize default data.<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; data[0] = 0;<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Save original iorequest because some entries get modified.<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; origir = (pioreq) &amp;origifsr;<br>&nbsp; &nbsp; memcpy( &amp;origifsr, pir, sizeof( ifsreq ));<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Get the current process name.<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; FilemonGetProcess( processname );<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Get the time<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; VTD_Get_Real_Time( &amp;timehi, &amp;timelo );<br>&nbsp; &nbsp; datetimehi = IFSMgr_Get_DOSTime( &amp;datetimelo );<br>&nbsp; &nbsp; dostime = VTD_Get_Date_And_Time( &amp;dosdate );<br>&nbsp; &nbsp; datetimelo = dostime - ((datetimehi &gt;&gt; 11)&amp; 0x1F)*60*60*1000 - <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ((datetimehi &gt;&gt; 5) &amp; 0x3F)*60*1000 - <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ((datetimehi &amp; 0x1F)*2000);<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Special case for close call, since after the file's closed <br>&nbsp; &nbsp; // we can't query its name<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; if( fn == IFSFN_CLOSE ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; FilemonGetFullPath( origir-&gt;ir_fh, fullpathname, Drive, ResType, CodePage, origir );<br>&nbsp; &nbsp; }<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Call the previous hooker first, to get the return code.<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; retval = (*PrevIFSHookProc)(pfn, fn, Drive, ResType, CodePage, pir);<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Now extract parameters based on the function type.<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; dprintf("%d: %d/n", fn, pir-&gt;ir_fh ); <br>&nbsp; &nbsp; switch( fn ) {<br><br>&nbsp; &nbsp; case IFSFN_OPEN:<br><br>&nbsp; &nbsp; &nbsp; &nbsp; FilemonConvertPath( CONVERT_STANDARD, Drive, origir, CodePage, fullpathname );<br><br>&nbsp; &nbsp; &nbsp; &nbsp; TIME_DIFF();<br>&nbsp; &nbsp; &nbsp; &nbsp; sprintf(data,"");<br>&nbsp; &nbsp; &nbsp; &nbsp; if( origir-&gt;ir_options &amp; ACTION_CREATENEW ) strcat(data,"CREATENEW ");<br>&nbsp; &nbsp; &nbsp; &nbsp; if( origir-&gt;ir_options &amp; ACTION_OPENEXISTING ) strcat(data,"OPENEXISTING ");<br>&nbsp; &nbsp; &nbsp; &nbsp; if( origir-&gt;ir_options &amp; ACTION_REPLACEEXISTING ) strcat(data,"REPLACEEXISTING ");<br>&nbsp; &nbsp; &nbsp; &nbsp; switch (origir-&gt;ir_flags &amp; ACCESS_MODE_MASK) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; case ACCESS_READONLY:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; strcat(data,"READONLY ");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; case ACCESS_WRITEONLY:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; strcat(data,"WRITEONLY ");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; case ACCESS_READWRITE:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; strcat(data,"READWRITE ");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; case ACCESS_EXECUTE:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; strcat(data,"EXECUTE ");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; default:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; switch (origir-&gt;ir_flags &amp; SHARE_MODE_MASK) {<br>&nbsp; &nbsp; &nbsp; &nbsp; case SHARE_COMPATIBILITY:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; strcat(data,"COMPATIBILITY ");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; case SHARE_DENYREADWRITE:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; strcat(data,"DENYREADWRITE ");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; case SHARE_DENYWRITE:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; strcat(data,"DENYWRITE ");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; case SHARE_DENYREAD:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; strcat(data,"DENYREAD ");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; case SHARE_DENYNONE:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; strcat(data,"DENYNONE ");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; default:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; LogRecord( timelo, datetimelo, datetimehi, "%s/tOpen/t%s/t%s/t%s", <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;processname, fullpathname,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data, ErrorString( retval ));<br>&nbsp; &nbsp; &nbsp; &nbsp; FilemonLogHash( Drive, pir-&gt;ir_fh, fullpathname );<br>&nbsp; &nbsp; &nbsp; &nbsp; break;<br><br>&nbsp; &nbsp; case IFSFN_READ:<br>&nbsp; &nbsp; case IFSFN_WRITE:<br>&nbsp; &nbsp; &nbsp; &nbsp; FilemonGetFullPath( origir-&gt;ir_fh, fullpathname, Drive, ResType, CodePage, origir );<br>&nbsp; &nbsp; &nbsp; &nbsp; if( ((fn == IFSFN_READ &amp;&amp; FilterDef.logreads ) ||<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(fn == IFSFN_WRITE &amp;&amp; FilterDef.logwrites )) ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TIME_DIFF();<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf( data, "Offset: %ld Length: %ld", origir-&gt;ir_pos, origir-&gt;ir_length );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LogRecord( timelo, datetimelo, datetimehi, "%s/t%s/t%s/t%s/t%s", <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;processname, fn == IFSFN_READ? "Read" : "Write", <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;fullpathname,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data, ErrorString( retval ));<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; break;<br><br>&nbsp; &nbsp; case IFSFN_CLOSE:<br>&nbsp; &nbsp; &nbsp; &nbsp; if( FilterDef.logreads ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TIME_DIFF();<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch( origir-&gt;ir_flags ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case CLOSE_HANDLE: &nbsp; &nbsp; &nbsp;sprintf(data, "CLOSE_HANDLE"); &nbsp; &nbsp; &nbsp;break;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case CLOSE_FOR_PROCESS: sprintf(data, "CLOSE_FOR_PROCESS"); break;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case CLOSE_FINAL: &nbsp; &nbsp; &nbsp; sprintf(data, "CLOSE_FINAL"); &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; default: sprintf(data,"0x%02X",origir-&gt;ir_flags); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LogRecord( timelo, datetimelo, datetimehi, "%s/tClose/t%s/t%s/t%s", processname, <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;fullpathname, data, ErrorString( retval ));<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; if( origir-&gt;ir_flags == CLOSE_FINAL ) FilemonFreeHashEntry( Drive, origir-&gt;ir_fh);<br>&nbsp; &nbsp; &nbsp; &nbsp; break;<br><br>&nbsp; &nbsp; case IFSFN_DIR:<br><br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; // This works around a special case I've seen when hiting the "browse" button in the <br>&nbsp; &nbsp; &nbsp; &nbsp; // "have disk" dialog of the hardware wizard<br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; if( origir-&gt;ir_flags != 0xFF ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FilemonConvertPath( CONVERT_STANDARD, Drive, origir, CodePage, fullpathname );<br><br>&nbsp; &nbsp; &nbsp; &nbsp; } else {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf( fullpathname, "%c:", Drive+'A'-1);<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; TIME_DIFF();<br>&nbsp; &nbsp; &nbsp; &nbsp; log = FALSE;<br>&nbsp; &nbsp; &nbsp; &nbsp; switch( origir-&gt;ir_flags ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; case CREATE_DIR:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data, "CREATE");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( FilterDef.logwrites ) log = TRUE;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; case DELETE_DIR:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data,"DELETE");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( FilterDef.logwrites ) log = TRUE;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; case CHECK_DIR:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data,"CHECK");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( FilterDef.logreads ) log = TRUE;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; default:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data,"QUERY");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( FilterDef.logreads ) log = TRUE;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; if( log ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LogRecord( timelo, datetimelo, datetimehi, "%s/tDirectory/t%s/t%s/t%s", <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;processname, <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;fullpathname,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data, ErrorString( retval ));<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; break;<br><br>&nbsp; &nbsp; case IFSFN_SEEK:<br>&nbsp; &nbsp; &nbsp; &nbsp; FilemonGetFullPath( origir-&gt;ir_fh, fullpathname, Drive, ResType, CodePage, origir );<br>&nbsp; &nbsp; &nbsp; &nbsp; if( FilterDef.logreads) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TIME_DIFF();<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data, "%s Offset: %ld / New offset: %ld",<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; origir-&gt;ir_flags == FILE_BEGIN ? "Beginning" : "End",<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; origir-&gt;ir_pos, origir-&gt;ir_pos ); &nbsp; &nbsp; &nbsp; &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LogRecord( timelo, datetimelo, datetimehi, "%s/tSeek/t%s/t%s/t%s", <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;processname, fullpathname,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data, ErrorString( retval ));<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; break;<br><br>&nbsp; &nbsp; case IFSFN_COMMIT:<br>&nbsp; &nbsp; &nbsp; &nbsp; FilemonGetFullPath( origir-&gt;ir_fh, fullpathname, Drive, ResType, CodePage, origir );<br>&nbsp; &nbsp; &nbsp; &nbsp; if( FilterDef.logwrites) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TIME_DIFF();<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data, "%s", origir-&gt;ir_options == FILE_COMMIT_ASYNC ? <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "ASYNC" : "NOACCESSUPDATE" );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LogRecord( timelo, datetimelo, datetimehi, "%s/tCommit/t%s/t%s/t%s", <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;processname, fullpathname,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data, ErrorString( retval ));<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; break;<br><br>&nbsp; &nbsp; case IFSFN_FILELOCKS:<br>&nbsp; &nbsp; &nbsp; &nbsp; FilemonGetFullPath( origir-&gt;ir_fh, fullpathname, Drive, ResType, CodePage, origir );<br>&nbsp; &nbsp; &nbsp; &nbsp; if( FilterDef.logreads) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TIME_DIFF();<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data, "Offset: %ld Length:%ld", origir-&gt;ir_pos, origir-&gt;ir_locklen );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LogRecord( timelo, datetimelo, datetimehi, "%s/t%s/t%s/t%s/t%s", <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;processname, origir-&gt;ir_flags == LOCK_REGION ? "Lock" : "Unlock",<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;fullpathname,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data, ErrorString( retval ));<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; break;<br><br>&nbsp; &nbsp; case IFSFN_FINDOPEN:<br>&nbsp; &nbsp; &nbsp; &nbsp; if( FilterDef.logreads) { <br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FilemonConvertPath( CONVERT_FINDOPEN, Drive, origir, CodePage, fullpathname );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TIME_DIFF();<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( !retval ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; finddata = (_WIN32_FIND_DATA *) origir-&gt;ir_data;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; UniToBCS( data, finddata-&gt;cFileName, wstrlen(finddata-&gt;cFileName), MAXPATHLEN-1, BCS_WANSI, &amp;result );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data[ result.ddLower ] = 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LogRecord( timelo, datetimelo, datetimehi, "%s/tFindOpen/t%s/t%s/t%s", <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;processname, fullpathname,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data, ErrorString( retval ));<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; FilemonLogHash( Drive, pir-&gt;ir_fh, fullpathname );<br>&nbsp; &nbsp; &nbsp; &nbsp; break;<br><br>&nbsp; &nbsp; case IFSFN_FINDNEXT:<br>&nbsp; &nbsp; &nbsp; &nbsp; FilemonGetFullPath( origir-&gt;ir_fh, fullpathname, Drive, ResType, CodePage, origir );<br>&nbsp; &nbsp; &nbsp; &nbsp; if( FilterDef.logreads) { <br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TIME_DIFF();<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( !retval ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; finddata = (_WIN32_FIND_DATA *) origir-&gt;ir_data;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; UniToBCS( data, finddata-&gt;cFileName, wstrlen(finddata-&gt;cFileName), MAXPATHLEN-1, BCS_WANSI, &amp;result );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data[ result.ddLower ] = 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LogRecord( timelo, datetimelo, datetimehi, "%s/tFindNext/t%s/t%s/t%s", <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;processname, fullpathname,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data, ErrorString( retval ));<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; break;<br><br>&nbsp; &nbsp; case IFSFN_FINDCLOSE:<br>&nbsp; &nbsp; &nbsp; &nbsp; FilemonGetFullPath( origir-&gt;ir_fh, fullpathname, Drive, ResType, CodePage, origir );<br>&nbsp; &nbsp; &nbsp; &nbsp; if( FilterDef.logreads) { <br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TIME_DIFF();<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LogRecord( timelo, datetimelo, datetimehi, "%s/tFindClose/t%s/t/t%s", <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;processname, fullpathname,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ErrorString( retval ));<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; FilemonFreeHashEntry( Drive, origir-&gt;ir_fh );<br>&nbsp; &nbsp; &nbsp; &nbsp; break;<br><br>&nbsp; &nbsp; case IFSFN_FILEATTRIB:<br>&nbsp; &nbsp; &nbsp; &nbsp; if( FilterDef.logreads) { &nbsp; &nbsp;<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FilemonConvertPath( CONVERT_STANDARD, Drive, origir, CodePage, fullpathname );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TIME_DIFF();<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch(origir-&gt;ir_flags ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case GET_ATTRIBUTES:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data,"GetAttributes");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case SET_ATTRIBUTES:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data, "SetAttributes" );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case GET_ATTRIB_COMP_FILESIZE:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data, "GET_ATTRIB_COMP_FILESIZE" );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case SET_ATTRIB_MODIFY_DATETIME:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data, "SET_ATTRIB_MODIFY_DATETIME");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case SET_ATTRIB_LAST_ACCESS_DATETIME:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data, "SET_ATTRIB_LAST_ACCESS_DATETIME");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case GET_ATTRIB_LAST_ACCESS_DATETIME:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data, "GET_ATTRIB_LAST_ACCESS_DATETIME");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case SET_ATTRIB_CREATION_DATETIME:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data, "SET_ATTRIB_CREATION_DATETIME");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case GET_ATTRIB_CREATION_DATETIME:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data, "GET_ATTRIB_CREATION_DATETIME");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LogRecord( timelo, datetimelo, datetimehi, "%s/tAttributes/t%s/t%s/t%s", <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;processname, fullpathname,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data, ErrorString( retval ));<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; break;<br><br>&nbsp; &nbsp; case IFSFN_FILETIMES:<br>&nbsp; &nbsp; &nbsp; &nbsp; FilemonGetFullPath( origir-&gt;ir_fh, fullpathname, Drive, ResType, CodePage, origir );<br>&nbsp; &nbsp; &nbsp; &nbsp; if( FilterDef.logreads) { <br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TIME_DIFF();<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch( origir-&gt;ir_flags ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case GET_MODIFY_DATETIME:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data, "Get Modify");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case SET_MODIFY_DATETIME:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data, "Set Modify");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case GET_LAST_ACCESS_DATETIME:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data, "Get Access");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case SET_LAST_ACCESS_DATETIME:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data, "Set Access");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case GET_CREATION_DATETIME:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data, "Get Creation");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case SET_CREATION_DATETIME:<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data, "Set Creation");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LogRecord( timelo, datetimelo, datetimehi, "%s/tAttributes/t%s/t%s/t%s", <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;processname, fullpathname,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data, ErrorString( retval ));<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; break;<br><br>&nbsp; &nbsp; case IFSFN_FLUSH:<br>&nbsp; &nbsp; &nbsp; &nbsp; if( FilterDef.logwrites) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TIME_DIFF();<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LogRecord( timelo, datetimelo, datetimehi, "%s/tFlushVolume/t/t/t%s",<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;processname, ErrorString( retval ));<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; break;<br><br>&nbsp; &nbsp; case IFSFN_DELETE:<br>&nbsp; &nbsp; &nbsp; &nbsp; if( FilterDef.logwrites) { &nbsp; &nbsp;<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FilemonConvertPath( CONVERT_STANDARD, Drive, origir, CodePage, fullpathname );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TIME_DIFF();<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LogRecord( timelo, datetimelo, datetimehi, "%s/tDelete/t%s/t/t%s", <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;processname, fullpathname, ErrorString( retval ));<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; FilemonFreeHashEntry( Drive, origir-&gt;ir_fh );<br>&nbsp; &nbsp; &nbsp; &nbsp; break;<br><br>&nbsp; &nbsp; case IFSFN_SEARCH:<br>&nbsp; &nbsp; &nbsp; &nbsp; if( FilterDef.logreads ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( origir-&gt;ir_flags == SEARCH_FIRST ) <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FilemonConvertPath( CONVERT_STANDARD, Drive, origir, CodePage, fullpathname );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(fullpathname, "SearchNext" );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TIME_DIFF();<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( !retval ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; j = 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( origir-&gt;ir_attr &amp; FILE_ATTRIBUTE_LABEL ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data, "VolumeLabel: " );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; j = strlen( data );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; search = (struct srch_entry *) origir-&gt;ir_data;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for( i = 0; i &lt; 13; i++ ) <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( search-&gt;se_name != ' ' ) data[j++] = search-&gt;se_name;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data[j] = 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LogRecord( timelo, datetimelo, datetimehi, "%s/tSearch/t%s/t%s/t%s", <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;processname, fullpathname, data, ErrorString( retval )); &nbsp; &nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; <br>&nbsp; &nbsp; case IFSFN_GETDISKINFO:<br><br>&nbsp; &nbsp; &nbsp; &nbsp; if( FilterDef.logreads ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TIME_DIFF();<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if( !retval ) sprintf(data, "Free Space");<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; drivestring[0] = Drive+'A'-1;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; drivestring[1] = ':';<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; drivestring[2] = 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LogRecord( timelo, datetimelo, datetimehi, "%s/tGetDiskInfo/t%s/t%s/t%s",<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;processname, drivestring, data, ErrorString( retval ));<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; break;<br><br>&nbsp; &nbsp; case IFSFN_RENAME:<br>&nbsp; &nbsp; &nbsp; &nbsp; if( FilterDef.logwrites) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FilemonConvertPath( CONVERT_RENAME_SOURCE, Drive, origir, CodePage, fullpathname );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TIME_DIFF();<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LogRecord( timelo, datetimelo, datetimehi, "%s/tRename/t%s/t%s/t%s",<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;processname, fullpathname,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;FilemonConvertPath( CONVERT_RENAME_TARGET, Drive, origir, CodePage, data ),<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ErrorString( retval )); <br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; case IFSFN_IOCTL16DRIVE:<br>&nbsp; &nbsp; &nbsp; &nbsp; if( FilterDef.logreads || FilterDef.logwrites) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TIME_DIFF();<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sprintf(data, "Subfunction: %02Xh", origir-&gt;ir_flags );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; drivestring[0] = Drive+'A'-1;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; drivestring[1] = ':';<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; drivestring[2] = 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LogRecord( timelo, datetimelo, datetimehi, "%s/tIoctl/t%s/t%s/t%s",<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;processname, drivestring, data, ErrorString( retval ));<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; break;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; dprintf("==&gt;%d/n", fn );<br>&nbsp; &nbsp; return retval;<br>}<br>#pragma optimize("", on)<br><br>//----------------------------------------------------------------------<br>//<br>// OnSysDynamicDeviceInit<br>//<br>// Dynamic init. Install a file system filter hook.<br>//<br>//----------------------------------------------------------------------<br>BOOL <br>OnSysDynamicDeviceInit(<br>&nbsp; &nbsp; VOID<br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; int i;<br>&nbsp; &nbsp; MEMHANDLE hLog;<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Initialize the locks.<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; LogMutex = Create_Semaphore(1);<br>&nbsp; &nbsp; HashMutex &nbsp;= Create_Semaphore(1);<br>&nbsp; &nbsp; FilterMutex &nbsp;= Create_Semaphore(1);<br><br>&nbsp; &nbsp; // <br>&nbsp; &nbsp; // Zero hash table.<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; for(i = 0; i &lt; NUMHASH; i++ ) HashTable = NULL;<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Allocate the initial output buffer.<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; PageAllocate(LOGBUFPAGES, PG_SYS, 0, 0, 0, 0, NULL, PAGELOCKED, <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(PMEMHANDLE) &amp;hLog, (PVOID) &amp;Log );<br>&nbsp; &nbsp; Log-&gt;Handle = hLog;<br>&nbsp; &nbsp; Log-&gt;Len = 0;<br>&nbsp; &nbsp; Log-&gt;Next = NULL;<br>&nbsp; &nbsp; NumLog = 1;<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Hook IFS functions.<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; PrevIFSHookProc = IFSMgr_InstallFileSystemApiHook(FilemonHookProc);<br>&nbsp; &nbsp; return TRUE;<br>}<br><br>//----------------------------------------------------------------------<br>//<br>// OnSysDynamicDeviceExit<br>//<br>// Dynamic exit. Unhook everything.<br>//<br>//----------------------------------------------------------------------<br>BOOL <br>OnSysDynamicDeviceExit(<br>&nbsp; &nbsp; VOID<br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Unhook IFS functions.<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; IFSMgr_RemoveFileSystemApiHook(FilemonHookProc);<br><br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; // Free all memory.<br>&nbsp; &nbsp; //<br>&nbsp; &nbsp; FilemonHashCleanup();<br>&nbsp; &nbsp; FilemonFreeLog();<br>&nbsp; &nbsp; FilemonFreeFilters();<br>&nbsp; &nbsp; return TRUE;<br>}<br><br>//----------------------------------------------------------------------<br>//<br>// OnW32Deviceiocontrol<br>//<br>// Interface with the GUI.<br>//<br>//----------------------------------------------------------------------<br>DWORD <br>OnW32Deviceiocontrol(<br>&nbsp; &nbsp; PIOCTLPARAMS p<br>&nbsp; &nbsp; )<br>{<br>&nbsp; &nbsp; PLOG_BUF &nbsp; &nbsp; &nbsp;old;<br><br>&nbsp; &nbsp; switch( p-&gt;dioc_IOCtlCode ) {<br>&nbsp; &nbsp; case 0:<br>&nbsp; &nbsp; &nbsp; &nbsp; return ERROR_SUCCESS;<br><br>&nbsp; &nbsp; case IOCTL_FILEMON_ZEROSTATS:<br><br>&nbsp; &nbsp; &nbsp; &nbsp; Wait_Semaphore( LogMutex, BLOCK_SVC_INTS );<br>&nbsp; &nbsp; &nbsp; &nbsp; while ( Log-&gt;Next ) &nbsp;{<br>&nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Release the next entry.<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; old = Log-&gt;Next;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Log-&gt;Next = old-&gt;Next;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Signal_Semaphore( LogMutex );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PageFree( old-&gt;Handle, 0 );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Wait_Semaphore( LogMutex, BLOCK_SVC_INTS );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NumLog--;<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; Log-&gt;Len = 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; Signal_Semaphore( LogMutex );<br>&nbsp; &nbsp; &nbsp; &nbsp; Sequence = 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; return ERROR_SUCCESS;<br><br>&nbsp; &nbsp; case IOCTL_FILEMON_GETSTATS:<br><br>&nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; // Copy buffer into user space.<br>&nbsp; &nbsp; &nbsp; &nbsp; Wait_Semaphore( LogMutex, BLOCK_SVC_INTS );<br>&nbsp; &nbsp; &nbsp; &nbsp; if ( LOGBUFSIZE &gt; p-&gt;dioc_cbOutBuf ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Buffer is too small. Return error.<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Signal_Semaphore( LogMutex );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return ERROR_INSUFFICIENT_BUFFER;<br><br>&nbsp; &nbsp; &nbsp; &nbsp; } else if ( Log-&gt;Len &nbsp;|| &nbsp;Log-&gt;Next ) {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Switch to a new buffer.<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FilemonNewLog();<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Fetch the oldest buffer to give to caller.<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; old = FilemonOldestLog();<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Signal_Semaphore( LogMutex );<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Copy it into the caller's buffer.<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; memcpy( p-&gt;dioc_OutBuf, old-&gt;Data, old-&gt;Len );<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Return length of copied info.<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *p-&gt;dioc_bytesret = old-&gt;Len;<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // &nbsp; <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Deallocate the buffer.<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PageFree( old-&gt;Handle, 0 );<br><br>&nbsp; &nbsp; &nbsp; &nbsp; } else {<br><br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // There is no unread data.<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Signal_Semaphore( LogMutex );<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *p-&gt;dioc_bytesret = 0;<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; return ERROR_SUCCESS;<br><br>&nbsp; &nbsp; case IOCTL_FILEMON_STOPFILTER:<br><br>&nbsp; &nbsp; &nbsp; &nbsp; FilterOn = FALSE;<br>&nbsp; &nbsp; &nbsp; &nbsp; return ERROR_SUCCESS;<br><br>&nbsp; &nbsp; case IOCTL_FILEMON_STARTFILTER:<br><br>&nbsp; &nbsp; &nbsp; &nbsp; FilterOn = TRUE;<br>&nbsp; &nbsp; &nbsp; &nbsp; return ERROR_SUCCESS;<br><br>&nbsp; &nbsp; case IOCTL_FILEMON_SETFILTER:<br><br>&nbsp; &nbsp; &nbsp; &nbsp; FilterDef = * (PFILTER) p-&gt;dioc_InBuf;<br>&nbsp; &nbsp; &nbsp; &nbsp; FilemonUpdateFilters();<br>&nbsp; &nbsp; &nbsp; &nbsp; return ERROR_SUCCESS;<br><br>&nbsp; &nbsp; default:<br>&nbsp; &nbsp; &nbsp; &nbsp; return ERROR_INVALID_FUNCTION;<br>&nbsp; &nbsp; }<br>}<br>
 
VxD 好象在win2K不能运行
 
可以用WIN的外壳编程的方法实现<br>同时你可以在网上找一个用驱动写的文件保护工具,就上面那个VXD的驱动一起的,有个用于<br>2000的驱动。
 
定个邮件,不求分。
 
我在"delphi5开发人员指南中"找到用WIN的外壳编程,不过只能保护文件夹不能保护文件.如下代码有谁帮我将它改成可以保护文件<br><br><br>****************************************<br>1.扩展windows外壳(例子如下)<br>2.参考一下屏蔽广告软件的源码(我一起有一个,不知道放哪里了)<br>(转)<br>例子<br><br>利用Windows外壳扩展保护文件夹<br><br>在Win32操作系统(包括Win9X、Windows NT、Windows 2000)不但有方便的图形用户(GUI)界面,微软还为windows用户界面保留了强大的可扩充性。其中对于Windows界面的操作环境(这里称为外壳Shell),微软提供了一种称为外壳扩展(Shell Extensions)的功能来实现文件系统操作的可编程性。如果你的机器中安装了Word 7.0以上的版本,当你鼠标右键单击一个DOC文件,在弹出菜单中选“属性”项,在属性页中不仅显示显示文件的大小、建立日期等信息,同时还增加了Doc文档的摘要、统计等信息;又例如安装了winZip 6.0以上版本后,当选中一个或多个文件或文件夹后在单击鼠标右键,在弹出的右键菜单中就增加了“Add To Zip”等一个zip文件压缩选项。上面的这些功能都是通过Windows外壳扩展来实现的。<br><br>Windows外壳扩展是这样实现的。首先要编写外壳扩展程序,一个外壳扩展程序是基于COM(Component Object Model)组件模型的。外壳是通过接口(Interface)来访问对象的。外壳扩展被设计成32位的进程中服务器程序,并且都是以动态链接库的形式为操作系统提供服务的。<br><br>写好外壳扩展程序后,必须将它们注册才能生效。所有的外壳扩展都必须在Windows注册表的HKEY_CLASSES_ROOT/CLSID键之下进行注册。在该键下面可以找到许多名字像{ACDE002F-0000-0000-C000-000000000046}的键,这类键就是全局唯一类标识符。每一个外壳扩展都必须有一个全局唯一类标识符,Windows正是通过此唯一类标识符来找到外壳扩展处理程序的。在类标识符之下的InProcServer32子键下记录着外壳扩展动态链接库在系统中的位置。<br><br>&nbsp;<br><br>Windows系统支持以下7类的外壳扩展功能:<br><br>(1)Context menu handlers向特定类型的文件对象增添上下文相关菜单; <br><br>(2)Drag-and-drop handlers用来支持当用户对某种类型的文件对象进行拖放操作时的OLE数据传输; <br><br>(3)Icon handlers用来向某个文件对象提供一个特有的图标,也可以给某一类文件对象指定图标; <br><br>(4)Property sheet handlers给文件对象增添属性页,属性页可以为同一类文件对象所共有,也可以给一个文件对象指定特有的属性页; <br><br>(5)Copy-hook handlers在文件夹对象或者打印机对象被拷贝、移动、删除和重命名时,就会被系统调用,通过为Windows增加Copy-hook handlers,可以允许或者禁止其中的某些操作; <br><br>(6)Drop target handlers在一个对象被拖放到另一个对象上时,就会被系统被调用; <br><br>(7)Data object handlers在文件被拖放、拷贝或者粘贴时,就会被系统被调用。<br><br>本文介绍的文件夹保护功能就是通过上面的第5类,既Copy-hook handlers来实现的。一个支持Copy-hook handlers的程序除了上面提到的要在注册表的HKEY_CLASSES_ROOT/CLSID下注册之外,还需要在HKEY_CLASSES_ROOT/Directory/shellex/CopyHookHandlers/下注册服务器程序的类。<br><br>由于Windows外壳服务器程序是基于COM组件模型的,所以编写外壳程序就是构造一个COM对象的过程,由于Delphi4.0以上的版本支持Windows外壳扩展和COM组件模型,所以可以利用Delphi来编写外壳扩展程序。<br><br>利用Delphi编写Copy-hook handle需要实现ICopyHook接口。ICopyHook是一个十分简单的接口,要实现的只有CopyCallBack方法。ICopyHook的CopyCallBack方法的定义如下:<br><br>UINT CopyCallback(<br><br>&nbsp; HWND hwnd, file://Handle of the parent window for displaying UI objects<br><br>&nbsp; UINT wFunc, file://Operation to perform.<br><br>&nbsp; UINT wFlags, file://Flags that control the operation<br><br>&nbsp; LPCSTR pszSrcFile, file://Pointer to the source file<br><br>&nbsp; DWORD dwSrcAttribs, file://Source file attributes<br><br>&nbsp; LPCSTR pszDestFile, file://Pointer to the destination file<br><br>&nbsp; DWORD dwDestAttribs file://Destination file attributes<br><br>&nbsp; );<br><br>其中的参数hwnd是一个窗口句柄,Copy-hook handle以此为父窗口。参数wFunc指定要被执行的操作,其取值为下表中所列之一:<br><br>常量 取值 含义<br><br>FO_COPY $2 复制由pszSrcFile指定的文件到由pszDestFile指定的位置。<br><br>FO_DELETE $3 删除由pszSrcFile指定的文件。<br><br>FO_MOVE $1 移动由pszSrcFile指定的文件到由pszDestFile指定的位置。<br><br>FO_RENAME $4 重命名由pszSrcFile指定的文件到由pszDestFile指定的文件名。<br><br>PO_DELETE $13 删除pszSrcFile指定的打印机。<br><br>PO_PORTCHANGE $20 改变打印机端口。PszSrcFile和pszDestFile为两个以Null结尾的字符串,分别指定当前和新的打印机端口名。<br><br>PO_RENAME $14 重命名由pszSrcFile指定的打印机端口。<br><br>PO_REN_PORT $34 PO_RENAME和PO_PORTCHANGE的组合。<br><br>&nbsp;<br><br>&nbsp;参数wFlags指定操作的标志;参数pszSrcFile和pszDestFile指定源文件夹和目标文件夹。参数dwSrcAttribs和dwDesAttribs指定源文件夹和目标文件夹的属性。函数返回值可以为IDYES、IDNO和IDCANCEL。分别指示Windows外壳允许操作、阻止操作,但是其他操作继续、阻止当前操作,取消为执行的操作。<br><br>&nbsp;下面是具体的程序实现:<br><br>&nbsp;首先在Delphi的菜单中选 File|New选项,选择其中的DLL图标,按Ok键建立一个DLL工程文件,在其中添加以下代码:<br><br>library CopyHook;<br><br>&nbsp;<br><br>uses<br><br>&nbsp; ComServ,<br><br>&nbsp; CopyMain in 'CopyMain.pas';<br><br>&nbsp;<br><br>exports<br><br>&nbsp; DllGetClassObject,<br><br>&nbsp; DllCanUnloadNow,<br><br>&nbsp; DllRegisterServer,<br><br>&nbsp; DllUnregisterServer;<br><br>&nbsp;<br><br>{$R *.TLB}<br><br>&nbsp;<br><br>{$R *.RES}<br><br>&nbsp;<br><br>begin<br><br>end.<br><br>将文件保存为 CopyHook.dpr。再在Delphi菜单中选File|New选项,选择其中的Unit图标,按Ok键建立一个Pas文件,在其中加入以下代码:<br><br>unit CopyMain;<br><br>&nbsp;<br><br>interface<br><br>&nbsp;<br><br>uses Windows, ComObj, ShlObj;<br><br>&nbsp;<br><br>type<br><br>&nbsp; TCopyHook = class(TComObject, ICopyHook)<br><br>&nbsp; protected<br><br>&nbsp; function CopyCallback(Wnd: HWND; wFunc, wFlags: UINT; pszSrcFile: PAnsiChar;<br><br>&nbsp; dwSrcAttribs: DWORD; pszDestFile: PAnsiChar; dwDestAttribs: DWORD): UINT; stdcall;<br><br>&nbsp; end;<br><br>&nbsp;<br><br>&nbsp; TCopyHookFactory = class(TComObjectFactory)<br><br>&nbsp; protected<br><br>&nbsp; function GetProgID: string; override;<br><br>&nbsp; procedure ApproveShellExtension(Register: Boolean; const ClsID: string);<br><br>&nbsp; virtual;<br><br>&nbsp; public<br><br>&nbsp; procedure UpdateRegistry(Register: Boolean); override;<br><br>&nbsp; end;<br><br>&nbsp;<br><br>implementation<br><br>&nbsp;<br><br>uses ComServ, SysUtils, Registry;<br><br>&nbsp;<br><br>{ TCopyHook }<br><br>&nbsp;<br><br>file://当Windows外壳程序执行文件夹或者打印机端口操作时,CopyCallBack<br><br>file://方法就会被调用。<br><br>function TCopyHook.CopyCallback(Wnd: HWND; wFunc, wFlags: UINT;<br><br>&nbsp; pszSrcFile: PAnsiChar; dwSrcAttribs: DWORD; pszDestFile: PAnsiChar;<br><br>&nbsp; dwDestAttribs: DWORD): UINT;<br><br>const<br><br>&nbsp; FO_COPY = 2;<br><br>&nbsp; FO_DELETE = 3;<br><br>&nbsp; FO_MOVE = 1;<br><br>&nbsp; FO_RENAME = 4;<br><br>var<br><br>&nbsp; sOp:string;<br><br>begin<br><br>&nbsp; Case wFunc of<br><br>&nbsp; FO_COPY: sOp:=format('你确定要将 %s 拷贝到 %s 吗?',[pszSrcFile,pszDestFile]);<br><br>&nbsp; FO_DELETE: sOp:=format('你确定要将 %s 删除吗?',[pszSrcFile]);<br><br>&nbsp; FO_MOVE: sOp:=format('你确定要将 %s 转移到 %s 吗?',[pszSrcFile,pszDestFile]);<br><br>&nbsp; FO_RENAME: sOp:=format('你确定要将 %s 重命名为 %s 吗?',[pszSrcFile,pszDestFile]);<br><br>&nbsp; else<br><br>&nbsp; sOp:=format('无法识别的操作代码 %d',[wFlags]);<br><br>&nbsp; end;<br><br>&nbsp; // 提示,让用户决定是否执行操作<br><br>&nbsp; Result := MessageBox(Wnd, PChar(sOp),<br><br>&nbsp; '文件挂钩演示', MB_YESNOCANCEL);<br><br>end;<br><br>&nbsp;<br><br>{ TCopyHookFactory }<br><br>&nbsp;<br><br>function TCopyHookFactory.GetProgID: string;<br><br>begin<br><br>&nbsp; Result := '';<br><br>end;<br><br>&nbsp;<br><br>procedure TCopyHookFactory.UpdateRegistry(Register: Boolean);<br><br>var<br><br>&nbsp; ClsID: string;<br><br>begin<br><br>&nbsp; ClsID := GUIDToString(ClassID);<br><br>&nbsp; inherited UpdateRegistry(Register);<br><br>&nbsp; ApproveShellExtension(Register, ClsID);<br><br>&nbsp; if Register then<br><br>&nbsp; file://将clsid 加入到注册表的CopyHookHandlers中<br><br>&nbsp; CreateRegKey('directory/shellex/CopyHookHandlers/' + ClassName, '',<br><br>&nbsp; ClsID)<br><br>&nbsp; else<br><br>&nbsp; DeleteRegKey('directory/shellex/CopyHookHandlers/' + ClassName);<br><br>end;<br><br>&nbsp;<br><br>procedure TCopyHookFactory.ApproveShellExtension(Register: Boolean;<br><br>&nbsp; const ClsID: string);<br><br>const<br><br>&nbsp; SApproveKey = 'SOFTWARE/Microsoft/Windows/CurrentVersion/Shell Extensions/Approved';<br><br>begin<br><br>&nbsp; with TRegistry.Create do<br><br>&nbsp; try<br><br>&nbsp; RootKey := HKEY_LOCAL_MACHINE;<br><br>&nbsp; if not OpenKey(SApproveKey, True) then Exit;<br><br>&nbsp; if Register then WriteString(ClsID, Description)<br><br>&nbsp; else DeleteValue(ClsID);<br><br>&nbsp; finally<br><br>&nbsp; Free;<br><br>&nbsp; end;<br><br>end;<br><br>&nbsp;<br><br>const<br><br>&nbsp; CLSID_CopyHook: TGUID = '{66CD5F60-A044-11D0-A9BF-00A024E3867F}';<br><br>&nbsp; LIBID_CopyHook: TGUID = '{D2F531A0-0861-11D2-AE5C-74640BC10000}';<br><br>&nbsp;<br><br>initialization<br><br>&nbsp; TCopyHookFactory.Create(ComServer, TCopyHook, CLSID_CopyHook,<br><br>&nbsp; 'CR_CopyHook', '文件操作挂钩演示',ciMultiInstance, tmApartment);<br><br>end.<br>
 
这些什么钩子之类的东东全部没用。我也一直想找一个,但老是找不到。<br>哪位高高高高手能够实现下面功能才真的好:<br><br>1、打开(进入)一个目录之前(windows中可能双击,也可能单击,也可以在DOS下,地址<br>栏中键入,打开文件对话框中查看进入。。。。。等等),要完全的控制死,任何想进入该<br>目录的动作之前,都要弹出输入密码进行身份确认。<br>2、即使被拿到另一台机器当副盘,也要一样进不去。<br><br>这在windows2000中怎么也做不到,哪位高手能行,出钱我也肯。<br>
 
有谁会用LockFile和LockFileEX来锁定一个文件
 
BOOL LockFile(<br>&nbsp; &nbsp; HANDLE hFile, // handle of file to lock <br>&nbsp; &nbsp; DWORD dwFileOffsetLow, // low-order word of lock region offset <br>&nbsp; &nbsp; DWORD dwFileOffsetHigh, // high-order word of lock region offset &nbsp;<br>&nbsp; &nbsp; DWORD nNumberOfBytesToLockLow, // low-order word of length to lock <br>&nbsp; &nbsp; DWORD nNumberOfBytesToLockHigh // high-order word of length to lock <br>&nbsp; &nbsp;); <br>Parameters<br>hFile<br>Identifies the file with a region to be locked. The file handle must have been created with GENERIC_READ or GENERIC_WRITE access to the file (or both). <br>dwFileOffsetLow<br>Specifies the low-order word of the starting byte offset in the file where the lock should begin. <br>dwFileOffsetHigh<br>Specifies the high-order word of the starting byte offset in the file where the lock should begin. <br>nNumberOfBytesToLockLow<br>Specifies the low-order word of the length of the byte range to be locked. <br>nNumberOfBytesToLockHigh<br>Specifies the high-order word of the length of the byte range to be locked. <br>Return Values<br>If the function succeeds, the return value is nonzero.<br>If the function fails, the return value is zero. To get extended error information, call GetLastError. <br>Remarks<br>Locking a region of a file gives the locking process exclusive access to the specified region. File locks are not inherited by processes created by the locking process. <br>Locking a region of a file denies all other processes both read and write access to the specified region. Locking a region that goes beyond the current end-of-file position is not an error. <br>Locks may not overlap an existing locked region of the file. <br>The UnlockFile function unlocks a file region locked by LockFile <br>
 
第二个要求太难实现了吧。<br><br>上面所有的都只能在本地机。
 
你不如换一种思路,这样:先把要监视的目录备份一份,当发现被监视的目录内的内容有变化时,就把备份的给Copy过来覆盖原来的部分。
 
接受答案了.
 
后退
顶部