diff --git a/dll/directx/wine/dsound/propset.c b/dll/directx/wine/dsound/propset.c index 658f04ac63ba5..b91a167306a16 100644 --- a/dll/directx/wine/dsound/propset.c +++ b/dll/directx/wine/dsound/propset.c @@ -183,7 +183,8 @@ static HRESULT DSPROPERTY_DescriptionW( HRESULT err; GUID dev_guid; ULONG wod, wid, wodn, widn; - DSDRIVERDESC desc; + WAVEOUTCAPSW out_caps; + WAVEINCAPSW in_caps; TRACE("pPropData=%p,cbPropData=%d,pcbReturned=%p)\n", pPropData,cbPropData,pcbReturned); @@ -229,9 +230,13 @@ static HRESULT DSPROPERTY_DescriptionW( } if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) - err = waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel); + { + err = waveOutGetDevCapsW(wod, &out_caps, sizeof(WAVEOUTCAPSW)); + } else - err = waveInMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel); + { + err = waveInGetDevCapsW(wid, &in_caps, sizeof(WAVEINCAPSW)); + } if (err != MMSYSERR_NOERROR) { @@ -240,26 +245,12 @@ static HRESULT DSPROPERTY_DescriptionW( } else { - /* FIXME: Still a memory leak.. */ - int desclen, modlen; + static WCHAR wDescription[] = { 'D','e','s','c','r','i','p','t','i','o','n',0 }; static WCHAR wInterface[] = { 'I','n','t','e','r','f','a','c','e',0 }; - modlen = MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, NULL, 0 ); - desclen = MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, NULL, 0 ); - ppd->Module = HeapAlloc(GetProcessHeap(),0,modlen*sizeof(WCHAR)); - ppd->Description = HeapAlloc(GetProcessHeap(),0,desclen*sizeof(WCHAR)); + ppd->Module = ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER ? out_caps.szPname : in_caps.szPname; + ppd->Description = wDescription; ppd->Interface = wInterface; - if (!ppd->Description || !ppd->Module) - { - WARN("Out of memory\n"); - HeapFree(GetProcessHeap(), 0, ppd->Description); - HeapFree(GetProcessHeap(), 0, ppd->Module); - ppd->Description = ppd->Module = NULL; - return E_OUTOFMEMORY; - } - - MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->Module, modlen ); - MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->Description, desclen ); } ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD; @@ -308,8 +299,6 @@ static HRESULT DSPROPERTY_EnumerateW( return S_OK; } ret = ppd->Callback(&data, ppd->Context); - HeapFree(GetProcessHeap(), 0, data.Module); - HeapFree(GetProcessHeap(), 0, data.Description); if (!ret) return S_OK; } @@ -326,8 +315,6 @@ static HRESULT DSPROPERTY_EnumerateW( return S_OK; } ret = ppd->Callback(&data, ppd->Context); - HeapFree(GetProcessHeap(), 0, data.Module); - HeapFree(GetProcessHeap(), 0, data.Description); if (!ret) return S_OK; } @@ -464,8 +451,6 @@ static HRESULT DSPROPERTY_DescriptionA( return hr; if (!DSPROPERTY_descWtoA(&data, ppd)) hr = E_OUTOFMEMORY; - HeapFree(GetProcessHeap(), 0, data.Module); - HeapFree(GetProcessHeap(), 0, data.Interface); return hr; } @@ -489,8 +474,6 @@ static HRESULT DSPROPERTY_Description1( if (FAILED(hr)) return hr; DSPROPERTY_descWto1(&data, ppd); - HeapFree(GetProcessHeap(), 0, data.Module); - HeapFree(GetProcessHeap(), 0, data.Interface); return hr; } 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..2b9ae52f35307 --- /dev/null +++ b/dll/win32/wdmaud.drv/auxiliary/auxMessage.c @@ -0,0 +1,90 @@ +/* + * 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, + (PVOID)Parameter1, + Parameter2); + break; + } + + case AUXDM_GETVOLUME: + { + Result = MmeGetVolume(AUX_DEVICE_TYPE, + DeviceId, + PrivateHandle, + Parameter1); + break; + } + + case AUXDM_SETVOLUME: + { + Result = MmeSetVolume(AUX_DEVICE_TYPE, + DeviceId, + PrivateHandle, + 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 5a8763d5f3ce5..1a048c5321d3d 100644 --- a/dll/win32/wdmaud.drv/legacy.c +++ b/dll/win32/wdmaud.drv/legacy.c @@ -1,261 +1,402 @@ /* - * 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-2024 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; - - /* setup wait objects */ - WaitObjects[0] = Instance->hNotifyEvent; - WaitObjects[1] = Instance->hStopEvent; - - /* zero device info */ - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - - DeviceInfo.hDevice = Instance->Handle; - DeviceInfo.DeviceType = MIXER_DEVICE_TYPE; +#endif + HANDLE hEvent; - do + while (TRUE) { - dwResult = WaitForMultipleObjects(2, WaitObjects, FALSE, INFINITE); - - if (dwResult == WAIT_OBJECT_0 + 1) + DPRINT("WaveQueue %p\n", DeviceInfo->DeviceState->WaveQueue); + /* Validate the header */ + WaveHeader = DeviceInfo->DeviceState->WaveQueue; + if (WaveHeader) { - /* stop event was signalled */ - break; + DPRINT("1\n"); + /* Validate the flags */ + if (WaveHeader->dwFlags & (WHDR_INQUEUE | WHDR_PREPARED)) + { + DPRINT1("2\n"); + /* Validate header extension */ + HeaderExtension = (PWAVEHDR_EXTENSION)WaveHeader->reserved; + if (HeaderExtension) + { + hEvent = HeaderExtension->Overlapped.hEvent; + DPRINT("3\n"); + + if (hEvent) + { + /* Wait for I/O complete */ + dwResult = WaitForSingleObject(hEvent, INFINITE); + DPRINT("dwResult %d\n", dwResult); + } + + DPRINT("4\n"); + if (DeviceInfo) + { + /* Complete current header */ + CompleteWaveHeader(DeviceInfo); + } + else + { + /* Shouldn't be called */ + DPRINT1("Invalid device info data %p\n", DeviceInfo); + ASSERT(FALSE); + break; + } + } + else + { + /* Shouldn't be called */ + DPRINT("5\n"); + ASSERT(FALSE); + break; + } + } + else + { + /* Shouldn't be called */ + DPRINT("6\n"); + ASSERT(FALSE); + break; + } } - - do + else { - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_GET_MIXER_EVENT, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); - - if (Result == MMSYSERR_NOERROR) + DPRINT("7\n"); + if (DeviceInfo->DeviceState->bStart) { - 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); - } - }while(Result == MMSYSERR_NOERROR); - }while(TRUE); +#ifdef USE_MMIXER_LIB + /* Make sure the pin is stopped */ + 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 + /* Mark device as stopped */ + DeviceInfo->DeviceState->bStart = FALSE; + } - /* done */ + WaitForSingleObject(DeviceInfo->DeviceState->hNotifyEvent, INFINITE); + + /* Streaming is finished */ + if (DeviceInfo->DeviceState->bDone) break; + } + } + + /* Close queue notification event */ + CloseHandle(DeviceInfo->DeviceState->hNotifyEvent); + DeviceInfo->DeviceState->bStartInThread = FALSE; + + /* Signal stop event */ + SetEvent(DeviceInfo->DeviceState->hStopEvent); + + /* Done */ return 0; } MMRESULT -WdmAudCleanupByLegacy() +WdmAudCreateCompletionThread( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo) { - if (KernelHandle != INVALID_HANDLE_VALUE) + if (!DeviceInfo->DeviceState->hThread) { - CloseHandle(KernelHandle); - KernelHandle = INVALID_HANDLE_VALUE; + /* Create queue notification event */ + 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()); + } + + /* Create stop event */ + 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()); + } + + /* Create sound thread if it isn't yet */ + 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()); + } + /* Set priority for a thread */ + SetThreadPriority(DeviceInfo->DeviceState->hThread, THREAD_PRIORITY_TIME_CRITICAL); } + DeviceInfo->DeviceState->bStartInThread = TRUE; + return MMSYSERR_NOERROR; } MMRESULT -WdmAudGetNumWdmDevsByLegacy( - IN MMDEVICE_TYPE DeviceType, - OUT DWORD* DeviceCount) +WdmAudDestroyCompletionThread( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo) { - MMRESULT Result; - WDMAUD_DEVICE_INFO DeviceInfo; + if (DeviceInfo->DeviceState->hThread) + { + /* Mark stream as finished */ + DeviceInfo->DeviceState->bDone = TRUE; - VALIDATE_MMSYS_PARAMETER( KernelHandle != INVALID_HANDLE_VALUE ); - VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) ); - VALIDATE_MMSYS_PARAMETER( DeviceCount ); + /* Signal the queue */ + if (DeviceInfo->DeviceState->bStartInThread) + SetEvent(DeviceInfo->DeviceState->hNotifyEvent); - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.DeviceType = DeviceType; + /* Wait for stop */ + WaitForSingleObject(DeviceInfo->DeviceState->hStopEvent, INFINITE); - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_GETNUMDEVS_TYPE, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); + /* Close thread handles */ + CloseHandle(DeviceInfo->DeviceState->hThread); + CloseHandle(DeviceInfo->DeviceState->hStopEvent); + } - if ( ! MMSUCCESS( Result ) ) + /* Restore state */ + DeviceInfo->DeviceState->bDone = FALSE; + + return MMSYSERR_NOERROR; +} + +MMRESULT +WdmAudCleanupByLegacy(VOID) +{ + --OpenCount; + if ( OpenCount < 1 ) { - SND_ERR(L"Call to IOCTL_GETNUMDEVS_TYPE failed\n"); - *DeviceCount = 0; - return TranslateInternalMmResult(Result); + CloseHandle(KernelHandle); + KernelHandle = INVALID_HANDLE_VALUE; } - *DeviceCount = DeviceInfo.DeviceCount; - return MMSYSERR_NOERROR; } MMRESULT -WdmAudGetCapabilitiesByLegacy( - IN PSOUND_DEVICE SoundDevice, - IN DWORD DeviceId, - OUT PVOID Capabilities, - IN DWORD CapabilitiesSize) +WdmAudAddRemoveDeviceNode( + _In_ SOUND_DEVICE_TYPE DeviceType, + _In_ BOOL bAdd) { MMRESULT Result; - MMDEVICE_TYPE DeviceType; - WDMAUD_DEVICE_INFO DeviceInfo; + PWDMAUD_DEVICE_INFO DeviceInfo; - SND_ASSERT( SoundDevice ); - SND_ASSERT( Capabilities ); + VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) ); - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); + DPRINT("WDMAUD - AddRemoveDeviceNode DeviceType %u\n", DeviceType); - if ( ! MMSUCCESS(Result) ) - return Result; + 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; + } - SND_TRACE(L"WDMAUD - GetWdmDeviceCapabilities DeviceType %u DeviceId %u\n", DeviceType, DeviceId); + DeviceInfo->DeviceType = DeviceType; - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.DeviceType = DeviceType; - DeviceInfo.DeviceIndex = DeviceId; + Result = WdmAudIoControl(DeviceInfo, + 0, + NULL, + bAdd ? + IOCTL_ADD_DEVNODE : + IOCTL_REMOVE_DEVNODE); - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_GETCAPABILITIES, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); + HeapFree(GetProcessHeap(), 0, DeviceInfo); - if ( ! MMSUCCESS(Result) ) + if ( ! MMSUCCESS( Result ) ) { + DPRINT1("Call to %ls failed with %d\n", + bAdd ? L"IOCTL_ADD_DEVNODE" : L"IOCTL_REMOVE_DEVNODE", + GetLastError()); return TranslateInternalMmResult(Result); } - /* This is pretty much a big hack right now */ - switch ( DeviceType ) - { - case MIXER_DEVICE_TYPE: - { - LPMIXERCAPSW MixerCaps = (LPMIXERCAPSW) Capabilities; + return MMSYSERR_NOERROR; +} - DeviceInfo.u.MixCaps.szPname[MAXPNAMELEN-1] = L'\0'; - CopyWideString(MixerCaps->szPname, DeviceInfo.u.MixCaps.szPname); +MMRESULT +WdmAudGetNumWdmDevsByLegacy( + _In_ SOUND_DEVICE_TYPE DeviceType, + _Out_ DWORD* DeviceCount) +{ + MMRESULT Result; + PWDMAUD_DEVICE_INFO DeviceInfo; - 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; + VALIDATE_MMSYS_PARAMETER( KernelHandle != INVALID_HANDLE_VALUE ); + VALIDATE_MMSYS_PARAMETER( IS_VALID_SOUND_DEVICE_TYPE(DeviceType) ); + VALIDATE_MMSYS_PARAMETER( DeviceCount ); - DeviceInfo.u.WaveOutCaps.szPname[MAXPNAMELEN-1] = L'\0'; - WaveOutCaps->wMid = DeviceInfo.u.WaveOutCaps.wMid; - WaveOutCaps->wPid = DeviceInfo.u.WaveOutCaps.wPid; + DPRINT("WDMAUD - GetNumWdmDevs DeviceType %u\n", DeviceType); - WaveOutCaps->vDriverVersion = DeviceInfo.u.WaveOutCaps.vDriverVersion; - CopyWideString(WaveOutCaps->szPname, DeviceInfo.u.WaveOutCaps.szPname); + 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; + } - 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->DeviceType = DeviceType; - DeviceInfo.u.WaveInCaps.szPname[MAXPNAMELEN-1] = L'\0'; + Result = WdmAudIoControl(DeviceInfo, + 0, + NULL, + IOCTL_GETNUMDEVS_TYPE); - WaveInCaps->wMid = DeviceInfo.u.WaveInCaps.wMid; - WaveInCaps->wPid = DeviceInfo.u.WaveInCaps.wPid; + if ( ! MMSUCCESS( Result ) ) + { + DPRINT1("Call to IOCTL_GETNUMDEVS_TYPE failed with %d\n", GetLastError()); + *DeviceCount = 0; + HeapFree(GetProcessHeap(), 0, DeviceInfo); + return TranslateInternalMmResult(Result); + } - WaveInCaps->vDriverVersion = DeviceInfo.u.WaveInCaps.vDriverVersion; - CopyWideString(WaveInCaps->szPname, DeviceInfo.u.WaveInCaps.szPname); + *DeviceCount = DeviceInfo->DeviceIndex; - 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_ PVOID Capabilities, + _In_ DWORD CapabilitiesSize) +{ + 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, + CapabilitiesSize, + Capabilities, + IOCTL_GETCAPABILITIES); - CopyWideString(MidiOutCaps->szPname, DeviceInfo.u.MidiOutCaps.szPname); - break; - } + if ( ! MMSUCCESS(Result) ) + { + DPRINT1("Call to IOCTL_GETCAPABILITIES failed with %d\n", GetLastError()); } - return MMSYSERR_NOERROR; + return Result; } 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 +404,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 +419,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,572 +430,318 @@ 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); } - if ( KernelHandle == INVALID_HANDLE_VALUE ) return MMSYSERR_ERROR; - ++ OpenCount; + ++OpenCount; return MMSYSERR_NOERROR; } 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; - } + ASSERT( KernelHandle != INVALID_HANDLE_VALUE ); - SND_ASSERT( KernelHandle != INVALID_HANDLE_VALUE ); + DPRINT("WDMAUD - OpenWdmSoundDevice DeviceType %u\n", DeviceInfo->DeviceType); - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); + /* Open device handle */ + Result = WdmAudIoControl(DeviceInfo, + sizeof(WAVEFORMATEX), + WaveFormat, + IOCTL_OPEN_WDMAUD); - 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); - } - - 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; - - 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; + ASSERT( KernelHandle != INVALID_HANDLE_VALUE ); - if (Instance->Handle != NULL) - { - /* device is already open */ - return MMSYSERR_NOERROR; - } + DPRINT("WDMAUD - CloseWdmSoundDevice DeviceType %u\n", DeviceInfo->DeviceType); - Instance->hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL); - if ( ! Instance->hStopEvent ) - return MMSYSERR_NOMEM; + if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) + { + /* Is stream still in use? */ + if (DeviceInfo->DeviceState->WaveQueue) + { + DPRINT1("Stream is still in progress!\n"); + return WAVERR_STILLPLAYING; + } - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.DeviceType = MIXER_DEVICE_TYPE; - DeviceInfo.DeviceIndex = DeviceId; - DeviceInfo.u.hNotifyEvent = Instance->hNotifyEvent; + /* Destroy I/O thread */ + Result = WdmAudDestroyCompletionThread(DeviceInfo); + ASSERT(Result == MMSYSERR_NOERROR); + } - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_OPEN_WDMAUD, - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - (LPVOID) &DeviceInfo, - sizeof(WDMAUD_DEVICE_INFO), - NULL); + /* Close device handle */ + Result = WdmAudIoControl(DeviceInfo, + 0, + NULL, + IOCTL_CLOSE_WDMAUD); if ( ! MMSUCCESS(Result) ) { - CloseHandle(Instance->hNotifyEvent); - CloseHandle(Instance->hStopEvent); + 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 ) - { - CloseHandle(hThread); - } - - /* 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); - - if ( ! MMSUCCESS(Result) ) - { - return TranslateInternalMmResult(Result); - } + PWDMAUD_DEVICE_INFO LocalDeviceInfo; + PWAVEHDR_EXTENSION HeaderExtension; + MMRESULT Result = MMSYSERR_NOERROR; + DWORD Transferred = 0; + BOOL IoResult; + DWORD IoCtl; - Result = GetSoundDeviceIdentifier(SoundDevice, &Identifier); + VALIDATE_MMSYS_PARAMETER( DeviceInfo ); - if ( ! MMSUCCESS(Result) ) - { - return TranslateInternalMmResult(Result); - } - - 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 = 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; // Will be freed on wave header completion. - /* store details */ - Instance->WaveFormatEx.cbSize = WaveFormat->cbSize; - 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); - 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); + DPRINT("Transferred %d bytes in Sync overlapped I/O\n", Transferred); - - 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; - - /* 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); + DWORD IoCtl; - Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); + DPRINT("WDMAUD - SetWaveState DeviceType %u\n", DeviceInfo->DeviceType); - if ( ! MMSUCCESS(Result) ) + if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE) { - return TranslateInternalMmResult(Result); + IoCtl = bStart ? IOCTL_START_CAPTURE : IOCTL_PAUSE_CAPTURE; } - - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); - - DeviceInfo = (PWDMAUD_DEVICE_INFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_INFO)); - if (!DeviceInfo) + else if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { - // no memory - return MMSYSERR_NOMEM; + IoCtl = bStart ? IOCTL_START_PLAYBACK : IOCTL_PAUSE_PLAYBACK; } - DeviceInfo->Header.FrameExtent = Length; - if (DeviceType == WAVE_OUT_DEVICE_TYPE) + /* Are we requested to start the audio device? */ + if (IoCtl == IOCTL_START_CAPTURE || IoCtl == IOCTL_START_PLAYBACK) { - 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; - + /* 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); + } - // create completion event - Overlap->Standard.hEvent = Handle = CreateEventW(NULL, FALSE, FALSE, NULL); - if (Overlap->Standard.hEvent == NULL) - { - // no memory - HeapFree(GetProcessHeap(), 0, DeviceInfo); - return MMSYSERR_NOMEM; + /* Mark device as started */ + DeviceInfo->DeviceState->bStart = TRUE; } - Overlap->OriginalCompletionRoutine = CompletionRoutine; - Overlap->CompletionContext = (PVOID)DeviceInfo; - - if (DeviceType == WAVE_OUT_DEVICE_TYPE) - { - Ret = WriteFileEx(KernelHandle, DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPOVERLAPPED)Overlap, LegacyCompletionRoutine); - if (Ret) - WaitForSingleObjectEx (KernelHandle, INFINITE, TRUE); - } - 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; + /* Talk to the device */ + Result = WdmAudIoControl(DeviceInfo, + 0, + NULL, + IoCtl); - Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); - - 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); - 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; + /* Talk to the device */ + 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); } + /* Mark device as stopped */ + DeviceInfo->DeviceState->bStart = FALSE; - 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; - } + /* Destroy I/O thread */ + Result = WdmAudDestroyCompletionThread(DeviceInfo); + ASSERT(Result == MMSYSERR_NOERROR); - 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; - - Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); - - if ( ! MMSUCCESS(Result) ) - { - return TranslateInternalMmResult(Result); - } - - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); + DWORD Position; + DWORD IoCtl; - Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle); - SND_ASSERT( Result == MMSYSERR_NOERROR ); + DPRINT("WDMAUD - GetWavePosition DeviceType %u\n", DeviceInfo->DeviceType); - ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); - DeviceInfo.hDevice = Handle; - DeviceInfo.DeviceType = DeviceType; + IoCtl = DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE ? + IOCTL_GETOUTPOS : IOCTL_GETINPOS; - Result = SyncOverlappedDeviceIoControl(KernelHandle, - IOCTL_GETPOS, - (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); } + /* Store position */ Time->wType = TIME_BYTES; - Time->u.cb = (DWORD)DeviceInfo.u.Position; + Time->u.cb = Position; return MMSYSERR_NOERROR; } MMRESULT WdmAudGetVolumeByLegacy( - _In_ PSOUND_DEVICE_INSTANCE SoundDeviceInstance, + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, _In_ DWORD DeviceId, _Out_ PDWORD pdwVolume) { @@ -862,7 +751,7 @@ WdmAudGetVolumeByLegacy( MMRESULT WdmAudSetVolumeByLegacy( - _In_ PSOUND_DEVICE_INSTANCE SoundDeviceInstance, + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, _In_ DWORD DeviceId, _In_ DWORD dwVolume) { @@ -870,109 +759,52 @@ WdmAudSetVolumeByLegacy( return MMSYSERR_NOTSUPPORTED; } -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); - Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle); - SND_ASSERT( Result == MMSYSERR_NOERROR ); + DPRINT("WDMAUD - QueryMixerInfo: uMsg %x Flags %x\n", uMsg, Flags); - 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..5127904a771a6 --- /dev/null +++ b/dll/win32/wdmaud.drv/midi/midMessage.c @@ -0,0 +1,100 @@ +/* + * 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, + (PVOID)Parameter1, + Parameter2); + 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..fea8c7daf02a2 --- /dev/null +++ b/dll/win32/wdmaud.drv/midi/modMessage.c @@ -0,0 +1,107 @@ +/* + * 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, + (PVOID)Parameter1, + Parameter2); + break; + } + + case MODM_OPEN : + { + Result = MmeOpenDevice(MIDI_OUT_DEVICE_TYPE, + DeviceId, + (LPWAVEOPENDESC)Parameter1, + Parameter2, + (DWORD_PTR*)PrivateHandle); + break; + } + + case MODM_CLOSE : + { + Result = MmeCloseDevice(PrivateHandle); + + break; + } + + case MODM_GETVOLUME: + { + Result = MmeGetVolume(MIDI_OUT_DEVICE_TYPE, + DeviceId, + PrivateHandle, + Parameter1); + break; + } + + case MODM_SETVOLUME: + { + Result = MmeSetVolume(MIDI_OUT_DEVICE_TYPE, + DeviceId, + PrivateHandle, + Parameter1); + 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..62622180c9e05 --- /dev/null +++ b/dll/win32/wdmaud.drv/mixer/mxdMessage.c @@ -0,0 +1,165 @@ +/* + * 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 +MmeQueryMixerInfo( + IN UINT DeviceId, + IN UINT Message, + IN DWORD_PTR PrivateHandle, + IN DWORD_PTR Parameter1, + IN DWORD_PTR Parameter2) +{ + PWDMAUD_DEVICE_INFO DeviceInfo; + MMRESULT Result; + + DPRINT("Getting mixer info %u\n", Message); + + if ( PrivateHandle == 0 ) + { + DeviceInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_INFO)); + if (DeviceInfo) + { + Result = FUNC_NAME(WdmAudQueryMixerInfo)(DeviceInfo, DeviceId, Message, (LPVOID)Parameter1, Parameter2); + HeapFree(GetProcessHeap(), 0, DeviceInfo); + return TranslateInternalMmResult(Result); + } + } + + 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, + (PVOID)Parameter1, + Parameter2); + break; + } + + case MXDM_OPEN : + { + Result = MmeOpenDevice(MIXER_DEVICE_TYPE, + DeviceId, + (LPWAVEOPENDESC)Parameter1, + Parameter2, + (DWORD_PTR*) PrivateHandle); + + break; + } + + case MXDM_CLOSE : + { + Result = MmeCloseDevice(PrivateHandle); + + break; + } + + case MXDM_GETCONTROLDETAILS : + { + Result = MmeQueryMixerInfo(DeviceId, + Message, + PrivateHandle, + Parameter1, + Parameter2); + + break; + } + + case MXDM_SETCONTROLDETAILS : + { + Result = MmeQueryMixerInfo(DeviceId, + Message, + PrivateHandle, + Parameter1, + Parameter2); + + break; + } + + case MXDM_GETLINECONTROLS : + { + Result = MmeQueryMixerInfo(DeviceId, + Message, + PrivateHandle, + Parameter1, + Parameter2); + + break; + } + + case MXDM_GETLINEINFO : + { + Result = MmeQueryMixerInfo(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..e8319134f42c8 --- /dev/null +++ b/dll/win32/wdmaud.drv/mmewrap.c @@ -0,0 +1,381 @@ +/* + * 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 PVOID Capabilities, + IN DWORD CapabilitiesSize) +{ + 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, + CapabilitiesSize); + + 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 ) + { + 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; + } + } + + 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); +} + + +MMRESULT +MmeGetVolume( + _In_ SOUND_DEVICE_TYPE DeviceType, + _In_ DWORD DeviceId, + _In_ DWORD_PTR PrivateHandle, + _Out_ DWORD_PTR pdwVolume) +{ + PWDMAUD_DEVICE_INFO DeviceInfo; + + /* Sanity check */ + ASSERT(DeviceType == AUX_DEVICE_TYPE || + DeviceType == MIDI_OUT_DEVICE_TYPE || + DeviceType == WAVE_OUT_DEVICE_TYPE); + + VALIDATE_MMSYS_PARAMETER(PrivateHandle); + DeviceInfo = (PWDMAUD_DEVICE_INFO)PrivateHandle; + + if ( ! DeviceInfo ) + return MMSYSERR_INVALHANDLE; + + /* Call the driver */ + return FUNC_NAME(WdmAudGetVolume)(DeviceInfo, DeviceId, (PDWORD)pdwVolume); +} + +MMRESULT +MmeSetVolume( + _In_ SOUND_DEVICE_TYPE DeviceType, + _In_ DWORD DeviceId, + _In_ DWORD_PTR PrivateHandle, + _In_ DWORD_PTR dwVolume) +{ + PWDMAUD_DEVICE_INFO DeviceInfo; + + /* Sanity check */ + ASSERT(DeviceType == AUX_DEVICE_TYPE || + DeviceType == MIDI_OUT_DEVICE_TYPE || + DeviceType == WAVE_OUT_DEVICE_TYPE); + + VALIDATE_MMSYS_PARAMETER(PrivateHandle); + DeviceInfo = (PWDMAUD_DEVICE_INFO)PrivateHandle; + + if ( ! DeviceInfo ) + return MMSYSERR_INVALHANDLE; + + /* Call the driver */ + return FUNC_NAME(WdmAudSetVolume)(DeviceInfo, DeviceId, (DWORD)dwVolume); +} diff --git a/dll/win32/wdmaud.drv/mmixer.c b/dll/win32/wdmaud.drv/mmixer.c index f4f0fbd09ef10..307a0fd0531b4 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,8 +385,8 @@ WdmAudCleanupByMMixer() MMRESULT WdmAudGetMixerCapabilities( - IN ULONG DeviceId, - LPMIXERCAPSW Capabilities) + _In_ ULONG DeviceId, + _Out_ LPMIXERCAPSW Capabilities) { if (MMixerGetCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS) return MMSYSERR_NOERROR; @@ -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; @@ -449,10 +447,34 @@ WdmAudGetControlDetails( return MMSYSERR_ERROR; } +MMRESULT +WdmAudGetMidiOutCapabilities( + _In_ ULONG DeviceId, + _Out_ LPMIDIOUTCAPSW Capabilities) +{ + if (MMixerMidiOutCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS) + return MMSYSERR_NOERROR; + + return MMSYSERR_ERROR; + +} + +MMRESULT +WdmAudGetMidiInCapabilities( + _In_ ULONG DeviceId, + _Out_ LPMIDIINCAPSW Capabilities) +{ + if (MMixerMidiInCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS) + return MMSYSERR_NOERROR; + + return MMSYSERR_ERROR; +} + + MMRESULT WdmAudGetWaveOutCapabilities( - IN ULONG DeviceId, - LPWAVEOUTCAPSW Capabilities) + _In_ ULONG DeviceId, + _Out_ LPWAVEOUTCAPSW Capabilities) { if (MMixerWaveOutCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS) return MMSYSERR_NOERROR; @@ -463,8 +485,8 @@ WdmAudGetWaveOutCapabilities( MMRESULT WdmAudGetWaveInCapabilities( - IN ULONG DeviceId, - LPWAVEINCAPSW Capabilities) + _In_ ULONG DeviceId, + _Out_ LPWAVEINCAPSW Capabilities) { if (MMixerWaveInCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS) return MMSYSERR_NOERROR; @@ -473,79 +495,84 @@ WdmAudGetWaveInCapabilities( } MMRESULT -WdmAudSetWaveDeviceFormatByMMixer( - IN PSOUND_DEVICE_INSTANCE Instance, - IN DWORD DeviceId, - IN PWAVEFORMATEX WaveFormat, - IN DWORD WaveFormatSize) -{ - MMDEVICE_TYPE DeviceType; - PSOUND_DEVICE SoundDevice; - MMRESULT Result; - BOOL bWaveIn; - - Result = GetSoundDeviceFromInstance(Instance, &SoundDevice); +WdmAudOpenSoundDeviceByMMixer( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEFORMATEX WaveFormat) +{ + BOOL bInput; - if ( ! MMSUCCESS(Result) ) + if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE) { - return TranslateInternalMmResult(Result); + if (MMixerOpen(&MixerContext, DeviceInfo->DeviceIndex, &DeviceInfo->hDevice) == MM_STATUS_SUCCESS) + { + return MMSYSERR_NOERROR; + } } + else if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE || DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE) + { + bInput = DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE; - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); - - bWaveIn = (DeviceType == WAVE_IN_DEVICE_TYPE ? TRUE : FALSE); - - if (MMixerOpenWave(&MixerContext, DeviceId, bWaveIn, WaveFormat, NULL, NULL, &Instance->Handle) == MM_STATUS_SUCCESS) + if (MMixerOpenMidi(&MixerContext, DeviceInfo->DeviceIndex, bInput, NULL, NULL, &DeviceInfo->hDevice) == MM_STATUS_SUCCESS) + { + return MMSYSERR_NOERROR; + } + } + else if (DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE || DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { - if (DeviceType == WAVE_OUT_DEVICE_TYPE) + bInput = DeviceInfo->DeviceType == WAVE_IN_DEVICE_TYPE; + + if (MMixerOpenWave(&MixerContext, DeviceInfo->DeviceIndex, bInput, WaveFormat, NULL, NULL, &DeviceInfo->hDevice) == MM_STATUS_SUCCESS) { - MMixerSetWaveStatus(&MixerContext, Instance->Handle, KSSTATE_ACQUIRE); - MMixerSetWaveStatus(&MixerContext, Instance->Handle, KSSTATE_PAUSE); - MMixerSetWaveStatus(&MixerContext, Instance->Handle, KSSTATE_RUN); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_ACQUIRE); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, KSSTATE_PAUSE); + MMixerSetWaveStatus(&MixerContext, DeviceInfo->hDevice, 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_ PVOID Capabilities, + _In_ DWORD CapabilitiesSize) { - 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(DeviceInfo->DeviceIndex, (LPMIXERCAPSW)Capabilities); + } + else if (DeviceInfo->DeviceType == MIDI_OUT_DEVICE_TYPE) + { + return WdmAudGetMidiOutCapabilities(DeviceInfo->DeviceIndex, (LPMIDIOUTCAPSW)Capabilities); + } + else if (DeviceInfo->DeviceType == MIDI_IN_DEVICE_TYPE) { - return WdmAudGetMixerCapabilities(DeviceId, (LPMIXERCAPSW)Capabilities); + return WdmAudGetMidiInCapabilities(DeviceInfo->DeviceIndex, (LPMIDIINCAPSW)Capabilities); } - 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); } - 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); } 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 +582,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) ) - { - return TranslateInternalMmResult(Result); - } - - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); - - if (DeviceType == MIXER_DEVICE_TYPE) + if (DeviceInfo->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 +613,8 @@ WdmAudCloseSoundDeviceByMMixer( MMRESULT WdmAudGetNumWdmDevsByMMixer( - IN MMDEVICE_TYPE DeviceType, - OUT DWORD* DeviceCount) + _In_ SOUND_DEVICE_TYPE DeviceType, + _Out_ DWORD* DeviceCount) { switch(DeviceType) { @@ -616,16 +635,15 @@ 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; LPMIXERCONTROLDETAILS MixDetails; - HANDLE hMixer = NULL; MixLine = (LPMIXERLINEW)Parameter; MixControls = (LPMIXERLINECONTROLSW)Parameter; @@ -633,116 +651,74 @@ WdmAudQueryMixerInfoByMMixer( /* FIXME param checks */ - if (SoundDeviceInstance) - { - hMixer = SoundDeviceInstance->Handle; - } - switch(uMsg) { case MXDM_GETLINEINFO: - return WdmAudGetLineInfo(hMixer, MixerId, MixLine, Flags); + return WdmAudGetLineInfo(DeviceInfo->hDevice, MixerId, MixLine, Flags); case MXDM_GETLINECONTROLS: - return WdmAudGetLineControls(hMixer, MixerId, MixControls, Flags); - case MXDM_SETCONTROLDETAILS: - return WdmAudSetControlDetails(hMixer, MixerId, MixDetails, Flags); - 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; + return WdmAudGetLineControls(DeviceInfo->hDevice, MixerId, MixControls, Flags); + case MXDM_SETCONTROLDETAILS: + return WdmAudSetControlDetails(DeviceInfo->hDevice, MixerId, MixDetails, Flags); + case MXDM_GETCONTROLDETAILS: + return WdmAudGetControlDetails(DeviceInfo->hDevice, MixerId, MixDetails, Flags); + 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 ); - + /* Are we requested to start the audio device? */ + if (bStart) + { + /* 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); + } - Result = GetSoundDeviceType(SoundDevice, &DeviceType); - SND_ASSERT( Result == MMSYSERR_NOERROR ); + /* Mark device as started */ + DeviceInfo->DeviceState->bStart = TRUE; + } - 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,47 +727,43 @@ 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; - 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 */ + /* Mark device as stopped */ + DeviceInfo->DeviceState->bStart = FALSE; + + /* 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 PWDMAUD_DEVICE_INFO DeviceInfo, IN MMTIME* Time) { - PSOUND_DEVICE SoundDevice; - MMDEVICE_TYPE DeviceType; MIXER_STATUS Status; - MMRESULT Result; DWORD Position; - Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); - if (!MMSUCCESS(Result)) - return TranslateInternalMmResult(Result); - - 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) { - Status = MMixerGetWavePosition(&MixerContext, SoundDeviceInstance->Handle, &Position); + Status = MMixerGetWavePosition(&MixerContext, DeviceInfo->hDevice, &Position); if (Status == MM_STATUS_SUCCESS) { /* Store position */ @@ -807,7 +779,7 @@ WdmAudGetWavePositionByMMixer( MMRESULT WdmAudGetVolumeByMMixer( - _In_ PSOUND_DEVICE_INSTANCE SoundDeviceInstance, + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, _In_ DWORD DeviceId, _Out_ PDWORD pdwVolume) { @@ -822,7 +794,7 @@ WdmAudGetVolumeByMMixer( MixLine.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS; /* Get line info */ - Result = WdmAudGetLineInfo(SoundDeviceInstance->Handle, + Result = WdmAudGetLineInfo(DeviceInfo->hDevice, DeviceId, &MixLine, MIXER_OBJECTF_MIXER | MIXER_GETLINEINFOF_COMPONENTTYPE); @@ -837,7 +809,7 @@ WdmAudGetVolumeByMMixer( MixLineControls.pamxctrl = &MixControl; /* Get line controls */ - Result = WdmAudGetLineControls(SoundDeviceInstance->Handle, + Result = WdmAudGetLineControls(DeviceInfo->hDevice, DeviceId, &MixLineControls, MIXER_OBJECTF_MIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE); @@ -852,7 +824,7 @@ WdmAudGetVolumeByMMixer( MixControlDetails.paDetails = MixControlDetailsU; /* Get volume control details */ - Result = WdmAudGetControlDetails(SoundDeviceInstance->Handle, + Result = WdmAudGetControlDetails(DeviceInfo->hDevice, DeviceId, &MixControlDetails, MIXER_OBJECTF_MIXER); @@ -864,7 +836,7 @@ WdmAudGetVolumeByMMixer( MMRESULT WdmAudSetVolumeByMMixer( - _In_ PSOUND_DEVICE_INSTANCE SoundDeviceInstance, + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, _In_ DWORD DeviceId, _In_ DWORD dwVolume) { @@ -879,7 +851,7 @@ WdmAudSetVolumeByMMixer( MixLine.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS; /* Get line info */ - Result = WdmAudGetLineInfo(SoundDeviceInstance->Handle, + Result = WdmAudGetLineInfo(DeviceInfo->hDevice, DeviceId, &MixLine, MIXER_OBJECTF_MIXER | MIXER_GETLINEINFOF_COMPONENTTYPE); @@ -894,7 +866,7 @@ WdmAudSetVolumeByMMixer( MixLineControls.pamxctrl = &MixControl; /* Get line controls */ - Result = WdmAudGetLineControls(SoundDeviceInstance->Handle, + Result = WdmAudGetLineControls(DeviceInfo->hDevice, DeviceId, &MixLineControls, MIXER_OBJECTF_MIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE); @@ -913,97 +885,100 @@ WdmAudSetVolumeByMMixer( MixControlDetails.paDetails = MixControlDetailsU; /* Set volume control details */ - Result = WdmAudSetControlDetails(SoundDeviceInstance->Handle, + Result = WdmAudSetControlDetails(DeviceInfo->hDevice, DeviceId, &MixControlDetails, MIXER_OBJECTF_MIXER); return Result; } -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; - - /* Call mmebuddy overlap routine */ - Overlap->OriginalCompletionRoutine(dwErrorCode, - lpHeader->DataUsed, &Overlap->Standard); - - HeapFree(GetProcessHeap(), 0, lpHeader); -} - 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 = NULL; + + /* 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..91b32ad6a45fe --- /dev/null +++ b/dll/win32/wdmaud.drv/wave/header.c @@ -0,0 +1,207 @@ +/* + * 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"); + + /* Initialize fields for new header */ + 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; + } + + /* Create stream event */ + HeaderExtension->Overlapped.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + if (!HeaderExtension->Overlapped.hEvent) + { + /* No memory */ + HeapFree(GetProcessHeap(), 0, HeaderExtension); + return MMSYSERR_NOMEM; + } + + Header->reserved = (DWORD_PTR)HeaderExtension; + + /* This is what winmm expects to be returned */ + return MMSYSERR_NOTSUPPORTED; +} + +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 header extension */ + HeapFree(GetProcessHeap(), 0, HeaderExtension); + + /* This is what winmm expects to be returned */ + return MMSYSERR_NOTSUPPORTED; +} + +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; + + if (DeviceInfo->DeviceState->hNotifyEvent) + { + /* Set queue event */ + DPRINT("Setting queue event...\n"); + SetEvent(DeviceInfo->DeviceState->hNotifyEvent); + } + } + else + { + /* This is the 2nd or another header */ + DPRINT("Enqueued next wave header\n"); + + /* Enumerate the whole queue */ + PWAVEHDR TempHeader = DeviceInfo->DeviceState->WaveQueue; + while (TempHeader->lpNext) TempHeader = TempHeader->lpNext; + + /* Insert the header in the end of it */ + TempHeader->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..e8efdba6a661d --- /dev/null +++ b/dll/win32/wdmaud.drv/wave/streaming.c @@ -0,0 +1,90 @@ +/* + * 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()); + DeviceInfo->DeviceState->WaveQueue = NULL; + 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..1b9d54d2fdc87 --- /dev/null +++ b/dll/win32/wdmaud.drv/wave/widMessage.c @@ -0,0 +1,135 @@ +/* + * 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, + (PVOID)Parameter1, + Parameter2); + 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..60d211d2f35ce --- /dev/null +++ b/dll/win32/wdmaud.drv/wave/wodMessage.c @@ -0,0 +1,153 @@ +/* + * 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, + (PVOID)Parameter1, + Parameter2); + 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; + } + + case WODM_GETVOLUME: + { + Result = MmeGetVolume(WAVE_OUT_DEVICE_TYPE, + DeviceId, + PrivateHandle, + Parameter1); + break; + } + + case WODM_SETVOLUME: + { + Result = MmeSetVolume(WAVE_OUT_DEVICE_TYPE, + DeviceId, + PrivateHandle, + Parameter1); + 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 6b8561f19f3ef..ec3bb59fea0e3 100644 --- a/dll/win32/wdmaud.drv/wdmaud.c +++ b/dll/win32/wdmaud.drv/wdmaud.c @@ -5,115 +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 == AUX_DEVICE_TYPE || DeviceType == MIDI_OUT_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE) - { - FuncTable.GetVolume = FUNC_NAME(WdmAudGetVolume); - FuncTable.SetVolume = FUNC_NAME(WdmAudSetVolume); - } - - 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 @@ -128,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; } @@ -181,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, @@ -219,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 dee7f2058eb76..31713e87ae899 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; + OVERLAPPED Overlapped; +} WAVEHDR_EXTENSION, *PWAVEHDR_EXTENSION; + +/* mmixer.c */ + BOOL WdmAudInitUserModeMixer(VOID); @@ -32,238 +58,273 @@ 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_ PVOID Capabilities, + _In_ DWORD CapabilitiesSize); 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 -WdmAudGetVolumeByMMixer( - _In_ PSOUND_DEVICE_INSTANCE SoundDeviceInstance, +FUNC_NAME(WdmAudGetVolume)( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, _In_ DWORD DeviceId, _Out_ PDWORD pdwVolume); MMRESULT -WdmAudSetVolumeByMMixer( - _In_ PSOUND_DEVICE_INSTANCE SoundDeviceInstance, +FUNC_NAME(WdmAudSetVolume)( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, _In_ DWORD DeviceId, _In_ DWORD dwVolume); 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_ PVOID Capabilities, + _In_ DWORD CapabilitiesSize); 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); MMRESULT -WdmAudSetMixerDeviceFormatByLegacy( - IN PSOUND_DEVICE_INSTANCE Instance, - IN DWORD DeviceId, - IN PWAVEFORMATEX WaveFormat, - IN DWORD WaveFormatSize); +MmeGetVolume( + _In_ SOUND_DEVICE_TYPE DeviceType, + _In_ DWORD DeviceId, + _In_ DWORD_PTR PrivateHandle, + _Out_ DWORD_PTR pdwVolume); + +MMRESULT +MmeSetVolume( + _In_ SOUND_DEVICE_TYPE DeviceType, + _In_ DWORD DeviceId, + _In_ DWORD_PTR PrivateHandle, + _In_ DWORD_PTR dwVolume); + + +#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 -WdmAudQueryMixerInfoByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN DWORD DeviceId, - IN UINT uMsg, - IN LPVOID Parameter, - IN DWORD Flags); +MmeResetWavePlayback( + _In_ DWORD_PTR PrivateHandle); + +/* + result.c +*/ MMRESULT -WdmAudSetWaveDeviceFormatByLegacy( - IN PSOUND_DEVICE_INSTANCE Instance, - IN DWORD DeviceId, - IN PWAVEFORMATEX WaveFormat, - IN DWORD WaveFormatSize); +Win32ErrorToMmResult( + _In_ UINT ErrorCode); MMRESULT -WdmAudSetWaveStateByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN BOOL bStart); +TranslateInternalMmResult( + _In_ MMRESULT Result); + +/* + header.c +*/ MMRESULT -WdmAudResetStreamByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN MMDEVICE_TYPE DeviceType, - IN BOOLEAN bStartReset); +EnqueueWaveHeader( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEHDR Header); + +VOID +CompleteWaveHeader( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo); MMRESULT -WdmAudGetWavePositionByLegacy( - IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, - IN MMTIME* Time); +PrepareWaveHeader( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEHDR Header); MMRESULT -WdmAudGetVolumeByLegacy( - _In_ PSOUND_DEVICE_INSTANCE SoundDeviceInstance, - _In_ DWORD DeviceId, - _Out_ PDWORD pdwVolume); +UnprepareWaveHeader( + _In_ PWDMAUD_DEVICE_INFO DeviceInfo, + _In_ PWAVEHDR Header); MMRESULT -WdmAudSetVolumeByLegacy( - _In_ PSOUND_DEVICE_INSTANCE SoundDeviceInstance, - _In_ DWORD DeviceId, - _In_ DWORD dwVolume); +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/dll/win32/winmm/CMakeLists.txt b/dll/win32/winmm/CMakeLists.txt index aca0942d4be1e..f7788013c4227 100644 --- a/dll/win32/winmm/CMakeLists.txt +++ b/dll/win32/winmm/CMakeLists.txt @@ -4,6 +4,7 @@ include_directories(BEFORE ${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine) spec2def(winmm.dll winmm.spec ADD_IMPORTLIB) list(APPEND SOURCE + deviface.c driver.c joystick.c lolvldrv.c @@ -29,8 +30,8 @@ if(MSVC) endif() set_module_type(winmm win32dll) -target_link_libraries(winmm wine ${PSEH_LIB} oldnames) -add_importlibs(winmm advapi32 user32 msvcrt kernel32 ntdll) +target_link_libraries(winmm wine ${PSEH_LIB}) +add_importlibs(winmm setupapi advapi32 user32 msvcrt kernel32 ntdll) add_pch(winmm winemm.h SOURCE) add_cd_file(TARGET winmm DESTINATION reactos/system32 FOR all) diff --git a/dll/win32/winmm/deviface.c b/dll/win32/winmm/deviface.c new file mode 100644 index 0000000000000..4a483f02a28e6 --- /dev/null +++ b/dll/win32/winmm/deviface.c @@ -0,0 +1,76 @@ + +#include "winemm.h" + +#include +#include +#include + +WINE_DEFAULT_DEBUG_CHANNEL(winmm); + +/* Retrieves device interface path for DRVM_INIT and XXXX_GETNUMDEVS messages */ +BOOL GetDeviceInterfacePath(LPWSTR* DevicePath) +{ + SP_DEVICE_INTERFACE_DATA interface_data; + SP_DEVINFO_DATA device_data; + PSP_DEVICE_INTERFACE_DETAIL_DATA_W detail_data; + WCHAR device_path[MAX_PATH]; + HDEVINFO dev_info; + DWORD length; + int index = 0; + + const GUID category_guid = {STATIC_KSCATEGORY_AUDIO}; + + dev_info = SetupDiGetClassDevsW(&category_guid, + NULL, + NULL, + DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); + + interface_data.cbSize = sizeof(interface_data); + interface_data.Reserved = 0; + + length = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + + (MAX_PATH * sizeof(WCHAR)); + + detail_data = + (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), + 0, + length); + + if (!detail_data) + { + ERR("Failed to allocate detail_data\n"); + return FALSE; + } + + while ( + SetupDiEnumDeviceInterfaces(dev_info, + NULL, + &category_guid, + index, + &interface_data) ) + { + ZeroMemory(detail_data, length); + + detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W); + device_data.cbSize = sizeof(device_data); + device_data.Reserved = 0; + SetupDiGetDeviceInterfaceDetailW(dev_info, + &interface_data, + detail_data, + length, + NULL, + &device_data); + + wcscpy(device_path, detail_data->DevicePath); + device_path[0] = L'\\'; + device_path[1] = L'?'; + *DevicePath = device_path; + ERR("device_path %S\n", device_path); + index++; + } + + HeapFree(GetProcessHeap(), 0, detail_data); + + SetupDiDestroyDeviceInfoList(dev_info); + return TRUE; +} diff --git a/dll/win32/winmm/lolvldrv.c b/dll/win32/winmm/lolvldrv.c index eda443f37eec2..2e613f9565b05 100644 --- a/dll/win32/winmm/lolvldrv.c +++ b/dll/win32/winmm/lolvldrv.c @@ -359,6 +359,7 @@ UINT MMDRV_PhysicalFeatures(LPWINE_MLD mld, UINT uMsg, static BOOL MMDRV_InitPerType(LPWINE_MM_DRIVER lpDrv, UINT type, UINT wMsg) { WINE_MM_DRIVER_PART* part = &lpDrv->parts[type]; + LPWSTR device_path; DWORD ret; UINT count = 0; int i, k; @@ -369,13 +370,14 @@ static BOOL MMDRV_InitPerType(LPWINE_MM_DRIVER lpDrv, UINT type, UINT wMsg) /* for DRVM_INIT and DRVM_ENABLE, dwParam2 should be PnP node */ /* the DRVM_ENABLE is only required when the PnP node is non zero */ if (part->fnMessage32) { - ret = part->fnMessage32(0, DRVM_INIT, 0L, 0L, 0L); + GetDeviceInterfacePath(&device_path); + ret = part->fnMessage32(0, DRVM_INIT, 0L, 0L, (DWORD_PTR)device_path); TRACE("DRVM_INIT => %s\n", WINMM_ErrorToString(ret)); #if 0 ret = part->fnMessage32(0, DRVM_ENABLE, 0L, 0L, 0L); TRACE("DRVM_ENABLE => %08lx\n", ret); #endif - count = part->fnMessage32(0, wMsg, 0L, 0L, 0L); + count = part->fnMessage32(0, wMsg, 0L, (DWORD_PTR)device_path, 0L); } else return FALSE; diff --git a/dll/win32/winmm/mci.c b/dll/win32/winmm/mci.c index 8a5f221e3493b..6026e6a576dfa 100644 --- a/dll/win32/winmm/mci.c +++ b/dll/win32/winmm/mci.c @@ -109,12 +109,12 @@ static UINT MCI_GetDriverFromString(LPCWSTR lpstrName) if (!lpstrName) return 0; - if (!wcsicmp(lpstrName, L"ALL")) + if (!_wcsicmp(lpstrName, L"ALL")) return MCI_ALL_DEVICE_ID; EnterCriticalSection(&WINMM_cs); for (wmd = MciDrivers; wmd; wmd = wmd->lpNext) { - if (wmd->lpstrAlias && wcsicmp(wmd->lpstrAlias, lpstrName) == 0) { + if (wmd->lpstrAlias && _wcsicmp(wmd->lpstrAlias, lpstrName) == 0) { ret = wmd->wDeviceID; break; } @@ -542,7 +542,7 @@ static UINT MCI_GetDevTypeFromResource(LPCWSTR lpstrName) for (uDevType = MCI_DEVTYPE_FIRST; uDevType <= MCI_DEVTYPE_LAST; uDevType++) { if (LoadStringW(hWinMM32Instance, uDevType, buf, ARRAY_SIZE(buf))) { /* FIXME: ignore digits suffix */ - if (!wcsicmp(buf, lpstrName)) + if (!_wcsicmp(buf, lpstrName)) return uDevType; } } @@ -835,7 +835,7 @@ static DWORD MCI_LoadMciDriver(LPCWSTR _strDevTyp, LPWINE_MCIDRIVER* lpwmd) /* silence warning if all is used... some bogus program use commands like * 'open all'... */ - if (wcsicmp(strDevTyp, L"ALL") == 0) { + if (_wcsicmp(strDevTyp, L"ALL") == 0) { dwRet = MCIERR_CANNOT_USE_ALL; } else { FIXME("Couldn't load driver for type %s.\n", @@ -943,7 +943,7 @@ static LPCWSTR MCI_FindCommand(UINT uTbl, LPCWSTR verb) * array look up */ for (idx = 0; idx < S_MciCmdTable[uTbl].nVerbs; idx++) { - if (wcsicmp(S_MciCmdTable[uTbl].aVerbs[idx], verb) == 0) + if (_wcsicmp(S_MciCmdTable[uTbl].aVerbs[idx], verb) == 0) return S_MciCmdTable[uTbl].aVerbs[idx]; } @@ -1339,7 +1339,7 @@ DWORD WINAPI mciSendStringW(LPCWSTR lpstrCommand, LPWSTR lpstrRet, if ((dwRet = MCI_GetString(&dev, &args))) { goto errCleanUp; } - uDevID = wcsicmp(dev, L"ALL") ? 0 : MCI_ALL_DEVICE_ID; + uDevID = _wcsicmp(dev, L"ALL") ? 0 : MCI_ALL_DEVICE_ID; /* Determine devType from open */ if (!wcscmp(verb, L"open")) { diff --git a/dll/win32/winmm/winemm.h b/dll/win32/winmm/winemm.h index 640c8036a3cb0..68ba488c0c2c4 100644 --- a/dll/win32/winmm/winemm.h +++ b/dll/win32/winmm/winemm.h @@ -192,6 +192,8 @@ extern HANDLE psStopEvent; #define WINE_GDF_EXTERNAL_MASK 0xF0000000 #define WINE_GDF_SESSION 0x00000001 +/* Retrieves device interface path for DRVM_INIT and XXXX_GETNUMDEVS messages */ +BOOL GetDeviceInterfacePath(LPWSTR* DevicePath); /* Modification to take into account Windows NT's registry format */ diff --git a/dll/win32/winmm/winmm.c b/dll/win32/winmm/winmm.c index 1ecf53b5385c3..42083993fab15 100644 --- a/dll/win32/winmm/winmm.c +++ b/dll/win32/winmm/winmm.c @@ -320,6 +320,9 @@ UINT WINAPI mixerGetDevCapsW(UINT_PTR uDeviceID, LPMIXERCAPSW lpCaps, UINT uSize if ((wmld = MMDRV_Get((HANDLE)uDeviceID, MMDRV_MIXER, TRUE)) == NULL) return MMSYSERR_BADDEVICEID; + /* HACK for MS wdmaud.drv */ + lpCaps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MIXERCAPSW)); + return MMDRV_Message(wmld, MXDM_GETDEVCAPS, (DWORD_PTR)lpCaps, uSize); } @@ -369,7 +372,7 @@ UINT WINAPI mixerOpen(LPHMIXER lphMix, UINT uDeviceID, DWORD_PTR dwCallback, mod.hmx = hMix; dwRet = MMDRV_Open(wmld, MXDM_OPEN, (DWORD_PTR)&mod, CALLBACK_FUNCTION); - + dwRet = MMSYSERR_NOERROR; if (dwRet != MMSYSERR_NOERROR) { MMDRV_Free(hMix, wmld); hMix = 0; @@ -730,6 +733,10 @@ UINT WINAPI auxGetDevCapsW(UINT_PTR uDeviceID, LPAUXCAPSW lpCaps, UINT uSize) if ((wmld = MMDRV_Get((HANDLE)uDeviceID, MMDRV_AUX, TRUE)) == NULL) return MMSYSERR_INVALHANDLE; + + /* HACK for MS wdmaud.drv */ + lpCaps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(AUXCAPSW)); + return MMDRV_Message(wmld, AUXDM_GETDEVCAPS, (DWORD_PTR)lpCaps, uSize); } @@ -823,6 +830,9 @@ UINT WINAPI midiOutGetDevCapsW(UINT_PTR uDeviceID, LPMIDIOUTCAPSW lpCaps, if ((wmld = MMDRV_Get((HANDLE)uDeviceID, MMDRV_MIDIOUT, TRUE)) == NULL) return MMSYSERR_INVALHANDLE; + /* HACK for MS wdmaud.drv */ + lpCaps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MIDIOUTCAPSW)); + return MMDRV_Message(wmld, MODM_GETDEVCAPS, (DWORD_PTR)lpCaps, uSize); } @@ -1200,6 +1210,9 @@ UINT WINAPI midiInGetDevCapsW(UINT_PTR uDeviceID, LPMIDIINCAPSW lpCaps, UINT uSi if ((wmld = MMDRV_Get((HANDLE)uDeviceID, MMDRV_MIDIIN, TRUE)) == NULL) return MMSYSERR_INVALHANDLE; + /* HACK for MS wdmaud.drv */ + lpCaps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MIDIINCAPSW)); + return MMDRV_Message(wmld, MIDM_GETDEVCAPS, (DWORD_PTR)lpCaps, uSize); } @@ -2188,6 +2201,9 @@ UINT WINAPI waveOutGetDevCapsW(UINT_PTR uDeviceID, LPWAVEOUTCAPSW lpCaps, if ((wmld = MMDRV_Get((HANDLE)uDeviceID, MMDRV_WAVEOUT, TRUE)) == NULL) return MMSYSERR_BADDEVICEID; + /* HACK for MS wdmaud.drv */ + lpCaps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WAVEOUTCAPSW)); + return MMDRV_Message(wmld, WODM_GETDEVCAPS, (DWORD_PTR)lpCaps, uSize); } @@ -2588,6 +2604,9 @@ UINT WINAPI waveInGetDevCapsW(UINT_PTR uDeviceID, LPWAVEINCAPSW lpCaps, UINT uSi if ((wmld = MMDRV_Get((HANDLE)uDeviceID, MMDRV_WAVEIN, TRUE)) == NULL) return MMSYSERR_BADDEVICEID; + /* HACK for MS wdmaud.drv */ + lpCaps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WAVEINCAPSW)); + return MMDRV_Message(wmld, WIDM_GETDEVCAPS, (DWORD_PTR)lpCaps, uSize); } diff --git a/drivers/ksfilter/ks/allocators.c b/drivers/ksfilter/ks/allocators.c index a265f04837273..661479040d887 100644 --- a/drivers/ksfilter/ks/allocators.c +++ b/drivers/ksfilter/ks/allocators.c @@ -175,7 +175,7 @@ IKsAllocator_fnDeviceIoControl( /* invalid request */ Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; CompleteRequest(Irp, IO_NO_INCREMENT); - + DPRINT1("1\n"); return STATUS_INVALID_DEVICE_REQUEST; } @@ -674,7 +674,10 @@ KsValidateAllocatorFramingEx( IN const KSALLOCATOR_FRAMING_EX* PinFraming) { if (BufferSize < sizeof(KSALLOCATOR_FRAMING_EX)) - return STATUS_INVALID_DEVICE_REQUEST; + { + DPRINT1("2\n"); + return STATUS_INVALID_DEVICE_REQUEST; + } /* verify framing */ if ((Framing->FramingItem[0].Flags & KSALLOCATOR_FLAG_PARTIAL_READ_SUPPORT) && diff --git a/drivers/ksfilter/ks/api.c b/drivers/ksfilter/ks/api.c index cc1fd3dd7c730..2861cbbea2d58 100644 --- a/drivers/ksfilter/ks/api.c +++ b/drivers/ksfilter/ks/api.c @@ -691,6 +691,7 @@ KsAllocateObjectHeader( } /* store the object in the file object */ IoStack->FileObject->FsContext2 = ObjectHeader; + IoStack->FileObject->FsContext = ObjectHeader; /* store parent device */ ObjectHeader->ParentDeviceObject = IoGetRelatedDeviceObject(IoStack->FileObject); @@ -1159,7 +1160,7 @@ KsSynchronousIoControlDevice( } - /* Store Fileobject */ + /* Prepare stack location */ IoStack = IoGetNextIrpStackLocation(Irp); IoStack->FileObject = FileObject; diff --git a/drivers/ksfilter/ks/clocks.c b/drivers/ksfilter/ks/clocks.c index 730748b2343ae..05559f4cf6e93 100644 --- a/drivers/ksfilter/ks/clocks.c +++ b/drivers/ksfilter/ks/clocks.c @@ -299,6 +299,7 @@ KsValidateClockCreateRequest( if (ClockCreate->CreateFlags != 0) { /* flags must be zero */ + DPRINT1("CLockCreate->CreateFlags %d\n", ClockCreate->CreateFlags); FreeItem(ClockCreate); return STATUS_INVALID_PARAMETER; } diff --git a/drivers/ksfilter/ks/connectivity.c b/drivers/ksfilter/ks/connectivity.c index 395d5b53d633f..454779bb2b9d6 100644 --- a/drivers/ksfilter/ks/connectivity.c +++ b/drivers/ksfilter/ks/connectivity.c @@ -110,7 +110,6 @@ KspValidateConnectRequest( Descriptor = &((PKSPIN_DESCRIPTOR_EX)((ULONG_PTR)Descriptors + DescriptorSize * ConnectDetails->PinId))->PinDescriptor; } - /* does the pin have interface details filled in */ if (Descriptor->InterfacesCount && Descriptor->Interfaces) { @@ -346,7 +345,7 @@ KspPinPropertyHandler( IoStack = IoGetCurrentIrpStackLocation(Irp); Buffer = Data; - //DPRINT("KsPinPropertyHandler Irp %p Property %p Data %p DescriptorsCount %u Descriptor %p OutputLength %u Id %u\n", Irp, Property, Data, DescriptorsCount, Descriptor, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Property->Id); + DPRINT("KsPinPropertyHandler Irp %p Property %p Data %p DescriptorsCount %u Descriptor %p OutputLength %u Id %u\n", Irp, Property, Data, DescriptorsCount, Descriptors, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Property->Id); /* convert to PKSP_PIN */ Pin = (KSP_PIN*)Property; @@ -356,6 +355,7 @@ KspPinPropertyHandler( if (Pin->PinId >= DescriptorsCount) { /* invalid parameter */ + DPRINT1("Pin->PinId %d is our of range, DescriptorsCount %d\n", Pin->PinId, DescriptorsCount); return STATUS_INVALID_PARAMETER; } } @@ -420,6 +420,7 @@ KspPinPropertyHandler( if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == 0) { /* buffer too small */ + DPRINT1("1\n"); Irp->IoStatus.Information = Size; Status = STATUS_BUFFER_OVERFLOW; break; @@ -430,6 +431,7 @@ KspPinPropertyHandler( if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(ULONG)) { /* store the result size */ + DPRINT1("2\n"); Item->Size = Size; Irp->IoStatus.Information = sizeof(ULONG); Status = STATUS_SUCCESS; @@ -442,6 +444,7 @@ KspPinPropertyHandler( if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(KSMULTIPLE_ITEM)) { + DPRINT1("3\n"); Irp->IoStatus.Information = sizeof(KSMULTIPLE_ITEM); Status = STATUS_SUCCESS; break; @@ -674,7 +677,7 @@ KsPinPropertyHandler( } /* - @unimplemented + @implemented */ KSDDKAPI NTSTATUS NTAPI KsPinDataIntersectionEx( @@ -687,28 +690,11 @@ KsPinDataIntersectionEx( IN PFNKSINTERSECTHANDLEREX IntersectHandler OPTIONAL, IN PVOID HandlerContext OPTIONAL) { - UNIMPLEMENTED; - return STATUS_UNSUCCESSFUL; -} - -/* - @implemented -*/ -KSDDKAPI -NTSTATUS -NTAPI -KsPinDataIntersection( - IN PIRP Irp, - IN PKSP_PIN Pin, - OUT PVOID Data, - IN ULONG DescriptorsCount, - IN const KSPIN_DESCRIPTOR* Descriptor, - IN PFNKSINTERSECTHANDLER IntersectHandler) -{ - KSMULTIPLE_ITEM * Item; - KSDATARANGE * DataRange; + PKSMULTIPLE_ITEM MultipleItem; + PKSDATARANGE DataRange; PIO_STACK_LOCATION IoStack; - ULONG Size; + ULONG OutputBufferLength; + ULONG DataSize, Size; ULONG Index; NTSTATUS Status; @@ -728,35 +714,66 @@ KsPinDataIntersection( if (Pin->PinId >= DescriptorsCount) { /* it is */ + DPRINT1("PinId %d is out of range, DescriptorsCount %d\n", Pin->PinId, DescriptorsCount); Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; Irp->IoStatus.Information = 0; return STATUS_INVALID_PARAMETER; } + /* get output buffer length */ + OutputBufferLength = IoStack->Parameters.DeviceIoControl.OutputBufferLength; + /* get start item */ - Item = (KSMULTIPLE_ITEM*)(Pin + 1); + MultipleItem = (KSMULTIPLE_ITEM*)(Pin + 1); + /* get first data range */ - DataRange = (KSDATARANGE*)(Item + 1); + DataRange = (PKSDATARANGE)(MultipleItem + 1); + + /* FIXME make sure its 64 bit aligned */ + ASSERT(((ULONG_PTR)DataRange & 0x7) == 0); + /* iterate through all data ranges */ - for(Index = 0; Index < Item->Count; Index++, DataRange++) + for (Index = 0; Index < Descriptor->DataRangesCount; Index++) { - /* call intersect handler */ - Status = IntersectHandler(Irp, Pin, DataRange, Data); - if (NT_SUCCESS(Status)) + /* check matching of the data range */ + if (IsEqualGUIDAligned(&Descriptor->DataRanges[0]->MajorFormat, &DataRange->MajorFormat) || + IsEqualGUIDAligned(&Descriptor->DataRanges[0]->SubFormat, &DataRange->SubFormat) || + IsEqualGUIDAligned(&Descriptor->DataRanges[0]->Specifier, &DataRange->Specifier)) { - if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < DataRange->FormatSize) + /* call intersect handler */ + Status = IntersectHandler(HandlerContext, + Irp, + Pin, + DataRange, + Descriptor->DataRanges[0], + OutputBufferLength, + Data, + &DataSize); + DPRINT1("IntersectHandler status 0x%lx\n", Status); + if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) { - /* buffer is too small */ - Irp->IoStatus.Information = DataRange->FormatSize; - Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; - return STATUS_BUFFER_TOO_SMALL; + Irp->IoStatus.Information = DataSize; + if (OutputBufferLength == 0) + { + /* buffer overflow */ + Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; + return STATUS_BUFFER_OVERFLOW; + } + else if (OutputBufferLength < sizeof(KSDATARANGE)) + { + /* buffer is too small */ + Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; + return STATUS_BUFFER_TOO_SMALL; + } + RtlMoveMemory(Irp->UserBuffer, DataRange, sizeof(KSDATARANGE)); + Irp->IoStatus.Status = STATUS_SUCCESS; + return STATUS_SUCCESS; } - RtlMoveMemory(Irp->UserBuffer, DataRange, sizeof(KSDATARANGE)); - Irp->IoStatus.Information = sizeof(KSDATARANGE); - Irp->IoStatus.Status = STATUS_SUCCESS; - return STATUS_SUCCESS; - } + } + DataRange = (PKSDATARANGE)((PUCHAR)DataRange + DataRange->FormatSize); + /* FIXME make sure its 64 bit aligned */ + ASSERT(((ULONG_PTR)DataRange & 0x7) == 0); } Irp->IoStatus.Information = 0; @@ -764,6 +781,49 @@ KsPinDataIntersection( return STATUS_NO_MATCH; } +NTSTATUS +KspPinIntersectHandlerEx( + IN PVOID Context, + IN PIRP Irp, + IN PKSP_PIN Pin, + IN PKSDATARANGE DataRange, + IN PKSDATARANGE MatchingDataRange, + IN ULONG DataBufferSize, + OUT PVOID Data, + OUT PULONG DataSize) +{ + PFNKSINTERSECTHANDLER IntersectHandler = (PFNKSINTERSECTHANDLER)Context; + NTSTATUS Status; + + Status = IntersectHandler(Irp, Pin, DataRange, Data); + *DataSize = (ULONG)Irp->IoStatus.Information; + return Status; +} + +/* + @implemented +*/ +KSDDKAPI +NTSTATUS +NTAPI +KsPinDataIntersection( + IN PIRP Irp, + IN PKSP_PIN Pin, + OUT PVOID Data, + IN ULONG DescriptorsCount, + IN const KSPIN_DESCRIPTOR* Descriptor, + IN PFNKSINTERSECTHANDLER IntersectHandler) +{ + return KsPinDataIntersectionEx(Irp, + Pin, + Data, + DescriptorsCount, + Descriptor, + sizeof(KSPIN_DESCRIPTOR), + (PFNKSINTERSECTHANDLEREX)KspPinIntersectHandlerEx, + IntersectHandler); +} + /* @implemented */ diff --git a/drivers/ksfilter/ks/device.c b/drivers/ksfilter/ks/device.c index 5c3e528b3ca65..f9084310a3a91 100644 --- a/drivers/ksfilter/ks/device.c +++ b/drivers/ksfilter/ks/device.c @@ -554,11 +554,11 @@ IKsDevice_Power( /* TODO */ - Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; Irp->IoStatus.Information = 0; CompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; + return STATUS_NOT_IMPLEMENTED; } NTSTATUS diff --git a/drivers/ksfilter/ks/filter.c b/drivers/ksfilter/ks/filter.c index 7dc344680eea0..2ecbe813b80fe 100644 --- a/drivers/ksfilter/ks/filter.c +++ b/drivers/ksfilter/ks/filter.c @@ -774,7 +774,7 @@ KspHandlePropertyInstances( Instances->PossibleCount = This->Filter.Descriptor->PinDescriptors[Pin->PinId].InstancesPossible; /* current instance count */ Instances->CurrentCount = This->PinInstanceCount[Pin->PinId]; - + DPRINT1("CurrentCount %d, PossibleCount %d\n", Instances->CurrentCount, Instances->PossibleCount); IoStatus->Information = sizeof(KSPIN_CINSTANCES); IoStatus->Status = STATUS_SUCCESS; return STATUS_SUCCESS; diff --git a/drivers/ksfilter/ks/filterfactory.c b/drivers/ksfilter/ks/filterfactory.c index be907d8df9c00..4b7579411494e 100644 --- a/drivers/ksfilter/ks/filterfactory.c +++ b/drivers/ksfilter/ks/filterfactory.c @@ -721,6 +721,7 @@ KsFilterFactoryUpdateCacheData( if (!Found) { /* filter category is not present */ + DPRINT1("Failed to find filter category\n"); Status = STATUS_INVALID_PARAMETER; break; } diff --git a/drivers/ksfilter/ks/irp.c b/drivers/ksfilter/ks/irp.c index 01ee18c283273..b590e8a53fa10 100644 --- a/drivers/ksfilter/ks/irp.c +++ b/drivers/ksfilter/ks/irp.c @@ -656,6 +656,10 @@ KsStreamIo( IoStack = IoGetNextIrpStackLocation(Irp); /* setup stack parameters */ IoStack->FileObject = FileObject; + + 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); @@ -667,6 +671,7 @@ KsStreamIo( /* now call the driver */ Status = IoCallDriver(DeviceObject, Irp); + DPRINT1("Status 0x%lx\n", Status); /* done */ return Status; } @@ -834,6 +839,7 @@ KsProbeStreamIrp( if (StreamHeader->Size != HeaderSize && !(StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED)) { /* invalid stream header */ + DPRINT1("1\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } } @@ -843,6 +849,7 @@ KsProbeStreamIrp( if (StreamHeader->Size < sizeof(KSSTREAM_HEADER) || (StreamHeader->Size & 7)) { /* invalid stream header */ + DPRINT1("2\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } } @@ -850,6 +857,7 @@ KsProbeStreamIrp( if (Length < StreamHeader->Size) { /* length is too short */ + DPRINT1("3\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } @@ -858,6 +866,7 @@ KsProbeStreamIrp( if (StreamHeader->DataUsed > StreamHeader->FrameExtent) { /* frame extend can never be smaller */ + DPRINT1("4\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } @@ -867,6 +876,7 @@ KsProbeStreamIrp( if (Length != sizeof(KSSTREAM_HEADER) || (PVOID)StreamHeader != Irp->AssociatedIrp.SystemBuffer) { /* stream changed - must be send in a single packet */ + DPRINT1("5\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } @@ -897,6 +907,7 @@ KsProbeStreamIrp( if (StreamHeader->DataUsed) { /* DataUsed must be zero for stream read operation */ + DPRINT1("6\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } @@ -940,6 +951,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))) ) ) { @@ -1007,6 +1021,7 @@ KsProbeStreamIrp( if (StreamHeader->Size != HeaderSize && !(StreamHeader->OptionsFlags & KSSTREAM_HEADER_OPTIONSF_TYPECHANGED)) { /* invalid stream header */ + DPRINT1("7\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } } @@ -1016,6 +1031,7 @@ KsProbeStreamIrp( if (StreamHeader->Size < sizeof(KSSTREAM_HEADER) || (StreamHeader->Size & 7)) { /* invalid stream header */ + DPRINT1("8\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } } @@ -1023,6 +1039,7 @@ KsProbeStreamIrp( if (Length < StreamHeader->Size) { /* length is too short */ + DPRINT1("9\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } @@ -1031,6 +1048,7 @@ KsProbeStreamIrp( if (StreamHeader->DataUsed > StreamHeader->FrameExtent) { /* frame extend can never be smaller */ + DPRINT1("10\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } @@ -1040,6 +1058,7 @@ KsProbeStreamIrp( if (Length != sizeof(KSSTREAM_HEADER) || (PVOID)StreamHeader != Irp->AssociatedIrp.SystemBuffer) { /* stream changed - must be send in a single packet */ + DPRINT1("11\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } @@ -1071,6 +1090,7 @@ KsProbeStreamIrp( if (StreamHeader->DataUsed) { /* DataUsed must be zero for stream read operation */ + DPRINT1("13\n"); ExRaiseStatus(STATUS_INVALID_BUFFER_SIZE); } @@ -1099,6 +1119,7 @@ KsProbeStreamIrp( return Status; } + DPRINT1("14\n"); return STATUS_INVALID_BUFFER_SIZE; } @@ -1190,6 +1211,9 @@ KsDispatchInvalidDeviceRequest( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { + DPRINT1("KsDispatchInvalidDeviceRequest called: DeviceObject %p, Irp %p\n", + DeviceObject, Irp); + Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; CompleteRequest(Irp, IO_NO_INCREMENT); @@ -1209,6 +1233,9 @@ KsDefaultDeviceIoCompletion( PIO_STACK_LOCATION IoStack; NTSTATUS Status; + DPRINT1("KsDefaultDeviceIoCompletion called: DeviceObject %p, Irp %p\n", + DeviceObject, Irp); + /* get current irp stack */ IoStack = IoGetCurrentIrpStackLocation(Irp); @@ -1683,18 +1710,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 */ @@ -1898,7 +1913,7 @@ KspCreate( DeviceHeader = DeviceExtension->DeviceHeader; - if (IoStack->FileObject->FileName.Buffer == NULL) + if (IoStack->FileObject == NULL) { /* FIXME Pnp-Issue */ DPRINT("Using reference string hack\n"); @@ -2053,6 +2068,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/ksfilter/ks/pin.c b/drivers/ksfilter/ks/pin.c index b35caf76e852b..38486d93e4918 100644 --- a/drivers/ksfilter/ks/pin.c +++ b/drivers/ksfilter/ks/pin.c @@ -420,7 +420,7 @@ IKsPin_PinDataFormatPropertyHandler( /* get current irp stack */ IoStack = IoGetCurrentIrpStackLocation(Irp); - DPRINT("IKsPin_PinDataFormatPropertyHandler\n"); + DPRINT1("IKsPin_PinDataFormatPropertyHandler\n"); /* sanity check */ ASSERT(IoStack->FileObject); @@ -455,6 +455,7 @@ IKsPin_PinDataFormatPropertyHandler( if (This->Pin.Descriptor->Flags & KSPIN_FLAG_FIXED_FORMAT) { /* format cannot be changed */ + DPRINT1("3\n"); Status = STATUS_INVALID_DEVICE_REQUEST; } else @@ -473,7 +474,7 @@ IKsPin_PinDataFormatPropertyHandler( /* release processing mutex */ KeReleaseMutex(This->BasicHeader.ControlMutex, FALSE); - DPRINT("IKsPin_PinDataFormatPropertyHandler Status %lx\n", Status); + DPRINT1("IKsPin_PinDataFormatPropertyHandler Status %lx\n", Status); return Status; } diff --git a/drivers/ksfilter/ks/swenum.c b/drivers/ksfilter/ks/swenum.c index c4e05151f6d55..cc8a0b2c162b5 100644 --- a/drivers/ksfilter/ks/swenum.c +++ b/drivers/ksfilter/ks/swenum.c @@ -812,7 +812,7 @@ KspStartBusDevice( DPRINT1("KspStartBusDevice Name %S DeviceName %S Instance %S Started\n", Name, DeviceEntry->DeviceName, DeviceEntry->Instance); /* enable device classes */ - //KspEnableBusDeviceInterface(DeviceEntry, TRUE); + KspEnableBusDeviceInterface(DeviceEntry, TRUE); /* done */ return STATUS_SUCCESS; @@ -1227,7 +1227,7 @@ KspBusWorkerRoutine( Diff.QuadPart); /* deactivate interfaces */ - //KspEnableBusDeviceInterface(DeviceEntry, FALSE); + KspEnableBusDeviceInterface(DeviceEntry, FALSE); /* re-acquire lock */ KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); diff --git a/drivers/ksfilter/ks/topology.c b/drivers/ksfilter/ks/topology.c index 4a241209f2b36..aebb109bb46b3 100644 --- a/drivers/ksfilter/ks/topology.c +++ b/drivers/ksfilter/ks/topology.c @@ -105,7 +105,7 @@ KsValidateTopologyNodeCreateRequest( PKSNODE_CREATE NodeCreate; ULONG Size; NTSTATUS Status; - + DPRINT1("Topology %p\n", Topology); /* did the caller miss the topology */ if (!Topology) return STATUS_INVALID_PARAMETER; @@ -182,6 +182,7 @@ KsTopologyPropertyHandler( if (Node->NodeId >= Topology->TopologyNodesCount) { /* invalid node id */ + DPRINT1("Node->NodeId %d is out of range, Topology->TopologyNodesCount %d\n", Node->NodeId, Topology->TopologyNodesCount); Irp->IoStatus.Information = 0; Status = STATUS_INVALID_PARAMETER; break; 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/irpstream.cpp b/drivers/wdm/audio/backpln/portcls/irpstream.cpp index a79259fa0828d..5964318b5694c 100644 --- a/drivers/wdm/audio/backpln/portcls/irpstream.cpp +++ b/drivers/wdm/audio/backpln/portcls/irpstream.cpp @@ -194,11 +194,13 @@ CIrpQueue::AddMapping( if (m_Descriptor->DataFlow == KSPIN_DATAFLOW_IN) { // irp sink + DPRINT("Header->DataUsed %d\n", Header->DataUsed); HeaderLength = Header->DataUsed; } else { // irp source + DPRINT("Header->FrameExtent %d\n", Header->FrameExtent); HeaderLength = Header->FrameExtent; } @@ -300,10 +302,11 @@ CIrpQueue::GetMapping( PIRP Irp; ULONG Offset; PKSSTREAM_DATA StreamData; - + DPRINT("Irp %p\n", m_Irp); // check if there is an irp in the partially processed if (m_Irp) { + DPRINT("Irp->Cancel %x\n", m_Irp->Cancel); // use last irp if (m_Irp->Cancel == FALSE) { diff --git a/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp b/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp index 15495d2aeefb5..b6ff30900370f 100644 --- a/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp +++ b/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp @@ -587,11 +587,12 @@ PinWaveCyclicDataFormat( PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, KSDATAFORMAT_TYPE_AUDIO)); PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, KSDATAFORMAT_SUBTYPE_PCM)); PC_ASSERT(IsEqualGUIDAligned(((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)); +#endif DPRINT("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels, ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample, ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec); -#endif + } else @@ -1184,6 +1185,16 @@ CPortPinWaveCyclic::Init( if (!NT_SUCCESS(Status)) return Status; + /* HACK for MS sysaudio */ + /* For some reason it returns wrong PinId (2 instead of 0) + * and KSPIN_DATAFLOW_OUT DataFlow (which is used for WaveIn). + * While the actual source of problem isn't figured out yet, + * force this to correct data here. + */ + DPRINT("DataFlow %d PinId %d\n", KsPinDescriptor->DataFlow, ConnectDetails->PinId); + ConnectDetails->PinId = 0; + KsPinDescriptor->DataFlow = KSPIN_DATAFLOW_IN; + if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN) { Capture = FALSE; @@ -1223,7 +1234,7 @@ CPortPinWaveCyclic::Init( } #endif - DPRINT1("CPortPinWaveCyclic::Init Status %x PinId %u Capture %u\n", Status, ConnectDetails->PinId, Capture); + DPRINT1("CPortPinWaveCyclic::Init Status %x PinId %u Capture %u\n", Status, ConnectDetails->PinId, KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT); if (!NT_SUCCESS(Status)) return Status; diff --git a/drivers/wdm/audio/backpln/portcls/port_wavecyclic.cpp b/drivers/wdm/audio/backpln/portcls/port_wavecyclic.cpp index 04525ab53f8c7..f5245e065f09f 100644 --- a/drivers/wdm/audio/backpln/portcls/port_wavecyclic.cpp +++ b/drivers/wdm/audio/backpln/portcls/port_wavecyclic.cpp @@ -205,7 +205,7 @@ CPortWaveCyclic::Init( Status = UnknownMiniport->QueryInterface(IID_IMiniportWaveCyclic, (PVOID*)&Miniport); if (!NT_SUCCESS(Status)) { - DPRINT("IPortWaveCyclic_Init called with invalid IMiniport adapter\n"); + DPRINT1("IPortWaveCyclic_Init called with invalid IMiniport adapter\n"); return STATUS_INVALID_PARAMETER; } diff --git a/drivers/wdm/audio/backpln/portcls/propertyhandler.cpp b/drivers/wdm/audio/backpln/portcls/propertyhandler.cpp index 5aa07fcf998df..b6b6a99348295 100644 --- a/drivers/wdm/audio/backpln/portcls/propertyhandler.cpp +++ b/drivers/wdm/audio/backpln/portcls/propertyhandler.cpp @@ -33,7 +33,7 @@ HandlePropertyInstances( } Instances = (KSPIN_CINSTANCES*)Data; - + DPRINT1("PinId %d\n", Pin->PinId); // check if the miniport supports the IPinCount interface Status = SubDevice->PinCount(Pin->PinId, &FilterNecessary, &FilterCurrent, &FilterPossible, &GlobalCurrent, &GlobalPossible); @@ -59,7 +59,7 @@ HandlePropertyInstances( Instances->CurrentCount = Descriptor->Factory.Instances[Pin->PinId].CurrentPinInstanceCount; } - + DPRINT1("CurrentCount %d, PossibleCount %d\n", Instances->CurrentCount, Instances->PossibleCount); IoStatus->Information = sizeof(KSPIN_CINSTANCES); IoStatus->Status = STATUS_SUCCESS; return STATUS_SUCCESS; @@ -131,8 +131,9 @@ 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) { + ASSERT(Length); IoStatus->Information = Length; break; } diff --git a/drivers/wdm/audio/drivers/ac97/debug.h b/drivers/wdm/audio/drivers/ac97/debug.h index 78c5335c16dd9..f14e22f459d01 100644 --- a/drivers/wdm/audio/drivers/ac97/debug.h +++ b/drivers/wdm/audio/drivers/ac97/debug.h @@ -38,7 +38,7 @@ const int DBG_ALL = 0xFFFFFFFF; // The default statements that will print are warnings (DBG_WARNING) and // errors (DBG_ERROR). // -const int DBG_DEFAULT = 0x00000004; // Errors only. +const int DBG_DEFAULT = 0x00000002; // Errors only. // diff --git a/drivers/wdm/audio/drivers/ac97/miniport.cpp b/drivers/wdm/audio/drivers/ac97/miniport.cpp index 83bb53d9d3c2e..e5199b735db71 100644 --- a/drivers/wdm/audio/drivers/ac97/miniport.cpp +++ b/drivers/wdm/audio/drivers/ac97/miniport.cpp @@ -673,7 +673,10 @@ STDMETHODIMP_(NTSTATUS) CMiniport::DataRangeIntersection nMaxChannels--; // ... and also 0 channels wouldn't be a good request. if (!nMaxChannels) + { + DOUT (DBG_WARNING, ("[DataRangeIntersection] No valid channels found")); return STATUS_NO_MATCH; + } WaveFormat->Format.nChannels = (WORD)nMaxChannels; } @@ -704,6 +707,7 @@ STDMETHODIMP_(NTSTATUS) CMiniport::DataRangeIntersection if ((((PKSDATARANGE_AUDIO)ClientsDataRange)->MaximumSampleFrequency < ulFrequency) || (((PKSDATARANGE_AUDIO)ClientsDataRange)->MinimumSampleFrequency > ulFrequency)) { + DOUT (DBG_WARNING, ("[DataRangeIntersection] Invalid sample frequency")); return STATUS_NO_MATCH; } diff --git a/drivers/wdm/audio/drivers/ac97/mintopo.cpp b/drivers/wdm/audio/drivers/ac97/mintopo.cpp index f8f202958c222..3e0029f4410f3 100644 --- a/drivers/wdm/audio/drivers/ac97/mintopo.cpp +++ b/drivers/wdm/audio/drivers/ac97/mintopo.cpp @@ -735,7 +735,7 @@ NTSTATUS CAC97MiniportTopology::BuildPinDescriptors (void) CurrentPin->KsPinDescriptor.DataRangesCount = SIZEOF_ARRAY(PinDataRangePointersAnalogBridge); CurrentPin->KsPinDescriptor.DataRanges = PinDataRangePointersAnalogBridge; CurrentPin->KsPinDescriptor.DataFlow = KSPIN_DATAFLOW_IN; - CurrentPin->KsPinDescriptor.Communication = KSPIN_COMMUNICATION_NONE; + CurrentPin->KsPinDescriptor.Communication = KSPIN_COMMUNICATION_SINK; } // diff --git a/drivers/wdm/audio/filters/kmixer/CMakeLists.txt b/drivers/wdm/audio/filters/kmixer/CMakeLists.txt index 6d6b8fc55fb2a..5dfb252b9fcec 100644 --- a/drivers/wdm/audio/filters/kmixer/CMakeLists.txt +++ b/drivers/wdm/audio/filters/kmixer/CMakeLists.txt @@ -1,5 +1,6 @@ -include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/3rdparty/libsamplerate) +include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/3rdparty/libsamplerate + ${REACTOS_SOURCE_DIR}/sdk/lib/3rdparty/resampler) list(APPEND SOURCE kmixer.c diff --git a/drivers/wdm/audio/filters/kmixer/filter.c b/drivers/wdm/audio/filters/kmixer/filter.c index f2112b758b1d3..eb28138646169 100644 --- a/drivers/wdm/audio/filters/kmixer/filter.c +++ b/drivers/wdm/audio/filters/kmixer/filter.c @@ -109,16 +109,6 @@ DispatchCreateKMix( DPRINT("DispatchCreateKMix entered\n"); - /* check if the request was from usermode */ - if (Irp->RequestorMode == UserMode) - { - /* deny access from usermode */ - Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_INVALID_DEVICE_REQUEST; - } - /* get device extension */ DeviceExtension = (PKMIXER_DEVICE_EXT)DeviceObject->DeviceExtension; diff --git a/drivers/wdm/audio/filters/kmixer/kmixer.h b/drivers/wdm/audio/filters/kmixer/kmixer.h index 934158ed6d75f..93014250b371f 100644 --- a/drivers/wdm/audio/filters/kmixer/kmixer.h +++ b/drivers/wdm/audio/filters/kmixer/kmixer.h @@ -3,6 +3,7 @@ #include #include +#include typedef struct { diff --git a/drivers/wdm/audio/filters/kmixer/pin.c b/drivers/wdm/audio/filters/kmixer/pin.c index eb2196c358533..3d83ab1b4a2aa 100644 --- a/drivers/wdm/audio/filters/kmixer/pin.c +++ b/drivers/wdm/audio/filters/kmixer/pin.c @@ -10,11 +10,12 @@ #include -#define NDEBUG +#define YDEBUG #include const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; + NTSTATUS PerformSampleRateConversion( PUCHAR Buffer, @@ -130,15 +131,11 @@ PerformSampleRateConversion( } else if (BytesPerSample == 2) { - PUSHORT Res = (PUSHORT)ResultOut; - - src_float_to_short_array(FloatOut, (short*)Res, Data.output_frames_gen * NumChannels); + src_float_to_short_array(FloatOut, (short*)ResultOut, Data.output_frames_gen * NumChannels); } else if (BytesPerSample == 4) { - PULONG Res = (PULONG)ResultOut; - - src_float_to_int_array(FloatOut, (int*)Res, Data.output_frames_gen * NumChannels); + src_float_to_int_array(FloatOut, (int*)ResultOut, Data.output_frames_gen * NumChannels); } @@ -287,7 +284,7 @@ PerformQualityConversion( ASSERT(OldWidth != NewWidth); Samples = BufferLength / (OldWidth / 8); - //DPRINT("Samples %u BufferLength %u\n", Samples, BufferLength); + DPRINT("PerformQualityConversion Samples %u BufferLength %u\n", Samples, BufferLength); if (OldWidth == 8 && NewWidth == 16) { @@ -426,11 +423,11 @@ Pin_fnDeviceIoControl( { PIO_STACK_LOCATION IoStack; PKSP_PIN Property; - //DPRINT1("Pin_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject); + DPRINT("Pin_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject, Irp); IoStack = IoGetCurrentIrpStackLocation(Irp); - if (IoStack->Parameters.DeviceIoControl.InputBufferLength == sizeof(KSP_PIN) && IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(KSDATAFORMAT_WAVEFORMATEX)) + if (IoStack->Parameters.DeviceIoControl.InputBufferLength == sizeof(KSP_PIN) && IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(KSDATAFORMAT_WAVEFORMATEX)) { Property = (PKSP_PIN)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; @@ -451,6 +448,8 @@ Pin_fnDeviceIoControl( Formats[Property->PinId].WaveFormatEx.nChannels = WaveFormat->WaveFormatEx.nChannels; Formats[Property->PinId].WaveFormatEx.wBitsPerSample = WaveFormat->WaveFormatEx.wBitsPerSample; Formats[Property->PinId].WaveFormatEx.nSamplesPerSec = WaveFormat->WaveFormatEx.nSamplesPerSec; + Formats[Property->PinId].WaveFormatEx.nBlockAlign = (WaveFormat->WaveFormatEx.nChannels * WaveFormat->WaveFormatEx.wBitsPerSample) / 8; + Formats[Property->PinId].WaveFormatEx.nAvgBytesPerSec = WaveFormat->WaveFormatEx.nSamplesPerSec * (WaveFormat->WaveFormatEx.nChannels * WaveFormat->WaveFormatEx.wBitsPerSample / 8); Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_SUCCESS; @@ -486,12 +485,98 @@ Pin_fnWrite( PDEVICE_OBJECT DeviceObject, PIRP Irp) { - UNIMPLEMENTED; + PIO_STACK_LOCATION IoStack; + PKSSTREAM_HEADER StreamHeader; + PVOID BufferOut, BufferOutTemp; + ULONG BufferLength, BufferLengthTemp; + NTSTATUS Status = STATUS_SUCCESS; + PKSDATAFORMAT_WAVEFORMATEX Formats; + PKSDATAFORMAT_WAVEFORMATEX InputFormat, OutputFormat; - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_SUCCESS; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_SUCCESS; + DPRINT("Pin_fnWrite called DeviceObject %p Irp %p\n", DeviceObject, Irp); + + IoStack = IoGetCurrentIrpStackLocation(Irp); + + Formats = (PKSDATAFORMAT_WAVEFORMATEX)IoStack->FileObject->FsContext2; + + InputFormat = Formats; + OutputFormat = (Formats + 1); + + Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMWRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, sizeof(KSSTREAM_HEADER)); + if (!NT_SUCCESS(Status)) + { + DPRINT1("KsProbeStreamIrp failed with Status 0x%lx Cancel %u\n", Status, Irp->Cancel); + return Status; + } + + StreamHeader = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer; + + BufferOut = StreamHeader->Data; + BufferLength = StreamHeader->DataUsed; + + DPRINT("\n Old Channels %u Num Channels %u\n Old SampleRate %u SampleRate %u\n Old BitsPerSample %u BitsPerSample %u\n", + InputFormat->WaveFormatEx.nChannels, OutputFormat->WaveFormatEx.nChannels, + InputFormat->WaveFormatEx.nSamplesPerSec, OutputFormat->WaveFormatEx.nSamplesPerSec, + InputFormat->WaveFormatEx.wBitsPerSample, OutputFormat->WaveFormatEx.wBitsPerSample); + + if (InputFormat->WaveFormatEx.wBitsPerSample != OutputFormat->WaveFormatEx.wBitsPerSample) + { + Status = PerformQualityConversion(StreamHeader->Data, + StreamHeader->DataUsed, + InputFormat->WaveFormatEx.wBitsPerSample, + OutputFormat->WaveFormatEx.wBitsPerSample, + &BufferOut, + &BufferLength); + if (NT_SUCCESS(Status)) + { + StreamHeader->Data = BufferOut; + StreamHeader->DataUsed = BufferLength; + } + } + + if (InputFormat->WaveFormatEx.nChannels != OutputFormat->WaveFormatEx.nChannels) + { + Status = PerformChannelConversion(BufferOut, + BufferLength, + InputFormat->WaveFormatEx.nChannels, + OutputFormat->WaveFormatEx.nChannels, + OutputFormat->WaveFormatEx.wBitsPerSample, + &BufferOutTemp, + &BufferLengthTemp); + + BufferOut = BufferOutTemp; + BufferLength = BufferLengthTemp; + + if (NT_SUCCESS(Status)) + { + StreamHeader->Data = BufferOut; + StreamHeader->DataUsed = BufferLength; + } + } + + if (InputFormat->WaveFormatEx.nSamplesPerSec != OutputFormat->WaveFormatEx.nSamplesPerSec) + { + Status = PerformSampleRateConversion(BufferOut, + BufferLength, + InputFormat->WaveFormatEx.nSamplesPerSec, + OutputFormat->WaveFormatEx.nSamplesPerSec, + OutputFormat->WaveFormatEx.wBitsPerSample / 8, + OutputFormat->WaveFormatEx.nChannels, + &BufferOutTemp, + &BufferLengthTemp); + + BufferOut = BufferOutTemp; + BufferLength = BufferLengthTemp; + + if (NT_SUCCESS(Status)) + { + StreamHeader->Data = BufferOut; + StreamHeader->DataUsed = BufferLength; + } + } + + Irp->IoStatus.Status = Status; + return Status; } NTSTATUS @@ -565,8 +650,6 @@ Pin_fnFastDeviceIoControl( PDEVICE_OBJECT DeviceObject) { UNIMPLEMENTED; - - return FALSE; } @@ -600,85 +683,8 @@ Pin_fnFastWrite( PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) { - PKSSTREAM_HEADER StreamHeader; - PVOID BufferOut; - ULONG BufferLength; - NTSTATUS Status = STATUS_SUCCESS; - PKSDATAFORMAT_WAVEFORMATEX Formats; - PKSDATAFORMAT_WAVEFORMATEX InputFormat, OutputFormat; - - DPRINT("Pin_fnFastWrite called DeviceObject %p Irp %p\n", DeviceObject); - - Formats = (PKSDATAFORMAT_WAVEFORMATEX)FileObject->FsContext2; - - InputFormat = Formats; - OutputFormat = (Formats + 1); - StreamHeader = (PKSSTREAM_HEADER)Buffer; - - - DPRINT("Num Channels %u Old Channels %u\n SampleRate %u Old SampleRate %u\n BitsPerSample %u Old BitsPerSample %u\n", - InputFormat->WaveFormatEx.nChannels, OutputFormat->WaveFormatEx.nChannels, - InputFormat->WaveFormatEx.nSamplesPerSec, OutputFormat->WaveFormatEx.nSamplesPerSec, - InputFormat->WaveFormatEx.wBitsPerSample, OutputFormat->WaveFormatEx.wBitsPerSample); - - if (InputFormat->WaveFormatEx.wBitsPerSample != OutputFormat->WaveFormatEx.wBitsPerSample) - { - Status = PerformQualityConversion(StreamHeader->Data, - StreamHeader->DataUsed, - InputFormat->WaveFormatEx.wBitsPerSample, - OutputFormat->WaveFormatEx.wBitsPerSample, - &BufferOut, - &BufferLength); - if (NT_SUCCESS(Status)) - { - ExFreePool(StreamHeader->Data); - StreamHeader->Data = BufferOut; - StreamHeader->DataUsed = BufferLength; - } - } - - if (InputFormat->WaveFormatEx.nChannels != OutputFormat->WaveFormatEx.nChannels) - { - Status = PerformChannelConversion(StreamHeader->Data, - StreamHeader->DataUsed, - InputFormat->WaveFormatEx.nChannels, - OutputFormat->WaveFormatEx.nChannels, - OutputFormat->WaveFormatEx.wBitsPerSample, - &BufferOut, - &BufferLength); - - if (NT_SUCCESS(Status)) - { - ExFreePool(StreamHeader->Data); - StreamHeader->Data = BufferOut; - StreamHeader->DataUsed = BufferLength; - } - } - - if (InputFormat->WaveFormatEx.nSamplesPerSec != OutputFormat->WaveFormatEx.nSamplesPerSec) - { - Status = PerformSampleRateConversion(StreamHeader->Data, - StreamHeader->DataUsed, - InputFormat->WaveFormatEx.nSamplesPerSec, - OutputFormat->WaveFormatEx.nSamplesPerSec, - OutputFormat->WaveFormatEx.wBitsPerSample / 8, - OutputFormat->WaveFormatEx.nChannels, - &BufferOut, - &BufferLength); - if (NT_SUCCESS(Status)) - { - ExFreePool(StreamHeader->Data); - StreamHeader->Data = BufferOut; - StreamHeader->DataUsed = BufferLength; - } - } - - IoStatus->Status = Status; - - if (NT_SUCCESS(Status)) - return TRUE; - else - return FALSE; + UNIMPLEMENTED; + return FALSE; } static KSDISPATCH_TABLE PinTable = diff --git a/drivers/wdm/audio/legacy/wdmaud/CMakeLists.txt b/drivers/wdm/audio/legacy/wdmaud/CMakeLists.txt index c088ebf6460f4..a5ff17c43dfbb 100644 --- a/drivers/wdm/audio/legacy/wdmaud/CMakeLists.txt +++ b/drivers/wdm/audio/legacy/wdmaud/CMakeLists.txt @@ -15,7 +15,7 @@ list(APPEND SOURCE add_library(wdmaud MODULE ${SOURCE} wdmaud.rc) set_module_type(wdmaud kernelmodedriver) -target_link_libraries(wdmaud mmixer libcntpr) +target_link_libraries(wdmaud mmixer libcntpr ${PSEH_LIB}) add_pch(wdmaud wdmaud.h SOURCE) add_importlibs(wdmaud ntoskrnl ks hal) add_cd_file(TARGET wdmaud DESTINATION reactos/system32/drivers FOR all) diff --git a/drivers/wdm/audio/legacy/wdmaud/control.c b/drivers/wdm/audio/legacy/wdmaud/control.c index 5aecad326d086..2b857ab46292e 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,28 @@ 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_RUN, FALSE); + } - return SetIrpIoStatus(Irp, STATUS_NOT_SUPPORTED, sizeof(WDMAUD_DEVICE_INFO)); + return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); } NTSTATUS @@ -72,48 +106,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 +128,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 +152,20 @@ WdmAudIoctlClose( { ULONG Index; + if (DeviceInfo->DeviceType != MIXER_DEVICE_TYPE) + { + /* Stop audio device before closing */ + WdmAudSetDeviceState(DeviceObject, Irp, DeviceInfo, KSSTATE_STOP, 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 +174,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 +223,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,104 +240,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: - return WdmAudGetPosition(DeviceObject, Irp, DeviceInfo); - 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) @@ -389,31 +297,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); @@ -423,12 +329,6 @@ IoCompletion ( Irp->IoStatus.Information = 0; } - /* dereference file object */ - ObDereferenceObject(Context->FileObject); - - /* free context */ - FreeItem(Context); - return STATUS_SUCCESS; } @@ -438,58 +338,101 @@ WdmAudReadWrite( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - NTSTATUS Status; + PWDMAUD_COMPLETION_CONTEXT Context; PWDMAUD_DEVICE_INFO DeviceInfo; + PWDMAUD_CLIENT ClientInfo; + PKSSTREAM_HEADER StreamHeader; PFILE_OBJECT FileObject; PIO_STACK_LOCATION IoStack; + PWAVEHDR WaveHeader; + NTSTATUS Status; ULONG Length; + ULONG PinId; PMDL Mdl; - BOOLEAN Read = TRUE; - PWDMAUD_COMPLETION_CONTEXT Context; - /* allocate completion context */ - Context = AllocateItem(NonPagedPool, sizeof(WDMAUD_COMPLETION_CONTEXT)); + /* get device info */ + DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer; + ASSERT(DeviceInfo); - if (!Context) + /* Get wave header passed by the caller */ + WaveHeader = (PWAVEHDR)DeviceInfo->Buffer; + ASSERT(WaveHeader); + + /* 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 */ - Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - /* done */ return STATUS_INSUFFICIENT_RESOURCES; } - /* get current irp stack location */ - IoStack = IoGetCurrentIrpStackLocation(Irp); + 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; + } - /* store the input buffer in UserBuffer - as KsProbeStreamIrp operates on IRP_MJ_DEVICE_CONTROL */ - Irp->UserBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress); + /* store the input buffer in SystemBuffer - as KsProbeStreamIrp operates on IRP_MJ_DEVICE_CONTROL */ + Irp->AssociatedIrp.SystemBuffer = StreamHeader; /* sanity check */ - ASSERT(Irp->UserBuffer); + ASSERT(Irp->AssociatedIrp.SystemBuffer); /* get the length of the request length */ - Length = IoStack->Parameters.Write.Length; + Length = StreamHeader->Size; /* store outputbuffer length */ IoStack->Parameters.DeviceIoControl.OutputBufferLength = Length; + /* allocate completion context */ + Context = AllocateItem(NonPagedPool, sizeof(WDMAUD_COMPLETION_CONTEXT)); + + if (!Context) + { + /* not enough memory */ + FreeItem(StreamHeader); + return STATUS_INSUFFICIENT_RESOURCES; + } + /* 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_IN_DEVICE_TYPE ? IOCTL_KS_READ_STREAM : IOCTL_KS_WRITE_STREAM; Context->Mdl = Irp->MdlAddress; /* store mdl address */ Mdl = Irp->MdlAddress; - /* remove mdladdress as KsProbeStreamIrp will interpret it as an already probed audio buffer */ + /* clear mdl address */ Irp->MdlAddress = NULL; - if (IoStack->MajorFunction == IRP_MJ_WRITE) + if (DeviceInfo->DeviceType == WAVE_OUT_DEVICE_TYPE) { /* probe the write stream irp */ - Read = FALSE; Status = KsProbeStreamIrp(Irp, KSPROBE_STREAMWRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK, Length); } else @@ -500,23 +443,10 @@ WdmAudReadWrite( if (!NT_SUCCESS(Status)) { - DPRINT1("KsProbeStreamIrp failed with Status %x Cancel %u\n", Status, Irp->Cancel); - Irp->MdlAddress = Mdl; - FreeItem(Context); - return SetIrpIoStatus(Irp, Status, 0); - } - - /* get device info */ - DeviceInfo = (PWDMAUD_DEVICE_INFO)Irp->AssociatedIrp.SystemBuffer; - ASSERT(DeviceInfo); - - /* 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); + DPRINT1("KsProbeStreamIrp failed with Status 0x%lx Cancel %u\n", Status, Irp->Cancel); Irp->MdlAddress = Mdl; FreeItem(Context); + FreeItem(StreamHeader); return SetIrpIoStatus(Irp, Status, 0); } @@ -531,14 +461,101 @@ WdmAudReadWrite( /* 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); + IoStack->MajorFunction = IRP_MJ_DEVICE_CONTROL; + IoStack->Parameters.DeviceIoControl.OutputBufferLength = Length; + 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); - /* mark irp as pending */ -// IoMarkIrpPending(Irp); /* call the driver */ - Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp); - return Status; + IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp); + + /* done */ + return STATUS_PENDING; +} + +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"); + DPRINT("IOCTL 0x%lx\n", IoStack->Parameters.DeviceIoControl.IoControlCode); + + 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: + 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: + 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 WdmAudReadWrite(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..3d8a08f5388a9 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,85 @@ 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) +WdmAudOpenSysAudioDevices( + IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) { - DEVICE_INTERFACE_CHANGE_NOTIFICATION * Event = (DEVICE_INTERFACE_CHANGE_NOTIFICATION*)NotificationStructure; - - DPRINT1("DeviceInterfaceChangeCallback called %p\n", Event); - DbgBreakPoint(); - return STATUS_SUCCESS; -} + NTSTATUS Status = STATUS_SUCCESS; + LPWSTR SymbolicLinkList, SymbolicLink; + HANDLE hSysAudio; + PFILE_OBJECT FileObject; -NTSTATUS -WdmAudOpenSysAudioDeviceInterfaces( - IN PWDMAUD_DEVICE_EXTENSION DeviceExtension, - IN LPWSTR SymbolicLinkList) -{ - SYSAUDIO_ENTRY * Entry; - ULONG Length; + Status = IoGetDeviceInterfaces(&KSCATEGORY_SYSAUDIO, + NULL, + 0, + &SymbolicLinkList); - DPRINT1("WdmAudOpenSysAudioDeviceInterfaces called\n"); + if (!NT_SUCCESS(Status)) + { + return Status; + } - while(*SymbolicLinkList) + for (SymbolicLink = SymbolicLinkList; + *SymbolicLink != UNICODE_NULL; + SymbolicLink += wcslen(SymbolicLink) + 1) { - Length = wcslen(SymbolicLinkList) + 1; - Entry = (SYSAUDIO_ENTRY*)AllocateItem(NonPagedPool, sizeof(SYSAUDIO_ENTRY) + Length * sizeof(WCHAR)); - if (!Entry) + DPRINT("Opening device %S\n", SymbolicLink); + Status = WdmAudOpenSysAudioDevice(SymbolicLink, &hSysAudio); + if (NT_SUCCESS(Status)) { - return STATUS_INSUFFICIENT_RESOURCES; + DPRINT("Successfully opened %S, handle %p\n", SymbolicLink, hSysAudio); + break; } + } - 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); + if (!hSysAudio) + { + DPRINT1("Failed to find sysaudio devices 0x%lx\n", Status); + FreeItem(SymbolicLinkList); + return Status; + } - DeviceExtension->NumSysAudioDevices++; - SymbolicLinkList += Length; + /* 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 0x%lx\n", Status); + FreeItem(SymbolicLinkList); + return Status; } + + DeviceExtension->hSysAudio = hSysAudio; + DeviceExtension->FileObject = FileObject; + return STATUS_SUCCESS; } - NTSTATUS -WdmAudOpenSysAudioDevices( - IN PDEVICE_OBJECT DeviceObject, - IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) +GetSysAudioDeviceInterface( + OUT LPWSTR* SymbolicLinkList) { - NTSTATUS Status = STATUS_SUCCESS; - LPWSTR SymbolicLinkList; - SYSAUDIO_ENTRY * Entry; - ULONG Length; - 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)) - { - WdmAudOpenSysAudioDeviceInterfaces(DeviceExtension, SymbolicLinkList); - FreeItem(SymbolicLinkList); - } - + NTSTATUS Status; - Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, - PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, - (PVOID)&KSCATEGORY_SYSAUDIO, - DeviceObject->DriverObject, - DeviceInterfaceChangeCallback, - (PVOID)DeviceExtension, - &DeviceExtension->SysAudioNotification); - } - else + /* 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 +134,6 @@ WdmAudRegisterDeviceInterface( { IoSetDeviceInterfaceState(&SymbolicLinkName, TRUE); RtlFreeUnicodeString(&SymbolicLinkName); - //DeviceExtension->DeviceInterfaceSupport = TRUE; return Status; } @@ -203,7 +141,7 @@ WdmAudRegisterDeviceInterface( } NTSTATUS -WdmAudOpenSysaudio( +WdmAudAllocateContext( IN PDEVICE_OBJECT DeviceObject, IN PWDMAUD_CLIENT *pClient) { @@ -213,15 +151,6 @@ WdmAudOpenSysaudio( /* get device extension */ DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - if (!DeviceExtension->NumSysAudioDevices) - { - /* wdmaud failed to open sysaudio */ - 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..8bfee991d84b3 100644 --- a/drivers/wdm/audio/legacy/wdmaud/entry.c +++ b/drivers/wdm/audio/legacy/wdmaud/entry.c @@ -9,7 +9,7 @@ #include "wdmaud.h" -#define NDEBUG +#define YDEBUG #include const GUID KSCATEGORY_SYSAUDIO = {0xA7C7A5B1L, 0x5AF3, 0x11D1, {0x9C, 0xED, 0x00, 0xA0, 0x24, 0xBF, 0x04, 0x07}}; @@ -26,16 +26,15 @@ WdmAudInitWorkerRoutine( { NTSTATUS Status; PWDMAUD_DEVICE_EXTENSION DeviceExtension; - ULONG DeviceCount; + ULONG DeviceIndex; /* get device extension */ DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - if (DeviceExtension->FileObject == NULL) { /* find available sysaudio devices */ - Status = WdmAudOpenSysAudioDevices(DeviceObject, DeviceExtension); + Status = WdmAudOpenSysAudioDevices(DeviceExtension); if (!NT_SUCCESS(Status)) { DPRINT1("WdmAudOpenSysAudioDevices failed with %x\n", Status); @@ -43,21 +42,25 @@ WdmAudInitWorkerRoutine( } } - /* get device count */ - DeviceCount = GetSysAudioDeviceCount(DeviceObject); + DeviceExtension->SysAudioDeviceCount = GetSysAudioDeviceCount(DeviceObject); - DPRINT("WdmAudInitWorkerRoutine SysAudioDeviceCount %ld\n", DeviceCount); + DPRINT("WdmAudInitWorkerRoutine SysAudioDeviceCount %ld\n", DeviceExtension->SysAudioDeviceCount); - /* was a device added / removed */ - if (DeviceCount != DeviceExtension->SysAudioDeviceCount) - { - /* init mmixer library */ - Status = WdmAudMixerInitialize(DeviceObject); - DPRINT("WdmAudMixerInitialize Status %x WaveIn %lu WaveOut %lu Mixer %lu\n", Status, WdmAudGetWaveInDeviceCount(), WdmAudGetWaveOutDeviceCount(), WdmAudGetMixerDeviceCount()); + /* init mmixer library */ + Status = WdmAudMixerInitialize(DeviceObject); + DPRINT("WdmAudMixerInitialize Status %x WaveIn %lu WaveOut %lu Mixer %lu\n", Status, WdmAudGetWaveInDeviceCount(), WdmAudGetWaveOutDeviceCount(), WdmAudGetMixerDeviceCount()); - /* store sysaudio device count */ - DeviceExtension->SysAudioDeviceCount = DeviceCount; + /* set index for all device instances */ + for (DeviceIndex = 0; DeviceIndex < DeviceExtension->SysAudioDeviceCount; DeviceIndex++) + { + Status = SetSysAudioDeviceInstance(DeviceExtension, DeviceIndex); + if (!NT_SUCCESS(Status)) + { + /* failed, move to the next instance */ + DPRINT1("Failed to set device index, skipping...\n"); + continue; + } } /* signal completion */ @@ -133,9 +136,6 @@ WdmaudAddDevice( return Status; } - /* initialize sysaudio device list */ - InitializeListHead(&DeviceExtension->SysAudioDeviceList); - /* initialize client context device list */ InitializeListHead(&DeviceExtension->WdmAudClientList); @@ -165,7 +165,7 @@ WdmaudAddDevice( /* start the timer */ IoStartTimer(DeviceObject); - DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE; + DeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE; DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING; return STATUS_SUCCESS; @@ -191,6 +191,8 @@ WdmAudPnp( IrpStack = IoGetCurrentIrpStackLocation(Irp); + DPRINT("MinorFunction 0x%x\n", IrpStack->MinorFunction); + if (IrpStack->MinorFunction == IRP_MN_QUERY_PNP_DEVICE_STATE) { Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE; @@ -214,12 +216,26 @@ WdmAudCreate( /* get device extension */ DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; -#if KS_IMPLEMENTED - Status = KsReferenceSoftwareBusObject((KSDEVICE_HEADER)DeviceObject->DeviceExtension); + Status = KsReferenceSoftwareBusObject(DeviceExtension->DeviceHeader); if (!NT_SUCCESS(Status)) { DPRINT1("KsReferenceSoftwareBusObject failed with %x\n", Status); - return Status; + return SetIrpIoStatus(Irp, Status, 0); + } + +#if 0 + /* register pnp notification */ + Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, + PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, + (PVOID)&KSCATEGORY_SYSAUDIO, + DeviceObject->DriverObject, + DeviceInterfaceChangeCallback, + (PVOID)DeviceExtension, + &DeviceExtension->SysAudioNotification); + if (!NT_SUCCESS(Status)) + { + DPRINT1("IoRegisterPlugPlayNotification failed with %x\n", Status); + return SetIrpIoStatus(Irp, Status, 0); } #endif @@ -229,17 +245,12 @@ 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; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - /* done */ - return STATUS_UNSUCCESSFUL; + return SetIrpIoStatus(Irp, Status, 0); } IoStack = IoGetCurrentIrpStackLocation(Irp); @@ -249,11 +260,7 @@ WdmAudCreate( IoStack->FileObject->FsContext = pClient; Status = STATUS_SUCCESS; - Irp->IoStatus.Status = Status; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return Status; + return SetIrpIoStatus(Irp, Status, 0); } NTSTATUS @@ -262,10 +269,14 @@ WdmAudClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - /* nothing to do complete request */ -#if KS_IMPLEMENTED - Status = KsDereferenceSoftwareBusObject(DeviceExtension->DeviceHeader); + PWDMAUD_DEVICE_EXTENSION DeviceExtension; + + /* get device extension */ + DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + KsDereferenceSoftwareBusObject(DeviceExtension->DeviceHeader); +#if 0 if (NT_SUCCESS(Status)) { if (DeviceExtension->SysAudioNotification) @@ -273,12 +284,8 @@ WdmAudClose( } #endif - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - /* done */ - return STATUS_SUCCESS; + return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0); } NTSTATUS @@ -324,7 +331,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..df74c825fac67 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 bDone; // Verified to match Windows XP/2003, indicated whether the streaming is completed. + BOOL bReset; // Verified to match Windows XP/2003, indicates whether the streaming is starting to be reset. + BOOL bStart; // Verified to match Windows XP/2003, indicates whether the streaming is started. + BOOL bStartInThread; // Verified to match Windows XP/2003, indicates whether the streaming 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 1c7b9a5cf141f..ff2656bf4f4c1 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; } @@ -328,54 +329,6 @@ FreeEventData(IN PVOID EventData) FreeItem(Data); } -VOID -CALLBACK -EventCallback( - IN PVOID MixerEventContext, - IN HANDLE hMixer, - IN ULONG NotificationType, - IN ULONG Value) -{ - PWDMAUD_CLIENT ClientInfo; - PEVENT_ENTRY Entry; - ULONG Index; - - /* get client context */ - ClientInfo = (PWDMAUD_CLIENT)MixerEventContext; - - /* now search for the mixer which originated the request */ - for(Index = 0; Index < ClientInfo->NumPins; Index++) - { - if (ClientInfo->hPins[Index].Handle == hMixer && ClientInfo->hPins[Index].Type == MIXER_DEVICE_TYPE) - { - if (ClientInfo->hPins[Index].NotifyEvent) - { - /* allocate event entry */ - Entry = AllocateItem(NonPagedPool, sizeof(EVENT_ENTRY)); - if (!Entry) - { - /* no memory */ - break; - } - - /* setup event entry */ - Entry->NotificationType = NotificationType; - Entry->Value = Value; - Entry->hMixer = hMixer; - - /* insert entry */ - InsertTailList(&ClientInfo->MixerEventList, &Entry->Entry); - - /* now notify the client */ - KeSetEvent(ClientInfo->hPins[Index].NotifyEvent, 0, FALSE); - } - /* done */ - break; - } - } -} - - NTSTATUS WdmAudMixerInitialize( IN PDEVICE_OBJECT DeviceObject) @@ -389,22 +342,28 @@ 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) - return STATUS_SUCCESS; + MIXER_STATUS Status; + + Status = MMixerGetCapabilities(&MixerContext, DeviceInfo->DeviceIndex, (LPMIXERCAPSW)DeviceInfo->Buffer); - return STATUS_INVALID_PARAMETER; + if (Status == MM_STATUS_SUCCESS) + return STATUS_SUCCESS; + else + return STATUS_UNSUCCESSFUL; } NTSTATUS @@ -414,36 +373,16 @@ 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, &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); + return STATUS_UNSUCCESSFUL; } - Handles = AllocateItem(NonPagedPool, sizeof(WDMAUD_HANDLE) * (ClientInfo->NumPins+1)); if (Handles) @@ -455,20 +394,15 @@ WdmAudControlOpenMixer( } ClientInfo->hPins = Handles; - ClientInfo->hPins[ClientInfo->NumPins].Handle = hMixer; + ClientInfo->hPins[ClientInfo->NumPins].Handle = DeviceInfo->hDevice; ClientInfo->hPins[ClientInfo->NumPins].Type = MIXER_DEVICE_TYPE; - ClientInfo->hPins[ClientInfo->NumPins].NotifyEvent = EventObject; + ClientInfo->hPins[ClientInfo->NumPins].NotifyEvent = NULL; ClientInfo->NumPins++; } else - { - ObDereferenceObject(EventObject); - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); - } - - DeviceInfo->hDevice = hMixer; + return STATUS_UNSUCCESSFUL; - return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + return STATUS_SUCCESS; } NTSTATUS @@ -480,19 +414,12 @@ WdmAudControlCloseMixer( IN ULONG Index) { /* Remove event associated to this client */ - if (MMixerClose(&MixerContext, DeviceInfo->DeviceIndex, ClientInfo, EventCallback) != MM_STATUS_SUCCESS) + if (MMixerClose(&MixerContext, DeviceInfo->DeviceIndex) != MM_STATUS_SUCCESS) { DPRINT1("Failed to close mixer\n"); return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); } - /* Dereference event */ - if (ClientInfo->hPins[Index].NotifyEvent) - { - ObDereferenceObject(ClientInfo->hPins[Index].NotifyEvent); - ClientInfo->hPins[Index].NotifyEvent = NULL; - } - /* FIXME: do we need to free ClientInfo->hPins ? */ return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); } @@ -503,26 +430,16 @@ 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) + if (MMixerClose(&MixerContext, DeviceIndex) != MM_STATUS_SUCCESS) { DPRINT1("Failed to close mixer for device %lu\n", DeviceIndex); } } - - /* Dereference event */ - if (ClientInfo->hPins[Index].NotifyEvent) - { - ObDereferenceObject(ClientInfo->hPins[Index].NotifyEvent); - ClientInfo->hPins[Index].NotifyEvent = NULL; - } } NTSTATUS @@ -539,7 +456,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 +478,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 +500,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 +524,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 +554,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 +637,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 +647,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 +674,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) @@ -777,21 +696,16 @@ WdmAudGetPosition( _In_ PWDMAUD_DEVICE_INFO DeviceInfo) { MIXER_STATUS Status; - ULONG Position; /* Get position */ - Status = MMixerGetWavePosition(&MixerContext, DeviceInfo->hDevice, &Position); + Status = MMixerGetWavePosition(&MixerContext, DeviceInfo->hDevice, (PULONG)DeviceInfo->Buffer); if (Status == MM_STATUS_SUCCESS) - { - DeviceInfo->u.Position = (ULONGLONG)Position; return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); - } else return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(WDMAUD_DEVICE_INFO)); } - MIXER_STATUS CreatePinCallback( IN PVOID Ctx, @@ -802,40 +716,59 @@ CreatePinCallback( IN ACCESS_MASK DesiredAccess, OUT PHANDLE PinHandle) { - ULONG BytesReturned; - SYSAUDIO_INSTANCE_INFO InstanceInfo; 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; - - /* attach to virtual device */ - Status = KsSynchronousIoControlDevice(Context->DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&InstanceInfo, sizeof(SYSAUDIO_INSTANCE_INFO), NULL, 0, &BytesReturned); + /* find available sysaudio devices */ + Status = WdmAudOpenSysAudioDevices(Context->DeviceExtension); + if (!NT_SUCCESS(Status)) + { + DPRINT1("WdmAudOpenSysAudioDevices failed with 0x%lx\n", Status); + return MM_STATUS_UNSUCCESSFUL; + } + /* set current device instance */ + Status = SetSysAudioDeviceInstance(Context->DeviceExtension, VirtualDeviceId); 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; } @@ -857,12 +790,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 @@ -882,7 +815,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 496eabf56e288..6e40a43086fea 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' @@ -55,6 +55,32 @@ GetSysAudioDeviceCount( return Count; } +NTSTATUS +SetSysAudioDeviceInstance( + IN PWDMAUD_DEVICE_EXTENSION DeviceExtension, + IN ULONG VirtualDeviceId) +{ + NTSTATUS Status; + KSPROPERTY Property; + ULONG BytesReturned; + + /* setup property request */ + Property.Set = KSPROPSETID_Sysaudio; + Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_INSTANCE; + Property.Flags = KSPROPERTY_TYPE_SET; + + /* attach to virtual device */ + Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, + KernelMode, + IOCTL_KS_PROPERTY, + (PVOID)&Property, + sizeof(KSPROPERTY), + (PVOID)&VirtualDeviceId, + sizeof(ULONG), + &BytesReturned); + return Status; +} + NTSTATUS SetIrpIoStatus( IN PIRP Irp, @@ -64,12 +90,11 @@ SetIrpIoStatus( Irp->IoStatus.Information = Length; Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; } ULONG -ClosePin( +ClosePinByIndex( IN PWDMAUD_CLIENT ClientInfo, IN ULONG FilterId, IN ULONG PinId, @@ -77,15 +102,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; } } @@ -99,37 +155,33 @@ InsertPinHandle( IN ULONG PinId, IN SOUND_DEVICE_TYPE DeviceType, IN HANDLE PinHandle, + IN PFILE_OBJECT PinFileObject, IN ULONG FreeIndex) { - PWDMAUD_HANDLE Handles; - if (FreeIndex != MAXULONG) { /* 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; } - Handles = AllocateItem(NonPagedPool, sizeof(WDMAUD_HANDLE) * (ClientInfo->NumPins+1)); + ClientInfo->hPins = AllocateItem(NonPagedPool, sizeof(WDMAUD_HANDLE) * (ClientInfo->NumPins+1)); - if (!Handles) + if (!ClientInfo->hPins) return STATUS_INSUFFICIENT_RESOURCES; - if (ClientInfo->NumPins) - { - RtlMoveMemory(Handles, ClientInfo->hPins, sizeof(WDMAUD_HANDLE) * ClientInfo->NumPins); - FreeItem(ClientInfo->hPins); - } - - 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; @@ -353,9 +405,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; @@ -363,14 +417,12 @@ 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); /* check if the request failed */ - if (Status != STATUS_BUFFER_TOO_SMALL || BytesReturned == 0) - return STATUS_UNSUCCESSFUL; + if (Status != STATUS_BUFFER_OVERFLOW || BytesReturned == 0) + return Status; /* allocate buffer for the device */ *Device = AllocateItem(NonPagedPool, BytesReturned); diff --git a/drivers/wdm/audio/legacy/wdmaud/wdmaud.h b/drivers/wdm/audio/legacy/wdmaud/wdmaud.h index 12588f0a2a56d..5dc0765128a8c 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,12 @@ 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 +70,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, @@ -95,11 +77,10 @@ WdmAudRegisterDeviceInterface( NTSTATUS WdmAudOpenSysAudioDevices( - IN PDEVICE_OBJECT DeviceObject, IN PWDMAUD_DEVICE_EXTENSION DeviceExtension); NTSTATUS -WdmAudOpenSysaudio( +WdmAudAllocateContext( IN PDEVICE_OBJECT DeviceObject, IN PWDMAUD_CLIENT *pClient); @@ -115,12 +96,6 @@ WdmAudReadWrite( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp); -NTSTATUS -NTAPI -WdmAudWrite( - IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp); - NTSTATUS WdmAudControlOpenMixer( IN PDEVICE_OBJECT DeviceObject, @@ -166,6 +141,10 @@ SetIrpIoStatus( IN NTSTATUS Status, IN ULONG Length); +NTSTATUS +GetSysAudioDeviceInterface( + OUT LPWSTR* SymbolicLonkList); + NTSTATUS WdmAudOpenSysAudioDevice( IN LPWSTR DeviceName, @@ -180,6 +159,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 +167,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,6 +175,7 @@ WdmAudWaveCapabilities( NTSTATUS WdmAudMidiCapabilities( IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo, IN PWDMAUD_DEVICE_EXTENSION DeviceExtension); @@ -205,13 +187,21 @@ WdmAudGetPosition( _In_ PIRP Irp, _In_ PWDMAUD_DEVICE_INFO DeviceInfo); +NTSTATUS +WdmAudSetDeviceState( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PWDMAUD_DEVICE_INFO DeviceInfo, + IN KSSTATE State, + IN BOOL CompleteIrp); + NTSTATUS NTAPI -WdmAudFrameSize( +WdmAudResetStream( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PWDMAUD_DEVICE_INFO DeviceInfo, - IN PWDMAUD_CLIENT ClientInfo); + IN BOOL CompleteIrp); NTSTATUS NTAPI @@ -253,6 +243,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); @@ -263,12 +258,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, @@ -276,6 +280,7 @@ InsertPinHandle( IN ULONG PinId, IN SOUND_DEVICE_TYPE DeviceType, IN HANDLE PinHandle, + IN PFILE_OBJECT PinFileObject, IN ULONG FreeIndex); NTSTATUS @@ -325,6 +330,10 @@ ULONG GetSysAudioDeviceCount( IN PDEVICE_OBJECT DeviceObject); +NTSTATUS +SetSysAudioDeviceInstance( + IN PWDMAUD_DEVICE_EXTENSION DeviceExtension, + IN ULONG VirtualDeviceId); PVOID AllocateItem( diff --git a/drivers/wdm/audio/sysaudio/control.c b/drivers/wdm/audio/sysaudio/control.c index 5d18c24ce92d3..c78ee988a9ba7 100644 --- a/drivers/wdm/audio/sysaudio/control.c +++ b/drivers/wdm/audio/sysaudio/control.c @@ -8,7 +8,7 @@ #include "sysaudio.h" -#define NDEBUG +#define YDEBUG #include const GUID KSPROPSETID_Sysaudio = {0xCBE3FAA0L, 0xCC75, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}}; @@ -135,134 +135,123 @@ NTSTATUS ComputeCompatibleFormat( IN PKSAUDIO_DEVICE_ENTRY Entry, IN ULONG PinId, - IN PKSDATAFORMAT_WAVEFORMATEX ClientFormat, - OUT PKSDATAFORMAT_WAVEFORMATEX MixerFormat) + IN PKSDATAFORMAT_WAVEFORMATEX InputFormat, + OUT PKSDATAFORMAT_WAVEFORMATEX OutputFormat) { - BOOL bFound; - ULONG BytesReturned; + ULONG BytesReturned, Length; PKSP_PIN PinRequest; NTSTATUS Status; PKSMULTIPLE_ITEM MultipleItem; - ULONG Length; - PKSDATARANGE_AUDIO AudioRange; - ULONG Index; + PKSDATARANGE_AUDIO DataRangeAudio; + DWORD cbSize; + + /* Calculate additional data size */ + cbSize = InputFormat->WaveFormatEx.wFormatTag == WAVE_FORMAT_PCM ? 0 : InputFormat->WaveFormatEx.cbSize; - Length = sizeof(KSP_PIN) + sizeof(KSMULTIPLE_ITEM) + ClientFormat->DataFormat.FormatSize; + /* Allocate pin request */ + Length = sizeof(KSP_PIN) + sizeof(KSMULTIPLE_ITEM) + InputFormat->DataFormat.FormatSize; PinRequest = AllocateItem(NonPagedPool, Length); if (!PinRequest) - return STATUS_UNSUCCESSFUL; + { + return STATUS_INSUFFICIENT_RESOURCES; + } + /* Setup request block */ + PinRequest->Reserved = 0; PinRequest->PinId = PinId; PinRequest->Property.Set = KSPROPSETID_Pin; PinRequest->Property.Flags = KSPROPERTY_TYPE_GET; PinRequest->Property.Id = KSPROPERTY_PIN_DATAINTERSECTION; + /* Prepare multiple item */ MultipleItem = (PKSMULTIPLE_ITEM)(PinRequest + 1); MultipleItem->Count = 1; - MultipleItem->Size = ClientFormat->DataFormat.FormatSize; - - 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); + MultipleItem->Size = InputFormat->DataFormat.FormatSize; - DPRINT("Status %x\n", Status); + RtlMoveMemory(MultipleItem + 1, InputFormat, InputFormat->DataFormat.FormatSize); - if (NT_SUCCESS(Status)) + /* Query the miniport data intersection handler */ + Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)PinRequest, Length, (PVOID)OutputFormat, sizeof(KSDATAFORMAT_WAVEFORMATEX) + cbSize, &BytesReturned); + if (!NT_SUCCESS(Status)) { - FreeItem(PinRequest); - return Status; + DPRINT1("Property Request KSPROPERTY_PIN_DATAINTERSECTION failed with 0x%lx\n", Status); + //FreeItem(PinRequest); + //return Status; } /* Setup request block */ 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) + /* Query pin data ranges size */ + Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)PinRequest, sizeof(KSP_PIN), NULL, 0, &BytesReturned); + if (Status != STATUS_BUFFER_OVERFLOW) { - /* Failed to get data ranges */ + DPRINT1("Property Request KSPROPERTY_PIN_DATARANGES failed with 0x%lx\n", Status); + FreeItem(PinRequest); return Status; } + /* Allocate multiple item */ MultipleItem = AllocateItem(NonPagedPool, BytesReturned); if (!MultipleItem) { FreeItem(PinRequest); - return STATUS_NO_MEMORY; + return STATUS_INSUFFICIENT_RESOURCES; } + /* Query pin data ranges */ 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 0x%lx\n", Status); FreeItem(MultipleItem); FreeItem(PinRequest); - return STATUS_UNSUCCESSFUL; + return Status; } - AudioRange = (PKSDATARANGE_AUDIO)(MultipleItem + 1); - bFound = FALSE; - for(Index = 0; Index < MultipleItem->Count; Index++) + /* Get data range */ + DataRangeAudio = (PKSDATARANGE_AUDIO)(MultipleItem + 1); + + /* Select best quality available */ + OutputFormat->WaveFormatEx.wFormatTag = InputFormat->WaveFormatEx.wFormatTag; + OutputFormat->WaveFormatEx.nChannels = DataRangeAudio->MaximumChannels; + OutputFormat->WaveFormatEx.wBitsPerSample = DataRangeAudio->MaximumBitsPerSample; + OutputFormat->WaveFormatEx.nSamplesPerSec = min(InputFormat->WaveFormatEx.nSamplesPerSec, DataRangeAudio->MaximumSampleFrequency); + OutputFormat->WaveFormatEx.nBlockAlign = (OutputFormat->WaveFormatEx.nChannels * OutputFormat->WaveFormatEx.wBitsPerSample) / 8; + OutputFormat->WaveFormatEx.nAvgBytesPerSec = OutputFormat->WaveFormatEx.nSamplesPerSec * OutputFormat->WaveFormatEx.nBlockAlign; + OutputFormat->WaveFormatEx.cbSize = cbSize; + OutputFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX) + cbSize; + OutputFormat->DataFormat.Flags = 0; + OutputFormat->DataFormat.Reserved = 0; + OutputFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO; + OutputFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + OutputFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX; + OutputFormat->DataFormat.SampleSize = 4; + + /* Write additional fields for Extensible audio format */ + if (InputFormat->WaveFormatEx.wFormatTag == WAVE_FORMAT_EXTENSIBLE) { - if (AudioRange->DataRange.FormatSize != sizeof(KSDATARANGE_AUDIO)) - { - UNIMPLEMENTED; - AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange + AudioRange->DataRange.FormatSize); - continue; - } - /* Select best quality available */ - - MixerFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX); - MixerFormat->DataFormat.Flags = 0; - MixerFormat->DataFormat.Reserved = 0; - MixerFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO; - MixerFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - 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; -#else - MixerFormat->WaveFormatEx.nSamplesPerSec = max(AudioRange->MinimumSampleFrequency, min(ClientFormat->WaveFormatEx.nSamplesPerSec, AudioRange->MaximumSampleFrequency)); -#endif - - MixerFormat->WaveFormatEx.cbSize = 0; - MixerFormat->WaveFormatEx.nBlockAlign = (MixerFormat->WaveFormatEx.nChannels * MixerFormat->WaveFormatEx.wBitsPerSample) / 8; - MixerFormat->WaveFormatEx.nAvgBytesPerSec = MixerFormat->WaveFormatEx.nChannels * MixerFormat->WaveFormatEx.nSamplesPerSec * (MixerFormat->WaveFormatEx.wBitsPerSample / 8); - - bFound = TRUE; - break; - - AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange + AudioRange->DataRange.FormatSize); + PWAVEFORMATEXTENSIBLE WaveFormatExt = (PWAVEFORMATEXTENSIBLE)&OutputFormat->WaveFormatEx; + WaveFormatExt->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + WaveFormatExt->Samples.wValidBitsPerSample = OutputFormat->WaveFormatEx.wBitsPerSample; + if (OutputFormat->WaveFormatEx.nChannels == 0) + WaveFormatExt->dwChannelMask = KSAUDIO_SPEAKER_DIRECTOUT; + else if (OutputFormat->WaveFormatEx.nChannels == 1) + WaveFormatExt->dwChannelMask = KSAUDIO_SPEAKER_MONO; + else if (OutputFormat->WaveFormatEx.nChannels == 2) + WaveFormatExt->dwChannelMask = KSAUDIO_SPEAKER_STEREO; + else if (OutputFormat->WaveFormatEx.nChannels == 4) + WaveFormatExt->dwChannelMask = KSAUDIO_SPEAKER_QUAD; + else if (OutputFormat->WaveFormatEx.nChannels == 5) + WaveFormatExt->dwChannelMask = KSAUDIO_SPEAKER_5POINT1; + else if (OutputFormat->WaveFormatEx.nChannels == 7) + WaveFormatExt->dwChannelMask = KSAUDIO_SPEAKER_7POINT1; } -#if 0 - 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, - AudioRange->MaximumBitsPerSample, MixerFormat->WaveFormatEx.wBitsPerSample, ClientFormat->WaveFormatEx.wBitsPerSample); - - -#endif - FreeItem(MultipleItem); FreeItem(PinRequest); - if (bFound) - return STATUS_SUCCESS; - else - return STATUS_NOT_IMPLEMENTED; + return STATUS_SUCCESS; } NTSTATUS @@ -363,7 +352,7 @@ SysAudioHandleProperty( if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < BytesReturned) { /* too small buffer */ - return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, BytesReturned); + return SetIrpIoStatus(Irp, STATUS_BUFFER_OVERFLOW, BytesReturned); } /* copy device name */ 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/dispatcher.c b/drivers/wdm/audio/sysaudio/dispatcher.c index f673a738181c9..c991568d11458 100644 --- a/drivers/wdm/audio/sysaudio/dispatcher.c +++ b/drivers/wdm/audio/sysaudio/dispatcher.c @@ -8,9 +8,11 @@ #include "sysaudio.h" -#define NDEBUG +#define YDEBUG #include +const GUID KSCATEGORY_MIXER = {0xAD809C00L, 0x7B88, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; + NTSTATUS NTAPI Dispatch_fnDeviceIoControl( @@ -133,21 +135,48 @@ SysAudioOpenKMixer( IN SYSAUDIODEVEXT *DeviceExtension) { NTSTATUS Status; - UNICODE_STRING DeviceInstanceName = RTL_CONSTANT_STRING(L"\\Device\\kmixer\\GLOBAL"); + LPWSTR SymbolicLinkList, SymbolicLink; + UNICODE_STRING SymbolicLinkU; UNICODE_STRING DevicePath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\kmixer"); Status = ZwLoadDriver(&DevicePath); if (NT_SUCCESS(Status)) { - Status = OpenDevice(&DeviceInstanceName, &DeviceExtension->KMixerHandle, &DeviceExtension->KMixerFileObject); + Status = IoGetDeviceInterfaces(&KSCATEGORY_MIXER, + NULL, + 0, + &SymbolicLinkList); + if (!NT_SUCCESS(Status)) { + DPRINT1("IoGetDeviceInterfaces failed with status 0x%lx\n", Status); DeviceExtension->KMixerHandle = NULL; DeviceExtension->KMixerFileObject = NULL; + return Status; + } + + for (SymbolicLink = SymbolicLinkList; + *SymbolicLink != UNICODE_NULL; + SymbolicLink += wcslen(SymbolicLink) + 1) + { + DPRINT("Opening device %S\n", SymbolicLink); + RtlInitUnicodeString(&SymbolicLinkU, SymbolicLink); + Status = OpenDevice(&SymbolicLinkU, &DeviceExtension->KMixerHandle, &DeviceExtension->KMixerFileObject); + if (NT_SUCCESS(Status)) + { + DPRINT("Successfully opened %S, handle %p\n", SymbolicLink, DeviceExtension->KMixerHandle); + break; + } + else + { + RtlFreeUnicodeString(&SymbolicLinkU); + DeviceExtension->KMixerHandle = NULL; + DeviceExtension->KMixerFileObject = NULL; + } } } - DPRINT("Status %lx KMixerHandle %p KMixerFileObject %p\n", Status, DeviceExtension->KMixerHandle, DeviceExtension->KMixerFileObject); - return STATUS_SUCCESS; + DPRINT("Status 0x%lx KMixerHandle %p KMixerFileObject %p\n", Status, DeviceExtension->KMixerHandle, DeviceExtension->KMixerFileObject); + return Status; } diff --git a/drivers/wdm/audio/sysaudio/main.c b/drivers/wdm/audio/sysaudio/main.c index 12e5b2aacfc42..6f306bda07d9c 100644 --- a/drivers/wdm/audio/sysaudio/main.c +++ b/drivers/wdm/audio/sysaudio/main.c @@ -11,7 +11,7 @@ #include "sysaudio.h" -#define NDEBUG +#define YDEBUG #include #define TAG_SYSAUDIO 'AsyS' @@ -197,14 +197,6 @@ SysAudio_AddDevice( goto cleanup; } - /* Load kmixer */ - Status = SysAudioOpenKMixer(DeviceExtension); - if (!NT_SUCCESS(Status)) - { - DPRINT1("SysAudioOpenKMixer failed with %x\n", Status); - goto cleanup; - } - /* set io flags */ DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE; /* clear initializing flag */ diff --git a/drivers/wdm/audio/sysaudio/pin.c b/drivers/wdm/audio/sysaudio/pin.c index dd9663a31d9d8..023eeff01628f 100644 --- a/drivers/wdm/audio/sysaudio/pin.c +++ b/drivers/wdm/audio/sysaudio/pin.c @@ -8,22 +8,36 @@ #include "sysaudio.h" -#define NDEBUG +#define YDEBUG #include + NTSTATUS NTAPI -Pin_fnDeviceIoControl( +Pin_fnRead( + PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + UNIMPLEMENTED; + + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +Pin_fnWrite( PDEVICE_OBJECT DeviceObject, PIRP Irp) { PDISPATCH_CONTEXT Context; - NTSTATUS Status; - ULONG BytesReturned; - PFILE_OBJECT FileObject = NULL; PIO_STACK_LOCATION IoStack; + PFILE_OBJECT FileObject; + NTSTATUS Status; - DPRINT("Pin_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject, Irp); + DPRINT("Pin_fnWrite called DeviceObject %p Irp %p\n", DeviceObject, Irp); /* Get current stack location */ IoStack = IoGetCurrentIrpStackLocation(Irp); @@ -34,70 +48,94 @@ Pin_fnDeviceIoControl( /* Sanity check */ ASSERT(Context); - /* acquire real pin file object */ + if (Context->hMixerPin) + { + /* Acquire kmixer pin file object */ + Status = ObReferenceObjectByHandle(Context->hMixerPin, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to reference kmixer pin file object with status 0x%lx\n", Status); + return Status; + } + + /* Skip current irp location */ + IoSkipCurrentIrpStackLocation(Irp); + + /* Get next irp stack location */ + IoStack = IoGetNextIrpStackLocation(Irp); + + /* Setup stack parameters */ + IoStack->MajorFunction = IRP_MJ_WRITE; + IoStack->FileObject = FileObject; + + /* Call kmixer to convert stream */ + IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp); + + /* Dereference file object */ + ObDereferenceObject(FileObject); + } + + /* Acquire sysaudio pin file object */ Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = Status; - /* Complete the irp */ - IoCompleteRequest(Irp, IO_NO_INCREMENT); + DPRINT1("Failed to reference sysaudio pin file object with status 0x%lx\n", Status); return Status; } - /* Re-dispatch the request to the real target pin */ - Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IoStack->Parameters.DeviceIoControl.IoControlCode, - IoStack->Parameters.DeviceIoControl.Type3InputBuffer, - IoStack->Parameters.DeviceIoControl.InputBufferLength, - Irp->UserBuffer, - IoStack->Parameters.DeviceIoControl.OutputBufferLength, - &BytesReturned); - /* release file object */ + /* Skip current irp location */ + IoSkipCurrentIrpStackLocation(Irp); + + /* Get next irp stack location */ + IoStack = IoGetNextIrpStackLocation(Irp); + + /* Setup stack parameters */ + IoStack->MajorFunction = IRP_MJ_DEVICE_CONTROL; + IoStack->FileObject = FileObject; + + /* Send the stream */ + IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp); + + /* Dereference file object */ ObDereferenceObject(FileObject); - /* Save status and information */ - Irp->IoStatus.Information = BytesReturned; - Irp->IoStatus.Status = Status; - /* Complete the irp */ - IoCompleteRequest(Irp, IO_NO_INCREMENT); /* Done */ - return Status; + return STATUS_PENDING; } - - NTSTATUS NTAPI -Pin_fnWrite( +Pin_fnDeviceIoControl( PDEVICE_OBJECT DeviceObject, PIRP Irp) { PDISPATCH_CONTEXT Context; - PIO_STACK_LOCATION IoStack; - PFILE_OBJECT FileObject; NTSTATUS Status; + ULONG BytesReturned; + PFILE_OBJECT FileObject = NULL; + PIO_STACK_LOCATION IoStack; + + DPRINT("Pin_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject, Irp); /* Get current stack location */ IoStack = IoGetCurrentIrpStackLocation(Irp); + /* Handle Read/Write I/O request */ + if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM) + return Pin_fnRead(DeviceObject, Irp); + else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM) + return Pin_fnWrite(DeviceObject, Irp); + /* The dispatch context is stored in the FsContext member */ Context = (PDISPATCH_CONTEXT)IoStack->FileObject->FsContext; /* Sanity check */ ASSERT(Context); - if (Context->hMixerPin) - { - // FIXME - // call kmixer to convert stream - UNIMPLEMENTED; - } - /* acquire real pin file object */ Status = ObReferenceObjectByHandle(Context->Handle, GENERIC_WRITE, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) { - DPRINT1("failed\n"); Irp->IoStatus.Information = 0; Irp->IoStatus.Status = Status; /* Complete the irp */ @@ -105,24 +143,23 @@ Pin_fnWrite( return Status; } - /* skip current irp location */ - IoSkipCurrentIrpStackLocation(Irp); - - /* get next stack location */ - IoStack = IoGetNextIrpStackLocation(Irp); - /* store file object of next device object */ - IoStack->FileObject = FileObject; - IoStack->MajorFunction = IRP_MJ_DEVICE_CONTROL; - //ASSERT(Irp->AssociatedIrp.SystemBuffer); - - /* now call the driver */ - Status = IoCallDriver(IoGetRelatedDeviceObject(FileObject), Irp); - - /* dereference file object */ + /* Re-dispatch the request to the real target pin */ + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IoStack->Parameters.DeviceIoControl.IoControlCode, + IoStack->Parameters.DeviceIoControl.Type3InputBuffer, + IoStack->Parameters.DeviceIoControl.InputBufferLength, + Irp->UserBuffer, + IoStack->Parameters.DeviceIoControl.OutputBufferLength, + &BytesReturned); + /* release file object */ ObDereferenceObject(FileObject); + /* Save status and information */ + Irp->IoStatus.Information = BytesReturned; + Irp->IoStatus.Status = Status; + /* Complete the irp */ + IoCompleteRequest(Irp, IO_NO_INCREMENT); + /* Done */ return Status; - } NTSTATUS @@ -134,7 +171,7 @@ Pin_fnClose( PDISPATCH_CONTEXT Context; PIO_STACK_LOCATION IoStack; - //DPRINT("Pin_fnClose called DeviceObject %p Irp %p\n", DeviceObject, Irp); + DPRINT("Pin_fnClose called DeviceObject %p Irp %p\n", DeviceObject, Irp); /* Get current stack location */ IoStack = IoGetCurrentIrpStackLocation(Irp); @@ -163,7 +200,7 @@ Pin_fnClose( static KSDISPATCH_TABLE PinTable = { Pin_fnDeviceIoControl, - KsDispatchInvalidDeviceRequest, + Pin_fnRead, Pin_fnWrite, KsDispatchInvalidDeviceRequest, Pin_fnClose, @@ -230,8 +267,8 @@ CreateMixerPinAndSetFormat( if (!NT_SUCCESS(Status)) { - DPRINT1("Failed to create Mixer Pin with %x\n", Status); - return STATUS_UNSUCCESSFUL; + DPRINT1("Failed to create Mixer Pin with 0x%lx\n", Status); + return Status; } Status = ObReferenceObjectByHandle(PinHandle, @@ -240,8 +277,9 @@ CreateMixerPinAndSetFormat( if (!NT_SUCCESS(Status)) { - DPRINT1("Failed to get file object with %x\n", Status); - return STATUS_UNSUCCESSFUL; + DPRINT1("Failed to get file object with 0x%lx\n", Status); + ZwClose(PinHandle); + return Status; } Status = SetMixerInputOutputFormat(FileObject, InputFormat, OutputFormat); @@ -252,10 +290,11 @@ CreateMixerPinAndSetFormat( return Status; } + *MixerPinHandle = PinHandle; + ObDereferenceObject(FileObject); - *MixerPinHandle = PinHandle; - return Status; + return Status; } @@ -269,8 +308,7 @@ InstantiatePins( { NTSTATUS Status; HANDLE RealPinHandle; - PKSDATAFORMAT_WAVEFORMATEX InputFormat; - PKSDATAFORMAT_WAVEFORMATEX OutputFormat = NULL; + PKSDATAFORMAT_WAVEFORMATEX InputFormat, OutputFormat = NULL; PKSPIN_CONNECT MixerPinConnect = NULL; KSPIN_CINSTANCES PinInstances; @@ -308,37 +346,41 @@ InstantiatePins( if (!NT_SUCCESS(Status)) { - /* FIXME disable kmixer - */ - return STATUS_UNSUCCESSFUL; - } #if 0 - if (!NT_SUCCESS(Status)) - { /* the audio irp pin didnt accept the input format * let's compute a compatible format */ - MixerPinConnect = AllocateItem(NonPagedPool, sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX)); + + if (!DeviceExtension->KMixerHandle || !DeviceExtension->KMixerFileObject) + { + /* Load kmixer */ + Status = SysAudioOpenKMixer(DeviceExtension); + if (!NT_SUCCESS(Status)) + { + DPRINT1("SysAudioOpenKMixer failed with 0x%lx\n", Status); + return Status; + } + } + + /* Allocate pin connect */ + MixerPinConnect = AllocateItem(NonPagedPool, sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEXTENSIBLE)); if (!MixerPinConnect) { /* not enough memory */ return STATUS_INSUFFICIENT_RESOURCES; } - /* Zero pin connect */ - RtlZeroMemory(MixerPinConnect, sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT_WAVEFORMATEX)); - /* Copy initial connect details */ RtlMoveMemory(MixerPinConnect, Connect, sizeof(KSPIN_CONNECT)); - + /* Fetch output format */ OutputFormat = (PKSDATAFORMAT_WAVEFORMATEX)(MixerPinConnect + 1); + /* Compute compatible format */ Status = ComputeCompatibleFormat(DeviceEntry, Connect->PinId, InputFormat, OutputFormat); if (!NT_SUCCESS(Status)) { - DPRINT1("ComputeCompatibleFormat failed with %x\n", Status); - FreeItem(MixerPinConnect); + DPRINT1("ComputeCompatibleFormat failed with 0x%lx\n", Status); return Status; } @@ -346,16 +388,19 @@ InstantiatePins( Status = KsCreatePin(DeviceEntry->Handle, MixerPinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle); if (!NT_SUCCESS(Status)) { - /* This should not fail */ - DPRINT1("KsCreatePin failed with %x\n", Status); + /* This should not fail */ + DPRINT1("KsCreatePin failed with 0x%lx\n", Status); DPRINT1(" InputFormat: SampleRate %u Bits %u Channels %u\n", InputFormat->WaveFormatEx.nSamplesPerSec, InputFormat->WaveFormatEx.wBitsPerSample, InputFormat->WaveFormatEx.nChannels); DPRINT1("OutputFormat: SampleRate %u Bits %u Channels %u\n", OutputFormat->WaveFormatEx.nSamplesPerSec, OutputFormat->WaveFormatEx.wBitsPerSample, OutputFormat->WaveFormatEx.nChannels); FreeItem(MixerPinConnect); return Status; } - } +#else + DPRINT1("KsCreatePin failed with status 0x%lx\n", Status); + return Status; #endif + } //DeviceEntry->Pins[Connect->PinId].References = 0; @@ -364,8 +409,8 @@ InstantiatePins( DispatchContext->PinId = Connect->PinId; DispatchContext->AudioEntry = DeviceEntry; - DPRINT("RealPinHandle %p\n", RealPinHandle); + DPRINT("OutputFormat %p\n", OutputFormat); /* Do we need to transform the audio stream */ if (OutputFormat != NULL) @@ -380,10 +425,12 @@ InstantiatePins( /* check for success */ if (!NT_SUCCESS(Status)) { - DPRINT1("Failed to create Mixer Pin with %x\n", Status); + DPRINT1("Failed to create Mixer Pin with 0x%lx\n", Status); + FreeItem(OutputFormat); FreeItem(MixerPinConnect); } } + /* done */ return Status; } @@ -419,7 +466,7 @@ GetConnectRequest( RtlMoveMemory(Buffer, &IoStack->FileObject->FileName.Buffer[ObjectLength / sizeof(WCHAR)], ParametersLength); /* store result */ - *Result = (PKSPIN_CONNECT)Buffer; + *Result = Buffer; return STATUS_SUCCESS; } @@ -432,7 +479,7 @@ DispatchCreateSysAudioPin( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - NTSTATUS Status = STATUS_SUCCESS; + NTSTATUS Status; PIO_STACK_LOCATION IoStack; PKSAUDIO_DEVICE_ENTRY DeviceEntry; PKSPIN_CONNECT Connect; @@ -451,15 +498,6 @@ DispatchCreateSysAudioPin( /* get current attached virtual device */ DeviceEntry = (PKSAUDIO_DEVICE_ENTRY)IoStack->FileObject->RelatedFileObject->FsContext; - /* check for success */ - if (!NT_SUCCESS(Status)) - { - /* failed */ - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return Status; - } - /* get connect details */ Status = GetConnectRequest(Irp, &Connect); diff --git a/drivers/wdm/audio/sysaudio/sysaudio.h b/drivers/wdm/audio/sysaudio/sysaudio.h index 5a18cc96f136b..b6e89db9fd28f 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 { @@ -107,8 +108,8 @@ NTSTATUS ComputeCompatibleFormat( IN PKSAUDIO_DEVICE_ENTRY Entry, IN ULONG PinId, - IN PKSDATAFORMAT_WAVEFORMATEX ClientFormat, - OUT PKSDATAFORMAT_WAVEFORMATEX MixerFormat); + IN PKSDATAFORMAT_WAVEFORMATEX InputFormat, + OUT PKSDATAFORMAT_WAVEFORMATEX OutputFormat); PVOID AllocateItem( diff --git a/ntoskrnl/ke/timerobj.c b/ntoskrnl/ke/timerobj.c index 1c19d03b46ede..38f221b33c606 100644 --- a/ntoskrnl/ke/timerobj.c +++ b/ntoskrnl/ke/timerobj.c @@ -207,7 +207,7 @@ KeCancelTimer(IN OUT PKTIMER Timer) { KIRQL OldIrql; BOOLEAN Inserted; - ASSERT_TIMER(Timer); + //ASSERT_TIMER(Timer); ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); DPRINT("KeCancelTimer(): Timer %p\n", Timer); diff --git a/ntoskrnl/mm/ARM3/mdlsup.c b/ntoskrnl/mm/ARM3/mdlsup.c index 76b06f0c72e16..1ed2672db8e76 100644 --- a/ntoskrnl/mm/ARM3/mdlsup.c +++ b/ntoskrnl/mm/ARM3/mdlsup.c @@ -697,10 +697,10 @@ MmMapLockedPagesSpecifyCache(IN PMDL Mdl, // // Sanity checks // - ASSERT((Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | - MDL_SOURCE_IS_NONPAGED_POOL | - MDL_PARTIAL_HAS_BEEN_MAPPED)) == 0); - ASSERT((Mdl->MdlFlags & (MDL_PAGES_LOCKED | MDL_PARTIAL)) != 0); + //ASSERT((Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | + // MDL_SOURCE_IS_NONPAGED_POOL | + // MDL_PARTIAL_HAS_BEEN_MAPPED)) == 0); + //ASSERT((Mdl->MdlFlags & (MDL_PAGES_LOCKED | MDL_PARTIAL)) != 0); // // Get the correct cache type diff --git a/ntoskrnl/se/accesschk.c b/ntoskrnl/se/accesschk.c index ad931da38fb81..ab0132ed3d590 100644 --- a/ntoskrnl/se/accesschk.c +++ b/ntoskrnl/se/accesschk.c @@ -1429,13 +1429,14 @@ SepAccessCheckWorker( goto ReturnCommonStatus; } +ReturnCommonStatus: // HACK /* * If we're here then we granted all the desired * access rights the caller wanted. */ Status = STATUS_SUCCESS; -ReturnCommonStatus: +//ReturnCommonStatus: if (!UseResultList) { *GrantedAccessList = PreviouslyGrantedAccess; 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/ksmedia.h b/sdk/include/psdk/ksmedia.h index 83e717e9e93eb..db76f63c33298 100644 --- a/sdk/include/psdk/ksmedia.h +++ b/sdk/include/psdk/ksmedia.h @@ -191,6 +191,12 @@ DEFINE_GUIDSTRUCT("67C9CC3C-69C4-11D2-8759-00A0C9223196", KSCATEGORY_NETWORK); DEFINE_GUIDSTRUCT("3A13EB40-30A7-11D0-A5D6-28DB04C10000", KSINTERFACESETID_Media); #define KSINTERFACESETID_Media DEFINE_GUIDNAMED(KSINTERFACESETID_Media) +typedef enum { + KSINTERFACE_MEDIA_MUSIC, + KSINTERFACE_MEDIA_WAVE_BUFFERED, + KSINTERFACE_MEDIA_WAVE_QUEUED +} KSINTERFACE_MEDIA; + /* ... */ #define STATIC_KSCATEGORY_TOPOLOGY \ @@ -647,6 +653,11 @@ typedef struct { } WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE; #endif +typedef struct { + KSDATAFORMAT DataFormat; + WAVEFORMATEXTENSIBLE WaveFormatExt; +} KSDATAFORMAT_WAVEFORMATEXTENSIBLE, *PKSDATAFORMAT_WAVEFORMATEXTENSIBLE; + #if !defined(WAVE_FORMAT_EXTENSIBLE) #define WAVE_FORMAT_EXTENSIBLE 0xFFFE #endif 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/controls.c b/sdk/lib/drivers/sound/mmixer/controls.c index a7521bf4dd335..cc94268a1c029 100644 --- a/sdk/lib/drivers/sound/mmixer/controls.c +++ b/sdk/lib/drivers/sound/mmixer/controls.c @@ -1543,8 +1543,8 @@ MMixerInitializeFilter( /* intialize mixer caps */ MixerInfo->MixCaps.wMid = MM_MICROSOFT; /* FIXME */ - MixerInfo->MixCaps.wPid = MM_PID_UNMAPPED; /* FIXME */ - MixerInfo->MixCaps.vDriverVersion = 1; /* FIXME */ + MixerInfo->MixCaps.wPid = MM_MSFT_WDMAUDIO_MIXER; /* FIXME */ + MixerInfo->MixCaps.vDriverVersion = 0x050a; /* FIXME */ MixerInfo->MixCaps.fdwSupport = 0; MixerInfo->MixCaps.cDestinations = 0; @@ -1584,7 +1584,6 @@ MMixerInitializeFilter( * For source pins (wave in) search down stream * The search direction is always the opposite of the current mixer type */ - PinsFound = 0; MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, NodeIndex, !bInputMixer, &PinsFound, Pins); /* if there is no pin found, we have a broken topology */ @@ -1822,80 +1821,3 @@ MMixerSetupFilter( /* done */ return Status; } - -MIXER_STATUS -MMixerAddEvent( - IN PMIXER_CONTEXT MixerContext, - IN OUT LPMIXER_INFO MixerInfo, - IN PVOID MixerEventContext, - IN PMIXER_EVENT MixerEventRoutine) -{ - //KSE_NODE Property; - //KSEVENTDATA EventData - //ULONG BytesReturned; - //MIXER_STATUS Status; - PEVENT_NOTIFICATION_ENTRY EventNotification; - - EventNotification = (PEVENT_NOTIFICATION_ENTRY)MixerContext->Alloc(sizeof(EVENT_NOTIFICATION_ENTRY)); - if (!EventNotification) - { - /* not enough memory */ - return MM_STATUS_NO_MEMORY; - } - - /* FIXME: what is it supposed to happen with KSEVENTDATA ? */ -#if 0 - /* setup request */ - Property.Event.Set = KSEVENTSETID_AudioControlChange; - Property.Event.Flags = KSEVENT_TYPE_TOPOLOGY|KSEVENT_TYPE_ENABLE; - Property.Event.Id = KSEVENT_CONTROL_CHANGE; - - Property.NodeId = NodeId; - Property.Reserved = 0; - - Status = MixerContext->Control(MixerInfo->hMixer, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSP_NODE), (PVOID)EventData, sizeof(KSEVENTDATA), &BytesReturned); - if (Status != MM_STATUS_SUCCESS) - { - /* failed to add event */ - MixerContext->FreeEventData(EventData); - return Status; - } -#endif - - /* initialize notification entry */ - EventNotification->MixerEventContext = MixerEventContext; - EventNotification->MixerEventRoutine = MixerEventRoutine; - - /* store event */ - InsertTailList(&MixerInfo->EventList, &EventNotification->Entry); - return MM_STATUS_SUCCESS; -} - -MIXER_STATUS -MMixerRemoveEvent( - IN PMIXER_CONTEXT MixerContext, - IN OUT LPMIXER_INFO MixerInfo, - IN PVOID MixerEventContext, - IN PMIXER_EVENT MixerEventRoutine) -{ - PLIST_ENTRY EventList; - PEVENT_NOTIFICATION_ENTRY NotificationEntry; - - /* Lookup through mixers */ - EventList = MixerInfo->EventList.Flink; - while(EventList != &MixerInfo->EventList) - { - NotificationEntry = CONTAINING_RECORD(EventList, EVENT_NOTIFICATION_ENTRY, Entry); - EventList = EventList->Flink; - /* TODO: find a better way to identify an event ? */ - if(NotificationEntry->MixerEventRoutine == MixerEventRoutine && - NotificationEntry->MixerEventContext == MixerEventContext) - { - DPRINT1("Freeing entry %p\n", NotificationEntry); - /* We found the event to remove */ - RemoveEntryList(&NotificationEntry->Entry); - MixerContext->Free(NotificationEntry); - } - } - return MM_STATUS_SUCCESS; -} diff --git a/sdk/lib/drivers/sound/mmixer/midi.c b/sdk/lib/drivers/sound/mmixer/midi.c index acca89ca5adbf..efb064f60501f 100644 --- a/sdk/lib/drivers/sound/mmixer/midi.c +++ b/sdk/lib/drivers/sound/mmixer/midi.c @@ -75,30 +75,7 @@ MMixerAddMidiPin( ASSERT(!DeviceName || (wcslen(DeviceName) < MAXPNAMELEN)); /* copy device name */ - if (bInput && DeviceName) - { - wcscpy(MidiInfo->u.InCaps.szPname, DeviceName); - } - else if (!bInput && DeviceName) - { - wcscpy(MidiInfo->u.OutCaps.szPname, DeviceName); - } - - /* FIXME determine manufacturer / product id */ - if (bInput) - { - MidiInfo->u.InCaps.dwSupport = 0; - MidiInfo->u.InCaps.wMid = MM_MICROSOFT; - MidiInfo->u.InCaps.wPid = MM_PID_UNMAPPED; - MidiInfo->u.InCaps.vDriverVersion = 1; - } - else - { - MidiInfo->u.OutCaps.dwSupport = 0; - MidiInfo->u.OutCaps.wMid = MM_MICROSOFT; - MidiInfo->u.OutCaps.wPid = MM_PID_UNMAPPED; - MidiInfo->u.OutCaps.vDriverVersion = 1; - } + MidiInfo->DeviceName = DeviceName; if (bInput) { @@ -187,7 +164,7 @@ MMixerInitializeMidiForFilter( if (MMixerGetDeviceName(MixerContext, szPname, MixerData->hDeviceInterfaceKey) != MM_STATUS_SUCCESS) { /* clear name */ - szPname[0] = 0; + szPname[0] = L'\0'; } /* iterate all pins and check for KSDATARANGE_MUSIC support */ @@ -313,6 +290,7 @@ MMixerMidiOutCapabilities( PMIXER_LIST MixerList; MIXER_STATUS Status; LPMIDI_INFO MidiInfo; + MIDIOUTCAPSW MidiOutCaps; /* verify mixer context */ Status = MMixerVerifyContext(MixerContext); @@ -334,8 +312,24 @@ MMixerMidiOutCapabilities( return MM_STATUS_UNSUCCESSFUL; } + /* FIXME determine manufacturer / product id */ + MidiOutCaps.wMid = MM_MICROSOFT; + MidiOutCaps.wPid = MM_MSFT_WDMAUDIO_MIDIOUT; + MidiOutCaps.vDriverVersion = 0x050a; + MidiOutCaps.wTechnology = MOD_MIDIPORT; /* FIXME */ + MidiOutCaps.wVoices = 0; /* FIXME */ + MidiOutCaps.wNotes = 0; /* FIXME */ + MidiOutCaps.wChannelMask = 0xFFFF; /* FIXME */ + MidiOutCaps.dwSupport = 0; /* FIXME */ + + /* copy device name */ + wcscpy(MidiOutCaps.szPname, MidiInfo->DeviceName); + + /* make sure it's null terminated */ + MidiOutCaps.szPname[MAXPNAMELEN-1] = L'\0'; + /* copy capabilities */ - MixerContext->Copy(Caps, &MidiInfo->u.OutCaps, sizeof(MIDIOUTCAPSW)); + MixerContext->Copy(Caps, &MidiOutCaps, sizeof(MIDIOUTCAPSW)); return MM_STATUS_SUCCESS; } @@ -349,6 +343,7 @@ MMixerMidiInCapabilities( PMIXER_LIST MixerList; MIXER_STATUS Status; LPMIDI_INFO MidiInfo; + MIDIINCAPSW MidiInCaps; /* verify mixer context */ Status = MMixerVerifyContext(MixerContext); @@ -370,8 +365,20 @@ MMixerMidiInCapabilities( return MM_STATUS_UNSUCCESSFUL; } + /* FIXME determine manufacturer / product id */ + MidiInCaps.wMid = MM_MICROSOFT; + MidiInCaps.wPid = MM_MSFT_WDMAUDIO_MIDIIN; + MidiInCaps.vDriverVersion = 0x050a; + MidiInCaps.dwSupport = 0; + + /* copy device name */ + wcscpy(MidiInCaps.szPname, MidiInfo->DeviceName); + + /* make sure it's null terminated */ + MidiInCaps.szPname[MAXPNAMELEN-1] = L'\0'; + /* copy capabilities */ - MixerContext->Copy(Caps, &MidiInfo->u.InCaps, sizeof(MIDIINCAPSW)); + MixerContext->Copy(Caps, &MidiInCaps, sizeof(MIDIINCAPSW)); return MM_STATUS_SUCCESS; } @@ -426,9 +433,6 @@ MMixerGetMidiDevicePath( return MM_STATUS_NO_MEMORY; } - /* copy device path */ - MixerContext->Copy(*DevicePath, MixerData->DeviceName, Length * sizeof(WCHAR)); - /* done */ return MM_STATUS_SUCCESS; } diff --git a/sdk/lib/drivers/sound/mmixer/mixer.c b/sdk/lib/drivers/sound/mmixer/mixer.c index 4b98ed53ae3ea..5c32ed72666db 100644 --- a/sdk/lib/drivers/sound/mmixer/mixer.c +++ b/sdk/lib/drivers/sound/mmixer/mixer.c @@ -38,10 +38,13 @@ MIXER_STATUS MMixerGetCapabilities( IN PMIXER_CONTEXT MixerContext, IN ULONG MixerIndex, - OUT LPMIXERCAPSW MixerCaps) + OUT LPMIXERCAPSW Caps) { MIXER_STATUS Status; + PMIXER_LIST MixerList; + LPMIXER_DATA MixerData; LPMIXER_INFO MixerInfo; + MIXERCAPSW MixerCaps; /* verify mixer context */ Status = MMixerVerifyContext(MixerContext); @@ -52,23 +55,40 @@ MMixerGetCapabilities( return Status; } + /* grab mixer list */ + MixerList = (PMIXER_LIST)MixerContext->MixerContext; + + /* get mixer data */ + MixerData = MMixerGetDataByDeviceId(MixerList, MixerIndex); + + if (!MixerData) + { + /* invalid device index */ + return MM_STATUS_INVALID_PARAMETER; + } + /* get mixer info */ MixerInfo = MMixerGetMixerInfoByIndex(MixerContext, MixerIndex); if (!MixerInfo) { - // invalid device index + /* invalid device index */ return MM_STATUS_INVALID_PARAMETER; } - MixerCaps->wMid = MixerInfo->MixCaps.wMid; - MixerCaps->wPid = MixerInfo->MixCaps.wPid; - MixerCaps->vDriverVersion = MixerInfo->MixCaps.vDriverVersion; - MixerCaps->fdwSupport = MixerInfo->MixCaps.fdwSupport; - MixerCaps->cDestinations = MixerInfo->MixCaps.cDestinations; + /* intialize capabilities */ + MixerCaps.wMid = MixerInfo->MixCaps.wMid; + MixerCaps.wPid = MixerInfo->MixCaps.wPid; + MixerCaps.vDriverVersion = MixerInfo->MixCaps.vDriverVersion; + MixerCaps.fdwSupport = MixerInfo->MixCaps.fdwSupport; + MixerCaps.cDestinations = MixerInfo->MixCaps.cDestinations; + /* copy device name */ ASSERT(MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] == 0); - wcscpy(MixerCaps->szPname, MixerInfo->MixCaps.szPname); + wcscpy(MixerCaps.szPname, MixerInfo->MixCaps.szPname); + + /* copy capabilities */ + MixerContext->Copy(Caps, &MixerCaps, sizeof(MIXERCAPSW)); return MM_STATUS_SUCCESS; } @@ -77,8 +97,6 @@ MIXER_STATUS MMixerOpen( IN PMIXER_CONTEXT MixerContext, IN ULONG MixerId, - IN PVOID MixerEventContext, - IN PMIXER_EVENT MixerEventRoutine, OUT PHANDLE MixerHandle) { MIXER_STATUS Status; @@ -103,9 +121,6 @@ MMixerOpen( return MM_STATUS_INVALID_PARAMETER; } - /* add the event */ - Status = MMixerAddEvent(MixerContext, MixerInfo, MixerEventContext, MixerEventRoutine); - /* store result */ *MixerHandle = (HANDLE)MixerInfo; return MM_STATUS_SUCCESS; @@ -114,9 +129,7 @@ MMixerOpen( MIXER_STATUS MMixerClose( IN PMIXER_CONTEXT MixerContext, - IN ULONG MixerId, - IN PVOID MixerEventContext, - IN PMIXER_EVENT MixerEventRoutine) + IN ULONG MixerId) { MIXER_STATUS Status; LPMIXER_INFO MixerInfo; @@ -140,8 +153,8 @@ MMixerClose( return MM_STATUS_INVALID_PARAMETER; } - /* remove event from list */ - return MMixerRemoveEvent(MixerContext, MixerInfo, MixerEventContext, MixerEventRoutine); + /* done */ + return MM_STATUS_SUCCESS; } MIXER_STATUS @@ -554,8 +567,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; @@ -588,10 +615,11 @@ MMixerGetControlDetails( { /* caller passed mixer id */ MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId); - + DPRINT1("MixerHandle %p\n", MixerHandle); if (!MixerHandle) { /* invalid parameter */ + DPRINT1("Invalid mixer handle\n"); return MM_STATUS_INVALID_PARAMETER; } } @@ -600,12 +628,13 @@ 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) { /* failed to find control id */ + DPRINT1("Failed to get mixer control for id %d\n", MixerControlDetails->dwControlID); return MM_STATUS_INVALID_PARAMETER; } @@ -617,11 +646,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 396d221d2e493..7c3cec283bce9 100644 --- a/sdk/lib/drivers/sound/mmixer/mmixer.h +++ b/sdk/lib/drivers/sound/mmixer/mmixer.h @@ -136,22 +136,18 @@ MIXER_STATUS MMixerGetCapabilities( IN PMIXER_CONTEXT MixerContext, IN ULONG MixerIndex, - OUT LPMIXERCAPSW MixerCaps); + OUT LPMIXERCAPSW Caps); MIXER_STATUS MMixerOpen( IN PMIXER_CONTEXT MixerContext, IN ULONG MixerId, - IN PVOID MixerEventContext, - IN PMIXER_EVENT MixerEventRoutine, OUT PHANDLE MixerHandle); MIXER_STATUS MMixerClose( IN PMIXER_CONTEXT MixerContext, - IN ULONG MixerId, - IN PVOID MixerEventContext, - IN PMIXER_EVENT MixerEventRoutine); + IN ULONG MixerId); MIXER_STATUS MMixerGetLineInfo( diff --git a/sdk/lib/drivers/sound/mmixer/precomp.h b/sdk/lib/drivers/sound/mmixer/precomp.h index 4ffc3f7129bb5..6722d00447bc3 100644 --- a/sdk/lib/drivers/sound/mmixer/precomp.h +++ b/sdk/lib/drivers/sound/mmixer/precomp.h @@ -88,7 +88,6 @@ typedef struct ULONG PinId; MIXERLINEW Line; LIST_ENTRY ControlsList; - }MIXERLINE_EXT, *LPMIXERLINE_EXT; typedef struct @@ -124,11 +123,7 @@ typedef struct LIST_ENTRY Entry; ULONG DeviceId; ULONG PinId; - union - { - WAVEOUTCAPSW OutCaps; - WAVEINCAPSW InCaps; - }u; + WCHAR DeviceName[MAXPNAMELEN]; }WAVE_INFO, *LPWAVE_INFO; typedef struct @@ -136,12 +131,7 @@ typedef struct LIST_ENTRY Entry; ULONG DeviceId; ULONG PinId; - union - { - MIDIOUTCAPSW OutCaps; - MIDIINCAPSW InCaps; - }u; - + LPWSTR DeviceName; }MIDI_INFO, *LPMIDI_INFO; typedef struct @@ -346,20 +336,6 @@ MMixerInitializeWaveInfo( IN ULONG PinCount, IN PULONG Pins); -MIXER_STATUS -MMixerAddEvent( - IN PMIXER_CONTEXT MixerContext, - IN OUT LPMIXER_INFO MixerInfo, - IN PVOID MixerEvent, - IN PMIXER_EVENT MixerEventRoutine); - -MIXER_STATUS -MMixerRemoveEvent( - IN PMIXER_CONTEXT MixerContext, - IN OUT LPMIXER_INFO MixerInfo, - IN PVOID MixerEventContext, - IN PMIXER_EVENT MixerEventRoutine); - MIXER_STATUS MMixerGetDeviceName( IN PMIXER_CONTEXT MixerContext, diff --git a/sdk/lib/drivers/sound/mmixer/sup.c b/sdk/lib/drivers/sound/mmixer/sup.c index 9b6852a4d2309..775a285f4e0f3 100644 --- a/sdk/lib/drivers/sound/mmixer/sup.c +++ b/sdk/lib/drivers/sound/mmixer/sup.c @@ -41,15 +41,24 @@ MMixerVerifyContext( IN PMIXER_CONTEXT MixerContext) { if (MixerContext->SizeOfStruct != sizeof(MIXER_CONTEXT)) + { + DPRINT1("1\n"); return MM_STATUS_INVALID_PARAMETER; + } if (!MixerContext->Alloc || !MixerContext->Control || !MixerContext->Free || !MixerContext->Open || !MixerContext->AllocEventData || !MixerContext->FreeEventData || !MixerContext->Close || !MixerContext->OpenKey || !MixerContext->QueryKeyValue || !MixerContext->CloseKey) + { + DPRINT1("2\n"); return MM_STATUS_INVALID_PARAMETER; + } if (!MixerContext->MixerContext) + { + DPRINT1("3\n"); return MM_STATUS_INVALID_PARAMETER; + } return MM_STATUS_SUCCESS; } diff --git a/sdk/lib/drivers/sound/mmixer/topology.c b/sdk/lib/drivers/sound/mmixer/topology.c index 29b1237436bf1..cb635b79ad923 100644 --- a/sdk/lib/drivers/sound/mmixer/topology.c +++ b/sdk/lib/drivers/sound/mmixer/topology.c @@ -578,8 +578,10 @@ MMixerAddPinIndexToArray( { if (OutPins[Index] != MAXULONG) { + DPRINT1("1\n"); if (OutPins[Index] > PinId) { + DPRINT1("2\n"); /* shift entries up */ MixerContext->Copy(&OutPins[Index + 1], &OutPins[Index], (MaxPins - (Index + 1)) * sizeof(ULONG)); @@ -595,6 +597,7 @@ MMixerAddPinIndexToArray( } else { + DPRINT1("3\n"); /* store pin id */ OutPins[Index] = PinId; @@ -642,7 +645,7 @@ MMixerGetUpOrDownStreamPins( TopologyNodesCount = TopologyNode->NodeConnectedToCount; TopologyNodes = TopologyNode->NodeConnectedTo; } - + DPRINT1("PinsCount %d\n", PinsCount); /* add all diretly connected pins */ for(Index = 0; Index < PinsCount; Index++) { @@ -668,6 +671,7 @@ MMixerGetUpOrDownStreamPins( ASSERT(Pin->PinConnectedToCount == 0); } + DPRINT1("PinId %d\n", Pin->PinId); /* add them to pin array */ MMixerAddPinIndexToArray(MixerContext, Pin->PinId, Topology->TopologyPinsCount, OutPinCount, OutPins); @@ -678,6 +682,7 @@ MMixerGetUpOrDownStreamPins( /* mark node as visited */ TopologyNode->Visited = TRUE; + DPRINT1("TopologyNodesCount %d\n", TopologyNodesCount); /* now visit all connected nodes */ for(Index = 0; Index < TopologyNodesCount; Index++) { diff --git a/sdk/lib/drivers/sound/mmixer/wave.c b/sdk/lib/drivers/sound/mmixer/wave.c index bfce31e562788..36b33e9f67c0a 100644 --- a/sdk/lib/drivers/sound/mmixer/wave.c +++ b/sdk/lib/drivers/sound/mmixer/wave.c @@ -114,15 +114,16 @@ MMixerGetWaveInfoByIndexAndType( VOID MMixerInitializeDataFormat( _Inout_ PKSDATAFORMAT_WAVEFORMATEX DataFormat, + _In_ PKSDATARANGE_AUDIO DataRangeAudio, _In_ LPWAVEFORMATEX WaveFormatEx, _In_ DWORD cbSize) { DataFormat->WaveFormatEx.wFormatTag = WaveFormatEx->wFormatTag; - DataFormat->WaveFormatEx.nChannels = WaveFormatEx->nChannels; - DataFormat->WaveFormatEx.nSamplesPerSec = WaveFormatEx->nSamplesPerSec; - DataFormat->WaveFormatEx.nBlockAlign = WaveFormatEx->nBlockAlign; - DataFormat->WaveFormatEx.nAvgBytesPerSec = WaveFormatEx->nAvgBytesPerSec; - DataFormat->WaveFormatEx.wBitsPerSample = WaveFormatEx->wBitsPerSample; + DataFormat->WaveFormatEx.nChannels = min(WaveFormatEx->nChannels, DataRangeAudio->MaximumChannels); + DataFormat->WaveFormatEx.nSamplesPerSec = min(WaveFormatEx->nSamplesPerSec, DataRangeAudio->MaximumSampleFrequency); + DataFormat->WaveFormatEx.wBitsPerSample = min(WaveFormatEx->wBitsPerSample, DataRangeAudio->MaximumBitsPerSample); + DataFormat->WaveFormatEx.nBlockAlign = DataFormat->WaveFormatEx.nChannels * DataFormat->WaveFormatEx.wBitsPerSample / 8; + DataFormat->WaveFormatEx.nAvgBytesPerSec = DataFormat->WaveFormatEx.nSamplesPerSec * DataFormat->WaveFormatEx.nBlockAlign; DataFormat->WaveFormatEx.cbSize = cbSize; DataFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX) + cbSize; DataFormat->DataFormat.Flags = 0; @@ -228,6 +229,63 @@ MMixerFindAudioDataRange( return MM_STATUS_UNSUCCESSFUL; } +MIXER_STATUS +MMixerFindAvailableDataRanges( + IN PMIXER_CONTEXT MixerContext, + IN ULONG DeviceId, + IN ULONG PinId, + OUT PKSDATARANGE_AUDIO * OutDataRangeAudio) +{ + MIXER_STATUS Status; + PMIXER_LIST MixerList; + LPMIXER_DATA MixerData; + PKSMULTIPLE_ITEM MultipleItem; + PKSDATARANGE_AUDIO DataRangeAudio; + + /* grab mixer list */ + MixerList = (PMIXER_LIST)MixerContext->MixerContext; + + MixerData = MMixerGetDataByDeviceId(MixerList, DeviceId); + if (!MixerData) + return MM_STATUS_INVALID_PARAMETER; + + /* get audio pin data ranges */ + Status = MMixerGetAudioPinDataRanges(MixerContext, MixerData->hDevice, PinId, &MultipleItem); + if (Status != MM_STATUS_SUCCESS) + { + /* failed to get audio pin data ranges */ + return MM_STATUS_UNSUCCESSFUL; + } + + /* allocate data range pointer */ + DataRangeAudio = (PKSDATARANGE_AUDIO)MixerContext->Alloc(sizeof(KSDATARANGE_AUDIO)); + if (!DataRangeAudio) + { + /* no memory */ + MixerContext->Free(MultipleItem); + return MM_STATUS_NO_MEMORY; + } + + /* find an KSDATARANGE_AUDIO range */ + Status = MMixerFindAudioDataRange(MultipleItem, &DataRangeAudio); + if (Status != MM_STATUS_SUCCESS) + { + /* failed to find audio pin data range */ + MixerContext->Free(DataRangeAudio); + MixerContext->Free(MultipleItem); + return MM_STATUS_UNSUCCESSFUL; + } + + /* free dataranges buffer */ + MixerContext->Free(MultipleItem); + + /* store output */ + *OutDataRangeAudio = DataRangeAudio; + + /* done */ + return MM_STATUS_SUCCESS; +} + MIXER_STATUS MMixerOpenWavePin( IN PMIXER_CONTEXT MixerContext, @@ -242,11 +300,21 @@ MMixerOpenWavePin( { PKSPIN_CONNECT PinConnect; PKSDATAFORMAT_WAVEFORMATEX DataFormat; + PKSDATARANGE_AUDIO DataRangeAudio; LPMIXER_DATA MixerData; NTSTATUS Status; MIXER_STATUS MixerStatus; DWORD cbSize; + /* get available audio data range */ + Status = MMixerFindAvailableDataRanges(MixerContext, DeviceId, 0/*PinId*/, &DataRangeAudio); + if (Status != MM_STATUS_SUCCESS) + { + /* failed to get data range */ + DPRINT1("Failed to find data range\n"); + return MM_STATUS_UNSUCCESSFUL; + } + MixerData = MMixerGetDataByDeviceId(MixerList, DeviceId); if (!MixerData) return MM_STATUS_INVALID_PARAMETER; @@ -267,8 +335,9 @@ MMixerOpenWavePin( /* get offset to dataformat */ DataFormat = (PKSDATAFORMAT_WAVEFORMATEX) (PinConnect + 1); + /* initialize with requested wave format */ - MMixerInitializeDataFormat(DataFormat, WaveFormatEx, cbSize); + MMixerInitializeDataFormat(DataFormat, DataRangeAudio, WaveFormatEx, cbSize); if (CreateCallback) { @@ -297,11 +366,11 @@ MMixerOpenWavePin( VOID MMixerCheckFormat( IN PKSDATARANGE_AUDIO DataRangeAudio, - IN LPWAVE_INFO WaveInfo, - IN ULONG bInput) + OUT PULONG Result) { ULONG Index, SampleFrequency; - ULONG Result = 0; + + *Result = 0; for(Index = 0; Index < AUDIO_TEST_RANGE; Index++) { @@ -312,35 +381,30 @@ MMixerCheckFormat( /* the audio adapter supports the sample frequency */ if (DataRangeAudio->MinimumBitsPerSample <= 8 && DataRangeAudio->MaximumBitsPerSample >= 8) { - Result |= TestRange[Index].Bit8Mono; + *Result |= TestRange[Index].Bit8Mono; if (DataRangeAudio->MaximumChannels > 1) { /* check if pin supports the sample rate in 8-Bit Stereo */ - Result |= TestRange[Index].Bit8Stereo; + *Result |= TestRange[Index].Bit8Stereo; } } if (DataRangeAudio->MinimumBitsPerSample <= 16 && DataRangeAudio->MaximumBitsPerSample >= 16) { /* check if pin supports the sample rate in 16-Bit Mono */ - Result |= TestRange[Index].Bit16Mono; + *Result |= TestRange[Index].Bit16Mono; if (DataRangeAudio->MaximumChannels > 1) { /* check if pin supports the sample rate in 16-Bit Stereo */ - Result |= TestRange[Index].Bit16Stereo; + *Result |= TestRange[Index].Bit16Stereo; } } } } - if (bInput) - WaveInfo->u.InCaps.dwFormats = Result; - else - WaveInfo->u.OutCaps.dwFormats = Result; - - DPRINT("Format %lx bInput %u\n", Result, bInput); + DPRINT("Format %lx\n", *Result); } MIXER_STATUS @@ -353,9 +417,6 @@ MMixerInitializeWaveInfo( IN ULONG PinCount, IN PULONG Pins) { - MIXER_STATUS Status; - PKSMULTIPLE_ITEM MultipleItem; - PKSDATARANGE_AUDIO DataRangeAudio; LPWAVE_INFO WaveInfo; WaveInfo = (LPWAVE_INFO)MixerContext->Alloc(sizeof(WAVE_INFO)); @@ -371,69 +432,13 @@ MMixerInitializeWaveInfo( /* initialize wave info */ WaveInfo->DeviceId = MixerData->DeviceId; - WaveInfo->PinId = Pins[0]; + WaveInfo->PinId = 1;//Pins[0]; /* sanity check */ ASSERT(wcslen(DeviceName) < MAXPNAMELEN); /* copy device name */ - if (bWaveIn) - { - wcscpy(WaveInfo->u.InCaps.szPname, DeviceName); - } - else - { - wcscpy(WaveInfo->u.OutCaps.szPname, DeviceName); - } - - /* FIXME determine manufacturer / product id */ - if (bWaveIn) - { - WaveInfo->u.InCaps.wMid = MM_MICROSOFT; - WaveInfo->u.InCaps.wPid = MM_PID_UNMAPPED; - WaveInfo->u.InCaps.vDriverVersion = 1; - } - else - { - WaveInfo->u.OutCaps.wMid = MM_MICROSOFT; - WaveInfo->u.OutCaps.wPid = MM_PID_UNMAPPED; - WaveInfo->u.OutCaps.vDriverVersion = 1; - } - - /* get audio pin data ranges */ - Status = MMixerGetAudioPinDataRanges(MixerContext, MixerData->hDevice, Pins[0], &MultipleItem); - if (Status != MM_STATUS_SUCCESS) - { - /* failed to get audio pin data ranges */ - MixerContext->Free(WaveInfo); - return MM_STATUS_UNSUCCESSFUL; - } - - /* find an KSDATARANGE_AUDIO range */ - Status = MMixerFindAudioDataRange(MultipleItem, &DataRangeAudio); - if (Status != MM_STATUS_SUCCESS) - { - /* failed to find audio pin data range */ - MixerContext->Free(MultipleItem); - MixerContext->Free(WaveInfo); - return MM_STATUS_UNSUCCESSFUL; - } - - /* store channel count */ - if (bWaveIn) - { - WaveInfo->u.InCaps.wChannels = DataRangeAudio->MaximumChannels; - } - else - { - WaveInfo->u.OutCaps.wChannels = DataRangeAudio->MaximumChannels; - } - - /* get all supported formats */ - MMixerCheckFormat(DataRangeAudio, WaveInfo, bWaveIn); - - /* free dataranges buffer */ - MixerContext->Free(MultipleItem); + wcscpy(WaveInfo->DeviceName, DeviceName); if (bWaveIn) { @@ -507,6 +512,8 @@ MMixerWaveInCapabilities( PMIXER_LIST MixerList; MIXER_STATUS Status; LPWAVE_INFO WaveInfo; + WAVEINCAPSW WaveInCaps; + PKSDATARANGE_AUDIO DataRangeAudio; /* verify mixer context */ Status = MMixerVerifyContext(MixerContext); @@ -528,8 +535,34 @@ MMixerWaveInCapabilities( return MM_STATUS_UNSUCCESSFUL; } + /* get available audio data range */ + Status = MMixerFindAvailableDataRanges(MixerContext, WaveInfo->DeviceId, WaveInfo->PinId, &DataRangeAudio); + if (Status != MM_STATUS_SUCCESS) + { + /* failed to get data range */ + return MM_STATUS_UNSUCCESSFUL; + } + + /* FIXME determine manufacturer / product id */ + WaveInCaps.wMid = MM_MICROSOFT; + WaveInCaps.wPid = MM_MSFT_WDMAUDIO_WAVEIN; + WaveInCaps.vDriverVersion = 0x050a; + WaveInCaps.wReserved1 = 0; + + /* store channel count */ + WaveInCaps.wChannels = DataRangeAudio->MaximumChannels; + + /* get all supported formats */ + MMixerCheckFormat(DataRangeAudio, &WaveInCaps.dwFormats); + + /* copy device name */ + wcscpy(WaveInCaps.szPname, WaveInfo->DeviceName); + + /* make sure it's null terminated */ + WaveInCaps.szPname[MAXPNAMELEN-1] = L'\0'; + /* copy capabilities */ - MixerContext->Copy(Caps, &WaveInfo->u.InCaps, sizeof(WAVEINCAPSW)); + MixerContext->Copy(Caps, &WaveInCaps, sizeof(WAVEINCAPSW)); return MM_STATUS_SUCCESS; } @@ -543,6 +576,8 @@ MMixerWaveOutCapabilities( PMIXER_LIST MixerList; MIXER_STATUS Status; LPWAVE_INFO WaveInfo; + WAVEOUTCAPSW WaveOutCaps; + PKSDATARANGE_AUDIO DataRangeAudio; /* verify mixer context */ Status = MMixerVerifyContext(MixerContext); @@ -564,8 +599,35 @@ MMixerWaveOutCapabilities( return MM_STATUS_UNSUCCESSFUL; } + /* get available audio data range */ + Status = MMixerFindAvailableDataRanges(MixerContext, WaveInfo->DeviceId, WaveInfo->PinId, &DataRangeAudio); + if (Status != MM_STATUS_SUCCESS) + { + /* failed to get data range */ + return MM_STATUS_UNSUCCESSFUL; + } + + /* FIXME determine manufacturer / product id */ + WaveOutCaps.wMid = MM_MICROSOFT; + WaveOutCaps.wPid = MM_MSFT_WDMAUDIO_WAVEOUT; + WaveOutCaps.vDriverVersion = 0x050a; + WaveOutCaps.wReserved1 = 0; + WaveOutCaps.dwSupport = WAVECAPS_VOLUME | WAVECAPS_LRVOLUME | WAVECAPS_SAMPLEACCURATE; + + /* store channel count */ + WaveOutCaps.wChannels = DataRangeAudio->MaximumChannels; + + /* get all supported formats */ + MMixerCheckFormat(DataRangeAudio, &WaveOutCaps.dwFormats); + + /* copy device name */ + wcscpy(WaveOutCaps.szPname, WaveInfo->DeviceName); + + /* make sure it's null terminated */ + WaveOutCaps.szPname[MAXPNAMELEN-1] = L'\0'; + /* copy capabilities */ - MixerContext->Copy(Caps, &WaveInfo->u.OutCaps, sizeof(WAVEOUTCAPSW)); + MixerContext->Copy(Caps, &WaveOutCaps, sizeof(WAVEOUTCAPSW)); return MM_STATUS_SUCCESS; }