[WDMAUD_KERNEL]
[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
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 = ExAllocatePool(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 ExFreePool(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 = ExAllocatePool(NonPagedPool, PartialInformation->DataLength);
97 if (!*ResultBuffer)
98 {
99 /* not enough memory */
100 ExFreePool(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 ExFreePool(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 PVOID Mem = ExAllocatePool(NonPagedPool, NumBytes);
153 if (!Mem)
154 return Mem;
155
156 RtlZeroMemory(Mem, NumBytes);
157 return Mem;
158 }
159
160 MIXER_STATUS
161 Close(HANDLE hDevice)
162 {
163 if (ZwClose(hDevice) == STATUS_SUCCESS)
164 return MM_STATUS_SUCCESS;
165 else
166 return MM_STATUS_UNSUCCESSFUL;
167 }
168
169 VOID
170 Free(PVOID Block)
171 {
172 ExFreePool(Block);
173 }
174
175 VOID
176 Copy(PVOID Src, PVOID Dst, ULONG NumBytes)
177 {
178 RtlMoveMemory(Src, Dst, NumBytes);
179 }
180
181 MIXER_STATUS
182 Open(
183 IN LPWSTR DevicePath,
184 OUT PHANDLE hDevice)
185 {
186 if (WdmAudOpenSysAudioDevice(DevicePath, hDevice) == STATUS_SUCCESS)
187 return MM_STATUS_SUCCESS;
188 else
189 return MM_STATUS_UNSUCCESSFUL;
190 }
191
192 MIXER_STATUS
193 Control(
194 IN HANDLE hMixer,
195 IN ULONG dwIoControlCode,
196 IN PVOID lpInBuffer,
197 IN ULONG nInBufferSize,
198 OUT PVOID lpOutBuffer,
199 ULONG nOutBufferSize,
200 PULONG lpBytesReturned)
201 {
202 NTSTATUS Status;
203 PFILE_OBJECT FileObject;
204
205 /* get file object */
206 Status = ObReferenceObjectByHandle(hMixer, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
207 if (!NT_SUCCESS(Status))
208 {
209 DPRINT("failed to reference %p with %lx\n", hMixer, Status);
210 return MM_STATUS_UNSUCCESSFUL;
211 }
212
213 /* perform request */
214 Status = KsSynchronousIoControlDevice(FileObject, KernelMode, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned);
215
216 /* release object reference */
217 ObDereferenceObject(FileObject);
218
219 if (Status == STATUS_MORE_ENTRIES || Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
220 {
221 /* more data is available */
222 return MM_STATUS_MORE_ENTRIES;
223 }
224 else if (Status == STATUS_SUCCESS)
225 {
226 /* operation succeeded */
227 return MM_STATUS_SUCCESS;
228 }
229 else
230 {
231 DPRINT("Failed with %lx\n", Status);
232 return MM_STATUS_UNSUCCESSFUL;
233 }
234 }
235
236 MIXER_STATUS
237 Enum(
238 IN PVOID EnumContext,
239 IN ULONG DeviceIndex,
240 OUT LPWSTR * DeviceName,
241 OUT PHANDLE OutHandle,
242 OUT PHANDLE OutKey)
243 {
244 PDEVICE_OBJECT DeviceObject;
245 ULONG DeviceCount;
246 NTSTATUS Status;
247 UNICODE_STRING KeyName;
248
249 /* get enumeration context */
250 DeviceObject = (PDEVICE_OBJECT)EnumContext;
251
252 /* get device count */
253 DeviceCount = GetSysAudioDeviceCount(DeviceObject);
254
255 if (DeviceIndex >= DeviceCount)
256 {
257 /* no more devices */
258 return MM_STATUS_NO_MORE_DEVICES;
259 }
260
261 /* get device name */
262 Status = GetSysAudioDevicePnpName(DeviceObject, DeviceIndex, DeviceName);
263
264 if (!NT_SUCCESS(Status))
265 {
266 /* failed to retrieve device name */
267 return MM_STATUS_UNSUCCESSFUL;
268 }
269
270 /* intialize key name */
271 RtlInitUnicodeString(&KeyName, *DeviceName);
272
273 /* open device interface key */
274 Status = IoOpenDeviceInterfaceRegistryKey(&KeyName, GENERIC_READ | GENERIC_WRITE, OutKey);
275 #if 0
276 if (!NT_SUCCESS(Status))
277 {
278 /* failed to open key */
279 DPRINT("IoOpenDeviceInterfaceRegistryKey failed with %lx\n", Status);
280 ExFreePool(*DeviceName);
281 return MM_STATUS_UNSUCCESSFUL;
282 }
283 #endif
284
285 /* open device handle */
286 Status = OpenDevice(*DeviceName, OutHandle, NULL);
287 if (!NT_SUCCESS(Status))
288 {
289 /* failed to open device */
290 return MM_STATUS_UNSUCCESSFUL;
291 }
292
293 return MM_STATUS_SUCCESS;
294 }
295
296 PVOID
297 AllocEventData(
298 IN ULONG ExtraSize)
299 {
300 PKSEVENTDATA Data = (PKSEVENTDATA)ExAllocatePool(NonPagedPool, sizeof(KSEVENTDATA) + ExtraSize);
301 if (!Data)
302 return NULL;
303
304 Data->EventObject.Event = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
305 if (!Data->EventHandle.Event)
306 {
307 ExFreePool(Data);
308 return NULL;
309 }
310
311 KeInitializeEvent(Data->EventObject.Event, NotificationEvent, FALSE);
312
313 Data->NotificationType = KSEVENTF_EVENT_HANDLE;
314 return Data;
315 }
316
317 VOID
318 FreeEventData(IN PVOID EventData)
319 {
320 PKSEVENTDATA Data = (PKSEVENTDATA)EventData;
321
322 ExFreePool(Data->EventHandle.Event);
323 ExFreePool(Data);
324 }
325
326 NTSTATUS
327 WdmAudMixerInitialize(
328 IN PDEVICE_OBJECT DeviceObject)
329 {
330 MIXER_STATUS Status;
331
332 /* initialize the mixer library */
333 Status = MMixerInitialize(&MixerContext, Enum, (PVOID)DeviceObject);
334
335 if (Status != MM_STATUS_SUCCESS)
336 {
337 /* failed to initialize mmixer library */
338 DPRINT("MMixerInitialize failed with %lx\n", Status);
339 }
340
341 return Status;
342 }
343
344 NTSTATUS
345 WdmAudMixerCapabilities(
346 IN PDEVICE_OBJECT DeviceObject,
347 IN PWDMAUD_DEVICE_INFO DeviceInfo,
348 IN PWDMAUD_CLIENT ClientInfo,
349 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension)
350 {
351 if (MMixerGetCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MixCaps) == MM_STATUS_SUCCESS)
352 return STATUS_SUCCESS;
353
354 return STATUS_INVALID_PARAMETER;
355 }
356
357 NTSTATUS
358 WdmAudControlOpenMixer(
359 IN PDEVICE_OBJECT DeviceObject,
360 IN PIRP Irp,
361 IN PWDMAUD_DEVICE_INFO DeviceInfo,
362 IN PWDMAUD_CLIENT ClientInfo)
363 {
364 HANDLE hMixer;
365 PWDMAUD_HANDLE Handles;
366 PWDMAUD_DEVICE_EXTENSION DeviceExtension;
367 NTSTATUS Status;
368 PKEVENT EventObject = NULL;
369
370 DPRINT("WdmAudControlOpenMixer\n");
371
372 DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
373
374 if (DeviceInfo->u.hNotifyEvent)
375 {
376 Status = ObReferenceObjectByHandle(DeviceInfo->u.hNotifyEvent, EVENT_MODIFY_STATE, ExEventObjectType, UserMode, (LPVOID*)&EventObject, NULL);
377
378 if (!NT_SUCCESS(Status))
379 {
380 DPRINT1("Invalid notify event passed %p from client %p\n", DeviceInfo->u.hNotifyEvent, ClientInfo);
381 DbgBreakPoint();
382 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
383 }
384 }
385
386 if (MMixerOpen(&MixerContext, DeviceInfo->DeviceIndex, EventObject, NULL /* FIXME */, &hMixer) != MM_STATUS_SUCCESS)
387 {
388 ObDereferenceObject(EventObject);
389 DPRINT1("Failed to open mixer\n");
390 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
391 }
392
393
394 Handles = ExAllocatePool(NonPagedPool, sizeof(WDMAUD_HANDLE) * (ClientInfo->NumPins+1));
395
396 if (Handles)
397 {
398 if (ClientInfo->NumPins)
399 {
400 RtlMoveMemory(Handles, ClientInfo->hPins, sizeof(WDMAUD_HANDLE) * ClientInfo->NumPins);
401 ExFreePool(ClientInfo->hPins);
402 }
403
404 ClientInfo->hPins = Handles;
405 ClientInfo->hPins[ClientInfo->NumPins].Handle = hMixer;
406 ClientInfo->hPins[ClientInfo->NumPins].Type = MIXER_DEVICE_TYPE;
407 ClientInfo->hPins[ClientInfo->NumPins].NotifyEvent = EventObject;
408 ClientInfo->NumPins++;
409 }
410 else
411 {
412 ObDereferenceObject(EventObject);
413 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
414 }
415
416 DeviceInfo->hDevice = hMixer;
417
418 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
419 }
420
421 NTSTATUS
422 NTAPI
423 WdmAudGetControlDetails(
424 IN PDEVICE_OBJECT DeviceObject,
425 IN PIRP Irp,
426 IN PWDMAUD_DEVICE_INFO DeviceInfo,
427 IN PWDMAUD_CLIENT ClientInfo)
428 {
429 MIXER_STATUS Status;
430
431 /* clear hmixer type flag */
432 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
433
434 /* query mmixer library */
435 Status = MMixerGetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixDetails);
436
437 if (Status == MM_STATUS_SUCCESS)
438 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
439 else
440 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
441 }
442
443 NTSTATUS
444 NTAPI
445 WdmAudGetLineInfo(
446 IN PDEVICE_OBJECT DeviceObject,
447 IN PIRP Irp,
448 IN PWDMAUD_DEVICE_INFO DeviceInfo,
449 IN PWDMAUD_CLIENT ClientInfo)
450 {
451 MIXER_STATUS Status;
452
453 /* clear hmixer type flag */
454 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
455
456 /* query mixer library */
457 Status = MMixerGetLineInfo(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixLine);
458
459 if (Status == MM_STATUS_SUCCESS)
460 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
461 else
462 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
463 }
464
465 NTSTATUS
466 NTAPI
467 WdmAudGetLineControls(
468 IN PDEVICE_OBJECT DeviceObject,
469 IN PIRP Irp,
470 IN PWDMAUD_DEVICE_INFO DeviceInfo,
471 IN PWDMAUD_CLIENT ClientInfo)
472 {
473 MIXER_STATUS Status;
474
475 /* clear hmixer type flag */
476 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
477
478 /* query mixer library */
479 Status = MMixerGetLineControls(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixControls);
480
481 if (Status == MM_STATUS_SUCCESS)
482 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
483 else
484 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
485
486
487 }
488
489 NTSTATUS
490 NTAPI
491 WdmAudSetControlDetails(
492 IN PDEVICE_OBJECT DeviceObject,
493 IN PIRP Irp,
494 IN PWDMAUD_DEVICE_INFO DeviceInfo,
495 IN PWDMAUD_CLIENT ClientInfo)
496 {
497 MIXER_STATUS Status;
498
499 /* clear hmixer type flag */
500 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
501
502 /* query mixer library */
503 Status = MMixerSetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixDetails);
504
505 if (Status == MM_STATUS_SUCCESS)
506 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
507 else
508 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
509 }
510
511 NTSTATUS
512 NTAPI
513 WdmAudGetMixerEvent(
514 IN PDEVICE_OBJECT DeviceObject,
515 IN PIRP Irp,
516 IN PWDMAUD_DEVICE_INFO DeviceInfo,
517 IN PWDMAUD_CLIENT ClientInfo)
518 {
519 UNIMPLEMENTED
520 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
521 }
522
523 ULONG
524 WdmAudGetMixerDeviceCount()
525 {
526 return MMixerGetCount(&MixerContext);
527 }
528
529 ULONG
530 WdmAudGetWaveInDeviceCount()
531 {
532 return MMixerGetWaveInCount(&MixerContext);
533 }
534
535 ULONG
536 WdmAudGetWaveOutDeviceCount()
537 {
538 return MMixerGetWaveOutCount(&MixerContext);
539 }
540
541 NTSTATUS
542 WdmAudGetMixerPnpNameByIndex(
543 IN ULONG DeviceIndex,
544 OUT LPWSTR * Device)
545 {
546 UNIMPLEMENTED
547 return STATUS_NOT_IMPLEMENTED;
548 }
549
550 NTSTATUS
551 WdmAudGetPnpNameByIndexAndType(
552 IN ULONG DeviceIndex,
553 IN SOUND_DEVICE_TYPE DeviceType,
554 OUT LPWSTR *Device)
555 {
556 UNIMPLEMENTED
557 return STATUS_NOT_IMPLEMENTED;
558 }
559
560 NTSTATUS
561 WdmAudWaveCapabilities(
562 IN PDEVICE_OBJECT DeviceObject,
563 IN PWDMAUD_DEVICE_INFO DeviceInfo,
564 IN PWDMAUD_CLIENT ClientInfo,
565 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension)
566 {
567 MIXER_STATUS Status;
568
569 if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
570 {
571 /* get capabilities */
572 Status = MMixerWaveInCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveInCaps);
573 }
574 else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
575 {
576 /* get capabilities */
577 Status = MMixerWaveOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveOutCaps);
578 }
579 else
580 {
581 ASSERT(0);
582 return STATUS_UNSUCCESSFUL;
583 }
584
585 if (Status == MM_STATUS_SUCCESS)
586 return STATUS_SUCCESS;
587 else
588 return STATUS_UNSUCCESSFUL;
589 }
590
591
592 MIXER_STATUS
593 CreatePinCallback(
594 IN PVOID Ctx,
595 IN ULONG VirtualDeviceId,
596 IN ULONG PinId,
597 IN HANDLE hFilter,
598 IN PKSPIN_CONNECT PinConnect,
599 IN ACCESS_MASK DesiredAccess,
600 OUT PHANDLE PinHandle)
601 {
602 ULONG BytesReturned;
603 SYSAUDIO_INSTANCE_INFO InstanceInfo;
604 NTSTATUS Status;
605 ULONG FreeIndex;
606 PPIN_CREATE_CONTEXT Context = (PPIN_CREATE_CONTEXT)Ctx;
607
608 /* setup property request */
609 InstanceInfo.Property.Set = KSPROPSETID_Sysaudio;
610 InstanceInfo.Property.Id = KSPROPERTY_SYSAUDIO_INSTANCE_INFO;
611 InstanceInfo.Property.Flags = KSPROPERTY_TYPE_SET;
612 InstanceInfo.Flags = 0;
613 InstanceInfo.DeviceNumber = VirtualDeviceId;
614
615 /* attach to virtual device */
616 Status = KsSynchronousIoControlDevice(Context->DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&InstanceInfo, sizeof(SYSAUDIO_INSTANCE_INFO), NULL, 0, &BytesReturned);
617
618 if (!NT_SUCCESS(Status))
619 return MM_STATUS_UNSUCCESSFUL;
620
621 /* close existing pin */
622 FreeIndex = ClosePin(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType);
623
624 /* now create the pin */
625 Status = KsCreatePin(Context->DeviceExtension->hSysAudio, PinConnect, DesiredAccess, PinHandle);
626
627 /* check for success */
628 if (!NT_SUCCESS(Status))
629 return MM_STATUS_UNSUCCESSFUL;
630
631 /* store the handle */
632 Status = InsertPinHandle(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType, *PinHandle, FreeIndex);
633 if (!NT_SUCCESS(Status))
634 {
635 /* failed to insert handle */
636 ZwClose(*PinHandle);
637 return MM_STATUS_UNSUCCESSFUL;
638 }
639
640 return MM_STATUS_SUCCESS;
641 }
642
643 NTSTATUS
644 WdmAudControlOpenWave(
645 IN PDEVICE_OBJECT DeviceObject,
646 IN PIRP Irp,
647 IN PWDMAUD_DEVICE_INFO DeviceInfo,
648 IN PWDMAUD_CLIENT ClientInfo)
649 {
650 MIXER_STATUS Status;
651 PIN_CREATE_CONTEXT Context;
652
653 Context.ClientInfo = ClientInfo;
654 Context.DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
655 Context.DeviceType = DeviceInfo->DeviceType;
656
657 Status = MMixerOpenWave(&MixerContext, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE, &DeviceInfo->u.WaveFormatEx, CreatePinCallback, &Context, &DeviceInfo->hDevice);
658
659 if (Status == MM_STATUS_SUCCESS)
660 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
661 else
662 return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO));
663 }