- Implement KsProbeStreamIrp
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Wed, 19 Aug 2009 12:24:28 +0000 (12:24 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Wed, 19 Aug 2009 12:24:28 +0000 (12:24 +0000)
- 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

index e4b48ce..ef993e2 100644 (file)
@@ -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
 }
 
 /*