看流星社区

 找回密码
 注册账号
查看: 3118|回复: 0

Minifilter过滤,功能实现对驱动目录的监控,包括创建,重命名,删除并实现hips

[复制链接]

该用户从未签到

发表于 2017-6-1 13:32:32 | 显示全部楼层 |阅读模式
注意下:我的这套过滤只能用在nt6系统上
原因是使用一个nt6上才有的函数
见函数
PsGetProcessFullName

其实没必要自己来写获取全路径
因为minifilter已经给我们提供了获取全路径的函数
FltGetFileNameInformation

我就不改了,哈哈


说说遇到的问题吧
在监控创建的时候,我是在post中监控,我拒绝后,会弹窗,2-3次吧,也就是会请求2-3次,我的解决方法是记录上一次拒绝的文件全路径,然后下一次来的时候来比对
这里可以将处理过的文件加入链表或者hash,我偷懒了,就直接用这种方法来解决多重求情的问题,
这里注意下,出现多次请求的原因是你第一次放行了,那么我们第二次的时候就知道比对的时候就直接放行了


考虑过在pre中监控
但根据MF周老师的意见 说在这里拿到的信息是不准确的,
可以用下面一句话总结:
在pre中是对请求本身就行拦截,在post中是对请求完成结果的拦截.
遵循周老师的意见,我还是在post中监控


在拦截创建的时候,还有一个问题,就是如果创建的时候我拒绝了,那么返回给用户的会出现一个替换的框(文件已存在,但大小是0)
针对这个情况,我直接对这个data设置文件属性 有点像前面学习的IRP下发强删文件



//就算拒绝了 也会创建一个空文件 这里我们删除
                        fdi.DeleteFile = TRUE;
                        FltSetInformationFile(FltObjects->Instance, FltObjects->FileObject, &fdi, sizeof(FILE_DISPOSITION_INFORMATION), FileDispositionInformation);[/code]


在post中 我们可以使用FltCancelFileOpen 或者FltCancelFileIrp(未测试)来取消前面的操作


还有一点是,刚开始写的时候我直接对Create的回调函数进行过滤,没有判断文件打开的属性,或是文件还是文件夹
然后一直弹窗,然后 你懂得....
然后就修复了 对文件夹的判断和打开的判断
这里其实是有BUG的 为什么这么说呢,在CreateFile的函数中 我们可以用FILE_OPEN_IF创建文件 这里没有过滤
这里不应该在内核中过滤 原因是如果这里填写了对FILE_OPEN_IF的过滤,会不断弹窗,而且这个时候在这里已经不能判断文件是否存在了 已经完成了
已经生成了一个文件 一个为空的文件
那么怎么办呢,思路是得到此时文件的大小,如果是0则是新建,否则就是打开操作
获取大小的方法我知道的是通过FltReadFile去读文件 然后BytesRead就是文件的大小
还有一个思路就是在pre中过滤,此时文件还没有创建,我们得到文件的全路径,然后打开,如果返回NO_FOUND就说明是新建操作
下面是对文件夹的判断

if (!NT_SUCCESS( Data->IoStatus.Status ) ||
        (STATUS_REPARSE == Data->IoStatus.Status)) {

        return FLT_POSTOP_FINISHED_PROCESSING;
    }
       
        Options = Data->Iopb-&gtarameters.Create.Options;

         if (FlagOn(Options, FILE_DIRECTORY_FILE) ||
                 FlagOn(FltObjects->FileObject->Flags, FO_VOLUME_OPEN) ||
                 FlagOn(Data->Flags, SL_OPEN_PAGING_FILE))
    {
        return FLT_POSTOP_FINISHED_PROCESSING;
    }

         ulDisposition = (Data->Iopb-&gtarameters.Create.Options >> 24) & 0xFF;
        if (ulDisposition == FILE_CREATE || ulDisposition == FILE_OVERWRITE || ulDisposition == FILE_OVERWRITE_IF)
    {
                PopWindow = TRUE;
    }[/code]


另外遇到的问题是删除
删除分两种
一种是直接删除 也就是shift+Del的方式
这种没什么问题
另外一种普通的删除,右键文件-删除-或者直接按Del
这其实一个发现 + 更名的操作
这个发现具体我也不知道怎么说,因为你普通删除文件的时候,不是有一个正在发现文件吗,就是统计文件的大小操作
然后就是更名的操作
这是我第一次实验时出现的情况
我的操作是 普通删除->放行->然后就出现了这个框
有了这个后 就简单了,在PreSetInforMation中获得文件全路径,匹配如果中间有Recycle.Bin的字符串
但这不是准确的,我也偷懒啦




至于重命名 无非就是拿到重命名后的路径
两种方法
1.直接在buffer中拿
2.FltGetDestinationFileNameInformation获得
不懂的是:重命名的路径能直接在buffer中拿到 为什么还要使用FltGetDestinationFileNameInformation呢,知道的人可以回复下

pRenameInfo = (PFILE_RENAME_INFORMATION)Data->Iopb-&gtarameters.SetFileInformation.InfoBuffer;
                       
                                /*
                                //这也是可行的
                                wstrTest = ExAllocatePool(NonPagedPool,pRenameInfo->FileNameLength + 1);
                                if(wstrTest == NULL)
                                        leave;

                                memset(wstrTest,'\0',pRenameInfo->FileNameLength + 1);

                                wcsncpy(wstrTest,pRenameInfo->FileName,pRenameInfo->FileNameLength);
                                DbgPrint("%ws\n",wstrTest);*/

                               
                                status = FltGetDestinationFileNameInformation(Instance,Data->Iopb->TargetFileObject,pRenameInfo->RootDirectory,pRenameInfo->FileName,pRenameInfo->FileNameLength,FLT_FILE_NAME_NORMALIZED,&pOutReNameinfo);
                                if(!NT_SUCCESS(status))
                                {
                                        DbgPrint("FltGetDestinationFileNameInformation is faild! 0x%x",status);
                                        leave;
                                }
                                wcsncpy(¬ification->RePathName,pOutReNameinfo->Name.Buffer,pOutReNameinfo->Name.MaximumLength);
                               
                                DbgPrint("重命名:%wZ\n",&pOutReNameinfo->Name);

                                FltReleaseFileNameInformation(pOutReNameinfo);[/code]


其他没什么了 就是R3的处理了,我对创建多次请求的判断是放在R3的
核心文件:R0

#include <fltKernel.h>
#include <dontuse.h>
#include <suppress.h>
#include "scanuk.h"
#include "scanner.h"

#pragma prefast(disable:__WARNING_ENCODE_MEMBER_FUNCTION_POINTER, "Not valid for kernel mode drivers")


