Esempio n. 1
0
NTSTATUS
NTAPI
PropertyItemDispatch(
    IN PIRP Irp,
    IN PKSIDENTIFIER  Request,
    IN OUT PVOID  Data)
{
    PPCPROPERTY_REQUEST PropertyRequest;
    PSUBDEVICE_DESCRIPTOR Descriptor;
    PKSPROPERTY Property;
    PPCNODE_DESCRIPTOR NodeDescriptor;
    PKSNODEPROPERTY NodeProperty;
    PKSPROPERTY_SET PropertySet;
    PPCPROPERTY_ITEM PropertyItem;
    PPCAUTOMATION_TABLE NodeAutomation;
    PIO_STACK_LOCATION IoStack;
    ULONG InstanceSize, ValueSize, Index;
    PVOID Instance;
    NTSTATUS Status;

    // allocate a property request
    PropertyRequest = (PPCPROPERTY_REQUEST)AllocateItem(NonPagedPool, sizeof(PCPROPERTY_REQUEST), TAG_PORTCLASS);
    if (!PropertyRequest)
        return STATUS_INSUFFICIENT_RESOURCES;

    // grab device descriptor
    Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);

    // get current irp stack
    IoStack = IoGetCurrentIrpStackLocation(Irp);

    // get input property request
    Property = (PKSPROPERTY)Request;

    // get property set
    PropertySet = (PKSPROPERTY_SET)KSPROPERTY_SET_IRP_STORAGE(Irp);

    // sanity check
    PC_ASSERT(Descriptor);
    PC_ASSERT(Descriptor->UnknownMiniport);

    // get instance / value size
    InstanceSize = IoStack->Parameters.DeviceIoControl.InputBufferLength;
    Instance = Request;
    ValueSize = IoStack->Parameters.DeviceIoControl.OutputBufferLength;

    // initialize property request
    PropertyRequest->MajorTarget = Descriptor->UnknownMiniport;
    PropertyRequest->MinorTarget = Descriptor->UnknownStream;
    PropertyRequest->Irp = Irp;
    PropertyRequest->Verb = Property->Flags;


    // check if this is filter / pin property request
    if (!(Property->Flags & KSPROPERTY_TYPE_TOPOLOGY))
    {
        // adjust input buffer size
        InstanceSize -= sizeof(KSPROPERTY);
        Instance = (PVOID)((ULONG_PTR)Instance + sizeof(KSPROPERTY));

        // filter / pin property request dont use node field
        PropertyRequest->Node = MAXULONG;
    }
    else if (InstanceSize >= sizeof(KSNODEPROPERTY))
    {
        // request is for a node
        InstanceSize -= sizeof(KSNODEPROPERTY);
        Instance = (PVOID)((ULONG_PTR)Instance + sizeof(KSNODEPROPERTY));

        // cast node property request
        NodeProperty = (PKSNODEPROPERTY)Request;

        // store node id
        PropertyRequest->Node = NodeProperty->NodeId;
    }
    else
    {
        // invalid buffer size
        return STATUS_INVALID_BUFFER_SIZE;
    }

    // store instance size
    PropertyRequest->InstanceSize = InstanceSize;
    PropertyRequest->Instance = (InstanceSize != 0 ? Instance : NULL);

    // store value size
    PropertyRequest->ValueSize = ValueSize;
    PropertyRequest->Value = Data;

    // now scan the property set for the attached property set item stored in Relations member
    if (PropertySet)
    {
        // sanity check
        PC_ASSERT(IsEqualGUIDAligned(Property->Set, *PropertySet->Set));

        for(Index = 0; Index < PropertySet->PropertiesCount; Index++)
        {
            // check if they got the same property id
            if (PropertySet->PropertyItem[Index].PropertyId == Property->Id)
            {
                // found item
                PropertyRequest->PropertyItem = (const PCPROPERTY_ITEM*)PropertySet->PropertyItem[Index].Relations;

                // done
                break;
            }
        }
    }

    // check if there has been a property set item attached
    if (!PropertyRequest->PropertyItem)
    {
        // is topology node id valid
        if (PropertyRequest->Node < Descriptor->DeviceDescriptor->NodeCount)
        {
            // get node descriptor
            NodeDescriptor = (PPCNODE_DESCRIPTOR) ((ULONG_PTR)Descriptor->DeviceDescriptor->Nodes + PropertyRequest->Node * Descriptor->DeviceDescriptor->NodeSize);

            // get node automation table
            NodeAutomation = (PPCAUTOMATION_TABLE)NodeDescriptor->AutomationTable;

            // has it got a automation table
            if (NodeAutomation)
            {
                // now scan the properties and check if it supports this request
                PropertyItem = (PPCPROPERTY_ITEM)NodeAutomation->Properties;
                for(Index = 0; Index < NodeAutomation->PropertyCount; Index++)
                {
                    // are they same property
                    if (IsEqualGUIDAligned(*PropertyItem->Set, Property->Set))
                    {
                        if (PropertyItem->Id == Property->Id)
                        {
                            // found match
                            PropertyRequest->PropertyItem = PropertyItem;
                            DPRINT("Using property item %p\n", PropertyItem);
                            // done
                            break;
                        }
                    }

                    // move to next property item
                    PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + NodeAutomation->PropertyItemSize);
                }
            }
        }
    }

    if (PropertyRequest->PropertyItem && PropertyRequest->PropertyItem->Handler)
    {
        // now call the handler
        UNICODE_STRING GuidBuffer;
        RtlStringFromGUID(Property->Set, &GuidBuffer);
        DPRINT("Calling Node %lu MajorTarget %p MinorTarget %p PropertySet %S PropertyId %lu PropertyFlags %lx InstanceSize %lu ValueSize %lu Handler %p PropertyRequest %p PropertyItemFlags %lx PropertyItemId %lu\n",
               PropertyRequest->Node, PropertyRequest->MajorTarget, PropertyRequest->MinorTarget, GuidBuffer.Buffer, Property->Id, Property->Flags, PropertyRequest->InstanceSize, PropertyRequest->ValueSize,
               PropertyRequest->PropertyItem->Handler, PropertyRequest, PropertyRequest->PropertyItem->Flags, PropertyRequest->PropertyItem->Id);
        RtlFreeUnicodeString(&GuidBuffer);
        Status = PropertyRequest->PropertyItem->Handler(PropertyRequest);
        DPRINT("Status %lx ValueSize %lu Information %lu\n", Status, PropertyRequest->ValueSize, Irp->IoStatus.Information);
        Irp->IoStatus.Information = PropertyRequest->ValueSize;

        if (Status != STATUS_PENDING)
        {
            // free property request
            FreeItem(PropertyRequest, TAG_PORTCLASS);
        }
    }
    else
    {
        FreeItem(PropertyRequest, TAG_PORTCLASS);
        Status = STATUS_NOT_FOUND;
    }

    /* done */
    return Status;
}
Esempio n. 2
0
NTSTATUS
KspPropertyHandler(
    IN PIRP Irp,
    IN  ULONG PropertySetsCount,
    IN  const KSPROPERTY_SET* PropertySet,
    IN  PFNKSALLOCATOR Allocator OPTIONAL,
    IN  ULONG PropertyItemSize OPTIONAL)
{
    PKSPROPERTY Property;
    PKSPROPERTY_SET Set;
    PIO_STACK_LOCATION IoStack;
    NTSTATUS Status;
    PFNKSHANDLER PropertyHandler = NULL;
    ULONG Index;
    LPGUID Guid;

    /* 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;

//    DPRINT("KspPropertyHandler Irp %p PropertySetsCount %u PropertySet %p Allocator %p PropertyItemSize %u ExpectedPropertyItemSize %u\n", Irp, PropertySetsCount, PropertySet, Allocator, PropertyItemSize, sizeof(KSPROPERTY_ITEM));

    /* sanity check */
    ASSERT(PropertyItemSize == 0 || PropertyItemSize == sizeof(KSPROPERTY_ITEM));

    /* find the property handler */
    Status = FindPropertyHandler(&Irp->IoStatus, PropertySet, PropertySetsCount, Property, IoStack->Parameters.DeviceIoControl.InputBufferLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Irp->UserBuffer, &PropertyHandler, &Set);

    if (NT_SUCCESS(Status) && PropertyHandler)
    {
        /* call property handler */
        KSPROPERTY_SET_IRP_STORAGE(Irp) = Set;
        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);
            }
        }
    }
    else if (IsEqualGUIDAligned(&Property->Set, &GUID_NULL) && Property->Id == 0 && (Property->Flags & KSPROPERTY_TYPE_SETSUPPORT) == KSPROPERTY_TYPE_SETSUPPORT)
    {
        // store output size
        Irp->IoStatus.Information = sizeof(GUID) * PropertySetsCount;
        if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(GUID) * PropertySetsCount)
        {
            // buffer too small
            return STATUS_MORE_ENTRIES;
        }

        // get output buffer
        Guid = (LPGUID)Irp->UserBuffer;

       // copy property guids from property sets
       for(Index = 0; Index < PropertySetsCount; Index++)
       {
           RtlMoveMemory(&Guid[Index], PropertySet[Index].Set, sizeof(GUID));
       }
       Status = STATUS_SUCCESS;
    }

    /* done */
    return Status;
}