LONG APIENTRY DriverProc( DWORD DriverId, HANDLE DriverHandle, UINT Message, LONG Parameter1, LONG Parameter2) { MMRESULT Result; switch ( Message ) { case DRV_LOAD : { SND_TRACE(L"DRV_LOAD\n"); Result = InitEntrypointMutexes(); if ( ! MMSUCCESS(Result) ) return 0L; Result = EnumerateNt4ServiceSoundDevices(L"sndblst", 0, FoundDevice); if ( ! MMSUCCESS(Result) ) { CleanupEntrypointMutexes(); UnlistAllSoundDevices(); return 0L; } /* PSOUND_DEVICE snd; GetSoundDevice(WAVE_OUT_DEVICE_TYPE, 0, &snd); GetSoundDevice(AUX_DEVICE_TYPE, 0, &snd); GetSoundDevice(AUX_DEVICE_TYPE, 1, &snd); GetSoundDevice(AUX_DEVICE_TYPE, 2, &snd); */ SND_TRACE(L"Initialisation complete\n"); return 1L; } case DRV_FREE : { SND_TRACE(L"DRV_FREE\n"); /* TODO: Clean up the path names! */ UnlistAllSoundDevices(); CleanupEntrypointMutexes(); SND_TRACE(L"Unfreed memory blocks: %d\n", GetMemoryAllocationCount()); return 1L; } case DRV_ENABLE : case DRV_DISABLE : { SND_TRACE(L"DRV_ENABLE / DRV_DISABLE\n"); return 1L; } case DRV_OPEN : case DRV_CLOSE : { SND_TRACE(L"DRV_OPEN / DRV_CLOSE\n"); return 1L; } case DRV_QUERYCONFIGURE : { SND_TRACE(L"DRV_QUERYCONFIGURE"); return 0L; } case DRV_CONFIGURE : return DRVCNF_OK; default : SND_TRACE(L"Unhandled message %d\n", Message); return DefDriverProc(DriverId, DriverHandle, Message, Parameter1, Parameter2); } }
MMRESULT GetSoundBlasterDeviceCapabilities( IN PSOUND_DEVICE SoundDevice, IN DWORD DeviceId, OUT PVOID Capabilities, IN DWORD CapabilitiesSize) { MMRESULT Result; MMDEVICE_TYPE DeviceType; SND_ASSERT( SoundDevice ); SND_ASSERT( Capabilities ); SND_TRACE(L"Sndblst - GetSoundBlasterDeviceCapabilities\n"); Result = GetSoundDeviceType(SoundDevice, &DeviceType); SND_ASSERT( Result == MMSYSERR_NOERROR ); /* Use the default method of obtaining device capabilities */ Result = GetNt4SoundDeviceCapabilities(SoundDevice, Capabilities, CapabilitiesSize); if ( ! MMSUCCESS(Result) ) return Result; /* Inject the appropriate device name */ switch ( DeviceType ) { case WAVE_OUT_DEVICE_TYPE : { LPWAVEOUTCAPS WaveOutCaps = (LPWAVEOUTCAPS) Capabilities; CopyWideString(WaveOutCaps->szPname, SBWaveOutDeviceName); break; } case WAVE_IN_DEVICE_TYPE : { LPWAVEINCAPS WaveInCaps = (LPWAVEINCAPS) Capabilities; CopyWideString(WaveInCaps->szPname, SBWaveInDeviceName); break; } case MIDI_OUT_DEVICE_TYPE : { LPMIDIOUTCAPS MidiOutCaps = (LPMIDIOUTCAPS) Capabilities; CopyWideString(MidiOutCaps->szPname, SBMidiOutDeviceName); break; } case MIDI_IN_DEVICE_TYPE : { LPMIDIINCAPS MidiInCaps = (LPMIDIINCAPS) Capabilities; CopyWideString(MidiInCaps->szPname, SBMidiInDeviceName); break; } case AUX_DEVICE_TYPE : { LPAUXCAPS AuxCaps = (LPAUXCAPS) Capabilities; CopyWideString(AuxCaps->szPname, SBAuxDeviceName); break; } case MIXER_DEVICE_TYPE : { LPMIXERCAPS MixerCaps = (LPMIXERCAPS) Capabilities; CopyWideString(MixerCaps->szPname, SBMixerDeviceName); break; } } return MMSYSERR_NOERROR; }
/* 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); SND_TRACE(L"modMessage - Message type %d\n", Message); switch ( Message ) { case MODM_GETNUMDEVS : { Result = GetSoundDeviceCount(MIDI_OUT_DEVICE_TYPE); break; } case MODM_GETDEVCAPS : { Result = MmeGetSoundDeviceCapabilities(MIDI_OUT_DEVICE_TYPE, DeviceId, (PVOID) Parameter1, Parameter2); break; } case DRV_QUERYDEVICEINTERFACESIZE : { Result = MmeGetDeviceInterfaceString(MIDI_OUT_DEVICE_TYPE, DeviceId, NULL, 0, (DWORD*)Parameter1); //FIXME DWORD_PTR break; } case DRV_QUERYDEVICEINTERFACE : { Result = MmeGetDeviceInterfaceString(MIDI_OUT_DEVICE_TYPE, DeviceId, (LPWSTR)Parameter1, Parameter2, NULL); //FIXME DWORD_PTR break; } case MODM_OPEN : { Result = MmeOpenDevice(MIDI_OUT_DEVICE_TYPE, DeviceId, (LPWAVEOPENDESC) Parameter1, /* unused */ Parameter2, (DWORD_PTR*)PrivateHandle); break; } case MODM_CLOSE : { Result = MmeCloseDevice(PrivateHandle); break; } } SND_TRACE(L"modMessage returning MMRESULT %d\n", Result); ReleaseEntrypointMutex(MIDI_OUT_DEVICE_TYPE); return Result; }
/* Open one of the Device sub-keys belonging to the sound driver. NT4 only. */ MMRESULT OpenSoundDeviceRegKey( IN LPWSTR ServiceName, IN DWORD DeviceIndex, OUT PHKEY KeyHandle) { SIZE_T PathLength; PWCHAR RegPath; VALIDATE_MMSYS_PARAMETER( ServiceName ); VALIDATE_MMSYS_PARAMETER( KeyHandle ); /* Work out the space required to hold the path: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ sndblst\ Parameters\ Device123\ */ PathLength = wcslen(REG_SERVICES_KEY_NAME_U) + 1 + wcslen(ServiceName) + 1 + wcslen(REG_PARAMETERS_KEY_NAME_U) + 1 + wcslen(REG_DEVICE_KEY_NAME_U) + GetDigitCount(DeviceIndex); /* Allocate storage for the string */ RegPath = AllocateWideString(PathLength); if ( ! RegPath ) { return MMSYSERR_NOMEM; } /* Write the path */ wsprintf(RegPath, L"%ls\\%ls\\%ls\\%ls%d", REG_SERVICES_KEY_NAME_U, ServiceName, REG_PARAMETERS_KEY_NAME_U, REG_DEVICE_KEY_NAME_U, DeviceIndex); SND_TRACE(L"Opening reg key: %wS\n", RegPath); /* Perform the open */ if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, RegPath, 0, KEY_READ, KeyHandle) != ERROR_SUCCESS ) { /* Couldn't open the key */ SND_ERR(L"Failed to open reg key: %wS\n", RegPath); FreeMemory(RegPath); return MMSYSERR_ERROR; } FreeMemory(RegPath); return MMSYSERR_NOERROR; }
MMRESULT DestroySoundDeviceInstance( IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance) { MMRESULT Result; PMMFUNCTION_TABLE FunctionTable; PSOUND_DEVICE SoundDevice; PVOID Handle; SND_TRACE(L"Destroying a sound device instance\n"); VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) ); Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); if ( ! MMSUCCESS(Result) ) return TranslateInternalMmResult(Result); Result = GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle); if ( ! MMSUCCESS(Result) ) return TranslateInternalMmResult(Result); /* Get the "close" routine from the function table, and validate it */ Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable); if ( ! MMSUCCESS(Result) ) return TranslateInternalMmResult(Result); SND_ASSERT( FunctionTable->Close ); if ( FunctionTable->Close == NULL ) { /* This indicates bad practice, really! If you can open, why not close?! */ return MMSYSERR_NOTSUPPORTED; } /* Stop the streaming thread */ if ( SoundDeviceInstance->Thread ) { Result = DestroySoundThread(SoundDeviceInstance->Thread); SND_ASSERT( MMSUCCESS(Result) ); /* It should succeed! */ if ( ! MMSUCCESS(Result ) ) { return TranslateInternalMmResult(Result); } } /* Blank this out here */ SoundDeviceInstance->Thread = NULL; /* Try and close the device */ Result = FunctionTable->Close(SoundDeviceInstance, Handle); SND_ASSERT( MMSUCCESS(Result) ); /* It should succeed! */ if ( ! MMSUCCESS(Result) ) return TranslateInternalMmResult(Result); /* Drop it from the list */ Result = UnlistSoundDeviceInstance(SoundDeviceInstance); SND_ASSERT( MMSUCCESS(Result) ); /* It should succeed! */ if ( ! MMSUCCESS(Result) ) return TranslateInternalMmResult(Result); FreeSoundDeviceInstance(SoundDeviceInstance); return MMSYSERR_NOERROR; }
/* Provides an implementation for the "get capabilities" request, using the standard IOCTLs used by NT4 sound drivers. */ MMRESULT GetNt4SoundDeviceCapabilities( IN PSOUND_DEVICE SoundDevice, OUT PVOID Capabilities, IN DWORD CapabilitiesSize) { MMRESULT Result; MMDEVICE_TYPE DeviceType; DWORD IoCtl; HANDLE DeviceHandle; /* If these are bad there's an internal error with MME-Buddy! */ SND_ASSERT( SoundDevice ); SND_ASSERT( Capabilities ); SND_ASSERT( CapabilitiesSize > 0 ); SND_TRACE(L"NT4 get-capabilities routine called\n"); /* Get the device type */ Result = GetSoundDeviceType(SoundDevice, &DeviceType); SND_ASSERT( Result == MMSYSERR_NOERROR ); if ( ! MMSUCCESS(Result) ) return TranslateInternalMmResult(Result); /* Choose the appropriate IOCTL */ if ( IS_WAVE_DEVICE_TYPE(DeviceType) ) { IoCtl = IOCTL_WAVE_GET_CAPABILITIES; } else if ( IS_MIDI_DEVICE_TYPE(DeviceType) ) { IoCtl = IOCTL_MIDI_GET_CAPABILITIES; } else { /* FIXME - need to support AUX and mixer devices */ SND_ASSERT( FALSE ); IoCtl = 0; } /* Get the capabilities information from the driver */ Result = OpenNt4KernelSoundDevice(SoundDevice, TRUE, &DeviceHandle); if ( ! MMSUCCESS(Result) ) { SND_ERR(L"Failed to open device"); return TranslateInternalMmResult(Result); } Result = SyncOverlappedDeviceIoControl(DeviceHandle, IoCtl, Capabilities, CapabilitiesSize, NULL, 0, NULL); CloseKernelSoundDevice(DeviceHandle); if ( ! MMSUCCESS(Result) ) { SND_ERR(L"Retrieval of capabilities information failed\n"); Result = TranslateInternalMmResult(Result); } return Result; }
MMRESULT CreateSoundDeviceInstance( IN PSOUND_DEVICE SoundDevice, OUT PSOUND_DEVICE_INSTANCE* SoundDeviceInstance) { MMRESULT Result; PMMFUNCTION_TABLE FunctionTable; SND_TRACE(L"Creating a sound device instance\n"); VALIDATE_MMSYS_PARAMETER( IsValidSoundDevice(SoundDevice) ); VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance != NULL ); Result = AllocateSoundDeviceInstance(SoundDeviceInstance); if ( ! MMSUCCESS(Result) ) return TranslateInternalMmResult(Result); /* Get the "open" routine from the function table, and validate it */ Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable); if ( ! MMSUCCESS(Result) ) { FreeSoundDeviceInstance(*SoundDeviceInstance); return TranslateInternalMmResult(Result); } if ( FunctionTable->Open == NULL ) { FreeSoundDeviceInstance(*SoundDeviceInstance); return MMSYSERR_NOTSUPPORTED; } /* Set up the members of the structure */ (*SoundDeviceInstance)->Next = NULL; (*SoundDeviceInstance)->Device = SoundDevice; (*SoundDeviceInstance)->Handle = NULL; (*SoundDeviceInstance)->Thread = NULL; (*SoundDeviceInstance)->WinMM.Handle = INVALID_HANDLE_VALUE; (*SoundDeviceInstance)->WinMM.ClientCallback = 0; (*SoundDeviceInstance)->WinMM.ClientCallbackInstanceData = 0; (*SoundDeviceInstance)->WinMM.Flags = 0; /* Initialise the members of the struct used by the sound thread */ (*SoundDeviceInstance)->HeadWaveHeader = NULL; (*SoundDeviceInstance)->TailWaveHeader = NULL; (*SoundDeviceInstance)->OutstandingBuffers = 0; (*SoundDeviceInstance)->LoopsRemaining = 0; /* Create the streaming thread (TODO - is this for wave only?) */ Result = CreateSoundThread(&(*SoundDeviceInstance)->Thread); if ( ! MMSUCCESS(Result) ) { FreeSoundDeviceInstance(*SoundDeviceInstance); return TranslateInternalMmResult(Result); } /* Add the instance to the list */ Result = ListSoundDeviceInstance(SoundDevice, *SoundDeviceInstance); if ( ! MMSUCCESS(Result) ) { FreeSoundDeviceInstance(*SoundDeviceInstance); return TranslateInternalMmResult(Result); } /* Try and open the device */ Result = FunctionTable->Open(SoundDevice, (&(*SoundDeviceInstance)->Handle)); if ( ! MMSUCCESS(Result) ) { UnlistSoundDeviceInstance(*SoundDeviceInstance); FreeSoundDeviceInstance(*SoundDeviceInstance); return TranslateInternalMmResult(Result); } return MMSYSERR_NOERROR; }
MMRESULT WdmAudQueryMixerInfoByLegacy( IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, 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 ); 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; 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)); IoControlCode = IOCTL_SETCONTROLDETAILS; break; case MXDM_GETCONTROLDETAILS: RtlCopyMemory(&DeviceInfo.u.MixDetails, MixDetails, sizeof(MIXERCONTROLDETAILS)); IoControlCode = IOCTL_GETCONTROLDETAILS; break; default: SND_ASSERT(0); return MMSYSERR_NOTSUPPORTED; } Result = SyncOverlappedDeviceIoControl(KernelHandle, IoControlCode, (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), NULL); if ( ! MMSUCCESS(Result) ) { return Result; } switch(uMsg) { case MXDM_GETLINEINFO: { RtlCopyMemory(MixLine, &DeviceInfo.u.MixLine, sizeof(MIXERLINEW)); break; } } return Result; }
MMRESULT WdmAudSetWaveDeviceFormatByLegacy( IN PSOUND_DEVICE_INSTANCE Instance, IN DWORD DeviceId, IN PWAVEFORMATEX WaveFormat, IN DWORD WaveFormatSize) { MMRESULT Result; PSOUND_DEVICE SoundDevice; PVOID Identifier; WDMAUD_DEVICE_INFO DeviceInfo; MMDEVICE_TYPE DeviceType; Result = GetSoundDeviceFromInstance(Instance, &SoundDevice); if ( ! MMSUCCESS(Result) ) { return TranslateInternalMmResult(Result); } Result = GetSoundDeviceIdentifier(SoundDevice, &Identifier); if ( ! MMSUCCESS(Result) ) { return TranslateInternalMmResult(Result); } if (Instance->Handle != NULL) { /* device is already open */ return MMSYSERR_NOERROR; } Result = GetSoundDeviceType(SoundDevice, &DeviceType); SND_ASSERT( Result == MMSYSERR_NOERROR ); ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); DeviceInfo.DeviceType = DeviceType; DeviceInfo.DeviceIndex = DeviceId; DeviceInfo.u.WaveFormatEx.cbSize = sizeof(WAVEFORMATEX); //WaveFormat->cbSize; DeviceInfo.u.WaveFormatEx.wFormatTag = WaveFormat->wFormatTag; #ifdef USERMODE_MIXER DeviceInfo.u.WaveFormatEx.nChannels = 2; DeviceInfo.u.WaveFormatEx.nSamplesPerSec = 44100; DeviceInfo.u.WaveFormatEx.nBlockAlign = 4; DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = 176400; DeviceInfo.u.WaveFormatEx.wBitsPerSample = 16; #else DeviceInfo.u.WaveFormatEx.nChannels = WaveFormat->nChannels; DeviceInfo.u.WaveFormatEx.nSamplesPerSec = WaveFormat->nSamplesPerSec; DeviceInfo.u.WaveFormatEx.nBlockAlign = WaveFormat->nBlockAlign; DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec = WaveFormat->nAvgBytesPerSec; DeviceInfo.u.WaveFormatEx.wBitsPerSample = (DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec * 8) / (DeviceInfo.u.WaveFormatEx.nSamplesPerSec * DeviceInfo.u.WaveFormatEx.nChannels); #endif Result = SyncOverlappedDeviceIoControl(KernelHandle, IOCTL_OPEN_WDMAUD, (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), NULL); if ( ! MMSUCCESS(Result) ) { return TranslateInternalMmResult(Result); } 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; } /* store details */ Instance->WaveFormatEx.cbSize = sizeof(WAVEFORMATEX); Instance->WaveFormatEx.wBitsPerSample = (DeviceInfo.u.WaveFormatEx.nAvgBytesPerSec * 8) / (DeviceInfo.u.WaveFormatEx.nSamplesPerSec * DeviceInfo.u.WaveFormatEx.nChannels); /* Store sound device handle instance handle */ Instance->Handle = (PVOID)DeviceInfo.hDevice; /* Now determine framing requirements */ Result = SyncOverlappedDeviceIoControl(KernelHandle, IOCTL_GETFRAMESIZE, (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), NULL); if ( MMSUCCESS(Result) ) { if (DeviceInfo.u.FrameSize) { Instance->FrameSize = DeviceInfo.u.FrameSize * 2; Instance->BufferCount = WaveFormat->nAvgBytesPerSec / Instance->FrameSize; SND_TRACE(L"FrameSize %u BufferCount %u\n", Instance->FrameSize, Instance->BufferCount); } } else { // use a default of 100 buffers Instance->BufferCount = 100; } /* Now acquire resources */ DeviceInfo.u.State = KSSTATE_ACQUIRE; SyncOverlappedDeviceIoControl(KernelHandle, IOCTL_SETDEVICE_STATE, (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), NULL); /* pause the pin */ DeviceInfo.u.State = KSSTATE_PAUSE; SyncOverlappedDeviceIoControl(KernelHandle, IOCTL_SETDEVICE_STATE, (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), NULL); /* start the pin */ DeviceInfo.u.State = KSSTATE_RUN; SyncOverlappedDeviceIoControl(KernelHandle, IOCTL_SETDEVICE_STATE, (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), NULL); return MMSYSERR_NOERROR; }
MMRESULT WdmAudOpenSoundDeviceByLegacy( IN PSOUND_DEVICE SoundDevice, OUT PVOID *Handle) { HDEVINFO hDevInfo; SP_DEVICE_INTERFACE_DATA DeviceInterfaceData; GUID SWBusGuid = {STATIC_KSCATEGORY_WDMAUD}; PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData; if ( KernelHandle == INVALID_HANDLE_VALUE ) { hDevInfo = SetupDiGetClassDevsW(&SWBusGuid, NULL, NULL, DIGCF_DEVICEINTERFACE| DIGCF_PRESENT); if (!hDevInfo) { // failed return MMSYSERR_ERROR; } DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); if (!SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &SWBusGuid, 0, &DeviceInterfaceData)) { // failed SetupDiDestroyDeviceInfoList(hDevInfo); return MMSYSERR_ERROR; } DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)); if (!DeviceInterfaceDetailData) { // failed SetupDiDestroyDeviceInfoList(hDevInfo); return MMSYSERR_ERROR; } 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)) { // failed HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData); SetupDiDestroyDeviceInfoList(hDevInfo); return MMSYSERR_ERROR; } SND_TRACE(L"Opening wdmaud device '%s'\n",DeviceInterfaceDetailData->DevicePath); KernelHandle = CreateFileW(DeviceInterfaceDetailData->DevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData); SetupDiDestroyDeviceInfoList(hDevInfo); } if ( KernelHandle == INVALID_HANDLE_VALUE ) return MMSYSERR_ERROR; ++ OpenCount; return MMSYSERR_NOERROR; }
MMRESULT WdmAudGetCapabilitiesByLegacy( IN PSOUND_DEVICE SoundDevice, IN DWORD DeviceId, OUT PVOID Capabilities, IN DWORD CapabilitiesSize) { MMRESULT Result; MMDEVICE_TYPE DeviceType; WDMAUD_DEVICE_INFO DeviceInfo; SND_ASSERT( SoundDevice ); SND_ASSERT( Capabilities ); Result = GetSoundDeviceType(SoundDevice, &DeviceType); SND_ASSERT( Result == MMSYSERR_NOERROR ); if ( ! MMSUCCESS(Result) ) return Result; SND_TRACE(L"WDMAUD - GetWdmDeviceCapabilities DeviceType %u DeviceId %u\n", DeviceType, DeviceId); ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); DeviceInfo.DeviceType = DeviceType; DeviceInfo.DeviceIndex = DeviceId; Result = SyncOverlappedDeviceIoControl(KernelHandle, IOCTL_GETCAPABILITIES, (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), NULL); if ( ! MMSUCCESS(Result) ) { return TranslateInternalMmResult(Result); } /* This is pretty much a big hack right now */ switch ( DeviceType ) { case MIXER_DEVICE_TYPE: { LPMIXERCAPSW MixerCaps = (LPMIXERCAPSW) Capabilities; DeviceInfo.u.MixCaps.szPname[MAXPNAMELEN-1] = L'\0'; CopyWideString(MixerCaps->szPname, DeviceInfo.u.MixCaps.szPname); MixerCaps->cDestinations = DeviceInfo.u.MixCaps.cDestinations; MixerCaps->fdwSupport = DeviceInfo.u.MixCaps.fdwSupport; MixerCaps->vDriverVersion = DeviceInfo.u.MixCaps.vDriverVersion; MixerCaps->wMid = DeviceInfo.u.MixCaps.wMid; MixerCaps->wPid = DeviceInfo.u.MixCaps.wPid; break; } case WAVE_OUT_DEVICE_TYPE : { LPWAVEOUTCAPSW WaveOutCaps = (LPWAVEOUTCAPSW) Capabilities; DeviceInfo.u.WaveOutCaps.szPname[MAXPNAMELEN-1] = L'\0'; WaveOutCaps->wMid = DeviceInfo.u.WaveOutCaps.wMid; WaveOutCaps->wPid = DeviceInfo.u.WaveOutCaps.wPid; WaveOutCaps->vDriverVersion = DeviceInfo.u.WaveOutCaps.vDriverVersion; CopyWideString(WaveOutCaps->szPname, DeviceInfo.u.WaveOutCaps.szPname); WaveOutCaps->dwFormats = DeviceInfo.u.WaveOutCaps.dwFormats; WaveOutCaps->wChannels = DeviceInfo.u.WaveOutCaps.wChannels; WaveOutCaps->dwSupport = DeviceInfo.u.WaveOutCaps.dwSupport; break; } case WAVE_IN_DEVICE_TYPE : { LPWAVEINCAPSW WaveInCaps = (LPWAVEINCAPSW) Capabilities; DeviceInfo.u.WaveInCaps.szPname[MAXPNAMELEN-1] = L'\0'; WaveInCaps->wMid = DeviceInfo.u.WaveInCaps.wMid; WaveInCaps->wPid = DeviceInfo.u.WaveInCaps.wPid; WaveInCaps->vDriverVersion = DeviceInfo.u.WaveInCaps.vDriverVersion; CopyWideString(WaveInCaps->szPname, DeviceInfo.u.WaveInCaps.szPname); WaveInCaps->dwFormats = DeviceInfo.u.WaveInCaps.dwFormats; WaveInCaps->wChannels = DeviceInfo.u.WaveInCaps.wChannels; WaveInCaps->wReserved1 = 0; break; } case MIDI_IN_DEVICE_TYPE : { LPMIDIINCAPSW MidiInCaps = (LPMIDIINCAPSW)Capabilities; DeviceInfo.u.MidiInCaps.szPname[MAXPNAMELEN-1] = L'\0'; MidiInCaps->vDriverVersion = DeviceInfo.u.MidiInCaps.vDriverVersion; MidiInCaps->wMid = DeviceInfo.u.MidiInCaps.wMid; MidiInCaps->wPid = DeviceInfo.u.MidiInCaps.wPid; MidiInCaps->dwSupport = DeviceInfo.u.MidiInCaps.dwSupport; CopyWideString(MidiInCaps->szPname, DeviceInfo.u.MidiInCaps.szPname); break; } case MIDI_OUT_DEVICE_TYPE : { LPMIDIOUTCAPSW MidiOutCaps = (LPMIDIOUTCAPSW)Capabilities; DeviceInfo.u.MidiOutCaps.szPname[MAXPNAMELEN-1] = L'\0'; MidiOutCaps->vDriverVersion = DeviceInfo.u.MidiOutCaps.vDriverVersion; MidiOutCaps->wMid = DeviceInfo.u.MidiOutCaps.wMid; MidiOutCaps->wPid = DeviceInfo.u.MidiOutCaps.wPid; MidiOutCaps->dwSupport = DeviceInfo.u.MidiOutCaps.dwSupport; CopyWideString(MidiOutCaps->szPname, DeviceInfo.u.MidiOutCaps.szPname); break; } } return MMSYSERR_NOERROR; }