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