From 9d6768ef658a9d97f1bbdff65a40e229265c2c1c Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Wed, 19 Aug 2009 12:24:28 +0000 Subject: [PATCH] - Implement KsProbeStreamIrp - Currently commented out as gcc finds it hard to find a member in a struct svn path=/trunk/; revision=42784 --- reactos/drivers/ksfilter/ks/irp.c | 398 +++++++++++++++++++++++++++++- 1 file changed, 396 insertions(+), 2 deletions(-) diff --git a/reactos/drivers/ksfilter/ks/irp.c b/reactos/drivers/ksfilter/ks/irp.c index e4b48ce6f4c..ef993e28788 100644 --- a/reactos/drivers/ksfilter/ks/irp.c +++ b/reactos/drivers/ksfilter/ks/irp.c @@ -645,8 +645,402 @@ KsProbeStreamIrp( IN ULONG ProbeFlags, IN ULONG HeaderSize) { - UNIMPLEMENTED; - return STATUS_UNSUCCESSFUL; +#if 0 + PMDL Mdl; + PVOID Buffer; + LOCK_OPERATION Operation; + NTSTATUS Status = STATUS_SUCCESS; + PKSSTREAM_HEADER StreamHeader; + PIO_STACK_LOCATION IoStack; + ULONG Length; + BOOLEAN AllocateMdl = FALSE; + + /* get current irp stack */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + Length = IoStack->Parameters.DeviceIoControl.InputBufferLength; + + if (Irp->RequestorMode == KernelMode || Irp->AssociatedIrp.SystemBuffer) + { +AllocMdl: + /* check if alloc mdl flag is passed */ + if (!(ProbeFlags & KSPROBE_ALLOCATEMDL)) + { + /* nothing more to do */ + return STATUS_SUCCESS; + } + if (Irp->MdlAddress) + { +ProbeMdl: + if (ProbeFlags & KSPROBE_PROBEANDLOCK) + { + if (Irp->MdlAddress->MdlFlags & (MDL_PAGES_LOCKED | MDL_SOURCE_IS_NONPAGED_POOL)) + { + if (ProbeFlags & KSPROBE_SYSTEMADDRESS) + { + _SEH2_TRY + { + /* loop through all mdls and probe them */ + Mdl = Irp->MdlAddress; + do + { + /* the mapping can fail */ + Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL; + + if (Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL)) + { + /* no need to probe these pages */ + Buffer = Mdl->MappedSystemVa; + } + else + { + /* probe that mdl */ + Buffer = MmMapLockedPages(Mdl, KernelMode); + } + + /* check if the mapping succeeded */ + if (!Buffer) + { + /* raise exception we'll catch */ + ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); + } + + /* iterate to next mdl */ + Mdl = Mdl->Next; + + }while(Mdl); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Exception, get the error code */ + Status = _SEH2_GetExceptionCode(); + } _SEH2_END; + } + } + else + { + _SEH2_TRY + { + /* loop through all mdls and probe them */ + Mdl = Irp->MdlAddress; + + /* determine operation */ + Operation = (ProbeFlags & KSPROBE_STREAMWRITE) ? IoWriteAccess : IoReadAccess; + + do + { + /* probe the pages */ + MmProbeAndLockPages(Mdl, Irp->RequestorMode, Operation); + + if (ProbeFlags & KSPROBE_SYSTEMADDRESS) + { + /* the mapping can fail */ + Mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL; + + if (Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL)) + { + /* no need to probe these pages */ + Buffer = Mdl->MappedSystemVa; + } + else + { + /* probe that mdl */ + Buffer = MmMapLockedPages(Mdl, KernelMode); + } + + /* check if the mapping succeeded */ + if (!Buffer) + { + /* raise exception we'll catch */ + ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); + } + } + + /* iterate to next mdl */ + Mdl = Mdl->Next; + + }while(Mdl); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Exception, get the error code */ + Status = _SEH2_GetExceptionCode(); + } _SEH2_END; + } + } + return Status; + } + + /* check all stream headers */ + StreamHeader = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer; + + _SEH2_TRY + { + do + { + if (HeaderSize) + { + /* does the supplied header size match stream header size and no type changed */ + if (StreamHeader->Size != HeaderSize && !(StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED)) + { + /* invalid stream header */ + ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); + } + } + else + { + /* stream must be at least of size KSSTREAM_HEADER and size must be 8-byte block aligned */ + if (StreamHeader->Size < sizeof(KSSTREAM_HEADER) || (StreamHeader->Size & 7)) + { + /* invalid stream header */ + ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); + } + } + + if (Length < StreamHeader->Size) + { + /* length is too short */ + ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); + } + + if (ProbeFlags & KSPROBE_STREAMWRITE) + { + if (StreamHeader->DataUsed > StreamHeader->FrameExtent) + { + /* frame extend can never be smaller */ + ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); + } + + /* is this stream change packet */ + if (StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED) + { + if (Length != sizeof(KSSTREAM_HEADER) || (PVOID)StreamHeader != Irp->AssociatedIrp.SystemBuffer) + { + /* stream changed - must be send in a single packet */ + ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); + } + + if (!(ProbeFlags & KSPROBE_ALLOWFORMATCHANGE)) + { + /* caller does not permit format changes */ + ExRaiseStatus(STATUS_INVALID_PARAMETER); + } + + if (StreamHeader->FrameExtend) + { + /* allocate an mdl */ + Mdl = IoAllocateMdl(StreamHeader->Data, StreamHeader->FrameExtend, FALSE, TRUE, Irp); + + if (!Mdl) + { + /* not enough memory */ + ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); + } + + /* break-out to probe for the irp */ + break; + } + } + } + else + { + if (StreamHeader->DataUsed) + { + /* DataUsed must be zero for stream read operation */ + ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); + } + + if (StreamHeader->OptionsFlags) + { + /* no flags supported for reading */ + ExRaiseStatus(STATUS_INVALID_PARAMETER); + } + } + + if (StreamHeader->FrameExtend) + { + /* allocate an mdl */ + Mdl = IoAllocateMdl(StreamHeader->Data, StreamHeader->FrameExtend, Irp->MdlAddress != NULL, TRUE, Irp); + if (!Mdl) + { + /* not enough memory */ + ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); + } + } + + /* move to next stream header */ + Length -= StreamHeader->Size; + StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size); + }while(Length); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Exception, get the error code */ + Status = _SEH2_GetExceptionCode(); + }_SEH2_END; + + /* now probe the allocated mdl's */ + if (!NT_SUCCESS(Status)) + return Status; + else + goto ProbeMdl; + } + + /* probe user mode buffers */ + if (Length && ( (!HeaderSize) || (Length % HeaderSize == 0) || ((ProbeFlags & KSPROBE_ALLOWFORMATCHANGE) && (Length == sizeof(KSSTREAM_HEADER))) ) ) + { + /* allocate stream header buffer */ + Irp->AssociatedIrp.SystemBuffer = ExAllocatePool(NonPagedPool, Length); + + if (!Irp->AssociatedIrp.SystemBuffer) + { + /* no memory */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + _SEH2_TRY + { + if (ProbeFlags & KSPROBE_STREAMWRITE) + { + if (ProbeFlags & KSPROBE_MODIFY) + ProbeForWrite(Irp->UserBuffer, Length, sizeof(UCHAR)); + else + ProbeForRead(Irp->UserBuffer, Length, sizeof(UCHAR)); + } + else + { + /* stream reads means writing */ + ProbeForWrite(Irp->UserBuffer, Length, sizeof(UCHAR)); + } + + /* copy stream buffer */ + RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer, Irp->UserBuffer, Length); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Exception, get the error code */ + Status = _SEH2_GetExceptionCode(); + }_SEH2_END; + + if (!NT_SUCCESS(Status)) + { + /* failed */ + return Status; + } + + if (ProbeFlags & KSPROBE_ALLOCATEMDL) + { + /* alloc mdls */ + goto AllocMdl; + } + + _SEH2_TRY + { + do + { + if (HeaderSize) + { + /* does the supplied header size match stream header size and no type changed */ + if (StreamHeader->Size != HeaderSize && !(StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED)) + { + /* invalid stream header */ + ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); + } + } + else + { + /* stream must be at least of size KSSTREAM_HEADER and size must be 8-byte block aligned */ + if (StreamHeader->Size < sizeof(KSSTREAM_HEADER) || (StreamHeader->Size & 7)) + { + /* invalid stream header */ + ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); + } + } + + if (Length < StreamHeader->Size) + { + /* length is too short */ + ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); + } + + if (ProbeFlags & KSPROBE_STREAMWRITE) + { + if (StreamHeader->DataUsed > StreamHeader->FrameExtend) + { + /* frame extend can never be smaller */ + ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); + } + + /* is this stream change packet */ + if (StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED) + { + if (Length != sizeof(KSSTREAM_HEADER) || (PVOID)StreamHeader != Irp->AssociatedIrp.SystemBuffer) + { + /* stream changed - must be send in a single packet */ + ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); + } + + if (!(ProbeFlags & KSPROBE_ALLOWFORMATCHANGE)) + { + /* caller does not permit format changes */ + ExRaiseStatus(STATUS_INVALID_PARAMETER); + } + + if (StreamHeader->FrameExtend) + { + /* allocate an mdl */ + Mdl = IoAllocateMdl(StreamHeader->Data, StreamHeader->FrameExtend, FALSE, TRUE, Irp); + + if (!Mdl) + { + /* not enough memory */ + ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES); + } + + /* break out to probe for the irp */ + AllocateMdl = TRUE; + break; + } + } + } + else + { + if (StreamHeader->DataUsed) + { + /* DataUsed must be zero for stream read operation */ + ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); + } + + if (StreamHeader->OptionsFlags) + { + /* no flags supported for reading */ + ExRaiseStatus(STATUS_INVALID_PARAMETER); + } + } + + /* move to next stream header */ + Length -= StreamHeader->Size; + StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size); + }while(Length); + + }_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Exception, get the error code */ + Status = _SEH2_GetExceptionCode(); + }_SEH2_END; + + /* now probe the allocated mdl's */ + if (NT_SUCCESS(Status)) + goto AllocMdl; + else + return Status; + } + + return STATUS_INVALID_BUFFER_SIZE; +#else + UNIMPLEMENTED + return STATUS_NOT_IMPLEMENTED; +#endif } /*