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