- Implement KsPropertyHandler, KsPropertyHandlerWithAllocator, KsFastPropertyHandler
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Fri, 14 Aug 2009 19:44:01 +0000 (19:44 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Fri, 14 Aug 2009 19:44:01 +0000 (19:44 +0000)
svn path=/trunk/; revision=42669

reactos/drivers/ksfilter/ks/filter.c
reactos/drivers/ksfilter/ks/property.c

index c31dfac..a1d9baf 100644 (file)
@@ -636,57 +636,6 @@ KspPinPropertyHandler(
     return Status;
 }
 
-NTSTATUS
-FindPropertyHandler(
-    IN PIO_STATUS_BLOCK IoStatus,
-    IN KSPROPERTY_SET * FilterPropertySet,
-    IN ULONG FilterPropertySetCount,
-    IN PKSPROPERTY Property,
-    IN ULONG InputBufferLength,
-    IN ULONG OutputBufferLength,
-    OUT PFNKSHANDLER *PropertyHandler)
-{
-    ULONG Index, ItemIndex;
-
-    for(Index = 0; Index < FilterPropertySetCount; Index++)
-    {
-        if (IsEqualGUIDAligned(&Property->Set, FilterPropertySet[Index].Set))
-        {
-            for(ItemIndex = 0; ItemIndex < FilterPropertySet[Index].PropertiesCount; ItemIndex++)
-            {
-                if (FilterPropertySet[Index].PropertyItem[ItemIndex].PropertyId == Property->Id)
-                {
-                    if (Property->Flags & KSPROPERTY_TYPE_SET)
-                        *PropertyHandler = FilterPropertySet[Index].PropertyItem[ItemIndex].SetPropertyHandler;
-
-                    if (Property->Flags & KSPROPERTY_TYPE_GET)
-                        *PropertyHandler = FilterPropertySet[Index].PropertyItem[ItemIndex].GetPropertyHandler;
-
-                    if (FilterPropertySet[Index].PropertyItem[ItemIndex].MinProperty > InputBufferLength)
-                    {
-                        /* too small input buffer */
-                        IoStatus->Information = FilterPropertySet[Index].PropertyItem[ItemIndex].MinProperty;
-                        IoStatus->Status = STATUS_BUFFER_TOO_SMALL;
-                        return STATUS_BUFFER_TOO_SMALL;
-                    }
-
-                    if (FilterPropertySet[Index].PropertyItem[ItemIndex].MinData > OutputBufferLength)
-                    {
-                        /* too small output buffer */
-                        IoStatus->Information = FilterPropertySet[Index].PropertyItem[ItemIndex].MinData;
-                        IoStatus->Status = STATUS_BUFFER_TOO_SMALL;
-                        return STATUS_BUFFER_TOO_SMALL;
-                    }
-                    return STATUS_SUCCESS;
-                }
-            }
-        }
-    }
-    return STATUS_UNSUCCESSFUL;
-}
-
-
-
 NTSTATUS
 NTAPI
 IKsFilter_DispatchDeviceIoControl(
@@ -724,7 +673,7 @@ IKsFilter_DispatchDeviceIoControl(
     }
 
     /* find a supported property handler */
-    Status = FindPropertyHandler(&Irp->IoStatus, FilterPropertySet, 2, IoStack->Parameters.DeviceIoControl.Type3InputBuffer, IoStack->Parameters.DeviceIoControl.InputBufferLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength, &PropertyHandler);
+    Status = KsPropertyHandler(Irp, 2, FilterPropertySet);
     if (NT_SUCCESS(Status))
     {
         KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (PVOID)This;
index f53329d..cc56bbb 100644 (file)
@@ -8,8 +8,129 @@
 
 #include "priv.h"
 
+
+NTSTATUS
+FindPropertyHandler(
+    IN PIO_STATUS_BLOCK IoStatus,
+    IN  const KSPROPERTY_SET* PropertySet,
+    IN ULONG PropertySetCount,
+    IN PKSPROPERTY Property,
+    IN ULONG InputBufferLength,
+    IN ULONG OutputBufferLength,
+    OUT PFNKSHANDLER *PropertyHandler)
+{
+    ULONG Index, ItemIndex;
+
+    for(Index = 0; Index < PropertySetCount; Index++)
+    {
+        if (IsEqualGUIDAligned(&Property->Set, PropertySet[Index].Set))
+        {
+            for(ItemIndex = 0; ItemIndex < PropertySet[Index].PropertiesCount; ItemIndex++)
+            {
+                if (PropertySet[Index].PropertyItem[ItemIndex].PropertyId == Property->Id)
+                {
+                    if (PropertySet[Index].PropertyItem[ItemIndex].MinProperty > InputBufferLength)
+                    {
+                        /* too small input buffer */
+                        IoStatus->Information = PropertySet[Index].PropertyItem[ItemIndex].MinProperty;
+                        return STATUS_INVALID_PARAMETER;
+                    }
+
+                    if (PropertySet[Index].PropertyItem[ItemIndex].MinData > OutputBufferLength)
+                    {
+                        /* too small output buffer */
+                        IoStatus->Information = PropertySet[Index].PropertyItem[ItemIndex].MinData;
+                        return STATUS_BUFFER_TOO_SMALL;
+                    }
+
+                    if (Property->Flags & KSPROPERTY_TYPE_SET)
+                        *PropertyHandler = PropertySet[Index].PropertyItem[ItemIndex].SetPropertyHandler;
+
+                    if (Property->Flags & KSPROPERTY_TYPE_GET)
+                        *PropertyHandler = PropertySet[Index].PropertyItem[ItemIndex].GetPropertyHandler;
+
+                    return STATUS_SUCCESS;
+                }
+            }
+        }
+    }
+    return STATUS_NOT_FOUND;
+}
+
+
+NTSTATUS
+KspPropertyHandler(
+    IN PIRP Irp,
+    IN  ULONG PropertySetsCount,
+    IN  const KSPROPERTY_SET* PropertySet,
+    IN  PFNKSALLOCATOR Allocator OPTIONAL,
+    IN  ULONG PropertyItemSize OPTIONAL)
+{
+    PKSPROPERTY Property;
+    PIO_STACK_LOCATION IoStack;
+    NTSTATUS Status;
+    PFNKSHANDLER PropertyHandler;
+
+    /* get current irp stack */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    /* check if inputbuffer at least holds KSPROPERTY item */
+    if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY))
+    {
+        /* invalid parameter */
+        Irp->IoStatus.Information = sizeof(KSPROPERTY);
+        return STATUS_INVALID_BUFFER_SIZE;
+    }
+
+    /* FIXME probe the input / output buffer if from user mode */
+
+
+    /* get input property request */
+    Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
+
+    /* sanity check */
+    ASSERT(PropertyItemSize == 0 || PropertyItemSize == sizeof(KSPROPERTY_ITEM));
+    if (IsEqualGUIDAligned(&Property->Set, &KSPROPSETID_Topology))
+    {
+        /* use KsTopologyPropertyHandler for this business */
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* find the property handler */
+    Status = FindPropertyHandler(&Irp->IoStatus, PropertySet, PropertySetsCount, Property, IoStack->Parameters.DeviceIoControl.InputBufferLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength, &PropertyHandler);
+
+    if (NT_SUCCESS(Status))
+    {
+        /* call property handler */
+        Status = PropertyHandler(Irp, Property, Irp->UserBuffer);
+
+        if (Status == STATUS_BUFFER_TOO_SMALL)
+        {
+            /* output buffer is too small */
+            if (Allocator)
+            {
+                /* allocate the requested amount */
+                Status = Allocator(Irp, Irp->IoStatus.Information, FALSE);
+
+                /* check if the block was allocated */
+                if (!NT_SUCCESS(Status))
+                {
+                    /* no memory */
+                    return STATUS_INSUFFICIENT_RESOURCES;
+                }
+
+                /* re-call property handler */
+                Status = PropertyHandler(Irp, Property, Irp->UserBuffer);
+            }
+        }
+    }
+
+    /* done */
+    return Status;
+}
+
 /*
-    @unimplemented
+    @implemented
 */
 KSDDKAPI
 NTSTATUS
@@ -19,13 +140,12 @@ KsPropertyHandler(
     IN  ULONG PropertySetsCount,
     IN  const KSPROPERTY_SET* PropertySet)
 {
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
+    return KspPropertyHandler(Irp, PropertySetsCount, PropertySet, NULL, 0);
 }
 
 
 /*
-    @unimplemented
+    @implemented
 */
 KSDDKAPI
 NTSTATUS
@@ -37,10 +157,48 @@ KsPropertyHandlerWithAllocator(
     IN  PFNKSALLOCATOR Allocator OPTIONAL,
     IN  ULONG PropertyItemSize OPTIONAL)
 {
-    UNIMPLEMENTED;
-    return STATUS_UNSUCCESSFUL;
+    return KspPropertyHandler(Irp, PropertySetsCount, PropertySet, Allocator, PropertyItemSize);
 }
 
+NTSTATUS
+FindFastPropertyHandler(
+    IN ULONG FastIoCount,
+    IN const KSFASTPROPERTY_ITEM * FastIoTable,
+    IN PKSPROPERTY PropertyId,
+    OUT PFNKSFASTHANDLER * FastPropertyHandler)
+{
+    ULONG Index;
+
+    /* iterate through all items */
+    for(Index = 0; Index < FastIoCount; Index++)
+    {
+        if (PropertyId->Id == FastIoTable[Index].PropertyId)
+        {
+            if (PropertyId->Flags & KSPROPERTY_TYPE_SET)
+            {
+                if (FastIoTable[Index].SetSupported)
+                {
+                    *FastPropertyHandler = FastIoTable[Index].SetPropertyHandler;
+                    return STATUS_SUCCESS;
+                }
+            }
+
+            if (PropertyId->Flags & KSPROPERTY_TYPE_GET)
+            {
+                if (FastIoTable[Index].GetSupported)
+                {
+                    *FastPropertyHandler = FastIoTable[Index].GetPropertyHandler;
+                    return STATUS_SUCCESS;
+                }
+            }
+        }
+
+    }
+    /* no fast property handler found */
+    return STATUS_NOT_FOUND;
+}
+
+
 /*
     @unimplemented
 */
@@ -57,6 +215,68 @@ KsFastPropertyHandler(
     IN  ULONG PropertySetsCount,
     IN  const KSPROPERTY_SET* PropertySet)
 {
-    UNIMPLEMENTED;
+    KSPROPERTY PropRequest;
+    KPROCESSOR_MODE Mode;
+    NTSTATUS Status = STATUS_SUCCESS;
+    ULONG Index;
+    PFNKSFASTHANDLER FastPropertyHandler;
+
+    if (PropertyLength < sizeof(KSPROPERTY))
+    {
+        /* invalid request */
+        return FALSE;
+    }
+
+    /* get previous mode */
+    Mode = ExGetPreviousMode();
+
+    if (Mode == KernelMode)
+    {
+        /* just copy it */
+        RtlMoveMemory(&PropRequest, Property, sizeof(KSPROPERTY));
+    }
+    else
+    {
+        /* need to probe the buffer */
+        _SEH2_TRY
+        {
+            ProbeForRead(Property, sizeof(KSPROPERTY), sizeof(UCHAR));
+            RtlMoveMemory(&PropRequest, Property, sizeof(KSPROPERTY));
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            /* Exception, get the error code */
+            Status = _SEH2_GetExceptionCode();
+        }_SEH2_END;
+
+        if (!NT_SUCCESS(Status))
+            return FALSE;
+    }
+
+    /* are there any property sets provided */
+    if (PropertySetsCount)
+    {
+        /* iterate through all property sets count */
+        Index = 0;
+        do
+        {
+            /* does the property id match */
+            if (IsEqualGUIDAligned(PropertySet[Index].Set, &PropRequest.Set))
+            {
+                /* try to find a fast property handler */
+                Status = FindFastPropertyHandler(PropertySet[Index].FastIoCount, PropertySet[Index].FastIoTable, &PropRequest, &FastPropertyHandler);
+
+                if (NT_SUCCESS(Status))
+                {
+                    /* call fast property handler */
+                    ASSERT(PropertyLength == sizeof(KSPROPERTY)); /* FIXME check if property length is bigger -> copy params */
+                    ASSERT(Mode == KernelMode); /* FIXME need to probe usermode output buffer */
+                    return FastPropertyHandler(FileObject, &PropRequest, sizeof(KSPROPERTY), Data, DataLength, IoStatus);
+                }
+            }
+            /* move to next item */
+            Index++;
+        }while(Index < PropertySetsCount);
+    }
     return FALSE;
 }