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