NTSTATUS
PsReferenceProcessFilePointer (
IN PEPROCESS Process,
OUT PVOID *OutFileObject
);

SCANNER_DATA ScannerData;

UNICODE_STRING g_LastDelFileName = {0};

//
//  This is a static list of file name extensions files we are interested in scanning
//

const UNICODE_STRING ScannerExtensionsToScan[] =
    { RTL_CONSTANT_STRING( L"doc"),
      RTL_CONSTANT_STRING( L"txt"),
      RTL_CONSTANT_STRING( L"bat"),
      RTL_CONSTANT_STRING( L"cmd"),
      RTL_CONSTANT_STRING( L"inf"),
      /*RTL_CONSTANT_STRING( L"ini"),   Removed, to much usage*/
      {0, 0, NULL}
    };


//
//  Function prototypes
//

NTSTATUS
ScannerPortConnect (
    __in PFLT_PORT ClientPort,
    __in_opt PVOID ServerPortCookie,
    __in_bcount_opt(SizeOfContext) PVOID ConnectionContext,
    __in ULONG SizeOfContext,
    __deref_out_opt PVOID *ConnectionCookie
    );

VOID
ScannerPortDisconnect (
    __in_opt PVOID ConnectionCookie
    );

NTSTATUS
ScannerpScanFileInUserMode (
    __in PFLT_INSTANCE Instance,
    __in PFILE_OBJECT FileObject,
    __out PBOOLEAN SafeToOpen
    );

BOOLEAN
ScannerpCheckExtension (
    __in PUNICODE_STRING Extension
    );

NTSTATUS
MyScannerpScanFileInUserMode (
    __in PFLT_INSTANCE Instance,
    __in PFILE_OBJECT FileObject,
        __in PFLT_CALLBACK_DATA Data,
        __in ULONG                Operation,
    __out PBOOLEAN SafeToOpen
    );

//
//  Assign text sections for each routine.
//

#ifdef ALLOC_PRAGMA
    #pragma alloc_text(INIT, DriverEntry)
    #pragma alloc_text(PAGE, ScannerInstanceSetup)
    #pragma alloc_text(PAGE, ScannerPreCreate)
        #pragma alloc_text(PAGE, ScannerPostCreate)
    #pragma alloc_text(PAGE, ScannerPortConnect)
    #pragma alloc_text(PAGE, ScannerPortDisconnect)
        #pragma alloc_text(PAGE, ScannerPostSetInforMation)
        #pragma alloc_text(PAGE, ScannerPreSetInforMation )
//IsPatternMatch
//PsGetProcessFullName
#endif


//
//  Constant FLT_REGISTRATION structure for our filter.  This
//  initializes the callback routines our filter wants to register
//  for.  This is only used to register with the filter manager
//

const FLT_OPERATION_REGISTRATION Callbacks[] = {

    { IRP_MJ_CREATE,
      0,
      ScannerPreCreate,
      ScannerPostCreate},

    { IRP_MJ_CLEANUP,
      0,
      ScannerPreCleanup,
      NULL},

    { IRP_MJ_WRITE,
      0,
      ScannerPreWrite,
      NULL},

        { IRP_MJ_SET_INFORMATION,
          0,
          ScannerPreSetInforMation,
          ScannerPostSetInforMation},

    { IRP_MJ_OPERATION_END }
};


const FLT_CONTEXT_REGISTRATION ContextRegistration[] = {

    { FLT_STREAMHANDLE_CONTEXT,
      0,
      NULL,
      sizeof(SCANNER_STREAM_HANDLE_CONTEXT),
      'chBS' },

    { FLT_CONTEXT_END }
};

const FLT_REGISTRATION FilterRegistration = {

    sizeof( FLT_REGISTRATION ),         //  Size
    FLT_REGISTRATION_VERSION,           //  Version
    0,                                  //  Flags
    ContextRegistration,                //  Context Registration.
    Callbacks,                          //  Operation callbacks
    ScannerUnload,                      //  FilterUnload
    ScannerInstanceSetup,               //  InstanceSetup
    ScannerQueryTeardown,               //  InstanceQueryTeardown
    NULL,                               //  InstanceTeardownStart
    NULL,                               //  InstanceTeardownComplete
    NULL,                               //  GenerateFileName
    NULL,                               //  GenerateDestinationFileName
    NULL                                //  NormalizeNameComponent
};



BOOLEAN IsPatternMatch(PUNICODE_STRING Expression, PUNICODE_STRING Name, BOOLEAN IgnoreCase)
{
        return FsRtlIsNameInExpression(
                Expression,
                Name,
                IgnoreCase,//如果这里设置为TRUE,那么Expression必须是大写的
                NULL
                );
       
}

PUNICODE_STRING PsGetProcessFullName(PEPROCESS pTargetProcess)
{
        PFILE_OBJECT pFileObject=NULL;
        POBJECT_NAME_INFORMATION pObjectNameInfo=NULL;
                if(!NT_SUCCESS(PsReferenceProcessFilePointer(pTargetProcess,&pFileObject)))
                return NULL;
        if(!NT_SUCCESS(IoQueryFileDosDeviceName(pFileObject,&pObjectNameInfo)))
                return NULL;
                ObDereferenceObject(pFileObject);
        return &(pObjectNameInfo->Name);//尚未释放内存 以及 ObDereferenceObject
}

