- Implement KsPropertyHandler, KsPropertyHandlerWithAllocator, KsFastPropertyHandler

svn path=/trunk/; revision=42669
This commit is contained in:
Johannes Anderwald 2009-08-14 19:44:01 +00:00
parent 11a3ac6f28
commit 74bd2a036d
2 changed files with 228 additions and 59 deletions

View 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;

View 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;
}