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
14 KSSTREAM_HEADER Header
;
16 PSOUND_OVERLAPPED Overlap
;
17 LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
;
19 }IO_PACKET
, *LPIO_PACKET
;
21 BOOL MMixerLibraryInitialized
= FALSE
;
25 PVOID
Alloc(ULONG NumBytes
);
26 MIXER_STATUS
Close(HANDLE hDevice
);
27 VOID
Free(PVOID Block
);
28 VOID
Copy(PVOID Src
, PVOID Dst
, ULONG NumBytes
);
29 MIXER_STATUS
Open(IN LPWSTR DevicePath
, OUT PHANDLE hDevice
);
30 MIXER_STATUS
Control(IN HANDLE hMixer
, IN ULONG dwIoControlCode
, IN PVOID lpInBuffer
, IN ULONG nInBufferSize
, OUT PVOID lpOutBuffer
, ULONG nOutBufferSize
, PULONG lpBytesReturned
);
31 MIXER_STATUS
Enum(IN PVOID EnumContext
, IN ULONG DeviceIndex
, OUT LPWSTR
* DeviceName
, OUT PHANDLE OutHandle
, OUT PHANDLE OutKey
);
32 MIXER_STATUS
OpenKey(IN HANDLE hKey
, IN LPWSTR SubKey
, IN ULONG DesiredAccess
, OUT PHANDLE OutKey
);
33 MIXER_STATUS
CloseKey(IN HANDLE hKey
);
34 MIXER_STATUS
QueryKeyValue(IN HANDLE hKey
, IN LPWSTR KeyName
, OUT PVOID
* ResultBuffer
, OUT PULONG ResultLength
, OUT PULONG KeyType
);
35 PVOID
AllocEventData(IN ULONG ExtraSize
);
36 VOID
FreeEventData(IN PVOID EventData
);
38 MIXER_CONTEXT MixerContext
=
40 sizeof(MIXER_CONTEXT
),
55 GUID CategoryGuid
= {STATIC_KSCATEGORY_AUDIO
};
61 OUT PVOID
* ResultBuffer
,
62 OUT PULONG ResultLength
,
65 if (RegQueryValueExW((HKEY
)hKey
, KeyName
, NULL
, KeyType
, NULL
, ResultLength
) == ERROR_FILE_NOT_FOUND
)
66 return MM_STATUS_UNSUCCESSFUL
;
68 *ResultBuffer
= HeapAlloc(GetProcessHeap(), 0, *ResultLength
);
69 if (*ResultBuffer
== NULL
)
70 return MM_STATUS_NO_MEMORY
;
72 if (RegQueryValueExW((HKEY
)hKey
, KeyName
, NULL
, KeyType
, *ResultBuffer
, ResultLength
) != ERROR_SUCCESS
)
74 HeapFree(GetProcessHeap(), 0, *ResultBuffer
);
75 return MM_STATUS_UNSUCCESSFUL
;
77 return MM_STATUS_SUCCESS
;
84 IN ULONG DesiredAccess
,
87 if (RegOpenKeyExW((HKEY
)hKey
, SubKey
, 0, DesiredAccess
, (PHKEY
)OutKey
) == ERROR_SUCCESS
)
88 return MM_STATUS_SUCCESS
;
90 return MM_STATUS_UNSUCCESSFUL
;
97 RegCloseKey((HKEY
)hKey
);
98 return MM_STATUS_SUCCESS
;
102 PVOID
Alloc(ULONG NumBytes
)
104 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, NumBytes
);
108 Close(HANDLE hDevice
)
110 if (CloseHandle(hDevice
))
111 return MM_STATUS_SUCCESS
;
113 return MM_STATUS_UNSUCCESSFUL
;
119 HeapFree(GetProcessHeap(), 0, Block
);
123 Copy(PVOID Src
, PVOID Dst
, ULONG NumBytes
)
125 RtlMoveMemory(Src
, Dst
, NumBytes
);
130 IN LPWSTR DevicePath
,
133 DevicePath
[1] = L
'\\';
134 *hDevice
= CreateFileW(DevicePath
,
135 GENERIC_READ
| GENERIC_WRITE
,
139 FILE_FLAG_OVERLAPPED
,
141 if (*hDevice
== INVALID_HANDLE_VALUE
)
143 return MM_STATUS_UNSUCCESSFUL
;
146 return MM_STATUS_SUCCESS
;
152 IN ULONG dwIoControlCode
,
154 IN ULONG nInBufferSize
,
155 OUT PVOID lpOutBuffer
,
156 ULONG nOutBufferSize
,
157 PULONG lpBytesReturned
)
159 OVERLAPPED Overlapped
;
161 DWORD Transferred
= 0;
163 /* Overlapped I/O is done here - this is used for waiting for completion */
164 ZeroMemory(&Overlapped
, sizeof(OVERLAPPED
));
165 Overlapped
.hEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
167 if ( ! Overlapped
.hEvent
)
168 return MM_STATUS_NO_MEMORY
;
170 /* Talk to the device */
171 IoResult
= DeviceIoControl(hMixer
,
180 /* If failure occurs, make sure it's not just due to the overlapped I/O */
183 if ( GetLastError() != ERROR_IO_PENDING
)
185 CloseHandle(Overlapped
.hEvent
);
187 if (GetLastError() == ERROR_MORE_DATA
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
189 if ( lpBytesReturned
)
190 *lpBytesReturned
= Transferred
;
191 return MM_STATUS_MORE_ENTRIES
;
194 return MM_STATUS_UNSUCCESSFUL
;
198 /* Wait for the I/O to complete */
199 IoResult
= GetOverlappedResult(hMixer
,
204 /* Don't need this any more */
205 CloseHandle(Overlapped
.hEvent
);
208 return MM_STATUS_UNSUCCESSFUL
;
210 if ( lpBytesReturned
)
211 *lpBytesReturned
= Transferred
;
213 return MM_STATUS_SUCCESS
;
218 IN PVOID EnumContext
,
219 IN ULONG DeviceIndex
,
220 OUT LPWSTR
* DeviceName
,
221 OUT PHANDLE OutHandle
,
224 SP_DEVICE_INTERFACE_DATA InterfaceData
;
225 SP_DEVINFO_DATA DeviceData
;
226 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DetailData
;
231 //printf("Enum EnumContext %p DeviceIndex %lu OutHandle %p\n", EnumContext, DeviceIndex, OutHandle);
233 InterfaceData
.cbSize
= sizeof(InterfaceData
);
234 InterfaceData
.Reserved
= 0;
236 Result
= SetupDiEnumDeviceInterfaces(EnumContext
,
244 if (GetLastError() == ERROR_NO_MORE_ITEMS
)
246 return MM_STATUS_NO_MORE_DEVICES
;
248 return MM_STATUS_UNSUCCESSFUL
;
251 Length
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) + MAX_PATH
* sizeof(WCHAR
);
252 DetailData
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(),
255 DetailData
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
256 DeviceData
.cbSize
= sizeof(DeviceData
);
257 DeviceData
.Reserved
= 0;
259 Result
= SetupDiGetDeviceInterfaceDetailW(EnumContext
,
268 DPRINT("SetupDiGetDeviceInterfaceDetailW failed with %lu\n", GetLastError());
269 return MM_STATUS_UNSUCCESSFUL
;
273 *OutKey
= SetupDiOpenDeviceInterfaceRegKey(EnumContext
, &InterfaceData
, 0, KEY_READ
);
274 if ((HKEY
)*OutKey
== INVALID_HANDLE_VALUE
)
276 HeapFree(GetProcessHeap(), 0, DetailData
);
277 return MM_STATUS_UNSUCCESSFUL
;
280 Status
= Open(DetailData
->DevicePath
, OutHandle
);
282 if (Status
!= MM_STATUS_SUCCESS
)
284 RegCloseKey((HKEY
)*OutKey
);
285 HeapFree(GetProcessHeap(), 0, DetailData
);
289 *DeviceName
= (LPWSTR
)HeapAlloc(GetProcessHeap(), 0, (wcslen(DetailData
->DevicePath
)+1) * sizeof(WCHAR
));
290 if (*DeviceName
== NULL
)
292 CloseHandle(*OutHandle
);
293 RegCloseKey((HKEY
)*OutKey
);
294 HeapFree(GetProcessHeap(), 0, DetailData
);
295 return MM_STATUS_NO_MEMORY
;
297 wcscpy(*DeviceName
, DetailData
->DevicePath
);
298 HeapFree(GetProcessHeap(), 0, DetailData
);
307 PKSEVENTDATA Data
= (PKSEVENTDATA
)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(KSEVENTDATA
) + ExtraSize
);
311 Data
->EventHandle
.Event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
312 if (!Data
->EventHandle
.Event
)
314 HeapFree(GetProcessHeap(), 0, Data
);
318 Data
->NotificationType
= KSEVENTF_EVENT_HANDLE
;
323 FreeEventData(IN PVOID EventData
)
325 PKSEVENTDATA Data
= (PKSEVENTDATA
)EventData
;
327 CloseHandle(Data
->EventHandle
.Event
);
328 HeapFree(GetProcessHeap(), 0, Data
);
333 WdmAudInitUserModeMixer()
335 HDEVINFO DeviceHandle
;
338 if (MMixerLibraryInitialized
)
340 /* library is already initialized */
345 /* create a device list */
346 DeviceHandle
= SetupDiGetClassDevs(&CategoryGuid
,
349 DIGCF_DEVICEINTERFACE
/* FIXME |DIGCF_PRESENT*/);
351 if (DeviceHandle
== INVALID_HANDLE_VALUE
)
353 /* failed to create a device list */
358 /* initialize the mixer library */
359 Status
= MMixerInitialize(&MixerContext
, Enum
, (PVOID
)DeviceHandle
);
361 /* free device list */
362 SetupDiDestroyDeviceInfoList(DeviceHandle
);
364 if (Status
!= MM_STATUS_SUCCESS
)
366 /* failed to initialize mixer library */
367 DPRINT1("Failed to initialize mixer library with %x\n", Status
);
371 /* library is now initialized */
372 MMixerLibraryInitialized
= TRUE
;
374 /* completed successfully */
379 WdmAudCleanupByMMixer()
382 return MMSYSERR_NOERROR
;
386 WdmAudGetMixerCapabilties(
388 LPMIXERCAPSW Capabilities
)
390 if (MMixerGetCapabilities(&MixerContext
, DeviceId
, Capabilities
) == MM_STATUS_SUCCESS
)
391 return MMSYSERR_NOERROR
;
393 return MMSYSERR_BADDEVICEID
;
400 IN LPMIXERLINEW MixLine
,
403 if (MMixerGetLineInfo(&MixerContext
, hMixer
, MixerId
, Flags
, MixLine
) == MM_STATUS_SUCCESS
)
404 return MMSYSERR_NOERROR
;
406 return MMSYSERR_ERROR
;
410 WdmAudGetLineControls(
413 IN LPMIXERLINECONTROLSW MixControls
,
416 if (MMixerGetLineControls(&MixerContext
, hMixer
, MixerId
, Flags
, MixControls
) == MM_STATUS_SUCCESS
)
417 return MMSYSERR_NOERROR
;
419 return MMSYSERR_ERROR
;
423 WdmAudSetControlDetails(
426 IN LPMIXERCONTROLDETAILS MixDetails
,
429 if (MMixerSetControlDetails(&MixerContext
, hMixer
, MixerId
, Flags
, MixDetails
) == MM_STATUS_SUCCESS
)
430 return MMSYSERR_NOERROR
;
432 return MMSYSERR_ERROR
;
437 WdmAudGetControlDetails(
440 IN LPMIXERCONTROLDETAILS MixDetails
,
443 if (MMixerGetControlDetails(&MixerContext
, hMixer
, MixerId
, Flags
, MixDetails
) == MM_STATUS_SUCCESS
)
444 return MMSYSERR_NOERROR
;
446 return MMSYSERR_ERROR
;
450 WdmAudGetWaveOutCapabilities(
452 LPWAVEOUTCAPSW Capabilities
)
454 if (MMixerWaveOutCapabilities(&MixerContext
, DeviceId
, Capabilities
) == MM_STATUS_SUCCESS
)
455 return MMSYSERR_NOERROR
;
457 return MMSYSERR_ERROR
;
462 WdmAudGetWaveInCapabilities(
464 LPWAVEINCAPSW Capabilities
)
466 if (MMixerWaveInCapabilities(&MixerContext
, DeviceId
, Capabilities
) == MM_STATUS_SUCCESS
)
467 return MMSYSERR_NOERROR
;
469 return MMSYSERR_ERROR
;
473 WdmAudSetWaveDeviceFormatByMMixer(
474 IN PSOUND_DEVICE_INSTANCE Instance
,
476 IN PWAVEFORMATEX WaveFormat
,
477 IN DWORD WaveFormatSize
)
479 MMDEVICE_TYPE DeviceType
;
480 PSOUND_DEVICE SoundDevice
;
484 Result
= GetSoundDeviceFromInstance(Instance
, &SoundDevice
);
486 if ( ! MMSUCCESS(Result
) )
488 return TranslateInternalMmResult(Result
);
491 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
492 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
494 bWaveIn
= (DeviceType
== WAVE_IN_DEVICE_TYPE
? TRUE
: FALSE
);
496 if (MMixerOpenWave(&MixerContext
, DeviceId
, bWaveIn
, WaveFormat
, NULL
, NULL
, &Instance
->Handle
) == MM_STATUS_SUCCESS
)
498 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
500 MMixerSetWaveStatus(&MixerContext
, Instance
->Handle
, KSSTATE_ACQUIRE
);
501 MMixerSetWaveStatus(&MixerContext
, Instance
->Handle
, KSSTATE_PAUSE
);
502 MMixerSetWaveStatus(&MixerContext
, Instance
->Handle
, KSSTATE_RUN
);
504 return MMSYSERR_NOERROR
;
506 return MMSYSERR_ERROR
;
511 WdmAudGetCapabilitiesByMMixer(
512 IN PSOUND_DEVICE SoundDevice
,
514 OUT PVOID Capabilities
,
515 IN DWORD CapabilitiesSize
)
517 MMDEVICE_TYPE DeviceType
;
520 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
521 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
523 if (DeviceType
== MIXER_DEVICE_TYPE
)
525 return WdmAudGetMixerCapabilties(DeviceId
, (LPMIXERCAPSW
)Capabilities
);
527 else if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
529 return WdmAudGetWaveOutCapabilities(DeviceId
, (LPWAVEOUTCAPSW
)Capabilities
);
531 else if (DeviceType
== WAVE_IN_DEVICE_TYPE
)
533 return WdmAudGetWaveInCapabilities(DeviceId
, (LPWAVEINCAPSW
)Capabilities
);
538 return MMSYSERR_ERROR
;
543 WdmAudOpenSoundDeviceByMMixer(
544 IN
struct _SOUND_DEVICE
* SoundDevice
,
547 if (WdmAudInitUserModeMixer())
548 return MMSYSERR_NOERROR
;
550 return MMSYSERR_ERROR
;
554 WdmAudCloseSoundDeviceByMMixer(
555 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
558 MMDEVICE_TYPE DeviceType
;
559 PSOUND_DEVICE SoundDevice
;
562 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
564 if ( ! MMSUCCESS(Result
) )
566 return TranslateInternalMmResult(Result
);
569 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
570 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
572 if (DeviceType
== MIXER_DEVICE_TYPE
)
575 return MMSYSERR_NOERROR
;
577 else if (DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceType
== WAVE_OUT_DEVICE_TYPE
)
579 /* make sure the pin is stopped */
580 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_PAUSE
);
581 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_ACQUIRE
);
582 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_STOP
);
585 return MMSYSERR_NOERROR
;
588 /* midi is not supported */
589 return MMSYSERR_ERROR
;
593 WdmAudGetNumWdmDevsByMMixer(
594 IN MMDEVICE_TYPE DeviceType
,
595 OUT DWORD
* DeviceCount
)
599 case MIXER_DEVICE_TYPE
:
600 *DeviceCount
= MMixerGetCount(&MixerContext
);
602 case WAVE_OUT_DEVICE_TYPE
:
603 *DeviceCount
= MMixerGetWaveOutCount(&MixerContext
);
605 case WAVE_IN_DEVICE_TYPE
:
606 *DeviceCount
= MMixerGetWaveInCount(&MixerContext
);
611 return MMSYSERR_NOERROR
;
615 WdmAudQueryMixerInfoByMMixer(
616 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
622 LPMIXERLINEW MixLine
;
623 LPMIXERLINECONTROLSW MixControls
;
624 LPMIXERCONTROLDETAILS MixDetails
;
625 HANDLE hMixer
= NULL
;
627 MixLine
= (LPMIXERLINEW
)Parameter
;
628 MixControls
= (LPMIXERLINECONTROLSW
)Parameter
;
629 MixDetails
= (LPMIXERCONTROLDETAILS
)Parameter
;
631 /* FIXME param checks */
633 if (SoundDeviceInstance
)
635 hMixer
= SoundDeviceInstance
->Handle
;
640 case MXDM_GETLINEINFO
:
641 return WdmAudGetLineInfo(hMixer
, MixerId
, MixLine
, Flags
);
642 case MXDM_GETLINECONTROLS
:
643 return WdmAudGetLineControls(hMixer
, MixerId
, MixControls
, Flags
);
644 case MXDM_SETCONTROLDETAILS
:
645 return WdmAudSetControlDetails(hMixer
, MixerId
, MixDetails
, Flags
);
646 case MXDM_GETCONTROLDETAILS
:
647 return WdmAudGetControlDetails(hMixer
, MixerId
, MixDetails
, Flags
);
649 DPRINT1("MixerId %lu, uMsg %lu, Parameter %p, Flags %lu\n", MixerId
, uMsg
, Parameter
, Flags
);
651 return MMSYSERR_NOTSUPPORTED
;
656 WdmAudGetDeviceInterfaceStringByMMixer(
657 IN MMDEVICE_TYPE DeviceType
,
660 IN DWORD InterfaceLength
,
661 OUT DWORD
* InterfaceSize
)
664 return MMSYSERR_NOTSUPPORTED
;
670 IN PVOID MixerEventContext
,
672 IN ULONG NotificationType
,
675 PSOUND_DEVICE_INSTANCE Instance
= (PSOUND_DEVICE_INSTANCE
)MixerEventContext
;
677 DriverCallback(Instance
->WinMM
.ClientCallback
,
678 HIWORD(Instance
->WinMM
.Flags
),
679 Instance
->WinMM
.Handle
,
681 Instance
->WinMM
.ClientCallbackInstanceData
,
687 WdmAudSetMixerDeviceFormatByMMixer(
688 IN PSOUND_DEVICE_INSTANCE Instance
,
690 IN PWAVEFORMATEX WaveFormat
,
691 IN DWORD WaveFormatSize
)
693 if (MMixerOpen(&MixerContext
, DeviceId
, (PVOID
)Instance
, MixerEventCallback
, &Instance
->Handle
) == MM_STATUS_SUCCESS
)
694 return MMSYSERR_NOERROR
;
696 return MMSYSERR_BADDEVICEID
;
700 WdmAudSetWaveStateByMMixer(
701 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
704 MMDEVICE_TYPE DeviceType
;
705 PSOUND_DEVICE SoundDevice
;
708 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
709 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
712 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
713 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
715 if (DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceType
== WAVE_OUT_DEVICE_TYPE
)
719 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_ACQUIRE
);
720 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_PAUSE
);
721 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_RUN
);
725 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_PAUSE
);
726 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_ACQUIRE
);
727 MMixerSetWaveStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_STOP
);
730 else if (DeviceType
== MIDI_IN_DEVICE_TYPE
|| DeviceType
== MIDI_OUT_DEVICE_TYPE
)
734 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_ACQUIRE
);
735 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_PAUSE
);
736 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_RUN
);
740 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_PAUSE
);
741 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_ACQUIRE
);
742 MMixerSetMidiStatus(&MixerContext
, SoundDeviceInstance
->Handle
, KSSTATE_STOP
);
746 return MMSYSERR_NOERROR
;
750 WdmAudResetStreamByMMixer(
751 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
752 IN MMDEVICE_TYPE DeviceType
,
753 IN BOOLEAN bStartReset
)
757 if (DeviceType
== WAVE_IN_DEVICE_TYPE
|| DeviceType
== WAVE_OUT_DEVICE_TYPE
)
759 Status
= MMixerSetWaveResetState(&MixerContext
, SoundDeviceInstance
->Handle
, bStartReset
);
760 if (Status
== MM_STATUS_SUCCESS
)
762 /* completed successfully */
763 return MMSYSERR_NOERROR
;
768 return MMSYSERR_NOTSUPPORTED
;
772 WdmAudGetWavePositionByMMixer(
773 IN
struct _SOUND_DEVICE_INSTANCE
* SoundDeviceInstance
,
777 return MMSYSERR_NOTSUPPORTED
;
787 LPIO_PACKET Packet
= (LPIO_PACKET
)lpParameter
;
789 Result
= SyncOverlappedDeviceIoControl(Packet
->hDevice
,
794 sizeof(KSSTREAM_HEADER
),
797 Packet
->CompletionRoutine(ERROR_SUCCESS
, Packet
->Header
.DataUsed
, (LPOVERLAPPED
)Packet
->Overlap
);
799 HeapFree(GetProcessHeap(), 0, Packet
);
804 WdmAudCommitWaveBufferByMMixer(
805 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance
,
808 IN PSOUND_OVERLAPPED Overlap
,
809 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
)
811 PSOUND_DEVICE SoundDevice
;
812 MMDEVICE_TYPE DeviceType
;
817 Result
= GetSoundDeviceFromInstance(SoundDeviceInstance
, &SoundDevice
);
819 if ( ! MMSUCCESS(Result
) )
821 return TranslateInternalMmResult(Result
);
824 Result
= GetSoundDeviceType(SoundDevice
, &DeviceType
);
825 SND_ASSERT( Result
== MMSYSERR_NOERROR
);
827 Packet
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IO_PACKET
));
831 return MMSYSERR_NOMEM
;
834 /* setup stream packet */
835 Packet
->Header
.Size
= sizeof(KSSTREAM_HEADER
);
836 Packet
->Header
.PresentationTime
.Numerator
= 1;
837 Packet
->Header
.PresentationTime
.Denominator
= 1;
838 Packet
->Header
.Data
= OffsetPtr
;
839 Packet
->Header
.FrameExtent
= Length
;
840 Packet
->hDevice
= SoundDeviceInstance
->Handle
;
841 Packet
->Overlap
= Overlap
;
842 Packet
->CompletionRoutine
= CompletionRoutine
;
843 Packet
->IoCtl
= (DeviceType
== WAVE_OUT_DEVICE_TYPE
? IOCTL_KS_WRITE_STREAM
: IOCTL_KS_READ_STREAM
);
845 if (DeviceType
== WAVE_OUT_DEVICE_TYPE
)
847 Packet
->Header
.DataUsed
= Length
;
850 hThread
= CreateThread(NULL
, 0, IoStreamingThread
, (LPVOID
)Packet
, 0, NULL
);
854 return MMSYSERR_ERROR
;
857 CloseHandle(hThread
);
859 return MMSYSERR_NOERROR
;