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

驱动学习 专栏收录该内容
94 篇文章 7 订阅

注意下:我的这套过滤只能用在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);


在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->Parameters.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->Parameters.Create.Options >> 24) & 0xFF;
	if (ulDisposition == FILE_CREATE || ulDisposition == FILE_OVERWRITE || ulDisposition == FILE_OVERWRITE_IF)
    {
		PopWindow = TRUE;
    }


另外遇到的问题是删除

删除分两种

一种是直接删除 也就是shift+Del的方式

这种没什么问题

另外一种普通的删除,右键文件-删除-或者直接按Del

这其实一个发现 + 更名的操作

这个发现具体我也不知道怎么说,因为你普通删除文件的时候,不是有一个正在发现文件吗,就是统计文件的大小操作

然后就是更名的操作

这是我第一次实验时出现的情况

我的操作是 普通删除->放行->然后就出现了这个框

有了这个后 就简单了,在PreSetInforMation中获得文件全路径,匹配如果中间有Recycle.Bin的字符串

但这不是准确的,我也偷懒啦



至于重命名 无非就是拿到重命名后的路径

两种方法

1.直接在buffer中拿

2.FltGetDestinationFileNameInformation获得

不懂的是:重命名的路径能直接在buffer中拿到 为什么还要使用FltGetDestinationFileNameInformation呢,知道的人可以回复下

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);


其他没什么了 就是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("Pre 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("Pos Creta!\n");

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

        return FLT_POSTOP_FINISHED_PROCESSING;
    }
	
	Options = Data->Iopb->Parameters.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->Parameters.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->Parameters.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->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_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;
}




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::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(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::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(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[i] = CreateThread( NULL,
                                   0,
								   (LPTHREAD_START_ROUTINE)ScannerWorker,
                                   &context,
                                   0,
                                   &threadId );

		if (threads[i] == 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);
}

其中的HandData函数就是弹个窗,得到返回值 就不给出了

  • 2
    点赞
  • 1
    评论
  • 6
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

评论1
请先登录 后发表评论~
©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页

打赏作者

zhuhuibeishadiao

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值