在minifilter中,可以使用CtxGetFileContext,CtxCreateFileContext等函数保存context。
以FileContext为例,新建的文件可以保存一个context进去,然后当这个文件被删除的时候,操作系统会调用minifilter的清理函数来删除相应的context。
那么坑:
如果海量创建文件,那么context就会越来越多,如果文件一直不删除,那么驱动里面的context就会炸掉。
一般保存context如下:
NTSTATUS
CtxFindOrCreateFileContext(
_In_ PFLT_CALLBACK_DATA Cbd,
_In_ BOOLEAN CreateIfNotFound,
_When_(CreateIfNotFound != FALSE, _In_) _When_(CreateIfNotFound == FALSE, _In_opt_) PUNICODE_STRING FileName,
_Outptr_ PCTX_FILE_CONTEXT *FileContext,
_Out_opt_ PBOOLEAN ContextCreated
)
/*++
Routine Description:
This routine finds the file context for the target file.
Optionally, if the context does not exist this routing creates
a new one and attaches the context to the file.
Arguments:
Cbd - Supplies a pointer to the callbackData which
declares the requested operation.
CreateIfNotFound - Supplies if the file context must be created if missing
FileName - Supplies the file name
FileContext - Returns the file context
ContextCreated - Returns if a new context was created
Return Value:
Status
--*/
{
NTSTATUS status;
PCTX_FILE_CONTEXT fileContext;
PCTX_FILE_CONTEXT oldFileContext;
PAGED_CODE();
*FileContext = NULL;
if (ContextCreated != NULL) *ContextCreated = FALSE;
//
// First try to get the file context.
//
PT_DBG_PRINT(PTDBG_TRACE_ROUTINES,
("[hzskxxdlpminimon]: Trying to get file context (FileObject = %p, Instance = %p)\n",
Cbd->Iopb->TargetFileObject,
Cbd->Iopb->TargetInstance));
status = FltGetFileContext(Cbd->Iopb->TargetInstance,
Cbd->Iopb->TargetFileObject,
&fileContext);
//
// If the call failed because the context does not exist
// and the user wants to creat a new one, the create a
// new context
//
if (!NT_SUCCESS(status) &&
(status == STATUS_NOT_FOUND) &&
CreateIfNotFound) {
//
// Create a file context
//
PT_DBG_PRINT(PTDBG_TRACE_ROUTINES,
("[hzskxxdlpminimon]: Creating file context (FileObject = %p, Instance = %p)\n",
Cbd->Iopb->TargetFileObject,
Cbd->Iopb->TargetInstance));
status = CtxCreateFileContext(FileName, &fileContext);
if (!NT_SUCCESS(status)) {
PT_DBG_PRINT(PTDBG_TRACE_ROUTINES,
("[hzskxxdlpminimon]: Failed to create file context with status 0x%x. (FileObject = %p, Instance = %p)\n",
status,
Cbd->Iopb->TargetFileObject,
Cbd->Iopb->TargetInstance));
return status;
}
//
// Set the new context we just allocated on the file object
//
PT_DBG_PRINT(PTDBG_TRACE_ROUTINES,
("[hzskxxdlpminimon]: Setting file context %p (FileObject = %p, Instance = %p)\n",
fileContext,
Cbd->Iopb->TargetFileObject,
Cbd->Iopb->TargetInstance));
status = FltSetFileContext(Cbd->Iopb->TargetInstance,
Cbd->Iopb->TargetFileObject,
FLT_SET_CONTEXT_KEEP_IF_EXISTS,
fileContext,
&oldFileContext);
if (!NT_SUCCESS(status)) {
PT_DBG_PRINT(PTDBG_TRACE_ROUTINES,
("[hzskxxdlpminimon]: Failed to set file context with status 0x%x. (FileObject = %p, Instance = %p)\n",
status,
Cbd->Iopb->TargetFileObject,
Cbd->Iopb->TargetInstance));
//
// We release the context here because FltSetFileContext failed
//
// If FltSetFileContext succeeded then the context will be returned
// to the caller. The caller will use the context and then release it
// when he is done with the context.
//
PT_DBG_PRINT(PTDBG_TRACE_ROUTINES,
("[hzskxxdlpminimon]: Releasing file context %p (FileObject = %p, Instance = %p)\n",
fileContext,
Cbd->Iopb->TargetFileObject,
Cbd->Iopb->TargetInstance));
FltReleaseContext(fileContext);
if (status != STATUS_FLT_CONTEXT_ALREADY_DEFINED) {
//
// FltSetFileContext failed for a reason other than the context already
// existing on the file. So the object now does not have any context set
// on it. So we return failure to the caller.
//
PT_DBG_PRINT(PTDBG_TRACE_ROUTINES,
("[hzskxxdlpminimon]: Failed to set file context with status 0x%x != STATUS_FLT_CONTEXT_ALREADY_DEFINED. (FileObject = %p, Instance = %p)\n",
status,
Cbd->Iopb->TargetFileObject,
Cbd->Iopb->TargetInstance));
return status;
}
//
// Race condition. Someone has set a context after we queried it.
// Use the already set context instead
//
PT_DBG_PRINT(PTDBG_TRACE_ROUTINES,
("[hzskxxdlpminimon]: File context already defined. Retaining old file context %p (FileObject = %p, Instance = %p)\n",
oldFileContext,
Cbd->Iopb->TargetFileObject,
Cbd->Iopb->TargetInstance));
//
// Return the existing context. Note that the new context that we allocated has already been
// released above.
//
fileContext = oldFileContext;
status = STATUS_SUCCESS;
}
else {
if (ContextCreated != NULL) *ContextCreated = TRUE;
}
}
*FileContext = fileContext;
return status;
}
每次调用CreateFile,可以尝试创建一个context,或者找到之前的context,一个文件路径对应一个context。
然后当这个文件被删除的时候,操作系统会调用驱动注册的函数:
{ FLT_FILE_CONTEXT,
0,
CtxContextCleanup,
CTX_FILE_CONTEXT_SIZE,
CTX_FILE_CONTEXT_TAG },
驱动执行CtxContextCleanup,删除相应context。
如果一直创建,很明显,驱动里面的context越来越多,导致:
每次调用CreateFile的时候,要从已有context里面查找,context越多,速度越慢
驱动里面的context越来越多,最后的结果可想而知
控制context的量,如果太多,就删除一些,弊端:删除之后,后面的IRP_WRITE_FILE就获取不到路径了(File Mapping情况)
其他办法?目前没找到更好的
不要使用context机制。