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