mirror of
https://github.com/reactos/reactos.git
synced 2025-04-25 16:10:29 +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_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_PortDMus;
|
||||
const GUID IID_IMiniportDMus;
|
||||
const GUID CLSID_PortDMus = {0xb7902fe9L, 0xfb0a, 0x11d1, {0x81, 0xb0, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1}};
|
||||
|
||||
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_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 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_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_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_IPortDMus = {0xc096df9cL, 0xfb09, 0x11d1, {0x81, 0xb0, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1}};
|
||||
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}};
|
||||
|
|
|
@ -497,7 +497,7 @@ DECLARE_INTERFACE_(IPortFilterWaveRT, IIrpTarget)
|
|||
typedef IPortFilterWaveRT *PPORTFILTERWAVERT;
|
||||
|
||||
/*****************************************************************************
|
||||
* IPortPinWavePci
|
||||
* IPortPinWaveRT
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
|
@ -569,6 +569,59 @@ DECLARE_INTERFACE_(IPortPinWaveCyclic, IIrpTarget)
|
|||
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
|
||||
*****************************************************************************
|
||||
|
|
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))
|
||||
Status = NewPortMidi(OutPort);
|
||||
Status = NewPortDMus(OutPort);
|
||||
else if (IsEqualGUIDAligned(ClassId, &CLSID_PortDMus))
|
||||
Status = NewPortDMus(OutPort);
|
||||
else if (IsEqualGUIDAligned(ClassId, &CLSID_PortTopology))
|
||||
|
|
|
@ -11,16 +11,39 @@
|
|||
typedef struct
|
||||
{
|
||||
IPortDMusVtbl *lpVtbl;
|
||||
IServiceSinkVtbl *lpVtblServiceSink;
|
||||
ISubdeviceVtbl *lpVtblSubDevice;
|
||||
|
||||
LONG ref;
|
||||
BOOL bInitialized;
|
||||
IMiniportDMus *pMiniport;
|
||||
IMiniportMidi *pMiniportMidi;
|
||||
DEVICE_OBJECT *pDeviceObject;
|
||||
PSERVICEGROUP ServiceGroup;
|
||||
PPINCOUNT pPinCount;
|
||||
PPOWERNOTIFY pPowerNotify;
|
||||
PPORTFILTERDMUS Filter;
|
||||
|
||||
PPCFILTER_DESCRIPTOR pDescriptor;
|
||||
PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor;
|
||||
|
||||
}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
|
||||
|
@ -33,19 +56,39 @@ IPortDMus_fnQueryInterface(
|
|||
IN REFIID refiid,
|
||||
OUT PVOID* Output)
|
||||
{
|
||||
UNICODE_STRING GuidString;
|
||||
IPortDMusImpl * This = (IPortDMusImpl*)iface;
|
||||
|
||||
|
||||
if (IsEqualGUIDAligned(refiid, &IID_IPortDMus) ||
|
||||
IsEqualGUIDAligned(refiid, &IID_IPortMidi) ||
|
||||
IsEqualGUIDAligned(refiid, &IID_IUnknown))
|
||||
{
|
||||
*Output = &This->lpVtbl;
|
||||
_InterlockedIncrement(&This->ref);
|
||||
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_IDrmPort) ||
|
||||
IsEqualGUIDAligned(refiid, &IID_IDrmPort2))
|
||||
{
|
||||
return NewIDrmPort((PDRMPORT2*)Output);
|
||||
}
|
||||
else if (IsEqualGUIDAligned(refiid, &IID_IPortClsVersion))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -118,8 +161,12 @@ IPortDMus_fnInit(
|
|||
IN PUNKNOWN UnknownAdapter OPTIONAL,
|
||||
IN PRESOURCELIST ResourceList)
|
||||
{
|
||||
IMiniportDMus * Miniport;
|
||||
IMiniportDMus * Miniport = NULL;
|
||||
IMiniportMidi * MidiMiniport = NULL;
|
||||
NTSTATUS Status;
|
||||
PSERVICEGROUP ServiceGroup;
|
||||
PPINCOUNT PinCount;
|
||||
PPOWERNOTIFY PowerNotify;
|
||||
IPortDMusImpl * This = (IPortDMusImpl*)iface;
|
||||
|
||||
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
|
||||
|
@ -133,25 +180,111 @@ IPortDMus_fnInit(
|
|||
Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IMiniportDMus, (PVOID*)&Miniport);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("IPortDMus_Init called with invalid IMiniport adapter\n");
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
/* check for legacy interface */
|
||||
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))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
ASSERT(This->ServiceGroup);
|
||||
ASSERT(ServiceGroup == This->ServiceGroup);
|
||||
|
||||
/* Initialize port object */
|
||||
This->pMiniport = Miniport;
|
||||
This->pMiniportMidi = MidiMiniport;
|
||||
This->pDeviceObject = DeviceObject;
|
||||
This->bInitialized = TRUE;
|
||||
|
||||
/* increment reference on miniport adapter */
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -180,11 +313,339 @@ IPortDMus_fnNewRegistryKey(
|
|||
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
|
||||
NewPortDMus(
|
||||
OUT PPORT* OutPort)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
IPortDMusImpl * This = AllocateItem(NonPagedPool, sizeof(IPortDMusImpl), TAG_PORTCLASS);
|
||||
|
||||
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>drm.c</file>
|
||||
<file>drm_port.c</file>
|
||||
<file>filter_dmus.c</file>
|
||||
<file>filter_wavecyclic.c</file>
|
||||
<file>filter_wavepci.c</file>
|
||||
<file>filter_wavert.c</file>
|
||||
|
@ -29,13 +30,13 @@
|
|||
<file>miniport.c</file>
|
||||
<file>miniport_dmus.c</file>
|
||||
<file>miniport_fmsynth.c</file>
|
||||
<file>pin_dmus.c</file>
|
||||
<file>pin_wavecyclic.c</file>
|
||||
<file>pin_wavepci.c</file>
|
||||
<file>pin_wavert.c</file>
|
||||
<file>pool.c</file>
|
||||
<file>port.c</file>
|
||||
<file>port_dmus.c</file>
|
||||
<file>port_midi.c</file>
|
||||
<file>port_topology.c</file>
|
||||
<file>port_wavecyclic.c</file>
|
||||
<file>port_wavepci.c</file>
|
||||
|
|
|
@ -63,9 +63,6 @@ NTSTATUS NewMiniportFmSynth(
|
|||
OUT PMINIPORT* OutMiniport,
|
||||
IN REFCLSID ClassId);
|
||||
|
||||
NTSTATUS NewPortMidi(
|
||||
OUT PPORT* OutPort);
|
||||
|
||||
NTSTATUS NewPortDMus(
|
||||
OUT PPORT* OutPort);
|
||||
|
||||
|
@ -109,6 +106,19 @@ PMINIPORTWAVEPCI
|
|||
GetWavePciMiniport(
|
||||
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)
|
||||
|
||||
NTSTATUS
|
||||
|
|
Loading…
Reference in a new issue