Is there any discussion or documentation on how IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION and IRP_MJ_RELEASE_FOR_SECTION_SYNCHRONIZATION can be filtered in a mini-filter? I am totally unclear about what can be returned.
My filter driver is a bit of a hybrid. It layers over a real file system, but also “virtualizes” additional (read-only) files on specific paths where those files do not actually exist. The filter driver implements all the necessary IRPs to allow access to this virtual content.
The design is 12-13 years old - initially as a legacy filter driver, and about 5 years ago re-worked as a mini-filter. And it generally works well.
But I am now seeing an occasional thread lock-up, which I strongly suspect comes from the implementation of the IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION pre-op on a virtual file. I can find no examples of this usage anywhere and very little documentation.
My current implementation for the pre-op is:
FLT_PREOP_CALLBACK_STATUS
iOraFltFilterSectionSyncPreOp(
IN OUT PFLT_CALLBACK_DATA Data,
IN PCFLT_RELATED_OBJECTS FltObjects,
OUT PVOID *CompletionContext
)
{
PFLT_CONTEXT pContext;
UNREFERENCED_PARAMETER( CompletionContext );
// Is this one of our file objects?
if ( FltGetStreamHandleContext( FltObjects->Instance, FltObjects->FileObject, &pContext ) == STATUS_SUCCESS )
{
// Get our own FCB that contains the resource to acquire
icpt_open_fcb* fcb = GetFcbFromStreamContext(pContext);
FltReleaseContext( pContext );
if (Data->Iopb->MajorFunction == IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION)
{
TRACE_PRINT1( “Section Sync Acquire %08x\n”, h ) ;
ExAcquireResourceExclusiveLite( &fcb->resource, TRUE );
Data->IoStatus.Status =
Data->Iopb->Parameters.AcquireForSectionSynchronization.SyncType == SyncTypeCreateSection ?
STATUS_FILE_LOCKED_WITH_ONLY_READERS : STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY;
}
else
{
TRACE_PRINT1( “Section Sync Release %08x\n”, h ) ;
if ( ExIsResourceAcquiredExclusiveLite( &fcb->resource ) )
{
ExReleaseResourceForThreadLite ( &fcb->resource, ExGetCurrentResourceThread() ) ;
Data->IoStatus.Status = STATUS_FSFILTER_OP_COMPLETED_SUCCESSFULLY;
}
}
Data->IoStatus.Information = 0;
return FLT_PREOP_COMPLETE;
}
return FLT_PREOP_SUCCESS_NO_CALLBACK;
}
Is a mini-filter allowed to complete these operations like this? Would these be the correct status codes? Am I obliged to pass down the operation as far as the underlying driver? (discussion of FsRtlRegisterFileSystemFilterCallbacks implied this may be necessary for a legacy filter).
The eventual lock-up is on the next IRP_MJ_READ pre-op for virtual content *following* the IRP_MJ_RELEASE_FOR_SECTION_SYNCHRONIZATION, where the filter driver calls a ZwReadFile on a totally diferent (internal real file) kernel handle:
nt!KiSwapContext+0x26 (FPO: [Uses EBP] [0,0,4])
nt!KiSwapThread+0x266
nt!KiCommitThreadWait+0x1df
nt!KeWaitForSingleObject+0x393
nt!IopSynchronousServiceTail+0x270
nt!NtReadFile+0x644
nt!KiFastCallEntry+0x12a (FPO: [0,3] TrapFrame @ 8c23f59c)
nt!ZwReadFile+0x11 (FPO: [9,0,0])
grFilter!iOraFltUtilReadFile+0x28
All pointers gratefully received. Thanks
Brian