From 9bcd8dcb8e70ba9a8d449678a8c6de0c1c1be5a0 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Fri, 28 Oct 2016 16:33:54 -0700 Subject: [PATCH] sys: FspIopCompleteIrpEx: handle SRV2 query directory completion --- src/sys/dirctl.c | 9 +++++++++ src/sys/iop.c | 44 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/sys/dirctl.c b/src/sys/dirctl.c index de8fb4ab..cd520e31 100644 --- a/src/sys/dirctl.c +++ b/src/sys/dirctl.c @@ -17,6 +17,15 @@ #include +/* + * NOTE: + * + * FspIopCompleteIrpEx does some special processing for IRP_MJ_DIRECTORY_CONTROL / + * IRP_MN_QUERY_DIRECTORY IRP's that come from SRV2. If the processing of this IRP + * changes substantially (in particular if we eliminate our use of + * Irp->AssociatedIrp.SystemBuffer) we should also revisit FspIopCompleteIrpEx. + */ + static NTSTATUS FspFsvolQueryDirectoryCopy( PUNICODE_STRING DirectoryPattern, BOOLEAN CaseInsensitive, UINT64 DirectoryOffset, PUINT64 PDirectoryOffset, diff --git a/src/sys/iop.c b/src/sys/iop.c index 5cc0a5a1..12a39d38 100644 --- a/src/sys/iop.c +++ b/src/sys/iop.c @@ -225,7 +225,49 @@ VOID FspIopCompleteIrpEx(PIRP Irp, NTSTATUS Result, BOOLEAN DeviceDereference) } /* get the device object out of the IRP before completion */ - PDEVICE_OBJECT DeviceObject = IoGetCurrentIrpStackLocation(Irp)->DeviceObject; + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + PDEVICE_OBJECT DeviceObject = IrpSp->DeviceObject; + + /* + * HACK: + * + * Turns out that SRV2 sends an undocumented flavor of IRP_MJ_DIRECTORY_CONTROL / + * IRP_MN_QUERY_DIRECTORY. These IRP's have a non-NULL Irp->MdlAddress. They expect + * the FSD to fill the buffer pointed by Irp->MdlAddress and they cannot handle + * completed IRP's with a non-NULL Irp->AssociatedIrp.SystemBuffer. So we have to + * provide special support for these IRPs. + * + * While this processing is IRP_MJ_DIRECTORY_CONTROL specific, we do this here for + * these reasons: + * + * 1. There may be other IRP's that have similar completion requirements under SRV2. + * If/when such IRP's are discovered the completion processing can be centralized + * here. + * 2. IRP_MJ_DIRECTORY_CONTROL has a few different ways that it can complete IRP's. + * It is far simpler to do this processing here, even if not academically correct. + * + * This will have to be revisited if IRP_MJ_DIRECTORY_CONTROL processing changes + * substantially (e.g. to no longer use Irp->AssociatedIrp.SystemBuffer). + */ + if (IRP_MJ_DIRECTORY_CONTROL == IrpSp->MajorFunction && + IRP_MN_QUERY_DIRECTORY == IrpSp->MinorFunction && + 0 != Irp->MdlAddress && /* SRV2 queries have this set */ + 0 != Irp->AssociatedIrp.SystemBuffer && + FlagOn(Irp->Flags, IRP_BUFFERED_IO)) + { + if (STATUS_SUCCESS == Result) + { + PVOID Address = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); + if (0 != Address) + RtlCopyMemory(Address, Irp->AssociatedIrp.SystemBuffer, Irp->IoStatus.Information); + else + Result = STATUS_INSUFFICIENT_RESOURCES; + } + + FspFreeExternal(Irp->AssociatedIrp.SystemBuffer); + Irp->AssociatedIrp.SystemBuffer = 0; + ClearFlag(Irp->Flags, IRP_INPUT_OPERATION | IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER); + } if (STATUS_SUCCESS != Result && STATUS_REPARSE != Result && STATUS_BUFFER_OVERFLOW != Result) Irp->IoStatus.Information = 0;