1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Kernel Streaming
4  * FILE:            drivers/wdm/audio/backpln/portcls/filter_wavepci.cpp
5  * PURPOSE:         portcls wave pci filter
6  * PROGRAMMER:      Johannes Anderwald
7  */
8 
9 #include "private.hpp"
10 
11 #define NDEBUG
12 #include <debug.h>
13 
14 class CPortFilterWavePci : public CUnknownImpl<IPortFilterWavePci>
15 {
16 public:
17     STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
18 
19     IMP_IPortFilterPci;
CPortFilterWavePci(IUnknown * OuterUnknown)20     CPortFilterWavePci(IUnknown *OuterUnknown){}
~CPortFilterWavePci()21     virtual ~CPortFilterWavePci(){}
22 
23 protected:
24     IPortWavePci* m_Port;
25     IPortPinWavePci ** m_Pins;
26     SUBDEVICE_DESCRIPTOR * m_Descriptor;
27 };
28 
29 NTSTATUS
30 NTAPI
QueryInterface(IN REFIID refiid,OUT PVOID * Output)31 CPortFilterWavePci::QueryInterface(
32 
33     IN  REFIID refiid,
34     OUT PVOID* Output)
35 {
36 
37     if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) ||
38         IsEqualGUIDAligned(refiid, IID_IUnknown))
39     {
40         *Output = PVOID(PUNKNOWN(this));
41         PUNKNOWN(*Output)->AddRef();
42         return STATUS_SUCCESS;
43     }
44     else if (IsEqualGUIDAligned(refiid, IID_IPort))
45     {
46         *Output = PUNKNOWN(m_Port);
47         PUNKNOWN(*Output)->AddRef();
48         return STATUS_SUCCESS;
49     }
50 
51     return STATUS_UNSUCCESSFUL;
52 }
53 
54 NTSTATUS
55 NTAPI
NewIrpTarget(OUT struct IIrpTarget ** OutTarget,IN PCWSTR Name,IN PUNKNOWN Unknown,IN POOL_TYPE PoolType,IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN KSOBJECT_CREATE * CreateObject)56 CPortFilterWavePci::NewIrpTarget(
57     OUT struct IIrpTarget **OutTarget,
58     IN PCWSTR Name,
59     IN PUNKNOWN Unknown,
60     IN POOL_TYPE PoolType,
61     IN PDEVICE_OBJECT DeviceObject,
62     IN PIRP Irp,
63     IN KSOBJECT_CREATE *CreateObject)
64 {
65     NTSTATUS Status;
66     IPortPinWavePci * Pin;
67     PKSPIN_CONNECT ConnectDetails;
68 
69 #if 0
70     ASSERT(m_Port);
71     ASSERT(m_Descriptor);
72     ASSERT(m_Pins);
73 #endif
74 
75     DPRINT("CPortFilterWavePci::NewIrpTarget entered\n");
76 
77     // let's verify the connection request
78     Status = PcValidateConnectRequest(Irp, &m_Descriptor->Factory, &ConnectDetails);
79     if (!NT_SUCCESS(Status))
80     {
81         return STATUS_UNSUCCESSFUL;
82     }
83 
84     if (m_Pins[ConnectDetails->PinId] &&
85         (m_Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount == m_Descriptor->Factory.Instances[ConnectDetails->PinId].MaxFilterInstanceCount))
86     {
87         // no available instance
88         return STATUS_UNSUCCESSFUL;
89     }
90 
91     // now create the pin
92     Status = NewPortPinWavePci(&Pin);
93     if (!NT_SUCCESS(Status))
94     {
95         return Status;
96     }
97 
98     // initialize the pin
99     Status = Pin->Init(m_Port, this, ConnectDetails, &m_Descriptor->Factory.KsPinDescriptor[ConnectDetails->PinId], GetDeviceObjectFromPortWavePci(m_Port));
100     if (!NT_SUCCESS(Status))
101     {
102         Pin->Release();
103         return Status;
104     }
105 
106     // store pin
107     m_Pins[ConnectDetails->PinId] = Pin;
108 
109     // store result
110     *OutTarget = (IIrpTarget*)Pin;
111 
112     // increment current instance count
113     m_Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount++;
114 
115     return Status;
116 }
117 
118 NTSTATUS
119 NTAPI
DeviceIoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)120 CPortFilterWavePci::DeviceIoControl(
121     IN PDEVICE_OBJECT DeviceObject,
122     IN PIRP Irp)
123 {
124     PIO_STACK_LOCATION IoStack;
125     NTSTATUS Status;
126 
127     IoStack = IoGetCurrentIrpStackLocation(Irp);
128 
129     if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY)
130     {
131         DPRINT("Unhandled function %lx Length %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode, IoStack->Parameters.DeviceIoControl.InputBufferLength);
132 
133         Irp->IoStatus.Status = STATUS_SUCCESS;
134 
135         IoCompleteRequest(Irp, IO_NO_INCREMENT);
136         return STATUS_SUCCESS;
137     }
138 
139     Status = PcHandlePropertyWithTable(Irp, m_Descriptor->FilterPropertySetCount, m_Descriptor->FilterPropertySet, m_Descriptor);
140     if (Status != STATUS_PENDING)
141     {
142         Irp->IoStatus.Status = Status;
143         DPRINT("Result %x Length %u\n", Status, Irp->IoStatus.Information);
144         IoCompleteRequest(Irp, IO_NO_INCREMENT);
145     }
146     return Status;
147 }
148 
149 NTSTATUS
150 NTAPI
Read(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)151 CPortFilterWavePci::Read(
152     IN PDEVICE_OBJECT DeviceObject,
153     IN PIRP Irp)
154 {
155     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
156 }
157 
158 NTSTATUS
159 NTAPI
Write(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)160 CPortFilterWavePci::Write(
161     IN PDEVICE_OBJECT DeviceObject,
162     IN PIRP Irp)
163 {
164     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
165 }
166 
167 NTSTATUS
168 NTAPI
Flush(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)169 CPortFilterWavePci::Flush(
170     IN PDEVICE_OBJECT DeviceObject,
171     IN PIRP Irp)
172 {
173     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
174 }
175 
176 NTSTATUS
177 NTAPI
Close(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)178 CPortFilterWavePci::Close(
179     IN PDEVICE_OBJECT DeviceObject,
180     IN PIRP Irp)
181 {
182     Irp->IoStatus.Status = STATUS_SUCCESS;
183     Irp->IoStatus.Information = 0;
184     IoCompleteRequest(Irp, IO_NO_INCREMENT);
185 
186     return STATUS_UNSUCCESSFUL;
187 }
188 
189 NTSTATUS
190 NTAPI
QuerySecurity(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)191 CPortFilterWavePci::QuerySecurity(
192     IN PDEVICE_OBJECT DeviceObject,
193     IN PIRP Irp)
194 {
195     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
196 }
197 
198 NTSTATUS
199 NTAPI
SetSecurity(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)200 CPortFilterWavePci::SetSecurity(
201     IN PDEVICE_OBJECT DeviceObject,
202     IN PIRP Irp)
203 {
204     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
205 }
206 
207 BOOLEAN
208 NTAPI
FastDeviceIoControl(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)209 CPortFilterWavePci::FastDeviceIoControl(
210     IN PFILE_OBJECT FileObject,
211     IN BOOLEAN Wait,
212     IN PVOID InputBuffer,
213     IN ULONG InputBufferLength,
214     OUT PVOID OutputBuffer,
215     IN ULONG OutputBufferLength,
216     IN ULONG IoControlCode,
217     OUT PIO_STATUS_BLOCK StatusBlock,
218     IN PDEVICE_OBJECT DeviceObject)
219 {
220     return FALSE;
221 }
222 
223 BOOLEAN
224 NTAPI
FastRead(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)225 CPortFilterWavePci::FastRead(
226     IN PFILE_OBJECT FileObject,
227     IN PLARGE_INTEGER FileOffset,
228     IN ULONG Length,
229     IN BOOLEAN Wait,
230     IN ULONG LockKey,
231     IN PVOID Buffer,
232     OUT PIO_STATUS_BLOCK StatusBlock,
233     IN PDEVICE_OBJECT DeviceObject)
234 {
235     return FALSE;
236 }
237 
238 BOOLEAN
239 NTAPI
FastWrite(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)240 CPortFilterWavePci::FastWrite(
241     IN PFILE_OBJECT FileObject,
242     IN PLARGE_INTEGER FileOffset,
243     IN ULONG Length,
244     IN BOOLEAN Wait,
245     IN ULONG LockKey,
246     IN PVOID Buffer,
247     OUT PIO_STATUS_BLOCK StatusBlock,
248     IN PDEVICE_OBJECT DeviceObject)
249 {
250     return FALSE;
251 }
252 
253 NTSTATUS
254 NTAPI
Init(IN IPortWavePci * Port)255 CPortFilterWavePci::Init(
256     IN IPortWavePci* Port)
257 {
258     ISubdevice * ISubDevice;
259     SUBDEVICE_DESCRIPTOR * Descriptor;
260     NTSTATUS Status;
261 
262     m_Port = Port;
263 
264     // get our private interface
265     Status = m_Port->QueryInterface(IID_ISubdevice, (PVOID*)&ISubDevice);
266     if (!NT_SUCCESS(Status))
267         return STATUS_UNSUCCESSFUL;
268 
269     // get the subdevice descriptor
270     Status = ISubDevice->GetDescriptor(&Descriptor);
271 
272     // release subdevice interface
273     ISubDevice->Release();
274 
275     if (!NT_SUCCESS(Status))
276         return STATUS_UNSUCCESSFUL;
277 
278     // save descriptor
279     m_Descriptor = Descriptor;
280 
281     // allocate pin array
282     m_Pins = (IPortPinWavePci**)AllocateItem(NonPagedPool, Descriptor->Factory.PinDescriptorCount * sizeof(IPortPinWavePci*), TAG_PORTCLASS);
283 
284     if (!m_Pins)
285         return STATUS_UNSUCCESSFUL;
286 
287     // increment reference count
288     Port->AddRef();
289 
290     return STATUS_SUCCESS;
291 }
292 
293 NTSTATUS
294 NTAPI
FreePin(IN struct IPortPinWavePci * Pin)295 CPortFilterWavePci::FreePin(
296     IN struct IPortPinWavePci* Pin)
297 {
298     ULONG Index;
299 
300     for(Index = 0; Index < m_Descriptor->Factory.PinDescriptorCount; Index++)
301     {
302         if (m_Pins[Index] == Pin)
303         {
304             m_Descriptor->Factory.Instances[Index].CurrentPinInstanceCount--;
305             m_Pins[Index] = NULL;
306             return STATUS_SUCCESS;
307         }
308     }
309     return STATUS_UNSUCCESSFUL;
310 }
311 
312 NTSTATUS
NewPortFilterWavePci(OUT IPortFilterWavePci ** OutFilter)313 NewPortFilterWavePci(
314     OUT IPortFilterWavePci ** OutFilter)
315 {
316     CPortFilterWavePci * This;
317 
318     This = new(NonPagedPool, TAG_PORTCLASS)CPortFilterWavePci(NULL);
319     if (!This)
320         return STATUS_INSUFFICIENT_RESOURCES;
321 
322     This->AddRef();
323 
324     // return result
325     *OutFilter = (IPortFilterWavePci*)This;
326 
327     return STATUS_SUCCESS;
328 }
329