Hello.
I have a problem on a system where two minifilters are running. One of them implements own oplock processing. Another minifilter does oplock request using FltPerformAsynchronousIo with specified PFLT_COMPLETED_ASYNC_IO_CALLBACK CallbackRoutine. When file is closed and PostCleanup invokes FltCheckOplock, BSOD MULTIPLE_IRP_COMPLETE_REQUESTS (44) happends.
Here are the main pieces of those minifilters code that illustrates a problem.
Both drivers are based on Passthrough sample. Some things in Passthrough2 are done just to simplify and show the problem. I know that one global oplock structure and detection of stream by file extension is not good, but that does not have effect on a problem.
/////////////////////////////////////////////////////////////
I. Minifilter that does request of the oplock (Passthrough, altitude 370400):
BOOLEAN IsMatchWithExt(PUNICODE_STRING pUs, PWCHAR wsFile)
{
UNICODE_STRING usFile;
RtlInitUnicodeString(&usFile, wsFile);
if (wsFile && pUs && pUs->Length && usFile.Length)
{
return 0 == RtlCompareUnicodeString(pUs, &usFile, TRUE);
}else
{
return FALSE;
}
}
BOOLEAN IsOurFile(IN OUT PFLT_CALLBACK_DATA Data)
{
PFLT_FILE_NAME_INFORMATION NameInfo = NULL;
NTSTATUS Status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED|FLT_FILE_NAME_QUERY_DEFAULT, &NameInfo);
BOOLEAN bRet = FALSE;
if (NT_SUCCESS(Status))
{
Status = FltParseFileNameInformation( NameInfo );
if (NT_SUCCESS(Status))
{
if ( IsMatchWithExt(&NameInfo->Extension, L"123ABC789") )
{
bRet = TRUE;
}
}
}
if (NameInfo)
{
FltReleaseFileNameInformation(NameInfo);
}
return bRet;
}
FLT_PREOP_CALLBACK_STATUS
PtPreCreate(
IN OUT PFLT_CALLBACK_DATA Data,
IN PCFLT_RELATED_OBJECTS FltObjects,
OUT PVOID *CompletionContext
)
{
return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}
VOID PtCompleteAsyncIoCallback(
PFLT_CALLBACK_DATA CallbackData,
PFLT_CONTEXT Context
)
{
PFLT_CALLBACK_DATA RetNewCallbackData = (PFLT_CALLBACK_DATA)Context;
DbgPrint("PtCompleteAsyncIoCallback:\n");
FltFreeCallbackData(RetNewCallbackData);
}
FLT_POSTOP_CALLBACK_STATUS
PtPostCreate(
IN OUT PFLT_CALLBACK_DATA Data,
IN PCFLT_RELATED_OBJECTS FltObjects,
IN PVOID CompletionContext,
IN FLT_POST_OPERATION_FLAGS Flags
)
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( CompletionContext );
if (IsOurFile(Data))
{
PFLT_CALLBACK_DATA NewRequest = NULL;
NTSTATUS Status = FltAllocateCallbackData(FltObjects->Instance, FltObjects->FileObject, &NewRequest);
DbgPrint("PtPostCreate: FltAllocateCallbackData 0x%08X\n", Status );
if (NT_SUCCESS(Status))
{
NewRequest->Iopb->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL;
NewRequest->Iopb->MinorFunction = IRP_MN_USER_FS_REQUEST;
NewRequest->Iopb->OperationFlags = 0;
NewRequest->Iopb->Parameters.FileSystemControl.Buffered.FsControlCode = FSCTL_REQUEST_FILTER_OPLOCK;
NewRequest->Iopb->Parameters.FileSystemControl.Buffered.InputBufferLength = 0;
NewRequest->Iopb->Parameters.FileSystemControl.Buffered.OutputBufferLength = 0;
NewRequest->Iopb->Parameters.FileSystemControl.Buffered.SystemBuffer = NULL;
Status = FltPerformAsynchronousIo(
NewRequest,
PtCompleteAsyncIoCallback,
NewRequest
);
DbgPrint("PtPostCreate: FltPerformAsynchronousIo 0x%08X\n", Status );
}
}
return FLT_POSTOP_FINISHED_PROCESSING;
}
/////////////////////////////////////////////////////////////
II. Minifilter which does oplocks handling (Passthrough2, altitude 270400):
BOOLEAN IsMatchWithExt(PUNICODE_STRING pUs, PWCHAR wsFile);
BOOLEAN IsOurFile(IN OUT PFLT_CALLBACK_DATA Data);
FLT_PREOP_CALLBACK_STATUS
Pt2PreCreate(
IN OUT PFLT_CALLBACK_DATA Data,
IN PCFLT_RELATED_OBJECTS FltObjects,
OUT PVOID *CompletionContext
)
{
return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}
FLT_POSTOP_CALLBACK_STATUS
Pt2PostCreate(
IN OUT PFLT_CALLBACK_DATA Data,
IN PCFLT_RELATED_OBJECTS FltObjects,
IN PVOID CompletionContext,
IN FLT_POST_OPERATION_FLAGS Flags
)
{
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( CompletionContext );
if (IsOurFile(Data) &&
NULL == g_Oplock)
{
FltInitializeOplock(&g_Oplock);
}
return FLT_POSTOP_FINISHED_PROCESSING;
}
FLT_PREOP_CALLBACK_STATUS
Pt2PreCleanup(
IN OUT PFLT_CALLBACK_DATA Data,
IN PCFLT_RELATED_OBJECTS FltObjects,
OUT PVOID *CompletionContext
)
{
if (IsOurFile(Data))
{
*(PULONG)CompletionContext = 1;
return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
FLT_POSTOP_CALLBACK_STATUS
Pt2PostCleanup (
IN OUT PFLT_CALLBACK_DATA Data,
IN PCFLT_RELATED_OBJECTS FltObjects,
IN PVOID CompletionContext,
IN FLT_POST_OPERATION_FLAGS Flags
)
{
if ((ULONG)1 == (ULONG)CompletionContext)
{
FltCheckOplock(&g_Oplock, Data, NULL, NULL, NULL);
FltUninitializeOplock(&g_Oplock);
g_Oplock = NULL;
}
return FLT_POSTOP_FINISHED_PROCESSING;
}
FLT_PREOP_CALLBACK_STATUS
Pt2PreFileSystemControl(
IN OUT PFLT_CALLBACK_DATA Data,
IN PCFLT_RELATED_OBJECTS FltObjects,
OUT PVOID *CompletionContext
)
{
ULONG fsControlCode = Data->Iopb->Parameters.FileSystemControl.Common.FsControlCode;
if (FSCTL_REQUEST_FILTER_OPLOCK != fsControlCode)
{
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
if (IsOurFile(Data))
{
FLT_PREOP_CALLBACK_STATUS status = FltOplockFsctrl(
&g_Oplock, //__in POPLOCK Oplock,
Data, //__in PFLT_CALLBACK_DATA CallbackData,
1 //__in ULONG OpenCount
);
DbgPrint("Pt2PreFileSystemControl status=%d\n", status);
return status;
}
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
////////////////////////////////////////////////
The minifilter which requests oplock: "PassThrough", altitude "370400".
The minifilter which handles oplocks: "PassThrough2", altitude "270400".
Output of analyze command:
kd> !analyze -v
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************
MULTIPLE_IRP_COMPLETE_REQUESTS (44)
A driver has requested that an IRP be completed (IoCompleteRequest()), but
the packet has already been completed. This is a tough bug to find because
the easiest case, a driver actually attempted to complete its own packet
twice, is generally not what happened. Rather, two separate drivers each
believe that they own the packet, and each attempts to complete it. The
first actually works, and the second fails. Tracking down which drivers
in the system actually did this is difficult, generally because the trails
of the first driver have been covered by the second. However, the driver
stack for the current request can be found by examining the DeviceObject
fields in each of the stack locations.
Arguments:
Arg1: 816e2968, Address of the IRP
Arg2: 00000d64
Arg3: 00000000
Arg4: 00000000
Debugging Details:
TRIAGER: Could not open triage file : C:\WINDDK\8.0\Debuggers\x64\triage\modclass.ini, error 2
IRP_ADDRESS: 816e2968
DEFAULT_BUCKET_ID: DRIVER_FAULT
BUGCHECK_STR: 0x44
PROCESS_NAME: FileTestOplocks
LAST_CONTROL_TRANSFER: from 804f7b9d to 80527bdc
STACK_TEXT:
f05f91c8 804f7b9d 00000003 f05f9524 00000000 nt!RtlpBreakWithStatusInstruction
f05f9214 804f878a 00000003 00000000 816e2968 nt!KiBugCheckDebugBreak+0x19
f05f95f4 804f8cb5 00000044 816e2968 00000d64 nt!KeBugCheck2+0x574
f05f9614 804f08c1 00000044 816e2968 00000d64 nt!KeBugCheckEx+0x1b
f05f964c f9789785 f05f9680 f9789d9f 816e2968 nt!IopfCompleteRequest+0x2c5
f05f9654 f9789d9f 816e2968 00000000 816e2ab3 fltMgr!FltpCompleteRequest+0x2d
f05f9680 f978cd59 f05f9698 00000000 00000001 fltMgr!FltpLegacyProcessingAfterPreCallbacksCompleted+0x10f
f05f96b0 f978a0f5 816bc444 00000004 00000000 fltMgr!FltCompletePendedPreOperation+0x8b
f05f96c4 804f069e 81ba5978 816e2968 816bc444 fltMgr!FltpFsRtlCompletionRoutine+0x27
f05f96f4 804eb8fb e10adfe0 816b8788 816b8788 nt!IopfCompleteRequest+0xa2
f05f9738 804ec13b e10adfe0 816b88f4 816b8788 nt!FsRtlOplockCleanup+0xc7
f05f9758 f978a18b f9ec8f8c 816b8788 00000000 nt!FsRtlCheckOplock+0x153
f05f9784 f9ec899f f9ec8f8c 816908cc 00000000 fltMgr!FltCheckOplock+0x87
f05f97a0 f9786ef3 816908cc f05f97c4 00000001 PassThrough2!Pt2PostCleanup+0x1f [d:\work\tickets\35774\passthrough2navoplock\passthrough2.c @ 1018]
f05f9808 f9789338 00690870 816b88d3 81690870 fltMgr!FltpPerformPostCallbacks+0x1c5
f05f981c f9789867 81690870 816b8788 f05f985c fltMgr!FltpProcessIoCompletion+0x10
f05f982c 804f069e 81ba5978 816b8788 81690870 fltMgr!FltpPassThroughCompletion+0x89
f05f985c f96e26bb e109e008 81b0d100 f05f9a7c nt!IopfCompleteRequest+0xa2
f05f986c f9707c9d f05f9a98 816b8788 00000000 Ntfs!NtfsCompleteRequest+0xac
f05f9a7c f9707d4d f05f9a98 816b8788 00000000 Ntfs!NtfsCommonCleanup+0x2604
f05f9bf4 804ee119 81b0d020 816b8788 816b8788 Ntfs!NtfsFsdCleanup+0xcf
f05f9c70 80578d3c 81956728 81bb8730 81956740 nt!IopfCallDriver+0x31
f05f9ca4 805b2154 81924230 81ba5978 0012019f nt!IopCloseFile+0x27c
f05f9cd4 805b1a81 81924230 00000001 81bb8730 nt!ObpDecrementHandleCount+0xd4
f05f9cfc 805b1b1f e19310f8 81956740 00000098 nt!ObpCloseHandleTableEntry+0x14d
f05f9d44 805b1c57 00000098 00000001 00000000 nt!ObpCloseHandle+0x87
f05f9d58 8053d638 00000098 0012f4cc 7c90e4f4 nt!NtClose+0x1d
f05f9d58 7c90e4f4 00000098 0012f4cc 7c90e4f4 nt!KiFastCallEntry+0xf8
0012f4bc 7c90cfdc 7c809c1b 00000098 0012f5bc ntdll!KiFastSystemCallRet
0012f4c0 7c809c1b 00000098 0012f5bc 0046c94e ntdll!NtClose+0xc
0012f4cc 0046c94e 00000098 0012f698 00453149 kernel32!CloseHandle+0x51
WARNING: Stack unwind information not available. Following frames may be wrong.
0012f5bc 0046beff 00010164 0012f794 00453149 FileTestOplocks+0x6c94e
0012f698 0046b774 00010164 00000000 00000419 FileTestOplocks+0x6beff
0012f794 7e418734 00010164 00000111 00000419 FileTestOplocks+0x6b774
0012f7c0 7e423ce4 00453149 00010164 00000111 USER32!InternalCallWinProc+0x28
0012f82c 7e423b30 00000000 00453149 00010164 USER32!UserCallDlgProcCheckWow+0x146
0012f874 7e42309b 00000000 00000111 00000419 USER32!DefDlgProcWorker+0xa8
0012f8a4 7e4292e3 007603b0 0075e220 00000419 USER32!SendMessageWorker+0x384
0012f8c4 773f7354 00010164 00000111 00000419 USER32!SendMessageW+0x7f
0012f8e4 773f7436 0019a2c0 00000000 000b0036 COMCTL32!Button_NotifyParent+0x3d
0012f900 773f973b 0019a2c0 00000001 0012f9f8 COMCTL32!Button_ReleaseCapture+0xd7
0012f990 7e418734 00010196 00000202 00000000 COMCTL32!Button_WndProc+0x887
0012f9bc 7e418816 773f8eb4 00010196 00000202 USER32!InternalCallWinProc+0x28
0012fa24 7e4189cd 00000000 773f8eb4 00010196 USER32!UserCallWinProcCheckWow+0x150
0012fa84 7e418a10 0012fca0 00000000 0012fab8 USER32!DispatchMessageWorker+0x306
0012fa94 7e4274ff 0012fca0 7ffd7000 0012fac8 USER32!DispatchMessageW+0xf
0012fab8 0045cf2d 0001015c 007618c8 0012fce4 USER32!IsDialogMessageW+0x572
0012fbbc 0045bb4b 0001015c 00010160 0012fca0 FileTestOplocks+0x5cf2d
0012fce4 00486e62 00000000 001564e0 80000001 FileTestOplocks+0x5bb4b
0012fef8 004a204f 00400000 00000000 000205f4 FileTestOplocks+0x86e62
0012ffb8 004a1d8d 0012fff0 7c817067 80000001 FileTestOplocks+0xa204f
0012ffc0 7c817067 80000001 001295bc 7ffd7000 FileTestOplocks+0xa1d8d
0012fff0 00000000 00454409 00000000 78746341 kernel32!BaseProcessStart+0x23
STACK_COMMAND: kb
FOLLOWUP_IP:
PassThrough2!Pt2PostCleanup+1f [d:\work\tickets\35774\passthrough2navoplock\passthrough2.c @ 1018]
f9ec899f 688c8fecf9 push offset PassThrough2!g_Oplock (f9ec8f8c)
FAULTING_SOURCE_LINE: d:\work\tickets\35774\passthrough2navoplock\passthrough2.c
FAULTING_SOURCE_FILE: d:\work\tickets\35774\passthrough2navoplock\passthrough2.c
FAULTING_SOURCE_LINE_NUMBER: 1018
FAULTING_SOURCE_CODE:
1014: if ((ULONG)1 == (ULONG)CompletionContext)
1015: {
1016: FltCheckOplock(&g_Oplock, Data, NULL, NULL, NULL);
1017:
1018: FltUninitializeOplock(&g_Oplock);
1019: g_Oplock = NULL;
1020: }
1021:
1022: return FLT_POSTOP_FINISHED_PROCESSING;
1023: }
The sequence of execution during debug:
// On create file C:\Testfile.123ABC789
- PtPostCreate, FltAllocateCallbackData, FltPerformAsynchronousIo(FSCTL_REQUEST_FILTER_OPLOCK)
- Pt2PreFileSystemControl, FLT_PREOP_PENDING from FltOplockFsctrl
//On close file C:\Testfile.123ABC789
3) Pt2PostCleanup, call of FltCheckOplock
4) PtCompleteAsyncIoCallback, call of FltFreeCallbackData
?
BSOD 44
During debug breakpoint on fltMgr!FltpCompleteRequest was invoked twice for the Irp corresponding to the FSCTL_REQUEST_FILTER_OPLOCK. First time it succeed, on the second time it crashed system.
Both that drivers seems correct for me, but considering BSOD there is an error somewhere. Tested on WinXP and Win7. When just one of minifilters is running all works great. I can attach a full sample sources ready for compilation, if required.
Could you please point me to the problems in specified sources?
Best regards,
Alexey Barabash