The 'UNIMPLEMENTED' macro call should be followed explicitely by a semicolon.
[reactos.git] / reactos / drivers / wdm / audio / backpln / portcls / pin_wavert.cpp
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 }