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     switch (IoStack->Parameters.DeviceIoControl.IoControlCode)
309     {
310         case IOCTL_KS_PROPERTY:
311             return HandleKsProperty(Irp);
312 
313         case IOCTL_KS_ENABLE_EVENT:
314             /* FIXME UNIMPLEMENTED */
315             UNIMPLEMENTED_ONCE;
316             break;
317 
318         case IOCTL_KS_DISABLE_EVENT:
319             /* FIXME UNIMPLEMENTED */
320             UNIMPLEMENTED_ONCE;
321             break;
322 
323         case IOCTL_KS_HANDSHAKE:
324             /* FIXME UNIMPLEMENTED */
325             UNIMPLEMENTED_ONCE;
326             break;
327 
328         case IOCTL_KS_METHOD:
329             /* FIXME UNIMPLEMENTED */
330             UNIMPLEMENTED_ONCE;
331             return KsDefaultDeviceIoCompletion(DeviceObject, Irp);
332 
333         case IOCTL_KS_RESET_STATE:
334             /* FIXME UNIMPLEMENTED */
335             UNIMPLEMENTED_ONCE;
336             break;
337 
338         case IOCTL_KS_WRITE_STREAM:
339         case IOCTL_KS_READ_STREAM:
340             return HandleKsStream(Irp);
341 
342         default:
343             return KsDefaultDeviceIoCompletion(DeviceObject, Irp);
344     }
345 
346     Irp->IoStatus.Information = 0;
347     Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
348     IoCompleteRequest(Irp, IO_NO_INCREMENT);
349 
350     return STATUS_UNSUCCESSFUL;
351 }
352 
353 NTSTATUS
354 NTAPI
355 CPortPinWaveRT::Read(
356     IN PDEVICE_OBJECT DeviceObject,
357     IN PIRP Irp)
358 {
359     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
360 }
361 
362 NTSTATUS
363 NTAPI
364 CPortPinWaveRT::Write(
365     IN PDEVICE_OBJECT DeviceObject,
366     IN PIRP Irp)
367 {
368     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
369 }
370 
371 NTSTATUS
372 NTAPI
373 CPortPinWaveRT::Flush(
374     IN PDEVICE_OBJECT DeviceObject,
375     IN PIRP Irp)
376 {
377     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
378 }
379 
380 VOID
381 NTAPI
382 CloseStreamRoutine(
383     IN PDEVICE_OBJECT  DeviceObject,
384     IN PVOID Context)
385 {
386     PMINIPORTWAVERTSTREAM Stream;
387     NTSTATUS Status;
388     ISubdevice *ISubDevice;
389     PSUBDEVICE_DESCRIPTOR Descriptor;
390     CPortPinWaveRT * This;
391     PCLOSESTREAM_CONTEXT Ctx = (PCLOSESTREAM_CONTEXT)Context;
392 
393     This = (CPortPinWaveRT*)Ctx->Pin;
394 
395     if (This->m_Stream)
396     {
397         if (This->m_State != KSSTATE_STOP)
398         {
399             This->m_Stream->SetState(KSSTATE_STOP);
400             KeStallExecutionProcessor(10);
401         }
402     }
403 
404     Status = This->m_Port->QueryInterface(IID_ISubdevice, (PVOID*)&ISubDevice);
405     if (NT_SUCCESS(Status))
406     {
407         Status = ISubDevice->GetDescriptor(&Descriptor);
408         if (NT_SUCCESS(Status))
409         {
410             Descriptor->Factory.Instances[This->m_ConnectDetails->PinId].CurrentPinInstanceCount--;
411         }
412         ISubDevice->Release();
413     }
414 
415     if (This->m_Format)
416     {
417         FreeItem(This->m_Format, TAG_PORTCLASS);
418         This->m_Format = NULL;
419     }
420 
421     if (This->m_IrpQueue)
422     {
423         This->m_IrpQueue->Release();
424     }
425 
426     // complete the irp
427     Ctx->Irp->IoStatus.Information = 0;
428     Ctx->Irp->IoStatus.Status = STATUS_SUCCESS;
429     IoCompleteRequest(Ctx->Irp, IO_NO_INCREMENT);
430 
431     // free the work item
432     IoFreeWorkItem(Ctx->WorkItem);
433 
434     // free work item ctx
435     FreeItem(Ctx, TAG_PORTCLASS);
436 
437     if (This->m_Stream)
438     {
439         Stream = This->m_Stream;
440         This->m_Stream = NULL;
441         DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
442         Stream->Release();
443     }
444 }
445 
446 NTSTATUS
447 NTAPI
448 CPortPinWaveRT::Close(
449     IN PDEVICE_OBJECT DeviceObject,
450     IN PIRP Irp)
451 {
452     PCLOSESTREAM_CONTEXT Ctx;
453 
454     if (m_Stream)
455     {
456         Ctx = (PCLOSESTREAM_CONTEXT)AllocateItem(NonPagedPool, sizeof(CLOSESTREAM_CONTEXT), TAG_PORTCLASS);
457         if (!Ctx)
458         {
459             DPRINT("Failed to allocate stream context\n");
460             goto cleanup;
461         }
462 
463         Ctx->WorkItem = IoAllocateWorkItem(DeviceObject);
464         if (!Ctx->WorkItem)
465         {
466             DPRINT("Failed to allocate work item\n");
467             goto cleanup;
468         }
469 
470         Ctx->Irp = Irp;
471         Ctx->Pin = this;
472 
473         IoMarkIrpPending(Irp);
474         Irp->IoStatus.Information = 0;
475         Irp->IoStatus.Status = STATUS_PENDING;
476 
477         // defer work item
478         IoQueueWorkItem(Ctx->WorkItem, CloseStreamRoutine, DelayedWorkQueue, (PVOID)Ctx);
479         // Return result
480         return STATUS_PENDING;
481     }
482 
483     Irp->IoStatus.Information = 0;
484     Irp->IoStatus.Status = STATUS_SUCCESS;
485     IoCompleteRequest(Irp, IO_NO_INCREMENT);
486 
487     return STATUS_SUCCESS;
488 
489 cleanup:
490 
491     if (Ctx)
492         FreeItem(Ctx, TAG_PORTCLASS);
493 
494     Irp->IoStatus.Information = 0;
495     Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
496     IoCompleteRequest(Irp, IO_NO_INCREMENT);
497     return STATUS_UNSUCCESSFUL;
498 
499 }
500 
501 NTSTATUS
502 NTAPI
503 CPortPinWaveRT::QuerySecurity(
504     IN PDEVICE_OBJECT DeviceObject,
505     IN PIRP Irp)
506 {
507     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
508 }
509 
510 NTSTATUS
511 NTAPI
512 CPortPinWaveRT::SetSecurity(
513     IN PDEVICE_OBJECT DeviceObject,
514     IN PIRP Irp)
515 {
516     return KsDispatchInvalidDeviceRequest(DeviceObject, Irp);
517 }
518 
519 BOOLEAN
520 NTAPI
521 CPortPinWaveRT::FastDeviceIoControl(
522     IN PFILE_OBJECT FileObject,
523     IN BOOLEAN Wait,
524     IN PVOID InputBuffer,
525     IN ULONG InputBufferLength,
526     OUT PVOID OutputBuffer,
527     IN ULONG OutputBufferLength,
528     IN ULONG IoControlCode,
529     OUT PIO_STATUS_BLOCK StatusBlock,
530     IN PDEVICE_OBJECT DeviceObject)
531 {
532     return FALSE;
533 }
534 
535 BOOLEAN
536 NTAPI
537 CPortPinWaveRT::FastRead(
538     IN PFILE_OBJECT FileObject,
539     IN PLARGE_INTEGER FileOffset,
540     IN ULONG Length,
541     IN BOOLEAN Wait,
542     IN ULONG LockKey,
543     IN PVOID Buffer,
544     OUT PIO_STATUS_BLOCK StatusBlock,
545     IN PDEVICE_OBJECT DeviceObject)
546 {
547     return FALSE;
548 }
549 
550 BOOLEAN
551 NTAPI
552 CPortPinWaveRT::FastWrite(
553     IN PFILE_OBJECT FileObject,
554     IN PLARGE_INTEGER FileOffset,
555     IN ULONG Length,
556     IN BOOLEAN Wait,
557     IN ULONG LockKey,
558     IN PVOID Buffer,
559     OUT PIO_STATUS_BLOCK StatusBlock,
560     IN PDEVICE_OBJECT DeviceObject)
561 {
562     return FALSE;
563 }
564 
565 NTSTATUS
566 NTAPI
567 CPortPinWaveRT::Init(
568     IN PPORTWAVERT Port,
569     IN PPORTFILTERWAVERT Filter,
570     IN KSPIN_CONNECT * ConnectDetails,
571     IN KSPIN_DESCRIPTOR * KsPinDescriptor,
572     IN PDEVICE_OBJECT DeviceObject)
573 {
574     NTSTATUS Status;
575     PKSDATAFORMAT DataFormat;
576     BOOLEAN Capture;
577     KSRTAUDIO_HWLATENCY Latency;
578 
579     Port->AddRef();
580     Filter->AddRef();
581 
582     m_Port = Port;
583     m_Filter = Filter;
584     m_KsPinDescriptor = KsPinDescriptor;
585     m_ConnectDetails = ConnectDetails;
586     m_Miniport = GetWaveRTMiniport(Port);
587 
588     DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
589 
590     DPRINT("CPortPinWaveRT::Init entered\n");
591 
592     m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
593     if (!m_Format)
594         return STATUS_INSUFFICIENT_RESOURCES;
595 
596     RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
597 
598     Status = NewIrpQueue(&m_IrpQueue);
599     if (!NT_SUCCESS(Status))
600     {
601         goto cleanup;
602     }
603 
604     Status = m_IrpQueue->Init(ConnectDetails, KsPinDescriptor, 0, 0, FALSE);
605     if (!NT_SUCCESS(Status))
606     {
607         goto cleanup;
608     }
609 
610     Status = NewPortWaveRTStream(&m_PortStream);
611     if (!NT_SUCCESS(Status))
612     {
613         goto cleanup;
614     }
615 
616     if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
617     {
618         Capture = FALSE;
619     }
620     else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
621     {
622         Capture = TRUE;
623     }
624     else
625     {
626         DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
627         KeBugCheck(0);
628         while(TRUE);
629     }
630 
631     Status = m_Miniport->NewStream(&m_Stream, m_PortStream, ConnectDetails->PinId, Capture, m_Format);
632     DPRINT("CPortPinWaveRT::Init Status %x\n", Status);
633 
634     if (!NT_SUCCESS(Status))
635         goto cleanup;
636 
637     m_Stream->GetHWLatency(&Latency);
638     // delay of 10 millisec
639     m_Delay = Int32x32To64(10, -10000);
640 
641     Status = m_Stream->AllocateAudioBuffer(16384 * 11, &m_Mdl, &m_CommonBufferSize, &m_CommonBufferOffset, &m_CacheType);
642     if (!NT_SUCCESS(Status))
643     {
644         DPRINT("AllocateAudioBuffer failed with %x\n", Status);
645         goto cleanup;
646     }
647 
648     m_CommonBuffer = MmGetSystemAddressForMdlSafe(m_Mdl, NormalPagePriority);
649     if (!m_CommonBuffer)
650     {
651         DPRINT("Failed to get system address %x\n", Status);
652         IoFreeMdl(m_Mdl);
653         m_Mdl = NULL;
654         goto cleanup;
655     }
656 
657     DPRINT("Setting state to acquire %x\n", m_Stream->SetState(KSSTATE_ACQUIRE));
658     DPRINT("Setting state to pause %x\n", m_Stream->SetState(KSSTATE_PAUSE));
659     m_State = KSSTATE_PAUSE;
660     return STATUS_SUCCESS;
661 
662 cleanup:
663     if (m_IrpQueue)
664     {
665         m_IrpQueue->Release();
666         m_IrpQueue = NULL;
667     }
668 
669     if (m_Format)
670     {
671         FreeItem(m_Format, TAG_PORTCLASS);
672         m_Format = NULL;
673     }
674 
675     if (m_Stream)
676     {
677         m_Stream->Release();
678         m_Stream = NULL;
679     }
680     else
681     {
682         if (m_PortStream)
683         {
684             m_PortStream->Release();
685             m_PortStream = NULL;
686         }
687 
688     }
689     return Status;
690 }
691 
692 
693 NTSTATUS
694 NewPortPinWaveRT(
695     OUT IPortPinWaveRT ** OutPin)
696 {
697     CPortPinWaveRT * This;
698 
699     This = new(NonPagedPool, TAG_PORTCLASS) CPortPinWaveRT(NULL);
700     if (!This)
701         return STATUS_INSUFFICIENT_RESOURCES;
702 
703     This->AddRef();
704 
705     // store result
706     *OutPin = (PPORTPINWAVERT)This;
707 
708     return STATUS_SUCCESS;
709 }
710