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; }
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; }
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; }
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 WdmAudGetDeviceInterfaceStringByLegacy( IN MMDEVICE_TYPE DeviceType, IN DWORD DeviceId, IN LPWSTR Interface, IN DWORD InterfaceLength, OUT DWORD * InterfaceSize) { WDMAUD_DEVICE_INFO DeviceInfo; MMRESULT Result; ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO)); DeviceInfo.DeviceType = DeviceType; DeviceInfo.DeviceIndex = DeviceId; Result = SyncOverlappedDeviceIoControl(KernelHandle, IOCTL_QUERYDEVICEINTERFACESTRING, (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), NULL); if ( ! MMSUCCESS(Result) ) { return TranslateInternalMmResult(Result); } if (!Interface) { SND_ASSERT(InterfaceSize); *InterfaceSize = DeviceInfo.u.Interface.DeviceInterfaceStringSize; return MMSYSERR_NOERROR; } if (InterfaceLength < DeviceInfo.u.Interface.DeviceInterfaceStringSize) { /* buffer is too small */ return MMSYSERR_MOREDATA; } DeviceInfo.u.Interface.DeviceInterfaceStringSize = InterfaceLength; DeviceInfo.u.Interface.DeviceInterfaceString = Interface; Result = SyncOverlappedDeviceIoControl(KernelHandle, IOCTL_QUERYDEVICEINTERFACESTRING, (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), (LPVOID) &DeviceInfo, sizeof(WDMAUD_DEVICE_INFO), NULL); if ( MMSUCCESS(Result) && InterfaceLength > 2) { Interface[1] = L'\\'; Interface[InterfaceLength-1] = L'\0'; } return Result; }
MMRESULT WdmAudCommitWaveBufferByLegacy( IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, IN PVOID OffsetPtr, IN DWORD Length, IN PSOUND_OVERLAPPED Overlap, IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine) { HANDLE Handle; MMRESULT Result; PWDMAUD_DEVICE_INFO DeviceInfo; PSOUND_DEVICE SoundDevice; MMDEVICE_TYPE DeviceType; BOOL Ret; VALIDATE_MMSYS_PARAMETER( SoundDeviceInstance ); VALIDATE_MMSYS_PARAMETER( OffsetPtr ); VALIDATE_MMSYS_PARAMETER( Overlap ); VALIDATE_MMSYS_PARAMETER( CompletionRoutine ); GetSoundDeviceInstanceHandle(SoundDeviceInstance, &Handle); SND_ASSERT(Handle); Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); if ( ! MMSUCCESS(Result) ) { return TranslateInternalMmResult(Result); } Result = GetSoundDeviceType(SoundDevice, &DeviceType); SND_ASSERT( Result == MMSYSERR_NOERROR ); DeviceInfo = (PWDMAUD_DEVICE_INFO)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WDMAUD_DEVICE_INFO)); if (!DeviceInfo) { // no memory return MMSYSERR_NOMEM; } DeviceInfo->Header.FrameExtent = Length; if (DeviceType == WAVE_OUT_DEVICE_TYPE) { DeviceInfo->Header.DataUsed = Length; } DeviceInfo->Header.Data = OffsetPtr; DeviceInfo->Header.Size = sizeof(WDMAUD_DEVICE_INFO); DeviceInfo->Header.PresentationTime.Numerator = 1; DeviceInfo->Header.PresentationTime.Denominator = 1; DeviceInfo->hDevice = Handle; DeviceInfo->DeviceType = DeviceType; // 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; } 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 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 WdmAudCloseSoundDeviceByLegacy( IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, IN PVOID Handle) { WDMAUD_DEVICE_INFO DeviceInfo; MMRESULT Result; MMDEVICE_TYPE DeviceType; PSOUND_DEVICE SoundDevice; Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice); if ( ! MMSUCCESS(Result) ) { return TranslateInternalMmResult(Result); } if ( OpenCount == 0 ) { return MMSYSERR_NOERROR; } SND_ASSERT( KernelHandle != INVALID_HANDLE_VALUE ); Result = GetSoundDeviceType(SoundDevice, &DeviceType); SND_ASSERT( Result == MMSYSERR_NOERROR ); 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) { SetEvent(SoundDeviceInstance->hStopEvent); CloseHandle(SoundDeviceInstance->hStopEvent); CloseHandle(SoundDeviceInstance->hNotifyEvent); } --OpenCount; if ( OpenCount < 1 ) { CloseHandle(KernelHandle); KernelHandle = INVALID_HANDLE_VALUE; } 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; }