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 = AllocateItem(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 FreeItem(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 = AllocateItem(NonPagedPool, PartialInformation->DataLength); 97 if (!*ResultBuffer) 98 { 99 /* not enough memory */ 100 FreeItem(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 FreeItem(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 return AllocateItem(NonPagedPool, NumBytes); 153 } 154 155 MIXER_STATUS 156 Close(HANDLE hDevice) 157 { 158 if (ZwClose(hDevice) == STATUS_SUCCESS) 159 return MM_STATUS_SUCCESS; 160 else 161 return MM_STATUS_UNSUCCESSFUL; 162 } 163 164 VOID 165 Free(PVOID Block) 166 { 167 FreeItem(Block); 168 } 169 170 VOID 171 Copy(PVOID Src, PVOID Dst, ULONG NumBytes) 172 { 173 RtlMoveMemory(Src, Dst, NumBytes); 174 } 175 176 MIXER_STATUS 177 Open( 178 IN LPWSTR DevicePath, 179 OUT PHANDLE hDevice) 180 { 181 if (WdmAudOpenSysAudioDevice(DevicePath, hDevice) == STATUS_SUCCESS) 182 return MM_STATUS_SUCCESS; 183 else 184 return MM_STATUS_UNSUCCESSFUL; 185 } 186 187 MIXER_STATUS 188 Control( 189 IN HANDLE hMixer, 190 IN ULONG dwIoControlCode, 191 IN PVOID lpInBuffer, 192 IN ULONG nInBufferSize, 193 OUT PVOID lpOutBuffer, 194 ULONG nOutBufferSize, 195 PULONG lpBytesReturned) 196 { 197 NTSTATUS Status; 198 PFILE_OBJECT FileObject; 199 200 /* get file object */ 201 Status = ObReferenceObjectByHandle(hMixer, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); 202 if (!NT_SUCCESS(Status)) 203 { 204 DPRINT("failed to reference %p with %lx\n", hMixer, Status); 205 return MM_STATUS_UNSUCCESSFUL; 206 } 207 208 /* perform request */ 209 Status = KsSynchronousIoControlDevice(FileObject, KernelMode, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned); 210 211 /* release object reference */ 212 ObDereferenceObject(FileObject); 213 214 if (Status == STATUS_MORE_ENTRIES || Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) 215 { 216 /* more data is available */ 217 return MM_STATUS_MORE_ENTRIES; 218 } 219 else if (Status == STATUS_SUCCESS) 220 { 221 /* operation succeeded */ 222 return MM_STATUS_SUCCESS; 223 } 224 else 225 { 226 DPRINT("Failed with %lx\n", Status); 227 return MM_STATUS_UNSUCCESSFUL; 228 } 229 } 230 231 MIXER_STATUS 232 Enum( 233 IN PVOID EnumContext, 234 IN ULONG DeviceIndex, 235 OUT LPWSTR * DeviceName, 236 OUT PHANDLE OutHandle, 237 OUT PHANDLE OutKey) 238 { 239 PDEVICE_OBJECT DeviceObject; 240 ULONG DeviceCount; 241 NTSTATUS Status; 242 UNICODE_STRING KeyName; 243 244 /* get enumeration context */ 245 DeviceObject = (PDEVICE_OBJECT)EnumContext; 246 247 /* get device count */ 248 DeviceCount = GetSysAudioDeviceCount(DeviceObject); 249 250 if (DeviceIndex >= DeviceCount) 251 { 252 /* no more devices */ 253 return MM_STATUS_NO_MORE_DEVICES; 254 } 255 256 /* get device name */ 257 Status = GetSysAudioDevicePnpName(DeviceObject, DeviceIndex, DeviceName); 258 259 if (!NT_SUCCESS(Status)) 260 { 261 /* failed to retrieve device name */ 262 return MM_STATUS_UNSUCCESSFUL; 263 } 264 265 /* intialize key name */ 266 RtlInitUnicodeString(&KeyName, *DeviceName); 267 268 /* open device interface key */ 269 Status = IoOpenDeviceInterfaceRegistryKey(&KeyName, GENERIC_READ | GENERIC_WRITE, OutKey); 270 #if 0 271 if (!NT_SUCCESS(Status)) 272 { 273 /* failed to open key */ 274 DPRINT("IoOpenDeviceInterfaceRegistryKey failed with %lx\n", Status); 275 FreeItem(*DeviceName); 276 return MM_STATUS_UNSUCCESSFUL; 277 } 278 #endif 279 280 /* open device handle */ 281 Status = OpenDevice(*DeviceName, OutHandle, NULL); 282 if (!NT_SUCCESS(Status)) 283 { 284 /* failed to open device */ 285 return MM_STATUS_UNSUCCESSFUL; 286 } 287 288 return MM_STATUS_SUCCESS; 289 } 290 291 PVOID 292 AllocEventData( 293 IN ULONG ExtraSize) 294 { 295 PKSEVENTDATA Data = (PKSEVENTDATA)AllocateItem(NonPagedPool, sizeof(KSEVENTDATA) + ExtraSize); 296 if (!Data) 297 return NULL; 298 299 Data->EventObject.Event = AllocateItem(NonPagedPool, sizeof(KEVENT)); 300 if (!Data->EventHandle.Event) 301 { 302 FreeItem(Data); 303 return NULL; 304 } 305 306 KeInitializeEvent(Data->EventObject.Event, NotificationEvent, FALSE); 307 308 Data->NotificationType = KSEVENTF_EVENT_HANDLE; 309 return Data; 310 } 311 312 VOID 313 FreeEventData(IN PVOID EventData) 314 { 315 PKSEVENTDATA Data = (PKSEVENTDATA)EventData; 316 317 FreeItem(Data->EventHandle.Event); 318 FreeItem(Data); 319 } 320 321 VOID 322 CALLBACK 323 EventCallback( 324 IN PVOID MixerEventContext, 325 IN HANDLE hMixer, 326 IN ULONG NotificationType, 327 IN ULONG Value) 328 { 329 PWDMAUD_CLIENT ClientInfo; 330 PEVENT_ENTRY Entry; 331 ULONG Index; 332 333 /* get client context */ 334 ClientInfo = (PWDMAUD_CLIENT)MixerEventContext; 335 336 /* now search for the mixer which originated the request */ 337 for(Index = 0; Index < ClientInfo->NumPins; Index++) 338 { 339 if (ClientInfo->hPins[Index].Handle == hMixer && ClientInfo->hPins[Index].Type == MIXER_DEVICE_TYPE) 340 { 341 if (ClientInfo->hPins[Index].NotifyEvent) 342 { 343 /* allocate event entry */ 344 Entry = AllocateItem(NonPagedPool, sizeof(EVENT_ENTRY)); 345 if (!Entry) 346 { 347 /* no memory */ 348 break; 349 } 350 351 /* setup event entry */ 352 Entry->NotificationType = NotificationType; 353 Entry->Value = Value; 354 Entry->hMixer = hMixer; 355 356 /* insert entry */ 357 InsertTailList(&ClientInfo->MixerEventList, &Entry->Entry); 358 359 /* now notify the client */ 360 KeSetEvent(ClientInfo->hPins[Index].NotifyEvent, 0, FALSE); 361 } 362 /* done */ 363 break; 364 } 365 } 366 } 367 368 369 NTSTATUS 370 WdmAudMixerInitialize( 371 IN PDEVICE_OBJECT DeviceObject) 372 { 373 MIXER_STATUS Status; 374 375 /* initialize the mixer library */ 376 Status = MMixerInitialize(&MixerContext, Enum, (PVOID)DeviceObject); 377 378 if (Status != MM_STATUS_SUCCESS) 379 { 380 /* failed to initialize mmixer library */ 381 DPRINT("MMixerInitialize failed with %lx\n", Status); 382 } 383 384 return Status; 385 } 386 387 NTSTATUS 388 WdmAudMixerCapabilities( 389 IN PDEVICE_OBJECT DeviceObject, 390 IN PWDMAUD_DEVICE_INFO DeviceInfo, 391 IN PWDMAUD_CLIENT ClientInfo, 392 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) 393 { 394 if (MMixerGetCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MixCaps) == MM_STATUS_SUCCESS) 395 return STATUS_SUCCESS; 396 397 return STATUS_INVALID_PARAMETER; 398 } 399 400 NTSTATUS 401 WdmAudControlOpenMixer( 402 IN PDEVICE_OBJECT DeviceObject, 403 IN PIRP Irp, 404 IN PWDMAUD_DEVICE_INFO DeviceInfo, 405 IN PWDMAUD_CLIENT ClientInfo) 406 { 407 HANDLE hMixer; 408 PWDMAUD_HANDLE Handles; 409 //PWDMAUD_DEVICE_EXTENSION DeviceExtension; 410 NTSTATUS Status; 411 PKEVENT EventObject = NULL; 412 413 DPRINT("WdmAudControlOpenMixer\n"); 414 415 //DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 416 417 if (DeviceInfo->u.hNotifyEvent) 418 { 419 Status = ObReferenceObjectByHandle(DeviceInfo->u.hNotifyEvent, EVENT_MODIFY_STATE, ExEventObjectType, UserMode, (LPVOID*)&EventObject, NULL); 420 421 if (!NT_SUCCESS(Status)) 422 { 423 DPRINT1("Invalid notify event passed %p from client %p\n", DeviceInfo->u.hNotifyEvent, ClientInfo); 424 DbgBreakPoint(); 425 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); 426 } 427 } 428 429 if (MMixerOpen(&MixerContext, DeviceInfo->DeviceIndex, ClientInfo, EventCallback, &hMixer) != MM_STATUS_SUCCESS) 430 { 431 ObDereferenceObject(EventObject); 432 DPRINT1("Failed to open mixer\n"); 433 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); 434 } 435 436 437 Handles = AllocateItem(NonPagedPool, sizeof(WDMAUD_HANDLE) * (ClientInfo->NumPins+1)); 438 439 if (Handles) 440 { 441 if (ClientInfo->NumPins) 442 { 443 RtlMoveMemory(Handles, ClientInfo->hPins, sizeof(WDMAUD_HANDLE) * ClientInfo->NumPins); 444 FreeItem(ClientInfo->hPins); 445 } 446 447 ClientInfo->hPins = Handles; 448 ClientInfo->hPins[ClientInfo->NumPins].Handle = hMixer; 449 ClientInfo->hPins[ClientInfo->NumPins].Type = MIXER_DEVICE_TYPE; 450 ClientInfo->hPins[ClientInfo->NumPins].NotifyEvent = EventObject; 451 ClientInfo->NumPins++; 452 } 453 else 454 { 455 ObDereferenceObject(EventObject); 456 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); 457 } 458 459 DeviceInfo->hDevice = hMixer; 460 461 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 462 } 463 464 NTSTATUS 465 NTAPI 466 WdmAudGetControlDetails( 467 IN PDEVICE_OBJECT DeviceObject, 468 IN PIRP Irp, 469 IN PWDMAUD_DEVICE_INFO DeviceInfo, 470 IN PWDMAUD_CLIENT ClientInfo) 471 { 472 MIXER_STATUS Status; 473 474 /* clear hmixer type flag */ 475 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER; 476 477 /* query mmixer library */ 478 Status = MMixerGetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixDetails); 479 480 if (Status == MM_STATUS_SUCCESS) 481 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 482 else 483 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); 484 } 485 486 NTSTATUS 487 NTAPI 488 WdmAudGetLineInfo( 489 IN PDEVICE_OBJECT DeviceObject, 490 IN PIRP Irp, 491 IN PWDMAUD_DEVICE_INFO DeviceInfo, 492 IN PWDMAUD_CLIENT ClientInfo) 493 { 494 MIXER_STATUS Status; 495 496 /* clear hmixer type flag */ 497 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER; 498 499 /* query mixer library */ 500 Status = MMixerGetLineInfo(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixLine); 501 502 if (Status == MM_STATUS_SUCCESS) 503 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 504 else 505 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); 506 } 507 508 NTSTATUS 509 NTAPI 510 WdmAudGetLineControls( 511 IN PDEVICE_OBJECT DeviceObject, 512 IN PIRP Irp, 513 IN PWDMAUD_DEVICE_INFO DeviceInfo, 514 IN PWDMAUD_CLIENT ClientInfo) 515 { 516 MIXER_STATUS Status; 517 518 /* clear hmixer type flag */ 519 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER; 520 521 /* query mixer library */ 522 Status = MMixerGetLineControls(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixControls); 523 524 if (Status == MM_STATUS_SUCCESS) 525 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 526 else 527 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); 528 529 530 } 531 532 NTSTATUS 533 NTAPI 534 WdmAudSetControlDetails( 535 IN PDEVICE_OBJECT DeviceObject, 536 IN PIRP Irp, 537 IN PWDMAUD_DEVICE_INFO DeviceInfo, 538 IN PWDMAUD_CLIENT ClientInfo) 539 { 540 MIXER_STATUS Status; 541 542 /* clear hmixer type flag */ 543 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER; 544 545 /* query mixer library */ 546 Status = MMixerSetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixDetails); 547 548 if (Status == MM_STATUS_SUCCESS) 549 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 550 else 551 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); 552 } 553 554 NTSTATUS 555 NTAPI 556 WdmAudGetMixerEvent( 557 IN PDEVICE_OBJECT DeviceObject, 558 IN PIRP Irp, 559 IN PWDMAUD_DEVICE_INFO DeviceInfo, 560 IN PWDMAUD_CLIENT ClientInfo) 561 { 562 PLIST_ENTRY Entry; 563 PEVENT_ENTRY EventEntry; 564 565 /* enumerate event list and check if there is a new event */ 566 Entry = ClientInfo->MixerEventList.Flink; 567 568 while(Entry != &ClientInfo->MixerEventList) 569 { 570 /* grab event entry */ 571 EventEntry = (PEVENT_ENTRY)CONTAINING_RECORD(Entry, EVENT_ENTRY, Entry); 572 573 if (EventEntry->hMixer == DeviceInfo->hDevice) 574 { 575 /* found an entry */ 576 DeviceInfo->u.MixerEvent.hMixer = EventEntry->hMixer; 577 DeviceInfo->u.MixerEvent.NotificationType = EventEntry->NotificationType; 578 DeviceInfo->u.MixerEvent.Value = EventEntry->Value; 579 580 /* remove entry from list */ 581 RemoveEntryList(&EventEntry->Entry); 582 583 /* free event entry */ 584 FreeItem(EventEntry); 585 586 /* done */ 587 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 588 } 589 590 /* move to next */ 591 Entry = Entry->Flink; 592 } 593 594 /* no event entry available */ 595 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); 596 } 597 598 ULONG 599 WdmAudGetMixerDeviceCount() 600 { 601 return MMixerGetCount(&MixerContext); 602 } 603 604 ULONG 605 WdmAudGetWaveInDeviceCount() 606 { 607 return MMixerGetWaveInCount(&MixerContext); 608 } 609 610 ULONG 611 WdmAudGetWaveOutDeviceCount() 612 { 613 return MMixerGetWaveOutCount(&MixerContext); 614 } 615 616 ULONG 617 WdmAudGetMidiInDeviceCount() 618 { 619 return MMixerGetMidiInCount(&MixerContext); 620 } 621 622 ULONG 623 WdmAudGetMidiOutDeviceCount() 624 { 625 return MMixerGetWaveOutCount(&MixerContext); 626 } 627 628 NTSTATUS 629 WdmAudGetPnpNameByIndexAndType( 630 IN ULONG DeviceIndex, 631 IN SOUND_DEVICE_TYPE DeviceType, 632 OUT LPWSTR *DevicePath) 633 { 634 if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE) 635 { 636 if (MMixerGetWaveDevicePath(&MixerContext, DeviceType == WAVE_IN_DEVICE_TYPE, DeviceIndex, DevicePath) == MM_STATUS_SUCCESS) 637 return STATUS_SUCCESS; 638 else 639 return STATUS_UNSUCCESSFUL; 640 } 641 else if (DeviceType == MIDI_IN_DEVICE_TYPE || DeviceType == MIDI_OUT_DEVICE_TYPE) 642 { 643 if (MMixerGetMidiDevicePath(&MixerContext, DeviceType == MIDI_IN_DEVICE_TYPE, DeviceIndex, DevicePath) == MM_STATUS_SUCCESS) 644 return STATUS_SUCCESS; 645 else 646 return STATUS_UNSUCCESSFUL; 647 } 648 else if (DeviceType == MIXER_DEVICE_TYPE) 649 { 650 UNIMPLEMENTED; 651 } 652 653 return STATUS_UNSUCCESSFUL; 654 } 655 656 NTSTATUS 657 WdmAudWaveCapabilities( 658 IN PDEVICE_OBJECT DeviceObject, 659 IN PWDMAUD_DEVICE_INFO DeviceInfo, 660 IN PWDMAUD_CLIENT ClientInfo, 661 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) 662 { 663 MIXER_STATUS Status = MM_STATUS_UNSUCCESSFUL; 664 665 if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) 666 { 667 /* get capabilities */ 668 Status = MMixerWaveInCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveInCaps); 669 } 670 else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) 671 { 672 /* get capabilities */ 673 Status = MMixerWaveOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveOutCaps); 674 } 675 676 if (Status == MM_STATUS_SUCCESS) 677 return STATUS_SUCCESS; 678 else 679 return Status; 680 } 681 682 NTSTATUS 683 WdmAudMidiCapabilities( 684 IN PDEVICE_OBJECT DeviceObject, 685 IN PWDMAUD_DEVICE_INFO DeviceInfo, 686 IN PWDMAUD_CLIENT ClientInfo, 687 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) 688 { 689 MIXER_STATUS Status = MM_STATUS_UNSUCCESSFUL; 690 691 if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE) 692 { 693 /* get capabilities */ 694 Status = MMixerMidiInCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MidiInCaps); 695 } 696 else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) 697 { 698 /* get capabilities */ 699 Status = MMixerMidiOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MidiOutCaps); 700 } 701 702 if (Status == MM_STATUS_SUCCESS) 703 return STATUS_SUCCESS; 704 else 705 return STATUS_UNSUCCESSFUL; 706 } 707 708 709 MIXER_STATUS 710 CreatePinCallback( 711 IN PVOID Ctx, 712 IN ULONG VirtualDeviceId, 713 IN ULONG PinId, 714 IN HANDLE hFilter, 715 IN PKSPIN_CONNECT PinConnect, 716 IN ACCESS_MASK DesiredAccess, 717 OUT PHANDLE PinHandle) 718 { 719 ULONG BytesReturned; 720 SYSAUDIO_INSTANCE_INFO InstanceInfo; 721 NTSTATUS Status; 722 ULONG FreeIndex; 723 PPIN_CREATE_CONTEXT Context = (PPIN_CREATE_CONTEXT)Ctx; 724 725 /* setup property request */ 726 InstanceInfo.Property.Set = KSPROPSETID_Sysaudio; 727 InstanceInfo.Property.Id = KSPROPERTY_SYSAUDIO_INSTANCE_INFO; 728 InstanceInfo.Property.Flags = KSPROPERTY_TYPE_SET; 729 InstanceInfo.Flags = 0; 730 InstanceInfo.DeviceNumber = VirtualDeviceId; 731 732 /* attach to virtual device */ 733 Status = KsSynchronousIoControlDevice(Context->DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&InstanceInfo, sizeof(SYSAUDIO_INSTANCE_INFO), NULL, 0, &BytesReturned); 734 735 if (!NT_SUCCESS(Status)) 736 return MM_STATUS_UNSUCCESSFUL; 737 738 /* close existing pin */ 739 FreeIndex = ClosePin(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType); 740 741 /* now create the pin */ 742 Status = KsCreatePin(Context->DeviceExtension->hSysAudio, PinConnect, DesiredAccess, PinHandle); 743 744 /* check for success */ 745 if (!NT_SUCCESS(Status)) 746 return MM_STATUS_UNSUCCESSFUL; 747 748 /* store the handle */ 749 Status = InsertPinHandle(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType, *PinHandle, FreeIndex); 750 if (!NT_SUCCESS(Status)) 751 { 752 /* failed to insert handle */ 753 ZwClose(*PinHandle); 754 return MM_STATUS_UNSUCCESSFUL; 755 } 756 757 return MM_STATUS_SUCCESS; 758 } 759 760 NTSTATUS 761 WdmAudControlOpenWave( 762 IN PDEVICE_OBJECT DeviceObject, 763 IN PIRP Irp, 764 IN PWDMAUD_DEVICE_INFO DeviceInfo, 765 IN PWDMAUD_CLIENT ClientInfo) 766 { 767 MIXER_STATUS Status; 768 PIN_CREATE_CONTEXT Context; 769 770 Context.ClientInfo = ClientInfo; 771 Context.DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 772 Context.DeviceType = DeviceInfo->DeviceType; 773 774 Status = MMixerOpenWave(&MixerContext, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE, &DeviceInfo->u.WaveFormatEx, CreatePinCallback, &Context, &DeviceInfo->hDevice); 775 776 if (Status == MM_STATUS_SUCCESS) 777 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 778 else 779 return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO)); 780 } 781 782 NTSTATUS 783 WdmAudControlOpenMidi( 784 IN PDEVICE_OBJECT DeviceObject, 785 IN PIRP Irp, 786 IN PWDMAUD_DEVICE_INFO DeviceInfo, 787 IN PWDMAUD_CLIENT ClientInfo) 788 { 789 MIXER_STATUS Status; 790 PIN_CREATE_CONTEXT Context; 791 792 Context.ClientInfo = ClientInfo; 793 Context.DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 794 Context.DeviceType = DeviceInfo->DeviceType; 795 796 Status = MMixerOpenMidi(&MixerContext, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE, CreatePinCallback, &Context, &DeviceInfo->hDevice); 797 798 if (Status == MM_STATUS_SUCCESS) 799 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 800 else 801 return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO)); 802 } 803 804