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

注意下:我的这套过滤只能用在nt6系统上

原因是使用一个nt6上才有的函数

见函数

PsGetProcessFullName

其实没必要自己来写获取全路径

因为minifilter已经给我们提供了获取全路径的函数

FltGetFileNameInformation

我就不改了,哈哈

 

说说遇到的问题吧

在监控创建的时候,我是在post中监控,我拒绝后,会弹窗,2-3次吧,也就是会请求2-3次,我的解决方法是记录上一次拒绝的文件全路径,然后下一次来的时候来比对

这里可以将处理过的文件加入链表或者hash,我偷懒了,就直接用这种方法来解决多重求情的问题,

这里注意下,出现多次请求的原因是你第一次放行了,那么我们第二次的时候就知道比对的时候就直接放行了

 

考虑过在pre中监控

但根据MF周老师的意见 说在这里拿到的信息是不准确的,

可以用下面一句话总结:

在pre中是对请求本身就行拦截,在post中是对请求完成结果的拦截.

遵循周老师的意见,我还是在post中监控

 

在拦截创建的时候,还有一个问题,就是如果创建的时候我拒绝了,那么返回给用户的会出现一个替换的框(文件已存在,但大小是0)

针对这个情况,我直接对这个data设置文件属性 有点像前面学习的IRP下发强删文件

 

 

  1. //就算拒绝了 也会创建一个空文件 这里我们删除  
  2.             fdi.DeleteFile = TRUE;  
  3.             FltSetInformationFile(FltObjects->Instance, FltObjects->FileObject, &fdi, sizeof(FILE_DISPOSITION_INFORMATION), FileDispositionInformation);  
//就算拒绝了 也会创建一个空文件 这里我们删除
			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就说明是新建操作

