我正在編寫一個Windows Minifilter Driver,它需要在IRP_MJ_CLEANUP上讀取整個文件(只有大小達到特定閾值的文件)。由於FltReadFile可能不會從preop回調中調用,因此我將作業排入工作隊列並在那裏執行。當我讀完文件時,我調用FltCompletePendedPreOperation並調用post-cleanup回調函數,該函數也將post操作作爲延期工作來處理。下面是我的代碼片段:在延遲工作項目中的預清理階段讀取文件
static NTSTATUS HandlePreCleanup(_In_ PFLT_CALLBACK_DATA Data,
_Out_ PVOID *Context)
{
NTSTATUS Status = STATUS_SUCCESS;
PFLT_INSTANCE Instance;
PFILE_OBJECT FileObject;
PVOID Buffer = NULL;
LARGE_INTEGER FileOffset;
FileObject = Data->Iopb->TargetFileObject;
Instance = Data->Iopb->TargetInstance;
Buffer = ExAllocatePoolWithTag(PagedPool,
(ULONG) FILE_CHUNK_SIZE,
PPFILTER_FILE_POOLTAG);
if (Buffer == NULL) {
PPERROR("Failed allocating file chunk\n");
Status = STATUS_MEMORY_NOT_ALLOCATED;
goto out;
}
FileOffset.QuadPart = 0;
for (;;) {
ULONG BytesRead;
Status = FltReadFile(
Instance, FileObject, &FileOffset,
(ULONG) FILE_CHUNK_SIZE, Buffer,
FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET,
&BytesRead, NULL, NULL
);
if (!NT_SUCCESS(Status)) {
if (Status == STATUS_END_OF_FILE) {
Status = STATUS_SUCCESS;
break;
}
PPERROR("Failed reading from file %wZ: error %d\n",
&FileObject->FileName, Status);
goto out;
}
FileOffset.QuadPart += BytesRead;
}
out:
if (Buffer != NULL) {
ExFreePoolWithTag(Buffer, PPFILTER_FILE_POOLTAG);
}
return Status;
}
static VOID DeferredPreCallback(_In_ PFLT_DEFERRED_IO_WORKITEM WorkItem,
_In_ PFLT_CALLBACK_DATA Data,
_In_opt_ PVOID Context)
{
NTSTATUS Status = STATUS_SUCCESS;
PVOID PostContext = NULL;
UNREFERENCED_PARAMETER(Context);
switch (Data->Iopb->MajorFunction) {
case IRP_MJ_CLEANUP:
Status = HandlePreCleanup(Data, &PostContext);
break;
default:
NT_ASSERTMSG("Unexpected deferred pre callback operation",
FALSE);
break;
}
FltCompletePendedPreOperation(Data,
FLT_PREOP_SUCCESS_WITH_CALLBACK,
PostContext);
FltFreeDeferredIoWorkItem(WorkItem);
}
static NTSTATUS QueueWork(_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PFLT_DEFERRED_IO_WORKITEM_ROUTINE WorkRoutine,
_In_ PVOID Context)
{
NTSTATUS Status = STATUS_SUCCESS;
PFLT_DEFERRED_IO_WORKITEM WorkItem = NULL;
WorkItem = FltAllocateDeferredIoWorkItem();
if (WorkItem == NULL) {
Status = STATUS_MEMORY_NOT_ALLOCATED;
PPERROR("Failed allocating work item\n");
goto failed;
}
Status = FltQueueDeferredIoWorkItem(WorkItem, Data, WorkRoutine,
CriticalWorkQueue, Context);
if (!NT_SUCCESS(Status)) {
PPERROR("Failed queuing work item to queue: error %d\n",
Status);
goto failed;
}
return STATUS_SUCCESS;
failed:
if (WorkItem != NULL) {
FltFreeDeferredIoWorkItem(WorkItem);
}
return Status;
}
static FLT_PREOP_CALLBACK_STATUS DeferPreCallback(
_Inout_ PFLT_CALLBACK_DATA Data,
_In_ PCFLT_RELATED_OBJECTS FltObjects,
_Out_ PVOID *CompletionContext
)
{
NTSTATUS Status = STATUS_SUCCESS;
UNREFERENCED_PARAMETER(FltObjects);
UNREFERENCED_PARAMETER(CompletionContext);
Status = QueueWork(Data, DeferredPreCallback, NULL);
if (!NT_SUCCESS(Status)) {
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
return FLT_PREOP_PENDING;
}
CONST FLT_OPERATION_REGISTRATION OperationRegistrations[] = {
{
IRP_MJ_CLEANUP,
0,
DeferPreCallback,
DeferPostCallback,
NULL
},
{ IRP_MJ_OPERATION_END },
};
這證明了一會兒工作,但系統似乎一段時間後掛(僵局?)。這個問題似乎與調用FltReadFile,因爲掛起不會發生在刪除此調用。任何想法,爲什麼會發生這種情況或如何進一步調試?