fbc76389405a93ddd2048c48d88a66199463dc1e
[reactos.git] / drivers / wdm / audio / legacy / wdmaud / mmixer.c
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 EventCallback(
323 IN PVOID MixerEventContext,
324 IN HANDLE hMixer,
325 IN ULONG NotificationType,
326 IN ULONG Value)
327 {
328 PWDMAUD_CLIENT ClientInfo;
329 PEVENT_ENTRY Entry;
330 ULONG Index;
331
332 /* get client context */
333 ClientInfo = (PWDMAUD_CLIENT)MixerEventContext;
334
335 /* now search for the mixer which originated the request */
336 for(Index = 0; Index < ClientInfo->NumPins; Index++)
337 {
338 if (ClientInfo->hPins[Index].Handle == hMixer && ClientInfo->hPins[Index].Type == MIXER_DEVICE_TYPE)
339 {
340 if (ClientInfo->hPins[Index].NotifyEvent)
341 {
342 /* allocate event entry */
343 Entry = AllocateItem(NonPagedPool, sizeof(EVENT_ENTRY));
344 if (!Entry)
345 {
346 /* no memory */
347 break;
348 }
349
350 /* setup event entry */
351 Entry->NotificationType = NotificationType;
352 Entry->Value = Value;
353 Entry->hMixer = hMixer;
354
355 /* insert entry */
356 InsertTailList(&ClientInfo->MixerEventList, &Entry->Entry);
357
358 /* now notify the client */
359 KeSetEvent(ClientInfo->hPins[Index].NotifyEvent, 0, FALSE);
360 }
361 /* done */
362 break;
363 }
364 }
365 }
366
367
368 NTSTATUS
369 WdmAudMixerInitialize(
370 IN PDEVICE_OBJECT DeviceObject)
371 {
372 MIXER_STATUS Status;
373
374 /* initialize the mixer library */
375 Status = MMixerInitialize(&MixerContext, Enum, (PVOID)DeviceObject);
376
377 if (Status != MM_STATUS_SUCCESS)
378 {
379 /* failed to initialize mmixer library */
380 DPRINT("MMixerInitialize failed with %lx\n", Status);
381 }
382
383 return Status;
384 }
385
386 NTSTATUS
387 WdmAudMixerCapabilities(
388 IN PDEVICE_OBJECT DeviceObject,
389 IN PWDMAUD_DEVICE_INFO DeviceInfo,
390 IN PWDMAUD_CLIENT ClientInfo,
391 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension)
392 {
393 if (MMixerGetCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MixCaps) == MM_STATUS_SUCCESS)
394 return STATUS_SUCCESS;
395
396 return STATUS_INVALID_PARAMETER;
397 }
398
399 NTSTATUS
400 WdmAudControlOpenMixer(
401 IN PDEVICE_OBJECT DeviceObject,
402 IN PIRP Irp,
403 IN PWDMAUD_DEVICE_INFO DeviceInfo,
404 IN PWDMAUD_CLIENT ClientInfo)
405 {
406 HANDLE hMixer;
407 PWDMAUD_HANDLE Handles;
408 PWDMAUD_DEVICE_EXTENSION DeviceExtension;
409 NTSTATUS Status;
410 PKEVENT EventObject = NULL;
411
412 DPRINT("WdmAudControlOpenMixer\n");
413
414 DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
415
416 if (DeviceInfo->u.hNotifyEvent)
417 {
418 Status = ObReferenceObjectByHandle(DeviceInfo->u.hNotifyEvent, EVENT_MODIFY_STATE, ExEventObjectType, UserMode, (LPVOID*)&EventObject, NULL);
419
420 if (!NT_SUCCESS(Status))
421 {
422 DPRINT1("Invalid notify event passed %p from client %p\n", DeviceInfo->u.hNotifyEvent, ClientInfo);
423 DbgBreakPoint();
424 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
425 }
426 }
427
428 if (MMixerOpen(&MixerContext, DeviceInfo->DeviceIndex, ClientInfo, EventCallback, &hMixer) != MM_STATUS_SUCCESS)
429 {
430 ObDereferenceObject(EventObject);
431 DPRINT1("Failed to open mixer\n");
432 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
433 }
434
435
436 Handles = AllocateItem(NonPagedPool, sizeof(WDMAUD_HANDLE) * (ClientInfo->NumPins+1));
437
438 if (Handles)
439 {
440 if (ClientInfo->NumPins)
441 {
442 RtlMoveMemory(Handles, ClientInfo->hPins, sizeof(WDMAUD_HANDLE) * ClientInfo->NumPins);
443 FreeItem(ClientInfo->hPins);
444 }
445
446 ClientInfo->hPins = Handles;
447 ClientInfo->hPins[ClientInfo->NumPins].Handle = hMixer;
448 ClientInfo->hPins[ClientInfo->NumPins].Type = MIXER_DEVICE_TYPE;
449 ClientInfo->hPins[ClientInfo->NumPins].NotifyEvent = EventObject;
450 ClientInfo->NumPins++;
451 }
452 else
453 {
454 ObDereferenceObject(EventObject);
455 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
456 }
457
458 DeviceInfo->hDevice = hMixer;
459
460 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
461 }
462
463 NTSTATUS
464 NTAPI
465 WdmAudGetControlDetails(
466 IN PDEVICE_OBJECT DeviceObject,
467 IN PIRP Irp,
468 IN PWDMAUD_DEVICE_INFO DeviceInfo,
469 IN PWDMAUD_CLIENT ClientInfo)
470 {
471 MIXER_STATUS Status;
472
473 /* clear hmixer type flag */
474 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
475
476 /* query mmixer library */
477 Status = MMixerGetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixDetails);
478
479 if (Status == MM_STATUS_SUCCESS)
480 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
481 else
482 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
483 }
484
485 NTSTATUS
486 NTAPI
487 WdmAudGetLineInfo(
488 IN PDEVICE_OBJECT DeviceObject,
489 IN PIRP Irp,
490 IN PWDMAUD_DEVICE_INFO DeviceInfo,
491 IN PWDMAUD_CLIENT ClientInfo)
492 {
493 MIXER_STATUS Status;
494
495 /* clear hmixer type flag */
496 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
497
498 /* query mixer library */
499 Status = MMixerGetLineInfo(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixLine);
500
501 if (Status == MM_STATUS_SUCCESS)
502 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
503 else
504 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
505 }
506
507 NTSTATUS
508 NTAPI
509 WdmAudGetLineControls(
510 IN PDEVICE_OBJECT DeviceObject,
511 IN PIRP Irp,
512 IN PWDMAUD_DEVICE_INFO DeviceInfo,
513 IN PWDMAUD_CLIENT ClientInfo)
514 {
515 MIXER_STATUS Status;
516
517 /* clear hmixer type flag */
518 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
519
520 /* query mixer library */
521 Status = MMixerGetLineControls(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixControls);
522
523 if (Status == MM_STATUS_SUCCESS)
524 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
525 else
526 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
527
528
529 }
530
531 NTSTATUS
532 NTAPI
533 WdmAudSetControlDetails(
534 IN PDEVICE_OBJECT DeviceObject,
535 IN PIRP Irp,
536 IN PWDMAUD_DEVICE_INFO DeviceInfo,
537 IN PWDMAUD_CLIENT ClientInfo)
538 {
539 MIXER_STATUS Status;
540
541 /* clear hmixer type flag */
542 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
543
544 /* query mixer library */
545 Status = MMixerSetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixDetails);
546
547 if (Status == MM_STATUS_SUCCESS)
548 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
549 else
550 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
551 }
552
553 NTSTATUS
554 NTAPI
555 WdmAudGetMixerEvent(
556 IN PDEVICE_OBJECT DeviceObject,
557 IN PIRP Irp,
558 IN PWDMAUD_DEVICE_INFO DeviceInfo,
559 IN PWDMAUD_CLIENT ClientInfo)
560 {
561 PLIST_ENTRY Entry;
562 PEVENT_ENTRY EventEntry;
563
564 /* enumerate event list and check if there is a new event */
565 Entry = ClientInfo->MixerEventList.Flink;
566
567 while(Entry != &ClientInfo->MixerEventList)
568 {
569 /* grab event entry */
570 EventEntry = (PEVENT_ENTRY)CONTAINING_RECORD(Entry, EVENT_ENTRY, Entry);
571
572 if (EventEntry->hMixer == DeviceInfo->hDevice)
573 {
574 /* found an entry */
575 DeviceInfo->u.MixerEvent.hMixer = EventEntry->hMixer;
576 DeviceInfo->u.MixerEvent.NotificationType = EventEntry->NotificationType;
577 DeviceInfo->u.MixerEvent.Value = EventEntry->Value;
578
579 /* remove entry from list */
580 RemoveEntryList(&EventEntry->Entry);
581
582 /* free event entry */
583 FreeItem(EventEntry);
584
585 /* done */
586 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
587 }
588
589 /* move to next */
590 Entry = Entry->Flink;
591 }
592
593 /* no event entry available */
594 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
595 }
596
597 ULONG
598 WdmAudGetMixerDeviceCount()
599 {
600 return MMixerGetCount(&MixerContext);
601 }
602
603 ULONG
604 WdmAudGetWaveInDeviceCount()
605 {
606 return MMixerGetWaveInCount(&MixerContext);
607 }
608
609 ULONG
610 WdmAudGetWaveOutDeviceCount()
611 {
612 return MMixerGetWaveOutCount(&MixerContext);
613 }
614
615 ULONG
616 WdmAudGetMidiInDeviceCount()
617 {
618 return MMixerGetMidiInCount(&MixerContext);
619 }
620
621 ULONG
622 WdmAudGetMidiOutDeviceCount()
623 {
624 return MMixerGetWaveOutCount(&MixerContext);
625 }
626
627 NTSTATUS
628 WdmAudGetPnpNameByIndexAndType(
629 IN ULONG DeviceIndex,
630 IN SOUND_DEVICE_TYPE DeviceType,
631 OUT LPWSTR *DevicePath)
632 {
633 if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE)
634 {
635 if (MMixerGetWaveDevicePath(&MixerContext, DeviceType == WAVE_IN_DEVICE_TYPE, DeviceIndex, DevicePath) == MM_STATUS_SUCCESS)
636 return STATUS_SUCCESS;
637 else
638 return STATUS_UNSUCCESSFUL;
639 }
640 else if (DeviceType == MIDI_IN_DEVICE_TYPE || DeviceType == MIDI_OUT_DEVICE_TYPE)
641 {
642 if (MMixerGetMidiDevicePath(&MixerContext, DeviceType == MIDI_IN_DEVICE_TYPE, DeviceIndex, DevicePath) == MM_STATUS_SUCCESS)
643 return STATUS_SUCCESS;
644 else
645 return STATUS_UNSUCCESSFUL;
646 }
647 else if (DeviceType == MIXER_DEVICE_TYPE)
648 {
649 UNIMPLEMENTED;
650 }
651
652 return STATUS_UNSUCCESSFUL;
653 }
654
655 NTSTATUS
656 WdmAudWaveCapabilities(
657 IN PDEVICE_OBJECT DeviceObject,
658 IN PWDMAUD_DEVICE_INFO DeviceInfo,
659 IN PWDMAUD_CLIENT ClientInfo,
660 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension)
661 {
662 MIXER_STATUS Status = MM_STATUS_UNSUCCESSFUL;
663
664 if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
665 {
666 /* get capabilities */
667 Status = MMixerWaveInCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveInCaps);
668 }
669 else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
670 {
671 /* get capabilities */
672 Status = MMixerWaveOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveOutCaps);
673 }
674
675 if (Status == MM_STATUS_SUCCESS)
676 return STATUS_SUCCESS;
677 else
678 return Status;
679 }
680
681 NTSTATUS
682 WdmAudMidiCapabilities(
683 IN PDEVICE_OBJECT DeviceObject,
684 IN PWDMAUD_DEVICE_INFO DeviceInfo,
685 IN PWDMAUD_CLIENT ClientInfo,
686 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension)
687 {
688 MIXER_STATUS Status = MM_STATUS_UNSUCCESSFUL;
689
690 if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE)
691 {
692 /* get capabilities */
693 Status = MMixerMidiInCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MidiInCaps);
694 }
695 else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
696 {
697 /* get capabilities */
698 Status = MMixerMidiOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MidiOutCaps);
699 }
700
701 if (Status == MM_STATUS_SUCCESS)
702 return STATUS_SUCCESS;
703 else
704 return STATUS_UNSUCCESSFUL;
705 }
706
707
708 MIXER_STATUS
709 CreatePinCallback(
710 IN PVOID Ctx,
711 IN ULONG VirtualDeviceId,
712 IN ULONG PinId,
713 IN HANDLE hFilter,
714 IN PKSPIN_CONNECT PinConnect,
715 IN ACCESS_MASK DesiredAccess,
716 OUT PHANDLE PinHandle)
717 {
718 ULONG BytesReturned;
719 SYSAUDIO_INSTANCE_INFO InstanceInfo;
720 NTSTATUS Status;
721 ULONG FreeIndex;
722 PPIN_CREATE_CONTEXT Context = (PPIN_CREATE_CONTEXT)Ctx;
723
724 /* setup property request */
725 InstanceInfo.Property.Set = KSPROPSETID_Sysaudio;
726 InstanceInfo.Property.Id = KSPROPERTY_SYSAUDIO_INSTANCE_INFO;
727 InstanceInfo.Property.Flags = KSPROPERTY_TYPE_SET;
728 InstanceInfo.Flags = 0;
729 InstanceInfo.DeviceNumber = VirtualDeviceId;
730
731 /* attach to virtual device */
732 Status = KsSynchronousIoControlDevice(Context->DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&InstanceInfo, sizeof(SYSAUDIO_INSTANCE_INFO), NULL, 0, &BytesReturned);
733
734 if (!NT_SUCCESS(Status))
735 return MM_STATUS_UNSUCCESSFUL;
736
737 /* close existing pin */
738 FreeIndex = ClosePin(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType);
739
740 /* now create the pin */
741 Status = KsCreatePin(Context->DeviceExtension->hSysAudio, PinConnect, DesiredAccess, PinHandle);
742
743 /* check for success */
744 if (!NT_SUCCESS(Status))
745 return MM_STATUS_UNSUCCESSFUL;
746
747 /* store the handle */
748 Status = InsertPinHandle(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType, *PinHandle, FreeIndex);
749 if (!NT_SUCCESS(Status))
750 {
751 /* failed to insert handle */
752 ZwClose(*PinHandle);
753 return MM_STATUS_UNSUCCESSFUL;
754 }
755
756 return MM_STATUS_SUCCESS;
757 }
758
759 NTSTATUS
760 WdmAudControlOpenWave(
761 IN PDEVICE_OBJECT DeviceObject,
762 IN PIRP Irp,
763 IN PWDMAUD_DEVICE_INFO DeviceInfo,
764 IN PWDMAUD_CLIENT ClientInfo)
765 {
766 MIXER_STATUS Status;
767 PIN_CREATE_CONTEXT Context;
768
769 Context.ClientInfo = ClientInfo;
770 Context.DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
771 Context.DeviceType = DeviceInfo->DeviceType;
772
773 Status = MMixerOpenWave(&MixerContext, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE, &DeviceInfo->u.WaveFormatEx, CreatePinCallback, &Context, &DeviceInfo->hDevice);
774
775 if (Status == MM_STATUS_SUCCESS)
776 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
777 else
778 return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO));
779 }
780
781 NTSTATUS
782 WdmAudControlOpenMidi(
783 IN PDEVICE_OBJECT DeviceObject,
784 IN PIRP Irp,
785 IN PWDMAUD_DEVICE_INFO DeviceInfo,
786 IN PWDMAUD_CLIENT ClientInfo)
787 {
788 MIXER_STATUS Status;
789 PIN_CREATE_CONTEXT Context;
790
791 Context.ClientInfo = ClientInfo;
792 Context.DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
793 Context.DeviceType = DeviceInfo->DeviceType;
794
795 Status = MMixerOpenMidi(&MixerContext, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE, CreatePinCallback, &Context, &DeviceInfo->hDevice);
796
797 if (Status == MM_STATUS_SUCCESS)
798 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
799 else
800 return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO));
801 }
802