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