下面是对文件夹的判断

 

  1. if (!NT_SUCCESS( Data->IoStatus.Status ) ||  
  2.        (STATUS_REPARSE == Data->IoStatus.Status)) {  
  3.   
  4.        return FLT_POSTOP_FINISHED_PROCESSING;  
  5.    }  
  6.   
  7. Options = Data->Iopb->Parameters.Create.Options;  
  8.   
  9.  if (FlagOn(Options, FILE_DIRECTORY_FILE) ||  
  10.      FlagOn(FltObjects->FileObject->Flags, FO_VOLUME_OPEN) ||  
  11.      FlagOn(Data->Flags, SL_OPEN_PAGING_FILE))  
  12.    {  
  13.        return FLT_POSTOP_FINISHED_PROCESSING;  
  14.    }  
  15.   
  16.  ulDisposition = (Data->Iopb->Parameters.Create.Options >> 24) & 0xFF;  
  17. if (ulDisposition == FILE_CREATE || ulDisposition == FILE_OVERWRITE || ulDisposition == FILE_OVERWRITE_IF)  
  18.    {  
  19.     PopWindow = TRUE;  
  20.    }  
 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呢,知道的人可以回复下

 

  1. pRenameInfo = (PFILE_RENAME_INFORMATION)Data->Iopb->Parameters.SetFileInformation.InfoBuffer;  
  2.               
  3.                 /* 
  4.                 //这也是可行的 
  5.                 wstrTest = ExAllocatePool(NonPagedPool,pRenameInfo->FileNameLength + 1); 
  6.                 if(wstrTest == NULL) 
  7.                     leave; 
  8.  
  9.                 memset(wstrTest,'\0',pRenameInfo->FileNameLength + 1); 
  10.  
  11.                 wcsncpy(wstrTest,pRenameInfo->FileName,pRenameInfo->FileNameLength); 
  12.                 DbgPrint("%ws\n",wstrTest);*/  
  13.   
  14.                   
  15.                 status = FltGetDestinationFileNameInformation(Instance,Data->Iopb->TargetFileObject,pRenameInfo->RootDirectory,pRenameInfo->FileName,pRenameInfo->FileNameLength,FLT_FILE_NAME_NORMALIZED,&pOutReNameinfo);  
  16.                 if(!NT_SUCCESS(status))  
  17.                 {  
  18.                     DbgPrint("FltGetDestinationFileNameInformation is faild! 0x%x",status);  
  19.                     leave;  
  20.                 }  
  21.                 wcsncpy(¬ification->RePathName,pOutReNameinfo->Name.Buffer,pOutReNameinfo->Name.MaximumLength);  
  22.                   
  23.                 DbgPrint("重命名:%wZ\n",&pOutReNameinfo->Name);  
  24.   
  25.                 FltReleaseFileNameInformation(pOutReNameinfo);  
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

 

  1. #include <fltKernel.h>  
  2. #include <dontuse.h>  
  3. #include <suppress.h>  
  4. #include "scanuk.h"  
  5. #include "scanner.h"  
  6.   
  7. #pragma prefast(disable:__WARNING_ENCODE_MEMBER_FUNCTION_POINTER, "Not valid for kernel mode drivers")  
  8.   
  9.   
  10. NTSTATUS  
  11. PsReferenceProcessFilePointer (  
  12. IN PEPROCESS Process,  
  13. OUT PVOID *OutFileObject  
  14. );  
  15.   
  16. SCANNER_DATA ScannerData;  
  17.   
  18. UNICODE_STRING g_LastDelFileName = {0};  
  19.   
  20. //  
  21. //  This is a static list of file name extensions files we are interested in scanning  
  22. //  
  23.   
  24. const UNICODE_STRING ScannerExtensionsToScan[] =  
  25.     { RTL_CONSTANT_STRING( L"doc"),  
  26.       RTL_CONSTANT_STRING( L"txt"),  
  27.       RTL_CONSTANT_STRING( L"bat"),  
  28.       RTL_CONSTANT_STRING( L"cmd"),  
  29.       RTL_CONSTANT_STRING( L"inf"),  
  30.       /*RTL_CONSTANT_STRING( L"ini"),   Removed, to much usage*/  
  31.       {0, 0, NULL}  
  32.     };  
  33.   
  34.   
  35. //  
  36. //  Function prototypes  
  37. //  
  38.   
  39. NTSTATUS  
  40. ScannerPortConnect (  
  41.     __in PFLT_PORT ClientPort,  
  42.     __in_opt PVOID ServerPortCookie,  
  43.     __in_bcount_opt(SizeOfContext) PVOID ConnectionContext,  
  44.     __in ULONG SizeOfContext,  
  45.     __deref_out_opt PVOID *ConnectionCookie  
  46.     );  
  47.   
  48. VOID  
  49. ScannerPortDisconnect (  
  50.     __in_opt PVOID ConnectionCookie  
  51.     );  
  52.   
  53. NTSTATUS  
  54. ScannerpScanFileInUserMode (  
  55.     __in PFLT_INSTANCE Instance,  
  56.     __in PFILE_OBJECT FileObject,  
  57.     __out PBOOLEAN SafeToOpen  
  58.     );  
  59.   
  60. BOOLEAN  
  61. ScannerpCheckExtension (  
  62.     __in PUNICODE_STRING Extension  
  63.     );  
  64.   
  65. NTSTATUS  
  66. MyScannerpScanFileInUserMode (  
  67.     __in PFLT_INSTANCE Instance,  
  68.     __in PFILE_OBJECT FileObject,  
  69.     __in PFLT_CALLBACK_DATA Data,  
  70.     __in ULONG      Operation,  
  71.     __out PBOOLEAN SafeToOpen  
  72.     );  
  73.   
  74. //  
  75. //  Assign text sections for each routine.  
  76. //  
  77.   
  78. #ifdef ALLOC_PRAGMA  
  79.     #pragma alloc_text(INIT, DriverEntry)  
  80.     #pragma alloc_text(PAGE, ScannerInstanceSetup)  
  81.     #pragma alloc_text(PAGE, ScannerPreCreate)  
  82.     #pragma alloc_text(PAGE, ScannerPostCreate)  
  83.     #pragma alloc_text(PAGE, ScannerPortConnect)  
  84.     #pragma alloc_text(PAGE, ScannerPortDisconnect)  
  85.     #pragma alloc_text(PAGE, ScannerPostSetInforMation)  
  86.     #pragma alloc_text(PAGE, ScannerPreSetInforMation )  
  87. //IsPatternMatch  
  88. //PsGetProcessFullName  
  89. #endif  
  90.   
  91.   
  92. //  
  93. //  Constant FLT_REGISTRATION structure for our filter.  This  
  94. //  initializes the callback routines our filter wants to register  
  95. //  for.  This is only used to register with the filter manager  
  96. //  
  97.   
  98. const FLT_OPERATION_REGISTRATION Callbacks[] = {  
  99.   
  100.     { IRP_MJ_CREATE,  
  101.       0,  
  102.       ScannerPreCreate,  
  103.       ScannerPostCreate},  
  104.   
  105.     { IRP_MJ_CLEANUP,  
  106.       0,  
  107.       ScannerPreCleanup,  
  108.       NULL},  
  109.   
  110.     { IRP_MJ_WRITE,  
  111.       0,  
  112.       ScannerPreWrite,  
  113.       NULL},  
  114.   
  115.     { IRP_MJ_SET_INFORMATION,  
  116.       0,  
  117.       ScannerPreSetInforMation,  
  118.       ScannerPostSetInforMation},  
  119.   
  120.     { IRP_MJ_OPERATION_END }  
  121. };  
  122.   
  123.   
  124. const FLT_CONTEXT_REGISTRATION ContextRegistration[] = {  
  125.   
  126.     { FLT_STREAMHANDLE_CONTEXT,  
  127.       0,  
  128.       NULL,  
  129.       sizeof(SCANNER_STREAM_HANDLE_CONTEXT),  
  130.       'chBS' },  
  131.   
  132.     { FLT_CONTEXT_END }  
  133. };  
  134.   
  135. const FLT_REGISTRATION FilterRegistration = {  
  136.   
  137.     sizeof( FLT_REGISTRATION ),         //  Size  
  138.     FLT_REGISTRATION_VERSION,           //  Version  
  139.     0,                                  //  Flags  
  140.     ContextRegistration,                //  Context Registration.  
  141.     Callbacks,                          //  Operation callbacks  
  142.     ScannerUnload,                      //  FilterUnload  
  143.     ScannerInstanceSetup,               //  InstanceSetup  
  144.     ScannerQueryTeardown,               //  InstanceQueryTeardown  
  145.     NULL,                               //  InstanceTeardownStart  
  146.     NULL,                               //  InstanceTeardownComplete  
  147.     NULL,                               //  GenerateFileName  
  148.     NULL,                               //  GenerateDestinationFileName  
  149.     NULL                                //  NormalizeNameComponent  
  150. };  
  151.   
  152.   
  153.   
  154. BOOLEAN IsPatternMatch(PUNICODE_STRING Expression, PUNICODE_STRING Name, BOOLEAN IgnoreCase)  
  155. {  
  156.     return FsRtlIsNameInExpression(  
  157.         Expression,  
  158.         Name,  
  159.         IgnoreCase,//如果这里设置为TRUE,那么Expression必须是大写的  
  160.         NULL  
  161.         );   
  162.       
  163. }  
  164.   
  165. PUNICODE_STRING PsGetProcessFullName(PEPROCESS pTargetProcess)  
  166. {  
  167.         PFILE_OBJECT pFileObject=NULL;  
  168.         POBJECT_NAME_INFORMATION pObjectNameInfo=NULL;  
  169.         if(!NT_SUCCESS(PsReferenceProcessFilePointer(pTargetProcess,&pFileObject)))  
  170.                 return NULL;  
  171.         if(!NT_SUCCESS(IoQueryFileDosDeviceName(pFileObject,&pObjectNameInfo)))  
  172.                 return NULL;  
  173.         ObDereferenceObject(pFileObject);  
  174.         return &(pObjectNameInfo->Name);//尚未释放内存 以及 ObDereferenceObject  
  175. }  
  176.   
  177. ULONG g_Count = 0;  
  178. NTSTATUS  
  179. DriverEntry (  
  180.     __in PDRIVER_OBJECT DriverObject,  
  181.     __in PUNICODE_STRING RegistryPath  
  182.     )  
  183. {  
  184.     OBJECT_ATTRIBUTES oa;  
  185.     UNICODE_STRING uniString;  
  186.     PSECURITY_DESCRIPTOR sd;  
  187.     NTSTATUS status;  
  188.   
  189.     UNREFERENCED_PARAMETER( RegistryPath );  
  190.   
  191.     g_LastDelFileName.Buffer = ExAllocatePool(NonPagedPool,MAX_PATH*2);  
  192.     g_LastDelFileName.Length = g_LastDelFileName.MaximumLength = MAX_PATH*2;  
  193.     memset(g_LastDelFileName.Buffer,'\0',MAX_PATH*2);  
  194.   
  195.     //注册回调  
  196.     status = FltRegisterFilter( DriverObject,  
  197.                                 &FilterRegistration,  
  198.                                 &ScannerData.Filter );  
  199.   
  200.   
  201.     if (!NT_SUCCESS( status )) {  
  202.   
  203.         return status;  
  204.     }  
  205.   
  206.     //创建端口  
  207.     RtlInitUnicodeString( &uniString, ScannerPortName );  
  208.   
  209.     //设置通信端口权限 ,只有管理员和系统进程才能操作  
  210.     status = FltBuildDefaultSecurityDescriptor( &sd, FLT_PORT_ALL_ACCESS );  
  211.   
  212.     if (NT_SUCCESS( status )) {  
  213.   
  214.         InitializeObjectAttributes( &oa,  
  215.                                     &uniString,  
  216.                                     OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,  
  217.                                     NULL,  
  218.                                     sd );  
  219.   
  220.         //创建通信端口,并设置对应的回调函数  
  221.         status = FltCreateCommunicationPort( ScannerData.Filter,  
  222.                                              &ScannerData.ServerPort,  
  223.                                              &oa,//设置的名字  
  224.                                              NULL,  
  225.                                              ScannerPortConnect,//当R3连接时回调 主要是记录R3的进程ID或EPROCESS以便放过本进程 还有记录R3的通信端口,给后面主动通信的时候用  
  226.                                              ScannerPortDisconnect,//当R3离线时回调 主要是关闭R3端口和设置R3的进程信息为NULL  
  227.                                              NULL,//处理R3主动函数 比如R3下新的规则,  
  228.                                              1 );//最后一个常为1  
  229.         //设置好后需要释放权限的设置  
  230.         FltFreeSecurityDescriptor( sd );  
  231.   
  232.         if (NT_SUCCESS( status )) {  
  233.   
  234.             //  
  235.             //  Start filtering I/O.  
  236.             //  
  237.             //开始过滤  
  238.             status = FltStartFiltering( ScannerData.Filter );  
  239.   
  240.             if (NT_SUCCESS( status )) {  
  241.   
  242.                 return STATUS_SUCCESS;  
  243.             }  
  244.             //失败就滚吧  
  245.             FltCloseCommunicationPort( ScannerData.ServerPort );  
  246.         }  
  247.     }  
  248.     //失败就滚吧  
  249.     FltUnregisterFilter( ScannerData.Filter );  
  250.   
  251.     return status;  
  252. }  
  253.   
  254.   
  255. NTSTATUS  
  256. ScannerPortConnect (  
  257.     __in PFLT_PORT ClientPort,  
  258.     __in_opt PVOID ServerPortCookie,  
  259.     __in_bcount_opt(SizeOfContext) PVOID ConnectionContext,  
  260.     __in ULONG SizeOfContext,  
  261.     __deref_out_opt PVOID *ConnectionCookie  
  262.     )  
  263. {  
  264.     PAGED_CODE();  
  265.   
  266.     UNREFERENCED_PARAMETER( ServerPortCookie );  
  267.     UNREFERENCED_PARAMETER( ConnectionContext );  
  268.     UNREFERENCED_PARAMETER( SizeOfContext);  
  269.     UNREFERENCED_PARAMETER( ConnectionCookie );  
  270.   
  271.     ASSERT( ScannerData.ClientPort == NULL );  
  272.     ASSERT( ScannerData.UserProcess == NULL );  
  273.   
  274.     //设置本身进程 和 R3的的通信端口 给后面判断和通信时使用  
  275.     ScannerData.UserProcess = PsGetCurrentProcess();  
  276.     ScannerData.ClientPort = ClientPort;  
  277.   
  278.     DbgPrint( "!!! scanner.sys --- connected, port=0x%p\n", ClientPort );  
  279.   
  280.     return STATUS_SUCCESS;  
  281. }  
  282.   
  283.   
  284. VOID  
  285. ScannerPortDisconnect(  
  286.      __in_opt PVOID ConnectionCookie  
  287.      )  
  288. {  
  289.     UNREFERENCED_PARAMETER( ConnectionCookie );  
  290.   
  291.     PAGED_CODE();  
  292.   
  293.     DbgPrint( "!!! scanner.sys --- disconnected, port=0x%p\n", ScannerData.ClientPort );  
  294.   
  295.     //关闭R3通信端口  
  296.     FltCloseClientPort( ScannerData.Filter, &ScannerData.ClientPort );  
  297.   
  298.     //设置R3进程为0  
  299.     ScannerData.UserProcess = NULL;  
  300. }  
  301.   
  302.   
  303. NTSTATUS  
  304. ScannerUnload (  
  305.     __in FLT_FILTER_UNLOAD_FLAGS Flags  
  306.     )  
  307. {  
  308.     UNREFERENCED_PARAMETER( Flags );  
  309.   
  310.     //  
  311.     //  Close the server port.  
  312.     //  
  313.     if(g_LastDelFileName.Buffer)  
  314.         ExFreePool(g_LastDelFileName.Buffer);  
  315.   
  316.     FltCloseCommunicationPort( ScannerData.ServerPort );  
  317.       
  318.   
  319.     //  
  320.     //  Unregister the filter  
  321.     //  
  322.   
  323.     FltUnregisterFilter( ScannerData.Filter );  
  324.   
  325.     return STATUS_SUCCESS;  
  326. }  
  327.   
  328. NTSTATUS  
  329. ScannerInstanceSetup (  
  330.     __in PCFLT_RELATED_OBJECTS FltObjects,  
  331.     __in FLT_INSTANCE_SETUP_FLAGS Flags,  
  332.     __in DEVICE_TYPE VolumeDeviceType,  
  333.     __in FLT_FILESYSTEM_TYPE VolumeFilesystemType  
  334.     )  
  335. {  
  336.     UNREFERENCED_PARAMETER( FltObjects );  
  337.     UNREFERENCED_PARAMETER( Flags );  
  338.     UNREFERENCED_PARAMETER( VolumeFilesystemType );  
  339.   
  340.     PAGED_CODE();  
  341.   
  342.     ASSERT( FltObjects->Filter == ScannerData.Filter );  
  343.   
  344.     //  
  345.     //  Don't attach to network volumes.  
  346.     //  
  347.   
  348.     if (VolumeDeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM) {  
  349.   
  350.        return STATUS_FLT_DO_NOT_ATTACH;  
  351.     }  
  352.   
  353.     return STATUS_SUCCESS;  
  354. }  
  355.   
  356. NTSTATUS  
  357. ScannerQueryTeardown (  
  358.     __in PCFLT_RELATED_OBJECTS FltObjects,  
  359.     __in FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags  
  360.     )  
  361. {  
  362.     UNREFERENCED_PARAMETER( FltObjects );  
  363.     UNREFERENCED_PARAMETER( Flags );  
  364.   
  365.     return STATUS_SUCCESS;  
  366. }  
  367.   
  368.   
  369. FLT_PREOP_CALLBACK_STATUS  
  370. ScannerPreCreate (  
  371.     __inout PFLT_CALLBACK_DATA Data,  
  372.     __in PCFLT_RELATED_OBJECTS FltObjects,  
  373.     __deref_out_opt PVOID *CompletionContext  
  374.     )  
  375. {  
  376.     UNREFERENCED_PARAMETER( FltObjects );  
  377.     UNREFERENCED_PARAMETER( CompletionContext );  
  378.   
  379.     PAGED_CODE();  
  380.   
  381.     //  
  382.     //  See if this create is being done by our user process.  
  383.     //  
  384.     //DbgPrint("Pre Creta!\n");  
  385.   
  386.     if (IoThreadToProcess( Data->Thread ) == ScannerData.UserProcess) {  
  387.   
  388.         DbgPrint( "!!! scanner.sys -- allowing create for trusted process \n" );  
  389.   
  390.         return FLT_PREOP_SUCCESS_NO_CALLBACK;  
  391.     }  
  392.   
  393.     return FLT_PREOP_SUCCESS_WITH_CALLBACK;  
  394. }  
  395.   
  396. BOOLEAN  
  397. ScannerpCheckExtension (  
  398.     __in PUNICODE_STRING Extension  
  399.     )  
  400. {  
  401.     const UNICODE_STRING *ext;  
  402.   
  403.     if (Extension->Length == 0) {  
  404.   
  405.         return FALSE;  
  406.     }  
  407.   
  408.     //  
  409.     //  Check if it matches any one of our static extension list  
  410.     //  
  411.   
  412.     ext = ScannerExtensionsToScan;  
  413.   
  414.     while (ext->Buffer != NULL) {  
  415.   
  416.         if (RtlCompareUnicodeString( Extension, ext, TRUE ) == 0) {  
  417.   
  418.             //  
  419.             //  A match. We are interested in this file  
  420.             //  
  421.   
  422.             return TRUE;  
  423.         }  
  424.         ext++;  
  425.     }  
  426.   
  427.     return FALSE;  
  428. }  
  429.   
  430. //处理打开,创建时(一般这个时候提示的话就是已经被感染了)  
  431. FLT_POSTOP_CALLBACK_STATUS  
  432. ScannerPostCreate (  
  433.     __inout PFLT_CALLBACK_DATA Data,  
  434.     __in PCFLT_RELATED_OBJECTS FltObjects,  
  435.     __in_opt PVOID CompletionContext,  
  436.     __in FLT_POST_OPERATION_FLAGS Flags  
  437.     )  
  438. {  
  439.     FLT_POSTOP_CALLBACK_STATUS returnStatus = FLT_POSTOP_FINISHED_PROCESSING;  
  440.     PFLT_FILE_NAME_INFORMATION nameInfo;  
  441.     NTSTATUS status;  
  442.     BOOLEAN safeToOpen, scanFile;  
  443.     UNICODE_STRING ustrRule = {0};  
  444.     ULONG  Options;  
  445.     ULONG ulDisposition;  
  446.     BOOLEAN PopWindow = FALSE;  
  447.     FILE_DISPOSITION_INFORMATION  fdi;  
  448.   
  449.     UNREFERENCED_PARAMETER( CompletionContext );  
  450.     UNREFERENCED_PARAMETER( Flags );  
  451.     //UNREFERENCED_PARAMETER( Flags );  
  452.   
  453.     //  
  454.     //  If this create was failing anyway, don't bother scanning now.  
  455.     //  
  456.   
  457.     //DbgPrint("Pos Creta!\n");  
  458.   
  459.     if (!NT_SUCCESS( Data->IoStatus.Status ) ||  
  460.         (STATUS_REPARSE == Data->IoStatus.Status)) {  
  461.   
  462.         return FLT_POSTOP_FINISHED_PROCESSING;  
  463.     }  
  464.       
  465.     Options = Data->Iopb->Parameters.Create.Options;  
  466.   
  467.      if (FlagOn(Options, FILE_DIRECTORY_FILE) ||  
  468.          FlagOn(FltObjects->FileObject->Flags, FO_VOLUME_OPEN) ||  
  469.          FlagOn(Data->Flags, SL_OPEN_PAGING_FILE))  
  470.     {  
  471.         return FLT_POSTOP_FINISHED_PROCESSING;  
  472.     }  
  473.   
  474.      ulDisposition = (Data->Iopb->Parameters.Create.Options >> 24) & 0xFF;  
  475.     if (ulDisposition == FILE_CREATE || ulDisposition == FILE_OVERWRITE || ulDisposition == FILE_OVERWRITE_IF)  
  476.     {  
  477.         PopWindow = TRUE;  
  478.     }  
  479.   
  480.     status = FltGetFileNameInformation( Data,  
  481.                                         FLT_FILE_NAME_NORMALIZED |  
  482.                                             FLT_FILE_NAME_QUERY_DEFAULT,  
  483.                                         &nameInfo );  
  484.   
  485.     if (!NT_SUCCESS( status )) {  
  486.   
  487.         return FLT_POSTOP_FINISHED_PROCESSING;  
  488.     }  
  489.   
  490.     FltParseFileNameInformation( nameInfo );  
  491.   
  492.     //  
  493.     //  Check if the extension matches the list of extensions we are interested in  
  494.     //  
  495.   
  496.     RtlInitUnicodeString(&ustrRule, L"\\*\\*\\WINDOWS\\SYSTEM32\\*\\*.SYS");  
  497.       
  498.     scanFile = IsPatternMatch(&ustrRule,&nameInfo->Name,TRUE);  
  499.     //DbgPrint("%wZ\n",&nameInfo->Name);  
  500.     //scanFile = ScannerpCheckExtension( &nameInfo->Extension );  
  501.   
  502.     //  
  503.     //  Release file name info, we're done with it  
  504.     //  
  505.   
  506.     FltReleaseFileNameInformation( nameInfo );  
  507.   
  508.     if (!scanFile) {  
  509.   
  510.         //  
  511.         //  Not an extension we are interested in  
  512.         //  
  513.   
  514.         return FLT_POSTOP_FINISHED_PROCESSING;  
  515.     }  
  516.   
  517.     if(PopWindow)  
  518.     {  
  519.          MyScannerpScanFileInUserMode( FltObjects->Instance,  
  520.                                        FltObjects->FileObject,  
  521.                                        Data,  
  522.                                        1,  
  523.                                        &safeToOpen );  
  524.   
  525.         if (!safeToOpen) {  
  526.   
  527.             //  
  528.             //  Ask the filter manager to undo the create.  
  529.             //  
  530.   
  531.             DbgPrint( "!!! scanner.sys -- foul language detected in postcreate !!!\n" );  
  532.   
  533.             DbgPrint( "!!! scanner.sys -- undoing create \n" );  
  534.   
  535.             //就算拒绝了 也会创建一个空文件 这里我们删除  
  536.             fdi.DeleteFile = TRUE;  
  537.             FltSetInformationFile(FltObjects->Instance, FltObjects->FileObject, &fdi, sizeof(FILE_DISPOSITION_INFORMATION), FileDispositionInformation);  
  538.   
  539.             FltCancelFileOpen( FltObjects->Instance, FltObjects->FileObject );  
  540.   
  541.             Data->IoStatus.Status = STATUS_ACCESS_DENIED;  
  542.             Data->IoStatus.Information = 0;  
  543.   
  544.             returnStatus = FLT_POSTOP_FINISHED_PROCESSING;  
  545.   
  546.         }  
  547.     }  
  548.   
  549.     return returnStatus;  
  550. }  
  551.   
  552. //处理打开时 有写权限但 打开成功时是安全的,等它关闭的时候的我们来扫描它  
  553. //触发这个回调的条件是文件引用技术为0,这个包括内核+R3的计数,一般是在上层使用了ZwClose或者CloseHandle时调用  
  554. FLT_PREOP_CALLBACK_STATUS  
  555. ScannerPreCleanup (  
  556.     __inout PFLT_CALLBACK_DATA Data,  
  557.     __in PCFLT_RELATED_OBJECTS FltObjects,  
  558.     __deref_out_opt PVOID *CompletionContext  
  559.     )  
  560. {  
  561.   
  562.     UNREFERENCED_PARAMETER( Data );  
  563.     UNREFERENCED_PARAMETER( FltObjects );  
  564.     UNREFERENCED_PARAMETER( CompletionContext );  
  565.   
  566.   
  567.     return FLT_PREOP_SUCCESS_NO_CALLBACK;  
  568. }  
  569.   
  570.   
  571.   
  572.   
  573. //处理写关闭  
  574. FLT_PREOP_CALLBACK_STATUS  
  575. ScannerPreWrite (  
  576.     __inout PFLT_CALLBACK_DATA Data,  
  577.     __in PCFLT_RELATED_OBJECTS FltObjects,  
  578.     __deref_out_opt PVOID *CompletionContext  
  579.     )  
  580. {  
  581.     FLT_PREOP_CALLBACK_STATUS returnStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;  
  582.     UNREFERENCED_PARAMETER( CompletionContext );  
  583.     UNREFERENCED_PARAMETER( FltObjects );  
  584.     UNREFERENCED_PARAMETER( Data );  
  585.   
  586.     //  
  587.     //  If not client port just ignore this write.  
  588.     //  
  589.     //如果R3进程退出了  
  590.     if (ScannerData.ClientPort == NULL) {  
  591.   
  592.         return FLT_PREOP_SUCCESS_NO_CALLBACK;  
  593.     }  
  594.     return returnStatus;  
  595. }  
  596.   
  597. BOOLEAN isNeedWatchFile(PFLT_CALLBACK_DATA Data)  
  598. {  
  599.     BOOLEAN Ret = FALSE;  
  600.     UNICODE_STRING ustrRule = {0};  
  601.     PFLT_FILE_NAME_INFORMATION nameInfo = {0};  
  602.     NTSTATUS status = STATUS_SUCCESS;  
  603.   
  604.     status = FltGetFileNameInformation( Data,  
  605.                                         FLT_FILE_NAME_NORMALIZED |  
  606.                                             FLT_FILE_NAME_QUERY_DEFAULT,  
  607.                                         &nameInfo );  
  608.   
  609.     if (!NT_SUCCESS( status )) {  
  610.   
  611.         return FALSE;  
  612.     }  
  613.   
  614.     FltParseFileNameInformation( nameInfo );  
  615.   
  616.     RtlInitUnicodeString(&ustrRule, L"\\*\\*\\WINDOWS\\SYSTEM32\\*\\*.SYS");  
  617.   
  618.     Ret = IsPatternMatch(&ustrRule,&nameInfo->Name,TRUE);  
  619.   
  620.     FltReleaseFileNameInformation( nameInfo );  
  621.   
  622.     return Ret;  
  623. }  
  624.   
  625. VOID UnicodeToChar(PUNICODE_STRING src, char *dst)  
  626. {  
  627.     ANSI_STRING string;  
  628.     RtlUnicodeStringToAnsiString(&string,src,TRUE);  
  629.     strcpy(dst,string.Buffer);  
  630.     RtlFreeAnsiString(&string);  
  631. }  
  632.   
  633. BOOLEAN isRecycle(PFLT_CALLBACK_DATA Data ,PCFLT_RELATED_OBJECTS FltObje)  
  634. {  
  635.     BOOLEAN Ret = FALSE;  
  636.     PFLT_FILE_NAME_INFORMATION nameInfo = {0};  
  637.     PFILE_RENAME_INFORMATION pRenameInfo = {0};  
  638.     NTSTATUS status = STATUS_SUCCESS;  
  639.     char *temp = (char*)ExAllocatePool(NonPagedPool,MAX_PATH*2);  
  640.   
  641.     if(temp == NULL)  
  642.         return TRUE;  
  643.   
  644.   
  645.     memset(temp,'\0',MAX_PATH*2);  
  646.   
  647.     //特殊情况,当字符串中包含$Recycle.Bin时是普通删除,实际上删除只是更名而已  
  648.     pRenameInfo = (PFILE_RENAME_INFORMATION)Data->Iopb->Parameters.SetFileInformation.InfoBuffer;  
  649.   
  650.     status = FltGetDestinationFileNameInformation(FltObje->Instance,Data->Iopb->TargetFileObject,pRenameInfo->RootDirectory,pRenameInfo->FileName,pRenameInfo->FileNameLength,FLT_FILE_NAME_NORMALIZED,&nameInfo);  
  651.     if(!NT_SUCCESS(status))  
  652.     {  
  653.         DbgPrint("FltGetDestinationFileNameInformation is faild! 0x%x",status);  
  654.         return TRUE;  
  655.     }  
  656.   
  657.     UnicodeToChar(&nameInfo->Name,temp);  
  658.     if(strstr(temp,"Recycle.Bin"))  
  659.         Ret = TRUE;  
  660.     else  
  661.         Ret = FALSE;  
  662.   
  663.     FltReleaseFileNameInformation(nameInfo);  
  664.     
  665.     ExFreePool(temp);  
  666.   
  667.     return Ret;  
  668. }  
  669.   
  670. FLT_PREOP_CALLBACK_STATUS  
  671. ScannerPreSetInforMation(  
  672.     __inout PFLT_CALLBACK_DATA Data,  
  673.     __in PCFLT_RELATED_OBJECTS FltObjects,  
  674.     __deref_out_opt PVOID *CompletionContext  
  675.     )  
  676. {  
  677.     FLT_PREOP_CALLBACK_STATUS status = FLT_PREOP_SUCCESS_NO_CALLBACK;  
  678.     ULONG Options = 0;//记录操作类型 1创建,2重命名,3删除  
  679.     BOOLEAN isAllow = TRUE;//是否放行  
  680.     UNREFERENCED_PARAMETER(Data);  
  681.     UNREFERENCED_PARAMETER(FltObjects);  
  682.     UNREFERENCED_PARAMETER(CompletionContext);  
  683.     //UNREFERENCED_PARAMETER(FltObjects);  
  684.   
  685.     if(ScannerData.ClientPort == NULL)  
  686.     {  
  687.         return FLT_PREOP_SUCCESS_NO_CALLBACK;  
  688.     }  
  689.   
  690.     if(ScannerData.UserProcess == PsGetCurrentProcess())  
  691.     {  
  692.         return FLT_PREOP_SUCCESS_NO_CALLBACK;  
  693.     }  
  694.   
  695.   
  696.     /* 
  697.             lpIrpStack->Parameters.SetFile.FileInformationClass == FileRenameInformation ||//重命名 
  698.             lpIrpStack->Parameters.SetFile.FileInformationClass == FileBasicInformation || //设置基础信息 
  699.             lpIrpStack->Parameters.SetFile.FileInformationClass == FileAllocationInformation || 
  700.             lpIrpStack->Parameters.SetFile.FileInformationClass == FileEndOfFileInformation ||//设置大小 
  701.             lpIrpStack->Parameters.SetFile.FileInformationClass == FileDispositionInformation)//删除 
  702.              
  703.     */  
  704.   
  705.     if(Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileRenameInformation ||  
  706.        Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileDispositionInformation )  
  707.     {  
  708.         switch (Data->Iopb->Parameters.SetFileInformation.FileInformationClass)  
  709.         {  
  710.         case FileRenameInformation:  
  711.             Options = 2;  
  712.             break;  
  713.         case FileDispositionInformation:  
  714.             Options = 3;  
  715.             break;  
  716.         default:  
  717.             Options = 0;//爆炸啦  
  718.             break;  
  719.         }  
  720.   
  721.         //判断是不是我们要监控的  
  722.         if(!isNeedWatchFile(Data))  
  723.         {  
  724.             return FLT_PREOP_SUCCESS_NO_CALLBACK;  
  725.         }  
  726.   
  727.         if(Options == 2)  
  728.         {  
  729.             if(isRecycle(Data,FltObjects))  
  730.             {  
  731.                 return FLT_PREOP_SUCCESS_NO_CALLBACK;  
  732.             }  
  733.         }  
  734.   
  735.   
  736.         //进程路径,操作类型,原路径,重命名后路径  
  737.         MyScannerpScanFileInUserMode(FltObjects->Instance,FltObjects->FileObject,Data,Options,&isAllow);  
  738.   
  739.         if(!isAllow)  
  740.         {  
  741.             DbgPrint("ReName in PreSetInforMation !\n");  
  742.             Data->IoStatus.Status = STATUS_ACCESS_DENIED;  
  743.             Data->IoStatus.Information = 0;  
  744.             status = FLT_PREOP_COMPLETE;  
  745.         }else  
  746.         {  
  747.             status = FLT_PREOP_SUCCESS_NO_CALLBACK;  
  748.         }  
  749.   
  750.     }  
  751.   
  752.     return status;  
  753. }  
  754.   
  755.   
  756. FLT_POSTOP_CALLBACK_STATUS  
  757. ScannerPostSetInforMation (  
  758.     __inout PFLT_CALLBACK_DATA Data,  
  759.     __in PCFLT_RELATED_OBJECTS FltObjects,  
  760.     __in_opt PVOID CompletionContext,  
  761.     __in FLT_POST_OPERATION_FLAGS Flags  
  762.     )  
  763. {  
  764.     //FLT_POSTOP_CALLBACK_STATUS status = FLT_POSTOP_FINISHED_PROCESSING;  
  765.     //ULONG Options = 0;//记录操作类型 1创建,2重命名,3删除  
  766.     //BOOLEAN isAllow = TRUE;//是否放行  
  767.     UNREFERENCED_PARAMETER(Flags);  
  768.     UNREFERENCED_PARAMETER(Data);  
  769.     UNREFERENCED_PARAMETER(FltObjects);  
  770.     UNREFERENCED_PARAMETER(CompletionContext);  
  771.   
  772.     /* 
  773.             lpIrpStack->Parameters.SetFile.FileInformationClass == FileRenameInformation ||//重命名 
  774.             lpIrpStack->Parameters.SetFile.FileInformationClass == FileBasicInformation || //设置基础信息 
  775.             lpIrpStack->Parameters.SetFile.FileInformationClass == FileAllocationInformation || 
  776.             lpIrpStack->Parameters.SetFile.FileInformationClass == FileEndOfFileInformation ||//设置大小 
  777.             lpIrpStack->Parameters.SetFile.FileInformationClass == FileDispositionInformation)//删除 
  778.              
  779.     */  
  780.     //if(Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileRenameInformation ||  
  781.     //   Data->Iopb->Parameters.SetFileInformation.FileInformationClass == FileDispositionInformation )  
  782.     //{  
  783.     //  switch (Data->Iopb->Parameters.SetFileInformation.FileInformationClass)  
  784.     //  {  
  785.     //  case FileRenameInformation:  
  786.     //      Options = 2;  
  787.     //      break;  
  788.     //  case FileDispositionInformation:  
  789.     //      Options = 3;  
  790.     //      break;  
  791.     //  default:  
  792.     //      Options = 0;//爆炸啦  
  793.     //      break;  
  794.     //  }  
  795.   
  796.     //  //判断是不是我们要监控的  
  797.     //  if(!isNeedWatchFile(Data))  
  798.     //  {  
  799.     //      return FLT_POSTOP_FINISHED_PROCESSING;  
  800.     //  }  
  801.   
  802.     //  if(Options == 2)  
  803.     //  {  
  804.     //      if(isRecycle(Data,FltObjects))  
  805.     //      {  
  806.     //          return FLT_POSTOP_FINISHED_PROCESSING;  
  807.     //      }  
  808.     //  }  
  809.   
  810.   
  811.     //  //进程路径,操作类型,原路径,重命名后路径  
  812.     //  MyScannerpScanFileInUserMode(FltObjects->Instance,FltObjects->FileObject,Data,Options,&isAllow);  
  813.   
  814.     //  if(!isAllow)  
  815.     //  {  
  816.     //      DbgPrint("ReName in PostSetInforMation !\n");  
  817.     //        
  818.     //      FltCancelFileOpen( FltObjects->Instance, FltObjects->FileObject );  
  819.     //      Data->IoStatus.Status = STATUS_ACCESS_DENIED;  
  820.  //           Data->IoStatus.Information = 0;  
  821.     //        
  822.  //           status = FLT_POSTOP_FINISHED_PROCESSING;  
  823.     //  }else  
  824.     //  {  
  825.     //      status = FLT_POSTOP_FINISHED_PROCESSING;  
  826.     //  }  
  827.   
  828.     //}  
  829.   
  830.     //return status;  
  831.     return FLT_POSTOP_FINISHED_PROCESSING;  
  832. }  
  833.   
  834.   
  835.   
  836. //操作类型 1创建 2重命名 3 删除  
  837. NTSTATUS  
  838. MyScannerpScanFileInUserMode (  
  839.     __in PFLT_INSTANCE Instance,  
  840.     __in PFILE_OBJECT FileObject,  
  841.     __in PFLT_CALLBACK_DATA Data,  
  842.     __in ULONG      Operation,  
  843.     __out PBOOLEAN SafeToOpen  
  844.     )  
  845. {  
  846.     NTSTATUS status = STATUS_SUCCESS;  
  847.    
  848.     PSCANNER_NOTIFICATION notification = NULL;  
  849.      
  850.     ULONG replyLength = 0;  
  851.     PEPROCESS pEprocess = 0;  
  852.     PUNICODE_STRING uSProcessPath = NULL;  
  853.     PFLT_FILE_NAME_INFORMATION nameInfo;  
  854.     PFLT_FILE_NAME_INFORMATION pOutReNameinfo;  
  855.     PFILE_RENAME_INFORMATION pRenameInfo;  
  856.   
  857.     UNREFERENCED_PARAMETER( FileObject );  
  858.     UNREFERENCED_PARAMETER( Instance );  
  859.     *SafeToOpen = TRUE;  
  860.   
  861.     //  
  862.     //  If not client port just return.  
  863.     //  
  864.   
  865.     if (ScannerData.ClientPort == NULL) {  
  866.   
  867.         return STATUS_SUCCESS;  
  868.     }  
  869.   
  870.     try {  
  871.             notification = ExAllocatePoolWithTag( NonPagedPool,  
  872.                                               sizeof( SCANNER_NOTIFICATION ),  
  873.                                               'nacS' );  
  874.   
  875.             if(NULL == notification)   
  876.             {  
  877.                 status = STATUS_INSUFFICIENT_RESOURCES;  
  878.                 leave;  
  879.             }  
  880.   
  881.             //在这里获取进程路径,操作类型,目标路径  
  882.             //拷贝操作类型  
  883.   
  884.             notification->Operation = Operation;  
  885.           
  886.             pEprocess =   
  887.             Data->Thread ? IoThreadToProcess(Data->Thread) : PsGetCurrentProcess();  
  888.   
  889.             if(pEprocess == NULL)  
  890.             {  
  891.                 status = STATUS_INSUFFICIENT_RESOURCES;  
  892.                 leave;  
  893.             }  
  894.   
  895.             uSProcessPath = PsGetProcessFullName(pEprocess);//这里需要释放UNICODESTRING 的内存  
  896.   
  897.             if(uSProcessPath == NULL)  
  898.             {  
  899.                 status = STATUS_INSUFFICIENT_RESOURCES;  
  900.                 leave;  
  901.             }  
  902.   
  903.             //拷贝进程路径  
  904.             wcsncpy(¬ification->ProcessPath,uSProcessPath->Buffer,uSProcessPath->Length);  
  905.               
  906.   
  907.             //wcsncpy(¬ification->ProcessPath,L"test",wcslen(L"test"));  
  908.   
  909.   
  910.              status = FltGetFileNameInformation( Data,  
  911.                                             FLT_FILE_NAME_NORMALIZED |  
  912.                                                 FLT_FILE_NAME_QUERY_DEFAULT,  
  913.                                             &nameInfo );  
  914.              //FltGetDestinationFileNameInformation(  
  915.   
  916.             if (!NT_SUCCESS( status )) {  
  917.   
  918.                 status = STATUS_INSUFFICIENT_RESOURCES;  
  919.                 leave;  
  920.             }  
  921.   
  922.               
  923.   
  924.             //拷贝目标路径  
  925.             FltParseFileNameInformation( nameInfo );  
  926.   
  927.             //这里应该注意下多线程的  
  928.             if(Operation == 3)  
  929.             {  
  930.                 //DbgPrint("[DjWow]%wZ\n",&g_LastDelFileName);  
  931.                 //DbgPrint("[DjWow]%wZ\n",&nameInfo->Name);  
  932.                 if(wcsncmp(g_LastDelFileName.Buffer,nameInfo->Name.Buffer,nameInfo->Name.MaximumLength) == 0)  
  933.                 {  
  934.                     FltReleaseFileNameInformation( nameInfo );  
  935.                     memset(g_LastDelFileName.Buffer,'\0',MAX_PATH*2);  
  936.                     *SafeToOpen = TRUE;  
  937.                     leave;  
  938.                 }  
  939.             }  
  940.   
  941.             if(Operation == 3)  
  942.             {  
  943.                 wcsncpy(g_LastDelFileName.Buffer,nameInfo->Name.Buffer,nameInfo->Name.MaximumLength);  
  944.             }  
  945.   
  946.             wcsncpy(¬ification->TargetPath,nameInfo->Name.Buffer,nameInfo->Name.MaximumLength);  
  947.           
  948.             FltReleaseFileNameInformation( nameInfo );  
  949.   
  950.             if(Operation == 2)//重命名  
  951.             {  
  952.                 pRenameInfo = (PFILE_RENAME_INFORMATION)Data->Iopb->Parameters.SetFileInformation.InfoBuffer;  
  953.               
  954.                 /* 
  955.                 //这也是可行的 
  956.                 wstrTest = ExAllocatePool(NonPagedPool,pRenameInfo->FileNameLength + 1); 
  957.                 if(wstrTest == NULL) 
  958.                     leave; 
  959.  
  960.                 memset(wstrTest,'\0',pRenameInfo->FileNameLength + 1); 
  961.  
  962.                 wcsncpy(wstrTest,pRenameInfo->FileName,pRenameInfo->FileNameLength); 
  963.                 DbgPrint("%ws\n",wstrTest);*/  
  964.   
  965.                   
  966.                 status = FltGetDestinationFileNameInformation(Instance,Data->Iopb->TargetFileObject,pRenameInfo->RootDirectory,pRenameInfo->FileName,pRenameInfo->FileNameLength,FLT_FILE_NAME_NORMALIZED,&pOutReNameinfo);  
  967.                 if(!NT_SUCCESS(status))  
  968.                 {  
  969.                     DbgPrint("FltGetDestinationFileNameInformation is faild! 0x%x",status);  
  970.                     leave;  
  971.                 }  
  972.                 wcsncpy(¬ification->RePathName,pOutReNameinfo->Name.Buffer,pOutReNameinfo->Name.MaximumLength);  
  973.                   
  974.                 DbgPrint("重命名:%wZ\n",&pOutReNameinfo->Name);  
  975.   
  976.                 FltReleaseFileNameInformation(pOutReNameinfo);  
  977.             }  
  978.   
  979.             replyLength = sizeof( SCANNER_REPLY );  
  980.   
  981.             status = FltSendMessage( ScannerData.Filter,  
  982.                                      &ScannerData.ClientPort,  
  983.                                      notification,  
  984.                                      sizeof(SCANNER_NOTIFICATION),  
  985.                                      notification,  
  986.                                      &replyLength,  
  987.                                      NULL );  
  988.   
  989.             if (STATUS_SUCCESS == status) {  
  990.   
  991.                 *SafeToOpen = ((PSCANNER_REPLY) notification)->SafeToOpen;  
  992.   
  993.             } else {  
  994.   
  995.                 //  
  996.                 //  Couldn't send message  
  997.                 //  
  998.   
  999.                 DbgPrint( "!!! scanner.sys --- couldn't send message to user-mode to scan file, status 0x%X\n", status );  
  1000.             }  
  1001.   
  1002.     } finally {  
  1003.   
  1004.         if (NULL != notification) {  
  1005.   
  1006.             ExFreePoolWithTag( notification, 'nacS' );  
  1007.         }  
  1008.   
  1009.         if(NULL != pEprocess)  
  1010.         {  
  1011.             //ObfDereferenceObject(pEprocess);  
  1012.         }  
  1013.   
  1014.         if(NULL != uSProcessPath)  
  1015.         {  
  1016.             ExFreePool(uSProcessPath);  
  1017.         }  
  1018.   
  1019.     }  
  1020.   
  1021.     return status;  
  1022. }  
