2 * PROJECT: ReactOS Sound System
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/wdmaud.drv/mmixer.c
6 * PURPOSE: WDM Audio Mixer API (User-mode part)
7 * PROGRAMMERS: Johannes Anderwald
21 KSSTREAM_HEADER Header
;
23 PSOUND_OVERLAPPED Overlap
;
24 LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
;
26 }IO_PACKET
, *LPIO_PACKET
;
28 BOOL MMixerLibraryInitialized
= FALSE
;
32 PVOID
Alloc(ULONG NumBytes
);
33 MIXER_STATUS
Close(HANDLE hDevice
);
34 VOID
Free(PVOID Block
);
35 VOID
Copy(PVOID Src
, PVOID Dst
, ULONG NumBytes
);
36 MIXER_STATUS
Open(IN LPWSTR DevicePath
, OUT PHANDLE hDevice
);
37 MIXER_STATUS
Control(IN HANDLE hMixer
, IN ULONG dwIoControlCode
, IN PVOID lpInBuffer
, IN ULONG nInBufferSize
, OUT PVOID lpOutBuffer
, ULONG nOutBufferSize
, PULONG lpBytesReturned
);
38 MIXER_STATUS
Enum(IN PVOID EnumContext
, IN ULONG DeviceIndex
, OUT LPWSTR
* DeviceName
, OUT PHANDLE OutHandle
, OUT PHANDLE OutKey
);
39 MIXER_STATUS
OpenKey(IN HANDLE hKey
, IN LPWSTR SubKey
, IN ULONG DesiredAccess
, OUT PHANDLE OutKey
);
40 MIXER_STATUS
CloseKey(IN HANDLE hKey
);
41 MIXER_STATUS
QueryKeyValue(IN HANDLE hKey
, IN LPWSTR KeyName
, OUT PVOID
* ResultBuffer
, OUT PULONG ResultLength
, OUT PULONG KeyType
);
42 PVOID
AllocEventData(IN ULONG ExtraSize
);
43 VOID
FreeEventData(IN PVOID EventData
);
45 MIXER_CONTEXT MixerContext
=
47 sizeof(MIXER_CONTEXT
),
62 GUID CategoryGuid
= {STATIC_KSCATEGORY_AUDIO
};
68 OUT PVOID
* ResultBuffer
,
69 OUT PULONG ResultLength
,
72 if (RegQueryValueExW((HKEY
)hKey
, KeyName
, NULL
, KeyType
, NULL
, ResultLength
) == ERROR_FILE_NOT_FOUND
)
73 return MM_STATUS_UNSUCCESSFUL
;
75 *ResultBuffer
= HeapAlloc(GetProcessHeap(), 0, *ResultLength
);
76 if (*ResultBuffer
== NULL
)
77 return MM_STATUS_NO_MEMORY
;
79 if (RegQueryValueExW((HKEY
)hKey
, KeyName
, NULL
, KeyType
, *ResultBuffer
, ResultLength
) != ERROR_SUCCESS
)
81 HeapFree(GetProcessHeap(), 0, *ResultBuffer
);
82 return MM_STATUS_UNSUCCESSFUL
;
84 return MM_STATUS_SUCCESS
;
91 IN ULONG DesiredAccess
,
94 if (RegOpenKeyExW((HKEY
)hKey
, SubKey
, 0, DesiredAccess
, (PHKEY
)OutKey
) == ERROR_SUCCESS
)
95 return MM_STATUS_SUCCESS
;
97 return MM_STATUS_UNSUCCESSFUL
;
104 RegCloseKey((HKEY
)hKey
);
105 return MM_STATUS_SUCCESS
;
109 PVOID
Alloc(ULONG NumBytes
)
111 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, NumBytes
);
115 Close(HANDLE hDevice
)
117 if (CloseHandle(hDevice
))
118 return MM_STATUS_SUCCESS
;
120 return MM_STATUS_UNSUCCESSFUL
;
126 HeapFree(GetProcessHeap(), 0, Block
);
130 Copy(PVOID Src
, PVOID Dst
, ULONG NumBytes
)
132 RtlMoveMemory(Src
, Dst
, NumBytes
);
137 IN LPWSTR DevicePath
,
140 DevicePath
[1] = L
'\\';
141 *hDevice
= CreateFileW(DevicePath
,
142 GENERIC_READ
| GENERIC_WRITE
,
146 FILE_FLAG_OVERLAPPED
,
148 if (*hDevice
== INVALID_HANDLE_VALUE
)
150 return MM_STATUS_UNSUCCESSFUL
;
153 return MM_STATUS_SUCCESS
;
159 IN ULONG dwIoControlCode
,
161 IN ULONG nInBufferSize
,
162 OUT PVOID lpOutBuffer
,
163 ULONG nOutBufferSize
,
164 PULONG lpBytesReturned
)
166 OVERLAPPED Overlapped
;
168 DWORD Transferred
= 0;
170 /* Overlapped I/O is done here - this is used for waiting for completion */
171 ZeroMemory(&Overlapped
, sizeof(OVERLAPPED
));
172 Overlapped
.hEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
174 if ( ! Overlapped
.hEvent
)
175 return MM_STATUS_NO_MEMORY
;
177 /* Talk to the device */
178 IoResult
= DeviceIoControl(hMixer
,
187 /* If failure occurs, make sure it's not just due to the overlapped I/O */
190 if ( GetLastError() != ERROR_IO_PENDING
)
192 CloseHandle(Overlapped
.hEvent
);
194 if (GetLastError() == ERROR_MORE_DATA
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
196 if ( lpBytesReturned
)
197 *lpBytesReturned
= Transferred
;
198 return MM_STATUS_MORE_ENTRIES
;
201 return MM_STATUS_UNSUCCESSFUL
;
205 /* Wait for the I/O to complete */
206 IoResult
= GetOverlappedResult(hMixer
,
211 /* Don't need this any more */
212 CloseHandle(Overlapped
.hEvent
);
215 return MM_STATUS_UNSUCCESSFUL
;
217 if ( lpBytesReturned
)
218 *lpBytesReturned
= Transferred
;
220 return MM_STATUS_SUCCESS
;
225 IN PVOID EnumContext
,
226 IN ULONG DeviceIndex
,
227 OUT LPWSTR
* DeviceName
,
228 OUT PHANDLE OutHandle
,
231 SP_DEVICE_INTERFACE_DATA InterfaceData
;
232 SP_DEVINFO_DATA DeviceData
;
233 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DetailData
;
238 //printf("Enum EnumContext %p DeviceIndex %lu OutHandle %p\n", EnumContext, DeviceIndex, OutHandle);
240 InterfaceData
.cbSize
= sizeof(InterfaceData
);
241 InterfaceData
.Reserved
= 0;
243 Result
= SetupDiEnumDeviceInterfaces(EnumContext
,
251 if (GetLastError() == ERROR_NO_MORE_ITEMS
)
253 return MM_STATUS_NO_MORE_DEVICES
;
255 return MM_STATUS_UNSUCCESSFUL
;
258 Length
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) + MAX_PATH
* sizeof(WCHAR
);
259 DetailData
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(),
262 DetailData
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
263 DeviceData
.cbSize
= sizeof(DeviceData
);
264 DeviceData
.Reserved
= 0;
266 Result
= SetupDiGetDeviceInterfaceDetailW(EnumContext
,
275 DPRINT("SetupDiGetDeviceInterfaceDetailW failed with %lu\n", GetLastError());
276 return MM_STATUS_UNSUCCESSFUL
;
280 *OutKey
= SetupDiOpenDeviceInterfaceRegKey(EnumContext
, &InterfaceData
, 0, KEY_READ
);
281 if ((HKEY
)*OutKey
== INVALID_HANDLE_VALUE
)
283 HeapFree(GetProcessHeap(), 0, DetailData
);
284 return MM_STATUS_UNSUCCESSFUL
;
287 Status
= Open(DetailData
->DevicePath
, OutHandle
);
289 if (Status
!= MM_STATUS_SUCCESS
)
291 RegCloseKey((HKEY
)*OutKey
);
292 HeapFree(GetProcessHeap(), 0, DetailData
);
296 *DeviceName
= (LPWSTR
)HeapAlloc(GetProcessHeap(), 0, (wcslen(DetailData
->DevicePath
)+1) * sizeof(WCHAR
));
297 if (*DeviceName
== NULL
)
299 CloseHandle(*OutHandle
);
300 RegCloseKey((HKEY
)*OutKey
);
301 HeapFree(GetProcessHeap(), 0, DetailData
);
302 return MM_STATUS_NO_MEMORY
;
304 wcscpy(*DeviceName
, DetailData
->DevicePath
);
305 HeapFree(GetProcessHeap(), 0, DetailData
);
314 PKSEVENTDATA Data
= (PKSEVENTDATA
)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(KSEVENTDATA
) + ExtraSize
);
318 Data
->EventHandle
.Event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
319 if (!Data
->EventHandle
.Event
)
321 HeapFree(GetProcessHeap(), 0, Data
);
325 Data
->NotificationType
= KSEVENTF_EVENT_HANDLE
;
330 FreeEventData(IN PVOID EventData
)
332 PKSEVENTDATA Data
= (PKSEVENTDATA
)EventData
;
334 CloseHandle(Data
->EventHandle
.Event
);
335 HeapFree(GetProcessHeap(), 0, Data
);
340 WdmAudInitUserModeMixer()
342 HDEVINFO DeviceHandle
;
345 if (MMixerLibraryInitialized
)
347 /* library is already initialized */
352 /* create a device list */
353 DeviceHandle
= SetupDiGetClassDevs(&CategoryGuid
,
356 DIGCF_DEVICEINTERFACE
/* FIXME |DIGCF_PRESENT*/);
358 if (DeviceHandle
== INVALID_HANDLE_VALUE
)
360 /* failed to create a device list */
365 /* initialize the mixer library */
366 Status
= MMixerInitialize(&MixerContext
, Enum
, (PVOID
)DeviceHandle
);
368 /* free device list */
369 SetupDiDestroyDeviceInfoList(DeviceHandle
);
371 if (Status
!= MM_STATUS_SUCCESS
)
373 /* failed to initialize mixer library */
374 DPRINT1("Failed to initialize mixer library with %x\n", Status
);
378 /* library is now initialized */
379 MMixerLibraryInitialized
= TRUE
;
381 /* completed successfully */
386 WdmAudCleanupByMMixer()
389 return MMSYSERR_NOERROR
;
393 WdmAudGetMixerCapabilties(
395 LPMIXERCAPSW Capabilities
)
397 if (MMixerGetCapabilities(&MixerContext
, DeviceId
, Capabilities
) == MM_STATUS_SUCCESS
)
398 return MMSYSERR_NOERROR
;
400 return MMSYSERR_BADDEVICEID
;
407 IN LPMIXERLINEW MixLine
,
410 if (MMixerGetLineInfo(&MixerContext
, hMixer
, MixerId
, Flags
, MixLine
) == MM_STATUS_SUCCESS
)
411 return MMSYSERR_NOERROR
;
413 return MMSYSERR_ERROR
;
417 WdmAudGetLineControls(
420 IN LPMIXERLINECONTROLSW MixControls
,
423 if (MMixerGetLineControls(&MixerContext
, hMixer
, MixerId
, Flags
, MixControls
) == MM_STATUS_SUCCESS
)
424 return MMSYSERR_NOERROR
;
426 return MMSYSERR_ERROR
;
430 WdmAudSetControlDetails(
433 IN LPMIXERCONTROLDETAILS MixDetails
,
436 if (MMixerSetControlDetails(&MixerContext
, hMixer
, MixerId
, Flags
, MixDetails
) == MM_STATUS_SUCCESS
)
437 return MMSYSERR_NOERROR
;
439 return MMSYSERR_ERROR
;
444 WdmAudGetControlDetails(
447 IN LPMIXERCONTROLDETAILS MixDetails
,
450 if (MMixerGetControlDetails(&MixerContext
, hMixer
, MixerId
, Flags
, MixDetails
) == MM_STATUS_SUCCESS
)
451 return MMSYSERR_NOERROR
;
453 return MMSYSERR_ERROR
;
457 WdmAudGetWaveOutCapabilities(
459 LPWAVEOUTCAPSW Capabilities
)
461 if (MMixerWaveOutCapabilities(&MixerContext
, DeviceId
, Capabilities
) == MM_STATUS_SUCCESS
)
462 return MMSYSERR_NOERROR
;
464 return MMSYSERR_ERROR
;
469 WdmAudGetWaveInCapabilities(
471 LPWAVEINCAPSW Capabilities
)
473 if (MMixerWaveInCapabilities(&MixerContext
, DeviceId
, Capabilities
) == MM_STATUS_SUCCESS
)
474 return MMSYSERR_NOERROR
;
476 return MMSYSERR_ERROR
;
480 WdmAudSetWaveDeviceFormatByMMixer(
481 IN PSOUND_DEVICE_INSTANCE Instance
,
483 IN PWAVEFORMATEX WaveFormat
,
484 IN DWORD WaveFormatSize
)
486 MMDEVICE_TYPE DeviceType
;
487 PSOUND_DEVICE SoundDevice
;
491 Result
= GetSoundDeviceFromInstance(Instance
, &SoundDevice
);
493 if ( ! MMSUCCESS(Result
) )
495 return TranslateInternalMmResult(Result
);
498 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
499 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
501 bWaveIn
= (DeviceType
== WAVE_IN_DEVICE_TYPE
? TRUE
: FALSE
);
503 if (MMixerOpenWave(&MixerContext
, DeviceId
, bWaveIn
, WaveFormat
, NULL
, NULL
, &Instance
->Handle
) == MM_STATUS_SUCCESS
)
505 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
507 MMixerSetWaveStatus(&MixerContext
, Instance
->Handle
, KSSTATE_ACQUIRE
);
508 MMixerSetWaveStatus(&MixerContext
, Instance
->Handle
, KSSTATE_PAUSE
);
509 MMixerSetWaveStatus(&MixerContext
, Instance
->Handle
, KSSTATE_RUN
);
511 return MMSYSERR_NOERROR
;
513 return MMSYSERR_ERROR
;
518 WdmAudGetCapabilitiesByMMixer(
519 IN PSOUND_DEVICE SoundDevice
,
521 OUT PVOID Capabilities
,
522 IN DWORD CapabilitiesSize
)
524 MMDEVICE_TYPE DeviceType
;
527 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
528 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
530 if (DeviceType
== MIXER_DEVICE_TYPE
)
532 return WdmAudGetMixerCapabilties(DeviceId
, (LPMIXERCAPSW
)Capabilities
);
534 else if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
536 return WdmAudGetWaveOutCapabilities(DeviceId
, (LPWAVEOUTCAPSW
)Capabilities
);
538 else if (DeviceType
== WAVE_IN_DEVICE_TYPE
)
540 return WdmAudGetWaveInCapabilities(DeviceId
, (LPWAVEINCAPSW
)Capabilities
);
545 return MMSYSERR_ERROR
;
550 WdmAudOpenSoundDeviceByMMixer(
551 IN
struct _SOUND_DEVICE
* SoundDevice
,
554 if (WdmAudInitUserModeMixer())
555 return MMSYSERR_NOERROR
;
557 return MMSYSERR_ERROR
;
561 WdmAudCloseSoundDeviceByMMixer(
562 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
565 MMDEVICE_TYPE DeviceType
;
566 PSOUND_DEVICE SoundDevice
;
569 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
571 if ( ! MMSUCCESS(Result
) )
573 return TranslateInternalMmResult(Result
);
576 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
577 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
579 if (DeviceType
== MIXER_DEVICE_TYPE
)
582 return MMSYSERR_NOERROR
;
584 else if (DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceType
== WAVE_OUT_DEVICE_TYPE
)
586 /* make sure the pin is stopped */
587 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_PAUSE
);
588 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_ACQUIRE
);
589 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_STOP
);
592 return MMSYSERR_NOERROR
;
595 /* midi is not supported */
596 return MMSYSERR_ERROR
;
600 WdmAudGetNumWdmDevsByMMixer(
601 IN MMDEVICE_TYPE DeviceType
,
602 OUT DWORD
* DeviceCount
)
606 case MIXER_DEVICE_TYPE
:
607 *DeviceCount
= MMixerGetCount(&MixerContext
);
609 case WAVE_OUT_DEVICE_TYPE
:
610 *DeviceCount
= MMixerGetWaveOutCount(&MixerContext
);
612 case WAVE_IN_DEVICE_TYPE
:
613 *DeviceCount
= MMixerGetWaveInCount(&MixerContext
);
618 return MMSYSERR_NOERROR
;
622 WdmAudQueryMixerInfoByMMixer(
623 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
629 LPMIXERLINEW MixLine
;
630 LPMIXERLINECONTROLSW MixControls
;
631 LPMIXERCONTROLDETAILS MixDetails
;
632 HANDLE hMixer
= NULL
;
634 MixLine
= (LPMIXERLINEW
)Parameter
;
635 MixControls
= (LPMIXERLINECONTROLSW
)Parameter
;
636 MixDetails
= (LPMIXERCONTROLDETAILS
)Parameter
;
638 /* FIXME param checks */
640 if (SoundDeviceInstance
)
642 hMixer
= SoundDeviceInstance
->Handle
;
647 case MXDM_GETLINEINFO
:
648 return WdmAudGetLineInfo(hMixer
, MixerId
, MixLine
, Flags
);
649 case MXDM_GETLINECONTROLS
:
650 return WdmAudGetLineControls(hMixer
, MixerId
, MixControls
, Flags
);
651 case MXDM_SETCONTROLDETAILS
:
652 return WdmAudSetControlDetails(hMixer
, MixerId
, MixDetails
, Flags
);
653 case MXDM_GETCONTROLDETAILS
:
654 return WdmAudGetControlDetails(hMixer
, MixerId
, MixDetails
, Flags
);
656 DPRINT1("MixerId %lu, uMsg %lu, Parameter %p, Flags %lu\n", MixerId
, uMsg
, Parameter
, Flags
);
658 return MMSYSERR_NOTSUPPORTED
;
663 WdmAudGetDeviceInterfaceStringByMMixer(
664 IN MMDEVICE_TYPE DeviceType
,
667 IN DWORD InterfaceLength
,
668 OUT DWORD
* InterfaceSize
)
671 return MMSYSERR_NOTSUPPORTED
;
677 IN PVOID MixerEventContext
,
679 IN ULONG NotificationType
,
682 PSOUND_DEVICE_INSTANCE Instance
= (PSOUND_DEVICE_INSTANCE
)MixerEventContext
;
684 DriverCallback(Instance
->WinMM
.ClientCallback
,
685 HIWORD(Instance
->WinMM
.Flags
),
686 Instance
->WinMM
.Handle
,
688 Instance
->WinMM
.ClientCallbackInstanceData
,
694 WdmAudSetMixerDeviceFormatByMMixer(
695 IN PSOUND_DEVICE_INSTANCE Instance
,
697 IN PWAVEFORMATEX WaveFormat
,
698 IN DWORD WaveFormatSize
)
700 if (MMixerOpen(&MixerContext
, DeviceId
, (PVOID
)Instance
, MixerEventCallback
, &Instance
->Handle
) == MM_STATUS_SUCCESS
)
701 return MMSYSERR_NOERROR
;
703 return MMSYSERR_BADDEVICEID
;
707 WdmAudSetWaveStateByMMixer(
708 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
711 MMDEVICE_TYPE DeviceType
;
712 PSOUND_DEVICE SoundDevice
;
715 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
716 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
719 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
720 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
722 if (DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceType
== WAVE_OUT_DEVICE_TYPE
)
726 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_ACQUIRE
);
727 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_PAUSE
);
728 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_RUN
);
732 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_PAUSE
);
733 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_ACQUIRE
);
734 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_STOP
);
737 else if (DeviceType
== MIDI_IN_DEVICE_TYPE
|| DeviceType
== MIDI_OUT_DEVICE_TYPE
)
741 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_ACQUIRE
);
742 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_PAUSE
);
743 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_RUN
);
747 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_PAUSE
);
748 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_ACQUIRE
);
749 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_STOP
);
753 return MMSYSERR_NOERROR
;
757 WdmAudResetStreamByMMixer(
758 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
759 IN MMDEVICE_TYPE DeviceType
,
760 IN BOOLEAN bStartReset
)
764 if (DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceType
== WAVE_OUT_DEVICE_TYPE
)
766 Status
= MMixerSetWaveResetState(&MixerContext
, SoundDeviceInstance
->Handle
, bStartReset
);
767 if (Status
== MM_STATUS_SUCCESS
)
769 /* completed successfully */
770 return MMSYSERR_NOERROR
;
775 return MMSYSERR_NOTSUPPORTED
;
779 WdmAudGetWavePositionByMMixer(
780 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
784 return MMSYSERR_NOTSUPPORTED
;
794 LPIO_PACKET Packet
= (LPIO_PACKET
)lpParameter
;
796 /*Result = */ SyncOverlappedDeviceIoControl(Packet
->hDevice
,
801 sizeof(KSSTREAM_HEADER
),
804 Packet
->CompletionRoutine(ERROR_SUCCESS
, Packet
->Header
.DataUsed
, (LPOVERLAPPED
)Packet
->Overlap
);
806 HeapFree(GetProcessHeap(), 0, Packet
);
811 WdmAudCommitWaveBufferByMMixer(
812 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
815 IN PSOUND_OVERLAPPED Overlap
,
816 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
)
818 PSOUND_DEVICE SoundDevice
;
819 MMDEVICE_TYPE DeviceType
;
824 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
826 if ( ! MMSUCCESS(Result
) )
828 return TranslateInternalMmResult(Result
);
831 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
832 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
834 Packet
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IO_PACKET
));
838 return MMSYSERR_NOMEM
;
841 /* setup stream packet */
842 Packet
->Header
.Size
= sizeof(KSSTREAM_HEADER
);
843 Packet
->Header
.PresentationTime
.Numerator
= 1;
844 Packet
->Header
.PresentationTime
.Denominator
= 1;
845 Packet
->Header
.Data
= OffsetPtr
;
846 Packet
->Header
.FrameExtent
= Length
;
847 Packet
->hDevice
= SoundDeviceInstance
->Handle
;
848 Packet
->Overlap
= Overlap
;
849 Packet
->CompletionRoutine
= CompletionRoutine
;
850 Packet
->IoCtl
= (DeviceType
== WAVE_OUT_DEVICE_TYPE
? IOCTL_KS_WRITE_STREAM
: IOCTL_KS_READ_STREAM
);
852 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
854 Packet
->Header
.DataUsed
= Length
;
857 hThread
= CreateThread(NULL
, 0, IoStreamingThread
, (LPVOID
)Packet
, 0, NULL
);
861 return MMSYSERR_ERROR
;
864 CloseHandle(hThread
);
866 return MMSYSERR_NOERROR
;