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