diff --git a/opt/fsext/inc/winfsp/fsext.h b/opt/fsext/inc/winfsp/fsext.h index 5344795d..e2b180f3 100644 --- a/opt/fsext/inc/winfsp/fsext.h +++ b/opt/fsext/inc/winfsp/fsext.h @@ -53,6 +53,9 @@ typedef struct FSP_DDI_DEF(NTSTATUS, FspFsextProviderRegister, FSP_FSEXT_PROVIDER *Provider) +FSP_DDI_DEF(NTSTATUS, FspFsextProviderTransact, + PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject, + FSP_FSCTL_TRANSACT_RSP *Response, FSP_FSCTL_TRANSACT_REQ **PRequest) FSP_DDI_DEF(NTSTATUS, FspPosixMapUidToSid, UINT32 Uid, diff --git a/opt/fsext/lib/winfsp-x64.lib b/opt/fsext/lib/winfsp-x64.lib index 9d30816f..3ab901fb 100644 Binary files a/opt/fsext/lib/winfsp-x64.lib and b/opt/fsext/lib/winfsp-x64.lib differ diff --git a/opt/fsext/lib/winfsp-x86.lib b/opt/fsext/lib/winfsp-x86.lib index 6616c9bb..7870c6e6 100644 Binary files a/opt/fsext/lib/winfsp-x86.lib and b/opt/fsext/lib/winfsp-x86.lib differ diff --git a/src/sys/fsext.c b/src/sys/fsext.c index e4faacb0..3e3601cf 100644 --- a/src/sys/fsext.c +++ b/src/sys/fsext.c @@ -132,3 +132,56 @@ NTSTATUS FspFsextProviderRegister(FSP_FSEXT_PROVIDER *Provider) return Result; } + +NTSTATUS FspFsextProviderTransact(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject, + FSP_FSCTL_TRANSACT_RSP *Response, FSP_FSCTL_TRANSACT_REQ **PRequest) +{ + /* + * This function uses IoBuildDeviceIoControlRequest to build an IRP and then send it + * to the WinFsp driver. IoBuildDeviceIoControlRequest places the IRP in the IRP queue + * thus allowing it to be cancelled with CancelSynchronousIo. + * + * Special kernel APC's must be enabled: + * See https://www.osr.com/blog/2018/02/14/beware-iobuilddeviceiocontrolrequest/ + */ + ASSERT(!KeAreAllApcsDisabled()); + + NTSTATUS Result; + IO_STATUS_BLOCK IoStatus; + PIRP Irp; + PIO_STACK_LOCATION IrpSp; + + if (0 != PRequest) + *PRequest = 0; + + if (0 == DeviceObject) + DeviceObject = IoGetRelatedDeviceObject(FileObject); + + Irp = IoBuildDeviceIoControlRequest(FSP_FSCTL_TRANSACT_INTERNAL, + DeviceObject, + Response, + 0 != Response ? Response->Size : 0, + PRequest, + 0 != PRequest ? sizeof(PVOID) : 0, + FALSE, + 0, + &IoStatus); + if (0 == Irp) + return STATUS_INSUFFICIENT_RESOURCES; + + /* + * IoBuildDeviceIoControlRequest builds an IOCTL IRP without a FileObject. + * Patch it so that it is an FSCTL IRP with a FileObject. Mark it as + * IRP_SYNCHRONOUS_API so that CancelSynchronousIo can cancel it. + */ + Irp->Flags |= IRP_SYNCHRONOUS_API; + IrpSp = IoGetNextIrpStackLocation(Irp); + IrpSp->MajorFunction = IRP_MJ_FILE_SYSTEM_CONTROL; + IrpSp->MinorFunction = IRP_MN_USER_FS_REQUEST; + IrpSp->FileObject = FileObject; + + Result = IoCallDriver(DeviceObject, Irp); + ASSERT(STATUS_PENDING != Result); + + return Result; +} diff --git a/tools/build-sample.bat b/tools/build-sample.bat old mode 100644 new mode 100755 diff --git a/tools/fsreg.bat b/tools/fsreg.bat old mode 100644 new mode 100755 diff --git a/tools/impdef.bat b/tools/impdef.bat old mode 100644 new mode 100755