SwapBuffer驱动进阶(二)
来源:互联网 发布:最好玩的网络手机游戏 编辑:程序博客网 时间:2024/06/10 04:05
在前面的SwapBuffer驱动进阶(一)中我们添加了一个Create的回调,那么如何让后面的PreRead识别出相同的文件,采用的方法是添加文件流的上下文。首先我们设计一个数据结构,也就是文件流的上下文,主要是需要保存什么文件信息://文件的上下文信息typedef struct _FILE_STREAM_CONTEXT{UCHAR ucIsEncryptFile; ----这个文件是不是加密文件,只要在一开始识别一次就可以了,文件流生命周期是文件打开后,只要文件没有关闭,那么这个文件流就一直存在,读写操作的时候,这个文件流的上下文都可以看到。UINT32uiFileSize;UNICODE_STRINGusFileName; ----在read的Pre和Post等中,是很可能看不到真正的文件名的,只有在Create的时候才会出现C;\1.txt这样的,所以必须在这里就记录下来,然后文件流存在的期间,就可以通过这个上下文查看自己的真实的文件名,用于策略控制UNICODE_STRINGusVolumeName; ----所在的卷的名称,这个也是上面的文件名,是不带卷路径的,和这个一起拼接完整路径UCHAR ucIsNeedFilter; ----在Create的时候,判断是否需要过滤之类的标记,一般的策略都在Create的时候就确定了。PERESOURCE pResource; ----资源锁} FILE_STREAM_CONTEXT, *PFILE_STREAM_CONTEXT;1. 需要先在CreateFile中,先尝试获取下当前的文件流上下文,是否已经有存在了:(注意: 这里一定要在PostCreate中,不能在PreCreate中,因为在PreCreate()中调用FltGetStreamContext()会报告NOT_SUPPORT错误,而在PostCreate()中调用FltGetStreamContext报告Not_Found,这个才是正常的)还有一个前提条件,每次Create以后,对处理的文件,都要CcFlushCache刷缓存,这样才能到文件里读,而不是缓存中读取,这个方案其实就是刷新缓存的方案。https://msdn.microsoft.com/en-us/library/windows/hardware/ff543144(v=vs.85).aspxNTSTATUS FltGetStreamContext( _In_ PFLT_INSTANCE Instance, _In_ PFILE_OBJECT FileObject, _Out_ PFLT_CONTEXT *Context);
STATUS_NOT_FOUND ---返回该值,说明还没有创建文件流上下文,那么就要创建:status = FltAllocateContext(pfltGlobalFilterHandle, ---这个驱动创建时候的过滤句柄,全局的FLT_STREAM_CONTEXT,FILE_STREAM_CONTEXT_SIZE,NonPagedPool,(PFLT_CONTEXT *)&pscFileStreamContext); -----获取的上下文内存(FltReleaseContext(pscFileStreamContext);)继续初始化:RtlZeroMemory(pscFileStreamContext, FILE_STREAM_CONTEXT_SIZE); ---初始化给里面的资源锁,分配一个内存pscFileStreamContext->prResource = (PERESOURCE)ExAllocatePoolWithTag(NonPagedPool,sizeof(ERESOURCE),MEM_TAG_FILE_TABLE);
// 初始化 prResourceExInitializeResourceLite(pscFileStreamContext->prResource);//设置上下文status = FltSetStreamContext(pfiInstance,pfoFileObject,FLT_SET_CONTEXT_KEEP_IF_EXISTS,pscFileStreamContext,(PFLT_CONTEXT *)&pscOldStreamContext); ---看看是不是有老的,//如果有老的,要释放内存if (pscOldStreamContext != NULL) { FltReleaseContext(pscOldStreamContext); }//通知同步一下FILE_STREAM_CONTEXT_LOCK_ON(pscFileStreamContext);这样就表示设置成功了。pscFileStreamContext ----这个用户就可以直接进行操作了
问题: 期间遇到过一个错误: 就是在调用 FltAllocateContext()分配内存的时候,出现了STATUS_FLT_CONTEXT_ALLOCATION_NOT_FOUND这个错误是之前需要注册一个上下文的清理函数,代码如下:
#define MEM_CALLBACK_TAG 'calb'#define MEM_TAG_FILE_TABLE 'cftm'
VOIDFsfilterMinifilter_CleanupContextNotify(__in PFLT_CONTEXT pcContext,__in FLT_CONTEXT_TYPE pctContextType){PVOLUME_CONTEXT pvcVolumeContext = NULL;PFILE_STREAM_CONTEXT pscFileStreamContext = NULL;
PAGED_CODE();
Flt_FsRtlEnterFileSystem();
switch (pctContextType) {case FLT_VOLUME_CONTEXT:{pvcVolumeContext = (PVOLUME_CONTEXT)pcContext;if (pvcVolumeContext->Name.Buffer != NULL) {
ExFreePool(pvcVolumeContext->Name.Buffer);pvcVolumeContext->Name.Buffer = NULL;}}break;case FLT_STREAM_CONTEXT:{pscFileStreamContext = (PFILE_STREAM_CONTEXT)pcContext;
//// 释放上下文//FctFreeCustFileStreamContext(pscFileStreamContext);}break;}
Flt_FsRtlExitFileSystem();}
CONST FLT_CONTEXT_REGISTRATION ContextNotifications[] = {{ FLT_VOLUME_CONTEXT, 0, FsfilterMinifilter_CleanupContextNotify, sizeof(VOLUME_CONTEXT), MEM_CALLBACK_TAG },{ FLT_STREAM_CONTEXT, 0, FsfilterMinifilter_CleanupContextNotify, FILE_STREAM_CONTEXT_SIZE, MEM_TAG_FILE_TABLE },{ FLT_CONTEXT_END}};
//文件的上下文信息
typedef struct _FILE_STREAM_CONTEXT
{
UCHAR ucIsEncryptFile; ----这个文件是不是加密文件,只要在一开始识别一次就可以了,文件流生命周期是文件打开后,只要文件没有关闭,那么这个文件流就一直存在,读写操作的时候,这个文件流的上下文都可以看到。
UINT32uiFileSize;
UNICODE_STRINGusFileName; ----在read的Pre和Post等中,是很可能看不到真正的文件名的,只有在Create的时候才会出现C;\1.txt这样的,所以必须在这里就记录下来,然后文件流存在的期间,就可以通过这个上下文查看自己的真实的文件名,用于策略控制
UNICODE_STRINGusVolumeName; ----所在的卷的名称,这个也是上面的文件名,是不带卷路径的,和这个一起拼接完整路径
UCHAR ucIsNeedFilter; ----在Create的时候,判断是否需要过滤之类的标记,一般的策略都在Create的时候就确定了。
PERESOURCE pResource; ----资源锁
} FILE_STREAM_CONTEXT, *PFILE_STREAM_CONTEXT;
NTSTATUS FltGetStreamContext( _In_ PFLT_INSTANCE Instance, _In_ PFILE_OBJECT FileObject, _Out_ PFLT_CONTEXT *Context);
status = FltAllocateContext(pfltGlobalFilterHandle, ---这个驱动创建时候的过滤句柄,全局的
FLT_STREAM_CONTEXT,
FILE_STREAM_CONTEXT_SIZE,
NonPagedPool,
(PFLT_CONTEXT *)&pscFileStreamContext); -----获取的上下文内存
(FltReleaseContext(pscFileStreamContext);)
继续初始化:
RtlZeroMemory(pscFileStreamContext, FILE_STREAM_CONTEXT_SIZE); ---初始化
pscFileStreamContext->prResource = (PERESOURCE)ExAllocatePoolWithTag(
NonPagedPool,
sizeof(ERESOURCE),
MEM_TAG_FILE_TABLE);
// 初始化 prResource
ExInitializeResourceLite(pscFileStreamContext->prResource);
status = FltSetStreamContext(
pfiInstance,
pfoFileObject,
FLT_SET_CONTEXT_KEEP_IF_EXISTS,
pscFileStreamContext,
(PFLT_CONTEXT *)&pscOldStreamContext); ---看看是不是有老的,
if (pscOldStreamContext != NULL) {
FltReleaseContext(pscOldStreamContext);
}
这个错误是之前需要注册一个上下文的清理函数,代码如下:
#define MEM_CALLBACK_TAG 'calb'
#define MEM_TAG_FILE_TABLE 'cftm'
VOID
FsfilterMinifilter_CleanupContextNotify(
__in PFLT_CONTEXT pcContext,
__in FLT_CONTEXT_TYPE pctContextType
)
{
PVOLUME_CONTEXT pvcVolumeContext = NULL;
PFILE_STREAM_CONTEXT pscFileStreamContext = NULL;
PAGED_CODE();
Flt_FsRtlEnterFileSystem();
switch (pctContextType) {
case FLT_VOLUME_CONTEXT:
{
pvcVolumeContext = (PVOLUME_CONTEXT)pcContext;
if (pvcVolumeContext->Name.Buffer != NULL) {
ExFreePool(pvcVolumeContext->Name.Buffer);
pvcVolumeContext->Name.Buffer = NULL;
}
}
break;
case FLT_STREAM_CONTEXT:
{
pscFileStreamContext = (PFILE_STREAM_CONTEXT)pcContext;
//
// 释放上下文
//
FctFreeCustFileStreamContext(pscFileStreamContext);
}
break;
}
Flt_FsRtlExitFileSystem();
}
CONST FLT_CONTEXT_REGISTRATION ContextNotifications[] = {
{ FLT_VOLUME_CONTEXT, 0, FsfilterMinifilter_CleanupContextNotify, sizeof(VOLUME_CONTEXT), MEM_CALLBACK_TAG },
{ FLT_STREAM_CONTEXT, 0, FsfilterMinifilter_CleanupContextNotify, FILE_STREAM_CONTEXT_SIZE, MEM_TAG_FILE_TABLE },
{ FLT_CONTEXT_END}
};
阅读全文
0 0
- SwapBuffer驱动进阶(二)
- SwapBuffer驱动进阶(一)
- swapbuffer
- 块设备驱动实战进阶篇二 (调试基础二:ftrace)
- SwapBuffer分析
- javascript进阶(二)
- requirejs进阶(二)
- RequireJS进阶(二)
- Python进阶(二)
- RequireJS进阶(二)
- makefile进阶(二)
- Spark进阶(二)
- Dagger2 进阶(二)
- Javascript进阶(二)
- hibernate进阶(二)
- 使用webdriver扒取网站小说(二)-----进阶篇(分层数据驱动)
- C#进阶教程(二)
- Mvc 路由进阶(二)
- sysu-17B01签到
- HMM学习
- 永恒之蓝与Oacle RAC:Oracle不支持在心跳交换机上关闭任何端口
- react_basic(6)
- Python 操作MySQL数据库
- SwapBuffer驱动进阶(二)
- JS的tostring()和toLocaleString()的区别
- 自定义标题栏
- 类和对象2-默认成员函数(构造析构)
- jxl读写excel文件(util)
- [BIT0429]-Java-接口之間的多繼承關係
- SwapBuffer驱动进阶(一)
- android studio 引入glide4.2报错
- zheng项目-从rpc-service开始!