fd321ea9c54c5ba63faffbe6fd0a2e10fb385f25
[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 PFILE_OBJECT FileObject;
132 NTSTATUS Status;
133 ULONG BytesReturned;
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 /* call the portcls audio pin */
163 Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_WRITE_STREAM,
164 Irp->UserBuffer,
165 IoStack->Parameters.Write.Length,
166 NULL,
167 0,
168 &BytesReturned);
169
170
171 /* Release file object */
172 ObDereferenceObject(FileObject);
173
174 /* Save status and information */
175 Irp->IoStatus.Status = Status;
176 Irp->IoStatus.Information = BytesReturned;
177 /* Complete the irp */
178 IoCompleteRequest(Irp, IO_NO_INCREMENT);
179 /* Done */
180 return Status;
181 }
182
183 NTSTATUS
184 NTAPI
185 Pin_fnFlush(
186 PDEVICE_OBJECT DeviceObject,
187 PIRP Irp)
188 {
189 PDISPATCH_CONTEXT Context;
190 PIO_STACK_LOCATION IoStack;
191 PDEVICE_OBJECT PinDeviceObject;
192 PIRP PinIrp;
193 PFILE_OBJECT FileObject;
194 IO_STATUS_BLOCK IoStatus;
195 KEVENT Event;
196 NTSTATUS Status = STATUS_UNSUCCESSFUL;
197
198 /* Get current stack location */
199 IoStack = IoGetCurrentIrpStackLocation(Irp);
200
201 /* The dispatch context is stored in the FsContext2 member */
202 Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext2;
203
204 /* Sanity check */
205 ASSERT(Context);
206
207
208 /* acquire real pin file object */
209 Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
210 if (!NT_SUCCESS(Status))
211 {
212 Irp->IoStatus.Information = 0;
213 Irp->IoStatus.Status = Status;
214 /* Complete the irp */
215 IoCompleteRequest(Irp, IO_NO_INCREMENT);
216 return Status;
217 }
218
219 /* Get Pin's device object */
220 PinDeviceObject = IoGetRelatedDeviceObject(FileObject);
221
222 /* release file object */
223 ObDereferenceObject(FileObject);
224
225 /* Initialize notification event */
226 KeInitializeEvent(&Event, NotificationEvent, FALSE);
227
228 /* build target irp */
229 PinIrp = IoBuildSynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS, PinDeviceObject, NULL, 0, NULL, &Event, &IoStatus);
230 if (PinIrp)
231 {
232
233 /* Get the next stack location */
234 IoStack = IoGetNextIrpStackLocation(PinIrp);
235 /* The file object must be present in the irp as it contains the KSOBJECT_HEADER */
236 IoStack->FileObject = FileObject;
237
238 /* call the driver */
239 Status = IoCallDriver(PinDeviceObject, PinIrp);
240 /* Has request already completed ? */
241 if (Status == STATUS_PENDING)
242 {
243 /* Wait untill the request has completed */
244 KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, NULL);
245 /* Update status */
246 Status = IoStatus.Status;
247 }
248 }
249
250 /* store status */
251 Irp->IoStatus.Status = Status;
252 Irp->IoStatus.Information = 0;
253 /* Complete the irp */
254 IoCompleteRequest(Irp, IO_NO_INCREMENT);
255 /* Done */
256 return Status;
257 }
258
259 NTSTATUS
260 NTAPI
261 Pin_fnClose(
262 PDEVICE_OBJECT DeviceObject,
263 PIRP Irp)
264 {
265 PDISPATCH_CONTEXT Context;
266 PIO_STACK_LOCATION IoStack;
267
268 DPRINT("Pin_fnClose called DeviceObject %p Irp %p\n", DeviceObject);
269
270 /* Get current stack location */
271 IoStack = IoGetCurrentIrpStackLocation(Irp);
272
273 /* The dispatch context is stored in the FsContext2 member */
274 Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext2;
275
276 if (Context->Handle)
277 {
278 ZwClose(Context->Handle);
279 }
280 ZwClose(Context->hMixerPin);
281
282 ExFreePool(Context);
283
284 Irp->IoStatus.Status = STATUS_SUCCESS;
285 Irp->IoStatus.Information = 0;
286 IoCompleteRequest(Irp, IO_NO_INCREMENT);
287 return STATUS_SUCCESS;
288 }
289
290 NTSTATUS
291 NTAPI
292 Pin_fnQuerySecurity(
293 PDEVICE_OBJECT DeviceObject,
294 PIRP Irp)
295 {
296 DPRINT("Pin_fnQuerySecurity called DeviceObject %p Irp %p\n", DeviceObject);
297
298 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
299 Irp->IoStatus.Information = 0;
300 IoCompleteRequest(Irp, IO_NO_INCREMENT);
301 return STATUS_UNSUCCESSFUL;
302 }
303
304 NTSTATUS
305 NTAPI
306 Pin_fnSetSecurity(
307 PDEVICE_OBJECT DeviceObject,
308 PIRP Irp)
309 {
310
311 DPRINT("Pin_fnSetSecurity called DeviceObject %p Irp %p\n", DeviceObject);
312
313 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
314 Irp->IoStatus.Information = 0;
315 IoCompleteRequest(Irp, IO_NO_INCREMENT);
316 return STATUS_UNSUCCESSFUL;
317 }
318
319 BOOLEAN
320 NTAPI
321 Pin_fnFastDeviceIoControl(
322 PFILE_OBJECT FileObject,
323 BOOLEAN Wait,
324 PVOID InputBuffer,
325 ULONG InputBufferLength,
326 PVOID OutputBuffer,
327 ULONG OutputBufferLength,
328 ULONG IoControlCode,
329 PIO_STATUS_BLOCK IoStatus,
330 PDEVICE_OBJECT DeviceObject)
331 {
332 DPRINT("Pin_fnFastDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
333
334
335 return FALSE;
336 }
337
338
339 BOOLEAN
340 NTAPI
341 Pin_fnFastRead(
342 PFILE_OBJECT FileObject,
343 PLARGE_INTEGER FileOffset,
344 ULONG Length,
345 BOOLEAN Wait,
346 ULONG LockKey,
347 PVOID Buffer,
348 PIO_STATUS_BLOCK IoStatus,
349 PDEVICE_OBJECT DeviceObject)
350 {
351 DPRINT("Pin_fnFastRead called DeviceObject %p Irp %p\n", DeviceObject);
352
353 return FALSE;
354
355 }
356
357 BOOLEAN
358 NTAPI
359 Pin_fnFastWrite(
360 PFILE_OBJECT FileObject,
361 PLARGE_INTEGER FileOffset,
362 ULONG Length,
363 BOOLEAN Wait,
364 ULONG LockKey,
365 PVOID Buffer,
366 PIO_STATUS_BLOCK IoStatus,
367 PDEVICE_OBJECT DeviceObject)
368 {
369 PDISPATCH_CONTEXT Context;
370 PFILE_OBJECT RealFileObject;
371 NTSTATUS Status;
372
373 DPRINT("Pin_fnFastWrite called DeviceObject %p Irp %p\n", DeviceObject);
374
375 Context = (PDISPATCH_CONTEXT)FileObject->FsContext2;
376
377 if (Context->hMixerPin)
378 {
379 Status = ObReferenceObjectByHandle(Context->hMixerPin, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&RealFileObject, NULL);
380 if (NT_SUCCESS(Status))
381 {
382 Status = KsStreamIo(RealFileObject, NULL, NULL, NULL, NULL, 0, IoStatus, Buffer, Length, KSSTREAM_WRITE, UserMode);
383 ObDereferenceObject(RealFileObject);
384 }
385
386 if (!NT_SUCCESS(Status))
387 {
388 DPRINT1("Mixing stream failed with %lx\n", Status);
389 DbgBreakPoint();
390 return FALSE;
391 }
392 }
393
394 Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&RealFileObject, NULL);
395 if (!NT_SUCCESS(Status))
396 return FALSE;
397
398 Status = KsStreamIo(RealFileObject, NULL, NULL, NULL, NULL, 0, IoStatus, Buffer, Length, KSSTREAM_WRITE, UserMode);
399
400 ObDereferenceObject(RealFileObject);
401
402 if (NT_SUCCESS(Status))
403 return TRUE;
404 else
405 return FALSE;
406 }
407
408 static KSDISPATCH_TABLE PinTable =
409 {
410 Pin_fnDeviceIoControl,
411 Pin_fnRead,
412 Pin_fnWrite,
413 Pin_fnFlush,
414 Pin_fnClose,
415 Pin_fnQuerySecurity,
416 Pin_fnSetSecurity,
417 Pin_fnFastDeviceIoControl,
418 Pin_fnFastRead,
419 Pin_fnFastWrite,
420 };
421
422 NTSTATUS
423 SetMixerInputOutputFormat(
424 IN PFILE_OBJECT FileObject,
425 IN PKSDATAFORMAT InputFormat,
426 IN PKSDATAFORMAT OutputFormat)
427 {
428 KSP_PIN PinRequest;
429 ULONG BytesReturned;
430 NTSTATUS Status;
431
432 /* re-using pin */
433 PinRequest.Property.Set = KSPROPSETID_Connection;
434 PinRequest.Property.Flags = KSPROPERTY_TYPE_SET;
435 PinRequest.Property.Id = KSPROPERTY_CONNECTION_DATAFORMAT;
436
437 /* set the input format */
438 PinRequest.PinId = 0;
439 DPRINT("InputFormat %p Size %u WaveFormatSize %u DataFormat %u WaveEx %u\n", InputFormat, InputFormat->FormatSize, sizeof(KSDATAFORMAT_WAVEFORMATEX), sizeof(KSDATAFORMAT), sizeof(WAVEFORMATEX));
440 Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY,
441 (PVOID)&PinRequest,
442 sizeof(KSP_PIN),
443 (PVOID)InputFormat,
444 InputFormat->FormatSize,
445 &BytesReturned);
446 if (!NT_SUCCESS(Status))
447 return Status;
448
449 /* set the the output format */
450 PinRequest.PinId = 1;
451 DPRINT("OutputFormat %p Size %u WaveFormatSize %u DataFormat %u WaveEx %u\n", OutputFormat, OutputFormat->FormatSize, sizeof(KSDATAFORMAT_WAVEFORMATEX), sizeof(KSDATAFORMAT), sizeof(WAVEFORMATEX));
452 Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY,
453 (PVOID)&PinRequest,
454 sizeof(KSP_PIN),
455 (PVOID)OutputFormat,
456 OutputFormat->FormatSize,
457 &BytesReturned);
458 return Status;
459 }
460
461
462 NTSTATUS
463 CreateMixerPinAndSetFormat(
464 IN HANDLE KMixerHandle,
465 IN KSPIN_CONNECT *PinConnect,
466 IN PKSDATAFORMAT InputFormat,
467 IN PKSDATAFORMAT OutputFormat,
468 OUT PHANDLE MixerPinHandle)
469 {
470 NTSTATUS Status;
471 HANDLE PinHandle;
472 PFILE_OBJECT FileObject;
473
474 Status = KsCreatePin(KMixerHandle, PinConnect, GENERIC_READ | GENERIC_WRITE, &PinHandle);
475
476 if (!NT_SUCCESS(Status))
477 {
478 DPRINT1("Failed to create Mixer Pin with %x\n", Status);
479 return STATUS_UNSUCCESSFUL;
480 }
481
482 Status = ObReferenceObjectByHandle(PinHandle,
483 GENERIC_READ | GENERIC_WRITE,
484 IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
485
486 if (!NT_SUCCESS(Status))
487 {
488 DPRINT1("Failed to get file object with %x\n", Status);
489 return STATUS_UNSUCCESSFUL;
490 }
491
492 Status = SetMixerInputOutputFormat(FileObject, InputFormat, OutputFormat);
493 if (!NT_SUCCESS(Status))
494 {
495 ObDereferenceObject(FileObject);
496 ZwClose(PinHandle);
497 }
498
499 ObDereferenceObject(FileObject);
500
501 *MixerPinHandle = PinHandle;
502 return Status;
503 }
504
505
506 NTSTATUS
507 NTAPI
508 InstantiatePins(
509 IN PKSAUDIO_DEVICE_ENTRY DeviceEntry,
510 IN PKSPIN_CONNECT Connect,
511 IN PDISPATCH_CONTEXT DispatchContext,
512 IN PSYSAUDIODEVEXT DeviceExtension)
513 {
514 NTSTATUS Status;
515 HANDLE RealPinHandle;
516 PKSDATAFORMAT_WAVEFORMATEX InputFormat;
517 PKSDATAFORMAT_WAVEFORMATEX OutputFormat = NULL;
518 PKSPIN_CONNECT MixerPinConnect = NULL;
519 KSPIN_CINSTANCES PinInstances;
520
521 DPRINT("InstantiatePins entered\n");
522
523 /* query instance count */
524 Status = GetPinInstanceCount(DeviceEntry, &PinInstances, Connect);
525 if (!NT_SUCCESS(Status))
526 {
527 /* failed to query instance count */
528 return Status;
529 }
530
531 /* can be the pin be instantiated */
532 if (PinInstances.PossibleCount == 0)
533 {
534 /* caller wanted to open an instance-less pin */
535 return STATUS_UNSUCCESSFUL;
536 }
537
538 /* has the maximum instance count been exceeded */
539 if (PinInstances.CurrentCount == PinInstances.PossibleCount)
540 {
541 /* FIXME pin already exists
542 * and kmixer infrastructure is not implemented
543 */
544 return STATUS_UNSUCCESSFUL;
545 }
546
547 /* Fetch input format */
548 InputFormat = (PKSDATAFORMAT_WAVEFORMATEX)(Connect + 1);
549
550 /* Let's try to create the audio irp pin */
551 Status = KsCreatePin(DeviceEntry->Handle, Connect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle);
552
553 if (!NT_SUCCESS(Status))
554 {
555 /* the audio irp pin didnt accept the input format
556 * let's compute a compatible format
557 */
558 MixerPinConnect = ExAllocatePool(NonPagedPool, sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX));
559 if (!MixerPinConnect)
560 {
561 /* not enough memory */
562 return STATUS_INSUFFICIENT_RESOURCES;
563 }
564
565 /* Zero pin connect */
566 RtlZeroMemory(MixerPinConnect, sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX));
567
568 /* Copy initial connect details */
569 RtlMoveMemory(MixerPinConnect, Connect, sizeof(KSPIN_CONNECT));
570
571
572 OutputFormat = (PKSDATAFORMAT_WAVEFORMATEX)(MixerPinConnect + 1);
573
574 Status = ComputeCompatibleFormat(DeviceEntry, Connect->PinId, InputFormat, OutputFormat);
575 if (!NT_SUCCESS(Status))
576 {
577 DPRINT1("ComputeCompatibleFormat failed with %x\n", Status);
578 ExFreePool(MixerPinConnect);
579 return Status;
580 }
581
582 /* Retry with Mixer format */
583 Status = KsCreatePin(DeviceEntry->Handle, MixerPinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle);
584 if (!NT_SUCCESS(Status))
585 {
586 /* This should not fail */
587 DPRINT1("KsCreatePin failed with %x\n", Status);
588 DPRINT1(" InputFormat: SampleRate %u Bits %u Channels %u\n", InputFormat->WaveFormatEx.nSamplesPerSec, InputFormat->WaveFormatEx.wBitsPerSample, InputFormat->WaveFormatEx.nChannels);
589 DPRINT1("OutputFormat: SampleRate %u Bits %u Channels %u\n", OutputFormat->WaveFormatEx.nSamplesPerSec, OutputFormat->WaveFormatEx.wBitsPerSample, OutputFormat->WaveFormatEx.nChannels);
590
591 ExFreePool(MixerPinConnect);
592 return Status;
593 }
594 }
595
596 DeviceEntry->Pins[Connect->PinId].References = 0;
597
598 /* initialize dispatch context */
599 DispatchContext->Handle = RealPinHandle;
600 DispatchContext->PinId = Connect->PinId;
601 DispatchContext->AudioEntry = DeviceEntry;
602
603
604 /* Do we need to transform the audio stream */
605 if (OutputFormat != NULL)
606 {
607 /* Now create the mixer pin */
608 Status = CreateMixerPinAndSetFormat(DeviceExtension->KMixerHandle,
609 MixerPinConnect,
610 (PKSDATAFORMAT)InputFormat,
611 (PKSDATAFORMAT)OutputFormat,
612 &DispatchContext->hMixerPin);
613
614 /* check for success */
615 if (!NT_SUCCESS(Status))
616 {
617 DPRINT1("Failed to create Mixer Pin with %x\n", Status);
618 ExFreePool(MixerPinConnect);
619 }
620 }
621 /* done */
622 return Status;
623 }
624
625 NTSTATUS
626 NTAPI
627 DispatchCreateSysAudioPin(
628 IN PDEVICE_OBJECT DeviceObject,
629 IN PIRP Irp)
630 {
631 NTSTATUS Status = STATUS_SUCCESS;
632 KSOBJECT_HEADER ObjectHeader;
633 PIO_STACK_LOCATION IoStack;
634 PKSAUDIO_DEVICE_ENTRY DeviceEntry;
635 PKSPIN_CONNECT Connect = NULL;
636 PDISPATCH_CONTEXT DispatchContext;
637
638 DPRINT("DispatchCreateSysAudioPin entered\n");
639
640 /* get current stack location */
641 IoStack = IoGetCurrentIrpStackLocation(Irp);
642
643 /* sanity checks */
644 ASSERT(IoStack->FileObject);
645 ASSERT(IoStack->FileObject->RelatedFileObject);
646 ASSERT(IoStack->FileObject->RelatedFileObject->FsContext2);
647
648 /* get current attached virtual device */
649 DeviceEntry = (PKSAUDIO_DEVICE_ENTRY)IoStack->FileObject->RelatedFileObject->FsContext2;
650
651 /* now validate pin connect request */
652 Status = KsValidateConnectRequest(Irp, DeviceEntry->PinDescriptorsCount, DeviceEntry->PinDescriptors, &Connect);
653
654 /* check for success */
655 if (!NT_SUCCESS(Status))
656 {
657 /* failed */
658 Irp->IoStatus.Status = Status;
659 IoCompleteRequest(Irp, IO_NO_INCREMENT);
660 return Status;
661 }
662
663 /* allocate dispatch context */
664 DispatchContext = ExAllocatePool(NonPagedPool, sizeof(DISPATCH_CONTEXT));
665 if (!DispatchContext)
666 {
667 /* failed */
668 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
669 IoCompleteRequest(Irp, IO_NO_INCREMENT);
670 return STATUS_INSUFFICIENT_RESOURCES;
671 }
672
673 /* zero dispatch context */
674 RtlZeroMemory(DispatchContext, sizeof(DISPATCH_CONTEXT));
675
676 /* allocate object header */
677 Status = KsAllocateObjectHeader(&ObjectHeader, 0, NULL, Irp, &PinTable);
678 if (!NT_SUCCESS(Status))
679 {
680 /* failed */
681 ExFreePool(DispatchContext);
682 Irp->IoStatus.Status = Status;
683 IoCompleteRequest(Irp, IO_NO_INCREMENT);
684 return Status;
685 }
686
687 /* now instantiate the pins */
688 Status = InstantiatePins(DeviceEntry, Connect, DispatchContext, (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension);
689 if (!NT_SUCCESS(Status))
690 {
691 /* failed */
692 KsFreeObjectHeader(ObjectHeader);
693 ExFreePool(DispatchContext);
694 }
695 else
696 {
697 /* store dispatch context */
698 IoStack->FileObject->FsContext2 = (PVOID)DispatchContext;
699 }
700
701
702 /* FIXME create items for clocks / allocators */
703 Irp->IoStatus.Status = Status;
704 IoCompleteRequest(Irp, IO_NO_INCREMENT);
705 return Status;
706 }