[ros-diffs] [janderwald] 40797: - Implement IPortWaveRT, IPortFilterWaveRT, IPortPinWaveRT interface for audio drivers >= Vista

janderwald at svn.reactos.org janderwald at svn.reactos.org
Tue May 5 18:01:40 CEST 2009


Author: janderwald
Date: Tue May  5 20:01:39 2009
New Revision: 40797

URL: http://svn.reactos.org/svn/reactos?rev=40797&view=rev
Log:
- Implement IPortWaveRT, IPortFilterWaveRT, IPortPinWaveRT interface for audio drivers >= Vista

Added:
    trunk/reactos/drivers/wdm/audio/backpln/portcls/filter_wavert.c   (with props)
    trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavert.c   (with props)
    trunk/reactos/drivers/wdm/audio/backpln/portcls/port_wavert.c   (with props)
    trunk/reactos/drivers/wdm/audio/backpln/portcls/port_wavertstream.c   (with props)
Modified:
    trunk/reactos/drivers/wdm/audio/backpln/portcls/guids.c
    trunk/reactos/drivers/wdm/audio/backpln/portcls/interfaces.h
    trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c
    trunk/reactos/drivers/wdm/audio/backpln/portcls/private.h

Added: trunk/reactos/drivers/wdm/audio/backpln/portcls/filter_wavert.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/portcls/filter_wavert.c?rev=40797&view=auto
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/filter_wavert.c (added)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/filter_wavert.c [iso-8859-1] Tue May  5 20:01:39 2009
@@ -1,0 +1,462 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Kernel Streaming
+ * FILE:            drivers/wdm/audio/backpln/portcls/filter_wavert.c
+ * PURPOSE:         portcls wave RT filter
+ * PROGRAMMER:      Johannes Anderwald
+ */
+
+#include "private.h"
+
+typedef struct
+{
+    IPortFilterWaveRTVtbl *lpVtbl;
+
+    LONG ref;
+
+    IPortWaveRT* Port;
+    IPortPinWaveRT ** Pins;
+    SUBDEVICE_DESCRIPTOR * Descriptor;
+
+}IPortFilterWaveRTImpl;
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+IPortFilterWaveRT_fnQueryInterface(
+    IPortFilterWaveRT* iface,
+    IN  REFIID refiid,
+    OUT PVOID* Output)
+{
+    IPortFilterWaveRTImpl * This = (IPortFilterWaveRTImpl*)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
+IPortFilterWaveRT_fnAddRef(
+    IPortFilterWaveRT* iface)
+{
+    IPortFilterWaveRTImpl * This = (IPortFilterWaveRTImpl*)iface;
+
+    return InterlockedIncrement(&This->ref);
+}
+
+/*
+ * @implemented
+ */
+ULONG
+NTAPI
+IPortFilterWaveRT_fnRelease(
+    IPortFilterWaveRT* iface)
+{
+    IPortFilterWaveRTImpl * This = (IPortFilterWaveRTImpl*)iface;
+
+    InterlockedDecrement(&This->ref);
+
+    if (This->ref == 0)
+    {
+        FreeItem(This, TAG_PORTCLASS);
+        return 0;
+    }
+    return This->ref;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+IPortFilterWaveRT_fnNewIrpTarget(
+    IN IPortFilterWaveRT* 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;
+    IPortPinWaveRT * Pin;
+    PKSPIN_CONNECT ConnectDetails;
+    IPortFilterWaveRTImpl * This = (IPortFilterWaveRTImpl *)iface;
+
+    ASSERT(This->Port);
+    ASSERT(This->Descriptor);
+    ASSERT(This->Pins);
+
+    DPRINT("IPortFilterWaveRT_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);
+        This->Pins[ConnectDetails->PinId]->lpVtbl->Close(This->Pins[ConnectDetails->PinId], DeviceObject, NULL);
+    }
+
+    /* now create the pin */
+    Status = NewPortPinWaveRT(&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], GetDeviceObjectFromPortWaveRT(This->Port));
+    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
+IPortFilterWaveRT_fnDeviceIoControl(
+    IN IPortFilterWaveRT* iface,
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+    ISubdevice *SubDevice = NULL;
+    SUBDEVICE_DESCRIPTOR * Descriptor;
+    NTSTATUS Status;
+    IPortFilterWaveRTImpl * This = (IPortFilterWaveRTImpl *)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
+IPortFilterWaveRT_fnRead(
+    IN IPortFilterWaveRT* iface,
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+IPortFilterWaveRT_fnWrite(
+    IN IPortFilterWaveRT* iface,
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+IPortFilterWaveRT_fnFlush(
+    IN IPortFilterWaveRT* iface,
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+IPortFilterWaveRT_fnClose(
+    IN IPortFilterWaveRT* iface,
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    ULONG Index;
+    IPortFilterWaveRTImpl * This = (IPortFilterWaveRTImpl *)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
+IPortFilterWaveRT_fnQuerySecurity(
+    IN IPortFilterWaveRT* iface,
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+IPortFilterWaveRT_fnSetSecurity(
+    IN IPortFilterWaveRT* iface,
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+IPortFilterWaveRT_fnFastDeviceIoControl(
+    IN IPortFilterWaveRT* 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;
+    IPortFilterWaveRTImpl * This = (IPortFilterWaveRTImpl *)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
+IPortFilterWaveRT_fnFastRead(
+    IN IPortFilterWaveRT* 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
+IPortFilterWaveRT_fnFastWrite(
+    IN IPortFilterWaveRT* 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
+IPortFilterWaveRT_fnInit(
+    IN IPortFilterWaveRT* iface,
+    IN IPortWaveRT* Port)
+{
+    ISubdevice * ISubDevice;
+    SUBDEVICE_DESCRIPTOR * Descriptor;
+    NTSTATUS Status;
+    IPortFilterWaveRTImpl * This = (IPortFilterWaveRTImpl*)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(IPortPinWaveRT*), TAG_PORTCLASS);
+
+    if (!This->Pins)
+        return STATUS_UNSUCCESSFUL;
+
+    /* increment reference count */
+    Port->lpVtbl->AddRef(Port);
+
+    return STATUS_SUCCESS;
+}
+
+static IPortFilterWaveRTVtbl vt_IPortFilterWaveRT =
+{
+    IPortFilterWaveRT_fnQueryInterface,
+    IPortFilterWaveRT_fnAddRef,
+    IPortFilterWaveRT_fnRelease,
+    IPortFilterWaveRT_fnNewIrpTarget,
+    IPortFilterWaveRT_fnDeviceIoControl,
+    IPortFilterWaveRT_fnRead,
+    IPortFilterWaveRT_fnWrite,
+    IPortFilterWaveRT_fnFlush,
+    IPortFilterWaveRT_fnClose,
+    IPortFilterWaveRT_fnQuerySecurity,
+    IPortFilterWaveRT_fnSetSecurity,
+    IPortFilterWaveRT_fnFastDeviceIoControl,
+    IPortFilterWaveRT_fnFastRead,
+    IPortFilterWaveRT_fnFastWrite,
+    IPortFilterWaveRT_fnInit
+};
+
+NTSTATUS 
+NewPortFilterWaveRT(
+    OUT IPortFilterWaveRT ** OutFilter)
+{
+    IPortFilterWaveRTImpl * This;
+
+    This = AllocateItem(NonPagedPool, sizeof(IPortFilterWaveRTImpl), TAG_PORTCLASS);
+    if (!This)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    /* initialize IPortFilterWaveRT */
+    This->ref = 1;
+    This->lpVtbl = &vt_IPortFilterWaveRT;
+
+    /* return result */
+    *OutFilter = (IPortFilterWaveRT*)&This->lpVtbl;
+
+    return STATUS_SUCCESS;
+}

Propchange: trunk/reactos/drivers/wdm/audio/backpln/portcls/filter_wavert.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/guids.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/portcls/guids.c?rev=40797&r1=40796&r2=40797&view=diff
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/guids.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/guids.c [iso-8859-1] Tue May  5 20:01:39 2009
@@ -76,3 +76,14 @@
 const GUID IID_IIrpTarget = {0xB4C90A60, 0x5791, 0x11D0, {0xF9, 0x86, 0x00, 0xA0, 0xC9, 0x11, 0xB5, 0x44}};
 const GUID IID_IIrpTargetFactory =  {0xB4C90A62, 0x5791, 0x11D0, {0xF9, 0x86, 0x00, 0xA0, 0xC9, 0x11, 0xB5, 0x44}};
 
+
+///
+/// >= Vista GUIDs
+///
+const GUID IID_IPortWaveRT                       = {0x339ff909, 0x68a9, 0x4310, {0xb0, 0x9b, 0x27, 0x4e, 0x96, 0xee, 0x4c, 0xbd}};
+const GUID IID_IPortWaveRTStream                 = {0x1809ce5a, 0x64bc, 0x4e62, {0xbd, 0x7d, 0x95, 0xbc, 0xe4, 0x3d, 0xe3, 0x93}};
+const GUID IID_IMiniportWaveRT                   = {0x0f9fc4d6, 0x6061, 0x4f3c, {0xb1, 0xfc, 0x7, 0x5e, 0x35, 0xf7, 0x96, 0xa}};
+const GUID IID_IMiniportWaveRTStream             = {0x000ac9ab, 0xfaab, 0x4f3d, {0x94, 0x55, 0x6f, 0xf8, 0x30, 0x6a, 0x74, 0xa0}};
+const GUID IID_IMiniportWaveRTStreamNotification = {0x23759128, 0x96f1, 0x423b, {0xab, 0x4d, 0x81, 0x63, 0x5b, 0xcf, 0x8c, 0xa1}};
+
+

Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/interfaces.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/portcls/interfaces.h?rev=40797&r1=40796&r2=40797&view=diff
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/interfaces.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/interfaces.h [iso-8859-1] Tue May  5 20:01:39 2009
@@ -475,6 +475,50 @@
 typedef IPortPinWavePci *PPORTPINWAVEPCI;
 
 /*****************************************************************************
+ * IPortFilterWaveRT
+ *****************************************************************************
+ */
+
+#undef INTERFACE
+#define INTERFACE IPortFilterWaveRT
+
+DECLARE_INTERFACE_(IPortFilterWaveRT, IIrpTarget)
+{
+    DEFINE_ABSTRACT_UNKNOWN()
+
+    DEFINE_ABSTRACT_IRPTARGET()
+
+    STDMETHOD_(NTSTATUS, Init)(THIS_
+        IN PPORTWAVERT Port)PURE;
+};
+
+typedef IPortFilterWaveRT *PPORTFILTERWAVERT;
+
+/*****************************************************************************
+ * IPortPinWavePci
+ *****************************************************************************
+ */
+
+#undef INTERFACE
+#define INTERFACE IPortPinWaveRT
+
+DECLARE_INTERFACE_(IPortPinWaveRT, IIrpTarget)
+{
+    DEFINE_ABSTRACT_UNKNOWN()
+
+    DEFINE_ABSTRACT_IRPTARGET()
+
+    STDMETHOD_(NTSTATUS, Init)(THIS_
+        IN PPORTWAVERT Port,
+        IN PPORTFILTERWAVERT Filter,
+        IN KSPIN_CONNECT * ConnectDetails,
+        IN KSPIN_DESCRIPTOR * PinDescriptor,
+        IN PDEVICE_OBJECT DeviceObject) PURE;
+};
+
+typedef IPortPinWavePci *PPORTPINWAVERT;
+
+/*****************************************************************************
  * IPortFilterWaveCyclic
  *****************************************************************************
  */

Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c?rev=40797&r1=40796&r2=40797&view=diff
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c [iso-8859-1] Tue May  5 20:01:39 2009
@@ -31,9 +31,6 @@
 
     IIrpQueue * IrpQueue;
 
-    PUCHAR ActiveIrpBuffer;
-    ULONG ActiveIrpBufferSize;
-    ULONG ActiveIrpOffset;
     ULONG FrameSize;
     BOOL Capture;
 

Added: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavert.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavert.c?rev=40797&view=auto
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavert.c (added)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavert.c [iso-8859-1] Tue May  5 20:01:39 2009
@@ -1,0 +1,1044 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Kernel Streaming
+ * FILE:            drivers/wdm/audio/backpln/portcls/pin_wavert.c
+ * PURPOSE:         WaveRT IRP Audio Pin
+ * PROGRAMMER:      Johannes Anderwald
+ */
+
+#include "private.h"
+
+typedef struct
+{
+    IPortPinWaveRTVtbl *lpVtbl;
+    IServiceSinkVtbl *lpVtblServiceSink;
+    LONG ref;
+
+    IPortWaveRT * Port;
+    IPortFilterWaveRT * Filter;
+    KSPIN_DESCRIPTOR * KsPinDescriptor;
+    PMINIPORTWAVERT Miniport;
+    PMINIPORTWAVERTSTREAM Stream;
+    PPORTWAVERTSTREAM PortStream;
+    PSERVICEGROUP ServiceGroup;
+    KSSTATE State;
+    PKSDATAFORMAT Format;
+    KSPIN_CONNECT * ConnectDetails;
+
+    PVOID CommonBuffer;
+    ULONG CommonBufferSize;
+    ULONG CommonBufferOffset;
+
+    IIrpQueue * IrpQueue;
+
+    BOOL Capture;
+
+    ULONG TotalPackets;
+    ULONG PreCompleted;
+    ULONG PostCompleted;
+
+    ULONGLONG Delay;
+
+    MEMORY_CACHING_TYPE CacheType;
+    PMDL Mdl;
+
+}IPortPinWaveRTImpl;
+
+
+typedef struct
+{
+    IPortPinWaveRTImpl *Pin;
+    PIO_WORKITEM WorkItem;
+    KSSTATE State;
+}SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT;
+
+static
+VOID
+NTAPI
+SetStreamState(
+   IN IPortPinWaveRTImpl * This,
+   IN KSSTATE State);
+
+//==================================================================================================================================
+static
+NTSTATUS
+NTAPI
+IServiceSink_fnQueryInterface(
+    IServiceSink* iface,
+    IN  REFIID refiid,
+    OUT PVOID* Output)
+{
+    IPortPinWaveRTImpl * This = (IPortPinWaveRTImpl*)CONTAINING_RECORD(iface, IPortPinWaveRTImpl, 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)
+{
+    IPortPinWaveRTImpl * This = (IPortPinWaveRTImpl*)CONTAINING_RECORD(iface, IPortPinWaveRTImpl, lpVtblServiceSink);
+    DPRINT("IServiceSink_fnAddRef entered\n");
+
+    return InterlockedIncrement(&This->ref);
+}
+
+static
+ULONG
+NTAPI
+IServiceSink_fnRelease(
+    IServiceSink* iface)
+{
+    IPortPinWaveRTImpl * This = (IPortPinWaveRTImpl*)CONTAINING_RECORD(iface, IPortPinWaveRTImpl, 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
+IServiceSink_fnRequestService(
+    IServiceSink* iface)
+{
+    KSAUDIO_POSITION Position;
+    NTSTATUS Status;
+    PUCHAR Buffer;
+    ULONG BufferSize;
+    IPortPinWaveRTImpl * This = (IPortPinWaveRTImpl*)CONTAINING_RECORD(iface, IPortPinWaveRTImpl, lpVtblServiceSink);
+
+    ASSERT_IRQL(DISPATCH_LEVEL);
+
+    Status = This->IrpQueue->lpVtbl->GetMapping(This->IrpQueue, &Buffer, &BufferSize);
+    if (!NT_SUCCESS(Status))
+    {
+        SetStreamState(This, KSSTATE_STOP);
+        return;
+    }
+
+    Status = This->Stream->lpVtbl->GetPosition(This->Stream, &Position);
+    DPRINT("PlayOffset %llu WriteOffset %llu %u Buffer %p BufferSize %u\n", Position.PlayOffset, Position.WriteOffset, Buffer, This->CommonBufferSize, BufferSize);
+
+    //FIXME
+    // implement writing into cyclic buffer
+    //
+
+    /* reschedule the timer */
+    This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, This->Delay);
+}
+
+static IServiceSinkVtbl vt_IServiceSink = 
+{
+    IServiceSink_fnQueryInterface,
+    IServiceSink_fnAddRef,
+    IServiceSink_fnRelease,
+    IServiceSink_fnRequestService
+};
+
+
+static
+VOID
+NTAPI
+SetStreamWorkerRoutine(
+    IN PDEVICE_OBJECT  DeviceObject,
+    IN PVOID  Context)
+{
+    IPortPinWaveRTImpl * 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->Stream->lpVtbl->SetState(This->Stream, 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
+            This->ServiceGroup->lpVtbl->CancelDelayedService(This->ServiceGroup);
+            DPRINT1("Stopping PreCompleted %u PostCompleted %u\n", This->PreCompleted, This->PostCompleted);
+        }
+
+        if (This->State == KSSTATE_RUN)
+        {
+            /* start the notification timer */
+            This->ServiceGroup->lpVtbl->RequestDelayedService(This->ServiceGroup, This->Delay);
+        }
+    }
+}
+
+static
+VOID
+NTAPI
+SetStreamState(
+   IN IPortPinWaveRTImpl * This,
+   IN KSSTATE State)
+{
+    PDEVICE_OBJECT DeviceObject;
+    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;
+
+    /* Get device object */
+    DeviceObject = GetDeviceObjectFromPortWaveRT(This->Port);
+
+    /* allocate set state context */
+    Context = AllocateItem(NonPagedPool, sizeof(SETSTREAM_CONTEXT), TAG_PORTCLASS);
+
+    if (!Context)
+        return;
+
+    /* allocate work item */
+    WorkItem = IoAllocateWorkItem(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);
+}
+
+//==================================================================================================================================
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+IPortPinWaveRT_fnQueryInterface(
+    IPortPinWaveRT* iface,
+    IN  REFIID refiid,
+    OUT PVOID* Output)
+{
+    IPortPinWaveRTImpl * This = (IPortPinWaveRTImpl*)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
+IPortPinWaveRT_fnAddRef(
+    IPortPinWaveRT* iface)
+{
+    IPortPinWaveRTImpl * This = (IPortPinWaveRTImpl*)iface;
+
+    return InterlockedIncrement(&This->ref);
+}
+
+/*
+ * @implemented
+ */
+ULONG
+NTAPI
+IPortPinWaveRT_fnRelease(
+    IPortPinWaveRT* iface)
+{
+    IPortPinWaveRTImpl * This = (IPortPinWaveRTImpl*)iface;
+
+    InterlockedDecrement(&This->ref);
+
+    if (This->ref == 0)
+    {
+        FreeItem(This, TAG_PORTCLASS);
+        return 0;
+    }
+    return This->ref;
+}
+
+/*
+ * @unimplemented
+ */
+NTSTATUS
+NTAPI
+IPortPinWaveRT_fnNewIrpTarget(
+    IN IPortPinWaveRT* 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
+    return STATUS_UNSUCCESSFUL;
+}
+
+NTSTATUS
+NTAPI
+IPortPinWaveRT_HandleKsProperty(
+    IN IPortPinWaveRT * iface,
+    IN PIRP Irp)
+{
+    PKSPROPERTY Property;
+    NTSTATUS Status;
+    UNICODE_STRING GuidString;
+    PIO_STACK_LOCATION IoStack;
+    IPortPinWaveRTImpl * This = (IPortPinWaveRTImpl*)iface;
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    DPRINT("IPortPinWave_HandleKsProperty entered\n");
+
+    if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY))
+    {
+        Irp->IoStatus.Information = 0;
+        Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
+
+    if (IsEqualGUIDAligned(&Property->Set, &KSPROPSETID_Connection))
+    {
+        if (Property->Id == KSPROPERTY_CONNECTION_STATE)
+        {
+            PKSSTATE State = (PKSSTATE)Irp->UserBuffer;
+
+            if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KSSTATE))
+            {
+                Irp->IoStatus.Information = sizeof(KSSTATE);
+                Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
+                IoCompleteRequest(Irp, IO_NO_INCREMENT);
+                return STATUS_BUFFER_TOO_SMALL;
+            }
+
+            if (Property->Flags & KSPROPERTY_TYPE_SET)
+            {
+                Status = STATUS_UNSUCCESSFUL;
+                Irp->IoStatus.Information = 0;
+
+                if (This->Stream)
+                {
+                    Status = This->Stream->lpVtbl->SetState(This->Stream, *State);
+
+                    DPRINT1("Setting state %u %x\n", *State, Status);
+                    if (NT_SUCCESS(Status))
+                    {
+                        This->State = *State;
+                    }
+                }
+                Irp->IoStatus.Status = Status;
+                IoCompleteRequest(Irp, IO_NO_INCREMENT);
+                return Status;
+            }
+            else if (Property->Flags & KSPROPERTY_TYPE_GET)
+            {
+                *State = This->State;
+                Irp->IoStatus.Information = sizeof(KSSTATE);
+                Irp->IoStatus.Status = STATUS_SUCCESS;
+                IoCompleteRequest(Irp, IO_NO_INCREMENT);
+                return STATUS_SUCCESS;
+            }
+        }
+        else if (Property->Id == KSPROPERTY_CONNECTION_DATAFORMAT)
+        {
+            PKSDATAFORMAT DataFormat = (PKSDATAFORMAT)Irp->UserBuffer;
+            if (Property->Flags & KSPROPERTY_TYPE_SET)
+            {
+                PKSDATAFORMAT NewDataFormat;
+                if (!RtlCompareMemory(DataFormat, This->Format, DataFormat->FormatSize))
+                {
+                    Irp->IoStatus.Information = DataFormat->FormatSize;
+                    Irp->IoStatus.Status = STATUS_SUCCESS;
+                    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+                    return STATUS_SUCCESS;
+                }
+
+                NewDataFormat = AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
+                if (!NewDataFormat)
+                {
+                    Irp->IoStatus.Information = 0;
+                    Irp->IoStatus.Status = STATUS_NO_MEMORY;
+                    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+                    return STATUS_NO_MEMORY;
+                }
+                RtlMoveMemory(NewDataFormat, DataFormat, DataFormat->FormatSize);
+
+                if (This->Stream)
+                {
+                    ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
+                    ASSERT(NewDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX));
+                    ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, &KSDATAFORMAT_TYPE_AUDIO));
+                    ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM));
+                    ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX));
+
+                    ASSERT(This->State == KSSTATE_STOP);
+                    DPRINT1("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels,
+                                                                                 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample,
+                                                                                 ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec);
+
+                    Status = This->Stream->lpVtbl->SetFormat(This->Stream, NewDataFormat);
+                    if (NT_SUCCESS(Status))
+                    {
+                        if (This->Format)
+                            ExFreePoolWithTag(This->Format, TAG_PORTCLASS);
+
+                        This->IrpQueue->lpVtbl->UpdateFormat(This->IrpQueue, (PKSDATAFORMAT)NewDataFormat);
+                        This->Format = NewDataFormat;
+                        Irp->IoStatus.Information = DataFormat->FormatSize;
+                        Irp->IoStatus.Status = STATUS_SUCCESS;
+                        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+                        return STATUS_SUCCESS;
+                    }
+                }
+                DPRINT1("Failed to set format\n");
+                Irp->IoStatus.Information = 0;
+                Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+                IoCompleteRequest(Irp, IO_NO_INCREMENT);
+                return STATUS_UNSUCCESSFUL;
+            }
+            else if (Property->Flags & KSPROPERTY_TYPE_GET)
+            {
+                if (!This->Format)
+                {
+                    DPRINT1("No format\n");
+                    Irp->IoStatus.Information = 0;
+                    Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+                    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+                    return STATUS_UNSUCCESSFUL;
+                }
+                if (This->Format->FormatSize > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
+                {
+                    Irp->IoStatus.Information = This->Format->FormatSize;
+                    Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
+                    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+                    return STATUS_BUFFER_TOO_SMALL;
+                }
+
+                RtlMoveMemory(DataFormat, This->Format, This->Format->FormatSize);
+                Irp->IoStatus.Information = DataFormat->FormatSize;
+                Irp->IoStatus.Status = STATUS_SUCCESS;
+                IoCompleteRequest(Irp, IO_NO_INCREMENT);
+                return STATUS_SUCCESS;
+            }
+        }
+
+    }
+    RtlStringFromGUID(&Property->Set, &GuidString);
+    DPRINT1("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
+    DbgBreakPoint();
+    RtlFreeUnicodeString(&GuidString);
+
+    Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
+    Irp->IoStatus.Information = 0;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+IPortPinWaveRT_HandleKsStream(
+    IN IPortPinWaveRT * iface,
+    IN PIRP Irp)
+{
+    IPortPinWaveRTImpl * This = (IPortPinWaveRTImpl*)iface;
+
+    DPRINT("IPortPinWaveRT_HandleKsStream entered State %u Stream %p\n", This->State, This->Stream);
+
+    return STATUS_PENDING;
+}
+
+/*
+ * @unimplemented
+ */
+NTSTATUS
+NTAPI
+IPortPinWaveRT_fnDeviceIoControl(
+    IN IPortPinWaveRT* iface,
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    PIO_STACK_LOCATION IoStack;
+
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+
+    if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
+    {
+       return IPortPinWaveRT_HandleKsProperty(iface, Irp);
+    }
+    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
+    {
+        /// FIXME
+        /// handle enable event
+    }
+    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT)
+    {
+        /// FIXME
+        /// handle disable event
+    }
+    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
+    {
+        /// FIXME
+        /// handle reset state
+    }
+    else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
+    {
+       return IPortPinWaveRT_HandleKsStream(iface, Irp);
+    }
+    else
+    {
+        return KsDefaultDeviceIoCompletion(DeviceObject, Irp);
+    }
+
+    UNIMPLEMENTED
+    DbgBreakPoint();
+
+    Irp->IoStatus.Information = 0;
+    Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return STATUS_UNSUCCESSFUL;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+IPortPinWaveRT_fnRead(
+    IN IPortPinWaveRT* iface,
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+IPortPinWaveRT_fnWrite(
+    IN IPortPinWaveRT* iface,
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+IPortPinWaveRT_fnFlush(
+    IN IPortPinWaveRT* iface,
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
+}
+
+static
+VOID
+NTAPI
+CloseStreamRoutine(
+    IN PDEVICE_OBJECT  DeviceObject,
+    IN PVOID Context)
+{
+    PMINIPORTWAVERTSTREAM Stream;
+    NTSTATUS Status;
+    ISubdevice *ISubDevice;
+    PSUBDEVICE_DESCRIPTOR Descriptor;
+    IPortPinWaveRTImpl * This;
+    PCLOSESTREAM_CONTEXT Ctx = (PCLOSESTREAM_CONTEXT)Context;
+
+    This = (IPortPinWaveRTImpl*)Ctx->Pin;
+
+    if (This->Stream)
+    {
+        if (This->State != KSSTATE_STOP)
+        {
+            This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP);
+            KeStallExecutionProcessor(10);
+        }
+    }
+
+    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;
+    }
+
+    if (This->IrpQueue)
+    {
+        This->IrpQueue->lpVtbl->Release(This->IrpQueue);
+    }
+
+    /* 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);
+
+    if (This->Stream)
+    {
+        Stream = This->Stream;
+        This->Stream = NULL;
+        DPRINT1("Closing stream at Irql %u\n", KeGetCurrentIrql());
+        Stream->lpVtbl->Release(Stream);
+        /* this line is never reached */
+    }
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+IPortPinWaveRT_fnClose(
+    IN IPortPinWaveRT* iface,
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    PCLOSESTREAM_CONTEXT Ctx;
+    IPortPinWaveRTImpl * This = (IPortPinWaveRTImpl*)iface;
+
+    if (This->Stream)
+    {
+        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
+IPortPinWaveRT_fnQuerySecurity(
+    IN IPortPinWaveRT* iface,
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+IPortPinWaveRT_fnSetSecurity(
+    IN IPortPinWaveRT* iface,
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
+{
+    return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+IPortPinWaveRT_fnFastDeviceIoControl(
+    IN IPortPinWaveRT* 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
+IPortPinWaveRT_fnFastRead(
+    IN IPortPinWaveRT* 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;
+    IPortPinWaveRTImpl * This = (IPortPinWaveRTImpl*)iface;
+
+    DPRINT("IPortPinWaveRT_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));
+
+        This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_RUN);
+        This->State = KSSTATE_RUN;
+    }
+    return TRUE;
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+IPortPinWaveRT_fnFastWrite(
+    IN IPortPinWaveRT* 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;
+    IPortPinWaveRTImpl * This = (IPortPinWaveRTImpl*)iface;
+
+    InterlockedIncrement((PLONG)&This->TotalPackets);
+
+    DPRINT("IPortPinWaveRT_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
+IPortPinWaveRT_fnInit(
+    IN IPortPinWaveRT* iface,
+    IN PPORTWAVERT Port,
+    IN PPORTFILTERWAVERT Filter,
+    IN KSPIN_CONNECT * ConnectDetails,
+    IN KSPIN_DESCRIPTOR * KsPinDescriptor,
+    IN PDEVICE_OBJECT DeviceObject)
+{
+    NTSTATUS Status;
+    PKSDATAFORMAT DataFormat;
+    BOOL Capture;
+    KSRTAUDIO_HWLATENCY Latency;
+    IPortPinWaveRTImpl * This = (IPortPinWaveRTImpl*)iface;
+
+    Port->lpVtbl->AddRef(Port);
+    Filter->lpVtbl->AddRef(Filter);
+
+    This->Port = Port;
+    This->Filter = Filter;
+    This->KsPinDescriptor = KsPinDescriptor;
+    This->ConnectDetails = ConnectDetails;
+    This->Miniport = GetWaveRTMiniport(Port);
+
+    DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
+
+    DPRINT("IPortPinWaveRT_fnInit entered\n");
+
+    This->Format = AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
+    if (!This->Format)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    RtlMoveMemory(This->Format, DataFormat, DataFormat->FormatSize);
+
+    Status = NewIrpQueue(&This->IrpQueue);
+    if (!NT_SUCCESS(Status))
+    {
+        goto cleanup;
+    }
+
+    Status = This->IrpQueue->lpVtbl->Init(This->IrpQueue, ConnectDetails, DataFormat, DeviceObject, 0);
+    if (!NT_SUCCESS(Status))
+    {
+        goto cleanup;
+    }
+
+    Status = NewPortWaveRTStream(&This->PortStream);
+    if (!NT_SUCCESS(Status))
+    {
+        goto cleanup;
+    }
+
+    Status = PcNewServiceGroup(&This->ServiceGroup, NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        goto cleanup;
+    }
+
+    This->ServiceGroup->lpVtbl->AddMember(This->ServiceGroup, (PSERVICESINK)&This->lpVtblServiceSink);
+    This->ServiceGroup->lpVtbl->SupportDelayedService(This->ServiceGroup);
+
+    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 = This->Miniport->lpVtbl->NewStream(This->Miniport,
+                                               &This->Stream,
+                                               This->PortStream,
+                                               ConnectDetails->PinId,
+                                               Capture,
+                                               This->Format);
+    DPRINT("IPortPinWaveRT_fnInit Status %x\n", Status);
+
+    if (!NT_SUCCESS(Status))
+        goto cleanup;
+
+    This->Stream->lpVtbl->GetHWLatency(This->Stream, &Latency);
+    /* minimum delay of 10 milisec */
+    This->Delay = Int32x32To64(min(max(Latency.ChipsetDelay + Latency.CodecDelay + Latency.FifoSize, 10), 10), -10000);
+
+    Status = This->Stream->lpVtbl->AllocateAudioBuffer(This->Stream, 16384, &This->Mdl, &This->CommonBufferSize, &This->CommonBufferOffset, &This->CacheType);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("AllocateAudioBuffer failed with %x\n", Status);
+        goto cleanup;
+    }
+
+    This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP);
+    This->State = KSSTATE_STOP;
+    This->Capture = Capture;
+
+    This->Stream->lpVtbl->SetFormat(This->Stream, (PKSDATAFORMAT)This->Format);
+    return STATUS_SUCCESS;
+
+cleanup:
+    if (This->IrpQueue)
+    {
+        This->IrpQueue->lpVtbl->Release(This->IrpQueue);
+        This->IrpQueue = NULL;
+    }
+
+    if (This->Format)
+    {
+        FreeItem(This->Format, TAG_PORTCLASS);
+        This->Format = NULL;
+    }
+
+    if (This->ServiceGroup)
+    {
+        This->ServiceGroup->lpVtbl->Release(This->ServiceGroup);
+        This->ServiceGroup = NULL;
+    }
+
+    if (This->PortStream)
+    {
+        This->PortStream->lpVtbl->Release(This->PortStream);
+        This->PortStream = NULL;
+    }
+
+    return Status;
+}
+
+static IPortPinWaveRTVtbl vt_IPortPinWaveRT =
+{
+    IPortPinWaveRT_fnQueryInterface,
+    IPortPinWaveRT_fnAddRef,
+    IPortPinWaveRT_fnRelease,
+    IPortPinWaveRT_fnNewIrpTarget,
+    IPortPinWaveRT_fnDeviceIoControl,
+    IPortPinWaveRT_fnRead,
+    IPortPinWaveRT_fnWrite,
+    IPortPinWaveRT_fnFlush,
+    IPortPinWaveRT_fnClose,
+    IPortPinWaveRT_fnQuerySecurity,
+    IPortPinWaveRT_fnSetSecurity,
+    IPortPinWaveRT_fnFastDeviceIoControl,
+    IPortPinWaveRT_fnFastRead,
+    IPortPinWaveRT_fnFastWrite,
+    IPortPinWaveRT_fnInit
+};
+
+NTSTATUS NewPortPinWaveRT(
+    OUT IPortPinWaveRT ** OutPin)
+{
+    IPortPinWaveRTImpl * This;
+
+    This = AllocateItem(NonPagedPool, sizeof(IPortPinWaveRTImpl), TAG_PORTCLASS);
+    if (!This)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    /* initialize IPortPinWaveRT */
+    This->ref = 1;
+    This->lpVtbl = &vt_IPortPinWaveRT;
+    This->lpVtblServiceSink = &vt_IServiceSink;
+
+    /* store result */
+    *OutPin = (IPortPinWaveRT*)&This->lpVtbl;
+
+    return STATUS_SUCCESS;
+}

Propchange: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavert.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: trunk/reactos/drivers/wdm/audio/backpln/portcls/port_wavert.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/portcls/port_wavert.c?rev=40797&view=auto
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/port_wavert.c (added)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/port_wavert.c [iso-8859-1] Tue May  5 20:01:39 2009
@@ -1,0 +1,676 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Kernel Streaming
+ * FILE:            drivers/wdm/audio/backpln/portcls/port_wavert.c
+ * PURPOSE:         WaveRT Port Driver
+ * PROGRAMMER:      Johannes Anderwald
+ */
+
+#include "private.h"
+
+typedef struct
+{
+    IPortWaveRTVtbl *lpVtbl;
+    IPortEventsVtbl *lpVbtlPortEvents;
+    IUnregisterSubdeviceVtbl *lpVtblUnregisterSubdevice;
+    IUnregisterPhysicalConnectionVtbl *lpVtblPhysicalConnection;
+    IPortEventsVtbl *lpVtblPortEvents;
+    ISubdeviceVtbl *lpVtblSubDevice;
+
+    LONG ref;
+
+    BOOL bInitialized;
+    PDEVICE_OBJECT pDeviceObject;
+    PMINIPORTWAVERT pMiniport;
+    PRESOURCELIST pResourceList;
+    PPINCOUNT pPinCount;
+    PPOWERNOTIFY pPowerNotify;
+    PPCFILTER_DESCRIPTOR pDescriptor;
+    PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor;
+    IPortFilterWaveRT * Filter;
+}IPortWaveRTImpl;
+
+static GUID InterfaceGuids[3] = 
+{
+    {
+        /// KSCATEGORY_RENDER
+        0x65E8773EL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
+    },
+    {
+        /// KSCATEGORY_CAPTURE
+        0x65E8773DL, 0x8F56, 0x11D0, {0xA3, 0xB9, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
+    },
+    {
+        /// KS_CATEGORY_AUDIO
+        0x6994AD04, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}
+    }
+};
+
+DEFINE_KSPROPERTY_TOPOLOGYSET(PortFilterWaveRTTopologySet, TopologyPropertyHandler);
+DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PortFilterWaveRTPinSet, PinPropertyHandler, PinPropertyHandler, PinPropertyHandler);
+
+KSPROPERTY_SET WaveRTPropertySet[] =
+{
+    {
+        &KSPROPSETID_Topology,
+        sizeof(PortFilterWaveRTTopologySet) / sizeof(KSPROPERTY_ITEM),
+        (const KSPROPERTY_ITEM*)&PortFilterWaveRTTopologySet,
+        0,
+        NULL
+    },
+    {
+        &KSPROPSETID_Pin,
+        sizeof(PortFilterWaveRTPinSet) / sizeof(KSPROPERTY_ITEM),
+        (const KSPROPERTY_ITEM*)&PortFilterWaveRTPinSet,
+        0,
+        NULL
+    }
+};
+
+//KSEVENTSETID_LoopedStreaming, Type = KSEVENT_LOOPEDSTREAMING_POSITION
+//KSEVENTSETID_Connection, Type = KSEVENT_CONNECTION_ENDOFSTREAM,
+
+
+
+#if 0
+static const KSIDENTIFIER Identifiers[] = 
+{
+    {
+        &KSINTERFACESETID_Standard,
+        0,
+        0
+    },
+    {
+        &KSINTERFACESETID_Standard,
+        1,
+        0
+    }
+};
+#endif
+
+//---------------------------------------------------------------
+// IPortEvents
+//
+
+static
+NTSTATUS
+NTAPI
+IPortEvents_fnQueryInterface(
+    IPortEvents* iface,
+    IN  REFIID refiid,
+    OUT PVOID* Output)
+{
+    IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblPortEvents);
+
+    DPRINT("IPortEvents_fnQueryInterface entered\n");
+
+    if (IsEqualGUIDAligned(refiid, &IID_IPortEvents) ||
+        IsEqualGUIDAligned(refiid, &IID_IUnknown))
+    {
+        *Output = &This->lpVbtlPortEvents;
+        InterlockedIncrement(&This->ref);
+        return STATUS_SUCCESS;
+    }
+    return STATUS_UNSUCCESSFUL;
+}
+
+static
+ULONG
+NTAPI
+IPortEvents_fnAddRef(
+    IPortEvents* iface)
+{
+    IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblPortEvents);
+    DPRINT("IPortEvents_fnQueryInterface entered\n");
+    return InterlockedIncrement(&This->ref);
+}
+
+static
+ULONG
+NTAPI
+IPortEvents_fnRelease(
+    IPortEvents* iface)
+{
+    IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblPortEvents);
+
+    DPRINT("IPortEvents_fnRelease entered\n");
+    InterlockedDecrement(&This->ref);
+
+    if (This->ref == 0)
+    {
+        FreeItem(This, TAG_PORTCLASS);
+        return 0;
+    }
+    /* Return new reference count */
+    return This->ref;
+}
+
+static
+void
+NTAPI
+IPortEvents_fnAddEventToEventList(
+    IPortEvents* iface,
+    IN PKSEVENT_ENTRY EventEntry)
+{
+    UNIMPLEMENTED
+}
+
+
+static
+void
+NTAPI
+IPortEvents_fnGenerateEventList(
+    IPortEvents* iface,
+    IN  GUID* Set OPTIONAL,
+    IN  ULONG EventId,
+    IN  BOOL PinEvent,
+    IN  ULONG PinId,
+    IN  BOOL NodeEvent,
+    IN  ULONG NodeId)
+{
+    UNIMPLEMENTED
+}
+
+static IPortEventsVtbl vt_IPortEvents = 
+{
+    IPortEvents_fnQueryInterface,
+    IPortEvents_fnAddRef,
+    IPortEvents_fnRelease,
+    IPortEvents_fnAddEventToEventList,
+    IPortEvents_fnGenerateEventList
+};
+
+//---------------------------------------------------------------
+// IUnknown interface functions
+//
+
+NTSTATUS
+NTAPI
+IPortWaveRT_fnQueryInterface(
+    IPortWaveRT* iface,
+    IN  REFIID refiid,
+    OUT PVOID* Output)
+{
+    UNICODE_STRING GuidString;
+    IPortWaveRTImpl * This = (IPortWaveRTImpl*)iface;
+
+    if (IsEqualGUIDAligned(refiid, &IID_IPortWaveRT) ||
+        IsEqualGUIDAligned(refiid, &IID_IUnknown))
+    {
+        *Output = &This->lpVtbl;
+        InterlockedIncrement(&This->ref);
+        return STATUS_SUCCESS;
+    }
+    else if (IsEqualGUIDAligned(refiid, &IID_IPortEvents))
+    {
+        *Output = &This->lpVtblPortEvents;
+        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("IPortWaveRT_fnQueryInterface no interface!!! iface %S\n", GuidString.Buffer);
+        RtlFreeUnicodeString(&GuidString);
+    }
+
+    return STATUS_UNSUCCESSFUL;
+}
+
+ULONG
+NTAPI
+IPortWaveRT_fnAddRef(
+    IPortWaveRT* iface)
+{
+    IPortWaveRTImpl * This = (IPortWaveRTImpl*)iface;
+
+    return InterlockedIncrement(&This->ref);
+}
+
+ULONG
+NTAPI
+IPortWaveRT_fnRelease(
+    IPortWaveRT* iface)
+{
+    IPortWaveRTImpl * This = (IPortWaveRTImpl*)iface;
+
+    InterlockedDecrement(&This->ref);
+
+    if (This->ref == 0)
+    {
+        if (This->bInitialized)
+        {
+            This->pMiniport->lpVtbl->Release(This->pMiniport);
+        }
+        if (This->pPinCount)
+            This->pPinCount->lpVtbl->Release(This->pPinCount);
+
+        if (This->pPowerNotify)
+            This->pPowerNotify->lpVtbl->Release(This->pPowerNotify);
+
+        FreeItem(This, TAG_PORTCLASS);
+        return 0;
+    }
+    /* Return new reference count */
+    return This->ref;
+}
+
+
+//---------------------------------------------------------------
+// IPort interface functions
+//
+
+NTSTATUS
+NTAPI
+IPortWaveRT_fnGetDeviceProperty(
+    IN IPortWaveRT * iface,
+    IN DEVICE_REGISTRY_PROPERTY  DeviceRegistryProperty,
+    IN ULONG  BufferLength,
+    OUT PVOID  PropertyBuffer,
+    OUT PULONG  ReturnLength)
+{
+    IPortWaveRTImpl * This = (IPortWaveRTImpl*)iface;
+    ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
+
+    if (!This->bInitialized)
+    {
+        DPRINT("IPortWaveRT_fnNewRegistryKey called w/o initiazed\n");
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    return IoGetDeviceProperty(This->pDeviceObject, DeviceRegistryProperty, BufferLength, PropertyBuffer, ReturnLength);
+}
+
+NTSTATUS
+NTAPI
+IPortWaveRT_fnInit(
+    IN IPortWaveRT * iface,
+    IN PDEVICE_OBJECT  DeviceObject,
+    IN PIRP  Irp,
+    IN PUNKNOWN  UnknownMiniport,
+    IN PUNKNOWN  UnknownAdapter  OPTIONAL,
+    IN PRESOURCELIST  ResourceList)
+{
+    IMiniportWaveRT * Miniport;
+    NTSTATUS Status;
+    PPINCOUNT PinCount;
+    PPOWERNOTIFY PowerNotify;
+    IPortWaveRTImpl * This = (IPortWaveRTImpl*)iface;
+
+    DPRINT("IPortWaveRT_Init entered %p\n", This);
+    ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
+
+    if (This->bInitialized)
+    {
+        DPRINT("IPortWaveRT_Init called again\n");
+        return STATUS_SUCCESS;
+    }
+
+    Status = UnknownMiniport->lpVtbl->QueryInterface(UnknownMiniport, &IID_IMiniportWaveRT, (PVOID*)&Miniport);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT("IPortWaveRT_Init called with invalid IMiniport adapter\n");
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Initialize port object */
+    This->pMiniport = Miniport;
+    This->pDeviceObject = DeviceObject;
+    This->bInitialized = TRUE;
+    This->pResourceList = ResourceList;
+
+    /* increment reference on miniport adapter */
+    Miniport->lpVtbl->AddRef(Miniport);
+
+    Status = Miniport->lpVtbl->Init(Miniport, UnknownAdapter, ResourceList, iface);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT("IMiniportWaveRT_Init failed with %x\n", Status);
+        Miniport->lpVtbl->Release(Miniport);
+        This->bInitialized = FALSE;
+        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;
+    }
+
+    /* create the subdevice descriptor */
+    Status = PcCreateSubdeviceDescriptor(&This->SubDeviceDescriptor, 
+                                         3,
+                                         InterfaceGuids,
+                                         0, 
+                                         NULL,
+                                         2, 
+                                         WaveRTPropertySet,
+                                         0,
+                                         0,
+                                         0,
+                                         NULL,
+                                         0,
+                                         NULL,
+                                         This->pDescriptor);
+
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("PcCreateSubdeviceDescriptor failed with %x\n", Status);
+        Miniport->lpVtbl->Release(Miniport);
+        This->bInitialized = FALSE;
+        return Status;
+    }
+
+    /* 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;
+    }
+
+    /* increment reference on resource list */
+    ResourceList->lpVtbl->AddRef(ResourceList);
+
+
+    DPRINT("IPortWaveRT successfully initialized\n");
+    return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+NTAPI
+IPortWaveRT_fnNewRegistryKey(
+    IN IPortWaveRT * 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)
+{
+    IPortWaveRTImpl * This = (IPortWaveRTImpl*)iface;
+
+    ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
+
+    if (!This->bInitialized)
+    {
+        DPRINT("IPortWaveRT_fnNewRegistryKey called w/o initialized\n");
+        return STATUS_UNSUCCESSFUL;
+    }
+    return PcNewRegistryKey(OutRegistryKey, OuterUnknown, RegistryKeyType, DesiredAccess, This->pDeviceObject, NULL /*FIXME*/, ObjectAttributes, CreateOptions, Disposition);
+}
+
+static IPortWaveRTVtbl vt_IPortWaveRTVtbl =
+{
+    IPortWaveRT_fnQueryInterface,
+    IPortWaveRT_fnAddRef,
+    IPortWaveRT_fnRelease,
+    IPortWaveRT_fnInit,
+    IPortWaveRT_fnGetDeviceProperty,
+    IPortWaveRT_fnNewRegistryKey
+};
+
+//---------------------------------------------------------------
+// ISubdevice interface
+//
+
+static
+NTSTATUS
+NTAPI
+ISubDevice_fnQueryInterface(
+    IN ISubdevice *iface,
+    IN REFIID InterfaceId,
+    IN PVOID* Interface)
+{
+    IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
+
+    return IPortWaveRT_fnQueryInterface((IPortWaveRT*)This, InterfaceId, Interface);
+}
+
+static
+ULONG
+NTAPI
+ISubDevice_fnAddRef(
+    IN ISubdevice *iface)
+{
+    IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
+
+    return IPortWaveRT_fnAddRef((IPortWaveRT*)This);
+}
+
+static
+ULONG
+NTAPI
+ISubDevice_fnRelease(
+    IN ISubdevice *iface)
+{
+    IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
+
+    return IPortWaveRT_fnRelease((IPortWaveRT*)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;
+    IPortFilterWaveRT * Filter;
+    IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
+
+    DPRINT("ISubDevice_NewIrpTarget this %p\n", This);
+
+    if (This->Filter)
+    {
+        *OutTarget = (IIrpTarget*)This->Filter;
+        return STATUS_SUCCESS;
+    }
+
+
+    Status = NewPortFilterWaveRT(&Filter);
+    if (!NT_SUCCESS(Status))
+    {
+        return Status;
+    }
+
+    Status = Filter->lpVtbl->Init(Filter, (IPortWaveRT*)This);
+    if (!NT_SUCCESS(Status))
+    {
+        Filter->lpVtbl->Release(Filter);
+        return Status;
+    }
+
+    *OutTarget = (IIrpTarget*)Filter;
+    return Status;
+}
+
+static
+NTSTATUS
+NTAPI
+ISubDevice_fnReleaseChildren(
+    IN ISubdevice *iface)
+{
+    //IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
+
+    UNIMPLEMENTED
+    return STATUS_UNSUCCESSFUL;
+}
+
+static
+NTSTATUS
+NTAPI
+ISubDevice_fnGetDescriptor(
+    IN ISubdevice *iface,
+    IN SUBDEVICE_DESCRIPTOR ** Descriptor)
+{
+    IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, lpVtblSubDevice);
+
+    ASSERT(This->SubDeviceDescriptor != NULL);
+
+    *Descriptor = This->SubDeviceDescriptor;
+
+    DPRINT("ISubDevice_GetDescriptor this %p desc %p\n", This, 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)
+{
+    IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, 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)
+{
+    IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, 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)
+{
+    IPortWaveRTImpl * This = (IPortWaveRTImpl*)CONTAINING_RECORD(iface, IPortWaveRTImpl, 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
+};
+
+
+///--------------------------------------------------------------
+PMINIPORTWAVERT
+GetWaveRTMiniport(
+    IN IPortWaveRT* iface)
+{
+    IPortWaveRTImpl * This = (IPortWaveRTImpl *)iface;
+    return This->pMiniport;
+}
+
+PDEVICE_OBJECT
+GetDeviceObjectFromPortWaveRT(
+    PPORTWAVERT iface)
+{
+    IPortWaveRTImpl * This = (IPortWaveRTImpl *)iface;
+    return This->pDeviceObject;
+}
+
+//---------------------------------------------------------------
+// IPortWaveRT constructor
+//
+
+NTSTATUS
+NewPortWaveRT(
+    OUT PPORT* OutPort)
+{
+    IPortWaveRTImpl * This;
+
+    This = AllocateItem(NonPagedPool, sizeof(IPortWaveRTImpl), TAG_PORTCLASS);
+    if (!This)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    This->lpVtbl = &vt_IPortWaveRTVtbl;
+    This->lpVtblSubDevice = &vt_ISubdeviceVtbl;
+    This->lpVtblPortEvents = &vt_IPortEvents;
+    This->ref = 1;
+    *OutPort = (PPORT)(&This->lpVtbl);
+
+    DPRINT("NewPortWaveRT %p\n", *OutPort);
+
+    return STATUS_SUCCESS;
+}
+

Propchange: trunk/reactos/drivers/wdm/audio/backpln/portcls/port_wavert.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: trunk/reactos/drivers/wdm/audio/backpln/portcls/port_wavertstream.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/portcls/port_wavertstream.c?rev=40797&view=auto
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/port_wavertstream.c (added)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/port_wavertstream.c [iso-8859-1] Tue May  5 20:01:39 2009
@@ -1,0 +1,247 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS Kernel Streaming
+ * FILE:            drivers/wdm/audio/backpln/portcls/port_wavertstream.c
+ * PURPOSE:         WaveRTStream helper object
+ * PROGRAMMER:      Johannes Anderwald
+ */
+
+#include "private.h"
+
+typedef struct
+{
+    IPortWaveRTStreamVtbl *lpVtbl;
+    LONG ref;
+
+}IPortWaveRTStreamImpl;
+
+/*
+ * @implemented
+ */
+static
+NTSTATUS
+NTAPI
+IPortWaveRTStream_fnQueryInterface(
+    IPortWaveRTStream* iface,
+    IN  REFIID refiid,
+    OUT PVOID* Output)
+{
+    IPortWaveRTStreamImpl * This = (IPortWaveRTStreamImpl*)iface;
+
+    DPRINT("IPortWaveRTStream_fnQueryInterface entered\n");
+
+    if (IsEqualGUIDAligned(refiid, &IID_IPortWaveRTStream) ||
+        IsEqualGUIDAligned(refiid, &IID_IUnknown))
+    {
+        *Output = &This->lpVtbl;
+        InterlockedIncrement(&This->ref);
+        return STATUS_SUCCESS;
+    }
+    return STATUS_UNSUCCESSFUL;
+}
+
+/*
+ * @implemented
+ */
+static
+ULONG
+NTAPI
+IPortWaveRTStream_fnAddRef(
+    IPortWaveRTStream* iface)
+{
+    IPortWaveRTStreamImpl * This = (IPortWaveRTStreamImpl*)iface;
+    DPRINT("IPortWaveRTStream_fnAddRef entered\n");
+
+    return InterlockedIncrement(&This->ref);
+}
+
+/*
+ * @implemented
+ */
+static
+ULONG
+NTAPI
+IPortWaveRTStream_fnRelease(
+    IPortWaveRTStream* iface)
+{
+    IPortWaveRTStreamImpl * This = (IPortWaveRTStreamImpl*)iface;
+
+    InterlockedDecrement(&This->ref);
+
+    DPRINT("IPortWaveRTStream_fnRelease entered %u\n", This->ref);
+
+    if (This->ref == 0)
+    {
+        FreeItem(This, TAG_PORTCLASS);
+        return 0;
+    }
+    /* Return new reference count */
+    return This->ref;
+}
+
+/*
+ * @implemented
+ */
+static
+PMDL
+NTAPI
+IPortWaveRTStream_fnAllocatePagesForMdl(
+    IN IPortWaveRTStream* iface,
+    IN PHYSICAL_ADDRESS HighAddress,
+    IN SIZE_T TotalBytes)
+{
+    return MmAllocatePagesForMdl(RtlConvertUlongToLargeInteger(0), HighAddress, RtlConvertUlongToLargeInteger(0), TotalBytes);
+}
+
+/*
+ * @implemented
+ */
+static
+PMDL
+NTAPI
+IPortWaveRTStream_fnAllocateContiguousPagesForMdl(
+    IN IPortWaveRTStream* iface,
+    IN PHYSICAL_ADDRESS LowAddress,
+    IN PHYSICAL_ADDRESS HighAddress,
+    IN SIZE_T TotalBytes)
+{
+    PMDL Mdl;
+    PVOID Buffer;
+    PHYSICAL_ADDRESS Address;
+
+    Buffer = MmAllocateContiguousMemorySpecifyCache(TotalBytes, LowAddress, HighAddress, RtlConvertUlongToLargeInteger(0), MmNonCached);
+    if (!Buffer)
+    {
+        DPRINT1("MmAllocateContiguousMemorySpecifyCache failed\n");
+        return NULL;
+    }
+
+    Address = MmGetPhysicalAddress(Buffer);
+
+    MmFreeContiguousMemorySpecifyCache(Buffer, TotalBytes, MmNonCached);
+
+    Mdl = MmAllocatePagesForMdl(Address, HighAddress, RtlConvertUlongToLargeInteger(0), TotalBytes);
+    if (!Mdl)
+    {
+        DPRINT1("MmAllocatePagesForMdl failed\n");
+        return NULL;
+    }
+
+    if (MmGetMdlByteCount(Mdl) < TotalBytes)
+    {
+        MmFreePagesFromMdl(Mdl);
+        ExFreePool(Mdl);
+        return NULL;
+    }
+
+    return NULL;
+}
+
+/*
+ * @implemented
+ */
+static
+PVOID
+NTAPI
+IPortWaveRTStream_fnMapAllocatedPages(
+    IN IPortWaveRTStream* iface,
+    IN PMDL MemoryDescriptorList,
+    IN MEMORY_CACHING_TYPE CacheType)
+{
+    return MmMapLockedPagesSpecifyCache(MemoryDescriptorList, KernelMode, CacheType, NULL, 0, NormalPagePriority);
+}
+
+/*
+ * @implemented
+ */
+static
+VOID
+NTAPI
+IPortWaveRTStream_fnUnmapAllocatedPages(
+    IN IPortWaveRTStream* iface,
+    IN PVOID   BaseAddress,
+    IN PMDL MemoryDescriptorList)
+{
+    MmUnmapLockedPages(BaseAddress, MemoryDescriptorList);
+}
+
+/*
+ * @implemented
+ */
+static
+VOID
+NTAPI
+IPortWaveRTStream_fnFreePagesFromMdl(
+    IN IPortWaveRTStream* iface,
+    IN PMDL MemoryDescriptorList)
+{
+    MmFreePagesFromMdl(MemoryDescriptorList);
+    ExFreePool(MemoryDescriptorList);
+}
+
+/*
+ * @implemented
+ */
+static
+ULONG
+NTAPI
+IPortWaveRTStream_fnGetPhysicalPagesCount(
+    IN IPortWaveRTStream* iface,
+    IN PMDL MemoryDescriptorList)
+{
+    return ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, MmGetMdlByteCount(MemoryDescriptorList));
+}
+
+/*
+ * @implemented
+ */
+static
+PHYSICAL_ADDRESS
+NTAPI
+IPortWaveRTStream_fnGetPhysicalPageAddress(
+    IN IPortWaveRTStream* iface,
+    IN PMDL    MemoryDescriptorList,
+    IN ULONG Index)
+{
+    PVOID Buffer;
+    ULONG Pages;
+
+    Pages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(0, MmGetMdlByteCount(MemoryDescriptorList));
+    if (Pages <= Index)
+    {
+        DPRINT1("OutOfBounds: Pages %u Index %u\n", Pages, Index);
+        return RtlConvertUlongToLargeInteger(0);
+    }
+
+    Buffer = UlongToPtr(PtrToUlong(MmGetSystemAddressForMdl(MemoryDescriptorList)) + Index * PAGE_SIZE);
+    return MmGetPhysicalAddress(Buffer);
+}
+
+static IPortWaveRTStreamVtbl vt_PortWaveRTStream =
+{
+    IPortWaveRTStream_fnQueryInterface,
+    IPortWaveRTStream_fnAddRef,
+    IPortWaveRTStream_fnRelease,
+    IPortWaveRTStream_fnAllocatePagesForMdl,
+    IPortWaveRTStream_fnAllocateContiguousPagesForMdl,
+    IPortWaveRTStream_fnMapAllocatedPages,
+    IPortWaveRTStream_fnUnmapAllocatedPages,
+    IPortWaveRTStream_fnFreePagesFromMdl,
+    IPortWaveRTStream_fnGetPhysicalPagesCount,
+    IPortWaveRTStream_fnGetPhysicalPageAddress
+};
+
+NTSTATUS
+NewPortWaveRTStream(
+    PPORTWAVERTSTREAM *OutStream)
+{
+    IPortWaveRTStreamImpl* This = AllocateItem(NonPagedPool, sizeof(IPortWaveRTStreamImpl), TAG_PORTCLASS);
+    if (!This)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    This->ref = 1;
+    This->lpVtbl = &vt_PortWaveRTStream;
+
+    *OutStream = (PPORTWAVERTSTREAM)&This->lpVtbl;
+    return STATUS_SUCCESS;
+}

Propchange: trunk/reactos/drivers/wdm/audio/backpln/portcls/port_wavertstream.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/private.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/portcls/private.h?rev=40797&r1=40796&r2=40797&view=diff
==============================================================================
--- trunk/reactos/drivers/wdm/audio/backpln/portcls/private.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/wdm/audio/backpln/portcls/private.h [iso-8859-1] Tue May  5 20:01:39 2009
@@ -108,6 +108,25 @@
 PMINIPORTWAVEPCI
 GetWavePciMiniport(
     PPORTWAVEPCI Port);
+
+NTSTATUS 
+NewPortFilterWaveRT(
+    OUT IPortFilterWaveRT ** OutFilter);
+
+NTSTATUS NewPortPinWaveRT(
+    OUT IPortPinWaveRT ** OutPin);
+
+PMINIPORTWAVERT
+GetWaveRTMiniport(
+    IN IPortWaveRT* iface);
+
+PDEVICE_OBJECT
+GetDeviceObjectFromPortWaveRT(
+    IPortWaveRT* iface);
+
+NTSTATUS
+NewPortWaveRTStream(
+    PPORTWAVERTSTREAM *OutStream);
 
 NTSTATUS
 NTAPI



More information about the Ros-diffs mailing list