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