- Fix building of ReactOS
[reactos.git] / reactos / dll / win32 / wdmaud.drv / wdmaud.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 *
9 * NOTES: Looking for wodMessage & co? You won't find them here. Try
10 * the MME Buddy library, which is where these routines are
11 * actually implemented.
12 *
13 */
14
15 #include <windows.h>
16 #include <ntddsnd.h>
17 #include <sndtypes.h>
18 #include <mmddk.h>
19 #include <mmebuddy.h>
20
21 #include <ks.h>
22 #include <ksmedia.h>
23 #include "interface.h"
24
25 #define KERNEL_DEVICE_NAME L"\\\\.\\wdmaud"
26
27 PWSTR UnknownWaveIn = L"Wave Input";
28 PWSTR UnknownWaveOut = L"Wave Output";
29 PWSTR UnknownMidiIn = L"Midi Input";
30 PWSTR UnknownMidiOut = L"Midi Output";
31
32 HANDLE KernelHandle = INVALID_HANDLE_VALUE;
33 DWORD OpenCount = 0;
34
35 MMRESULT
36 WriteFileEx_Remixer(
37 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
38 IN PVOID OffsetPtr,
39 IN DWORD Length,
40 IN PSOUND_OVERLAPPED Overlap,
41 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine);
42
43
44
45 MMRESULT
46 GetNumWdmDevs(
47 IN HANDLE Handle,
48 IN MMDEVICE_TYPE DeviceType,
49 OUT DWORD* DeviceCount)
50 {
51 MMRESULT Result;
52 WDMAUD_DEVICE_INFO DeviceInfo;
53
54 VALIDATE_MMSYS_PARAMETER( Handle != INVALID_HANDLE_VALUE );
55 VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) );
56 VALIDATE_MMSYS_PARAMETER( DeviceCount );
57
58 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
59 DeviceInfo.DeviceType = DeviceType;
60
61 Result = SyncOverlappedDeviceIoControl(Handle,
62 IOCTL_GETNUMDEVS_TYPE,
63 (LPVOID) &DeviceInfo,
64 sizeof(WDMAUD_DEVICE_INFO),
65 (LPVOID) &DeviceInfo,
66 sizeof(WDMAUD_DEVICE_INFO),
67 NULL);
68
69 if ( ! MMSUCCESS( Result ) )
70 {
71 SND_ERR(L"Call to IOCTL_GETNUMDEVS_TYPE failed\n");
72 *DeviceCount = 0;
73 return TranslateInternalMmResult(Result);
74 }
75
76 *DeviceCount = DeviceInfo.DeviceCount;
77
78 return MMSYSERR_NOERROR;
79 }
80
81 MMRESULT
82 GetWdmDeviceCapabilities(
83 IN PSOUND_DEVICE SoundDevice,
84 IN DWORD DeviceId,
85 OUT PVOID Capabilities,
86 IN DWORD CapabilitiesSize)
87 {
88 /* NOTE - At this time, WDMAUD does not support this properly */
89
90 MMRESULT Result;
91 MMDEVICE_TYPE DeviceType;
92 WDMAUD_DEVICE_INFO DeviceInfo;
93
94 SND_ASSERT( SoundDevice );
95 SND_ASSERT( Capabilities );
96
97 SND_TRACE(L"WDMAUD - GetWdmDeviceCapabilities\n");
98
99 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
100 SND_ASSERT( Result == MMSYSERR_NOERROR );
101
102 if ( ! MMSUCCESS(Result) )
103 return Result;
104
105
106 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
107 DeviceInfo.DeviceType = DeviceType;
108 DeviceInfo.DeviceIndex = DeviceId;
109
110 Result = SyncOverlappedDeviceIoControl(KernelHandle,
111 IOCTL_GETCAPABILITIES,
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 return TranslateInternalMmResult(Result);
121 }
122
123 SND_TRACE(L"WDMAUD Name %S\n", DeviceInfo.u.WaveOutCaps.szPname);
124
125 /* This is pretty much a big hack right now */
126 switch ( DeviceType )
127 {
128 case MIXER_DEVICE_TYPE:
129 {
130 LPMIXERCAPS MixerCaps = (LPMIXERCAPS) Capabilities;
131
132 CopyWideString(MixerCaps->szPname, DeviceInfo.u.WaveOutCaps.szPname);
133
134 MixerCaps->cDestinations = DeviceInfo.u.MixCaps.cDestinations;
135 MixerCaps->fdwSupport = DeviceInfo.u.MixCaps.fdwSupport;
136 MixerCaps->vDriverVersion = DeviceInfo.u.MixCaps.vDriverVersion;
137 MixerCaps->wMid = DeviceInfo.u.MixCaps.wMid;
138 MixerCaps->wPid = DeviceInfo.u.MixCaps.wPid;
139 break;
140 }
141 case WAVE_OUT_DEVICE_TYPE :
142 {
143 LPWAVEOUTCAPS WaveOutCaps = (LPWAVEOUTCAPS) Capabilities;
144 WaveOutCaps->wMid = DeviceInfo.u.WaveOutCaps.wMid;
145 WaveOutCaps->wPid = DeviceInfo.u.WaveOutCaps.wPid;
146
147 WaveOutCaps->vDriverVersion = 0x0001;
148 CopyWideString(WaveOutCaps->szPname, DeviceInfo.u.WaveOutCaps.szPname);
149
150 WaveOutCaps->dwFormats = DeviceInfo.u.WaveOutCaps.dwFormats;
151 WaveOutCaps->wChannels = DeviceInfo.u.WaveOutCaps.wChannels;
152 WaveOutCaps->dwSupport = DeviceInfo.u.WaveOutCaps.dwSupport;
153 break;
154 }
155 case WAVE_IN_DEVICE_TYPE :
156 {
157 LPWAVEINCAPS WaveInCaps = (LPWAVEINCAPS) Capabilities;
158 CopyWideString(WaveInCaps->szPname, DeviceInfo.u.WaveOutCaps.szPname);
159 /* TODO... other fields */
160 break;
161 }
162 }
163
164 return MMSYSERR_NOERROR;
165 }
166
167
168 MMRESULT
169 OpenWdmSoundDevice(
170 IN struct _SOUND_DEVICE* SoundDevice, /* NOT USED */
171 OUT PVOID* Handle)
172 {
173 /* Only open this if it's not already open */
174 if ( KernelHandle == INVALID_HANDLE_VALUE )
175 {
176 SND_TRACE(L"Opening wdmaud device\n");
177 KernelHandle = CreateFileW(KERNEL_DEVICE_NAME,
178 GENERIC_READ | GENERIC_WRITE,
179 0,
180 NULL,
181 OPEN_EXISTING,
182 FILE_FLAG_OVERLAPPED,
183 NULL);
184 }
185
186 if ( KernelHandle == INVALID_HANDLE_VALUE )
187 return MMSYSERR_ERROR;
188
189 SND_ASSERT( Handle );
190
191 *Handle = KernelHandle;
192 ++ OpenCount;
193
194 return MMSYSERR_NOERROR;
195 }
196
197 MMRESULT
198 CloseWdmSoundDevice(
199 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
200 IN PVOID Handle)
201 {
202 WDMAUD_DEVICE_INFO DeviceInfo;
203 MMRESULT Result;
204 MMDEVICE_TYPE DeviceType;
205 PSOUND_DEVICE SoundDevice;
206
207 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
208
209 if ( ! MMSUCCESS(Result) )
210 {
211 return TranslateInternalMmResult(Result);
212 }
213
214 if ( OpenCount == 0 )
215 {
216 return MMSYSERR_NOERROR;
217 }
218
219 SND_ASSERT( KernelHandle != INVALID_HANDLE_VALUE );
220
221 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
222 SND_ASSERT( Result == MMSYSERR_NOERROR );
223
224 if (SoundDeviceInstance->Handle != (PVOID)KernelHandle)
225 {
226 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
227
228 DeviceInfo.DeviceType = DeviceType;
229 DeviceInfo.hDevice = SoundDeviceInstance->Handle;
230
231 /* First stop the stream */
232 if (DeviceType != MIXER_DEVICE_TYPE)
233 {
234 DeviceInfo.u.State = KSSTATE_STOP;
235 SyncOverlappedDeviceIoControl(KernelHandle,
236 IOCTL_SETDEVICE_STATE,
237 (LPVOID) &DeviceInfo,
238 sizeof(WDMAUD_DEVICE_INFO),
239 (LPVOID) &DeviceInfo,
240 sizeof(WDMAUD_DEVICE_INFO),
241 NULL);
242 }
243
244 SyncOverlappedDeviceIoControl(KernelHandle,
245 IOCTL_CLOSE_WDMAUD,
246 (LPVOID) &DeviceInfo,
247 sizeof(WDMAUD_DEVICE_INFO),
248 (LPVOID) &DeviceInfo,
249 sizeof(WDMAUD_DEVICE_INFO),
250 NULL);
251 }
252
253 --OpenCount;
254
255 if ( OpenCount < 1 )
256 {
257 CloseHandle(KernelHandle);
258 KernelHandle = INVALID_HANDLE_VALUE;
259 }
260
261 return MMSYSERR_NOERROR;
262 }
263
264
265 MMRESULT
266 QueryWdmWaveDeviceFormatSupport(
267 IN PSOUND_DEVICE Device,
268 IN PWAVEFORMATEX WaveFormat,
269 IN DWORD WaveFormatSize)
270 {
271 /* Whatever... */
272 return MMSYSERR_NOERROR;
273 }
274
275
276 MMRESULT
277 SetWdmMixerDeviceFormat(
278 IN PSOUND_DEVICE_INSTANCE Instance,
279 IN DWORD DeviceId,
280 IN PWAVEFORMATEX WaveFormat,
281 IN DWORD WaveFormatSize)
282 {
283 MMRESULT Result;
284 WDMAUD_DEVICE_INFO DeviceInfo;
285
286 if (Instance->Handle != KernelHandle)
287 {
288 /* device is already open */
289 return MMSYSERR_NOERROR;
290 }
291
292
293 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
294 DeviceInfo.DeviceType = MIXER_DEVICE_TYPE;
295 DeviceInfo.DeviceIndex = DeviceId;
296
297 Result = SyncOverlappedDeviceIoControl(KernelHandle,
298 IOCTL_OPEN_WDMAUD,
299 (LPVOID) &DeviceInfo,
300 sizeof(WDMAUD_DEVICE_INFO),
301 (LPVOID) &DeviceInfo,
302 sizeof(WDMAUD_DEVICE_INFO),
303 NULL);
304
305 if ( ! MMSUCCESS(Result) )
306 {
307 return TranslateInternalMmResult(Result);
308 }
309
310 /* Store sound device handle instance handle */
311 Instance->Handle = (PVOID)DeviceInfo.hDevice;
312
313 return MMSYSERR_NOERROR;
314 }
315
316 MMRESULT
317 SetWdmWaveDeviceFormat(
318 IN PSOUND_DEVICE_INSTANCE Instance,
319 IN DWORD DeviceId,
320 IN PWAVEFORMATEX WaveFormat,
321 IN DWORD WaveFormatSize)
322 {
323 MMRESULT Result;
324 PSOUND_DEVICE SoundDevice;
325 PVOID Identifier;
326 WDMAUD_DEVICE_INFO DeviceInfo;
327 MMDEVICE_TYPE DeviceType;
328
329 Result = GetSoundDeviceFromInstance(Instance, &SoundDevice);
330
331 if ( ! MMSUCCESS(Result) )
332 {
333 return TranslateInternalMmResult(Result);
334 }
335
336 Result = GetSoundDeviceIdentifier(SoundDevice, &Identifier);
337
338 if ( ! MMSUCCESS(Result) )
339 {
340 return TranslateInternalMmResult(Result);
341 }
342
343 if (Instance->Handle != KernelHandle)
344 {
345 /* device is already open */
346 return MMSYSERR_NOERROR;
347 }
348
349
350 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
351 SND_ASSERT( Result == MMSYSERR_NOERROR );
352
353 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
354 DeviceInfo.DeviceType = DeviceType;
355 DeviceInfo.DeviceIndex = DeviceId;
356 DeviceInfo.u.WaveFormatEx.cbSize = WaveFormat->cbSize;
357 DeviceInfo.u.WaveFormatEx.wFormatTag = WaveFormat->wFormatTag;
358 #ifdef USERMODE_MIXER
359 DeviceInfo.u.WaveFormatEx.nChannels = 2;
360 DeviceInfo.u.WaveFormatEx.nSamplesPerSec = 44100;
361 DeviceInfo.u.WaveFormatEx.nBlockAlign = 4;
362 DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = 176400;
363 DeviceInfo.u.WaveFormatEx.wBitsPerSample = 16;
364 #else
365 DeviceInfo.u.WaveFormatEx.nChannels = WaveFormat->nChannels;
366 DeviceInfo.u.WaveFormatEx.nSamplesPerSec = WaveFormat->nSamplesPerSec;
367 DeviceInfo.u.WaveFormatEx.nBlockAlign = WaveFormat->nBlockAlign;
368 DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = WaveFormat->nAvgBytesPerSec;
369 DeviceInfo.u.WaveFormatEx.wBitsPerSample = WaveFormat->wBitsPerSample;
370 #endif
371
372 Result = SyncOverlappedDeviceIoControl(KernelHandle,
373 IOCTL_OPEN_WDMAUD,
374 (LPVOID) &DeviceInfo,
375 sizeof(WDMAUD_DEVICE_INFO),
376 (LPVOID) &DeviceInfo,
377 sizeof(WDMAUD_DEVICE_INFO),
378 NULL);
379
380 if ( ! MMSUCCESS(Result) )
381 {
382 return TranslateInternalMmResult(Result);
383 }
384
385 /* Store format */
386 Instance->WaveFormatEx.cbSize = WaveFormat->cbSize;
387 Instance->WaveFormatEx.wFormatTag = WaveFormat->wFormatTag;
388 Instance->WaveFormatEx.nChannels = WaveFormat->nChannels;
389 Instance->WaveFormatEx.nSamplesPerSec = WaveFormat->nSamplesPerSec;
390 Instance->WaveFormatEx.nBlockAlign = WaveFormat->nBlockAlign;
391 Instance->WaveFormatEx.nAvgBytesPerSec = WaveFormat->nAvgBytesPerSec;
392 Instance->WaveFormatEx.wBitsPerSample = WaveFormat->wBitsPerSample;
393
394 /* Store sound device handle instance handle */
395 Instance->Handle = (PVOID)DeviceInfo.hDevice;
396
397 /* Now determine framing requirements */
398 Result = SyncOverlappedDeviceIoControl(KernelHandle,
399 IOCTL_GETFRAMESIZE,
400 (LPVOID) &DeviceInfo,
401 sizeof(WDMAUD_DEVICE_INFO),
402 (LPVOID) &DeviceInfo,
403 sizeof(WDMAUD_DEVICE_INFO),
404 NULL);
405
406 if ( MMSUCCESS(Result) )
407 {
408 if (DeviceInfo.u.FrameSize)
409 {
410 //Instance->FrameSize = DeviceInfo.u.FrameSize;
411 Instance->BufferCount = WaveFormat->nAvgBytesPerSec / Instance->FrameSize;
412 SND_TRACE(L"FrameSize %u BufferCount %u\n", Instance->FrameSize, Instance->BufferCount);
413 }
414 }
415
416 /* Now start the stream */
417 DeviceInfo.u.State = KSSTATE_RUN;
418 SyncOverlappedDeviceIoControl(KernelHandle,
419 IOCTL_SETDEVICE_STATE,
420 (LPVOID) &DeviceInfo,
421 sizeof(WDMAUD_DEVICE_INFO),
422 (LPVOID) &DeviceInfo,
423 sizeof(WDMAUD_DEVICE_INFO),
424 NULL);
425
426 return MMSYSERR_NOERROR;
427 }
428
429 MMRESULT
430 WriteFileEx_Committer2(
431 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
432 IN PVOID OffsetPtr,
433 IN DWORD Length,
434 IN PSOUND_OVERLAPPED Overlap,
435 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine)
436 {
437 HANDLE Handle;
438 MMRESULT Result;
439 WDMAUD_DEVICE_INFO DeviceInfo;
440 PSOUND_DEVICE SoundDevice;
441 MMDEVICE_TYPE DeviceType;
442 BOOL Ret;
443
444 VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance );
445 VALIDATE_MMSYS_PARAMETER( OffsetPtr );
446 VALIDATE_MMSYS_PARAMETER( Overlap );
447 VALIDATE_MMSYS_PARAMETER( CompletionRoutine );
448
449 GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
450
451
452 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
453
454 if ( ! MMSUCCESS(Result) )
455 {
456 return TranslateInternalMmResult(Result);
457 }
458
459 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
460 SND_ASSERT( Result == MMSYSERR_NOERROR );
461
462 SND_ASSERT(Handle);
463
464 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
465
466 DeviceInfo.Header.FrameExtent = Length;
467 if (DeviceType == WAVE_OUT_DEVICE_TYPE)
468 {
469 DeviceInfo.Header.DataUsed = Length;
470 }
471 DeviceInfo.Header.Data = OffsetPtr;
472 DeviceInfo.Header.Size = sizeof(WDMAUD_DEVICE_INFO);
473 DeviceInfo.Header.PresentationTime.Numerator = 1;
474 DeviceInfo.Header.PresentationTime.Denominator = 1;
475 DeviceInfo.hDevice = Handle;
476 DeviceInfo.DeviceType = DeviceType;
477
478 Overlap->Standard.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
479
480 if (DeviceType == WAVE_OUT_DEVICE_TYPE)
481 {
482 Ret = WriteFileEx(KernelHandle, &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, CompletionRoutine);
483 if (Ret)
484 WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
485 }
486 else if (DeviceType == WAVE_IN_DEVICE_TYPE)
487 {
488 Ret = ReadFileEx(KernelHandle, &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, CompletionRoutine);
489 if (Ret)
490 WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE);
491 }
492
493 return MMSYSERR_NOERROR;
494 }
495
496 MMRESULT
497 GetWdmPosition(
498 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
499 IN MMTIME* Time)
500 {
501 MMRESULT Result;
502 PSOUND_DEVICE SoundDevice;
503 WDMAUD_DEVICE_INFO DeviceInfo;
504 MMDEVICE_TYPE DeviceType;
505 HANDLE Handle;
506
507 Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
508
509 if ( ! MMSUCCESS(Result) )
510 {
511 return TranslateInternalMmResult(Result);
512 }
513
514 Result = GetSoundDeviceType(SoundDevice, &DeviceType);
515 SND_ASSERT( Result == MMSYSERR_NOERROR );
516
517 Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
518 SND_ASSERT( Result == MMSYSERR_NOERROR );
519
520 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
521 DeviceInfo.hDevice = Handle;
522 DeviceInfo.DeviceType = DeviceType;
523
524 Result = SyncOverlappedDeviceIoControl(KernelHandle,
525 IOCTL_OPEN_WDMAUD,
526 (LPVOID) &DeviceInfo,
527 sizeof(WDMAUD_DEVICE_INFO),
528 (LPVOID) &DeviceInfo,
529 sizeof(WDMAUD_DEVICE_INFO),
530 NULL);
531
532 if ( ! MMSUCCESS(Result) )
533 {
534 return TranslateInternalMmResult(Result);
535 }
536
537 Time->wType = TIME_BYTES;
538 Time->u.cb = (DWORD)DeviceInfo.u.Position;
539
540 return MMSYSERR_NOERROR;
541 }
542
543 MMRESULT
544 QueryMixerInfo(
545 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
546 IN UINT uMsg,
547 IN LPVOID Parameter,
548 IN DWORD Flags)
549 {
550 MMRESULT Result;
551 WDMAUD_DEVICE_INFO DeviceInfo;
552 HANDLE Handle;
553 DWORD IoControlCode;
554 LPMIXERLINEW MixLine;
555 LPMIXERLINECONTROLSW MixControls;
556 LPMIXERCONTROLDETAILS MixDetails;
557
558 SND_TRACE(L"uMsg %x Flags %x\n", uMsg, Flags);
559
560 Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle);
561 SND_ASSERT( Result == MMSYSERR_NOERROR );
562
563 ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
564 DeviceInfo.hDevice = Handle;
565 DeviceInfo.DeviceType = MIXER_DEVICE_TYPE;
566 DeviceInfo.Flags = Flags;
567
568 MixLine = (LPMIXERLINEW)Parameter;
569 MixControls = (LPMIXERLINECONTROLSW)Parameter;
570 MixDetails = (LPMIXERCONTROLDETAILS)Parameter;
571
572 switch(uMsg)
573 {
574 case MXDM_GETLINEINFO:
575 RtlCopyMemory(&DeviceInfo.u.MixLine, MixLine, sizeof(MIXERLINEW));
576 IoControlCode = IOCTL_GETLINEINFO;
577 break;
578 case MXDM_GETLINECONTROLS:
579 RtlCopyMemory(&DeviceInfo.u.MixControls, MixControls, sizeof(MIXERLINECONTROLSW));
580 IoControlCode = IOCTL_GETLINECONTROLS;
581 break;
582 case MXDM_SETCONTROLDETAILS:
583 RtlCopyMemory(&DeviceInfo.u.MixDetails, MixDetails, sizeof(MIXERCONTROLDETAILS));
584 IoControlCode = IOCTL_SETCONTROLDETAILS;
585 break;
586 case MXDM_GETCONTROLDETAILS:
587 RtlCopyMemory(&DeviceInfo.u.MixDetails, MixDetails, sizeof(MIXERCONTROLDETAILS));
588 IoControlCode = IOCTL_GETCONTROLDETAILS;
589 break;
590 default:
591 SND_ASSERT(0);
592 }
593
594 Result = SyncOverlappedDeviceIoControl(KernelHandle,
595 IoControlCode,
596 (LPVOID) &DeviceInfo,
597 sizeof(WDMAUD_DEVICE_INFO),
598 (LPVOID) &DeviceInfo,
599 sizeof(WDMAUD_DEVICE_INFO),
600 NULL);
601
602 if ( ! MMSUCCESS(Result) )
603 {
604 return TranslateInternalMmResult(Result);
605 }
606
607 switch(uMsg)
608 {
609 case MXDM_GETLINEINFO:
610 {
611 RtlCopyMemory(MixLine, &DeviceInfo.u.MixLine, sizeof(MIXERLINEW));
612 break;
613 }
614 }
615
616 return Result;
617 }
618
619
620 MMRESULT
621 PopulateWdmDeviceList(
622 HANDLE Handle,
623 MMDEVICE_TYPE DeviceType)
624 {
625 MMRESULT Result;
626 DWORD DeviceCount = 0;
627 PSOUND_DEVICE SoundDevice = NULL;
628 MMFUNCTION_TABLE FuncTable;
629 DWORD i;
630
631 VALIDATE_MMSYS_PARAMETER( Handle != INVALID_HANDLE_VALUE );
632 VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) );
633
634 Result = GetNumWdmDevs(Handle, DeviceType, &DeviceCount);
635
636 if ( ! MMSUCCESS(Result) )
637 {
638 SND_ERR(L"Error %d while obtaining number of devices\n", Result);
639 return TranslateInternalMmResult(Result);
640 }
641
642 SND_TRACE(L"%d devices of type %d found\n", DeviceCount, DeviceType);
643
644
645 for ( i = 0; i < DeviceCount; ++ i )
646 {
647 Result = ListSoundDevice(DeviceType, (PVOID) i, &SoundDevice);
648
649 if ( ! MMSUCCESS(Result) )
650 {
651 SND_ERR(L"Failed to list sound device - error %d\n", Result);
652 return TranslateInternalMmResult(Result);
653 }
654
655 /* Set up our function table */
656 ZeroMemory(&FuncTable, sizeof(MMFUNCTION_TABLE));
657 FuncTable.GetCapabilities = GetWdmDeviceCapabilities;
658 FuncTable.QueryWaveFormatSupport = QueryWdmWaveDeviceFormatSupport;
659 if (DeviceType == MIXER_DEVICE_TYPE)
660 {
661 FuncTable.SetWaveFormat = SetWdmMixerDeviceFormat;
662 FuncTable.QueryMixerInfo = QueryMixerInfo;
663 }
664 else
665 {
666 FuncTable.SetWaveFormat = SetWdmWaveDeviceFormat;
667 }
668
669 FuncTable.Open = OpenWdmSoundDevice;
670 FuncTable.Close = CloseWdmSoundDevice;
671 #ifndef USERMODE_MIXER
672 FuncTable.CommitWaveBuffer = WriteFileEx_Committer2;
673 #else
674 FuncTable.CommitWaveBuffer = WriteFileEx_Remixer;
675 #endif
676 FuncTable.GetPos = GetWdmPosition;
677
678 SetSoundDeviceFunctionTable(SoundDevice, &FuncTable);
679 }
680
681 return MMSYSERR_NOERROR;
682 }
683
684
685
686 LONG
687 APIENTRY
688 DriverProc(
689 DWORD DriverId,
690 HANDLE DriverHandle,
691 UINT Message,
692 LONG Parameter1,
693 LONG Parameter2)
694 {
695 MMRESULT Result;
696
697 switch ( Message )
698 {
699 case DRV_LOAD :
700 {
701 HANDLE Handle;
702 SND_TRACE(L"DRV_LOAD\n");
703
704 Result = InitEntrypointMutexes();
705
706 if ( ! MMSUCCESS(Result) )
707 return 0L;
708
709 OpenWdmSoundDevice(NULL, &Handle);
710
711 if ( Handle == INVALID_HANDLE_VALUE )
712 {
713 SND_ERR(L"Failed to open %s\n", KERNEL_DEVICE_NAME);
714 CleanupEntrypointMutexes();
715
716 //UnlistAllSoundDevices();
717
718 return 0L;
719 }
720
721 /* Populate the device lists */
722 SND_TRACE(L"Populating device lists\n");
723 PopulateWdmDeviceList(KernelHandle, WAVE_OUT_DEVICE_TYPE);
724 PopulateWdmDeviceList(KernelHandle, WAVE_IN_DEVICE_TYPE);
725 PopulateWdmDeviceList(KernelHandle, MIDI_OUT_DEVICE_TYPE);
726 PopulateWdmDeviceList(KernelHandle, MIDI_IN_DEVICE_TYPE);
727 PopulateWdmDeviceList(KernelHandle, AUX_DEVICE_TYPE);
728 PopulateWdmDeviceList(KernelHandle, MIXER_DEVICE_TYPE);
729
730 SND_TRACE(L"Initialisation complete\n");
731
732 return 1L;
733 }
734
735 case DRV_FREE :
736 {
737 SND_TRACE(L"DRV_FREE\n");
738
739 if ( KernelHandle != INVALID_HANDLE_VALUE )
740 {
741 CloseHandle(KernelHandle);
742 KernelHandle = INVALID_HANDLE_VALUE;
743 }
744
745 /* TODO: Clean up the path names! */
746 UnlistAllSoundDevices();
747
748 CleanupEntrypointMutexes();
749
750 SND_TRACE(L"Unfreed memory blocks: %d\n",
751 GetMemoryAllocationCount());
752
753 return 1L;
754 }
755
756 case DRV_ENABLE :
757 case DRV_DISABLE :
758 {
759 SND_TRACE(L"DRV_ENABLE / DRV_DISABLE\n");
760 return 1L;
761 }
762
763 case DRV_OPEN :
764 case DRV_CLOSE :
765 {
766 SND_TRACE(L"DRV_OPEN / DRV_CLOSE\n");
767 return 1L;
768 }
769
770 case DRV_QUERYCONFIGURE :
771 {
772 SND_TRACE(L"DRV_QUERYCONFIGURE\n");
773 return 0L;
774 }
775 case DRV_CONFIGURE :
776 return DRVCNF_OK;
777
778 default :
779 SND_TRACE(L"Unhandled message %d\n", Message);
780 return DefDriverProc(DriverId,
781 DriverHandle,
782 Message,
783 Parameter1,
784 Parameter2);
785 }
786 }
787
788
789 BOOL WINAPI DllMain(
790 HINSTANCE hinstDLL,
791 DWORD fdwReason,
792 LPVOID lpvReserved)
793 {
794 switch ( fdwReason )
795 {
796 case DLL_PROCESS_ATTACH :
797 SND_TRACE(L"WDMAUD.DRV - Process attached\n");
798 break;
799 case DLL_PROCESS_DETACH :
800 SND_TRACE(L"WDMAUD.DRV - Process detached\n");
801 break;
802 case DLL_THREAD_ATTACH :
803 SND_TRACE(L"WDMAUD.DRV - Thread attached\n");
804 break;
805 case DLL_THREAD_DETACH :
806 SND_TRACE(L"WDMAUD.DRV - Thread detached\n");
807 break;
808 }
809
810 return TRUE;
811 }