ULONG g_Count = 0;
NTSTATUS
DriverEntry (
    __in PDRIVER_OBJECT DriverObject,
    __in PUNICODE_STRING RegistryPath
    )
{
    OBJECT_ATTRIBUTES oa;
    UNICODE_STRING uniString;
    PSECURITY_DESCRIPTOR sd;
    NTSTATUS status;

    UNREFERENCED_PARAMETER( RegistryPath );

        g_LastDelFileName.Buffer = ExAllocatePool(NonPagedPool,MAX_PATH*2);
        g_LastDelFileName.Length = g_LastDelFileName.MaximumLength = MAX_PATH*2;
        memset(g_LastDelFileName.Buffer,'\0',MAX_PATH*2);

        //注册回调
    status = FltRegisterFilter( DriverObject,
                                &FilterRegistration,
                                &ScannerData.Filter );


    if (!NT_SUCCESS( status )) {

        return status;
    }

        //创建端口
    RtlInitUnicodeString( &uniString, ScannerPortName );

        //设置通信端口权限 ,只有管理员和系统进程才能操作
    status = FltBuildDefaultSecurityDescriptor( &sd, FLT_PORT_ALL_ACCESS );

    if (NT_SUCCESS( status )) {

        InitializeObjectAttributes( &oa,
                                    &uniString,
                                    OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                                    NULL,
                                    sd );

                //创建通信端口,并设置对应的回调函数
        status = FltCreateCommunicationPort( ScannerData.Filter,
                                             &ScannerData.ServerPort,
                                             &oa,//设置的名字
                                             NULL,
                                             ScannerPortConnect,//当R3连接时回调 主要是记录R3的进程ID或EPROCESS以便放过本进程 还有记录R3的通信端口,给后面主动通信的时候用
                                             ScannerPortDisconnect,//当R3离线时回调 主要是关闭R3端口和设置R3的进程信息为NULL
                                             NULL,//处理R3主动函数 比如R3下新的规则,
                                             1 );//最后一个常为1
                //设置好后需要释放权限的设置
        FltFreeSecurityDescriptor( sd );

        if (NT_SUCCESS( status )) {

            //
            //  Start filtering I/O.
            //
                        //开始过滤
            status = FltStartFiltering( ScannerData.Filter );

            if (NT_SUCCESS( status )) {

                return STATUS_SUCCESS;
            }
                        //失败就滚吧
            FltCloseCommunicationPort( ScannerData.ServerPort );
        }
    }
        //失败就滚吧
    FltUnregisterFilter( ScannerData.Filter );

    return status;
}


NTSTATUS
ScannerPortConnect (
    __in PFLT_PORT ClientPort,
    __in_opt PVOID ServerPortCookie,
    __in_bcount_opt(SizeOfContext) PVOID ConnectionContext,
    __in ULONG SizeOfContext,
    __deref_out_opt PVOID *ConnectionCookie
    )
{
    PAGED_CODE();

    UNREFERENCED_PARAMETER( ServerPortCookie );
    UNREFERENCED_PARAMETER( ConnectionContext );
    UNREFERENCED_PARAMETER( SizeOfContext);
    UNREFERENCED_PARAMETER( ConnectionCookie );

    ASSERT( ScannerData.ClientPort == NULL );
    ASSERT( ScannerData.UserProcess == NULL );

        //设置本身进程 和 R3的的通信端口 给后面判断和通信时使用
    ScannerData.UserProcess = PsGetCurrentProcess();
    ScannerData.ClientPort = ClientPort;

    DbgPrint( "!!! scanner.sys --- connected, port=0x%p\n", ClientPort );

    return STATUS_SUCCESS;
}


VOID
ScannerPortDisconnect(
     __in_opt PVOID ConnectionCookie
     )
{
    UNREFERENCED_PARAMETER( ConnectionCookie );

    PAGED_CODE();

    DbgPrint( "!!! scanner.sys --- disconnected, port=0x%p\n", ScannerData.ClientPort );

        //关闭R3通信端口
    FltCloseClientPort( ScannerData.Filter, &ScannerData.ClientPort );

        //设置R3进程为0
    ScannerData.UserProcess = NULL;
}


NTSTATUS
ScannerUnload (
    __in FLT_FILTER_UNLOAD_FLAGS Flags
    )
{
    UNREFERENCED_PARAMETER( Flags );

    //
    //  Close the server port.
    //
        if(g_LastDelFileName.Buffer)
                ExFreePool(g_LastDelFileName.Buffer);

    FltCloseCommunicationPort( ScannerData.ServerPort );
       

    //
    //  Unregister the filter
    //

    FltUnregisterFilter( ScannerData.Filter );

    return STATUS_SUCCESS;
}

NTSTATUS
ScannerInstanceSetup (
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __in FLT_INSTANCE_SETUP_FLAGS Flags,
    __in DEVICE_TYPE VolumeDeviceType,
    __in FLT_FILESYSTEM_TYPE VolumeFilesystemType
    )
{
    UNREFERENCED_PARAMETER( FltObjects );
    UNREFERENCED_PARAMETER( Flags );
    UNREFERENCED_PARAMETER( VolumeFilesystemType );

    PAGED_CODE();

    ASSERT( FltObjects->Filter == ScannerData.Filter );

    //
    //  Don't attach to network volumes.
    //

    if (VolumeDeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM) {

       return STATUS_FLT_DO_NOT_ATTACH;
    }

    return STATUS_SUCCESS;
}

NTSTATUS
ScannerQueryTeardown (
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __in FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags
    )
{
    UNREFERENCED_PARAMETER( FltObjects );
    UNREFERENCED_PARAMETER( Flags );

    return STATUS_SUCCESS;
}


FLT_PREOP_CALLBACK_STATUS
ScannerPreCreate (
    __inout PFLT_CALLBACK_DATA Data,
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __deref_out_opt PVOID *CompletionContext
    )
{
    UNREFERENCED_PARAMETER( FltObjects );
    UNREFERENCED_PARAMETER( CompletionContext );

    PAGED_CODE();

    //
    //  See if this create is being done by our user process.
    //
        //DbgPrint(&quotre Creta!\n");

    if (IoThreadToProcess( Data->Thread ) == ScannerData.UserProcess) {

        DbgPrint( "!!! scanner.sys -- allowing create for trusted process \n" );

        return FLT_PREOP_SUCCESS_NO_CALLBACK;
    }

    return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}

BOOLEAN
ScannerpCheckExtension (
    __in PUNICODE_STRING Extension
    )
{
    const UNICODE_STRING *ext;

    if (Extension->Length == 0) {

        return FALSE;
    }

    //
    //  Check if it matches any one of our static extension list
    //

    ext = ScannerExtensionsToScan;

    while (ext->Buffer != NULL) {

        if (RtlCompareUnicodeString( Extension, ext, TRUE ) == 0) {

            //
            //  A match. We are interested in this file
            //

            return TRUE;
        }
        ext++;
    }

    return FALSE;
}

