- Implement CPortFilterWaveCyclic::FastDeviceIoControl
[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
139 IoStack = IoGetCurrentIrpStackLocation(Irp);
140
141 if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY)
142 {
143 DPRINT1("Unhandled function %lx Length %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode, IoStack->Parameters.DeviceIoControl.InputBufferLength);
144
145 Irp->IoStatus.Status = STATUS_SUCCESS;
146
147 IoCompleteRequest(Irp, IO_NO_INCREMENT);
148 return STATUS_SUCCESS;
149 }
150
151 PC_ASSERT(IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY);
152
153 return PcPropertyHandler(Irp, m_Descriptor);
154 }
155
156 NTSTATUS
157 NTAPI
158 CPortFilterWaveCyclic::Read(
159 IN PDEVICE_OBJECT DeviceObject,
160 IN PIRP Irp)
161 {
162 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
163 }
164
165 NTSTATUS
166 NTAPI
167 CPortFilterWaveCyclic::Write(
168 IN PDEVICE_OBJECT DeviceObject,
169 IN PIRP Irp)
170 {
171 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
172 }
173
174 NTSTATUS
175 NTAPI
176 CPortFilterWaveCyclic::Flush(
177 IN PDEVICE_OBJECT DeviceObject,
178 IN PIRP Irp)
179 {
180 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
181 }
182
183 NTSTATUS
184 NTAPI
185 CPortFilterWaveCyclic::Close(
186 IN PDEVICE_OBJECT DeviceObject,
187 IN PIRP Irp)
188 {
189 //ULONG Index;
190 NTSTATUS Status = STATUS_SUCCESS;
191
192 #if 0
193 if (m_ref == 1)
194 {
195 for(Index = 0; Index < m_Descriptor->Factory.PinDescriptorCount; Index++)
196 {
197 // all pins should have been closed by now
198 ASSERT(m_Pins[Index] == NULL);
199 }
200
201 // release reference to port
202 m_SubDevice->Release(m_SubDevice);
203
204 // time to shutdown the audio system
205 Status = m_SubDevice->ReleaseChildren(m_SubDevice);
206 }
207 #endif
208
209 Irp->IoStatus.Status = Status;
210 Irp->IoStatus.Information = 0;
211 IoCompleteRequest(Irp, IO_NO_INCREMENT);
212
213 return STATUS_SUCCESS;
214 }
215
216 NTSTATUS
217 NTAPI
218 CPortFilterWaveCyclic::QuerySecurity(
219 IN PDEVICE_OBJECT DeviceObject,
220 IN PIRP Irp)
221 {
222 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
223 }
224
225 NTSTATUS
226 NTAPI
227 CPortFilterWaveCyclic::SetSecurity(
228 IN PDEVICE_OBJECT DeviceObject,
229 IN PIRP Irp)
230 {
231 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
232 }
233
234 BOOLEAN
235 NTAPI
236 CPortFilterWaveCyclic::FastDeviceIoControl(
237 IN PFILE_OBJECT FileObject,
238 IN BOOLEAN Wait,
239 IN PVOID InputBuffer,
240 IN ULONG InputBufferLength,
241 OUT PVOID OutputBuffer,
242 IN ULONG OutputBufferLength,
243 IN ULONG IoControlCode,
244 OUT PIO_STATUS_BLOCK StatusBlock,
245 IN PDEVICE_OBJECT DeviceObject)
246 {
247 return KsDispatchFastIoDeviceControlFailure(FileObject, Wait, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, IoControlCode, StatusBlock, DeviceObject);
248 }
249
250 BOOLEAN
251 NTAPI
252 CPortFilterWaveCyclic::FastRead(
253 IN PFILE_OBJECT FileObject,
254 IN PLARGE_INTEGER FileOffset,
255 IN ULONG Length,
256 IN BOOLEAN Wait,
257 IN ULONG LockKey,
258 IN PVOID Buffer,
259 OUT PIO_STATUS_BLOCK StatusBlock,
260 IN PDEVICE_OBJECT DeviceObject)
261 {
262 UNIMPLEMENTED
263 return FALSE;
264 }
265
266 BOOLEAN
267 NTAPI
268 CPortFilterWaveCyclic::FastWrite(
269 IN PFILE_OBJECT FileObject,
270 IN PLARGE_INTEGER FileOffset,
271 IN ULONG Length,
272 IN BOOLEAN Wait,
273 IN ULONG LockKey,
274 IN PVOID Buffer,
275 OUT PIO_STATUS_BLOCK StatusBlock,
276 IN PDEVICE_OBJECT DeviceObject)
277 {
278 UNIMPLEMENTED
279 return FALSE;
280 }
281
282 NTSTATUS
283 NTAPI
284 CPortFilterWaveCyclic::Init(
285 IN IPortWaveCyclic* Port)
286 {
287 ISubdevice * ISubDevice;
288 SUBDEVICE_DESCRIPTOR * Descriptor;
289 NTSTATUS Status;
290
291 // get our private interface
292 Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&ISubDevice);
293 if (!NT_SUCCESS(Status))
294 return STATUS_UNSUCCESSFUL;
295
296 // get the subdevice descriptor
297 Status = ISubDevice->GetDescriptor(&Descriptor);
298
299 // store subdevice interface
300 m_SubDevice = ISubDevice;
301
302 if (!NT_SUCCESS(Status))
303 return STATUS_UNSUCCESSFUL;
304
305 // save descriptor
306 m_Descriptor = Descriptor;
307
308 // allocate pin array
309 m_Pins = (IPortPinWaveCyclic**)AllocateItem(NonPagedPool, Descriptor->Factory.PinDescriptorCount * sizeof(IPortPinWaveCyclic*), TAG_PORTCLASS);
310
311 if (!m_Pins)
312 return STATUS_UNSUCCESSFUL;
313
314 // store port driver
315 m_Port = Port;
316
317 return STATUS_SUCCESS;
318 }
319
320
321 NTSTATUS
322 NTAPI
323 CPortFilterWaveCyclic::FreePin(
324 IN struct IPortPinWaveCyclic* Pin)
325 {
326 ULONG Index;
327
328 for(Index = 0; Index < m_Descriptor->Factory.PinDescriptorCount; Index++)
329 {
330 if (m_Pins[Index] == Pin)
331 {
332 m_Descriptor->Factory.Instances[Index].CurrentPinInstanceCount--;
333 m_Pins[Index]->Release();
334 m_Pins[Index] = NULL;
335 return STATUS_SUCCESS;
336 }
337 }
338 return STATUS_UNSUCCESSFUL;
339 }
340
341
342 NTSTATUS
343 NewPortFilterWaveCyclic(
344 OUT IPortFilterWaveCyclic ** OutFilter)
345 {
346 CPortFilterWaveCyclic * This;
347
348 This = new(NonPagedPool, TAG_PORTCLASS)CPortFilterWaveCyclic(NULL);
349
350 if (!This)
351 return STATUS_INSUFFICIENT_RESOURCES;
352
353 This->AddRef();
354
355 // return result
356 *OutFilter = (IPortFilterWaveCyclic*)This;
357
358 return STATUS_SUCCESS;
359 }
360