diff --git a/inc/winfsp/fsctl.h b/inc/winfsp/fsctl.h index a1541af8..0fbdb986 100644 --- a/inc/winfsp/fsctl.h +++ b/inc/winfsp/fsctl.h @@ -31,7 +31,6 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid = #define FSP_FSCTL_CREATE_BUFFER_SIZE 128 #define FSP_FSCTL_TRANSACT_BUFFER_SIZE 4096 -#define FSP_FSCTL_TRANSACT_REQ_SIZEMAX 1536 /* marshalling */ #pragma warning(push) @@ -62,6 +61,36 @@ typedef struct } Req; } FSP_TRANSACT_RSP; #pragma warning(pop) +static inline FSP_TRANSACT_REQ *FspFsctlTransactProduceRequest( + FSP_TRANSACT_REQ *Request, SIZE_T RequestSize, PVOID RequestBufEnd) +{ + PVOID NextRequest = (PUINT8)Request + RequestSize; + return NextRequest <= RequestBufEnd ? NextRequest : 0; +} +static inline const FSP_TRANSACT_REQ *FspFsctlTransactConsumeRequest( + const FSP_TRANSACT_REQ *Request, PVOID RequestBufEnd) +{ + if ((PUINT8)Request + sizeof(Request->Size) > (PUINT8)RequestBufEnd || + sizeof(FSP_TRANSACT_REQ) > Request->Size) + return 0; + PVOID NextRequest = (PUINT8)Request + Request->Size; + return NextRequest <= RequestBufEnd ? NextRequest : 0; +} +static inline FSP_TRANSACT_RSP *FspFsctlTransactProduceResponse( + FSP_TRANSACT_RSP *Response, SIZE_T ResponseSize, PVOID ResponseBufEnd) +{ + PVOID NextResponse = (PUINT8)Response + ResponseSize; + return NextResponse <= ResponseBufEnd ? NextResponse : 0; +} +static inline const FSP_TRANSACT_RSP *FspFsctlTransactConsumeResponse( + const FSP_TRANSACT_RSP *Response, PVOID ResponseBufEnd) +{ + if ((PUINT8)Response + sizeof(Response->Size) > (PUINT8)ResponseBufEnd || + sizeof(FSP_TRANSACT_RSP) > Response->Size) + return 0; + PVOID NextResponse = (PUINT8)Response + Response->Size; + return NextResponse <= ResponseBufEnd ? NextResponse : 0; +} #if !defined(WINFSP_SYS_DRIVER_H_INTERNAL) NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath, PSECURITY_DESCRIPTOR SecurityDescriptor, diff --git a/src/sys/fsctl.c b/src/sys/fsctl.c index a9094f1c..ca42ce68 100644 --- a/src/sys/fsctl.c +++ b/src/sys/fsctl.c @@ -120,9 +120,9 @@ static NTSTATUS FspFsvrtTransact( NTSTATUS Result; FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject); - PUINT8 SystemBufferPtr, SystemBufferEnd; - FSP_TRANSACT_RSP *Response; - FSP_TRANSACT_REQ *Request; + PUINT8 SystemBufferEnd; + const FSP_TRANSACT_RSP *Response, *NextResponse; + FSP_TRANSACT_REQ *Request, *NextRequest, *PendingIrpRequest; PIRP ProcessIrp, PendingIrp; /* access check */ @@ -136,19 +136,18 @@ static NTSTATUS FspFsvrtTransact( SystemBufferEnd = (PUINT8)SystemBuffer + InputBufferLength; for (;;) { - if ((PUINT8)Response + sizeof(Response->Size) > SystemBufferEnd || - sizeof(FSP_TRANSACT_RSP) > Response->Size || - (PUINT8)Response + Response->Size > SystemBufferEnd) + NextResponse = FspFsctlTransactConsumeResponse(Response, SystemBufferEnd); + if (0 == NextResponse) break; ProcessIrp = FspIoqEndProcessingIrp(&FsvrtDeviceExtension->Ioq, Response->Hint); if (0 == ProcessIrp) - /* either IRP was canceled or a bogus IrpHint was provided */ + /* either IRP was canceled or a bogus Hint was provided */ continue; //FspDispatchProcessedIrp(ProcessIrp, Response); - Response = (PVOID)((PUINT8)Response + Response->Size); + Response = NextResponse; } /* wait for an IRP to arrive */ @@ -159,14 +158,21 @@ static NTSTATUS FspFsvrtTransact( } /* send any pending IRP's to the user-mode file system */ - SystemBufferPtr = SystemBuffer; + Request = SystemBuffer; SystemBufferEnd = (PUINT8)SystemBuffer + OutputBufferLength; - ASSERT(SystemBufferPtr + FSP_FSCTL_TRANSACT_REQ_SIZEMAX + sizeof(Request->Size) <= SystemBufferEnd); - for (BOOLEAN LoopedOnce = FALSE;; LoopedOnce = TRUE) + for (;;) { - if (SystemBufferPtr + FSP_FSCTL_TRANSACT_REQ_SIZEMAX + sizeof(Request->Size) > SystemBufferEnd) + PendingIrpRequest = PendingIrp->Tail.Overlay.DriverContext[0]; + + NextRequest = FspFsctlTransactProduceRequest( + Request, PendingIrpRequest->Size, SystemBufferEnd); + ASSERT(0 != NextRequest || Request != SystemBuffer); + if (0 == NextRequest) break; + RtlCopyMemory(Request, PendingIrpRequest, PendingIrpRequest->Size); + Request = NextRequest; + if (!FspIoqStartProcessingIrp(&FsvrtDeviceExtension->Ioq, PendingIrp)) { /* @@ -180,17 +186,12 @@ static NTSTATUS FspFsvrtTransact( return STATUS_CANCELLED; } - Request = PendingIrp->Tail.Overlay.DriverContext[0]; - RtlCopyMemory(SystemBufferPtr, Request, Request->Size); - SystemBufferPtr += Request->Size; - PendingIrp = FspIoqNextPendingIrp(&FsvrtDeviceExtension->Ioq, 0); if (0 == PendingIrp) break; + } - ASSERT(SystemBufferPtr + sizeof(Request->Size) <= SystemBufferEnd); - RtlZeroMemory(SystemBufferPtr, SystemBufferEnd - SystemBufferPtr); - Irp->IoStatus.Information = SystemBufferPtr - (PUINT8)SystemBuffer; + Irp->IoStatus.Information = (PUINT8)Request - (PUINT8)SystemBuffer; return STATUS_SUCCESS; }