FILEMON.C
上传用户:hmgghm
上传日期:2007-01-07
资源大小:335k
文件大小:48k
源码类别:

文件操作

开发平台:

Visual C++

  1. //======================================================================
  2. //
  3. // FILEMON.c - main module for VxD FILEMON
  4. //
  5. // By Mark Russinovich and Bryce Cogswell
  6. //
  7. //======================================================================
  8. #define   DEVICE_MAIN
  9. #include  <vtoolsc.h>
  10. #include  "..guiioctlcmd.h"
  11. #include  "filemon.h"
  12. #undef    DEVICE_MAIN
  13. #if DEBUG
  14. #define dprint(arg) dprintf arg
  15. #else
  16. #define dprint(arg)
  17. #endif
  18. //----------------------------------------------------------------------
  19. //                     G L O B A L   D A T A 
  20. //----------------------------------------------------------------------
  21. //
  22. // Indicates if the GUI wants activity to be logged
  23. //
  24. BOOLEAN                 FilterOn = FALSE;
  25. //
  26. // Global filter (sent to us by the GUI)
  27. //
  28. FILTER                  FilterDef;
  29. //
  30. // Array of process and path filters 
  31. //
  32. ULONG                   NumIncludeFilters = 0;
  33. PCHAR                   IncludeFilters[MAXFILTERS];
  34. ULONG                   NumExcludeFilters = 0;
  35. PCHAR                   ExcludeFilters[MAXFILTERS];
  36. //
  37. // Real service pointers with the hook thunks
  38. //
  39. ppIFSFileHookFunc       PrevIFSHookProc;
  40. //
  41. // Hash table data 
  42. //
  43. PHASH_ENTRY         HashTable[NUMHASH];
  44. //
  45. // List of freed entries (to save some allocation calls)
  46. //
  47. PHASH_ENTRY         FreeEntries = NULL;
  48. //
  49. // Buffer data
  50. //
  51. PSTORE_BUF         Store  = NULL;
  52. ULONG         Sequence  = 0;
  53. //
  54. // Maximum amount of buffers we will grab for buffered unread data
  55. //
  56. ULONG         NumStore  = 0;
  57. ULONG         MaxStore  = 5;
  58. //
  59. // Semaphore for critical sections
  60. //
  61. SEMHANDLE               StoreMutex, HashMutex, FilterMutex;
  62. //
  63. // Unknown error string
  64. //
  65. CHAR                    errstring[32];
  66. //
  67. // Measuring duration or absolute time
  68. //
  69. BOOLEAN                 TimeIsDuration = TRUE;
  70. //----------------------------------------------------------------------
  71. //                   V X D  C O N T R O L
  72. //----------------------------------------------------------------------
  73. //
  74. // Device declaration
  75. //
  76. Declare_Virtual_Device(FILEMON)
  77. //
  78. // Message handlers - we only care about dynamic loading and unloading
  79. //
  80.     DefineControlHandler(SYS_DYNAMIC_DEVICE_INIT, OnSysDynamicDeviceInit);
  81.     DefineControlHandler(SYS_DYNAMIC_DEVICE_EXIT, OnSysDynamicDeviceExit);
  82.     DefineControlHandler(W32_DEVICEIOCONTROL, OnW32Deviceiocontrol);
  83. //----------------------------------------------------------------------
  84. // 
  85. // ControlDispatcher
  86. //
  87. // Multiplexes incoming VxD messages from Windows to their handlers.
  88. //
  89. //----------------------------------------------------------------------
  90.     BOOL __cdecl ControlDispatcher(
  91.         DWORD dwControlMessage,
  92.         DWORD EBX,
  93.         DWORD EDX,
  94.         DWORD ESI,
  95.         DWORD EDI,
  96.         DWORD ECX)
  97. {
  98.     START_CONTROL_DISPATCH
  99.         ON_SYS_DYNAMIC_DEVICE_INIT(OnSysDynamicDeviceInit);
  100.     ON_SYS_DYNAMIC_DEVICE_EXIT(OnSysDynamicDeviceExit);
  101.     ON_W32_DEVICEIOCONTROL(OnW32Deviceiocontrol);
  102.     END_CONTROL_DISPATCH
  103.         return TRUE;
  104. }
  105. //----------------------------------------------------------------------
  106. //      P A T T E R N   M A T C H I N G   R O U T I N E S
  107. //----------------------------------------------------------------------
  108. //----------------------------------------------------------------------
  109. //
  110. // MatchOkay
  111. //
  112. // Only thing left after compare is more mask. This routine makes
  113. // sure that its a valid wild card ending so that its really a match.
  114. //
  115. //----------------------------------------------------------------------
  116. BOOLEAN MatchOkay( PCHAR Pattern )
  117. {
  118.     //
  119.     // If pattern isn't empty, it must be a wildcard
  120.     //
  121.     if( *Pattern && *Pattern != '*' ) {
  122.  
  123.         return FALSE;
  124.     }
  125.     //
  126.     // Matched
  127.     //
  128.     return TRUE;
  129. }
  130. //----------------------------------------------------------------------
  131. //
  132. // MatchWithPattern
  133. //
  134. // Performs nifty wildcard comparison.
  135. //
  136. //----------------------------------------------------------------------
  137. BOOLEAN MatchWithPattern( PCHAR Pattern, PCHAR Name )
  138. {
  139.     CHAR   upcase;
  140.     //
  141.     // End of pattern?
  142.     //
  143.     if( !*Pattern ) {
  144.         return FALSE;
  145.     }
  146.     //
  147.     // If we hit a wild card, do recursion
  148.     //
  149.     if( *Pattern == '*' ) {
  150.         Pattern++;
  151.         while( *Name && *Pattern ) {
  152.             if( *Name >= 'a' && *Name <= 'z' )
  153.                 upcase = *Name - 'a' + 'A';
  154.             else
  155.                 upcase = *Name;
  156.             //
  157.             // See if this substring matches
  158.             //
  159.             if( *Pattern == upcase || *Name == '*' ) {
  160.                 if( MatchWithPattern( Pattern+1, Name+1 )) {
  161.                     return TRUE;
  162.                 }
  163.             }
  164.             //
  165.             // Try the next substring
  166.             //
  167.             Name++;
  168.         }
  169.         //
  170.         // See if match condition was met
  171.         //
  172.         return MatchOkay( Pattern );
  173.     } 
  174.     //
  175.     // Do straight compare until we hit a wild card
  176.     //
  177.     while( *Name && *Pattern != '*' ) {
  178.         if( *Name >= 'a' && *Name <= 'z' )
  179.             upcase = *Name - 'a' + 'A';
  180.         else
  181.             upcase = *Name;
  182.         if( *Pattern == upcase ) {
  183.             Pattern++;
  184.             Name++;
  185.         } else {
  186.             return FALSE;
  187.         }
  188.     }
  189.     //
  190.     // If not done, recurse
  191.     //
  192.     if( *Name ) {
  193.         return MatchWithPattern( Pattern, Name );
  194.     }
  195.     //
  196.     // Make sure its a match
  197.     //
  198.     return MatchOkay( Pattern );
  199. }
  200. //----------------------------------------------------------------------
  201. //            B U F F E R   M A N A G E M E N T
  202. //----------------------------------------------------------------------
  203. //----------------------------------------------------------------------
  204. //
  205. // FilemonFreeStore
  206. //
  207. // Frees all the data output buffers that we have currently allocated.
  208. //
  209. //----------------------------------------------------------------------
  210. VOID FilemonFreeStore()
  211. {
  212.     PSTORE_BUF  prev;
  213.     
  214.     //
  215.     // Just traverse the list of allocated output buffers
  216.     //
  217.     while( Store ) {
  218.         prev = Store->Next;
  219.         PageFree( (MEMHANDLE) Store, 0 );
  220.         Store = prev;
  221.     }
  222. }
  223. //----------------------------------------------------------------------
  224. //
  225. // FilemonNewStore
  226. //
  227. // Called when the current buffer has filled up. This moves us to the
  228. // pre-allocated buffer and then allocates another buffer.
  229. //
  230. // Returns FALSE if another thread is already allocating a buffer.
  231. //
  232. //----------------------------------------------------------------------
  233. BOOLEAN FilemonNewStore( void )
  234. {
  235.     PSTORE_BUF prev = Store, newstore;
  236.     static busyAllocating = FALSE;
  237.     //
  238.     // If we have maxed out or haven't accessed the current store
  239.     // just return.
  240.     //
  241.     if( MaxStore == NumStore ) {
  242.         Store->Len = 0;
  243.         return TRUE;
  244.     }
  245.     //
  246.     // If the output buffer we currently are using is empty, just
  247.     // use it, or if we are busy already allocating a buffer, return
  248.     //
  249.     if( !Store->Len || busyAllocating ) 
  250.         return !busyAllocating;
  251.     //
  252.     // Allocate a new output buffer. Release lock to prevent deadlock
  253.     // on reentrance (allocating memory can result in file I/O
  254.     //
  255.     busyAllocating = TRUE;
  256.     Signal_Semaphore( StoreMutex );
  257.     PageAllocate(STORESIZE, PG_SYS, 0, 0, 0, 0, NULL, PAGELOCKED, 
  258.                  (PMEMHANDLE) &newstore, (PVOID) &newstore );
  259.     Wait_Semaphore( StoreMutex, BLOCK_SVC_INTS );
  260.     busyAllocating = FALSE;
  261.     if( newstore ) { 
  262.         //
  263.         // Allocation was successful so add the buffer to the list
  264.         // of allocated buffers and increment the buffer count.
  265.         //
  266.         Store   = newstore;
  267.         Store->Len  = 0;
  268.         Store->Next = prev;
  269.         NumStore++;
  270.     } else {
  271.         //
  272.         // The allocation failed - just reuse the current buffer
  273.         //
  274.         Store->Len = 0;
  275.     }
  276.     Signal_Semaphore( StoreMutex );
  277.     return TRUE;
  278. }
  279. //----------------------------------------------------------------------
  280. //
  281. // FilemonOldestStore
  282. //
  283. // Goes through the linked list of storage buffers and returns the 
  284. // oldest one.
  285. //
  286. //----------------------------------------------------------------------
  287. PSTORE_BUF FilemonOldestStore( void )
  288. {
  289.     PSTORE_BUF  ptr = Store, prev = NULL;
  290.     //
  291.     // Traverse the list
  292.     //    
  293.     while ( ptr->Next ) {
  294.         ptr = (prev = ptr)->Next;
  295.     }
  296.     //
  297.     // Remove the buffer from the list
  298.     //
  299.     if ( prev ) {
  300.         prev->Next = NULL;    
  301.     }
  302.     NumStore--;
  303.     return ptr;
  304. }
  305. //----------------------------------------------------------------------
  306. //
  307. // FilemonResetStore
  308. //
  309. // When a GUI is no longer communicating with us, but we can't unload,
  310. // we reset the storage buffers.
  311. //
  312. //----------------------------------------------------------------------
  313. VOID FilemonResetStore()
  314. {
  315.     PSTORE_BUF  current, next;
  316.     //
  317.     // Traverse the list of output buffers
  318.     //
  319.     current = Store->Next;
  320.     while( current ) {
  321.         //
  322.         // Free the buffer
  323.         //
  324.         next = current->Next;
  325.         PageFree( (MEMHANDLE) current, 0 );
  326.         current = next;
  327.     }
  328.     // 
  329.     // Move the output pointer in the buffer that's being kept
  330.     // the start of the buffer.
  331.     // 
  332.     Store->Len = 0;
  333.     Store->Next = NULL;
  334. }
  335. //----------------------------------------------------------------------
  336. //
  337. // UpdateStore
  338. //
  339. // Add a new string to Store, if it fits.
  340. //
  341. //----------------------------------------------------------------------
  342. void UpdateStore( ULONG seq, ULONG time, const char * format, ... )
  343. {
  344.     PENTRY Entry;
  345.     ULONG len;
  346.     va_list arg_ptr;
  347.     CHAR        text[MAXPATHLEN];
  348.     //
  349.     // If no filtering is desired, don't bother
  350.     //
  351.     if( !FilterOn ) {
  352.  
  353.         return;
  354.     }
  355.     //
  356.     // Lock the output buffer.
  357.     //
  358.     Wait_Semaphore( StoreMutex, BLOCK_SVC_INTS );
  359.     //
  360.     // Vsprintf to determine length of the buffer
  361.     //
  362.     _asm cld;
  363.     va_start( arg_ptr, format );
  364.     len = vsprintf( text, format, arg_ptr );
  365.     va_end( arg_ptr );
  366.     //
  367.     // If the current output buffer is near capacity, move to a new
  368.     // output buffer
  369.     //
  370.     if( (ULONG) (Store->Len + len + sizeof(ENTRY) +1) >= MAX_STORE ) {
  371.         if( !FilemonNewStore() ) {
  372.   
  373.             //
  374.             // Just return if a thread is in the process
  375.             // of allocating a buffer.
  376.             //
  377.             Signal_Semaphore( StoreMutex );
  378.             return;
  379.         }
  380.     } 
  381.     //
  382.     // Extract the sequence number and store it
  383.     //
  384.     Entry = (void *)(Store->Data+Store->Len);
  385.     Entry->seq = seq;
  386.     Entry->time.u.LowPart = time;
  387.     Entry->time.u.HighPart = 0;
  388.     _asm cld;
  389.     memcpy( Entry->text, text, len + 1 );
  390.  
  391.     //
  392.     // Store the length of the string, plus 1 for the terminating
  393.     // NULL  
  394.     //   
  395.     Store->Len += (Entry->text - (PCHAR) Entry) + len + 1;
  396.  
  397.     //
  398.     // Release the output buffer lock
  399.     //
  400.     Signal_Semaphore( StoreMutex );
  401. }
  402. //----------------------------------------------------------------------
  403. //       H A S H   T A B L E   M A N A G E M E N T
  404. //----------------------------------------------------------------------
  405. //----------------------------------------------------------------------
  406. //
  407. // FilemonHashCleanup
  408. //
  409. // Called when we are unloading to free any memory that we have 
  410. // in our possession.
  411. //
  412. //----------------------------------------------------------------------
  413. VOID FilemonHashCleanup()
  414. {
  415.     PHASH_ENTRY hashEntry, nextEntry;
  416.     ULONG i;
  417.   
  418.     //
  419.     // First, free the hash table entries
  420.     //
  421.     for( i = 0; i < NUMHASH; i++ ) {
  422.         hashEntry = HashTable[i];
  423.         while( hashEntry ) {
  424.             nextEntry = hashEntry->Next;
  425.             HeapFree( hashEntry->FullName, 0 );
  426.             HeapFree( hashEntry, 0 );
  427.             hashEntry = nextEntry;
  428.         }
  429.     }
  430.     //
  431.     // Now, free structures on our free list
  432.     //
  433.     while( FreeEntries ) {
  434.         nextEntry = FreeEntries->Next;
  435.         HeapFree( FreeEntries, 0 );
  436.         FreeEntries = nextEntry;
  437.     }
  438. }
  439. //----------------------------------------------------------------------
  440. //
  441. // FilemonStoreHash
  442. //
  443. // Stores the key and associated fullpath in the hash table.
  444. //
  445. //----------------------------------------------------------------------
  446. VOID FilemonStoreHash( sfn_t filenumber, PCHAR fullname )
  447. {
  448.     PHASH_ENTRY     newEntry;
  449.     Wait_Semaphore( HashMutex, BLOCK_SVC_INTS );
  450.     //
  451.     // Find or allocate an entry to use.
  452.     //
  453.     if( FreeEntries ) {
  454.         newEntry    = FreeEntries;
  455.         FreeEntries = FreeEntries->Next;
  456.         Signal_Semaphore( HashMutex );
  457.     } else {
  458.     
  459.         //
  460.         // Have to release the lock, because memory allocation can 
  461.         // cause re-entrancy.
  462.         //
  463.         Signal_Semaphore( HashMutex );
  464.         newEntry = HeapAllocate( sizeof(HASH_ENTRY), 0 );
  465.         //
  466.         // Is there memory for the allocation?
  467.         //
  468.         if( !newEntry ) return;
  469.     }
  470.     //
  471.     // Initialize the new entry.
  472.     //
  473.     newEntry->filenumber          = filenumber;
  474.     newEntry->FullName            = HeapAllocate( strlen(fullname)+1, 0);
  475.     //
  476.     // Make sure the allocation succeeded.
  477.     //
  478.     if( !newEntry->FullName ) {
  479.         HeapFree( newEntry, 0 );
  480.         return;
  481.     }
  482.     strcpy( newEntry->FullName, fullname );
  483.     //
  484.     // Lock the hash table and insert the new entry.
  485.     //
  486.     Wait_Semaphore( HashMutex, BLOCK_SVC_INTS );
  487.     newEntry->Next = HashTable[ HASHOBJECT(filenumber) ];
  488.     HashTable[ HASHOBJECT(filenumber) ] = newEntry;
  489.     Signal_Semaphore( HashMutex );
  490. }
  491. //----------------------------------------------------------------------
  492. //
  493. // FilemonFreeHashEntry
  494. //
  495. // When we see a file close, we can free the string we had associated
  496. // with the fileobject being closed since we know it won't be used
  497. // again.
  498. //
  499. //----------------------------------------------------------------------
  500. VOID FilemonFreeHashEntry( sfn_t filenumber )
  501. {
  502.     PHASH_ENTRY hashEntry, prevEntry;
  503.     Wait_Semaphore( HashMutex, BLOCK_SVC_INTS );
  504.     //
  505.     // Look-up the entry.
  506.     //
  507.     hashEntry = HashTable[ HASHOBJECT( filenumber ) ];
  508.     prevEntry = NULL;
  509.     while( hashEntry && hashEntry->filenumber != filenumber ) {
  510.         prevEntry = hashEntry;
  511.         hashEntry = hashEntry->Next;
  512.     }
  513.     //  
  514.     // If we fall of the hash list without finding what we're looking
  515.     // for, just return.
  516.     //
  517.     if( !hashEntry ) {
  518.         Signal_Semaphore( HashMutex );
  519.         return;
  520.     }
  521.     //
  522.     // Got it! Remove it from the list
  523.     //
  524.     if( prevEntry ) {
  525.         prevEntry->Next = hashEntry->Next;
  526.     } else {
  527.         HashTable[ HASHOBJECT( filenumber )] = hashEntry->Next;
  528.     }
  529.     //
  530.     // Free the memory associated with the name of the free entry.
  531.     //
  532.     hashEntry->Next  = FreeEntries;
  533.     FreeEntries  = hashEntry;
  534.     Signal_Semaphore( HashMutex );
  535.     //
  536.     // Free the memory associated with it
  537.     //
  538.     HeapFree( hashEntry->FullName, 0 );
  539. }
  540. //----------------------------------------------------------------------
  541. //       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
  542. //----------------------------------------------------------------------
  543. //----------------------------------------------------------------------
  544. //
  545. // ErrorString
  546. //
  547. // Returns the string form of an error code.
  548. //
  549. //----------------------------------------------------------------------
  550. PCHAR ErrorString( DWORD retval )
  551. {
  552.     switch( retval ) {
  553.     case ERROR_INVALID_FUNCTION:
  554.         return "INVALIDFUNC"; 
  555.     case ERROR_SUCCESS:
  556.         return "SUCCESS";
  557.     case ERROR_OUTOFMEMORY:
  558.         return "OUTOFMEM";
  559.     case ERROR_ACCESS_DENIED:
  560.         return "ACCDENIED";
  561.     case ERROR_PATH_NOT_FOUND:
  562.         return "NOTFOUND";
  563.     case ERROR_TOO_MANY_OPEN_FILES:
  564.         return "TOOMANYOPEN";
  565.     case ERROR_FILE_NOT_FOUND:
  566.         return "NOTFOUND";
  567.     case ERROR_NO_MORE_ITEMS:
  568.         return "NOMORE";
  569.     case ERROR_GEN_FAILURE:
  570.         return "GENFAILURE";
  571.     case ERROR_MORE_DATA:
  572.         return "MOREDATA";
  573.     case ERROR_INVALID_DRIVE:
  574.         return "INVALIDDRIVE";
  575.     case ERROR_NOT_SAME_DEVICE:
  576.         return "DIFFERENTDEVICE";
  577.     case ERROR_WRITE_PROTECT:
  578.         return "WRITEPROTECTED";
  579.     case ERROR_SHARING_VIOLATION:
  580.         return "SHARING";
  581.     case ERROR_BAD_UNIT:
  582.         return "BADUNIT";
  583.     case ERROR_NOT_READY:
  584.         return "NOTREADY";
  585.     case ERROR_NO_MORE_FILES:
  586.         return "NOMORE";
  587.     case ERROR_BAD_COMMAND:
  588.         return "BADCOMMAND";
  589.     default:
  590.         sprintf(errstring, "0x%x", retval );
  591.         return errstring;
  592.     }
  593. }
  594. //----------------------------------------------------------------------
  595. //
  596. // FilemonFreeFilters
  597. //
  598. // Fress storage we allocated for filter strings.
  599. //
  600. //----------------------------------------------------------------------
  601. VOID FilemonFreeFilters()
  602. {
  603.     ULONG   i;
  604.     for( i = 0; i < NumIncludeFilters; i++ ) {
  605.         HeapFree( IncludeFilters[i], 0 );
  606.     }
  607.     for( i = 0; i < NumExcludeFilters; i++ ) {
  608.         HeapFree( ExcludeFilters[i], 0 );
  609.     }
  610.     NumIncludeFilters = 0;
  611.     NumExcludeFilters = 0;
  612. }
  613. //----------------------------------------------------------------------
  614. //
  615. // MakeFilterArray
  616. //
  617. // Takes a filter string and splits into components (a component
  618. // is seperated with a ';')
  619. //
  620. //----------------------------------------------------------------------
  621. VOID MakeFilterArray( PCHAR FilterString,
  622.                       PCHAR FilterArray[],
  623.                       PULONG NumFilters )
  624. {
  625.     PCHAR filterStart;
  626.     ULONG filterLength;
  627.     //
  628.     // Scan through the process filters
  629.     //
  630.     filterStart = FilterString;
  631.     while( *filterStart ) {
  632.         filterLength = 0;
  633.         while( filterStart[filterLength] &&
  634.                filterStart[filterLength] != ';' ) {
  635.             filterLength++;
  636.         }
  637.         //
  638.         // Ignore zero-length components
  639.         //
  640.         if( filterLength ) {
  641.             FilterArray[ *NumFilters ] = 
  642.                 HeapAllocate( filterLength + 1, 0 );
  643.             strncpy( FilterArray[ *NumFilters ],
  644.                      filterStart, filterLength );
  645.             FilterArray[ *NumFilters ][filterLength] = 0;
  646.             (*NumFilters)++;
  647.         }
  648.     
  649.         //
  650.         // Are we done?
  651.         //
  652.         if( !filterStart[filterLength] ) break;
  653.         //
  654.         // Move to the next component (skip over ';')
  655.         //
  656.         filterStart += filterLength + 1;
  657.     }
  658. }
  659. //----------------------------------------------------------------------
  660. //
  661. // FilemonUpdateFilters
  662. //
  663. // Takes a new filter specification and updates the filter
  664. // arrays with them.
  665. //
  666. //----------------------------------------------------------------------
  667. VOID FilemonUpdateFilters()
  668. {
  669.     //
  670.     // Free old filters (if any)
  671.     //
  672.     Wait_Semaphore( FilterMutex, BLOCK_SVC_INTS );
  673.     FilemonFreeFilters();
  674.     //
  675.     // Create new filter arrays
  676.     //
  677.     MakeFilterArray( FilterDef.includefilter,
  678.                      IncludeFilters, &NumIncludeFilters );
  679.     MakeFilterArray( FilterDef.excludefilter,
  680.                      ExcludeFilters, &NumExcludeFilters );
  681.     Signal_Semaphore( FilterMutex );
  682. }
  683. //----------------------------------------------------------------------
  684. //
  685. // wstrlen
  686. //
  687. // Determine the length of a wide-character string.
  688. //
  689. //----------------------------------------------------------------------
  690. int wstrlen( unsigned short *unistring )
  691. {
  692.     int i = 0;
  693.     int len = 0;
  694.   
  695.     while( unistring[i++] != 0 ) len+=2;
  696.     return len;
  697. }
  698. //----------------------------------------------------------------------
  699. //
  700. // FilmonGetProcess
  701. //
  702. // Retrieves the process name.
  703. //
  704. //----------------------------------------------------------------------
  705. FILTERSTATUS FilemonGetProcess( PCHAR ProcessName )
  706. {
  707.     PVOID       CurProc;
  708.     PVOID       ring3proc;
  709.     char        *name;
  710.     ULONG       i;
  711.     //
  712.     // Get the ring0 process pointer.
  713.     //
  714.     CurProc = VWIN32_GetCurrentProcessHandle();
  715.   
  716.     //
  717.     // Now, map the ring3 PCB 
  718.     //
  719.     ring3proc = (PVOID) SelectorMapFlat( Get_Sys_VM_Handle(), 
  720.                                          (DWORD) (*(PDWORD) ((char *) CurProc + 0x38)) | 0x7, 0 );
  721.     if( ring3proc == (PVOID) -1 ) {
  722.         strcpy( ProcessName, "???");
  723.     } else {
  724.         //
  725.         // copy out the process name (max 8 characters)
  726.         //
  727.         name = ((char *)ring3proc) + 0xF2;
  728.         if( name[0] >= 'A' && name[0] < 'z' ) {
  729.             strcpy( ProcessName, name );
  730.             ProcessName[8] = 0;
  731.         } else {
  732.             strcpy( ProcessName, "???" );
  733.         }
  734.     }
  735.     //
  736.     // Ignore filemon-generated output
  737.     //
  738.     if( !stricmp( ProcessName, "Filemon" )) return FILTERFAIL;
  739.     //
  740.     // Apply process name filters
  741.     //
  742.     Wait_Semaphore( FilterMutex, BLOCK_SVC_INTS );
  743.     for( i = 0; i < NumExcludeFilters; i++ ) {
  744.         if( MatchWithPattern( ExcludeFilters[i], ProcessName )) {
  745.             Signal_Semaphore( FilterMutex );
  746.             return FILTERFAIL;
  747.         }
  748.     }
  749.     for( i = 0; i < NumIncludeFilters; i++ ) {
  750.         if( MatchWithPattern( IncludeFilters[i], ProcessName ) ) {
  751.             Signal_Semaphore( FilterMutex );
  752.             return FILTERPASS;
  753.         }
  754.     }
  755.     Signal_Semaphore( FilterMutex );
  756.     return FILTERNOMATCH;
  757. }
  758. //----------------------------------------------------------------------
  759. //
  760. // ApplyNameFilter
  761. //
  762. // If the name matches the exclusion mask, we do not log it. Else if
  763. // it doesn't match the inclusion mask we do not log it. 
  764. //
  765. //----------------------------------------------------------------------
  766. FILTERSTATUS ApplyNameFilter( PCHAR fullname )
  767. {
  768.     ULONG    i;
  769.     //   
  770.     // If it matches the exclusion string, do not log it
  771.     //
  772.     Wait_Semaphore( FilterMutex, BLOCK_SVC_INTS );
  773.     for( i = 0; i < NumExcludeFilters; i++ ) {
  774.         if( MatchWithPattern( ExcludeFilters[i], fullname ) ) {
  775.             Signal_Semaphore( FilterMutex );
  776.             return FILTERFAIL;
  777.         }
  778.     }
  779.  
  780.     //
  781.     // If it matches an include filter then log it
  782.     //
  783.     for( i = 0; i < NumIncludeFilters; i++ ) {
  784.         if( MatchWithPattern( IncludeFilters[i], fullname )) {
  785.             Signal_Semaphore( FilterMutex );
  786.             return FILTERPASS;
  787.         }
  788.     }
  789.     //
  790.     // It didn't match any include filters so don't log
  791.     //
  792.     Signal_Semaphore( FilterMutex );
  793.     return FILTERNOMATCH;
  794. }
  795. //----------------------------------------------------------------------
  796. //
  797. // ApplyFilters
  798. //
  799. // Gets the process name and then performs filtering logic.
  800. //
  801. //----------------------------------------------------------------------
  802. BOOLEAN ApplyFilters( PCHAR ProcessName, PCHAR FullName )
  803. {
  804.     FILTERSTATUS   filterStatus, nameFilterStatus;
  805.     //
  806.     // Try the process filter
  807.     //
  808.     filterStatus = FilemonGetProcess( ProcessName );
  809.     if( filterStatus == FILTERPASS ||
  810. filterStatus == FILTERNOMATCH ) {
  811.         //
  812.         // Try the path filter
  813.         //
  814.         nameFilterStatus = ApplyNameFilter( FullName );
  815.         if( (filterStatus == FILTERPASS && nameFilterStatus != FILTERFAIL) ||
  816.             nameFilterStatus == FILTERPASS ) {
  817.             
  818.             return TRUE;
  819.         }
  820.     } 
  821.     return FALSE;
  822. }
  823. //----------------------------------------------------------------------
  824. //
  825. // FilemonConvertPath
  826. //
  827. // Converts a unicode path name to ANSI.
  828. //
  829. //----------------------------------------------------------------------
  830. PCHAR FilemonConvertPath( int drive, path_t ppath, PCHAR fullpathname )
  831. {
  832.     int  i = 0;
  833.     _QWORD  result;
  834.     //
  835.     // Stick on the drive letter if we know it.
  836.     //
  837.     if( drive != 0xFF ) {
  838.  
  839.         fullpathname[0] = drive+'A'-1;
  840.         fullpathname[1] = ':';
  841.         i = 2;
  842.     } 
  843.     UniToBCSPath( &fullpathname[i], ppath->pp_elements, MAXPATHLEN, BCS_WANSI, &result );
  844.     return( fullpathname );
  845. }
  846. //----------------------------------------------------------------------
  847. //
  848. // FilemonGetFullPath
  849. //
  850. // Returns the full pathname of a file, if we can obtain one, else
  851. // returns a handle.
  852. //
  853. //----------------------------------------------------------------------
  854. PCHAR FilemonGetFullPath(  sfn_t filenumber, PCHAR fullname,
  855.                            int Drive, int ResType, int CodePage, pioreq pir )
  856. {
  857.     PHASH_ENTRY hashEntry;
  858.     pIFSFunc        enumFunc;
  859.     ifsreq          ifsr;
  860.     path_t          uniFullName;
  861.     int             retval;
  862.     //
  863.     // See if we find the key in the hash table.
  864.     //
  865.     Wait_Semaphore( HashMutex, BLOCK_SVC_INTS );
  866.     hashEntry = HashTable[ HASHOBJECT( filenumber ) ];
  867.     while( hashEntry && hashEntry->filenumber != filenumber ) {
  868.         hashEntry = hashEntry->Next;
  869.     }
  870.     Signal_Semaphore( HashMutex );
  871.     fullname[0] = 0;
  872.     if( hashEntry ) {
  873.         strcpy( fullname, hashEntry->FullName );
  874.     } else {
  875.         //
  876.         // File name isn't in the table, so ask the
  877.         // underlying file system
  878.         //
  879.         sprintf( fullname, "0x%X", filenumber );
  880.         uniFullName = IFSMgr_GetHeap( MAXPATHLEN );
  881.         if( uniFullName ) {
  882.             
  883.             //
  884.             // Send a query file name request
  885.             //
  886.             memcpy( &ifsr, pir, sizeof( ifsreq ));
  887.             ifsr.ifsir.ir_flags = ENUMH_GETFILENAME;
  888.             ifsr.ifsir.ir_ppath = uniFullName;
  889.             enumFunc = ifsr.ifs_hndl->hf_misc->hm_func[HM_ENUMHANDLE];
  890.             retval = (*PrevIFSHookProc)(enumFunc, IFSFN_ENUMHANDLE, 
  891.                                         Drive, ResType, CodePage, 
  892.                                         (pioreq) &ifsr);
  893.             if( retval == ERROR_SUCCESS ) {
  894.                 
  895.                 FilemonConvertPath( Drive, uniFullName, fullname );
  896.                 FilemonStoreHash( filenumber, fullname );
  897.             }
  898.             IFSMgr_RetHeap( (void *) uniFullName );
  899.         } 
  900.     }
  901.     return fullname;
  902. }
  903. //----------------------------------------------------------------------
  904. //
  905. // FilemonHookProc
  906. //
  907. // All (most) IFS functions come through this routine for us to look
  908. // at.
  909. //
  910. //----------------------------------------------------------------------
  911. #pragma optimize("", off)
  912. int _cdecl FilemonHookProc(pIFSFunc pfn, int fn, int Drive, int ResType,
  913.                            int CodePage, pioreq pir)
  914. {
  915.     int                retval;
  916.     char               fullpathname[MAXPATHLEN];
  917.     char               processname[64];
  918.     char               data[256];
  919.     char               drivestring[4];
  920.     ioreq              origir;
  921.     _WIN32_FIND_DATA   *finddata;
  922.     struct srch_entry  *search;
  923.     BOOLEAN            log;
  924.     _QWORD             result;
  925.     DWORD              timelo, timehi;
  926.     DWORD              timelo1, timehi1;
  927.     int                i, j;
  928.     // 
  929.     // Inititlize default data.
  930.     //
  931.     data[0] = 0;
  932.     //
  933.     // Save original iorequest because some entries get modified.
  934.     //
  935.     origir = *pir;
  936.     //
  937.     // Get the current process name.
  938.     //
  939.     FilemonGetProcess( processname );
  940.     //
  941.     // Get the time
  942.     //
  943.     if( TimeIsDuration ) {
  944.         VTD_Get_Real_Time( &timehi, &timelo );
  945.     } else {
  946.         timelo = IFSMgr_Get_DOSTime( &timehi );
  947.     }       
  948.     //
  949.     // Call the previous hooker first, to get the return code.
  950.     //
  951.     retval = (*PrevIFSHookProc)(pfn, fn, Drive, ResType, CodePage, pir);
  952.     //
  953.     // Now extract parameters based on the function type.
  954.     //
  955.     switch( fn ) {
  956.     case IFSFN_OPEN:
  957.         FilemonConvertPath( Drive, pir->ir_ppath, fullpathname );
  958.         if( ApplyFilters( processname, fullpathname )) {
  959.             if( TimeIsDuration ) {
  960.                 VTD_Get_Real_Time( &timehi1, &timelo1 );
  961.                 timelo = timelo1 - timelo;
  962.             }
  963.             sprintf(data,"");
  964.             if( origir.ir_options & ACTION_CREATENEW ) strcat(data,"CREATENEW ");
  965.             if( origir.ir_options & ACTION_OPENEXISTING ) strcat(data,"OPENEXISTING ");
  966.             if( origir.ir_options & ACTION_REPLACEEXISTING ) strcat(data,"REPLACEEXISTING ");
  967.             switch (origir.ir_flags & ACCESS_MODE_MASK) {
  968.             case ACCESS_READONLY:
  969.                 strcat(data,"READONLY ");
  970.                 break;
  971.             case ACCESS_WRITEONLY:
  972.                 strcat(data,"WRITEONLY ");
  973.                 break;
  974.             case ACCESS_READWRITE:
  975.                 strcat(data,"READWRITE ");
  976.                 break;
  977.             case ACCESS_EXECUTE:
  978.                 strcat(data,"EXECUTE ");
  979.                 break;
  980.             default:
  981.                 break;
  982.             }
  983.             switch (origir.ir_flags & SHARE_MODE_MASK) {
  984.             case SHARE_COMPATIBILITY:
  985.                 strcat(data,"COMPATIBILITY ");
  986.                 break;
  987.             case SHARE_DENYREADWRITE:
  988.                 strcat(data,"DENYREADWRITE ");
  989.                 break;
  990.             case SHARE_DENYWRITE:
  991.                 strcat(data,"DENYWRITE ");
  992.                 break;
  993.             case SHARE_DENYREAD:
  994.                 strcat(data,"DENYREAD ");
  995.                 break;
  996.             case SHARE_DENYNONE:
  997.                 strcat(data,"DENYNONE ");
  998.                 break;
  999.             default:
  1000.                 break;
  1001.             }
  1002.             UpdateStore( Sequence++, timelo, "%stOpent%st%st%s", 
  1003.                          processname, fullpathname,
  1004.                          data, ErrorString( retval ));
  1005.         }
  1006.         FilemonStoreHash( pir->ir_sfn, fullpathname );
  1007.         break;
  1008.     case IFSFN_READ:
  1009.     case IFSFN_WRITE:
  1010.         FilemonGetFullPath( pir->ir_sfn, fullpathname, Drive, ResType, CodePage, pir );
  1011.         if( ((fn == IFSFN_READ && FilterDef.logreads ) ||
  1012.              (fn == IFSFN_WRITE && FilterDef.logwrites )) &&
  1013.             ApplyFilters( processname, fullpathname )) {
  1014.             if( TimeIsDuration ) {
  1015.                 VTD_Get_Real_Time( &timehi1, &timelo1 );
  1016.                 timelo = timelo1 - timelo;
  1017.             }
  1018.             sprintf( data, "Offset: %ld Length: %ld", origir.ir_pos, origir.ir_length );
  1019.             UpdateStore( Sequence++, timelo, "%st%st%st%st%s", 
  1020.                          processname, fn == IFSFN_READ? "Read" : "Write", 
  1021.                          fullpathname,
  1022.                          data, ErrorString( retval ));
  1023.         }
  1024.         break;
  1025.     case IFSFN_CLOSE:
  1026.         FilemonGetFullPath( pir->ir_sfn, fullpathname, Drive, ResType, CodePage, pir );
  1027.         if( ApplyFilters( processname, fullpathname ) && FilterDef.logreads ) {
  1028.             if( TimeIsDuration ) {
  1029.                 VTD_Get_Real_Time( &timehi1, &timelo1 );
  1030.                 timelo = timelo1 - timelo;
  1031.             }
  1032.             switch( origir.ir_flags ) {
  1033.             case CLOSE_HANDLE:      sprintf(data, "CLOSE_HANDLE");      break;
  1034.             case CLOSE_FOR_PROCESS: sprintf(data, "CLOSE_FOR_PROCESS"); break;
  1035.             case CLOSE_FINAL:       sprintf(data, "CLOSE_FINAL");       break;
  1036.             default: sprintf(data,"0x%02X",origir.ir_flags);            break;
  1037.             }
  1038.             UpdateStore( Sequence++, timelo, "%stCloset%st%st%s", processname, 
  1039.                          fullpathname, data, ErrorString( retval ));
  1040.         }
  1041.         if ( origir.ir_flags == CLOSE_FINAL ) FilemonFreeHashEntry( origir.ir_sfn );
  1042.         break;
  1043.     case IFSFN_DIR:
  1044.         FilemonConvertPath( Drive, pir->ir_ppath, fullpathname );
  1045.         if( ApplyFilters( processname, fullpathname )) {
  1046.             if( TimeIsDuration ) {
  1047.                 VTD_Get_Real_Time( &timehi1, &timelo1 );
  1048.                 timelo = timelo1 - timelo;
  1049.             }
  1050.             log = FALSE;
  1051.             switch( pir->ir_flags ) {
  1052.             case CREATE_DIR:
  1053.                 sprintf(data, "CREATE");
  1054.                 if( FilterDef.logwrites ) log = TRUE;
  1055.                 break;
  1056.             case DELETE_DIR:
  1057.                 sprintf(data,"DELETE");
  1058.                 if( FilterDef.logwrites ) log = TRUE;
  1059.                 break;
  1060.             case CHECK_DIR:
  1061.                 sprintf(data,"CHECK");
  1062.                 if( FilterDef.logreads ) log = TRUE;
  1063.                 break;
  1064.             default:
  1065.                 sprintf(data,"QUERY");
  1066.                 if( FilterDef.logreads ) log = TRUE;
  1067.                 break;
  1068.             }
  1069.             if( log ) {
  1070.                 UpdateStore( Sequence++, timelo, "%stDirectoryt%st%st%s", 
  1071.                              processname, 
  1072.                              fullpathname,
  1073.                              data, ErrorString( retval ));
  1074.             }
  1075.         }
  1076.         break;
  1077.     case IFSFN_SEEK:
  1078.         FilemonGetFullPath( pir->ir_sfn, fullpathname, Drive, ResType, CodePage, pir );
  1079.         if( ApplyFilters( processname, fullpathname ) && FilterDef.logreads) {
  1080.             if( TimeIsDuration ) {
  1081.                 VTD_Get_Real_Time( &timehi1, &timelo1 );
  1082.                 timelo = timelo1 - timelo;
  1083.             }
  1084.             sprintf(data, "%s Offset: %ld",
  1085.                     pir->ir_flags == FILE_BEGIN ? "Beginning" : "End",
  1086.                     origir.ir_pos );
  1087.             UpdateStore( Sequence++, timelo, "%stSeekt%st%st%s", 
  1088.                          processname, fullpathname,
  1089.                          data, ErrorString( retval ));
  1090.         }
  1091.         break;
  1092.     case IFSFN_COMMIT:
  1093.         FilemonGetFullPath( pir->ir_sfn, fullpathname, Drive, ResType, CodePage, pir );
  1094.         if( ApplyFilters( processname, fullpathname ) && FilterDef.logwrites) {
  1095.             if( TimeIsDuration ) {
  1096.                 VTD_Get_Real_Time( &timehi1, &timelo1 );
  1097.                 timelo = timelo1 - timelo;
  1098.             }
  1099.             sprintf(data, "%s", pir->ir_options == FILE_COMMIT_ASYNC ? 
  1100.                     "ASYNC" : "NOACCESSUPDATE" );
  1101.             UpdateStore( Sequence++, timelo, "%stCommitt%st%st%s", 
  1102.                          processname, fullpathname,
  1103.                          data, ErrorString( retval ));
  1104.         }
  1105.         break;
  1106.     case IFSFN_FILELOCKS:
  1107.         FilemonGetFullPath( pir->ir_sfn, fullpathname, Drive, ResType, CodePage, pir );
  1108.         if( ApplyFilters( processname, fullpathname ) && FilterDef.logreads) {
  1109.             if( TimeIsDuration ) {
  1110.                 VTD_Get_Real_Time( &timehi1, &timelo1 );
  1111.                 timelo = timelo1 - timelo;
  1112.             }
  1113.             sprintf(data, "Offset: %ld Length:%ld", origir.ir_pos, origir.ir_locklen );
  1114.             UpdateStore( Sequence++, timelo, "%st%st%st%st%s", 
  1115.                          processname, origir.ir_flags == LOCK_REGION ? "Lock" : "Unlock",
  1116.                          fullpathname,
  1117.                          data, ErrorString( retval ));
  1118.         }
  1119.         break;
  1120.     case IFSFN_FINDOPEN:
  1121.         FilemonConvertPath( Drive, pir->ir_ppath, fullpathname ); 
  1122.         if( ApplyFilters( processname, fullpathname ) && FilterDef.logreads) {
  1123.             if( TimeIsDuration ) {
  1124.                 VTD_Get_Real_Time( &timehi1, &timelo1 );
  1125.                 timelo = timelo1 - timelo;
  1126.             }
  1127.             if( !retval ) {
  1128.                 finddata = (_WIN32_FIND_DATA *) pir->ir_data;
  1129.                 UniToBCS( data, finddata->cFileName, MAXPATHLEN, wstrlen(finddata->cFileName),BCS_WANSI, &result );
  1130.                 data[wstrlen(finddata->cFileName)/2] = 0;
  1131.             }
  1132.             UpdateStore( Sequence++, timelo, "%stFindOpent%st%st%s", 
  1133.                          processname, fullpathname,
  1134.                          data, ErrorString( retval ));
  1135.         }
  1136.         FilemonStoreHash( pir->ir_sfn, fullpathname );
  1137.         break;
  1138.     case IFSFN_FINDNEXT:
  1139.         FilemonGetFullPath( pir->ir_sfn, fullpathname, Drive, ResType, CodePage, pir );
  1140.         if( ApplyFilters( processname, fullpathname ) && FilterDef.logreads) {
  1141.             if( TimeIsDuration ) {
  1142.                 VTD_Get_Real_Time( &timehi1, &timelo1 );
  1143.                 timelo = timelo1 - timelo;
  1144.             }
  1145.             if( !retval ) {
  1146.                 finddata = (_WIN32_FIND_DATA *) pir->ir_data;
  1147.                 UniToBCS( data, finddata->cFileName, MAXPATHLEN, wstrlen(finddata->cFileName),BCS_WANSI, &result );
  1148.                 data[wstrlen(finddata->cFileName)/2] = 0;
  1149.             }
  1150.             UpdateStore( Sequence++, timelo, "%stFindNextt%st%st%s", 
  1151.                          processname, fullpathname,
  1152.                          data, ErrorString( retval ));
  1153.         }
  1154.         break;
  1155.     case IFSFN_FINDCLOSE:
  1156.         FilemonGetFullPath( pir->ir_sfn, fullpathname, Drive, ResType, CodePage, pir );
  1157.         if( ApplyFilters( processname, fullpathname ) && FilterDef.logreads) {
  1158.             if( TimeIsDuration ) {
  1159.                 VTD_Get_Real_Time( &timehi1, &timelo1 );
  1160.                 timelo = timelo1 - timelo;
  1161.             }
  1162.             UpdateStore( Sequence++, timelo, "%stFindCloset%stt%s", 
  1163.                          processname, fullpathname,
  1164.                          ErrorString( retval ));
  1165.         }
  1166.         FilemonFreeHashEntry( pir->ir_sfn );
  1167.         break;
  1168.     case IFSFN_FILEATTRIB:
  1169.         FilemonConvertPath( Drive, pir->ir_ppath, fullpathname );
  1170.         if( ApplyFilters( processname, fullpathname ) && FilterDef.logreads) {    
  1171.             if( TimeIsDuration ) {
  1172.                 VTD_Get_Real_Time( &timehi1, &timelo1 );
  1173.                 timelo = timelo1 - timelo;
  1174.             }
  1175.             switch(origir.ir_flags ) {
  1176.             case GET_ATTRIBUTES:
  1177.                 sprintf(data,"GetAttributes");
  1178.                 break;
  1179.             case SET_ATTRIBUTES:
  1180.                 sprintf(data, "SetAttributes" );
  1181.                 break;
  1182.             case GET_ATTRIB_COMP_FILESIZE:
  1183.                 sprintf(data, "GET_ATTRIB_COMP_FILESIZE" );
  1184.                 break;
  1185.             case SET_ATTRIB_MODIFY_DATETIME:
  1186.                 sprintf(data, "SET_ATTRIB_MODIFY_DATETIME");
  1187.                 break;
  1188.             case SET_ATTRIB_LAST_ACCESS_DATETIME:
  1189.                 sprintf(data, "SET_ATTRIB_LAST_ACCESS_DATETIME");
  1190.                 break;
  1191.             case GET_ATTRIB_LAST_ACCESS_DATETIME:
  1192.                 sprintf(data, "GET_ATTRIB_LAST_ACCESS_DATETIME");
  1193.                 break;
  1194.             case SET_ATTRIB_CREATION_DATETIME:
  1195.                 sprintf(data, "SET_ATTRIB_CREATION_DATETIME");
  1196.                 break;
  1197.             case GET_ATTRIB_CREATION_DATETIME:
  1198.                 sprintf(data, "GET_ATTRIB_CREATION_DATETIME");
  1199.                 break;
  1200.             }
  1201.             UpdateStore( Sequence++, timelo, "%stAttributest%st%st%s", 
  1202.                          processname, fullpathname,
  1203.                          data, ErrorString( retval ));
  1204.         }
  1205.         break;
  1206.     case IFSFN_FILETIMES:
  1207.         FilemonGetFullPath( pir->ir_sfn, fullpathname, Drive, ResType, CodePage, pir );
  1208.         if( ApplyFilters( processname, fullpathname ) && FilterDef.logreads) {
  1209.             if( TimeIsDuration ) {
  1210.                 VTD_Get_Real_Time( &timehi1, &timelo1 );
  1211.                 timelo = timelo1 - timelo;
  1212.             }
  1213.             switch( pir->ir_flags ) {
  1214.             case GET_MODIFY_DATETIME:
  1215.                 sprintf(data, "Get Modify");
  1216.                 break;
  1217.             case SET_MODIFY_DATETIME:
  1218.                 sprintf(data, "Set Modify");
  1219.                 break;
  1220.             case GET_LAST_ACCESS_DATETIME:
  1221.                 sprintf(data, "Get Access");
  1222.                 break;
  1223.             case SET_LAST_ACCESS_DATETIME:
  1224.                 sprintf(data, "Set Access");
  1225.                 break;
  1226.             case GET_CREATION_DATETIME:
  1227.                 sprintf(data, "Get Creation");
  1228.                 break;
  1229.             case SET_CREATION_DATETIME:
  1230.                 sprintf(data, "Set Creation");
  1231.                 break;
  1232.             }
  1233.             UpdateStore( Sequence++, timelo, "%stAttributest%st%st%s", 
  1234.                          processname, fullpathname,
  1235.                          data, ErrorString( retval ));
  1236.         }
  1237.         break;
  1238.     case IFSFN_FLUSH:
  1239.         if( FilemonGetProcess(processname) == FILTERPASS && FilterDef.logwrites) {
  1240.             if( TimeIsDuration ) {
  1241.                 VTD_Get_Real_Time( &timehi1, &timelo1 );
  1242.                 timelo = timelo1 - timelo;
  1243.             }
  1244.             UpdateStore( Sequence++, timelo, "%stFlushVolumettt%s",
  1245.                          processname, ErrorString( retval ));
  1246.         }
  1247.         break;
  1248.     case IFSFN_DELETE:
  1249.         FilemonConvertPath( Drive, pir->ir_ppath, fullpathname );
  1250.         if( ApplyFilters( processname, fullpathname ) && FilterDef.logwrites) {    
  1251.             if( TimeIsDuration ) {
  1252.                 VTD_Get_Real_Time( &timehi1, &timelo1 );
  1253.                 timelo = timelo1 - timelo;
  1254.             }
  1255.             UpdateStore( Sequence++, timelo, "%stDeletet%stt%s", 
  1256.                          processname, fullpathname,
  1257.                          ErrorString( retval ));
  1258.         }
  1259.         FilemonFreeHashEntry( pir->ir_sfn );
  1260.         break;
  1261.     case IFSFN_SEARCH:
  1262.         if( pir->ir_flags == SEARCH_FIRST ) 
  1263.             FilemonConvertPath( Drive, pir->ir_ppath, fullpathname );
  1264.         else
  1265.             sprintf(fullpathname, "SearchNext" );
  1266.         if( ApplyFilters( processname, fullpathname ) && FilterDef.logreads ) {
  1267.             if( TimeIsDuration ) {
  1268.                 VTD_Get_Real_Time( &timehi1, &timelo1 );
  1269.                 timelo = timelo1 - timelo;
  1270.             }
  1271.             if( !retval ) {
  1272.                 j = 0;
  1273.                 if( origir.ir_attr & FILE_ATTRIBUTE_LABEL ) {
  1274.                     sprintf(data, "VolumeLabel: " );
  1275.                     j = strlen( data );
  1276.                 }
  1277.                 search = (struct srch_entry *) origir.ir_data;
  1278.                 for( i = 0; i < 13; i++ ) 
  1279.                     if( search->se_name[i] != ' ' ) data[j++] = search->se_name[i];
  1280.                 data[j] = 0;
  1281.             }
  1282.             UpdateStore( Sequence++, timelo, "%stSearcht%st%st%s", 
  1283.                          processname, fullpathname, data, ErrorString( retval ));    
  1284.         }
  1285.         break;
  1286.     
  1287.     case IFSFN_GETDISKINFO:
  1288.         if( FilemonGetProcess( processname ) == FILTERPASS && FilterDef.logreads ) {
  1289.             if( TimeIsDuration ) {
  1290.                 VTD_Get_Real_Time( &timehi1, &timelo1 );
  1291.                 timelo = timelo1 - timelo;
  1292.             }
  1293.             if( !retval ) sprintf(data, "Free Space");
  1294.             drivestring[0] = Drive+'A'-1;
  1295.             drivestring[1] = ':';
  1296.             drivestring[2] = 0;
  1297.             UpdateStore( Sequence++, timelo, "%stGetDiskInfot%st%st%s",
  1298.                          processname, drivestring, data, ErrorString( retval ));
  1299.         }
  1300.         break;
  1301.     case IFSFN_RENAME:
  1302.         FilemonConvertPath( Drive, pir->ir_ppath, fullpathname );
  1303.         if( ApplyFilters( processname, fullpathname ) && FilterDef.logwrites) {          
  1304.             if( TimeIsDuration ) {
  1305.                 VTD_Get_Real_Time( &timehi1, &timelo1 );
  1306.                 timelo = timelo1 - timelo;
  1307.             }
  1308.             UpdateStore( Sequence++, timelo, "%stRenamet%st%st%s",
  1309.                          processname, fullpathname,
  1310.                          FilemonConvertPath( Drive, pir->ir_ppath2, data ),
  1311.                          ErrorString( retval ));  
  1312.         }
  1313.         break;
  1314.     case IFSFN_IOCTL16DRIVE:
  1315.         if( FilemonGetProcess( processname ) == FILTERPASS && (FilterDef.logreads || FilterDef.logwrites)) {
  1316.             if( TimeIsDuration ) {
  1317.                 VTD_Get_Real_Time( &timehi1, &timelo1 );
  1318.                 timelo = timelo1 - timelo;
  1319.             }
  1320.             sprintf(data, "Subfunction: %02Xh", pir->ir_flags );
  1321.             drivestring[0] = Drive+'A'-1;
  1322.             drivestring[1] = ':';
  1323.             drivestring[2] = 0;
  1324.             UpdateStore( Sequence++, timelo, "%stIoctlt%st%st%s",
  1325.                          processname, drivestring, data, ErrorString( retval ));
  1326.         }
  1327.         break;
  1328.     }
  1329.     dprintf("==>%dn", fn );
  1330.     return retval;
  1331. }
  1332. #pragma optimize("", on)
  1333. //----------------------------------------------------------------------
  1334. //
  1335. // OnSysDynamicDeviceInit
  1336. //
  1337. // Dynamic init. Hook all registry related VxD APIs.
  1338. //
  1339. //----------------------------------------------------------------------
  1340. BOOL OnSysDynamicDeviceInit()
  1341. {
  1342.     int i;
  1343.     //
  1344.     // Initialize the locks.
  1345.     //
  1346.     StoreMutex = Create_Semaphore(1);
  1347.     HashMutex  = Create_Semaphore(1);
  1348.     FilterMutex  = Create_Semaphore(1);
  1349.     // 
  1350.     // Zero hash table.
  1351.     //
  1352.     for(i = 0; i < NUMHASH; i++ ) HashTable[i] = NULL;
  1353.     //
  1354.     // Allocate the initial output buffer.
  1355.     //
  1356.     PageAllocate(STORESIZE, PG_SYS, 0, 0, 0, 0, NULL, PAGELOCKED, 
  1357.                  (PMEMHANDLE) &Store, (PVOID) &Store );
  1358.     Store->Len = 0;
  1359.     Store->Next = NULL;
  1360.     NumStore = 1;
  1361.     //
  1362.     // Hook IFS functions.
  1363.     //
  1364.     PrevIFSHookProc = IFSMgr_InstallFileSystemApiHook(FilemonHookProc);
  1365.     return TRUE;
  1366. }
  1367. //----------------------------------------------------------------------
  1368. //
  1369. // OnSysDynamicDeviceExit
  1370. //
  1371. // Dynamic exit. Unhook everything.
  1372. //
  1373. //----------------------------------------------------------------------
  1374. BOOL OnSysDynamicDeviceExit()
  1375. {
  1376.     //
  1377.     // Unhook IFS functions.
  1378.     //
  1379.     IFSMgr_RemoveFileSystemApiHook(FilemonHookProc);
  1380.     //
  1381.     // Free all memory.
  1382.     //
  1383.     FilemonHashCleanup();
  1384.     FilemonFreeStore();
  1385.     FilemonFreeFilters();
  1386.     return TRUE;
  1387. }
  1388. //----------------------------------------------------------------------
  1389. //
  1390. // OnW32Deviceiocontrol
  1391. //
  1392. // Interface with the GUI.
  1393. //
  1394. //----------------------------------------------------------------------
  1395. DWORD OnW32Deviceiocontrol(PIOCTLPARAMS p)
  1396. {
  1397.     PSTORE_BUF      old;
  1398.     switch( p->dioc_IOCtlCode ) {
  1399.     case 0:
  1400.         return 0;
  1401.     case IOCTL_FILEMON_ZEROSTATS:
  1402.         Wait_Semaphore( StoreMutex, BLOCK_SVC_INTS );
  1403.         while ( Store->Next )  {
  1404.  
  1405.             //
  1406.             // Release the next entry.
  1407.             //
  1408.             old = Store->Next;
  1409.             Store->Next = old->Next;
  1410.             Signal_Semaphore( StoreMutex );
  1411.             PageFree( (MEMHANDLE) old, 0 );
  1412.             Wait_Semaphore( StoreMutex, BLOCK_SVC_INTS );
  1413.             NumStore--;
  1414.         }
  1415.         Store->Len = 0;
  1416.         Signal_Semaphore( StoreMutex );
  1417.         Sequence = 0;
  1418.         return 0;
  1419.     case IOCTL_FILEMON_GETSTATS:
  1420.         //
  1421.         // Copy buffer into user space.
  1422.         Wait_Semaphore( StoreMutex, BLOCK_SVC_INTS );
  1423.         if ( MAX_STORE > p->dioc_cbOutBuf ) {
  1424.             //
  1425.             // Buffer is too small. Return error.
  1426.             //
  1427.             Signal_Semaphore( StoreMutex );
  1428.             return 1;
  1429.         } else if ( Store->Len  ||  Store->Next ) {
  1430.             //
  1431.             // Switch to a new buffer.
  1432.             //
  1433.             FilemonNewStore();
  1434.             //
  1435.             // Fetch the oldest buffer to give to caller.
  1436.             //
  1437.             old = FilemonOldestStore();
  1438.             Signal_Semaphore( StoreMutex );
  1439.             //
  1440.             // Copy it into the caller's buffer.
  1441.             //
  1442.             memcpy( p->dioc_OutBuf, old->Data, old->Len );
  1443.             //
  1444.             // Return length of copied info.
  1445.             //
  1446.             *p->dioc_bytesret = old->Len;
  1447.             //   
  1448.             // Deallocate the buffer.
  1449.             //
  1450.             PageFree( (MEMHANDLE) old, 0 );
  1451.         } else {
  1452.             //
  1453.             // There is no unread data.
  1454.             //
  1455.             Signal_Semaphore( StoreMutex );
  1456.             *p->dioc_bytesret = 0;
  1457.         }
  1458.         return 0;
  1459.     case IOCTL_FILEMON_STOPFILTER:
  1460.         FilterOn = FALSE;
  1461.         return 0;
  1462.     case IOCTL_FILEMON_STARTFILTER:
  1463.         FilterOn = TRUE;
  1464.         return 0;
  1465.     case IOCTL_FILEMON_SETFILTER:
  1466.         FilterDef = * (PFILTER) p->dioc_InBuf;
  1467.         FilemonUpdateFilters();
  1468.         return 0;
  1469.     case IOCTL_FILEMON_TIMETYPE:
  1470.         TimeIsDuration = * (PBOOLEAN) p->dioc_InBuf;
  1471.         return 0;
  1472.     default:
  1473.         return 1;
  1474.     }
  1475. }