Merge trunk head (r41474)
[reactos.git] / reactos / drivers / wdm / audio / sysaudio / pin.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/sysaudio/deviface.c
5 * PURPOSE: System Audio graph builder
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "sysaudio.h"
10
11 NTSTATUS
12 NTAPI
13 Pin_fnDeviceIoControl(
14 PDEVICE_OBJECT DeviceObject,
15 PIRP Irp)
16 {
17 PDISPATCH_CONTEXT Context;
18 NTSTATUS Status;
19 ULONG BytesReturned;
20 PFILE_OBJECT FileObject;
21 PIO_STACK_LOCATION IoStack;
22
23 DPRINT("Pin_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
24
25 /* Get current stack location */
26 IoStack = IoGetCurrentIrpStackLocation(Irp);
27
28 /* The dispatch context is stored in the FsContext2 member */
29 Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext2;
30
31 /* Sanity check */
32 ASSERT(Context);
33
34 /* acquire real pin file object */
35 Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
36 if (!NT_SUCCESS(Status))
37 {
38 Irp->IoStatus.Information = 0;
39 Irp->IoStatus.Status = Status;
40 /* Complete the irp */
41 IoCompleteRequest(Irp, IO_NO_INCREMENT);
42 return Status;
43 }
44
45 /* Re-dispatch the request to the real target pin */
46 Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IoStack->Parameters.DeviceIoControl.IoControlCode,
47 IoStack->Parameters.DeviceIoControl.Type3InputBuffer,
48 IoStack->Parameters.DeviceIoControl.InputBufferLength,
49 Irp->UserBuffer,
50 IoStack->Parameters.DeviceIoControl.OutputBufferLength,
51 &BytesReturned);
52 /* release file object */
53 ObDereferenceObject(FileObject);
54
55 /* Save status and information */
56 Irp->IoStatus.Information = BytesReturned;
57 Irp->IoStatus.Status = Status;
58 /* Complete the irp */
59 IoCompleteRequest(Irp, IO_NO_INCREMENT);
60 /* Done */
61 return Status;
62 }
63
64 NTSTATUS
65 NTAPI
66 Pin_fnRead(
67 PDEVICE_OBJECT DeviceObject,
68 PIRP Irp)
69 {
70 PDISPATCH_CONTEXT Context;
71 PIO_STACK_LOCATION IoStack;
72 ULONG BytesReturned;
73 PFILE_OBJECT FileObject;
74 NTSTATUS Status;
75
76 /* Get current stack location */
77 IoStack = IoGetCurrentIrpStackLocation(Irp);
78
79 /* The dispatch context is stored in the FsContext2 member */
80 Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext2;
81
82 /* Sanity check */
83 ASSERT(Context);
84
85 /* acquire real pin file object */
86 Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
87 if (!NT_SUCCESS(Status))
88 {
89 Irp->IoStatus.Information = 0;
90 Irp->IoStatus.Status = Status;
91 /* Complete the irp */
92 IoCompleteRequest(Irp, IO_NO_INCREMENT);
93 return Status;
94 }
95
96 /* Re-dispatch the request to the real target pin */
97 Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_READ_STREAM,
98 MmGetMdlVirtualAddress(Irp->MdlAddress),
99 IoStack->Parameters.Read.Length,
100 NULL,
101 0,
102 &BytesReturned);
103
104 /* release file object */
105 ObDereferenceObject(FileObject);
106
107 if (Context->hMixerPin)
108 {
109 // FIXME
110 // call kmixer to convert stream
111 UNIMPLEMENTED
112 }
113
114 /* Save status and information */
115 Irp->IoStatus.Status = Status;
116 Irp->IoStatus.Information = 0;
117 /* Complete the irp */
118 IoCompleteRequest(Irp, IO_NO_INCREMENT);
119 /* Done */
120 return Status;
121 }
122
123 NTSTATUS
124 NTAPI
125 Pin_fnWrite(
126 PDEVICE_OBJECT DeviceObject,
127 PIRP Irp)
128 {
129 PDISPATCH_CONTEXT Context;
130 PIO_STACK_LOCATION IoStack;
131 ULONG BytesReturned;
132 PFILE_OBJECT FileObject;
133 NTSTATUS Status;
134
135 /* Get current stack location */
136 IoStack = IoGetCurrentIrpStackLocation(Irp);
137
138 /* The dispatch context is stored in the FsContext2 member */
139 Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext2;
140
141 /* Sanity check */
142 ASSERT(Context);
143
144 if (Context->hMixerPin)
145 {
146 // FIXME
147 // call kmixer to convert stream
148 UNIMPLEMENTED
149 }
150
151 /* acquire real pin file object */
152 Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
153 if (!NT_SUCCESS(Status))
154 {
155 Irp->IoStatus.Information = 0;
156 Irp->IoStatus.Status = Status;
157 /* Complete the irp */
158 IoCompleteRequest(Irp, IO_NO_INCREMENT);
159 return Status;
160 }
161
162 /* Re-dispatch the request to the real target pin */
163 Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_WRITE_STREAM,
164 MmGetMdlVirtualAddress(Irp->MdlAddress),
165 IoStack->Parameters.Read.Length,
166 NULL,
167 0,
168 &BytesReturned);
169
170 /* release file object */
171 ObDereferenceObject(FileObject);
172
173 /* Save status and information */
174 Irp->IoStatus.Status = Status;
175 Irp->IoStatus.Information = 0;
176 /* Complete the irp */
177 IoCompleteRequest(Irp, IO_NO_INCREMENT);
178 /* Done */
179 return Status;
180 }
181
182 NTSTATUS
183 NTAPI
184 Pin_fnFlush(
185 PDEVICE_OBJECT DeviceObject,
186 PIRP Irp)
187 {
188 PDISPATCH_CONTEXT Context;
189 PIO_STACK_LOCATION IoStack;
190 PDEVICE_OBJECT PinDeviceObject;
191 PIRP PinIrp;
192 PFILE_OBJECT FileObject;
193 IO_STATUS_BLOCK IoStatus;
194 KEVENT Event;
195 NTSTATUS Status = STATUS_UNSUCCESSFUL;
196
197 /* Get current stack location */
198 IoStack = IoGetCurrentIrpStackLocation(Irp);
199
200 /* The dispatch context is stored in the FsContext2 member */
201 Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext2;
202
203 /* Sanity check */
204 ASSERT(Context);
205
206
207 /* acquire real pin file object */
208 Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
209 if (!NT_SUCCESS(Status))
210 {
211 Irp->IoStatus.Information = 0;
212 Irp->IoStatus.Status = Status;
213 /* Complete the irp */
214 IoCompleteRequest(Irp, IO_NO_INCREMENT);
215 return Status;
216 }
217
218 /* Get Pin's device object */
219 PinDeviceObject = IoGetRelatedDeviceObject(FileObject);
220
221 /* release file object */
222 ObDereferenceObject(FileObject);
223
224 /* Initialize notification event */
225 KeInitializeEvent(&Event, NotificationEvent, FALSE);
226
227 /* build target irp */
228 PinIrp = IoBuildSynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS, PinDeviceObject, NULL, 0, NULL, &Event, &IoStatus);
229 if (PinIrp)
230 {
231
232 /* Get the next stack location */
233 IoStack = IoGetNextIrpStackLocation(PinIrp);
234 /* The file object must be present in the irp as it contains the KSOBJECT_HEADER */
235 IoStack->FileObject = FileObject;
236
237 /* call the driver */
238 Status = IoCallDriver(PinDeviceObject, PinIrp);
239 /* Has request already completed ? */
240 if (Status == STATUS_PENDING)
241 {
242 /* Wait untill the request has completed */
243 KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, NULL);
244 /* Update status */
245 Status = IoStatus.Status;
246 }
247 }
248
249 /* store status */
250 Irp->IoStatus.Status = Status;
251 Irp->IoStatus.Information = 0;
252 /* Complete the irp */
253 IoCompleteRequest(Irp, IO_NO_INCREMENT);
254 /* Done */
255 return Status;
256 }
257
258 NTSTATUS
259 NTAPI
260 Pin_fnClose(
261 PDEVICE_OBJECT DeviceObject,
262 PIRP Irp)
263 {
264 PDISPATCH_CONTEXT Context;
265 PIO_STACK_LOCATION IoStack;
266
267 DPRINT("Pin_fnClose called DeviceObject %p Irp %p\n", DeviceObject);
268
269 /* Get current stack location */
270 IoStack = IoGetCurrentIrpStackLocation(Irp);
271
272 /* The dispatch context is stored in the FsContext2 member */
273 Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext2;
274
275 if (Context->Handle)
276 {
277 ZwClose(Context->Handle);
278 }
279 ZwClose(Context->hMixerPin);
280
281 ExFreePool(Context);
282
283 Irp->IoStatus.Status = STATUS_SUCCESS;
284 Irp->IoStatus.Information = 0;
285 IoCompleteRequest(Irp, IO_NO_INCREMENT);
286 return STATUS_SUCCESS;
287 }
288
289 NTSTATUS
290 NTAPI
291 Pin_fnQuerySecurity(
292 PDEVICE_OBJECT DeviceObject,
293 PIRP Irp)
294 {
295 DPRINT("Pin_fnQuerySecurity called DeviceObject %p Irp %p\n", DeviceObject);
296
297 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
298 Irp->IoStatus.Information = 0;
299 IoCompleteRequest(Irp, IO_NO_INCREMENT);
300 return STATUS_UNSUCCESSFUL;
301 }
302
303 NTSTATUS
304 NTAPI
305 Pin_fnSetSecurity(
306 PDEVICE_OBJECT DeviceObject,
307 PIRP Irp)
308 {
309
310 DPRINT("Pin_fnSetSecurity called DeviceObject %p Irp %p\n", DeviceObject);
311
312 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
313 Irp->IoStatus.Information = 0;
314 IoCompleteRequest(Irp, IO_NO_INCREMENT);
315 return STATUS_UNSUCCESSFUL;
316 }
317
318 BOOLEAN
319 NTAPI
320 Pin_fnFastDeviceIoControl(
321 PFILE_OBJECT FileObject,
322 BOOLEAN Wait,
323 PVOID InputBuffer,
324 ULONG InputBufferLength,
325 PVOID OutputBuffer,
326 ULONG OutputBufferLength,
327 ULONG IoControlCode,
328 PIO_STATUS_BLOCK IoStatus,
329 PDEVICE_OBJECT DeviceObject)
330 {
331 DPRINT("Pin_fnFastDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
332
333
334 return FALSE;
335 }
336
337
338 BOOLEAN
339 NTAPI
340 Pin_fnFastRead(
341 PFILE_OBJECT FileObject,
342 PLARGE_INTEGER FileOffset,
343 ULONG Length,
344 BOOLEAN Wait,
345 ULONG LockKey,
346 PVOID Buffer,
347 PIO_STATUS_BLOCK IoStatus,
348 PDEVICE_OBJECT DeviceObject)
349 {
350 DPRINT("Pin_fnFastRead called DeviceObject %p Irp %p\n", DeviceObject);
351
352 return FALSE;
353
354 }
355
356 BOOLEAN
357 NTAPI
358 Pin_fnFastWrite(
359 PFILE_OBJECT FileObject,
360 PLARGE_INTEGER FileOffset,
361 ULONG Length,
362 BOOLEAN Wait,
363 ULONG LockKey,
364 PVOID Buffer,
365 PIO_STATUS_BLOCK IoStatus,
366 PDEVICE_OBJECT DeviceObject)
367 {
368 PDISPATCH_CONTEXT Context;
369 PFILE_OBJECT RealFileObject;
370 NTSTATUS Status;
371
372 DPRINT("Pin_fnFastWrite called DeviceObject %p Irp %p\n", DeviceObject);
373
374 Context = (PDISPATCH_CONTEXT)FileObject->FsContext2;
375
376 if (Context->hMixerPin)
377 {
378 Status = ObReferenceObjectByHandle(Context->hMixerPin, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&RealFileObject, NULL);
379 if (NT_SUCCESS(Status))
380 {
381 Status = KsStreamIo(RealFileObject, NULL, NULL, NULL, NULL, 0, IoStatus, Buffer, Length, KSSTREAM_WRITE, KernelMode);
382 ObDereferenceObject(RealFileObject);
383 }
384
385 if (!NT_SUCCESS(Status))
386 {
387 DPRINT1("Mixing stream failed with %lx\n", Status);
388 return FALSE;
389 }
390 }
391
392 Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&RealFileObject, NULL);
393 if (!NT_SUCCESS(Status))
394 return FALSE;
395
396 Status = KsStreamIo(RealFileObject, NULL, NULL, NULL, NULL, 0, IoStatus, Buffer, Length, KSSTREAM_WRITE, KernelMode);
397
398 ObDereferenceObject(RealFileObject);
399
400 if (Status == STATUS_SUCCESS)
401 return TRUE;
402 else
403 return FALSE;
404 }
405
406 static KSDISPATCH_TABLE PinTable =
407 {
408 Pin_fnDeviceIoControl,
409 Pin_fnRead,
410 Pin_fnWrite,
411 Pin_fnFlush,
412 Pin_fnClose,
413 Pin_fnQuerySecurity,
414 Pin_fnSetSecurity,
415 Pin_fnFastDeviceIoControl,
416 Pin_fnFastRead,
417 Pin_fnFastWrite,
418 };
419
420 NTSTATUS
421 CreateDispatcher(
422 IN PIRP Irp)
423 {
424 NTSTATUS Status;
425 KSOBJECT_HEADER ObjectHeader;
426
427 /* allocate object header */
428 Status = KsAllocateObjectHeader(&ObjectHeader, 0, NULL, Irp, &PinTable);
429 return Status;
430 }