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 + -
显示快捷键?