- Convert portcls to a C++ driver
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / pin_dmus.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/backpln/portcls/pin_dmus.cpp
5 * PURPOSE: DMus IRP Audio Pin
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "private.hpp"
10
11 class CPortPinDMus : public IPortPinDMus
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_IPortPinDMus;
33 IMP_IServiceSink;
34 IMP_IMasterClock;
35 IMP_IAllocatorMXF;
36
37 CPortPinDMus(IUnknown * OuterUnknown){}
38 virtual ~CPortPinDMus(){}
39
40 protected:
41 VOID TransferMidiDataToDMus();
42 VOID TransferMidiData();
43
44 VOID NTAPI SetStreamState(IN KSSTATE State);
45
46
47 IPortDMus * m_Port;
48 IPortFilterDMus * m_Filter;
49 KSPIN_DESCRIPTOR * m_KsPinDescriptor;
50 PMINIPORTDMUS m_Miniport;
51
52 PSERVICEGROUP m_ServiceGroup;
53
54 PMXF m_Mxf;
55 ULONGLONG m_SchedulePreFetch;
56 NPAGED_LOOKASIDE_LIST m_LookAsideEvent;
57 NPAGED_LOOKASIDE_LIST m_LookAsideBuffer;
58
59 PMINIPORTMIDI m_MidiMiniport;
60 PMINIPORTMIDISTREAM m_MidiStream;
61
62
63 KSSTATE m_State;
64 PKSDATAFORMAT m_Format;
65 KSPIN_CONNECT * m_ConnectDetails;
66
67 DMUS_STREAM_TYPE m_Capture;
68 PDEVICE_OBJECT m_DeviceObject;
69 IIrpQueue * m_IrpQueue;
70
71 ULONG m_TotalPackets;
72 ULONG m_PreCompleted;
73 ULONG m_PostCompleted;
74
75 ULONG m_LastTag;
76
77 LONG m_Ref;
78
79 friend VOID NTAPI SetStreamWorkerRoutineDMus(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context);
80 friend VOID NTAPI CloseStreamRoutineDMus(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context);
81
82 };
83
84 typedef struct
85 {
86 DMUS_KERNEL_EVENT Event;
87 PVOID Tag;
88 }DMUS_KERNEL_EVENT_WITH_TAG, *PDMUS_KERNEL_EVENT_WITH_TAG;
89
90 typedef struct
91 {
92 CPortPinDMus *Pin;
93 PIO_WORKITEM WorkItem;
94 KSSTATE State;
95 }SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT;
96
97 //==================================================================================================================================
98 NTSTATUS
99 NTAPI
100 CPortPinDMus::GetTime(OUT REFERENCE_TIME *prtTime)
101 {
102 UNIMPLEMENTED
103 return STATUS_SUCCESS;
104 }
105
106 //==================================================================================================================================
107 NTSTATUS
108 NTAPI
109 CPortPinDMus::GetMessage(
110 OUT PDMUS_KERNEL_EVENT * ppDMKEvt)
111 {
112 PVOID Buffer;
113
114 Buffer = ExAllocateFromNPagedLookasideList(&m_LookAsideEvent);
115 if (!Buffer)
116 return STATUS_INSUFFICIENT_RESOURCES;
117
118 *ppDMKEvt = (PDMUS_KERNEL_EVENT)Buffer;
119 RtlZeroMemory(Buffer, sizeof(DMUS_KERNEL_EVENT));
120 return STATUS_SUCCESS;
121 }
122
123 USHORT
124 NTAPI
125 CPortPinDMus::GetBufferSize()
126 {
127 return PAGE_SIZE;
128 }
129
130 NTSTATUS
131 NTAPI
132 CPortPinDMus::GetBuffer(
133 OUT PBYTE * ppBuffer)
134 {
135 PVOID Buffer;
136
137 Buffer = ExAllocateFromNPagedLookasideList(&m_LookAsideBuffer);
138 if (!Buffer)
139 return STATUS_INSUFFICIENT_RESOURCES;
140
141 *ppBuffer = (PBYTE)Buffer;
142 RtlZeroMemory(Buffer, PAGE_SIZE);
143 return STATUS_SUCCESS;
144 }
145
146
147 NTSTATUS
148 NTAPI
149 CPortPinDMus::PutBuffer(
150 IN PBYTE pBuffer)
151 {
152 PDMUS_KERNEL_EVENT_WITH_TAG Event = (PDMUS_KERNEL_EVENT_WITH_TAG)pBuffer;
153
154 m_IrpQueue->ReleaseMappingWithTag(Event->Tag);
155
156 ExFreeToNPagedLookasideList(&m_LookAsideBuffer, pBuffer);
157 return STATUS_SUCCESS;
158 }
159
160 NTSTATUS
161 NTAPI
162 CPortPinDMus::SetState(
163 IN KSSTATE State)
164 {
165 UNIMPLEMENTED
166 return STATUS_NOT_IMPLEMENTED;
167 }
168
169
170 NTSTATUS
171 NTAPI
172 CPortPinDMus::PutMessage(
173 IN PDMUS_KERNEL_EVENT pDMKEvt)
174 {
175 ExFreeToNPagedLookasideList(&m_LookAsideEvent, pDMKEvt);
176 return STATUS_SUCCESS;
177 }
178
179
180 NTSTATUS
181 NTAPI
182 CPortPinDMus::ConnectOutput(
183 IN PMXF sinkMXF)
184 {
185 UNIMPLEMENTED
186 return STATUS_NOT_IMPLEMENTED;
187 }
188
189
190 NTSTATUS
191 NTAPI
192 CPortPinDMus::DisconnectOutput(
193 IN PMXF sinkMXF)
194 {
195 UNIMPLEMENTED
196 return STATUS_NOT_IMPLEMENTED;
197 }
198
199 //==================================================================================================================================
200
201 VOID
202 NTAPI
203 SetStreamWorkerRoutineDMus(
204 IN PDEVICE_OBJECT DeviceObject,
205 IN PVOID Context)
206 {
207 CPortPinDMus* This;
208 KSSTATE State;
209 NTSTATUS Status;
210 PSETSTREAM_CONTEXT Ctx = (PSETSTREAM_CONTEXT)Context;
211
212 This = Ctx->Pin;
213 State = Ctx->State;
214
215 IoFreeWorkItem(Ctx->WorkItem);
216 FreeItem(Ctx, TAG_PORTCLASS);
217
218 // Has the audio stream resumed?
219 if (This->m_IrpQueue->NumMappings() && State == KSSTATE_STOP)
220 return;
221
222 // Set the state
223 if (This->m_MidiStream)
224 {
225 Status = This->m_MidiStream->SetState(State);
226 }
227 else
228 {
229 Status = This->m_Mxf->SetState(State);
230 }
231
232 if (NT_SUCCESS(Status))
233 {
234 // Set internal state to requested state
235 This->m_State = State;
236
237 if (This->m_State == KSSTATE_STOP)
238 {
239 // reset start stream
240 This->m_IrpQueue->CancelBuffers(); //FIX function name
241 DPRINT1("Stopping PreCompleted %u PostCompleted %u\n", This->m_PreCompleted, This->m_PostCompleted);
242 }
243 }
244 }
245
246 VOID
247 NTAPI
248 CPortPinDMus::SetStreamState(
249 IN KSSTATE State)
250 {
251 PIO_WORKITEM WorkItem;
252 PSETSTREAM_CONTEXT Context;
253
254 PC_ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
255
256 // Has the audio stream resumed?
257 if (m_IrpQueue->NumMappings() && State == KSSTATE_STOP)
258 return;
259
260 // Has the audio state already been set?
261 if (m_State == State)
262 return;
263
264 // allocate set state context
265 Context = (PSETSTREAM_CONTEXT)AllocateItem(NonPagedPool, sizeof(SETSTREAM_CONTEXT), TAG_PORTCLASS);
266
267 if (!Context)
268 return;
269
270 // allocate work item
271 WorkItem = IoAllocateWorkItem(m_DeviceObject);
272
273 if (!WorkItem)
274 {
275 ExFreePool(Context);
276 return;
277 }
278
279 Context->Pin = this;
280 Context->WorkItem = WorkItem;
281 Context->State = State;
282
283 // queue the work item
284 IoQueueWorkItem(WorkItem, SetStreamWorkerRoutineDMus, DelayedWorkQueue, (PVOID)Context);
285 }
286
287 VOID
288 CPortPinDMus::TransferMidiData()
289 {
290 NTSTATUS Status;
291 PUCHAR Buffer;
292 ULONG BufferSize;
293 ULONG BytesWritten;
294
295 do
296 {
297 Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
298 if (!NT_SUCCESS(Status))
299 {
300 SetStreamState(KSSTATE_STOP);
301 return;
302 }
303
304 if (m_Capture)
305 {
306 Status = m_MidiStream->Read(Buffer, BufferSize, &BytesWritten);
307 if (!NT_SUCCESS(Status))
308 {
309 DPRINT("Read failed with %x\n", Status);
310 return;
311 }
312 }
313 else
314 {
315 Status = m_MidiStream->Write(Buffer, BufferSize, &BytesWritten);
316 if (!NT_SUCCESS(Status))
317 {
318 DPRINT("Write failed with %x\n", Status);
319 return;
320 }
321 }
322
323 if (!BytesWritten)
324 {
325 DPRINT("Device is busy retry later\n");
326 return;
327 }
328
329 m_IrpQueue->UpdateMapping(BytesWritten);
330
331 }while(TRUE);
332
333 }
334
335 VOID
336 CPortPinDMus::TransferMidiDataToDMus()
337 {
338 NTSTATUS Status;
339 PHYSICAL_ADDRESS PhysicalAddress;
340 ULONG BufferSize, Flags;
341 PVOID Buffer;
342 PDMUS_KERNEL_EVENT_WITH_TAG Event, LastEvent = NULL, Root = NULL;
343
344 do
345 {
346 m_LastTag++;
347 Status = m_IrpQueue->GetMappingWithTag(UlongToPtr(m_LastTag), &PhysicalAddress, &Buffer, &BufferSize, &Flags);
348 if (!NT_SUCCESS(Status))
349 {
350 break;
351 }
352
353 Status = GetMessage((PDMUS_KERNEL_EVENT*)&Event);
354 if (!NT_SUCCESS(Status))
355 break;
356
357 //FIXME
358 //set up struct
359 //Event->Event.usFlags = DMUS_KEF_EVENT_COMPLETE;
360 Event->Event.cbStruct = sizeof(DMUS_KERNEL_EVENT);
361 Event->Event.cbEvent = BufferSize;
362 Event->Event.uData.pbData = (PBYTE)Buffer;
363
364
365 if (!Root)
366 Root = Event;
367 else
368 LastEvent->Event.pNextEvt = (struct _DMUS_KERNEL_EVENT *)Event;
369
370 LastEvent = Event;
371 LastEvent->Event.pNextEvt = NULL;
372 LastEvent->Tag = UlongToPtr(m_LastTag);
373
374 }while(TRUE);
375
376 if (!Root)
377 {
378 SetStreamState(KSSTATE_STOP);
379 return;
380 }
381
382 Status = m_Mxf->PutMessage((PDMUS_KERNEL_EVENT)Root);
383 DPRINT("Status %x\n", Status);
384 }
385
386
387
388 VOID
389 NTAPI
390 CPortPinDMus::RequestService()
391 {
392 PC_ASSERT_IRQL(DISPATCH_LEVEL);
393
394 if (m_MidiStream)
395 {
396 TransferMidiData();
397 }
398 else if (m_Mxf)
399 {
400 TransferMidiDataToDMus();
401 }
402 }
403
404 //==================================================================================================================================
405 NTSTATUS
406 NTAPI
407 CPortPinDMus::QueryInterface(
408 IN REFIID refiid,
409 OUT PVOID* Output)
410 {
411
412 if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) ||
413 IsEqualGUIDAligned(refiid, IID_IUnknown))
414 {
415 *Output = PVOID(PUNKNOWN(this));
416 PUNKNOWN(*Output)->AddRef();
417 return STATUS_SUCCESS;
418 }
419
420 return STATUS_UNSUCCESSFUL;
421 }
422
423 NTSTATUS
424 NTAPI
425 CPortPinDMus::NewIrpTarget(
426 OUT struct IIrpTarget **OutTarget,
427 IN WCHAR * Name,
428 IN PUNKNOWN Unknown,
429 IN POOL_TYPE PoolType,
430 IN PDEVICE_OBJECT DeviceObject,
431 IN PIRP Irp,
432 IN KSOBJECT_CREATE *CreateObject)
433 {
434 UNIMPLEMENTED
435
436 Irp->IoStatus.Information = 0;
437 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
438 IoCompleteRequest(Irp, IO_NO_INCREMENT);
439
440 return STATUS_UNSUCCESSFUL;
441 }
442
443 NTSTATUS
444 NTAPI
445 CPortPinDMus::DeviceIoControl(
446 IN PDEVICE_OBJECT DeviceObject,
447 IN PIRP Irp)
448 {
449 UNIMPLEMENTED
450
451 Irp->IoStatus.Information = 0;
452 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
453 IoCompleteRequest(Irp, IO_NO_INCREMENT);
454
455 return STATUS_UNSUCCESSFUL;
456 }
457
458 NTSTATUS
459 NTAPI
460 CPortPinDMus::Read(
461 IN PDEVICE_OBJECT DeviceObject,
462 IN PIRP Irp)
463 {
464 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
465 }
466
467 NTSTATUS
468 NTAPI
469 CPortPinDMus::Write(
470 IN PDEVICE_OBJECT DeviceObject,
471 IN PIRP Irp)
472 {
473 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
474 }
475
476 NTSTATUS
477 NTAPI
478 CPortPinDMus::Flush(
479 IN PDEVICE_OBJECT DeviceObject,
480 IN PIRP Irp)
481 {
482 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
483 }
484
485
486 VOID
487 NTAPI
488 CloseStreamRoutineDMus(
489 IN PDEVICE_OBJECT DeviceObject,
490 IN PVOID Context)
491 {
492 PMINIPORTMIDISTREAM Stream = NULL;
493 NTSTATUS Status;
494 ISubdevice *ISubDevice;
495 PSUBDEVICE_DESCRIPTOR Descriptor;
496 CPortPinDMus * This;
497 PCLOSESTREAM_CONTEXT Ctx = (PCLOSESTREAM_CONTEXT)Context;
498
499 This = (CPortPinDMus*)Ctx->Pin;
500
501 if (This->m_MidiStream)
502 {
503 if (This->m_State != KSSTATE_STOP)
504 {
505 This->m_MidiStream->SetState(KSSTATE_STOP);
506 }
507 Stream = This->m_MidiStream;
508 This->m_MidiStream = NULL;
509 }
510
511 if (This->m_ServiceGroup)
512 {
513 This->m_ServiceGroup->RemoveMember(PSERVICESINK(This));
514 }
515
516 Status = This->m_Port->QueryInterface(IID_ISubdevice, (PVOID*)&ISubDevice);
517 if (NT_SUCCESS(Status))
518 {
519 Status = ISubDevice->GetDescriptor(&Descriptor);
520 if (NT_SUCCESS(Status))
521 {
522 Descriptor->Factory.Instances[This->m_ConnectDetails->PinId].CurrentPinInstanceCount--;
523 ISubDevice->Release();
524 }
525 }
526
527 if (This->m_Format)
528 {
529 ExFreePool(This->m_Format);
530 This->m_Format = NULL;
531 }
532
533 // complete the irp
534 Ctx->Irp->IoStatus.Information = 0;
535 Ctx->Irp->IoStatus.Status = STATUS_SUCCESS;
536 IoCompleteRequest(Ctx->Irp, IO_NO_INCREMENT);
537
538 // free the work item
539 IoFreeWorkItem(Ctx->WorkItem);
540
541 // free work item ctx
542 FreeItem(Ctx, TAG_PORTCLASS);
543
544 // destroy DMus pin
545 This->m_Filter->FreePin(PPORTPINDMUS(This));
546
547 if (Stream)
548 {
549 DPRINT1("Closing stream at Irql %u\n", KeGetCurrentIrql());
550 Stream->Release();
551 }
552 }
553
554 NTSTATUS
555 NTAPI
556 CPortPinDMus::Close(
557 IN PDEVICE_OBJECT DeviceObject,
558 IN PIRP Irp)
559 {
560 PCLOSESTREAM_CONTEXT Ctx;
561
562 if (m_MidiStream || m_Mxf)
563 {
564 Ctx = (PCLOSESTREAM_CONTEXT)AllocateItem(NonPagedPool, sizeof(CLOSESTREAM_CONTEXT), TAG_PORTCLASS);
565 if (!Ctx)
566 {
567 DPRINT1("Failed to allocate stream context\n");
568 goto cleanup;
569 }
570
571 Ctx->WorkItem = IoAllocateWorkItem(DeviceObject);
572 if (!Ctx->WorkItem)
573 {
574 DPRINT1("Failed to allocate work item\n");
575 goto cleanup;
576 }
577
578 Ctx->Irp = Irp;
579 Ctx->Pin = this;
580
581 IoMarkIrpPending(Irp);
582 Irp->IoStatus.Information = 0;
583 Irp->IoStatus.Status = STATUS_PENDING;
584
585 // defer work item
586 IoQueueWorkItem(Ctx->WorkItem, CloseStreamRoutineDMus, DelayedWorkQueue, (PVOID)Ctx);
587 // Return result
588 return STATUS_PENDING;
589 }
590
591 Irp->IoStatus.Information = 0;
592 Irp->IoStatus.Status = STATUS_SUCCESS;
593 IoCompleteRequest(Irp, IO_NO_INCREMENT);
594
595 return STATUS_SUCCESS;
596
597 cleanup:
598
599 if (Ctx)
600 FreeItem(Ctx, TAG_PORTCLASS);
601
602 Irp->IoStatus.Information = 0;
603 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
604 IoCompleteRequest(Irp, IO_NO_INCREMENT);
605 return STATUS_UNSUCCESSFUL;
606
607 }
608
609 NTSTATUS
610 NTAPI
611 CPortPinDMus::QuerySecurity(
612 IN PDEVICE_OBJECT DeviceObject,
613 IN PIRP Irp)
614 {
615 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
616 }
617
618 NTSTATUS
619 NTAPI
620 CPortPinDMus::SetSecurity(
621 IN PDEVICE_OBJECT DeviceObject,
622 IN PIRP Irp)
623 {
624 return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
625 }
626
627 BOOLEAN
628 NTAPI
629 CPortPinDMus::FastDeviceIoControl(
630 IN PFILE_OBJECT FileObject,
631 IN BOOLEAN Wait,
632 IN PVOID InputBuffer,
633 IN ULONG InputBufferLength,
634 OUT PVOID OutputBuffer,
635 IN ULONG OutputBufferLength,
636 IN ULONG IoControlCode,
637 OUT PIO_STATUS_BLOCK StatusBlock,
638 IN PDEVICE_OBJECT DeviceObject)
639 {
640 return FALSE;
641 }
642
643 BOOLEAN
644 NTAPI
645 CPortPinDMus::FastRead(
646 IN PFILE_OBJECT FileObject,
647 IN PLARGE_INTEGER FileOffset,
648 IN ULONG Length,
649 IN BOOLEAN Wait,
650 IN ULONG LockKey,
651 IN PVOID Buffer,
652 OUT PIO_STATUS_BLOCK StatusBlock,
653 IN PDEVICE_OBJECT DeviceObject)
654 {
655 return FALSE;
656 }
657
658 BOOLEAN
659 NTAPI
660 CPortPinDMus::FastWrite(
661 IN PFILE_OBJECT FileObject,
662 IN PLARGE_INTEGER FileOffset,
663 IN ULONG Length,
664 IN BOOLEAN Wait,
665 IN ULONG LockKey,
666 IN PVOID Buffer,
667 OUT PIO_STATUS_BLOCK StatusBlock,
668 IN PDEVICE_OBJECT DeviceObject)
669 {
670 return FALSE;
671 }
672
673 NTSTATUS
674 NTAPI
675 CPortPinDMus::Init(
676 IN PPORTDMUS Port,
677 IN PPORTFILTERDMUS Filter,
678 IN KSPIN_CONNECT * ConnectDetails,
679 IN KSPIN_DESCRIPTOR * KsPinDescriptor,
680 IN PDEVICE_OBJECT DeviceObject)
681 {
682 NTSTATUS Status;
683 PKSDATAFORMAT DataFormat;
684 DMUS_STREAM_TYPE Type;
685
686 Port->AddRef();
687 Filter->AddRef();
688
689 m_Port = Port;
690 m_Filter = Filter;
691 m_KsPinDescriptor = KsPinDescriptor;
692 m_ConnectDetails = ConnectDetails;
693 m_DeviceObject = DeviceObject;
694
695 GetDMusMiniport(Port, &m_Miniport, &m_MidiMiniport);
696
697 DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
698
699 DPRINT("CPortPinDMus::Init entered\n");
700
701 m_Format = (PKSDATAFORMAT)ExAllocatePoolWithTag(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
702 if (!m_Format)
703 return STATUS_INSUFFICIENT_RESOURCES;
704
705 RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
706
707 if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
708 {
709 Type = DMUS_STREAM_MIDI_RENDER;
710 }
711 else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
712 {
713 Type = DMUS_STREAM_MIDI_CAPTURE;
714 }
715 else
716 {
717 DPRINT1("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
718 KeBugCheck(0);
719 }
720
721 Status = NewIrpQueue(&m_IrpQueue);
722 if (!NT_SUCCESS(Status))
723 {
724 DPRINT1("Failed to allocate IrpQueue with %x\n", Status);
725 return Status;
726 }
727
728 if (m_MidiMiniport)
729 {
730 Status = m_MidiMiniport->NewStream(&m_MidiStream, NULL, NonPagedPool, ConnectDetails->PinId, Type, m_Format, &m_ServiceGroup);
731
732 DPRINT("CPortPinDMus::Init Status %x\n", Status);
733
734 if (!NT_SUCCESS(Status))
735 return Status;
736 }
737 else
738 {
739 Status = m_Miniport->NewStream(&m_Mxf, NULL, NonPagedPool, ConnectDetails->PinId, Type, m_Format, &m_ServiceGroup, PAllocatorMXF(this), PMASTERCLOCK(this),&m_SchedulePreFetch);
740
741 DPRINT("CPortPinDMus::Init Status %x\n", Status);
742
743 if (!NT_SUCCESS(Status))
744 return Status;
745
746 if (Type == DMUS_STREAM_MIDI_CAPTURE)
747 {
748 Status = m_Mxf->ConnectOutput(PMXF(this));
749 if (!NT_SUCCESS(Status))
750 {
751 DPRINT("IMXF_ConnectOutput failed with Status %x\n", Status);
752 return Status;
753 }
754 }
755
756 ExInitializeNPagedLookasideList(&m_LookAsideEvent, NULL, NULL, 0, sizeof(DMUS_KERNEL_EVENT_WITH_TAG), TAG_PORTCLASS, 0);
757 ExInitializeNPagedLookasideList(&m_LookAsideBuffer, NULL, NULL, 0, PAGE_SIZE, TAG_PORTCLASS, 0);
758 }
759
760 if (m_ServiceGroup)
761 {
762 Status = m_ServiceGroup->AddMember(PSERVICESINK(this));
763 if (!NT_SUCCESS(Status))
764 {
765 DPRINT1("Failed to add pin to service group\n");
766 return Status;
767 }
768 m_ServiceGroup->SupportDelayedService();
769 }
770
771 Status = m_IrpQueue->Init(ConnectDetails, m_Format, DeviceObject, 0, 0, NULL);
772 if (!NT_SUCCESS(Status))
773 {
774 DPRINT1("IrpQueue_Init failed with %x\n", Status);
775 return Status;
776 }
777
778 m_State = KSSTATE_STOP;
779 m_Capture = Type;
780
781 return STATUS_SUCCESS;
782 }
783
784 VOID
785 NTAPI
786 CPortPinDMus::Notify()
787 {
788 m_ServiceGroup->RequestService();
789 }
790
791 NTSTATUS
792 NewPortPinDMus(
793 OUT IPortPinDMus ** OutPin)
794 {
795 CPortPinDMus * This;
796
797 This = new (NonPagedPool, TAG_PORTCLASS)CPortPinDMus(NULL);
798 if (!This)
799 return STATUS_INSUFFICIENT_RESOURCES;
800
801 This->AddRef();
802
803 // store result
804 *OutPin = (IPortPinDMus*)This;
805
806 return STATUS_SUCCESS;
807 }
808