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 #include <mmixer.h> 12 13 #define NDEBUG 14 #include <debug.h> 15 16 PVOID Alloc(ULONG NumBytes); 17 MIXER_STATUS Close(HANDLE hDevice); 18 VOID Free(PVOID Block); 19 VOID Copy(PVOID Src, PVOID Dst, ULONG NumBytes); 20 MIXER_STATUS Open(IN LPWSTR DevicePath, OUT PHANDLE hDevice); 21 MIXER_STATUS Control(IN HANDLE hMixer, IN ULONG dwIoControlCode, IN PVOID lpInBuffer, IN ULONG nInBufferSize, OUT PVOID lpOutBuffer, ULONG nOutBufferSize, PULONG lpBytesReturned); 22 MIXER_STATUS Enum(IN PVOID EnumContext, IN ULONG DeviceIndex, OUT LPWSTR * DeviceName, OUT PHANDLE OutHandle, OUT PHANDLE OutKey); 23 MIXER_STATUS OpenKey(IN HANDLE hKey, IN LPWSTR SubKey, IN ULONG DesiredAccess, OUT PHANDLE OutKey); 24 MIXER_STATUS CloseKey(IN HANDLE hKey); 25 MIXER_STATUS QueryKeyValue(IN HANDLE hKey, IN LPWSTR KeyName, OUT PVOID * ResultBuffer, OUT PULONG ResultLength, OUT PULONG KeyType); 26 PVOID AllocEventData(IN ULONG ExtraSize); 27 VOID FreeEventData(IN PVOID EventData); 28 29 MIXER_CONTEXT MixerContext = 30 { 31 sizeof(MIXER_CONTEXT), 32 NULL, 33 Alloc, 34 Control, 35 Free, 36 Open, 37 Close, 38 Copy, 39 OpenKey, 40 QueryKeyValue, 41 CloseKey, 42 AllocEventData, 43 FreeEventData 44 }; 45 46 GUID CategoryGuid = {STATIC_KSCATEGORY_AUDIO}; 47 48 MIXER_STATUS 49 QueryKeyValue( 50 IN HANDLE hKey, 51 IN LPWSTR lpKeyName, 52 OUT PVOID * ResultBuffer, 53 OUT PULONG ResultLength, 54 OUT PULONG KeyType) 55 { 56 NTSTATUS Status; 57 UNICODE_STRING KeyName; 58 ULONG Length; 59 PKEY_VALUE_PARTIAL_INFORMATION PartialInformation; 60 61 /* initialize key name */ 62 RtlInitUnicodeString(&KeyName, lpKeyName); 63 64 /* now query MatchingDeviceId key */ 65 Status = ZwQueryValueKey(hKey, &KeyName, KeyValuePartialInformation, NULL, 0, &Length); 66 67 /* check for success */ 68 if (Status != STATUS_BUFFER_TOO_SMALL) 69 return MM_STATUS_UNSUCCESSFUL; 70 71 /* allocate a buffer for key data */ 72 PartialInformation = AllocateItem(NonPagedPool, Length); 73 74 if (!PartialInformation) 75 return MM_STATUS_NO_MEMORY; 76 77 78 /* now query MatchingDeviceId key */ 79 Status = ZwQueryValueKey(hKey, &KeyName, KeyValuePartialInformation, PartialInformation, Length, &Length); 80 81 /* check for success */ 82 if (!NT_SUCCESS(Status)) 83 { 84 FreeItem(PartialInformation); 85 return MM_STATUS_UNSUCCESSFUL; 86 } 87 88 if (KeyType) 89 { 90 /* return key type */ 91 *KeyType = PartialInformation->Type; 92 } 93 94 if (ResultLength) 95 { 96 /* return data length */ 97 *ResultLength = PartialInformation->DataLength; 98 } 99 100 *ResultBuffer = AllocateItem(NonPagedPool, PartialInformation->DataLength); 101 if (!*ResultBuffer) 102 { 103 /* not enough memory */ 104 FreeItem(PartialInformation); 105 return MM_STATUS_NO_MEMORY; 106 } 107 108 /* copy key value */ 109 RtlMoveMemory(*ResultBuffer, PartialInformation->Data, PartialInformation->DataLength); 110 111 /* free key info */ 112 FreeItem(PartialInformation); 113 114 return MM_STATUS_SUCCESS; 115 } 116 117 MIXER_STATUS 118 OpenKey( 119 IN HANDLE hKey, 120 IN LPWSTR lpSubKeyName, 121 IN ULONG DesiredAccess, 122 OUT PHANDLE OutKey) 123 { 124 OBJECT_ATTRIBUTES ObjectAttributes; 125 UNICODE_STRING SubKeyName; 126 NTSTATUS Status; 127 128 /* initialize sub key name */ 129 RtlInitUnicodeString(&SubKeyName, lpSubKeyName); 130 131 /* initialize key attributes */ 132 InitializeObjectAttributes(&ObjectAttributes, &SubKeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE | OBJ_OPENIF, hKey, NULL); 133 134 /* open the key */ 135 Status = ZwOpenKey(OutKey, DesiredAccess, &ObjectAttributes); 136 137 if (NT_SUCCESS(Status)) 138 return MM_STATUS_SUCCESS; 139 else 140 return MM_STATUS_UNSUCCESSFUL; 141 } 142 143 MIXER_STATUS 144 CloseKey( 145 IN HANDLE hKey) 146 { 147 if (ZwClose(hKey) == STATUS_SUCCESS) 148 return MM_STATUS_SUCCESS; 149 else 150 return MM_STATUS_UNSUCCESSFUL; 151 } 152 153 154 PVOID Alloc(ULONG NumBytes) 155 { 156 return AllocateItem(NonPagedPool, NumBytes); 157 } 158 159 MIXER_STATUS 160 Close(HANDLE hDevice) 161 { 162 if (ZwClose(hDevice) == STATUS_SUCCESS) 163 return MM_STATUS_SUCCESS; 164 else 165 return MM_STATUS_UNSUCCESSFUL; 166 } 167 168 VOID 169 Free(PVOID Block) 170 { 171 FreeItem(Block); 172 } 173 174 VOID 175 Copy(PVOID Src, PVOID Dst, ULONG NumBytes) 176 { 177 RtlMoveMemory(Src, Dst, NumBytes); 178 } 179 180 MIXER_STATUS 181 Open( 182 IN LPWSTR DevicePath, 183 OUT PHANDLE hDevice) 184 { 185 if (WdmAudOpenSysAudioDevice(DevicePath, hDevice) == STATUS_SUCCESS) 186 return MM_STATUS_SUCCESS; 187 else 188 return MM_STATUS_UNSUCCESSFUL; 189 } 190 191 MIXER_STATUS 192 Control( 193 IN HANDLE hMixer, 194 IN ULONG dwIoControlCode, 195 IN PVOID lpInBuffer, 196 IN ULONG nInBufferSize, 197 OUT PVOID lpOutBuffer, 198 ULONG nOutBufferSize, 199 PULONG lpBytesReturned) 200 { 201 NTSTATUS Status; 202 PFILE_OBJECT FileObject; 203 204 /* get file object */ 205 Status = ObReferenceObjectByHandle(hMixer, GENERIC_READ | GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); 206 if (!NT_SUCCESS(Status)) 207 { 208 DPRINT("failed to reference %p with %lx\n", hMixer, Status); 209 return MM_STATUS_UNSUCCESSFUL; 210 } 211 212 /* perform request */ 213 Status = KsSynchronousIoControlDevice(FileObject, KernelMode, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned); 214 215 /* release object reference */ 216 ObDereferenceObject(FileObject); 217 218 if (Status == STATUS_MORE_ENTRIES || Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) 219 { 220 /* more data is available */ 221 return MM_STATUS_MORE_ENTRIES; 222 } 223 else if (Status == STATUS_SUCCESS) 224 { 225 /* operation succeeded */ 226 return MM_STATUS_SUCCESS; 227 } 228 else 229 { 230 DPRINT("Failed with %lx\n", Status); 231 return MM_STATUS_UNSUCCESSFUL; 232 } 233 } 234 235 MIXER_STATUS 236 Enum( 237 IN PVOID EnumContext, 238 IN ULONG DeviceIndex, 239 OUT LPWSTR * DeviceName, 240 OUT PHANDLE OutHandle, 241 OUT PHANDLE OutKey) 242 { 243 PDEVICE_OBJECT DeviceObject; 244 ULONG DeviceCount; 245 NTSTATUS Status; 246 UNICODE_STRING KeyName; 247 248 /* get enumeration context */ 249 DeviceObject = (PDEVICE_OBJECT)EnumContext; 250 251 /* get device count */ 252 DeviceCount = GetSysAudioDeviceCount(DeviceObject); 253 254 if (DeviceIndex >= DeviceCount) 255 { 256 /* no more devices */ 257 return MM_STATUS_NO_MORE_DEVICES; 258 } 259 260 /* get device name */ 261 Status = GetSysAudioDevicePnpName(DeviceObject, DeviceIndex, DeviceName); 262 263 if (!NT_SUCCESS(Status)) 264 { 265 /* failed to retrieve device name */ 266 return MM_STATUS_UNSUCCESSFUL; 267 } 268 269 /* initialize key name */ 270 RtlInitUnicodeString(&KeyName, *DeviceName); 271 272 /* open device interface key */ 273 Status = IoOpenDeviceInterfaceRegistryKey(&KeyName, GENERIC_READ | GENERIC_WRITE, OutKey); 274 275 if (!NT_SUCCESS(Status)) 276 { 277 *OutKey = NULL; 278 } 279 280 #if 0 281 if (!NT_SUCCESS(Status)) 282 { 283 /* failed to open key */ 284 DPRINT("IoOpenDeviceInterfaceRegistryKey failed with %lx\n", Status); 285 FreeItem(*DeviceName); 286 return MM_STATUS_UNSUCCESSFUL; 287 } 288 #endif 289 290 /* open device handle */ 291 Status = OpenDevice(*DeviceName, OutHandle, NULL); 292 if (!NT_SUCCESS(Status)) 293 { 294 /* failed to open device */ 295 return MM_STATUS_UNSUCCESSFUL; 296 } 297 298 return MM_STATUS_SUCCESS; 299 } 300 301 PVOID 302 AllocEventData( 303 IN ULONG ExtraSize) 304 { 305 PKSEVENTDATA Data = (PKSEVENTDATA)AllocateItem(NonPagedPool, sizeof(KSEVENTDATA) + ExtraSize); 306 if (!Data) 307 return NULL; 308 309 Data->EventObject.Event = AllocateItem(NonPagedPool, sizeof(KEVENT)); 310 if (!Data->EventHandle.Event) 311 { 312 FreeItem(Data); 313 return NULL; 314 } 315 316 KeInitializeEvent(Data->EventObject.Event, NotificationEvent, FALSE); 317 318 Data->NotificationType = KSEVENTF_EVENT_HANDLE; 319 return Data; 320 } 321 322 VOID 323 FreeEventData(IN PVOID EventData) 324 { 325 PKSEVENTDATA Data = (PKSEVENTDATA)EventData; 326 327 FreeItem(Data->EventHandle.Event); 328 FreeItem(Data); 329 } 330 331 VOID 332 CALLBACK 333 EventCallback( 334 IN PVOID MixerEventContext, 335 IN HANDLE hMixer, 336 IN ULONG NotificationType, 337 IN ULONG Value) 338 { 339 PWDMAUD_CLIENT ClientInfo; 340 PEVENT_ENTRY Entry; 341 ULONG Index; 342 343 /* get client context */ 344 ClientInfo = (PWDMAUD_CLIENT)MixerEventContext; 345 346 /* now search for the mixer which originated the request */ 347 for(Index = 0; Index < ClientInfo->NumPins; Index++) 348 { 349 if (ClientInfo->hPins[Index].Handle == hMixer && ClientInfo->hPins[Index].Type == MIXER_DEVICE_TYPE) 350 { 351 if (ClientInfo->hPins[Index].NotifyEvent) 352 { 353 /* allocate event entry */ 354 Entry = AllocateItem(NonPagedPool, sizeof(EVENT_ENTRY)); 355 if (!Entry) 356 { 357 /* no memory */ 358 break; 359 } 360 361 /* setup event entry */ 362 Entry->NotificationType = NotificationType; 363 Entry->Value = Value; 364 Entry->hMixer = hMixer; 365 366 /* insert entry */ 367 InsertTailList(&ClientInfo->MixerEventList, &Entry->Entry); 368 369 /* now notify the client */ 370 KeSetEvent(ClientInfo->hPins[Index].NotifyEvent, 0, FALSE); 371 } 372 /* done */ 373 break; 374 } 375 } 376 } 377 378 379 NTSTATUS 380 WdmAudMixerInitialize( 381 IN PDEVICE_OBJECT DeviceObject) 382 { 383 MIXER_STATUS Status; 384 385 /* initialize the mixer library */ 386 Status = MMixerInitialize(&MixerContext, Enum, (PVOID)DeviceObject); 387 388 if (Status != MM_STATUS_SUCCESS) 389 { 390 /* failed to initialize mmixer library */ 391 DPRINT("MMixerInitialize failed with %lx\n", Status); 392 } 393 394 return Status; 395 } 396 397 NTSTATUS 398 WdmAudMixerCapabilities( 399 IN PDEVICE_OBJECT DeviceObject, 400 IN PWDMAUD_DEVICE_INFO DeviceInfo, 401 IN PWDMAUD_CLIENT ClientInfo, 402 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) 403 { 404 if (MMixerGetCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MixCaps) == MM_STATUS_SUCCESS) 405 return STATUS_SUCCESS; 406 407 return STATUS_INVALID_PARAMETER; 408 } 409 410 NTSTATUS 411 WdmAudControlOpenMixer( 412 IN PDEVICE_OBJECT DeviceObject, 413 IN PIRP Irp, 414 IN PWDMAUD_DEVICE_INFO DeviceInfo, 415 IN PWDMAUD_CLIENT ClientInfo) 416 { 417 HANDLE hMixer; 418 PWDMAUD_HANDLE Handles; 419 //PWDMAUD_DEVICE_EXTENSION DeviceExtension; 420 NTSTATUS Status; 421 PKEVENT EventObject = NULL; 422 423 DPRINT("WdmAudControlOpenMixer\n"); 424 425 //DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 426 427 if (DeviceInfo->u.hNotifyEvent) 428 { 429 Status = ObReferenceObjectByHandle(DeviceInfo->u.hNotifyEvent, EVENT_MODIFY_STATE, *ExEventObjectType, UserMode, (LPVOID*)&EventObject, NULL); 430 431 if (!NT_SUCCESS(Status)) 432 { 433 DPRINT1("Invalid notify event passed %p from client %p\n", DeviceInfo->u.hNotifyEvent, ClientInfo); 434 DbgBreakPoint(); 435 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); 436 } 437 } 438 439 if (MMixerOpen(&MixerContext, DeviceInfo->DeviceIndex, ClientInfo, EventCallback, &hMixer) != MM_STATUS_SUCCESS) 440 { 441 ObDereferenceObject(EventObject); 442 DPRINT1("Failed to open mixer\n"); 443 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); 444 } 445 446 447 Handles = AllocateItem(NonPagedPool, sizeof(WDMAUD_HANDLE) * (ClientInfo->NumPins+1)); 448 449 if (Handles) 450 { 451 if (ClientInfo->NumPins) 452 { 453 RtlMoveMemory(Handles, ClientInfo->hPins, sizeof(WDMAUD_HANDLE) * ClientInfo->NumPins); 454 FreeItem(ClientInfo->hPins); 455 } 456 457 ClientInfo->hPins = Handles; 458 ClientInfo->hPins[ClientInfo->NumPins].Handle = hMixer; 459 ClientInfo->hPins[ClientInfo->NumPins].Type = MIXER_DEVICE_TYPE; 460 ClientInfo->hPins[ClientInfo->NumPins].NotifyEvent = EventObject; 461 ClientInfo->NumPins++; 462 } 463 else 464 { 465 ObDereferenceObject(EventObject); 466 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); 467 } 468 469 DeviceInfo->hDevice = hMixer; 470 471 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 472 } 473 474 NTSTATUS 475 WdmAudControlCloseMixer( 476 IN PDEVICE_OBJECT DeviceObject, 477 IN PIRP Irp, 478 IN PWDMAUD_DEVICE_INFO DeviceInfo, 479 IN PWDMAUD_CLIENT ClientInfo, 480 IN ULONG Index) 481 { 482 /* Remove event associated to this client */ 483 if (MMixerClose(&MixerContext, DeviceInfo->DeviceIndex, ClientInfo, EventCallback) != MM_STATUS_SUCCESS) 484 { 485 DPRINT1("Failed to close mixer\n"); 486 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); 487 } 488 489 /* Dereference event */ 490 if (ClientInfo->hPins[Index].NotifyEvent) 491 { 492 ObDereferenceObject(ClientInfo->hPins[Index].NotifyEvent); 493 ClientInfo->hPins[Index].NotifyEvent = NULL; 494 } 495 496 /* FIXME: do we need to free ClientInfo->hPins ? */ 497 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 498 } 499 500 VOID 501 WdmAudCloseAllMixers( 502 IN PDEVICE_OBJECT DeviceObject, 503 IN PWDMAUD_CLIENT ClientInfo, 504 IN ULONG Index) 505 { 506 ULONG DeviceCount, DeviceIndex; 507 508 /* Get all mixers */ 509 DeviceCount = GetSysAudioDeviceCount(DeviceObject); 510 511 /* Close every mixer attached to the device */ 512 for (DeviceIndex = 0; DeviceIndex < DeviceCount; DeviceIndex++) 513 { 514 if (MMixerClose(&MixerContext, DeviceIndex, ClientInfo, EventCallback) != MM_STATUS_SUCCESS) 515 { 516 DPRINT1("Failed to close mixer for device %lu\n", DeviceIndex); 517 } 518 } 519 520 /* Dereference event */ 521 if (ClientInfo->hPins[Index].NotifyEvent) 522 { 523 ObDereferenceObject(ClientInfo->hPins[Index].NotifyEvent); 524 ClientInfo->hPins[Index].NotifyEvent = NULL; 525 } 526 } 527 528 NTSTATUS 529 NTAPI 530 WdmAudGetControlDetails( 531 IN PDEVICE_OBJECT DeviceObject, 532 IN PIRP Irp, 533 IN PWDMAUD_DEVICE_INFO DeviceInfo, 534 IN PWDMAUD_CLIENT ClientInfo) 535 { 536 MIXER_STATUS Status; 537 538 /* clear hmixer type flag */ 539 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER; 540 541 /* query mmixer library */ 542 Status = MMixerGetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixDetails); 543 544 if (Status == MM_STATUS_SUCCESS) 545 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 546 else 547 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); 548 } 549 550 NTSTATUS 551 NTAPI 552 WdmAudGetLineInfo( 553 IN PDEVICE_OBJECT DeviceObject, 554 IN PIRP Irp, 555 IN PWDMAUD_DEVICE_INFO DeviceInfo, 556 IN PWDMAUD_CLIENT ClientInfo) 557 { 558 MIXER_STATUS Status; 559 560 /* clear hmixer type flag */ 561 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER; 562 563 /* query mixer library */ 564 Status = MMixerGetLineInfo(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixLine); 565 566 if (Status == MM_STATUS_SUCCESS) 567 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 568 else 569 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); 570 } 571 572 NTSTATUS 573 NTAPI 574 WdmAudGetLineControls( 575 IN PDEVICE_OBJECT DeviceObject, 576 IN PIRP Irp, 577 IN PWDMAUD_DEVICE_INFO DeviceInfo, 578 IN PWDMAUD_CLIENT ClientInfo) 579 { 580 MIXER_STATUS Status; 581 582 /* clear hmixer type flag */ 583 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER; 584 585 /* query mixer library */ 586 Status = MMixerGetLineControls(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixControls); 587 588 if (Status == MM_STATUS_SUCCESS) 589 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 590 else 591 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); 592 593 594 } 595 596 NTSTATUS 597 NTAPI 598 WdmAudSetControlDetails( 599 IN PDEVICE_OBJECT DeviceObject, 600 IN PIRP Irp, 601 IN PWDMAUD_DEVICE_INFO DeviceInfo, 602 IN PWDMAUD_CLIENT ClientInfo) 603 { 604 MIXER_STATUS Status; 605 606 /* clear hmixer type flag */ 607 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER; 608 609 /* query mixer library */ 610 Status = MMixerSetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixDetails); 611 612 if (Status == MM_STATUS_SUCCESS) 613 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 614 else 615 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); 616 } 617 618 NTSTATUS 619 NTAPI 620 WdmAudGetMixerEvent( 621 IN PDEVICE_OBJECT DeviceObject, 622 IN PIRP Irp, 623 IN PWDMAUD_DEVICE_INFO DeviceInfo, 624 IN PWDMAUD_CLIENT ClientInfo) 625 { 626 PLIST_ENTRY Entry; 627 PEVENT_ENTRY EventEntry; 628 629 /* enumerate event list and check if there is a new event */ 630 Entry = ClientInfo->MixerEventList.Flink; 631 632 while(Entry != &ClientInfo->MixerEventList) 633 { 634 /* grab event entry */ 635 EventEntry = (PEVENT_ENTRY)CONTAINING_RECORD(Entry, EVENT_ENTRY, Entry); 636 637 if (EventEntry->hMixer == DeviceInfo->hDevice) 638 { 639 /* found an entry */ 640 DeviceInfo->u.MixerEvent.hMixer = EventEntry->hMixer; 641 DeviceInfo->u.MixerEvent.NotificationType = EventEntry->NotificationType; 642 DeviceInfo->u.MixerEvent.Value = EventEntry->Value; 643 644 /* remove entry from list */ 645 RemoveEntryList(&EventEntry->Entry); 646 647 /* free event entry */ 648 FreeItem(EventEntry); 649 650 /* done */ 651 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 652 } 653 654 /* move to next */ 655 Entry = Entry->Flink; 656 } 657 658 /* no event entry available */ 659 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); 660 } 661 662 ULONG 663 WdmAudGetMixerDeviceCount() 664 { 665 return MMixerGetCount(&MixerContext); 666 } 667 668 ULONG 669 WdmAudGetWaveInDeviceCount() 670 { 671 return MMixerGetWaveInCount(&MixerContext); 672 } 673 674 ULONG 675 WdmAudGetWaveOutDeviceCount() 676 { 677 return MMixerGetWaveOutCount(&MixerContext); 678 } 679 680 ULONG 681 WdmAudGetMidiInDeviceCount() 682 { 683 return MMixerGetMidiInCount(&MixerContext); 684 } 685 686 ULONG 687 WdmAudGetMidiOutDeviceCount() 688 { 689 return MMixerGetWaveOutCount(&MixerContext); 690 } 691 692 NTSTATUS 693 WdmAudGetPnpNameByIndexAndType( 694 IN ULONG DeviceIndex, 695 IN SOUND_DEVICE_TYPE DeviceType, 696 OUT LPWSTR *DevicePath) 697 { 698 if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE) 699 { 700 if (MMixerGetWaveDevicePath(&MixerContext, DeviceType == WAVE_IN_DEVICE_TYPE, DeviceIndex, DevicePath) == MM_STATUS_SUCCESS) 701 return STATUS_SUCCESS; 702 else 703 return STATUS_UNSUCCESSFUL; 704 } 705 else if (DeviceType == MIDI_IN_DEVICE_TYPE || DeviceType == MIDI_OUT_DEVICE_TYPE) 706 { 707 if (MMixerGetMidiDevicePath(&MixerContext, DeviceType == MIDI_IN_DEVICE_TYPE, DeviceIndex, DevicePath) == MM_STATUS_SUCCESS) 708 return STATUS_SUCCESS; 709 else 710 return STATUS_UNSUCCESSFUL; 711 } 712 else if (DeviceType == MIXER_DEVICE_TYPE) 713 { 714 UNIMPLEMENTED; 715 } 716 717 return STATUS_UNSUCCESSFUL; 718 } 719 720 NTSTATUS 721 WdmAudWaveCapabilities( 722 IN PDEVICE_OBJECT DeviceObject, 723 IN PWDMAUD_DEVICE_INFO DeviceInfo, 724 IN PWDMAUD_CLIENT ClientInfo, 725 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) 726 { 727 MIXER_STATUS Status = MM_STATUS_UNSUCCESSFUL; 728 729 if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) 730 { 731 /* get capabilities */ 732 Status = MMixerWaveInCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveInCaps); 733 } 734 else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) 735 { 736 /* get capabilities */ 737 Status = MMixerWaveOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveOutCaps); 738 } 739 740 if (Status == MM_STATUS_SUCCESS) 741 return STATUS_SUCCESS; 742 else 743 return Status; 744 } 745 746 NTSTATUS 747 WdmAudMidiCapabilities( 748 IN PDEVICE_OBJECT DeviceObject, 749 IN PWDMAUD_DEVICE_INFO DeviceInfo, 750 IN PWDMAUD_CLIENT ClientInfo, 751 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) 752 { 753 MIXER_STATUS Status = MM_STATUS_UNSUCCESSFUL; 754 755 if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE) 756 { 757 /* get capabilities */ 758 Status = MMixerMidiInCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MidiInCaps); 759 } 760 else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) 761 { 762 /* get capabilities */ 763 Status = MMixerMidiOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MidiOutCaps); 764 } 765 766 if (Status == MM_STATUS_SUCCESS) 767 return STATUS_SUCCESS; 768 else 769 return STATUS_UNSUCCESSFUL; 770 } 771 772 NTSTATUS 773 NTAPI 774 WdmAudGetPosition( 775 _In_ PDEVICE_OBJECT DeviceObject, 776 _In_ PIRP Irp, 777 _In_ PWDMAUD_DEVICE_INFO DeviceInfo) 778 { 779 MIXER_STATUS Status; 780 ULONG Position; 781 782 /* Get position */ 783 Status = MMixerGetWavePosition(&MixerContext, DeviceInfo->hDevice, &Position); 784 785 if (Status == MM_STATUS_SUCCESS) 786 { 787 DeviceInfo->u.Position = (ULONGLONG)Position; 788 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 789 } 790 else 791 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); 792 } 793 794 795 MIXER_STATUS 796 CreatePinCallback( 797 IN PVOID Ctx, 798 IN ULONG VirtualDeviceId, 799 IN ULONG PinId, 800 IN HANDLE hFilter, 801 IN PKSPIN_CONNECT PinConnect, 802 IN ACCESS_MASK DesiredAccess, 803 OUT PHANDLE PinHandle) 804 { 805 ULONG BytesReturned; 806 SYSAUDIO_INSTANCE_INFO InstanceInfo; 807 NTSTATUS Status; 808 ULONG FreeIndex; 809 PPIN_CREATE_CONTEXT Context = (PPIN_CREATE_CONTEXT)Ctx; 810 811 /* setup property request */ 812 InstanceInfo.Property.Set = KSPROPSETID_Sysaudio; 813 InstanceInfo.Property.Id = KSPROPERTY_SYSAUDIO_INSTANCE_INFO; 814 InstanceInfo.Property.Flags = KSPROPERTY_TYPE_SET; 815 InstanceInfo.Flags = 0; 816 InstanceInfo.DeviceNumber = VirtualDeviceId; 817 818 /* attach to virtual device */ 819 Status = KsSynchronousIoControlDevice(Context->DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&InstanceInfo, sizeof(SYSAUDIO_INSTANCE_INFO), NULL, 0, &BytesReturned); 820 821 if (!NT_SUCCESS(Status)) 822 return MM_STATUS_UNSUCCESSFUL; 823 824 /* close existing pin */ 825 FreeIndex = ClosePin(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType); 826 827 /* now create the pin */ 828 Status = KsCreatePin(Context->DeviceExtension->hSysAudio, PinConnect, DesiredAccess, PinHandle); 829 830 /* check for success */ 831 if (!NT_SUCCESS(Status)) 832 return MM_STATUS_UNSUCCESSFUL; 833 834 /* store the handle */ 835 Status = InsertPinHandle(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType, *PinHandle, FreeIndex); 836 if (!NT_SUCCESS(Status)) 837 { 838 /* failed to insert handle */ 839 ZwClose(*PinHandle); 840 return MM_STATUS_UNSUCCESSFUL; 841 } 842 843 return MM_STATUS_SUCCESS; 844 } 845 846 NTSTATUS 847 WdmAudControlOpenWave( 848 IN PDEVICE_OBJECT DeviceObject, 849 IN PIRP Irp, 850 IN PWDMAUD_DEVICE_INFO DeviceInfo, 851 IN PWDMAUD_CLIENT ClientInfo) 852 { 853 MIXER_STATUS Status; 854 PIN_CREATE_CONTEXT Context; 855 856 Context.ClientInfo = ClientInfo; 857 Context.DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 858 Context.DeviceType = DeviceInfo->DeviceType; 859 860 Status = MMixerOpenWave(&MixerContext, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE, &DeviceInfo->u.WaveFormatEx, CreatePinCallback, &Context, &DeviceInfo->hDevice); 861 862 if (Status == MM_STATUS_SUCCESS) 863 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 864 else 865 return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO)); 866 } 867 868 NTSTATUS 869 WdmAudControlOpenMidi( 870 IN PDEVICE_OBJECT DeviceObject, 871 IN PIRP Irp, 872 IN PWDMAUD_DEVICE_INFO DeviceInfo, 873 IN PWDMAUD_CLIENT ClientInfo) 874 { 875 MIXER_STATUS Status; 876 PIN_CREATE_CONTEXT Context; 877 878 Context.ClientInfo = ClientInfo; 879 Context.DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 880 Context.DeviceType = DeviceInfo->DeviceType; 881 882 Status = MMixerOpenMidi(&MixerContext, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE, CreatePinCallback, &Context, &DeviceInfo->hDevice); 883 884 if (Status == MM_STATUS_SUCCESS) 885 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); 886 else 887 return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO)); 888 } 889