defddr
驱动牛犊
驱动牛犊
  • 注册日期2010-07-08
  • 最后登录2012-03-04
  • 粉丝0
  • 关注0
  • 积分16分
  • 威望121点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:2945回复:1

minifilter下过滤写操作无法使用FltDoCompletionProcessingWhenSafe 或FltQueueDeferredIoWorkItem

楼主#
更多 发布于:2010-12-10 14:09
学习MINIFILTER中,一反编译文件得到如下,我尝试将写成C
但是FltDoCompletionProcessingWhenSafe与FltQueueDeferredIoWorkItem总是失败
FltQueueDeferredIoWorkItem返回STATUS_FLT_NOT_SAFE_TO_POST_OPERATION
请问是什么原因?



函数主要为对写到硬盘的数据进行处理 所以设置为FLTFL_OPERATION_REGISTRATION_SKIP_CACHED_IO
IRP_MJ_WRITE,
FLTFL_OPERATION_REGISTRATION_SKIP_CACHED_IO,
FileProPreWrite,
FileProPostWrite
/*****************************************************************************************/
/****************************************************************************************************************************/
int __stdcall Write_post(int a1, int a2, int a3, int a4) 
{ 
int ebp0; // ebp@0 
int result; // eax@1 
int v6; // eax@11 
int v7; // edi@11 
int v8; // esi@14 
signed int v9; // [sp-8h] [bp-38h]@12 
int v10; // [sp-4h] [bp-34h]@12 
int v11; // [sp+10h] [bp-20h]@1 
char v12; // [sp+17h] [bp-19h]@1 
CPPEH_RECORD ms_exc; // [sp+18h] [bp-18h]@2 

result = 0; 
v11 = 0; 
v12 = 1; 
if ( a3 ) 
{ 
ms_exc.disabled = 0; 
if ( *(_DWORD *)(a1 + 12) < 0 || !*(_DWORD *)(a1 + 16) ) 
{ 
v11 = 0; 
goto LABEL_18; 
} 
if ( !(**(_BYTE **)(a1 + 8) & 0x42) ) 
IoGetTopLevelIrp();//此函数有发挥作用? 
if ( !(a4 & 1) ) 
{ 
if ( (unsigned __int8)FltDoCompletionProcessingWhenSafe(a1, a2, a3, a4, sub_13DB8, &v11) )//我写的代码中这些有很大概率无法进入 
{ 
v12 = 0; 
goto LABEL_18; 
} 
if ( !(*(_BYTE *)a1 & 1) ) 
goto LABEL_18; 
v6 = FltAllocateDeferredIoWorkItem(); 
v7 = v6; 
if ( v6 ) 
{ 
v8 = FltQueueDeferredIoWorkItem(v6, a1, sub_13E70, 1, a3);//我写的代码中这些有很大概率无法进入,返回 
if ( v8 >= 0 ) 
{ 
v12 = 0; 
v11 = 1; 
goto LABEL_18; 
} 
FltFreeDeferredIoWorkItem(v7); 
v10 = v8; 
v9 = 1165; 
} 
else 
{ 
v10 = 0; 
v9 = 1155; 
} 
} 
v11 = 0; 
LABEL_18: 
ms_exc.disabled = -2;//异常处理 可暂时不理会 
sub_147C4(a3, ebp0);//清除内存等操作 
result = v11; 
} 
return result; 
}


