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).aspx
NTSTATUS 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);

 // 初始化 prResource
ExInitializeResourceLite(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'

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

原创粉丝点击