mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 18:25:58 +00:00
- Implement IPortMidi, IPortFilterDMus, IPortPinDMus
- Implement reading / writing midi stream data using IMiniportMidiStream interface - Delete old IPortMidi implementation svn path=/trunk/; revision=40835
This commit is contained in:
parent
0cddd07a48
commit
a5731d82f9
9 changed files with 1894 additions and 500 deletions
503
reactos/drivers/wdm/audio/backpln/portcls/filter_dmus.c
Normal file
503
reactos/drivers/wdm/audio/backpln/portcls/filter_dmus.c
Normal file
|
@ -0,0 +1,503 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS Kernel Streaming
|
||||||
|
* FILE: drivers/wdm/audio/backpln/portcls/filter_dmus.c
|
||||||
|
* PURPOSE: portcls wave pci filter
|
||||||
|
* PROGRAMMER: Johannes Anderwald
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "private.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
IPortFilterDMusVtbl *lpVtbl;
|
||||||
|
|
||||||
|
LONG ref;
|
||||||
|
|
||||||
|
IPortDMus* Port;
|
||||||
|
IPortPinDMus ** Pins;
|
||||||
|
SUBDEVICE_DESCRIPTOR * Descriptor;
|
||||||
|
|
||||||
|
}IPortFilterDMusImpl;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IPortFilterDMus_fnQueryInterface(
|
||||||
|
IPortFilterDMus* iface,
|
||||||
|
IN REFIID refiid,
|
||||||
|
OUT PVOID* Output)
|
||||||
|
{
|
||||||
|
IPortFilterDMusImpl * This = (IPortFilterDMusImpl*)iface;
|
||||||
|
|
||||||
|
if (IsEqualGUIDAligned(refiid, &IID_IIrpTarget) ||
|
||||||
|
IsEqualGUIDAligned(refiid, &IID_IUnknown))
|
||||||
|
{
|
||||||
|
*Output = &This->lpVtbl;
|
||||||
|
InterlockedIncrement(&This->ref);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else if (IsEqualGUIDAligned(refiid, &IID_IPort))
|
||||||
|
{
|
||||||
|
*Output = This->Port;
|
||||||
|
This->Port->lpVtbl->AddRef(This->Port);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
IPortFilterDMus_fnAddRef(
|
||||||
|
IPortFilterDMus* iface)
|
||||||
|
{
|
||||||
|
IPortFilterDMusImpl * This = (IPortFilterDMusImpl*)iface;
|
||||||
|
|
||||||
|
return InterlockedIncrement(&This->ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
IPortFilterDMus_fnRelease(
|
||||||
|
IPortFilterDMus* iface)
|
||||||
|
{
|
||||||
|
IPortFilterDMusImpl * This = (IPortFilterDMusImpl*)iface;
|
||||||
|
|
||||||
|
InterlockedDecrement(&This->ref);
|
||||||
|
|
||||||
|
if (This->ref == 0)
|
||||||
|
{
|
||||||
|
FreeItem(This, TAG_PORTCLASS);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return This->ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IPortFilterDMus_fnNewIrpTarget(
|
||||||
|
IN IPortFilterDMus* iface,
|
||||||
|
OUT struct IIrpTarget **OutTarget,
|
||||||
|
IN WCHAR * Name,
|
||||||
|
IN PUNKNOWN Unknown,
|
||||||
|
IN POOL_TYPE PoolType,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN KSOBJECT_CREATE *CreateObject)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
IPortPinDMus * Pin;
|
||||||
|
PKSPIN_CONNECT ConnectDetails;
|
||||||
|
IPortFilterDMusImpl * This = (IPortFilterDMusImpl *)iface;
|
||||||
|
|
||||||
|
ASSERT(This->Port);
|
||||||
|
ASSERT(This->Descriptor);
|
||||||
|
ASSERT(This->Pins);
|
||||||
|
|
||||||
|
DPRINT("IPortFilterDMus_fnNewIrpTarget entered\n");
|
||||||
|
|
||||||
|
/* let's verify the connection request */
|
||||||
|
Status = PcValidateConnectRequest(Irp, &This->Descriptor->Factory, &ConnectDetails);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (This->Pins[ConnectDetails->PinId] && This->Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount)
|
||||||
|
{
|
||||||
|
/* release existing instance */
|
||||||
|
ASSERT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now create the pin */
|
||||||
|
Status = NewPortPinDMus(&Pin);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize the pin */
|
||||||
|
Status = Pin->lpVtbl->Init(Pin, This->Port, iface, ConnectDetails, &This->Descriptor->Factory.KsPinDescriptor[ConnectDetails->PinId], DeviceObject);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
Pin->lpVtbl->Release(Pin);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* release existing pin */
|
||||||
|
if (This->Pins[ConnectDetails->PinId])
|
||||||
|
{
|
||||||
|
This->Pins[ConnectDetails->PinId]->lpVtbl->Release(This->Pins[ConnectDetails->PinId]);
|
||||||
|
}
|
||||||
|
/* store pin */
|
||||||
|
This->Pins[ConnectDetails->PinId] = Pin;
|
||||||
|
|
||||||
|
/* store result */
|
||||||
|
*OutTarget = (IIrpTarget*)Pin;
|
||||||
|
|
||||||
|
/* increment current instance count */
|
||||||
|
This->Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount++;
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IPortFilterDMus_fnDeviceIoControl(
|
||||||
|
IN IPortFilterDMus* iface,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
PIO_STACK_LOCATION IoStack;
|
||||||
|
ISubdevice *SubDevice = NULL;
|
||||||
|
SUBDEVICE_DESCRIPTOR * Descriptor;
|
||||||
|
NTSTATUS Status;
|
||||||
|
IPortFilterDMusImpl * This = (IPortFilterDMusImpl *)iface;
|
||||||
|
|
||||||
|
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY);
|
||||||
|
Status = This->Port->lpVtbl->QueryInterface(This->Port, &IID_ISubdevice, (PVOID*)&SubDevice);
|
||||||
|
ASSERT(Status == STATUS_SUCCESS);
|
||||||
|
ASSERT(SubDevice != NULL);
|
||||||
|
|
||||||
|
Status = SubDevice->lpVtbl->GetDescriptor(SubDevice, &Descriptor);
|
||||||
|
ASSERT(Status == STATUS_SUCCESS);
|
||||||
|
ASSERT(Descriptor != NULL);
|
||||||
|
|
||||||
|
SubDevice->lpVtbl->Release(SubDevice);
|
||||||
|
|
||||||
|
return PcPropertyHandler(Irp, Descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IPortFilterDMus_fnRead(
|
||||||
|
IN IPortFilterDMus* iface,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IPortFilterDMus_fnWrite(
|
||||||
|
IN IPortFilterDMus* iface,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IPortFilterDMus_fnFlush(
|
||||||
|
IN IPortFilterDMus* iface,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IPortFilterDMus_fnClose(
|
||||||
|
IN IPortFilterDMus* iface,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
ULONG Index;
|
||||||
|
IPortFilterDMusImpl * This = (IPortFilterDMusImpl *)iface;
|
||||||
|
|
||||||
|
for(Index = 0; Index < This->Descriptor->Factory.PinDescriptorCount; Index++)
|
||||||
|
{
|
||||||
|
if (This->Pins[Index])
|
||||||
|
{
|
||||||
|
This->Pins[Index]->lpVtbl->Close(This->Pins[Index], DeviceObject, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IPortFilterDMus_fnQuerySecurity(
|
||||||
|
IN IPortFilterDMus* iface,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IPortFilterDMus_fnSetSecurity(
|
||||||
|
IN IPortFilterDMus* iface,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
IPortFilterDMus_fnFastDeviceIoControl(
|
||||||
|
IN IPortFilterDMus* iface,
|
||||||
|
IN PFILE_OBJECT FileObject,
|
||||||
|
IN BOOLEAN Wait,
|
||||||
|
IN PVOID InputBuffer,
|
||||||
|
IN ULONG InputBufferLength,
|
||||||
|
OUT PVOID OutputBuffer,
|
||||||
|
IN ULONG OutputBufferLength,
|
||||||
|
IN ULONG IoControlCode,
|
||||||
|
OUT PIO_STATUS_BLOCK StatusBlock,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
ULONG Index;
|
||||||
|
PKSPROPERTY Property;
|
||||||
|
NTSTATUS Status;
|
||||||
|
ISubdevice * SubDevice = NULL;
|
||||||
|
PSUBDEVICE_DESCRIPTOR Descriptor = NULL;
|
||||||
|
IPortFilterDMusImpl * This = (IPortFilterDMusImpl *)iface;
|
||||||
|
|
||||||
|
Property = (PKSPROPERTY)InputBuffer;
|
||||||
|
|
||||||
|
if (InputBufferLength < sizeof(KSPROPERTY))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
|
||||||
|
/* get private interface */
|
||||||
|
Status = This->Port->lpVtbl->QueryInterface(This->Port, &IID_ISubdevice, (PVOID*)&SubDevice);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* get descriptor */
|
||||||
|
Status = SubDevice->lpVtbl->GetDescriptor(SubDevice, &Descriptor);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
SubDevice->lpVtbl->Release(SubDevice);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Index = 0; Index < Descriptor->FilterPropertySet.FreeKsPropertySetOffset; Index++)
|
||||||
|
{
|
||||||
|
if (IsEqualGUIDAligned(&Property->Set, Descriptor->FilterPropertySet.Properties[Index].Set))
|
||||||
|
{
|
||||||
|
FastPropertyHandler(FileObject, (PKSPROPERTY)InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, StatusBlock,
|
||||||
|
1,
|
||||||
|
&Descriptor->FilterPropertySet.Properties[Index],
|
||||||
|
Descriptor, SubDevice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
IPortFilterDMus_fnFastRead(
|
||||||
|
IN IPortFilterDMus* iface,
|
||||||
|
IN PFILE_OBJECT FileObject,
|
||||||
|
IN PLARGE_INTEGER FileOffset,
|
||||||
|
IN ULONG Length,
|
||||||
|
IN BOOLEAN Wait,
|
||||||
|
IN ULONG LockKey,
|
||||||
|
IN PVOID Buffer,
|
||||||
|
OUT PIO_STATUS_BLOCK StatusBlock,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
IPortFilterDMus_fnFastWrite(
|
||||||
|
IN IPortFilterDMus* iface,
|
||||||
|
IN PFILE_OBJECT FileObject,
|
||||||
|
IN PLARGE_INTEGER FileOffset,
|
||||||
|
IN ULONG Length,
|
||||||
|
IN BOOLEAN Wait,
|
||||||
|
IN ULONG LockKey,
|
||||||
|
IN PVOID Buffer,
|
||||||
|
OUT PIO_STATUS_BLOCK StatusBlock,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IPortFilterDMus_fnInit(
|
||||||
|
IN IPortFilterDMus* iface,
|
||||||
|
IN IPortDMus* Port)
|
||||||
|
{
|
||||||
|
ISubdevice * ISubDevice;
|
||||||
|
SUBDEVICE_DESCRIPTOR * Descriptor;
|
||||||
|
NTSTATUS Status;
|
||||||
|
IPortFilterDMusImpl * This = (IPortFilterDMusImpl*)iface;
|
||||||
|
|
||||||
|
This->Port = Port;
|
||||||
|
|
||||||
|
/* get our private interface */
|
||||||
|
Status = This->Port->lpVtbl->QueryInterface(This->Port, &IID_ISubdevice, (PVOID*)&ISubDevice);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
|
/* get the subdevice descriptor */
|
||||||
|
Status = ISubDevice->lpVtbl->GetDescriptor(ISubDevice, &Descriptor);
|
||||||
|
|
||||||
|
/* release subdevice interface */
|
||||||
|
ISubDevice->lpVtbl->Release(ISubDevice);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
|
/* save descriptor */
|
||||||
|
This->Descriptor = Descriptor;
|
||||||
|
|
||||||
|
/* allocate pin array */
|
||||||
|
This->Pins = AllocateItem(NonPagedPool, Descriptor->Factory.PinDescriptorCount * sizeof(IPortPinDMus*), TAG_PORTCLASS);
|
||||||
|
|
||||||
|
if (!This->Pins)
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
|
/* increment reference count */
|
||||||
|
Port->lpVtbl->AddRef(Port);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IPortFilterDMus_fnFreePin(
|
||||||
|
IN IPortFilterDMus* iface,
|
||||||
|
IN struct IPortPinDMus* Pin)
|
||||||
|
{
|
||||||
|
ULONG Index;
|
||||||
|
IPortFilterDMusImpl * This = (IPortFilterDMusImpl*)iface;
|
||||||
|
|
||||||
|
for(Index = 0; Index < This->Descriptor->Factory.PinDescriptorCount; Index++)
|
||||||
|
{
|
||||||
|
if (This->Pins[Index] == Pin)
|
||||||
|
{
|
||||||
|
This->Pins[Index]->lpVtbl->Release(This->Pins[Index]);
|
||||||
|
This->Pins[Index] = NULL;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
IPortFilterDMus_fnNotifyPins(
|
||||||
|
IN IPortFilterDMus* iface)
|
||||||
|
{
|
||||||
|
ULONG Index;
|
||||||
|
IPortFilterDMusImpl * This = (IPortFilterDMusImpl*)iface;
|
||||||
|
|
||||||
|
DPRINT("Notifying %u pins\n", This->Descriptor->Factory.PinDescriptorCount);
|
||||||
|
|
||||||
|
for(Index = 0; Index < This->Descriptor->Factory.PinDescriptorCount; Index++)
|
||||||
|
{
|
||||||
|
This->Pins[Index]->lpVtbl->Notify(This->Pins[Index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static IPortFilterDMusVtbl vt_IPortFilterDMus =
|
||||||
|
{
|
||||||
|
IPortFilterDMus_fnQueryInterface,
|
||||||
|
IPortFilterDMus_fnAddRef,
|
||||||
|
IPortFilterDMus_fnRelease,
|
||||||
|
IPortFilterDMus_fnNewIrpTarget,
|
||||||
|
IPortFilterDMus_fnDeviceIoControl,
|
||||||
|
IPortFilterDMus_fnRead,
|
||||||
|
IPortFilterDMus_fnWrite,
|
||||||
|
IPortFilterDMus_fnFlush,
|
||||||
|
IPortFilterDMus_fnClose,
|
||||||
|
IPortFilterDMus_fnQuerySecurity,
|
||||||
|
IPortFilterDMus_fnSetSecurity,
|
||||||
|
IPortFilterDMus_fnFastDeviceIoControl,
|
||||||
|
IPortFilterDMus_fnFastRead,
|
||||||
|
IPortFilterDMus_fnFastWrite,
|
||||||
|
IPortFilterDMus_fnInit,
|
||||||
|
IPortFilterDMus_fnFreePin,
|
||||||
|
IPortFilterDMus_fnNotifyPins
|
||||||
|
};
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NewPortFilterDMus(
|
||||||
|
OUT PPORTFILTERDMUS * OutFilter)
|
||||||
|
{
|
||||||
|
IPortFilterDMusImpl * This;
|
||||||
|
|
||||||
|
This = AllocateItem(NonPagedPool, sizeof(IPortFilterDMusImpl), TAG_PORTCLASS);
|
||||||
|
if (!This)
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
|
/* initialize IPortFilterDMus */
|
||||||
|
This->ref = 1;
|
||||||
|
This->lpVtbl = &vt_IPortFilterDMus;
|
||||||
|
|
||||||
|
/* return result */
|
||||||
|
*OutFilter = (IPortFilterDMus*)&This->lpVtbl;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
|
@ -13,10 +13,14 @@ const GUID CLSID_PortTopology = {0xb4c90a32L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00,
|
||||||
const GUID CLSID_PortMidi = {0xb4c90a43L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
|
const GUID CLSID_PortMidi = {0xb4c90a43L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
|
||||||
const GUID CLSID_PortWaveCyclic = {0xb4c90a2aL, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
|
const GUID CLSID_PortWaveCyclic = {0xb4c90a2aL, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
|
||||||
const GUID CLSID_PortWavePci = {0xb4c90a54L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
|
const GUID CLSID_PortWavePci = {0xb4c90a54L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
|
||||||
const GUID CLSID_PortDMus;
|
const GUID CLSID_PortDMus = {0xb7902fe9L, 0xfb0a, 0x11d1, {0x81, 0xb0, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1}};
|
||||||
const GUID IID_IMiniportDMus;
|
|
||||||
|
|
||||||
|
const GUID IID_IMiniportDMus = {0xc096df9dL, 0xfb09, 0x11d1, {0x81, 0xb0, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1}};
|
||||||
const GUID IID_IMiniportTopology = {0xb4c90a31L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
|
const GUID IID_IMiniportTopology = {0xb4c90a31L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
|
||||||
|
const GUID IID_IMiniportMidi = {0xb4c90a41L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
|
||||||
|
const GUID IID_IMiniportWavePci = {0xb4c90a52L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
|
||||||
|
|
||||||
|
|
||||||
const GUID IID_IPortTopology = {0xb4c90a30L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
|
const GUID IID_IPortTopology = {0xb4c90a30L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
|
||||||
|
|
||||||
const GUID CLSID_MiniportDriverDMusUART;
|
const GUID CLSID_MiniportDriverDMusUART;
|
||||||
|
@ -32,8 +36,7 @@ const GUID IID_IInterruptSync = {0x22C6AC63L, 0x851B, 0x11D0, {0x9A, 0x7F, 0x00,
|
||||||
const GUID IID_IPortWavePci = {0xb4c90a50L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
|
const GUID IID_IPortWavePci = {0xb4c90a50L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
|
||||||
const GUID IID_IPortWavePciStream = {0xb4c90a51L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
|
const GUID IID_IPortWavePciStream = {0xb4c90a51L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
|
||||||
const GUID IID_IPortMidi = {0xb4c90a40L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
|
const GUID IID_IPortMidi = {0xb4c90a40L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
|
||||||
const GUID IID_IMiniportMidi = {0xb4c90a41L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
|
const GUID IID_IPortDMus = {0xc096df9cL, 0xfb09, 0x11d1, {0x81, 0xb0, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1}};
|
||||||
const GUID IID_IMiniportWavePci = {0xb4c90a52L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
|
|
||||||
const GUID IID_IAdapterPowerManagement = {0x793417D0L, 0x35FE, 0x11D1, {0xAD, 0x08, 0x00, 0xA0, 0xC9, 0x0A, 0xB1, 0xB0}};
|
const GUID IID_IAdapterPowerManagement = {0x793417D0L, 0x35FE, 0x11D1, {0xAD, 0x08, 0x00, 0xA0, 0xC9, 0x0A, 0xB1, 0xB0}};
|
||||||
|
|
||||||
const GUID IID_IMiniportWaveCyclic = {0xb4c90a27L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
|
const GUID IID_IMiniportWaveCyclic = {0xb4c90a27L, 0x5791, 0x11d0, {0x86, 0xf9, 0x00, 0xa0, 0xc9, 0x11, 0xb5, 0x44}};
|
||||||
|
|
|
@ -497,7 +497,7 @@ DECLARE_INTERFACE_(IPortFilterWaveRT, IIrpTarget)
|
||||||
typedef IPortFilterWaveRT *PPORTFILTERWAVERT;
|
typedef IPortFilterWaveRT *PPORTFILTERWAVERT;
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* IPortPinWavePci
|
* IPortPinWaveRT
|
||||||
*****************************************************************************
|
*****************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -569,6 +569,59 @@ DECLARE_INTERFACE_(IPortPinWaveCyclic, IIrpTarget)
|
||||||
STDMETHOD_(PMINIPORT, GetMiniport)(THIS);
|
STDMETHOD_(PMINIPORT, GetMiniport)(THIS);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* IPortFilterDMus
|
||||||
|
*****************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef INTERFACE
|
||||||
|
#define INTERFACE IPortFilterDMus
|
||||||
|
|
||||||
|
struct IPortPinDMus;
|
||||||
|
|
||||||
|
DECLARE_INTERFACE_(IPortFilterDMus, IIrpTarget)
|
||||||
|
{
|
||||||
|
DEFINE_ABSTRACT_UNKNOWN()
|
||||||
|
|
||||||
|
DEFINE_ABSTRACT_IRPTARGET()
|
||||||
|
|
||||||
|
STDMETHOD_(NTSTATUS, Init)(THIS_
|
||||||
|
IN PPORTDMUS Port)PURE;
|
||||||
|
|
||||||
|
STDMETHOD_(NTSTATUS, FreePin)(THIS_
|
||||||
|
IN struct IPortPinDMus* Pin)PURE;
|
||||||
|
|
||||||
|
STDMETHOD_(VOID, NotifyPins)(THIS);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef IPortFilterDMus *PPORTFILTERDMUS;
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* IPortPinDMus
|
||||||
|
*****************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef INTERFACE
|
||||||
|
#define INTERFACE IPortPinDMus
|
||||||
|
|
||||||
|
DECLARE_INTERFACE_(IPortPinDMus, IIrpTarget)
|
||||||
|
{
|
||||||
|
DEFINE_ABSTRACT_UNKNOWN()
|
||||||
|
|
||||||
|
DEFINE_ABSTRACT_IRPTARGET()
|
||||||
|
|
||||||
|
STDMETHOD_(NTSTATUS, Init)(THIS_
|
||||||
|
IN PPORTDMUS Port,
|
||||||
|
IN PPORTFILTERDMUS Filter,
|
||||||
|
IN KSPIN_CONNECT * ConnectDetails,
|
||||||
|
IN KSPIN_DESCRIPTOR * PinDescriptor,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject) PURE;
|
||||||
|
|
||||||
|
STDMETHOD_(VOID, Notify)(THIS);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef IPortPinDMus *PPORTPINDMUS;
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* IDmaChannelInit
|
* IDmaChannelInit
|
||||||
*****************************************************************************
|
*****************************************************************************
|
||||||
|
|
844
reactos/drivers/wdm/audio/backpln/portcls/pin_dmus.c
Normal file
844
reactos/drivers/wdm/audio/backpln/portcls/pin_dmus.c
Normal file
|
@ -0,0 +1,844 @@
|
||||||
|
/*
|
||||||
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
|
* PROJECT: ReactOS Kernel Streaming
|
||||||
|
* FILE: drivers/wdm/audio/backpln/portcls/pin_dmus.c
|
||||||
|
* PURPOSE: DMus IRP Audio Pin
|
||||||
|
* PROGRAMMER: Johannes Anderwald
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "private.h"
|
||||||
|
|
||||||
|
#include "private.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
IPortPinDMusVtbl *lpVtbl;
|
||||||
|
IServiceSinkVtbl *lpVtblServiceSink;
|
||||||
|
|
||||||
|
LONG ref;
|
||||||
|
IPortDMus * Port;
|
||||||
|
IPortFilterDMus * Filter;
|
||||||
|
KSPIN_DESCRIPTOR * KsPinDescriptor;
|
||||||
|
PMINIPORTDMUS Miniport;
|
||||||
|
|
||||||
|
PSERVICEGROUP ServiceGroup;
|
||||||
|
|
||||||
|
PMINIPORTMIDI MidiMiniport;
|
||||||
|
PMINIPORTMIDISTREAM MidiStream;
|
||||||
|
|
||||||
|
|
||||||
|
KSSTATE State;
|
||||||
|
PKSDATAFORMAT Format;
|
||||||
|
KSPIN_CONNECT * ConnectDetails;
|
||||||
|
|
||||||
|
BOOL Capture;
|
||||||
|
PDEVICE_OBJECT DeviceObject;
|
||||||
|
IIrpQueue * IrpQueue;
|
||||||
|
|
||||||
|
ULONG TotalPackets;
|
||||||
|
ULONG PreCompleted;
|
||||||
|
ULONG PostCompleted;
|
||||||
|
|
||||||
|
}IPortPinDMusImpl;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
IPortPinDMusImpl *Pin;
|
||||||
|
PIO_WORKITEM WorkItem;
|
||||||
|
KSSTATE State;
|
||||||
|
}SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT;
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IPortDMus_fnProcessNewIrp(
|
||||||
|
IPortPinDMusImpl * This);
|
||||||
|
|
||||||
|
//==================================================================================================================================
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IServiceSink_fnQueryInterface(
|
||||||
|
IServiceSink* iface,
|
||||||
|
IN REFIID refiid,
|
||||||
|
OUT PVOID* Output)
|
||||||
|
{
|
||||||
|
IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblServiceSink);
|
||||||
|
|
||||||
|
DPRINT("IServiceSink_fnQueryInterface entered\n");
|
||||||
|
|
||||||
|
if (IsEqualGUIDAligned(refiid, &IID_IServiceSink) ||
|
||||||
|
IsEqualGUIDAligned(refiid, &IID_IUnknown))
|
||||||
|
{
|
||||||
|
*Output = &This->lpVtblServiceSink;
|
||||||
|
InterlockedIncrement(&This->ref);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
IServiceSink_fnAddRef(
|
||||||
|
IServiceSink* iface)
|
||||||
|
{
|
||||||
|
IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblServiceSink);
|
||||||
|
DPRINT("IServiceSink_fnAddRef entered\n");
|
||||||
|
|
||||||
|
return InterlockedIncrement(&This->ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
IServiceSink_fnRelease(
|
||||||
|
IServiceSink* iface)
|
||||||
|
{
|
||||||
|
IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblServiceSink);
|
||||||
|
|
||||||
|
InterlockedDecrement(&This->ref);
|
||||||
|
|
||||||
|
DPRINT("IServiceSink_fnRelease entered %u\n", This->ref);
|
||||||
|
|
||||||
|
if (This->ref == 0)
|
||||||
|
{
|
||||||
|
FreeItem(This, TAG_PORTCLASS);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Return new reference count */
|
||||||
|
return This->ref;
|
||||||
|
}
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
SetStreamWorkerRoutine(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PVOID Context)
|
||||||
|
{
|
||||||
|
IPortPinDMusImpl * This;
|
||||||
|
PSETSTREAM_CONTEXT Ctx = (PSETSTREAM_CONTEXT)Context;
|
||||||
|
KSSTATE State;
|
||||||
|
|
||||||
|
This = Ctx->Pin;
|
||||||
|
State = Ctx->State;
|
||||||
|
|
||||||
|
IoFreeWorkItem(Ctx->WorkItem);
|
||||||
|
FreeItem(Ctx, TAG_PORTCLASS);
|
||||||
|
|
||||||
|
/* Has the audio stream resumed? */
|
||||||
|
if (This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue) && State == KSSTATE_STOP)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Set the state */
|
||||||
|
if (NT_SUCCESS(This->MidiStream->lpVtbl->SetState(This->MidiStream, State)))
|
||||||
|
{
|
||||||
|
/* Set internal state to stop */
|
||||||
|
This->State = State;
|
||||||
|
|
||||||
|
if (This->State == KSSTATE_STOP)
|
||||||
|
{
|
||||||
|
/* reset start stream */
|
||||||
|
This->IrpQueue->lpVtbl->CancelBuffers(This->IrpQueue); //FIX function name
|
||||||
|
DPRINT1("Stopping PreCompleted %u PostCompleted %u\n", This->PreCompleted, This->PostCompleted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
SetStreamState(
|
||||||
|
IN IPortPinDMusImpl * This,
|
||||||
|
IN KSSTATE State)
|
||||||
|
{
|
||||||
|
PIO_WORKITEM WorkItem;
|
||||||
|
PSETSTREAM_CONTEXT Context;
|
||||||
|
|
||||||
|
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
|
||||||
|
|
||||||
|
/* Has the audio stream resumed? */
|
||||||
|
if (This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue) && State == KSSTATE_STOP)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Has the audio state already been set? */
|
||||||
|
if (This->State == State)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* allocate set state context */
|
||||||
|
Context = AllocateItem(NonPagedPool, sizeof(SETSTREAM_CONTEXT), TAG_PORTCLASS);
|
||||||
|
|
||||||
|
if (!Context)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* allocate work item */
|
||||||
|
WorkItem = IoAllocateWorkItem(This->DeviceObject);
|
||||||
|
|
||||||
|
if (!WorkItem)
|
||||||
|
{
|
||||||
|
ExFreePool(Context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context->Pin = (PVOID)This;
|
||||||
|
Context->WorkItem = WorkItem;
|
||||||
|
Context->State = State;
|
||||||
|
|
||||||
|
/* queue the work item */
|
||||||
|
IoQueueWorkItem(WorkItem, SetStreamWorkerRoutine, DelayedWorkQueue, (PVOID)Context);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
TransferMidiData(
|
||||||
|
IPortPinDMusImpl * This)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PUCHAR Buffer;
|
||||||
|
ULONG BufferSize;
|
||||||
|
ULONG BytesWritten;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Status = This->IrpQueue->lpVtbl->GetMapping(This->IrpQueue, &Buffer, &BufferSize);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
SetStreamState(This, KSSTATE_STOP);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (This->Capture)
|
||||||
|
{
|
||||||
|
Status = This->MidiStream->lpVtbl->Read(This->MidiStream, Buffer, BufferSize, &BytesWritten);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("Read failed with %x\n", Status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Status = This->MidiStream->lpVtbl->Write(This->MidiStream, Buffer, BufferSize, &BytesWritten);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("Write failed with %x\n", Status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!BytesWritten)
|
||||||
|
{
|
||||||
|
DPRINT("Device is busy retry later\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
This->IrpQueue->lpVtbl->UpdateMapping(This->IrpQueue, BytesWritten);
|
||||||
|
|
||||||
|
}while(TRUE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
IServiceSink_fnRequestService(
|
||||||
|
IServiceSink* iface)
|
||||||
|
{
|
||||||
|
IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblServiceSink);
|
||||||
|
|
||||||
|
ASSERT_IRQL(DISPATCH_LEVEL);
|
||||||
|
|
||||||
|
if (This->MidiStream)
|
||||||
|
{
|
||||||
|
TransferMidiData(This);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static IServiceSinkVtbl vt_IServiceSink =
|
||||||
|
{
|
||||||
|
IServiceSink_fnQueryInterface,
|
||||||
|
IServiceSink_fnAddRef,
|
||||||
|
IServiceSink_fnRelease,
|
||||||
|
IServiceSink_fnRequestService
|
||||||
|
};
|
||||||
|
|
||||||
|
//==================================================================================================================================
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IPortPinDMus_fnQueryInterface(
|
||||||
|
IPortPinDMus* iface,
|
||||||
|
IN REFIID refiid,
|
||||||
|
OUT PVOID* Output)
|
||||||
|
{
|
||||||
|
IPortPinDMusImpl * This = (IPortPinDMusImpl*)iface;
|
||||||
|
|
||||||
|
if (IsEqualGUIDAligned(refiid, &IID_IIrpTarget) ||
|
||||||
|
IsEqualGUIDAligned(refiid, &IID_IUnknown))
|
||||||
|
{
|
||||||
|
*Output = &This->lpVtbl;
|
||||||
|
InterlockedIncrement(&This->ref);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
IPortPinDMus_fnAddRef(
|
||||||
|
IPortPinDMus* iface)
|
||||||
|
{
|
||||||
|
IPortPinDMusImpl * This = (IPortPinDMusImpl*)iface;
|
||||||
|
|
||||||
|
return InterlockedIncrement(&This->ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
IPortPinDMus_fnRelease(
|
||||||
|
IPortPinDMus* iface)
|
||||||
|
{
|
||||||
|
IPortPinDMusImpl * This = (IPortPinDMusImpl*)iface;
|
||||||
|
|
||||||
|
InterlockedDecrement(&This->ref);
|
||||||
|
|
||||||
|
if (This->ref == 0)
|
||||||
|
{
|
||||||
|
FreeItem(This, TAG_PORTCLASS);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return This->ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @unimplemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IPortPinDMus_fnNewIrpTarget(
|
||||||
|
IN IPortPinDMus* iface,
|
||||||
|
OUT struct IIrpTarget **OutTarget,
|
||||||
|
IN WCHAR * Name,
|
||||||
|
IN PUNKNOWN Unknown,
|
||||||
|
IN POOL_TYPE PoolType,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN KSOBJECT_CREATE *CreateObject)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @unimplemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IPortPinDMus_fnDeviceIoControl(
|
||||||
|
IN IPortPinDMus* iface,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IPortPinDMus_fnRead(
|
||||||
|
IN IPortPinDMus* iface,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IPortPinDMus_fnWrite(
|
||||||
|
IN IPortPinDMus* iface,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IPortPinDMus_fnFlush(
|
||||||
|
IN IPortPinDMus* iface,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
CloseStreamRoutine(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PVOID Context)
|
||||||
|
{
|
||||||
|
PMINIPORTMIDISTREAM Stream = NULL;
|
||||||
|
NTSTATUS Status;
|
||||||
|
ISubdevice *ISubDevice;
|
||||||
|
PSUBDEVICE_DESCRIPTOR Descriptor;
|
||||||
|
IPortPinDMusImpl * This;
|
||||||
|
PCLOSESTREAM_CONTEXT Ctx = (PCLOSESTREAM_CONTEXT)Context;
|
||||||
|
|
||||||
|
This = (IPortPinDMusImpl*)Ctx->Pin;
|
||||||
|
|
||||||
|
if (This->MidiStream)
|
||||||
|
{
|
||||||
|
if (This->State != KSSTATE_STOP)
|
||||||
|
{
|
||||||
|
This->MidiStream->lpVtbl->SetState(This->MidiStream, KSSTATE_STOP);
|
||||||
|
KeStallExecutionProcessor(10);
|
||||||
|
}
|
||||||
|
Stream = This->MidiStream;
|
||||||
|
This->MidiStream = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (This->ServiceGroup)
|
||||||
|
{
|
||||||
|
This->ServiceGroup->lpVtbl->RemoveMember(This->ServiceGroup, (PSERVICESINK)&This->lpVtblServiceSink);
|
||||||
|
This->ServiceGroup->lpVtbl->Release(This->ServiceGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = This->Port->lpVtbl->QueryInterface(This->Port, &IID_ISubdevice, (PVOID*)&ISubDevice);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
Status = ISubDevice->lpVtbl->GetDescriptor(ISubDevice, &Descriptor);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ISubDevice->lpVtbl->Release(ISubDevice);
|
||||||
|
Descriptor->Factory.Instances[This->ConnectDetails->PinId].CurrentPinInstanceCount--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (This->Format)
|
||||||
|
{
|
||||||
|
ExFreePool(This->Format);
|
||||||
|
This->Format = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* complete the irp */
|
||||||
|
Ctx->Irp->IoStatus.Information = 0;
|
||||||
|
Ctx->Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
IoCompleteRequest(Ctx->Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
/* free the work item */
|
||||||
|
IoFreeWorkItem(Ctx->WorkItem);
|
||||||
|
|
||||||
|
/* free work item ctx */
|
||||||
|
FreeItem(Ctx, TAG_PORTCLASS);
|
||||||
|
|
||||||
|
/* destroy DMus pin */
|
||||||
|
This->Filter->lpVtbl->FreePin(This->Filter, (PPORTPINDMUS)This);
|
||||||
|
|
||||||
|
if (Stream)
|
||||||
|
{
|
||||||
|
DPRINT1("Closing stream at Irql %u\n", KeGetCurrentIrql());
|
||||||
|
Stream->lpVtbl->Release(Stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IPortPinDMus_fnClose(
|
||||||
|
IN IPortPinDMus* iface,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
PCLOSESTREAM_CONTEXT Ctx;
|
||||||
|
IPortPinDMusImpl * This = (IPortPinDMusImpl*)iface;
|
||||||
|
|
||||||
|
if (This->MidiStream)
|
||||||
|
{
|
||||||
|
Ctx = AllocateItem(NonPagedPool, sizeof(CLOSESTREAM_CONTEXT), TAG_PORTCLASS);
|
||||||
|
if (!Ctx)
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to allocate stream context\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ctx->WorkItem = IoAllocateWorkItem(DeviceObject);
|
||||||
|
if (!Ctx->WorkItem)
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to allocate work item\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ctx->Irp = Irp;
|
||||||
|
Ctx->Pin = (PVOID)This;
|
||||||
|
|
||||||
|
IoMarkIrpPending(Irp);
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Irp->IoStatus.Status = STATUS_PENDING;
|
||||||
|
|
||||||
|
/* defer work item */
|
||||||
|
IoQueueWorkItem(Ctx->WorkItem, CloseStreamRoutine, DelayedWorkQueue, (PVOID)Ctx);
|
||||||
|
/* Return result */
|
||||||
|
return STATUS_PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
|
if (Ctx)
|
||||||
|
FreeItem(Ctx, TAG_PORTCLASS);
|
||||||
|
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IPortPinDMus_fnQuerySecurity(
|
||||||
|
IN IPortPinDMus* iface,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IPortPinDMus_fnSetSecurity(
|
||||||
|
IN IPortPinDMus* iface,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
IPortPinDMus_fnFastDeviceIoControl(
|
||||||
|
IN IPortPinDMus* iface,
|
||||||
|
IN PFILE_OBJECT FileObject,
|
||||||
|
IN BOOLEAN Wait,
|
||||||
|
IN PVOID InputBuffer,
|
||||||
|
IN ULONG InputBufferLength,
|
||||||
|
OUT PVOID OutputBuffer,
|
||||||
|
IN ULONG OutputBufferLength,
|
||||||
|
IN ULONG IoControlCode,
|
||||||
|
OUT PIO_STATUS_BLOCK StatusBlock,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
IPortPinDMus_fnFastRead(
|
||||||
|
IN IPortPinDMus* iface,
|
||||||
|
IN PFILE_OBJECT FileObject,
|
||||||
|
IN PLARGE_INTEGER FileOffset,
|
||||||
|
IN ULONG Length,
|
||||||
|
IN BOOLEAN Wait,
|
||||||
|
IN ULONG LockKey,
|
||||||
|
IN PVOID Buffer,
|
||||||
|
OUT PIO_STATUS_BLOCK StatusBlock,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PCONTEXT_WRITE Packet;
|
||||||
|
PIRP Irp;
|
||||||
|
IPortPinDMusImpl * This = (IPortPinDMusImpl*)iface;
|
||||||
|
|
||||||
|
DPRINT("IPortPinDMus_fnFastRead entered\n");
|
||||||
|
|
||||||
|
Packet = (PCONTEXT_WRITE)Buffer;
|
||||||
|
|
||||||
|
Irp = Packet->Irp;
|
||||||
|
StatusBlock->Status = STATUS_PENDING;
|
||||||
|
|
||||||
|
Status = This->IrpQueue->lpVtbl->AddMapping(This->IrpQueue, Buffer, Length, Irp);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue) == TRUE && This->State != KSSTATE_RUN)
|
||||||
|
{
|
||||||
|
/* some should initiate a state request but didnt do it */
|
||||||
|
DPRINT1("Starting stream with %lu mappings\n", This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue));
|
||||||
|
SetStreamState(This, KSSTATE_RUN);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
IPortPinDMus_fnFastWrite(
|
||||||
|
IN IPortPinDMus* iface,
|
||||||
|
IN PFILE_OBJECT FileObject,
|
||||||
|
IN PLARGE_INTEGER FileOffset,
|
||||||
|
IN ULONG Length,
|
||||||
|
IN BOOLEAN Wait,
|
||||||
|
IN ULONG LockKey,
|
||||||
|
IN PVOID Buffer,
|
||||||
|
OUT PIO_STATUS_BLOCK StatusBlock,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PCONTEXT_WRITE Packet;
|
||||||
|
PIRP Irp;
|
||||||
|
IPortPinDMusImpl * This = (IPortPinDMusImpl*)iface;
|
||||||
|
|
||||||
|
InterlockedIncrement((PLONG)&This->TotalPackets);
|
||||||
|
|
||||||
|
DPRINT("IPortPinDMus_fnFastWrite entered Total %u Pre %u Post %u\n", This->TotalPackets, This->PreCompleted, This->PostCompleted);
|
||||||
|
|
||||||
|
Packet = (PCONTEXT_WRITE)Buffer;
|
||||||
|
|
||||||
|
|
||||||
|
if (This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue))
|
||||||
|
{
|
||||||
|
Irp = Packet->Irp;
|
||||||
|
StatusBlock->Status = STATUS_PENDING;
|
||||||
|
InterlockedIncrement((PLONG)&This->PostCompleted);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Irp = NULL;
|
||||||
|
Packet->Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
Packet->Irp->IoStatus.Information = Packet->Header.FrameExtent;
|
||||||
|
IoCompleteRequest(Packet->Irp, IO_SOUND_INCREMENT);
|
||||||
|
StatusBlock->Status = STATUS_SUCCESS;
|
||||||
|
InterlockedIncrement((PLONG)&This->PreCompleted);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = This->IrpQueue->lpVtbl->AddMapping(This->IrpQueue, Buffer, Length, Irp);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (This->IrpQueue->lpVtbl->MinimumDataAvailable(This->IrpQueue) == TRUE && This->State != KSSTATE_RUN)
|
||||||
|
{
|
||||||
|
SetStreamState(This, KSSTATE_RUN);
|
||||||
|
/* some should initiate a state request but didnt do it */
|
||||||
|
DPRINT1("Starting stream with %lu mappings Status %x\n", This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue), Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @unimplemented
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IPortPinDMus_fnInit(
|
||||||
|
IN IPortPinDMus* iface,
|
||||||
|
IN PPORTDMUS Port,
|
||||||
|
IN PPORTFILTERDMUS Filter,
|
||||||
|
IN KSPIN_CONNECT * ConnectDetails,
|
||||||
|
IN KSPIN_DESCRIPTOR * KsPinDescriptor,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PKSDATAFORMAT DataFormat;
|
||||||
|
BOOL Capture;
|
||||||
|
|
||||||
|
IPortPinDMusImpl * This = (IPortPinDMusImpl*)iface;
|
||||||
|
|
||||||
|
Port->lpVtbl->AddRef(Port);
|
||||||
|
Filter->lpVtbl->AddRef(Filter);
|
||||||
|
|
||||||
|
This->Port = Port;
|
||||||
|
This->Filter = Filter;
|
||||||
|
This->KsPinDescriptor = KsPinDescriptor;
|
||||||
|
This->ConnectDetails = ConnectDetails;
|
||||||
|
This->DeviceObject = DeviceObject;
|
||||||
|
GetDMusMiniport(Port, &This->Miniport, &This->MidiMiniport);
|
||||||
|
|
||||||
|
DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
|
||||||
|
|
||||||
|
DPRINT("IPortPinDMus_fnInit entered\n");
|
||||||
|
|
||||||
|
This->Format = ExAllocatePoolWithTag(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
|
||||||
|
if (!This->Format)
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
|
RtlMoveMemory(This->Format, DataFormat, DataFormat->FormatSize);
|
||||||
|
|
||||||
|
if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
|
||||||
|
{
|
||||||
|
Capture = FALSE;
|
||||||
|
}
|
||||||
|
else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
|
||||||
|
{
|
||||||
|
Capture = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DPRINT1("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
|
||||||
|
KeBugCheck(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = NewIrpQueue(&This->IrpQueue);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to allocate IrpQueue with %x\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (This->MidiMiniport)
|
||||||
|
{
|
||||||
|
Status = This->MidiMiniport->lpVtbl->NewStream(This->MidiMiniport,
|
||||||
|
&This->MidiStream,
|
||||||
|
NULL,
|
||||||
|
NonPagedPool,
|
||||||
|
ConnectDetails->PinId,
|
||||||
|
Capture,
|
||||||
|
This->Format,
|
||||||
|
&This->ServiceGroup);
|
||||||
|
|
||||||
|
DPRINT("IPortPinDMus_fnInit Status %x\n", Status);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (This->ServiceGroup)
|
||||||
|
{
|
||||||
|
Status = This->ServiceGroup->lpVtbl->AddMember(This->ServiceGroup,
|
||||||
|
(PSERVICESINK)&This->lpVtblServiceSink);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Failed to add pin to service group\n");
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
This->ServiceGroup->lpVtbl->SupportDelayedService(This->ServiceGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails, This->Format, DeviceObject, 0);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("IrpQueue_Init failed with %x\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
This->State = KSSTATE_STOP;
|
||||||
|
This->Capture = Capture;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @implemented
|
||||||
|
*/
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
IPortPinDMus_fnNotify(
|
||||||
|
IN IPortPinDMus* iface)
|
||||||
|
{
|
||||||
|
IPortPinDMusImpl * This = (IPortPinDMusImpl*)iface;
|
||||||
|
|
||||||
|
This->ServiceGroup->lpVtbl->RequestService(This->ServiceGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
static IPortPinDMusVtbl vt_IPortPinDMus =
|
||||||
|
{
|
||||||
|
IPortPinDMus_fnQueryInterface,
|
||||||
|
IPortPinDMus_fnAddRef,
|
||||||
|
IPortPinDMus_fnRelease,
|
||||||
|
IPortPinDMus_fnNewIrpTarget,
|
||||||
|
IPortPinDMus_fnDeviceIoControl,
|
||||||
|
IPortPinDMus_fnRead,
|
||||||
|
IPortPinDMus_fnWrite,
|
||||||
|
IPortPinDMus_fnFlush,
|
||||||
|
IPortPinDMus_fnClose,
|
||||||
|
IPortPinDMus_fnQuerySecurity,
|
||||||
|
IPortPinDMus_fnSetSecurity,
|
||||||
|
IPortPinDMus_fnFastDeviceIoControl,
|
||||||
|
IPortPinDMus_fnFastRead,
|
||||||
|
IPortPinDMus_fnFastWrite,
|
||||||
|
IPortPinDMus_fnInit,
|
||||||
|
IPortPinDMus_fnNotify
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS NewPortPinDMus(
|
||||||
|
OUT IPortPinDMus ** OutPin)
|
||||||
|
{
|
||||||
|
IPortPinDMusImpl * This;
|
||||||
|
|
||||||
|
This = AllocateItem(NonPagedPool, sizeof(IPortPinDMusImpl), TAG_PORTCLASS);
|
||||||
|
if (!This)
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
|
/* initialize IPortPinDMus */
|
||||||
|
This->ref = 1;
|
||||||
|
This->lpVtbl = &vt_IPortPinDMus;
|
||||||
|
This->lpVtblServiceSink = &vt_IServiceSink;
|
||||||
|
|
||||||
|
|
||||||
|
/* store result */
|
||||||
|
*OutPin = (IPortPinDMus*)&This->lpVtbl;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ PcNewPort(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsEqualGUIDAligned(ClassId, &CLSID_PortMidi))
|
if (IsEqualGUIDAligned(ClassId, &CLSID_PortMidi))
|
||||||
Status = NewPortMidi(OutPort);
|
Status = NewPortDMus(OutPort);
|
||||||
else if (IsEqualGUIDAligned(ClassId, &CLSID_PortDMus))
|
else if (IsEqualGUIDAligned(ClassId, &CLSID_PortDMus))
|
||||||
Status = NewPortDMus(OutPort);
|
Status = NewPortDMus(OutPort);
|
||||||
else if (IsEqualGUIDAligned(ClassId, &CLSID_PortTopology))
|
else if (IsEqualGUIDAligned(ClassId, &CLSID_PortTopology))
|
||||||
|
|
|
@ -11,16 +11,39 @@
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
IPortDMusVtbl *lpVtbl;
|
IPortDMusVtbl *lpVtbl;
|
||||||
|
IServiceSinkVtbl *lpVtblServiceSink;
|
||||||
|
ISubdeviceVtbl *lpVtblSubDevice;
|
||||||
|
|
||||||
LONG ref;
|
LONG ref;
|
||||||
BOOL bInitialized;
|
BOOL bInitialized;
|
||||||
IMiniportDMus *pMiniport;
|
IMiniportDMus *pMiniport;
|
||||||
|
IMiniportMidi *pMiniportMidi;
|
||||||
DEVICE_OBJECT *pDeviceObject;
|
DEVICE_OBJECT *pDeviceObject;
|
||||||
PSERVICEGROUP ServiceGroup;
|
PSERVICEGROUP ServiceGroup;
|
||||||
|
PPINCOUNT pPinCount;
|
||||||
|
PPOWERNOTIFY pPowerNotify;
|
||||||
|
PPORTFILTERDMUS Filter;
|
||||||
|
|
||||||
|
PPCFILTER_DESCRIPTOR pDescriptor;
|
||||||
|
PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor;
|
||||||
|
|
||||||
}IPortDMusImpl;
|
}IPortDMusImpl;
|
||||||
|
|
||||||
const GUID IID_IPortDMus;
|
static GUID InterfaceGuids[3] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
/// KS_CATEGORY_AUDIO
|
||||||
|
0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// KS_CATEGORY_RENDER
|
||||||
|
0x65E8773E, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
/// KS_CATEGORY_CAPTURE
|
||||||
|
0x65E8773D, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// IUnknown interface functions
|
// IUnknown interface functions
|
||||||
|
@ -33,19 +56,39 @@ IPortDMus_fnQueryInterface(
|
||||||
IN REFIID refiid,
|
IN REFIID refiid,
|
||||||
OUT PVOID* Output)
|
OUT PVOID* Output)
|
||||||
{
|
{
|
||||||
|
UNICODE_STRING GuidString;
|
||||||
IPortDMusImpl * This = (IPortDMusImpl*)iface;
|
IPortDMusImpl * This = (IPortDMusImpl*)iface;
|
||||||
|
|
||||||
|
|
||||||
if (IsEqualGUIDAligned(refiid, &IID_IPortDMus) ||
|
if (IsEqualGUIDAligned(refiid, &IID_IPortDMus) ||
|
||||||
|
IsEqualGUIDAligned(refiid, &IID_IPortMidi) ||
|
||||||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
|
IsEqualGUIDAligned(refiid, &IID_IUnknown))
|
||||||
{
|
{
|
||||||
*Output = &This->lpVtbl;
|
*Output = &This->lpVtbl;
|
||||||
_InterlockedIncrement(&This->ref);
|
InterlockedIncrement(&This->ref);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
else if (IsEqualGUIDAligned(refiid, &IID_ISubdevice))
|
||||||
|
{
|
||||||
|
*Output = &This->lpVtblSubDevice;
|
||||||
|
InterlockedIncrement(&This->ref);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else if (IsEqualGUIDAligned(refiid, &IID_IDrmPort) ||
|
||||||
|
IsEqualGUIDAligned(refiid, &IID_IDrmPort2))
|
||||||
|
{
|
||||||
|
return NewIDrmPort((PDRMPORT2*)Output);
|
||||||
|
}
|
||||||
else if (IsEqualGUIDAligned(refiid, &IID_IPortClsVersion))
|
else if (IsEqualGUIDAligned(refiid, &IID_IPortClsVersion))
|
||||||
{
|
{
|
||||||
return NewPortClsVersion((PPORTCLSVERSION*)Output);
|
return NewPortClsVersion((PPORTCLSVERSION*)Output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
DPRINT1("IPortMidi_fnQueryInterface no interface!!! iface %S\n", GuidString.Buffer);
|
||||||
|
RtlFreeUnicodeString(&GuidString);
|
||||||
|
}
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,8 +161,12 @@ IPortDMus_fnInit(
|
||||||
IN PUNKNOWN UnknownAdapter OPTIONAL,
|
IN PUNKNOWN UnknownAdapter OPTIONAL,
|
||||||
IN PRESOURCELIST ResourceList)
|
IN PRESOURCELIST ResourceList)
|
||||||
{
|
{
|
||||||
IMiniportDMus * Miniport;
|
IMiniportDMus * Miniport = NULL;
|
||||||
|
IMiniportMidi * MidiMiniport = NULL;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
PSERVICEGROUP ServiceGroup;
|
||||||
|
PPINCOUNT PinCount;
|
||||||
|
PPOWERNOTIFY PowerNotify;
|
||||||
IPortDMusImpl * This = (IPortDMusImpl*)iface;
|
IPortDMusImpl * This = (IPortDMusImpl*)iface;
|
||||||
|
|
||||||
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
|
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
|
||||||
|
@ -133,25 +180,111 @@ IPortDMus_fnInit(
|
||||||
Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IMiniportDMus, (PVOID*)&Miniport);
|
Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IMiniportDMus, (PVOID*)&Miniport);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT("IPortDMus_Init called with invalid IMiniport adapter\n");
|
/* check for legacy interface */
|
||||||
return STATUS_INVALID_PARAMETER;
|
Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IMiniportMidi, (PVOID*)&MidiMiniport);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("IPortDMus_Init called with invalid IMiniport adapter\n");
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = Miniport->lpVtbl->Init(Miniport, UnknownAdapter, ResourceList, iface, &This->ServiceGroup);
|
if (Miniport)
|
||||||
|
{
|
||||||
|
/* initialize IMiniportDMus */
|
||||||
|
Status = Miniport->lpVtbl->Init(Miniport, UnknownAdapter, ResourceList, iface, &ServiceGroup);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("IMiniportDMus_Init failed with %x\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the miniport device descriptor */
|
||||||
|
Status = Miniport->lpVtbl->GetDescription(Miniport, &This->pDescriptor);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("failed to get description\n");
|
||||||
|
Miniport->lpVtbl->Release(Miniport);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* initialize IMiniportMidi */
|
||||||
|
Status = MidiMiniport->lpVtbl->Init(MidiMiniport, UnknownAdapter, ResourceList, (IPortMidi*)iface, &ServiceGroup);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT("IMiniportMidi_Init failed with %x\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the miniport device descriptor */
|
||||||
|
Status = MidiMiniport->lpVtbl->GetDescription(MidiMiniport, &This->pDescriptor);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("failed to get description\n");
|
||||||
|
MidiMiniport->lpVtbl->Release(MidiMiniport);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create the subdevice descriptor */
|
||||||
|
Status = PcCreateSubdeviceDescriptor(&This->SubDeviceDescriptor,
|
||||||
|
3,
|
||||||
|
InterfaceGuids,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
This->pDescriptor);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
DPRINT("IMinIPortDMus_Init failed with %x\n", Status);
|
DPRINT1("Failed to create descriptior\n");
|
||||||
|
|
||||||
|
if (Miniport)
|
||||||
|
Miniport->lpVtbl->Release(Miniport);
|
||||||
|
else
|
||||||
|
MidiMiniport->lpVtbl->Release(MidiMiniport);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASSERT(This->ServiceGroup);
|
||||||
|
ASSERT(ServiceGroup == This->ServiceGroup);
|
||||||
|
|
||||||
/* Initialize port object */
|
/* Initialize port object */
|
||||||
This->pMiniport = Miniport;
|
This->pMiniport = Miniport;
|
||||||
|
This->pMiniportMidi = MidiMiniport;
|
||||||
This->pDeviceObject = DeviceObject;
|
This->pDeviceObject = DeviceObject;
|
||||||
This->bInitialized = TRUE;
|
This->bInitialized = TRUE;
|
||||||
|
|
||||||
/* increment reference on miniport adapter */
|
/* increment reference on miniport adapter */
|
||||||
Miniport->lpVtbl->AddRef(Miniport);
|
Miniport->lpVtbl->AddRef(Miniport);
|
||||||
|
|
||||||
|
|
||||||
|
/* check if it supports IPinCount interface */
|
||||||
|
Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IPinCount, (PVOID*)&PinCount);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* store IPinCount interface */
|
||||||
|
This->pPinCount = PinCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* does the Miniport adapter support IPowerNotify interface*/
|
||||||
|
Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IPowerNotify, (PVOID*)&PowerNotify);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
/* store reference */
|
||||||
|
This->pPowerNotify = PowerNotify;
|
||||||
|
}
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,11 +313,339 @@ IPortDMus_fnNewRegistryKey(
|
||||||
return STATUS_UNSUCCESSFUL;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
IPortDMus_fnNotify(
|
||||||
|
IN IPortDMus * iface,
|
||||||
|
IN PSERVICEGROUP ServiceGroup OPTIONAL)
|
||||||
|
{
|
||||||
|
IPortDMusImpl * This = (IPortDMusImpl*)iface;
|
||||||
|
|
||||||
|
if (ServiceGroup)
|
||||||
|
{
|
||||||
|
ServiceGroup->lpVtbl->RequestService (ServiceGroup);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(This->ServiceGroup);
|
||||||
|
|
||||||
|
/* notify miniport service group */
|
||||||
|
This->ServiceGroup->lpVtbl->RequestService(This->ServiceGroup);
|
||||||
|
|
||||||
|
/* notify stream miniport service group */
|
||||||
|
if (This->Filter)
|
||||||
|
{
|
||||||
|
This->Filter->lpVtbl->NotifyPins(This->Filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
IPortDMus_fnRegisterServiceGroup(
|
||||||
|
IN IPortDMus * iface,
|
||||||
|
IN PSERVICEGROUP ServiceGroup)
|
||||||
|
{
|
||||||
|
IPortDMusImpl * This = (IPortDMusImpl*)iface;
|
||||||
|
|
||||||
|
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
|
||||||
|
|
||||||
|
This->ServiceGroup = ServiceGroup;
|
||||||
|
|
||||||
|
ServiceGroup->lpVtbl->AddRef(ServiceGroup);
|
||||||
|
ServiceGroup->lpVtbl->AddMember(ServiceGroup, (PSERVICESINK)&This->lpVtblServiceSink);
|
||||||
|
}
|
||||||
|
|
||||||
|
static IPortDMusVtbl vt_IPortDMus =
|
||||||
|
{
|
||||||
|
/* IUnknown methods */
|
||||||
|
IPortDMus_fnQueryInterface,
|
||||||
|
IPortDMus_fnAddRef,
|
||||||
|
IPortDMus_fnRelease,
|
||||||
|
/* IPort methods */
|
||||||
|
IPortDMus_fnInit,
|
||||||
|
IPortDMus_fnGetDeviceProperty,
|
||||||
|
IPortDMus_fnNewRegistryKey,
|
||||||
|
IPortDMus_fnNotify,
|
||||||
|
IPortDMus_fnRegisterServiceGroup
|
||||||
|
};
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// ISubdevice interface
|
||||||
|
//
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
ISubDevice_fnQueryInterface(
|
||||||
|
IN ISubdevice *iface,
|
||||||
|
IN REFIID InterfaceId,
|
||||||
|
IN PVOID* Interface)
|
||||||
|
{
|
||||||
|
IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblSubDevice);
|
||||||
|
|
||||||
|
return IPortDMus_fnQueryInterface((IPortDMus*)This, InterfaceId, Interface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
ISubDevice_fnAddRef(
|
||||||
|
IN ISubdevice *iface)
|
||||||
|
{
|
||||||
|
IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblSubDevice);
|
||||||
|
|
||||||
|
return IPortDMus_fnAddRef((IPortDMus*)This);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
ISubDevice_fnRelease(
|
||||||
|
IN ISubdevice *iface)
|
||||||
|
{
|
||||||
|
IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblSubDevice);
|
||||||
|
|
||||||
|
return IPortDMus_fnRelease((IPortDMus*)This);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
ISubDevice_fnNewIrpTarget(
|
||||||
|
IN ISubdevice *iface,
|
||||||
|
OUT struct IIrpTarget **OutTarget,
|
||||||
|
IN WCHAR * Name,
|
||||||
|
IN PUNKNOWN Unknown,
|
||||||
|
IN POOL_TYPE PoolType,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN KSOBJECT_CREATE *CreateObject)
|
||||||
|
{
|
||||||
|
NTSTATUS Status;
|
||||||
|
PPORTFILTERDMUS Filter;
|
||||||
|
IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblSubDevice);
|
||||||
|
|
||||||
|
DPRINT("ISubDevice_NewIrpTarget this %p\n", This);
|
||||||
|
|
||||||
|
if (This->Filter)
|
||||||
|
{
|
||||||
|
*OutTarget = (IIrpTarget*)This->Filter;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Status = NewPortFilterDMus(&Filter);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = Filter->lpVtbl->Init(Filter, (PPORTDMUS)This);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
Filter->lpVtbl->Release(Filter);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
*OutTarget = (IIrpTarget*)Filter;
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
ISubDevice_fnReleaseChildren(
|
||||||
|
IN ISubdevice *iface)
|
||||||
|
{
|
||||||
|
//IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblSubDevice);
|
||||||
|
|
||||||
|
UNIMPLEMENTED
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
ISubDevice_fnGetDescriptor(
|
||||||
|
IN ISubdevice *iface,
|
||||||
|
IN SUBDEVICE_DESCRIPTOR ** Descriptor)
|
||||||
|
{
|
||||||
|
IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblSubDevice);
|
||||||
|
|
||||||
|
DPRINT("ISubDevice_GetDescriptor this %p\n", This);
|
||||||
|
*Descriptor = This->SubDeviceDescriptor;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
ISubDevice_fnDataRangeIntersection(
|
||||||
|
IN ISubdevice *iface,
|
||||||
|
IN ULONG PinId,
|
||||||
|
IN PKSDATARANGE DataRange,
|
||||||
|
IN PKSDATARANGE MatchingDataRange,
|
||||||
|
IN ULONG OutputBufferLength,
|
||||||
|
OUT PVOID ResultantFormat OPTIONAL,
|
||||||
|
OUT PULONG ResultantFormatLength)
|
||||||
|
{
|
||||||
|
IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblSubDevice);
|
||||||
|
|
||||||
|
DPRINT("ISubDevice_DataRangeIntersection this %p\n", This);
|
||||||
|
|
||||||
|
if (This->pMiniport)
|
||||||
|
{
|
||||||
|
return This->pMiniport->lpVtbl->DataRangeIntersection (This->pMiniport, PinId, DataRange, MatchingDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
ISubDevice_fnPowerChangeNotify(
|
||||||
|
IN ISubdevice *iface,
|
||||||
|
IN POWER_STATE PowerState)
|
||||||
|
{
|
||||||
|
IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblSubDevice);
|
||||||
|
|
||||||
|
if (This->pPowerNotify)
|
||||||
|
{
|
||||||
|
This->pPowerNotify->lpVtbl->PowerChangeNotify(This->pPowerNotify, PowerState);
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
ISubDevice_fnPinCount(
|
||||||
|
IN ISubdevice *iface,
|
||||||
|
IN ULONG PinId,
|
||||||
|
IN OUT PULONG FilterNecessary,
|
||||||
|
IN OUT PULONG FilterCurrent,
|
||||||
|
IN OUT PULONG FilterPossible,
|
||||||
|
IN OUT PULONG GlobalCurrent,
|
||||||
|
IN OUT PULONG GlobalPossible)
|
||||||
|
{
|
||||||
|
IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblSubDevice);
|
||||||
|
|
||||||
|
if (This->pPinCount)
|
||||||
|
{
|
||||||
|
This->pPinCount->lpVtbl->PinCount(This->pPinCount, PinId, FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME
|
||||||
|
* scan filter descriptor
|
||||||
|
*/
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ISubdeviceVtbl vt_ISubdevice =
|
||||||
|
{
|
||||||
|
ISubDevice_fnQueryInterface,
|
||||||
|
ISubDevice_fnAddRef,
|
||||||
|
ISubDevice_fnRelease,
|
||||||
|
ISubDevice_fnNewIrpTarget,
|
||||||
|
ISubDevice_fnReleaseChildren,
|
||||||
|
ISubDevice_fnGetDescriptor,
|
||||||
|
ISubDevice_fnDataRangeIntersection,
|
||||||
|
ISubDevice_fnPowerChangeNotify,
|
||||||
|
ISubDevice_fnPinCount
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
IServiceSink_fnQueryInterface(
|
||||||
|
IServiceSink* iface,
|
||||||
|
IN REFIID refiid,
|
||||||
|
OUT PVOID* Output)
|
||||||
|
{
|
||||||
|
IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblServiceSink);
|
||||||
|
|
||||||
|
if (IsEqualGUIDAligned(refiid, &IID_IServiceSink) ||
|
||||||
|
IsEqualGUIDAligned(refiid, &IID_IUnknown))
|
||||||
|
{
|
||||||
|
*Output = &This->lpVtblServiceSink;
|
||||||
|
InterlockedIncrement(&This->ref);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DPRINT("Unknown interface requested\n");
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
IServiceSink_fnAddRef(
|
||||||
|
IServiceSink* iface)
|
||||||
|
{
|
||||||
|
IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblServiceSink);
|
||||||
|
return IPortDMus_fnAddRef((IPortDMus*)This);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
ULONG
|
||||||
|
NTAPI
|
||||||
|
IServiceSink_fnRelease(
|
||||||
|
IServiceSink* iface)
|
||||||
|
{
|
||||||
|
IPortDMusImpl * This = (IPortDMusImpl*)CONTAINING_RECORD(iface, IPortDMusImpl, lpVtblServiceSink);
|
||||||
|
return IPortDMus_fnRelease((IPortDMus*)This);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
IServiceSink_fnRequestService(
|
||||||
|
IServiceSink* iface)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED
|
||||||
|
}
|
||||||
|
|
||||||
|
static IServiceSinkVtbl vt_IServiceSink =
|
||||||
|
{
|
||||||
|
IServiceSink_fnQueryInterface,
|
||||||
|
IServiceSink_fnAddRef,
|
||||||
|
IServiceSink_fnRelease,
|
||||||
|
IServiceSink_fnRequestService
|
||||||
|
};
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NewPortDMus(
|
NewPortDMus(
|
||||||
OUT PPORT* OutPort)
|
OUT PPORT* OutPort)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
IPortDMusImpl * This = AllocateItem(NonPagedPool, sizeof(IPortDMusImpl), TAG_PORTCLASS);
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
|
if (!This)
|
||||||
|
{
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
This->ref = 1;
|
||||||
|
This->lpVtbl = &vt_IPortDMus;
|
||||||
|
This->lpVtblServiceSink = &vt_IServiceSink;
|
||||||
|
This->lpVtblSubDevice = &vt_ISubdevice;
|
||||||
|
|
||||||
|
*OutPort = (PPORT)&This->lpVtbl;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
GetDMusMiniport(
|
||||||
|
IN IPortDMus * iface,
|
||||||
|
IN PMINIPORTDMUS * Miniport,
|
||||||
|
IN PMINIPORTMIDI * MidiMiniport)
|
||||||
|
{
|
||||||
|
IPortDMusImpl * This = (IPortDMusImpl*)iface;
|
||||||
|
|
||||||
|
*Miniport = This->pMiniport;
|
||||||
|
*MidiMiniport = This->pMiniportMidi;
|
||||||
|
}
|
||||||
|
|
|
@ -1,481 +0,0 @@
|
||||||
/*
|
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
|
||||||
* PROJECT: ReactOS Kernel Streaming
|
|
||||||
* FILE: drivers/wdm/audio/backpln/portcls/port_midi.c
|
|
||||||
* PURPOSE: Midi Port driver
|
|
||||||
* PROGRAMMER: Johannes Anderwald
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "private.h"
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
IPortMidiVtbl *lpVtbl;
|
|
||||||
ISubdeviceVtbl *lpVtblSubDevice;
|
|
||||||
|
|
||||||
LONG ref;
|
|
||||||
BOOL bInitialized;
|
|
||||||
|
|
||||||
PMINIPORTMIDI pMiniport;
|
|
||||||
PDEVICE_OBJECT pDeviceObject;
|
|
||||||
PPINCOUNT pPinCount;
|
|
||||||
PPOWERNOTIFY pPowerNotify;
|
|
||||||
PSERVICEGROUP pServiceGroup;
|
|
||||||
|
|
||||||
PPCFILTER_DESCRIPTOR pDescriptor;
|
|
||||||
PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor;
|
|
||||||
}IPortMidiImpl;
|
|
||||||
|
|
||||||
static GUID InterfaceGuids[3] =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
/// KS_CATEGORY_AUDIO
|
|
||||||
0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
/// KS_CATEGORY_RENDER
|
|
||||||
0x65E8773E, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
/// KS_CATEGORY_CAPTURE
|
|
||||||
0x65E8773D, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
|
||||||
// IUnknown interface functions
|
|
||||||
//
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
IPortMidi_fnQueryInterface(
|
|
||||||
IPortMidi* iface,
|
|
||||||
IN REFIID refiid,
|
|
||||||
OUT PVOID* Output)
|
|
||||||
{
|
|
||||||
UNICODE_STRING GuidString;
|
|
||||||
IPortMidiImpl * This = (IPortMidiImpl*)iface;
|
|
||||||
|
|
||||||
DPRINT("IPortMidi_fnQueryInterface\n");
|
|
||||||
|
|
||||||
if (IsEqualGUIDAligned(refiid, &IID_IPortMidi) ||
|
|
||||||
IsEqualGUIDAligned(refiid, &IID_IPort) ||
|
|
||||||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
|
|
||||||
{
|
|
||||||
*Output = &This->lpVtbl;
|
|
||||||
InterlockedIncrement(&This->ref);
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
else if (IsEqualGUIDAligned(refiid, &IID_ISubdevice))
|
|
||||||
{
|
|
||||||
*Output = &This->lpVtblSubDevice;
|
|
||||||
InterlockedIncrement(&This->ref);
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
else if (IsEqualGUIDAligned(refiid, &IID_IPortClsVersion))
|
|
||||||
{
|
|
||||||
return NewPortClsVersion((PPORTCLSVERSION*)Output);
|
|
||||||
}
|
|
||||||
else if (IsEqualGUIDAligned(refiid, &IID_IDrmPort) ||
|
|
||||||
IsEqualGUIDAligned(refiid, &IID_IDrmPort2))
|
|
||||||
{
|
|
||||||
return NewIDrmPort((PDRMPORT2*)Output);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RtlStringFromGUID(refiid, &GuidString) == STATUS_SUCCESS)
|
|
||||||
{
|
|
||||||
DPRINT1("IPortMidi_fnQueryInterface no interface!!! iface %S\n", GuidString.Buffer);
|
|
||||||
RtlFreeUnicodeString(&GuidString);
|
|
||||||
}
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG
|
|
||||||
NTAPI
|
|
||||||
IPortMidi_fnAddRef(
|
|
||||||
IPortMidi* iface)
|
|
||||||
{
|
|
||||||
IPortMidiImpl * This = (IPortMidiImpl*)iface;
|
|
||||||
|
|
||||||
return InterlockedIncrement(&This->ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
ULONG
|
|
||||||
NTAPI
|
|
||||||
IPortMidi_fnRelease(
|
|
||||||
IPortMidi* iface)
|
|
||||||
{
|
|
||||||
IPortMidiImpl * This = (IPortMidiImpl*)iface;
|
|
||||||
|
|
||||||
InterlockedDecrement(&This->ref);
|
|
||||||
|
|
||||||
if (This->ref == 0)
|
|
||||||
{
|
|
||||||
FreeItem(This, TAG_PORTCLASS);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* Return new reference count */
|
|
||||||
return This->ref;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
|
||||||
// IPort interface functions
|
|
||||||
//
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
IPortMidi_fnGetDeviceProperty(
|
|
||||||
IN IPortMidi * iface,
|
|
||||||
IN DEVICE_REGISTRY_PROPERTY DeviceRegistryProperty,
|
|
||||||
IN ULONG BufferLength,
|
|
||||||
OUT PVOID PropertyBuffer,
|
|
||||||
OUT PULONG ReturnLength)
|
|
||||||
{
|
|
||||||
IPortMidiImpl * This = (IPortMidiImpl*)iface;
|
|
||||||
|
|
||||||
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
|
|
||||||
|
|
||||||
if (!This->bInitialized)
|
|
||||||
{
|
|
||||||
DPRINT("IPortMidi_fnNewRegistryKey called w/o initiazed\n");
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return IoGetDeviceProperty(This->pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
IPortMidi_fnInit(
|
|
||||||
IN IPortMidi * iface,
|
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
|
||||||
IN PIRP Irp,
|
|
||||||
IN PUNKNOWN UnknownMiniport,
|
|
||||||
IN PUNKNOWN UnknownAdapter OPTIONAL,
|
|
||||||
IN PRESOURCELIST ResourceList)
|
|
||||||
{
|
|
||||||
IMiniportMidi * Miniport;
|
|
||||||
IServiceGroup * ServiceGroup = NULL;
|
|
||||||
NTSTATUS Status;
|
|
||||||
IPortMidiImpl * This = (IPortMidiImpl*)iface;
|
|
||||||
|
|
||||||
DPRINT("IPortMidi_fnInit entered This %p DeviceObject %p Irp %p UnknownMiniport %p UnknownAdapter %p ResourceList %p\n",
|
|
||||||
This, DeviceObject, Irp, UnknownMiniport, UnknownAdapter, ResourceList);
|
|
||||||
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
|
|
||||||
|
|
||||||
if (This->bInitialized)
|
|
||||||
{
|
|
||||||
DPRINT1("IPortMidi_Init called again\n");
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IMiniportMidi, (PVOID*)&Miniport);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("IPortMidi_Init called with invalid IMiniport adapter\n");
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize port object */
|
|
||||||
This->pMiniport = Miniport;
|
|
||||||
This->pDeviceObject = DeviceObject;
|
|
||||||
This->bInitialized = TRUE;
|
|
||||||
|
|
||||||
/* increment reference on miniport adapter */
|
|
||||||
Miniport->lpVtbl->AddRef(Miniport);
|
|
||||||
|
|
||||||
Status = Miniport->lpVtbl->Init(Miniport, UnknownAdapter, ResourceList, iface, &ServiceGroup);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("IPortMidi_Init failed with %x\n", Status);
|
|
||||||
This->bInitialized = FALSE;
|
|
||||||
Miniport->lpVtbl->Release(Miniport);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get the miniport device descriptor */
|
|
||||||
Status = Miniport->lpVtbl->GetDescription(Miniport, &This->pDescriptor);
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
DPRINT1("failed to get description\n");
|
|
||||||
Miniport->lpVtbl->Release(Miniport);
|
|
||||||
This->bInitialized = FALSE;
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
This->pServiceGroup = ServiceGroup;
|
|
||||||
|
|
||||||
/* create the subdevice descriptor */
|
|
||||||
Status = PcCreateSubdeviceDescriptor(&This->SubDeviceDescriptor,
|
|
||||||
3,
|
|
||||||
InterfaceGuids,
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
This->pDescriptor);
|
|
||||||
|
|
||||||
|
|
||||||
DPRINT("IPortMidi_fnInit success\n");
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
IPortMidi_fnNewRegistryKey(
|
|
||||||
IN IPortMidi * iface,
|
|
||||||
OUT PREGISTRYKEY *OutRegistryKey,
|
|
||||||
IN PUNKNOWN OuterUnknown OPTIONAL,
|
|
||||||
IN ULONG RegistryKeyType,
|
|
||||||
IN ACCESS_MASK DesiredAccess,
|
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
|
|
||||||
IN ULONG CreateOptions OPTIONAL,
|
|
||||||
OUT PULONG Disposition OPTIONAL)
|
|
||||||
{
|
|
||||||
IPortMidiImpl * This = (IPortMidiImpl*)iface;
|
|
||||||
|
|
||||||
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
|
|
||||||
|
|
||||||
if (!This->bInitialized)
|
|
||||||
{
|
|
||||||
DPRINT("IPortMidi_fnNewRegistryKey called w/o initialized\n");
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
return PcNewRegistryKey(OutRegistryKey,
|
|
||||||
OuterUnknown,
|
|
||||||
RegistryKeyType,
|
|
||||||
DesiredAccess,
|
|
||||||
This->pDeviceObject,
|
|
||||||
NULL,//FIXME
|
|
||||||
ObjectAttributes,
|
|
||||||
CreateOptions,
|
|
||||||
Disposition);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
VOID
|
|
||||||
NTAPI
|
|
||||||
IPortMidi_fnNotify(
|
|
||||||
IN IPortMidi * iface,
|
|
||||||
IN PSERVICEGROUP ServiceGroup OPTIONAL)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED
|
|
||||||
}
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
IPortMidi_fnRegisterServiceGroup(
|
|
||||||
IN IPortMidi * iface,
|
|
||||||
IN PSERVICEGROUP ServiceGroup)
|
|
||||||
{
|
|
||||||
UNIMPLEMENTED
|
|
||||||
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static IPortMidiVtbl vt_IPortMidi =
|
|
||||||
{
|
|
||||||
/* IUnknown methods */
|
|
||||||
IPortMidi_fnQueryInterface,
|
|
||||||
IPortMidi_fnAddRef,
|
|
||||||
IPortMidi_fnRelease,
|
|
||||||
/* IPort methods */
|
|
||||||
IPortMidi_fnInit,
|
|
||||||
IPortMidi_fnGetDeviceProperty,
|
|
||||||
IPortMidi_fnNewRegistryKey,
|
|
||||||
IPortMidi_fnNotify,
|
|
||||||
IPortMidi_fnRegisterServiceGroup
|
|
||||||
};
|
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
|
||||||
// ISubdevice interface
|
|
||||||
//
|
|
||||||
|
|
||||||
static
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
ISubDevice_fnQueryInterface(
|
|
||||||
IN ISubdevice *iface,
|
|
||||||
IN REFIID InterfaceId,
|
|
||||||
IN PVOID* Interface)
|
|
||||||
{
|
|
||||||
IPortMidiImpl * This = (IPortMidiImpl*)CONTAINING_RECORD(iface, IPortMidiImpl, lpVtblSubDevice);
|
|
||||||
|
|
||||||
return IPortMidi_fnQueryInterface((IPortMidi*)This, InterfaceId, Interface);
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
ULONG
|
|
||||||
NTAPI
|
|
||||||
ISubDevice_fnAddRef(
|
|
||||||
IN ISubdevice *iface)
|
|
||||||
{
|
|
||||||
IPortMidiImpl * This = (IPortMidiImpl*)CONTAINING_RECORD(iface, IPortMidiImpl, lpVtblSubDevice);
|
|
||||||
|
|
||||||
return IPortMidi_fnAddRef((IPortMidi*)This);
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
ULONG
|
|
||||||
NTAPI
|
|
||||||
ISubDevice_fnRelease(
|
|
||||||
IN ISubdevice *iface)
|
|
||||||
{
|
|
||||||
IPortMidiImpl * This = (IPortMidiImpl*)CONTAINING_RECORD(iface, IPortMidiImpl, lpVtblSubDevice);
|
|
||||||
|
|
||||||
return IPortMidi_fnRelease((IPortMidi*)This);
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
ISubDevice_fnNewIrpTarget(
|
|
||||||
IN ISubdevice *iface,
|
|
||||||
OUT struct IIrpTarget **OutTarget,
|
|
||||||
IN WCHAR * Name,
|
|
||||||
IN PUNKNOWN Unknown,
|
|
||||||
IN POOL_TYPE PoolType,
|
|
||||||
IN PDEVICE_OBJECT DeviceObject,
|
|
||||||
IN PIRP Irp,
|
|
||||||
IN KSOBJECT_CREATE *CreateObject)
|
|
||||||
{
|
|
||||||
//IPortMidiImpl * This = (IPortMidiImpl*)CONTAINING_RECORD(iface, IPortMidiImpl, lpVtblSubDevice);
|
|
||||||
|
|
||||||
UNIMPLEMENTED
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
ISubDevice_fnReleaseChildren(
|
|
||||||
IN ISubdevice *iface)
|
|
||||||
{
|
|
||||||
//IPortMidiImpl * This = (IPortMidiImpl*)CONTAINING_RECORD(iface, IPortMidiImpl, lpVtblSubDevice);
|
|
||||||
|
|
||||||
UNIMPLEMENTED
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
ISubDevice_fnGetDescriptor(
|
|
||||||
IN ISubdevice *iface,
|
|
||||||
IN SUBDEVICE_DESCRIPTOR ** Descriptor)
|
|
||||||
{
|
|
||||||
IPortMidiImpl * This = (IPortMidiImpl*)CONTAINING_RECORD(iface, IPortMidiImpl, lpVtblSubDevice);
|
|
||||||
|
|
||||||
DPRINT("ISubDevice_GetDescriptor this %p\n", This);
|
|
||||||
*Descriptor = This->SubDeviceDescriptor;
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
ISubDevice_fnDataRangeIntersection(
|
|
||||||
IN ISubdevice *iface,
|
|
||||||
IN ULONG PinId,
|
|
||||||
IN PKSDATARANGE DataRange,
|
|
||||||
IN PKSDATARANGE MatchingDataRange,
|
|
||||||
IN ULONG OutputBufferLength,
|
|
||||||
OUT PVOID ResultantFormat OPTIONAL,
|
|
||||||
OUT PULONG ResultantFormatLength)
|
|
||||||
{
|
|
||||||
IPortMidiImpl * This = (IPortMidiImpl*)CONTAINING_RECORD(iface, IPortMidiImpl, lpVtblSubDevice);
|
|
||||||
|
|
||||||
DPRINT("ISubDevice_DataRangeIntersection this %p\n", This);
|
|
||||||
|
|
||||||
if (This->pMiniport)
|
|
||||||
{
|
|
||||||
return This->pMiniport->lpVtbl->DataRangeIntersection (This->pMiniport, PinId, DataRange, MatchingDataRange, OutputBufferLength, ResultantFormat, ResultantFormatLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
ISubDevice_fnPowerChangeNotify(
|
|
||||||
IN ISubdevice *iface,
|
|
||||||
IN POWER_STATE PowerState)
|
|
||||||
{
|
|
||||||
IPortMidiImpl * This = (IPortMidiImpl*)CONTAINING_RECORD(iface, IPortMidiImpl, lpVtblSubDevice);
|
|
||||||
|
|
||||||
if (This->pPowerNotify)
|
|
||||||
{
|
|
||||||
This->pPowerNotify->lpVtbl->PowerChangeNotify(This->pPowerNotify, PowerState);
|
|
||||||
}
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
ISubDevice_fnPinCount(
|
|
||||||
IN ISubdevice *iface,
|
|
||||||
IN ULONG PinId,
|
|
||||||
IN OUT PULONG FilterNecessary,
|
|
||||||
IN OUT PULONG FilterCurrent,
|
|
||||||
IN OUT PULONG FilterPossible,
|
|
||||||
IN OUT PULONG GlobalCurrent,
|
|
||||||
IN OUT PULONG GlobalPossible)
|
|
||||||
{
|
|
||||||
IPortMidiImpl * This = (IPortMidiImpl*)CONTAINING_RECORD(iface, IPortMidiImpl, lpVtblSubDevice);
|
|
||||||
|
|
||||||
if (This->pPinCount)
|
|
||||||
{
|
|
||||||
This->pPinCount->lpVtbl->PinCount(This->pPinCount, PinId, FilterNecessary, FilterCurrent, FilterPossible, GlobalCurrent, GlobalPossible);
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME
|
|
||||||
* scan filter descriptor
|
|
||||||
*/
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ISubdeviceVtbl vt_ISubdeviceVtbl =
|
|
||||||
{
|
|
||||||
ISubDevice_fnQueryInterface,
|
|
||||||
ISubDevice_fnAddRef,
|
|
||||||
ISubDevice_fnRelease,
|
|
||||||
ISubDevice_fnNewIrpTarget,
|
|
||||||
ISubDevice_fnReleaseChildren,
|
|
||||||
ISubDevice_fnGetDescriptor,
|
|
||||||
ISubDevice_fnDataRangeIntersection,
|
|
||||||
ISubDevice_fnPowerChangeNotify,
|
|
||||||
ISubDevice_fnPinCount
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NewPortMidi(
|
|
||||||
OUT PPORT* OutPort)
|
|
||||||
{
|
|
||||||
IPortMidiImpl * This;
|
|
||||||
|
|
||||||
This = AllocateItem(NonPagedPool, sizeof(IPortMidiImpl), TAG_PORTCLASS);
|
|
||||||
if (!This)
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
|
|
||||||
This->lpVtbl = &vt_IPortMidi;
|
|
||||||
This->lpVtblSubDevice = &vt_ISubdeviceVtbl;
|
|
||||||
This->ref = 1;
|
|
||||||
*OutPort = (PPORT)(&This->lpVtbl);
|
|
||||||
|
|
||||||
DPRINT("NewPortMidi result %p\n", *OutPort);
|
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
|
@ -19,6 +19,7 @@
|
||||||
<file>dma_slave.c</file>
|
<file>dma_slave.c</file>
|
||||||
<file>drm.c</file>
|
<file>drm.c</file>
|
||||||
<file>drm_port.c</file>
|
<file>drm_port.c</file>
|
||||||
|
<file>filter_dmus.c</file>
|
||||||
<file>filter_wavecyclic.c</file>
|
<file>filter_wavecyclic.c</file>
|
||||||
<file>filter_wavepci.c</file>
|
<file>filter_wavepci.c</file>
|
||||||
<file>filter_wavert.c</file>
|
<file>filter_wavert.c</file>
|
||||||
|
@ -29,13 +30,13 @@
|
||||||
<file>miniport.c</file>
|
<file>miniport.c</file>
|
||||||
<file>miniport_dmus.c</file>
|
<file>miniport_dmus.c</file>
|
||||||
<file>miniport_fmsynth.c</file>
|
<file>miniport_fmsynth.c</file>
|
||||||
|
<file>pin_dmus.c</file>
|
||||||
<file>pin_wavecyclic.c</file>
|
<file>pin_wavecyclic.c</file>
|
||||||
<file>pin_wavepci.c</file>
|
<file>pin_wavepci.c</file>
|
||||||
<file>pin_wavert.c</file>
|
<file>pin_wavert.c</file>
|
||||||
<file>pool.c</file>
|
<file>pool.c</file>
|
||||||
<file>port.c</file>
|
<file>port.c</file>
|
||||||
<file>port_dmus.c</file>
|
<file>port_dmus.c</file>
|
||||||
<file>port_midi.c</file>
|
|
||||||
<file>port_topology.c</file>
|
<file>port_topology.c</file>
|
||||||
<file>port_wavecyclic.c</file>
|
<file>port_wavecyclic.c</file>
|
||||||
<file>port_wavepci.c</file>
|
<file>port_wavepci.c</file>
|
||||||
|
|
|
@ -63,9 +63,6 @@ NTSTATUS NewMiniportFmSynth(
|
||||||
OUT PMINIPORT* OutMiniport,
|
OUT PMINIPORT* OutMiniport,
|
||||||
IN REFCLSID ClassId);
|
IN REFCLSID ClassId);
|
||||||
|
|
||||||
NTSTATUS NewPortMidi(
|
|
||||||
OUT PPORT* OutPort);
|
|
||||||
|
|
||||||
NTSTATUS NewPortDMus(
|
NTSTATUS NewPortDMus(
|
||||||
OUT PPORT* OutPort);
|
OUT PPORT* OutPort);
|
||||||
|
|
||||||
|
@ -109,6 +106,19 @@ PMINIPORTWAVEPCI
|
||||||
GetWavePciMiniport(
|
GetWavePciMiniport(
|
||||||
PPORTWAVEPCI Port);
|
PPORTWAVEPCI Port);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NewPortFilterDMus(
|
||||||
|
OUT PPORTFILTERDMUS * OutFilter);
|
||||||
|
|
||||||
|
NTSTATUS NewPortPinDMus(
|
||||||
|
OUT PPORTPINDMUS * OutPin);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
GetDMusMiniport(
|
||||||
|
IN IPortDMus * iface,
|
||||||
|
IN PMINIPORTDMUS * Miniport,
|
||||||
|
IN PMINIPORTMIDI * MidiMiniport);
|
||||||
|
|
||||||
#if (NTDDI_VERSION >= NTDDI_VISTA)
|
#if (NTDDI_VERSION >= NTDDI_VISTA)
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue