📄 mspylib.c
字号:
/*++
Copyright (c) 1989-2002 Microsoft Corporation
Module Name:
mspyLib.c
Abstract:
This contains library support routines for MiniSpy
Environment:
Kernel mode
--*/
#include "mspyKern.h"
//---------------------------------------------------------------------------
// Assign text sections for each routine.
//---------------------------------------------------------------------------
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, SpyReadDriverParameters)
#endif
//---------------------------------------------------------------------------
// Log Record allocation routines
//---------------------------------------------------------------------------
PRECORD_LIST
SpyAllocateBuffer (
__out PULONG RecordType
)
/*++
Routine Description:
Allocates a new buffer from the MiniSpyData.FreeBufferList if there is
enough memory to do so and we have not exceed our maximum buffer
count.
NOTE: Because there is no interlock between testing if we have exceeded
the record allocation limit and actually increment the in use
count it is possible to temporarily allocate one or two buffers
more then the limit. Because this is such a rare situation there
is not point to handling this.
NOTE: This code must be NON-PAGED because it can be called on the
paging path or at DPC level.
Arguments:
RecordType - Receives information on what type of record was allocated.
Return Value:
Pointer to the allocated buffer, or NULL if the allocation failed.
--*/
{
PVOID newBuffer;
ULONG newRecordType = RECORD_TYPE_NORMAL;
//
// See if we have room to allocate more buffers
//
if (MiniSpyData.RecordsAllocated < MiniSpyData.MaxRecordsToAllocate) {
InterlockedIncrement( &MiniSpyData.RecordsAllocated );
newBuffer = ExAllocateFromNPagedLookasideList( &MiniSpyData.FreeBufferList );
if (newBuffer == NULL) {
//
// We failed to allocate the memory. Decrement our global count
// and return what type of memory we have.
//
InterlockedDecrement( &MiniSpyData.RecordsAllocated );
newRecordType = RECORD_TYPE_FLAG_OUT_OF_MEMORY;
}
} else {
//
// No more room to allocate memory, return we didn't get a buffer
// and why.
//
newRecordType = RECORD_TYPE_FLAG_EXCEED_MEMORY_ALLOWANCE;
newBuffer = NULL;
}
*RecordType = newRecordType;
return newBuffer;
}
VOID
SpyFreeBuffer (
__in PVOID Buffer
)
/*++
Routine Description:
Free an allocate buffer.
NOTE: This code must be NON-PAGED because it can be called on the
paging path or at DPC level.
Arguments:
Buffer - The buffer to free.
Return Value:
None.
--*/
{
//
// Free the memory, update the counter
//
InterlockedDecrement( &MiniSpyData.RecordsAllocated );
ExFreeToNPagedLookasideList( &MiniSpyData.FreeBufferList, Buffer );
}
//---------------------------------------------------------------------------
// Logging routines
//---------------------------------------------------------------------------
PRECORD_LIST
SpyNewRecord (
VOID
)
/*++
Routine Description:
Allocates a new RECORD_LIST structure if there is enough memory to do so. A
sequence number is updated for each request for a new record.
NOTE: This code must be NON-PAGED because it can be called on the
paging path or at DPC level.
Arguments:
None
Return Value:
Pointer to the RECORD_LIST allocated, or NULL if no memory is available.
--*/
{
PRECORD_LIST newRecord;
ULONG initialRecordType;
//
// Allocate the buffer
//
newRecord = SpyAllocateBuffer( &initialRecordType );
if (newRecord == NULL) {
//
// We could not allocate a record, see if the static buffer is
// in use. If not, we will use it
//
if (!InterlockedExchange( &MiniSpyData.StaticBufferInUse, TRUE )) {
newRecord = (PRECORD_LIST)MiniSpyData.OutOfMemoryBuffer;
initialRecordType |= RECORD_TYPE_FLAG_STATIC;
}
}
//
// If we got a record (doesn't matter if it is static or not), init it
//
if (newRecord != NULL) {
//
// Init the new record
//
newRecord->LogRecord.RecordType = initialRecordType;
newRecord->LogRecord.Length = sizeof(LOG_RECORD);
newRecord->LogRecord.SequenceNumber = InterlockedIncrement( &MiniSpyData.LogSequenceNumber );
RtlZeroMemory( &newRecord->LogRecord.Data, sizeof( RECORD_DATA ) );
}
return( newRecord );
}
VOID
SpyFreeRecord (
__in PRECORD_LIST Record
)
/*++
Routine Description:
Free the given buffer
NOTE: This code must be NON-PAGED because it can be called on the
paging path or at DPC level.
Arguments:
Record - the buffer to free
Return Value:
None.
--*/
{
if (FlagOn(Record->LogRecord.RecordType,RECORD_TYPE_FLAG_STATIC)) {
//
// This was our static buffer, mark it available.
//
ASSERT(MiniSpyData.StaticBufferInUse);
MiniSpyData.StaticBufferInUse = FALSE;
} else {
SpyFreeBuffer( Record );
}
}
VOID
SpySetRecordName (
__inout PLOG_RECORD LogRecord,
__in PUNICODE_STRING Name
)
/*++
Routine Description:
Sets the given file name in the LogRecord.
NOTE: This code must be NON-PAGED because it can be called on the
paging path.
Arguments:
LogRecord - The record in which to set the name.
Name - The name to insert
Return Value:
None.
--*/
{
ULONG nameCopyLength;
PCHAR copyPointer = (PCHAR)LogRecord->Name;
if (NULL != Name) {
//
// Need space for NULL termination
//
if (Name->Length > (MAX_NAME_SPACE - sizeof( UNICODE_NULL ))) {
nameCopyLength = MAX_NAME_SPACE - sizeof( UNICODE_NULL );
} else {
nameCopyLength = (ULONG)Name->Length;
}
//
// We will always round up log-record length to sizeof(PVOID) so that
// the next log record starts on the right PVOID boundary to prevent
// IA64 alignment faults. The length of the record of course
// includes the additional NULL at the end.
//
LogRecord->Length = ROUND_TO_SIZE( (LogRecord->Length +
nameCopyLength +
sizeof( UNICODE_NULL )),
sizeof( PVOID ) );
RtlCopyMemory( copyPointer, Name->Buffer, nameCopyLength );
//
// Null terminate the name
//
copyPointer += nameCopyLength;
*((PWCHAR) copyPointer) = UNICODE_NULL;
ASSERT(LogRecord->Length <= MAX_LOG_RECORD_LENGTH);
}
}
VOID
SpyLogPreOperationData (
__in PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__inout PRECORD_LIST RecordList
)
/*++
Routine Description:
This is called from the pre-operation callback routine to copy the
necessary information into the log record.
NOTE: This code must be NON-PAGED because it can be called on the
paging path.
Arguments:
Data - The Data structure that contains the information we want to record.
FltObjects - Pointer to the io objects involved in this operation.
RecordList - Where we want to save the data
Return Value:
None.
--*/
{
PRECORD_DATA recordData = &RecordList->LogRecord.Data;
PDEVICE_OBJECT devObj;
NTSTATUS status;
status = FltGetDeviceObject(FltObjects->Volume,&devObj);
if (NT_SUCCESS(status)) {
ObDereferenceObject(devObj);
} else {
devObj = NULL;
}
//
// Save the information we want
//
recordData->CallbackMajorId = Data->Iopb->MajorFunction;
recordData->CallbackMinorId = Data->Iopb->MinorFunction;
recordData->IrpFlags = Data->Iopb->IrpFlags;
recordData->Flags = Data->Flags;
recordData->DeviceObject = (FILE_ID)devObj;
recordData->FileObject = (FILE_ID)FltObjects->FileObject;
recordData->Transaction = (FILE_ID)FltObjects->Transaction;
recordData->ProcessId = (FILE_ID)PsGetCurrentProcessId();
recordData->ThreadId = (FILE_ID)PsGetCurrentThreadId();
recordData->Arg1 = Data->Iopb->Parameters.Others.Argument1;
recordData->Arg2 = Data->Iopb->Parameters.Others.Argument2;
recordData->Arg3 = Data->Iopb->Parameters.Others.Argument3;
recordData->Arg4 = Data->Iopb->Parameters.Others.Argument4;
recordData->Arg5 = Data->Iopb->Parameters.Others.Argument5;
recordData->Arg6.QuadPart = Data->Iopb->Parameters.Others.Argument6.QuadPart;
KeQuerySystemTime( &recordData->OriginatingTime );
}
VOID
SpyLogPostOperationData (
__in PFLT_CALLBACK_DATA Data,
__inout PRECORD_LIST RecordList
)
/*++
Routine Description:
This is called from the post-operation callback routine to copy the
necessary information into the log record.
NOTE: This code must be NON-PAGED because it can be called on the
paging path or at DPC level.
Arguments:
Data - The Data structure that contains the information we want to record.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -