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