REGMON.C
上传用户:kevenhsn
上传日期:2007-01-03
资源大小:251k
文件大小:50k
源码类别:

系统编程

开发平台:

Visual C++

  1. //======================================================================
  2. //
  3. // REGMON.c - main module for VxD REGMON
  4. //
  5. // Copyright(C) 1996-1999 Mark Russinovich and Bryce Cogswell
  6. // Systems Internals - http://www.sysinternals.com
  7. //
  8. //======================================================================
  9. #define   DEVICE_MAIN
  10. #include  <vtoolsc.h>
  11. #include  "..guiioctlcmd.h"
  12. #include  "regmon.h"
  13. #undef    DEVICE_MAIN
  14. #if DEBUG
  15. #define dprint(arg) dprintf arg
  16. #else
  17. #define dprint(arg)
  18. #endif
  19. //----------------------------------------------------------------------
  20. //                     G L O B A L   D A T A 
  21. //----------------------------------------------------------------------
  22. //
  23. // Real service pointers with the hook thunks
  24. //
  25. HDSC_Thunk ROKThunk;
  26. LONG (*RealRegOpenKey)(HKEY, PCHAR, PHKEY );
  27. HDSC_Thunk RCKThunk;
  28. LONG (*RealRegCloseKey)(HKEY );
  29. HDSC_Thunk RFKThunk;
  30. LONG (*RealRegFlushKey)(HKEY );
  31. HDSC_Thunk RCRKThunk;
  32. LONG (*RealRegCreateKey)(HKEY, PCHAR, PHKEY );
  33. HDSC_Thunk RDKThunk;
  34. LONG (*RealRegDeleteKey)(HKEY, PCHAR );
  35. HDSC_Thunk RDVThunk;
  36. LONG (*RealRegDeleteValue)(HKEY, PCHAR );
  37. HDSC_Thunk REKThunk;
  38. LONG (*RealRegEnumKey)(HKEY, DWORD, PCHAR, DWORD );
  39. HDSC_Thunk REVThunk;
  40. LONG (*RealRegEnumValue)(HKEY, DWORD, PCHAR, PDWORD, PDWORD, PDWORD,
  41.                          PBYTE, PDWORD );
  42. HDSC_Thunk RQIKThunk;
  43. LONG (*RealRegQueryInfoKey)(HKEY, PCHAR, PDWORD, DWORD, PDWORD, PDWORD,
  44.                             PDWORD, PDWORD, PDWORD, PDWORD, PDWORD, 
  45.                             PFILETIME );
  46. LONG (__stdcall *RealWin32RegQueryInfoKey)(PCLIENT_STRUCT, DWORD, 
  47.                                            HKEY, PDWORD, PDWORD, PDWORD, 
  48.                                            PDWORD, PDWORD );
  49. HDSC_Thunk RQVThunk;
  50. LONG (*RealRegQueryValue)( HKEY, PCHAR, PCHAR, PLONG );
  51. HDSC_Thunk RQVEThunk;
  52. LONG (*RealRegQueryValueEx)(HKEY, PCHAR, PDWORD, PDWORD, PBYTE, PDWORD );
  53. HDSC_Thunk RSVThunk;
  54. LONG (*RealRegSetValue)( HKEY, PCHAR, DWORD, PCHAR, DWORD );
  55. HDSC_Thunk RSVEThunk;
  56. LONG (*RealRegSetValueEx)(HKEY, PCHAR, DWORD, DWORD, PBYTE, DWORD );
  57. HDSC_Thunk RRPDKThunk;
  58. LONG (*RealRegRemapPreDefKey)(HKEY, HKEY );
  59. HDSC_Thunk RQMVThunk;
  60. LONG (*RealRegQueryMultipleValues)(HKEY, PVALENT, DWORD, PCHAR, PDWORD );
  61. HDSC_Thunk RCDKThunk;
  62. LONG (*RealRegCreateDynKey)( PCHAR, PVOID, PVOID, PVOID, DWORD, PVMMHKEY);
  63. //
  64. // Indicates if the GUI wants activity to be logged
  65. //
  66. BOOLEAN                 FilterOn = FALSE;
  67. //
  68. // Global filter (sent to us by the GUI)
  69. //
  70. FILTER                  FilterDef;
  71. //
  72. // Array of process and path filters 
  73. //
  74. ULONG                   NumProcessFilters = 0;
  75. PCHAR                   ProcessFilters[MAXFILTERS];
  76. ULONG                   NumProcessExcludeFilters = 0;
  77. PCHAR                   ProcessExcludeFilters[MAXFILTERS];
  78. ULONG                   NumPathIncludeFilters = 0;
  79. PCHAR                   PathIncludeFilters[MAXFILTERS];
  80. ULONG                   NumPathExcludeFilters = 0;
  81. PCHAR                   PathExcludeFilters[MAXFILTERS];
  82. //
  83. // Hash table data 
  84. //
  85. PHASH_ENTRY HashTable[NUMHASH];
  86. //
  87. // List of freed entries (to save some allocation calls)
  88. //
  89. PHASH_ENTRY FreeEntries = NULL;
  90. //
  91. // Buffer data
  92. //
  93. PSTORE_BUF Store  = NULL;
  94. ULONG Sequence  = 0;
  95. //
  96. // Maximum amount of buffers we will grab for buffered unread data
  97. //
  98. ULONG NumStore  = 0;
  99. ULONG MaxStore  = 5;
  100. //
  101. // Semaphore for critical sections
  102. //
  103. SEMHANDLE               StoreMutex, HashMutex, FilterMutex;
  104. //
  105. // Unknown error string
  106. //
  107. CHAR                    errstring[32];
  108. //
  109. // VMM's Win32 service table (at least one Win32 registry
  110. // call gets routed through here, bypassing the
  111. // standard VMM VxD service entry points!)
  112. //
  113. PDWORD                  VMMWin32ServiceTable;
  114. //----------------------------------------------------------------------
  115. //                   V X D  C O N T R O L
  116. //----------------------------------------------------------------------
  117. //
  118. // Device declaration
  119. //
  120. Declare_Virtual_Device(REGMON)
  121. //
  122. // Message handlers - we only care about dynamic loading and unloading
  123. //
  124.     DefineControlHandler(SYS_DYNAMIC_DEVICE_INIT, OnSysDynamicDeviceInit);
  125.     DefineControlHandler(SYS_DYNAMIC_DEVICE_EXIT, OnSysDynamicDeviceExit);
  126.     DefineControlHandler(W32_DEVICEIOCONTROL, OnW32Deviceiocontrol);
  127. //----------------------------------------------------------------------
  128. // 
  129. // ControlDispatcher
  130. //
  131. // Multiplexes incoming VxD messages from Windows to their handlers.
  132. //
  133. //----------------------------------------------------------------------
  134.     BOOL __cdecl ControlDispatcher(
  135.         DWORD dwControlMessage,
  136.         DWORD EBX,
  137.         DWORD EDX,
  138.         DWORD ESI,
  139.         DWORD EDI,
  140.         DWORD ECX)
  141. {
  142.     START_CONTROL_DISPATCH
  143.         ON_SYS_DYNAMIC_DEVICE_INIT(OnSysDynamicDeviceInit);
  144.     ON_SYS_DYNAMIC_DEVICE_EXIT(OnSysDynamicDeviceExit);
  145.     ON_W32_DEVICEIOCONTROL(OnW32Deviceiocontrol);
  146.     END_CONTROL_DISPATCH
  147.         return TRUE;
  148. }
  149. //----------------------------------------------------------------------
  150. //      P A T T E R N   M A T C H I N G   R O U T I N E S
  151. //----------------------------------------------------------------------
  152. //----------------------------------------------------------------------
  153. //
  154. // MatchOkay
  155. //
  156. // Only thing left after compare is more mask. This routine makes
  157. // sure that its a valid wild card ending so that its really a match.
  158. //
  159. //----------------------------------------------------------------------
  160. BOOLEAN MatchOkay( PCHAR Pattern )
  161. {
  162.     //
  163.     // If pattern isn't empty, it must be a wildcard
  164.     //
  165.     if( *Pattern && *Pattern != '*' ) {
  166.  
  167.         return FALSE;
  168.     }
  169.     //
  170.     // Matched
  171.     //
  172.     return TRUE;
  173. }
  174. //----------------------------------------------------------------------
  175. //
  176. // MatchWithPattern
  177. //
  178. // Performs nifty wildcard comparison.
  179. //
  180. //----------------------------------------------------------------------
  181. BOOLEAN MatchWithPattern( PCHAR Pattern, PCHAR Name )
  182. {
  183.     CHAR   upcase;
  184.     //
  185.     // End of pattern?
  186.     //
  187.     if( !*Pattern ) {
  188.         return FALSE;
  189.     }
  190.     //
  191.     // If we hit a wild card, do recursion
  192.     //
  193.     if( *Pattern == '*' ) {
  194.         Pattern++;
  195.         while( *Name && *Pattern ) {
  196.             if( *Name >= 'a' && *Name <= 'z' )
  197.                 upcase = *Name - 'a' + 'A';
  198.             else
  199.                 upcase = *Name;
  200.             //
  201.             // See if this substring matches
  202.             //
  203.             if( *Pattern == upcase || *Name == '*' ) {
  204.                 if( MatchWithPattern( Pattern+1, Name+1 )) {
  205.                     return TRUE;
  206.                 }
  207.             }
  208.             //
  209.             // Try the next substring
  210.             //
  211.             Name++;
  212.         }
  213.         //
  214.         // See if match condition was met
  215.         //
  216.         return MatchOkay( Pattern );
  217.     } 
  218.     //
  219.     // Do straight compare until we hit a wild card
  220.     //
  221.     while( *Name && *Pattern != '*' ) {
  222.         if( *Name >= 'a' && *Name <= 'z' )
  223.             upcase = *Name - 'a' + 'A';
  224.         else
  225.             upcase = *Name;
  226.         if( *Pattern == upcase ) {
  227.             Pattern++;
  228.             Name++;
  229.         } else {
  230.             return FALSE;
  231.         }
  232.     }
  233.     //
  234.     // If not done, recurse
  235.     //
  236.     if( *Name ) {
  237.         return MatchWithPattern( Pattern, Name );
  238.     }
  239.     //
  240.     // Make sure its a match
  241.     //
  242.     return MatchOkay( Pattern );
  243. }
  244. //----------------------------------------------------------------------
  245. // B U F F E R  M A N A G E M E N T  A N D  P R I N T  R O U T I N E S
  246. //----------------------------------------------------------------------
  247. //----------------------------------------------------------------------
  248. //
  249. // RegmonFreeStore
  250. //
  251. // Frees all the data output buffers that we have currently allocated.
  252. //
  253. //----------------------------------------------------------------------
  254. VOID RegmonFreeStore()
  255. {
  256.     PSTORE_BUF  prev;
  257.     
  258.     //
  259.     // Just traverse the list of allocated output buffers
  260.     //
  261.     while( Store ) {
  262.         prev = Store->Next;
  263.         PageFree( (MEMHANDLE) Store, 0 );
  264.         Store = prev;
  265.     }
  266. }
  267. //----------------------------------------------------------------------
  268. //
  269. // RegmonNewStore
  270. //
  271. // Called when the current buffer has filled up. This moves us to the
  272. // pre-allocated buffer and then allocates another buffer.
  273. //
  274. //----------------------------------------------------------------------
  275. void RegmonNewStore( void )
  276. {
  277.     PSTORE_BUF prev = Store, newstore;
  278.     //
  279.     // If we have maxed out or haven't accessed the current store
  280.     // just return.
  281.     //
  282.     if( MaxStore == NumStore ) {
  283.         Store->Len = 0;
  284.         return;
  285.     }
  286.     //
  287.     // If the output buffer we currently are using is empty, just
  288.     // use it.
  289.     //
  290.     if( !Store->Len ) 
  291.         return;
  292.     //
  293.     // Allocate a new output buffer
  294.     //
  295.     PageAllocate(STORESIZE, PG_SYS, 0, 0, 0, 0, NULL, PAGELOCKED, 
  296.                  (PMEMHANDLE) &newstore, (PVOID) &newstore );
  297.     if( newstore ) { 
  298.         //
  299.         // Allocation was successful so add the buffer to the list
  300.         // of allocated buffers and increment the buffer count.
  301.         //
  302.         Store   = newstore;
  303.         Store->Len  = 0;
  304.         Store->Next = prev;
  305.         NumStore++;
  306.     } else {
  307.         //
  308.         // The allocation failed - just reuse the current buffer
  309.         //
  310.         Store->Len = 0;
  311.     }
  312. }
  313. //----------------------------------------------------------------------
  314. //
  315. // RegmonOldestStore
  316. //
  317. // Goes through the linked list of storage buffers and returns the 
  318. // oldest one.
  319. //
  320. //----------------------------------------------------------------------
  321. PSTORE_BUF RegmonOldestStore( void )
  322. {
  323.     PSTORE_BUF  ptr = Store, prev = NULL;
  324.     //
  325.     // Traverse the list
  326.     //    
  327.     while ( ptr->Next ) {
  328.         ptr = (prev = ptr)->Next;
  329.     }
  330.     //
  331.     // Remove the buffer from the list
  332.     //
  333.     if ( prev ) {
  334.         prev->Next = NULL;    
  335.     }
  336.     NumStore--;
  337.     return ptr;
  338. }
  339. //----------------------------------------------------------------------
  340. //
  341. // RegmonResetStore
  342. //
  343. // When a GUI is no longer communicating with us, but we can't unload,
  344. // we reset the storage buffers.
  345. //
  346. //----------------------------------------------------------------------
  347. VOID RegmonResetStore()
  348. {
  349.     PSTORE_BUF  current, next;
  350.     //
  351.     // Traverse the list of output buffers
  352.     //
  353.     current = Store->Next;
  354.     while( current ) {
  355.         //
  356.         // Free the buffer
  357.         //
  358.         next = current->Next;
  359.         PageFree( (MEMHANDLE) current, 0 );
  360.         current = next;
  361.     }
  362.     // 
  363.     // Move the output pointer in the buffer that's being kept
  364.     // the start of the buffer.
  365.     // 
  366.     Store->Len = 0;
  367.     Store->Next = NULL;
  368. }
  369. //----------------------------------------------------------------------
  370. //
  371. // UpdateStore
  372. //
  373. // Add a new string to Store, if it fits.
  374. //
  375. //----------------------------------------------------------------------
  376. void UpdateStore( ULONG seq, const char * format, ... )
  377. {
  378.     PENTRY Entry;
  379.     ULONG len;
  380.     va_list arg_ptr;
  381.     static CHAR text[MAXPATHLEN];
  382.     //
  383.     // If no filtering is desired, don't bother
  384.     //
  385.     if( !FilterOn ) {
  386.  
  387.         return;
  388.     }
  389.     //
  390.     // Lock the output buffer.
  391.     //
  392.     Wait_Semaphore( StoreMutex, BLOCK_SVC_INTS );
  393.     //
  394.     // Vsprintf to determine length of the buffer
  395.     //
  396.     _asm cld;
  397.     va_start( arg_ptr, format );
  398.     len = vsprintf( text, format, arg_ptr );
  399.     va_end( arg_ptr );
  400.     //
  401.     // If the current output buffer is near capacity, move to a new
  402.     // output buffer
  403.     //
  404.     if( (ULONG) (Store->Len + len + sizeof(ENTRY) +1) >= MAX_STORE ) {
  405.         RegmonNewStore();
  406.     }
  407.     //
  408.     // Extract the sequence number and store it
  409.     //
  410.     Entry = (void *)(Store->Data+Store->Len);
  411.     Entry->seq = seq;
  412.     _asm cld;
  413.     memcpy( Entry->text, text, len+1 );
  414.  
  415.     //
  416.     // Store the length of the string, plus 1 for the terminating
  417.     // NULL  
  418.     //   
  419.     Store->Len += sizeof(Entry->seq)+len+1;
  420.     //
  421.     // Release the output buffer lock
  422.     //
  423.     Signal_Semaphore( StoreMutex );
  424. }
  425. //----------------------------------------------------------------------
  426. //       H A S H   T A B L E   M A N A G E M E N T
  427. //----------------------------------------------------------------------
  428. //----------------------------------------------------------------------
  429. //
  430. // RegmonHashCleanup
  431. //
  432. // Called when we are unloading to free any memory that we have 
  433. // in our possession.
  434. //
  435. //----------------------------------------------------------------------
  436. VOID RegmonHashCleanup()
  437. {
  438.     PHASH_ENTRY hashEntry, nextEntry;
  439.     ULONG i;
  440.   
  441.     //
  442.     // First, free the hash table entries
  443.     //
  444.     for( i = 0; i < NUMHASH; i++ ) {
  445.         hashEntry = HashTable[i];
  446.         while( hashEntry ) {
  447.             nextEntry = hashEntry->Next;
  448.             HeapFree( hashEntry->FullName, 0 );
  449.             HeapFree( hashEntry, 0 );
  450.             hashEntry = nextEntry;
  451.         }
  452.     }
  453.     //
  454.     // Now, free structures on our free list
  455.     //
  456.     while( FreeEntries ) {
  457.         nextEntry = FreeEntries->Next;
  458.         HeapFree( FreeEntries, 0 );
  459.         FreeEntries = nextEntry;
  460.     }
  461. }
  462. //----------------------------------------------------------------------
  463. //
  464. // RegmonStoreHash
  465. //
  466. // Stores the key and associated fullpath in the hash table.
  467. //
  468. //----------------------------------------------------------------------
  469. VOID RegmonStoreHash( HKEY hkey, PCHAR fullname )
  470. {
  471.     PHASH_ENTRY     newEntry;
  472.     Wait_Semaphore( HashMutex, BLOCK_SVC_INTS );
  473.     //
  474.     // Find or allocate an entry to use
  475.     //
  476.     if( FreeEntries ) {
  477.         newEntry    = FreeEntries;
  478.         FreeEntries = FreeEntries->Next;
  479.     } else {
  480.         newEntry = HeapAllocate( sizeof(HASH_ENTRY), 0 );
  481.     }
  482.     //
  483.     // Initialize the new entry.
  484.     //
  485.     newEntry->hkey             = hkey;
  486.     newEntry->FullName          = HeapAllocate( strlen(fullname)+1, 0);
  487.     newEntry->Next = HashTable[ HASHOBJECT(hkey) ];
  488.     HashTable[ HASHOBJECT(hkey) ] = newEntry;
  489.     strcpy( newEntry->FullName, fullname );
  490.     Signal_Semaphore( HashMutex );
  491. }
  492. //----------------------------------------------------------------------
  493. //
  494. // RegmonFreeHashEntry
  495. //
  496. // When we see a file close, we can free the string we had associated
  497. // with the fileobject being closed since we know it won't be used
  498. // again.
  499. //
  500. //----------------------------------------------------------------------
  501. VOID RegmonFreeHashEntry( HKEY hkey )
  502. {
  503.     PHASH_ENTRY hashEntry, prevEntry;
  504.     Wait_Semaphore( HashMutex, BLOCK_SVC_INTS );
  505.     //
  506.     // Look-up the entry.
  507.     //
  508.     hashEntry = HashTable[ HASHOBJECT( hkey ) ];
  509.     prevEntry = NULL;
  510.     while( hashEntry && hashEntry->hkey != hkey ) {
  511.         prevEntry = hashEntry;
  512.         hashEntry = hashEntry->Next;
  513.     }
  514.   
  515.     //  
  516.     // If we fall of the hash list without finding what we're looking
  517.     // for, just return.
  518.     //
  519.     if( !hashEntry ) {
  520.         Signal_Semaphore( HashMutex );
  521.         return;
  522.     }
  523.     //
  524.     // Got it! Remove it from the list
  525.     //
  526.     if( prevEntry ) {
  527.         prevEntry->Next = hashEntry->Next;
  528.     } else {
  529.         HashTable[ HASHOBJECT( hkey )] = hashEntry->Next;
  530.     }
  531.     //
  532.     // Free the memory associated with it
  533.     //
  534.     HeapFree( hashEntry->FullName, 0 );
  535.     //
  536.     // Put it on our free list  
  537.     //
  538.     hashEntry->Next  = FreeEntries;
  539.     FreeEntries  = hashEntry;
  540.     Signal_Semaphore( HashMutex );
  541. }
  542. //----------------------------------------------------------------------
  543. //       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
  544. //----------------------------------------------------------------------
  545. //----------------------------------------------------------------------
  546. //
  547. // ErrorString
  548. //
  549. // Returns the string form of an error code.
  550. //
  551. //----------------------------------------------------------------------
  552. PCHAR ErrorString( DWORD retval )
  553. {
  554.     //
  555.     // Before transating, apply error filter
  556.     //
  557.     if( retval == ERROR_SUCCESS && !FilterDef.logsuccess ) return NULL;
  558.     if( retval != ERROR_SUCCESS && !FilterDef.logerror   ) return NULL;
  559.     //
  560.     // Passed filter, so log it
  561.     //
  562.     switch( retval ) {
  563.     case ERROR_SUCCESS:
  564.         return "SUCCESS";
  565.     case ERROR_KEY_DELETED:
  566.         return "KEYDELETED";
  567.     case ERROR_BADKEY:
  568.         return "BADKEY";
  569.     case ERROR_REGISTRY_IO_FAILED:
  570.         return "IOFAILED";
  571.     case ERROR_REGISTRY_CORRUPT:
  572.         return "CORRUPT";
  573.     case ERROR_BADDB:
  574.         return "BADDB";
  575.     case ERROR_OUTOFMEMORY:
  576.         return "OUTOFMEM";
  577.     case ERROR_ACCESS_DENIED:
  578.         return "ACCDENIED";
  579.     case ERROR_FILE_NOT_FOUND:
  580.         return "NOTFOUND";
  581.     case ERROR_NO_MORE_ITEMS:
  582.         return "NOMORE";
  583.     case ERROR_MORE_DATA:
  584.         return "MOREDATA";
  585.     default:
  586.         sprintf(errstring, "%xn", retval );
  587.         return errstring;
  588.     }
  589. }
  590. //----------------------------------------------------------------------
  591. //
  592. // RegmonFreeFilters
  593. //
  594. // Fress storage we allocated for filter strings.
  595. //
  596. //----------------------------------------------------------------------
  597. VOID RegmonFreeFilters()
  598. {
  599.     ULONG   i;
  600.     for( i = 0; i < NumProcessFilters; i++ ) {
  601.         HeapFree( ProcessFilters[i], 0 );
  602.     }
  603.     for( i = 0; i < NumProcessExcludeFilters; i++ ) {
  604.         HeapFree( ProcessExcludeFilters[i], 0 );
  605.     }
  606.     for( i = 0; i < NumPathIncludeFilters; i++ ) {
  607.         HeapFree( PathIncludeFilters[i], 0 );
  608.     }
  609.     for( i = 0; i < NumPathExcludeFilters; i++ ) {
  610.         HeapFree( PathExcludeFilters[i], 0 );
  611.     }
  612.     NumProcessFilters = 0;
  613.     NumProcessExcludeFilters = 0;
  614.     NumPathIncludeFilters = 0;
  615.     NumPathExcludeFilters = 0;
  616. }
  617. //----------------------------------------------------------------------
  618. //
  619. // MakeFilterArray
  620. //
  621. // Takes a filter string and splits into components (a component
  622. // is seperated with a ';')
  623. //
  624. //----------------------------------------------------------------------
  625. VOID MakeFilterArray( PCHAR FilterString,
  626.                       PCHAR FilterArray[],
  627.                       PULONG NumFilters )
  628. {
  629.     PCHAR filterStart;
  630.     ULONG filterLength;
  631.     //
  632.     // Scan through the process filters
  633.     //
  634.     filterStart = FilterString;
  635.     while( *filterStart ) {
  636.         filterLength = 0;
  637.         while( filterStart[filterLength] &&
  638.                filterStart[filterLength] != ';' ) {
  639.             filterLength++;
  640.         }
  641.         //
  642.         // Ignore zero-length components
  643.         //
  644.         if( filterLength ) {
  645.             FilterArray[ *NumFilters ] = 
  646.                 HeapAllocate( filterLength + 1, 0 );
  647.             strncpy( FilterArray[ *NumFilters ],
  648.                      filterStart, filterLength );
  649.             FilterArray[ *NumFilters ][filterLength] = 0;
  650.             (*NumFilters)++;
  651.         }
  652.     
  653.         //
  654.         // Are we done?
  655.         //
  656.         if( !filterStart[filterLength] ) break;
  657.         //
  658.         // Move to the next component (skip over ';')
  659.         //
  660.         filterStart += filterLength + 1;
  661.     }
  662. }
  663. //----------------------------------------------------------------------
  664. //
  665. // RegmonUpdateFilters
  666. //
  667. // Takes a new filter specification and updates the filter
  668. // arrays with them.
  669. //
  670. //----------------------------------------------------------------------
  671. VOID RegmonUpdateFilters()
  672. {
  673.     //
  674.     // Free old filters (if any)
  675.     //
  676.     Wait_Semaphore( FilterMutex, BLOCK_SVC_INTS );
  677.     RegmonFreeFilters();
  678.     //
  679.     // Create new filter arrays
  680.     //
  681.     MakeFilterArray( FilterDef.processfilter,
  682.                      ProcessFilters, &NumProcessFilters );
  683.     MakeFilterArray( FilterDef.processexclude,
  684.                      ProcessExcludeFilters, &NumProcessExcludeFilters );
  685.     MakeFilterArray( FilterDef.pathfilter,
  686.                      PathIncludeFilters, &NumPathIncludeFilters );
  687.     MakeFilterArray( FilterDef.excludefilter,
  688.                      PathExcludeFilters, &NumPathExcludeFilters );    
  689.     Signal_Semaphore( FilterMutex );
  690. }
  691. //----------------------------------------------------------------------
  692. //
  693. // GetProcess
  694. //
  695. // Retrieves the process name.
  696. //
  697. //----------------------------------------------------------------------
  698. PCHAR GetProcess( PCHAR ProcessName )
  699. {
  700.     PVOID       CurProc;
  701.     PVOID       ring3proc;
  702.     char        *name;
  703.     ULONG       i;
  704.     //
  705.     // Get the ring0 process pointer.
  706.     //
  707.     CurProc = VWIN32_GetCurrentProcessHandle();
  708.   
  709.     //
  710.     // Now, map the ring3 PCB 
  711.     //
  712.     ring3proc = (PVOID) SelectorMapFlat( Get_Sys_VM_Handle(), 
  713.                                          (DWORD) (*(PDWORD) ((char *) CurProc + 0x38)) | 0x7, 0 );
  714.     if( ring3proc == (PVOID) -1 ) {
  715.         strcpy( ProcessName, "???");
  716.         return ProcessName;
  717.     }
  718.     //
  719.     // copy out the process name (max 8 characters)
  720.     //
  721.     name = ((char *)ring3proc) + 0xF2;
  722.     if( name[0] >= 'A' && name[0] < 'z' ) {
  723.         strcpy( ProcessName, name );
  724.         ProcessName[8] = 0;
  725.     } else {
  726.         strcpy( ProcessName, "???" );
  727.     }
  728.     //
  729.     // Apply process name filters
  730.     //
  731.     Wait_Semaphore( FilterMutex, BLOCK_SVC_INTS );
  732.     for( i = 0; i < NumProcessExcludeFilters; i++ ) {
  733.         if( MatchWithPattern( ProcessExcludeFilters[i], ProcessName )) {
  734.             Signal_Semaphore( FilterMutex );
  735.             return NULL;
  736.         }
  737.     }
  738.     for( i = 0; i < NumProcessFilters; i++ ) {
  739.         if( MatchWithPattern( ProcessFilters[i], ProcessName ) ) {
  740.             Signal_Semaphore( FilterMutex );
  741.             return ProcessName;
  742.         }
  743.     }
  744.     Signal_Semaphore( FilterMutex );
  745.     return NULL;
  746. }
  747. //----------------------------------------------------------------------
  748. //
  749. // ApplyNameFilter
  750. //
  751. // If the name matches the exclusion mask, we do not log it. Else if
  752. // it doesn't match the inclusion mask we do not log it. 
  753. //
  754. //----------------------------------------------------------------------
  755. BOOLEAN ApplyNameFilter( PCHAR fullname )
  756. {
  757.     ULONG    i;
  758.     //   
  759.     // If it matches the exclusion string, do not log it
  760.     //
  761.     Wait_Semaphore( FilterMutex, BLOCK_SVC_INTS );
  762.     for( i = 0; i < NumPathExcludeFilters; i++ ) {
  763.         if( MatchWithPattern( PathExcludeFilters[i], fullname ) ) {
  764.             Signal_Semaphore( FilterMutex );
  765.             return FALSE;
  766.         }
  767.     }
  768.  
  769.     //
  770.     // If it matches an include filter then log it
  771.     //
  772.     for( i = 0; i < NumPathIncludeFilters; i++ ) {
  773.         if( MatchWithPattern( PathIncludeFilters[i], fullname )) {
  774.             Signal_Semaphore( FilterMutex );
  775.             return TRUE;
  776.         }
  777.     }
  778.     //
  779.     // It didn't match any include filters so don't log
  780.     //
  781.     Signal_Semaphore( FilterMutex );
  782.     return FALSE;
  783. }
  784. //----------------------------------------------------------------------
  785. //
  786. // GetFullName
  787. //
  788. // Returns the full pathname of a key, if we can obtain one, else
  789. // returns a handle.
  790. //
  791. //----------------------------------------------------------------------
  792. void GetFullName( HKEY hKey, PCHAR lpszSubKey, PCHAR lpszValue, 
  793.                   PCHAR fullname )
  794. {
  795.     PHASH_ENTRY hashEntry;
  796.     CHAR                tmpkey[16];
  797.     //
  798.     // See if we find the key in the hash table
  799.     //
  800.     fullname[0] = 0;
  801.     Wait_Semaphore( HashMutex, BLOCK_SVC_INTS );
  802.     hashEntry = HashTable[ HASHOBJECT( hKey ) ];
  803.     while( hashEntry && hashEntry->hkey != hKey ) {
  804.         hashEntry = hashEntry->Next;
  805.     }
  806.     Signal_Semaphore( HashMutex );
  807.     if( hashEntry ) {
  808.         strcpy( fullname, hashEntry->FullName );
  809.     } else {
  810.         //
  811.         // Okay, make a name
  812.         //
  813.         switch( hKey ) {
  814.         case HKEY_CLASSES_ROOT:
  815.             strcat(fullname, "HKCR");
  816.             break;
  817.         case HKEY_CURRENT_USER:
  818.             strcat(fullname, "HKCU");
  819.             break;
  820.         case HKEY_LOCAL_MACHINE:
  821.             strcat(fullname, "HKLM");
  822.             break;
  823.         case HKEY_USERS:
  824.             strcat(fullname, "HKU");
  825.             break;
  826.         case HKEY_CURRENT_CONFIG:
  827.             strcat(fullname, "HKCC");
  828.             break;
  829.         case HKEY_DYN_DATA:
  830.             strcat(fullname, "HKDD");
  831.             break;
  832.         default:
  833.             //
  834.             // We will only get here if key was created before we loaded
  835.             //
  836.             sprintf( tmpkey, "0x%X", hKey );
  837.             strcat(fullname, tmpkey );
  838.             break;
  839.         }
  840.     }
  841.     //
  842.     // Append subkey and value, if they are there
  843.     //
  844.     if( lpszSubKey ) {
  845.         if( lpszSubKey[0] ) {
  846.             strcat( fullname, "\" );
  847.             strcat( fullname, lpszSubKey );
  848.         }
  849.     }
  850.     if( lpszValue ) {
  851.         if( lpszValue[0] ) {
  852.             strcat( fullname, "\" );
  853.             strcat( fullname, lpszValue );
  854.         }
  855.     }
  856. }
  857. //----------------------------------------------------------------------
  858. // REGISTRY HOOKS
  859. //
  860. // All these hooks do essentially the same thing: dump API-specific
  861. // info into the data buffer, call the original handler, and then
  862. // dump any return information.
  863. //----------------------------------------------------------------------
  864. LONG HookRegOpenKey( HKEY hkey, PCHAR lpszSubKey, PHKEY phkResult) {
  865.     LONG     retval;
  866.     CHAR     fullname[NAMELEN], data[DATASIZE], process[PROCESSLEN];
  867.     GetFullName( hkey, lpszSubKey, NULL, fullname );
  868.     retval = RealRegOpenKey( hkey, lpszSubKey, phkResult );
  869.     data[0] = 0;
  870.     if( retval == ERROR_SUCCESS ) {
  871.         RegmonFreeHashEntry( *phkResult );
  872.         RegmonStoreHash( *phkResult, fullname );
  873.         sprintf(data,"hKey: 0x%X", *phkResult );
  874.     }  
  875.     if( GetProcess( process ) && ApplyNameFilter( fullname ) && ErrorString( retval ) &&
  876.         FilterDef.logreads ) {
  877.         UpdateStore( Sequence++, "%stOpenKeyt%st%st%s", 
  878.                      process, fullname, ErrorString( retval ), data);
  879.     }
  880.     return retval;
  881. }
  882. LONG HookRegCreateKey( HKEY hkey, PCHAR lpszSubKey, PHKEY phkResult) {
  883.     LONG      retval;
  884.     CHAR      fullname[NAMELEN], data[DATASIZE], process[PROCESSLEN];
  885.     GetFullName( hkey, lpszSubKey, NULL, fullname );
  886.     retval = RealRegCreateKey( hkey, lpszSubKey, phkResult );
  887.     data[0] = 0;
  888.     if( retval == ERROR_SUCCESS ) {
  889.         RegmonFreeHashEntry( *phkResult );
  890.         RegmonStoreHash( *phkResult, fullname );
  891.         sprintf(data,"hKey: 0x%X", *phkResult );
  892.     }
  893.     if( GetProcess( process ) && ApplyNameFilter( fullname ) && ErrorString( retval ) &&
  894.         FilterDef.logwrites ) {
  895.         UpdateStore( Sequence++, "%stCreateKeyt%st%st%s", 
  896.                      process, fullname, ErrorString( retval ), data);
  897.     }
  898.     return retval;
  899. }
  900. LONG HookRegDeleteKey( HKEY hkey, PCHAR lpszSubKey ) {
  901.     LONG      retval;
  902.     CHAR      fullname[NAMELEN], process[PROCESSLEN];
  903.     GetFullName( hkey, lpszSubKey, NULL, fullname );  
  904.     retval = RealRegDeleteKey( hkey, lpszSubKey );
  905.     if( GetProcess( process ) && ApplyNameFilter( fullname ) && ErrorString( retval ) &&
  906.         FilterDef.logwrites ) {
  907.         UpdateStore( Sequence++, "%stDeleteKeyt%st%s", 
  908.                      process, fullname, ErrorString( retval ));
  909.     }
  910.     return retval;
  911. }
  912. LONG HookRegDeleteValue( HKEY hkey, PCHAR lpszSubKey ) {
  913.     LONG      retval;
  914.     CHAR      fullname[NAMELEN], process[PROCESSLEN];
  915.     GetFullName( hkey, lpszSubKey, NULL, fullname );  
  916.     retval = RealRegDeleteValue( hkey, lpszSubKey );
  917.     if( GetProcess( process ) && ApplyNameFilter( fullname ) && ErrorString( retval ) &&
  918.         FilterDef.logwrites ) {
  919.         UpdateStore( Sequence++, "%stDeleteValuet%st%s", 
  920.                      process, fullname, ErrorString( retval ));
  921.     }
  922.     return retval;
  923. }
  924. LONG HookRegCloseKey(HKEY hkey) {
  925.     LONG      retval;
  926.     CHAR      fullname[NAMELEN], process[PROCESSLEN];
  927.     GetFullName( hkey, NULL, NULL, fullname );  
  928.     retval = RealRegCloseKey( hkey );
  929.     if( GetProcess( process ) && ApplyNameFilter( fullname ) && ErrorString( retval ) &&
  930.         FilterDef.logreads ) {
  931.         UpdateStore( Sequence++, "%stCloseKeyt%st%s", 
  932.                      process, fullname, ErrorString( retval ));
  933.     }
  934.     RegmonFreeHashEntry( hkey );
  935.     return retval;
  936. }
  937. LONG HookRegFlushKey( HKEY hkey ) {
  938.     LONG      retval;
  939.     CHAR      fullname[NAMELEN], process[PROCESSLEN];
  940.     GetFullName( hkey, NULL, NULL, fullname );  
  941.     retval = RealRegFlushKey( hkey );
  942.     if( GetProcess( process ) && ApplyNameFilter( fullname ) && ErrorString( retval ) &&
  943.         FilterDef.logwrites ) {
  944.         UpdateStore( Sequence++, "%stFlushKeyt%st%s", 
  945.                      process, fullname, ErrorString( retval ));
  946.     }
  947.     return retval;
  948. }
  949. LONG HookRegEnumKey(HKEY hkey, DWORD iSubKey, PCHAR lpszName, DWORD cchName) {
  950.     LONG      retval;
  951.     CHAR      fullname[NAMELEN], process[PROCESSLEN];
  952.   
  953.     GetFullName( hkey, NULL, NULL, fullname );
  954.     retval = RealRegEnumKey( hkey, iSubKey, lpszName, cchName );
  955.     if( GetProcess( process ) && ApplyNameFilter( fullname ) && ErrorString( retval ) &&
  956.         FilterDef.logreads ) {
  957.   
  958.         UpdateStore( Sequence++, "%stEnumKeyt%st%st%s", 
  959.                      process, fullname, 
  960.                      ErrorString( retval ),
  961.                      retval == ERROR_SUCCESS ? lpszName : "");  
  962.     }
  963.     return retval;
  964. }
  965. LONG HookRegEnumValue(HKEY hkey, DWORD iValue, PCHAR lpszValue, 
  966.                       PDWORD lpcchValue, PDWORD lpdwReserved, 
  967.                       PDWORD lpdwType, PBYTE lpbData, PDWORD lpcbData) {
  968.     LONG      retval;
  969.     int       i, len;
  970.     CHAR      fullname[NAMELEN], data[DATASIZE], tmp[2*BINARYLEN], process[PROCESSLEN];
  971.     GetFullName( hkey, NULL, NULL, fullname );
  972.     retval = RealRegEnumValue( hkey, iValue, lpszValue, lpcchValue,
  973.                                lpdwReserved, lpdwType, lpbData, lpcbData );
  974.     data[0] = 0;
  975.     if( retval == ERROR_SUCCESS && lpbData && *lpcbData ) {
  976.         strcat( data, lpszValue );
  977.         strcat( data, ": ");
  978.         if( !lpdwType || *lpdwType == REG_BINARY ) {
  979.             if( *lpcbData > BINARYLEN ) len = BINARYLEN;
  980.             else len = *lpcbData;
  981.             for( i = 0; i < len; i++ ) {
  982.                 sprintf( tmp, "%X ", lpbData[i]);
  983.                 strcat( data, tmp );
  984.             }
  985.             if( *lpcbData > BINARYLEN) strcat( data, "...");
  986.         } else if( *lpdwType == REG_SZ ) {
  987.             strcat( data, """);
  988.             strncat( data, lpbData, STRINGLEN );
  989.             strcat( data, """);
  990.         } else if( *lpdwType == REG_DWORD ) {
  991.             sprintf( tmp, "0x%X", *(PDWORD) lpbData );
  992.             strcat( data, tmp );
  993.         }
  994.     }
  995.     if( GetProcess( process ) && ApplyNameFilter( fullname ) && ErrorString( retval ) &&
  996.         FilterDef.logreads ) {
  997.         UpdateStore( Sequence++, "%stEnumValuet%st%st%s", 
  998.                      process, fullname, ErrorString( retval ),
  999.                      data ); 
  1000.     }
  1001.     return retval;
  1002. }
  1003. LONG HookRegQueryInfoKey( HKEY hKey, PCHAR lpszClass, PDWORD lpcchClass,  
  1004.                           DWORD lpdwReserved, PDWORD lpcSubKeys, 
  1005.                           PDWORD lpcchMaxSubKey, PDWORD  pcchMaxClass, 
  1006.                           PDWORD lpcValues, PDWORD lpcchMaxValueName, 
  1007.                           PDWORD lpcbMaxValueData, 
  1008.                           PDWORD lpcbSecurityDescriptor, 
  1009.                           PFILETIME lpftLastWriteTime) {
  1010.     LONG      retval;
  1011.     CHAR      fullname[NAMELEN], process[PROCESSLEN];
  1012.     GetFullName( hKey, NULL, NULL, fullname );
  1013.     retval = RealRegQueryInfoKey( hKey, lpszClass, lpcchClass, lpdwReserved, 
  1014.                                   lpcSubKeys, lpcchMaxSubKey, pcchMaxClass,
  1015.                                   lpcValues, lpcchMaxValueName,
  1016.                                   lpcbMaxValueData,
  1017.                                   lpcbSecurityDescriptor,
  1018.                                   lpftLastWriteTime );
  1019.     if( GetProcess( process ) && ApplyNameFilter( fullname ) && ErrorString( retval ) &&
  1020.         FilterDef.logreads ) {
  1021.         if( retval == ERROR_SUCCESS && lpcSubKeys && lpcValues ) 
  1022.             UpdateStore( Sequence++, "%stQueryKeyt%st%stKeys: %d Values: %d", 
  1023.                          process, fullname, ErrorString( retval ), *lpcSubKeys, *lpcValues );
  1024.         else
  1025.             UpdateStore( Sequence++, "%stQueryKeyt%st%s", 
  1026.                          process, fullname, ErrorString( retval ));  
  1027.     }
  1028.     return retval;
  1029. }
  1030. LONG HookRegQueryValue( HKEY hkey, PCHAR lpszSubKey, PCHAR lpszValue, 
  1031.                         PLONG pcbValue ) {
  1032.     LONG      retval;
  1033.     CHAR      fullname[NAMELEN], data[DATASIZE], process[PROCESSLEN];
  1034.     GetFullName( hkey, lpszSubKey, "(Default)", fullname );
  1035.     retval = RealRegQueryValue( hkey, lpszSubKey, lpszValue, pcbValue );
  1036.     data[0] = 0;
  1037.     if( retval == ERROR_SUCCESS && lpszValue && *pcbValue ) {
  1038.         strcpy( data, """);
  1039.         strncat( data, lpszValue, STRINGLEN );
  1040.         if( strlen( lpszValue ) > STRINGLEN ) 
  1041.             strcat( data, "..." );
  1042.         strcat( data, """);
  1043.     }
  1044.     if( GetProcess( process ) && ApplyNameFilter( fullname ) && ErrorString( retval ) &&
  1045.         FilterDef.logreads ) {
  1046.         UpdateStore( Sequence++, "%stQueryValuet%st%st%s", 
  1047.                      process, fullname, ErrorString( retval ), data);
  1048.     }
  1049.     return retval;
  1050. }
  1051. LONG HookRegQueryValueEx( HKEY hkey, PCHAR lpszValueName, 
  1052.                           PDWORD lpdwReserved, PDWORD lpdwType, 
  1053.                           PBYTE lpbData, PDWORD lpcbData ) {
  1054.     LONG      retval;
  1055.     int       i, len;
  1056.     CHAR      fullname[NAMELEN], data[DATASIZE], tmp[2*BINARYLEN], process[PROCESSLEN];
  1057.   
  1058.     GetFullName( hkey, NULL, lpszValueName, fullname );
  1059.     retval = RealRegQueryValueEx( hkey, lpszValueName, lpdwReserved, 
  1060.                                   lpdwType, lpbData, lpcbData );
  1061.     data[0] = 0;
  1062.     if( retval == ERROR_SUCCESS && lpbData ) {
  1063.         if( !lpdwType || *lpdwType == REG_BINARY ) {
  1064.             if( *lpcbData > BINARYLEN ) len = BINARYLEN;
  1065.             else len = *lpcbData;
  1066.             for( i = 0; i < len; i++ ) {
  1067.                 sprintf( tmp, "%X ", lpbData[i]);
  1068.                 strcat( data, tmp );
  1069.             }
  1070.             if( *lpcbData > BINARYLEN) strcat( data, "...");
  1071.         } else if( *lpdwType == REG_SZ ) {
  1072.             strcpy( data, """);
  1073.             strncat( data, lpbData, STRINGLEN );
  1074.             if( strlen( lpbData ) > STRINGLEN ) 
  1075.                 strcat( data, "..." );
  1076.             strcat( data, """);
  1077.         } else if( *lpdwType == REG_DWORD ) {
  1078.             sprintf( data, "0x%X", *(PDWORD) lpbData );
  1079.         }
  1080.     } 
  1081.     if( GetProcess( process ) && ApplyNameFilter( fullname ) && ErrorString( retval ) &&
  1082.         FilterDef.logreads) {
  1083.         UpdateStore( Sequence++, "%stQueryValueExt%st%st%s", 
  1084.                      process, fullname, ErrorString( retval ), data);  
  1085.     }
  1086.     return retval;
  1087. }
  1088. LONG HookRegSetValue( HKEY hkey, PCHAR lpszSubKey, DWORD fdwType, 
  1089.                       PCHAR lpszData, DWORD cbData ) {
  1090.     LONG      retval;
  1091.     CHAR      fullname[NAMELEN], data[DATASIZE], process[PROCESSLEN];
  1092.   
  1093.     GetFullName( hkey, lpszSubKey, "(Default)", fullname );
  1094.     retval = RealRegSetValue( hkey, lpszSubKey, fdwType, lpszData, cbData );
  1095.     data[0] = 0;
  1096.     if( lpszData ) {
  1097.         strcpy( data,""");
  1098.         strncat(data, lpszData, STRINGLEN );
  1099.         if( strlen( lpszData ) > STRINGLEN ) 
  1100.             strcat( data, "..." );
  1101.         strcat( data, """);
  1102.     }
  1103.     if( GetProcess( process ) && ApplyNameFilter( fullname ) && ErrorString( retval ) &&
  1104.         FilterDef.logwrites) {
  1105.         UpdateStore( Sequence++, "%stSetValuet%st%st%s", 
  1106.                      process, fullname, ErrorString( retval ), data );  
  1107.     }
  1108.     return retval;
  1109. }
  1110. LONG HookRegSetValueEx( HKEY hkey, PCHAR lpszValueName, 
  1111.                         DWORD lpdwReserved, DWORD fdwType, 
  1112.                         PBYTE lpbData, DWORD lpcbData ) {
  1113.     LONG      retval;
  1114.     int       i, len;
  1115.     CHAR      fullname[NAMELEN], data[DATASIZE], tmp[2*BINARYLEN], process[PROCESSLEN];
  1116.   
  1117.     GetFullName( hkey, NULL, lpszValueName, fullname );
  1118.     retval = RealRegSetValueEx( hkey, lpszValueName, lpdwReserved, 
  1119.                                 fdwType, lpbData, lpcbData );
  1120.     data[0] = 0;
  1121.     if( fdwType == REG_SZ ) {
  1122.         strcpy( data, """);
  1123.         strncat( data, lpbData, STRINGLEN );
  1124.         if( strlen( lpbData ) > STRINGLEN ) 
  1125.             strcat( data, "..." );
  1126.         strcat( data, """);
  1127.     } else if( fdwType == REG_BINARY ) {
  1128.         if( lpcbData > BINARYLEN ) len = BINARYLEN;
  1129.         else len = lpcbData;
  1130.         for( i = 0; i < len; i++ ) {
  1131.             sprintf( tmp, "%X ", lpbData[i]);
  1132.             strcat( data, tmp );
  1133.         }
  1134.         if( lpcbData > BINARYLEN) strcat( data, "...");
  1135.     } else if( fdwType == REG_DWORD ) {
  1136.         sprintf( data, "0x%X", *(PDWORD) lpbData );
  1137.     }
  1138.     if( GetProcess( process ) && ApplyNameFilter( fullname ) && ErrorString( retval ) &&
  1139.         FilterDef.logwrites) {
  1140.         UpdateStore( Sequence++, "%stSetValueExt%st%st%s", 
  1141.                      process, fullname, ErrorString( retval ), data );  
  1142.     }
  1143.     return retval;
  1144. }
  1145. LONG HookRegRemapPreDefKey( HKEY hkey, HKEY hRootKey ) {
  1146.     LONG      retval;
  1147.     CHAR      fullname[NAMELEN], process[PROCESSLEN];
  1148.     GetFullName( hkey, NULL, NULL, fullname );
  1149.     retval = RealRegRemapPreDefKey( hkey, hRootKey );
  1150.     if( GetProcess( process ) && ApplyNameFilter( fullname ) && ErrorString( retval )) {
  1151.         UpdateStore( Sequence++, "%stRemapPreKeyt%st%stRoot: %s", 
  1152.                      process, fullname, ErrorString( retval ),
  1153.                      hRootKey == HKEY_CURRENT_USER ? "HKCU" : "HKCC" );
  1154.     }
  1155.     return retval;
  1156. }
  1157. LONG HookRegQueryMultipleValues( HKEY hKey, PVALENT pValent, 
  1158.                                  DWORD dwNumVals, PCHAR pValueBuf, 
  1159.                                  PDWORD pTotSize ) {
  1160.     LONG      retval;
  1161.     CHAR      fullname[NAMELEN], process[PROCESSLEN];
  1162.     GetFullName( hKey, NULL, NULL, fullname );
  1163.     retval = RealRegQueryMultipleValues( hKey, pValent,
  1164.                                          dwNumVals, pValueBuf, pTotSize );
  1165.     if( GetProcess( process ) && ApplyNameFilter( fullname ) && ErrorString( retval ) &&
  1166.         FilterDef.logreads) {
  1167.         UpdateStore( Sequence++, "%stQueryMultValt%st%s", 
  1168.                      process, fullname, ErrorString( retval ));  
  1169.     }
  1170.     return retval;
  1171. }
  1172. LONG HookRegCreateDynKey( PCHAR szName, PVOID KeyContext, 
  1173.                           PVOID pInfo, PVOID pValList, 
  1174.                           DWORD dwNumVals, PVMMHKEY pKeyHandle ) {
  1175.     LONG      retval;
  1176.     CHAR      fullname[NAMELEN], process[PROCESSLEN];
  1177.     sprintf(fullname, "DYNDAT\%s", szName );
  1178.     retval = RealRegCreateDynKey( szName, KeyContext, pInfo, pValList,
  1179.                                   dwNumVals, pKeyHandle );
  1180.     if( GetProcess( process ) && ApplyNameFilter( fullname ) && ErrorString( retval ) &&
  1181.         FilterDef.logreads) {
  1182.         UpdateStore( Sequence++, "%stCreateDynKeyt%st%sthKey: 0x%X", 
  1183.                      process, fullname, ErrorString( retval ),
  1184.                      *pKeyHandle ); 
  1185.     }
  1186.     if( retval == ERROR_SUCCESS ) {
  1187.         RegmonStoreHash( *pKeyHandle, fullname );
  1188.     }
  1189.     return retval;
  1190. }
  1191. LONG __stdcall HookWin32RegQueryInfoKey( volatile PCLIENT_STRUCT pClientRegs, DWORD Dummy2, 
  1192.                                          HKEY hKey, 
  1193.                                          PDWORD lpcSubKeys, 
  1194.                                          PDWORD lpcchMaxSubKey, 
  1195.                                          PDWORD lpcValues, PDWORD lpcchMaxValueName, 
  1196.                                          PDWORD lpcbMaxValueData )
  1197. {
  1198.     LONG      retval;
  1199.     CHAR      fullname[NAMELEN], process[PROCESSLEN];
  1200.     //
  1201.     // NOTE: this special hook is needed because Win95 has a bug where
  1202.     // the Win32 call to RegQueryInfoKey gets routed to VMM's Win32 
  1203.     // service table, but the service table handler does *not* call the
  1204.     // VMM RegQueryInfoKey entry point. Therefore, we have to hook the
  1205.     // VMM Win32 service as a special case.
  1206.     //
  1207.     GetFullName( hKey, NULL, NULL, fullname );
  1208.     //
  1209.     // The return code is stored in the client registers
  1210.     //
  1211.     RealWin32RegQueryInfoKey( pClientRegs, Dummy2, 
  1212.                               hKey, lpcSubKeys, lpcchMaxSubKey, 
  1213.                               lpcValues, lpcchMaxValueName,
  1214.                               lpcbMaxValueData );
  1215.     retval = pClientRegs->CRS.Client_EAX;
  1216.     if( GetProcess( process ) && ApplyNameFilter( fullname ) && ErrorString( retval ) &&
  1217.         FilterDef.logreads) {
  1218.         if( retval == ERROR_SUCCESS && lpcSubKeys && lpcValues ) 
  1219.             UpdateStore( Sequence++, "%stQueryKeyt%st%stKeys: %d Values: %d", 
  1220.                          process, fullname, ErrorString( retval ), *lpcSubKeys, *lpcValues );
  1221.         else
  1222.             UpdateStore( Sequence++, "%stQueryKeyt%st%s", 
  1223.                          process, fullname, ErrorString( retval ));  
  1224.     }
  1225.     return retval;
  1226. }
  1227. //----------------------------------------------------------------------
  1228. //
  1229. // OnSysDynamicDeviceInit
  1230. //
  1231. // Dynamic init. Hook all registry related VxD APIs.
  1232. //
  1233. //----------------------------------------------------------------------
  1234. BOOL OnSysDynamicDeviceInit()
  1235. {
  1236.     int i;
  1237.     PDDB vmmDDB;
  1238.     //
  1239.     // Initialize semaphores
  1240.     //
  1241.     StoreMutex = Create_Semaphore(1);
  1242.     HashMutex  = Create_Semaphore(1);
  1243.     FilterMutex  = Create_Semaphore(1);
  1244.     //
  1245.     // Zero hash table
  1246.     //
  1247.     for(i = 0; i < NUMHASH; i++ ) HashTable[i] = NULL;
  1248.     //
  1249.     // Allocate first output buffer
  1250.     //
  1251.     PageAllocate(STORESIZE, PG_SYS, 0, 0, 0, 0, NULL, PAGELOCKED, 
  1252.                  (PMEMHANDLE) &Store, (PVOID) &Store );
  1253.     Store->Len = 0;
  1254.     Store->Next = NULL;
  1255.     NumStore = 1;
  1256.     //
  1257.     // Hook all registry routines
  1258.     //
  1259.     RealRegOpenKey = Hook_Device_Service_C(___RegOpenKey, HookRegOpenKey,
  1260.                                            &ROKThunk );
  1261.     RealRegCloseKey = Hook_Device_Service_C(___RegCloseKey, HookRegCloseKey,
  1262.                                             &RCKThunk );
  1263.     RealRegCreateKey = Hook_Device_Service_C(___RegCreateKey, HookRegCreateKey,
  1264.                                              &RCRKThunk );
  1265.     RealRegDeleteKey = Hook_Device_Service_C(___RegDeleteKey, HookRegDeleteKey,
  1266.                                              &RDKThunk );
  1267.     RealRegDeleteValue = Hook_Device_Service_C(___RegDeleteValue, 
  1268.                                                HookRegDeleteValue,
  1269.                                                &RDVThunk );
  1270.     RealRegEnumKey   = Hook_Device_Service_C(___RegEnumKey,
  1271.                                              HookRegEnumKey,
  1272.                                              &REKThunk );
  1273.     RealRegEnumValue = Hook_Device_Service_C(___RegEnumValue, 
  1274.                                              HookRegEnumValue,
  1275.                                              &REVThunk );
  1276.     RealRegFlushKey  = Hook_Device_Service_C(___RegFlushKey,
  1277.                                              HookRegFlushKey,
  1278.                                              &RFKThunk );
  1279.     RealRegQueryInfoKey  = Hook_Device_Service_C(___RegQueryInfoKey,
  1280.                                                  HookRegQueryInfoKey,
  1281.                                                  &RQIKThunk );
  1282.     RealRegQueryValue = Hook_Device_Service_C(___RegQueryValue,
  1283.                                               HookRegQueryValue,
  1284.                                               &RQVThunk );
  1285.     RealRegQueryValueEx = Hook_Device_Service_C(___RegQueryValueEx,
  1286.                                                 HookRegQueryValueEx,
  1287.                                                 &RQVEThunk );
  1288.     RealRegSetValue = Hook_Device_Service_C(___RegSetValue,
  1289.                                             HookRegSetValue,
  1290.                                             &RSVThunk );
  1291.     RealRegSetValueEx = Hook_Device_Service_C(___RegSetValueEx,
  1292.                                               HookRegSetValueEx,
  1293.                                               &RSVEThunk );
  1294.     RealRegRemapPreDefKey = Hook_Device_Service_C(___RegRemapPreDefKey,
  1295.                                                   HookRegRemapPreDefKey,
  1296.                                                   &RRPDKThunk );
  1297.     RealRegQueryMultipleValues = Hook_Device_Service_C(___RegQueryMultipleValues,
  1298.                                                        HookRegQueryMultipleValues,
  1299.                                                        &RQMVThunk );
  1300.     RealRegCreateDynKey = Hook_Device_Service_C(___RegCreateDynKey,
  1301.                                                 HookRegCreateDynKey,
  1302.                                                 &RCDKThunk );
  1303.     //
  1304.     // We have to hook the Win32 service for query info key
  1305.     // (isn't win95 just great?)
  1306.     //
  1307.     vmmDDB = Get_DDB( VMM_DEVICE_ID, "" );
  1308.     VMMWin32ServiceTable = (PDWORD) vmmDDB->DDB_Win32_Service_Table;
  1309.     RealWin32RegQueryInfoKey = (PVOID) VMMWin32ServiceTable[ VMMWIN32QUERYINFOKEY ];
  1310.     VMMWin32ServiceTable[ VMMWIN32QUERYINFOKEY ] = (DWORD) HookWin32RegQueryInfoKey;
  1311.     return TRUE;
  1312. }
  1313. //----------------------------------------------------------------------
  1314. //
  1315. // OnSysDynamicDeviceExit
  1316. //
  1317. // Dynamic exit. Unhook everything.
  1318. //
  1319. //----------------------------------------------------------------------
  1320. BOOL OnSysDynamicDeviceExit()
  1321. {
  1322.     Unhook_Device_Service_C(___RegOpenKey, &ROKThunk );
  1323.     Unhook_Device_Service_C(___RegCloseKey, &RCKThunk );
  1324.     Unhook_Device_Service_C(___RegCreateKey, &RCRKThunk );
  1325.     Unhook_Device_Service_C(___RegDeleteKey, &RDKThunk );
  1326.     Unhook_Device_Service_C(___RegDeleteValue, &RDVThunk );
  1327.     Unhook_Device_Service_C(___RegEnumKey, &REKThunk );
  1328.     Unhook_Device_Service_C(___RegEnumValue, &REVThunk );
  1329.     Unhook_Device_Service_C(___RegFlushKey, &RFKThunk );
  1330.     Unhook_Device_Service_C(___RegQueryInfoKey, &RQIKThunk );
  1331.     Unhook_Device_Service_C(___RegQueryValue, &RQVThunk );
  1332.     Unhook_Device_Service_C(___RegQueryValueEx, &RQVEThunk );
  1333.     Unhook_Device_Service_C(___RegSetValue, &RSVThunk );
  1334.     Unhook_Device_Service_C(___RegSetValueEx, &RSVEThunk );
  1335.     Unhook_Device_Service_C(___RegRemapPreDefKey, &RRPDKThunk );
  1336.     Unhook_Device_Service_C(___RegQueryMultipleValues, &RQMVThunk );
  1337.     Unhook_Device_Service_C(___RegCreateDynKey, &RCDKThunk );
  1338.     VMMWin32ServiceTable[ VMMWIN32QUERYINFOKEY ] = (DWORD) RealWin32RegQueryInfoKey;
  1339.     //
  1340.     // Free all memory
  1341.     //
  1342.     RegmonHashCleanup();
  1343.     RegmonFreeStore();
  1344.     RegmonFreeFilters();
  1345.     return TRUE;
  1346. }
  1347. //----------------------------------------------------------------------
  1348. //
  1349. // OnW32Deviceiocontrol
  1350. //
  1351. // Interface with the GUI.
  1352. //
  1353. //----------------------------------------------------------------------
  1354. DWORD OnW32Deviceiocontrol(PIOCTLPARAMS p)
  1355. {
  1356.     PSTORE_BUF      old;
  1357.     switch( p->dioc_IOCtlCode ) {
  1358.     case 0:
  1359.         return 0;
  1360.     case REGMON_zerostats:
  1361.   
  1362.         Wait_Semaphore( StoreMutex, BLOCK_SVC_INTS );
  1363.         while ( Store->Next )  {
  1364.  
  1365.             //
  1366.             // Release the next entry.
  1367.             //
  1368.             old = Store->Next;
  1369.             Store->Next = old->Next;
  1370.             Signal_Semaphore( StoreMutex );
  1371.             PageFree( (MEMHANDLE) old, 0 );
  1372.             Wait_Semaphore( StoreMutex, BLOCK_SVC_INTS );
  1373.             NumStore--;
  1374.         }
  1375.         Store->Len = 0;
  1376.         Signal_Semaphore( StoreMutex );
  1377.         Sequence = 0;
  1378.         return 0;
  1379.     case REGMON_getstats:
  1380.   
  1381.         //
  1382.         // Copy buffer into user space.
  1383.         Wait_Semaphore( StoreMutex, BLOCK_SVC_INTS );
  1384.         if ( MAX_STORE > p->dioc_cbOutBuf ) {
  1385.             //
  1386.             // Buffer is too small. Return error.
  1387.             //
  1388.             Signal_Semaphore( StoreMutex );
  1389.             return 1;
  1390.         } else if ( Store->Len  ||  Store->Next ) {
  1391.             //
  1392.             // Switch to a new buffer.
  1393.             //
  1394.             RegmonNewStore();
  1395.             //
  1396.             // Fetch the oldest buffer to give to caller.
  1397.             //
  1398.             old = RegmonOldestStore();
  1399.             Signal_Semaphore( StoreMutex );
  1400.             //
  1401.             // Copy it into the caller's buffer.
  1402.             //
  1403.             memcpy( p->dioc_OutBuf, old->Data, old->Len );
  1404.             //
  1405.             // Return length of copied info.
  1406.             //
  1407.             *p->dioc_bytesret = old->Len;
  1408.             //   
  1409.             // Deallocate the buffer.
  1410.             //
  1411.             PageFree( (MEMHANDLE) old, 0 );
  1412.             NumStore--;
  1413.         } else {
  1414.             //
  1415.             // There is no unread data.
  1416.             //
  1417.             Signal_Semaphore( StoreMutex );
  1418.             *p->dioc_bytesret = 0;
  1419.         }
  1420.         return 0;
  1421.     case REGMON_unhook:
  1422.         FilterOn = FALSE;
  1423.         return 0;
  1424.     case REGMON_hook:
  1425.         FilterOn = TRUE;
  1426.         return 0;
  1427.     case REGMON_setfilter:
  1428.         FilterDef = * (PFILTER) p->dioc_InBuf;
  1429.         RegmonUpdateFilters();
  1430.         return 0;
  1431.     }
  1432.     return 0;
  1433. }