1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Kernel Streaming
4  * FILE:            drivers/wdm/audio/backpln/portcls/pin_wavert.cpp
5  * PURPOSE:         WaveRT IRP Audio Pin
6  * PROGRAMMER:      Johannes Anderwald
7  */
8 
9 #include "private.hpp"
10 
11 #ifndef YDEBUG
12 #define NDEBUG
13 #endif
14 
15 #include <debug.h>
16 
17 class CPortPinWaveRT : public CUnknownImpl<IPortPinWaveRT>
18 {
19 public:
20     STDMETHODIMP QueryInterface( REFIID InterfaceId, PVOID* Interface);
21 
22     IMP_IPortPinWaveRT;
23     CPortPinWaveRT(IUnknown *OuterUnknown){}
24     virtual ~CPortPinWaveRT(){}
25 
26 protected:
27 
28     IPortWaveRT * m_Port;
29     IPortFilterWaveRT * m_Filter;
30     KSPIN_DESCRIPTOR * m_KsPinDescriptor;
31     PMINIPORTWAVERT m_Miniport;
32     PMINIPORTWAVERTSTREAM m_Stream;
33     PPORTWAVERTSTREAM m_PortStream;
34     KSSTATE m_State;
35     PKSDATAFORMAT m_Format;
36     KSPIN_CONNECT * m_ConnectDetails;
37 
38     PVOID m_CommonBuffer;
39     ULONG m_CommonBufferSize;
40     ULONG m_CommonBufferOffset;
41 
42     IIrpQueue * m_IrpQueue;
43 
44     BOOL m_Capture;
45 
46     ULONG m_TotalPackets;
47     ULONG m_PreCompleted;
48     ULONG m_PostCompleted;
49 
50     ULONGLONG m_Delay;
51 
52     MEMORY_CACHING_TYPE m_CacheType;
53     PMDL m_Mdl;
54 
55     NTSTATUS NTAPI HandleKsProperty(IN PIRP Irp);
56     NTSTATUS NTAPI HandleKsStream(IN PIRP Irp);
57     VOID NTAPI SetStreamState(IN KSSTATE State);
58     friend VOID NTAPI SetStreamWorkerRoutine(IN PDEVICE_OBJECT  DeviceObject, IN PVOID  Context);
59     friend VOID NTAPI CloseStreamRoutine(IN PDEVICE_OBJECT  DeviceObject, IN PVOID Context);
60 
61 };
62 
63 
64 typedef struct
65 {
66     CPortPinWaveRT *Pin;
67     PIO_WORKITEM WorkItem;
68     KSSTATE State;
69 }SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT;
70 
71 
72 //==================================================================================================================================
73 NTSTATUS
74 NTAPI
75 CPortPinWaveRT::QueryInterface(
76     IN  REFIID refiid,
77     OUT PVOID* Output)
78 {
79     DPRINT("IServiceSink_fnQueryInterface entered\n");
80 
81     if (IsEqualGUIDAligned(refiid, IID_IIrpTarget) ||
82         IsEqualGUIDAligned(refiid, IID_IUnknown))
83     {
84         *Output = PVOID(PUNKNOWN((IIrpTarget*)this));
85         PUNKNOWN(*Output)->AddRef();
86         return STATUS_SUCCESS;
87     }
88     return STATUS_UNSUCCESSFUL;
89 }
90 
91 //==================================================================================================================================
92 
93 NTSTATUS
94 NTAPI
95 CPortPinWaveRT::NewIrpTarget(
96     OUT struct IIrpTarget **OutTarget,
97     IN PCWSTR Name,
98     IN PUNKNOWN Unknown,
99     IN POOL_TYPE PoolType,
100     IN PDEVICE_OBJECT DeviceObject,
101     IN PIRP Irp,
102     IN KSOBJECT_CREATE *CreateObject)
103 {
104     UNIMPLEMENTED;
105     return STATUS_UNSUCCESSFUL;
106 }
107 
108 NTSTATUS
109 NTAPI
110 CPortPinWaveRT::HandleKsProperty(
111     IN PIRP Irp)
112 {
113     PKSPROPERTY Property;
114     NTSTATUS Status;
115     UNICODE_STRING GuidString;
116     PIO_STACK_LOCATION IoStack;
117 
118     IoStack = IoGetCurrentIrpStackLocation(Irp);
119 
120     DPRINT("IPortPinWave_HandleKsProperty entered\n");
121 
122     if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY))
123     {
124         Irp->IoStatus.Information = 0;
125         Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
126         IoCompleteRequest(Irp, IO_NO_INCREMENT);
127         return STATUS_INVALID_PARAMETER;
128     }
129 
130     Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
131 
132     if (IsEqualGUIDAligned(Property->Set, KSPROPSETID_Connection))
133     {
134         if (Property->Id == KSPROPERTY_CONNECTION_STATE)
135         {
136             PKSSTATE State = (PKSSTATE)Irp->UserBuffer;
137 
138             if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KSSTATE))
139             {
140                 Irp->IoStatus.Information = sizeof(KSSTATE);
141                 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
142                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
143                 return STATUS_BUFFER_TOO_SMALL;
144             }
145 
146             if (Property->Flags & KSPROPERTY_TYPE_SET)
147             {
148                 Status = STATUS_UNSUCCESSFUL;
149                 Irp->IoStatus.Information = 0;
150 
151                 if (m_Stream)
152                 {
153                     Status = m_Stream->SetState(*State);
154 
155                     DPRINT("Setting state %u %x\n", *State, Status);
156                     if (NT_SUCCESS(Status))
157                     {
158                         m_State = *State;
159                     }
160                 }
161                 Irp->IoStatus.Status = Status;
162                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
163                 return Status;
164             }
165             else if (Property->Flags & KSPROPERTY_TYPE_GET)
166             {
167                 *State = m_State;
168                 Irp->IoStatus.Information = sizeof(KSSTATE);
169                 Irp->IoStatus.Status = STATUS_SUCCESS;
170                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
171                 return STATUS_SUCCESS;
172             }
173         }
174         else if (Property->Id == KSPROPERTY_CONNECTION_DATAFORMAT)
175         {
176             PKSDATAFORMAT DataFormat = (PKSDATAFORMAT)Irp->UserBuffer;
177             if (Property->Flags & KSPROPERTY_TYPE_SET)
178             {
179                 PKSDATAFORMAT NewDataFormat;
180                 if (!RtlCompareMemory(DataFormat, m_Format, DataFormat->FormatSize))
181                 {
182                     Irp->IoStatus.Information = DataFormat->FormatSize;
183                     Irp->IoStatus.Status = STATUS_SUCCESS;
184                     IoCompleteRequest(Irp, IO_NO_INCREMENT);
185                     return STATUS_SUCCESS;
186                 }
187 
188                 NewDataFormat = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
189                 if (!NewDataFormat)
190                 {
191                     Irp->IoStatus.Information = 0;
192                     Irp->IoStatus.Status = STATUS_NO_MEMORY;
193                     IoCompleteRequest(Irp, IO_NO_INCREMENT);
194                     return STATUS_NO_MEMORY;
195                 }
196                 RtlMoveMemory(NewDataFormat, DataFormat, DataFormat->FormatSize);
197 
198                 if (m_Stream)
199                 {
200 #if 0
201                     ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
202                     ASSERT(NewDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX));
203                     ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, &KSDATAFORMAT_TYPE_AUDIO));
204                     ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM));
205                     ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX));
206 
207                     ASSERT(m_State == KSSTATE_STOP);
208 #endif
209                     DPRINT("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels,
210                                                                                  ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample,
211                                                                                  ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec);
212 
213                     Status = m_Stream->SetFormat(NewDataFormat);
214                     if (NT_SUCCESS(Status))
215                     {
216                         if (m_Format)
217                             FreeItem(m_Format, TAG_PORTCLASS);
218 
219                         m_Format = NewDataFormat;
220                         Irp->IoStatus.Information = DataFormat->FormatSize;
221                         Irp->IoStatus.Status = STATUS_SUCCESS;
222                         IoCompleteRequest(Irp, IO_NO_INCREMENT);
223                         return STATUS_SUCCESS;
224                     }
225                 }
226                 DPRINT("Failed to set format\n");
227                 Irp->IoStatus.Information = 0;
228                 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
229                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
230                 return STATUS_UNSUCCESSFUL;
231             }
232             else if (Property->Flags & KSPROPERTY_TYPE_GET)
233             {
234                 if (!m_Format)
235                 {
236                     DPRINT("No format\n");
237                     Irp->IoStatus.Information = 0;
238                     Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
239                     IoCompleteRequest(Irp, IO_NO_INCREMENT);
240                     return STATUS_UNSUCCESSFUL;
241                 }
242                 if (m_Format->FormatSize > IoStack->Parameters.DeviceIoControl.OutputBufferLength)
243                 {
244                     Irp->IoStatus.Information = m_Format->FormatSize;
245                     Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
246                     IoCompleteRequest(Irp, IO_NO_INCREMENT);
247                     return STATUS_BUFFER_TOO_SMALL;
248                 }
249 
250                 RtlMoveMemory(DataFormat, m_Format, m_Format->FormatSize);
251                 Irp->IoStatus.Information = DataFormat->FormatSize;
252                 Irp->IoStatus.Status = STATUS_SUCCESS;
253                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
254                 return STATUS_SUCCESS;
255             }
256         }
257 
258     }
259     RtlStringFromGUID(Property->Set, &GuidString);
260     DPRINT("Unhandled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
261     RtlFreeUnicodeString(&GuidString);
262 
263     Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
264     Irp->IoStatus.Information = 0;
265     IoCompleteRequest(Irp, IO_NO_INCREMENT);
266     return STATUS_NOT_IMPLEMENTED;
267 }
268 
269 NTSTATUS
270 NTAPI
271 CPortPinWaveRT::HandleKsStream(
272     IN PIRP Irp)
273 {
274     DPRINT("IPortPinWaveRT_HandleKsStream entered State %u Stream %p is UNIMPLEMENTED\n", m_State, m_Stream);
275 
276     return STATUS_PENDING;
277 }
278 
279 NTSTATUS
280 NTAPI
281 CPortPinWaveRT::DeviceIoControl(
282     IN PDEVICE_OBJECT DeviceObject,
283     IN PIRP Irp)
284 {
285     PIO_STACK_LOCATION IoStack;
286 
287     IoStack = IoGetCurrentIrpStackLocation(Irp);
288 
289 
290     switch (IoStack->Parameters.DeviceIoControl.IoControlCode)
291     {
292         case IOCTL_KS_PROPERTY:
293             return HandleKsProperty(Irp);
294 
295         case IOCTL_KS_ENABLE_EVENT:
296             /* FIXME UNIMPLEMENTED */
297             UNIMPLEMENTED_ONCE;
298             break;
299 
300         case IOCTL_KS_DISABLE_EVENT:
301             /* FIXME UNIMPLEMENTED */
302             UNIMPLEMENTED_ONCE;
303             break;
304 
305         case IOCTL_KS_HANDSHAKE:
306             /* FIXME UNIMPLEMENTED */
307             UNIMPLEMENTED_ONCE;
308             break;
309 
310         case IOCTL_KS_METHOD:
311             /* FIXME UNIMPLEMENTED */
312             UNIMPLEMENTED_ONCE;
313             return KsDefaultDeviceIoCompletion(DeviceObject, Irp);
314 
315         case IOCTL_KS_RESET_STATE:
316             /* FIXME UNIMPLEMENTED */
317             UNIMPLEMENTED_ONCE;
318             break;
319 
320         case IOCTL_KS_WRITE_STREAM:
321         case IOCTL_KS_READ_STREAM:
322             return HandleKsStream(Irp);
323 
324         default:
325             return KsDefaultDeviceIoCompletion(DeviceObject, Irp);
326     }
327 
328     Irp->IoStatus.Information = 0;
329     Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
330     IoCompleteRequest(Irp, IO_NO_INCREMENT);
331 
332     return STATUS_UNSUCCESSFUL;
333 }
334 
335 NTSTATUS
336 NTAPI
337 CPortPinWaveRT::Read(
338     IN PDEVICE_OBJECT DeviceObject,
339     IN PIRP Irp)
340 {
341     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
342 }
343 
344 NTSTATUS
345 NTAPI
346 CPortPinWaveRT::Write(
347     IN PDEVICE_OBJECT DeviceObject,
348     IN PIRP Irp)
349 {
350     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
351 }
352 
353 NTSTATUS
354 NTAPI
355 CPortPinWaveRT::Flush(
356     IN PDEVICE_OBJECT DeviceObject,
357     IN PIRP Irp)
358 {
359     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
360 }
361 
362 VOID
363 NTAPI
364 CloseStreamRoutine(
365     IN PDEVICE_OBJECT  DeviceObject,
366     IN PVOID Context)
367 {
368     PMINIPORTWAVERTSTREAM Stream;
369     NTSTATUS Status;
370     ISubdevice *ISubDevice;
371     PSUBDEVICE_DESCRIPTOR Descriptor;
372     CPortPinWaveRT * This;
373     PCLOSESTREAM_CONTEXT Ctx = (PCLOSESTREAM_CONTEXT)Context;
374 
375     This = (CPortPinWaveRT*)Ctx->Pin;
376 
377     if (This->m_Stream)
378     {
379         if (This->m_State != KSSTATE_STOP)
380         {
381             This->m_Stream->SetState(KSSTATE_STOP);
382             KeStallExecutionProcessor(10);
383         }
384     }
385 
386     Status = This->m_Port->QueryInterface(IID_ISubdevice, (PVOID*)&ISubDevice);
387     if (NT_SUCCESS(Status))
388     {
389         Status = ISubDevice->GetDescriptor(&Descriptor);
390         if (NT_SUCCESS(Status))
391         {
392             Descriptor->Factory.Instances[This->m_ConnectDetails->PinId].CurrentPinInstanceCount--;
393         }
394         ISubDevice->Release();
395     }
396 
397     if (This->m_Format)
398     {
399         FreeItem(This->m_Format, TAG_PORTCLASS);
400         This->m_Format = NULL;
401     }
402 
403     if (This->m_IrpQueue)
404     {
405         This->m_IrpQueue->Release();
406     }
407 
408     // complete the irp
409     Ctx->Irp->IoStatus.Information = 0;
410     Ctx->Irp->IoStatus.Status = STATUS_SUCCESS;
411     IoCompleteRequest(Ctx->Irp, IO_NO_INCREMENT);
412 
413     // free the work item
414     IoFreeWorkItem(Ctx->WorkItem);
415 
416     // free work item ctx
417     FreeItem(Ctx, TAG_PORTCLASS);
418 
419     if (This->m_Stream)
420     {
421         Stream = This->m_Stream;
422         This->m_Stream = NULL;
423         DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
424         Stream->Release();
425     }
426 }
427 
428 NTSTATUS
429 NTAPI
430 CPortPinWaveRT::Close(
431     IN PDEVICE_OBJECT DeviceObject,
432     IN PIRP Irp)
433 {
434     PCLOSESTREAM_CONTEXT Ctx;
435 
436     if (m_Stream)
437     {
438         Ctx = (PCLOSESTREAM_CONTEXT)AllocateItem(NonPagedPool, sizeof(CLOSESTREAM_CONTEXT), TAG_PORTCLASS);
439         if (!Ctx)
440         {
441             DPRINT("Failed to allocate stream context\n");
442             goto cleanup;
443         }
444 
445         Ctx->WorkItem = IoAllocateWorkItem(DeviceObject);
446         if (!Ctx->WorkItem)
447         {
448             DPRINT("Failed to allocate work item\n");
449             goto cleanup;
450         }
451 
452         Ctx->Irp = Irp;
453         Ctx->Pin = this;
454 
455         IoMarkIrpPending(Irp);
456         Irp->IoStatus.Information = 0;
457         Irp->IoStatus.Status = STATUS_PENDING;
458 
459         // defer work item
460         IoQueueWorkItem(Ctx->WorkItem, CloseStreamRoutine, DelayedWorkQueue, (PVOID)Ctx);
461         // Return result
462         return STATUS_PENDING;
463     }
464 
465     Irp->IoStatus.Information = 0;
466     Irp->IoStatus.Status = STATUS_SUCCESS;
467     IoCompleteRequest(Irp, IO_NO_INCREMENT);
468 
469     return STATUS_SUCCESS;
470 
471 cleanup:
472 
473     if (Ctx)
474         FreeItem(Ctx, TAG_PORTCLASS);
475 
476     Irp->IoStatus.Information = 0;
477     Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
478     IoCompleteRequest(Irp, IO_NO_INCREMENT);
479     return STATUS_UNSUCCESSFUL;
480 
481 }
482 
483 NTSTATUS
484 NTAPI
485 CPortPinWaveRT::QuerySecurity(
486     IN PDEVICE_OBJECT DeviceObject,
487     IN PIRP Irp)
488 {
489     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
490 }
491 
492 NTSTATUS
493 NTAPI
494 CPortPinWaveRT::SetSecurity(
495     IN PDEVICE_OBJECT DeviceObject,
496     IN PIRP Irp)
497 {
498     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
499 }
500 
501 BOOLEAN
502 NTAPI
503 CPortPinWaveRT::FastDeviceIoControl(
504     IN PFILE_OBJECT FileObject,
505     IN BOOLEAN Wait,
506     IN PVOID InputBuffer,
507     IN ULONG InputBufferLength,
508     OUT PVOID OutputBuffer,
509     IN ULONG OutputBufferLength,
510     IN ULONG IoControlCode,
511     OUT PIO_STATUS_BLOCK StatusBlock,
512     IN PDEVICE_OBJECT DeviceObject)
513 {
514     return FALSE;
515 }
516 
517 BOOLEAN
518 NTAPI
519 CPortPinWaveRT::FastRead(
520     IN PFILE_OBJECT FileObject,
521     IN PLARGE_INTEGER FileOffset,
522     IN ULONG Length,
523     IN BOOLEAN Wait,
524     IN ULONG LockKey,
525     IN PVOID Buffer,
526     OUT PIO_STATUS_BLOCK StatusBlock,
527     IN PDEVICE_OBJECT DeviceObject)
528 {
529     return FALSE;
530 }
531 
532 BOOLEAN
533 NTAPI
534 CPortPinWaveRT::FastWrite(
535     IN PFILE_OBJECT FileObject,
536     IN PLARGE_INTEGER FileOffset,
537     IN ULONG Length,
538     IN BOOLEAN Wait,
539     IN ULONG LockKey,
540     IN PVOID Buffer,
541     OUT PIO_STATUS_BLOCK StatusBlock,
542     IN PDEVICE_OBJECT DeviceObject)
543 {
544     return FALSE;
545 }
546 
547 NTSTATUS
548 NTAPI
549 CPortPinWaveRT::Init(
550     IN PPORTWAVERT Port,
551     IN PPORTFILTERWAVERT Filter,
552     IN KSPIN_CONNECT * ConnectDetails,
553     IN KSPIN_DESCRIPTOR * KsPinDescriptor,
554     IN PDEVICE_OBJECT DeviceObject)
555 {
556     NTSTATUS Status;
557     PKSDATAFORMAT DataFormat;
558     BOOLEAN Capture;
559     KSRTAUDIO_HWLATENCY Latency;
560 
561     Port->AddRef();
562     Filter->AddRef();
563 
564     m_Port = Port;
565     m_Filter = Filter;
566     m_KsPinDescriptor = KsPinDescriptor;
567     m_ConnectDetails = ConnectDetails;
568     m_Miniport = GetWaveRTMiniport(Port);
569 
570     DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
571 
572     DPRINT("CPortPinWaveRT::Init entered\n");
573 
574     m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
575     if (!m_Format)
576         return STATUS_INSUFFICIENT_RESOURCES;
577 
578     RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
579 
580     Status = NewIrpQueue(&m_IrpQueue);
581     if (!NT_SUCCESS(Status))
582     {
583         goto cleanup;
584     }
585 
586     Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor, 0, 0, FALSE);
587     if (!NT_SUCCESS(Status))
588     {
589         goto cleanup;
590     }
591 
592     Status = NewPortWaveRTStream(&m_PortStream);
593     if (!NT_SUCCESS(Status))
594     {
595         goto cleanup;
596     }
597 
598     if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
599     {
600         Capture = FALSE;
601     }
602     else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
603     {
604         Capture = TRUE;
605     }
606     else
607     {
608         DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
609         KeBugCheck(0);
610         while(TRUE);
611     }
612 
613     Status = m_Miniport->NewStream(&m_Stream, m_PortStream, ConnectDetails->PinId, Capture, m_Format);
614     DPRINT("CPortPinWaveRT::Init Status %x\n", Status);
615 
616     if (!NT_SUCCESS(Status))
617         goto cleanup;
618 
619     m_Stream->GetHWLatency(&Latency);
620     // delay of 10 millisec
621     m_Delay = Int32x32To64(10, -10000);
622 
623     Status = m_Stream->AllocateAudioBuffer(16384 * 11, &m_Mdl, &m_CommonBufferSize, &m_CommonBufferOffset, &m_CacheType);
624     if (!NT_SUCCESS(Status))
625     {
626         DPRINT("AllocateAudioBuffer failed with %x\n", Status);
627         goto cleanup;
628     }
629 
630     m_CommonBuffer = MmGetSystemAddressForMdlSafe(m_Mdl, NormalPagePriority);
631     if (!m_CommonBuffer)
632     {
633         DPRINT("Failed to get system address %x\n", Status);
634         IoFreeMdl(m_Mdl);
635         m_Mdl = NULL;
636         goto cleanup;
637     }
638 
639     DPRINT("Setting state to acquire %x\n", m_Stream->SetState(KSSTATE_ACQUIRE));
640     DPRINT("Setting state to pause %x\n", m_Stream->SetState(KSSTATE_PAUSE));
641     m_State = KSSTATE_PAUSE;
642     return STATUS_SUCCESS;
643 
644 cleanup:
645     if (m_IrpQueue)
646     {
647         m_IrpQueue->Release();
648         m_IrpQueue = NULL;
649     }
650 
651     if (m_Format)
652     {
653         FreeItem(m_Format, TAG_PORTCLASS);
654         m_Format = NULL;
655     }
656 
657     if (m_Stream)
658     {
659         m_Stream->Release();
660         m_Stream = NULL;
661     }
662     else
663     {
664         if (m_PortStream)
665         {
666             m_PortStream->Release();
667             m_PortStream = NULL;
668         }
669 
670     }
671     return Status;
672 }
673 
674 
675 NTSTATUS
676 NewPortPinWaveRT(
677     OUT IPortPinWaveRT ** OutPin)
678 {
679     CPortPinWaveRT * This;
680 
681     This = new(NonPagedPool, TAG_PORTCLASS) CPortPinWaveRT(NULL);
682     if (!This)
683         return STATUS_INSUFFICIENT_RESOURCES;
684 
685     This->AddRef();
686 
687     // store result
688     *OutPin = (PPORTPINWAVERT)This;
689 
690     return STATUS_SUCCESS;
691 }
692