//处理打开,创建时(一般这个时候提示的话就是已经被感染了)
FLT_POSTOP_CALLBACK_STATUS
ScannerPostCreate (
    __inout PFLT_CALLBACK_DATA Data,
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __in_opt PVOID CompletionContext,
    __in FLT_POST_OPERATION_FLAGS Flags
    )
{
    FLT_POSTOP_CALLBACK_STATUS returnStatus = FLT_POSTOP_FINISHED_PROCESSING;
    PFLT_FILE_NAME_INFORMATION nameInfo;
    NTSTATUS status;
    BOOLEAN safeToOpen, scanFile;
        UNICODE_STRING ustrRule = {0};
    ULONG  Options;
        ULONG ulDisposition;
        BOOLEAN PopWindow = FALSE;
        FILE_DISPOSITION_INFORMATION  fdi;

    UNREFERENCED_PARAMETER( CompletionContext );
        UNREFERENCED_PARAMETER( Flags );
    //UNREFERENCED_PARAMETER( Flags );

    //
    //  If this create was failing anyway, don't bother scanning now.
    //

        //DbgPrint(&quotos Creta!\n");

    if (!NT_SUCCESS( Data->IoStatus.Status ) ||
        (STATUS_REPARSE == Data->IoStatus.Status)) {

        return FLT_POSTOP_FINISHED_PROCESSING;
    }
       
        Options = Data->Iopb-&gtarameters.Create.Options;

         if (FlagOn(Options, FILE_DIRECTORY_FILE) ||
                 FlagOn(FltObjects->FileObject->Flags, FO_VOLUME_OPEN) ||
                 FlagOn(Data->Flags, SL_OPEN_PAGING_FILE))
    {
        return FLT_POSTOP_FINISHED_PROCESSING;
    }

         ulDisposition = (Data->Iopb-&gtarameters.Create.Options >> 24) & 0xFF;
        if (ulDisposition == FILE_CREATE || ulDisposition == FILE_OVERWRITE || ulDisposition == FILE_OVERWRITE_IF)
    {
                PopWindow = TRUE;
    }

    status = FltGetFileNameInformation( Data,
                                        FLT_FILE_NAME_NORMALIZED |
                                            FLT_FILE_NAME_QUERY_DEFAULT,
                                        &nameInfo );

    if (!NT_SUCCESS( status )) {

        return FLT_POSTOP_FINISHED_PROCESSING;
    }

    FltParseFileNameInformation( nameInfo );

    //
    //  Check if the extension matches the list of extensions we are interested in
    //

        RtlInitUnicodeString(&ustrRule, L"\\*\\*\\WINDOWS\\SYSTEM32\\*\\*.SYS");
       
        scanFile = IsPatternMatch(&ustrRule,&nameInfo->Name,TRUE);
        //DbgPrint("%wZ\n",&nameInfo->Name);
    //scanFile = ScannerpCheckExtension( &nameInfo->Extension );

    //
    //  Release file name info, we're done with it
    //

    FltReleaseFileNameInformation( nameInfo );

    if (!scanFile) {

        //
        //  Not an extension we are interested in
        //

        return FLT_POSTOP_FINISHED_PROCESSING;
    }

        if(PopWindow)
        {
                 MyScannerpScanFileInUserMode( FltObjects->Instance,
                                       FltObjects->FileObject,
                                                                           Data,
                                                                           1,
                                       &safeToOpen );

                if (!safeToOpen) {

                        //
                        //  Ask the filter manager to undo the create.
                        //

                        DbgPrint( "!!! scanner.sys -- foul language detected in postcreate !!!\n" );

                        DbgPrint( "!!! scanner.sys -- undoing create \n" );

                        //就算拒绝了 也会创建一个空文件 这里我们删除
                        fdi.DeleteFile = TRUE;
                        FltSetInformationFile(FltObjects->Instance, FltObjects->FileObject, &fdi, sizeof(FILE_DISPOSITION_INFORMATION), FileDispositionInformation);

                        FltCancelFileOpen( FltObjects->Instance, FltObjects->FileObject );

                        Data->IoStatus.Status = STATUS_ACCESS_DENIED;
                        Data->IoStatus.Information = 0;

                        returnStatus = FLT_POSTOP_FINISHED_PROCESSING;

                }
        }

    return returnStatus;
}

//处理打开时 有写权限但 打开成功时是安全的,等它关闭的时候的我们来扫描它
//触发这个回调的条件是文件引用技术为0,这个包括内核+R3的计数,一般是在上层使用了ZwClose或者CloseHandle时调用
FLT_PREOP_CALLBACK_STATUS
ScannerPreCleanup (
    __inout PFLT_CALLBACK_DATA Data,
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __deref_out_opt PVOID *CompletionContext
    )
{

    UNREFERENCED_PARAMETER( Data );
        UNREFERENCED_PARAMETER( FltObjects );
    UNREFERENCED_PARAMETER( CompletionContext );


    return FLT_PREOP_SUCCESS_NO_CALLBACK;
}




//处理写关闭
FLT_PREOP_CALLBACK_STATUS
ScannerPreWrite (
    __inout PFLT_CALLBACK_DATA Data,
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __deref_out_opt PVOID *CompletionContext
    )
{
    FLT_PREOP_CALLBACK_STATUS returnStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
    UNREFERENCED_PARAMETER( CompletionContext );
        UNREFERENCED_PARAMETER( FltObjects );
        UNREFERENCED_PARAMETER( Data );

    //
    //  If not client port just ignore this write.
    //
        //如果R3进程退出了
    if (ScannerData.ClientPort == NULL) {

        return FLT_PREOP_SUCCESS_NO_CALLBACK;
    }
    return returnStatus;
}

BOOLEAN isNeedWatchFile(PFLT_CALLBACK_DATA Data)
{
        BOOLEAN Ret = FALSE;
        UNICODE_STRING ustrRule = {0};
        PFLT_FILE_NAME_INFORMATION nameInfo = {0};
        NTSTATUS status = STATUS_SUCCESS;

        status = FltGetFileNameInformation( Data,
                                        FLT_FILE_NAME_NORMALIZED |
                                            FLT_FILE_NAME_QUERY_DEFAULT,
                                        &nameInfo );

    if (!NT_SUCCESS( status )) {

                return FALSE;
    }

    FltParseFileNameInformation( nameInfo );

        RtlInitUnicodeString(&ustrRule, L"\\*\\*\\WINDOWS\\SYSTEM32\\*\\*.SYS");

        Ret = IsPatternMatch(&ustrRule,&nameInfo->Name,TRUE);

    FltReleaseFileNameInformation( nameInfo );

        return Ret;
}

VOID UnicodeToChar(PUNICODE_STRING src, char *dst)
{
        ANSI_STRING string;
        RtlUnicodeStringToAnsiString(&string,src,TRUE);
        strcpy(dst,string.Buffer);
        RtlFreeAnsiString(&string);
}

