FILEMON.C
资源名称:filesrc.zip [点击查看]
上传用户:hmgghm
上传日期:2007-01-07
资源大小:335k
文件大小:48k
源码类别:
文件操作
开发平台:
Visual C++
- //======================================================================
- //
- // FILEMON.c - main module for VxD FILEMON
- //
- // By Mark Russinovich and Bryce Cogswell
- //
- //======================================================================
- #define DEVICE_MAIN
- #include <vtoolsc.h>
- #include "..guiioctlcmd.h"
- #include "filemon.h"
- #undef DEVICE_MAIN
- #if DEBUG
- #define dprint(arg) dprintf arg
- #else
- #define dprint(arg)
- #endif
- //----------------------------------------------------------------------
- // G L O B A L D A T A
- //----------------------------------------------------------------------
- //
- // Indicates if the GUI wants activity to be logged
- //
- BOOLEAN FilterOn = FALSE;
- //
- // Global filter (sent to us by the GUI)
- //
- FILTER FilterDef;
- //
- // Array of process and path filters
- //
- ULONG NumIncludeFilters = 0;
- PCHAR IncludeFilters[MAXFILTERS];
- ULONG NumExcludeFilters = 0;
- PCHAR ExcludeFilters[MAXFILTERS];
- //
- // Real service pointers with the hook thunks
- //
- ppIFSFileHookFunc PrevIFSHookProc;
- //
- // Hash table data
- //
- PHASH_ENTRY HashTable[NUMHASH];
- //
- // List of freed entries (to save some allocation calls)
- //
- PHASH_ENTRY FreeEntries = NULL;
- //
- // Buffer data
- //
- PSTORE_BUF Store = NULL;
- ULONG Sequence = 0;
- //
- // Maximum amount of buffers we will grab for buffered unread data
- //
- ULONG NumStore = 0;
- ULONG MaxStore = 5;
- //
- // Semaphore for critical sections
- //
- SEMHANDLE StoreMutex, HashMutex, FilterMutex;
- //
- // Unknown error string
- //
- CHAR errstring[32];
- //
- // Measuring duration or absolute time
- //
- BOOLEAN TimeIsDuration = TRUE;
- //----------------------------------------------------------------------
- // V X D C O N T R O L
- //----------------------------------------------------------------------
- //
- // Device declaration
- //
- Declare_Virtual_Device(FILEMON)
- //
- // Message handlers - we only care about dynamic loading and unloading
- //
- DefineControlHandler(SYS_DYNAMIC_DEVICE_INIT, OnSysDynamicDeviceInit);
- DefineControlHandler(SYS_DYNAMIC_DEVICE_EXIT, OnSysDynamicDeviceExit);
- DefineControlHandler(W32_DEVICEIOCONTROL, OnW32Deviceiocontrol);
- //----------------------------------------------------------------------
- //
- // ControlDispatcher
- //
- // Multiplexes incoming VxD messages from Windows to their handlers.
- //
- //----------------------------------------------------------------------
- BOOL __cdecl ControlDispatcher(
- DWORD dwControlMessage,
- DWORD EBX,
- DWORD EDX,
- DWORD ESI,
- DWORD EDI,
- DWORD ECX)
- {
- START_CONTROL_DISPATCH
- ON_SYS_DYNAMIC_DEVICE_INIT(OnSysDynamicDeviceInit);
- ON_SYS_DYNAMIC_DEVICE_EXIT(OnSysDynamicDeviceExit);
- ON_W32_DEVICEIOCONTROL(OnW32Deviceiocontrol);
- END_CONTROL_DISPATCH
- return TRUE;
- }
- //----------------------------------------------------------------------
- // P A T T E R N M A T C H I N G R O U T I N E S
- //----------------------------------------------------------------------
- //----------------------------------------------------------------------
- //
- // MatchOkay
- //
- // Only thing left after compare is more mask. This routine makes
- // sure that its a valid wild card ending so that its really a match.
- //
- //----------------------------------------------------------------------
- BOOLEAN MatchOkay( PCHAR Pattern )
- {
- //
- // If pattern isn't empty, it must be a wildcard
- //
- if( *Pattern && *Pattern != '*' ) {
- return FALSE;
- }
- //
- // Matched
- //
- return TRUE;
- }
- //----------------------------------------------------------------------
- //
- // MatchWithPattern
- //
- // Performs nifty wildcard comparison.
- //
- //----------------------------------------------------------------------
- BOOLEAN MatchWithPattern( PCHAR Pattern, PCHAR Name )
- {
- CHAR upcase;
- //
- // End of pattern?
- //
- if( !*Pattern ) {
- return FALSE;
- }
- //
- // If we hit a wild card, do recursion
- //
- if( *Pattern == '*' ) {
- Pattern++;
- while( *Name && *Pattern ) {
- if( *Name >= 'a' && *Name <= 'z' )
- upcase = *Name - 'a' + 'A';
- else
- upcase = *Name;
- //
- // See if this substring matches
- //
- if( *Pattern == upcase || *Name == '*' ) {
- if( MatchWithPattern( Pattern+1, Name+1 )) {
- return TRUE;
- }
- }
- //
- // Try the next substring
- //
- Name++;
- }
- //
- // See if match condition was met
- //
- return MatchOkay( Pattern );
- }
- //
- // Do straight compare until we hit a wild card
- //
- while( *Name && *Pattern != '*' ) {
- if( *Name >= 'a' && *Name <= 'z' )
- upcase = *Name - 'a' + 'A';
- else
- upcase = *Name;
- if( *Pattern == upcase ) {
- Pattern++;
- Name++;
- } else {
- return FALSE;
- }
- }
- //
- // If not done, recurse
- //
- if( *Name ) {
- return MatchWithPattern( Pattern, Name );
- }
- //
- // Make sure its a match
- //
- return MatchOkay( Pattern );
- }
- //----------------------------------------------------------------------
- // B U F F E R M A N A G E M E N T
- //----------------------------------------------------------------------
- //----------------------------------------------------------------------
- //
- // FilemonFreeStore
- //
- // Frees all the data output buffers that we have currently allocated.
- //
- //----------------------------------------------------------------------
- VOID FilemonFreeStore()
- {
- PSTORE_BUF prev;
- //
- // Just traverse the list of allocated output buffers
- //
- while( Store ) {
- prev = Store->Next;
- PageFree( (MEMHANDLE) Store, 0 );
- Store = prev;
- }
- }
- //----------------------------------------------------------------------
- //
- // FilemonNewStore
- //
- // Called when the current buffer has filled up. This moves us to the
- // pre-allocated buffer and then allocates another buffer.
- //
- // Returns FALSE if another thread is already allocating a buffer.
- //
- //----------------------------------------------------------------------
- BOOLEAN FilemonNewStore( void )
- {
- PSTORE_BUF prev = Store, newstore;
- static busyAllocating = FALSE;
- //
- // If we have maxed out or haven't accessed the current store
- // just return.
- //
- if( MaxStore == NumStore ) {
- Store->Len = 0;
- return TRUE;
- }
- //
- // If the output buffer we currently are using is empty, just
- // use it, or if we are busy already allocating a buffer, return
- //
- if( !Store->Len || busyAllocating )
- return !busyAllocating;
- //
- // Allocate a new output buffer. Release lock to prevent deadlock
- // on reentrance (allocating memory can result in file I/O
- //
- busyAllocating = TRUE;
- Signal_Semaphore( StoreMutex );
- PageAllocate(STORESIZE, PG_SYS, 0, 0, 0, 0, NULL, PAGELOCKED,
- (PMEMHANDLE) &newstore, (PVOID) &newstore );
- Wait_Semaphore( StoreMutex, BLOCK_SVC_INTS );
- busyAllocating = FALSE;
- if( newstore ) {
- //
- // Allocation was successful so add the buffer to the list
- // of allocated buffers and increment the buffer count.
- //
- Store = newstore;
- Store->Len = 0;
- Store->Next = prev;
- NumStore++;
- } else {
- //
- // The allocation failed - just reuse the current buffer
- //
- Store->Len = 0;
- }
- Signal_Semaphore( StoreMutex );
- return TRUE;
- }
- //----------------------------------------------------------------------
- //
- // FilemonOldestStore
- //
- // Goes through the linked list of storage buffers and returns the
- // oldest one.
- //
- //----------------------------------------------------------------------
- PSTORE_BUF FilemonOldestStore( void )
- {
- PSTORE_BUF ptr = Store, prev = NULL;
- //
- // Traverse the list
- //
- while ( ptr->Next ) {
- ptr = (prev = ptr)->Next;
- }
- //
- // Remove the buffer from the list
- //
- if ( prev ) {
- prev->Next = NULL;
- }
- NumStore--;
- return ptr;
- }
- //----------------------------------------------------------------------
- //
- // FilemonResetStore
- //
- // When a GUI is no longer communicating with us, but we can't unload,
- // we reset the storage buffers.
- //
- //----------------------------------------------------------------------
- VOID FilemonResetStore()
- {
- PSTORE_BUF current, next;
- //
- // Traverse the list of output buffers
- //
- current = Store->Next;
- while( current ) {
- //
- // Free the buffer
- //
- next = current->Next;
- PageFree( (MEMHANDLE) current, 0 );
- current = next;
- }
- //
- // Move the output pointer in the buffer that's being kept
- // the start of the buffer.
- //
- Store->Len = 0;
- Store->Next = NULL;
- }
- //----------------------------------------------------------------------
- //
- // UpdateStore
- //
- // Add a new string to Store, if it fits.
- //
- //----------------------------------------------------------------------
- void UpdateStore( ULONG seq, ULONG time, const char * format, ... )
- {
- PENTRY Entry;
- ULONG len;
- va_list arg_ptr;
- CHAR text[MAXPATHLEN];
- //
- // If no filtering is desired, don't bother
- //
- if( !FilterOn ) {
- return;
- }
- //
- // Lock the output buffer.
- //
- Wait_Semaphore( StoreMutex, BLOCK_SVC_INTS );
- //
- // Vsprintf to determine length of the buffer
- //
- _asm cld;
- va_start( arg_ptr, format );
- len = vsprintf( text, format, arg_ptr );
- va_end( arg_ptr );
- //
- // If the current output buffer is near capacity, move to a new
- // output buffer
- //
- if( (ULONG) (Store->Len + len + sizeof(ENTRY) +1) >= MAX_STORE ) {
- if( !FilemonNewStore() ) {
- //
- // Just return if a thread is in the process
- // of allocating a buffer.
- //
- Signal_Semaphore( StoreMutex );
- return;
- }
- }
- //
- // Extract the sequence number and store it
- //
- Entry = (void *)(Store->Data+Store->Len);
- Entry->seq = seq;
- Entry->time.u.LowPart = time;
- Entry->time.u.HighPart = 0;
- _asm cld;
- memcpy( Entry->text, text, len + 1 );
- //
- // Store the length of the string, plus 1 for the terminating
- // NULL
- //
- Store->Len += (Entry->text - (PCHAR) Entry) + len + 1;
- //
- // Release the output buffer lock
- //
- Signal_Semaphore( StoreMutex );
- }
- //----------------------------------------------------------------------
- // H A S H T A B L E M A N A G E M E N T
- //----------------------------------------------------------------------
- //----------------------------------------------------------------------
- //
- // FilemonHashCleanup
- //
- // Called when we are unloading to free any memory that we have
- // in our possession.
- //
- //----------------------------------------------------------------------
- VOID FilemonHashCleanup()
- {
- PHASH_ENTRY hashEntry, nextEntry;
- ULONG i;
- //
- // First, free the hash table entries
- //
- for( i = 0; i < NUMHASH; i++ ) {
- hashEntry = HashTable[i];
- while( hashEntry ) {
- nextEntry = hashEntry->Next;
- HeapFree( hashEntry->FullName, 0 );
- HeapFree( hashEntry, 0 );
- hashEntry = nextEntry;
- }
- }
- //
- // Now, free structures on our free list
- //
- while( FreeEntries ) {
- nextEntry = FreeEntries->Next;
- HeapFree( FreeEntries, 0 );
- FreeEntries = nextEntry;
- }
- }
- //----------------------------------------------------------------------
- //
- // FilemonStoreHash
- //
- // Stores the key and associated fullpath in the hash table.
- //
- //----------------------------------------------------------------------
- VOID FilemonStoreHash( sfn_t filenumber, PCHAR fullname )
- {
- PHASH_ENTRY newEntry;
- Wait_Semaphore( HashMutex, BLOCK_SVC_INTS );
- //
- // Find or allocate an entry to use.
- //
- if( FreeEntries ) {
- newEntry = FreeEntries;
- FreeEntries = FreeEntries->Next;
- Signal_Semaphore( HashMutex );
- } else {
- //
- // Have to release the lock, because memory allocation can
- // cause re-entrancy.
- //
- Signal_Semaphore( HashMutex );
- newEntry = HeapAllocate( sizeof(HASH_ENTRY), 0 );
- //
- // Is there memory for the allocation?
- //
- if( !newEntry ) return;
- }
- //
- // Initialize the new entry.
- //
- newEntry->filenumber = filenumber;
- newEntry->FullName = HeapAllocate( strlen(fullname)+1, 0);
- //
- // Make sure the allocation succeeded.
- //
- if( !newEntry->FullName ) {
- HeapFree( newEntry, 0 );
- return;
- }
- strcpy( newEntry->FullName, fullname );
- //
- // Lock the hash table and insert the new entry.
- //
- Wait_Semaphore( HashMutex, BLOCK_SVC_INTS );
- newEntry->Next = HashTable[ HASHOBJECT(filenumber) ];
- HashTable[ HASHOBJECT(filenumber) ] = newEntry;
- Signal_Semaphore( HashMutex );
- }
- //----------------------------------------------------------------------
- //
- // FilemonFreeHashEntry
- //
- // When we see a file close, we can free the string we had associated
- // with the fileobject being closed since we know it won't be used
- // again.
- //
- //----------------------------------------------------------------------
- VOID FilemonFreeHashEntry( sfn_t filenumber )
- {
- PHASH_ENTRY hashEntry, prevEntry;
- Wait_Semaphore( HashMutex, BLOCK_SVC_INTS );
- //
- // Look-up the entry.
- //
- hashEntry = HashTable[ HASHOBJECT( filenumber ) ];
- prevEntry = NULL;
- while( hashEntry && hashEntry->filenumber != filenumber ) {
- prevEntry = hashEntry;
- hashEntry = hashEntry->Next;
- }
- //
- // If we fall of the hash list without finding what we're looking
- // for, just return.
- //
- if( !hashEntry ) {
- Signal_Semaphore( HashMutex );
- return;
- }
- //
- // Got it! Remove it from the list
- //
- if( prevEntry ) {
- prevEntry->Next = hashEntry->Next;
- } else {
- HashTable[ HASHOBJECT( filenumber )] = hashEntry->Next;
- }
- //
- // Free the memory associated with the name of the free entry.
- //
- hashEntry->Next = FreeEntries;
- FreeEntries = hashEntry;
- Signal_Semaphore( HashMutex );
- //
- // Free the memory associated with it
- //
- HeapFree( hashEntry->FullName, 0 );
- }
- //----------------------------------------------------------------------
- // P A T H A N D P R O C E S S N A M E R O U T I N E S
- //----------------------------------------------------------------------
- //----------------------------------------------------------------------
- //
- // ErrorString
- //
- // Returns the string form of an error code.
- //
- //----------------------------------------------------------------------
- PCHAR ErrorString( DWORD retval )
- {
- switch( retval ) {
- case ERROR_INVALID_FUNCTION:
- return "INVALIDFUNC";
- case ERROR_SUCCESS:
- return "SUCCESS";
- case ERROR_OUTOFMEMORY:
- return "OUTOFMEM";
- case ERROR_ACCESS_DENIED:
- return "ACCDENIED";
- case ERROR_PATH_NOT_FOUND:
- return "NOTFOUND";
- case ERROR_TOO_MANY_OPEN_FILES:
- return "TOOMANYOPEN";
- case ERROR_FILE_NOT_FOUND:
- return "NOTFOUND";
- case ERROR_NO_MORE_ITEMS:
- return "NOMORE";
- case ERROR_GEN_FAILURE:
- return "GENFAILURE";
- case ERROR_MORE_DATA:
- return "MOREDATA";
- case ERROR_INVALID_DRIVE:
- return "INVALIDDRIVE";
- case ERROR_NOT_SAME_DEVICE:
- return "DIFFERENTDEVICE";
- case ERROR_WRITE_PROTECT:
- return "WRITEPROTECTED";
- case ERROR_SHARING_VIOLATION:
- return "SHARING";
- case ERROR_BAD_UNIT:
- return "BADUNIT";
- case ERROR_NOT_READY:
- return "NOTREADY";
- case ERROR_NO_MORE_FILES:
- return "NOMORE";
- case ERROR_BAD_COMMAND:
- return "BADCOMMAND";
- default:
- sprintf(errstring, "0x%x", retval );
- return errstring;
- }
- }
- //----------------------------------------------------------------------
- //
- // FilemonFreeFilters
- //
- // Fress storage we allocated for filter strings.
- //
- //----------------------------------------------------------------------
- VOID FilemonFreeFilters()
- {
- ULONG i;
- for( i = 0; i < NumIncludeFilters; i++ ) {
- HeapFree( IncludeFilters[i], 0 );
- }
- for( i = 0; i < NumExcludeFilters; i++ ) {
- HeapFree( ExcludeFilters[i], 0 );
- }
- NumIncludeFilters = 0;
- NumExcludeFilters = 0;
- }
- //----------------------------------------------------------------------
- //
- // MakeFilterArray
- //
- // Takes a filter string and splits into components (a component
- // is seperated with a ';')
- //
- //----------------------------------------------------------------------
- VOID MakeFilterArray( PCHAR FilterString,
- PCHAR FilterArray[],
- PULONG NumFilters )
- {
- PCHAR filterStart;
- ULONG filterLength;
- //
- // Scan through the process filters
- //
- filterStart = FilterString;
- while( *filterStart ) {
- filterLength = 0;
- while( filterStart[filterLength] &&
- filterStart[filterLength] != ';' ) {
- filterLength++;
- }
- //
- // Ignore zero-length components
- //
- if( filterLength ) {
- FilterArray[ *NumFilters ] =
- HeapAllocate( filterLength + 1, 0 );
- strncpy( FilterArray[ *NumFilters ],
- filterStart, filterLength );
- FilterArray[ *NumFilters ][filterLength] = 0;
- (*NumFilters)++;
- }
- //
- // Are we done?
- //
- if( !filterStart[filterLength] ) break;
- //
- // Move to the next component (skip over ';')
- //
- filterStart += filterLength + 1;
- }
- }
- //----------------------------------------------------------------------
- //
- // FilemonUpdateFilters
- //
- // Takes a new filter specification and updates the filter
- // arrays with them.
- //
- //----------------------------------------------------------------------
- VOID FilemonUpdateFilters()
- {
- //
- // Free old filters (if any)
- //
- Wait_Semaphore( FilterMutex, BLOCK_SVC_INTS );
- FilemonFreeFilters();
- //
- // Create new filter arrays
- //
- MakeFilterArray( FilterDef.includefilter,
- IncludeFilters, &NumIncludeFilters );
- MakeFilterArray( FilterDef.excludefilter,
- ExcludeFilters, &NumExcludeFilters );
- Signal_Semaphore( FilterMutex );
- }
- //----------------------------------------------------------------------
- //
- // wstrlen
- //
- // Determine the length of a wide-character string.
- //
- //----------------------------------------------------------------------
- int wstrlen( unsigned short *unistring )
- {
- int i = 0;
- int len = 0;
- while( unistring[i++] != 0 ) len+=2;
- return len;
- }
- //----------------------------------------------------------------------
- //
- // FilmonGetProcess
- //
- // Retrieves the process name.
- //
- //----------------------------------------------------------------------
- FILTERSTATUS FilemonGetProcess( PCHAR ProcessName )
- {
- PVOID CurProc;
- PVOID ring3proc;
- char *name;
- ULONG i;
- //
- // Get the ring0 process pointer.
- //
- CurProc = VWIN32_GetCurrentProcessHandle();
- //
- // Now, map the ring3 PCB
- //
- ring3proc = (PVOID) SelectorMapFlat( Get_Sys_VM_Handle(),
- (DWORD) (*(PDWORD) ((char *) CurProc + 0x38)) | 0x7, 0 );
- if( ring3proc == (PVOID) -1 ) {
- strcpy( ProcessName, "???");
- } else {
- //
- // copy out the process name (max 8 characters)
- //
- name = ((char *)ring3proc) + 0xF2;
- if( name[0] >= 'A' && name[0] < 'z' ) {
- strcpy( ProcessName, name );
- ProcessName[8] = 0;
- } else {
- strcpy( ProcessName, "???" );
- }
- }
- //
- // Ignore filemon-generated output
- //
- if( !stricmp( ProcessName, "Filemon" )) return FILTERFAIL;
- //
- // Apply process name filters
- //
- Wait_Semaphore( FilterMutex, BLOCK_SVC_INTS );
- for( i = 0; i < NumExcludeFilters; i++ ) {
- if( MatchWithPattern( ExcludeFilters[i], ProcessName )) {
- Signal_Semaphore( FilterMutex );
- return FILTERFAIL;
- }
- }
- for( i = 0; i < NumIncludeFilters; i++ ) {
- if( MatchWithPattern( IncludeFilters[i], ProcessName ) ) {
- Signal_Semaphore( FilterMutex );
- return FILTERPASS;
- }
- }
- Signal_Semaphore( FilterMutex );
- return FILTERNOMATCH;
- }
- //----------------------------------------------------------------------
- //
- // ApplyNameFilter
- //
- // If the name matches the exclusion mask, we do not log it. Else if
- // it doesn't match the inclusion mask we do not log it.
- //
- //----------------------------------------------------------------------
- FILTERSTATUS ApplyNameFilter( PCHAR fullname )
- {
- ULONG i;
- //
- // If it matches the exclusion string, do not log it
- //
- Wait_Semaphore( FilterMutex, BLOCK_SVC_INTS );
- for( i = 0; i < NumExcludeFilters; i++ ) {
- if( MatchWithPattern( ExcludeFilters[i], fullname ) ) {
- Signal_Semaphore( FilterMutex );
- return FILTERFAIL;
- }
- }
- //
- // If it matches an include filter then log it
- //
- for( i = 0; i < NumIncludeFilters; i++ ) {
- if( MatchWithPattern( IncludeFilters[i], fullname )) {
- Signal_Semaphore( FilterMutex );
- return FILTERPASS;
- }
- }
- //
- // It didn't match any include filters so don't log
- //
- Signal_Semaphore( FilterMutex );
- return FILTERNOMATCH;
- }
- //----------------------------------------------------------------------
- //
- // ApplyFilters
- //
- // Gets the process name and then performs filtering logic.
- //
- //----------------------------------------------------------------------
- BOOLEAN ApplyFilters( PCHAR ProcessName, PCHAR FullName )
- {
- FILTERSTATUS filterStatus, nameFilterStatus;
- //
- // Try the process filter
- //
- filterStatus = FilemonGetProcess( ProcessName );
- if( filterStatus == FILTERPASS ||
- filterStatus == FILTERNOMATCH ) {
- //
- // Try the path filter
- //
- nameFilterStatus = ApplyNameFilter( FullName );
- if( (filterStatus == FILTERPASS && nameFilterStatus != FILTERFAIL) ||
- nameFilterStatus == FILTERPASS ) {
- return TRUE;
- }
- }
- return FALSE;
- }
- //----------------------------------------------------------------------
- //
- // FilemonConvertPath
- //
- // Converts a unicode path name to ANSI.
- //
- //----------------------------------------------------------------------
- PCHAR FilemonConvertPath( int drive, path_t ppath, PCHAR fullpathname )
- {
- int i = 0;
- _QWORD result;
- //
- // Stick on the drive letter if we know it.
- //
- if( drive != 0xFF ) {
- fullpathname[0] = drive+'A'-1;
- fullpathname[1] = ':';
- i = 2;
- }
- UniToBCSPath( &fullpathname[i], ppath->pp_elements, MAXPATHLEN, BCS_WANSI, &result );
- return( fullpathname );
- }
- //----------------------------------------------------------------------
- //
- // FilemonGetFullPath
- //
- // Returns the full pathname of a file, if we can obtain one, else
- // returns a handle.
- //
- //----------------------------------------------------------------------
- PCHAR FilemonGetFullPath( sfn_t filenumber, PCHAR fullname,
- int Drive, int ResType, int CodePage, pioreq pir )
- {
- PHASH_ENTRY hashEntry;
- pIFSFunc enumFunc;
- ifsreq ifsr;
- path_t uniFullName;
- int retval;
- //
- // See if we find the key in the hash table.
- //
- Wait_Semaphore( HashMutex, BLOCK_SVC_INTS );
- hashEntry = HashTable[ HASHOBJECT( filenumber ) ];
- while( hashEntry && hashEntry->filenumber != filenumber ) {
- hashEntry = hashEntry->Next;
- }
- Signal_Semaphore( HashMutex );
- fullname[0] = 0;
- if( hashEntry ) {
- strcpy( fullname, hashEntry->FullName );
- } else {
- //
- // File name isn't in the table, so ask the
- // underlying file system
- //
- sprintf( fullname, "0x%X", filenumber );
- uniFullName = IFSMgr_GetHeap( MAXPATHLEN );
- if( uniFullName ) {
- //
- // Send a query file name request
- //
- memcpy( &ifsr, pir, sizeof( ifsreq ));
- ifsr.ifsir.ir_flags = ENUMH_GETFILENAME;
- ifsr.ifsir.ir_ppath = uniFullName;
- enumFunc = ifsr.ifs_hndl->hf_misc->hm_func[HM_ENUMHANDLE];
- retval = (*PrevIFSHookProc)(enumFunc, IFSFN_ENUMHANDLE,
- Drive, ResType, CodePage,
- (pioreq) &ifsr);
- if( retval == ERROR_SUCCESS ) {
- FilemonConvertPath( Drive, uniFullName, fullname );
- FilemonStoreHash( filenumber, fullname );
- }
- IFSMgr_RetHeap( (void *) uniFullName );
- }
- }
- return fullname;
- }
- //----------------------------------------------------------------------
- //
- // FilemonHookProc
- //
- // All (most) IFS functions come through this routine for us to look
- // at.
- //
- //----------------------------------------------------------------------
- #pragma optimize("", off)
- int _cdecl FilemonHookProc(pIFSFunc pfn, int fn, int Drive, int ResType,
- int CodePage, pioreq pir)
- {
- int retval;
- char fullpathname[MAXPATHLEN];
- char processname[64];
- char data[256];
- char drivestring[4];
- ioreq origir;
- _WIN32_FIND_DATA *finddata;
- struct srch_entry *search;
- BOOLEAN log;
- _QWORD result;
- DWORD timelo, timehi;
- DWORD timelo1, timehi1;
- int i, j;
- //
- // Inititlize default data.
- //
- data[0] = 0;
- //
- // Save original iorequest because some entries get modified.
- //
- origir = *pir;
- //
- // Get the current process name.
- //
- FilemonGetProcess( processname );
- //
- // Get the time
- //
- if( TimeIsDuration ) {
- VTD_Get_Real_Time( &timehi, &timelo );
- } else {
- timelo = IFSMgr_Get_DOSTime( &timehi );
- }
- //
- // Call the previous hooker first, to get the return code.
- //
- retval = (*PrevIFSHookProc)(pfn, fn, Drive, ResType, CodePage, pir);
- //
- // Now extract parameters based on the function type.
- //
- switch( fn ) {
- case IFSFN_OPEN:
- FilemonConvertPath( Drive, pir->ir_ppath, fullpathname );
- if( ApplyFilters( processname, fullpathname )) {
- if( TimeIsDuration ) {
- VTD_Get_Real_Time( &timehi1, &timelo1 );
- timelo = timelo1 - timelo;
- }
- sprintf(data,"");
- if( origir.ir_options & ACTION_CREATENEW ) strcat(data,"CREATENEW ");
- if( origir.ir_options & ACTION_OPENEXISTING ) strcat(data,"OPENEXISTING ");
- if( origir.ir_options & ACTION_REPLACEEXISTING ) strcat(data,"REPLACEEXISTING ");
- switch (origir.ir_flags & ACCESS_MODE_MASK) {
- case ACCESS_READONLY:
- strcat(data,"READONLY ");
- break;
- case ACCESS_WRITEONLY:
- strcat(data,"WRITEONLY ");
- break;
- case ACCESS_READWRITE:
- strcat(data,"READWRITE ");
- break;
- case ACCESS_EXECUTE:
- strcat(data,"EXECUTE ");
- break;
- default:
- break;
- }
- switch (origir.ir_flags & SHARE_MODE_MASK) {
- case SHARE_COMPATIBILITY:
- strcat(data,"COMPATIBILITY ");
- break;
- case SHARE_DENYREADWRITE:
- strcat(data,"DENYREADWRITE ");
- break;
- case SHARE_DENYWRITE:
- strcat(data,"DENYWRITE ");
- break;
- case SHARE_DENYREAD:
- strcat(data,"DENYREAD ");
- break;
- case SHARE_DENYNONE:
- strcat(data,"DENYNONE ");
- break;
- default:
- break;
- }
- UpdateStore( Sequence++, timelo, "%stOpent%st%st%s",
- processname, fullpathname,
- data, ErrorString( retval ));
- }
- FilemonStoreHash( pir->ir_sfn, fullpathname );
- break;
- case IFSFN_READ:
- case IFSFN_WRITE:
- FilemonGetFullPath( pir->ir_sfn, fullpathname, Drive, ResType, CodePage, pir );
- if( ((fn == IFSFN_READ && FilterDef.logreads ) ||
- (fn == IFSFN_WRITE && FilterDef.logwrites )) &&
- ApplyFilters( processname, fullpathname )) {
- if( TimeIsDuration ) {
- VTD_Get_Real_Time( &timehi1, &timelo1 );
- timelo = timelo1 - timelo;
- }
- sprintf( data, "Offset: %ld Length: %ld", origir.ir_pos, origir.ir_length );
- UpdateStore( Sequence++, timelo, "%st%st%st%st%s",
- processname, fn == IFSFN_READ? "Read" : "Write",
- fullpathname,
- data, ErrorString( retval ));
- }
- break;
- case IFSFN_CLOSE:
- FilemonGetFullPath( pir->ir_sfn, fullpathname, Drive, ResType, CodePage, pir );
- if( ApplyFilters( processname, fullpathname ) && FilterDef.logreads ) {
- if( TimeIsDuration ) {
- VTD_Get_Real_Time( &timehi1, &timelo1 );
- timelo = timelo1 - timelo;
- }
- switch( origir.ir_flags ) {
- case CLOSE_HANDLE: sprintf(data, "CLOSE_HANDLE"); break;
- case CLOSE_FOR_PROCESS: sprintf(data, "CLOSE_FOR_PROCESS"); break;
- case CLOSE_FINAL: sprintf(data, "CLOSE_FINAL"); break;
- default: sprintf(data,"0x%02X",origir.ir_flags); break;
- }
- UpdateStore( Sequence++, timelo, "%stCloset%st%st%s", processname,
- fullpathname, data, ErrorString( retval ));
- }
- if ( origir.ir_flags == CLOSE_FINAL ) FilemonFreeHashEntry( origir.ir_sfn );
- break;
- case IFSFN_DIR:
- FilemonConvertPath( Drive, pir->ir_ppath, fullpathname );
- if( ApplyFilters( processname, fullpathname )) {
- if( TimeIsDuration ) {
- VTD_Get_Real_Time( &timehi1, &timelo1 );
- timelo = timelo1 - timelo;
- }
- log = FALSE;
- switch( pir->ir_flags ) {
- case CREATE_DIR:
- sprintf(data, "CREATE");
- if( FilterDef.logwrites ) log = TRUE;
- break;
- case DELETE_DIR:
- sprintf(data,"DELETE");
- if( FilterDef.logwrites ) log = TRUE;
- break;
- case CHECK_DIR:
- sprintf(data,"CHECK");
- if( FilterDef.logreads ) log = TRUE;
- break;
- default:
- sprintf(data,"QUERY");
- if( FilterDef.logreads ) log = TRUE;
- break;
- }
- if( log ) {
- UpdateStore( Sequence++, timelo, "%stDirectoryt%st%st%s",
- processname,
- fullpathname,
- data, ErrorString( retval ));
- }
- }
- break;
- case IFSFN_SEEK:
- FilemonGetFullPath( pir->ir_sfn, fullpathname, Drive, ResType, CodePage, pir );
- if( ApplyFilters( processname, fullpathname ) && FilterDef.logreads) {
- if( TimeIsDuration ) {
- VTD_Get_Real_Time( &timehi1, &timelo1 );
- timelo = timelo1 - timelo;
- }
- sprintf(data, "%s Offset: %ld",
- pir->ir_flags == FILE_BEGIN ? "Beginning" : "End",
- origir.ir_pos );
- UpdateStore( Sequence++, timelo, "%stSeekt%st%st%s",
- processname, fullpathname,
- data, ErrorString( retval ));
- }
- break;
- case IFSFN_COMMIT:
- FilemonGetFullPath( pir->ir_sfn, fullpathname, Drive, ResType, CodePage, pir );
- if( ApplyFilters( processname, fullpathname ) && FilterDef.logwrites) {
- if( TimeIsDuration ) {
- VTD_Get_Real_Time( &timehi1, &timelo1 );
- timelo = timelo1 - timelo;
- }
- sprintf(data, "%s", pir->ir_options == FILE_COMMIT_ASYNC ?
- "ASYNC" : "NOACCESSUPDATE" );
- UpdateStore( Sequence++, timelo, "%stCommitt%st%st%s",
- processname, fullpathname,
- data, ErrorString( retval ));
- }
- break;
- case IFSFN_FILELOCKS:
- FilemonGetFullPath( pir->ir_sfn, fullpathname, Drive, ResType, CodePage, pir );
- if( ApplyFilters( processname, fullpathname ) && FilterDef.logreads) {
- if( TimeIsDuration ) {
- VTD_Get_Real_Time( &timehi1, &timelo1 );
- timelo = timelo1 - timelo;
- }
- sprintf(data, "Offset: %ld Length:%ld", origir.ir_pos, origir.ir_locklen );
- UpdateStore( Sequence++, timelo, "%st%st%st%st%s",
- processname, origir.ir_flags == LOCK_REGION ? "Lock" : "Unlock",
- fullpathname,
- data, ErrorString( retval ));
- }
- break;
- case IFSFN_FINDOPEN:
- FilemonConvertPath( Drive, pir->ir_ppath, fullpathname );
- if( ApplyFilters( processname, fullpathname ) && FilterDef.logreads) {
- if( TimeIsDuration ) {
- VTD_Get_Real_Time( &timehi1, &timelo1 );
- timelo = timelo1 - timelo;
- }
- if( !retval ) {
- finddata = (_WIN32_FIND_DATA *) pir->ir_data;
- UniToBCS( data, finddata->cFileName, MAXPATHLEN, wstrlen(finddata->cFileName),BCS_WANSI, &result );
- data[wstrlen(finddata->cFileName)/2] = 0;
- }
- UpdateStore( Sequence++, timelo, "%stFindOpent%st%st%s",
- processname, fullpathname,
- data, ErrorString( retval ));
- }
- FilemonStoreHash( pir->ir_sfn, fullpathname );
- break;
- case IFSFN_FINDNEXT:
- FilemonGetFullPath( pir->ir_sfn, fullpathname, Drive, ResType, CodePage, pir );
- if( ApplyFilters( processname, fullpathname ) && FilterDef.logreads) {
- if( TimeIsDuration ) {
- VTD_Get_Real_Time( &timehi1, &timelo1 );
- timelo = timelo1 - timelo;
- }
- if( !retval ) {
- finddata = (_WIN32_FIND_DATA *) pir->ir_data;
- UniToBCS( data, finddata->cFileName, MAXPATHLEN, wstrlen(finddata->cFileName),BCS_WANSI, &result );
- data[wstrlen(finddata->cFileName)/2] = 0;
- }
- UpdateStore( Sequence++, timelo, "%stFindNextt%st%st%s",
- processname, fullpathname,
- data, ErrorString( retval ));
- }
- break;
- case IFSFN_FINDCLOSE:
- FilemonGetFullPath( pir->ir_sfn, fullpathname, Drive, ResType, CodePage, pir );
- if( ApplyFilters( processname, fullpathname ) && FilterDef.logreads) {
- if( TimeIsDuration ) {
- VTD_Get_Real_Time( &timehi1, &timelo1 );
- timelo = timelo1 - timelo;
- }
- UpdateStore( Sequence++, timelo, "%stFindCloset%stt%s",
- processname, fullpathname,
- ErrorString( retval ));
- }
- FilemonFreeHashEntry( pir->ir_sfn );
- break;
- case IFSFN_FILEATTRIB:
- FilemonConvertPath( Drive, pir->ir_ppath, fullpathname );
- if( ApplyFilters( processname, fullpathname ) && FilterDef.logreads) {
- if( TimeIsDuration ) {
- VTD_Get_Real_Time( &timehi1, &timelo1 );
- timelo = timelo1 - timelo;
- }
- switch(origir.ir_flags ) {
- case GET_ATTRIBUTES:
- sprintf(data,"GetAttributes");
- break;
- case SET_ATTRIBUTES:
- sprintf(data, "SetAttributes" );
- break;
- case GET_ATTRIB_COMP_FILESIZE:
- sprintf(data, "GET_ATTRIB_COMP_FILESIZE" );
- break;
- case SET_ATTRIB_MODIFY_DATETIME:
- sprintf(data, "SET_ATTRIB_MODIFY_DATETIME");
- break;
- case SET_ATTRIB_LAST_ACCESS_DATETIME:
- sprintf(data, "SET_ATTRIB_LAST_ACCESS_DATETIME");
- break;
- case GET_ATTRIB_LAST_ACCESS_DATETIME:
- sprintf(data, "GET_ATTRIB_LAST_ACCESS_DATETIME");
- break;
- case SET_ATTRIB_CREATION_DATETIME:
- sprintf(data, "SET_ATTRIB_CREATION_DATETIME");
- break;
- case GET_ATTRIB_CREATION_DATETIME:
- sprintf(data, "GET_ATTRIB_CREATION_DATETIME");
- break;
- }
- UpdateStore( Sequence++, timelo, "%stAttributest%st%st%s",
- processname, fullpathname,
- data, ErrorString( retval ));
- }
- break;
- case IFSFN_FILETIMES:
- FilemonGetFullPath( pir->ir_sfn, fullpathname, Drive, ResType, CodePage, pir );
- if( ApplyFilters( processname, fullpathname ) && FilterDef.logreads) {
- if( TimeIsDuration ) {
- VTD_Get_Real_Time( &timehi1, &timelo1 );
- timelo = timelo1 - timelo;
- }
- switch( pir->ir_flags ) {
- case GET_MODIFY_DATETIME:
- sprintf(data, "Get Modify");
- break;
- case SET_MODIFY_DATETIME:
- sprintf(data, "Set Modify");
- break;
- case GET_LAST_ACCESS_DATETIME:
- sprintf(data, "Get Access");
- break;
- case SET_LAST_ACCESS_DATETIME:
- sprintf(data, "Set Access");
- break;
- case GET_CREATION_DATETIME:
- sprintf(data, "Get Creation");
- break;
- case SET_CREATION_DATETIME:
- sprintf(data, "Set Creation");
- break;
- }
- UpdateStore( Sequence++, timelo, "%stAttributest%st%st%s",
- processname, fullpathname,
- data, ErrorString( retval ));
- }
- break;
- case IFSFN_FLUSH:
- if( FilemonGetProcess(processname) == FILTERPASS && FilterDef.logwrites) {
- if( TimeIsDuration ) {
- VTD_Get_Real_Time( &timehi1, &timelo1 );
- timelo = timelo1 - timelo;
- }
- UpdateStore( Sequence++, timelo, "%stFlushVolumettt%s",
- processname, ErrorString( retval ));
- }
- break;
- case IFSFN_DELETE:
- FilemonConvertPath( Drive, pir->ir_ppath, fullpathname );
- if( ApplyFilters( processname, fullpathname ) && FilterDef.logwrites) {
- if( TimeIsDuration ) {
- VTD_Get_Real_Time( &timehi1, &timelo1 );
- timelo = timelo1 - timelo;
- }
- UpdateStore( Sequence++, timelo, "%stDeletet%stt%s",
- processname, fullpathname,
- ErrorString( retval ));
- }
- FilemonFreeHashEntry( pir->ir_sfn );
- break;
- case IFSFN_SEARCH:
- if( pir->ir_flags == SEARCH_FIRST )
- FilemonConvertPath( Drive, pir->ir_ppath, fullpathname );
- else
- sprintf(fullpathname, "SearchNext" );
- if( ApplyFilters( processname, fullpathname ) && FilterDef.logreads ) {
- if( TimeIsDuration ) {
- VTD_Get_Real_Time( &timehi1, &timelo1 );
- timelo = timelo1 - timelo;
- }
- if( !retval ) {
- j = 0;
- if( origir.ir_attr & FILE_ATTRIBUTE_LABEL ) {
- sprintf(data, "VolumeLabel: " );
- j = strlen( data );
- }
- search = (struct srch_entry *) origir.ir_data;
- for( i = 0; i < 13; i++ )
- if( search->se_name[i] != ' ' ) data[j++] = search->se_name[i];
- data[j] = 0;
- }
- UpdateStore( Sequence++, timelo, "%stSearcht%st%st%s",
- processname, fullpathname, data, ErrorString( retval ));
- }
- break;
- case IFSFN_GETDISKINFO:
- if( FilemonGetProcess( processname ) == FILTERPASS && FilterDef.logreads ) {
- if( TimeIsDuration ) {
- VTD_Get_Real_Time( &timehi1, &timelo1 );
- timelo = timelo1 - timelo;
- }
- if( !retval ) sprintf(data, "Free Space");
- drivestring[0] = Drive+'A'-1;
- drivestring[1] = ':';
- drivestring[2] = 0;
- UpdateStore( Sequence++, timelo, "%stGetDiskInfot%st%st%s",
- processname, drivestring, data, ErrorString( retval ));
- }
- break;
- case IFSFN_RENAME:
- FilemonConvertPath( Drive, pir->ir_ppath, fullpathname );
- if( ApplyFilters( processname, fullpathname ) && FilterDef.logwrites) {
- if( TimeIsDuration ) {
- VTD_Get_Real_Time( &timehi1, &timelo1 );
- timelo = timelo1 - timelo;
- }
- UpdateStore( Sequence++, timelo, "%stRenamet%st%st%s",
- processname, fullpathname,
- FilemonConvertPath( Drive, pir->ir_ppath2, data ),
- ErrorString( retval ));
- }
- break;
- case IFSFN_IOCTL16DRIVE:
- if( FilemonGetProcess( processname ) == FILTERPASS && (FilterDef.logreads || FilterDef.logwrites)) {
- if( TimeIsDuration ) {
- VTD_Get_Real_Time( &timehi1, &timelo1 );
- timelo = timelo1 - timelo;
- }
- sprintf(data, "Subfunction: %02Xh", pir->ir_flags );
- drivestring[0] = Drive+'A'-1;
- drivestring[1] = ':';
- drivestring[2] = 0;
- UpdateStore( Sequence++, timelo, "%stIoctlt%st%st%s",
- processname, drivestring, data, ErrorString( retval ));
- }
- break;
- }
- dprintf("==>%dn", fn );
- return retval;
- }
- #pragma optimize("", on)
- //----------------------------------------------------------------------
- //
- // OnSysDynamicDeviceInit
- //
- // Dynamic init. Hook all registry related VxD APIs.
- //
- //----------------------------------------------------------------------
- BOOL OnSysDynamicDeviceInit()
- {
- int i;
- //
- // Initialize the locks.
- //
- StoreMutex = Create_Semaphore(1);
- HashMutex = Create_Semaphore(1);
- FilterMutex = Create_Semaphore(1);
- //
- // Zero hash table.
- //
- for(i = 0; i < NUMHASH; i++ ) HashTable[i] = NULL;
- //
- // Allocate the initial output buffer.
- //
- PageAllocate(STORESIZE, PG_SYS, 0, 0, 0, 0, NULL, PAGELOCKED,
- (PMEMHANDLE) &Store, (PVOID) &Store );
- Store->Len = 0;
- Store->Next = NULL;
- NumStore = 1;
- //
- // Hook IFS functions.
- //
- PrevIFSHookProc = IFSMgr_InstallFileSystemApiHook(FilemonHookProc);
- return TRUE;
- }
- //----------------------------------------------------------------------
- //
- // OnSysDynamicDeviceExit
- //
- // Dynamic exit. Unhook everything.
- //
- //----------------------------------------------------------------------
- BOOL OnSysDynamicDeviceExit()
- {
- //
- // Unhook IFS functions.
- //
- IFSMgr_RemoveFileSystemApiHook(FilemonHookProc);
- //
- // Free all memory.
- //
- FilemonHashCleanup();
- FilemonFreeStore();
- FilemonFreeFilters();
- return TRUE;
- }
- //----------------------------------------------------------------------
- //
- // OnW32Deviceiocontrol
- //
- // Interface with the GUI.
- //
- //----------------------------------------------------------------------
- DWORD OnW32Deviceiocontrol(PIOCTLPARAMS p)
- {
- PSTORE_BUF old;
- switch( p->dioc_IOCtlCode ) {
- case 0:
- return 0;
- case IOCTL_FILEMON_ZEROSTATS:
- Wait_Semaphore( StoreMutex, BLOCK_SVC_INTS );
- while ( Store->Next ) {
- //
- // Release the next entry.
- //
- old = Store->Next;
- Store->Next = old->Next;
- Signal_Semaphore( StoreMutex );
- PageFree( (MEMHANDLE) old, 0 );
- Wait_Semaphore( StoreMutex, BLOCK_SVC_INTS );
- NumStore--;
- }
- Store->Len = 0;
- Signal_Semaphore( StoreMutex );
- Sequence = 0;
- return 0;
- case IOCTL_FILEMON_GETSTATS:
- //
- // Copy buffer into user space.
- Wait_Semaphore( StoreMutex, BLOCK_SVC_INTS );
- if ( MAX_STORE > p->dioc_cbOutBuf ) {
- //
- // Buffer is too small. Return error.
- //
- Signal_Semaphore( StoreMutex );
- return 1;
- } else if ( Store->Len || Store->Next ) {
- //
- // Switch to a new buffer.
- //
- FilemonNewStore();
- //
- // Fetch the oldest buffer to give to caller.
- //
- old = FilemonOldestStore();
- Signal_Semaphore( StoreMutex );
- //
- // Copy it into the caller's buffer.
- //
- memcpy( p->dioc_OutBuf, old->Data, old->Len );
- //
- // Return length of copied info.
- //
- *p->dioc_bytesret = old->Len;
- //
- // Deallocate the buffer.
- //
- PageFree( (MEMHANDLE) old, 0 );
- } else {
- //
- // There is no unread data.
- //
- Signal_Semaphore( StoreMutex );
- *p->dioc_bytesret = 0;
- }
- return 0;
- case IOCTL_FILEMON_STOPFILTER:
- FilterOn = FALSE;
- return 0;
- case IOCTL_FILEMON_STARTFILTER:
- FilterOn = TRUE;
- return 0;
- case IOCTL_FILEMON_SETFILTER:
- FilterDef = * (PFILTER) p->dioc_InBuf;
- FilemonUpdateFilters();
- return 0;
- case IOCTL_FILEMON_TIMETYPE:
- TimeIsDuration = * (PBOOLEAN) p->dioc_InBuf;
- return 0;
- default:
- return 1;
- }
- }