Sync with trunk (r48123)
[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 NTSTATUS
322 WdmAudMixerInitialize(
323 IN PDEVICE_OBJECT DeviceObject)
324 {
325 MIXER_STATUS Status;
326
327 /* initialize the mixer library */
328 Status = MMixerInitialize(&MixerContext, Enum, (PVOID)DeviceObject);
329
330 if (Status != MM_STATUS_SUCCESS)
331 {
332 /* failed to initialize mmixer library */
333 DPRINT("MMixerInitialize failed with %lx\n", Status);
334 }
335
336 return Status;
337 }
338
339 NTSTATUS
340 WdmAudMixerCapabilities(
341 IN PDEVICE_OBJECT DeviceObject,
342 IN PWDMAUD_DEVICE_INFO DeviceInfo,
343 IN PWDMAUD_CLIENT ClientInfo,
344 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension)
345 {
346 if (MMixerGetCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MixCaps) == MM_STATUS_SUCCESS)
347 return STATUS_SUCCESS;
348
349 return STATUS_INVALID_PARAMETER;
350 }
351
352 NTSTATUS
353 WdmAudControlOpenMixer(
354 IN PDEVICE_OBJECT DeviceObject,
355 IN PIRP Irp,
356 IN PWDMAUD_DEVICE_INFO DeviceInfo,
357 IN PWDMAUD_CLIENT ClientInfo)
358 {
359 HANDLE hMixer;
360 PWDMAUD_HANDLE Handles;
361 PWDMAUD_DEVICE_EXTENSION DeviceExtension;
362 NTSTATUS Status;
363 PKEVENT EventObject = NULL;
364
365 DPRINT("WdmAudControlOpenMixer\n");
366
367 DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
368
369 if (DeviceInfo->u.hNotifyEvent)
370 {
371 Status = ObReferenceObjectByHandle(DeviceInfo->u.hNotifyEvent, EVENT_MODIFY_STATE, ExEventObjectType, UserMode, (LPVOID*)&EventObject, NULL);
372
373 if (!NT_SUCCESS(Status))
374 {
375 DPRINT1("Invalid notify event passed %p from client %p\n", DeviceInfo->u.hNotifyEvent, ClientInfo);
376 DbgBreakPoint();
377 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
378 }
379 }
380
381 if (MMixerOpen(&MixerContext, DeviceInfo->DeviceIndex, EventObject, NULL /* FIXME */, &hMixer) != MM_STATUS_SUCCESS)
382 {
383 ObDereferenceObject(EventObject);
384 DPRINT1("Failed to open mixer\n");
385 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
386 }
387
388
389 Handles = AllocateItem(NonPagedPool, sizeof(WDMAUD_HANDLE) * (ClientInfo->NumPins+1));
390
391 if (Handles)
392 {
393 if (ClientInfo->NumPins)
394 {
395 RtlMoveMemory(Handles, ClientInfo->hPins, sizeof(WDMAUD_HANDLE) * ClientInfo->NumPins);
396 FreeItem(ClientInfo->hPins);
397 }
398
399 ClientInfo->hPins = Handles;
400 ClientInfo->hPins[ClientInfo->NumPins].Handle = hMixer;
401 ClientInfo->hPins[ClientInfo->NumPins].Type = MIXER_DEVICE_TYPE;
402 ClientInfo->hPins[ClientInfo->NumPins].NotifyEvent = EventObject;
403 ClientInfo->NumPins++;
404 }
405 else
406 {
407 ObDereferenceObject(EventObject);
408 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
409 }
410
411 DeviceInfo->hDevice = hMixer;
412
413 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
414 }
415
416 NTSTATUS
417 NTAPI
418 WdmAudGetControlDetails(
419 IN PDEVICE_OBJECT DeviceObject,
420 IN PIRP Irp,
421 IN PWDMAUD_DEVICE_INFO DeviceInfo,
422 IN PWDMAUD_CLIENT ClientInfo)
423 {
424 MIXER_STATUS Status;
425
426 /* clear hmixer type flag */
427 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
428
429 /* query mmixer library */
430 Status = MMixerGetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixDetails);
431
432 if (Status == MM_STATUS_SUCCESS)
433 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
434 else
435 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
436 }
437
438 NTSTATUS
439 NTAPI
440 WdmAudGetLineInfo(
441 IN PDEVICE_OBJECT DeviceObject,
442 IN PIRP Irp,
443 IN PWDMAUD_DEVICE_INFO DeviceInfo,
444 IN PWDMAUD_CLIENT ClientInfo)
445 {
446 MIXER_STATUS Status;
447
448 /* clear hmixer type flag */
449 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
450
451 /* query mixer library */
452 Status = MMixerGetLineInfo(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixLine);
453
454 if (Status == MM_STATUS_SUCCESS)
455 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
456 else
457 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
458 }
459
460 NTSTATUS
461 NTAPI
462 WdmAudGetLineControls(
463 IN PDEVICE_OBJECT DeviceObject,
464 IN PIRP Irp,
465 IN PWDMAUD_DEVICE_INFO DeviceInfo,
466 IN PWDMAUD_CLIENT ClientInfo)
467 {
468 MIXER_STATUS Status;
469
470 /* clear hmixer type flag */
471 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
472
473 /* query mixer library */
474 Status = MMixerGetLineControls(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixControls);
475
476 if (Status == MM_STATUS_SUCCESS)
477 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
478 else
479 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
480
481
482 }
483
484 NTSTATUS
485 NTAPI
486 WdmAudSetControlDetails(
487 IN PDEVICE_OBJECT DeviceObject,
488 IN PIRP Irp,
489 IN PWDMAUD_DEVICE_INFO DeviceInfo,
490 IN PWDMAUD_CLIENT ClientInfo)
491 {
492 MIXER_STATUS Status;
493
494 /* clear hmixer type flag */
495 DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
496
497 /* query mixer library */
498 Status = MMixerSetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixDetails);
499
500 if (Status == MM_STATUS_SUCCESS)
501 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
502 else
503 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
504 }
505
506 NTSTATUS
507 NTAPI
508 WdmAudGetMixerEvent(
509 IN PDEVICE_OBJECT DeviceObject,
510 IN PIRP Irp,
511 IN PWDMAUD_DEVICE_INFO DeviceInfo,
512 IN PWDMAUD_CLIENT ClientInfo)
513 {
514 UNIMPLEMENTED
515 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO));
516 }
517
518 ULONG
519 WdmAudGetMixerDeviceCount()
520 {
521 return MMixerGetCount(&MixerContext);
522 }
523
524 ULONG
525 WdmAudGetWaveInDeviceCount()
526 {
527 return MMixerGetWaveInCount(&MixerContext);
528 }
529
530 ULONG
531 WdmAudGetWaveOutDeviceCount()
532 {
533 return MMixerGetWaveOutCount(&MixerContext);
534 }
535
536 NTSTATUS
537 WdmAudGetMixerPnpNameByIndex(
538 IN ULONG DeviceIndex,
539 OUT LPWSTR * Device)
540 {
541 UNIMPLEMENTED
542 return STATUS_NOT_IMPLEMENTED;
543 }
544
545 NTSTATUS
546 WdmAudGetPnpNameByIndexAndType(
547 IN ULONG DeviceIndex,
548 IN SOUND_DEVICE_TYPE DeviceType,
549 OUT LPWSTR *DevicePath)
550 {
551 if (MMixerGetWaveDevicePath(&MixerContext, DeviceType == WAVE_IN_DEVICE_TYPE, DeviceIndex, DevicePath) == MM_STATUS_SUCCESS)
552 return STATUS_SUCCESS;
553 else
554 return STATUS_UNSUCCESSFUL;
555 }
556
557 NTSTATUS
558 WdmAudWaveCapabilities(
559 IN PDEVICE_OBJECT DeviceObject,
560 IN PWDMAUD_DEVICE_INFO DeviceInfo,
561 IN PWDMAUD_CLIENT ClientInfo,
562 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension)
563 {
564 MIXER_STATUS Status;
565
566 if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE)
567 {
568 /* get capabilities */
569 Status = MMixerWaveInCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveInCaps);
570 }
571 else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE)
572 {
573 /* get capabilities */
574 Status = MMixerWaveOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveOutCaps);
575 }
576 else
577 {
578 ASSERT(0);
579 return STATUS_UNSUCCESSFUL;
580 }
581
582 if (Status == MM_STATUS_SUCCESS)
583 return STATUS_SUCCESS;
584 else
585 return STATUS_UNSUCCESSFUL;
586 }
587
588
589 MIXER_STATUS
590 CreatePinCallback(
591 IN PVOID Ctx,
592 IN ULONG VirtualDeviceId,
593 IN ULONG PinId,
594 IN HANDLE hFilter,
595 IN PKSPIN_CONNECT PinConnect,
596 IN ACCESS_MASK DesiredAccess,
597 OUT PHANDLE PinHandle)
598 {
599 ULONG BytesReturned;
600 SYSAUDIO_INSTANCE_INFO InstanceInfo;
601 NTSTATUS Status;
602 ULONG FreeIndex;
603 PPIN_CREATE_CONTEXT Context = (PPIN_CREATE_CONTEXT)Ctx;
604
605 /* setup property request */
606 InstanceInfo.Property.Set = KSPROPSETID_Sysaudio;
607 InstanceInfo.Property.Id = KSPROPERTY_SYSAUDIO_INSTANCE_INFO;
608 InstanceInfo.Property.Flags = KSPROPERTY_TYPE_SET;
609 InstanceInfo.Flags = 0;
610 InstanceInfo.DeviceNumber = VirtualDeviceId;
611
612 /* attach to virtual device */
613 Status = KsSynchronousIoControlDevice(Context->DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&InstanceInfo, sizeof(SYSAUDIO_INSTANCE_INFO), NULL, 0, &BytesReturned);
614
615 if (!NT_SUCCESS(Status))
616 return MM_STATUS_UNSUCCESSFUL;
617
618 /* close existing pin */
619 FreeIndex = ClosePin(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType);
620
621 /* now create the pin */
622 Status = KsCreatePin(Context->DeviceExtension->hSysAudio, PinConnect, DesiredAccess, PinHandle);
623
624 /* check for success */
625 if (!NT_SUCCESS(Status))
626 return MM_STATUS_UNSUCCESSFUL;
627
628 /* store the handle */
629 Status = InsertPinHandle(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType, *PinHandle, FreeIndex);
630 if (!NT_SUCCESS(Status))
631 {
632 /* failed to insert handle */
633 ZwClose(*PinHandle);
634 return MM_STATUS_UNSUCCESSFUL;
635 }
636
637 return MM_STATUS_SUCCESS;
638 }
639
640 NTSTATUS
641 WdmAudControlOpenWave(
642 IN PDEVICE_OBJECT DeviceObject,
643 IN PIRP Irp,
644 IN PWDMAUD_DEVICE_INFO DeviceInfo,
645 IN PWDMAUD_CLIENT ClientInfo)
646 {
647 MIXER_STATUS Status;
648 PIN_CREATE_CONTEXT Context;
649
650 Context.ClientInfo = ClientInfo;
651 Context.DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
652 Context.DeviceType = DeviceInfo->DeviceType;
653
654 Status = MMixerOpenWave(&MixerContext, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE, &DeviceInfo->u.WaveFormatEx, CreatePinCallback, &Context, &DeviceInfo->hDevice);
655
656 if (Status == MM_STATUS_SUCCESS)
657 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
658 else
659 return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO));
660 }