diff --git a/dll/win32/wdmaud.drv/CMakeLists.txt b/dll/win32/wdmaud.drv/CMakeLists.txt index 16703b0d0fd4d..0bc70205c4047 100644 --- a/dll/win32/wdmaud.drv/CMakeLists.txt +++ b/dll/win32/wdmaud.drv/CMakeLists.txt @@ -8,10 +8,21 @@ include_directories( spec2def(wdmaud.drv wdmaud.spec) list(APPEND SOURCE - wdmaud.c - mixer.c - mmixer.c legacy.c + mmewrap.c + mmixer.c + reentrancy.c + resample.c + result.c + wdmaud.c + auxiliary/auxMessage.c + midi/midMessage.c + midi/modMessage.c + mixer/mxdMessage.c + wave/header.c + wave/streaming.c + wave/widMessage.c + wave/wodMessage.c wdmaud.h) add_library(wdmaud.drv MODULE @@ -21,7 +32,7 @@ add_library(wdmaud.drv MODULE set_module_type(wdmaud.drv win32dll UNICODE) set_target_properties(wdmaud.drv PROPERTIES SUFFIX "") -target_link_libraries(wdmaud.drv mmebuddy libsamplerate mmixer) +target_link_libraries(wdmaud.drv libsamplerate mmixer) add_importlibs(wdmaud.drv user32 winmm advapi32 msvcrt setupapi ksuser kernel32 ntdll) add_pch(wdmaud.drv wdmaud.h SOURCE) add_cd_file(TARGET wdmaud.drv DESTINATION reactos/system32 FOR all) diff --git a/dll/win32/wdmaud.drv/auxiliary/auxMessage.c b/dll/win32/wdmaud.drv/auxiliary/auxMessage.c new file mode 100644 index 0000000000000..7790599238fdc --- /dev/null +++ b/dll/win32/wdmaud.drv/auxiliary/auxMessage.c @@ -0,0 +1,71 @@ +/* + * PROJECT: ReactOS Sound System "MME Buddy" Library + * LICENSE: GPL - See COPYING in the top level directory + * FILE: lib/sound/mmebuddy/auxiliary/auxMessage.c + * + * PURPOSE: Provides the auxMessage exported function, as required by + * the MME API, for auxiliary device support. + * + * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) +*/ + +#include "wdmaud.h" + +#define YDEBUG +#include + +/* + Standard MME driver entry-point for messages relating to auxiliary devices. +*/ +DWORD +APIENTRY +auxMessage( + UINT DeviceId, + UINT Message, + DWORD_PTR PrivateHandle, + DWORD_PTR Parameter1, + DWORD_PTR Parameter2) +{ + MMRESULT Result = MMSYSERR_NOTSUPPORTED; + + AcquireEntrypointMutex(AUX_DEVICE_TYPE); + + DPRINT("auxMessage - Message type %d\n", Message); + + switch ( Message ) + { +#ifndef USE_MMIXER_LIB + case AUXM_INIT: + { + Result = WdmAudAddRemoveDeviceNode(AUX_DEVICE_TYPE, TRUE); + break; + } + + case DRVM_EXIT: + { + Result = WdmAudAddRemoveDeviceNode(AUX_DEVICE_TYPE, FALSE); + break; + } +#endif + + case AUXDM_GETNUMDEVS : + { + Result = MmeGetNumDevs(AUX_DEVICE_TYPE); + break; + } + + case AUXDM_GETDEVCAPS : + { + Result = MmeGetSoundDeviceCapabilities(AUX_DEVICE_TYPE, + DeviceId, + (MDEVICECAPSEX*)Parameter1); + break; + } + } + + DPRINT("auxMessage returning MMRESULT %d\n", Result); + + ReleaseEntrypointMutex(AUX_DEVICE_TYPE); + + return Result; +} diff --git a/dll/win32/wdmaud.drv/legacy.c b/dll/win32/wdmaud.drv/legacy.c index 00c9507341d8e..9ea5b2ce11fee 100644 --- a/dll/win32/wdmaud.drv/legacy.c +++ b/dll/win32/wdmaud.drv/legacy.c @@ -1,89 +1,265 @@ /* - * PROJECT: ReactOS Sound System - * LICENSE: GPL - See COPYING in the top level directory - * FILE: dll/win32/wdmaud.drv/wdmaud.c - * - * PURPOSE: WDM Audio Driver (User-mode part) - * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) - Johannes Anderwald - * - * NOTES: Looking for wodMessage & co? You won't find them here. Try - * the MME Buddy library, which is where these routines are - * actually implemented. - * + * PROJECT: ReactOS Audio Subsystem + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: WDM Audio Driver Mapper (User-mode part) + * COPYRIGHT: Copyright 2007-2008 Andrew Greenwood (silverblade@reactos.org) + * Copyright 2009-2010 Johannes Anderwald + * Copyright 2022 Oleg Dubinskiy (oleg.dubinskij30@gmail.com) */ #include "wdmaud.h" -#define NDEBUG -#include -#include +#include -#define KERNEL_DEVICE_NAME L"\\\\.\\wdmaud" +#define YDEBUG +#include +extern MIXER_CONTEXT MixerContext; HANDLE KernelHandle = INVALID_HANDLE_VALUE; DWORD OpenCount = 0; +/* + This is a wrapper around DeviceIoControl which provides control over + instantiated sound devices. It waits for I/O to complete (since an + instantiated sound device is opened _In_ overlapped mode, this is necessary). +*/ +MMRESULT +WdmAudIoControl( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_opt_ ULONG BufferSize, + _In_opt_ PVOID Buffer, + _In_ DWORD IoControlCode) +{ + MMRESULT Result = MMSYSERR_NOERROR; + OVERLAPPED Overlapped; + DWORD Transferred = 0; + BOOL IoResult; + + /* Overlapped I/O is done here - this is used for waiting for completion */ + ZeroMemory(&Overlapped, sizeof(OVERLAPPED)); + Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + if ( ! Overlapped.hEvent ) + return Win32ErrorToMmResult(GetLastError()); + + /* Store input data */ + DeviceInfo->BufferSize = BufferSize; + DeviceInfo->Buffer = Buffer; + + /* Talk to the device */ + IoResult = DeviceIoControl(KernelHandle, + IoControlCode, + DeviceInfo, + sizeof(WDMAUD_DEVICE_INFO), + DeviceInfo, + sizeof(WDMAUD_DEVICE_INFO), + &Transferred, + &Overlapped); + + /* If failure occurs, make sure it's not just due to the overlapped I/O */ + if ( ! IoResult ) + { + if (GetLastError() == ERROR_IO_PENDING) + { + /* Wait for I/O complete */ + WaitForSingleObject(Overlapped.hEvent, INFINITE); + } + Result = Win32ErrorToMmResult(GetLastError()); + } + + /* Don't need this any more */ + CloseHandle(Overlapped.hEvent); + + DPRINT("Transferred %d bytes in Sync overlapped I/O\n", Transferred); + + return Result; +} + DWORD WINAPI -MixerEventThreadRoutine( +WaveThreadRoutine( LPVOID Parameter) { - HANDLE WaitObjects[2]; - DWORD dwResult; + PWDMAUD_DEVICE_INFO DeviceInfo = (PWDMAUD_DEVICE_INFO)Parameter; + PWAVEHDR_EXTENSION HeaderExtension; + DWORD dwResult = WAIT_FAILED; + PWAVEHDR WaveHeader; +#ifndef USE_MMIXER_LIB MMRESULT Result; - WDMAUD_DEVICE_INFO DeviceInfo; - PSOUND_DEVICE_INSTANCE Instance = (PSOUND_DEVICE_INSTANCE)Parameter; +#endif + HANDLE hEvent; + + while (TRUE) + { + DPRINT("WaveQueue %p\n", DeviceInfo->DeviceState->WaveQueue); + WaveHeader = DeviceInfo->DeviceState->WaveQueue; + if (WaveHeader) + { + DPRINT("1\n"); + HeaderExtension = (PWAVEHDR_EXTENSION)WaveHeader->reserved; + if (HeaderExtension) + { + hEvent = HeaderExtension->Overlapped->hEvent; + DPRINT("2\n"); + + /* Wait for I/O complete */ + dwResult = WaitForSingleObject(hEvent, INFINITE); + DPRINT("dwResult %d\n", dwResult); + + DPRINT("3\n"); + if (DeviceInfo) + { + /* Complete current header */ + CompleteWaveHeader(DeviceInfo); + } + else + { + DPRINT1("Invalid device info data %p\n", DeviceInfo); + break; + } + } + else + { + /* Failed, move to the next header */ + DeviceInfo->DeviceState->WaveQueue = DeviceInfo->DeviceState->WaveQueue->lpNext; + } + } + else + { + /* Failed, move to the next header */ + DeviceInfo->DeviceState->WaveQueue = DeviceInfo->DeviceState->WaveQueue->lpNext; + } - /* setup wait objects */ - WaitObjects[0] = Instance->hNotifyEvent; - WaitObjects[1] = Instance->hStopEvent; + if (!WaveHeader) + { + DPRINT("6\n"); + if (DeviceInfo->DeviceState->bStart) + { + DPRINT("7\n"); +#ifdef USE_MMIXER_LIB + /* make sure the pin is stopped */ + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_PAUSE); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_ACQUIRE); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_STOP); +#else + /* Stop streaming if no more data to stream */ + Result = WdmAudIoControl(DeviceInfo, + 0, + NULL, + DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? + IOCTL_PAUSE_PLAYBACK : IOCTL_PAUSE_CAPTURE); + if (!MMSUCCESS(Result)) + { + DPRINT1("Call to %s failed with %d\n", + DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? + "IOCTL_PAUSE_PLAYBACK" : "IOCTL_PAUSE_CAPTURE", + GetLastError()); + break; + } +#endif + DeviceInfo->DeviceState->bStart = FALSE; + } + + /* Wait for stop event complete */ + WaitForSingleObject(DeviceInfo->DeviceState->hNotifyEvent, INFINITE); - /* zero device info */ - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); + /* Done */ + break; + } + } - DeviceInfo.hDevice = Instance->Handle; - DeviceInfo.DeviceType = MIXER_DEVICE_TYPE; + CloseHandle(DeviceInfo->DeviceState->hNotifyEvent); + SetEvent(DeviceInfo->DeviceState->hStopEvent); - do + /* Done */ + return 0; +} + +MMRESULT +WdmAudCreateCompletionThread( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo) +{ + if (!DeviceInfo->DeviceState->hThread) { - dwResult = WaitForMultipleObjects(2, WaitObjects, FALSE, INFINITE); + if (!DeviceInfo->DeviceState->hNotifyEvent) + { + DeviceInfo->DeviceState->hNotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + if (!DeviceInfo->DeviceState->hNotifyEvent) + { + DPRINT1("CreateEventW failed with %d\n", GetLastError()); + DeviceInfo->DeviceState->bStartInThread = FALSE; + return Win32ErrorToMmResult(GetLastError()); + } + } - if (dwResult == WAIT_OBJECT_0 + 1) + if (!DeviceInfo->DeviceState->hStopEvent) { - /* stop event was signalled */ - break; + DeviceInfo->DeviceState->hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + if (!DeviceInfo->DeviceState->hStopEvent) + { + DPRINT1("CreateEventW failed with %d\n", GetLastError()); + DeviceInfo->DeviceState->bStartInThread = FALSE; + /* Close previous handle */ + CloseHandle(DeviceInfo->DeviceState->hNotifyEvent); + return Win32ErrorToMmResult(GetLastError()); + } } - do + DeviceInfo->DeviceState->hThread = CreateThread(NULL, + 0, + WaveThreadRoutine, + DeviceInfo, + 0, + NULL); + if (!DeviceInfo->DeviceState->hThread) + { + DPRINT1("CreateThread failed with %d\n", GetLastError()); + DeviceInfo->DeviceState->bStartInThread = FALSE; + /* Close previous handles */ + CloseHandle(DeviceInfo->DeviceState->hNotifyEvent); + CloseHandle(DeviceInfo->DeviceState->hStopEvent); + return Win32ErrorToMmResult(GetLastError()); + } + SetThreadPriority(DeviceInfo->DeviceState->hThread, THREAD_PRIORITY_TIME_CRITICAL); + } + + DeviceInfo->DeviceState->bStartInThread = TRUE; + + return MMSYSERR_NOERROR; +} + +MMRESULT +WdmAudDestroyCompletionThread( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo) +{ + if (DeviceInfo->DeviceState->hThread) + { + if (DeviceInfo->DeviceState->hNotifyEvent) { - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_GET_MIXER_EVENT, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); - - if (Result == MMSYSERR_NOERROR) + if (DeviceInfo->DeviceState->bStartInThread) { - DriverCallback(Instance->WinMM.ClientCallback, - HIWORD(Instance->WinMM.Flags), - Instance->WinMM.Handle, - DeviceInfo.u.MixerEvent.NotificationType, - Instance->WinMM.ClientCallbackInstanceData, - (DWORD_PTR)DeviceInfo.u.MixerEvent.Value, - 0); + SetEvent(DeviceInfo->DeviceState->hNotifyEvent); } - }while(Result == MMSYSERR_NOERROR); - }while(TRUE); + } - /* done */ - return 0; + if (DeviceInfo->DeviceState->hStopEvent) + { + WaitForSingleObject(DeviceInfo->DeviceState->hStopEvent, INFINITE); + } + + CloseHandle(DeviceInfo->DeviceState->hThread); + + if (DeviceInfo->DeviceState->hStopEvent) + { + CloseHandle(DeviceInfo->DeviceState->hStopEvent); + } + } + + return MMSYSERR_NOERROR; } MMRESULT -WdmAudCleanupByLegacy() +WdmAudCleanupByLegacy(VOID) { if (KernelHandle != INVALID_HANDLE_VALUE) { @@ -95,167 +271,121 @@ WdmAudCleanupByLegacy() } MMRESULT -WdmAudGetNumWdmDevsByLegacy( - IN MMDEVICE_TYPE DeviceType, - OUT DWORD* DeviceCount) +WdmAudAddRemoveDeviceNode( + _In_ SOUND_DEVICE_TYPE DeviceType, + _In_ BOOL bAdd) { MMRESULT Result; - WDMAUD_DEVICE_INFO DeviceInfo; + PWDMAUD_DEVICE_INFO DeviceInfo; - VALIDATE_MMSYS_PARAMETER( KernelHandle != INVALID_HANDLE_VALUE ); VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) ); - VALIDATE_MMSYS_PARAMETER( DeviceCount ); - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.DeviceType = DeviceType; + DPRINT("WDMAUD - AddRemoveDeviceNode DeviceType %u\n", DeviceType); + + DeviceInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_INFO)); + if (!DeviceInfo) + { + /* No memory */ + DPRINT1("Failed to allocate WDMAUD_DEVICE_INFO structure\n"); + return MMSYSERR_NOMEM; + } + + DeviceInfo->DeviceType = DeviceType; - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_GETNUMDEVS_TYPE, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); + Result = WdmAudIoControl(DeviceInfo, + 0, + NULL, + bAdd ? + IOCTL_ADD_DEVNODE : + IOCTL_REMOVE_DEVNODE); + + HeapFree(GetProcessHeap(), 0, DeviceInfo); if ( ! MMSUCCESS( Result ) ) { - SND_ERR(L"Call to IOCTL_GETNUMDEVS_TYPE failed\n"); - *DeviceCount = 0; + DPRINT1("Call to %ls failed with %d\n", + bAdd ? L"IOCTL_ADD_DEVNODE" : L"IOCTL_REMOVE_DEVNODE", + GetLastError()); return TranslateInternalMmResult(Result); } - *DeviceCount = DeviceInfo.DeviceCount; - return MMSYSERR_NOERROR; } MMRESULT -WdmAudGetCapabilitiesByLegacy( - IN PSOUND_DEVICE SoundDevice, - IN DWORD DeviceId, - OUT PVOID Capabilities, - IN DWORD CapabilitiesSize) +WdmAudGetNumWdmDevsByLegacy( + _In_ SOUND_DEVICE_TYPE DeviceType, + _Out_ DWORD* DeviceCount) { MMRESULT Result; - MMDEVICE_TYPE DeviceType; - WDMAUD_DEVICE_INFO DeviceInfo; - - SND_ASSERT( SoundDevice ); - SND_ASSERT( Capabilities ); + PWDMAUD_DEVICE_INFO DeviceInfo; - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); + VALIDATE_MMSYS_PARAMETER( KernelHandle != INVALID_HANDLE_VALUE ); + VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) ); + VALIDATE_MMSYS_PARAMETER( DeviceCount ); - if ( ! MMSUCCESS(Result) ) - return Result; + DPRINT("WDMAUD - GetNumWdmDevs DeviceType %u\n", DeviceType); - SND_TRACE(L"WDMAUD - GetWdmDeviceCapabilities DeviceType %u DeviceId %u\n", DeviceType, DeviceId); + DeviceInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_INFO)); + if (!DeviceInfo) + { + /* No memory */ + DPRINT1("Failed to allocate WDMAUD_DEVICE_INFO structure\n"); + return MMSYSERR_NOMEM; + } - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.DeviceType = DeviceType; - DeviceInfo.DeviceIndex = DeviceId; + DeviceInfo->DeviceType = DeviceType; - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_GETCAPABILITIES, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); + Result = WdmAudIoControl(DeviceInfo, + 0, + NULL, + IOCTL_GETNUMDEVS_TYPE); - if ( ! MMSUCCESS(Result) ) + if ( ! MMSUCCESS( Result ) ) { + DPRINT1("Call to IOCTL_GETNUMDEVS_TYPE failed with %d\n", GetLastError()); + *DeviceCount = 0; + HeapFree(GetProcessHeap(), 0, DeviceInfo); return TranslateInternalMmResult(Result); } - /* This is pretty much a big hack right now */ - switch ( DeviceType ) - { - case MIXER_DEVICE_TYPE: - { - LPMIXERCAPSW MixerCaps = (LPMIXERCAPSW) Capabilities; - - DeviceInfo.u.MixCaps.szPname[MAXPNAMELEN-1] = L'\0'; - CopyWideString(MixerCaps->szPname, DeviceInfo.u.MixCaps.szPname); - - MixerCaps->cDestinations = DeviceInfo.u.MixCaps.cDestinations; - MixerCaps->fdwSupport = DeviceInfo.u.MixCaps.fdwSupport; - MixerCaps->vDriverVersion = DeviceInfo.u.MixCaps.vDriverVersion; - MixerCaps->wMid = DeviceInfo.u.MixCaps.wMid; - MixerCaps->wPid = DeviceInfo.u.MixCaps.wPid; - break; - } - case WAVE_OUT_DEVICE_TYPE : - { - LPWAVEOUTCAPSW WaveOutCaps = (LPWAVEOUTCAPSW) Capabilities; - - DeviceInfo.u.WaveOutCaps.szPname[MAXPNAMELEN-1] = L'\0'; - WaveOutCaps->wMid = DeviceInfo.u.WaveOutCaps.wMid; - WaveOutCaps->wPid = DeviceInfo.u.WaveOutCaps.wPid; - - WaveOutCaps->vDriverVersion = DeviceInfo.u.WaveOutCaps.vDriverVersion; - CopyWideString(WaveOutCaps->szPname, DeviceInfo.u.WaveOutCaps.szPname); - - WaveOutCaps->dwFormats = DeviceInfo.u.WaveOutCaps.dwFormats; - WaveOutCaps->wChannels = DeviceInfo.u.WaveOutCaps.wChannels; - WaveOutCaps->dwSupport = DeviceInfo.u.WaveOutCaps.dwSupport; - break; - } - case WAVE_IN_DEVICE_TYPE : - { - LPWAVEINCAPSW WaveInCaps = (LPWAVEINCAPSW) Capabilities; - - DeviceInfo.u.WaveInCaps.szPname[MAXPNAMELEN-1] = L'\0'; + *DeviceCount = DeviceInfo->DeviceIndex; - WaveInCaps->wMid = DeviceInfo.u.WaveInCaps.wMid; - WaveInCaps->wPid = DeviceInfo.u.WaveInCaps.wPid; - - WaveInCaps->vDriverVersion = DeviceInfo.u.WaveInCaps.vDriverVersion; - CopyWideString(WaveInCaps->szPname, DeviceInfo.u.WaveInCaps.szPname); - - WaveInCaps->dwFormats = DeviceInfo.u.WaveInCaps.dwFormats; - WaveInCaps->wChannels = DeviceInfo.u.WaveInCaps.wChannels; - WaveInCaps->wReserved1 = 0; - break; - } - case MIDI_IN_DEVICE_TYPE : - { - LPMIDIINCAPSW MidiInCaps = (LPMIDIINCAPSW)Capabilities; + HeapFree(GetProcessHeap(), 0, DeviceInfo); - DeviceInfo.u.MidiInCaps.szPname[MAXPNAMELEN-1] = L'\0'; + return MMSYSERR_NOERROR; +} - MidiInCaps->vDriverVersion = DeviceInfo.u.MidiInCaps.vDriverVersion; - MidiInCaps->wMid = DeviceInfo.u.MidiInCaps.wMid; - MidiInCaps->wPid = DeviceInfo.u.MidiInCaps.wPid; - MidiInCaps->dwSupport = DeviceInfo.u.MidiInCaps.dwSupport; +MMRESULT +WdmAudGetCapabilitiesByLegacy( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _Out_ MDEVICECAPSEX* Capabilities) +{ + MMRESULT Result; - CopyWideString(MidiInCaps->szPname, DeviceInfo.u.MidiInCaps.szPname); - break; - } - case MIDI_OUT_DEVICE_TYPE : - { - LPMIDIOUTCAPSW MidiOutCaps = (LPMIDIOUTCAPSW)Capabilities; + ASSERT( Capabilities ); - DeviceInfo.u.MidiOutCaps.szPname[MAXPNAMELEN-1] = L'\0'; + DPRINT("WDMAUD - GetWdmDeviceCapabilities DeviceType %u DeviceId %u\n", DeviceInfo->DeviceType, DeviceInfo->DeviceIndex); - MidiOutCaps->vDriverVersion = DeviceInfo.u.MidiOutCaps.vDriverVersion; - MidiOutCaps->wMid = DeviceInfo.u.MidiOutCaps.wMid; - MidiOutCaps->wPid = DeviceInfo.u.MidiOutCaps.wPid; - MidiOutCaps->dwSupport = DeviceInfo.u.MidiOutCaps.dwSupport; + Result = WdmAudIoControl(DeviceInfo, + Capabilities->cbSize, + Capabilities->pCaps, + IOCTL_GETCAPABILITIES); - CopyWideString(MidiOutCaps->szPname, DeviceInfo.u.MidiOutCaps.szPname); - break; - } + if ( ! MMSUCCESS(Result) ) + { + DPRINT1("Call to IOCTL_GETCAPABILITIES failed with %d\n", GetLastError()); + Capabilities = NULL; + return TranslateInternalMmResult(Result); } return MMSYSERR_NOERROR; } MMRESULT -WdmAudOpenSoundDeviceByLegacy( - IN PSOUND_DEVICE SoundDevice, - OUT PVOID *Handle) +WdmAudOpenKernelSoundDeviceByLegacy(VOID) { + DWORD dwSize; HDEVINFO hDevInfo; SP_DEVICE_INTERFACE_DATA DeviceInterfaceData; GUID SWBusGuid = {STATIC_KSCATEGORY_WDMAUD}; @@ -263,7 +393,7 @@ WdmAudOpenSoundDeviceByLegacy( if ( KernelHandle == INVALID_HANDLE_VALUE ) { - hDevInfo = SetupDiGetClassDevsW(&SWBusGuid, NULL, NULL, DIGCF_DEVICEINTERFACE| DIGCF_PRESENT); + hDevInfo = SetupDiGetClassDevsW(&SWBusGuid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); if (!hDevInfo) { // failed @@ -278,7 +408,9 @@ WdmAudOpenSoundDeviceByLegacy( return MMSYSERR_ERROR; } - DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)); + SetupDiGetDeviceInterfaceDetailW(hDevInfo, &DeviceInterfaceData, NULL, 0, &dwSize, NULL); + + DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), 0, dwSize); if (!DeviceInterfaceDetailData) { // failed @@ -287,21 +419,22 @@ WdmAudOpenSoundDeviceByLegacy( } DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W); - if (!SetupDiGetDeviceInterfaceDetailW(hDevInfo, &DeviceInterfaceData, DeviceInterfaceDetailData,MAX_PATH * sizeof(WCHAR) + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W), NULL, NULL)) + if (!SetupDiGetDeviceInterfaceDetailW(hDevInfo, &DeviceInterfaceData, DeviceInterfaceDetailData, dwSize, &dwSize, NULL)) { // failed HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData); SetupDiDestroyDeviceInfoList(hDevInfo); return MMSYSERR_ERROR; } - SND_TRACE(L"Opening wdmaud device '%s'\n",DeviceInterfaceDetailData->DevicePath); + + DPRINT("Opening wdmaud device '%ls'\n", DeviceInterfaceDetailData->DevicePath); KernelHandle = CreateFileW(DeviceInterfaceDetailData->DevicePath, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, - NULL); + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, + NULL); HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData); SetupDiDestroyDeviceInfoList(hDevInfo); @@ -317,643 +450,332 @@ WdmAudOpenSoundDeviceByLegacy( } MMRESULT -WdmAudCloseSoundDeviceByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN PVOID Handle) +WdmAudOpenSoundDeviceByLegacy( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEFORMATEX WaveFormat) { - WDMAUD_DEVICE_INFO DeviceInfo; MMRESULT Result; - MMDEVICE_TYPE DeviceType; - PSOUND_DEVICE SoundDevice; - - Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); - - if ( ! MMSUCCESS(Result) ) - { - return TranslateInternalMmResult(Result); - } if ( OpenCount == 0 ) { return MMSYSERR_NOERROR; } - SND_ASSERT( KernelHandle != INVALID_HANDLE_VALUE ); + ASSERT( KernelHandle != INVALID_HANDLE_VALUE ); - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); + DPRINT("WDMAUD - OpenWdmSoundDevice DeviceType %u\n", DeviceInfo->DeviceType); - if (SoundDeviceInstance->Handle != (PVOID)KernelHandle) - { - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - - DeviceInfo.DeviceType = DeviceType; - DeviceInfo.hDevice = SoundDeviceInstance->Handle; - - /* First stop the stream */ - if (DeviceType != MIXER_DEVICE_TYPE) - { - DeviceInfo.u.State = KSSTATE_PAUSE; - SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_SETDEVICE_STATE, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); - - DeviceInfo.u.State = KSSTATE_ACQUIRE; - SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_SETDEVICE_STATE, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); - - - DeviceInfo.u.State = KSSTATE_STOP; - SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_SETDEVICE_STATE, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); - } + /* Open device handle */ + Result = WdmAudIoControl(DeviceInfo, + sizeof(WAVEFORMATEX), + WaveFormat, + IOCTL_OPEN_WDMAUD); - SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_CLOSE_WDMAUD, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); - } - - if (DeviceType == MIXER_DEVICE_TYPE) + if ( ! MMSUCCESS( Result ) ) { - SetEvent(SoundDeviceInstance->hStopEvent); - CloseHandle(SoundDeviceInstance->hStopEvent); - CloseHandle(SoundDeviceInstance->hNotifyEvent); + DPRINT1("Call to IOCTL_OPEN_WDMAUD failed with %d\n", GetLastError()); + return TranslateInternalMmResult(Result); } - --OpenCount; + DeviceInfo->DeviceState->bStart = TRUE; - if ( OpenCount < 1 ) - { - CloseHandle(KernelHandle); - KernelHandle = INVALID_HANDLE_VALUE; - } +#ifdef RESAMPLING_ENABLED + DeviceInfo->Buffer = WaveFormat; + DeviceInfo->BufferSize = sizeof(WAVEFORMATEX); +#endif return MMSYSERR_NOERROR; } MMRESULT -WdmAudSetMixerDeviceFormatByLegacy( - IN PSOUND_DEVICE_INSTANCE Instance, - IN DWORD DeviceId, - IN PWAVEFORMATEX WaveFormat, - IN DWORD WaveFormatSize) +WdmAudCloseSoundDeviceByLegacy( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PVOID Handle) { MMRESULT Result; - WDMAUD_DEVICE_INFO DeviceInfo; - HANDLE hThread; - Instance->hNotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL); - if ( ! Instance->hNotifyEvent ) - return MMSYSERR_NOMEM; - - if (Instance->Handle != NULL) + if ( OpenCount == 0 ) { - /* device is already open */ return MMSYSERR_NOERROR; } - Instance->hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL); - if ( ! Instance->hStopEvent ) - return MMSYSERR_NOMEM; - - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.DeviceType = MIXER_DEVICE_TYPE; - DeviceInfo.DeviceIndex = DeviceId; - DeviceInfo.u.hNotifyEvent = Instance->hNotifyEvent; + ASSERT( KernelHandle != INVALID_HANDLE_VALUE ); - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_OPEN_WDMAUD, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); + DPRINT("WDMAUD - CloseWdmSoundDevice DeviceType %u\n", DeviceInfo->DeviceType); - if ( ! MMSUCCESS(Result) ) + if (DeviceInfo->hDevice != KernelHandle) { - CloseHandle(Instance->hNotifyEvent); - CloseHandle(Instance->hStopEvent); - return TranslateInternalMmResult(Result); + if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + { + /* Destroy I/O thread */ + Result = WdmAudDestroyCompletionThread(DeviceInfo); + ASSERT(Result == MMSYSERR_NOERROR); + } + + DeviceInfo->DeviceState->bStart = FALSE; + + /* Close device handle */ + Result = WdmAudIoControl(DeviceInfo, + 0, + NULL, + IOCTL_CLOSE_WDMAUD); + + if ( ! MMSUCCESS(Result) ) + { + DPRINT1("Call to IOCTL_CLOSE_WDMAUD failed with %d\n", GetLastError()); + return TranslateInternalMmResult(Result); + } } - hThread = CreateThread(NULL, 0, MixerEventThreadRoutine, (LPVOID)Instance, 0, NULL); - if ( hThread ) + --OpenCount; + + if ( OpenCount < 1 ) { - CloseHandle(hThread); + CloseHandle(KernelHandle); + KernelHandle = INVALID_HANDLE_VALUE; } - /* Store sound device handle instance handle */ - Instance->Handle = (PVOID)DeviceInfo.hDevice; - return MMSYSERR_NOERROR; } MMRESULT -WdmAudSetWaveDeviceFormatByLegacy( - IN PSOUND_DEVICE_INSTANCE Instance, - IN DWORD DeviceId, - IN PWAVEFORMATEX WaveFormat, - IN DWORD WaveFormatSize) +WdmAudSubmitWaveHeaderByLegacy( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEHDR WaveHeader) { - MMRESULT Result; - PSOUND_DEVICE SoundDevice; - PVOID Identifier; - WDMAUD_DEVICE_INFO DeviceInfo; - MMDEVICE_TYPE DeviceType; - - Result = GetSoundDeviceFromInstance(Instance, &SoundDevice); + PWDMAUD_DEVICE_INFO LocalDeviceInfo; + PWAVEHDR_EXTENSION HeaderExtension; + MMRESULT Result = MMSYSERR_NOERROR; + DWORD Transferred = 0; + BOOL IoResult; + DWORD IoCtl; - if ( ! MMSUCCESS(Result) ) - { - return TranslateInternalMmResult(Result); - } - - Result = GetSoundDeviceIdentifier(SoundDevice, &Identifier); - - if ( ! MMSUCCESS(Result) ) - { - return TranslateInternalMmResult(Result); - } + VALIDATE_MMSYS_PARAMETER( DeviceInfo ); - if (Instance->Handle != NULL) - { - /* device is already open */ - return MMSYSERR_NOERROR; - } + DPRINT("WDMAUD - SubmitWaveHeader DeviceType %u\n", DeviceInfo->DeviceType); - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - - SND_ASSERT( Result == MMSYSERR_NOERROR ); - - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.DeviceType = DeviceType; - DeviceInfo.DeviceIndex = DeviceId; - DeviceInfo.u.WaveFormatEx.cbSize = sizeof(WAVEFORMATEX); //WaveFormat->cbSize; - DeviceInfo.u.WaveFormatEx.wFormatTag = WaveFormat->wFormatTag; -#ifdef USERMODE_MIXER - DeviceInfo.u.WaveFormatEx.nChannels = 2; - DeviceInfo.u.WaveFormatEx.nSamplesPerSec = 44100; - DeviceInfo.u.WaveFormatEx.nBlockAlign = 4; - DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = 176400; - DeviceInfo.u.WaveFormatEx.wBitsPerSample = 16; -#else - DeviceInfo.u.WaveFormatEx.nChannels = WaveFormat->nChannels; - DeviceInfo.u.WaveFormatEx.nSamplesPerSec = WaveFormat->nSamplesPerSec; - DeviceInfo.u.WaveFormatEx.nBlockAlign = WaveFormat->nBlockAlign; - DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = WaveFormat->nAvgBytesPerSec; - DeviceInfo.u.WaveFormatEx.wBitsPerSample = (DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec * 8) / (DeviceInfo.u.WaveFormatEx.nSamplesPerSec * DeviceInfo.u.WaveFormatEx.nChannels); +#ifdef RESAMPLING_ENABLED + /* Resample the stream */ + Result = WdmAudResampleStream(DeviceInfo, WaveHeader); + ASSERT( Result == MMSYSERR_NOERROR ); #endif - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_OPEN_WDMAUD, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); - - if ( ! MMSUCCESS(Result) ) + LocalDeviceInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_INFO)); + if (!LocalDeviceInfo) { - return TranslateInternalMmResult(Result); + /* No memory */ + DPRINT1("Failed to allocate WDMAUD_DEVICE_INFO structure\n"); + return MMSYSERR_NOMEM; } - if (WaveFormatSize >= sizeof(WAVEFORMAT)) - { - /* Store format */ - Instance->WaveFormatEx.wFormatTag = WaveFormat->wFormatTag; - Instance->WaveFormatEx.nChannels = WaveFormat->nChannels; - Instance->WaveFormatEx.nSamplesPerSec = WaveFormat->nSamplesPerSec; - Instance->WaveFormatEx.nBlockAlign = WaveFormat->nBlockAlign; - Instance->WaveFormatEx.nAvgBytesPerSec = WaveFormat->nAvgBytesPerSec; - } + HeaderExtension = (PWAVEHDR_EXTENSION)WaveHeader->reserved; + HeaderExtension->DeviceInfo = LocalDeviceInfo; - /* store details */ - Instance->WaveFormatEx.cbSize = sizeof(WAVEFORMATEX); - Instance->WaveFormatEx.wBitsPerSample = (DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec * 8) / (DeviceInfo.u.WaveFormatEx.nSamplesPerSec * DeviceInfo.u.WaveFormatEx.nChannels); + LocalDeviceInfo->DeviceType = DeviceInfo->DeviceType; + LocalDeviceInfo->DeviceIndex = DeviceInfo->DeviceIndex; + LocalDeviceInfo->hDevice = DeviceInfo->hDevice; + LocalDeviceInfo->Buffer = WaveHeader; + LocalDeviceInfo->BufferSize = sizeof(WAVEHDR); - /* Store sound device handle instance handle */ - Instance->Handle = (PVOID)DeviceInfo.hDevice; + if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + IoCtl = IOCTL_WRITEDATA; + else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) + IoCtl = IOCTL_READDATA; - /* Now determine framing requirements */ - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_GETFRAMESIZE, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); + IoResult = DeviceIoControl(KernelHandle, + IoCtl, + LocalDeviceInfo, + sizeof(WDMAUD_DEVICE_INFO), + LocalDeviceInfo, + sizeof(WDMAUD_DEVICE_INFO), + &Transferred, + HeaderExtension->Overlapped); + HeapFree(GetProcessHeap(), 0, LocalDeviceInfo); - if ( MMSUCCESS(Result) ) + if (!IoResult) { - if (DeviceInfo.u.FrameSize) + if (GetLastError() != ERROR_IO_PENDING) { - Instance->FrameSize = DeviceInfo.u.FrameSize * 2; - Instance->BufferCount = WaveFormat->nAvgBytesPerSec / Instance->FrameSize; - SND_TRACE(L"FrameSize %u BufferCount %u\n", Instance->FrameSize, Instance->BufferCount); + DPRINT1("Call to %s failed with %d\n", + DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? + "IOCTL_WRITEDATA" : "IOCTL_READDATA", + GetLastError()); } + Result = Win32ErrorToMmResult(GetLastError()); } - else + + if (MMSUCCESS(Result)) { - // use a default of 100 buffers - Instance->BufferCount = 100; + /* Create I/O thread */ + Result = WdmAudCreateCompletionThread(DeviceInfo); + if (!MMSUCCESS(Result)) + { + /* Failed */ + DPRINT1("Failed to create sound thread with error %d\n", GetLastError()); + return TranslateInternalMmResult(Result); + } } - /* Now acquire resources */ - DeviceInfo.u.State = KSSTATE_ACQUIRE; - SyncOverlappedDeviceIoControl(KernelHandle, IOCTL_SETDEVICE_STATE, (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), NULL); - - /* pause the pin */ - DeviceInfo.u.State = KSSTATE_PAUSE; - SyncOverlappedDeviceIoControl(KernelHandle, IOCTL_SETDEVICE_STATE, (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), NULL); - - /* start the pin */ - DeviceInfo.u.State = KSSTATE_RUN; - SyncOverlappedDeviceIoControl(KernelHandle, IOCTL_SETDEVICE_STATE, (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), NULL); - - - return MMSYSERR_NOERROR; -} - -VOID -CALLBACK -LegacyCompletionRoutine( - IN DWORD dwErrorCode, - IN DWORD dwNumberOfBytesTransferred, - IN LPOVERLAPPED lpOverlapped) -{ - PSOUND_OVERLAPPED Overlap; - PWDMAUD_DEVICE_INFO DeviceInfo; - - Overlap = (PSOUND_OVERLAPPED)lpOverlapped; - DeviceInfo = (PWDMAUD_DEVICE_INFO)Overlap->CompletionContext; + DPRINT("Transferred %d bytes in Sync overlapped I/O\n", Transferred); - /* Call mmebuddy overlap routine */ - Overlap->OriginalCompletionRoutine(dwErrorCode, DeviceInfo->Header.DataUsed, lpOverlapped); - - HeapFree(GetProcessHeap(), 0, DeviceInfo); + return Result; } MMRESULT -WdmAudCommitWaveBufferByLegacy( - IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, - IN PVOID OffsetPtr, - IN DWORD Length, - IN PSOUND_OVERLAPPED Overlap, - IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine) +WdmAudSetWaveStateByLegacy( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ BOOL bStart) { - HANDLE Handle; MMRESULT Result; - PWDMAUD_DEVICE_INFO DeviceInfo; - PSOUND_DEVICE SoundDevice; - MMDEVICE_TYPE DeviceType; - BOOL Ret; - - VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance ); - VALIDATE_MMSYS_PARAMETER( OffsetPtr ); - VALIDATE_MMSYS_PARAMETER( Overlap ); - VALIDATE_MMSYS_PARAMETER( CompletionRoutine ); - - GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle); - SND_ASSERT(Handle); - - Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); - - if ( ! MMSUCCESS(Result) ) - { - return TranslateInternalMmResult(Result); - } - - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); + DWORD IoCtl; - DeviceInfo = (PWDMAUD_DEVICE_INFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_INFO)); - if (!DeviceInfo) - { - // no memory - return MMSYSERR_NOMEM; - } - - DeviceInfo->Header.FrameExtent = Length; - if (DeviceType == WAVE_OUT_DEVICE_TYPE) - { - DeviceInfo->Header.DataUsed = Length; - } - DeviceInfo->Header.Data = OffsetPtr; - DeviceInfo->Header.Size = sizeof(WDMAUD_DEVICE_INFO); - DeviceInfo->Header.PresentationTime.Numerator = 1; - DeviceInfo->Header.PresentationTime.Denominator = 1; - DeviceInfo->hDevice = Handle; - DeviceInfo->DeviceType = DeviceType; + DPRINT("WDMAUD - SetWaveState DeviceType %u\n", DeviceInfo->DeviceType); + DeviceInfo->DeviceState->bStart = bStart; - // create completion event - Overlap->Standard.hEvent = Handle = CreateEventW(NULL, FALSE, FALSE, NULL); - if (Overlap->Standard.hEvent == NULL) + if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) { - // no memory - HeapFree(GetProcessHeap(), 0, DeviceInfo); - return MMSYSERR_NOMEM; + IoCtl = bStart ? IOCTL_START_CAPTURE : IOCTL_PAUSE_CAPTURE; } - - Overlap->OriginalCompletionRoutine = CompletionRoutine; - Overlap->CompletionContext = (PVOID)DeviceInfo; - - if (DeviceType == WAVE_OUT_DEVICE_TYPE) + else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { - Ret = WriteFileEx(KernelHandle, DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, LegacyCompletionRoutine); - if (Ret) - WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE); + IoCtl = bStart ? IOCTL_START_PLAYBACK : IOCTL_PAUSE_PLAYBACK; } - else if (DeviceType == WAVE_IN_DEVICE_TYPE) - { - Ret = ReadFileEx(KernelHandle, DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, LegacyCompletionRoutine); - if (Ret) - WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE); - } - - // close event handle - CloseHandle(Handle); - - return MMSYSERR_NOERROR; -} - -MMRESULT -WdmAudSetWaveStateByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN BOOL bStart) -{ - MMRESULT Result; - PSOUND_DEVICE SoundDevice; - WDMAUD_DEVICE_INFO DeviceInfo; - MMDEVICE_TYPE DeviceType; - HANDLE Handle; - Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); + Result = WdmAudIoControl(DeviceInfo, + 0, + NULL, + IoCtl); - if ( ! MMSUCCESS(Result) ) + if ( ! MMSUCCESS( Result ) ) { + DPRINT1("Call to %s failed with %d\n", + DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? + (bStart ? "IOCTL_START_PLAYBACK" : "IOCTL_PAUSE_PLAYBACK") : + (bStart ? "IOCTL_START_CAPTURE" : "IOCTL_PAUSE_CAPTURE"), + GetLastError()); return TranslateInternalMmResult(Result); } - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); - - Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle); - SND_ASSERT( Result == MMSYSERR_NOERROR ); - - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.hDevice = Handle; - DeviceInfo.DeviceType = DeviceType; - - if (bStart) - DeviceInfo.u.State = KSSTATE_RUN; - else - DeviceInfo.u.State = KSSTATE_PAUSE; - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_SETDEVICE_STATE, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); - - return Result; + return MMSYSERR_NOERROR; } MMRESULT -WdmAudGetDeviceInterfaceStringByLegacy( - IN MMDEVICE_TYPE DeviceType, - IN DWORD DeviceId, - IN LPWSTR Interface, - IN DWORD InterfaceLength, - OUT DWORD * InterfaceSize) +WdmAudResetStreamByLegacy( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ BOOL bStartReset) { - WDMAUD_DEVICE_INFO DeviceInfo; MMRESULT Result; + DWORD IoCtl; - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.DeviceType = DeviceType; - DeviceInfo.DeviceIndex = DeviceId; + DPRINT("WDMAUD - ResetWaveStream DeviceType %u\n", DeviceInfo->DeviceType); + DeviceInfo->DeviceState->bReset = bStartReset; + DeviceInfo->DeviceState->bStart = FALSE; - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_QUERYDEVICEINTERFACESTRING, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); + IoCtl = DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? + IOCTL_RESET_PLAYBACK : IOCTL_RESET_CAPTURE; + Result = WdmAudIoControl(DeviceInfo, + 0, + NULL, + IoCtl); if ( ! MMSUCCESS(Result) ) { + DPRINT1("Call to %s failed with %d\n", + DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? + "IOCTL_RESET_PLAYBACK" : "IOCTL_RESET_CAPTURE", + GetLastError()); return TranslateInternalMmResult(Result); } + Result = WdmAudDestroyCompletionThread(DeviceInfo); + ASSERT(Result == MMSYSERR_NOERROR); - if (!Interface) - { - SND_ASSERT(InterfaceSize); - - *InterfaceSize = DeviceInfo.u.Interface.DeviceInterfaceStringSize; - return MMSYSERR_NOERROR; - } - - if (InterfaceLength < DeviceInfo.u.Interface.DeviceInterfaceStringSize) - { - /* buffer is too small */ - return MMSYSERR_MOREDATA; - } - - DeviceInfo.u.Interface.DeviceInterfaceStringSize = InterfaceLength; - DeviceInfo.u.Interface.DeviceInterfaceString = Interface; - - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_QUERYDEVICEINTERFACESTRING, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); - - if ( MMSUCCESS(Result) && InterfaceLength > 2) - { - Interface[1] = L'\\'; - Interface[InterfaceLength-1] = L'\0'; - } - - return Result; + return MMSYSERR_NOERROR; } MMRESULT WdmAudGetWavePositionByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN MMTIME* Time) + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ MMTIME* Time) { MMRESULT Result; - PSOUND_DEVICE SoundDevice; - WDMAUD_DEVICE_INFO DeviceInfo; - MMDEVICE_TYPE DeviceType; - HANDLE Handle; + DWORD Position; + DWORD IoCtl; - Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); + DPRINT("WDMAUD - GetWavePosition DeviceType %u\n", DeviceInfo->DeviceType); - if ( ! MMSUCCESS(Result) ) - { - return TranslateInternalMmResult(Result); - } - - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); - - Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle); - SND_ASSERT( Result == MMSYSERR_NOERROR ); + IoCtl = DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? + IOCTL_GETOUTPOS : IOCTL_GETINPOS; - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.hDevice = Handle; - DeviceInfo.DeviceType = DeviceType; - - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_OPEN_WDMAUD, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); + Result = WdmAudIoControl(DeviceInfo, + sizeof(DWORD), + &Position, + IoCtl); if ( ! MMSUCCESS(Result) ) { + DPRINT1("Call to %s failed with %d\n", + DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? + "IOCTL_GETOUTPOS" : "IOCTL_GETINPOS", + GetLastError()); return TranslateInternalMmResult(Result); } - Time->wType = TIME_BYTES; - Time->u.cb = (DWORD)DeviceInfo.u.Position; + if (Time->wType == TIME_BYTES) + Time->u.cb = Position; return MMSYSERR_NOERROR; } - -MMRESULT -WdmAudResetStreamByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN MMDEVICE_TYPE DeviceType, - IN BOOLEAN bStartReset) -{ - MMRESULT Result; - HANDLE Handle; - WDMAUD_DEVICE_INFO DeviceInfo; - - Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle); - SND_ASSERT( Result == MMSYSERR_NOERROR ); - - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.hDevice = Handle; - DeviceInfo.DeviceType = DeviceType; - DeviceInfo.u.ResetStream = (bStartReset ? KSRESET_BEGIN : KSRESET_END); - - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_RESET_STREAM, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); - return Result; -} - MMRESULT WdmAudQueryMixerInfoByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN DWORD DeviceId, - IN UINT uMsg, - IN LPVOID Parameter, - IN DWORD Flags) + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ DWORD DeviceId, + _In_ UINT uMsg, + _In_ LPVOID Parameter, + _In_ DWORD Flags) { MMRESULT Result; - WDMAUD_DEVICE_INFO DeviceInfo; - HANDLE Handle; DWORD IoControlCode; - LPMIXERLINEW MixLine; - LPMIXERLINECONTROLSW MixControls; - LPMIXERCONTROLDETAILS MixDetails; - SND_TRACE(L"uMsg %x Flags %x\n", uMsg, Flags); + DPRINT("WDMAUD - QueryMixerInfo: uMsg %x Flags %x\n", uMsg, Flags); - Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle); - SND_ASSERT( Result == MMSYSERR_NOERROR ); - - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.hDevice = Handle; - DeviceInfo.DeviceIndex = DeviceId; - DeviceInfo.DeviceType = MIXER_DEVICE_TYPE; - DeviceInfo.Flags = Flags; - - MixLine = (LPMIXERLINEW)Parameter; - MixControls = (LPMIXERLINECONTROLSW)Parameter; - MixDetails = (LPMIXERCONTROLDETAILS)Parameter; + DeviceInfo->DeviceIndex = DeviceId; + DeviceInfo->DeviceType = MIXER_DEVICE_TYPE; + DeviceInfo->Flags = Flags; switch(uMsg) { case MXDM_GETLINEINFO: - RtlCopyMemory(&DeviceInfo.u.MixLine, MixLine, sizeof(MIXERLINEW)); IoControlCode = IOCTL_GETLINEINFO; break; case MXDM_GETLINECONTROLS: - RtlCopyMemory(&DeviceInfo.u.MixControls, MixControls, sizeof(MIXERLINECONTROLSW)); IoControlCode = IOCTL_GETLINECONTROLS; break; - case MXDM_SETCONTROLDETAILS: - RtlCopyMemory(&DeviceInfo.u.MixDetails, MixDetails, sizeof(MIXERCONTROLDETAILS)); + case MXDM_SETCONTROLDETAILS: IoControlCode = IOCTL_SETCONTROLDETAILS; break; - case MXDM_GETCONTROLDETAILS: - RtlCopyMemory(&DeviceInfo.u.MixDetails, MixDetails, sizeof(MIXERCONTROLDETAILS)); + case MXDM_GETCONTROLDETAILS: IoControlCode = IOCTL_GETCONTROLDETAILS; break; - default: - SND_ASSERT(0); - return MMSYSERR_NOTSUPPORTED; + default: + ASSERT(0); + break; } - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IoControlCode, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); + Result = WdmAudIoControl(DeviceInfo, + sizeof(Parameter), + Parameter, + IoControlCode); if ( ! MMSUCCESS(Result) ) { - return Result; - } - - switch(uMsg) - { - case MXDM_GETLINEINFO: - { - RtlCopyMemory(MixLine, &DeviceInfo.u.MixLine, sizeof(MIXERLINEW)); - break; - } + DPRINT1("Call to 0x%lx failed with %d\n", IoControlCode, GetLastError()); + return TranslateInternalMmResult(Result); } - return Result; + return MMSYSERR_NOERROR; } diff --git a/dll/win32/wdmaud.drv/midi/midMessage.c b/dll/win32/wdmaud.drv/midi/midMessage.c new file mode 100644 index 0000000000000..915111c1c9525 --- /dev/null +++ b/dll/win32/wdmaud.drv/midi/midMessage.c @@ -0,0 +1,99 @@ +/* + * PROJECT: ReactOS Sound System "MME Buddy" Library + * LICENSE: GPL - See COPYING in the top level directory + * FILE: lib/sound/mmebuddy/midi/midMessage.c + * + * PURPOSE: Provides the midMessage exported function, as required by + * the MME API, for MIDI input device support. + * + * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) +*/ + +#include "wdmaud.h" + +#define YDEBUG +#include + +/* + Standard MME driver entry-point for messages relating to MIDI input. +*/ +DWORD +APIENTRY +midMessage( + UINT DeviceId, + UINT Message, + DWORD_PTR PrivateHandle, + DWORD_PTR Parameter1, + DWORD_PTR Parameter2) +{ + MMRESULT Result = MMSYSERR_NOTSUPPORTED; + + AcquireEntrypointMutex(MIDI_IN_DEVICE_TYPE); + + DPRINT("midMessage - Message type %d\n", Message); + + switch ( Message ) + { +#ifndef USE_MMIXER_LIB + case MIDM_INIT: + { + Result = WdmAudAddRemoveDeviceNode(MIDI_IN_DEVICE_TYPE, TRUE); + break; + } + + case DRVM_EXIT: + { + Result = WdmAudAddRemoveDeviceNode(MIDI_IN_DEVICE_TYPE, FALSE); + break; + } +#endif + + case MIDM_GETNUMDEVS : + { + Result = MmeGetNumDevs(MIDI_IN_DEVICE_TYPE); + break; + } + + case MIDM_GETDEVCAPS : + { + Result = MmeGetSoundDeviceCapabilities(MIDI_IN_DEVICE_TYPE, + DeviceId, + (MDEVICECAPSEX*)Parameter1); + break; + } + + case MIDM_OPEN : + { + Result = MmeOpenDevice(MIDI_IN_DEVICE_TYPE, + DeviceId, + (LPWAVEOPENDESC) Parameter1, + Parameter2, + (DWORD_PTR*) PrivateHandle); + break; + } + + case MIDM_CLOSE : + { + Result = MmeCloseDevice(PrivateHandle); + break; + } + + case MIDM_START : + { + Result = MmeSetState(PrivateHandle, TRUE); + break; + } + + case MIDM_STOP : + { + Result = MmeSetState(PrivateHandle, FALSE); + break; + } + } + + DPRINT("midMessage returning MMRESULT %d\n", Result); + + ReleaseEntrypointMutex(MIDI_IN_DEVICE_TYPE); + + return Result; +} diff --git a/dll/win32/wdmaud.drv/midi/modMessage.c b/dll/win32/wdmaud.drv/midi/modMessage.c new file mode 100644 index 0000000000000..4ed9ca1fb16a2 --- /dev/null +++ b/dll/win32/wdmaud.drv/midi/modMessage.c @@ -0,0 +1,89 @@ +/* + * PROJECT: ReactOS Sound System "MME Buddy" Library + * LICENSE: GPL - See COPYING in the top level directory + * FILE: lib/sound/mmebuddy/midi/modMessage.c + * + * PURPOSE: Provides the modMessage exported function, as required by + * the MME API, for MIDI output device support. + * + * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) +*/ + +#include "wdmaud.h" + +#define YDEBUG +#include + +/* + Standard MME driver entry-point for messages relating to MIDI output. +*/ +DWORD +APIENTRY +modMessage( + UINT DeviceId, + UINT Message, + DWORD_PTR PrivateHandle, + DWORD_PTR Parameter1, + DWORD_PTR Parameter2) +{ + MMRESULT Result = MMSYSERR_NOTSUPPORTED; + + AcquireEntrypointMutex(MIDI_OUT_DEVICE_TYPE); + + DPRINT("modMessage - Message type %d\n", Message); + + switch ( Message ) + { +#ifndef USE_MMIXER_LIB + case MODM_INIT: + { + Result = WdmAudAddRemoveDeviceNode(MIDI_OUT_DEVICE_TYPE, TRUE); + break; + } + + case DRVM_EXIT: + { + Result = WdmAudAddRemoveDeviceNode(MIDI_OUT_DEVICE_TYPE, FALSE); + break; + } +#endif + + case MODM_GETNUMDEVS : + { + Result = MmeGetNumDevs(MIDI_OUT_DEVICE_TYPE); + break; + } + + case MODM_GETDEVCAPS : + { + Result = MmeGetSoundDeviceCapabilities(MIDI_OUT_DEVICE_TYPE, + DeviceId, + (MDEVICECAPSEX*)Parameter1); + break; + } + + case MODM_OPEN : + { + Result = MmeOpenDevice(MIDI_OUT_DEVICE_TYPE, + DeviceId, + (LPWAVEOPENDESC) Parameter1, /* unused */ + Parameter2, + (DWORD_PTR*)PrivateHandle); + break; + } + + case MODM_CLOSE : + { + Result = MmeCloseDevice(PrivateHandle); + + break; + } + + } + + DPRINT("modMessage returning MMRESULT %d\n", Result); + + ReleaseEntrypointMutex(MIDI_OUT_DEVICE_TYPE); + + return Result; +} diff --git a/dll/win32/wdmaud.drv/mixer/mxdMessage.c b/dll/win32/wdmaud.drv/mixer/mxdMessage.c new file mode 100644 index 0000000000000..4b872d6b1e0f7 --- /dev/null +++ b/dll/win32/wdmaud.drv/mixer/mxdMessage.c @@ -0,0 +1,157 @@ +/* + * PROJECT: ReactOS Sound System "MME Buddy" Library + * LICENSE: GPL - See COPYING in the top level directory + * FILE: lib/sound/mmebuddy/mixer/mxdMessage.c + * + * PURPOSE: Provides the mxdMessage exported function, as required by + * the MME API, for mixer device support. + * + * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) +*/ + +#include "wdmaud.h" + +#define YDEBUG +#include + +MMRESULT +MmeGetLineInfo( + IN UINT DeviceId, + IN UINT Message, + IN DWORD_PTR PrivateHandle, + IN DWORD_PTR Parameter1, + IN DWORD_PTR Parameter2) +{ + PWDMAUD_DEVICE_INFO DeviceInfo; + + DPRINT("Getting mixer info %u\n", Message); + + if ( PrivateHandle == 0 ) + { + return FUNC_NAME(WdmAudQueryMixerInfo)(NULL, DeviceId, Message, (LPVOID)Parameter1, Parameter2); + } + + VALIDATE_MMSYS_PARAMETER( PrivateHandle ); + DeviceInfo = (PWDMAUD_DEVICE_INFO) PrivateHandle; + + return FUNC_NAME(WdmAudQueryMixerInfo)(DeviceInfo, DeviceId, Message, (LPVOID)Parameter1, Parameter2); +} + + +/* + Standard MME driver entry-point for messages relating to mixers. +*/ +DWORD +APIENTRY +mxdMessage( + UINT DeviceId, + UINT Message, + DWORD_PTR PrivateHandle, + DWORD_PTR Parameter1, + DWORD_PTR Parameter2) +{ + MMRESULT Result = MMSYSERR_NOTSUPPORTED; + + AcquireEntrypointMutex(MIXER_DEVICE_TYPE); + + DPRINT("mxdMessage - Message type %d\n", Message); + + switch ( Message ) + { +#ifndef USE_MMIXER_LIB + case MXDM_INIT: + { + Result = WdmAudAddRemoveDeviceNode(MIXER_DEVICE_TYPE, TRUE); + break; + } + + case DRVM_EXIT: + { + Result = WdmAudAddRemoveDeviceNode(MIXER_DEVICE_TYPE, FALSE); + break; + } +#endif + + case MXDM_GETNUMDEVS : + { + Result = MmeGetNumDevs(MIXER_DEVICE_TYPE); + break; + } + + case MXDM_GETDEVCAPS : + { + Result = MmeGetSoundDeviceCapabilities(MIXER_DEVICE_TYPE, + DeviceId, + (MDEVICECAPSEX*)Parameter1); + break; + } + + case MXDM_OPEN : + { + Result = MmeOpenDevice(MIXER_DEVICE_TYPE, + DeviceId, + (LPWAVEOPENDESC) Parameter1, /* unused */ + Parameter2, + (DWORD_PTR*) PrivateHandle); + + break; + } + + case MXDM_CLOSE : + { + Result = MmeCloseDevice(PrivateHandle); + + break; + } + + case MXDM_GETCONTROLDETAILS : + { + Result = MmeGetLineInfo(DeviceId, + Message, + PrivateHandle, + Parameter1, + Parameter2); + + break; + } + + case MXDM_SETCONTROLDETAILS : + { + Result = MmeGetLineInfo(DeviceId, + Message, + PrivateHandle, + Parameter1, + Parameter2); + + break; + } + + case MXDM_GETLINECONTROLS : + { + Result = MmeGetLineInfo(DeviceId, + Message, + PrivateHandle, + Parameter1, + Parameter2); + + break; + } + + case MXDM_GETLINEINFO : + { + Result = MmeGetLineInfo(DeviceId, + Message, + PrivateHandle, + Parameter1, + Parameter2); + + break; + } + } + + DPRINT("mxdMessage returning MMRESULT %d\n", Result); + + ReleaseEntrypointMutex(MIXER_DEVICE_TYPE); + + return Result; +} diff --git a/dll/win32/wdmaud.drv/mmewrap.c b/dll/win32/wdmaud.drv/mmewrap.c new file mode 100644 index 0000000000000..5d2d7b866044f --- /dev/null +++ b/dll/win32/wdmaud.drv/mmewrap.c @@ -0,0 +1,335 @@ +/* + * PROJECT: ReactOS Sound System "MME Buddy" Library + * LICENSE: GPL - See COPYING in the top level directory + * FILE: lib/drivers/sound/mmebuddy/mmewrap.c + * + * PURPOSE: Interface between MME functions and MME Buddy's own. + * + * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) +*/ + +#include "wdmaud.h" + +#define YDEBUG +#include + +/* + Sets the device into running or stopped state +*/ + +MMRESULT +MmeSetState( + IN DWORD_PTR PrivateHandle, + IN BOOL bStart) +{ + PWDMAUD_DEVICE_INFO DeviceInfo; + + VALIDATE_MMSYS_PARAMETER( PrivateHandle ); + DeviceInfo = (PWDMAUD_DEVICE_INFO)PrivateHandle; + + VALIDATE_MMSYS_PARAMETER( DeviceInfo ); + + /* Try change state */ + return FUNC_NAME(WdmAudSetWaveState)(DeviceInfo, bStart); +} + +/* + Call the client application when something interesting happens (MME API + defines "interesting things" as device open, close, and buffer + completion.) +*/ +VOID +NotifyMmeClient( + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN UINT Message, + IN DWORD_PTR Parameter) +{ + ASSERT( DeviceInfo ); + + DPRINT("MME client callback - message %d, parameter %d\n", + (int) Message, + (int) Parameter); + + if ( DeviceInfo->dwCallback ) + { + DriverCallback(DeviceInfo->dwCallback, + HIWORD(DeviceInfo->Flags), + DeviceInfo->hDevice, + Message, + DeviceInfo->dwInstance, + Parameter, + 0); + } +} + +DWORD +MmeGetNumDevs( + IN SOUND_DEVICE_TYPE DeviceType) +{ + MMRESULT Result; + DWORD DeviceCount; + + VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) ); + + Result = FUNC_NAME(WdmAudGetNumWdmDevs)(DeviceType, &DeviceCount); + + if ( ! MMSUCCESS(Result) ) + { + DPRINT1("Error %d while obtaining number of devices\n", GetLastError()); + return 0; + } + + DPRINT("%d devices of type %d found\n", DeviceCount, DeviceType); + + return DeviceCount; +} + +/* + Obtains the capabilities of a sound device. This routine ensures that the + supplied CapabilitiesSize parameter at least meets the minimum size of the + relevant capabilities structure. + + Ultimately, it will call the GetCapabilities function specified in the + sound device's function table. Note that there are several of these, in a + union. This is simply to avoid manually typecasting when implementing the + functions. +*/ +MMRESULT +MmeGetSoundDeviceCapabilities( + IN SOUND_DEVICE_TYPE DeviceType, + IN DWORD DeviceId, + OUT MDEVICECAPSEX* Capabilities) +{ + PWDMAUD_DEVICE_INFO DeviceInfo; + MMRESULT Result; + + DPRINT("MME *_GETCAPS for device %d of type %d\n", DeviceId, DeviceType); + + /* FIXME: Validate device ID */ + VALIDATE_MMSYS_PARAMETER( Capabilities ); + VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) ); + + DeviceInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_INFO)); + if (!DeviceInfo) + { + /* No memory */ + return MMSYSERR_NOMEM; + } + + DeviceInfo->DeviceType = DeviceType; + DeviceInfo->DeviceIndex = DeviceId; + + Result = FUNC_NAME(WdmAudGetCapabilities)(DeviceInfo, + Capabilities); + + HeapFree(GetProcessHeap(), 0, DeviceInfo); + + return Result; +} + +MMRESULT +MmeOpenDevice( + IN SOUND_DEVICE_TYPE DeviceType, + IN UINT DeviceId, + IN LPWAVEOPENDESC OpenParameters, + IN DWORD Flags, + OUT DWORD_PTR* PrivateHandle) +{ + MMRESULT Result; + UINT Message; + PWDMAUD_DEVICE_INFO DeviceInfo; + + DPRINT("Opening device\n"); + + VALIDATE_MMSYS_PARAMETER( IS_WAVE_DEVICE_TYPE(DeviceType) || IS_MIXER_DEVICE_TYPE(DeviceType) || IS_MIDI_DEVICE_TYPE(DeviceType) ); /* FIXME? wave in too? */ + VALIDATE_MMSYS_PARAMETER( OpenParameters ); + + /* Check that winmm gave us a private handle to fill */ + VALIDATE_MMSYS_PARAMETER( PrivateHandle ); + + /* Allocate a new WDMAUD_DEVICE_INFO structure */ + DeviceInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_INFO)); + if (!DeviceInfo) + { + /* No memory */ + return MMSYSERR_NOMEM; + } + + /* Allocate a new WDMAUD_DEVICE_STATE structure */ + DeviceInfo->DeviceState = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_STATE)); + if (!DeviceInfo->DeviceState) + { + /* No memory */ + HeapFree(GetProcessHeap(), 0, DeviceInfo); + return MMSYSERR_NOMEM; + } + + if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE) + { + /* Check if the caller just wanted to know if a format is supported */ + if ( Flags & WAVE_FORMAT_QUERY ) + { +#if 0 + DeviceInfo->DeviceType = DeviceType; + DeviceInfo->DeviceIndex = DeviceId; + DeviceInfo->Flags = Flags; + + Result = FUNC_NAME(WdmAudOpenSoundDevice)(DeviceInfo, OpenParameters->lpFormat); + if (!MMSUCCESS(Result)) + { + DPRINT1("Audio format is not supported\n"); + Result = WAVERR_BADFORMAT; + } + + HeapFree(GetProcessHeap(), 0, DeviceInfo->DeviceState); + HeapFree(GetProcessHeap(), 0, DeviceInfo); + return Result; +#else + return MMSYSERR_NOERROR; +#endif + } + } + + DeviceInfo->DeviceType = DeviceType; + DeviceInfo->DeviceIndex = DeviceId; + DeviceInfo->hDevice = OpenParameters->hWave; + DeviceInfo->dwCallback = OpenParameters->dwCallback; + DeviceInfo->dwInstance = OpenParameters->dwInstance; + DeviceInfo->Flags = Flags; + DeviceInfo->hMixer = NULL; + DeviceInfo->NotificationType = 0; + DeviceInfo->Value = 0; + DeviceInfo->DeviceState->WaveQueue = NULL; + DeviceInfo->DeviceState->bStart = FALSE; + DeviceInfo->DeviceState->bStartInThread = FALSE; + DeviceInfo->DeviceState->hNotifyEvent = NULL; + DeviceInfo->DeviceState->hStopEvent = NULL; + DeviceInfo->DeviceState->hThread = NULL; + + /* Open sound device */ + Result = FUNC_NAME(WdmAudOpenSoundDevice)(DeviceInfo, OpenParameters->lpFormat); + if ( ! MMSUCCESS(Result) ) + { + HeapFree(GetProcessHeap(), 0, DeviceInfo->DeviceState); + HeapFree(GetProcessHeap(), 0, DeviceInfo); + return TranslateInternalMmResult(Result); + } + + /* Store the device info pointer in the private handle */ + *PrivateHandle = (DWORD_PTR)DeviceInfo; + + if (DeviceType == WAVE_OUT_DEVICE_TYPE || DeviceType == WAVE_IN_DEVICE_TYPE || + DeviceType == MIDI_OUT_DEVICE_TYPE || DeviceType == MIDI_IN_DEVICE_TYPE) + { + /* Let the application know the device is open */ + + if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + Message = WOM_OPEN; + else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) + Message = WIM_OPEN; + else if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE) + Message = MIM_OPEN; + else if (DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE) + Message = MOM_OPEN; + + ReleaseEntrypointMutex(DeviceType); + + NotifyMmeClient(DeviceInfo, + Message, + 0); + + AcquireEntrypointMutex(DeviceType); + } + + DPRINT("Device is now opened\n"); + + return MMSYSERR_NOERROR; +} + +MMRESULT +MmeCloseDevice( + IN DWORD_PTR PrivateHandle) +{ + MMRESULT Result; + PWDMAUD_DEVICE_INFO DeviceInfo; + UINT Message = 0; + + DPRINT("Closing wave device (WIDM_CLOSE / WODM_CLOSE)\n"); + + VALIDATE_MMSYS_PARAMETER( PrivateHandle ); + DeviceInfo = (PWDMAUD_DEVICE_INFO)PrivateHandle; + + if ( ! DeviceInfo ) + return MMSYSERR_INVALHANDLE; + + /* TODO: Check device is stopped! */ + + if (DeviceInfo->DeviceType != MIXER_DEVICE_TYPE) + { + ReleaseEntrypointMutex(DeviceInfo->DeviceType); + + if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + Message = WOM_CLOSE; + else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) + Message = WIM_CLOSE; + else if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE) + Message = MIM_CLOSE; + else if (DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE) + Message = MOM_CLOSE; + + /* TODO: Work with MIDI devices too */ + NotifyMmeClient(DeviceInfo, + Message, + 0); + + AcquireEntrypointMutex(DeviceInfo->DeviceType); + } + + /* Clode sound device */ + Result = FUNC_NAME(WdmAudCloseSoundDevice)(DeviceInfo, DeviceInfo->hDevice); + + /* Free device state */ + HeapFree(GetProcessHeap(), 0, DeviceInfo->DeviceState); + + /* Free device info */ + HeapFree(GetProcessHeap(), 0, DeviceInfo); + + return Result; +} + +MMRESULT +MmeResetWavePlayback( + IN DWORD_PTR PrivateHandle) +{ + PWDMAUD_DEVICE_INFO DeviceInfo; + + DPRINT("Resetting wave device (WODM_RESET)\n"); + + VALIDATE_MMSYS_PARAMETER( PrivateHandle ); + DeviceInfo = (PWDMAUD_DEVICE_INFO) PrivateHandle; + + return StopStreaming(DeviceInfo); +} + + +MMRESULT +MmeGetPosition( + IN DWORD_PTR PrivateHandle, + IN MMTIME* Time, + IN DWORD Size) +{ + PWDMAUD_DEVICE_INFO DeviceInfo; + + VALIDATE_MMSYS_PARAMETER( PrivateHandle ); + DeviceInfo = (PWDMAUD_DEVICE_INFO) PrivateHandle; + + if ( ! DeviceInfo ) + return MMSYSERR_INVALHANDLE; + + if ( Size != sizeof(MMTIME) ) + return MMSYSERR_INVALPARAM; + + /* Call the driver */ + return FUNC_NAME(WdmAudGetWavePosition)(DeviceInfo, Time); +} + diff --git a/dll/win32/wdmaud.drv/mmixer.c b/dll/win32/wdmaud.drv/mmixer.c index 8fc2ed6309c9b..3353097965e60 100644 --- a/dll/win32/wdmaud.drv/mmixer.c +++ b/dll/win32/wdmaud.drv/mmixer.c @@ -1,10 +1,9 @@ /* - * PROJECT: ReactOS Sound System - * LICENSE: GPL - See COPYING in the top level directory - * FILE: dll/win32/wdmaud.drv/mmixer.c - * + * PROJECT: ReactOS Audio Subsystem + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) * PURPOSE: WDM Audio Mixer API (User-mode part) - * PROGRAMMERS: Johannes Anderwald + * COPYRIGHT: Copyright 2009-2010 Johannes Anderwald + * Copyright 2022 Oleg Dubinskiy (oleg.dubinskij30@gmail.com) */ #include "wdmaud.h" @@ -12,31 +11,25 @@ #include #include #include -#define NTOS_MODE_USER -#include -#include -#define NDEBUG +#define YDEBUG #include -#include BOOL MMixerLibraryInitialized = FALSE; - - PVOID Alloc(ULONG NumBytes); MIXER_STATUS Close(HANDLE hDevice); VOID Free(PVOID Block); VOID Copy(PVOID Src, PVOID Dst, ULONG NumBytes); -MIXER_STATUS Open(IN LPWSTR DevicePath, OUT PHANDLE hDevice); -MIXER_STATUS Control(IN HANDLE hMixer, IN ULONG dwIoControlCode, IN PVOID lpInBuffer, IN ULONG nInBufferSize, OUT PVOID lpOutBuffer, ULONG nOutBufferSize, PULONG lpBytesReturned); -MIXER_STATUS Enum(IN PVOID EnumContext, IN ULONG DeviceIndex, OUT LPWSTR * DeviceName, OUT PHANDLE OutHandle, OUT PHANDLE OutKey); -MIXER_STATUS OpenKey(IN HANDLE hKey, IN LPWSTR SubKey, IN ULONG DesiredAccess, OUT PHANDLE OutKey); -MIXER_STATUS CloseKey(IN HANDLE hKey); -MIXER_STATUS QueryKeyValue(IN HANDLE hKey, IN LPWSTR KeyName, OUT PVOID * ResultBuffer, OUT PULONG ResultLength, OUT PULONG KeyType); -PVOID AllocEventData(IN ULONG ExtraSize); -VOID FreeEventData(IN PVOID EventData); +MIXER_STATUS Open(_In_ LPWSTR DevicePath, _Out_ PHANDLE hDevice); +MIXER_STATUS Control(_In_ HANDLE hMixer, _In_ ULONG dwIoControlCode, _In_ PVOID lpInBuffer, _In_ ULONG nInBufferSize, _Out_ PVOID lpOutBuffer, ULONG nOutBufferSize, PULONG lpBytesReturned); +MIXER_STATUS Enum(_In_ PVOID EnumContext, _In_ ULONG DeviceIndex, _Out_ LPWSTR * DeviceName, _Out_ PHANDLE OutHandle, _Out_ PHANDLE OutKey); +MIXER_STATUS OpenKey(_In_ HANDLE hKey, _In_ LPWSTR SubKey, _In_ ULONG DesiredAccess, _Out_ PHANDLE OutKey); +MIXER_STATUS CloseKey(_In_ HANDLE hKey); +MIXER_STATUS QueryKeyValue(_In_ HANDLE hKey, _In_ LPWSTR KeyName, _Out_ PVOID * ResultBuffer, _Out_ PULONG ResultLength, _Out_ PULONG KeyType); +PVOID AllocEventData(_In_ ULONG ExtraSize); +VOID FreeEventData(_In_ PVOID EventData); MIXER_CONTEXT MixerContext = { @@ -59,11 +52,11 @@ GUID CategoryGuid = {STATIC_KSCATEGORY_AUDIO}; MIXER_STATUS QueryKeyValue( - IN HANDLE hKey, - IN LPWSTR KeyName, - OUT PVOID * ResultBuffer, - OUT PULONG ResultLength, - OUT PULONG KeyType) + _In_ HANDLE hKey, + _In_ LPWSTR KeyName, + _Out_ PVOID * ResultBuffer, + _Out_ PULONG ResultLength, + _Out_ PULONG KeyType) { if (RegQueryValueExW((HKEY)hKey, KeyName, NULL, KeyType, NULL, ResultLength) == ERROR_FILE_NOT_FOUND) return MM_STATUS_UNSUCCESSFUL; @@ -82,10 +75,10 @@ QueryKeyValue( MIXER_STATUS OpenKey( - IN HANDLE hKey, - IN LPWSTR SubKey, - IN ULONG DesiredAccess, - OUT PHANDLE OutKey) + _In_ HANDLE hKey, + _In_ LPWSTR SubKey, + _In_ ULONG DesiredAccess, + _Out_ PHANDLE OutKey) { if (RegOpenKeyExW((HKEY)hKey, SubKey, 0, DesiredAccess, (PHKEY)OutKey) == ERROR_SUCCESS) return MM_STATUS_SUCCESS; @@ -95,7 +88,7 @@ OpenKey( MIXER_STATUS CloseKey( - IN HANDLE hKey) + _In_ HANDLE hKey) { RegCloseKey((HKEY)hKey); return MM_STATUS_SUCCESS; @@ -130,8 +123,8 @@ Copy(PVOID Src, PVOID Dst, ULONG NumBytes) MIXER_STATUS Open( - IN LPWSTR DevicePath, - OUT PHANDLE hDevice) + _In_ LPWSTR DevicePath, + _Out_ PHANDLE hDevice) { DevicePath[1] = L'\\'; *hDevice = CreateFileW(DevicePath, @@ -139,7 +132,7 @@ Open( 0, NULL, OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); if (*hDevice == INVALID_HANDLE_VALUE) { @@ -151,11 +144,11 @@ Open( MIXER_STATUS Control( - IN HANDLE hMixer, - IN ULONG dwIoControlCode, - IN PVOID lpInBuffer, - IN ULONG nInBufferSize, - OUT PVOID lpOutBuffer, + _In_ HANDLE hMixer, + _In_ ULONG dwIoControlCode, + _In_ PVOID lpInBuffer, + _In_ ULONG nInBufferSize, + _Out_ PVOID lpOutBuffer, ULONG nOutBufferSize, PULONG lpBytesReturned) { @@ -196,6 +189,11 @@ Control( return MM_STATUS_UNSUCCESSFUL; } + else + { + DPRINT("Waiting...\n"); + WaitForSingleObject(Overlapped.hEvent, INFINITE); + } } /* Wait for the I/O to complete */ @@ -218,11 +216,11 @@ Control( MIXER_STATUS Enum( - IN PVOID EnumContext, - IN ULONG DeviceIndex, - OUT LPWSTR * DeviceName, - OUT PHANDLE OutHandle, - OUT PHANDLE OutKey) + _In_ PVOID EnumContext, + _In_ ULONG DeviceIndex, + _Out_ LPWSTR * DeviceName, + _Out_ PHANDLE OutHandle, + _Out_ PHANDLE OutKey) { SP_DEVICE_INTERFACE_DATA InterfaceData; SP_DEVINFO_DATA DeviceData; @@ -237,10 +235,10 @@ Enum( InterfaceData.Reserved = 0; Result = SetupDiEnumDeviceInterfaces(EnumContext, - NULL, - &CategoryGuid, - DeviceIndex, - &InterfaceData); + NULL, + &CategoryGuid, + DeviceIndex, + &InterfaceData); if (!Result) { @@ -305,7 +303,7 @@ Enum( PVOID AllocEventData( - IN ULONG ExtraSize) + _In_ ULONG ExtraSize) { PKSEVENTDATA Data = (PKSEVENTDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(KSEVENTDATA) + ExtraSize); if (!Data) @@ -323,7 +321,7 @@ AllocEventData( } VOID -FreeEventData(IN PVOID EventData) +FreeEventData(_In_ PVOID EventData) { PKSEVENTDATA Data = (PKSEVENTDATA)EventData; @@ -349,7 +347,7 @@ WdmAudInitUserModeMixer() DeviceHandle = SetupDiGetClassDevs(&CategoryGuid, NULL, NULL, - DIGCF_DEVICEINTERFACE/* FIXME |DIGCF_PRESENT*/); + DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); if (DeviceHandle == INVALID_HANDLE_VALUE) { @@ -379,7 +377,7 @@ WdmAudInitUserModeMixer() } MMRESULT -WdmAudCleanupByMMixer() +WdmAudCleanupByMMixer(VOID) { /* TODO */ return MMSYSERR_NOERROR; @@ -387,7 +385,7 @@ WdmAudCleanupByMMixer() MMRESULT WdmAudGetMixerCapabilities( - IN ULONG DeviceId, + _In_ ULONG DeviceId, LPMIXERCAPSW Capabilities) { if (MMixerGetCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS) @@ -398,10 +396,10 @@ WdmAudGetMixerCapabilities( MMRESULT WdmAudGetLineInfo( - IN HANDLE hMixer, - IN DWORD MixerId, - IN LPMIXERLINEW MixLine, - IN ULONG Flags) + _In_ HANDLE hMixer, + _In_ DWORD MixerId, + _In_ LPMIXERLINEW MixLine, + _In_ ULONG Flags) { if (MMixerGetLineInfo(&MixerContext, hMixer, MixerId, Flags, MixLine) == MM_STATUS_SUCCESS) return MMSYSERR_NOERROR; @@ -411,10 +409,10 @@ WdmAudGetLineInfo( MMRESULT WdmAudGetLineControls( - IN HANDLE hMixer, - IN DWORD MixerId, - IN LPMIXERLINECONTROLSW MixControls, - IN ULONG Flags) + _In_ HANDLE hMixer, + _In_ DWORD MixerId, + _In_ LPMIXERLINECONTROLSW MixControls, + _In_ ULONG Flags) { if (MMixerGetLineControls(&MixerContext, hMixer, MixerId, Flags, MixControls) == MM_STATUS_SUCCESS) return MMSYSERR_NOERROR; @@ -424,10 +422,10 @@ WdmAudGetLineControls( MMRESULT WdmAudSetControlDetails( - IN HANDLE hMixer, - IN DWORD MixerId, - IN LPMIXERCONTROLDETAILS MixDetails, - IN ULONG Flags) + _In_ HANDLE hMixer, + _In_ DWORD MixerId, + _In_ LPMIXERCONTROLDETAILS MixDetails, + _In_ ULONG Flags) { if (MMixerSetControlDetails(&MixerContext, hMixer, MixerId, Flags, MixDetails) == MM_STATUS_SUCCESS) return MMSYSERR_NOERROR; @@ -438,10 +436,10 @@ WdmAudSetControlDetails( MMRESULT WdmAudGetControlDetails( - IN HANDLE hMixer, - IN DWORD MixerId, - IN LPMIXERCONTROLDETAILS MixDetails, - IN ULONG Flags) + _In_ HANDLE hMixer, + _In_ DWORD MixerId, + _In_ LPMIXERCONTROLDETAILS MixDetails, + _In_ ULONG Flags) { if (MMixerGetControlDetails(&MixerContext, hMixer, MixerId, Flags, MixDetails) == MM_STATUS_SUCCESS) return MMSYSERR_NOERROR; @@ -451,7 +449,7 @@ WdmAudGetControlDetails( MMRESULT WdmAudGetWaveOutCapabilities( - IN ULONG DeviceId, + _In_ ULONG DeviceId, LPWAVEOUTCAPSW Capabilities) { if (MMixerWaveOutCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS) @@ -463,7 +461,7 @@ WdmAudGetWaveOutCapabilities( MMRESULT WdmAudGetWaveInCapabilities( - IN ULONG DeviceId, + _In_ ULONG DeviceId, LPWAVEINCAPSW Capabilities) { if (MMixerWaveInCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS) @@ -472,80 +470,88 @@ WdmAudGetWaveInCapabilities( return MMSYSERR_ERROR; } + +VOID +CALLBACK +MixerEventCallback( + _In_ PVOID MixerEventContext, + _In_ HANDLE hMixer, + _In_ ULONG NotificationType, + _In_ ULONG Value) +{ + PWDMAUD_DEVICE_INFO DeviceInfo = (PWDMAUD_DEVICE_INFO)MixerEventContext; + + DriverCallback(DeviceInfo->dwCallback, + HIWORD(DeviceInfo->Flags), + DeviceInfo->hDevice, + NotificationType, + DeviceInfo->dwInstance, + (DWORD_PTR)Value, + 0); +} + MMRESULT -WdmAudSetWaveDeviceFormatByMMixer( - IN PSOUND_DEVICE_INSTANCE Instance, - IN DWORD DeviceId, - IN PWAVEFORMATEX WaveFormat, - IN DWORD WaveFormatSize) -{ - MMDEVICE_TYPE DeviceType; - PSOUND_DEVICE SoundDevice; - MMRESULT Result; +WdmAudOpenSoundDeviceByMMixer( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEFORMATEX WaveFormat) +{ BOOL bWaveIn; - Result = GetSoundDeviceFromInstance(Instance, &SoundDevice); - - if ( ! MMSUCCESS(Result) ) + if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE) { - return TranslateInternalMmResult(Result); + if (MMixerOpen(&MixerContext, DeviceInfo->DeviceIndex, (PVOID)DeviceInfo, MixerEventCallback, &DeviceInfo->hDevice) == MM_STATUS_SUCCESS) + { + return MMSYSERR_NOERROR; + } } + else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + { + bWaveIn = (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE ? TRUE : FALSE); - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); + if (MMixerOpenWave(&MixerContext, DeviceInfo->DeviceIndex, bWaveIn, WaveFormat, NULL, NULL, &DeviceInfo->hDevice) == MM_STATUS_SUCCESS) + { - bWaveIn = (DeviceType == WAVE_IN_DEVICE_TYPE ? TRUE : FALSE); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_ACQUIRE); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_PAUSE); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_RUN); - if (MMixerOpenWave(&MixerContext, DeviceId, bWaveIn, WaveFormat, NULL, NULL, &Instance->Handle) == MM_STATUS_SUCCESS) - { - if (DeviceType == WAVE_OUT_DEVICE_TYPE) - { - MMixerSetWaveStatus(&MixerContext, Instance->Handle, KSSTATE_ACQUIRE); - MMixerSetWaveStatus(&MixerContext, Instance->Handle, KSSTATE_PAUSE); - MMixerSetWaveStatus(&MixerContext, Instance->Handle, KSSTATE_RUN); +#ifdef RESAMPLING_ENABLED + DeviceInfo->Buffer = WaveFormat; + DeviceInfo->BufferSize = sizeof(WAVEFORMATEX); +#endif + + return MMSYSERR_NOERROR; } - return MMSYSERR_NOERROR; } return MMSYSERR_ERROR; } - MMRESULT WdmAudGetCapabilitiesByMMixer( - IN PSOUND_DEVICE SoundDevice, - IN DWORD DeviceId, - OUT PVOID Capabilities, - IN DWORD CapabilitiesSize) + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _Out_ MDEVICECAPSEX* Capabilities) { - MMDEVICE_TYPE DeviceType; - MMRESULT Result; - - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); - - if (DeviceType == MIXER_DEVICE_TYPE) + if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE) { - return WdmAudGetMixerCapabilities(DeviceId, (LPMIXERCAPSW)Capabilities); + return WdmAudGetMixerCapabilities(DeviceInfo->DeviceIndex, (LPMIXERCAPSW)Capabilities->pCaps); } - else if (DeviceType == WAVE_OUT_DEVICE_TYPE) + else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { - return WdmAudGetWaveOutCapabilities(DeviceId, (LPWAVEOUTCAPSW)Capabilities); + return WdmAudGetWaveOutCapabilities(DeviceInfo->DeviceIndex, (LPWAVEOUTCAPSW)Capabilities->pCaps); } - else if (DeviceType == WAVE_IN_DEVICE_TYPE) + else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) { - return WdmAudGetWaveInCapabilities(DeviceId, (LPWAVEINCAPSW)Capabilities); + return WdmAudGetWaveInCapabilities(DeviceInfo->DeviceIndex, (LPWAVEINCAPSW)Capabilities->pCaps); } else { // not supported - return MMSYSERR_ERROR; + return MMSYSERR_NOTSUPPORTED; } } MMRESULT -WdmAudOpenSoundDeviceByMMixer( - IN struct _SOUND_DEVICE* SoundDevice, - OUT PVOID* Handle) +WdmAudOpenKernelSoundDeviceByMMixer(VOID) { if (WdmAudInitUserModeMixer()) return MMSYSERR_NOERROR; @@ -555,36 +561,28 @@ WdmAudOpenSoundDeviceByMMixer( MMRESULT WdmAudCloseSoundDeviceByMMixer( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN PVOID Handle) + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PVOID Handle) { - MMDEVICE_TYPE DeviceType; - PSOUND_DEVICE SoundDevice; MMRESULT Result; - Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); - - if ( ! MMSUCCESS(Result) ) + if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE) { - return TranslateInternalMmResult(Result); - } - - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); - - if (DeviceType == MIXER_DEVICE_TYPE) - { - /* no op */ + CloseHandle(DeviceInfo->hDevice); return MMSYSERR_NOERROR; } - else if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE) + else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { + /* Destroy I/O thread */ + Result = WdmAudDestroyCompletionThread(DeviceInfo); + ASSERT(Result == MMSYSERR_NOERROR); + /* make sure the pin is stopped */ - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE); - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE); - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_STOP); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_PAUSE); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_ACQUIRE); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_STOP); - CloseHandle(Handle); + CloseHandle(DeviceInfo->hDevice); return MMSYSERR_NOERROR; } @@ -594,8 +592,8 @@ WdmAudCloseSoundDeviceByMMixer( MMRESULT WdmAudGetNumWdmDevsByMMixer( - IN MMDEVICE_TYPE DeviceType, - OUT DWORD* DeviceCount) + _In_ SOUND_DEVICE_TYPE DeviceType, + _Out_ DWORD* DeviceCount) { switch(DeviceType) { @@ -616,11 +614,11 @@ WdmAudGetNumWdmDevsByMMixer( MMRESULT WdmAudQueryMixerInfoByMMixer( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN DWORD MixerId, - IN UINT uMsg, - IN LPVOID Parameter, - IN DWORD Flags) + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ DWORD MixerId, + _In_ UINT uMsg, + _In_ LPVOID Parameter, + _In_ DWORD Flags) { LPMIXERLINEW MixLine; LPMIXERLINECONTROLSW MixControls; @@ -633,9 +631,9 @@ WdmAudQueryMixerInfoByMMixer( /* FIXME param checks */ - if (SoundDeviceInstance) + if (DeviceInfo) { - hMixer = SoundDeviceInstance->Handle; + hMixer = DeviceInfo->hDevice; } switch(uMsg) @@ -644,105 +642,52 @@ WdmAudQueryMixerInfoByMMixer( return WdmAudGetLineInfo(hMixer, MixerId, MixLine, Flags); case MXDM_GETLINECONTROLS: return WdmAudGetLineControls(hMixer, MixerId, MixControls, Flags); - case MXDM_SETCONTROLDETAILS: + case MXDM_SETCONTROLDETAILS: return WdmAudSetControlDetails(hMixer, MixerId, MixDetails, Flags); - case MXDM_GETCONTROLDETAILS: + case MXDM_GETCONTROLDETAILS: return WdmAudGetControlDetails(hMixer, MixerId, MixDetails, Flags); - default: - DPRINT1("MixerId %lu, uMsg %lu, Parameter %p, Flags %lu\n", MixerId, uMsg, Parameter, Flags); - SND_ASSERT(0); - return MMSYSERR_NOTSUPPORTED; + default: + DPRINT1("MixerId %lu, uMsg %lu, Parameter %p, Flags %lu\n", MixerId, uMsg, Parameter, Flags); + ASSERT(0); + return MMSYSERR_NOTSUPPORTED; } } -MMRESULT -WdmAudGetDeviceInterfaceStringByMMixer( - IN MMDEVICE_TYPE DeviceType, - IN DWORD DeviceId, - IN LPWSTR Interface, - IN DWORD InterfaceLength, - OUT DWORD * InterfaceSize) -{ - /* FIXME */ - return MMSYSERR_NOTSUPPORTED; -} - -VOID -CALLBACK -MixerEventCallback( - IN PVOID MixerEventContext, - IN HANDLE hMixer, - IN ULONG NotificationType, - IN ULONG Value) -{ - PSOUND_DEVICE_INSTANCE Instance = (PSOUND_DEVICE_INSTANCE)MixerEventContext; - - DriverCallback(Instance->WinMM.ClientCallback, - HIWORD(Instance->WinMM.Flags), - Instance->WinMM.Handle, - NotificationType, - Instance->WinMM.ClientCallbackInstanceData, - (DWORD_PTR)Value, - 0); -} - -MMRESULT -WdmAudSetMixerDeviceFormatByMMixer( - IN PSOUND_DEVICE_INSTANCE Instance, - IN DWORD DeviceId, - IN PWAVEFORMATEX WaveFormat, - IN DWORD WaveFormatSize) -{ - if (MMixerOpen(&MixerContext, DeviceId, (PVOID)Instance, MixerEventCallback, &Instance->Handle) == MM_STATUS_SUCCESS) - return MMSYSERR_NOERROR; - - return MMSYSERR_BADDEVICEID; -} - MMRESULT WdmAudSetWaveStateByMMixer( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN BOOL bStart) + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ BOOL bStart) { - MMDEVICE_TYPE DeviceType; - PSOUND_DEVICE SoundDevice; - MMRESULT Result; - - Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); - SND_ASSERT( Result == MMSYSERR_NOERROR ); - + DeviceInfo->DeviceState->bStart = bStart; - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); - - if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE) + if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { if (bStart) { - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE); - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE); - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_RUN); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_ACQUIRE); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_PAUSE); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_RUN); } else { - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE); - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE); - MMixerSetWaveStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_STOP); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_PAUSE); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_ACQUIRE); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_STOP); } } - else if (DeviceType == MIDI_IN_DEVICE_TYPE || DeviceType == MIDI_OUT_DEVICE_TYPE) + else if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE || DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE) { if (bStart) { - MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE); - MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE); - MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_RUN); + MMixerSetMidiStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_ACQUIRE); + MMixerSetMidiStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_PAUSE); + MMixerSetMidiStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_RUN); } else { - MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_PAUSE); - MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_ACQUIRE); - MMixerSetMidiStatus(&MixerContext, SoundDeviceInstance->Handle, KSSTATE_STOP); + MMixerSetMidiStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_PAUSE); + MMixerSetMidiStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_ACQUIRE); + MMixerSetMidiStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_STOP); } } @@ -751,119 +696,142 @@ WdmAudSetWaveStateByMMixer( MMRESULT WdmAudResetStreamByMMixer( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN MMDEVICE_TYPE DeviceType, - IN BOOLEAN bStartReset) + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ BOOL bStartReset) { MIXER_STATUS Status; + MMRESULT Result; + + DeviceInfo->DeviceState->bReset = bStartReset; - if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE) + if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { - Status = MMixerSetWaveResetState(&MixerContext, SoundDeviceInstance->Handle, bStartReset); + Status = MMixerSetWaveResetState(&MixerContext, DeviceInfo->hDevice, bStartReset); if (Status == MM_STATUS_SUCCESS) { - /* completed successfully */ + /* Destroy I/O thread */ + Result = WdmAudDestroyCompletionThread(DeviceInfo); + ASSERT(Result == MMSYSERR_NOERROR); + + /* Completed successfully */ return MMSYSERR_NOERROR; } } - return MMSYSERR_NOTSUPPORTED; } MMRESULT WdmAudGetWavePositionByMMixer( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN MMTIME* Time) + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ MMTIME* Time) { - /* FIXME */ - return MMSYSERR_NOTSUPPORTED; -} - -static -VOID WINAPI -CommitWaveBufferApc(PVOID ApcContext, - PIO_STATUS_BLOCK IoStatusBlock, - ULONG Reserved) -{ - DWORD dwErrorCode; - PSOUND_OVERLAPPED Overlap; - KSSTREAM_HEADER* lpHeader; - - dwErrorCode = RtlNtStatusToDosError(IoStatusBlock->Status); - Overlap = (PSOUND_OVERLAPPED)IoStatusBlock; - lpHeader = Overlap->CompletionContext; + MIXER_STATUS Status; + DWORD Position; + DPRINT("wType %u\n", Time->wType); + if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + { + Status = MMixerGetWavePosition(&MixerContext, DeviceInfo->hDevice, &Position); + if (Status == MM_STATUS_SUCCESS) + { + if (Time->wType == TIME_BYTES) + Time->u.cb = Position; - /* Call mmebuddy overlap routine */ - Overlap->OriginalCompletionRoutine(dwErrorCode, - lpHeader->DataUsed, &Overlap->Standard); + /* Completed successfully */ + return MMSYSERR_NOERROR; + } + } - HeapFree(GetProcessHeap(), 0, lpHeader); + return MMSYSERR_NOTSUPPORTED; } MMRESULT -WdmAudCommitWaveBufferByMMixer( - IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, - IN PVOID OffsetPtr, - IN DWORD Length, - IN PSOUND_OVERLAPPED Overlap, - IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine) -{ - PSOUND_DEVICE SoundDevice; - MMDEVICE_TYPE DeviceType; - MMRESULT Result; - ULONG IoCtl; - KSSTREAM_HEADER* lpHeader; - NTSTATUS Status; - - Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); - - if ( ! MMSUCCESS(Result) ) - { - return TranslateInternalMmResult(Result); - } +WdmAudSubmitWaveHeaderByMMixer( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEHDR WaveHeader) +{ + MMRESULT Result = MMSYSERR_NOERROR; + PWAVEHDR_EXTENSION HeaderExtension; + PKSSTREAM_HEADER lpHeader; + DWORD Transferred = 0; + BOOL IoResult; + DWORD IoCtl; - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); +#ifdef RESAMPLING_ENABLED + /* Resample the stream */ + Result = WdmAudResampleStream(DeviceInfo, WaveHeader); + ASSERT( Result == MMSYSERR_NOERROR ); +#endif lpHeader = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(KSSTREAM_HEADER)); if ( ! lpHeader ) { - /* no memory */ + /* No memory */ return MMSYSERR_NOMEM; } - /* setup stream packet */ + HeaderExtension = (PWAVEHDR_EXTENSION)WaveHeader->reserved; + HeaderExtension->DeviceInfo = DeviceInfo; + + /* Setup stream header */ lpHeader->Size = sizeof(KSSTREAM_HEADER); lpHeader->PresentationTime.Numerator = 1; lpHeader->PresentationTime.Denominator = 1; - lpHeader->Data = OffsetPtr; - lpHeader->FrameExtent = Length; - Overlap->CompletionContext = lpHeader; - Overlap->OriginalCompletionRoutine = CompletionRoutine; - IoCtl = (DeviceType == WAVE_OUT_DEVICE_TYPE ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM); + lpHeader->Data = WaveHeader->lpData; + lpHeader->FrameExtent = WaveHeader->dwBufferLength; - if (DeviceType == WAVE_OUT_DEVICE_TYPE) + if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { - lpHeader->DataUsed = Length; + lpHeader->DataUsed = WaveHeader->dwBufferLength; } + else + { + lpHeader->DataUsed = 0; + } + + /* Set IOCTL */ + if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + IoCtl = IOCTL_KS_WRITE_STREAM; + else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) + IoCtl = IOCTL_KS_READ_STREAM; - Status = NtDeviceIoControlFile(SoundDeviceInstance->Handle, - NULL, - CommitWaveBufferApc, - NULL, - (PIO_STATUS_BLOCK)Overlap, - IoCtl, - NULL, - 0, - lpHeader, - sizeof(KSSTREAM_HEADER)); + /* Talk to the device */ + IoResult = DeviceIoControl(DeviceInfo->hDevice, + IoCtl, + NULL, + 0, + lpHeader, + sizeof(KSSTREAM_HEADER), + &Transferred, + HeaderExtension->Overlapped); + HeapFree(GetProcessHeap(), 0, lpHeader); - if (!NT_SUCCESS(Status)) + /* If failure occurs, make sure it's not just due to the overlapped I/O */ + if (!IoResult) { - DPRINT1("NtDeviceIoControlFile() failed with status %08lx\n", Status); - return MMSYSERR_ERROR; + if (GetLastError() != ERROR_IO_PENDING) + { + DPRINT1("Call to %s failed with %d\n", + DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? + "IOCTL_KS_WRITE_STREAM" : "IOCTL_KS_READ_STREAM", + GetLastError()); + } + Result = Win32ErrorToMmResult(GetLastError()); } - return MMSYSERR_NOERROR; + if (MMSUCCESS(Result)) + { + /* Create I/O thread */ + Result = WdmAudCreateCompletionThread(DeviceInfo); + if (!MMSUCCESS(Result)) + { + /* Failed */ + DPRINT1("Failed to create sound thread with error %d\n", GetLastError()); + return TranslateInternalMmResult(Result); + } + } + + DPRINT("Transferred %d bytes in Sync overlapped I/O\n", Transferred); + + return Result; } diff --git a/dll/win32/wdmaud.drv/reentrancy.c b/dll/win32/wdmaud.drv/reentrancy.c new file mode 100644 index 0000000000000..0725cdf2bc7cb --- /dev/null +++ b/dll/win32/wdmaud.drv/reentrancy.c @@ -0,0 +1,106 @@ +/* + * PROJECT: ReactOS Sound System "MME Buddy" Library + * LICENSE: GPL - See COPYING in the top level directory + * FILE: lib/sound/mmebuddy/reentrancy.c + * + * PURPOSE: Provides entry-point mutex guards. + * + * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) +*/ + +#include "wdmaud.h" + +#define YDEBUG +#include + +HANDLE EntrypointMutexes[SOUND_DEVICE_TYPES]; + +/* + Creates a set of mutexes which are used for the purpose of guarding the + device-type specific module entry-points. If any of these fail creation, + all of them will be destroyed and the failure reported. +*/ +MMRESULT +InitEntrypointMutexes() +{ + UCHAR i; + MMRESULT Result = MMSYSERR_NOERROR; + + /* Blank all entries ni the table first */ + for ( i = 0; i < SOUND_DEVICE_TYPES; ++ i ) + { + EntrypointMutexes[i] = NULL; + } + + /* Now create the mutexes */ + for ( i = 0; i < SOUND_DEVICE_TYPES; ++ i ) + { + EntrypointMutexes[i] = CreateMutex(NULL, FALSE, NULL); + + if ( ! EntrypointMutexes[i] ) + { + Result = Win32ErrorToMmResult(GetLastError()); + + /* Clean up any mutexes we successfully created */ + CleanupEntrypointMutexes(); + break; + } + } + + return Result; +} + +/* + Cleans up any of the entry-point guard mutexes. This will only close the + handles of mutexes which have been created, making it safe for use as a + cleanup routine even within the InitEntrypointMutexes routine above. +*/ +VOID +CleanupEntrypointMutexes() +{ + UCHAR i; + + /* Only clean up a mutex if it actually exists */ + for ( i = 0; i < SOUND_DEVICE_TYPES; ++ i ) + { + if ( EntrypointMutexes[i] ) + { + CloseHandle(EntrypointMutexes[i]); + EntrypointMutexes[i] = NULL; + } + } +} + +/* + Grabs an entry-point mutex. +*/ +VOID +AcquireEntrypointMutex( + IN SOUND_DEVICE_TYPE DeviceType) +{ + UCHAR i; + + ASSERT( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) ); + i = SOUND_DEVICE_TYPE_TO_INDEX(DeviceType); + + ASSERT( EntrypointMutexes[i] ); + + WaitForSingleObject(EntrypointMutexes[i], INFINITE); +} + +/* + Releases an entry-point mutex. +*/ +VOID +ReleaseEntrypointMutex( + IN SOUND_DEVICE_TYPE DeviceType) +{ + UCHAR i; + + ASSERT( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) ); + i = SOUND_DEVICE_TYPE_TO_INDEX(DeviceType); + + ASSERT( EntrypointMutexes[i] ); + + ReleaseMutex(EntrypointMutexes[i]); +} diff --git a/dll/win32/wdmaud.drv/mixer.c b/dll/win32/wdmaud.drv/resample.c similarity index 76% rename from dll/win32/wdmaud.drv/mixer.c rename to dll/win32/wdmaud.drv/resample.c index 73cd376277e18..e572af747da55 100644 --- a/dll/win32/wdmaud.drv/mixer.c +++ b/dll/win32/wdmaud.drv/resample.c @@ -1,10 +1,9 @@ /* - * PROJECT: ReactOS Sound System - * LICENSE: GPL - See COPYING in the top level directory - * FILE: dll/win32/wdmaud.drv/mixer.c - * - * PURPOSE: WDM Audio Driver (User-mode part) - * PROGRAMMERS: Johannes Anderwald + * PROJECT: ReactOS Sound Subsystem + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: WDM Audio Driver resampling routines + * COPYRIGHT: Copyright 2009-2010 Johannes Anderwald + * Copyright 2022 Oleg Dubinskiy (oleg.dubinskij30@gmail.com) */ #include "wdmaud.h" @@ -12,11 +11,9 @@ #include #include -#define NDEBUG +#define YDEBUG #include -#include -extern HANDLE KernelHandle; DWORD PerformSampleRateConversion( @@ -38,7 +35,7 @@ PerformSampleRateConversion( ULONG NumSamples; ULONG NewSamples; - //SND_TRACE(L"PerformSampleRateConversion OldRate %u NewRate %u BytesPerSample %u NumChannels %u\n", OldRate, NewRate, BytesPerSample, NumChannels); + DPRINT("PerformSampleRateConversion OldRate %u NewRate %u BytesPerSample %u NumChannels %u\n", OldRate, NewRate, BytesPerSample, NumChannels); ASSERT(BytesPerSample == 1 || BytesPerSample == 2 || BytesPerSample == 4); @@ -151,7 +148,7 @@ PerformChannelConversion( Samples = BufferLength / (BitsPerSample / 8) / OldChannels; - SND_TRACE(L"PerformChannelConversion OldChannels %u NewChannels %u\n", OldChannels, NewChannels); + DPRINT("PerformChannelConversion OldChannels %u NewChannels %u\n", OldChannels, NewChannels); if (NewChannels > OldChannels) { @@ -258,7 +255,6 @@ PerformChannelConversion( return ERROR_SUCCESS; } - DWORD PerformQualityConversion( PUCHAR Buffer, @@ -274,9 +270,9 @@ PerformQualityConversion( ASSERT(OldWidth != NewWidth); Samples = BufferLength / (OldWidth / 8); - //DPRINT("Samples %u BufferLength %u\n", Samples, BufferLength); - //SND_TRACE(L"PerformQualityConversion OldWidth %u NewWidth %u\n", OldWidth, NewWidth); + DPRINT("PerformQualityConversion OldWidth %u NewWidth %u\n", OldWidth, NewWidth); + DPRINT("Samples %u BufferLength %u\n", Samples, BufferLength); if (OldWidth == 8 && NewWidth == 16) { @@ -406,79 +402,55 @@ PerformQualityConversion( return ERROR_SUCCESS; } -VOID -CALLBACK -MixerCompletionRoutine( - IN DWORD dwErrorCode, - IN DWORD dwNumberOfBytesTransferred, - IN LPOVERLAPPED lpOverlapped) -{ - PSOUND_OVERLAPPED Overlap = (PSOUND_OVERLAPPED)lpOverlapped; - - /* Call mmebuddy overlap routine */ - Overlap->OriginalCompletionRoutine(dwErrorCode, PtrToUlong(Overlap->CompletionContext), lpOverlapped); -} MMRESULT -WriteFileEx_Remixer( - IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, - IN PVOID OffsetPtr, - IN DWORD Length, - IN PSOUND_OVERLAPPED Overlap, - IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine) +WdmAudResampleStream( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _Inout_ PWAVEHDR WaveHeader) { - HANDLE Handle; - WDMAUD_DEVICE_INFO DeviceInfo; DWORD BufferLength, BufferLengthTemp; PVOID BufferOut, BufferOutTemp; + PWAVEFORMATEX WaveFormatEx; DWORD Status; - BOOL Result; - - VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance ); - VALIDATE_MMSYS_PARAMETER( OffsetPtr ); - VALIDATE_MMSYS_PARAMETER( Overlap ); - VALIDATE_MMSYS_PARAMETER( CompletionRoutine ); - GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle); + VALIDATE_MMSYS_PARAMETER( DeviceInfo ); - SND_ASSERT(Handle); + /* Get wave format */ + WaveFormatEx = (PWAVEFORMATEX)DeviceInfo->Buffer; - BufferOut = OffsetPtr; - BufferLength = Length; + /* Get input data */ + BufferOut = WaveHeader->lpData; + BufferLength = WaveHeader->dwBufferLength; - if (SoundDeviceInstance->WaveFormatEx.wBitsPerSample != 16) + /* Do the resampling */ + if (WaveFormatEx->wBitsPerSample > 16) { - Status = PerformQualityConversion(OffsetPtr, - Length, - SoundDeviceInstance->WaveFormatEx.wBitsPerSample, + Status = PerformQualityConversion((PUCHAR)WaveHeader->lpData, + WaveHeader->dwBufferLength, + WaveFormatEx->wBitsPerSample, 16, &BufferOut, &BufferLength); if (Status) { - SND_TRACE(L"PerformQualityConversion failed\n"); + DPRINT("PerformQualityConversion failed\n"); return MMSYSERR_NOERROR; } } - if (SoundDeviceInstance->WaveFormatEx.nChannels != 2) + if (WaveFormatEx->nChannels > 2) { Status = PerformChannelConversion(BufferOut, BufferLength, - SoundDeviceInstance->WaveFormatEx.nChannels, + WaveFormatEx->nChannels, 2, 16, &BufferOutTemp, &BufferLengthTemp); - if (BufferOut != OffsetPtr) - { - HeapFree(GetProcessHeap(), 0, BufferOut); - } - if (Status) { - SND_TRACE(L"PerformChannelConversion failed\n"); + DPRINT("PerformChannelConversion failed\n"); return MMSYSERR_NOERROR; } @@ -486,25 +458,20 @@ WriteFileEx_Remixer( BufferLength = BufferLengthTemp; } - if (SoundDeviceInstance->WaveFormatEx.nSamplesPerSec != 44100) + if (WaveFormatEx->nSamplesPerSec > 48000) { Status = PerformSampleRateConversion(BufferOut, BufferLength, - SoundDeviceInstance->WaveFormatEx.nSamplesPerSec, + WaveFormatEx->nSamplesPerSec, 44100, 2, 2, &BufferOutTemp, &BufferLengthTemp); - if (BufferOut != OffsetPtr) - { - HeapFree(GetProcessHeap(), 0, BufferOut); - } - if (Status) { - SND_TRACE(L"PerformSampleRateConversion failed\n"); + DPRINT("PerformSampleRateConversion failed\n"); return MMSYSERR_NOERROR; } @@ -512,42 +479,11 @@ WriteFileEx_Remixer( BufferLength = BufferLengthTemp; } - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.hDevice = Handle; - DeviceInfo.DeviceType = WAVE_OUT_DEVICE_TYPE; //FIXME - DeviceInfo.Header.FrameExtent = BufferLength; - DeviceInfo.Header.DataUsed = BufferLength; - DeviceInfo.Header.Data = BufferOut; - DeviceInfo.Header.Size = sizeof(KSSTREAM_HEADER); - DeviceInfo.Header.PresentationTime.Numerator = 1; - DeviceInfo.Header.PresentationTime.Denominator = 1; - - Overlap->CompletionContext = UlongToPtr(Length); - Overlap->OriginalCompletionRoutine = CompletionRoutine; - - Overlap->Standard.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); - - //SND_TRACE(L"OriginalLength %u NewLength %u\n", Length, BufferLength); - -#if 0 - Result = WriteFileEx(KernelHandle, &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, CompletionRoutine); -#else - Result = WriteFileEx(KernelHandle, &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, MixerCompletionRoutine); -#endif - - if ( ! Result ) - { - SND_TRACE(L"WriteFileEx failed with %x\n", GetLastError()); - return MMSYSERR_NOERROR; - } - - WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE); - -#ifdef USERMODE_MIXER - // if (BufferOut != OffsetPtr) - // HeapFree(GetProcessHeap(), 0, BufferOut); -#endif + DPRINT("OriginalLength %u NewLength %u\n", WaveHeader->dwBufferLength, BufferLength); + /* Set output data */ + WaveHeader->lpData = BufferOut; + WaveHeader->dwBufferLength = BufferLength; return MMSYSERR_NOERROR; } diff --git a/dll/win32/wdmaud.drv/result.c b/dll/win32/wdmaud.drv/result.c new file mode 100644 index 0000000000000..698d918a0dbe9 --- /dev/null +++ b/dll/win32/wdmaud.drv/result.c @@ -0,0 +1,74 @@ +/* + * PROJECT: ReactOS Sound Subsystem + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: WDM Audio Driver MMRESULT return code routines + * COPYRIGHT: Copyright 2009-2010 Johannes Anderwald + * Copyright 2022 Oleg Dubinskiy (oleg.dubinskij30@gmail.com) + */ + +#include + +/* + Translate a Win32 error code into an MMRESULT code. +*/ +MMRESULT +Win32ErrorToMmResult( + IN UINT ErrorCode) +{ + switch ( ErrorCode ) + { + case NO_ERROR : + case ERROR_IO_PENDING : + return MMSYSERR_NOERROR; + + case ERROR_BUSY : + return MMSYSERR_ALLOCATED; + + case ERROR_NOT_SUPPORTED : + case ERROR_INVALID_FUNCTION : + return MMSYSERR_NOTSUPPORTED; + + case ERROR_NOT_ENOUGH_MEMORY : + return MMSYSERR_NOMEM; + + case ERROR_ACCESS_DENIED : + return MMSYSERR_BADDEVICEID; + + case ERROR_INSUFFICIENT_BUFFER : + return MMSYSERR_INVALPARAM; + + case ERROR_INVALID_PARAMETER : + return MMSYSERR_INVALPARAM; + + + default : + return MMSYSERR_ERROR; + } +} + +/* + If a function invokes another function, this aids in translating the + result code so that it is applicable in the context of the original caller. + For example, specifying that an invalid parameter was passed probably does + not make much sense if the parameter wasn't passed by the original caller! + + This could potentially highlight internal logic problems. + + However, things like MMSYSERR_NOMEM make sense to return to the caller. +*/ +MMRESULT +TranslateInternalMmResult( + IN MMRESULT Result) +{ + switch ( Result ) + { + case MMSYSERR_INVALPARAM : + case MMSYSERR_INVALFLAG : + { + return MMSYSERR_ERROR; + } + } + + return Result; +} + diff --git a/dll/win32/wdmaud.drv/wave/header.c b/dll/win32/wdmaud.drv/wave/header.c new file mode 100644 index 0000000000000..8e4d74ff4b1a1 --- /dev/null +++ b/dll/win32/wdmaud.drv/wave/header.c @@ -0,0 +1,212 @@ +/* + * PROJECT: ReactOS Sound System "MME Buddy" Library + * LICENSE: GPL - See COPYING in the top level directory + * FILE: lib/drivers/sound/mmebuddy/wave/header.c + * + * PURPOSE: Wave header preparation and submission routines + * + * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) +*/ + +#include "wdmaud.h" + +#define YDEBUG +#include + + +/* + The following routines are basically handlers for: + - WODM_PREPARE + - WODM_UNPREPARE + - WODM_WRITE + + All of these calls are ultimately dealt with in the context of the + appropriate sound thread, so the implementation should expect itself to + be running in this other thread when any of these operations take place. +*/ + +MMRESULT +PrepareWaveHeader( + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN PWAVEHDR Header) +{ + PWAVEHDR_EXTENSION HeaderExtension; + + VALIDATE_MMSYS_PARAMETER( DeviceInfo ); + VALIDATE_MMSYS_PARAMETER( Header ); + + DPRINT("Preparing wave header\n"); + + Header->lpNext = NULL; + Header->reserved = 0; + + /* Allocate header extension */ + HeaderExtension = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WAVEHDR_EXTENSION)); + if (!HeaderExtension) + { + /* No memory */ + return MMSYSERR_NOMEM; + } + + /* Allocate OVERLAPPED */ + HeaderExtension->Overlapped = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OVERLAPPED)); + if (!HeaderExtension->Overlapped) + { + /* No memory */ + HeapFree(GetProcessHeap(), 0, HeaderExtension); + return MMSYSERR_NOMEM; + } + + /* Create stream event */ + HeaderExtension->Overlapped->hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + if (!HeaderExtension->Overlapped->hEvent) + { + /* No memory */ + HeapFree(GetProcessHeap(), 0, HeaderExtension->Overlapped); + HeapFree(GetProcessHeap(), 0, HeaderExtension); + return MMSYSERR_NOMEM; + } + + Header->reserved = (DWORD_PTR)HeaderExtension; + Header->dwFlags |= WHDR_PREPARED; + + /* Done */ + return MMSYSERR_NOERROR; +} + +MMRESULT +UnprepareWaveHeader( + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN PWAVEHDR Header) +{ + PWAVEHDR_EXTENSION HeaderExtension; + + VALIDATE_MMSYS_PARAMETER( DeviceInfo ); + VALIDATE_MMSYS_PARAMETER( Header ); + + DPRINT("Un-preparing wave header\n"); + + HeaderExtension = (PWAVEHDR_EXTENSION)Header->reserved; + + Header->reserved = 0; + + /* Destroy stream event */ + CloseHandle(HeaderExtension->Overlapped->hEvent); + + /* Free OVERALPPED */ + HeapFree(GetProcessHeap(), 0, HeaderExtension->Overlapped); + + /* Free header extension */ + HeapFree(GetProcessHeap(), 0, HeaderExtension); + + Header->dwFlags &= ~WHDR_PREPARED; + + /* Done */ + return MMSYSERR_NOERROR; +} + +MMRESULT +WriteWaveHeader( + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN PWAVEHDR Header) +{ + VALIDATE_MMSYS_PARAMETER( DeviceInfo ); + VALIDATE_MMSYS_PARAMETER( Header ); + + DPRINT("Submitting wave header\n"); + + /* + A few minor sanity checks - any custom checks should've been carried + out during wave header preparation etc. + */ + VALIDATE_MMSYS_PARAMETER( Header->lpData != NULL ); + VALIDATE_MMSYS_PARAMETER( Header->dwBufferLength > 0 ); + VALIDATE_MMSYS_PARAMETER( Header->dwFlags & WHDR_PREPARED ); + VALIDATE_MMSYS_PARAMETER( ! (Header->dwFlags & WHDR_INQUEUE) ); + + return EnqueueWaveHeader(DeviceInfo, Header); +} + + +/* + EnqueueWaveHeader + Put the header in the record/playback queue. This is performed within + the context of the sound thread, it must NEVER be called from another + thread. + + CompleteWaveHeader + Set the header information to indicate that it has finished playing, + and return it to the client application. This again must be called + within the context of the sound thread. +*/ + +MMRESULT +EnqueueWaveHeader( + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN PWAVEHDR Header) +{ + VALIDATE_MMSYS_PARAMETER( DeviceInfo ); + VALIDATE_MMSYS_PARAMETER( Header ); + + /* Set the "in queue" flag */ + Header->dwFlags |= WHDR_INQUEUE; + + /* Clear the "done" flag for the buffer */ + Header->dwFlags &= ~WHDR_DONE; + + if (!DeviceInfo->DeviceState->WaveQueue) + { + /* This is the first header in the queue */ + DPRINT("Enqueued first wave header\n"); + DeviceInfo->DeviceState->WaveQueue = Header; + + /* Set queue event */ + SetEvent(DeviceInfo->DeviceState->hNotifyEvent); + } + else + { + DPRINT("Enqueued next wave header\n"); + DeviceInfo->DeviceState->WaveQueue = Header; + DeviceInfo->DeviceState->WaveQueue->lpNext = Header; + } + + /* Do wave streaming */ + return DoWaveStreaming(DeviceInfo, Header); +} + +VOID +CompleteWaveHeader( + IN PWDMAUD_DEVICE_INFO DeviceInfo) +{ + PWAVEHDR_EXTENSION HeaderExtension; + PWAVEHDR Header; + + Header = DeviceInfo->DeviceState->WaveQueue; + + DPRINT("Completing wave header\n"); + + if ( Header ) + { + /* Move to the next header */ + DeviceInfo->DeviceState->WaveQueue = DeviceInfo->DeviceState->WaveQueue->lpNext; + + DPRINT("Returning buffer to client...\n"); + + /* Free header's device info */ + HeaderExtension = (PWAVEHDR_EXTENSION)Header->reserved; + if (HeaderExtension->DeviceInfo) + { + HeapFree(GetProcessHeap(), 0, HeaderExtension->DeviceInfo); + } + + /* Update the header */ + Header->lpNext = NULL; + Header->dwFlags &= ~WHDR_INQUEUE; + Header->dwFlags |= WHDR_DONE; + + /* Safe to do this without thread protection, as we're done with the header */ + NotifyMmeClient(DeviceInfo, + DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? WOM_DONE : WIM_DATA, + (DWORD_PTR)Header); + } +} diff --git a/dll/win32/wdmaud.drv/wave/streaming.c b/dll/win32/wdmaud.drv/wave/streaming.c new file mode 100644 index 0000000000000..4e7122215d561 --- /dev/null +++ b/dll/win32/wdmaud.drv/wave/streaming.c @@ -0,0 +1,89 @@ +/* + * PROJECT: ReactOS Sound System "MME Buddy" Library + * LICENSE: GPL - See COPYING in the top level directory + * FILE: lib/drivers/sound/mmebuddy/wave/streaming.c + * + * PURPOSE: Wave streaming + * + * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) +*/ + +#include "wdmaud.h" + +#define YDEBUG +#include + + +/* + DoWaveStreaming + Check if there is streaming to be done, and if so, do it. +*/ + +MMRESULT +DoWaveStreaming( + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN PWAVEHDR Header) +{ + MMRESULT Result; + + /* Is there any work to do? */ + if (!Header) + { + DPRINT("DoWaveStreaming: No work to do - doing nothing\n"); + return MMSYSERR_NOMEM; + } + + /* Sanity checks */ + ASSERT(Header->dwFlags & WHDR_PREPARED); + ASSERT(Header->dwFlags & WHDR_INQUEUE); + + /* Submit wave header */ + Result = FUNC_NAME(WdmAudSubmitWaveHeader)(DeviceInfo, Header); + if (!MMSUCCESS(Result)) + { + DPRINT1("WdmAudSubmitWaveHeader failed with error %d\n", GetLastError()); + Header->dwFlags &= ~WHDR_INQUEUE; + return TranslateInternalMmResult(Result); + } + + /* Done */ + return MMSYSERR_NOERROR; +} + +/* + Stream control functions + (External/internal thread pairs) + + TODO - Move elsewhere as these shouldn't be wave specific! +*/ + +MMRESULT +StopStreamingInSoundThread( + IN PWDMAUD_DEVICE_INFO DeviceInfo) +{ + MMRESULT Result; + + /* Reset the stream */ + Result = FUNC_NAME(WdmAudResetStream)(DeviceInfo, FALSE); + + if ( ! MMSUCCESS(Result) ) + { + /* Failed */ + return TranslateInternalMmResult(Result); + } + + return MMSYSERR_NOERROR; +} + +MMRESULT +StopStreaming( + IN PWDMAUD_DEVICE_INFO DeviceInfo) +{ + if ( ! DeviceInfo ) + return MMSYSERR_INVALHANDLE; + + if ( DeviceInfo->DeviceType != WAVE_OUT_DEVICE_TYPE && DeviceInfo->DeviceType != WAVE_IN_DEVICE_TYPE ) + return MMSYSERR_NOTSUPPORTED; + + return StopStreamingInSoundThread(DeviceInfo); +} diff --git a/dll/win32/wdmaud.drv/wave/widMessage.c b/dll/win32/wdmaud.drv/wave/widMessage.c new file mode 100644 index 0000000000000..272dc4427e0f9 --- /dev/null +++ b/dll/win32/wdmaud.drv/wave/widMessage.c @@ -0,0 +1,134 @@ +/* + * PROJECT: ReactOS Sound System "MME Buddy" Library + * LICENSE: GPL - See COPYING in the top level directory + * FILE: lib/sound/mmebuddy/wave/widMessage.c + * + * PURPOSE: Provides the widMessage exported function, as required by + * the MME API, for wave input device support. + * + * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) +*/ + +#include "wdmaud.h" + +#define YDEBUG +#include + +/* + Standard MME driver entry-point for messages relating to wave audio + input. +*/ +DWORD +APIENTRY +widMessage( + UINT DeviceId, + UINT Message, + DWORD_PTR PrivateHandle, + DWORD_PTR Parameter1, + DWORD_PTR Parameter2) +{ + MMRESULT Result = MMSYSERR_NOTSUPPORTED; + + AcquireEntrypointMutex(WAVE_IN_DEVICE_TYPE); + + DPRINT("widMessage - Message type %d\n", Message); + + switch ( Message ) + { +#ifndef USE_MMIXER_LIB + case WIDM_INIT: + { + Result = WdmAudAddRemoveDeviceNode(WAVE_IN_DEVICE_TYPE, TRUE); + break; + } + + case DRVM_EXIT: + { + Result = WdmAudAddRemoveDeviceNode(WAVE_IN_DEVICE_TYPE, FALSE); + break; + } +#endif + case WIDM_GETNUMDEVS : + { + Result = MmeGetNumDevs(WAVE_IN_DEVICE_TYPE); + break; + } + + case WIDM_START : + { + Result = MmeSetState(PrivateHandle, TRUE); + break; + } + + case WIDM_STOP : + { + Result = MmeSetState(PrivateHandle, FALSE); + break; + } + + case WIDM_GETDEVCAPS : + { + + Result = MmeGetSoundDeviceCapabilities(WAVE_IN_DEVICE_TYPE, + DeviceId, + (MDEVICECAPSEX*)Parameter1); + break; + } + case WIDM_OPEN : + { + + /* Do sanity checks for 'recording' SamplesPerSec value */ + LPWAVEOPENDESC OpenParameters = (LPWAVEOPENDESC)Parameter1; + if (OpenParameters->lpFormat->nSamplesPerSec > 100000) + OpenParameters->lpFormat->nSamplesPerSec = 100000; + if (OpenParameters->lpFormat->nSamplesPerSec < 5000) + OpenParameters->lpFormat->nSamplesPerSec = 5000; + + Result = MmeOpenDevice(WAVE_IN_DEVICE_TYPE, + DeviceId, + (LPWAVEOPENDESC) Parameter1, + Parameter2, + (DWORD_PTR*) PrivateHandle); + break; + } + + case WIDM_CLOSE : + { + Result = MmeCloseDevice(PrivateHandle); + + break; + } + + case WIDM_PREPARE : + { + /* TODO: Do we need to pass 2nd parameter? */ + Result = MmePrepareWaveHeader(PrivateHandle, Parameter1); + break; + } + + case WIDM_UNPREPARE : + { + Result = MmeUnprepareWaveHeader(PrivateHandle, Parameter1); + break; + } + + case WIDM_RESET : + { + /* Stop playback, reset position to zero */ + Result = MmeResetWavePlayback(PrivateHandle); + break; + } + + case WIDM_ADDBUFFER : + { + Result = MmeWriteWaveHeader(PrivateHandle, Parameter1); + break; + } + } + + DPRINT("widMessage returning MMRESULT %d\n", Result); + + ReleaseEntrypointMutex(WAVE_IN_DEVICE_TYPE); + + return Result; +} diff --git a/dll/win32/wdmaud.drv/wave/wodMessage.c b/dll/win32/wdmaud.drv/wave/wodMessage.c new file mode 100644 index 0000000000000..57ded37933dc0 --- /dev/null +++ b/dll/win32/wdmaud.drv/wave/wodMessage.c @@ -0,0 +1,134 @@ +/* + * PROJECT: ReactOS Sound System "MME Buddy" Library + * LICENSE: GPL - See COPYING in the top level directory + * FILE: lib/drivers/sound/mmebuddy/wave/wodMessage.c + * + * PURPOSE: Provides the wodMessage exported function, as required by + * the MME API, for wave output device support. + * + * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) +*/ + +#include "wdmaud.h" + +#define YDEBUG +#include + +/* + Standard MME driver entry-point for messages relating to wave audio + output. +*/ +DWORD +APIENTRY +wodMessage( + UINT DeviceId, + UINT Message, + DWORD_PTR PrivateHandle, + DWORD_PTR Parameter1, + DWORD_PTR Parameter2) +{ + MMRESULT Result = MMSYSERR_NOTSUPPORTED; + + AcquireEntrypointMutex(WAVE_OUT_DEVICE_TYPE); + + DPRINT("wodMessage - Message type %d\n", Message); + + switch ( Message ) + { +#ifndef USE_MMIXER_LIB + case WODM_INIT: + { + Result = WdmAudAddRemoveDeviceNode(WAVE_OUT_DEVICE_TYPE, TRUE); + break; + } + + case DRVM_EXIT: + { + Result = WdmAudAddRemoveDeviceNode(WAVE_OUT_DEVICE_TYPE, FALSE); + break; + } +#endif + + case WODM_GETNUMDEVS : + { + Result = MmeGetNumDevs(WAVE_OUT_DEVICE_TYPE); + break; + } + + case WODM_GETDEVCAPS : + { + Result = MmeGetSoundDeviceCapabilities(WAVE_OUT_DEVICE_TYPE, + DeviceId, + (MDEVICECAPSEX*)Parameter1); + break; + } + + case WODM_OPEN : + { + Result = MmeOpenDevice(WAVE_OUT_DEVICE_TYPE, + DeviceId, + (LPWAVEOPENDESC) Parameter1, + Parameter2, + (DWORD_PTR*)PrivateHandle); + break; + } + + case WODM_CLOSE : + { + Result = MmeCloseDevice(PrivateHandle); + + break; + } + + case WODM_PREPARE : + { + /* TODO: Do we need to pass 2nd parameter? */ + Result = MmePrepareWaveHeader(PrivateHandle, Parameter1); + break; + } + + case WODM_UNPREPARE : + { + Result = MmeUnprepareWaveHeader(PrivateHandle, Parameter1); + break; + } + + case WODM_WRITE : + { + Result = MmeWriteWaveHeader(PrivateHandle, Parameter1); + break; + } + + case WODM_RESET : + { + /* Stop playback, reset position to zero */ + Result = MmeResetWavePlayback(PrivateHandle); + break; + } + + case WODM_RESTART : + { + /* Continue playback when paused */ + Result = MmeSetState(PrivateHandle, TRUE); + break; + } + case WODM_PAUSE : + { + /* Pause playback */ + Result = MmeSetState(PrivateHandle, FALSE); + break; + } + + case WODM_GETPOS : + { + Result = MmeGetPosition(PrivateHandle, (MMTIME*)Parameter1, Parameter2); + break; + } + } + + DPRINT("wodMessage returning MMRESULT %d\n", Result); + + ReleaseEntrypointMutex(WAVE_OUT_DEVICE_TYPE); + + return Result; +} diff --git a/dll/win32/wdmaud.drv/wdmaud.c b/dll/win32/wdmaud.drv/wdmaud.c index 45308b3aff24e..ec3bb59fea0e3 100644 --- a/dll/win32/wdmaud.drv/wdmaud.c +++ b/dll/win32/wdmaud.drv/wdmaud.c @@ -5,109 +5,12 @@ * * PURPOSE: WDM Audio Driver (User-mode part) * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) - * - * NOTES: Looking for wodMessage & co? You won't find them here. Try - * the MME Buddy library, which is where these routines are - * actually implemented. - * */ #include "wdmaud.h" -#define NDEBUG +#define YDEBUG #include -#include - -#define USE_MMIXER_LIB -#ifndef USE_MMIXER_LIB -#define FUNC_NAME(x) x##ByLegacy -#else -#define FUNC_NAME(x) x##ByMMixer -#endif - -MMRESULT -QueryWdmWaveDeviceFormatSupport( - IN PSOUND_DEVICE Device, - IN PWAVEFORMATEX WaveFormat, - IN DWORD WaveFormatSize) -{ - /* Whatever... */ - return MMSYSERR_NOERROR; -} - -MMRESULT -PopulateWdmDeviceList( - MMDEVICE_TYPE DeviceType) -{ - MMRESULT Result; - DWORD DeviceCount = 0; - PSOUND_DEVICE SoundDevice = NULL; - MMFUNCTION_TABLE FuncTable; - DWORD i; - - VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) ); - - Result = FUNC_NAME(WdmAudGetNumWdmDevs)(DeviceType, &DeviceCount); - - if ( ! MMSUCCESS(Result) ) - { - SND_ERR(L"Error %d while obtaining number of devices\n", Result); - return TranslateInternalMmResult(Result); - } - - SND_TRACE(L"%d devices of type %d found\n", DeviceCount, DeviceType); - - - for ( i = 0; i < DeviceCount; ++ i ) - { - Result = ListSoundDevice(DeviceType, UlongToPtr(i), &SoundDevice); - - if ( ! MMSUCCESS(Result) ) - { - SND_ERR(L"Failed to list sound device - error %d\n", Result); - return TranslateInternalMmResult(Result); - } - - /* Set up our function table */ - ZeroMemory(&FuncTable, sizeof(MMFUNCTION_TABLE)); - FuncTable.GetCapabilities = FUNC_NAME(WdmAudGetCapabilities); - FuncTable.QueryWaveFormatSupport = QueryWdmWaveDeviceFormatSupport; //FIXME - FuncTable.Open = FUNC_NAME(WdmAudOpenSoundDevice); - FuncTable.Close = FUNC_NAME(WdmAudCloseSoundDevice); - FuncTable.GetDeviceInterfaceString = FUNC_NAME(WdmAudGetDeviceInterfaceString); - - if (DeviceType == MIXER_DEVICE_TYPE) - { - FuncTable.SetWaveFormat = FUNC_NAME(WdmAudSetMixerDeviceFormat); - FuncTable.QueryMixerInfo = FUNC_NAME(WdmAudQueryMixerInfo); - } - else if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE) - { - FuncTable.SetWaveFormat = FUNC_NAME(WdmAudSetWaveDeviceFormat); - FuncTable.SetState = FUNC_NAME(WdmAudSetWaveState); - FuncTable.ResetStream = FUNC_NAME(WdmAudResetStream); - FuncTable.GetPos = FUNC_NAME(WdmAudGetWavePosition); - -#ifndef USERMODE_MIXER - FuncTable.CommitWaveBuffer = FUNC_NAME(WdmAudCommitWaveBuffer); -#else - FuncTable.CommitWaveBuffer = WriteFileEx_Remixer; -#endif - } - else if (DeviceType == MIDI_IN_DEVICE_TYPE || DeviceType == MIDI_OUT_DEVICE_TYPE) - { - FuncTable.SetWaveFormat = FUNC_NAME(WdmAudSetMixerDeviceFormat); - FuncTable.SetState = FUNC_NAME(WdmAudSetWaveState); - FuncTable.GetPos = FUNC_NAME(WdmAudGetWavePosition); - } - - SetSoundDeviceFunctionTable(SoundDevice, &FuncTable); - } - - return MMSYSERR_NOERROR; -} - - LONG APIENTRY @@ -122,52 +25,85 @@ DriverProc( { case DRV_LOAD : { - HANDLE Handle; MMRESULT Result; - SND_TRACE(L"DRV_LOAD\n"); +#ifndef USE_MMIXER_LIB + PWDMAUD_DEVICE_INFO DeviceInfo; +#endif + DPRINT("DRV_LOAD\n"); Result = InitEntrypointMutexes(); if ( ! MMSUCCESS(Result) ) return 0L; - Result = FUNC_NAME(WdmAudOpenSoundDevice)(NULL, &Handle); + Result = FUNC_NAME(WdmAudOpenKernelSoundDevice)(); if ( Result != MMSYSERR_NOERROR ) { - SND_ERR(L"Failed to open \\\\.\\wdmaud\n"); - //UnlistAllSoundDevices(); + DPRINT1("Failed to open \\\\.\\wdmaud with %d\n", GetLastError()); return 0L; } - /* Populate the device lists */ - SND_TRACE(L"Populating device lists\n"); - PopulateWdmDeviceList(WAVE_OUT_DEVICE_TYPE); - PopulateWdmDeviceList(WAVE_IN_DEVICE_TYPE); - PopulateWdmDeviceList(MIDI_OUT_DEVICE_TYPE); - PopulateWdmDeviceList(MIDI_IN_DEVICE_TYPE); - PopulateWdmDeviceList(AUX_DEVICE_TYPE); - PopulateWdmDeviceList(MIXER_DEVICE_TYPE); +#ifndef USE_MMIXER_LIB + DeviceInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_INFO)); + if (!DeviceInfo) + { + /* No memory */ + DPRINT1("Failed to allocate WDMAUD_DEVICE_INFO structure\n"); + return 0L; + } + + /* Initialize wdmaud.sys */ + DeviceInfo->DeviceType = AUX_DEVICE_TYPE; + + Result = WdmAudIoControl(DeviceInfo, 0, NULL, IOCTL_INIT_WDMAUD); + HeapFree(GetProcessHeap(), 0, DeviceInfo); + if ( ! MMSUCCESS( Result ) ) + { + DPRINT1("Call to IOCTL_INIT_WDMAUD failed with %d\n", GetLastError()); + + return 0L; + } +#endif - SND_TRACE(L"Initialisation complete\n"); + DPRINT("Initialization completed\n"); return 1L; } case DRV_FREE : { - SND_TRACE(L"DRV_FREE\n"); +#ifndef USE_MMIXER_LIB + MMRESULT Result; + PWDMAUD_DEVICE_INFO DeviceInfo; +#endif + DPRINT("DRV_FREE\n"); +#ifndef USE_MMIXER_LIB + DeviceInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_INFO)); + if (!DeviceInfo) + { + /* No memory */ + DPRINT1("Failed to allocate WDMAUD_DEVICE_INFO structure\n"); + return 0L; + } - FUNC_NAME(WdmAudCleanup)(); + /* Unload wdmaud.sys */ + DeviceInfo->DeviceType = AUX_DEVICE_TYPE; - /* TODO: Clean up the path names! */ - UnlistAllSoundDevices(); + Result = WdmAudIoControl(DeviceInfo, 0, NULL, IOCTL_EXIT_WDMAUD); + HeapFree(GetProcessHeap(), 0, DeviceInfo); + if ( ! MMSUCCESS( Result ) ) + { + DPRINT1("Call to IOCTL_EXIT_WDMAUD failed with %d\n", GetLastError()); - CleanupEntrypointMutexes(); + return 0L; + } +#endif + + FUNC_NAME(WdmAudCleanup)(); - SND_TRACE(L"Unfreed memory blocks: %d\n", - GetMemoryAllocationCount()); + CleanupEntrypointMutexes(); return 1L; } @@ -175,27 +111,27 @@ DriverProc( case DRV_ENABLE : case DRV_DISABLE : { - SND_TRACE(L"DRV_ENABLE / DRV_DISABLE\n"); + DPRINT("DRV_ENABLE / DRV_DISABLE\n"); return 1L; } case DRV_OPEN : case DRV_CLOSE : { - SND_TRACE(L"DRV_OPEN / DRV_CLOSE\n"); + DPRINT("DRV_OPEN / DRV_CLOSE\n"); return 1L; } case DRV_QUERYCONFIGURE : { - SND_TRACE(L"DRV_QUERYCONFIGURE\n"); + DPRINT("DRV_QUERYCONFIGURE\n"); return 0L; } case DRV_CONFIGURE : return DRVCNF_OK; default : - SND_TRACE(L"Unhandled message %d\n", Message); + DPRINT("Unhandled message %d\n", Message); return DefDriverProc(DriverId, DriverHandle, Message, @@ -213,16 +149,16 @@ BOOL WINAPI DllMain( switch ( fdwReason ) { case DLL_PROCESS_ATTACH : - SND_TRACE(L"WDMAUD.DRV - Process attached\n"); + DPRINT("WDMAUD.DRV - Process attached\n"); break; case DLL_PROCESS_DETACH : - SND_TRACE(L"WDMAUD.DRV - Process detached\n"); + DPRINT("WDMAUD.DRV - Process detached\n"); break; case DLL_THREAD_ATTACH : - SND_TRACE(L"WDMAUD.DRV - Thread attached\n"); + DPRINT("WDMAUD.DRV - Thread attached\n"); break; case DLL_THREAD_DETACH : - SND_TRACE(L"WDMAUD.DRV - Thread detached\n"); + DPRINT("WDMAUD.DRV - Thread detached\n"); break; } diff --git a/dll/win32/wdmaud.drv/wdmaud.h b/dll/win32/wdmaud.drv/wdmaud.h index d3900b3adfa7f..7779c51f357bd 100644 --- a/dll/win32/wdmaud.drv/wdmaud.h +++ b/dll/win32/wdmaud.drv/wdmaud.h @@ -13,13 +13,39 @@ #include #include -#include #include #include #include #include #include +/* + * Enables user-mode stream resampling support. + * Resampling is required by some legacy devices + * those don't support modern audio formats. + * They're only able to use standard 44100 KHz sample rate, + * 2 (stereo) channels and 16 BPS quality. + * For example, Intel AC97 driver, + * which is used in VirtualBox by default. + */ +//#define RESAMPLING_ENABLED + +//#define USE_MMIXER_LIB +#ifndef USE_MMIXER_LIB +#define FUNC_NAME(x) x##ByLegacy +#else +#define FUNC_NAME(x) x##ByMMixer +#endif + +/* This lives in WAVEHDR.reserved */ +typedef struct +{ + PWDMAUD_DEVICE_INFO DeviceInfo; + LPOVERLAPPED Overlapped; +} WAVEHDR_EXTENSION, *PWAVEHDR_EXTENSION; + +/* mmixer.c */ + BOOL WdmAudInitUserModeMixer(VOID); @@ -32,214 +58,245 @@ WdmAudGetWaveInCount(VOID); ULONG WdmAudGetMixerCount(VOID); -MMRESULT -WdmAudGetNumWdmDevsByMMixer( - IN MMDEVICE_TYPE DeviceType, - OUT DWORD* DeviceCount); +/* resample.c */ MMRESULT -WdmAudCommitWaveBufferByLegacy( - IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, - IN PVOID OffsetPtr, - IN DWORD Length, - IN PSOUND_OVERLAPPED Overlap, - IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine); +WdmAudResampleStream( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ _Out_ PWAVEHDR WaveHeader); -MMRESULT -WriteFileEx_Remixer( - IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, - IN PVOID OffsetPtr, - IN DWORD Length, - IN PSOUND_OVERLAPPED Overlap, - IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine); +/* legacy.c */ MMRESULT -WdmAudGetCapabilitiesByMMixer( - IN PSOUND_DEVICE SoundDevice, - IN DWORD DeviceId, - OUT PVOID Capabilities, - IN DWORD CapabilitiesSize); +WdmAudIoControl( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_opt_ ULONG DataBufferSize, + _In_opt_ PVOID Buffer, + _In_ DWORD IoControlCode); MMRESULT -WdmAudOpenSoundDeviceByMMixer( - IN struct _SOUND_DEVICE* SoundDevice, - OUT PVOID* Handle); +WdmAudCreateCompletionThread( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo); MMRESULT -WdmAudCloseSoundDeviceByMMixer( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN PVOID Handle); +WdmAudDestroyCompletionThread( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo); MMRESULT -WdmAudGetLineInfo( - IN HANDLE hMixer, - IN DWORD MixerId, - IN LPMIXERLINEW MixLine, - IN ULONG Flags); +WdmAudAddRemoveDeviceNode( + _In_ SOUND_DEVICE_TYPE DeviceType, + _In_ BOOL bAdd); + +/* Shared functions for legacy.c and mmixer.c */ MMRESULT -WdmAudGetLineControls( - IN HANDLE hMixer, - IN DWORD MixerId, - IN LPMIXERLINECONTROLSW MixControls, - IN ULONG Flags); +FUNC_NAME(WdmAudOpenKernelSoundDevice)(VOID); MMRESULT -WdmAudSetControlDetails( - IN HANDLE hMixer, - IN DWORD MixerId, - IN LPMIXERCONTROLDETAILS MixDetails, - IN ULONG Flags); +FUNC_NAME(WdmAudCleanup)(VOID); MMRESULT -WdmAudGetControlDetails( - IN HANDLE hMixer, - IN DWORD MixerId, - IN LPMIXERCONTROLDETAILS MixDetails, - IN ULONG Flags); +FUNC_NAME(WdmAudGetCapabilities)( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _Out_ MDEVICECAPSEX* Capabilities); MMRESULT -WdmAudSetWaveDeviceFormatByMMixer( - IN PSOUND_DEVICE_INSTANCE Instance, - IN DWORD DeviceId, - IN PWAVEFORMATEX WaveFormat, - IN DWORD WaveFormatSize); +FUNC_NAME(WdmAudOpenSoundDevice)( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEFORMATEX WaveFormat); MMRESULT -WdmAudGetDeviceInterfaceStringByMMixer( - IN MMDEVICE_TYPE DeviceType, - IN DWORD DeviceId, - IN LPWSTR Interface, - IN DWORD InterfaceLength, - OUT DWORD * InterfaceSize); +FUNC_NAME(WdmAudCloseSoundDevice)( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PVOID Handle); MMRESULT -WdmAudSetMixerDeviceFormatByMMixer( - IN PSOUND_DEVICE_INSTANCE Instance, - IN DWORD DeviceId, - IN PWAVEFORMATEX WaveFormat, - IN DWORD WaveFormatSize); +FUNC_NAME(WdmAudQueryMixerInfo)( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ DWORD DeviceId, + _In_ UINT uMsg, + _In_ LPVOID Parameter, + _In_ DWORD Flags); MMRESULT -WdmAudQueryMixerInfoByMMixer( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN DWORD DeviceId, - IN UINT uMsg, - IN LPVOID Parameter, - IN DWORD Flags); +FUNC_NAME(WdmAudSetWaveState)( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ BOOL bStart); MMRESULT -WdmAudSetWaveStateByMMixer( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN BOOL bStart); +FUNC_NAME(WdmAudSubmitWaveHeader)( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEHDR WaveHeader); MMRESULT -WdmAudResetStreamByMMixer( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN MMDEVICE_TYPE DeviceType, - IN BOOLEAN bStartReset); +FUNC_NAME(WdmAudResetStream)( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ BOOL bStartReset); MMRESULT -WdmAudGetWavePositionByMMixer( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN MMTIME* Time); +FUNC_NAME(WdmAudGetWavePosition)( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ MMTIME* Time); MMRESULT -WdmAudCommitWaveBufferByMMixer( - IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, - IN PVOID OffsetPtr, - IN DWORD Length, - IN PSOUND_OVERLAPPED Overlap, - IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine); +FUNC_NAME(WdmAudGetNumWdmDevs)( + _In_ SOUND_DEVICE_TYPE DeviceType, + _Out_ DWORD* DeviceCount); + +/* + reentrancy.c +*/ MMRESULT -WdmAudCleanupByMMixer(VOID); +InitEntrypointMutexes(VOID); -/* legacy.c */ +VOID +CleanupEntrypointMutexes(VOID); + +VOID +AcquireEntrypointMutex( + _In_ SOUND_DEVICE_TYPE DeviceType); + +VOID +ReleaseEntrypointMutex( + _In_ SOUND_DEVICE_TYPE DeviceType); + +/* + mmewrap.c +*/ + +VOID +NotifyMmeClient( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ UINT Message, + _In_ DWORD_PTR Parameter); + +DWORD +MmeGetNumDevs( + _In_ SOUND_DEVICE_TYPE DeviceType); MMRESULT -WdmAudCleanupByLegacy(VOID); +MmeGetSoundDeviceCapabilities( + _In_ SOUND_DEVICE_TYPE DeviceType, + _In_ DWORD DeviceId, + _Out_ MDEVICECAPSEX* Capabilities); MMRESULT -WdmAudGetCapabilitiesByLegacy( - IN PSOUND_DEVICE SoundDevice, - IN DWORD DeviceId, - OUT PVOID Capabilities, - IN DWORD CapabilitiesSize); +MmeOpenDevice( + _In_ SOUND_DEVICE_TYPE DeviceType, + _In_ UINT DeviceId, + _In_ LPWAVEOPENDESC OpenParameters, + _In_ DWORD Flags, + _Out_ DWORD_PTR* PrivateHandle); MMRESULT -WdmAudOpenSoundDeviceByLegacy( - IN PSOUND_DEVICE SoundDevice, - OUT PVOID *Handle -); +MmeCloseDevice( + _In_ DWORD_PTR PrivateHandle); MMRESULT -WdmAudCloseSoundDeviceByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN PVOID Handle); +MmeGetPosition( + _In_ DWORD_PTR PrivateHandle, + _In_ MMTIME* Time, + _In_ DWORD Size); MMRESULT -WdmAudGetDeviceInterfaceStringByLegacy( - IN MMDEVICE_TYPE DeviceType, - IN DWORD DeviceId, - IN LPWSTR Interface, - IN DWORD InterfaceLength, - OUT DWORD * InterfaceSize); +MmeSetState( + _In_ DWORD_PTR PrivateHandle, + _In_ BOOL bStart); + + +#define MmePrepareWaveHeader(private_handle, header) \ + PrepareWaveHeader((PWDMAUD_DEVICE_INFO)private_handle, (PWAVEHDR)header) + +#define MmeUnprepareWaveHeader(private_handle, header) \ + UnprepareWaveHeader((PWDMAUD_DEVICE_INFO)private_handle, (PWAVEHDR)header) + +#define MmeWriteWaveHeader(private_handle, header) \ + WriteWaveHeader((PWDMAUD_DEVICE_INFO)private_handle, (PWAVEHDR)header) + +MMRESULT +MmeResetWavePlayback( + _In_ DWORD_PTR PrivateHandle); + +/* + result.c +*/ MMRESULT -WdmAudSetMixerDeviceFormatByLegacy( - IN PSOUND_DEVICE_INSTANCE Instance, - IN DWORD DeviceId, - IN PWAVEFORMATEX WaveFormat, - IN DWORD WaveFormatSize); +Win32ErrorToMmResult( + _In_ UINT ErrorCode); MMRESULT -WdmAudQueryMixerInfoByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN DWORD DeviceId, - IN UINT uMsg, - IN LPVOID Parameter, - IN DWORD Flags); +TranslateInternalMmResult( + _In_ MMRESULT Result); + +/* + header.c +*/ MMRESULT -WdmAudSetWaveDeviceFormatByLegacy( - IN PSOUND_DEVICE_INSTANCE Instance, - IN DWORD DeviceId, - IN PWAVEFORMATEX WaveFormat, - IN DWORD WaveFormatSize); +EnqueueWaveHeader( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEHDR Header); + +VOID +CompleteWaveHeader( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo); MMRESULT -WdmAudSetWaveStateByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN BOOL bStart); +PrepareWaveHeader( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEHDR Header); MMRESULT -WdmAudResetStreamByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN MMDEVICE_TYPE DeviceType, - IN BOOLEAN bStartReset); +UnprepareWaveHeader( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEHDR Header); MMRESULT -WdmAudGetWavePositionByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN MMTIME* Time); +WriteWaveHeader( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEHDR Header); + +/* + streaming.c +*/ MMRESULT -WriteFileEx_Committer2( - IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, - IN PVOID OffsetPtr, - IN DWORD Length, - IN PSOUND_OVERLAPPED Overlap, - IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine); +DoWaveStreaming( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEHDR Header); MMRESULT -WdmAudGetNumWdmDevsByLegacy( - IN MMDEVICE_TYPE DeviceType, - OUT DWORD* DeviceCount); +StopStreaming( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo); + + +/* + Convert a device type into a zero-based array index + */ + +#define SOUND_DEVICE_TYPE_TO_INDEX(x) \ + ( x - MIN_SOUND_DEVICE_TYPE ) + +#define INDEX_TO_SOUND_DEVICE_TYPE(x) \ + ( x + MIN_SOUND_DEVICE_TYPE ) + +/* + Validation +*/ + +#define VALIDATE_MMSYS_PARAMETER(parameter_condition) \ + { \ + if ( ! (parameter_condition) ) \ + { \ + DPRINT1("FAILED parameter check: %hS at File %S Line %lu\n", #parameter_condition, __FILE__, __LINE__); \ + return MMSYSERR_INVALPARAM; \ + } \ + } + +#define MMSUCCESS(result) \ + ( result == MMSYSERR_NOERROR ) -DWORD -WINAPI -MixerEventThreadRoutine( - LPVOID Parameter); #endif /* __WDMAUD_H__ */ diff --git a/dll/win32/wdmaud.drv/wdmaud.spec b/dll/win32/wdmaud.drv/wdmaud.spec index d6195cce4a3eb..81b24e86d9fa1 100644 --- a/dll/win32/wdmaud.drv/wdmaud.spec +++ b/dll/win32/wdmaud.drv/wdmaud.spec @@ -4,3 +4,4 @@ @ stdcall wodMessage(long long long long long) @ stdcall widMessage(long long long long long) @ stdcall modMessage(long long long long long) +@ stdcall midMessage(long long long long long) diff --git a/drivers/ksfilter/ks/irp.c b/drivers/ksfilter/ks/irp.c index ab5d1b2152380..b5232791acccc 100644 --- a/drivers/ksfilter/ks/irp.c +++ b/drivers/ksfilter/ks/irp.c @@ -634,8 +634,10 @@ KsStreamIo( IoStack = IoGetNextIrpStackLocation(Irp); /* setup stack parameters */ IoStack->FileObject = FileObject; - IoStack->Parameters.DeviceIoControl.InputBufferLength = Length; + IoStack->MajorFunction = IRP_MJ_DEVICE_CONTROL; IoStack->Parameters.DeviceIoControl.Type3InputBuffer = StreamHeaders; + IoStack->Parameters.DeviceIoControl.InputBufferLength = Length; + IoStack->Parameters.DeviceIoControl.OutputBufferLength = Length; IoStack->Parameters.DeviceIoControl.IoControlCode = (Flags == KSSTREAM_READ ? IOCTL_KS_READ_STREAM : IOCTL_KS_WRITE_STREAM); if (CompletionRoutine) @@ -646,6 +648,7 @@ KsStreamIo( /* now call the driver */ Status = IoCallDriver(DeviceObject, Irp); + DPRINT1("Status 0x%lx\n", Status); /* done */ return Status; } @@ -919,6 +922,9 @@ KsProbeStreamIrp( goto ProbeMdl; } + // HACK for MS portcls + HeaderSize = Length; + /* probe user mode buffers */ if (Length && ( (!HeaderSize) || (Length % HeaderSize == 0) || ((ProbeFlags & KSPROBE_ALLOWFORMATCHANGE) && (Length == sizeof(KSSTREAM_HEADER))) ) ) { @@ -1662,18 +1668,6 @@ KsAddIrpToCancelableQueue( DPRINT("KsAddIrpToCancelableQueue QueueHead %p SpinLock %p Irp %p ListLocation %x DriverCancel %p\n", QueueHead, SpinLock, Irp, ListLocation, DriverCancel); - // HACK for ms portcls - if (IoStack->MajorFunction == IRP_MJ_CREATE) - { - // complete the request - DPRINT1("MS HACK\n"); - Irp->IoStatus.Status = STATUS_SUCCESS; - CompleteRequest(Irp, IO_NO_INCREMENT); - - return; - } - - if (!DriverCancel) { /* default to KsCancelRoutine */ @@ -2032,6 +2026,9 @@ KsSetMajorFunctionHandler( { DPRINT("KsSetMajorFunctionHandler Function %x\n", MajorFunction); + // HACK for MS portcls + DriverObject->MajorFunction[IRP_MJ_CREATE] = KspCreate; + switch ( MajorFunction ) { case IRP_MJ_CREATE: diff --git a/drivers/wdm/audio/backpln/CMakeLists.txt b/drivers/wdm/audio/backpln/CMakeLists.txt index 867bad2f9c56b..970243d9bc47a 100644 --- a/drivers/wdm/audio/backpln/CMakeLists.txt +++ b/drivers/wdm/audio/backpln/CMakeLists.txt @@ -1,3 +1,3 @@ -add_subdirectory(audio_test) +#add_subdirectory(audio_test) add_subdirectory(portcls) diff --git a/drivers/wdm/audio/backpln/portcls/propertyhandler.cpp b/drivers/wdm/audio/backpln/portcls/propertyhandler.cpp index a63bff78b1014..98cf217840e26 100644 --- a/drivers/wdm/audio/backpln/portcls/propertyhandler.cpp +++ b/drivers/wdm/audio/backpln/portcls/propertyhandler.cpp @@ -135,7 +135,7 @@ HandleDataIntersection( Status = SubDevice->DataRangeIntersection(Pin->PinId, DataRange, (PKSDATARANGE)Descriptor->Factory.KsPinDescriptor[Pin->PinId].DataRanges[0], DataLength, Data, &Length); - if (Status == STATUS_SUCCESS) + if (Status == STATUS_SUCCESS || Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) { IoStatus->Information = Length; break; diff --git a/drivers/wdm/audio/legacy/wdmaud/control.c b/drivers/wdm/audio/legacy/wdmaud/control.c index f9ae9a323396b..67b06ae836471 100644 --- a/drivers/wdm/audio/legacy/wdmaud/control.c +++ b/drivers/wdm/audio/legacy/wdmaud/control.c @@ -9,11 +9,40 @@ #include "wdmaud.h" -#define NDEBUG +#define YDEBUG #include const GUID KSPROPSETID_Sysaudio = {0xCBE3FAA0L, 0xCC75, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}}; +NTSTATUS +WdmAudControlInitialize( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + NTSTATUS Status; + LPWSTR SymbolicLinkList; + PWDMAUD_DEVICE_EXTENSION DeviceExtension; + + /* Get device extension */ + DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + /* Get SysAudio device interface */ + Status = GetSysAudioDeviceInterface(&SymbolicLinkList); + if (NT_SUCCESS(Status)) + { + /* Wait for initialization finishing */ + KeWaitForSingleObject(&DeviceExtension->InitializationCompletionEvent, + Executive, + KernelMode, + FALSE, + NULL); + } + + ExFreePool(SymbolicLinkList); + + return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); +} + NTSTATUS WdmAudControlOpen( IN PDEVICE_OBJECT DeviceObject, @@ -21,23 +50,30 @@ WdmAudControlOpen( IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo) { + NTSTATUS Status; + if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE) { - return WdmAudControlOpenMixer(DeviceObject, Irp, DeviceInfo, ClientInfo); + Status = WdmAudControlOpenMixer(DeviceObject, Irp, DeviceInfo, ClientInfo); } - - if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) + else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) { - return WdmAudControlOpenWave(DeviceObject, Irp, DeviceInfo, ClientInfo); + Status = WdmAudControlOpenWave(DeviceObject, Irp, DeviceInfo, ClientInfo); } - - if (DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE || DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE) + else if (DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE || DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE) { - return WdmAudControlOpenMidi(DeviceObject, Irp, DeviceInfo, ClientInfo); + Status = WdmAudControlOpenMidi(DeviceObject, Irp, DeviceInfo, ClientInfo); } + if (NT_SUCCESS(Status) && DeviceInfo->DeviceType != MIXER_DEVICE_TYPE) + { + /* Start audio device after opening */ + WdmAudSetDeviceState(DeviceObject, Irp, DeviceInfo, KSSTATE_ACQUIRE, FALSE); + WdmAudSetDeviceState(DeviceObject, Irp, DeviceInfo, KSSTATE_PAUSE, FALSE); + WdmAudSetDeviceState(DeviceObject, Irp, DeviceInfo, KSSTATE_RUN, FALSE); + } - return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO)); + return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); } NTSTATUS @@ -72,48 +108,12 @@ WdmAudControlDeviceType( /* store result count */ - DeviceInfo->DeviceCount = Result; + DeviceInfo->DeviceIndex = Result; - DPRINT("WdmAudControlDeviceType Devices %u\n", DeviceInfo->DeviceCount); + DPRINT("WdmAudControlDeviceType Devices %u\n", DeviceInfo->DeviceIndex); return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); } -NTSTATUS -WdmAudControlDeviceState( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PWDMAUD_DEVICE_INFO DeviceInfo, - IN PWDMAUD_CLIENT ClientInfo) -{ - KSPROPERTY Property; - KSSTATE State; - NTSTATUS Status; - ULONG BytesReturned; - PFILE_OBJECT FileObject; - - DPRINT("WdmAudControlDeviceState\n"); - - Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo->hDevice, DeviceInfo->DeviceType); - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); - } - - Property.Set = KSPROPSETID_Connection; - Property.Id = KSPROPERTY_CONNECTION_STATE; - Property.Flags = KSPROPERTY_TYPE_SET; - - State = DeviceInfo->u.State; - - Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&State, sizeof(KSSTATE), &BytesReturned); - - ObDereferenceObject(FileObject); - - DPRINT("WdmAudControlDeviceState Status %x\n", Status); - return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); -} - NTSTATUS WdmAudCapabilities( IN PDEVICE_OBJECT DeviceObject, @@ -130,15 +130,15 @@ WdmAudCapabilities( if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE) { - Status = WdmAudMixerCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension); + Status = WdmAudMixerCapabilities(DeviceObject, Irp, DeviceInfo, ClientInfo, DeviceExtension); } else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { - Status = WdmAudWaveCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension); + Status = WdmAudWaveCapabilities(DeviceObject, Irp, DeviceInfo, ClientInfo, DeviceExtension); } else if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE || DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE) { - Status = WdmAudMidiCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension); + Status = WdmAudMidiCapabilities(DeviceObject, Irp, DeviceInfo, ClientInfo, DeviceExtension); } return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); @@ -154,15 +154,25 @@ WdmAudIoctlClose( { ULONG Index; + if (DeviceInfo->DeviceType != MIXER_DEVICE_TYPE) + { + /* Stop audio device before closing */ + WdmAudSetDeviceState(DeviceObject, Irp, DeviceInfo, KSSTATE_PAUSE, FALSE); + WdmAudSetDeviceState(DeviceObject, Irp, DeviceInfo, KSSTATE_ACQUIRE, FALSE); + WdmAudSetDeviceState(DeviceObject, Irp, DeviceInfo, KSSTATE_STOP, FALSE); + + /* Reset audio stream */ + WdmAudResetStream(DeviceObject, Irp, DeviceInfo, FALSE); + } + for(Index = 0; Index < ClientInfo->NumPins; Index++) { if (ClientInfo->hPins[Index].Handle == DeviceInfo->hDevice && ClientInfo->hPins[Index].Type != MIXER_DEVICE_TYPE) { DPRINT1("Closing device %p\n", DeviceInfo->hDevice); - ZwClose(DeviceInfo->hDevice); - ClientInfo->hPins[Index].Handle = NULL; - SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); - return STATUS_SUCCESS; + ClosePin(ClientInfo, Index); + DeviceInfo->hDevice = NULL; + return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); } else if (ClientInfo->hPins[Index].Handle == DeviceInfo->hDevice && ClientInfo->hPins[Index].Type == MIXER_DEVICE_TYPE) { @@ -171,98 +181,48 @@ WdmAudIoctlClose( } } - SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, sizeof(WDMAUD_DEVICE_INFO)); - return STATUS_INVALID_PARAMETER; + return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, sizeof(WDMAUD_DEVICE_INFO)); } NTSTATUS -NTAPI -WdmAudFrameSize( +WdmAudSetDeviceState( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, - IN PWDMAUD_CLIENT ClientInfo) + IN KSSTATE State, + IN BOOL CompleteIrp) // Avoids multiple IRP complete requests + // when calling internally from wdmaud. { - PFILE_OBJECT FileObject; + NTSTATUS Status; KSPROPERTY Property; ULONG BytesReturned; - KSALLOCATOR_FRAMING Framing; - NTSTATUS Status; + PFILE_OBJECT FileObject; + + DPRINT("WdmAudControlDeviceState\n"); - /* Get sysaudio pin file object */ - Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); + Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { - DPRINT1("Invalid buffer handle %p\n", DeviceInfo->hDevice); - return SetIrpIoStatus(Irp, Status, 0); + DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo->hDevice, DeviceInfo->DeviceType); + return CompleteIrp ? SetIrpIoStatus(Irp, Status, 0) : Status; } - /* Setup get framing request */ - Property.Id = KSPROPERTY_CONNECTION_ALLOCATORFRAMING; - Property.Flags = KSPROPERTY_TYPE_GET; Property.Set = KSPROPSETID_Connection; + Property.Id = KSPROPERTY_CONNECTION_STATE; + Property.Flags = KSPROPERTY_TYPE_SET; - Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&Framing, sizeof(KSALLOCATOR_FRAMING), &BytesReturned); - /* Did we succeed */ - if (NT_SUCCESS(Status)) + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&State, sizeof(KSSTATE), &BytesReturned); + if (!NT_SUCCESS(Status)) { - /* Store framesize */ - DeviceInfo->u.FrameSize = Framing.FrameSize; + DPRINT1("%x failed with status 0x%lx\n", State, Status); + ObDereferenceObject(FileObject); + return CompleteIrp ? SetIrpIoStatus(Irp, Status, 0) : Status; } - /* Release file object */ ObDereferenceObject(FileObject); - return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); - -} - -NTSTATUS -NTAPI -WdmAudGetDeviceInterface( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PWDMAUD_DEVICE_INFO DeviceInfo) -{ - NTSTATUS Status; - LPWSTR Device; - ULONG Size, Length; - - /* get device interface string input length */ - Size = DeviceInfo->u.Interface.DeviceInterfaceStringSize; - - /* get mixer info */ - Status = WdmAudGetPnpNameByIndexAndType(DeviceInfo->DeviceIndex, DeviceInfo->DeviceType, &Device); - - /* check for success */ - if (!NT_SUCCESS(Status)) - { - /* invalid device id */ - return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); - } - - /* calculate length */ - Length = (wcslen(Device)+1) * sizeof(WCHAR); - - if (!Size) - { - /* store device interface size */ - DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length; - } - else if (Size < Length) - { - /* buffer too small */ - DeviceInfo->u.Interface.DeviceInterfaceStringSize = Length; - return SetIrpIoStatus(Irp, STATUS_BUFFER_OVERFLOW, sizeof(WDMAUD_DEVICE_INFO)); - } - else - { - //FIXME SEH - RtlMoveMemory(DeviceInfo->u.Interface.DeviceInterfaceString, Device, Length); - } - - FreeItem(Device); - return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + DPRINT("WdmAudControlDeviceState Status 0x%lx BytesReturned %lu\n", Status, BytesReturned); + return CompleteIrp ? SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)) : STATUS_SUCCESS; } NTSTATUS @@ -270,10 +230,14 @@ NTAPI WdmAudResetStream( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, - IN PWDMAUD_DEVICE_INFO DeviceInfo) + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN BOOL CompleteIrp) // Avoids multiple IRP complete requests + // when calling internally from wdmaud. { - KSRESET ResetStream; + KSSTATE State; NTSTATUS Status; + KSRESET ResetStream; + KSPROPERTY Property; ULONG BytesReturned; PFILE_OBJECT FileObject; @@ -283,103 +247,55 @@ WdmAudResetStream( if (!NT_SUCCESS(Status)) { DPRINT1("Error: invalid device handle provided %p Type %x\n", DeviceInfo->hDevice, DeviceInfo->DeviceType); - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); + return CompleteIrp ? SetIrpIoStatus(Irp, Status, 0) : Status; } - ResetStream = DeviceInfo->u.ResetStream; - ASSERT(ResetStream == KSRESET_BEGIN || ResetStream == KSRESET_END); - - Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_RESET_STATE, (PVOID)&ResetStream, sizeof(KSRESET), NULL, 0, &BytesReturned); - - ObDereferenceObject(FileObject); - - DPRINT("WdmAudResetStream Status %x\n", Status); - return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); -} - -NTSTATUS -NTAPI -WdmAudDeviceControl( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp) -{ - PIO_STACK_LOCATION IoStack; - PWDMAUD_DEVICE_INFO DeviceInfo; - PWDMAUD_CLIENT ClientInfo; - - IoStack = IoGetCurrentIrpStackLocation(Irp); - - DPRINT("WdmAudDeviceControl entered\n"); - - if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(WDMAUD_DEVICE_INFO)) - { - /* invalid parameter */ - DPRINT1("Input buffer too small size %u expected %u\n", IoStack->Parameters.DeviceIoControl.InputBufferLength, sizeof(WDMAUD_DEVICE_INFO)); - return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0); - } + Property.Set = KSPROPSETID_Connection; + Property.Id = KSPROPERTY_CONNECTION_STATE; + Property.Flags = KSPROPERTY_TYPE_SET; - DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer; + State = DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? KSSTATE_PAUSE : KSSTATE_STOP; - if (DeviceInfo->DeviceType < MIN_SOUND_DEVICE_TYPE || DeviceInfo->DeviceType > MAX_SOUND_DEVICE_TYPE) + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&State, sizeof(KSSTATE), &BytesReturned); + if (!NT_SUCCESS(Status)) { - /* invalid parameter */ - DPRINT1("Error: device type not set\n"); - return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0); + DPRINT1("%ls failed with status 0x%lx\n", + DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? + L"KSSTATE_PAUSE" : L"KSSTATE_STOP", + Status); + ObDereferenceObject(FileObject); + return CompleteIrp ? SetIrpIoStatus(Irp, Status, 0) : Status; } - if (!IoStack->FileObject || !IoStack->FileObject->FsContext) + if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { - /* file object parameter */ - DPRINT1("Error: file object is not attached\n"); - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); + ResetStream = KSRESET_BEGIN; + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_RESET_STATE, (PVOID)&ResetStream, sizeof(KSRESET), NULL, 0, &BytesReturned); + if (!NT_SUCCESS(Status)) + { + DPRINT1("KSRESET_BEGIN failed with status 0x%lx\n", Status); + ObDereferenceObject(FileObject); + return CompleteIrp ? SetIrpIoStatus(Irp, Status, 0) : Status; + } + ResetStream = KSRESET_END; + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_RESET_STATE, (PVOID)&ResetStream, sizeof(KSRESET), NULL, 0, &BytesReturned); + if (!NT_SUCCESS(Status)) + { + DPRINT1("KSRESET_END failed with status 0x%lx\n", Status); + ObDereferenceObject(FileObject); + return CompleteIrp ? SetIrpIoStatus(Irp, Status, 0) : Status; + } } - ClientInfo = (PWDMAUD_CLIENT)IoStack->FileObject->FsContext; - DPRINT("WdmAudDeviceControl entered\n"); - - switch(IoStack->Parameters.DeviceIoControl.IoControlCode) - { - case IOCTL_OPEN_WDMAUD: - return WdmAudControlOpen(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_GETNUMDEVS_TYPE: - return WdmAudControlDeviceType(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_SETDEVICE_STATE: - return WdmAudControlDeviceState(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_GETCAPABILITIES: - return WdmAudCapabilities(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_CLOSE_WDMAUD: - return WdmAudIoctlClose(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_GETFRAMESIZE: - return WdmAudFrameSize(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_GETLINEINFO: - return WdmAudGetLineInfo(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_GETLINECONTROLS: - return WdmAudGetLineControls(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_SETCONTROLDETAILS: - return WdmAudSetControlDetails(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_GETCONTROLDETAILS: - return WdmAudGetControlDetails(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_QUERYDEVICEINTERFACESTRING: - return WdmAudGetDeviceInterface(DeviceObject, Irp, DeviceInfo); - case IOCTL_GET_MIXER_EVENT: - return WdmAudGetMixerEvent(DeviceObject, Irp, DeviceInfo, ClientInfo); - case IOCTL_RESET_STREAM: - return WdmAudResetStream(DeviceObject, Irp, DeviceInfo); - case IOCTL_GETPOS: - case IOCTL_GETDEVID: - case IOCTL_GETVOLUME: - case IOCTL_SETVOLUME: - - DPRINT1("Unhandled %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode); - break; - } + ObDereferenceObject(FileObject); - return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0); + DPRINT("WdmAudResetStream Status 0x%lx BytesReturned %lu\n", Status, BytesReturned); + return CompleteIrp ? SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)) : STATUS_SUCCESS; } NTSTATUS NTAPI -IoCompletion ( +IoCompletion( PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Ctx) @@ -388,31 +304,29 @@ IoCompletion ( PMDL Mdl, NextMdl; PWDMAUD_COMPLETION_CONTEXT Context = (PWDMAUD_COMPLETION_CONTEXT)Ctx; - /* get stream header */ - Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer; + /* Get stream header */ + Header = (PKSSTREAM_HEADER)Irp->UserBuffer; - /* sanity check */ + /* Sanity check */ ASSERT(Header); - /* time to free all allocated mdls */ + /* Time to free all allocated mdls */ Mdl = Irp->MdlAddress; while(Mdl) { - /* get next mdl */ + /* Get next mdl */ NextMdl = Mdl->Next; - /* unlock pages */ + /* Unlock pages */ MmUnlockPages(Mdl); - /* grab next mdl */ + /* Grab next mdl */ Mdl = NextMdl; } - //IoFreeMdl(Mdl); - /* clear mdl list */ - Irp->MdlAddress = Context->Mdl; - + /* Clear mdl list */ + Irp->MdlAddress = Context->Mdl; DPRINT("IoCompletion Irp %p IoStatus %lx Information %lx\n", Irp, Irp->IoStatus.Status, Irp->IoStatus.Information); @@ -422,122 +336,306 @@ IoCompletion ( Irp->IoStatus.Information = 0; } - /* dereference file object */ - ObDereferenceObject(Context->FileObject); - - /* free context */ - FreeItem(Context); - return STATUS_SUCCESS; } NTSTATUS NTAPI -WdmAudReadWrite( +WdmAudReadWriteInQueue( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - NTSTATUS Status; PWDMAUD_DEVICE_INFO DeviceInfo; + PWDMAUD_CLIENT ClientInfo; + PKSSTREAM_HEADER StreamHeader; PFILE_OBJECT FileObject; PIO_STACK_LOCATION IoStack; - ULONG Length; - PMDL Mdl; - BOOLEAN Read = TRUE; + PWAVEHDR WaveHeader; + ULONG PinId; PWDMAUD_COMPLETION_CONTEXT Context; + /* get device info */ + DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer; + ASSERT(DeviceInfo); + + /* Get wave header passed by the caller */ + WaveHeader = (PWAVEHDR)DeviceInfo->Buffer; + + /* get current irp stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + ASSERT(IoStack->FileObject); + + /* get client context struct */ + ClientInfo = (PWDMAUD_CLIENT)IoStack->FileObject->FsContext; + ASSERT(ClientInfo); + + /* get active pin */ + PinId = GetActivePin(ClientInfo); + ASSERT(PinId != MAXULONG); + + /* get pin file object */ + FileObject = ClientInfo->hPins[PinId].FileObject; + ASSERT(FileObject); + + /* Allocate stream header */ + StreamHeader = AllocateItem(NonPagedPool, sizeof(KSSTREAM_HEADER)); + if (!StreamHeader) + { + /* Not enough memory */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + StreamHeader->Size = sizeof(KSSTREAM_HEADER); + StreamHeader->PresentationTime.Numerator = 1; + StreamHeader->PresentationTime.Denominator = 1; + StreamHeader->Data = WaveHeader->lpData; + StreamHeader->FrameExtent = WaveHeader->dwBufferLength; + + if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + { + StreamHeader->DataUsed = WaveHeader->dwBufferLength; + } + else + { + StreamHeader->DataUsed = 0; + } + /* allocate completion context */ Context = AllocateItem(NonPagedPool, sizeof(WDMAUD_COMPLETION_CONTEXT)); if (!Context) { /* not enough memory */ - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - /* done */ + FreeItem(StreamHeader); return STATUS_INSUFFICIENT_RESOURCES; } - /* get current irp stack location */ - IoStack = IoGetCurrentIrpStackLocation(Irp); - - /* store the input buffer in UserBuffer - as KsProbeStreamIrp operates on IRP_MJ_DEVICE_CONTROL */ - Irp->UserBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress); + /* store the input buffer in UserBuffer */ + Irp->UserBuffer = StreamHeader; /* sanity check */ ASSERT(Irp->UserBuffer); - /* get the length of the request length */ - Length = IoStack->Parameters.Write.Length; - - /* store outputbuffer length */ - IoStack->Parameters.DeviceIoControl.OutputBufferLength = Length; - /* setup context */ - Context->Length = Length; - Context->Function = (IoStack->MajorFunction == IRP_MJ_WRITE ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM); + Context->Length = sizeof(KSSTREAM_HEADER); + Context->Function = (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM); Context->Mdl = Irp->MdlAddress; - /* store mdl address */ - Mdl = Irp->MdlAddress; + /* store file object whose reference is released in the completion callback */ + Context->FileObject = FileObject; + + /* get next stack location */ + IoStack = IoGetNextIrpStackLocation(Irp); + + /* prepare stack location */ + IoStack->FileObject = FileObject; + IoStack->MajorFunction = IRP_MJ_DEVICE_CONTROL; + IoStack->Parameters.DeviceIoControl.Type3InputBuffer = StreamHeader; + IoStack->Parameters.DeviceIoControl.InputBufferLength = sizeof(KSSTREAM_HEADER); + IoStack->Parameters.DeviceIoControl.OutputBufferLength = sizeof(KSSTREAM_HEADER); + IoStack->Parameters.DeviceIoControl.IoControlCode = (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE ? IOCTL_KS_READ_STREAM : IOCTL_KS_WRITE_STREAM); + IoSetCompletionRoutine(Irp, IoCompletion, (PVOID)Context, TRUE, TRUE, TRUE); + + /* call the driver */ + IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp); + + /* done */ + return STATUS_PENDING; +} - /* remove mdladdress as KsProbeStreamIrp will interpret it as an already probed audio buffer */ - Irp->MdlAddress = NULL; +NTSTATUS +NTAPI +WdmAudReadWrite( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PKSSTREAM_HEADER StreamHeader; + PIO_STACK_LOCATION IoStack; + PFILE_OBJECT FileObject; + PWAVEHDR WaveHeader; + NTSTATUS Status; + ULONG PinId; + PWDMAUD_CLIENT ClientInfo; + PWDMAUD_DEVICE_INFO DeviceInfo; + PWDMAUD_COMPLETION_CONTEXT Context; + + /* Get device info */ + DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer; + ASSERT(DeviceInfo); + + /* Get wave header passed by the caller */ + WaveHeader = (PWAVEHDR)DeviceInfo->Buffer; + + /* get current irp stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + ASSERT(IoStack->FileObject); + + /* get client context struct */ + ClientInfo = (PWDMAUD_CLIENT)IoStack->FileObject->FsContext; + ASSERT(ClientInfo); - if (IoStack->MajorFunction == IRP_MJ_WRITE) + /* get active pin */ + PinId = GetActivePin(ClientInfo); + ASSERT(PinId != MAXULONG); + + /* get pin file object */ + FileObject = ClientInfo->hPins[PinId].FileObject; + ASSERT(FileObject); + + /* Allocate stream header */ + StreamHeader = AllocateItem(NonPagedPool, sizeof(KSSTREAM_HEADER)); + if (!StreamHeader) { - /* probe the write stream irp */ - Read = FALSE; - Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMWRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, Length); + /* Not enough memory */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + StreamHeader->Size = sizeof(KSSTREAM_HEADER); + StreamHeader->PresentationTime.Numerator = 1; + StreamHeader->PresentationTime.Denominator = 1; + StreamHeader->Data = WaveHeader->lpData; + StreamHeader->FrameExtent = WaveHeader->dwBufferLength; + + if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + { + StreamHeader->DataUsed = WaveHeader->dwBufferLength; } else { - /* probe the read stream irp */ - Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMREAD | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, Length); + StreamHeader->DataUsed = 0; } - if (!NT_SUCCESS(Status)) + /* Allocate completion context */ + Context = AllocateItem(NonPagedPool, sizeof(WDMAUD_COMPLETION_CONTEXT)); + if (!Context) { - DPRINT1("KsProbeStreamIrp failed with Status %x Cancel %u\n", Status, Irp->Cancel); - Irp->MdlAddress = Mdl; - FreeItem(Context); - return SetIrpIoStatus(Irp, Status, 0); + /* Not enough memory */ + FreeItem(StreamHeader); + return STATUS_INSUFFICIENT_RESOURCES; } - /* get device info */ - DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer; - ASSERT(DeviceInfo); + /* Setup context */ + Context->Length = sizeof(KSSTREAM_HEADER); + Context->Function = (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM); + Context->Mdl = Irp->MdlAddress; + + /* Store file object */ + Context->FileObject = FileObject; + + /* Clear mdl address */ + //Irp->MdlAddress = NULL; + + /* Do the streaming */ + Status = KsStreamIo(FileObject, + NULL, + NULL, + IoCompletion, + Context, + KsInvokeOnSuccess | KsInvokeOnError | KsInvokeOnCancel, + Irp->UserIosb, + StreamHeader, + sizeof(KSSTREAM_HEADER), + DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? + KSSTREAM_WRITE : KSSTREAM_READ, + KernelMode); - /* now get sysaudio file object */ - Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { - DPRINT1("Invalid pin handle %p\n", DeviceInfo->hDevice); - Irp->MdlAddress = Mdl; + DPRINT1("KsStreamIo failed with Status 0x%lx\n", Status); FreeItem(Context); - return SetIrpIoStatus(Irp, Status, 0); + FreeItem(StreamHeader); + return Status; } - /* store file object whose reference is released in the completion callback */ - Context->FileObject = FileObject; + /* done */ + return STATUS_SUCCESS; +} - /* skip current irp stack location */ - IoSkipCurrentIrpStackLocation(Irp); +NTSTATUS +NTAPI +WdmAudDeviceControl( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + PWDMAUD_DEVICE_INFO DeviceInfo; + PWDMAUD_CLIENT ClientInfo; - /* get next stack location */ - IoStack = IoGetNextIrpStackLocation(Irp); + IoStack = IoGetCurrentIrpStackLocation(Irp); - /* prepare stack location */ - IoStack->FileObject = FileObject; - IoStack->Parameters.Write.Length = Length; - IoStack->MajorFunction = IRP_MJ_WRITE; - IoStack->Parameters.DeviceIoControl.IoControlCode = (Read ? IOCTL_KS_READ_STREAM : IOCTL_KS_WRITE_STREAM); - IoSetCompletionRoutine(Irp, IoCompletion, (PVOID)Context, TRUE, TRUE, TRUE); + DPRINT("WdmAudDeviceControl entered\n"); + DPRINT("IOCTL 0x%lx\n", IoStack->Parameters.DeviceIoControl.IoControlCode); - /* mark irp as pending */ -// IoMarkIrpPending(Irp); - /* call the driver */ - Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp); - return Status; + DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer; + if (DeviceInfo->DeviceType < MIN_SOUND_DEVICE_TYPE || DeviceInfo->DeviceType > MAX_SOUND_DEVICE_TYPE) + { + /* invalid parameter */ + DPRINT1("Error: device type not set\n"); + return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0); + } + + if (!IoStack->FileObject || !IoStack->FileObject->FsContext) + { + /* file object parameter */ + DPRINT1("Error: file object is not attached\n"); + return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); + } + ClientInfo = (PWDMAUD_CLIENT)IoStack->FileObject->FsContext; + + switch(IoStack->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_INIT_WDMAUD: + return WdmAudControlInitialize(DeviceObject, Irp); + case IOCTL_EXIT_WDMAUD: + /* No op */ + return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + case IOCTL_OPEN_WDMAUD: + case IOCTL_OPEN_MIXER: + return WdmAudControlOpen(DeviceObject, Irp, DeviceInfo, ClientInfo); + case IOCTL_GETNUMDEVS_TYPE: + return WdmAudControlDeviceType(DeviceObject, Irp, DeviceInfo, ClientInfo); + case IOCTL_GETCAPABILITIES: + return WdmAudCapabilities(DeviceObject, Irp, DeviceInfo, ClientInfo); + case IOCTL_CLOSE_WDMAUD: + return WdmAudIoctlClose(DeviceObject, Irp, DeviceInfo, ClientInfo); + case IOCTL_GET_MIXER_EVENT: + return WdmAudGetMixerEvent(DeviceObject, Irp, DeviceInfo, ClientInfo); + case IOCTL_GETLINEINFO: + return WdmAudGetLineInfo(DeviceObject, Irp, DeviceInfo, ClientInfo); + case IOCTL_GETLINECONTROLS: + return WdmAudGetLineControls(DeviceObject, Irp, DeviceInfo, ClientInfo); + case IOCTL_SETCONTROLDETAILS: + return WdmAudSetControlDetails(DeviceObject, Irp, DeviceInfo, ClientInfo); + case IOCTL_GETCONTROLDETAILS: + return WdmAudGetControlDetails(DeviceObject, Irp, DeviceInfo, ClientInfo); + case IOCTL_RESET_CAPTURE: + return WdmAudSetDeviceState(DeviceObject, Irp, DeviceInfo, KSSTATE_STOP, TRUE); + case IOCTL_RESET_PLAYBACK: + break; + //return WdmAudResetStream(DeviceObject, Irp, DeviceInfo, TRUE); + case IOCTL_GETINPOS: + case IOCTL_GETOUTPOS: + return WdmAudGetPosition(DeviceObject, Irp, DeviceInfo); + case IOCTL_PAUSE_CAPTURE: + return WdmAudSetDeviceState(DeviceObject, Irp, DeviceInfo, KSSTATE_STOP, TRUE); + case IOCTL_PAUSE_PLAYBACK: + break; + //return WdmAudSetDeviceState(DeviceObject, Irp, DeviceInfo, KSSTATE_PAUSE, TRUE); + case IOCTL_START_CAPTURE: + case IOCTL_START_PLAYBACK: + return WdmAudSetDeviceState(DeviceObject, Irp, DeviceInfo, KSSTATE_RUN, TRUE); + case IOCTL_READDATA: + case IOCTL_WRITEDATA: + return WdmAudReadWriteInQueue(DeviceObject, Irp); + case IOCTL_ADD_DEVNODE: + case IOCTL_REMOVE_DEVNODE: + case IOCTL_GETVOLUME: + case IOCTL_SETVOLUME: + + default: + DPRINT1("Unhandled 0x%x\n", IoStack->Parameters.DeviceIoControl.IoControlCode); + break; + } + + return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0); } diff --git a/drivers/wdm/audio/legacy/wdmaud/deviface.c b/drivers/wdm/audio/legacy/wdmaud/deviface.c index 8fafcfd8257a7..c56fc40e4f13a 100644 --- a/drivers/wdm/audio/legacy/wdmaud/deviface.c +++ b/drivers/wdm/audio/legacy/wdmaud/deviface.c @@ -9,9 +9,10 @@ #include "wdmaud.h" -#define NDEBUG +#define YDEBUG #include + NTSTATUS WdmAudOpenSysAudioDevice( IN LPWSTR DeviceName, @@ -39,147 +40,88 @@ WdmAudOpenSysAudioDevice( CreateFileTypeNone, NULL, IO_NO_PARAMETER_CHECKING | IO_FORCE_ACCESS_CHECK); - + DPRINT("IoCreateFile status 0x%lx\n", Status); return Status; } -NTSTATUS -NTAPI -DeviceInterfaceChangeCallback( - IN PVOID NotificationStructure, - IN PVOID Context) -{ - DEVICE_INTERFACE_CHANGE_NOTIFICATION * Event = (DEVICE_INTERFACE_CHANGE_NOTIFICATION*)NotificationStructure; - - DPRINT1("DeviceInterfaceChangeCallback called %p\n", Event); - DbgBreakPoint(); - return STATUS_SUCCESS; -} - -NTSTATUS -WdmAudOpenSysAudioDeviceInterfaces( - IN PWDMAUD_DEVICE_EXTENSION DeviceExtension, - IN LPWSTR SymbolicLinkList) -{ - SYSAUDIO_ENTRY * Entry; - ULONG Length; - - DPRINT1("WdmAudOpenSysAudioDeviceInterfaces called\n"); - - while(*SymbolicLinkList) - { - Length = wcslen(SymbolicLinkList) + 1; - Entry = (SYSAUDIO_ENTRY*)AllocateItem(NonPagedPool, sizeof(SYSAUDIO_ENTRY) + Length * sizeof(WCHAR)); - if (!Entry) - { - return STATUS_INSUFFICIENT_RESOURCES; - } - - Entry->SymbolicLink.Length = Length * sizeof(WCHAR); - Entry->SymbolicLink.MaximumLength = Length * sizeof(WCHAR); - Entry->SymbolicLink.Buffer = (LPWSTR) (Entry + 1); - wcscpy(Entry->SymbolicLink.Buffer, SymbolicLinkList); - - InsertTailList(&DeviceExtension->SysAudioDeviceList, &Entry->Entry); - - DeviceExtension->NumSysAudioDevices++; - SymbolicLinkList += Length; - } - return STATUS_SUCCESS; -} - - NTSTATUS WdmAudOpenSysAudioDevices( IN PDEVICE_OBJECT DeviceObject, IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) { NTSTATUS Status = STATUS_SUCCESS; - LPWSTR SymbolicLinkList; - SYSAUDIO_ENTRY * Entry; - ULONG Length; + LPWSTR SymbolicLinkList, SymbolicLink; HANDLE hSysAudio; PFILE_OBJECT FileObject; - UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\sysaudio\\GLOBAL"); - if (DeviceExtension->DeviceInterfaceSupport) + Status = IoGetDeviceInterfaces(&KSCATEGORY_SYSAUDIO, + NULL, + 0, + &SymbolicLinkList); + + if (!NT_SUCCESS(Status)) { - Status = IoGetDeviceInterfaces(&KSCATEGORY_SYSAUDIO, - NULL, - 0, - &SymbolicLinkList); + return Status; + } + for (SymbolicLink = SymbolicLinkList; + *SymbolicLink != UNICODE_NULL; + SymbolicLink += wcslen(SymbolicLink) + 1) + { + DPRINT("Opening device %S\n", SymbolicLink); + Status = WdmAudOpenSysAudioDevice(SymbolicLink, &hSysAudio); if (NT_SUCCESS(Status)) { - WdmAudOpenSysAudioDeviceInterfaces(DeviceExtension, SymbolicLinkList); - FreeItem(SymbolicLinkList); + DPRINT("Successfully opened %S, handle %p\n", SymbolicLink, hSysAudio); + break; } + } + if (!hSysAudio) + { + DPRINT1("Failed to find sysaudio devices 0x%lx\n", Status); + FreeItem(SymbolicLinkList); + return Status; + } - Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, - PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, - (PVOID)&KSCATEGORY_SYSAUDIO, - DeviceObject->DriverObject, - DeviceInterfaceChangeCallback, - (PVOID)DeviceExtension, - &DeviceExtension->SysAudioNotification); + /* get the file object */ + Status = ObReferenceObjectByHandle(hSysAudio, + FILE_READ_DATA | FILE_WRITE_DATA, + *IoFileObjectType, + KernelMode, + (PVOID*)&FileObject, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to reference FileObject %x\n", Status); + ZwClose(hSysAudio); + FreeItem(SymbolicLinkList); + return Status; } - else + + DeviceExtension->NumSysAudioDevices++; + DeviceExtension->hSysAudio = hSysAudio; + DeviceExtension->FileObject = FileObject; + + return STATUS_SUCCESS; +} + +NTSTATUS +GetSysAudioDeviceInterface( + OUT LPWSTR* SymbolicLinkList) +{ + NTSTATUS Status; + + /* Get SysAudio device interface */ + Status = IoGetDeviceInterfaces(&KSCATEGORY_SYSAUDIO, NULL, 0, SymbolicLinkList); + if (!NT_SUCCESS(Status)) { - Entry = (SYSAUDIO_ENTRY*)AllocateItem(NonPagedPool, sizeof(SYSAUDIO_ENTRY)); - if (!Entry) - { - return STATUS_INSUFFICIENT_RESOURCES; - } - - - Length = wcslen(DeviceName.Buffer) + 1; - Entry->SymbolicLink.Length = 0; - Entry->SymbolicLink.MaximumLength = Length * sizeof(WCHAR); - Entry->SymbolicLink.Buffer = AllocateItem(NonPagedPool, Entry->SymbolicLink.MaximumLength); - - if (!Entry->SymbolicLink.Buffer) - { - FreeItem(Entry); - return STATUS_INSUFFICIENT_RESOURCES; - } - - Status = RtlAppendUnicodeStringToString(&Entry->SymbolicLink, &DeviceName); - - if (!NT_SUCCESS(Status)) - { - FreeItem(Entry->SymbolicLink.Buffer); - FreeItem(Entry); - return Status; - } - - DPRINT("Opening device %S\n", Entry->SymbolicLink.Buffer); - Status = WdmAudOpenSysAudioDevice(Entry->SymbolicLink.Buffer, &hSysAudio); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to open sysaudio %x\n", Status); - FreeItem(Entry->SymbolicLink.Buffer); - FreeItem(Entry); - return Status; - } - - InsertTailList(&DeviceExtension->SysAudioDeviceList, &Entry->Entry); - DeviceExtension->NumSysAudioDevices++; - - /* get the file object */ - Status = ObReferenceObjectByHandle(hSysAudio, FILE_READ_DATA | FILE_WRITE_DATA, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to reference FileObject %x\n", Status); - ZwClose(hSysAudio); - return Status; - } - DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - DeviceExtension->hSysAudio = hSysAudio; - DeviceExtension->FileObject = FileObject; + DPRINT1("IoGetDeviceInterfaces failed with 0x%lx\n", Status); + return Status; } - return Status; + DPRINT("Got SysAudio device interface %ls\n", *SymbolicLinkList); + return STATUS_SUCCESS; } NTSTATUS @@ -195,7 +137,6 @@ WdmAudRegisterDeviceInterface( { IoSetDeviceInterfaceState(&SymbolicLinkName, TRUE); RtlFreeUnicodeString(&SymbolicLinkName); - //DeviceExtension->DeviceInterfaceSupport = TRUE; return Status; } @@ -203,7 +144,7 @@ WdmAudRegisterDeviceInterface( } NTSTATUS -WdmAudOpenSysaudio( +WdmAudAllocateContext( IN PDEVICE_OBJECT DeviceObject, IN PWDMAUD_CLIENT *pClient) { @@ -219,9 +160,6 @@ WdmAudOpenSysaudio( return STATUS_UNSUCCESSFUL; } - /* sanity check */ - ASSERT(!IsListEmpty(&DeviceExtension->SysAudioDeviceList)); - /* allocate client context struct */ Client = AllocateItem(NonPagedPool, sizeof(WDMAUD_CLIENT)); diff --git a/drivers/wdm/audio/legacy/wdmaud/entry.c b/drivers/wdm/audio/legacy/wdmaud/entry.c index 158fe92a5a10a..20b7d88784436 100644 --- a/drivers/wdm/audio/legacy/wdmaud/entry.c +++ b/drivers/wdm/audio/legacy/wdmaud/entry.c @@ -133,9 +133,6 @@ WdmaudAddDevice( return Status; } - /* initialize sysaudio device list */ - InitializeListHead(&DeviceExtension->SysAudioDeviceList); - /* initialize client context device list */ InitializeListHead(&DeviceExtension->WdmAudClientList); @@ -229,17 +226,16 @@ WdmAudCreate( WdmAudInitWorkerRoutine(DeviceObject, NULL); } - - Status = WdmAudOpenSysaudio(DeviceObject, &pClient); + Status = WdmAudAllocateContext(DeviceObject, &pClient); if (!NT_SUCCESS(Status)) { - DPRINT1("Failed to open sysaudio!\n"); + DPRINT1("Failed to allocate context, status 0x%lx!\n", Status); /* complete and forget */ - Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); /* done */ - return STATUS_UNSUCCESSFUL; + return Status; } IoStack = IoGetCurrentIrpStackLocation(Irp); @@ -324,7 +320,7 @@ WdmAudCleanup( if (pClient->hPins[Index].Handle && pClient->hPins[Index].Type != MIXER_DEVICE_TYPE) { /* found an still open audio pin */ - ZwClose(pClient->hPins[Index].Handle); + ClosePin(pClient, Index); } WdmAudCloseAllMixers(DeviceObject, pClient, Index); } diff --git a/drivers/wdm/audio/legacy/wdmaud/interface.h b/drivers/wdm/audio/legacy/wdmaud/interface.h index a6877e3dd8c3a..62f644ae52294 100644 --- a/drivers/wdm/audio/legacy/wdmaud/interface.h +++ b/drivers/wdm/audio/legacy/wdmaud/interface.h @@ -5,110 +5,144 @@ /// /// History: 12/02/2008 Created -// These are now in sndtypes.h -/* -typedef enum +#include + +/* Fixing alignment is needed to make the struct size compatible with MS */ +#pragma pack(1) + +/* Contains device state management related stuff */ +typedef struct { - DEVICE_TYPE_NONE = 0, - DEVICE_TYPE_WAVE_OUT, - DEVICE_TYPE_WAVE_IN, - DEVICE_TYPE_MIDI_IN, - DEVICE_TYPE_MIDI_OUT, - DEVICE_TYPE_AUX_IN, - DEVICE_TYPE_AUX_OUT + DWORD unk1; + HANDLE hThread; // Verified to match Windows XP/2003, the sound thread handle. + DWORD unk2; -}AUDIO_DEVICE_TYPE; -*/ + LPWAVEHDR WaveQueue; // Verified to match Windows XP/2003, wave queue header. + LPMIDIHDR MidiQueue; // Verified to match Windows XP/2003, midi queue header. -#include + DWORD unk3; + DWORD unk4; + + HANDLE hNotifyEvent; // Verified to match Windows XP/2003, queue notification event. + HANDLE hStopEvent; // Verified to match Windows XP/2003, queue stop event. + BOOL unk5; + BOOL bReset; // Verified to match Windows XP/2003, indicates whether device is starting to be reset. + BOOL bStart; // Verified to match Windows XP/2003, indicates whether device is to be started. + BOOL bStartInThread; // Verified to match Windows XP/2003, indicates whether the sound is started in thread. + + char unk6; + char unk7; + +}WDMAUD_DEVICE_STATE, *PWDMAUD_DEVICE_STATE; + +/* Contains the main information about a sound device */ typedef struct { - KSSTREAM_HEADER Header; - SOUND_DEVICE_TYPE DeviceType; - ULONG_PTR DeviceIndex; - - HANDLE hDevice; - ULONG DeviceCount; - ULONG Flags; - - union - { - MIXERCAPSW MixCaps; - MIXERCONTROLDETAILS MixDetails; - MIXERLINECONTROLSW MixControls; - MIXERLINEW MixLine; - WAVEFORMATEX WaveFormatEx; - WAVEOUTCAPSW WaveOutCaps; - AUXCAPSW AuxCaps; - WAVEINCAPSW WaveInCaps; - MIDIINCAPSW MidiInCaps; - MIDIOUTCAPSW MidiOutCaps; - ULONGLONG Position; - struct - { - LPWSTR DeviceInterfaceString; - ULONG DeviceInterfaceStringSize; - }Interface; - - struct - { - HANDLE hMixer; - ULONG NotificationType; - ULONG Value; - }MixerEvent; - KSSTATE State; - KSRESET ResetStream; - ULONG Volume; - ULONG FrameSize; - HANDLE hNotifyEvent; - }u; + PVOID unk1; + DWORD DeviceIndex; // Verified to match Windows XP/2003, indicates the ordering number of device. + SOUND_DEVICE_TYPE DeviceType; // Verified to match Windows XP/2003, indicates the type of the sound device, from 0 to 5. + HANDLE hDevice; // Verified to match Windows XP/2003, a handle to an opened audio device. + + DWORD_PTR dwInstance; // Verified to match Windows XP/2003, WinMM client callback's instance from the caller's WAVEOPENDESC structure. + DWORD_PTR dwCallback; // Verified to match Windows XP/2003, WinMM client callback from the caller's WAVEOPENDESC structure. + + DWORD unk2; + + DWORD Flags; // Verified to match Windows XP/2003, wave open flags passed in by the caller. + + PVOID Buffer; // Verified to match Windows XP/2003, optional buffer containing an additional data passed by the caller. It's different for different device management actions. + DWORD BufferSize; // Verified to match Windows XP/2003, the size, in bytes, of optional buffer passed by the caller. + + DWORD unk3; + DWORD unk4; + + HANDLE hMixer; + DWORD NotificationType; + DWORD Value; + + DWORD unk5; + DWORD unk6; + DWORD unk7; + INT unk8; + + PWDMAUD_DEVICE_STATE DeviceState; // Verified to match Windows XP/2003, WDMAUD_DEVICE_STATE structure for this device. + + LPCWSTR DeviceInterfaceString; // Verified to match Windows XP/2003, device interface string for this device. }WDMAUD_DEVICE_INFO, *PWDMAUD_DEVICE_INFO; +#pragma pack() + +/// IOCTL_INIT_WDMAUD +/// +/// Description: This IOCTL does the initialization of wdmaud.sys +/// +/// Arguments: Buffer is NULL, +/// BufferSize is zero +/// Return Code: STATUS_SUCCESS indicates success, otherwise appropriate error code +/// Prerequisites: none +#define IOCTL_INIT_WDMAUD \ + CTL_CODE(FILE_DEVICE_SOUND, \ + 0x0000, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) -/// IOCTL_OPEN_WDMAUD +/// IOCTL_ADD_DEVNODE /// -/// Description: This IOCTL informs wdmaud that an application whats to use wdmsys for a waveOut / waveIn / aux operation +/// Description: This IOCTL adds a new device node /// -/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, -/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure -/// Note: DeviceType identifies the device type, DeviceIndex the index, WaveFormatEx the device details -/// Result: is returned in hDevice +/// Arguments: Buffer is NULL, +/// BufferSize is zero +/// Note: DeviceType identifies the device type, DeviceIndex the index, WaveFormat the device details /// Return Code: STATUS_SUCCESS indicates success, otherwise appropriate error code /// Prerequisites: none -#define IOCTL_OPEN_WDMAUD \ +#define IOCTL_ADD_DEVNODE \ CTL_CODE(FILE_DEVICE_SOUND, \ - 0, \ + 0x0001, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) + +/// IOCTL_REMOVE_DEVNODE +/// +/// Description: This IOCTL removes an existing device node +/// +/// Arguments: Buffer is NULL, +/// BufferSize is zero +/// Note: DeviceType identifies the device type, DeviceIndex the index, WaveFormat the device details +/// Return Code: STATUS_SUCCESS indicates success, otherwise appropriate error code +/// Prerequisites: none +#define IOCTL_REMOVE_DEVNODE \ + CTL_CODE(FILE_DEVICE_SOUND, \ + 0x0002, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) -/// IOCTL_CLOSE_WDMAUD +/// IOCTL_GETCAPABILITIES /// -/// Description: This IOCTL informs that an application has finished with wdmsys and closes the connection +/// Description: This IOCTL retrieves the capabilities of an specific wave out device /// -/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, -/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure -/// Note: DeviceType, DeviceIndex and hDevice must be set +/// Arguments: Buffer is a pointer to a capabilities data, +/// BufferSize is size of capabilities data +/// Note: The DeviceType and DeviceIndex must be set /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: openend device +/// Prerequisites: none -#define IOCTL_CLOSE_WDMAUD \ +#define IOCTL_GETCAPABILITIES \ CTL_CODE(FILE_DEVICE_SOUND, \ - 1, \ + 0x0003, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) \ - + FILE_WRITE_ACCESS) /// IOCTL_GETNUMDEVS_TYPE /// -/// Description: This IOCTL queries the number of devices currently present of a specific type. The caller passes a WDMAUD_DEVICE_INFO structure. +/// Description: This IOCTL queries the number of devices currently present of a specific type. /// -/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, -/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure +/// Arguments: Buffer is NULL, +/// BufferSize is zero /// Note: The DeviceType contains the requested device type. /// Result: The result is returned in DeviceCount /// ReturnCode: STATUS_SUCCESS indicates success @@ -116,263 +150,355 @@ typedef struct #define IOCTL_GETNUMDEVS_TYPE \ CTL_CODE(FILE_DEVICE_SOUND, \ - 2, \ + 0x0004, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) -/// IOCTL_SETDEVICE_STATE +/// IOCTL_OPEN_WDMAUD /// -/// Description: This IOCTL sets an opened waveOut / waveIn / midiIn / midiOut / aux device to specific state +/// Description: This IOCTL informs wdmaud that an application whats to use wdmsys for a waveOut / waveIn / aux operation /// -/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, -/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure -/// Note: The DeviceType, DeviceIndex, hDevice and State member must be set. State determines the new state -/// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: opened device +/// Arguments: Buffer is a pointer to the WAVEFORMATEX structure, +/// BufferSize is size of the WAVEFORMATEX structure +/// Note: DeviceType identifies the device type, DeviceIndex the index, WaveFormat the device details +/// Result: is returned in hDevice +/// Return Code: STATUS_SUCCESS indicates success, otherwise appropriate error code +/// Prerequisites: none -#define IOCTL_SETDEVICE_STATE \ +#define IOCTL_OPEN_WDMAUD \ CTL_CODE(FILE_DEVICE_SOUND, \ - 3, \ + 0x0005, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) - + FILE_WRITE_ACCESS) -/// IOCTL_GETDEVID +/// IOCTL_CLOSE_WDMAUD /// -/// Description: This IOCTL returns the device index by its provided handle +/// Description: This IOCTL informs that an application has finished with wdmsys and closes the connection /// -/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, -/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure -/// Note: The DeviceType and hDevice must be set -/// Result: The result is returned in DeviceIndex +/// Arguments: Buffer is NULL, +/// BufferSize is zero +/// Note: DeviceType, DeviceIndex and hDevice must be set /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: opened device +/// Prerequisites: Openend device -#define IOCTL_GETDEVID \ +#define IOCTL_CLOSE_WDMAUD \ CTL_CODE(FILE_DEVICE_SOUND, \ - 4, \ + 0x0006, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) - + FILE_WRITE_ACCESS) /// IOCTL_GETVOLUME /// -/// Description: This IOCTL returns the volume a device +/// Description: This IOCTL returns the volume to a device /// /// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, /// InputBufferSize is size of WDMAUD_DEVICE_INFO structure /// Note: The DeviceType and hDevice must be set -/// Result: The result is returned in Volume /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: opened device +/// Prerequisites: Opened device #define IOCTL_GETVOLUME \ CTL_CODE(FILE_DEVICE_SOUND, \ - 5, \ + 0x0007, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) /// IOCTL_SETVOLUME /// -/// Description: This IOCTL sets the volume a device +/// Description: This IOCTL sets the volume for a device /// /// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, /// InputBufferSize is size of WDMAUD_DEVICE_INFO structure /// Note: The DeviceType, hDevice and Volume must be set /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: opened device +/// Prerequisites: Opened device #define IOCTL_SETVOLUME \ CTL_CODE(FILE_DEVICE_SOUND, \ - 6, \ + 0x0008, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) -/// IOCTL_GETCAPABILITIES +/// IOCTL_SETVOLUME /// -/// Description: This IOCTL retrieves the capabilities of an specific device +/// Description: This IOCTL does unloading of wdmaud.sys /// -/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, -/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure -/// Note: The DeviceType and DeviceIndex must be set +/// Arguments: InputBuffer is NULL, +/// InputBufferSize is zero /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: none +/// Prerequisites: Initialized device -#define IOCTL_GETCAPABILITIES \ +#define IOCTL_EXIT_WDMAUD \ CTL_CODE(FILE_DEVICE_SOUND, \ - 7, \ + 0x0009, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) +/// IOCTL_PAUSE_PLAYBACK +/// +/// Description: This IOCTL pauses playback of an opened waveOut device +/// +/// Arguments: Buffer is NULL, +/// BufferSize is zero +/// Note: The DeviceType and hDevice members must be set. State determines the new state +/// ReturnCode: STATUS_SUCCESS indicates success +/// Prerequisites: Opened device -/// IOCTL_WRITEDATA +#define IOCTL_PAUSE_PLAYBACK \ + CTL_CODE(FILE_DEVICE_SOUND, \ + 0x0040, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) + +/// IOCTL_START_PLAYBACK /// -/// Description: This IOCTL writes data to specified device +/// Description: This IOCTL starts playback for an opened waveOut device /// -/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, -/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure -/// Note: The DeviceType, DeviceIndex, hDevice, BufferSize and Buffer must be set +/// Arguments: Buffer is NULL, +/// BufferSize is zero +/// Note: The DeviceType and hDevice members must be set. State determines the new state /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: opened device +/// Prerequisites: Opened device -#define IOCTL_WRITEDATA \ +#define IOCTL_START_PLAYBACK \ + CTL_CODE(FILE_DEVICE_SOUND, \ + 0x0041, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) + +/// IOCTL_RESET_PLAYBACK +/// +/// Description: This IOCTL resets the stream for an opened waveOut device to default state +/// +/// Arguments: Buffer is NULL, +/// BufferSize is zero +/// Note: The DeviceType and hDevice members must be set. State determines the new state +/// ReturnCode: STATUS_SUCCESS indicates success +/// Prerequisites: Opened device + +#define IOCTL_RESET_PLAYBACK \ CTL_CODE(FILE_DEVICE_SOUND, \ - 8, \ + 0x0042, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) -/// IOCTL_GETPOS +/// IOCTL_GETOUTPOS /// /// Description: This IOCTL retrieves the current playback / write position /// -/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, -/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure +/// Arguments: Buffer is a pointer to a variable that receives playback / write position, +/// BufferSize is set to size of DWORD /// Note: The DeviceType and hDevice must be set /// Result: The result is returned in Position /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: opened device +/// Prerequisites: Opened device -#define IOCTL_GETPOS \ +#define IOCTL_GETOUTPOS \ CTL_CODE(FILE_DEVICE_SOUND, \ - 9, \ + 0x0044, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) -/// IOCTL_GETFRAMESIZE +/// IOCTL_WRITEDATA /// -/// Description: This IOCTL retrieves the frame size requirements for an audio pin +/// Description: This IOCTL writes data to the specified WaveOut device /// -/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, -/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure +/// Arguments: Buffer is a pointer to a WAVEHDR structure, +/// BufferSize is size of WAVEHDR structure /// Note: The DeviceType and hDevice must be set -/// Result: The result is returned in FrameSize /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: opened device +/// Prerequisites: Opened device -#define IOCTL_GETFRAMESIZE \ +#define IOCTL_WRITEDATA \ CTL_CODE(FILE_DEVICE_SOUND, \ - 10, \ + 0x0047, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) -/// IOCTL_GETLINEINFO +/// IOCTL_PAUSE_CAPTURE /// -/// Description: This IOCTL retrieves information on a mixerline +/// Description: This IOCTL pauses capture of an opened waveIn device /// -/// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, -/// InputBufferSize is size of WDMAUD_DEVICE_INFO structure -/// Note: The hDevice member must be set -/// Result: The result is returned in MixLine +/// Arguments: Buffer is NULL, +/// BufferSize is zero +/// Note: The DeviceType and hDevice members must be set. State determines the new state /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: opened device +/// Prerequisites: Opened device -#define IOCTL_GETLINEINFO \ +#define IOCTL_PAUSE_CAPTURE \ CTL_CODE(FILE_DEVICE_SOUND, \ - 11, \ + 0x0050, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) +/// IOCTL_START_CAPTURE +/// +/// Description: This IOCTL starts capture for an opened waveIn device +/// +/// Arguments: Buffer is NULL, +/// BufferSize is zero +/// Note: The DeviceType and hDevice members must be set. State determines the new state +/// ReturnCode: STATUS_SUCCESS indicates success +/// Prerequisites: Opened device -/// IOCTL_GETLINECONTROLS +#define IOCTL_START_CAPTURE \ + CTL_CODE(FILE_DEVICE_SOUND, \ + 0x0051, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) + +/// IOCTL_RESET_CAPTURE /// -/// Description: This IOCTL retrieves controls of a mixerline +/// Description: This IOCTL resets the stream for an opened waveIn device to default state +/// +/// Arguments: Buffer is NULL, +/// BufferSize is zero +/// Note: The DeviceType and hDevice members must be set. State determines the new state +/// ReturnCode: STATUS_SUCCESS indicates success +/// Prerequisites: Opened device + +#define IOCTL_RESET_CAPTURE \ + CTL_CODE(FILE_DEVICE_SOUND, \ + 0x0052, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) + +/// IOCTL_GETINPOS +/// +/// Description: This IOCTL retrieves the current capture / read position +/// +/// Arguments: Buffer is a pointer to a variable that receives playback / write position, +/// BufferSize is set to size of DWORD +/// Note: The DeviceType and hDevice must be set +/// Result: The result is returned in Position +/// ReturnCode: STATUS_SUCCESS indicates success +/// Prerequisites: Opened device + +#define IOCTL_GETINPOS \ + CTL_CODE(FILE_DEVICE_SOUND, \ + 0x0053, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) + +/// IOCTL_READDATA +/// +/// Description: This IOCTL reads data from the specified WaveIn device +/// +/// Arguments: Buffer is a pointer to a WAVEHDR structure, +/// BufferSize is size of WAVEHDR structure +/// Note: The DeviceType and hDevice must be set +/// ReturnCode: STATUS_SUCCESS indicates success +/// Prerequisites: Opened device + +#define IOCTL_READDATA \ + CTL_CODE(FILE_DEVICE_SOUND, \ + 0x0054, \ + METHOD_BUFFERED, \ + FILE_WRITE_ACCESS) + +/// IOCTL_OPEN_MIXER +/// +/// Description: This IOCTL opens mixer device /// /// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, /// InputBufferSize is size of WDMAUD_DEVICE_INFO structure /// Note: The hDevice member must be set -/// Result: The result is returned in MixControls +/// Result: The result is returned in MixLine /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: opened device +/// Prerequisites: Opened device -#define IOCTL_GETLINECONTROLS \ +#define IOCTL_OPEN_MIXER \ CTL_CODE(FILE_DEVICE_SOUND, \ - 12, \ + 0x00C0, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) - -/// IOCTL_SETCONTROLDETAILS +/// IOCTL_GET_MIXER_EVENT /// -/// Description: This IOCTL sets details of a control of a mixerline +/// Description: This IOCTL queries for wdmaud driver if there any new kernel streaming events available /// /// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, /// InputBufferSize is size of WDMAUD_DEVICE_INFO structure /// Note: The hDevice member must be set +/// Result: The result is returned in the struct MixerInfo /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: opened device -#define IOCTL_SETCONTROLDETAILS \ +#define IOCTL_GET_MIXER_EVENT \ CTL_CODE(FILE_DEVICE_SOUND, \ - 13, \ + 0x00C6, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) - -/// IOCTL_GETCONTROLDETAILS +/// IOCTL_GETLINEINFO /// -/// Description: This IOCTL gets details of a control of a mixerline +/// Description: This IOCTL retrieves information on a mixerline /// /// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, /// InputBufferSize is size of WDMAUD_DEVICE_INFO structure /// Note: The hDevice member must be set -/// Result: The result is returned in MixDetails +/// Result: The result is returned in MixLine /// ReturnCode: STATUS_SUCCESS indicates success -/// Prerequisites: opened device +/// Prerequisites: Opened device -#define IOCTL_GETCONTROLDETAILS \ +#define IOCTL_GETLINEINFO \ CTL_CODE(FILE_DEVICE_SOUND, \ - 14, \ + 0x00C2, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) -/// IOCTL_QUERYDEVICEINTERFACESTRING +/// IOCTL_GETLINECONTROLS /// -/// Description: This IOCTL queries the mixer / playback / recording device for its device interface string +/// Description: This IOCTL retrieves controls of a mixerline /// /// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, /// InputBufferSize is size of WDMAUD_DEVICE_INFO structure -/// Note: The DeviceType, DeviceIndex must be set -/// Result: The size is returned in Interface.DeviceInterfaceStringSize and if a buffer is supplied in Interface.DeviceInterfaceString -/// the device interface string is stored +/// Note: The hDevice member must be set +/// Result: The result is returned in MixControls /// ReturnCode: STATUS_SUCCESS indicates success +/// Prerequisites: Opened device -#define IOCTL_QUERYDEVICEINTERFACESTRING \ +#define IOCTL_GETLINECONTROLS \ CTL_CODE(FILE_DEVICE_SOUND, \ - 15, \ + 0x00C3, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) -/// IOCTL_GET_MIXER_EVENT + +/// IOCTL_SETCONTROLDETAILS /// -/// Description: This IOCTL queries for wdmaud driver if there any new kernel streaming events available +/// Description: This IOCTL sets details of a control of a mixerline /// /// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, /// InputBufferSize is size of WDMAUD_DEVICE_INFO structure /// Note: The hDevice member must be set -/// Result: The result is returned in the struct MixerInfo /// ReturnCode: STATUS_SUCCESS indicates success +/// Prerequisites: Opened device -#define IOCTL_GET_MIXER_EVENT \ +#define IOCTL_SETCONTROLDETAILS \ CTL_CODE(FILE_DEVICE_SOUND, \ - 16, \ + 0x00C4, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) -/// IOCTL_RESET_STREAM + +/// IOCTL_GETCONTROLDETAILS /// -/// Description: This IOCTL instructs wdmaud to reset a stream +/// Description: This IOCTL gets details of a control of a mixerline /// /// Arguments: InputBuffer is a pointer to a WDMAUD_DEVICE_INFO structure, /// InputBufferSize is size of WDMAUD_DEVICE_INFO structure -/// Note: The hDevice member must be set and DeviceType +/// Note: The hDevice member must be set +/// Result: The result is returned in MixDetails /// ReturnCode: STATUS_SUCCESS indicates success +/// Prerequisites: Opened device -#define IOCTL_RESET_STREAM \ +#define IOCTL_GETCONTROLDETAILS \ CTL_CODE(FILE_DEVICE_SOUND, \ - 17, \ + 0x00C5, \ METHOD_BUFFERED, \ - FILE_CREATE_TREE_CONNECTION | FILE_ANY_ACCESS) + FILE_WRITE_ACCESS) + diff --git a/drivers/wdm/audio/legacy/wdmaud/mmixer.c b/drivers/wdm/audio/legacy/wdmaud/mmixer.c index dbf97ba56081d..02e48096890ef 100644 --- a/drivers/wdm/audio/legacy/wdmaud/mmixer.c +++ b/drivers/wdm/audio/legacy/wdmaud/mmixer.c @@ -10,7 +10,7 @@ #include -#define NDEBUG +#define YDEBUG #include PVOID Alloc(ULONG NumBytes); @@ -202,10 +202,10 @@ Control( PFILE_OBJECT FileObject; /* get file object */ - Status = ObReferenceObjectByHandle(hMixer, GENERIC_READ | GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); + Status = ObReferenceObjectByHandle(hMixer, GENERIC_READ | GENERIC_WRITE, NULL, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { - DPRINT("failed to reference %p with %lx\n", hMixer, Status); + DPRINT("failed to reference %p with 0x%lx\n", hMixer, Status); return MM_STATUS_UNSUCCESSFUL; } @@ -227,7 +227,7 @@ Control( } else { - DPRINT("Failed with %lx\n", Status); + DPRINT("KsSynchronousIoControlDevice failed with 0x%lx\n", Status); return MM_STATUS_UNSUCCESSFUL; } } @@ -263,6 +263,7 @@ Enum( if (!NT_SUCCESS(Status)) { /* failed to retrieve device name */ + DPRINT1("Status 0x%lx\n", Status); return MM_STATUS_UNSUCCESSFUL; } @@ -389,19 +390,21 @@ WdmAudMixerInitialize( { /* failed to initialize mmixer library */ DPRINT("MMixerInitialize failed with %lx\n", Status); + return STATUS_UNSUCCESSFUL; } - return Status; + return STATUS_SUCCESS; } NTSTATUS WdmAudMixerCapabilities( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo, IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) { - if (MMixerGetCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MixCaps) == MM_STATUS_SUCCESS) + if (MMixerGetCapabilities(&MixerContext, DeviceInfo->DeviceIndex, (LPMIXERCAPSW)DeviceInfo->Buffer) == MM_STATUS_SUCCESS) return STATUS_SUCCESS; return STATUS_INVALID_PARAMETER; @@ -414,61 +417,15 @@ WdmAudControlOpenMixer( IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo) { - HANDLE hMixer; - PWDMAUD_HANDLE Handles; - //PWDMAUD_DEVICE_EXTENSION DeviceExtension; - NTSTATUS Status; - PKEVENT EventObject = NULL; - DPRINT("WdmAudControlOpenMixer\n"); - //DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - - if (DeviceInfo->u.hNotifyEvent) + if (MMixerOpen(&MixerContext, DeviceInfo->DeviceIndex, ClientInfo, EventCallback, &DeviceInfo->hDevice) != MM_STATUS_SUCCESS) { - Status = ObReferenceObjectByHandle(DeviceInfo->u.hNotifyEvent, EVENT_MODIFY_STATE, *ExEventObjectType, UserMode, (LPVOID*)&EventObject, NULL); - - if (!NT_SUCCESS(Status)) - { - DPRINT1("Invalid notify event passed %p from client %p\n", DeviceInfo->u.hNotifyEvent, ClientInfo); - DbgBreakPoint(); - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); - } - } - - if (MMixerOpen(&MixerContext, DeviceInfo->DeviceIndex, ClientInfo, EventCallback, &hMixer) != MM_STATUS_SUCCESS) - { - ObDereferenceObject(EventObject); DPRINT1("Failed to open mixer\n"); - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); - } - - - Handles = AllocateItem(NonPagedPool, sizeof(WDMAUD_HANDLE) * (ClientInfo->NumPins+1)); - - if (Handles) - { - if (ClientInfo->NumPins) - { - RtlMoveMemory(Handles, ClientInfo->hPins, sizeof(WDMAUD_HANDLE) * ClientInfo->NumPins); - FreeItem(ClientInfo->hPins); - } - - ClientInfo->hPins = Handles; - ClientInfo->hPins[ClientInfo->NumPins].Handle = hMixer; - ClientInfo->hPins[ClientInfo->NumPins].Type = MIXER_DEVICE_TYPE; - ClientInfo->hPins[ClientInfo->NumPins].NotifyEvent = EventObject; - ClientInfo->NumPins++; - } - else - { - ObDereferenceObject(EventObject); - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); + return STATUS_UNSUCCESSFUL; } - DeviceInfo->hDevice = hMixer; - - return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + return STATUS_SUCCESS; } NTSTATUS @@ -503,13 +460,10 @@ WdmAudCloseAllMixers( IN PWDMAUD_CLIENT ClientInfo, IN ULONG Index) { - ULONG DeviceCount, DeviceIndex; - - /* Get all mixers */ - DeviceCount = GetSysAudioDeviceCount(DeviceObject); + ULONG DeviceIndex; /* Close every mixer attached to the device */ - for (DeviceIndex = 0; DeviceIndex < DeviceCount; DeviceIndex++) + for (DeviceIndex = 0; DeviceIndex < Index; DeviceIndex++) { if (MMixerClose(&MixerContext, DeviceIndex, ClientInfo, EventCallback) != MM_STATUS_SUCCESS) { @@ -539,7 +493,7 @@ WdmAudGetControlDetails( DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER; /* query mmixer library */ - Status = MMixerGetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixDetails); + Status = MMixerGetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, (LPMIXERCONTROLDETAILS)DeviceInfo->Buffer); if (Status == MM_STATUS_SUCCESS) return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); @@ -561,7 +515,7 @@ WdmAudGetLineInfo( DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER; /* query mixer library */ - Status = MMixerGetLineInfo(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixLine); + Status = MMixerGetLineInfo(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, (LPMIXERLINEW)DeviceInfo->Buffer); if (Status == MM_STATUS_SUCCESS) return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); @@ -583,7 +537,7 @@ WdmAudGetLineControls( DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER; /* query mixer library */ - Status = MMixerGetLineControls(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixControls); + Status = MMixerGetLineControls(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, (LPMIXERLINECONTROLSW)DeviceInfo->Buffer); if (Status == MM_STATUS_SUCCESS) return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); @@ -607,7 +561,7 @@ WdmAudSetControlDetails( DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER; /* query mixer library */ - Status = MMixerSetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixDetails); + Status = MMixerSetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, (LPMIXERCONTROLDETAILS)&DeviceInfo->Buffer); if (Status == MM_STATUS_SUCCESS) return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); @@ -637,9 +591,9 @@ WdmAudGetMixerEvent( if (EventEntry->hMixer == DeviceInfo->hDevice) { /* found an entry */ - DeviceInfo->u.MixerEvent.hMixer = EventEntry->hMixer; - DeviceInfo->u.MixerEvent.NotificationType = EventEntry->NotificationType; - DeviceInfo->u.MixerEvent.Value = EventEntry->Value; + DeviceInfo->hMixer = EventEntry->hMixer; + DeviceInfo->NotificationType = EventEntry->NotificationType; + DeviceInfo->Value = EventEntry->Value; /* remove entry from list */ RemoveEntryList(&EventEntry->Entry); @@ -720,6 +674,7 @@ WdmAudGetPnpNameByIndexAndType( NTSTATUS WdmAudWaveCapabilities( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo, IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) @@ -729,23 +684,24 @@ WdmAudWaveCapabilities( if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) { /* get capabilities */ - Status = MMixerWaveInCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveInCaps); + Status = MMixerWaveInCapabilities(&MixerContext, DeviceInfo->DeviceIndex, (LPWAVEINCAPSW)DeviceInfo->Buffer); } else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { /* get capabilities */ - Status = MMixerWaveOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.WaveOutCaps); + Status = MMixerWaveOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, (LPWAVEOUTCAPSW)DeviceInfo->Buffer); } if (Status == MM_STATUS_SUCCESS) return STATUS_SUCCESS; else - return Status; + return STATUS_UNSUCCESSFUL; } NTSTATUS WdmAudMidiCapabilities( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo, IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) @@ -755,12 +711,12 @@ WdmAudMidiCapabilities( if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE) { /* get capabilities */ - Status = MMixerMidiInCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MidiInCaps); + Status = MMixerMidiInCapabilities(&MixerContext, DeviceInfo->DeviceIndex, (LPMIDIINCAPSW)DeviceInfo->Buffer); } - else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + else if (DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE) { /* get capabilities */ - Status = MMixerMidiOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->u.MidiOutCaps); + Status = MMixerMidiOutCapabilities(&MixerContext, DeviceInfo->DeviceIndex, (LPMIDIOUTCAPSW)DeviceInfo->Buffer); } if (Status == MM_STATUS_SUCCESS) @@ -769,6 +725,26 @@ WdmAudMidiCapabilities( return STATUS_UNSUCCESSFUL; } +NTSTATUS +NTAPI +WdmAudGetPosition( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PWDMAUD_DEVICE_INFO DeviceInfo) +{ + MIXER_STATUS Status; + DWORD Position; + + Status = MMixerGetWavePosition(&MixerContext, DeviceInfo->hDevice, &Position); + + DeviceInfo->Buffer = (PVOID)&Position; + + DPRINT("Success %x\n", Status == MM_STATUS_SUCCESS); + if (Status == MM_STATUS_SUCCESS) + return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + else + return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); +} MIXER_STATUS CreatePinCallback( @@ -781,39 +757,57 @@ CreatePinCallback( OUT PHANDLE PinHandle) { ULONG BytesReturned; - SYSAUDIO_INSTANCE_INFO InstanceInfo; + KSPROPERTY Property; NTSTATUS Status; ULONG FreeIndex; + PFILE_OBJECT PinFileObject; PPIN_CREATE_CONTEXT Context = (PPIN_CREATE_CONTEXT)Ctx; /* setup property request */ - InstanceInfo.Property.Set = KSPROPSETID_Sysaudio; - InstanceInfo.Property.Id = KSPROPERTY_SYSAUDIO_INSTANCE_INFO; - InstanceInfo.Property.Flags = KSPROPERTY_TYPE_SET; - InstanceInfo.Flags = 0; - InstanceInfo.DeviceNumber = VirtualDeviceId; + Property.Set = KSPROPSETID_Sysaudio; + Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_INSTANCE; + Property.Flags = KSPROPERTY_TYPE_SET; /* attach to virtual device */ - Status = KsSynchronousIoControlDevice(Context->DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&InstanceInfo, sizeof(SYSAUDIO_INSTANCE_INFO), NULL, 0, &BytesReturned); - + Status = KsSynchronousIoControlDevice(Context->DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&VirtualDeviceId, sizeof(ULONG), &BytesReturned); if (!NT_SUCCESS(Status)) + { + DPRINT1("KSPROPERTY_SYSAUDIO_DEVICE_INSTANCE failed with status 0x%lx\n", Status); return MM_STATUS_UNSUCCESSFUL; + } /* close existing pin */ - FreeIndex = ClosePin(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType); + FreeIndex = ClosePinByIndex(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType); /* now create the pin */ Status = KsCreatePin(Context->DeviceExtension->hSysAudio, PinConnect, DesiredAccess, PinHandle); + if (!NT_SUCCESS(Status)) + { + /* failed to create the pin */ + DPRINT1("KsCreatePin failed with status 0x%lx\n", Status); + return MM_STATUS_UNSUCCESSFUL; + } - /* check for success */ + /* get pin file object */ + Status = ObReferenceObjectByHandle(*PinHandle, + FILE_READ_DATA | FILE_WRITE_DATA, + *IoFileObjectType, + KernelMode, + (PVOID*)&PinFileObject, + NULL); if (!NT_SUCCESS(Status)) + { + DPRINT1("ObReferenceObjectByHandle failed with 0x%lx for %p\n", Status, *PinHandle); + ZwClose(*PinHandle); return MM_STATUS_UNSUCCESSFUL; + } /* store the handle */ - Status = InsertPinHandle(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType, *PinHandle, FreeIndex); + Status = InsertPinHandle(Context->ClientInfo, VirtualDeviceId, PinId, Context->DeviceType, *PinHandle, PinFileObject, FreeIndex); if (!NT_SUCCESS(Status)) { /* failed to insert handle */ + ObDereferenceObject(PinFileObject); ZwClose(*PinHandle); return MM_STATUS_UNSUCCESSFUL; } @@ -835,12 +829,12 @@ WdmAudControlOpenWave( Context.DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; Context.DeviceType = DeviceInfo->DeviceType; - Status = MMixerOpenWave(&MixerContext, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE, &DeviceInfo->u.WaveFormatEx, CreatePinCallback, &Context, &DeviceInfo->hDevice); + Status = MMixerOpenWave(&MixerContext, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE, (LPWAVEFORMATEX)DeviceInfo->Buffer, CreatePinCallback, &Context, &DeviceInfo->hDevice); if (Status == MM_STATUS_SUCCESS) - return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + return STATUS_SUCCESS; else - return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO)); + return STATUS_NOT_SUPPORTED; } NTSTATUS @@ -860,7 +854,7 @@ WdmAudControlOpenMidi( Status = MMixerOpenMidi(&MixerContext, DeviceInfo->DeviceIndex, DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE, CreatePinCallback, &Context, &DeviceInfo->hDevice); if (Status == MM_STATUS_SUCCESS) - return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + return STATUS_SUCCESS; else - return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO)); + return STATUS_NOT_SUPPORTED; } diff --git a/drivers/wdm/audio/legacy/wdmaud/sup.c b/drivers/wdm/audio/legacy/wdmaud/sup.c index 91334c09bb3dc..109e5cb1efa7a 100644 --- a/drivers/wdm/audio/legacy/wdmaud/sup.c +++ b/drivers/wdm/audio/legacy/wdmaud/sup.c @@ -11,7 +11,7 @@ #include -#define NDEBUG +#define YDEBUG #include #define TAG_WDMAUD 'DMDW' @@ -62,7 +62,6 @@ GetSysAudioDeviceCount( return Count; } - NTSTATUS SetIrpIoStatus( IN PIRP Irp, @@ -73,11 +72,10 @@ SetIrpIoStatus( Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; - } ULONG -ClosePin( +ClosePinByIndex( IN PWDMAUD_CLIENT ClientInfo, IN ULONG FilterId, IN ULONG PinId, @@ -85,15 +83,46 @@ ClosePin( { ULONG Index; + for (Index = 0; Index < ClientInfo->NumPins; Index++) + { + if (ClientInfo->hPins[Index].FilterId == FilterId && + ClientInfo->hPins[Index].PinId == PinId && + ClientInfo->hPins[Index].Handle && + ClientInfo->hPins[Index].Type == DeviceType) + { + DPRINT("Closing pin %p, index %d\n", ClientInfo->hPins[Index].Handle, Index); + ClosePin(ClientInfo, Index); + return Index; + } + } + return MAXULONG; +} + +VOID +ClosePin( + IN PWDMAUD_CLIENT ClientInfo, + IN ULONG Index) +{ + if (ClientInfo->hPins[Index].Type != MIXER_DEVICE_TYPE) + { + ObDereferenceObject(ClientInfo->hPins[Index].FileObject); + ZwClose(ClientInfo->hPins[Index].Handle); + ClientInfo->hPins[Index].Handle = NULL; + ClientInfo->hPins[Index].Active = FALSE; + } +} + +ULONG +GetActivePin( + IN PWDMAUD_CLIENT ClientInfo) +{ + ULONG Index; + for(Index = 0; Index < ClientInfo->NumPins; Index++) { - if (ClientInfo->hPins[Index].FilterId == FilterId && ClientInfo->hPins[Index].PinId == PinId && ClientInfo->hPins[Index].Handle && ClientInfo->hPins[Index].Type == DeviceType) + if (ClientInfo->hPins[Index].Active == TRUE && + ClientInfo->hPins[Index].Type != MIXER_DEVICE_TYPE) { - if (ClientInfo->hPins[Index].Type != MIXER_DEVICE_TYPE) - { - ZwClose(ClientInfo->hPins[Index].Handle); - } - ClientInfo->hPins[Index].Handle = NULL; return Index; } } @@ -107,6 +136,7 @@ InsertPinHandle( IN ULONG PinId, IN SOUND_DEVICE_TYPE DeviceType, IN HANDLE PinHandle, + IN PFILE_OBJECT PinFileObject, IN ULONG FreeIndex) { PWDMAUD_HANDLE Handles; @@ -115,9 +145,11 @@ InsertPinHandle( { /* re-use a free index */ ClientInfo->hPins[FreeIndex].Handle = PinHandle; + ClientInfo->hPins[FreeIndex].FileObject = PinFileObject; ClientInfo->hPins[FreeIndex].FilterId = FilterId; ClientInfo->hPins[FreeIndex].PinId = PinId; ClientInfo->hPins[FreeIndex].Type = DeviceType; + ClientInfo->hPins[FreeIndex].Active = TRUE; return STATUS_SUCCESS; } @@ -135,9 +167,11 @@ InsertPinHandle( ClientInfo->hPins = Handles; ClientInfo->hPins[ClientInfo->NumPins].Handle = PinHandle; + ClientInfo->hPins[ClientInfo->NumPins].FileObject = PinFileObject; ClientInfo->hPins[ClientInfo->NumPins].Type = DeviceType; ClientInfo->hPins[ClientInfo->NumPins].FilterId = FilterId; ClientInfo->hPins[ClientInfo->NumPins].PinId = PinId; + ClientInfo->hPins[ClientInfo->NumPins].Active = TRUE; ClientInfo->NumPins++; return STATUS_SUCCESS; @@ -364,9 +398,11 @@ GetSysAudioDevicePnpName( NTSTATUS Status; PWDMAUD_DEVICE_EXTENSION DeviceExtension; - /* first check if the device index is within bounds */ - if (DeviceIndex >= GetSysAudioDeviceCount(DeviceObject)) - return STATUS_INVALID_PARAMETER; + DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + /* first check if the device index is within bounds */ + if (DeviceIndex >= GetSysAudioDeviceCount(DeviceObject)) + return STATUS_INVALID_PARAMETER; /* setup the query request */ Pin.Property.Set = KSPROPSETID_Sysaudio; @@ -374,8 +410,6 @@ GetSysAudioDevicePnpName( Pin.Property.Flags = KSPROPERTY_TYPE_GET; Pin.PinId = DeviceIndex; - DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - /* query sysaudio for the device path */ Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY) + sizeof(ULONG), NULL, 0, &BytesReturned); diff --git a/drivers/wdm/audio/legacy/wdmaud/wdmaud.h b/drivers/wdm/audio/legacy/wdmaud/wdmaud.h index 4c56a87e21ea8..ab7d11a7b9b21 100644 --- a/drivers/wdm/audio/legacy/wdmaud/wdmaud.h +++ b/drivers/wdm/audio/legacy/wdmaud/wdmaud.h @@ -1,7 +1,9 @@ #ifndef _WDMAUD_PCH_ #define _WDMAUD_PCH_ +#include #include +#include #include #include "interface.h" @@ -14,13 +16,14 @@ typedef struct PFILE_OBJECT FileObject; }WDMAUD_COMPLETION_CONTEXT, *PWDMAUD_COMPLETION_CONTEXT; - typedef struct { HANDLE Handle; + PFILE_OBJECT FileObject; SOUND_DEVICE_TYPE Type; ULONG FilterId; ULONG PinId; + BOOL Active; PRKEVENT NotifyEvent; }WDMAUD_HANDLE, *PWDMAUD_HANDLE; @@ -42,22 +45,13 @@ typedef struct HANDLE hMixer; }EVENT_ENTRY, *PEVENT_ENTRY; -typedef struct -{ - LIST_ENTRY Entry; - UNICODE_STRING SymbolicLink; -}SYSAUDIO_ENTRY, *PSYSAUDIO_ENTRY; - typedef struct { KSDEVICE_HEADER DeviceHeader; PVOID SysAudioNotification; - BOOL DeviceInterfaceSupport; - KSPIN_LOCK Lock; ULONG NumSysAudioDevices; - LIST_ENTRY SysAudioDeviceList; HANDLE hSysAudio; PFILE_OBJECT FileObject; LIST_ENTRY WdmAudClientList; @@ -77,17 +71,6 @@ typedef struct SOUND_DEVICE_TYPE DeviceType; }PIN_CREATE_CONTEXT, *PPIN_CREATE_CONTEXT; - -NTSTATUS -NTAPI -OpenWavePin( - IN PWDMAUD_DEVICE_EXTENSION DeviceExtension, - IN ULONG FilterId, - IN ULONG PinId, - IN LPWAVEFORMATEX WaveFormatEx, - IN ACCESS_MASK DesiredAccess, - OUT PHANDLE PinHandle); - NTSTATUS WdmAudRegisterDeviceInterface( IN PDEVICE_OBJECT PhysicalDeviceObject, @@ -99,7 +82,7 @@ WdmAudOpenSysAudioDevices( IN PWDMAUD_DEVICE_EXTENSION DeviceExtension); NTSTATUS -WdmAudOpenSysaudio( +WdmAudAllocateContext( IN PDEVICE_OBJECT DeviceObject, IN PWDMAUD_CLIENT *pClient); @@ -117,7 +100,7 @@ WdmAudReadWrite( NTSTATUS NTAPI -WdmAudWrite( +WdmAudReadWriteInQueue( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); @@ -166,6 +149,10 @@ SetIrpIoStatus( IN NTSTATUS Status, IN ULONG Length); +NTSTATUS +GetSysAudioDeviceInterface( + OUT LPWSTR* SymbolicLonkList); + NTSTATUS WdmAudOpenSysAudioDevice( IN LPWSTR DeviceName, @@ -180,6 +167,7 @@ FindProductName( NTSTATUS WdmAudMixerCapabilities( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo, IN PWDMAUD_DEVICE_EXTENSION DeviceExtension); @@ -187,6 +175,7 @@ WdmAudMixerCapabilities( NTSTATUS WdmAudWaveCapabilities( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo, IN PWDMAUD_DEVICE_EXTENSION DeviceExtension); @@ -194,17 +183,33 @@ WdmAudWaveCapabilities( NTSTATUS WdmAudMidiCapabilities( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo, IN PWDMAUD_DEVICE_EXTENSION DeviceExtension); NTSTATUS NTAPI -WdmAudFrameSize( +WdmAudGetPosition( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PWDMAUD_DEVICE_INFO DeviceInfo); + +NTSTATUS +WdmAudSetDeviceState( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, - IN PWDMAUD_CLIENT ClientInfo); + IN KSSTATE State, + IN BOOL CompleteIrp); + +NTSTATUS +NTAPI +WdmAudResetStream( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN BOOL CompleteIrp); NTSTATUS NTAPI @@ -246,6 +251,11 @@ WdmAudGetControlDetails( IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo); +NTSTATUS +WdmAudControlInitialize( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp); + NTSTATUS WdmAudMixerInitialize( IN PDEVICE_OBJECT DeviceObject); @@ -256,12 +266,21 @@ WdmAudWaveInitialize( IN PDEVICE_OBJECT DeviceObject); ULONG -ClosePin( +ClosePinByIndex( IN PWDMAUD_CLIENT ClientInfo, IN ULONG FilterId, IN ULONG PinId, IN SOUND_DEVICE_TYPE DeviceType); +VOID +ClosePin( + IN PWDMAUD_CLIENT ClientInfo, + IN ULONG Index); + +ULONG +GetActivePin( + IN PWDMAUD_CLIENT ClientInfo); + NTSTATUS InsertPinHandle( IN PWDMAUD_CLIENT ClientInfo, @@ -269,6 +288,7 @@ InsertPinHandle( IN ULONG PinId, IN SOUND_DEVICE_TYPE DeviceType, IN HANDLE PinHandle, + IN PFILE_OBJECT PinFileObject, IN ULONG FreeIndex); NTSTATUS @@ -318,7 +338,6 @@ ULONG GetSysAudioDeviceCount( IN PDEVICE_OBJECT DeviceObject); - PVOID AllocateItem( IN POOL_TYPE PoolType, diff --git a/drivers/wdm/audio/sysaudio/control.c b/drivers/wdm/audio/sysaudio/control.c index 5d18c24ce92d3..c001e3dd3e570 100644 --- a/drivers/wdm/audio/sysaudio/control.c +++ b/drivers/wdm/audio/sysaudio/control.c @@ -164,11 +164,9 @@ ComputeCompatibleFormat( RtlMoveMemory(MultipleItem + 1, ClientFormat, ClientFormat->DataFormat.FormatSize); /* Query the miniport data intersection handler */ Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)PinRequest, Length, (PVOID)MixerFormat, sizeof(KSDATAFORMAT_WAVEFORMATEX), &BytesReturned); - - DPRINT("Status %x\n", Status); - - if (NT_SUCCESS(Status)) + if (Status != STATUS_BUFFER_TOO_SMALL) { + DPRINT1("Property Request KSPROPERTY_PIN_DATAINTERSECTION failed with %x\n", Status); FreeItem(PinRequest); return Status; } @@ -177,10 +175,11 @@ ComputeCompatibleFormat( PinRequest->Property.Id = KSPROPERTY_PIN_DATARANGES; /* Query pin data ranges */ Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)PinRequest, sizeof(KSP_PIN), NULL, 0, &BytesReturned); - - if (Status != STATUS_MORE_ENTRIES) + if (Status != STATUS_BUFFER_OVERFLOW) { /* Failed to get data ranges */ + DPRINT1("Property Request KSPROPERTY_PIN_DATARANGES failed with %x\n", Status); + FreeItem(PinRequest); return Status; } @@ -194,10 +193,10 @@ ComputeCompatibleFormat( Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)PinRequest, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned); if (!NT_SUCCESS(Status)) { - DPRINT("Property Request KSPROPERTY_PIN_DATARANGES failed with %x\n", Status); + DPRINT1("Property Request KSPROPERTY_PIN_DATARANGES failed with %x\n", Status); FreeItem(MultipleItem); FreeItem(PinRequest); - return STATUS_UNSUCCESSFUL; + return Status; } AudioRange = (PKSDATARANGE_AUDIO)(MultipleItem + 1); @@ -210,8 +209,8 @@ ComputeCompatibleFormat( AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange + AudioRange->DataRange.FormatSize); continue; } - /* Select best quality available */ + /* Select best quality available */ MixerFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX); MixerFormat->DataFormat.Flags = 0; MixerFormat->DataFormat.Reserved = 0; @@ -220,16 +219,8 @@ ComputeCompatibleFormat( MixerFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX; MixerFormat->DataFormat.SampleSize = 4; MixerFormat->WaveFormatEx.wFormatTag = ClientFormat->WaveFormatEx.wFormatTag; -#ifndef NO_AC97_HACK - /* HACK: AC97 does not support mono render / record */ - MixerFormat->WaveFormatEx.nChannels = 2; - /*HACK: AC97 only supports 16-Bit Bits */ - MixerFormat->WaveFormatEx.wBitsPerSample = 16; - -#else MixerFormat->WaveFormatEx.nChannels = min(ClientFormat->WaveFormatEx.nChannels, AudioRange->MaximumChannels); MixerFormat->WaveFormatEx.wBitsPerSample = AudioRange->MaximumBitsPerSample; -#endif #ifdef KMIXER_RESAMPLING_IMPLEMENTED MixerFormat->WaveFormatEx.nSamplesPerSec = AudioRange->MaximumSampleFrequency; @@ -247,7 +238,7 @@ ComputeCompatibleFormat( AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange + AudioRange->DataRange.FormatSize); } -#if 0 +#if 1 DPRINT1("\nNum Max Channels %u Channels %u Old Channels %u\n Max SampleRate %u SampleRate %u Old SampleRate %u\n Max BitsPerSample %u BitsPerSample %u Old BitsPerSample %u\n", AudioRange->MaximumChannels, MixerFormat->WaveFormatEx.nChannels, ClientFormat->WaveFormatEx.nChannels, AudioRange->MaximumSampleFrequency, MixerFormat->WaveFormatEx.nSamplesPerSec, ClientFormat->WaveFormatEx.nSamplesPerSec, @@ -423,7 +414,8 @@ SysAudioHandleProperty( *((PULONG)Irp->UserBuffer) = DeviceExtension->NumberOfKsAudioDevices; return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(ULONG)); } - else if (Property->Id == KSPROPERTY_SYSAUDIO_DEVICE_INSTANCE) + else if (Property->Id == KSPROPERTY_SYSAUDIO_DEVICE_INSTANCE || + Property->Id == KSPROPERTY_SYSAUDIO_DEVICE_DEFAULT) { if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG)) { diff --git a/drivers/wdm/audio/sysaudio/deviface.c b/drivers/wdm/audio/sysaudio/deviface.c index fa4e3756c12b6..b1e1f95b3914b 100644 --- a/drivers/wdm/audio/sysaudio/deviface.c +++ b/drivers/wdm/audio/sysaudio/deviface.c @@ -8,13 +8,14 @@ #include "sysaudio.h" -#define NDEBUG +#define YDEBUG #include const GUID GUID_DEVICE_INTERFACE_ARRIVAL = {0xCB3A4004L, 0x46F0, 0x11D0, {0xB0, 0x8F, 0x00, 0x60, 0x97, 0x13, 0x05, 0x3F}}; const GUID GUID_DEVICE_INTERFACE_REMOVAL = {0xCB3A4005L, 0x46F0, 0x11D0, {0xB0, 0x8F, 0x00, 0x60, 0x97, 0x13, 0x05, 0x3F}}; const GUID KS_CATEGORY_AUDIO = {0x6994AD04L, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; -const GUID KS_CATEGORY_TOPOLOGY = {0xDDA54A40, 0x1E4C, 0x11D1, {0xA0, 0x50, 0x40, 0x57, 0x05, 0xC1, 0x00, 0x00}}; +const GUID KS_CATEGORY_TOPOLOGY = {0xDDA54A40L, 0x1E4C, 0x11D1, {0xA0, 0x50, 0x40, 0x57, 0x05, 0xC1, 0x00, 0x00}}; +const GUID KS_CATEGORY_WDMAUD = {0x3E227E76L, 0x690D, 0x11D2, {0x81, 0x61, 0x00, 0x00, 0xF8, 0x77, 0x5B, 0xF1}}; const GUID DMOCATEGORY_ACOUSTIC_ECHO_CANCEL = {0xBF963D80L, 0xC559, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; NTSTATUS @@ -103,16 +104,6 @@ InsertAudioDevice( RtlAppendUnicodeStringToString(&DeviceEntry->DeviceName, DeviceName); } else - { - /* the device name needs to be prefixed */ - RtlAppendUnicodeToString(&DeviceEntry->DeviceName, L"\\??\\"); - RtlAppendUnicodeStringToString(&DeviceEntry->DeviceName, DeviceName); - - /* open device */ - Status = OpenDevice(&DeviceEntry->DeviceName, &DeviceEntry->Handle, &DeviceEntry->FileObject); - } - - if (!NT_SUCCESS(Status)) { goto cleanup; } @@ -124,7 +115,7 @@ InsertAudioDevice( InterlockedIncrement((PLONG)&DeviceExtension->NumberOfKsAudioDevices); DPRINT("Successfully opened audio device %u Device %S\n", DeviceExtension->NumberOfKsAudioDevices, DeviceEntry->DeviceName.Buffer); - return Status; + return STATUS_SUCCESS; cleanup: if (DeviceEntry) diff --git a/drivers/wdm/audio/sysaudio/main.c b/drivers/wdm/audio/sysaudio/main.c index ee7946146f3fd..7f692928a06c4 100644 --- a/drivers/wdm/audio/sysaudio/main.c +++ b/drivers/wdm/audio/sysaudio/main.c @@ -201,7 +201,7 @@ SysAudio_AddDevice( DPRINT1("Failed to register device notifications\n"); goto cleanup; } - +#if 0 /* Load kmixer */ Status = SysAudioOpenKMixer(DeviceExtension); if (!NT_SUCCESS(Status)) @@ -209,7 +209,7 @@ SysAudio_AddDevice( DPRINT1("SysAudioOpenKMixer failed with %x\n", Status); goto cleanup; } - +#endif /* set io flags */ DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE; /* clear initializing flag */ diff --git a/drivers/wdm/audio/sysaudio/sysaudio.h b/drivers/wdm/audio/sysaudio/sysaudio.h index 5a18cc96f136b..d8876d338459f 100644 --- a/drivers/wdm/audio/sysaudio/sysaudio.h +++ b/drivers/wdm/audio/sysaudio/sysaudio.h @@ -2,6 +2,7 @@ #define _SYSAUDIO_PCH_ #include +#include typedef struct { diff --git a/sdk/include/psdk/ks.h b/sdk/include/psdk/ks.h index 05a1dc9ed347c..9080f289d5259 100644 --- a/sdk/include/psdk/ks.h +++ b/sdk/include/psdk/ks.h @@ -5050,6 +5050,23 @@ KsFilterFactoryGetDevice( return KsGetDevice((PVOID)FilterFactory); } +_IRQL_requires_max_(PASSIVE_LEVEL) +KSDDKAPI +PVOID +NTAPI +KsGetObjectFromFileObject( + IN PFILE_OBJECT FileObject); + +_IRQL_requires_max_(PASSIVE_LEVEL) +static +__inline +PKSPIN +KsGetPinFromFileObject( + IN PFILE_OBJECT FileObject) +{ + return (PKSPIN)KsGetObjectFromFileObject(FileObject); +} + /* etc. */ #endif /* avstream */ diff --git a/sdk/include/psdk/mmddk.h b/sdk/include/psdk/mmddk.h index 48e7fb9ca58c1..354a9b288b3eb 100644 --- a/sdk/include/psdk/mmddk.h +++ b/sdk/include/psdk/mmddk.h @@ -395,6 +395,13 @@ typedef JOYDEVMSGPROC *LPJOYDEVMSGPROC; #define MAKEMCIRESOURCE(wRet, wRes) MAKELRESULT((wRet), (wRes)) +#ifdef __REACTOS__ +typedef struct { + DWORD cbSize; + LPVOID pCaps; +} MDEVICECAPSEX; +#endif // __REACTOS__ + typedef struct { DWORD_PTR dwCallback; DWORD_PTR dwInstance; diff --git a/sdk/include/reactos/libs/sound/sndtypes.h b/sdk/include/reactos/libs/sound/sndtypes.h index 2f2017b24e068..0403c59c755d8 100644 --- a/sdk/include/reactos/libs/sound/sndtypes.h +++ b/sdk/include/reactos/libs/sound/sndtypes.h @@ -25,16 +25,16 @@ typedef enum { // The sound device types - WAVE_IN_DEVICE_TYPE = 1, - WAVE_OUT_DEVICE_TYPE = 2, - MIDI_IN_DEVICE_TYPE = 3, - MIDI_OUT_DEVICE_TYPE = 4, - AUX_DEVICE_TYPE = 5, - MIXER_DEVICE_TYPE = 6, + WAVE_IN_DEVICE_TYPE = 0, + WAVE_OUT_DEVICE_TYPE = 1, + MIDI_IN_DEVICE_TYPE = 2, + MIDI_OUT_DEVICE_TYPE = 3, + MIXER_DEVICE_TYPE = 4, + AUX_DEVICE_TYPE = 5, // Range of valid device type IDs - MIN_SOUND_DEVICE_TYPE = 1, - MAX_SOUND_DEVICE_TYPE = 6, + MIN_SOUND_DEVICE_TYPE = 0, + MAX_SOUND_DEVICE_TYPE = 5, // Number of sound device types SOUND_DEVICE_TYPES = 6 diff --git a/sdk/lib/drivers/sound/mmixer/filter.c b/sdk/lib/drivers/sound/mmixer/filter.c index a41bcee7bb793..535ff7d4013de 100644 --- a/sdk/lib/drivers/sound/mmixer/filter.c +++ b/sdk/lib/drivers/sound/mmixer/filter.c @@ -180,11 +180,6 @@ MMixerGetControlTypeFromTopologyNode( /* mux control */ return MIXERCONTROL_CONTROLTYPE_MUX; } - else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_MUX)) - { - /* mux control */ - return MIXERCONTROL_CONTROLTYPE_MUX; - } else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_STEREO_WIDE)) { /* stero wide control */ diff --git a/sdk/lib/drivers/sound/mmixer/midi.c b/sdk/lib/drivers/sound/mmixer/midi.c index 969f252773ab7..7e4b5ba623df4 100644 --- a/sdk/lib/drivers/sound/mmixer/midi.c +++ b/sdk/lib/drivers/sound/mmixer/midi.c @@ -334,6 +334,15 @@ MMixerMidiOutCapabilities( return MM_STATUS_UNSUCCESSFUL; } + /* allocate destination buffer */ + Caps = MixerContext->Alloc(sizeof(MIDIOUTCAPSW)); + + if (!Caps) + { + /* no memory */ + return MM_STATUS_NO_MEMORY; + } + /* copy capabilities */ MixerContext->Copy(Caps, &MidiInfo->u.OutCaps, sizeof(MIDIOUTCAPSW)); @@ -370,6 +379,15 @@ MMixerMidiInCapabilities( return MM_STATUS_UNSUCCESSFUL; } + /* allocate destination buffer */ + Caps = MixerContext->Alloc(sizeof(MIDIINCAPSW)); + + if (!Caps) + { + /* no memory */ + return MM_STATUS_NO_MEMORY; + } + /* copy capabilities */ MixerContext->Copy(Caps, &MidiInfo->u.InCaps, sizeof(MIDIINCAPSW)); diff --git a/sdk/lib/drivers/sound/mmixer/mixer.c b/sdk/lib/drivers/sound/mmixer/mixer.c index 3b8d900bef6e8..6b9face7264b5 100644 --- a/sdk/lib/drivers/sound/mmixer/mixer.c +++ b/sdk/lib/drivers/sound/mmixer/mixer.c @@ -61,6 +61,15 @@ MMixerGetCapabilities( return MM_STATUS_INVALID_PARAMETER; } + /* allocate destination buffer */ + MixerCaps = MixerContext->Alloc(sizeof(MIXERCAPSW)); + + if (!MixerCaps) + { + /* no memory */ + return MM_STATUS_NO_MEMORY; + } + MixerCaps->wMid = MixerInfo->MixCaps.wMid; MixerCaps->wPid = MixerInfo->MixCaps.wPid; MixerCaps->vDriverVersion = MixerInfo->MixCaps.vDriverVersion; @@ -555,8 +564,22 @@ MMixerSetControlDetails( case MIXERCONTROL_CONTROLTYPE_MUX: Status = MMixerSetGetMuxControlDetails(MixerContext, MixerInfo, NodeId, TRUE, Flags, MixerControl, MixerControlDetails, MixerLine); break; + case MIXERCONTROL_CONTROLTYPE_ONOFF: + DPRINT1("Not Implemented MIXERCONTROL_CONTROLTYPE_ONOFF\n"); + break; + case MIXERCONTROL_CONTROLTYPE_LOUDNESS: + DPRINT1("Not Implemented MIXERCONTROL_CONTROLTYPE_LOUDNESS\n"); + break; + case MIXERCONTROL_CONTROLTYPE_PEAKMETER: + DPRINT1("Not Implemented MIXERCONTROL_CONTROLTYPE_PEAKMETER\n"); + break; + case MIXERCONTROL_CONTROLTYPE_FADER: + DPRINT1("Not Implemented MIXERCONTROL_CONTROLTYPE_FADER\n"); + break; + default: Status = MM_STATUS_NOT_IMPLEMENTED; + DPRINT1("ControlType %lx not implemented\n", MixerControl->Control.dwControlType); } return Status; @@ -601,7 +624,7 @@ MMixerGetControlDetails( MixerInfo = (LPMIXER_INFO)MixerHandle; /* get mixer control */ - Status = MMixerGetMixerControlById(MixerInfo, MixerControlDetails->dwControlID, &MixerLine, &MixerControl, &NodeId); + Status = MMixerGetMixerControlById(MixerInfo, MixerControlDetails->dwControlID, &MixerLine, &MixerControl, &NodeId); /* check for success */ if (Status != MM_STATUS_SUCCESS) @@ -618,11 +641,20 @@ MMixerGetControlDetails( case MIXERCONTROL_CONTROLTYPE_VOLUME: Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo, NodeId, FALSE, MixerControl, MixerControlDetails, MixerLine); break; + case MIXERCONTROL_CONTROLTYPE_MUX: + Status = MMixerSetGetMuxControlDetails(MixerContext, MixerInfo, NodeId, FALSE, Flags, MixerControl, MixerControlDetails, MixerLine); + break; case MIXERCONTROL_CONTROLTYPE_ONOFF: DPRINT1("Not Implemented MIXERCONTROL_CONTROLTYPE_ONOFF\n"); break; - case MIXERCONTROL_CONTROLTYPE_MUX: - Status = MMixerSetGetMuxControlDetails(MixerContext, MixerInfo, NodeId, FALSE, Flags, MixerControl, MixerControlDetails, MixerLine); + case MIXERCONTROL_CONTROLTYPE_LOUDNESS: + DPRINT1("Not Implemented MIXERCONTROL_CONTROLTYPE_LOUDNESS\n"); + break; + case MIXERCONTROL_CONTROLTYPE_PEAKMETER: + DPRINT1("Not Implemented MIXERCONTROL_CONTROLTYPE_PEAKMETER\n"); + break; + case MIXERCONTROL_CONTROLTYPE_FADER: + DPRINT1("Not Implemented MIXERCONTROL_CONTROLTYPE_FADER\n"); break; default: diff --git a/sdk/lib/drivers/sound/mmixer/mmixer.h b/sdk/lib/drivers/sound/mmixer/mmixer.h index 7d88125ce369b..9fbba22b015ba 100644 --- a/sdk/lib/drivers/sound/mmixer/mmixer.h +++ b/sdk/lib/drivers/sound/mmixer/mmixer.h @@ -207,6 +207,12 @@ MMixerOpenWave( IN PVOID Context, OUT PHANDLE PinHandle); +MIXER_STATUS +MMixerGetWavePosition( + IN PMIXER_CONTEXT MixerContext, + IN HANDLE PinHandle, + OUT DWORD * Position); + MIXER_STATUS MMixerSetWaveStatus( IN PMIXER_CONTEXT MixerContext, diff --git a/sdk/lib/drivers/sound/mmixer/sup.c b/sdk/lib/drivers/sound/mmixer/sup.c index 4fa8c080309c3..7e86d0f24d9a2 100644 --- a/sdk/lib/drivers/sound/mmixer/sup.c +++ b/sdk/lib/drivers/sound/mmixer/sup.c @@ -169,7 +169,7 @@ MMixerGetMixerInfoByIndex( /* get mixer list */ MixerList = (PMIXER_LIST)MixerContext->MixerContext; - + DPRINT1("MixerListCount %d\n", MixerList->MixerListCount); if (!MixerList->MixerListCount) return NULL; @@ -181,7 +181,7 @@ MMixerGetMixerInfoByIndex( if (Index == MixerIndex) return MixerInfo; - + DPRINT1("Index %d\n", Index); /* move to next mixer entry */ Index++; Entry = Entry->Flink; diff --git a/sdk/lib/drivers/sound/mmixer/wave.c b/sdk/lib/drivers/sound/mmixer/wave.c index 6326e3227d744..b8e4b64573211 100644 --- a/sdk/lib/drivers/sound/mmixer/wave.c +++ b/sdk/lib/drivers/sound/mmixer/wave.c @@ -126,8 +126,8 @@ MMixerInitializeDataFormat( DataFormat->WaveFormatEx.nBlockAlign = WaveFormatEx->nBlockAlign; DataFormat->WaveFormatEx.nAvgBytesPerSec = WaveFormatEx->nAvgBytesPerSec; DataFormat->WaveFormatEx.wBitsPerSample = WaveFormatEx->wBitsPerSample; - DataFormat->WaveFormatEx.cbSize = 0; - DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX); + DataFormat->WaveFormatEx.cbSize = WaveFormatEx->cbSize; + DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX) + WaveFormatEx->cbSize; DataFormat->DataFormat.Flags = 0; DataFormat->DataFormat.Reserved = 0; DataFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO; @@ -160,6 +160,7 @@ MMixerGetAudioPinDataRanges( Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)NULL, 0, &BytesReturned); if (Status != MM_STATUS_MORE_ENTRIES) { + DPRINT1("MM Status %x\n", Status); return Status; } @@ -174,6 +175,7 @@ MMixerGetAudioPinDataRanges( if (Status != MM_STATUS_SUCCESS) { /* failed */ + DPRINT1("MM Status %x\n", Status); MixerContext->Free(MultipleItem); return Status; } @@ -265,7 +267,10 @@ MMixerOpenWavePin( if (Status == STATUS_SUCCESS) MixerStatus = MM_STATUS_SUCCESS; else + { + DPRINT1("KsCreatePin failed with status 0x%lx\n", Status); MixerStatus = MM_STATUS_UNSUCCESSFUL; + } } /* free create info */ @@ -359,6 +364,16 @@ MMixerInitializeWaveInfo( /* sanity check */ ASSERT(wcslen(DeviceName) < MAXPNAMELEN); + /* initialize capabilities */ + if (bWaveIn) + { + memset(&WaveInfo->u.InCaps, 0, sizeof(WAVEINCAPSW)); + } + else + { + memset(&WaveInfo->u.OutCaps, 0, sizeof(WAVEOUTCAPSW)); + } + /* copy device name */ if (bWaveIn) { @@ -459,9 +474,17 @@ MMixerOpenWave( /* grab mixer list */ MixerList = (PMIXER_LIST)MixerContext->MixerContext; + DPRINT1("wFormatTag requested: 0x%x\n", WaveFormat->wFormatTag); + if (WaveFormat->wFormatTag != WAVE_FORMAT_PCM) + WaveFormat->wFormatTag = WAVE_FORMAT_PCM; + + if (WaveFormat->wFormatTag != WAVE_FORMAT_PCM && + WaveFormat->wFormatTag != WAVE_FORMAT_EXTENSIBLE && + WaveFormat->wFormatTag != WAVE_FORMAT_IEEE_FLOAT) { /* not implemented */ + DPRINT1("Unsupported wFormatTag requested: 0x%x\n", WaveFormat->wFormatTag); return MM_STATUS_NOT_IMPLEMENTED; } @@ -470,6 +493,7 @@ MMixerOpenWave( if (Status != MM_STATUS_SUCCESS) { /* failed to find wave info */ + DPRINT1("1\n"); return MM_STATUS_INVALID_PARAMETER; } @@ -517,6 +541,15 @@ MMixerWaveInCapabilities( return MM_STATUS_UNSUCCESSFUL; } + /* allocate destination buffer */ + Caps = MixerContext->Alloc(sizeof(WAVEINCAPSW)); + + if (!Caps) + { + /* no memory */ + return MM_STATUS_NO_MEMORY; + } + /* copy capabilities */ MixerContext->Copy(Caps, &WaveInfo->u.InCaps, sizeof(WAVEINCAPSW)); @@ -553,6 +586,15 @@ MMixerWaveOutCapabilities( return MM_STATUS_UNSUCCESSFUL; } + /* allocate destination buffer */ + Caps = MixerContext->Alloc(sizeof(WAVEOUTCAPSW)); + + if (!Caps) + { + /* no memory */ + return MM_STATUS_NO_MEMORY; + } + /* copy capabilities */ MixerContext->Copy(Caps, &WaveInfo->u.OutCaps, sizeof(WAVEOUTCAPSW)); @@ -603,6 +645,38 @@ MMixerGetWaveOutCount( return MixerList->WaveOutListCount; } +MIXER_STATUS +MMixerGetWavePosition( + IN PMIXER_CONTEXT MixerContext, + IN HANDLE PinHandle, + OUT DWORD * Position) +{ + KSAUDIO_POSITION AudioPosition; + KSPROPERTY Property; + MIXER_STATUS Status; + ULONG Length; + + /* verify mixer context */ + Status = MMixerVerifyContext(MixerContext); + + if (Status != MM_STATUS_SUCCESS) + { + /* invalid context passed */ + return Status; + } + + Property.Id = KSPROPERTY_AUDIO_POSITION; + Property.Set = KSPROPSETID_Audio; + Property.Flags = KSPROPERTY_TYPE_GET; + + Status = MixerContext->Control(PinHandle, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), &AudioPosition, sizeof(KSAUDIO_POSITION), &Length); + DPRINT1("Success %x\n", Status == MM_STATUS_SUCCESS); + /* Store audio position */ + *Position = (DWORD)AudioPosition.PlayOffset; + + return Status; +} + MIXER_STATUS MMixerSetWaveStatus( IN PMIXER_CONTEXT MixerContext,