/********************************************************************************************************/
FLT_POSTOP_CALLBACK_STATUS 
FileProPostWrite( 
__inout PFLT_CALLBACK_DATA Data, 
__in PCFLT_RELATED_OBJECTS FltObjects, 
__in_opt PVOID CompletionContext, 
__in FLT_POST_OPERATION_FLAGS Flags) 
{ 
PPRE_2_POST_CONTEXT p2pCtx; 
FLT_POSTOP_CALLBACK_STATUS RetPostOperationStatus; 
NTSTATUS status; 
PVOID newBuf = NULL; 
LARGE_INTEGER WriOffset; 
ULONG WriLen; 
UNICODE_STRING BackFile; 
OBJECT_ATTRIBUTES ObjAttrib; 
IO_STATUS_BLOCK IoStatusBlock = {0}; 
int i; 
HANDLE BackHandle = NULL; 
LARGE_INTEGER Interval; 
PFILE_OBJECT FileObject; 
ULONG WriteBytes; 
PFLT_DEFERRED_IO_WORKITEM PFltDefIoWorkItem = NULL; 


p2pCtx = CompletionContext; 
newBuf = p2pCtx->SwappedBuffer; 
//获得内存地址 
if(!newBuf) 
{ 
DbgPrint("PostWri SwappedBuffer is NULL\n"); 
ExFreeToNPagedLookasideList(&Pre2PostContextList,p2pCtx); 
return FLT_POSTOP_FINISHED_PROCESSING; 
} 
//确认之前写操作成功 
if((Data->IoStatus.Status < 0) || !(Data->IoStatus.Information)) 
{ 
DbgPrint("PostWri IRP Not Success\n"); 
goto PostWriEnd; 
} 
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
//确认写入成功开始对备份文件写入 
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
WriOffset = p2pCtx->WriteOffset; 
WriLen = p2pCtx->WriLen; 

DbgPrint("p2pCtx->WriteOffset %I64d\n",p2pCtx->WriteOffset); 
DbgPrint("p2pCtx->WriLen %d\n",p2pCtx->WriLen); 
DbgPrint("Buffer Address 0x%lx\n",newBuf); 

if (FltDoCompletionProcessingWhenSafe(Data,FltObjects,CompletionContext,Flags, 
WriteSafePostCallback,&RetPostOperationStatus)) // RetPostOperationsStatus 
{ 
return RetPostOperationStatus; 
} else 
{ 
DbgPrint("FltDoCompletionProcessingWhenSafe Failed\n"); 
PFltDefIoWorkItem = FltAllocateDeferredIoWorkItem(); 
if( NULL == PFltDefIoWorkItem ) 
{ 
Data->IoStatus.Status = STATUS_UNSUCCESSFUL; 
Data->IoStatus.Information = 0; 
DbgPrint("FltAllocateDeferredIoWorkItem Failed\n"); 
goto PostWriEnd; 
} 
status = FltQueueDeferredIoWorkItem(PFltDefIoWorkItem,Data,WriteQueueDefWorkItem,DelayedWorkQueue,CompletionContext); 
if(!NT_SUCCESS(status)) 
{ 
Data->IoStatus.Status = STATUS_UNSUCCESSFUL; 
Data->IoStatus.Information = 0; 
FltFreeDeferredIoWorkItem(PFltDefIoWorkItem); 
DbgPrint("FltQueueDeferredIoWorkItem Failed %lx\n",status); 
goto PostWriEnd; 
} 
ExFreePool(p2pCtx->SwappedBuffer); 
ExFreeToNPagedLookasideList(&Pre2PostContextList,p2pCtx); 
return FLT_POSTOP_MORE_PROCESSING_REQUIRED; 
} 

PostWriEnd: 
//此处应该将释放内存放入完成例程FltDoCompletionProcessingWhenSafe中 
ExFreePool(p2pCtx->SwappedBuffer); 
ExFreeToNPagedLookasideList(&Pre2PostContextList,p2pCtx); 
return FLT_POSTOP_FINISHED_PROCESSING; 
}


defddr
驱动牛犊
驱动牛犊
  • 注册日期2010-07-08
  • 最后登录2012-03-04
  • 粉丝0
  • 关注0
  • 积分16分
  • 威望121点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2010-12-17 11:24
或者这个问题转化成这个角度吧

我想仅仅过滤指定文件向磁盘写入内容的操作,请问如下设置对不对
{ IRP_MJ_CREATE,
//FLTFL_OPERATION_REGISTRATION_SKIP_CACHED_IO,
0,
FileProPreCreate,
FileProPostCreate},

{ IRP_MJ_CLEANUP,
0,
FileProPreCleanup,
NULL},

{ IRP_MJ_WRITE,
FLTFL_OPERATION_REGISTRATION_SKIP_CACHED_IO,
FileProPreWrite,
FileProPostWrite},
。。。。。。。。。
因为只是过滤磁盘操作 所以忽略掉缓存IO请问是否合适
在CREATE中进行文件名过滤 如果是我需要的文件 则设置StreamContext流上下文 然后再write写操作中进行上下文判断
这种思路是否正确?
设置流上下文及这些IRP中设置FLTFL_OPERATION_REGISTRATION_SKIP_CACHED_IO 是否正确?

因为在写操作 IRP_MJ_WRITE中截获指定文件写入磁盘的操作后 ,我想另开FltDoCompletionProcessingWhenSafe进行一些操作
根据WDK帮助 FltDoCompletionProcessingWhenSafe是不能再PAGING IO 下成功的 那么我该怎么办?

THX
游客

返回顶部