BOOLEAN isRecycle(PFLT_CALLBACK_DATA Data ,PCFLT_RELATED_OBJECTS FltObje)
{
        BOOLEAN Ret = FALSE;
        PFLT_FILE_NAME_INFORMATION nameInfo = {0};
        PFILE_RENAME_INFORMATION pRenameInfo = {0};
        NTSTATUS status = STATUS_SUCCESS;
        char *temp = (char*)ExAllocatePool(NonPagedPool,MAX_PATH*2);

        if(temp == NULL)
                return TRUE;


        memset(temp,'\0',MAX_PATH*2);

        //特殊情况,当字符串中包含$Recycle.Bin时是普通删除,实际上删除只是更名而已
        pRenameInfo = (PFILE_RENAME_INFORMATION)Data->Iopb-&gtarameters.SetFileInformation.InfoBuffer;

        status = FltGetDestinationFileNameInformation(FltObje->Instance,Data->Iopb->TargetFileObject,pRenameInfo->RootDirectory,pRenameInfo->FileName,pRenameInfo->FileNameLength,FLT_FILE_NAME_NORMALIZED,&nameInfo);
        if(!NT_SUCCESS(status))
        {
                DbgPrint("FltGetDestinationFileNameInformation is faild! 0x%x",status);
                return TRUE;
        }

        UnicodeToChar(&nameInfo->Name,temp);
        if(strstr(temp,"Recycle.Bin"))
                Ret = TRUE;
        else
                Ret = FALSE;

        FltReleaseFileNameInformation(nameInfo);
  
        ExFreePool(temp);

        return Ret;
}

FLT_PREOP_CALLBACK_STATUS
ScannerPreSetInforMation(
    __inout PFLT_CALLBACK_DATA Data,
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __deref_out_opt PVOID *CompletionContext
    )
{
        FLT_PREOP_CALLBACK_STATUS status = FLT_PREOP_SUCCESS_NO_CALLBACK;
        ULONG Options = 0;//记录操作类型 1创建,2重命名,3删除
        BOOLEAN isAllow = TRUE;//是否放行
        UNREFERENCED_PARAMETER(Data);
        UNREFERENCED_PARAMETER(FltObjects);
        UNREFERENCED_PARAMETER(CompletionContext);
        //UNREFERENCED_PARAMETER(FltObjects);

        if(ScannerData.ClientPort == NULL)
        {
                return FLT_PREOP_SUCCESS_NO_CALLBACK;
        }

        if(ScannerData.UserProcess == PsGetCurrentProcess())
        {
                return FLT_PREOP_SUCCESS_NO_CALLBACK;
        }


        /*
                        lpIrpStack-&gtarameters.SetFile.FileInformationClass == FileRenameInformation ||//重命名
            lpIrpStack-&gtarameters.SetFile.FileInformationClass == FileBasicInformation || //设置基础信息
            lpIrpStack->Parameters.SetFile.FileInformationClass == FileAllocationInformation ||
            lpIrpStack->Parameters.SetFile.FileInformationClass == FileEndOfFileInformation ||//设置大小
            lpIrpStack->Parameters.SetFile.FileInformationClass == FileDispositionInformation)//删除
                       
        */

        if(Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileRenameInformation ||
           Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileDispositionInformation )
        {
                switch (Data->Iopb->Parameters.SetFileInformation.FileInformationClass)
                {
                case FileRenameInformation:
                        Options = 2;
                        break;
                case FileDispositionInformation:
                        Options = 3;
                        break;
                default:
                        Options = 0;//爆炸啦
                        break;
                }

                //判断是不是我们要监控的
                if(!isNeedWatchFile(Data))
                {
                        return FLT_PREOP_SUCCESS_NO_CALLBACK;
                }

                if(Options == 2)
                {
                        if(isRecycle(Data,FltObjects))
                        {
                                return FLT_PREOP_SUCCESS_NO_CALLBACK;
                        }
                }


                //进程路径,操作类型,原路径,重命名后路径
                MyScannerpScanFileInUserMode(FltObjects->Instance,FltObjects->FileObject,Data,Options,&isAllow);

                if(!isAllow)
                {
                        DbgPrint("ReName in PreSetInforMation !\n");
                        Data->IoStatus.Status = STATUS_ACCESS_DENIED;
            Data->IoStatus.Information = 0;
            status = FLT_PREOP_COMPLETE;
                }else
                {
                        status = FLT_PREOP_SUCCESS_NO_CALLBACK;
                }

        }

        return status;
}


FLT_POSTOP_CALLBACK_STATUS
ScannerPostSetInforMation (
    __inout PFLT_CALLBACK_DATA Data,
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __in_opt PVOID CompletionContext,
    __in FLT_POST_OPERATION_FLAGS Flags
    )
{
        //FLT_POSTOP_CALLBACK_STATUS status = FLT_POSTOP_FINISHED_PROCESSING;
        //ULONG Options = 0;//记录操作类型 1创建,2重命名,3删除
        //BOOLEAN isAllow = TRUE;//是否放行
        UNREFERENCED_PARAMETER(Flags);
        UNREFERENCED_PARAMETER(Data);
        UNREFERENCED_PARAMETER(FltObjects);
        UNREFERENCED_PARAMETER(CompletionContext);

        /*
                        lpIrpStack->Parameters.SetFile.FileInformationClass == FileRenameInformation ||//重命名
            lpIrpStack->Parameters.SetFile.FileInformationClass == FileBasicInformation || //设置基础信息
            lpIrpStack->Parameters.SetFile.FileInformationClass == FileAllocationInformation ||
            lpIrpStack->Parameters.SetFile.FileInformationClass == FileEndOfFileInformation ||//设置大小
            lpIrpStack->Parameters.SetFile.FileInformationClass == FileDispositionInformation)//删除
                       
        */
        //if(Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileRenameInformation ||
        //   Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileDispositionInformation )
        //{
        //        switch (Data->Iopb->Parameters.SetFileInformation.FileInformationClass)
        //        {
        //        case FileRenameInformation:
        //                Options = 2;
        //                break;
        //        case FileDispositionInformation:
        //                Options = 3;
        //                break;
        //        default:
        //                Options = 0;//爆炸啦
        //                break;
        //        }

        //        //判断是不是我们要监控的
        //        if(!isNeedWatchFile(Data))
        //        {
        //                return FLT_POSTOP_FINISHED_PROCESSING;
        //        }

        //        if(Options == 2)
        //        {
        //                if(isRecycle(Data,FltObjects))
        //                {
        //                        return FLT_POSTOP_FINISHED_PROCESSING;
        //                }
        //        }


        //        //进程路径,操作类型,原路径,重命名后路径
        //        MyScannerpScanFileInUserMode(FltObjects->Instance,FltObjects->FileObject,Data,Options,&isAllow);

        //        if(!isAllow)
        //        {
        //                DbgPrint("ReName in PostSetInforMation !\n");
        //               
        //                FltCancelFileOpen( FltObjects->Instance, FltObjects->FileObject );
        //                Data->IoStatus.Status = STATUS_ACCESS_DENIED;
//           Data->IoStatus.Information = 0;
        //               
//           status = FLT_POSTOP_FINISHED_PROCESSING;
        //        }else
        //        {
        //                status = FLT_POSTOP_FINISHED_PROCESSING;
        //        }

        //}

        //return status;
        return FLT_POSTOP_FINISHED_PROCESSING;
}



//操作类型 1创建 2重命名 3 删除
NTSTATUS
MyScannerpScanFileInUserMode (
    __in PFLT_INSTANCE Instance,
    __in PFILE_OBJECT FileObject,
        __in PFLT_CALLBACK_DATA Data,
        __in ULONG                Operation,
    __out PBOOLEAN SafeToOpen
    )
{
    NTSTATUS status = STATUS_SUCCESS;

    PSCANNER_NOTIFICATION notification = NULL;
   
    ULONG replyLength = 0;
        PEPROCESS pEprocess = 0;
        PUNICODE_STRING uSProcessPath = NULL;
        PFLT_FILE_NAME_INFORMATION nameInfo;
        PFLT_FILE_NAME_INFORMATION pOutReNameinfo;
        PFILE_RENAME_INFORMATION pRenameInfo;

        UNREFERENCED_PARAMETER( FileObject );
        UNREFERENCED_PARAMETER( Instance );
    *SafeToOpen = TRUE;

    //
    //  If not client port just return.
    //

    if (ScannerData.ClientPort == NULL) {

        return STATUS_SUCCESS;
    }

    try {
                        notification = ExAllocatePoolWithTag( NonPagedPool,
                                              sizeof( SCANNER_NOTIFICATION ),
                                              'nacS' );

                        if(NULL == notification)
                        {
                                status = STATUS_INSUFFICIENT_RESOURCES;
                                leave;
                    }

                        //在这里获取进程路径,操作类型,目标路径
                        //拷贝操作类型

                        notification->Operation = Operation;
               
                        pEprocess =
                        Data->Thread ? IoThreadToProcess(Data->Thread) : PsGetCurrentProcess();

                        if(pEprocess == NULL)
                        {
                                status = STATUS_INSUFFICIENT_RESOURCES;
                                leave;
                        }

                        uSProcessPath = PsGetProcessFullName(pEprocess);//这里需要释放UNICODESTRING 的内存

                        if(uSProcessPath == NULL)
                        {
                                status = STATUS_INSUFFICIENT_RESOURCES;
                                leave;
                        }

                        //拷贝进程路径
                        wcsncpy(¬ification->ProcessPath,uSProcessPath->Buffer,uSProcessPath->Length);
                       

                        //wcsncpy(¬ification->ProcessPath,L"test",wcslen(L"test"));


                         status = FltGetFileNameInformation( Data,
                                                                                        FLT_FILE_NAME_NORMALIZED |
                                                                                                FLT_FILE_NAME_QUERY_DEFAULT,
                                                                                        &nameInfo );
                         //FltGetDestinationFileNameInformation(

                        if (!NT_SUCCESS( status )) {

                                status = STATUS_INSUFFICIENT_RESOURCES;
                                leave;
                        }

                       

                        //拷贝目标路径
                        FltParseFileNameInformation( nameInfo );

                        //这里应该注意下多线程的
                        if(Operation == 3)
                        {
                                //DbgPrint("[DjWow]%wZ\n",&g_LastDelFileName);
                                //DbgPrint("[DjWow]%wZ\n",&nameInfo->Name);
                                if(wcsncmp(g_LastDelFileName.Buffer,nameInfo->Name.Buffer,nameInfo->Name.MaximumLength) == 0)
                                {
                                        FltReleaseFileNameInformation( nameInfo );
                                        memset(g_LastDelFileName.Buffer,'\0',MAX_PATH*2);
                                        *SafeToOpen = TRUE;
                                        leave;
                                }
                        }

                        if(Operation == 3)
                        {
                                wcsncpy(g_LastDelFileName.Buffer,nameInfo->Name.Buffer,nameInfo->Name.MaximumLength);
                        }

                        wcsncpy(¬ification->TargetPath,nameInfo->Name.Buffer,nameInfo->Name.MaximumLength);
               
                        FltReleaseFileNameInformation( nameInfo );

                        if(Operation == 2)//重命名
                        {
                                pRenameInfo = (PFILE_RENAME_INFORMATION)Data->Iopb->Parameters.SetFileInformation.InfoBuffer;
                       
                                /*
                                //这也是可行的
                                wstrTest = ExAllocatePool(NonPagedPool,pRenameInfo->FileNameLength + 1);
                                if(wstrTest == NULL)
                                        leave;

                                memset(wstrTest,'\0',pRenameInfo->FileNameLength + 1);

                                wcsncpy(wstrTest,pRenameInfo->FileName,pRenameInfo->FileNameLength);
                                DbgPrint("%ws\n",wstrTest);*/

                               
                                status = FltGetDestinationFileNameInformation(Instance,Data->Iopb->TargetFileObject,pRenameInfo->RootDirectory,pRenameInfo->FileName,pRenameInfo->FileNameLength,FLT_FILE_NAME_NORMALIZED,&pOutReNameinfo);
                                if(!NT_SUCCESS(status))
                                {
                                        DbgPrint("FltGetDestinationFileNameInformation is faild! 0x%x",status);
                                        leave;
                                }
                                wcsncpy(¬ification->RePathName,pOutReNameinfo->Name.Buffer,pOutReNameinfo->Name.MaximumLength);
                               
                                DbgPrint("重命名:%wZ\n",&pOutReNameinfo->Name);

                                FltReleaseFileNameInformation(pOutReNameinfo);
                        }

            replyLength = sizeof( SCANNER_REPLY );

            status = FltSendMessage( ScannerData.Filter,
                                     &ScannerData.ClientPort,
                                     notification,
                                     sizeof(SCANNER_NOTIFICATION),
                                     notification,
                                     &replyLength,
                                     NULL );

            if (STATUS_SUCCESS == status) {

                *SafeToOpen = ((PSCANNER_REPLY) notification)->SafeToOpen;

            } else {

                //
                //  Couldn't send message
                //

                DbgPrint( "!!! scanner.sys --- couldn't send message to user-mode to scan file, status 0x%X\n", status );
            }

    } finally {

        if (NULL != notification) {

            ExFreePoolWithTag( notification, 'nacS' );
        }

                if(NULL != pEprocess)
                {
                        //ObfDereferenceObject(pEprocess);
                }

                if(NULL != uSProcessPath)
                {
                        ExFreePool(uSProcessPath);
                }

    }

    return status;
}



[/code]
R3:


// MiniFliter_MFCDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "MiniFliter_MFC.h"
#include "MiniFliter_MFCDlg.h"
#include "afxdialogex.h"
#include "resource.h"
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <winioctl.h>
#include <string.h>
#include <crtdbg.h>
#include <assert.h>
#include <fltuser.h>
#include "../MiniFliter_Scaner/scanuk.h"
#include "User.h"
#include <dontuse.h>
#include "PopupDlg.h"

#pragma comment(lib,"fltlib.lib")


#define SCANNER_DEFAULT_REQUEST_COUNT       5
#define SCANNER_DEFAULT_THREAD_COUNT        2
#define SCANNER_MAX_THREAD_COUNT            64


typedef struct _SCANNER_THREAD_CONTEXT {

    HANDLE Port;
    HANDLE Completion;

} SCANNER_THREAD_CONTEXT, *PSCANNER_THREAD_CONTEXT;


HANDLE g_port = 0;

#ifdef _DEBUG
#define new DEBUG_NEW
#endif



// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialogEx
{
public:
        CAboutDlg();

// 对话框数据
        enum { IDD = IDD_ABOUTBOX };

        protected:
        virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
        DECLARE_MESSAGE_MAP()
public:
        //virtual INT_PTR DoModal();
};

CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
{
}

