xref: /reactos/dll/win32/wdmaud.drv/legacy.c (revision 9046cc97)
1 /*
2  * PROJECT:     ReactOS Sound System
3  * LICENSE:     GPL - See COPYING in the top level directory
4  * FILE:        dll/win32/wdmaud.drv/wdmaud.c
5  *
6  * PURPOSE:     WDM Audio Driver (User-mode part)
7  * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
8                 Johannes Anderwald
9  *
10  * NOTES:       Looking for wodMessage & co? You won't find them here. Try
11  *              the MME Buddy library, which is where these routines are
12  *              actually implemented.
13  *
14  */
15 
16 #include "wdmaud.h"
17 
18 #define NDEBUG
19 #include <debug.h>
20 #include <mmebuddy_debug.h>
21 
22 #define KERNEL_DEVICE_NAME      L"\\\\.\\wdmaud"
23 
24 HANDLE KernelHandle = INVALID_HANDLE_VALUE;
25 DWORD OpenCount = 0;
26 
27 DWORD
28 WINAPI
MixerEventThreadRoutine(LPVOID Parameter)29 MixerEventThreadRoutine(
30     LPVOID Parameter)
31 {
32     HANDLE WaitObjects[2];
33     DWORD dwResult;
34     MMRESULT Result;
35     WDMAUD_DEVICE_INFO DeviceInfo;
36     PSOUND_DEVICE_INSTANCE Instance = (PSOUND_DEVICE_INSTANCE)Parameter;
37 
38     /* setup wait objects */
39     WaitObjects[0] = Instance->hNotifyEvent;
40     WaitObjects[1] = Instance->hStopEvent;
41 
42     /* zero device info */
43     ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
44 
45     DeviceInfo.hDevice = Instance->Handle;
46     DeviceInfo.DeviceType = MIXER_DEVICE_TYPE;
47 
48     do
49     {
50         dwResult = WaitForMultipleObjects(2, WaitObjects, FALSE, INFINITE);
51 
52         if (dwResult == WAIT_OBJECT_0 + 1)
53         {
54             /* stop event was signalled */
55             break;
56         }
57 
58         do
59         {
60             Result = SyncOverlappedDeviceIoControl(KernelHandle,
61                                                    IOCTL_GET_MIXER_EVENT,
62                                                    (LPVOID) &DeviceInfo,
63                                                    sizeof(WDMAUD_DEVICE_INFO),
64                                                    (LPVOID) &DeviceInfo,
65                                                    sizeof(WDMAUD_DEVICE_INFO),
66                                                    NULL);
67 
68             if (Result == MMSYSERR_NOERROR)
69             {
70                 DriverCallback(Instance->WinMM.ClientCallback,
71                                HIWORD(Instance->WinMM.Flags),
72                                Instance->WinMM.Handle,
73                                DeviceInfo.u.MixerEvent.NotificationType,
74                                Instance->WinMM.ClientCallbackInstanceData,
75                                (DWORD_PTR)DeviceInfo.u.MixerEvent.Value,
76                                0);
77             }
78         }while(Result == MMSYSERR_NOERROR);
79     }while(TRUE);
80 
81     /* done */
82     return 0;
83 }
84 
85 MMRESULT
WdmAudCleanupByLegacy()86 WdmAudCleanupByLegacy()
87 {
88     if (KernelHandle != INVALID_HANDLE_VALUE)
89     {
90         CloseHandle(KernelHandle);
91         KernelHandle = INVALID_HANDLE_VALUE;
92     }
93 
94     return MMSYSERR_NOERROR;
95 }
96 
97 MMRESULT
WdmAudGetNumWdmDevsByLegacy(IN MMDEVICE_TYPE DeviceType,OUT DWORD * DeviceCount)98 WdmAudGetNumWdmDevsByLegacy(
99     IN  MMDEVICE_TYPE DeviceType,
100     OUT DWORD* DeviceCount)
101 {
102     MMRESULT Result;
103     WDMAUD_DEVICE_INFO DeviceInfo;
104 
105     VALIDATE_MMSYS_PARAMETER( KernelHandle != INVALID_HANDLE_VALUE );
106     VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) );
107     VALIDATE_MMSYS_PARAMETER( DeviceCount );
108 
109     ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
110     DeviceInfo.DeviceType = DeviceType;
111 
112     Result = SyncOverlappedDeviceIoControl(KernelHandle,
113                                            IOCTL_GETNUMDEVS_TYPE,
114                                            (LPVOID) &DeviceInfo,
115                                            sizeof(WDMAUD_DEVICE_INFO),
116                                            (LPVOID) &DeviceInfo,
117                                            sizeof(WDMAUD_DEVICE_INFO),
118                                            NULL);
119 
120     if ( ! MMSUCCESS( Result ) )
121     {
122         SND_ERR(L"Call to IOCTL_GETNUMDEVS_TYPE failed\n");
123         *DeviceCount = 0;
124         return TranslateInternalMmResult(Result);
125     }
126 
127     *DeviceCount = DeviceInfo.DeviceCount;
128 
129     return MMSYSERR_NOERROR;
130 }
131 
132 MMRESULT
WdmAudGetCapabilitiesByLegacy(IN PSOUND_DEVICE SoundDevice,IN DWORD DeviceId,OUT PVOID Capabilities,IN DWORD CapabilitiesSize)133 WdmAudGetCapabilitiesByLegacy(
134     IN  PSOUND_DEVICE SoundDevice,
135     IN  DWORD DeviceId,
136     OUT PVOID Capabilities,
137     IN  DWORD CapabilitiesSize)
138 {
139     MMRESULT Result;
140     MMDEVICE_TYPE DeviceType;
141     WDMAUD_DEVICE_INFO DeviceInfo;
142 
143     SND_ASSERT( SoundDevice );
144     SND_ASSERT( Capabilities );
145 
146     Result = GetSoundDeviceType(SoundDevice, &DeviceType);
147     SND_ASSERT( Result == MMSYSERR_NOERROR );
148 
149     if ( ! MMSUCCESS(Result) )
150         return Result;
151 
152     SND_TRACE(L"WDMAUD - GetWdmDeviceCapabilities DeviceType %u DeviceId %u\n", DeviceType, DeviceId);
153 
154     ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
155     DeviceInfo.DeviceType = DeviceType;
156     DeviceInfo.DeviceIndex = DeviceId;
157 
158     Result = SyncOverlappedDeviceIoControl(KernelHandle,
159                                            IOCTL_GETCAPABILITIES,
160                                            (LPVOID) &DeviceInfo,
161                                            sizeof(WDMAUD_DEVICE_INFO),
162                                            (LPVOID) &DeviceInfo,
163                                            sizeof(WDMAUD_DEVICE_INFO),
164                                            NULL);
165 
166     if ( ! MMSUCCESS(Result) )
167     {
168         return TranslateInternalMmResult(Result);
169     }
170 
171     /* This is pretty much a big hack right now */
172     switch ( DeviceType )
173     {
174         case MIXER_DEVICE_TYPE:
175         {
176             LPMIXERCAPSW MixerCaps = (LPMIXERCAPSW) Capabilities;
177 
178             DeviceInfo.u.MixCaps.szPname[MAXPNAMELEN-1] = L'\0';
179             CopyWideString(MixerCaps->szPname, DeviceInfo.u.MixCaps.szPname);
180 
181             MixerCaps->cDestinations = DeviceInfo.u.MixCaps.cDestinations;
182             MixerCaps->fdwSupport = DeviceInfo.u.MixCaps.fdwSupport;
183             MixerCaps->vDriverVersion = DeviceInfo.u.MixCaps.vDriverVersion;
184             MixerCaps->wMid = DeviceInfo.u.MixCaps.wMid;
185             MixerCaps->wPid = DeviceInfo.u.MixCaps.wPid;
186             break;
187         }
188         case WAVE_OUT_DEVICE_TYPE :
189         {
190             LPWAVEOUTCAPSW WaveOutCaps = (LPWAVEOUTCAPSW) Capabilities;
191 
192             DeviceInfo.u.WaveOutCaps.szPname[MAXPNAMELEN-1] = L'\0';
193             WaveOutCaps->wMid = DeviceInfo.u.WaveOutCaps.wMid;
194             WaveOutCaps->wPid = DeviceInfo.u.WaveOutCaps.wPid;
195 
196             WaveOutCaps->vDriverVersion = DeviceInfo.u.WaveOutCaps.vDriverVersion;
197             CopyWideString(WaveOutCaps->szPname, DeviceInfo.u.WaveOutCaps.szPname);
198 
199             WaveOutCaps->dwFormats = DeviceInfo.u.WaveOutCaps.dwFormats;
200             WaveOutCaps->wChannels = DeviceInfo.u.WaveOutCaps.wChannels;
201             WaveOutCaps->dwSupport = DeviceInfo.u.WaveOutCaps.dwSupport;
202             break;
203         }
204         case WAVE_IN_DEVICE_TYPE :
205         {
206             LPWAVEINCAPSW WaveInCaps = (LPWAVEINCAPSW) Capabilities;
207 
208             DeviceInfo.u.WaveInCaps.szPname[MAXPNAMELEN-1] = L'\0';
209 
210             WaveInCaps->wMid = DeviceInfo.u.WaveInCaps.wMid;
211             WaveInCaps->wPid = DeviceInfo.u.WaveInCaps.wPid;
212 
213             WaveInCaps->vDriverVersion = DeviceInfo.u.WaveInCaps.vDriverVersion;
214             CopyWideString(WaveInCaps->szPname, DeviceInfo.u.WaveInCaps.szPname);
215 
216             WaveInCaps->dwFormats = DeviceInfo.u.WaveInCaps.dwFormats;
217             WaveInCaps->wChannels = DeviceInfo.u.WaveInCaps.wChannels;
218             WaveInCaps->wReserved1 = 0;
219             break;
220         }
221         case MIDI_IN_DEVICE_TYPE :
222         {
223             LPMIDIINCAPSW MidiInCaps = (LPMIDIINCAPSW)Capabilities;
224 
225             DeviceInfo.u.MidiInCaps.szPname[MAXPNAMELEN-1] = L'\0';
226 
227             MidiInCaps->vDriverVersion = DeviceInfo.u.MidiInCaps.vDriverVersion;
228             MidiInCaps->wMid = DeviceInfo.u.MidiInCaps.wMid;
229             MidiInCaps->wPid = DeviceInfo.u.MidiInCaps.wPid;
230             MidiInCaps->dwSupport = DeviceInfo.u.MidiInCaps.dwSupport;
231 
232             CopyWideString(MidiInCaps->szPname, DeviceInfo.u.MidiInCaps.szPname);
233             break;
234         }
235         case MIDI_OUT_DEVICE_TYPE :
236         {
237             LPMIDIOUTCAPSW MidiOutCaps = (LPMIDIOUTCAPSW)Capabilities;
238 
239             DeviceInfo.u.MidiOutCaps.szPname[MAXPNAMELEN-1] = L'\0';
240 
241             MidiOutCaps->vDriverVersion = DeviceInfo.u.MidiOutCaps.vDriverVersion;
242             MidiOutCaps->wMid = DeviceInfo.u.MidiOutCaps.wMid;
243             MidiOutCaps->wPid = DeviceInfo.u.MidiOutCaps.wPid;
244             MidiOutCaps->dwSupport = DeviceInfo.u.MidiOutCaps.dwSupport;
245 
246             CopyWideString(MidiOutCaps->szPname, DeviceInfo.u.MidiOutCaps.szPname);
247             break;
248         }
249     }
250 
251     return MMSYSERR_NOERROR;
252 }
253 
254 MMRESULT
WdmAudOpenSoundDeviceByLegacy(IN PSOUND_DEVICE SoundDevice,OUT PVOID * Handle)255 WdmAudOpenSoundDeviceByLegacy(
256     IN PSOUND_DEVICE SoundDevice,
257     OUT PVOID *Handle)
258 {
259     HDEVINFO hDevInfo;
260     SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
261     GUID SWBusGuid = {STATIC_KSCATEGORY_WDMAUD};
262     PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData;
263 
264     if ( KernelHandle == INVALID_HANDLE_VALUE )
265     {
266         hDevInfo = SetupDiGetClassDevsW(&SWBusGuid, NULL, NULL,  DIGCF_DEVICEINTERFACE| DIGCF_PRESENT);
267         if (!hDevInfo)
268         {
269             // failed
270             return MMSYSERR_ERROR;
271         }
272 
273         DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
274         if (!SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &SWBusGuid, 0, &DeviceInterfaceData))
275         {
276             // failed
277             SetupDiDestroyDeviceInfoList(hDevInfo);
278             return MMSYSERR_ERROR;
279         }
280 
281         DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W));
282         if (!DeviceInterfaceDetailData)
283         {
284             // failed
285             SetupDiDestroyDeviceInfoList(hDevInfo);
286             return MMSYSERR_ERROR;
287         }
288 
289         DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
290         if (!SetupDiGetDeviceInterfaceDetailW(hDevInfo,  &DeviceInterfaceData, DeviceInterfaceDetailData,MAX_PATH * sizeof(WCHAR) + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W), NULL, NULL))
291         {
292             // failed
293             HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
294             SetupDiDestroyDeviceInfoList(hDevInfo);
295             return MMSYSERR_ERROR;
296         }
297         SND_TRACE(L"Opening wdmaud device '%s'\n",DeviceInterfaceDetailData->DevicePath);
298         KernelHandle = CreateFileW(DeviceInterfaceDetailData->DevicePath,
299             GENERIC_READ | GENERIC_WRITE,
300             0,
301             NULL,
302             OPEN_EXISTING,
303             FILE_FLAG_OVERLAPPED,
304             NULL);
305 
306         HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
307         SetupDiDestroyDeviceInfoList(hDevInfo);
308     }
309 
310 
311     if ( KernelHandle == INVALID_HANDLE_VALUE )
312         return MMSYSERR_ERROR;
313 
314     ++ OpenCount;
315         return MMSYSERR_NOERROR;
316 
317 }
318 
319 MMRESULT
WdmAudCloseSoundDeviceByLegacy(IN struct _SOUND_DEVICE_INSTANCE * SoundDeviceInstance,IN PVOID Handle)320 WdmAudCloseSoundDeviceByLegacy(
321     IN  struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
322     IN  PVOID Handle)
323 {
324     WDMAUD_DEVICE_INFO DeviceInfo;
325     MMRESULT Result;
326     MMDEVICE_TYPE DeviceType;
327     PSOUND_DEVICE SoundDevice;
328 
329     Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
330 
331     if ( ! MMSUCCESS(Result) )
332     {
333         return TranslateInternalMmResult(Result);
334     }
335 
336     if ( OpenCount == 0 )
337     {
338         return MMSYSERR_NOERROR;
339     }
340 
341     SND_ASSERT( KernelHandle != INVALID_HANDLE_VALUE );
342 
343     Result = GetSoundDeviceType(SoundDevice, &DeviceType);
344     SND_ASSERT( Result == MMSYSERR_NOERROR );
345 
346     if (SoundDeviceInstance->Handle != (PVOID)KernelHandle)
347     {
348         ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
349 
350         DeviceInfo.DeviceType = DeviceType;
351         DeviceInfo.hDevice = SoundDeviceInstance->Handle;
352 
353          /* First stop the stream */
354          if (DeviceType != MIXER_DEVICE_TYPE)
355          {
356              DeviceInfo.u.State = KSSTATE_PAUSE;
357              SyncOverlappedDeviceIoControl(KernelHandle,
358                                            IOCTL_SETDEVICE_STATE,
359                                            (LPVOID) &DeviceInfo,
360                                            sizeof(WDMAUD_DEVICE_INFO),
361                                            (LPVOID) &DeviceInfo,
362                                             sizeof(WDMAUD_DEVICE_INFO),
363                                             NULL);
364 
365              DeviceInfo.u.State = KSSTATE_ACQUIRE;
366              SyncOverlappedDeviceIoControl(KernelHandle,
367                                            IOCTL_SETDEVICE_STATE,
368                                            (LPVOID) &DeviceInfo,
369                                            sizeof(WDMAUD_DEVICE_INFO),
370                                            (LPVOID) &DeviceInfo,
371                                             sizeof(WDMAUD_DEVICE_INFO),
372                                             NULL);
373 
374 
375              DeviceInfo.u.State = KSSTATE_STOP;
376              SyncOverlappedDeviceIoControl(KernelHandle,
377                                            IOCTL_SETDEVICE_STATE,
378                                            (LPVOID) &DeviceInfo,
379                                            sizeof(WDMAUD_DEVICE_INFO),
380                                            (LPVOID) &DeviceInfo,
381                                             sizeof(WDMAUD_DEVICE_INFO),
382                                             NULL);
383         }
384 
385         SyncOverlappedDeviceIoControl(KernelHandle,
386                                       IOCTL_CLOSE_WDMAUD,
387                                       (LPVOID) &DeviceInfo,
388                                       sizeof(WDMAUD_DEVICE_INFO),
389                                       (LPVOID) &DeviceInfo,
390                                       sizeof(WDMAUD_DEVICE_INFO),
391                                       NULL);
392     }
393 
394     if (DeviceType == MIXER_DEVICE_TYPE)
395     {
396         SetEvent(SoundDeviceInstance->hStopEvent);
397         CloseHandle(SoundDeviceInstance->hStopEvent);
398         CloseHandle(SoundDeviceInstance->hNotifyEvent);
399     }
400 
401     --OpenCount;
402 
403     if ( OpenCount < 1 )
404     {
405         CloseHandle(KernelHandle);
406         KernelHandle = INVALID_HANDLE_VALUE;
407     }
408 
409     return MMSYSERR_NOERROR;
410 }
411 
412 MMRESULT
WdmAudSetMixerDeviceFormatByLegacy(IN PSOUND_DEVICE_INSTANCE Instance,IN DWORD DeviceId,IN PWAVEFORMATEX WaveFormat,IN DWORD WaveFormatSize)413 WdmAudSetMixerDeviceFormatByLegacy(
414     IN  PSOUND_DEVICE_INSTANCE Instance,
415     IN  DWORD DeviceId,
416     IN  PWAVEFORMATEX WaveFormat,
417     IN  DWORD WaveFormatSize)
418 {
419     MMRESULT Result;
420     WDMAUD_DEVICE_INFO DeviceInfo;
421     HANDLE hThread;
422 
423     Instance->hNotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
424     if ( ! Instance->hNotifyEvent )
425         return MMSYSERR_NOMEM;
426 
427     if (Instance->Handle != NULL)
428     {
429         /* device is already open */
430         return MMSYSERR_NOERROR;
431     }
432 
433     Instance->hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
434     if ( ! Instance->hStopEvent )
435         return MMSYSERR_NOMEM;
436 
437     ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
438     DeviceInfo.DeviceType = MIXER_DEVICE_TYPE;
439     DeviceInfo.DeviceIndex = DeviceId;
440     DeviceInfo.u.hNotifyEvent = Instance->hNotifyEvent;
441 
442     Result = SyncOverlappedDeviceIoControl(KernelHandle,
443                                            IOCTL_OPEN_WDMAUD,
444                                            (LPVOID) &DeviceInfo,
445                                            sizeof(WDMAUD_DEVICE_INFO),
446                                            (LPVOID) &DeviceInfo,
447                                            sizeof(WDMAUD_DEVICE_INFO),
448                                            NULL);
449 
450     if ( ! MMSUCCESS(Result) )
451     {
452         CloseHandle(Instance->hNotifyEvent);
453         CloseHandle(Instance->hStopEvent);
454         return TranslateInternalMmResult(Result);
455     }
456 
457     hThread = CreateThread(NULL, 0, MixerEventThreadRoutine, (LPVOID)Instance, 0, NULL);
458     if (  hThread )
459     {
460         CloseHandle(hThread);
461     }
462 
463     /* Store sound device handle instance handle */
464     Instance->Handle = (PVOID)DeviceInfo.hDevice;
465 
466     return MMSYSERR_NOERROR;
467 }
468 
469 MMRESULT
WdmAudSetWaveDeviceFormatByLegacy(IN PSOUND_DEVICE_INSTANCE Instance,IN DWORD DeviceId,IN PWAVEFORMATEX WaveFormat,IN DWORD WaveFormatSize)470 WdmAudSetWaveDeviceFormatByLegacy(
471     IN  PSOUND_DEVICE_INSTANCE Instance,
472     IN  DWORD DeviceId,
473     IN  PWAVEFORMATEX WaveFormat,
474     IN  DWORD WaveFormatSize)
475 {
476     MMRESULT Result;
477     PSOUND_DEVICE SoundDevice;
478     PVOID Identifier;
479     WDMAUD_DEVICE_INFO DeviceInfo;
480     MMDEVICE_TYPE DeviceType;
481 
482     Result = GetSoundDeviceFromInstance(Instance, &SoundDevice);
483 
484     if ( ! MMSUCCESS(Result) )
485     {
486         return TranslateInternalMmResult(Result);
487     }
488 
489     Result = GetSoundDeviceIdentifier(SoundDevice, &Identifier);
490 
491     if ( ! MMSUCCESS(Result) )
492     {
493         return TranslateInternalMmResult(Result);
494     }
495 
496     if (Instance->Handle != NULL)
497     {
498         /* device is already open */
499         return MMSYSERR_NOERROR;
500     }
501 
502     Result = GetSoundDeviceType(SoundDevice, &DeviceType);
503 
504     SND_ASSERT( Result == MMSYSERR_NOERROR );
505 
506     ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
507     DeviceInfo.DeviceType = DeviceType;
508     DeviceInfo.DeviceIndex = DeviceId;
509     DeviceInfo.u.WaveFormatEx.cbSize = WaveFormat->cbSize;
510     DeviceInfo.u.WaveFormatEx.wFormatTag = WaveFormat->wFormatTag;
511 #ifdef USERMODE_MIXER
512     DeviceInfo.u.WaveFormatEx.nChannels = 2;
513     DeviceInfo.u.WaveFormatEx.nSamplesPerSec = 44100;
514     DeviceInfo.u.WaveFormatEx.nBlockAlign = 4;
515     DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = 176400;
516     DeviceInfo.u.WaveFormatEx.wBitsPerSample = 16;
517 #else
518     DeviceInfo.u.WaveFormatEx.nChannels = WaveFormat->nChannels;
519     DeviceInfo.u.WaveFormatEx.nSamplesPerSec = WaveFormat->nSamplesPerSec;
520     DeviceInfo.u.WaveFormatEx.nBlockAlign = WaveFormat->nBlockAlign;
521     DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = WaveFormat->nAvgBytesPerSec;
522     DeviceInfo.u.WaveFormatEx.wBitsPerSample = (DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec * 8) / (DeviceInfo.u.WaveFormatEx.nSamplesPerSec * DeviceInfo.u.WaveFormatEx.nChannels);
523 #endif
524 
525     Result = SyncOverlappedDeviceIoControl(KernelHandle,
526                                            IOCTL_OPEN_WDMAUD,
527                                            (LPVOID) &DeviceInfo,
528                                            sizeof(WDMAUD_DEVICE_INFO),
529                                            (LPVOID) &DeviceInfo,
530                                            sizeof(WDMAUD_DEVICE_INFO),
531                                            NULL);
532 
533     if ( ! MMSUCCESS(Result) )
534     {
535         return TranslateInternalMmResult(Result);
536     }
537 
538     if (WaveFormatSize >= sizeof(WAVEFORMAT))
539     {
540         /* Store format */
541         Instance->WaveFormatEx.wFormatTag = WaveFormat->wFormatTag;
542         Instance->WaveFormatEx.nChannels = WaveFormat->nChannels;
543         Instance->WaveFormatEx.nSamplesPerSec = WaveFormat->nSamplesPerSec;
544         Instance->WaveFormatEx.nBlockAlign = WaveFormat->nBlockAlign;
545         Instance->WaveFormatEx.nAvgBytesPerSec = WaveFormat->nAvgBytesPerSec;
546     }
547 
548     /* store details */
549     Instance->WaveFormatEx.cbSize = WaveFormat->cbSize;
550     Instance->WaveFormatEx.wBitsPerSample = (DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec * 8) / (DeviceInfo.u.WaveFormatEx.nSamplesPerSec * DeviceInfo.u.WaveFormatEx.nChannels);
551 
552     /* Store sound device handle instance handle */
553     Instance->Handle = (PVOID)DeviceInfo.hDevice;
554 
555     /* Now determine framing requirements */
556     Result = SyncOverlappedDeviceIoControl(KernelHandle,
557                                            IOCTL_GETFRAMESIZE,
558                                            (LPVOID) &DeviceInfo,
559                                            sizeof(WDMAUD_DEVICE_INFO),
560                                            (LPVOID) &DeviceInfo,
561                                            sizeof(WDMAUD_DEVICE_INFO),
562                                            NULL);
563 
564     if ( MMSUCCESS(Result) )
565     {
566         if (DeviceInfo.u.FrameSize)
567         {
568             Instance->FrameSize = DeviceInfo.u.FrameSize * 2;
569             Instance->BufferCount = WaveFormat->nAvgBytesPerSec / Instance->FrameSize;
570             SND_TRACE(L"FrameSize %u BufferCount %u\n", Instance->FrameSize, Instance->BufferCount);
571         }
572     }
573     else
574     {
575         // use a default of 100 buffers
576         Instance->BufferCount = 100;
577     }
578 
579     /* Now acquire resources */
580     DeviceInfo.u.State = KSSTATE_ACQUIRE;
581     SyncOverlappedDeviceIoControl(KernelHandle, IOCTL_SETDEVICE_STATE, (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), NULL);
582 
583     /* pause the pin */
584     DeviceInfo.u.State = KSSTATE_PAUSE;
585     SyncOverlappedDeviceIoControl(KernelHandle, IOCTL_SETDEVICE_STATE, (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), NULL);
586 
587     /* start the pin */
588     DeviceInfo.u.State = KSSTATE_RUN;
589     SyncOverlappedDeviceIoControl(KernelHandle, IOCTL_SETDEVICE_STATE, (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), NULL);
590 
591 
592     return MMSYSERR_NOERROR;
593 }
594 
595 VOID
596 CALLBACK
LegacyCompletionRoutine(IN DWORD dwErrorCode,IN DWORD dwNumberOfBytesTransferred,IN LPOVERLAPPED lpOverlapped)597 LegacyCompletionRoutine(
598     IN  DWORD dwErrorCode,
599     IN  DWORD dwNumberOfBytesTransferred,
600     IN  LPOVERLAPPED lpOverlapped)
601 {
602     PSOUND_OVERLAPPED Overlap;
603     PWDMAUD_DEVICE_INFO DeviceInfo;
604 
605     Overlap = (PSOUND_OVERLAPPED)lpOverlapped;
606     DeviceInfo = (PWDMAUD_DEVICE_INFO)Overlap->CompletionContext;
607 
608     /* Call mmebuddy overlap routine */
609     Overlap->OriginalCompletionRoutine(dwErrorCode, DeviceInfo->Header.DataUsed, lpOverlapped);
610 
611     HeapFree(GetProcessHeap(), 0, DeviceInfo);
612 }
613 
614 MMRESULT
WdmAudCommitWaveBufferByLegacy(IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,IN PVOID OffsetPtr,IN DWORD Length,IN PSOUND_OVERLAPPED Overlap,IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine)615 WdmAudCommitWaveBufferByLegacy(
616     IN  PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
617     IN  PVOID OffsetPtr,
618     IN  DWORD Length,
619     IN  PSOUND_OVERLAPPED Overlap,
620     IN  LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine)
621 {
622     HANDLE Handle;
623     MMRESULT Result;
624     PWDMAUD_DEVICE_INFO DeviceInfo;
625     PSOUND_DEVICE SoundDevice;
626     MMDEVICE_TYPE DeviceType;
627     BOOL Ret;
628 
629     VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance );
630     VALIDATE_MMSYS_PARAMETER( OffsetPtr );
631     VALIDATE_MMSYS_PARAMETER( Overlap );
632     VALIDATE_MMSYS_PARAMETER( CompletionRoutine );
633 
634     GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
635     SND_ASSERT(Handle);
636 
637     Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
638 
639     if ( ! MMSUCCESS(Result) )
640     {
641         return TranslateInternalMmResult(Result);
642     }
643 
644     Result = GetSoundDeviceType(SoundDevice, &DeviceType);
645     SND_ASSERT( Result == MMSYSERR_NOERROR );
646 
647     DeviceInfo = (PWDMAUD_DEVICE_INFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_INFO));
648     if (!DeviceInfo)
649     {
650         // no memory
651         return MMSYSERR_NOMEM;
652     }
653 
654     DeviceInfo->Header.FrameExtent = Length;
655     if (DeviceType == WAVE_OUT_DEVICE_TYPE)
656     {
657         DeviceInfo->Header.DataUsed = Length;
658     }
659     DeviceInfo->Header.Data = OffsetPtr;
660     DeviceInfo->Header.Size = sizeof(WDMAUD_DEVICE_INFO);
661     DeviceInfo->Header.PresentationTime.Numerator = 1;
662     DeviceInfo->Header.PresentationTime.Denominator = 1;
663     DeviceInfo->hDevice = Handle;
664     DeviceInfo->DeviceType = DeviceType;
665 
666 
667     // create completion event
668     Overlap->Standard.hEvent = Handle = CreateEventW(NULL, FALSE, FALSE, NULL);
669     if (Overlap->Standard.hEvent == NULL)
670     {
671         // no memory
672         HeapFree(GetProcessHeap(), 0, DeviceInfo);
673         return MMSYSERR_NOMEM;
674     }
675 
676     Overlap->OriginalCompletionRoutine = CompletionRoutine;
677     Overlap->CompletionContext = (PVOID)DeviceInfo;
678 
679     if (DeviceType == WAVE_OUT_DEVICE_TYPE)
680     {
681         Ret = WriteFileEx(KernelHandle, DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, LegacyCompletionRoutine);
682         if (Ret)
683             WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
684     }
685     else if (DeviceType == WAVE_IN_DEVICE_TYPE)
686     {
687         Ret = ReadFileEx(KernelHandle, DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, LegacyCompletionRoutine);
688         if (Ret)
689             WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
690     }
691 
692     // close event handle
693     CloseHandle(Handle);
694 
695     return MMSYSERR_NOERROR;
696 }
697 
698 MMRESULT
WdmAudSetWaveStateByLegacy(IN struct _SOUND_DEVICE_INSTANCE * SoundDeviceInstance,IN BOOL bStart)699 WdmAudSetWaveStateByLegacy(
700     IN  struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
701     IN BOOL bStart)
702 {
703     MMRESULT Result;
704     PSOUND_DEVICE SoundDevice;
705     WDMAUD_DEVICE_INFO DeviceInfo;
706     MMDEVICE_TYPE DeviceType;
707     HANDLE Handle;
708 
709     Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
710 
711     if ( ! MMSUCCESS(Result) )
712     {
713         return TranslateInternalMmResult(Result);
714     }
715 
716     Result = GetSoundDeviceType(SoundDevice, &DeviceType);
717     SND_ASSERT( Result == MMSYSERR_NOERROR );
718 
719     Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
720     SND_ASSERT( Result == MMSYSERR_NOERROR );
721 
722     ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
723     DeviceInfo.hDevice = Handle;
724     DeviceInfo.DeviceType = DeviceType;
725 
726     if (bStart)
727         DeviceInfo.u.State = KSSTATE_RUN;
728     else
729         DeviceInfo.u.State = KSSTATE_PAUSE;
730     Result = SyncOverlappedDeviceIoControl(KernelHandle,
731                                            IOCTL_SETDEVICE_STATE,
732                                            (LPVOID) &DeviceInfo,
733                                            sizeof(WDMAUD_DEVICE_INFO),
734                                            (LPVOID) &DeviceInfo,
735                                            sizeof(WDMAUD_DEVICE_INFO),
736                                            NULL);
737 
738     return Result;
739 }
740 
741 MMRESULT
WdmAudGetDeviceInterfaceStringByLegacy(IN MMDEVICE_TYPE DeviceType,IN DWORD DeviceId,IN LPWSTR Interface,IN DWORD InterfaceLength,OUT DWORD * InterfaceSize)742 WdmAudGetDeviceInterfaceStringByLegacy(
743     IN  MMDEVICE_TYPE DeviceType,
744     IN  DWORD DeviceId,
745     IN  LPWSTR Interface,
746     IN  DWORD  InterfaceLength,
747     OUT  DWORD * InterfaceSize)
748 {
749     WDMAUD_DEVICE_INFO DeviceInfo;
750     MMRESULT Result;
751 
752     ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
753     DeviceInfo.DeviceType = DeviceType;
754     DeviceInfo.DeviceIndex = DeviceId;
755 
756 
757     Result = SyncOverlappedDeviceIoControl(KernelHandle,
758                                            IOCTL_QUERYDEVICEINTERFACESTRING,
759                                            (LPVOID) &DeviceInfo,
760                                            sizeof(WDMAUD_DEVICE_INFO),
761                                            (LPVOID) &DeviceInfo,
762                                            sizeof(WDMAUD_DEVICE_INFO),
763                                            NULL);
764 
765 
766     if ( ! MMSUCCESS(Result) )
767     {
768         return TranslateInternalMmResult(Result);
769     }
770 
771 
772     if (!Interface)
773     {
774         SND_ASSERT(InterfaceSize);
775 
776         *InterfaceSize = DeviceInfo.u.Interface.DeviceInterfaceStringSize;
777         return MMSYSERR_NOERROR;
778     }
779 
780     if (InterfaceLength < DeviceInfo.u.Interface.DeviceInterfaceStringSize)
781     {
782         /* buffer is too small */
783         return MMSYSERR_MOREDATA;
784     }
785 
786     DeviceInfo.u.Interface.DeviceInterfaceStringSize = InterfaceLength;
787     DeviceInfo.u.Interface.DeviceInterfaceString = Interface;
788 
789     Result = SyncOverlappedDeviceIoControl(KernelHandle,
790                                            IOCTL_QUERYDEVICEINTERFACESTRING,
791                                            (LPVOID) &DeviceInfo,
792                                            sizeof(WDMAUD_DEVICE_INFO),
793                                            (LPVOID) &DeviceInfo,
794                                            sizeof(WDMAUD_DEVICE_INFO),
795                                            NULL);
796 
797     if (  MMSUCCESS(Result) && InterfaceLength > 2)
798     {
799         Interface[1] = L'\\';
800         Interface[InterfaceLength-1] = L'\0';
801     }
802 
803     return Result;
804 }
805 
806 MMRESULT
WdmAudGetWavePositionByLegacy(IN struct _SOUND_DEVICE_INSTANCE * SoundDeviceInstance,IN MMTIME * Time)807 WdmAudGetWavePositionByLegacy(
808     IN  struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
809     IN  MMTIME* Time)
810 {
811     MMRESULT Result;
812     PSOUND_DEVICE SoundDevice;
813     WDMAUD_DEVICE_INFO DeviceInfo;
814     MMDEVICE_TYPE DeviceType;
815     HANDLE Handle;
816 
817     Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
818 
819     if ( ! MMSUCCESS(Result) )
820     {
821         return TranslateInternalMmResult(Result);
822     }
823 
824     Result = GetSoundDeviceType(SoundDevice, &DeviceType);
825     SND_ASSERT( Result == MMSYSERR_NOERROR );
826 
827     Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
828     SND_ASSERT( Result == MMSYSERR_NOERROR );
829 
830     ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
831     DeviceInfo.hDevice = Handle;
832     DeviceInfo.DeviceType = DeviceType;
833 
834     Result = SyncOverlappedDeviceIoControl(KernelHandle,
835                                            IOCTL_GETPOS,
836                                            (LPVOID) &DeviceInfo,
837                                            sizeof(WDMAUD_DEVICE_INFO),
838                                            (LPVOID) &DeviceInfo,
839                                            sizeof(WDMAUD_DEVICE_INFO),
840                                            NULL);
841 
842     if ( ! MMSUCCESS(Result) )
843     {
844         return TranslateInternalMmResult(Result);
845     }
846 
847     Time->wType = TIME_BYTES;
848     Time->u.cb = (DWORD)DeviceInfo.u.Position;
849 
850     return MMSYSERR_NOERROR;
851 }
852 
853 MMRESULT
WdmAudGetVolumeByLegacy(_In_ PSOUND_DEVICE_INSTANCE SoundDeviceInstance,_In_ DWORD DeviceId,_Out_ PDWORD pdwVolume)854 WdmAudGetVolumeByLegacy(
855     _In_ PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
856     _In_ DWORD DeviceId,
857     _Out_ PDWORD pdwVolume)
858 {
859     /* FIXME */
860     return MMSYSERR_NOTSUPPORTED;
861 }
862 
863 MMRESULT
WdmAudSetVolumeByLegacy(_In_ PSOUND_DEVICE_INSTANCE SoundDeviceInstance,_In_ DWORD DeviceId,_In_ DWORD dwVolume)864 WdmAudSetVolumeByLegacy(
865     _In_ PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
866     _In_ DWORD DeviceId,
867     _In_ DWORD dwVolume)
868 {
869     /* FIXME */
870     return MMSYSERR_NOTSUPPORTED;
871 }
872 
873 MMRESULT
WdmAudResetStreamByLegacy(IN struct _SOUND_DEVICE_INSTANCE * SoundDeviceInstance,IN MMDEVICE_TYPE DeviceType,IN BOOLEAN bStartReset)874 WdmAudResetStreamByLegacy(
875     IN  struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
876     IN  MMDEVICE_TYPE DeviceType,
877     IN  BOOLEAN bStartReset)
878 {
879     MMRESULT Result;
880     HANDLE Handle;
881     WDMAUD_DEVICE_INFO DeviceInfo;
882 
883     Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
884     SND_ASSERT( Result == MMSYSERR_NOERROR );
885 
886     ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
887     DeviceInfo.hDevice = Handle;
888     DeviceInfo.DeviceType = DeviceType;
889     DeviceInfo.u.ResetStream = (bStartReset ? KSRESET_BEGIN : KSRESET_END);
890 
891     Result = SyncOverlappedDeviceIoControl(KernelHandle,
892                                            IOCTL_RESET_STREAM,
893                                            (LPVOID) &DeviceInfo,
894                                            sizeof(WDMAUD_DEVICE_INFO),
895                                            (LPVOID) &DeviceInfo,
896                                            sizeof(WDMAUD_DEVICE_INFO),
897                                            NULL);
898     return Result;
899 }
900 
901 MMRESULT
WdmAudQueryMixerInfoByLegacy(IN struct _SOUND_DEVICE_INSTANCE * SoundDeviceInstance,IN DWORD DeviceId,IN UINT uMsg,IN LPVOID Parameter,IN DWORD Flags)902 WdmAudQueryMixerInfoByLegacy(
903     IN  struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
904     IN DWORD DeviceId,
905     IN UINT uMsg,
906     IN LPVOID Parameter,
907     IN DWORD Flags)
908 {
909     MMRESULT Result;
910     WDMAUD_DEVICE_INFO DeviceInfo;
911     HANDLE Handle;
912     DWORD IoControlCode;
913     LPMIXERLINEW MixLine;
914     LPMIXERLINECONTROLSW MixControls;
915     LPMIXERCONTROLDETAILS MixDetails;
916 
917     SND_TRACE(L"uMsg %x Flags %x\n", uMsg, Flags);
918 
919     Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
920     SND_ASSERT( Result == MMSYSERR_NOERROR );
921 
922     ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
923     DeviceInfo.hDevice = Handle;
924     DeviceInfo.DeviceIndex = DeviceId;
925     DeviceInfo.DeviceType = MIXER_DEVICE_TYPE;
926     DeviceInfo.Flags = Flags;
927 
928     MixLine = (LPMIXERLINEW)Parameter;
929     MixControls = (LPMIXERLINECONTROLSW)Parameter;
930     MixDetails = (LPMIXERCONTROLDETAILS)Parameter;
931 
932     switch(uMsg)
933     {
934         case MXDM_GETLINEINFO:
935             RtlCopyMemory(&DeviceInfo.u.MixLine, MixLine, sizeof(MIXERLINEW));
936             IoControlCode = IOCTL_GETLINEINFO;
937             break;
938         case MXDM_GETLINECONTROLS:
939             RtlCopyMemory(&DeviceInfo.u.MixControls, MixControls, sizeof(MIXERLINECONTROLSW));
940             IoControlCode = IOCTL_GETLINECONTROLS;
941             break;
942        case MXDM_SETCONTROLDETAILS:
943             RtlCopyMemory(&DeviceInfo.u.MixDetails, MixDetails, sizeof(MIXERCONTROLDETAILS));
944             IoControlCode = IOCTL_SETCONTROLDETAILS;
945             break;
946        case MXDM_GETCONTROLDETAILS:
947             RtlCopyMemory(&DeviceInfo.u.MixDetails, MixDetails, sizeof(MIXERCONTROLDETAILS));
948             IoControlCode = IOCTL_GETCONTROLDETAILS;
949             break;
950        default:
951            SND_ASSERT(0);
952            return MMSYSERR_NOTSUPPORTED;
953     }
954 
955     Result = SyncOverlappedDeviceIoControl(KernelHandle,
956                                            IoControlCode,
957                                            (LPVOID) &DeviceInfo,
958                                            sizeof(WDMAUD_DEVICE_INFO),
959                                            (LPVOID) &DeviceInfo,
960                                            sizeof(WDMAUD_DEVICE_INFO),
961                                            NULL);
962 
963     if ( ! MMSUCCESS(Result) )
964     {
965         return Result;
966     }
967 
968     switch(uMsg)
969     {
970         case MXDM_GETLINEINFO:
971         {
972             RtlCopyMemory(MixLine, &DeviceInfo.u.MixLine, sizeof(MIXERLINEW));
973             break;
974         }
975     }
976 
977     return Result;
978 }
979