minispy.c
来自「miniFilter.rar所有框架代码以及对应的PPT资料,可以直接拿来进行修」· C语言 代码 · 共 1,145 行 · 第 1/3 页
C
1,145 行
)
/*++
Routine Description:
This is called whenever a user mode application wishes to communicate
with this minifilter.
Arguments:
ConnectionCookie - unused
OperationCode - An identifier describing what type of message this
is. These codes are defined by the MiniFilter.
InputBuffer - A buffer containing input data, can be NULL if there
is no input data.
InputBufferSize - The size in bytes of the InputBuffer.
OutputBuffer - A buffer provided by the application that originated
the communication in which to store data to be returned to this
application.
OutputBufferSize - The size in bytes of the OutputBuffer.
ReturnOutputBufferSize - The size in bytes of meaningful data
returned in the OutputBuffer.
Return Value:
Returns the status of processing the message.
--*/
{
MINISPY_COMMAND command;
NTSTATUS status;
PAGED_CODE();
UNREFERENCED_PARAMETER( ConnectionCookie );
//
// **** PLEASE READ ****
//
// The INPUT and OUTPUT buffers are raw user mode addresses. The filter
// manager has already done a ProbedForRead (on InputBuffer) and
// ProbedForWrite (on OutputBuffer) which guarentees they are valid
// addresses based on the access (user mode vs. kernel mode). The
// minifilter does not need to do their own probe.
//
// The filter manager is NOT doing any alignment checking on the pointers.
// The minifilter must do this themselves if they care (see below).
//
// The minifilter MUST continue to use a try/except around any access to
// these buffers.
//
if ((InputBuffer != NULL) &&
(InputBufferSize >= (FIELD_OFFSET(COMMAND_MESSAGE,Command) +
sizeof(MINISPY_COMMAND)))) {
try {
//
// Probe and capture input message: the message is raw user mode
// buffer, so need to protect with exception handler
//
command = ((PCOMMAND_MESSAGE) InputBuffer)->Command;
} except( EXCEPTION_EXECUTE_HANDLER ) {
return GetExceptionCode();
}
switch (command) {
case GetMiniSpyLog:
//
// Return as many log records as can fit into the OutputBuffer
//
if ((OutputBuffer == NULL) || (OutputBufferSize == 0)) {
status = STATUS_INVALID_PARAMETER;
break;
}
//
// We want to validate that the given buffer is POINTER
// aligned. But if this is a 64bit system and we want to
// support 32bit applications we need to be careful with how
// we do the check. Note that the way SpyGetLog is written
// it actually does not care about alignment but we are
// demonstrating how to do this type of check.
//
#if defined(_WIN64)
if (IoIs32bitProcess( NULL )) {
//
// Validate alignment for the 32bit process on a 64bit
// system
//
if (!IS_ALIGNED(OutputBuffer,sizeof(ULONG))) {
status = STATUS_DATATYPE_MISALIGNMENT;
break;
}
} else {
#endif
if (!IS_ALIGNED(OutputBuffer,sizeof(PVOID))) {
status = STATUS_DATATYPE_MISALIGNMENT;
break;
}
#if defined(_WIN64)
}
#endif
//
// Get the log record.
//
status = SpyGetLog( OutputBuffer,
OutputBufferSize,
ReturnOutputBufferLength );
break;
case GetMiniSpyVersion:
//
// Return version of the MiniSpy filter driver. Verify
// we have a valid user buffer including valid
// alignment
//
if ((OutputBufferSize < sizeof( MINISPYVER )) ||
(OutputBuffer == NULL)) {
status = STATUS_INVALID_PARAMETER;
break;
}
//
// Validate Buffer alignment. If a minifilter cares about
// the alignment value of the buffer pointer they must do
// this check themselves. Note that a try/except will not
// capture alignment faults.
//
if (!IS_ALIGNED(OutputBuffer,sizeof(ULONG))) {
status = STATUS_DATATYPE_MISALIGNMENT;
break;
}
//
// Protect access to raw user-mode output buffer with an
// exception handler
//
try {
((PMINISPYVER)OutputBuffer)->Major = MINISPY_MAJ_VERSION;
((PMINISPYVER)OutputBuffer)->Minor = MINISPY_MIN_VERSION;
} except( EXCEPTION_EXECUTE_HANDLER ) {
return GetExceptionCode();
}
*ReturnOutputBufferLength = sizeof( MINISPYVER );
status = STATUS_SUCCESS;
break;
default:
status = STATUS_INVALID_PARAMETER;
break;
}
} else {
status = STATUS_INVALID_PARAMETER;
}
return status;
}
//---------------------------------------------------------------------------
// Operation filtering routines
//---------------------------------------------------------------------------
FLT_PREOP_CALLBACK_STATUS
SpyPreOperationCallback (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__deref_out_opt PVOID *CompletionContext
)
/*++
Routine Description:
This routine receives ALL pre-operation callbacks for this filter. It then
tries to log information about the given operation. If we are able
to log information then we will call our post-operation callback routine.
NOTE: This routine must be NON-PAGED because it can be called on the
paging path.
Arguments:
Data - Contains information about the given operation.
FltObjects - Contains pointers to the various objects that are pertinent
to this operation.
CompletionContext - This receives the address of our log buffer for this
operation. Our completion routine then receives this buffer address.
Return Value:
Identifies how processing should continue for this operation
--*/
{
FLT_PREOP_CALLBACK_STATUS returnStatus = FLT_PREOP_SUCCESS_NO_CALLBACK; //assume we are NOT going to call our completion routine
PRECORD_LIST recordList;
PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
UNICODE_STRING defaultName;
PUNICODE_STRING nameToUse;
NTSTATUS status;
#if MINISPY_NOT_W2K
WCHAR name[MAX_NAME_SPACE/sizeof(WCHAR)];
#endif
//
// Try and get a log record
//
recordList = SpyNewRecord();
if (recordList) {
//
// We got a log record, if there is a file object, get its name.
//
// NOTE: By default, we use the query method
// FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP
// because MiniSpy would like to get the name as much as possible, but
// can cope if we can't retrieve a name. For a debugging type filter,
// like Minispy, this is reasonable, but for most production filters
// who need names reliably, they should query the name at times when it
// is known to be safe and use the query method
// FLT_FILE_NAME_QUERY_DEFAULT.
//
if (FltObjects->FileObject != NULL) {
status = FltGetFileNameInformation( Data,
FLT_FILE_NAME_NORMALIZED |
MiniSpyData.NameQueryMethod,
&nameInfo );
} else {
//
// Can't get a name when there's no file object
//
status = STATUS_UNSUCCESSFUL;
}
//
// Use the name if we got it else use a default name
//
if (NT_SUCCESS( status )) {
nameToUse = &nameInfo->Name;
//
// Parse the name if requested
//
if (FlagOn( MiniSpyData.DebugFlags, SPY_DEBUG_PARSE_NAMES )) {
status = FltParseFileNameInformation( nameInfo );
ASSERT(NT_SUCCESS(status));
}
} else {
#if MINISPY_NOT_W2K
NTSTATUS lstatus;
PFLT_FILE_NAME_INFORMATION lnameInfo;
//
// If we couldn't get the "normalized" name try and get the
// "opened" name
//
if (FltObjects->FileObject != NULL) {
//
// Get the opened name
//
lstatus = FltGetFileNameInformation( Data,
FLT_FILE_NAME_OPENED |
FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP,
&lnameInfo );
if (NT_SUCCESS(lstatus)) {
#pragma prefast(suppress:__WARNING_BANNED_API_USAGE, "reviewed and safe usage")
(VOID)_snwprintf( name,
sizeof(name)/sizeof(WCHAR),
L"<%08x> %wZ",
status,
&lnameInfo->Name );
FltReleaseFileNameInformation( lnameInfo );
} else {
//
// If that failed report both NORMALIZED status and
// OPENED status
//
#pragma prefast(suppress:__WARNING_BANNED_API_USAGE, "reviewed and safe usage")
(VOID)_snwprintf( name,
sizeof(name)/sizeof(WCHAR),
L"<NO NAME: NormalizeStatus=%08x OpenedStatus=%08x>",
status,
lstatus );
}
} else {
#pragma prefast(suppress:__WARNING_BANNED_API_USAGE, "reviewed and safe usage")
(VOID)_snwprintf( name,
sizeof(name)/sizeof(WCHAR),
L"<NO NAME>" );
}
RtlInitUnicodeString( &defaultName, name );
nameToUse = &defaultName;
#else
//
// We were unable to get the String safe routine to work on W2K
// Do it the old safe way
//
RtlInitUnicodeString( &defaultName, L"<NO NAME>" );
nameToUse = &defaultName;
#endif //MINISPY_NOT_W2K
#if DBG
//
// Debug support to break on certain errors.
//
if (FltObjects->FileObject != NULL) {
NTSTATUS retryStatus;
if ((StatusToBreakOn != 0) && (status == StatusToBreakOn)) {
DbgBreakPoint();
}
retryStatus = FltGetFileNameInformation( Data,
FLT_FILE_NAME_NORMALIZED |
MiniSpyData.NameQueryMethod,
&nameInfo );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?