1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Kernel Streaming 4 * FILE: drivers/wdm/audio/legacy/wdmaud/mmixer.c 5 * PURPOSE: WDM Legacy Mixer 6 * PROGRAMMER: Johannes Anderwald 7 */ 8 9 #include "wdmaud.h" 10 11 12 PVOID Alloc(ULONG NumBytes); 13 MIXER_STATUS Close(HANDLE hDevice); 14 VOID Free(PVOID Block); 15 VOID Copy(PVOID Src, PVOID Dst, ULONG NumBytes); 16 MIXER_STATUS Open(IN LPWSTR DevicePath, OUT PHANDLE hDevice); 17 MIXER_STATUS Control(IN HANDLE hMixer, IN ULONG dwIoControlCode, IN PVOID lpInBuffer, IN ULONG nInBufferSize, OUT PVOID lpOutBuffer, ULONG nOutBufferSize, PULONG lpBytesReturned); 18 MIXER_STATUS Enum(IN PVOID EnumContext, IN ULONG DeviceIndex, OUT LPWSTR * DeviceName, OUT PHANDLE OutHandle, OUT PHANDLE OutKey); 19 MIXER_STATUS OpenKey(IN HANDLE hKey, IN LPWSTR SubKey, IN ULONG DesiredAccess, OUT PHANDLE OutKey); 20 MIXER_STATUS CloseKey(IN HANDLE hKey); 21 MIXER_STATUS QueryKeyValue(IN HANDLE hKey, IN LPWSTR KeyName, OUT PVOID * ResultBuffer, OUT PULONG ResultLength, OUT PULONG KeyType); 22 PVOID AllocEventData(IN ULONG ExtraSize); 23 VOID FreeEventData(IN PVOID EventData); 24 25 MIXER_CONTEXT MixerContext = 26 { 27 sizeof(MIXER_CONTEXT), 28 NULL, 29 Alloc, 30 Control, 31 Free, 32 Open, 33 Close, 34 Copy, 35 OpenKey, 36 QueryKeyValue, 37 CloseKey, 38 AllocEventData, 39 FreeEventData 40 }; 41 42 GUID CategoryGuid = {STATIC_KSCATEGORY_AUDIO}; 43 44 MIXER_STATUS 45 QueryKeyValue( 46 IN HANDLE hKey, 47 IN LPWSTR lpKeyName, 48 OUT PVOID * ResultBuffer, 49 OUT PULONG ResultLength, 50 OUT PULONG KeyType) 51 { 52 NTSTATUS Status; 53 UNICODE_STRING KeyName; 54 ULONG Length; 55 PKEY_VALUE_PARTIAL_INFORMATION PartialInformation; 56 57 /* initialize key name */ 58 RtlInitUnicodeString(&KeyName, lpKeyName); 59 60 /* now query MatchingDeviceId key */ 61 Status = ZwQueryValueKey(hKey, &KeyName, KeyValuePartialInformation, NULL, 0, &Length); 62 63 /* check for success */ 64 if (Status != STATUS_BUFFER_TOO_SMALL) 65 return MM_STATUS_UNSUCCESSFUL; 66 67 /* allocate a buffer for key data */ 68 PartialInformation = ExAllocatePool(NonPagedPool, Length); 69 70 if (!PartialInformation) 71 return MM_STATUS_NO_MEMORY; 72 73 74 /* now query MatchingDeviceId key */ 75 Status = ZwQueryValueKey(hKey, &KeyName, KeyValuePartialInformation, PartialInformation, Length, &Length); 76 77 /* check for success */ 78 if (!NT_SUCCESS(Status)) 79 { 80 ExFreePool(PartialInformation); 81 return MM_STATUS_UNSUCCESSFUL; 82 } 83 84 if (KeyType) 85 { 86 /* return key type */ 87 *KeyType = PartialInformation->Type; 88 } 89 90 if (ResultLength) 91 { 92 /* return data length */ 93 *ResultLength = PartialInformation->DataLength; 94 } 95 96 *ResultBuffer = ExAllocatePool(NonPagedPool, PartialInformation->DataLength); 97 if (!*ResultBuffer) 98 { 99 /* not enough memory */ 100 ExFreePool(PartialInformation); 101 return MM_STATUS_NO_MEMORY; 102 } 103 104 /* copy key value */ 105 RtlMoveMemory(*ResultBuffer, PartialInformation->Data, PartialInformation->DataLength); 106 107 /* free key info */ 108 ExFreePool(PartialInformation); 109 110 return MM_STATUS_SUCCESS; 111 } 112 113 MIXER_STATUS 114 OpenKey( 115 IN HANDLE hKey, 116 IN LPWSTR lpSubKeyName, 117 IN ULONG DesiredAccess, 118 OUT PHANDLE OutKey) 119 { 120 OBJECT_ATTRIBUTES ObjectAttributes; 121 UNICODE_STRING SubKeyName; 122 NTSTATUS Status; 123 124 /* initialize sub key name */ 125 RtlInitUnicodeString(&SubKeyName, lpSubKeyName); 126 127 /* initialize key attributes */ 128 InitializeObjectAttributes(&ObjectAttributes, &SubKeyName, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, hKey, NULL); 129 130 /* open the key */ 131 Status = ZwOpenKey(OutKey, DesiredAccess, &ObjectAttributes); 132 133 if (NT_SUCCESS(Status)) 134 return MM_STATUS_SUCCESS; 135 else 136 return MM_STATUS_UNSUCCESSFUL; 137 } 138 139 MIXER_STATUS 140 CloseKey( 141 IN HANDLE hKey) 142 { 143 if (ZwClose(hKey) == STATUS_SUCCESS) 144 return MM_STATUS_SUCCESS; 145 else 146 return MM_STATUS_UNSUCCESSFUL; 147 } 148 149 150 PVOID Alloc(ULONG NumBytes) 151 { 152 PVOID Mem = ExAllocatePool(NonPagedPool, NumBytes); 153 if (!Mem) 154 return Mem; 155 156 RtlZeroMemory(Mem, NumBytes); 157 return Mem; 158 } 159 160 MIXER_STATUS 161 Close(HANDLE hDevice) 162 { 163 if (ZwClose(hDevice) == STATUS_SUCCESS) 164 return MM_STATUS_SUCCESS; 165 else 166 return MM_STATUS_UNSUCCESSFUL; 167 } 168 169 VOID 170 Free(PVOID Block) 171 { 172 ExFreePool(Block); 173 } 174 175 VOID 176 Copy(PVOID Src, PVOID Dst, ULONG NumBytes) 177 { 178 RtlMoveMemory(Src, Dst, NumBytes); 179 } 180 181 MIXER_STATUS 182 Open( 183 IN LPWSTR DevicePath, 184 OUT PHANDLE hDevice) 185 { 186 if (WdmAudOpenSysAudioDevice(DevicePath, hDevice) == STATUS_SUCCESS) 187 return MM_STATUS_SUCCESS; 188 else 189 return MM_STATUS_UNSUCCESSFUL; 190 } 191 192 MIXER_STATUS 193 Control( 194 IN HANDLE hMixer, 195 IN ULONG dwIoControlCode, 196 IN PVOID lpInBuffer, 197 IN ULONG nInBufferSize, 198 OUT PVOID lpOutBuffer, 199 ULONG nOutBufferSize, 200 PULONG lpBytesReturned) 201 { 202 NTSTATUS Status; 203 PFILE_OBJECT FileObject; 204 205 /* get file object */ 206 Status = ObReferenceObjectByHandle(hMixer, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); 207 if (!NT_SUCCESS(Status)) 208 { 209 DPRINT("failed to reference %p with %lx\n", hMixer, Status); 210 return MM_STATUS_UNSUCCESSFUL; 211 } 212 213 /* perform request */ 214 Status = KsSynchronousIoControlDevice(FileObject, KernelMode, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned); 215 216 /* release object reference */ 217 ObDereferenceObject(FileObject); 218 219 if (Status == STATUS_MORE_ENTRIES || Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) 220 { 221 /* more data is available */ 222 return MM_STATUS_MORE_ENTRIES; 223 } 224 else if (Status == STATUS_SUCCESS) 225 { 226 /* operation succeeded */ 227 return MM_STATUS_SUCCESS; 228 } 229 else 230 { 231 DPRINT("Failed with %lx\n", Status); 232 return MM_STATUS_UNSUCCESSFUL; 233 } 234 } 235 236 MIXER_STATUS 237 Enum( 238 IN PVOID EnumContext, 239 IN ULONG DeviceIndex, 240 OUT LPWSTR * DeviceName, 241 OUT PHANDLE OutHandle, 242 OUT PHANDLE OutKey) 243 { 244 PDEVICE_OBJECT DeviceObject; 245 ULONG DeviceCount; 246 NTSTATUS Status; 247 UNICODE_STRING KeyName; 248 249 /* get enumeration context */ 250 DeviceObject = (PDEVICE_OBJECT)EnumContext; 251 252 /* get device count */ 253 DeviceCount = GetSysAudioDeviceCount(DeviceObject); 254 255 if (DeviceIndex >= DeviceCount) 256 { 257 /* no more devices */ 258 return MM_STATUS_NO_MORE_DEVICES; 259 } 260 261 /* get device name */ 262 Status = GetSysAudioDevicePnpName(DeviceObject, DeviceIndex, DeviceName); 263 264 if (!NT_SUCCESS(Status)) 265 { 266 /* failed to retrieve device name */ 267 return MM_STATUS_UNSUCCESSFUL; 268 } 269 270 /* intialize key name */ 271 RtlInitUnicodeString(&KeyName, *DeviceName); 272 273 /* open device interface key */ 274 Status = IoOpenDeviceInterfaceRegistryKey(&KeyName, GENERIC_READ | GENERIC_WRITE, OutKey); 275 #if 0 276 if (!NT_SUCCESS(Status)) 277 { 278 /* failed to open key */ 279 DPRINT("IoOpenDeviceInterfaceRegistryKey failed with %lx\n", Status); 280 ExFreePool(*DeviceName); 281 return MM_STATUS_UNSUCCESSFUL; 282 } 283 #endif 284 285 /* open device handle */ 286 Status = OpenDevice(*DeviceName, OutHandle, NULL); 287 if (!NT_SUCCESS(Status)) 288 { 289 /* failed to open device */ 290 return MM_STATUS_UNSUCCESSFUL; 291 } 292 293 return MM_STATUS_SUCCESS; 294 } 295 296 PVOID 297 AllocEventData( 298 IN ULONG ExtraSize) 299 { 300 PKSEVENTDATA Data = (PKSEVENTDATA)ExAllocatePool(NonPagedPool, sizeof(KSEVENTDATA) + ExtraSize); 301 if (!Data) 302 return NULL; 303 304 Data->EventObject.Event = ExAllocatePool(NonPagedPool, sizeof(KEVENT)); 305 if (!Data->EventHandle.Event) 306 { 307 ExFreePool(Data); 308 return NULL; 309 } 310 311 KeInitializeEvent(Data->EventObject.Event, NotificationEvent, FALSE); 312 313 Data->NotificationType = KSEVENTF_EVENT_HANDLE; 314 return Data; 315 } 316 317 VOID 318 FreeEventData(IN PVOID EventData) 319 { 320 PKSEVENTDATA Data = (PKSEVENTDATA)EventData; 321 322 ExFreePool(Data->EventHandle.Event); 323 ExFreePool(Data); 324 } 325 326 NTSTATUS 327 WdmAudMixerInitialize( 328 IN PDEVICE_OBJECT DeviceObject) 329 { 330 MIXER_STATUS Status; 331 332 /* initialize the mixer library */ 333 Status = MMixerInitialize(&MixerContext, Enum, (PVOID)DeviceObject); 334 335 if (Status != MM_STATUS_SUCCESS) 336 { 337 /* failed to initialize mmixer library */ 338 DPRINT("MMixerInitialize failed with %lx\n", Status); 339 } 340 341 return Status; 342 } 343 344 NTSTATUS 345 WdmAudMixerCapabilities( 346 IN PDEVICE_OBJECT DeviceObject, 347 IN PWDMAUD_DEVICE_INFO DeviceInfo, 348 IN PWDMAUD_CLIENT ClientInfo, 349 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) 350 { 351 if (MMixerGetCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MixCaps) == MM_STATUS_SUCCESS) 352 return STATUS_SUCCESS; 353 354 return STATUS_INVALID_PARAMETER; 355 } 356 357 NTSTATUS 358 WdmAudControlOpenMixer( 359 IN PDEVICE_OBJECT DeviceObject, 360 IN PIRP Irp, 361 IN PWDMAUD_DEVICE_INFO DeviceInfo, 362 IN PWDMAUD_CLIENT ClientInfo) 363 { 364 HANDLE hMixer; 365 PWDMAUD_HANDLE Handles; 366 PWDMAUD_DEVICE_EXTENSION DeviceExtension; 367 NTSTATUS Status; 368 PKEVENT EventObject = NULL; 369 370 DPRINT("WdmAudControlOpenMixer\n"); 371 372 DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 373 374 if (DeviceInfo->u.hNotifyEvent) 375 { 376 Status = ObReferenceObjectByHandle(DeviceInfo->u.hNotifyEvent, EVENT_MODIFY_STATE, ExEventObjectType, UserMode, (LPVOID*)&EventObject, NULL); 377 378 if (!NT_SUCCESS(Status)) 379 { 380 DPRINT1("Invalid notify event passed %p from client %p\n", DeviceInfo->u.hNotifyEvent, ClientInfo); 381 DbgBreakPoint(); 382 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); 383 } 384 } 385 386 if (MMixerOpen(&MixerContext, DeviceInfo->DeviceIndex, EventObject, NULL /* FIXME */, &hMixer) != MM_STATUS_SUCCESS) 387 { 388 ObDereferenceObject(EventObject); 389 DPRINT1("Failed to open mixer\n"); 390 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); 391 } 392 393 394 Handles = ExAllocatePool(NonPagedPool, sizeof(WDMAUD_HANDLE) * (ClientInfo->NumPins+1)); 395 396 if (Handles) 397 { 398 if (ClientInfo->NumPins) 399 { 400 RtlMoveMemory(Handles, ClientInfo->hPins, sizeof(WDMAUD_HANDLE) * ClientInfo->NumPins); 401 ExFreePool(ClientInfo->hPins); 402 } 403 404 ClientInfo->hPins = Handles; 405 ClientInfo->hPins[ClientInfo->NumPins].Handle = hMixer; 406 ClientInfo->hPins[ClientInfo->NumPins].Type = MIXER_DEVICE_TYPE; 407 ClientInfo->hPins[ClientInfo->NumPins].NotifyEvent = EventObject; 408 ClientInfo->NumPins++; 409 } 410 else 411 { 412 ObDereferenceObject(EventObject); 413 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); 414 } 415 416 DeviceInfo->hDevice = hMixer; 417 418 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 419 } 420 421 NTSTATUS 422 NTAPI 423 WdmAudGetControlDetails( 424 IN PDEVICE_OBJECT DeviceObject, 425 IN PIRP Irp, 426 IN PWDMAUD_DEVICE_INFO DeviceInfo, 427 IN PWDMAUD_CLIENT ClientInfo) 428 { 429 MIXER_STATUS Status; 430 431 /* clear hmixer type flag */ 432 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER; 433 434 /* query mmixer library */ 435 Status = MMixerGetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixDetails); 436 437 if (Status == MM_STATUS_SUCCESS) 438 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 439 else 440 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); 441 } 442 443 NTSTATUS 444 NTAPI 445 WdmAudGetLineInfo( 446 IN PDEVICE_OBJECT DeviceObject, 447 IN PIRP Irp, 448 IN PWDMAUD_DEVICE_INFO DeviceInfo, 449 IN PWDMAUD_CLIENT ClientInfo) 450 { 451 MIXER_STATUS Status; 452 453 /* clear hmixer type flag */ 454 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER; 455 456 /* query mixer library */ 457 Status = MMixerGetLineInfo(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixLine); 458 459 if (Status == MM_STATUS_SUCCESS) 460 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 461 else 462 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); 463 } 464 465 NTSTATUS 466 NTAPI 467 WdmAudGetLineControls( 468 IN PDEVICE_OBJECT DeviceObject, 469 IN PIRP Irp, 470 IN PWDMAUD_DEVICE_INFO DeviceInfo, 471 IN PWDMAUD_CLIENT ClientInfo) 472 { 473 MIXER_STATUS Status; 474 475 /* clear hmixer type flag */ 476 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER; 477 478 /* query mixer library */ 479 Status = MMixerGetLineControls(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixControls); 480 481 if (Status == MM_STATUS_SUCCESS) 482 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 483 else 484 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); 485 486 487 } 488 489 NTSTATUS 490 NTAPI 491 WdmAudSetControlDetails( 492 IN PDEVICE_OBJECT DeviceObject, 493 IN PIRP Irp, 494 IN PWDMAUD_DEVICE_INFO DeviceInfo, 495 IN PWDMAUD_CLIENT ClientInfo) 496 { 497 MIXER_STATUS Status; 498 499 /* clear hmixer type flag */ 500 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER; 501 502 /* query mixer library */ 503 Status = MMixerSetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixDetails); 504 505 if (Status == MM_STATUS_SUCCESS) 506 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 507 else 508 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); 509 } 510 511 NTSTATUS 512 NTAPI 513 WdmAudGetMixerEvent( 514 IN PDEVICE_OBJECT DeviceObject, 515 IN PIRP Irp, 516 IN PWDMAUD_DEVICE_INFO DeviceInfo, 517 IN PWDMAUD_CLIENT ClientInfo) 518 { 519 UNIMPLEMENTED 520 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); 521 } 522 523 ULONG 524 WdmAudGetMixerDeviceCount() 525 { 526 return MMixerGetCount(&MixerContext); 527 } 528 529 ULONG 530 WdmAudGetWaveInDeviceCount() 531 { 532 return MMixerGetWaveInCount(&MixerContext); 533 } 534 535 ULONG 536 WdmAudGetWaveOutDeviceCount() 537 { 538 return MMixerGetWaveOutCount(&MixerContext); 539 } 540 541 NTSTATUS 542 WdmAudGetMixerPnpNameByIndex( 543 IN ULONG DeviceIndex, 544 OUT LPWSTR * Device) 545 { 546 UNIMPLEMENTED 547 return STATUS_NOT_IMPLEMENTED; 548 } 549 550 NTSTATUS 551 WdmAudGetPnpNameByIndexAndType( 552 IN ULONG DeviceIndex, 553 IN SOUND_DEVICE_TYPE DeviceType, 554 OUT LPWSTR *DevicePath) 555 { 556 if (MMixerGetWaveDevicePath(&MixerContext, DeviceType == WAVE_IN_DEVICE_TYPE, DeviceIndex, DevicePath) == MM_STATUS_SUCCESS) 557 return STATUS_SUCCESS; 558 else 559 return STATUS_UNSUCCESSFUL; 560 } 561 562 NTSTATUS 563 WdmAudWaveCapabilities( 564 IN PDEVICE_OBJECT DeviceObject, 565 IN PWDMAUD_DEVICE_INFO DeviceInfo, 566 IN PWDMAUD_CLIENT ClientInfo, 567 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) 568 { 569 MIXER_STATUS Status; 570 571 if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) 572 { 573 /* get capabilities */ 574 Status = MMixerWaveInCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveInCaps); 575 } 576 else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) 577 { 578 /* get capabilities */ 579 Status = MMixerWaveOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveOutCaps); 580 } 581 else 582 { 583 ASSERT(0); 584 return STATUS_UNSUCCESSFUL; 585 } 586 587 if (Status == MM_STATUS_SUCCESS) 588 return STATUS_SUCCESS; 589 else 590 return STATUS_UNSUCCESSFUL; 591 } 592 593 594 MIXER_STATUS 595 CreatePinCallback( 596 IN PVOID Ctx, 597 IN ULONG VirtualDeviceId, 598 IN ULONG PinId, 599 IN HANDLE hFilter, 600 IN PKSPIN_CONNECT PinConnect, 601 IN ACCESS_MASK DesiredAccess, 602 OUT PHANDLE PinHandle) 603 { 604 ULONG BytesReturned; 605 SYSAUDIO_INSTANCE_INFO InstanceInfo; 606 NTSTATUS Status; 607 ULONG FreeIndex; 608 PPIN_CREATE_CONTEXT Context = (PPIN_CREATE_CONTEXT)Ctx; 609 610 /* setup property request */ 611 InstanceInfo.Property.Set = KSPROPSETID_Sysaudio; 612 InstanceInfo.Property.Id = KSPROPERTY_SYSAUDIO_INSTANCE_INFO; 613 InstanceInfo.Property.Flags = KSPROPERTY_TYPE_SET; 614 InstanceInfo.Flags = 0; 615 InstanceInfo.DeviceNumber = VirtualDeviceId; 616 617 /* attach to virtual device */ 618 Status = KsSynchronousIoControlDevice(Context->DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&InstanceInfo, sizeof(SYSAUDIO_INSTANCE_INFO), NULL, 0, &BytesReturned); 619 620 if (!NT_SUCCESS(Status)) 621 return MM_STATUS_UNSUCCESSFUL; 622 623 /* close existing pin */ 624 FreeIndex = ClosePin(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType); 625 626 /* now create the pin */ 627 Status = KsCreatePin(Context->DeviceExtension->hSysAudio, PinConnect, DesiredAccess, PinHandle); 628 629 /* check for success */ 630 if (!NT_SUCCESS(Status)) 631 return MM_STATUS_UNSUCCESSFUL; 632 633 /* store the handle */ 634 Status = InsertPinHandle(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType, *PinHandle, FreeIndex); 635 if (!NT_SUCCESS(Status)) 636 { 637 /* failed to insert handle */ 638 ZwClose(*PinHandle); 639 return MM_STATUS_UNSUCCESSFUL; 640 } 641 642 return MM_STATUS_SUCCESS; 643 } 644 645 NTSTATUS 646 WdmAudControlOpenWave( 647 IN PDEVICE_OBJECT DeviceObject, 648 IN PIRP Irp, 649 IN PWDMAUD_DEVICE_INFO DeviceInfo, 650 IN PWDMAUD_CLIENT ClientInfo) 651 { 652 MIXER_STATUS Status; 653 PIN_CREATE_CONTEXT Context; 654 655 Context.ClientInfo = ClientInfo; 656 Context.DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 657 Context.DeviceType = DeviceInfo->DeviceType; 658 659 Status = MMixerOpenWave(&MixerContext, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE, &DeviceInfo->u.WaveFormatEx, CreatePinCallback, &Context, &DeviceInfo->hDevice); 660 661 if (Status == MM_STATUS_SUCCESS) 662 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 663 else 664 return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO)); 665 } 666