📄 regsys.c
字号:
// and tell the user there wasn't enough room for it.
//
if( ioStatus.Status == STATUS_DISK_FULL ) {
zeroLengthFile.EndOfFile.QuadPart = 0;
ZwSetInformationFile( LogFile, &ioStatus,
&zeroLengthFile, sizeof(zeroLengthFile), FileEndOfFileInformation );
ZwWriteFile( LogFile, NULL, NULL, NULL, &ioStatus,
diskFullError, strlen(diskFullError), NULL, NULL );
ZwClose( LogFile );
LogFile = INVALID_HANDLE_VALUE;
BootLogging = FALSE;
break;
}
entry = (PVOID) (entry->text + len);
}
}
//----------------------------------------------------------------------
//
// RegmonWriteBootLog - worker thread routine
//
// Writes a buffer out to the log file. We do this in a worker routine
// because the log file handle, which we opened in DriverEntry, is
// only valid in the System process, and worker threads execute in
// the system process. We are protected by the Store mutex while
// in this procedure, since we are called from NewStore, which
// is called after the Store mutex is acquired.
//
// NOTE: When Regmon is configured to log activity during a boot it
// is marked to start as the very first driver in the boot sequence.
// Because the SystemRoot symbolic link is not initialized until
// all boot drivers have finished initializing, Regmon is not able
// to open a boot log until some point later. In order that we can
// capture all registry activity we store away output buffers on a list
// until we try and succeed at opening the boot log. When we can we
// send out the accumulated data and then begin dumping buffers
// as they are generated.
//
//----------------------------------------------------------------------
VOID RegmonWriteBootLog( PVOID Context )
{
PSTORE_BUF currentStore = Context;
PSTORE_BUF saveStore, curSaveStore;
NTSTATUS ntStatus;
//
// If boot logging is still on, but the log file hasn't been opened,
// try to open it
//
if( BootLogging && LogFile == INVALID_HANDLE_VALUE ) {
ntStatus = RegmonOpenBootLog();
if( NT_SUCCESS( ntStatus )) {
//
// Finally! Process all the buffers we've saved away
//
curSaveStore = BootSavedStoreList;
while( curSaveStore ) {
RegmonWriteBuffer( curSaveStore );
BootSavedStoreList = curSaveStore->Next;
ExFreePool( curSaveStore );
curSaveStore = BootSavedStoreList;
}
}
}
//
// Either write out the current buffer or save it away to
// write out later
//
if( LogFile != INVALID_HANDLE_VALUE ) {
RegmonWriteBuffer( currentStore );
} else {
//
// Save this buffer away until we can successfully open
// the log file and write it out to disk
//
saveStore = ExAllocatePool( PagedPool, sizeof(*saveStore));
memcpy( saveStore, currentStore, sizeof(*saveStore) );
saveStore->Next = NULL;
if( BootSavedStoreList ) {
BootSavedStoreTail->Next = saveStore;
BootSavedStoreTail = saveStore;
} else {
BootSavedStoreList = saveStore;
BootSavedStoreTail = saveStore;
}
}
//
// Signal the event
//
KeSetEvent( &LoggingEvent, 0, FALSE );
}
//======================================================================
// B U F F E R R O U T I N E S
//======================================================================
//----------------------------------------------------------------------
//
// RegmonFreeStore
//
// Frees all the data output buffers that we have currently allocated.
//
//----------------------------------------------------------------------
VOID RegmonFreeStore()
{
PSTORE_BUF next;
while( Store ) {
next = Store->Next;
ExFreePool( Store );
Store = next;
}
}
//----------------------------------------------------------------------
//
// RegmonNewStore
//
// Called when the current buffer has filled up. This moves us to the
// pre-allocated buffer and then allocates another buffer.
//
//----------------------------------------------------------------------
void RegmonNewStore( void )
{
PSTORE_BUF prev = Store, newstore;
WORK_QUEUE_ITEM workItem;
//
// If we're boot logging, write the current store out to disk
//
if( BootLogging ) {
ExInitializeWorkItem( &workItem, RegmonWriteBootLog, Store );
ExQueueWorkItem( &workItem, CriticalWorkQueue );
KeWaitForSingleObject( &LoggingEvent, Executive, KernelMode, FALSE, NULL );
}
//
// If we have maxed out or haven't accessed the current store
// just return
//
if( MaxStore == NumStore ) {
Store->Len = 0;
return;
}
//
// See if we can re-use a store
//
if( !Store->Len ) {
return;
}
//
// Move to the next buffer and allocate another one
//
newstore = ExAllocatePool( PagedPool, sizeof(*Store) );
if( newstore ) {
Store = newstore;
Store->Len = 0;
Store->Next = prev;
NumStore++;
} else {
Store->Len = 0;
}
}
//----------------------------------------------------------------------
//
// RegmonOldestStore
//
// Goes through the linked list of storage buffers and returns the
// oldest one.
//
//----------------------------------------------------------------------
PSTORE_BUF RegmonOldestStore( void )
{
PSTORE_BUF ptr = Store, prev = NULL;
while ( ptr->Next ) {
ptr = (prev = ptr)->Next;
}
if ( prev ) {
prev->Next = NULL;
}
NumStore--;
return ptr;
}
//----------------------------------------------------------------------
//
// RegmonResetStore
//
// When a GUI is no longer communicating with us, but we can't unload,
// we reset the storage buffers.
//
//----------------------------------------------------------------------
VOID RegmonResetStore()
{
PSTORE_BUF current, next;
MUTEX_WAIT( StoreMutex );
//
// Traverse the list of output buffers
//
current = Store->Next;
while( current ) {
//
// Free the buffer
//
next = current->Next;
ExFreePool( current );
current = next;
}
//
// Move the output pointer in the buffer that's being kept
// the start of the buffer.
//
Store->Len = 0;
Store->Next = NULL;
MUTEX_RELEASE( StoreMutex );
}
//----------------------------------------------------------------------
//
// UpdateStore
//
// Add a new string to Store, if it fits.
//
//----------------------------------------------------------------------
void UpdateStore( const char * format, ... )
{
PENTRY Entry;
ULONG len;
va_list arg_ptr;
static CHAR text[MAXPATHLEN*2];
#define A (&format)
DbgPrint(( (char *)format, A[1], A[2], A[3], A[4], A[5], A[6] ));
DbgPrint(( "\n" ));
#undef A
//
// only do this if a GUI is active
//
if( !GUIActive ) return;
//
// Lock the buffer pool
//
MUTEX_WAIT( StoreMutex );
//
// Get a sequence numnber
//
InterlockedIncrement( &Sequence );
//
// Sprint the string to get the length
//
va_start( arg_ptr, format );
len = vsprintf( text, format, arg_ptr );
va_end( arg_ptr );
len += 4; len &= 0xFFFFFFFC; // +1 to include null terminator and +3 to allign on longword
//
// See if its time to switch to extra buffer
//
if ( Store->Len + len + sizeof(ENTRY) + 1 >= MAX_STORE ) {
RegmonNewStore();
}
//
// Store the sequence number so that
// a call's result can be paired with its
// initial data collected when it was made.
//
Entry = (void *)(Store->Data+Store->Len);
Entry->seq = Sequence;
memcpy( Entry->text, text, len );
Store->Len += sizeof(Entry->seq)+len;
//
// Release the buffer pool
//
MUTEX_RELEASE( StoreMutex );
}
//----------------------------------------------------------------------
//
// strncatZ
//
// Appends a string to another and attaches a null. NT 3.51 ntoskrnl
// does not export this function so we have to make our own, and give
// it a name that won't conflict with the strncat that NT 4.0 exports.
//
//----------------------------------------------------------------------
PCHAR strncatZ( PCHAR dest, PCHAR source, int length )
{
int origlen = strlen(dest);
strncpy( dest+origlen, source, length );
dest[ origlen+length ] = 0;
return(dest);
}
//======================================================================
// H A S H R O U T I N E S
//======================================================================
//----------------------------------------------------------------------
//
// RegmonHashCleanup
//
// Called when we are unloading to free any memory that we have
// in our possession.
//
//----------------------------------------------------------------------
VOID RegmonHashCleanup()
{
PHASH_ENTRY hashEntry, nextEntry;
ULONG i;
MUTEX_WAIT( HashMutex );
//
// First free the hash table entries
//
for( i = 0; i < NUMHASH; i++ ) {
hashEntry = HashTable[i];
while( hashEntry ) {
nextEntry = hashEntry->Next;
ExFreePool( hashEntry->FullPathName );
ExFreePool( hashEntry );
hashEntry = nextEntry;
}
}
hashEntry = FreeHashList;
while( hashEntry ) {
nextEntry = hashEntry->Next;
ExFreePool( hashEntry );
hashEntry = nextEntry;
}
MUTEX_RELEASE( HashMutex );
}
//----------------------------------------------------------------------
//
// RegmonStoreHash
//
// Stores the key and associated fullpath in the hash table.
//
//----------------------------------------------------------------------
VOID RegmonStoreHash( POBJECT object, PCHAR fullname )
{
PHASH_ENTRY newEntry;
MUTEX_WAIT( HashMutex );
if( FreeHashList ) {
newEntry = FreeHashList;
FreeHashList = newEntry->Next;
} else {
newEntry = ExAllocatePool( PagedPool, sizeof(HASH_ENTRY));
}
newEntry->Object = object;
newEntry->FullPathName = ExAllocatePool( PagedPool, strlen(fullname)+1 );
newEntry->Next = HashTable[ HASHOBJECT( object) ];
HashTable[ HASHOBJECT(object) ] = newEntry;
strcpy( newEntry->FullPathName, fullname );
MUTEX_RELEASE( HashMutex );
}
//----------------------------------------------------------------------
//
// RegmonFreeHashEntry
//
// When we see a key close, we can free the string we had associated
// with the fileobject being closed since we know it won't be used
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -