[WDMAUD_KERNEL]

- Always set Mute control on first channel
[PORTCLS]
- Rewrite node property handling. Fixes lots of bugs and fixes all winmm_winetest mixer failures

svn path=/trunk/; revision=44323
This commit is contained in:
Johannes Anderwald 2009-11-29 18:56:56 +00:00
parent eeba3408b2
commit f21af7347f
3 changed files with 273 additions and 198 deletions

View file

@ -1243,8 +1243,8 @@ CPortPinWaveCyclic::Init(
m_Port = Port;
m_Filter = Filter;
//DPRINT("Setting state to acquire %x\n", m_Stream->SetState(KSSTATE_ACQUIRE));
//DPRINT("Setting state to pause %x\n", m_Stream->SetState(KSSTATE_PAUSE));
DPRINT("Setting state to acquire %x\n", m_Stream->SetState(KSSTATE_ACQUIRE));
DPRINT("Setting state to pause %x\n", m_Stream->SetState(KSSTATE_PAUSE));
return STATUS_SUCCESS;
}

View file

@ -86,6 +86,269 @@ PcHandleDisableEventWithTable(
return KsDisableEvent(Irp, Descriptor->EventList, KSEVENTS_SPINLOCK, (PVOID)Descriptor->EventListLock);
}
NTSTATUS
PcHandleGuidNullRequest(
IN OUT PIRP Irp,
IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor)
{
PPCNODE_DESCRIPTOR Node;
PPCPROPERTY_ITEM PropertyItem;
PIO_STACK_LOCATION IoStack;
PKSP_NODE Property;
LPGUID Buffer;
ULONG Count = 0, SubIndex, Index;
// get current irp stack location
IoStack = IoGetCurrentIrpStackLocation(Irp);
// access property
Property = (PKSP_NODE)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
if (Property->NodeId >= SubDeviceDescriptor->DeviceDescriptor->NodeCount)
{
// request is out of bounds
Irp->IoStatus.Information = 0;
return STATUS_INVALID_PARAMETER;
}
Node = (PPCNODE_DESCRIPTOR)((ULONG_PTR)SubDeviceDescriptor->DeviceDescriptor->Nodes + (Property->NodeId * SubDeviceDescriptor->DeviceDescriptor->NodeSize));
if (!Node->AutomationTable)
{
// request is out of bounds
Irp->IoStatus.Information = 0;
return STATUS_INVALID_PARAMETER;
}
PC_ASSERT(Node->AutomationTable);
PC_ASSERT(Node->AutomationTable->PropertyCount);
PC_ASSERT(Node->AutomationTable->PropertyItemSize);
Buffer = (LPGUID)AllocateItem(NonPagedPool, sizeof (GUID) * Node->AutomationTable->PropertyCount, TAG_PORTCLASS);
if (!Buffer)
return STATUS_INSUFFICIENT_RESOURCES;
PropertyItem = (PCPROPERTY_ITEM*)Node->AutomationTable->Properties;
for (Index = 0; Index < Node->AutomationTable->PropertyCount; Index++)
{
BOOL Found = FALSE;
for (SubIndex = 0; SubIndex < Count; Index++)
{
if (IsEqualGUIDAligned(Buffer[SubIndex], *PropertyItem->Set))
{
Found = TRUE;
break;
}
}
if (!Found)
{
RtlMoveMemory(&Buffer[Count], PropertyItem->Set, sizeof (GUID));
Count++;
}
PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + Node->AutomationTable->PropertyItemSize);
}
// store result length
Irp->IoStatus.Information = sizeof (GUID) * Count;
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof (GUID) * Count)
{
// buffer too small
FreeItem(Buffer, TAG_PORTCLASS);
return STATUS_MORE_ENTRIES;
}
RtlMoveMemory(Irp->UserBuffer, Buffer, sizeof (GUID) * Count);
FreeItem(Buffer, TAG_PORTCLASS);
return STATUS_SUCCESS;
}
NTSTATUS
PcFindNodePropertyHandler(
PIRP Irp,
PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor,
OUT PPCPROPERTY_ITEM * OutPropertyItem)
{
PPCNODE_DESCRIPTOR Node;
PPCPROPERTY_ITEM PropertyItem;
PIO_STACK_LOCATION IoStack;
PKSP_NODE Property;
ULONG Index;
// get current irp stack location
IoStack = IoGetCurrentIrpStackLocation(Irp);
// access property
Property = (PKSP_NODE)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
if (Property->NodeId >= SubDeviceDescriptor->DeviceDescriptor->NodeCount)
{
// request is out of bounds
DPRINT("InvalidIndex %u %u\n", Property->NodeId, SubDeviceDescriptor->DeviceDescriptor->NodeCount);
return STATUS_INVALID_PARAMETER;
}
Node = (PPCNODE_DESCRIPTOR)((ULONG_PTR)SubDeviceDescriptor->DeviceDescriptor->Nodes + (Property->NodeId * SubDeviceDescriptor->DeviceDescriptor->NodeSize));
if (!Node->AutomationTable)
{
// request is out of bounds
Irp->IoStatus.Information = 0;
return STATUS_NOT_FOUND;
}
// sanity checks
PC_ASSERT(Node->AutomationTable);
PC_ASSERT(Node->AutomationTable->PropertyCount);
PC_ASSERT(Node->AutomationTable->PropertyItemSize);
PropertyItem = (PCPROPERTY_ITEM*)Node->AutomationTable->Properties;
DPRINT("NodeId %u PropertyCount %u\n", Property->NodeId, Node->AutomationTable->PropertyCount);
for(Index = 0; Index < Node->AutomationTable->PropertyCount; Index++)
{
if (IsEqualGUIDAligned(*PropertyItem->Set, Property->Property.Set) && PropertyItem->Id == Property->Property.Id)
{
//found property handler
*OutPropertyItem = PropertyItem;
return STATUS_SUCCESS;
}
PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + Node->AutomationTable->PropertyItemSize);
}
// no handler yet found
DPRINT("NotFound\n");
return STATUS_NOT_FOUND;
}
NTSTATUS
PcNodeBasicSupportHandler(
PIRP Irp,
PPCPROPERTY_ITEM PropertyItem)
{
PULONG Flags;
PIO_STACK_LOCATION IoStack;
PKSPROPERTY_DESCRIPTION Description;
PKSP_NODE Property;
// get current irp stack location
IoStack = IoGetCurrentIrpStackLocation(Irp);
// access property
Property = (PKSP_NODE)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
PC_ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(ULONG));
Flags= (PULONG)Irp->UserBuffer;
// reset flags
*Flags = 0;
if (PropertyItem->Flags & KSPROPERTY_TYPE_SET)
*Flags |= KSPROPERTY_TYPE_SET;
if (PropertyItem->Flags & KSPROPERTY_TYPE_GET)
*Flags |= KSPROPERTY_TYPE_GET;
// store result length
Irp->IoStatus.Information = sizeof(ULONG);
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(KSPROPERTY_DESCRIPTION))
{
// get output buffer
Description = (PKSPROPERTY_DESCRIPTION)Irp->UserBuffer;
// store result
Description->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION);
Description->PropTypeSet.Set = KSPROPTYPESETID_General;
Description->PropTypeSet.Id = 0;
Description->PropTypeSet.Flags = 0;
Description->MembersListCount = 0;
Description->Reserved = 0;
Irp->IoStatus.Information = sizeof(KSPROPERTY_DESCRIPTION);
}
return STATUS_SUCCESS;
}
NTSTATUS
PcHandleNodePropertyRequest(
PIRP Irp,
IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor)
{
PIO_STACK_LOCATION IoStack;
PPCPROPERTY_ITEM PropertyItem;
PPCPROPERTY_REQUEST PropertyRequest;
PKSP_NODE Property;
NTSTATUS Status;
// get current irp stack location
IoStack = IoGetCurrentIrpStackLocation(Irp);
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSP_NODE))
{
// certainly not a node property request
return STATUS_NOT_FOUND;
}
// access property
Property = (PKSP_NODE)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
if (IsEqualGUIDAligned(Property->Property.Set, GUID_NULL) && Property->Property.Id == 0 && Property->Property.Flags == (KSPROPERTY_TYPE_SETSUPPORT | KSPROPERTY_TYPE_TOPOLOGY))
{
return PcHandleGuidNullRequest(Irp, SubDeviceDescriptor);
}
// find property handler
Status = PcFindNodePropertyHandler(Irp, SubDeviceDescriptor, &PropertyItem);
// check for success
if (!NT_SUCCESS(Status))
{
// might not be a node property request
DPRINT("NotFound\n");
return STATUS_NOT_FOUND;
}
if (Property->Property.Flags & KSPROPERTY_TYPE_BASICSUPPORT)
{
// caller issued a basic property request
if (!(PropertyItem->Flags & KSPROPERTY_TYPE_BASICSUPPORT))
{
// driver does not have a basic support handler
return PcNodeBasicSupportHandler(Irp, PropertyItem);
}
}
// allocate a property request
PropertyRequest = (PPCPROPERTY_REQUEST)AllocateItem(NonPagedPool, sizeof(PCPROPERTY_REQUEST), TAG_PORTCLASS);
if (!PropertyRequest)
return STATUS_INSUFFICIENT_RESOURCES;
PropertyRequest->MajorTarget = SubDeviceDescriptor->UnknownMiniport;
PropertyRequest->MinorTarget = SubDeviceDescriptor->UnknownStream;
PropertyRequest->Irp = Irp;
PropertyRequest->Node = Property->NodeId;
PropertyRequest->PropertyItem = PropertyItem;
PropertyRequest->Verb = Property->Property.Flags;
PropertyRequest->InstanceSize = IoStack->Parameters.DeviceIoControl.InputBufferLength - sizeof(KSNODEPROPERTY);
PropertyRequest->Instance = (PVOID)((ULONG_PTR)IoStack->Parameters.DeviceIoControl.Type3InputBuffer + sizeof(KSNODEPROPERTY));
PropertyRequest->ValueSize = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
PropertyRequest->Value = Irp->UserBuffer;
Status = PropertyItem->Handler(PropertyRequest);
if (Status != STATUS_PENDING)
{
//request completed
Irp->IoStatus.Information = PropertyRequest->ValueSize;
ExFreePool(PropertyRequest);
}
// done
DPRINT("Status %x\n", Status);
return Status;
}
NTSTATUS
NTAPI
@ -96,207 +359,19 @@ PcHandlePropertyWithTable(
IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor)
{
NTSTATUS Status;
PIO_STACK_LOCATION IoStack;
PKSP_NODE Property;
PPCNODE_DESCRIPTOR Node;
PPCPROPERTY_ITEM PropertyItem;
ULONG Index;
LPGUID Buffer;
//PULONG Flags;
PPCPROPERTY_REQUEST PropertyRequest;
KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (PKSPROPERTY_ITEM)SubDeviceDescriptor;
// try handle it as node property request
Status = PcHandleNodePropertyRequest(Irp, SubDeviceDescriptor);
/* try first KsPropertyHandler */
Status = KsPropertyHandler(Irp, PropertySetCount, PropertySet);
if (Status != STATUS_NOT_FOUND)
return Status;
// get current irp stack location
IoStack = IoGetCurrentIrpStackLocation(Irp);
// access property
Property = (PKSP_NODE)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
// check if this a GUID_NULL request
if (Status == STATUS_NOT_FOUND)
{
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSP_NODE))
return Status;
// store device descriptor
KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (PKSPROPERTY_ITEM)SubDeviceDescriptor;
// check if its a request for a topology node
if (IsEqualGUIDAligned(Property->Property.Set, GUID_NULL) && Property->Property.Id == 0 && Property->Property.Flags == (KSPROPERTY_TYPE_SETSUPPORT | KSPROPERTY_TYPE_TOPOLOGY))
{
if (Property->NodeId >= SubDeviceDescriptor->DeviceDescriptor->NodeCount)
{
// request is out of bounds
Irp->IoStatus.Information = 0;
return STATUS_INVALID_PARAMETER;
}
Node = (PPCNODE_DESCRIPTOR)((ULONG_PTR)SubDeviceDescriptor->DeviceDescriptor->Nodes + (Property->NodeId * SubDeviceDescriptor->DeviceDescriptor->NodeSize));
if (!Node->AutomationTable)
{
// request is out of bounds
Irp->IoStatus.Information = 0;
return STATUS_INVALID_PARAMETER;
}
PC_ASSERT(Node->AutomationTable);
PC_ASSERT(Node->AutomationTable->PropertyCount);
PC_ASSERT(Node->AutomationTable->PropertyItemSize);
Buffer = (LPGUID)AllocateItem(NonPagedPool, sizeof (GUID) * Node->AutomationTable->PropertyCount, TAG_PORTCLASS);
if (!Buffer)
return STATUS_INSUFFICIENT_RESOURCES;
ULONG Count = 0, SubIndex;
PropertyItem = (PCPROPERTY_ITEM*)Node->AutomationTable->Properties;
for (Index = 0; Index < Node->AutomationTable->PropertyCount; Index++)
{
BOOL Found = FALSE;
for (SubIndex = 0; SubIndex < Count; Index++)
{
if (IsEqualGUIDAligned(Buffer[SubIndex], *PropertyItem->Set))
{
Found = TRUE;
break;
}
}
if (!Found)
{
RtlMoveMemory(&Buffer[Count], PropertyItem->Set, sizeof (GUID));
Count++;
}
PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + Node->AutomationTable->PropertyItemSize);
}
Irp->IoStatus.Information = sizeof (GUID) * Count;
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof (GUID) * Count)
{
// buffer too small
FreeItem(Buffer, TAG_PORTCLASS);
return STATUS_MORE_ENTRIES;
}
RtlMoveMemory(Irp->UserBuffer, Buffer, sizeof (GUID) * Count);
FreeItem(Buffer, TAG_PORTCLASS);
return STATUS_SUCCESS;
}
else /*if (Property->Property.Flags == (KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_TOPOLOGY) ||
Property->Property.Flags == (KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_TOPOLOGY) ||
Property->Property.Flags == (KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_TOPOLOGY)) */
{
//UNICODE_STRING GuidString;
if (Property->NodeId >= SubDeviceDescriptor->DeviceDescriptor->NodeCount)
{
// request is out of bounds
Irp->IoStatus.Information = 0;
return STATUS_INVALID_PARAMETER;
}
Node = (PPCNODE_DESCRIPTOR)((ULONG_PTR)SubDeviceDescriptor->DeviceDescriptor->Nodes + (Property->NodeId * SubDeviceDescriptor->DeviceDescriptor->NodeSize));
if (!Node->AutomationTable)
{
// request is out of bounds
Irp->IoStatus.Information = 0;
return STATUS_NOT_FOUND;
}
PC_ASSERT(Node->AutomationTable);
PC_ASSERT(Node->AutomationTable->PropertyCount);
PC_ASSERT(Node->AutomationTable->PropertyItemSize);
PropertyItem = (PCPROPERTY_ITEM*)Node->AutomationTable->Properties;
for(Index = 0; Index < Node->AutomationTable->PropertyCount; Index++)
{
if (IsEqualGUIDAligned(*PropertyItem->Set, Property->Property.Set) && PropertyItem->Id == Property->Property.Id)
{
if (Property->Property.Flags & KSPROPERTY_TYPE_BASICSUPPORT)
{
if (!(PropertyItem->Flags & KSPROPERTY_TYPE_BASICSUPPORT))
{
PC_ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(ULONG));
PULONG Flags = (PULONG)Irp->UserBuffer;
/* reset flags */
*Flags = 0;
if (PropertyItem->Flags & KSPROPERTY_TYPE_SET)
*Flags |= KSPROPERTY_TYPE_SET;
if (PropertyItem->Flags & KSPROPERTY_TYPE_GET)
*Flags |= KSPROPERTY_TYPE_GET;
Irp->IoStatus.Information = sizeof(ULONG);
if (IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(KSPROPERTY_DESCRIPTION))
{
/* get output buffer */
PKSPROPERTY_DESCRIPTION Description = (PKSPROPERTY_DESCRIPTION)Irp->UserBuffer;
/* store result */
Description->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION);
Description->PropTypeSet.Set = KSPROPTYPESETID_General;
Description->PropTypeSet.Id = 0;
Description->PropTypeSet.Flags = 0;
Description->MembersListCount = 0;
Description->Reserved = 0;
Irp->IoStatus.Information = sizeof(KSPROPERTY_DESCRIPTION);
}
return STATUS_SUCCESS;
}
}
PropertyRequest = (PPCPROPERTY_REQUEST)AllocateItem(NonPagedPool, sizeof(PCPROPERTY_REQUEST), TAG_PORTCLASS);
if (!PropertyRequest)
return STATUS_INSUFFICIENT_RESOURCES;
PC_ASSERT(SubDeviceDescriptor->UnknownMiniport);
PropertyRequest->MajorTarget = SubDeviceDescriptor->UnknownMiniport;
PropertyRequest->MinorTarget = SubDeviceDescriptor->UnknownStream;
PropertyRequest->Irp = Irp;
PropertyRequest->Node = Property->NodeId;
PropertyRequest->PropertyItem = PropertyItem;
PropertyRequest->Verb = Property->Property.Flags;
PropertyRequest->InstanceSize = IoStack->Parameters.DeviceIoControl.InputBufferLength - sizeof(KSNODEPROPERTY);
PropertyRequest->Instance = (PVOID)((ULONG_PTR)IoStack->Parameters.DeviceIoControl.Type3InputBuffer + sizeof(KSNODEPROPERTY));
PropertyRequest->ValueSize = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
PropertyRequest->Value = Irp->UserBuffer;
Status = PropertyItem->Handler(PropertyRequest);
if (Status != STATUS_PENDING)
{
//DPRINT("Status %x ValueSize %u
Irp->IoStatus.Information = PropertyRequest->ValueSize;
ExFreePool(PropertyRequest);
}
#if 0
RtlStringFromGUID(Property->Property.Set, &GuidString);
DPRINT("Id %u Flags %x Set %S FlagsItem %x Status %x\n", Property->Property.Id, Property->Property.Flags, GuidString.Buffer, PropertyItem->Flags, Status);
RtlFreeUnicodeString(&GuidString);
#endif
return Status;
}
PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + Node->AutomationTable->PropertyItemSize);
}
#if 0
RtlStringFromGUID(Property->Property.Set, &GuidString);
DPRINT("Id %u Flags %x Set %S Status %x\n", Property->Property.Id, Property->Property.Flags, GuidString.Buffer, Status);
RtlFreeUnicodeString(&GuidString);
#endif
}
/* then try KsPropertyHandler */
Status = KsPropertyHandler(Irp, PropertySetCount, PropertySet);
}
return Status;
}

View file

@ -2162,7 +2162,7 @@ SetGetMuteControlDetails(
Value = Input->fValue;
/* set control details */
Status = SetGetControlDetails(DeviceObject, DeviceId, NodeId, DeviceInfo, bSet, KSPROPERTY_AUDIO_MUTE, MAXULONG, &Value);
Status = SetGetControlDetails(DeviceObject, DeviceId, NodeId, DeviceInfo, bSet, KSPROPERTY_AUDIO_MUTE, 0, &Value);
if (!NT_SUCCESS(Status))
return Status;