- Implement PcHandlePropertyWithTable
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / filter_dmus.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/filter_dmus.cpp
5 * PURPOSE: portcls wave pci filter
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "private.hpp"
10
11 class CPortFilterDMus : public IPortFilterDMus
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_IPortFilterDMus;
33 CPortFilterDMus(IUnknown *OuterUnknown){}
34 virtual ~CPortFilterDMus(){}
35
36 protected:
37 IPortDMus* m_Port;
38 IPortPinDMus ** m_Pins;
39 SUBDEVICE_DESCRIPTOR * m_Descriptor;
40 LONG m_Ref;
41 };
42
43 NTSTATUS
44 NTAPI
45 CPortFilterDMus::QueryInterface(
46 IN REFIID refiid,
47 OUT PVOID* Output)
48 {
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 CPortFilterDMus::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 IPortPinDMus * Pin;
80 PKSPIN_CONNECT ConnectDetails;
81
82 PC_ASSERT(m_Port);
83 PC_ASSERT(m_Descriptor);
84 PC_ASSERT(m_Pins);
85
86 DPRINT("CPortFilterDMus::NewIrpTarget entered\n");
87
88 // let's verify the connection request
89 Status = PcValidateConnectRequest(Irp, &m_Descriptor->Factory, &ConnectDetails);
90 if (!NT_SUCCESS(Status))
91 {
92 return STATUS_UNSUCCESSFUL;
93 }
94
95 if (m_Pins[ConnectDetails->PinId] && m_Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount)
96 {
97 // release existing instance
98 PC_ASSERT(0);
99 }
100
101 // now create the pin
102 Status = NewPortPinDMus(&Pin);
103 if (!NT_SUCCESS(Status))
104 {
105 return Status;
106 }
107
108 // initialize the pin
109 Status = Pin->Init(m_Port, this, ConnectDetails, &m_Descriptor->Factory.KsPinDescriptor[ConnectDetails->PinId], DeviceObject);
110 if (!NT_SUCCESS(Status))
111 {
112 Pin->Release();
113 return Status;
114 }
115
116 // store pin
117 m_Pins[ConnectDetails->PinId] = Pin;
118
119 // store result
120 *OutTarget = (IIrpTarget*)Pin;
121
122 // increment current instance count
123 m_Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount++;
124
125 return Status;
126 }
127
128 NTSTATUS
129 NTAPI
130 CPortFilterDMus::DeviceIoControl(
131 IN PDEVICE_OBJECT DeviceObject,
132 IN PIRP Irp)
133 {
134 PIO_STACK_LOCATION IoStack;
135 NTSTATUS Status;
136
137 IoStack = IoGetCurrentIrpStackLocation(Irp);
138
139 if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_PROPERTY)
140 {
141 DPRINT1("Unhandled function %lx Length %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode, IoStack->Parameters.DeviceIoControl.InputBufferLength);
142
143 Irp->IoStatus.Status = STATUS_SUCCESS;
144
145 IoCompleteRequest(Irp, IO_NO_INCREMENT);
146 return STATUS_SUCCESS;
147 }
148
149 Status = PcHandlePropertyWithTable(Irp, m_Descriptor->FilterPropertySetCount, m_Descriptor->FilterPropertySet, m_Descriptor);
150 if (Status != STATUS_PENDING)
151 {
152 Irp->IoStatus.Status = Status;
153 DPRINT("Result %x Length %u\n", Status, Irp->IoStatus.Information);
154 IoCompleteRequest(Irp, IO_NO_INCREMENT);
155 }
156 return Status;
157 }
158
159 NTSTATUS
160 NTAPI
161 CPortFilterDMus::Read(
162 IN PDEVICE_OBJECT DeviceObject,
163 IN PIRP Irp)
164 {
165 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
166 }
167
168 NTSTATUS
169 NTAPI
170 CPortFilterDMus::Write(
171 IN PDEVICE_OBJECT DeviceObject,
172 IN PIRP Irp)
173 {
174 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
175 }
176
177 NTSTATUS
178 NTAPI
179 CPortFilterDMus::Flush(
180 IN PDEVICE_OBJECT DeviceObject,
181 IN PIRP Irp)
182 {
183 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
184 }
185
186 NTSTATUS
187 NTAPI
188 CPortFilterDMus::Close(
189 IN PDEVICE_OBJECT DeviceObject,
190 IN PIRP Irp)
191 {
192 Irp->IoStatus.Status = STATUS_SUCCESS;
193 Irp->IoStatus.Information = 0;
194 IoCompleteRequest(Irp, IO_NO_INCREMENT);
195
196 return STATUS_UNSUCCESSFUL;
197 }
198
199 NTSTATUS
200 NTAPI
201 CPortFilterDMus::QuerySecurity(
202 IN PDEVICE_OBJECT DeviceObject,
203 IN PIRP Irp)
204 {
205 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
206 }
207
208 NTSTATUS
209 NTAPI
210 CPortFilterDMus::SetSecurity(
211 IN PDEVICE_OBJECT DeviceObject,
212 IN PIRP Irp)
213 {
214 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
215 }
216
217 BOOLEAN
218 NTAPI
219 CPortFilterDMus::FastDeviceIoControl(
220 IN PFILE_OBJECT FileObject,
221 IN BOOLEAN Wait,
222 IN PVOID InputBuffer,
223 IN ULONG InputBufferLength,
224 OUT PVOID OutputBuffer,
225 IN ULONG OutputBufferLength,
226 IN ULONG IoControlCode,
227 OUT PIO_STATUS_BLOCK StatusBlock,
228 IN PDEVICE_OBJECT DeviceObject)
229 {
230 return FALSE;
231 }
232
233 BOOLEAN
234 NTAPI
235 CPortFilterDMus::FastRead(
236 IN PFILE_OBJECT FileObject,
237 IN PLARGE_INTEGER FileOffset,
238 IN ULONG Length,
239 IN BOOLEAN Wait,
240 IN ULONG LockKey,
241 IN PVOID Buffer,
242 OUT PIO_STATUS_BLOCK StatusBlock,
243 IN PDEVICE_OBJECT DeviceObject)
244 {
245 UNIMPLEMENTED
246 return FALSE;
247 }
248
249 BOOLEAN
250 NTAPI
251 CPortFilterDMus::FastWrite(
252 IN PFILE_OBJECT FileObject,
253 IN PLARGE_INTEGER FileOffset,
254 IN ULONG Length,
255 IN BOOLEAN Wait,
256 IN ULONG LockKey,
257 IN PVOID Buffer,
258 OUT PIO_STATUS_BLOCK StatusBlock,
259 IN PDEVICE_OBJECT DeviceObject)
260 {
261 UNIMPLEMENTED
262 return FALSE;
263 }
264
265 NTSTATUS
266 NTAPI
267 CPortFilterDMus::Init(
268 IN IPortDMus* Port)
269 {
270 ISubdevice * ISubDevice;
271 NTSTATUS Status;
272
273 m_Port = Port;
274
275 // get our private interface
276 Status = m_Port->QueryInterface(IID_ISubdevice, (PVOID*)&ISubDevice);
277 if (!NT_SUCCESS(Status))
278 return STATUS_UNSUCCESSFUL;
279
280 // get the subdevice descriptor
281 Status = ISubDevice->GetDescriptor(&m_Descriptor);
282
283 // release subdevice interface
284 ISubDevice->Release();
285
286 if (!NT_SUCCESS(Status))
287 return STATUS_UNSUCCESSFUL;
288
289 // allocate pin array
290 m_Pins = (IPortPinDMus**)AllocateItem(NonPagedPool, m_Descriptor->Factory.PinDescriptorCount * sizeof(IPortPinDMus*), TAG_PORTCLASS);
291
292 if (!m_Pins)
293 return STATUS_UNSUCCESSFUL;
294
295 // increment reference count
296 Port->AddRef();
297
298 return STATUS_SUCCESS;
299 }
300
301
302 NTSTATUS
303 NTAPI
304 CPortFilterDMus::FreePin(
305 IN struct IPortPinDMus* Pin)
306 {
307 ULONG Index;
308
309 for(Index = 0; Index < m_Descriptor->Factory.PinDescriptorCount; Index++)
310 {
311 if (m_Pins[Index] == Pin)
312 {
313 m_Pins[Index]->Release();
314 m_Pins[Index] = NULL;
315 return STATUS_SUCCESS;
316 }
317 }
318 return STATUS_UNSUCCESSFUL;
319 }
320
321 VOID
322 NTAPI
323 CPortFilterDMus::NotifyPins()
324 {
325 ULONG Index;
326
327 DPRINT("Notifying %u pins\n", m_Descriptor->Factory.PinDescriptorCount);
328
329 for(Index = 0; Index < m_Descriptor->Factory.PinDescriptorCount; Index++)
330 {
331 m_Pins[Index]->Notify();
332 }
333 }
334
335
336 NTSTATUS
337 NewPortFilterDMus(
338 OUT PPORTFILTERDMUS * OutFilter)
339 {
340 CPortFilterDMus * This;
341
342 This = new(NonPagedPool, TAG_PORTCLASS) CPortFilterDMus(NULL);
343 if (!This)
344 return STATUS_INSUFFICIENT_RESOURCES;
345
346 This->AddRef();
347
348 // return result
349 *OutFilter = (CPortFilterDMus*)This;
350
351 return STATUS_SUCCESS;
352 }
353
354