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