void CAboutDlg:oDataExchange(CDataExchange* pDX)
{
        CDialogEx:oDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
END_MESSAGE_MAP()


// CMiniFliter_MFCDlg 对话框



CMiniFliter_MFCDlg::CMiniFliter_MFCDlg(CWnd* pParent /*=NULL*/)
        : CDialogEx(CMiniFliter_MFCDlg::IDD, pParent)
{
        m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CMiniFliter_MFCDlg:oDataExchange(CDataExchange* pDX)
{
        CDialogEx:oDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CMiniFliter_MFCDlg, CDialogEx)
        ON_WM_SYSCOMMAND()
        ON_WM_PAINT()
        ON_WM_QUERYDRAGICON()
        ON_BN_CLICKED(IDC_START, &CMiniFliter_MFCDlg::OnBnClickedStart)
END_MESSAGE_MAP()


// CMiniFliter_MFCDlg 消息处理程序

BOOL CMiniFliter_MFCDlg::OnInitDialog()
{
        CDialogEx::OnInitDialog();

        // 将“关于...”菜单项添加到系统菜单中。

        // IDM_ABOUTBOX 必须在系统命令范围内。
        ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
        ASSERT(IDM_ABOUTBOX < 0xF000);

        CMenu* pSysMenu = GetSystemMenu(FALSE);
        if (pSysMenu != NULL)
        {
                BOOL bNameValid;
                CString strAboutMenu;
                bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
                ASSERT(bNameValid);
                if (!strAboutMenu.IsEmpty())
                {
                        pSysMenu->AppendMenu(MF_SEPARATOR);
                        pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
                }
        }

        // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
        //  执行此操作
        SetIcon(m_hIcon, TRUE);                        // 设置大图标
        SetIcon(m_hIcon, FALSE);                // 设置小图标

       

        return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CMiniFliter_MFCDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
        if ((nID & 0xFFF0) == IDM_ABOUTBOX)
        {
                CAboutDlg dlgAbout;
                //dlgAbout.DoModal();
        }
        else
        {
                CDialogEx::OnSysCommand(nID, lParam);
        }
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CMiniFliter_MFCDlg::OnPaint()
{
        if (IsIconic())
        {
                CPaintDC dc(this); // 用于绘制的设备上下文

                SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

                // 使图标在工作区矩形中居中
                int cxIcon = GetSystemMetrics(SM_CXICON);
                int cyIcon = GetSystemMetrics(SM_CYICON);
                CRect rect;
                GetClientRect(&rect);
                int x = (rect.Width() - cxIcon + 1) / 2;
                int y = (rect.Height() - cyIcon + 1) / 2;

                // 绘制图标
                dc.DrawIcon(x, y, m_hIcon);
        }
        else
        {
                CDialogEx::OnPaint();
        }
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CMiniFliter_MFCDlg::OnQueryDragIcon()
{
        return static_cast<HCURSOR>(m_hIcon);
}


DWORD HandData(LPCTSTR str)
{
        CPopupDlg dlg;
        dlg.SetText(str);
        dlg.DoModal();

        if(dlg.m_Allow == TRUE)
                return 1;
        else
                return 0;
       
}

DWORD
ScannerWorker(
    __in PSCANNER_THREAD_CONTEXT Context
    )
{
        DWORD                dwRet = 0;
    DWORD            outSize        = 0;

    HRESULT                hr = 0;
    ULONG_PTR        key        = 0;

        BOOL                result = TRUE;
        //CHAR                strPop[MAX_PATH*2]        = {0};
        WCHAR                strOptions[50*2] = {0};//操作类型字符串
        WCHAR                LastPath[MAX_PATH*2] = {0};
        BOOL                LastResult = TRUE;
       
        LPOVERLAPPED pOvlp;
    PSCANNER_NOTIFICATION notification;
    SCANNER_REPLY_MESSAGE replyMessage;
    PSCANNER_MESSAGE message;
        //DWORD dwRet = 0;
        CString tip = NULL;
   
        memset(LastPath,'\0',MAX_PATH*2);
#pragma warning(push)
#pragma warning(disable:4127) // conditional expression is constant

    while (TRUE) {

#pragma warning(pop)

        //
        //  Poll for messages from the filter component to scan.
        //

        result = GetQueuedCompletionStatus( Context->Completion, &outSize, &key, &pOvlp, INFINITE );

        //
        //  Obtain the message: note that the message we sent down via FltGetMessage() may NOT be
        //  the one dequeued off the completion queue: this is solely because there are multiple
        //  threads per single port handle. Any of the FilterGetMessage() issued messages can be
        //  completed in random order - and we will just dequeue a random one.
        //

        message = CONTAINING_RECORD( pOvlp, SCANNER_MESSAGE, Ovlp );

        if (!result) {
            hr = HRESULT_FROM_WIN32( GetLastError() );
            break;
        }

        //printf( "Received message, size %d\n", pOvlp->InternalHigh );
                //tip.Format(L"Received message, size %d\n", pOvlp->InternalHigh );


        notification = &message->Notification;

                if(notification->Operation == 1)
                {
                        if(wcsncmp(LastPath,notification->TargetPath,wcslen(notification->TargetPath))==0)
                        {
                                memset(LastPath,'\0',MAX_PATH*2);
                                result = LastResult;
                                goto EX;
                        }
                }

                memset(strOptions,'\0',50);
               

                switch (notification->Operation)
                {
                case 1:
                        wcscpy_s(strOptions,50,L"创建");
                        break;
                case 2:
                        wcscpy_s(strOptions,50,L"重命名");
                        break;
                case 3:
                        wcscpy_s(strOptions,50,L"删除");
                        break;
                default:
                        wcscpy_s(strOptions,50,L"爆炸");
                        break;
                }

                //memset(strPop,'\0',MAX_PATH*2);

                if(notification->Operation == 2)
                {
                        //sprintf(strPop,"进程:%S\r\n操作:%s\r\n目标:%S\r\n重名为:%S\r\n是否放行?",notification->ProcessPath,strOptions,notification->TargetPath,notification->RePathName);
                        tip.Format(L"进程:%s\r\n操作:%s\r\n目标:%s\r\n重名为:%s\r\n是否放行?",notification->ProcessPath,strOptions,notification->TargetPath,notification->RePathName);
                }else
                {
                        //sprintf(strPop,"进程:%S\r\n操作:%s\r\n目标:%S\r\n是否放行?",notification->ProcessPath,strOptions,notification->TargetPath);
                        tip.Format(L"进程:%s\r\n操作:%s\r\n目标:%s\r\n是否放行?",notification->ProcessPath,strOptions,notification->TargetPath);
                }

                Sleep(1000);
                //dwRet = MessageBoxA(NULL,strPop,"监控到攻击行为",MB_YESNO);

                dwRet = HandData(tip);

                if(dwRet == 1)
                        result = FALSE;
                else
                        result = TRUE;

                LastResult = result;
                EX:
                wcsncpy_s(LastPath,MAX_PATH*2,notification->TargetPath,MAX_PATH*2);

        replyMessage.ReplyHeader.Status = 0;
        replyMessage.ReplyHeader.MessageId = message->MessageHeader.MessageId;

        replyMessage.Reply.SafeToOpen = !result;

        printf( "Replying message, ResultCode: %d\n", replyMessage.Reply.SafeToOpen );

        hr = FilterReplyMessage( Context->Port,
                                 (PFILTER_REPLY_HEADER) &replyMessage,
                                 sizeof( replyMessage ) );

        if (SUCCEEDED( hr )) {

            printf( "Replied message\n" );

        } else {

            printf( "Scanner: Error replying message. Error = 0x%X\n", hr );
            break;
        }

        memset( &message->Ovlp, 0, sizeof( OVERLAPPED ) );

        hr = FilterGetMessage( Context->Port,
                               &message->MessageHeader,
                               FIELD_OFFSET( SCANNER_MESSAGE, Ovlp ),
                               &message->Ovlp );

        if (hr != HRESULT_FROM_WIN32( ERROR_IO_PENDING )) {

            break;
        }
    }

    if (!SUCCEEDED( hr )) {

        if (hr == HRESULT_FROM_WIN32( ERROR_INVALID_HANDLE )) {

            //
            //  Scanner port disconncted.
            //

            printf( "Scanner: Port is disconnected, probably due to scanner filter unloading.\n" );

        } else {

            printf( "Scanner: Unknown error occured. Error = 0x%X\n", hr );
        }
    }

    free( message );

    return hr;
}


//此函数需放到线程中执行
int InitFltUser()
{
        DWORD dwDefRequestCount = SCANNER_DEFAULT_REQUEST_COUNT;
        DWORD dwDefThreadCount = SCANNER_DEFAULT_THREAD_COUNT;
        DWORD dwMaxThreadCount = SCANNER_MAX_THREAD_COUNT;
        SCANNER_THREAD_CONTEXT context;
        PSCANNER_MESSAGE msg;
        HANDLE threads[SCANNER_MAX_THREAD_COUNT];
        CString tip = NULL;
        DWORD threadId;
        DWORD i = 0;

        //连接到端口

        HRESULT hr =  FilterConnectCommunicationPort(ScannerPortName,0,NULL,0,NULL,&g_port);

        if(IS_ERROR(hr))
        {
                AfxMessageBox(L"hr is null\n");
                return 0;
        }
       
        //为这个句柄创建一个Comption

        HANDLE completion = CreateIoCompletionPort( g_port,
                                         NULL,
                                         0,
                                                                                 dwDefThreadCount );

    if (completion == NULL)
        {
                tip.Format(L"ERROR: Creating completion port: %d\n", GetLastError());
                AfxMessageBox(tip);
        CloseHandle( g_port );
        return 0;
    }

        //tip.Format(L"Scanner: Port = 0x%p Completion = 0x%p\n", g_port, completion );
        //this->SetWindowTextW(tip);

    context.Port = g_port;
    context.Completion = completion;

    //创建规定的线程


        for (i = 0; i < dwDefThreadCount; i++)
        {
                //创建线程
                threads = CreateThread( NULL,
                                   0,
                                                                   (LPTHREAD_START_ROUTINE)ScannerWorker,
                                   &context,
                                   0,
                                   &threadId );

                if (threads == NULL)
                {
            hr = GetLastError();
                        tip.Format(L"ERROR: Couldn't create thread: %d\n", hr );
                        //this->SetWindowTextW(tip);
            goto main_cleanup;
        }

                for (DWORD j = 0; j < dwDefRequestCount; j++)
                {

            //
            //  Allocate the message.
            //

#pragma prefast(suppress:__WARNING_MEMORY_LEAK, "msg will not be leaked because it is freed in ScannerWorker")

            msg = (PSCANNER_MESSAGE)malloc( sizeof( SCANNER_MESSAGE ));

            if (msg == NULL) {

                hr = ERROR_NOT_ENOUGH_MEMORY;
                goto main_cleanup;
            }

            memset( &msg->Ovlp, 0, sizeof( OVERLAPPED ) );

            //
            //  Request messages from the filter driver.
            //

            hr = FilterGetMessage( g_port,
                                   &msg->MessageHeader,
                                   FIELD_OFFSET( SCANNER_MESSAGE, Ovlp ),
                                   &msg->Ovlp );

            if (hr != HRESULT_FROM_WIN32( ERROR_IO_PENDING ))
                        {

                free( msg );
                goto main_cleanup;
            }
        }
        }

        hr = S_OK;

    WaitForMultipleObjectsEx( i, threads, TRUE, INFINITE, FALSE );
        //返回线程数组和 数组个数
               
main_cleanup:

        tip.Format(L"Scanner:  All done. Result = 0x%08x\n", hr );
        //this->SetWindowTextW(tip);
        CloseHandle(g_port);
        CloseHandle(completion);

        return hr+1;
}


void CMiniFliter_MFCDlg::OnBnClickedStart()
{
        CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)InitFltUser,NULL,0,NULL);
}
[/code]
其中的HandData函数就是弹个窗,得到返回值 就不给出了
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-3-19 12:19

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表