#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:

 

 

  1. // MiniFliter_MFCDlg.cpp : 实现文件  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include "MiniFliter_MFC.h"  
  6. #include "MiniFliter_MFCDlg.h"  
  7. #include "afxdialogex.h"  
  8. #include "resource.h"  
  9. #include <windows.h>  
  10. #include <stdlib.h>  
  11. #include <stdio.h>  
  12. #include <winioctl.h>  
  13. #include <string.h>  
  14. #include <crtdbg.h>  
  15. #include <assert.h>  
  16. #include <fltuser.h>  
  17. #include "../MiniFliter_Scaner/scanuk.h"  
  18. #include "User.h"  
  19. #include <dontuse.h>  
  20. #include "PopupDlg.h"  
  21.   
  22. #pragma comment(lib,"fltlib.lib")  
  23.   
  24.   
  25. #define SCANNER_DEFAULT_REQUEST_COUNT       5  
  26. #define SCANNER_DEFAULT_THREAD_COUNT        2  
  27. #define SCANNER_MAX_THREAD_COUNT            64  
  28.   
  29.   
  30. typedef struct _SCANNER_THREAD_CONTEXT {  
  31.   
  32.     HANDLE Port;  
  33.     HANDLE Completion;  
  34.   
  35. } SCANNER_THREAD_CONTEXT, *PSCANNER_THREAD_CONTEXT;  
  36.   
  37.   
  38. HANDLE g_port = 0;  
  39.   
  40. #ifdef _DEBUG  
  41. #define new DEBUG_NEW  
  42. #endif  
  43.   
  44.   
  45.   
  46. // 用于应用程序“关于”菜单项的 CAboutDlg 对话框  
  47.   
  48. class CAboutDlg : public CDialogEx  
  49. {  
  50. public:  
  51.     CAboutDlg();  
  52.   
  53. // 对话框数据  
  54.     enum { IDD = IDD_ABOUTBOX };  
  55.   
  56.     protected:  
  57.     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持  
  58.   
  59. // 实现  
  60. protected:  
  61.     DECLARE_MESSAGE_MAP()  
  62. public:  
  63.     //virtual INT_PTR DoModal();  
  64. };  
  65.   
  66. CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)  
  67. {  
  68. }  
  69.   
  70. void CAboutDlg::DoDataExchange(CDataExchange* pDX)  
  71. {  
  72.     CDialogEx::DoDataExchange(pDX);  
  73. }  
  74.   
  75. BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)  
  76. END_MESSAGE_MAP()  
  77.   
  78.   
  79. // CMiniFliter_MFCDlg 对话框  
  80.   
  81.   
  82.   
  83. CMiniFliter_MFCDlg::CMiniFliter_MFCDlg(CWnd* pParent /*=NULL*/)  
  84.     : CDialogEx(CMiniFliter_MFCDlg::IDD, pParent)  
  85. {  
  86.     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);  
  87. }  
  88.   
  89. void CMiniFliter_MFCDlg::DoDataExchange(CDataExchange* pDX)  
  90. {  
  91.     CDialogEx::DoDataExchange(pDX);  
  92. }  
  93.   
  94. BEGIN_MESSAGE_MAP(CMiniFliter_MFCDlg, CDialogEx)  
  95.     ON_WM_SYSCOMMAND()  
  96.     ON_WM_PAINT()  
  97.     ON_WM_QUERYDRAGICON()  
  98.     ON_BN_CLICKED(IDC_START, &CMiniFliter_MFCDlg::OnBnClickedStart)  
  99. END_MESSAGE_MAP()  
  100.   
  101.   
  102. // CMiniFliter_MFCDlg 消息处理程序  
  103.   
  104. BOOL CMiniFliter_MFCDlg::OnInitDialog()  
  105. {  
  106.     CDialogEx::OnInitDialog();  
  107.   
  108.     // 将“关于...”菜单项添加到系统菜单中。  
  109.   
  110.     // IDM_ABOUTBOX 必须在系统命令范围内。  
  111.     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);  
  112.     ASSERT(IDM_ABOUTBOX < 0xF000);  
  113.   
  114.     CMenu* pSysMenu = GetSystemMenu(FALSE);  
  115.     if (pSysMenu != NULL)  
  116.     {  
  117.         BOOL bNameValid;  
  118.         CString strAboutMenu;  
  119.         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);  
  120.         ASSERT(bNameValid);  
  121.         if (!strAboutMenu.IsEmpty())  
  122.         {  
  123.             pSysMenu->AppendMenu(MF_SEPARATOR);  
  124.             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);  
  125.         }  
  126.     }  
  127.   
  128.     // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动  
  129.     //  执行此操作  
  130.     SetIcon(m_hIcon, TRUE);         // 设置大图标  
  131.     SetIcon(m_hIcon, FALSE);        // 设置小图标  
  132.   
  133.       
  134.   
  135.     return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE  
  136. }  
  137.   
  138. void CMiniFliter_MFCDlg::OnSysCommand(UINT nID, LPARAM lParam)  
  139. {  
  140.     if ((nID & 0xFFF0) == IDM_ABOUTBOX)  
  141.     {  
  142.         CAboutDlg dlgAbout;  
  143.         //dlgAbout.DoModal();  
  144.     }  
  145.     else  
  146.     {  
  147.         CDialogEx::OnSysCommand(nID, lParam);  
  148.     }  
  149. }  
  150.   
  151. // 如果向对话框添加最小化按钮,则需要下面的代码  
  152. //  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,  
  153. //  这将由框架自动完成。  
  154.   
  155. void CMiniFliter_MFCDlg::OnPaint()  
  156. {  
  157.     if (IsIconic())  
  158.     {  
  159.         CPaintDC dc(this); // 用于绘制的设备上下文  
  160.   
  161.         SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);  
  162.   
  163.         // 使图标在工作区矩形中居中  
  164.         int cxIcon = GetSystemMetrics(SM_CXICON);  
  165.         int cyIcon = GetSystemMetrics(SM_CYICON);  
  166.         CRect rect;  
  167.         GetClientRect(&rect);  
  168.         int x = (rect.Width() - cxIcon + 1) / 2;  
  169.         int y = (rect.Height() - cyIcon + 1) / 2;  
  170.   
  171.         // 绘制图标  
  172.         dc.DrawIcon(x, y, m_hIcon);  
  173.     }  
  174.     else  
  175.     {  
  176.         CDialogEx::OnPaint();  
  177.     }  
  178. }  
  179.   
  180. //当用户拖动最小化窗口时系统调用此函数取得光标  
  181. //显示。  
  182. HCURSOR CMiniFliter_MFCDlg::OnQueryDragIcon()  
  183. {  
  184.     return static_cast<HCURSOR>(m_hIcon);  
  185. }  
  186.   
  187.   
  188. DWORD HandData(LPCTSTR str)  
  189. {  
  190.     CPopupDlg dlg;  
  191.     dlg.SetText(str);  
  192.     dlg.DoModal();  
  193.   
  194.     if(dlg.m_Allow == TRUE)  
  195.         return 1;  
  196.     else  
  197.         return 0;  
  198.       
  199. }  
  200.   
  201. DWORD  
  202. ScannerWorker(  
  203.     __in PSCANNER_THREAD_CONTEXT Context  
  204.     )  
  205. {  
  206.     DWORD       dwRet = 0;  
  207.     DWORD       outSize = 0;  
  208.   
  209.     HRESULT     hr = 0;  
  210.     ULONG_PTR   key = 0;  
  211.   
  212.     BOOL        result = TRUE;  
  213.     //CHAR      strPop[MAX_PATH*2]  = {0};  
  214.     WCHAR       strOptions[50*2] = {0};//操作类型字符串  
  215.     WCHAR       LastPath[MAX_PATH*2] = {0};  
  216.     BOOL        LastResult = TRUE;  
  217.       
  218.     LPOVERLAPPED pOvlp;  
  219.     PSCANNER_NOTIFICATION notification;  
  220.     SCANNER_REPLY_MESSAGE replyMessage;  
  221.     PSCANNER_MESSAGE message;  
  222.     //DWORD dwRet = 0;  
  223.     CString tip = NULL;  
  224.      
  225.     memset(LastPath,'\0',MAX_PATH*2);  
  226. #pragma warning(push)  
  227. #pragma warning(disable:4127) // conditional expression is constant  
  228.   
  229.     while (TRUE) {  
  230.   
  231. #pragma warning(pop)  
  232.   
  233.         //  
  234.         //  Poll for messages from the filter component to scan.  
  235.         //  
  236.   
  237.         result = GetQueuedCompletionStatus( Context->Completion, &outSize, &key, &pOvlp, INFINITE );  
  238.   
  239.         //  
  240.         //  Obtain the message: note that the message we sent down via FltGetMessage() may NOT be  
  241.         //  the one dequeued off the completion queue: this is solely because there are multiple  
  242.         //  threads per single port handle. Any of the FilterGetMessage() issued messages can be  
  243.         //  completed in random order - and we will just dequeue a random one.  
  244.         //  
  245.   
  246.         message = CONTAINING_RECORD( pOvlp, SCANNER_MESSAGE, Ovlp );  
  247.   
  248.         if (!result) {  
  249.             hr = HRESULT_FROM_WIN32( GetLastError() );  
  250.             break;  
  251.         }  
  252.   
  253.         //printf( "Received message, size %d\n", pOvlp->InternalHigh );  
  254.         //tip.Format(L"Received message, size %d\n", pOvlp->InternalHigh );  
  255.   
  256.   
  257.         notification = &message->Notification;  
  258.   
  259.         if(notification->Operation == 1)  
  260.         {  
  261.             if(wcsncmp(LastPath,notification->TargetPath,wcslen(notification->TargetPath))==0)  
  262.             {  
  263.                 memset(LastPath,'\0',MAX_PATH*2);  
  264.                 result = LastResult;  
  265.                 goto EX;  
  266.             }  
  267.         }  
  268.   
  269.         memset(strOptions,'\0',50);  
  270.           
  271.   
  272.         switch (notification->Operation)  
  273.         {  
  274.         case 1:  
  275.             wcscpy_s(strOptions,50,L"创建");  
  276.             break;  
  277.         case 2:  
  278.             wcscpy_s(strOptions,50,L"重命名");  
  279.             break;  
  280.         case 3:  
  281.             wcscpy_s(strOptions,50,L"删除");  
  282.             break;  
  283.         default:  
  284.             wcscpy_s(strOptions,50,L"爆炸");  
  285.             break;  
  286.         }  
  287.   
  288.         //memset(strPop,'\0',MAX_PATH*2);  
  289.   
  290.         if(notification->Operation == 2)  
  291.         {  
  292.             //sprintf(strPop,"进程:%S\r\n操作:%s\r\n目标:%S\r\n重名为:%S\r\n是否放行?",notification->ProcessPath,strOptions,notification->TargetPath,notification->RePathName);  
  293.             tip.Format(L"进程:%s\r\n操作:%s\r\n目标:%s\r\n重名为:%s\r\n是否放行?",notification->ProcessPath,strOptions,notification->TargetPath,notification->RePathName);  
  294.         }else  
  295.         {  
  296.             //sprintf(strPop,"进程:%S\r\n操作:%s\r\n目标:%S\r\n是否放行?",notification->ProcessPath,strOptions,notification->TargetPath);  
  297.             tip.Format(L"进程:%s\r\n操作:%s\r\n目标:%s\r\n是否放行?",notification->ProcessPath,strOptions,notification->TargetPath);  
  298.         }  
  299.   
  300.         Sleep(1000);  
  301.         //dwRet = MessageBoxA(NULL,strPop,"监控到攻击行为",MB_YESNO);  
  302.   
  303.         dwRet = HandData(tip);  
  304.   
  305.         if(dwRet == 1)  
  306.             result = FALSE;  
  307.         else  
  308.             result = TRUE;  
  309.   
  310.         LastResult = result;  
  311.         EX:  
  312.         wcsncpy_s(LastPath,MAX_PATH*2,notification->TargetPath,MAX_PATH*2);  
  313.   
  314.         replyMessage.ReplyHeader.Status = 0;  
  315.         replyMessage.ReplyHeader.MessageId = message->MessageHeader.MessageId;  
  316.   
  317.         replyMessage.Reply.SafeToOpen = !result;  
  318.   
  319.         printf( "Replying message, ResultCode: %d\n", replyMessage.Reply.SafeToOpen );  
  320.   
  321.         hr = FilterReplyMessage( Context->Port,  
  322.                                  (PFILTER_REPLY_HEADER) &replyMessage,  
  323.                                  sizeof( replyMessage ) );  
  324.   
  325.         if (SUCCEEDED( hr )) {  
  326.   
  327.             printf( "Replied message\n" );  
  328.   
  329.         } else {  
  330.   
  331.             printf( "Scanner: Error replying message. Error = 0x%X\n", hr );  
  332.             break;  
  333.         }  
  334.   
  335.         memset( &message->Ovlp, 0, sizeof( OVERLAPPED ) );  
  336.   
  337.         hr = FilterGetMessage( Context->Port,  
  338.                                &message->MessageHeader,  
  339.                                FIELD_OFFSET( SCANNER_MESSAGE, Ovlp ),  
  340.                                &message->Ovlp );  
  341.   
  342.         if (hr != HRESULT_FROM_WIN32( ERROR_IO_PENDING )) {  
  343.   
  344.             break;  
  345.         }  
  346.     }  
  347.   
  348.     if (!SUCCEEDED( hr )) {  
  349.   
  350.         if (hr == HRESULT_FROM_WIN32( ERROR_INVALID_HANDLE )) {  
  351.   
  352.             //  
  353.             //  Scanner port disconncted.  
  354.             //  
  355.   
  356.             printf( "Scanner: Port is disconnected, probably due to scanner filter unloading.\n" );  
  357.   
  358.         } else {  
  359.   
  360.             printf( "Scanner: Unknown error occured. Error = 0x%X\n", hr );  
  361.         }  
  362.     }  
  363.   
  364.     free( message );  
  365.   
  366.     return hr;  
  367. }  
  368.   
  369.   
  370. //此函数需放到线程中执行  
  371. int InitFltUser()  
  372. {  
  373.     DWORD dwDefRequestCount = SCANNER_DEFAULT_REQUEST_COUNT;  
  374.     DWORD dwDefThreadCount = SCANNER_DEFAULT_THREAD_COUNT;  
  375.     DWORD dwMaxThreadCount = SCANNER_MAX_THREAD_COUNT;  
  376.     SCANNER_THREAD_CONTEXT context;  
  377.     PSCANNER_MESSAGE msg;  
  378.     HANDLE threads[SCANNER_MAX_THREAD_COUNT];  
  379.     CString tip = NULL;  
  380.     DWORD threadId;  
  381.     DWORD i = 0;  
  382.   
  383.     //连接到端口  
  384.   
  385.     HRESULT hr =  FilterConnectCommunicationPort(ScannerPortName,0,NULL,0,NULL,&g_port);  
  386.   
  387.     if(IS_ERROR(hr))  
  388.     {  
  389.         AfxMessageBox(L"hr is null\n");  
  390.         return 0;  
  391.     }  
  392.       
  393.     //为这个句柄创建一个Comption  
  394.   
  395.     HANDLE completion = CreateIoCompletionPort( g_port,  
  396.                                          NULL,  
  397.                                          0,  
  398.                                          dwDefThreadCount );  
  399.   
  400.     if (completion == NULL)   
  401.     {  
  402.         tip.Format(L"ERROR: Creating completion port: %d\n", GetLastError());  
  403.         AfxMessageBox(tip);  
  404.         CloseHandle( g_port );  
  405.         return 0;  
  406.     }  
  407.   
  408.     //tip.Format(L"Scanner: Port = 0x%p Completion = 0x%p\n", g_port, completion );  
  409.     //this->SetWindowTextW(tip);  
  410.   
  411.     context.Port = g_port;  
  412.     context.Completion = completion;  
  413.   
  414.     //创建规定的线程  
  415.   
  416.   
  417.     for (i = 0; i < dwDefThreadCount; i++)  
  418.     {  
  419.         //创建线程  
  420.         threads[i] = CreateThread( NULL,  
  421.                                    0,  
  422.                                    (LPTHREAD_START_ROUTINE)ScannerWorker,  
  423.                                    &context,  
  424.                                    0,  
  425.                                    &threadId );  
  426.   
  427.         if (threads[i] == NULL)   
  428.         {  
  429.             hr = GetLastError();  
  430.             tip.Format(L"ERROR: Couldn't create thread: %d\n", hr );  
  431.             //this->SetWindowTextW(tip);  
  432.             goto main_cleanup;  
  433.         }  
  434.   
  435.         for (DWORD j = 0; j < dwDefRequestCount; j++)   
  436.         {  
  437.   
  438.             //  
  439.             //  Allocate the message.  
  440.             //  
  441.   
  442. #pragma prefast(suppress:__WARNING_MEMORY_LEAK, "msg will not be leaked because it is freed in ScannerWorker")  
  443.   
  444.             msg = (PSCANNER_MESSAGE)malloc( sizeof( SCANNER_MESSAGE ));  
  445.   
  446.             if (msg == NULL) {  
  447.   
  448.                 hr = ERROR_NOT_ENOUGH_MEMORY;  
  449.                 goto main_cleanup;  
  450.             }  
  451.   
  452.             memset( &msg->Ovlp, 0, sizeof( OVERLAPPED ) );  
  453.   
  454.             //  
  455.             //  Request messages from the filter driver.  
  456.             //  
  457.   
  458.             hr = FilterGetMessage( g_port,  
  459.                                    &msg->MessageHeader,  
  460.                                    FIELD_OFFSET( SCANNER_MESSAGE, Ovlp ),  
  461.                                    &msg->Ovlp );  
  462.   
  463.             if (hr != HRESULT_FROM_WIN32( ERROR_IO_PENDING ))   
  464.             {  
  465.   
  466.                 free( msg );  
  467.                 goto main_cleanup;  
  468.             }  
  469.         }  
  470.     }  
  471.   
  472.     hr = S_OK;  
  473.   
  474.     WaitForMultipleObjectsEx( i, threads, TRUE, INFINITE, FALSE );  
  475.     //返回线程数组和 数组个数  
  476.           
  477. main_cleanup:  
  478.   
  479.     tip.Format(L"Scanner:  All done. Result = 0x%08x\n", hr );  
  480.     //this->SetWindowTextW(tip);  
  481.     CloseHandle(g_port);  
  482.     CloseHandle(completion);  
  483.   
  484.     return hr+1;  
  485. }  
  486.   
  487.   
  488. void CMiniFliter_MFCDlg::OnBnClickedStart()  
  489. {  
  490.     CreateThread(NULL,0, (LPTHREAD_START_ROUTINE)InitFltUser,NULL,0,NULL);  
  491. }  

posted on 2017-05-17 10:23  求索_在路上  阅读(2984)  评论(0)    收藏  举报

导航