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
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
);
29 MIXER_CONTEXT MixerContext
=
31 sizeof(MIXER_CONTEXT
),
46 GUID CategoryGuid
= {STATIC_KSCATEGORY_AUDIO
};
52 OUT PVOID
* ResultBuffer
,
53 OUT PULONG ResultLength
,
57 UNICODE_STRING KeyName
;
59 PKEY_VALUE_PARTIAL_INFORMATION PartialInformation
;
61 /* initialize key name */
62 RtlInitUnicodeString(&KeyName
, lpKeyName
);
64 /* now query MatchingDeviceId key */
65 Status
= ZwQueryValueKey(hKey
, &KeyName
, KeyValuePartialInformation
, NULL
, 0, &Length
);
67 /* check for success */
68 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
69 return MM_STATUS_UNSUCCESSFUL
;
71 /* allocate a buffer for key data */
72 PartialInformation
= AllocateItem(NonPagedPool
, Length
);
74 if (!PartialInformation
)
75 return MM_STATUS_NO_MEMORY
;
78 /* now query MatchingDeviceId key */
79 Status
= ZwQueryValueKey(hKey
, &KeyName
, KeyValuePartialInformation
, PartialInformation
, Length
, &Length
);
81 /* check for success */
82 if (!NT_SUCCESS(Status
))
84 FreeItem(PartialInformation
);
85 return MM_STATUS_UNSUCCESSFUL
;
91 *KeyType
= PartialInformation
->Type
;
96 /* return data length */
97 *ResultLength
= PartialInformation
->DataLength
;
100 *ResultBuffer
= AllocateItem(NonPagedPool
, PartialInformation
->DataLength
);
103 /* not enough memory */
104 FreeItem(PartialInformation
);
105 return MM_STATUS_NO_MEMORY
;
109 RtlMoveMemory(*ResultBuffer
, PartialInformation
->Data
, PartialInformation
->DataLength
);
112 FreeItem(PartialInformation
);
114 return MM_STATUS_SUCCESS
;
120 IN LPWSTR lpSubKeyName
,
121 IN ULONG DesiredAccess
,
124 OBJECT_ATTRIBUTES ObjectAttributes
;
125 UNICODE_STRING SubKeyName
;
128 /* initialize sub key name */
129 RtlInitUnicodeString(&SubKeyName
, lpSubKeyName
);
131 /* initialize key attributes */
132 InitializeObjectAttributes(&ObjectAttributes
, &SubKeyName
, OBJ_CASE_INSENSITIVE
| OBJ_OPENIF
, hKey
, NULL
);
135 Status
= ZwOpenKey(OutKey
, DesiredAccess
, &ObjectAttributes
);
137 if (NT_SUCCESS(Status
))
138 return MM_STATUS_SUCCESS
;
140 return MM_STATUS_UNSUCCESSFUL
;
147 if (ZwClose(hKey
) == STATUS_SUCCESS
)
148 return MM_STATUS_SUCCESS
;
150 return MM_STATUS_UNSUCCESSFUL
;
154 PVOID
Alloc(ULONG NumBytes
)
156 return AllocateItem(NonPagedPool
, NumBytes
);
160 Close(HANDLE hDevice
)
162 if (ZwClose(hDevice
) == STATUS_SUCCESS
)
163 return MM_STATUS_SUCCESS
;
165 return MM_STATUS_UNSUCCESSFUL
;
175 Copy(PVOID Src
, PVOID Dst
, ULONG NumBytes
)
177 RtlMoveMemory(Src
, Dst
, NumBytes
);
182 IN LPWSTR DevicePath
,
185 if (WdmAudOpenSysAudioDevice(DevicePath
, hDevice
) == STATUS_SUCCESS
)
186 return MM_STATUS_SUCCESS
;
188 return MM_STATUS_UNSUCCESSFUL
;
194 IN ULONG dwIoControlCode
,
196 IN ULONG nInBufferSize
,
197 OUT PVOID lpOutBuffer
,
198 ULONG nOutBufferSize
,
199 PULONG lpBytesReturned
)
202 PFILE_OBJECT FileObject
;
204 /* get file object */
205 Status
= ObReferenceObjectByHandle(hMixer
, GENERIC_READ
| GENERIC_WRITE
, *IoFileObjectType
, KernelMode
, (PVOID
*)&FileObject
, NULL
);
206 if (!NT_SUCCESS(Status
))
208 DPRINT("failed to reference %p with %lx\n", hMixer
, Status
);
209 return MM_STATUS_UNSUCCESSFUL
;
212 /* perform request */
213 Status
= KsSynchronousIoControlDevice(FileObject
, KernelMode
, dwIoControlCode
, lpInBuffer
, nInBufferSize
, lpOutBuffer
, nOutBufferSize
, lpBytesReturned
);
215 /* release object reference */
216 ObDereferenceObject(FileObject
);
218 if (Status
== STATUS_MORE_ENTRIES
|| Status
== STATUS_BUFFER_OVERFLOW
|| Status
== STATUS_BUFFER_TOO_SMALL
)
220 /* more data is available */
221 return MM_STATUS_MORE_ENTRIES
;
223 else if (Status
== STATUS_SUCCESS
)
225 /* operation succeeded */
226 return MM_STATUS_SUCCESS
;
230 DPRINT("Failed with %lx\n", Status
);
231 return MM_STATUS_UNSUCCESSFUL
;
237 IN PVOID EnumContext
,
238 IN ULONG DeviceIndex
,
239 OUT LPWSTR
* DeviceName
,
240 OUT PHANDLE OutHandle
,
243 PDEVICE_OBJECT DeviceObject
;
246 UNICODE_STRING KeyName
;
248 /* get enumeration context */
249 DeviceObject
= (PDEVICE_OBJECT
)EnumContext
;
251 /* get device count */
252 DeviceCount
= GetSysAudioDeviceCount(DeviceObject
);
254 if (DeviceIndex
>= DeviceCount
)
256 /* no more devices */
257 return MM_STATUS_NO_MORE_DEVICES
;
260 /* get device name */
261 Status
= GetSysAudioDevicePnpName(DeviceObject
, DeviceIndex
, DeviceName
);
263 if (!NT_SUCCESS(Status
))
265 /* failed to retrieve device name */
266 return MM_STATUS_UNSUCCESSFUL
;
269 /* initialize key name */
270 RtlInitUnicodeString(&KeyName
, *DeviceName
);
272 /* open device interface key */
273 Status
= IoOpenDeviceInterfaceRegistryKey(&KeyName
, GENERIC_READ
| GENERIC_WRITE
, OutKey
);
275 if (!NT_SUCCESS(Status
))
281 if (!NT_SUCCESS(Status
))
283 /* failed to open key */
284 DPRINT("IoOpenDeviceInterfaceRegistryKey failed with %lx\n", Status
);
285 FreeItem(*DeviceName
);
286 return MM_STATUS_UNSUCCESSFUL
;
290 /* open device handle */
291 Status
= OpenDevice(*DeviceName
, OutHandle
, NULL
);
292 if (!NT_SUCCESS(Status
))
294 /* failed to open device */
295 return MM_STATUS_UNSUCCESSFUL
;
298 return MM_STATUS_SUCCESS
;
305 PKSEVENTDATA Data
= (PKSEVENTDATA
)AllocateItem(NonPagedPool
, sizeof(KSEVENTDATA
) + ExtraSize
);
309 Data
->EventObject
.Event
= AllocateItem(NonPagedPool
, sizeof(KEVENT
));
310 if (!Data
->EventHandle
.Event
)
316 KeInitializeEvent(Data
->EventObject
.Event
, NotificationEvent
, FALSE
);
318 Data
->NotificationType
= KSEVENTF_EVENT_HANDLE
;
323 FreeEventData(IN PVOID EventData
)
325 PKSEVENTDATA Data
= (PKSEVENTDATA
)EventData
;
327 FreeItem(Data
->EventHandle
.Event
);
334 IN PVOID MixerEventContext
,
336 IN ULONG NotificationType
,
339 PWDMAUD_CLIENT ClientInfo
;
343 /* get client context */
344 ClientInfo
= (PWDMAUD_CLIENT
)MixerEventContext
;
346 /* now search for the mixer which originated the request */
347 for(Index
= 0; Index
< ClientInfo
->NumPins
; Index
++)
349 if (ClientInfo
->hPins
[Index
].Handle
== hMixer
&& ClientInfo
->hPins
[Index
].Type
== MIXER_DEVICE_TYPE
)
351 if (ClientInfo
->hPins
[Index
].NotifyEvent
)
353 /* allocate event entry */
354 Entry
= AllocateItem(NonPagedPool
, sizeof(EVENT_ENTRY
));
361 /* setup event entry */
362 Entry
->NotificationType
= NotificationType
;
363 Entry
->Value
= Value
;
364 Entry
->hMixer
= hMixer
;
367 InsertTailList(&ClientInfo
->MixerEventList
, &Entry
->Entry
);
369 /* now notify the client */
370 KeSetEvent(ClientInfo
->hPins
[Index
].NotifyEvent
, 0, FALSE
);
380 WdmAudMixerInitialize(
381 IN PDEVICE_OBJECT DeviceObject
)
385 /* initialize the mixer library */
386 Status
= MMixerInitialize(&MixerContext
, Enum
, (PVOID
)DeviceObject
);
388 if (Status
!= MM_STATUS_SUCCESS
)
390 /* failed to initialize mmixer library */
391 DPRINT("MMixerInitialize failed with %lx\n", Status
);
398 WdmAudMixerCapabilities(
399 IN PDEVICE_OBJECT DeviceObject
,
400 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
401 IN PWDMAUD_CLIENT ClientInfo
,
402 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension
)
404 if (MMixerGetCapabilities(&MixerContext
, DeviceInfo
->DeviceIndex
, &DeviceInfo
->u
.MixCaps
) == MM_STATUS_SUCCESS
)
405 return STATUS_SUCCESS
;
407 return STATUS_INVALID_PARAMETER
;
411 WdmAudControlOpenMixer(
412 IN PDEVICE_OBJECT DeviceObject
,
414 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
415 IN PWDMAUD_CLIENT ClientInfo
)
418 PWDMAUD_HANDLE Handles
;
419 //PWDMAUD_DEVICE_EXTENSION DeviceExtension;
421 PKEVENT EventObject
= NULL
;
423 DPRINT("WdmAudControlOpenMixer\n");
425 //DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
427 if (DeviceInfo
->u
.hNotifyEvent
)
429 Status
= ObReferenceObjectByHandle(DeviceInfo
->u
.hNotifyEvent
, EVENT_MODIFY_STATE
, *ExEventObjectType
, UserMode
, (LPVOID
*)&EventObject
, NULL
);
431 if (!NT_SUCCESS(Status
))
433 DPRINT1("Invalid notify event passed %p from client %p\n", DeviceInfo
->u
.hNotifyEvent
, ClientInfo
);
435 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
439 if (MMixerOpen(&MixerContext
, DeviceInfo
->DeviceIndex
, ClientInfo
, EventCallback
, &hMixer
) != MM_STATUS_SUCCESS
)
441 ObDereferenceObject(EventObject
);
442 DPRINT1("Failed to open mixer\n");
443 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, 0);
447 Handles
= AllocateItem(NonPagedPool
, sizeof(WDMAUD_HANDLE
) * (ClientInfo
->NumPins
+1));
451 if (ClientInfo
->NumPins
)
453 RtlMoveMemory(Handles
, ClientInfo
->hPins
, sizeof(WDMAUD_HANDLE
) * ClientInfo
->NumPins
);
454 FreeItem(ClientInfo
->hPins
);
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
++;
465 ObDereferenceObject(EventObject
);
466 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, sizeof(WDMAUD_DEVICE_INFO
));
469 DeviceInfo
->hDevice
= hMixer
;
471 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
475 WdmAudControlCloseMixer(
476 IN PDEVICE_OBJECT DeviceObject
,
478 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
479 IN PWDMAUD_CLIENT ClientInfo
,
482 /* Remove event associated to this client */
483 if (MMixerClose(&MixerContext
, DeviceInfo
->DeviceIndex
, ClientInfo
, EventCallback
) != MM_STATUS_SUCCESS
)
485 DPRINT1("Failed to close mixer\n");
486 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, sizeof(WDMAUD_DEVICE_INFO
));
489 /* Dereference event */
490 if (ClientInfo
->hPins
[Index
].NotifyEvent
)
492 ObDereferenceObject(ClientInfo
->hPins
[Index
].NotifyEvent
);
493 ClientInfo
->hPins
[Index
].NotifyEvent
= NULL
;
496 /* FIXME: do we need to free ClientInfo->hPins ? */
497 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
501 WdmAudCloseAllMixers(
502 IN PDEVICE_OBJECT DeviceObject
,
503 IN PWDMAUD_CLIENT ClientInfo
,
506 ULONG DeviceCount
, DeviceIndex
;
509 DeviceCount
= GetSysAudioDeviceCount(DeviceObject
);
511 /* Close every mixer attached to the device */
512 for (DeviceIndex
= 0; DeviceIndex
< DeviceCount
; DeviceIndex
++)
514 if (MMixerClose(&MixerContext
, DeviceIndex
, ClientInfo
, EventCallback
) != MM_STATUS_SUCCESS
)
516 DPRINT1("Failed to close mixer for device %lu\n", DeviceIndex
);
520 /* Dereference event */
521 if (ClientInfo
->hPins
[Index
].NotifyEvent
)
523 ObDereferenceObject(ClientInfo
->hPins
[Index
].NotifyEvent
);
524 ClientInfo
->hPins
[Index
].NotifyEvent
= NULL
;
530 WdmAudGetControlDetails(
531 IN PDEVICE_OBJECT DeviceObject
,
533 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
534 IN PWDMAUD_CLIENT ClientInfo
)
538 /* clear hmixer type flag */
539 DeviceInfo
->Flags
&= ~MIXER_OBJECTF_HMIXER
;
541 /* query mmixer library */
542 Status
= MMixerGetControlDetails(&MixerContext
, DeviceInfo
->hDevice
, DeviceInfo
->DeviceIndex
, DeviceInfo
->Flags
, &DeviceInfo
->u
.MixDetails
);
544 if (Status
== MM_STATUS_SUCCESS
)
545 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
547 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, sizeof(WDMAUD_DEVICE_INFO
));
553 IN PDEVICE_OBJECT DeviceObject
,
555 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
556 IN PWDMAUD_CLIENT ClientInfo
)
560 /* clear hmixer type flag */
561 DeviceInfo
->Flags
&= ~MIXER_OBJECTF_HMIXER
;
563 /* query mixer library */
564 Status
= MMixerGetLineInfo(&MixerContext
, DeviceInfo
->hDevice
, DeviceInfo
->DeviceIndex
, DeviceInfo
->Flags
, &DeviceInfo
->u
.MixLine
);
566 if (Status
== MM_STATUS_SUCCESS
)
567 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
569 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, sizeof(WDMAUD_DEVICE_INFO
));
574 WdmAudGetLineControls(
575 IN PDEVICE_OBJECT DeviceObject
,
577 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
578 IN PWDMAUD_CLIENT ClientInfo
)
582 /* clear hmixer type flag */
583 DeviceInfo
->Flags
&= ~MIXER_OBJECTF_HMIXER
;
585 /* query mixer library */
586 Status
= MMixerGetLineControls(&MixerContext
, DeviceInfo
->hDevice
, DeviceInfo
->DeviceIndex
, DeviceInfo
->Flags
, &DeviceInfo
->u
.MixControls
);
588 if (Status
== MM_STATUS_SUCCESS
)
589 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
591 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, sizeof(WDMAUD_DEVICE_INFO
));
598 WdmAudSetControlDetails(
599 IN PDEVICE_OBJECT DeviceObject
,
601 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
602 IN PWDMAUD_CLIENT ClientInfo
)
606 /* clear hmixer type flag */
607 DeviceInfo
->Flags
&= ~MIXER_OBJECTF_HMIXER
;
609 /* query mixer library */
610 Status
= MMixerSetControlDetails(&MixerContext
, DeviceInfo
->hDevice
, DeviceInfo
->DeviceIndex
, DeviceInfo
->Flags
, &DeviceInfo
->u
.MixDetails
);
612 if (Status
== MM_STATUS_SUCCESS
)
613 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
615 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, sizeof(WDMAUD_DEVICE_INFO
));
621 IN PDEVICE_OBJECT DeviceObject
,
623 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
624 IN PWDMAUD_CLIENT ClientInfo
)
627 PEVENT_ENTRY EventEntry
;
629 /* enumerate event list and check if there is a new event */
630 Entry
= ClientInfo
->MixerEventList
.Flink
;
632 while(Entry
!= &ClientInfo
->MixerEventList
)
634 /* grab event entry */
635 EventEntry
= (PEVENT_ENTRY
)CONTAINING_RECORD(Entry
, EVENT_ENTRY
, Entry
);
637 if (EventEntry
->hMixer
== DeviceInfo
->hDevice
)
640 DeviceInfo
->u
.MixerEvent
.hMixer
= EventEntry
->hMixer
;
641 DeviceInfo
->u
.MixerEvent
.NotificationType
= EventEntry
->NotificationType
;
642 DeviceInfo
->u
.MixerEvent
.Value
= EventEntry
->Value
;
644 /* remove entry from list */
645 RemoveEntryList(&EventEntry
->Entry
);
647 /* free event entry */
648 FreeItem(EventEntry
);
651 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
655 Entry
= Entry
->Flink
;
658 /* no event entry available */
659 return SetIrpIoStatus(Irp
, STATUS_UNSUCCESSFUL
, sizeof(WDMAUD_DEVICE_INFO
));
663 WdmAudGetMixerDeviceCount()
665 return MMixerGetCount(&MixerContext
);
669 WdmAudGetWaveInDeviceCount()
671 return MMixerGetWaveInCount(&MixerContext
);
675 WdmAudGetWaveOutDeviceCount()
677 return MMixerGetWaveOutCount(&MixerContext
);
681 WdmAudGetMidiInDeviceCount()
683 return MMixerGetMidiInCount(&MixerContext
);
687 WdmAudGetMidiOutDeviceCount()
689 return MMixerGetWaveOutCount(&MixerContext
);
693 WdmAudGetPnpNameByIndexAndType(
694 IN ULONG DeviceIndex
,
695 IN SOUND_DEVICE_TYPE DeviceType
,
696 OUT LPWSTR
*DevicePath
)
698 if (DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceType
== WAVE_OUT_DEVICE_TYPE
)
700 if (MMixerGetWaveDevicePath(&MixerContext
, DeviceType
== WAVE_IN_DEVICE_TYPE
, DeviceIndex
, DevicePath
) == MM_STATUS_SUCCESS
)
701 return STATUS_SUCCESS
;
703 return STATUS_UNSUCCESSFUL
;
705 else if (DeviceType
== MIDI_IN_DEVICE_TYPE
|| DeviceType
== MIDI_OUT_DEVICE_TYPE
)
707 if (MMixerGetMidiDevicePath(&MixerContext
, DeviceType
== MIDI_IN_DEVICE_TYPE
, DeviceIndex
, DevicePath
) == MM_STATUS_SUCCESS
)
708 return STATUS_SUCCESS
;
710 return STATUS_UNSUCCESSFUL
;
712 else if (DeviceType
== MIXER_DEVICE_TYPE
)
717 return STATUS_UNSUCCESSFUL
;
721 WdmAudWaveCapabilities(
722 IN PDEVICE_OBJECT DeviceObject
,
723 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
724 IN PWDMAUD_CLIENT ClientInfo
,
725 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension
)
727 MIXER_STATUS Status
= MM_STATUS_UNSUCCESSFUL
;
729 if (DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
)
731 /* get capabilities */
732 Status
= MMixerWaveInCapabilities(&MixerContext
, DeviceInfo
->DeviceIndex
, &DeviceInfo
->u
.WaveInCaps
);
734 else if (DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
)
736 /* get capabilities */
737 Status
= MMixerWaveOutCapabilities(&MixerContext
, DeviceInfo
->DeviceIndex
, &DeviceInfo
->u
.WaveOutCaps
);
740 if (Status
== MM_STATUS_SUCCESS
)
741 return STATUS_SUCCESS
;
747 WdmAudMidiCapabilities(
748 IN PDEVICE_OBJECT DeviceObject
,
749 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
750 IN PWDMAUD_CLIENT ClientInfo
,
751 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension
)
753 MIXER_STATUS Status
= MM_STATUS_UNSUCCESSFUL
;
755 if (DeviceInfo
->DeviceType
== MIDI_IN_DEVICE_TYPE
)
757 /* get capabilities */
758 Status
= MMixerMidiInCapabilities(&MixerContext
, DeviceInfo
->DeviceIndex
, &DeviceInfo
->u
.MidiInCaps
);
760 else if (DeviceInfo
->DeviceType
== WAVE_OUT_DEVICE_TYPE
)
762 /* get capabilities */
763 Status
= MMixerMidiOutCapabilities(&MixerContext
, DeviceInfo
->DeviceIndex
, &DeviceInfo
->u
.MidiOutCaps
);
766 if (Status
== MM_STATUS_SUCCESS
)
767 return STATUS_SUCCESS
;
769 return STATUS_UNSUCCESSFUL
;
776 IN ULONG VirtualDeviceId
,
779 IN PKSPIN_CONNECT PinConnect
,
780 IN ACCESS_MASK DesiredAccess
,
781 OUT PHANDLE PinHandle
)
784 SYSAUDIO_INSTANCE_INFO InstanceInfo
;
787 PPIN_CREATE_CONTEXT Context
= (PPIN_CREATE_CONTEXT
)Ctx
;
789 /* setup property request */
790 InstanceInfo
.Property
.Set
= KSPROPSETID_Sysaudio
;
791 InstanceInfo
.Property
.Id
= KSPROPERTY_SYSAUDIO_INSTANCE_INFO
;
792 InstanceInfo
.Property
.Flags
= KSPROPERTY_TYPE_SET
;
793 InstanceInfo
.Flags
= 0;
794 InstanceInfo
.DeviceNumber
= VirtualDeviceId
;
796 /* attach to virtual device */
797 Status
= KsSynchronousIoControlDevice(Context
->DeviceExtension
->FileObject
, KernelMode
, IOCTL_KS_PROPERTY
, (PVOID
)&InstanceInfo
, sizeof(SYSAUDIO_INSTANCE_INFO
), NULL
, 0, &BytesReturned
);
799 if (!NT_SUCCESS(Status
))
800 return MM_STATUS_UNSUCCESSFUL
;
802 /* close existing pin */
803 FreeIndex
= ClosePin(Context
->ClientInfo
, VirtualDeviceId
, PinId
, Context
->DeviceType
);
805 /* now create the pin */
806 Status
= KsCreatePin(Context
->DeviceExtension
->hSysAudio
, PinConnect
, DesiredAccess
, PinHandle
);
808 /* check for success */
809 if (!NT_SUCCESS(Status
))
810 return MM_STATUS_UNSUCCESSFUL
;
812 /* store the handle */
813 Status
= InsertPinHandle(Context
->ClientInfo
, VirtualDeviceId
, PinId
, Context
->DeviceType
, *PinHandle
, FreeIndex
);
814 if (!NT_SUCCESS(Status
))
816 /* failed to insert handle */
818 return MM_STATUS_UNSUCCESSFUL
;
821 return MM_STATUS_SUCCESS
;
825 WdmAudControlOpenWave(
826 IN PDEVICE_OBJECT DeviceObject
,
828 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
829 IN PWDMAUD_CLIENT ClientInfo
)
832 PIN_CREATE_CONTEXT Context
;
834 Context
.ClientInfo
= ClientInfo
;
835 Context
.DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
836 Context
.DeviceType
= DeviceInfo
->DeviceType
;
838 Status
= MMixerOpenWave(&MixerContext
, DeviceInfo
->DeviceIndex
, DeviceInfo
->DeviceType
== WAVE_IN_DEVICE_TYPE
, &DeviceInfo
->u
.WaveFormatEx
, CreatePinCallback
, &Context
, &DeviceInfo
->hDevice
);
840 if (Status
== MM_STATUS_SUCCESS
)
841 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
843 return SetIrpIoStatus(Irp
, STATUS_NOT_SUPPORTED
, sizeof(WDMAUD_DEVICE_INFO
));
847 WdmAudControlOpenMidi(
848 IN PDEVICE_OBJECT DeviceObject
,
850 IN PWDMAUD_DEVICE_INFO DeviceInfo
,
851 IN PWDMAUD_CLIENT ClientInfo
)
854 PIN_CREATE_CONTEXT Context
;
856 Context
.ClientInfo
= ClientInfo
;
857 Context
.DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
858 Context
.DeviceType
= DeviceInfo
->DeviceType
;
860 Status
= MMixerOpenMidi(&MixerContext
, DeviceInfo
->DeviceIndex
, DeviceInfo
->DeviceType
== MIDI_IN_DEVICE_TYPE
, CreatePinCallback
, &Context
, &DeviceInfo
->hDevice
);
862 if (Status
== MM_STATUS_SUCCESS
)
863 return SetIrpIoStatus(Irp
, STATUS_SUCCESS
, sizeof(WDMAUD_DEVICE_INFO
));
865 return SetIrpIoStatus(Irp
, STATUS_NOT_SUPPORTED
, sizeof(WDMAUD_DEVICE_INFO
));