[DRIVERS] Spelling fixes by Josh Soref. CORE-12286
[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 #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_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 NTAPI
476 WdmAudGetControlDetails(
477 IN PDEVICE_OBJECT DeviceObject,
478 IN PIRP Irp,
479 IN PWDMAUD_DEVICE_INFO DeviceInfo,
480 IN PWDMAUD_CLIENT ClientInfo)
481 {
482 MIXER_STATUS Status;
483
484 /* clear hmixer type flag */
485 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
486
487 /* query mmixer library */
488 Status = MMixerGetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixDetails);
489
490 if (Status == MM_STATUS_SUCCESS)
491 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
492 else
493 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
494 }
495
496 NTSTATUS
497 NTAPI
498 WdmAudGetLineInfo(
499 IN PDEVICE_OBJECT DeviceObject,
500 IN PIRP Irp,
501 IN PWDMAUD_DEVICE_INFO DeviceInfo,
502 IN PWDMAUD_CLIENT ClientInfo)
503 {
504 MIXER_STATUS Status;
505
506 /* clear hmixer type flag */
507 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
508
509 /* query mixer library */
510 Status = MMixerGetLineInfo(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixLine);
511
512 if (Status == MM_STATUS_SUCCESS)
513 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
514 else
515 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
516 }
517
518 NTSTATUS
519 NTAPI
520 WdmAudGetLineControls(
521 IN PDEVICE_OBJECT DeviceObject,
522 IN PIRP Irp,
523 IN PWDMAUD_DEVICE_INFO DeviceInfo,
524 IN PWDMAUD_CLIENT ClientInfo)
525 {
526 MIXER_STATUS Status;
527
528 /* clear hmixer type flag */
529 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
530
531 /* query mixer library */
532 Status = MMixerGetLineControls(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixControls);
533
534 if (Status == MM_STATUS_SUCCESS)
535 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
536 else
537 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
538
539
540 }
541
542 NTSTATUS
543 NTAPI
544 WdmAudSetControlDetails(
545 IN PDEVICE_OBJECT DeviceObject,
546 IN PIRP Irp,
547 IN PWDMAUD_DEVICE_INFO DeviceInfo,
548 IN PWDMAUD_CLIENT ClientInfo)
549 {
550 MIXER_STATUS Status;
551
552 /* clear hmixer type flag */
553 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
554
555 /* query mixer library */
556 Status = MMixerSetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixDetails);
557
558 if (Status == MM_STATUS_SUCCESS)
559 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
560 else
561 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
562 }
563
564 NTSTATUS
565 NTAPI
566 WdmAudGetMixerEvent(
567 IN PDEVICE_OBJECT DeviceObject,
568 IN PIRP Irp,
569 IN PWDMAUD_DEVICE_INFO DeviceInfo,
570 IN PWDMAUD_CLIENT ClientInfo)
571 {
572 PLIST_ENTRY Entry;
573 PEVENT_ENTRY EventEntry;
574
575 /* enumerate event list and check if there is a new event */
576 Entry = ClientInfo->MixerEventList.Flink;
577
578 while(Entry != &ClientInfo->MixerEventList)
579 {
580 /* grab event entry */
581 EventEntry = (PEVENT_ENTRY)CONTAINING_RECORD(Entry, EVENT_ENTRY, Entry);
582
583 if (EventEntry->hMixer == DeviceInfo->hDevice)
584 {
585 /* found an entry */
586 DeviceInfo->u.MixerEvent.hMixer = EventEntry->hMixer;
587 DeviceInfo->u.MixerEvent.NotificationType = EventEntry->NotificationType;
588 DeviceInfo->u.MixerEvent.Value = EventEntry->Value;
589
590 /* remove entry from list */
591 RemoveEntryList(&EventEntry->Entry);
592
593 /* free event entry */
594 FreeItem(EventEntry);
595
596 /* done */
597 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
598 }
599
600 /* move to next */
601 Entry = Entry->Flink;
602 }
603
604 /* no event entry available */
605 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
606 }
607
608 ULONG
609 WdmAudGetMixerDeviceCount()
610 {
611 return MMixerGetCount(&MixerContext);
612 }
613
614 ULONG
615 WdmAudGetWaveInDeviceCount()
616 {
617 return MMixerGetWaveInCount(&MixerContext);
618 }
619
620 ULONG
621 WdmAudGetWaveOutDeviceCount()
622 {
623 return MMixerGetWaveOutCount(&MixerContext);
624 }
625
626 ULONG
627 WdmAudGetMidiInDeviceCount()
628 {
629 return MMixerGetMidiInCount(&MixerContext);
630 }
631
632 ULONG
633 WdmAudGetMidiOutDeviceCount()
634 {
635 return MMixerGetWaveOutCount(&MixerContext);
636 }
637
638 NTSTATUS
639 WdmAudGetPnpNameByIndexAndType(
640 IN ULONG DeviceIndex,
641 IN SOUND_DEVICE_TYPE DeviceType,
642 OUT LPWSTR *DevicePath)
643 {
644 if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE)
645 {
646 if (MMixerGetWaveDevicePath(&MixerContext, DeviceType == WAVE_IN_DEVICE_TYPE, DeviceIndex, DevicePath) == MM_STATUS_SUCCESS)
647 return STATUS_SUCCESS;
648 else
649 return STATUS_UNSUCCESSFUL;
650 }
651 else if (DeviceType == MIDI_IN_DEVICE_TYPE || DeviceType == MIDI_OUT_DEVICE_TYPE)
652 {
653 if (MMixerGetMidiDevicePath(&MixerContext, DeviceType == MIDI_IN_DEVICE_TYPE, DeviceIndex, DevicePath) == MM_STATUS_SUCCESS)
654 return STATUS_SUCCESS;
655 else
656 return STATUS_UNSUCCESSFUL;
657 }
658 else if (DeviceType == MIXER_DEVICE_TYPE)
659 {
660 UNIMPLEMENTED;
661 }
662
663 return STATUS_UNSUCCESSFUL;
664 }
665
666 NTSTATUS
667 WdmAudWaveCapabilities(
668 IN PDEVICE_OBJECT DeviceObject,
669 IN PWDMAUD_DEVICE_INFO DeviceInfo,
670 IN PWDMAUD_CLIENT ClientInfo,
671 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension)
672 {
673 MIXER_STATUS Status = MM_STATUS_UNSUCCESSFUL;
674
675 if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
676 {
677 /* get capabilities */
678 Status = MMixerWaveInCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveInCaps);
679 }
680 else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
681 {
682 /* get capabilities */
683 Status = MMixerWaveOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveOutCaps);
684 }
685
686 if (Status == MM_STATUS_SUCCESS)
687 return STATUS_SUCCESS;
688 else
689 return Status;
690 }
691
692 NTSTATUS
693 WdmAudMidiCapabilities(
694 IN PDEVICE_OBJECT DeviceObject,
695 IN PWDMAUD_DEVICE_INFO DeviceInfo,
696 IN PWDMAUD_CLIENT ClientInfo,
697 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension)
698 {
699 MIXER_STATUS Status = MM_STATUS_UNSUCCESSFUL;
700
701 if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE)
702 {
703 /* get capabilities */
704 Status = MMixerMidiInCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MidiInCaps);
705 }
706 else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
707 {
708 /* get capabilities */
709 Status = MMixerMidiOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MidiOutCaps);
710 }
711
712 if (Status == MM_STATUS_SUCCESS)
713 return STATUS_SUCCESS;
714 else
715 return STATUS_UNSUCCESSFUL;
716 }
717
718
719 MIXER_STATUS
720 CreatePinCallback(
721 IN PVOID Ctx,
722 IN ULONG VirtualDeviceId,
723 IN ULONG PinId,
724 IN HANDLE hFilter,
725 IN PKSPIN_CONNECT PinConnect,
726 IN ACCESS_MASK DesiredAccess,
727 OUT PHANDLE PinHandle)
728 {
729 ULONG BytesReturned;
730 SYSAUDIO_INSTANCE_INFO InstanceInfo;
731 NTSTATUS Status;
732 ULONG FreeIndex;
733 PPIN_CREATE_CONTEXT Context = (PPIN_CREATE_CONTEXT)Ctx;
734
735 /* setup property request */
736 InstanceInfo.Property.Set = KSPROPSETID_Sysaudio;
737 InstanceInfo.Property.Id = KSPROPERTY_SYSAUDIO_INSTANCE_INFO;
738 InstanceInfo.Property.Flags = KSPROPERTY_TYPE_SET;
739 InstanceInfo.Flags = 0;
740 InstanceInfo.DeviceNumber = VirtualDeviceId;
741
742 /* attach to virtual device */
743 Status = KsSynchronousIoControlDevice(Context->DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&InstanceInfo, sizeof(SYSAUDIO_INSTANCE_INFO), NULL, 0, &BytesReturned);
744
745 if (!NT_SUCCESS(Status))
746 return MM_STATUS_UNSUCCESSFUL;
747
748 /* close existing pin */
749 FreeIndex = ClosePin(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType);
750
751 /* now create the pin */
752 Status = KsCreatePin(Context->DeviceExtension->hSysAudio, PinConnect, DesiredAccess, PinHandle);
753
754 /* check for success */
755 if (!NT_SUCCESS(Status))
756 return MM_STATUS_UNSUCCESSFUL;
757
758 /* store the handle */
759 Status = InsertPinHandle(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType, *PinHandle, FreeIndex);
760 if (!NT_SUCCESS(Status))
761 {
762 /* failed to insert handle */
763 ZwClose(*PinHandle);
764 return MM_STATUS_UNSUCCESSFUL;
765 }
766
767 return MM_STATUS_SUCCESS;
768 }
769
770 NTSTATUS
771 WdmAudControlOpenWave(
772 IN PDEVICE_OBJECT DeviceObject,
773 IN PIRP Irp,
774 IN PWDMAUD_DEVICE_INFO DeviceInfo,
775 IN PWDMAUD_CLIENT ClientInfo)
776 {
777 MIXER_STATUS Status;
778 PIN_CREATE_CONTEXT Context;
779
780 Context.ClientInfo = ClientInfo;
781 Context.DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
782 Context.DeviceType = DeviceInfo->DeviceType;
783
784 Status = MMixerOpenWave(&MixerContext, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE, &DeviceInfo->u.WaveFormatEx, CreatePinCallback, &Context, &DeviceInfo->hDevice);
785
786 if (Status == MM_STATUS_SUCCESS)
787 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
788 else
789 return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO));
790 }
791
792 NTSTATUS
793 WdmAudControlOpenMidi(
794 IN PDEVICE_OBJECT DeviceObject,
795 IN PIRP Irp,
796 IN PWDMAUD_DEVICE_INFO DeviceInfo,
797 IN PWDMAUD_CLIENT ClientInfo)
798 {
799 MIXER_STATUS Status;
800 PIN_CREATE_CONTEXT Context;
801
802 Context.ClientInfo = ClientInfo;
803 Context.DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
804 Context.DeviceType = DeviceInfo->DeviceType;
805
806 Status = MMixerOpenMidi(&MixerContext, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE, CreatePinCallback, &Context, &DeviceInfo->hDevice);
807
808 if (Status == MM_STATUS_SUCCESS)
809 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
810 else
811 return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO));
812 }