sync with trunk r46493
[reactos.git] / 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 LPMIXERCAPS MixerCaps = (LPMIXERCAPS) 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 LPWAVEOUTCAPS WaveOutCaps = (LPWAVEOUTCAPS) 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 = 0x0001;
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 = 0x0001;
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 }
220
221 return MMSYSERR_NOERROR;
222 }
223
224 MMRESULT
225 WdmAudOpenSoundDeviceByLegacy()
226 {
227 /* Only open this if it's not already open */
228 if ( KernelHandle == INVALID_HANDLE_VALUE )
229 {
230 SND_TRACE(L"Opening wdmaud device\n");
231 KernelHandle = CreateFileW(KERNEL_DEVICE_NAME,
232 GENERIC_READ | GENERIC_WRITE,
233 0,
234 NULL,
235 OPEN_EXISTING,
236 FILE_FLAG_OVERLAPPED,
237 NULL);
238 }
239
240 if ( KernelHandle == INVALID_HANDLE_VALUE )
241 return MMSYSERR_ERROR;
242
243 ++ OpenCount;
244
245 return MMSYSERR_NOERROR;
246 }
247
248 MMRESULT
249 WdmAudCloseSoundDeviceByLegacy(
250 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
251 IN PVOID Handle)
252 {
253 WDMAUD_DEVICE_INFO DeviceInfo;
254 MMRESULT Result;
255 MMDEVICE_TYPE DeviceType;
256 PSOUND_DEVICE SoundDevice;
257
258 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
259
260 if ( ! MMSUCCESS(Result) )
261 {
262 return TranslateInternalMmResult(Result);
263 }
264
265 if ( OpenCount == 0 )
266 {
267 return MMSYSERR_NOERROR;
268 }
269
270 SND_ASSERT( KernelHandle != INVALID_HANDLE_VALUE );
271
272 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
273 SND_ASSERT( Result == MMSYSERR_NOERROR );
274
275 if (SoundDeviceInstance->Handle != (PVOID)KernelHandle)
276 {
277 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
278
279 DeviceInfo.DeviceType = DeviceType;
280 DeviceInfo.hDevice = SoundDeviceInstance->Handle;
281
282 /* First stop the stream */
283 if (DeviceType != MIXER_DEVICE_TYPE)
284 {
285 DeviceInfo.u.State = KSSTATE_STOP;
286 SyncOverlappedDeviceIoControl(KernelHandle,
287 IOCTL_SETDEVICE_STATE,
288 (LPVOID) &DeviceInfo,
289 sizeof(WDMAUD_DEVICE_INFO),
290 (LPVOID) &DeviceInfo,
291 sizeof(WDMAUD_DEVICE_INFO),
292 NULL);
293 }
294
295 SyncOverlappedDeviceIoControl(KernelHandle,
296 IOCTL_CLOSE_WDMAUD,
297 (LPVOID) &DeviceInfo,
298 sizeof(WDMAUD_DEVICE_INFO),
299 (LPVOID) &DeviceInfo,
300 sizeof(WDMAUD_DEVICE_INFO),
301 NULL);
302 }
303
304 if (DeviceType == MIXER_DEVICE_TYPE)
305 {
306 SetEvent(SoundDeviceInstance->hStopEvent);
307 CloseHandle(SoundDeviceInstance->hStopEvent);
308 CloseHandle(SoundDeviceInstance->hNotifyEvent);
309 }
310
311 --OpenCount;
312
313 if ( OpenCount < 1 )
314 {
315 CloseHandle(KernelHandle);
316 KernelHandle = INVALID_HANDLE_VALUE;
317 }
318
319 return MMSYSERR_NOERROR;
320 }
321
322 MMRESULT
323 WdmAudSetMixerDeviceFormatByLegacy(
324 IN PSOUND_DEVICE_INSTANCE Instance,
325 IN DWORD DeviceId,
326 IN PWAVEFORMATEX WaveFormat,
327 IN DWORD WaveFormatSize)
328 {
329 MMRESULT Result;
330 WDMAUD_DEVICE_INFO DeviceInfo;
331 HANDLE hThread;
332
333 Instance->hNotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
334 if ( ! Instance->hNotifyEvent )
335 return MMSYSERR_NOMEM;
336
337 if (Instance->Handle != NULL)
338 {
339 /* device is already open */
340 return MMSYSERR_NOERROR;
341 }
342
343 Instance->hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
344 if ( ! Instance->hStopEvent )
345 return MMSYSERR_NOMEM;
346
347 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
348 DeviceInfo.DeviceType = MIXER_DEVICE_TYPE;
349 DeviceInfo.DeviceIndex = DeviceId;
350 DeviceInfo.u.hNotifyEvent = Instance->hNotifyEvent;
351
352 Result = SyncOverlappedDeviceIoControl(KernelHandle,
353 IOCTL_OPEN_WDMAUD,
354 (LPVOID) &DeviceInfo,
355 sizeof(WDMAUD_DEVICE_INFO),
356 (LPVOID) &DeviceInfo,
357 sizeof(WDMAUD_DEVICE_INFO),
358 NULL);
359
360 if ( ! MMSUCCESS(Result) )
361 {
362 CloseHandle(Instance->hNotifyEvent);
363 CloseHandle(Instance->hStopEvent);
364 return TranslateInternalMmResult(Result);
365 }
366
367 hThread = CreateThread(NULL, 0, MixerEventThreadRoutine, (LPVOID)Instance, 0, NULL);
368 if ( hThread )
369 {
370 CloseHandle(hThread);
371 }
372
373 /* Store sound device handle instance handle */
374 Instance->Handle = (PVOID)DeviceInfo.hDevice;
375
376 return MMSYSERR_NOERROR;
377 }
378
379 MMRESULT
380 WdmAudSetWaveDeviceFormatByLegacy(
381 IN PSOUND_DEVICE_INSTANCE Instance,
382 IN DWORD DeviceId,
383 IN PWAVEFORMATEX WaveFormat,
384 IN DWORD WaveFormatSize)
385 {
386 MMRESULT Result;
387 PSOUND_DEVICE SoundDevice;
388 PVOID Identifier;
389 WDMAUD_DEVICE_INFO DeviceInfo;
390 MMDEVICE_TYPE DeviceType;
391
392 Result = GetSoundDeviceFromInstance(Instance, &SoundDevice);
393
394 if ( ! MMSUCCESS(Result) )
395 {
396 return TranslateInternalMmResult(Result);
397 }
398
399 Result = GetSoundDeviceIdentifier(SoundDevice, &Identifier);
400
401 if ( ! MMSUCCESS(Result) )
402 {
403 return TranslateInternalMmResult(Result);
404 }
405
406 if (Instance->Handle != NULL)
407 {
408 /* device is already open */
409 return MMSYSERR_NOERROR;
410 }
411
412 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
413
414 SND_ASSERT( Result == MMSYSERR_NOERROR );
415
416 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
417 DeviceInfo.DeviceType = DeviceType;
418 DeviceInfo.DeviceIndex = DeviceId;
419 DeviceInfo.u.WaveFormatEx.cbSize = sizeof(WAVEFORMATEX); //WaveFormat->cbSize;
420 DeviceInfo.u.WaveFormatEx.wFormatTag = WaveFormat->wFormatTag;
421 #ifdef USERMODE_MIXER
422 DeviceInfo.u.WaveFormatEx.nChannels = 2;
423 DeviceInfo.u.WaveFormatEx.nSamplesPerSec = 44100;
424 DeviceInfo.u.WaveFormatEx.nBlockAlign = 4;
425 DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = 176400;
426 DeviceInfo.u.WaveFormatEx.wBitsPerSample = 16;
427 #else
428 DeviceInfo.u.WaveFormatEx.nChannels = WaveFormat->nChannels;
429 DeviceInfo.u.WaveFormatEx.nSamplesPerSec = WaveFormat->nSamplesPerSec;
430 DeviceInfo.u.WaveFormatEx.nBlockAlign = WaveFormat->nBlockAlign;
431 DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = WaveFormat->nAvgBytesPerSec;
432 DeviceInfo.u.WaveFormatEx.wBitsPerSample = WaveFormat->wBitsPerSample;
433 #endif
434
435 Result = SyncOverlappedDeviceIoControl(KernelHandle,
436 IOCTL_OPEN_WDMAUD,
437 (LPVOID) &DeviceInfo,
438 sizeof(WDMAUD_DEVICE_INFO),
439 (LPVOID) &DeviceInfo,
440 sizeof(WDMAUD_DEVICE_INFO),
441 NULL);
442
443 if ( ! MMSUCCESS(Result) )
444 {
445 return TranslateInternalMmResult(Result);
446 }
447
448 /* Store format */
449 Instance->WaveFormatEx.cbSize = WaveFormat->cbSize;
450 Instance->WaveFormatEx.wFormatTag = WaveFormat->wFormatTag;
451 Instance->WaveFormatEx.nChannels = WaveFormat->nChannels;
452 Instance->WaveFormatEx.nSamplesPerSec = WaveFormat->nSamplesPerSec;
453 Instance->WaveFormatEx.nBlockAlign = WaveFormat->nBlockAlign;
454 Instance->WaveFormatEx.nAvgBytesPerSec = WaveFormat->nAvgBytesPerSec;
455 Instance->WaveFormatEx.wBitsPerSample = WaveFormat->wBitsPerSample;
456
457 /* Store sound device handle instance handle */
458 Instance->Handle = (PVOID)DeviceInfo.hDevice;
459
460 /* Now determine framing requirements */
461 Result = SyncOverlappedDeviceIoControl(KernelHandle,
462 IOCTL_GETFRAMESIZE,
463 (LPVOID) &DeviceInfo,
464 sizeof(WDMAUD_DEVICE_INFO),
465 (LPVOID) &DeviceInfo,
466 sizeof(WDMAUD_DEVICE_INFO),
467 NULL);
468
469 if ( MMSUCCESS(Result) )
470 {
471 if (DeviceInfo.u.FrameSize)
472 {
473 Instance->FrameSize = DeviceInfo.u.FrameSize * 2;
474 Instance->BufferCount = WaveFormat->nAvgBytesPerSec / Instance->FrameSize;
475 SND_TRACE(L"FrameSize %u BufferCount %u\n", Instance->FrameSize, Instance->BufferCount);
476 }
477 }
478 else
479 {
480 // use a default of 100 buffers
481 Instance->BufferCount = 100;
482 }
483
484 if (DeviceType == WAVE_OUT_DEVICE_TYPE)
485 {
486 /* Now start the stream */
487 DeviceInfo.u.State = KSSTATE_RUN;
488 SyncOverlappedDeviceIoControl(KernelHandle,
489 IOCTL_SETDEVICE_STATE,
490 (LPVOID) &DeviceInfo,
491 sizeof(WDMAUD_DEVICE_INFO),
492 (LPVOID) &DeviceInfo,
493 sizeof(WDMAUD_DEVICE_INFO),
494 NULL);
495 }
496
497 return MMSYSERR_NOERROR;
498 }
499
500 MMRESULT
501 WdmAudCommitWaveBufferByLegacy(
502 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
503 IN PVOID OffsetPtr,
504 IN DWORD Length,
505 IN PSOUND_OVERLAPPED Overlap,
506 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine)
507 {
508 HANDLE Handle;
509 MMRESULT Result;
510 WDMAUD_DEVICE_INFO DeviceInfo;
511 PSOUND_DEVICE SoundDevice;
512 MMDEVICE_TYPE DeviceType;
513 BOOL Ret;
514
515 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance );
516 VALIDATE_MMSYS_PARAMETER( OffsetPtr );
517 VALIDATE_MMSYS_PARAMETER( Overlap );
518 VALIDATE_MMSYS_PARAMETER( CompletionRoutine );
519
520 GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
521 SND_ASSERT(Handle);
522
523 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
524
525 if ( ! MMSUCCESS(Result) )
526 {
527 return TranslateInternalMmResult(Result);
528 }
529
530 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
531 SND_ASSERT( Result == MMSYSERR_NOERROR );
532
533 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
534
535 DeviceInfo.Header.FrameExtent = Length;
536 if (DeviceType == WAVE_OUT_DEVICE_TYPE)
537 {
538 DeviceInfo.Header.DataUsed = Length;
539 }
540 DeviceInfo.Header.Data = OffsetPtr;
541 DeviceInfo.Header.Size = sizeof(WDMAUD_DEVICE_INFO);
542 DeviceInfo.Header.PresentationTime.Numerator = 1;
543 DeviceInfo.Header.PresentationTime.Denominator = 1;
544 DeviceInfo.hDevice = Handle;
545 DeviceInfo.DeviceType = DeviceType;
546
547
548
549 Overlap->Standard.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
550
551 if (DeviceType == WAVE_OUT_DEVICE_TYPE)
552 {
553 Ret = WriteFileEx(KernelHandle, &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, CompletionRoutine);
554 if (Ret)
555 WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
556 }
557 else if (DeviceType == WAVE_IN_DEVICE_TYPE)
558 {
559 Ret = ReadFileEx(KernelHandle, &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, CompletionRoutine);
560 //if (Ret)
561 // WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
562 }
563
564 return MMSYSERR_NOERROR;
565 }
566
567
568
569 MMRESULT
570 WdmAudSetWaveStateByLegacy(
571 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
572 IN BOOL bStart)
573 {
574 MMRESULT Result;
575 PSOUND_DEVICE SoundDevice;
576 WDMAUD_DEVICE_INFO DeviceInfo;
577 MMDEVICE_TYPE DeviceType;
578 HANDLE Handle;
579
580 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
581
582 if ( ! MMSUCCESS(Result) )
583 {
584 return TranslateInternalMmResult(Result);
585 }
586
587 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
588 SND_ASSERT( Result == MMSYSERR_NOERROR );
589
590 Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
591 SND_ASSERT( Result == MMSYSERR_NOERROR );
592
593 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
594 DeviceInfo.hDevice = Handle;
595 DeviceInfo.DeviceType = DeviceType;
596
597 if (bStart)
598 DeviceInfo.u.State = KSSTATE_RUN;
599 else
600 DeviceInfo.u.State = KSSTATE_PAUSE;
601 Result = SyncOverlappedDeviceIoControl(KernelHandle,
602 IOCTL_SETDEVICE_STATE,
603 (LPVOID) &DeviceInfo,
604 sizeof(WDMAUD_DEVICE_INFO),
605 (LPVOID) &DeviceInfo,
606 sizeof(WDMAUD_DEVICE_INFO),
607 NULL);
608
609 return Result;
610 }
611
612 MMRESULT
613 WdmAudGetDeviceInterfaceStringByLegacy(
614 IN MMDEVICE_TYPE DeviceType,
615 IN DWORD DeviceId,
616 IN LPWSTR Interface,
617 IN DWORD InterfaceLength,
618 OUT DWORD * InterfaceSize)
619 {
620 WDMAUD_DEVICE_INFO DeviceInfo;
621 MMRESULT Result;
622
623 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
624 DeviceInfo.DeviceType = DeviceType;
625 DeviceInfo.DeviceIndex = DeviceId;
626
627
628 Result = SyncOverlappedDeviceIoControl(KernelHandle,
629 IOCTL_QUERYDEVICEINTERFACESTRING,
630 (LPVOID) &DeviceInfo,
631 sizeof(WDMAUD_DEVICE_INFO),
632 (LPVOID) &DeviceInfo,
633 sizeof(WDMAUD_DEVICE_INFO),
634 NULL);
635
636
637 if ( ! MMSUCCESS(Result) )
638 {
639 return TranslateInternalMmResult(Result);
640 }
641
642
643 if (!Interface)
644 {
645 SND_ASSERT(InterfaceSize);
646
647 *InterfaceSize = DeviceInfo.u.Interface.DeviceInterfaceStringSize;
648 return MMSYSERR_NOERROR;
649 }
650
651 if (InterfaceLength < DeviceInfo.u.Interface.DeviceInterfaceStringSize)
652 {
653 /* buffer is too small */
654 return MMSYSERR_MOREDATA;
655 }
656
657 DeviceInfo.u.Interface.DeviceInterfaceStringSize = InterfaceLength;
658 DeviceInfo.u.Interface.DeviceInterfaceString = Interface;
659
660 Result = SyncOverlappedDeviceIoControl(KernelHandle,
661 IOCTL_QUERYDEVICEINTERFACESTRING,
662 (LPVOID) &DeviceInfo,
663 sizeof(WDMAUD_DEVICE_INFO),
664 (LPVOID) &DeviceInfo,
665 sizeof(WDMAUD_DEVICE_INFO),
666 NULL);
667
668 if ( MMSUCCESS(Result) && InterfaceLength > 2)
669 {
670 Interface[1] = L'\\';
671 Interface[InterfaceLength-1] = L'\0';
672 }
673
674 return Result;
675 }
676
677 MMRESULT
678 WdmAudGetWavePositionByLegacy(
679 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
680 IN MMTIME* Time)
681 {
682 MMRESULT Result;
683 PSOUND_DEVICE SoundDevice;
684 WDMAUD_DEVICE_INFO DeviceInfo;
685 MMDEVICE_TYPE DeviceType;
686 HANDLE Handle;
687
688 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
689
690 if ( ! MMSUCCESS(Result) )
691 {
692 return TranslateInternalMmResult(Result);
693 }
694
695 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
696 SND_ASSERT( Result == MMSYSERR_NOERROR );
697
698 Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
699 SND_ASSERT( Result == MMSYSERR_NOERROR );
700
701 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
702 DeviceInfo.hDevice = Handle;
703 DeviceInfo.DeviceType = DeviceType;
704
705 Result = SyncOverlappedDeviceIoControl(KernelHandle,
706 IOCTL_OPEN_WDMAUD,
707 (LPVOID) &DeviceInfo,
708 sizeof(WDMAUD_DEVICE_INFO),
709 (LPVOID) &DeviceInfo,
710 sizeof(WDMAUD_DEVICE_INFO),
711 NULL);
712
713 if ( ! MMSUCCESS(Result) )
714 {
715 return TranslateInternalMmResult(Result);
716 }
717
718 Time->wType = TIME_BYTES;
719 Time->u.cb = (DWORD)DeviceInfo.u.Position;
720
721 return MMSYSERR_NOERROR;
722 }
723
724
725 MMRESULT
726 WdmAudResetStreamByLegacy(
727 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
728 IN MMDEVICE_TYPE DeviceType,
729 IN BOOLEAN bStartReset)
730 {
731 MMRESULT Result;
732 HANDLE Handle;
733 WDMAUD_DEVICE_INFO DeviceInfo;
734
735 Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
736 SND_ASSERT( Result == MMSYSERR_NOERROR );
737
738 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
739 DeviceInfo.hDevice = Handle;
740 DeviceInfo.DeviceType = DeviceType;
741 DeviceInfo.u.ResetStream = (bStartReset ? KSRESET_BEGIN : KSRESET_END);
742
743 Result = SyncOverlappedDeviceIoControl(KernelHandle,
744 IOCTL_RESET_STREAM,
745 (LPVOID) &DeviceInfo,
746 sizeof(WDMAUD_DEVICE_INFO),
747 (LPVOID) &DeviceInfo,
748 sizeof(WDMAUD_DEVICE_INFO),
749 NULL);
750 return Result;
751 }
752
753 MMRESULT
754 WdmAudQueryMixerInfoByLegacy(
755 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
756 IN UINT uMsg,
757 IN LPVOID Parameter,
758 IN DWORD Flags)
759 {
760 MMRESULT Result;
761 WDMAUD_DEVICE_INFO DeviceInfo;
762 HANDLE Handle;
763 DWORD IoControlCode;
764 LPMIXERLINEW MixLine;
765 LPMIXERLINECONTROLSW MixControls;
766 LPMIXERCONTROLDETAILS MixDetails;
767
768 SND_TRACE(L"uMsg %x Flags %x\n", uMsg, Flags);
769
770 Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
771 SND_ASSERT( Result == MMSYSERR_NOERROR );
772
773 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
774 DeviceInfo.hDevice = Handle;
775 DeviceInfo.DeviceType = MIXER_DEVICE_TYPE;
776 DeviceInfo.Flags = Flags;
777
778 MixLine = (LPMIXERLINEW)Parameter;
779 MixControls = (LPMIXERLINECONTROLSW)Parameter;
780 MixDetails = (LPMIXERCONTROLDETAILS)Parameter;
781
782 switch(uMsg)
783 {
784 case MXDM_GETLINEINFO:
785 RtlCopyMemory(&DeviceInfo.u.MixLine, MixLine, sizeof(MIXERLINEW));
786 IoControlCode = IOCTL_GETLINEINFO;
787 break;
788 case MXDM_GETLINECONTROLS:
789 RtlCopyMemory(&DeviceInfo.u.MixControls, MixControls, sizeof(MIXERLINECONTROLSW));
790 IoControlCode = IOCTL_GETLINECONTROLS;
791 break;
792 case MXDM_SETCONTROLDETAILS:
793 RtlCopyMemory(&DeviceInfo.u.MixDetails, MixDetails, sizeof(MIXERCONTROLDETAILS));
794 IoControlCode = IOCTL_SETCONTROLDETAILS;
795 break;
796 case MXDM_GETCONTROLDETAILS:
797 RtlCopyMemory(&DeviceInfo.u.MixDetails, MixDetails, sizeof(MIXERCONTROLDETAILS));
798 IoControlCode = IOCTL_GETCONTROLDETAILS;
799 break;
800 default:
801 SND_ASSERT(0);
802 return MMSYSERR_NOTSUPPORTED;
803 }
804
805 Result = SyncOverlappedDeviceIoControl(KernelHandle,
806 IoControlCode,
807 (LPVOID) &DeviceInfo,
808 sizeof(WDMAUD_DEVICE_INFO),
809 (LPVOID) &DeviceInfo,
810 sizeof(WDMAUD_DEVICE_INFO),
811 NULL);
812
813 if ( ! MMSUCCESS(Result) )
814 {
815 return Result;
816 }
817
818 switch(uMsg)
819 {
820 case MXDM_GETLINEINFO:
821 {
822 RtlCopyMemory(MixLine, &DeviceInfo.u.MixLine, sizeof(MIXERLINEW));
823 break;
824 }
825 }
826
827 return Result;
828 }