|
|
/* Copyright (c) 1998-2001 Microsoft Corporation */ #define UNICODE
#define _UNICODE
#include "nt.h"
#include "ntrtl.h"
#include "nturtl.h"
#include "winmmi.h"
#include <mmreg.h>
#include <regstr.h>
#include <stdlib.h>
#include <tchar.h>
#include "audiosrvc.h"
extern PCWSTR waveReferenceDevInterfaceById(IN PWAVEDRV pdrvZ, IN UINT_PTR id); extern PCWSTR midiReferenceDevInterfaceById(IN PMIDIDRV pdrvZ, IN UINT_PTR id);
#define REGSTR_PATH_MULTIMEDIA_SOUNDMAPPER TEXT("Software\\Microsoft\\Multimedia\\Sound Mapper")
#define REGSTR_VAL_MULTIMEDIA_SOUNDMAPPER_PLAYBACK TEXT("Playback")
#define REGSTR_VAL_MULTIMEDIA_SOUNDMAPPER_RECORD TEXT("Record")
#define REGSTR_VAL_MULTIMEDIA_SOUNDMAPPER_CONSOLEVOICECOM_PLAYBACK TEXT("ConsoleVoiceComPlayback")
#define REGSTR_VAL_MULTIMEDIA_SOUNDMAPPER_CONSOLEVOICECOM_RECORD TEXT("ConsoleVoiceComRecord")
#define REGSTR_VAL_MULTIMEDIA_SOUNDMAPPER_PREFERREDONLY TEXT("PreferredOnly")
#define REGSTR_PATH_MEDIARESOURCES_MIDI REGSTR_PATH_MEDIARESOURCES TEXT("\\MIDI")
#define REGSTR_VAL_MEDIARESOURCES_MIDI_SUBKEY_ACTIVE TEXT("Active")
#define REGSTR_VAL_MEDIARESOURCES_MIDI_SUBKEY_DESCRIPTION TEXT("Description")
#define REGSTR_VAL_MEDIARESOURCES_MIDI_SUBKEY_DEVICEINTERFACE TEXT("DeviceInterface")
#define REGSTR_VAL_MEDIARESOURCES_MIDI_SUBKEY_PHYSDEVID TEXT("PhysDevID")
#define REGSTR_VAL_MEDIARESOURCES_MIDI_SUBKEY_PORT TEXT("Port")
#define REGSTR_PATH_MULTIMEDIA_MIDIMAP REGSTR_PATH_MULTIMEDIA TEXT("\\MIDIMap")
#define REGSTR_VAL_MULTIMEDIA_MIDIMAP_CONFIGURECOUNT TEXT("ConfigureCount")
#define REGSTR_VAL_MULTIMEDIA_MIDIMAP_USESCHEME TEXT("UseScheme")
#define REGSTR_VAL_MULTIMEDIA_MIDIMAP_DRIVERLIST TEXT("DriverList")
#define REGSTR_VAL_MULTIMEDIA_MIDIMAP_AUTOSCHEME TEXT("AutoScheme")
#define REGSTR_VAL_MULTIMEDIA_MIDIMAP_CURRENTINSTRUMENT TEXT("CurrentInstrument")
#define REGSTR_VAL_MULTIMEDIA_MIDIMAP_DEVICEINTERFACE TEXT("DeviceInterface")
#define REGSTR_VAL_MULTIMEDIA_MIDIMAP_RELATIVEINDEX TEXT("RelativeIndex")
#define REGSTR_VAL_MULTIMEDIA_MIDIMAP_SZPNAME TEXT("szPname")
#define REGSTR_VAL_SETUPPREFERREDAUDIODEVICES TEXT("SetupPreferredAudioDevices")
#define REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT TEXT("SetupPreferredAudioDevicesCount")
extern BOOL WaveMapperInitialized; // in winmm.c
extern BOOL MidiMapperInitialized; // in winmm.c
// Preferred Ids. Setting these to *_MAPPER indicates no setting.
PWSTR gpstrWoDefaultStringId = NULL; PWSTR gpstrWiDefaultStringId = NULL; PWSTR gpstrWoConsoleVoiceComStringId = NULL; PWSTR gpstrWiConsoleVoiceComStringId = NULL; BOOL gfUsePreferredWaveOnly = TRUE; PWSTR gpstrMoDefaultStringId = NULL;
// These will be TRUE if we sent the preferred device change
// to sysaudio.
BOOL gfWaveOutPreferredMessageSent = FALSE; BOOL gfWaveInPreferredMessageSent = FALSE; BOOL gfMidiOutPreferredMessageSent = FALSE;
//------------------------------------------------------------------------------
//
//
// Registry helpers
//
//
//------------------------------------------------------------------------------
LONG RegQuerySzValue(HKEY hkey, PCTSTR pValueName, PTSTR *ppstrValue) { LONG result; DWORD typeValue; DWORD cbstrValue = 0; BOOL f; result = RegQueryValueEx(hkey, pValueName, 0, &typeValue, NULL, &cbstrValue); if (ERROR_SUCCESS == result) { if (REG_SZ == typeValue) { PTSTR pstrValue; pstrValue = HeapAlloc(hHeap, 0, cbstrValue); if (pstrValue) { result = RegQueryValueEx(hkey, pValueName, 0, &typeValue, (PBYTE)pstrValue, &cbstrValue); if (ERROR_SUCCESS == result) { if (REG_SZ == typeValue) { *ppstrValue = pstrValue; } else { result = ERROR_FILE_NOT_FOUND; f = HeapFree(hHeap, 0, pstrValue); WinAssert(f); } } else { f = HeapFree(hHeap, 0, pstrValue); WinAssert(f); } } else { result = ERROR_OUTOFMEMORY; } } else { result = ERROR_FILE_NOT_FOUND; } } return result; }
LONG RegQueryDwordValue(HKEY hkey, PCTSTR pValueName, PDWORD pdwValue) { DWORD cbdwValue; LONG result;
cbdwValue = sizeof(*pdwValue); result = RegQueryValueEx(hkey, pValueName, 0, NULL, (PBYTE)pdwValue, &cbdwValue); return result; }
LONG RegSetSzValue(HKEY hkey, PCTSTR pValueName, PCTSTR pstrValue) { DWORD cbstrValue = (lstrlen(pstrValue) + 1) * sizeof(pstrValue[0]); return RegSetValueEx(hkey, pValueName, 0, REG_SZ, (PBYTE)pstrValue, cbstrValue); }
LONG RegSetDwordValue(HKEY hkey, PCTSTR pValueName, DWORD dwValue) { return RegSetValueEx(hkey, pValueName, 0, REG_DWORD, (PBYTE)&dwValue, sizeof(dwValue)); }
//------------------------------------------------------------------------------
//
//
// AutoSetupPreferredAudio functions
//
//
//------------------------------------------------------------------------------
//--------------------------------------------------------------------------;
//
// DWORD GetCurrentSetupPreferredAudioCount
//
// Arguments:
//
// Return value:
//
// History:
// 1/19/99 FrankYe Created
//
//--------------------------------------------------------------------------;
DWORD GetCurrentSetupPreferredAudioCount(void) { HKEY hkeySetupPreferredAudioDevices; DWORD SetupCount = 0; if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_MEDIARESOURCES TEXT("\\") REGSTR_VAL_SETUPPREFERREDAUDIODEVICES, 0, KEY_QUERY_VALUE, &hkeySetupPreferredAudioDevices)) { if (ERROR_SUCCESS != RegQueryDwordValue(hkeySetupPreferredAudioDevices, REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT, &SetupCount)) { Squirt("GCSPATS: Couldn't read hklm\\...\\SetupPreferredAudioDevicesCount"); } if (ERROR_SUCCESS != RegCloseKey(hkeySetupPreferredAudioDevices)) { WinAssert(!"GCSPATS: unexpected failure of RegCloseKey"); } } else { Squirt("GCSPATS: Couldn't open hklm\\...\\SetupPreferredAudioDevices"); }
return SetupCount; }
//--------------------------------------------------------------------------;
//
// DWORD GetDeviceInterfaceSetupPreferredAudioCount
//
// Arguments:
//
// Return value:
//
// History:
// 1/19/99 FrankYe Created
//
//--------------------------------------------------------------------------;
DWORD GetDeviceInterfaceSetupPreferredAudioCount(PCWSTR DeviceInterface) { PMMDEVICEINTERFACEINFO pdii; PMMPNPINFO pPnpInfo; LONG cbPnpInfo; DWORD count; int ii;
// Handle empty DeviceInterface names in case of legacy drivers
if (0 == lstrlen(DeviceInterface)) return 0;
if (ERROR_SUCCESS != winmmGetPnpInfo(&cbPnpInfo, &pPnpInfo)) return 0; pdii = (PMMDEVICEINTERFACEINFO)&(pPnpInfo[1]); pdii = PAD_POINTER(pdii);
for (ii = pPnpInfo->cDevInterfaces; ii; ii--) { // Searching for the device interface...
if (0 == lstrcmpi(pdii->szName, DeviceInterface)) break;
pdii = (PMMDEVICEINTERFACEINFO)(pdii->szName + lstrlenW(pdii->szName) + 1); pdii = PAD_POINTER(pdii); }
WinAssert(ii); count = pdii->SetupPreferredAudioCount; HeapFree(hHeap, 0, pPnpInfo);
return count; }
//------------------------------------------------------------------------------
//
//
// NotifyServerPreferredDeviceChange
//
//
//------------------------------------------------------------------------------
void NotifyServerPreferredDeviceChange(void) { winmmAdvisePreferredDeviceChange(); }
//------------------------------------------------------------------------------
//
//
// Wave
//
//
//------------------------------------------------------------------------------
MMRESULT waveWritePersistentConsoleVoiceCom(BOOL fOut, PTSTR pstrPref, BOOL fPrefOnly) { HKEY hkcu; HKEY hkSoundMapper; LONG result; BOOL fSuccess;
if (!NT_SUCCESS(RtlOpenCurrentUser(GENERIC_WRITE, &hkcu))) return MMSYSERR_WRITEERROR;
result = RegCreateKeyEx(hkcu, REGSTR_PATH_MULTIMEDIA_SOUNDMAPPER, 0, TEXT("\0"), REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hkSoundMapper, NULL); if (ERROR_SUCCESS == result) { DWORD cbstrPref;
cbstrPref = (lstrlen(pstrPref) + 1) * sizeof(pstrPref[0]);
if (fOut) { result = RegSetSzValue(hkSoundMapper, REGSTR_VAL_MULTIMEDIA_SOUNDMAPPER_CONSOLEVOICECOM_PLAYBACK, pstrPref); } else { result = RegSetSzValue(hkSoundMapper, REGSTR_VAL_MULTIMEDIA_SOUNDMAPPER_CONSOLEVOICECOM_RECORD, pstrPref); }
if (ERROR_SUCCESS == result) { fSuccess = TRUE; result = RegSetDwordValue(hkSoundMapper, REGSTR_VAL_MULTIMEDIA_SOUNDMAPPER_PREFERREDONLY, (DWORD)fPrefOnly); if (ERROR_SUCCESS != result) { Squirt("wWPCVC: Could not write hkcu\\...\\Sound Mapper\\PreferredOnly"); } result = RegSetDwordValue(hkSoundMapper, REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT, GetCurrentSetupPreferredAudioCount()); if (ERROR_SUCCESS != result) { Squirt("wWPCVC: Could not write hkcu\\...\\Sound Mapper\\SetupPreferredAudioCount"); } } result = RegCloseKey(hkSoundMapper); WinAssert(ERROR_SUCCESS == result); }
NtClose(hkcu);
return MMSYSERR_NOERROR; }
BOOL waveReadPersistentConsoleVoiceCom(BOOL fOut, PTSTR *ppstrPref, PBOOL pfPrefOnly, PDWORD pSetupCount) { HKEY hkcu; HKEY hkSoundMapper; LONG result; BOOL fSuccess;
fSuccess = FALSE;
*ppstrPref = NULL; *pfPrefOnly = FALSE; *pSetupCount = 0;
if (!NT_SUCCESS(RtlOpenCurrentUser(GENERIC_READ, &hkcu))) return FALSE;
result = RegOpenKeyEx(hkcu, REGSTR_PATH_MULTIMEDIA_SOUNDMAPPER, 0, KEY_QUERY_VALUE, &hkSoundMapper); if (ERROR_SUCCESS == result) { DWORD SetupCount;
result = RegQueryDwordValue(hkSoundMapper, REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT, &SetupCount); SetupCount = (ERROR_SUCCESS == result) ? SetupCount : 0; if (ERROR_SUCCESS == result) { PTSTR pstrPref; BOOL fPrefOnly; DWORD dwPrefOnly;
result = RegQueryDwordValue(hkSoundMapper, REGSTR_VAL_MULTIMEDIA_SOUNDMAPPER_PREFERREDONLY, &dwPrefOnly); fPrefOnly = (ERROR_SUCCESS == result) ? (0 != dwPrefOnly) : FALSE;
if (fOut) { result = RegQuerySzValue(hkSoundMapper, REGSTR_VAL_MULTIMEDIA_SOUNDMAPPER_CONSOLEVOICECOM_PLAYBACK, &pstrPref); } else { result = RegQuerySzValue(hkSoundMapper, REGSTR_VAL_MULTIMEDIA_SOUNDMAPPER_CONSOLEVOICECOM_RECORD, &pstrPref); } if (ERROR_SUCCESS != result) pstrPref = NULL;
*ppstrPref = pstrPref; *pfPrefOnly = fPrefOnly; *pSetupCount = SetupCount; fSuccess = TRUE; } result = RegCloseKey(hkSoundMapper); WinAssert(ERROR_SUCCESS == result); }
NtClose(hkcu);
return fSuccess; }
MMRESULT wavePickBestConsoleVoiceComId(BOOL fOut, PUINT pPrefId, PDWORD pdwFlags) { PTSTR pstrPref; UINT cWaveId; UINT WaveId; UINT UserSelectedId; UINT NonConsoleId; UINT PreferredId; DWORD UserSelectedIdSetupCount; BOOL fPrefOnly; BOOL f;
UserSelectedId = WAVE_MAPPER;
if (fOut) { waveOutGetCurrentPreferredId(&NonConsoleId, NULL); cWaveId = waveOutGetNumDevs();
waveReadPersistentConsoleVoiceCom(fOut, &pstrPref, &fPrefOnly, &UserSelectedIdSetupCount);
*pdwFlags = fPrefOnly ? DRVM_MAPPER_PREFERRED_FLAGS_PREFERREDONLY : 0;
for (WaveId = cWaveId-1; ((int)WaveId) >= 0; WaveId--) { WAVEOUTCAPS wc; MMRESULT mmr;
mmr = waveOutGetDevCaps(WaveId, &wc, sizeof(wc)); if (mmr) continue;
wc.szPname[MAXPNAMELEN-1] = TEXT('\0');
if (pstrPref && !lstrcmp(wc.szPname, pstrPref)) { UserSelectedId = WaveId; break; } } } else { waveInGetCurrentPreferredId(&NonConsoleId, NULL); cWaveId = waveInGetNumDevs();
waveReadPersistentConsoleVoiceCom(fOut, &pstrPref, &fPrefOnly, &UserSelectedIdSetupCount);
*pdwFlags = fPrefOnly ? DRVM_MAPPER_PREFERRED_FLAGS_PREFERREDONLY : 0;
for (WaveId = cWaveId-1; ((int)WaveId) >= 0; WaveId--) { WAVEINCAPS wc; MMRESULT mmr;
mmr = waveInGetDevCaps(WaveId, &wc, sizeof(wc)); if (mmr) continue;
wc.szPname[MAXPNAMELEN-1] = TEXT('\0');
if (pstrPref && !lstrcmp(wc.szPname, pstrPref)) { UserSelectedId = WaveId; break; } } }
if (pstrPref) { f = HeapFree(hHeap, 0, pstrPref); WinAssert(f); pstrPref = NULL; }
PreferredId = ((WAVE_MAPPER == UserSelectedId)?NonConsoleId:UserSelectedId);
*pPrefId = PreferredId; return MMSYSERR_NOERROR; }
//------------------------------------------------------------------------------
//
//
// WaveOut
//
//
//------------------------------------------------------------------------------
DWORD waveOutGetSetupPreferredAudioCount(UINT WaveId) { PCWSTR DeviceInterface; DWORD dwCount;
DeviceInterface = waveReferenceDevInterfaceById(&waveoutdrvZ, WaveId);
if(DeviceInterface == NULL) { return 0; }
dwCount = GetDeviceInterfaceSetupPreferredAudioCount(DeviceInterface); wdmDevInterfaceDec(DeviceInterface); return dwCount; }
MMRESULT waveOutSendPreferredMessage(BOOL fClear) { PCWSTR DeviceInterface; UINT WaveId, Flags; MMRESULT mmr;
if(!gfLogon) { return MMSYSERR_NOERROR; }
waveOutGetCurrentPreferredId(&WaveId, &Flags);
//Squirt("waveOutSendPreferredMessage: id %d f %d", WaveId, fClear);
if(WaveId == WAVE_MAPPER) { return MMSYSERR_NOERROR; }
DeviceInterface = waveReferenceDevInterfaceById(&waveoutdrvZ, WaveId);
if(DeviceInterface == NULL) { return MMSYSERR_NOERROR; }
gfWaveOutPreferredMessageSent = TRUE;
mmr = waveOutMessage((HWAVEOUT)(UINT_PTR)WaveId, WODM_PREFERRED, (DWORD_PTR)fClear, (DWORD_PTR)DeviceInterface); wdmDevInterfaceDec(DeviceInterface); return mmr; }
BOOL waveOutReadPersistentPref(PTSTR *ppstrPref, PBOOL pfPrefOnly, PDWORD pSetupCount) { HKEY hkcu; HKEY hkSoundMapper; LONG result; BOOL fSuccess;
fSuccess = FALSE;
*ppstrPref = NULL; *pfPrefOnly = FALSE; *pSetupCount = 0;
if (!NT_SUCCESS(RtlOpenCurrentUser(GENERIC_READ, &hkcu))) return FALSE;
result = RegOpenKeyEx(hkcu, REGSTR_PATH_MULTIMEDIA_SOUNDMAPPER, 0, KEY_QUERY_VALUE, &hkSoundMapper); if (ERROR_SUCCESS == result) { DWORD SetupCount;
result = RegQueryDwordValue(hkSoundMapper, REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT, &SetupCount); SetupCount = (ERROR_SUCCESS == result) ? SetupCount : 0; if (ERROR_SUCCESS == result) { PTSTR pstrPref; BOOL fPrefOnly; DWORD dwPrefOnly;
result = RegQueryDwordValue(hkSoundMapper, REGSTR_VAL_MULTIMEDIA_SOUNDMAPPER_PREFERREDONLY, &dwPrefOnly); fPrefOnly = (ERROR_SUCCESS == result) ? (0 != dwPrefOnly) : FALSE;
result = RegQuerySzValue(hkSoundMapper, REGSTR_VAL_MULTIMEDIA_SOUNDMAPPER_PLAYBACK, &pstrPref); if (ERROR_SUCCESS != result) pstrPref = NULL;
*ppstrPref = pstrPref; *pfPrefOnly = fPrefOnly; *pSetupCount = SetupCount; fSuccess = TRUE; } result = RegCloseKey(hkSoundMapper); WinAssert(ERROR_SUCCESS == result); }
NtClose(hkcu);
return fSuccess; }
MMRESULT waveOutPickBestId(PUINT pPrefId, PDWORD pdwFlags) { PTSTR pstrPref; UINT cWaveId; UINT WaveId; UINT MappableId; UINT MixableId; UINT UserSelectedId; UINT PreferredId; DWORD WaveIdSetupCount; DWORD MappableIdSetupCount; DWORD MixableIdSetupCount; DWORD UserSelectedIdSetupCount; DWORD PreferredIdSetupCount; BOOL fPrefOnly; BOOL f;
MappableId = WAVE_MAPPER; MixableId = WAVE_MAPPER; UserSelectedId = WAVE_MAPPER; PreferredId = WAVE_MAPPER;
MappableIdSetupCount = 0; MixableIdSetupCount = 0; UserSelectedIdSetupCount = 0; PreferredIdSetupCount = 0;
cWaveId = waveOutGetNumDevs();
waveOutReadPersistentPref(&pstrPref, &fPrefOnly, &UserSelectedIdSetupCount);
*pdwFlags = fPrefOnly ? DRVM_MAPPER_PREFERRED_FLAGS_PREFERREDONLY : 0;
for (WaveId = cWaveId-1; ((int)WaveId) >= 0; WaveId--) { WAVEOUTCAPS wc; UINT uMixerId; MMRESULT mmr; PWAVEDRV pdrv; BOOL fThisSession;
//
// check the protocol name
// mask all inappropriate TS/non-TS drivers
//
if (waveReferenceDriverById(&waveoutdrvZ, WaveId, &pdrv, NULL)) continue; fThisSession = !lstrcmpW(pdrv->wszSessProtocol, SessionProtocolName); mregDecUsagePtr(pdrv); if (!fThisSession) continue;
mmr = waveOutGetDevCaps(WaveId, &wc, sizeof(wc)); if (mmr) continue;
wc.szPname[MAXPNAMELEN-1] = TEXT('\0');
if (pstrPref && !lstrcmp(wc.szPname, pstrPref)) UserSelectedId = WaveId;
WaveIdSetupCount = waveOutGetSetupPreferredAudioCount(WaveId);
mmr = waveOutMessage((HWAVEOUT)(UINT_PTR)WaveId, DRV_QUERYMAPPABLE, 0L, 0L); if (mmr) continue;
if (WaveIdSetupCount >= MappableIdSetupCount) { MappableId = WaveId; MappableIdSetupCount = WaveIdSetupCount; }
mmr = mixerGetID((HMIXEROBJ)(UINT_PTR)WaveId, &uMixerId, MIXER_OBJECTF_WAVEOUT); if (mmr) continue;
if (WaveIdSetupCount >= MixableIdSetupCount) { MixableId = WaveId; MixableIdSetupCount = WaveIdSetupCount; } }
if (pstrPref) { f = HeapFree(hHeap, 0, pstrPref); WinAssert(f); pstrPref = NULL; }
PreferredId = MappableId; PreferredIdSetupCount = MappableIdSetupCount; if ((MixableIdSetupCount >= PreferredIdSetupCount) && (WAVE_MAPPER != MixableId)) { PreferredId = MixableId; PreferredIdSetupCount = MixableIdSetupCount; } if ((UserSelectedIdSetupCount >= PreferredIdSetupCount) && (WAVE_MAPPER != UserSelectedId)) { PreferredId = UserSelectedId; PreferredIdSetupCount = UserSelectedIdSetupCount; }
*pPrefId = PreferredId; return MMSYSERR_NOERROR; }
void waveOutGetCurrentPreferredId(PUINT pPrefId, PDWORD pdwFlags) { *pPrefId = WAVE_MAPPER; if (pdwFlags) *pdwFlags = gfUsePreferredWaveOnly ? DRVM_MAPPER_PREFERRED_FLAGS_PREFERREDONLY : 0; if (gpstrWoDefaultStringId) mregGetIdFromStringId(&waveoutdrvZ, gpstrWoDefaultStringId, pPrefId); return; }
BOOL waveOutWritePersistentPref(PTSTR pstrPref, BOOL fPrefOnly) { HKEY hkcu; HKEY hkSoundMapper; LONG result; BOOL fSuccess;
if (!NT_SUCCESS(RtlOpenCurrentUser(GENERIC_WRITE, &hkcu))) return MMSYSERR_WRITEERROR;
result = RegCreateKeyEx(hkcu, REGSTR_PATH_MULTIMEDIA_SOUNDMAPPER, 0, TEXT("\0"), REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hkSoundMapper, NULL); if (ERROR_SUCCESS == result) { DWORD cbstrPref;
cbstrPref = (lstrlen(pstrPref) + 1) * sizeof(pstrPref[0]); result = RegSetSzValue(hkSoundMapper, REGSTR_VAL_MULTIMEDIA_SOUNDMAPPER_PLAYBACK, pstrPref); if (ERROR_SUCCESS == result) { fSuccess = TRUE; result = RegSetDwordValue(hkSoundMapper, REGSTR_VAL_MULTIMEDIA_SOUNDMAPPER_PREFERREDONLY, (DWORD)fPrefOnly); if (ERROR_SUCCESS != result) { Squirt("wOWPP: Could not write hkcu\\...\\Sound Mapper\\PreferredOnly"); } result = RegSetDwordValue(hkSoundMapper, REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT, GetCurrentSetupPreferredAudioCount()); if (ERROR_SUCCESS != result) { Squirt("wOWPP: Could not write hkcu\\...\\Sound Mapper\\SetupPreferredAudioCount"); } } result = RegCloseKey(hkSoundMapper); WinAssert(ERROR_SUCCESS == result); }
NtClose(hkcu);
return MMSYSERR_NOERROR; }
MMRESULT waveOutSetCurrentPreferredId(UINT PrefId, DWORD dwFlags) { MMRESULT mmr; WinAssert(PrefId < wTotalWaveOutDevs || PrefId == WAVE_MAPPER);
mmr = MMSYSERR_NOERROR;
if (gpstrWoDefaultStringId) HeapFree(hHeap, 0, gpstrWoDefaultStringId); gpstrWoDefaultStringId = NULL; if (wTotalWaveOutDevs) { UINT mixerId; PWAVEDRV pwavedrv; UINT port; mmr = waveReferenceDriverById(&waveoutdrvZ, PrefId, &pwavedrv, &port); if (!mmr) { mmr = mregCreateStringIdFromDriverPort(pwavedrv, port, &gpstrWoDefaultStringId, NULL); if (!mmr) { if (!gfDisablePreferredDeviceReordering) { // Rearrange some of the driver list so that the preferred waveOut
// device and its associated mixer device have a good chance of
// having device ID 0
mmr = mixerGetID((HMIXEROBJ)(UINT_PTR)PrefId, &mixerId, MIXER_OBJECTF_WAVEOUT); if (mmr) mixerId = 0; if (0 != PrefId) { // Move the wave driver to the head of this list. This usually
// makes the preferred device have ID 0.
EnterNumDevs("waveOutSetCurrentPreferredId"); pwavedrv->Prev->Next = pwavedrv->Next; pwavedrv->Next->Prev = pwavedrv->Prev; pwavedrv->Next = waveoutdrvZ.Next; pwavedrv->Prev = &waveoutdrvZ; waveoutdrvZ.Next->Prev = pwavedrv; waveoutdrvZ.Next = pwavedrv; LeaveNumDevs("waveOutSetCurrentPreferredId"); mregDecUsagePtr(pwavedrv); } if (0 != mixerId) { PMIXERDRV pmixerdrv; mmr = mixerReferenceDriverById(mixerId, &pmixerdrv, NULL); if (!mmr) { EnterNumDevs("waveOutSetCurrentPreferredId"); pmixerdrv->Prev->Next = pmixerdrv->Next; pmixerdrv->Next->Prev = pmixerdrv->Prev; pmixerdrv->Next = mixerdrvZ.Next; pmixerdrv->Prev = &mixerdrvZ; mixerdrvZ.Next->Prev = pmixerdrv; mixerdrvZ.Next = pmixerdrv; LeaveNumDevs("waveOutSetCurrentPreferredId"); mregDecUsagePtr(pmixerdrv); } } }
// Errors in this body are not critical
mmr = MMSYSERR_NOERROR; } } }
if (!mmr) { gfUsePreferredWaveOnly = (0 != (dwFlags & DRVM_MAPPER_PREFERRED_FLAGS_PREFERREDONLY));
// Reconfigure the mapper only if it was already loaded. Don't cause it to
// load simply so that we can reconfigure it!
if (WaveMapperInitialized) waveOutMessage((HWAVEOUT)(UINT_PTR)WAVE_MAPPER, DRVM_MAPPER_RECONFIGURE, 0, 0); }
return mmr; }
MMRESULT waveOutSetPersistentPreferredId(UINT PrefId, DWORD dwFlags) { MMRESULT mmr; WAVEOUTCAPS woc;
if (0 != (dwFlags & ~DRVM_MAPPER_PREFERRED_FLAGS_PREFERREDONLY)) return MMSYSERR_INVALPARAM; mmr = waveOutGetDevCaps(PrefId, &woc, sizeof(woc)); if (!mmr) { woc.szPname[MAXPNAMELEN-1] = TEXT('\0'); mmr = waveOutWritePersistentPref(woc.szPname, 0 != (dwFlags & 0x00000001)); if (!mmr) { NotifyServerPreferredDeviceChange(); } else { Squirt("waveOutSetPersistentPreferredId: waveOutWritePersistenPref failed, mmr=%08Xh", mmr); } }
return mmr; }
void waveOutGetCurrentConsoleVoiceComId(PUINT pPrefId, PDWORD pdwFlags) { *pPrefId = WAVE_MAPPER; *pdwFlags = gfUsePreferredWaveOnly ? DRVM_MAPPER_PREFERRED_FLAGS_PREFERREDONLY : 0; if (gpstrWoConsoleVoiceComStringId) mregGetIdFromStringId(&waveoutdrvZ, gpstrWoConsoleVoiceComStringId, pPrefId); return; }
MMRESULT waveOutSetPersistentConsoleVoiceComId(UINT PrefId, DWORD dwFlags) { MMRESULT mmr; WAVEOUTCAPS woc;
if (0 != (dwFlags & ~DRVM_MAPPER_PREFERRED_FLAGS_PREFERREDONLY)) return MMSYSERR_INVALPARAM; mmr = waveOutGetDevCaps(PrefId, &woc, sizeof(woc)); if (!mmr) { woc.szPname[MAXPNAMELEN-1] = TEXT('\0'); mmr = waveWritePersistentConsoleVoiceCom(TRUE, woc.szPname, 0 != (dwFlags & 0x00000001)); if (!mmr) { NotifyServerPreferredDeviceChange(); } else { Squirt("waveOutSetPersistentConsoleVoiceComId: waveWritePersistentConsoleVoiceCom failed, mmr=%08Xh", mmr); } }
return mmr; }
MMRESULT waveOutSetCurrentConsoleVoiceComId(UINT PrefId, DWORD dwFlags) { MMRESULT mmr;
WinAssert(PrefId < wTotalWaveOutDevs || PrefId == WAVE_MAPPER);
mmr = MMSYSERR_NOERROR;
if (gpstrWoConsoleVoiceComStringId) HeapFree(hHeap, 0, gpstrWoConsoleVoiceComStringId); gpstrWoConsoleVoiceComStringId = NULL; if (wTotalWaveOutDevs) { PWAVEDRV pwavedrv; UINT port; mmr = waveReferenceDriverById(&waveoutdrvZ, PrefId, &pwavedrv, &port); if (!mmr) { mregCreateStringIdFromDriverPort(pwavedrv, port, &gpstrWoConsoleVoiceComStringId, NULL); gfUsePreferredWaveOnly = (0 != (dwFlags & DRVM_MAPPER_PREFERRED_FLAGS_PREFERREDONLY)); } }
return mmr; }
//------------------------------------------------------------------------------
//
//
// WaveIn
//
//
//------------------------------------------------------------------------------
DWORD waveInGetSetupPreferredAudioCount(UINT WaveId) { PCWSTR DeviceInterface; DWORD dwCount;
DeviceInterface = waveReferenceDevInterfaceById(&waveindrvZ, WaveId);
if(DeviceInterface == NULL) { return 0; }
dwCount = GetDeviceInterfaceSetupPreferredAudioCount(DeviceInterface); wdmDevInterfaceDec(DeviceInterface); return dwCount; }
MMRESULT waveInSendPreferredMessage(BOOL fClear) { PCWSTR DeviceInterface; UINT WaveId, Flags; MMRESULT mmr;
if(!gfLogon) { return MMSYSERR_NOERROR; }
waveInGetCurrentPreferredId(&WaveId, &Flags);
//Squirt("waveInSendPreferredMessage: id %d f %d", WaveId, fClear);
if(WaveId == WAVE_MAPPER) { return MMSYSERR_NOERROR; }
DeviceInterface = waveReferenceDevInterfaceById(&waveindrvZ, WaveId);
if(DeviceInterface == NULL) { return MMSYSERR_NOERROR; }
gfWaveInPreferredMessageSent = TRUE;
mmr = waveInMessage((HWAVEIN)(UINT_PTR)WaveId, WIDM_PREFERRED, (DWORD_PTR)fClear, (DWORD_PTR)DeviceInterface); wdmDevInterfaceDec(DeviceInterface); return mmr; }
BOOL waveInReadPersistentPref(PTSTR *ppstrPref, PBOOL pfPrefOnly, PDWORD pSetupCount) { HKEY hkcu; HKEY hkSoundMapper; LONG result; BOOL fSuccess;
fSuccess = FALSE; *ppstrPref = NULL; *pfPrefOnly = FALSE; *pSetupCount = 0;
if (!NT_SUCCESS(RtlOpenCurrentUser(GENERIC_READ, &hkcu))) return FALSE;
result = RegOpenKeyEx(hkcu, REGSTR_PATH_MULTIMEDIA_SOUNDMAPPER, 0, KEY_QUERY_VALUE, &hkSoundMapper); if (ERROR_SUCCESS == result) { DWORD SetupCount;
result = RegQueryDwordValue(hkSoundMapper, REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT, &SetupCount); SetupCount = (ERROR_SUCCESS == result) ? SetupCount : 0; if (ERROR_SUCCESS == result) { PTSTR pstrPref; BOOL fPrefOnly; DWORD dwPrefOnly;
result = RegQueryDwordValue(hkSoundMapper, REGSTR_VAL_MULTIMEDIA_SOUNDMAPPER_PREFERREDONLY, &dwPrefOnly); fPrefOnly = (ERROR_SUCCESS == result) ? (0 != dwPrefOnly) : FALSE;
result = RegQuerySzValue(hkSoundMapper, REGSTR_VAL_MULTIMEDIA_SOUNDMAPPER_RECORD, &pstrPref); if (ERROR_SUCCESS != result) pstrPref = NULL;
*ppstrPref = pstrPref; *pfPrefOnly = fPrefOnly; *pSetupCount = SetupCount; fSuccess = TRUE; } result = RegCloseKey(hkSoundMapper); WinAssert(ERROR_SUCCESS == result); }
NtClose(hkcu);
return fSuccess; }
MMRESULT waveInPickBestId(PUINT pPrefId, PDWORD pdwFlags) { PTSTR pstrPref; UINT cWaveId; UINT WaveId; UINT MappableId; UINT MixableId; UINT UserSelectedId; UINT PreferredId; DWORD WaveIdSetupCount; DWORD MappableIdSetupCount; DWORD MixableIdSetupCount; DWORD UserSelectedIdSetupCount; DWORD PreferredIdSetupCount; BOOL fPrefOnly; BOOL f;
MappableId = WAVE_MAPPER; MixableId = WAVE_MAPPER; UserSelectedId = WAVE_MAPPER; PreferredId = WAVE_MAPPER; MappableIdSetupCount = 0; MixableIdSetupCount = 0; UserSelectedIdSetupCount = 0; PreferredIdSetupCount = 0; cWaveId = waveInGetNumDevs();
waveInReadPersistentPref(&pstrPref, &fPrefOnly, &UserSelectedIdSetupCount);
*pdwFlags = fPrefOnly ? DRVM_MAPPER_PREFERRED_FLAGS_PREFERREDONLY : 0;
for (WaveId = cWaveId-1; ((int)WaveId) >= 0; WaveId--) { WAVEINCAPS wic; UINT uMixerId; MMRESULT mmr;
mmr = waveInGetDevCaps(WaveId, &wic, sizeof(wic)); if (MMSYSERR_NOERROR != mmr) continue;
wic.szPname[MAXPNAMELEN-1] = TEXT('\0');
if (pstrPref && !lstrcmp(wic.szPname, pstrPref)) UserSelectedId = WaveId;
WaveIdSetupCount = waveInGetSetupPreferredAudioCount(WaveId);
mmr = waveInMessage((HWAVEIN)(UINT_PTR)WaveId, DRV_QUERYMAPPABLE, 0L, 0L); if (MMSYSERR_NOERROR != mmr) continue;
if (WaveIdSetupCount >= MappableIdSetupCount) { MappableId = WaveId; MappableIdSetupCount = WaveIdSetupCount; }
mmr = mixerGetID((HMIXEROBJ)(UINT_PTR)WaveId, &uMixerId, MIXER_OBJECTF_WAVEIN); if (MMSYSERR_NOERROR != mmr) continue;
if (WaveIdSetupCount >= MixableIdSetupCount) { MixableId = WaveId; MixableIdSetupCount = WaveIdSetupCount; } }
if (pstrPref) { f = HeapFree(hHeap, 0, pstrPref); WinAssert(f); pstrPref = NULL; }
PreferredId = MappableId; PreferredIdSetupCount = MappableIdSetupCount; if ((MixableIdSetupCount >= PreferredIdSetupCount) && (WAVE_MAPPER != MixableId)) { PreferredId = MixableId; PreferredIdSetupCount = MixableIdSetupCount; } if ((UserSelectedIdSetupCount >= PreferredIdSetupCount) && (WAVE_MAPPER != UserSelectedId)) { PreferredId = UserSelectedId; PreferredIdSetupCount = UserSelectedIdSetupCount; }
*pPrefId = PreferredId; return MMSYSERR_NOERROR; }
void waveInGetCurrentPreferredId(PUINT pPrefId, PDWORD pdwFlags) { *pPrefId = WAVE_MAPPER; if (pdwFlags) *pdwFlags = gfUsePreferredWaveOnly ? DRVM_MAPPER_PREFERRED_FLAGS_PREFERREDONLY : 0; if (gpstrWiDefaultStringId) mregGetIdFromStringId(&waveindrvZ, gpstrWiDefaultStringId, pPrefId); return; }
BOOL waveInWritePersistentPref(PTSTR pstrPref, BOOL fPrefOnly) { HKEY hkcu; HKEY hkSoundMapper; LONG result; BOOL fSuccess;
if (!NT_SUCCESS(RtlOpenCurrentUser(GENERIC_WRITE, &hkcu))) return MMSYSERR_WRITEERROR;
result = RegCreateKeyEx(hkcu, REGSTR_PATH_MULTIMEDIA_SOUNDMAPPER, 0, TEXT("\0"), REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hkSoundMapper, NULL); if (ERROR_SUCCESS == result) { DWORD cbstrPref;
cbstrPref = (lstrlen(pstrPref) + 1) * sizeof(pstrPref[0]); result = RegSetSzValue(hkSoundMapper, REGSTR_VAL_MULTIMEDIA_SOUNDMAPPER_RECORD, pstrPref); if (ERROR_SUCCESS == result) { fSuccess = TRUE; result = RegSetDwordValue(hkSoundMapper, REGSTR_VAL_MULTIMEDIA_SOUNDMAPPER_PREFERREDONLY, (DWORD)fPrefOnly); if (ERROR_SUCCESS != result) { Squirt("wiWPP: Could not write hkcu\\...\\Sound Mapper\\PreferredOnly"); } result = RegSetDwordValue(hkSoundMapper, REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT, GetCurrentSetupPreferredAudioCount()); if (ERROR_SUCCESS != result) { Squirt("wiWPP: Could not write hkcu\\...\\Sound Mapper\\SetupPreferredAudioCount"); } } result = RegCloseKey(hkSoundMapper); WinAssert(ERROR_SUCCESS == result); }
NtClose(hkcu);
return MMSYSERR_NOERROR; }
MMRESULT waveInSetCurrentPreferredId(UINT PrefId, DWORD dwFlags) { MMRESULT mmr; WinAssert(PrefId < wTotalWaveInDevs || PrefId == WAVE_MAPPER);
mmr = MMSYSERR_NOERROR;
if (gpstrWiDefaultStringId) HeapFree(hHeap, 0, gpstrWiDefaultStringId); gpstrWiDefaultStringId = NULL; if (wTotalWaveInDevs) { PWAVEDRV pwavedrv; UINT port; mmr = waveReferenceDriverById(&waveindrvZ, PrefId, &pwavedrv, &port); if (!mmr) { mmr = mregCreateStringIdFromDriverPort(pwavedrv, port, &gpstrWiDefaultStringId, NULL); if (!mmr) { if (!gfDisablePreferredDeviceReordering) { // Rearrange some of the driver list so that the preferred waveIn
// device has a good chance of having device ID 0
if (0 != PrefId) { // Move the wave driver to the head of this list. This usually
// makes the preferred device have ID 0.
EnterNumDevs("waveInSetCurrentPreferredId"); pwavedrv->Prev->Next = pwavedrv->Next; pwavedrv->Next->Prev = pwavedrv->Prev; pwavedrv->Next = waveindrvZ.Next; pwavedrv->Prev = &waveindrvZ; waveindrvZ.Next->Prev = pwavedrv; waveindrvZ.Next = pwavedrv; LeaveNumDevs("waveInSetCurrentPreferredId"); mregDecUsagePtr(pwavedrv); } } } } }
if (!mmr) { gfUsePreferredWaveOnly = (0 != (dwFlags & DRVM_MAPPER_PREFERRED_FLAGS_PREFERREDONLY));
// Reconfigure the mapper only if it was already loaded. Don't cause it to
// load simply so that we can reconfigure it!
if (WaveMapperInitialized) waveInMessage((HWAVEIN)(UINT_PTR)WAVE_MAPPER, DRVM_MAPPER_RECONFIGURE, 0, 0); }
return mmr; }
MMRESULT waveInSetPersistentPreferredId(UINT PrefId, DWORD dwFlags) { MMRESULT mmr; WAVEINCAPS wc;
if (0 != (dwFlags & ~DRVM_MAPPER_PREFERRED_FLAGS_PREFERREDONLY)) return MMSYSERR_INVALPARAM;
mmr = waveInGetDevCaps(PrefId, &wc, sizeof(wc)); if (!mmr) { wc.szPname[MAXPNAMELEN-1] = TEXT('\0'); mmr = waveInWritePersistentPref(wc.szPname, 0 != (dwFlags & DRVM_MAPPER_PREFERRED_FLAGS_PREFERREDONLY)); if (!mmr) { NotifyServerPreferredDeviceChange(); } else { Squirt("waveInSetPersistentPreferredId: waveInWritePersistenPref failed, mmr=%08Xh", mmr); } }
return mmr; }
void waveInGetCurrentConsoleVoiceComId(PUINT pPrefId, PDWORD pdwFlags) { *pPrefId = WAVE_MAPPER; *pdwFlags = gfUsePreferredWaveOnly ? DRVM_MAPPER_PREFERRED_FLAGS_PREFERREDONLY : 0; if (gpstrWiConsoleVoiceComStringId) mregGetIdFromStringId(&waveindrvZ, gpstrWiConsoleVoiceComStringId, pPrefId); return; }
MMRESULT waveInSetPersistentConsoleVoiceComId(UINT PrefId, DWORD dwFlags) { MMRESULT mmr; WAVEINCAPS wic;
if (0 != (dwFlags & ~DRVM_MAPPER_PREFERRED_FLAGS_PREFERREDONLY)) return MMSYSERR_INVALPARAM; mmr = waveInGetDevCaps(PrefId, &wic, sizeof(wic)); if (!mmr) { wic.szPname[MAXPNAMELEN-1] = TEXT('\0'); mmr = waveWritePersistentConsoleVoiceCom(FALSE, wic.szPname, 0 != (dwFlags & 0x00000001)); if (!mmr) { NotifyServerPreferredDeviceChange(); } else { Squirt("waveInSetPersistentConsoleVoiceComId: waveWritePersistentConsoleVoiceCom failed, mmr=%08Xh", mmr); } }
return mmr; }
MMRESULT waveInSetCurrentConsoleVoiceComId(UINT PrefId, DWORD dwFlags) { MMRESULT mmr;
WinAssert(PrefId < wTotalWaveInDevs || PrefId == WAVE_MAPPER);
mmr = MMSYSERR_NOERROR;
if (gpstrWiConsoleVoiceComStringId) HeapFree(hHeap, 0, gpstrWiConsoleVoiceComStringId); gpstrWiConsoleVoiceComStringId = NULL; if (wTotalWaveInDevs) { PWAVEDRV pwavedrv; UINT port; mmr = waveReferenceDriverById(&waveindrvZ, PrefId, &pwavedrv, &port); if (!mmr) { mregCreateStringIdFromDriverPort(pwavedrv, port, &gpstrWiConsoleVoiceComStringId, NULL); gfUsePreferredWaveOnly = (0 != (dwFlags & DRVM_MAPPER_PREFERRED_FLAGS_PREFERREDONLY)); } }
return mmr; }
//------------------------------------------------------------------------------
//
//
// MidiOut
//
//
//------------------------------------------------------------------------------
DWORD midiOutGetSetupPreferredAudioCount(UINT MidiId) { PCWSTR DeviceInterface; DWORD dwCount;
DeviceInterface = midiReferenceDevInterfaceById(&midioutdrvZ, MidiId);
if(DeviceInterface == NULL) { return 0; }
dwCount = GetDeviceInterfaceSetupPreferredAudioCount(DeviceInterface); wdmDevInterfaceDec(DeviceInterface); return dwCount; }
MMRESULT midiOutSendPreferredMessage(BOOL fClear) { PCWSTR DeviceInterface; UINT MidiId; MMRESULT mmr;
if(!gfLogon) { return MMSYSERR_NOERROR; }
midiOutGetCurrentPreferredId(&MidiId, NULL);
if(MidiId == WAVE_MAPPER) { return MMSYSERR_NOERROR; }
DeviceInterface = midiReferenceDevInterfaceById(&midioutdrvZ, MidiId);
if(DeviceInterface == NULL) { return MMSYSERR_NOERROR; }
gfMidiOutPreferredMessageSent = TRUE;
mmr = midiOutMessage((HMIDIOUT)(UINT_PTR)MidiId, MODM_PREFERRED, (DWORD_PTR)fClear, (DWORD_PTR)DeviceInterface); wdmDevInterfaceDec(DeviceInterface); return mmr; }
MMRESULT midiOutWritePersistentPref(IN UINT MidiOutId, IN ULONG SetupCount) { HKEY hkMidiMapper; HKEY hkcu; MIDIOUTCAPS moc; DWORD dwDisposition; LONG result; MMRESULT mmr;
mmr = midiOutGetDevCaps(MidiOutId, &moc, sizeof(moc)); if (MMSYSERR_NOERROR != mmr) return mmr;
if (!NT_SUCCESS(RtlOpenCurrentUser(GENERIC_ALL, &hkcu))) return MMSYSERR_WRITEERROR;
result = RegCreateKeyEx(hkcu, REGSTR_PATH_MULTIMEDIA_MIDIMAP, 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_WRITE | KEY_QUERY_VALUE, NULL, &hkMidiMapper, &dwDisposition); if (ERROR_SUCCESS == result) { PCWSTR pstrDeviceInterface; UINT RelativeIndex;
pstrDeviceInterface = midiReferenceDevInterfaceById(&midioutdrvZ, MidiOutId); if (pstrDeviceInterface) { UINT i; RelativeIndex = 0; for (i = 0; i < MidiOutId; i++) { PCWSTR pstr = midiReferenceDevInterfaceById(&midioutdrvZ, i); if (pstr && !lstrcmpi(pstrDeviceInterface, pstr)) RelativeIndex++; if (pstr) wdmDevInterfaceDec(pstr); } } else { RelativeIndex = 0; }
result = RegSetSzValue(hkMidiMapper, REGSTR_VAL_MULTIMEDIA_MIDIMAP_SZPNAME, moc.szPname); if (ERROR_SUCCESS == result) result = RegSetDwordValue(hkMidiMapper, REGSTR_VAL_MULTIMEDIA_MIDIMAP_RELATIVEINDEX, RelativeIndex); if (ERROR_SUCCESS == result) result = RegSetSzValue(hkMidiMapper, REGSTR_VAL_MULTIMEDIA_MIDIMAP_DEVICEINTERFACE, pstrDeviceInterface ? pstrDeviceInterface : TEXT("")); if (ERROR_SUCCESS == result) result = RegSetDwordValue(hkMidiMapper, REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT, SetupCount); if (ERROR_SUCCESS == result) RegDeleteValue(hkMidiMapper, REGSTR_VAL_MULTIMEDIA_MIDIMAP_CURRENTINSTRUMENT);
if (pstrDeviceInterface) wdmDevInterfaceDec(pstrDeviceInterface); RegCloseKey(hkMidiMapper); }
if (ERROR_SUCCESS != result) mmr = MMSYSERR_WRITEERROR;
NtClose(hkcu); return mmr; }
MMRESULT midiOutGetIdFromName(IN PTSTR pstrName, OUT UINT *pMidiOutId) { UINT MidiOutId; UINT cMidiOutId; MMRESULT mmr;
cMidiOutId = midiOutGetNumDevs(); for (MidiOutId = 0; MidiOutId < cMidiOutId; MidiOutId++) { MIDIOUTCAPS moc; mmr = midiOutGetDevCaps(MidiOutId, &moc, sizeof(moc)); if (MMSYSERR_NOERROR == mmr) { if (!lstrcmp(pstrName, moc.szPname)) { mmr = MMSYSERR_NOERROR; break; } } } if (MidiOutId == cMidiOutId) { mmr = MMSYSERR_NODRIVER; }
if (MMSYSERR_NOERROR == mmr) *pMidiOutId = MidiOutId; return mmr; }
MMRESULT midiOutGetIdFromDiAndIndex(IN PTSTR pstrDeviceInterface, IN INT RelativeIndex, OUT UINT *pMidiOutId) { UINT cMidiOut; UINT MidiOutId; MMRESULT mmr;
mmr = MMSYSERR_NODRIVER;
cMidiOut = midiOutGetNumDevs(); if (0 == cMidiOut) return MMSYSERR_NODRIVER;
for (MidiOutId = 0; MidiOutId < cMidiOut; MidiOutId++) { PCWSTR pstr = midiReferenceDevInterfaceById(&midioutdrvZ, MidiOutId); if (pstr && !lstrcmpi(pstr, pstrDeviceInterface) && (0 == RelativeIndex--)) { *pMidiOutId = MidiOutId; wdmDevInterfaceDec(pstr); mmr = MMSYSERR_NOERROR; break; } if (pstr) wdmDevInterfaceDec(pstr); }
return mmr; }
MMRESULT midiOutGetInstrumentDriverData(IN PCTSTR pstrMidiSubkeyName, OUT PTSTR *ppstrDeviceInterface, OUT UINT *pDriverNum, OUT UINT *pPortNum, OUT PTSTR *ppstrPname) { HKEY hkMidi; HKEY hkMidiSubkey; LONG result; MMRESULT mmr; BOOL f;
mmr = MMSYSERR_ERROR; result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_MEDIARESOURCES_MIDI, 0, KEY_QUERY_VALUE, &hkMidi); if (ERROR_SUCCESS != result) return MMSYSERR_ERROR;
result = RegOpenKeyEx(hkMidi, pstrMidiSubkeyName, 0, KEY_QUERY_VALUE, &hkMidiSubkey); if (ERROR_SUCCESS == result) { PTSTR pstrActive;
result = RegQuerySzValue(hkMidiSubkey, REGSTR_VAL_MEDIARESOURCES_MIDI_SUBKEY_ACTIVE, &pstrActive); if (ERROR_SUCCESS == result) { PTCHAR pchEnd; BOOL fActive = _tcstol(pstrActive, &pchEnd, 10); f = HeapFree(hHeap, 0, pstrActive); WinAssert(f); if (fActive) { PTSTR pstrDeviceInterface = NULL; PTSTR pstrPname = NULL; DWORD dwDriverNum; DWORD dwPortNum;
result = RegQueryDwordValue(hkMidiSubkey, REGSTR_VAL_MEDIARESOURCES_MIDI_SUBKEY_PHYSDEVID, &dwDriverNum); if (ERROR_SUCCESS == result) result = RegQueryDwordValue(hkMidiSubkey, REGSTR_VAL_MEDIARESOURCES_MIDI_SUBKEY_PORT, &dwPortNum); if (ERROR_SUCCESS == result) RegQuerySzValue(hkMidiSubkey, REGSTR_VAL_MEDIARESOURCES_MIDI_SUBKEY_DEVICEINTERFACE, &pstrDeviceInterface); if (ERROR_SUCCESS == result) RegQuerySzValue(hkMidiSubkey, REGSTR_VAL_MEDIARESOURCES_MIDI_SUBKEY_DESCRIPTION, &pstrPname);
if (ERROR_SUCCESS == result) { *ppstrDeviceInterface = NULL; *ppstrPname = NULL;
if (pstrDeviceInterface) { if (lstrlen(pstrDeviceInterface)> 0) { *ppstrDeviceInterface = pstrDeviceInterface; } else { HeapFree(hHeap, 0, pstrDeviceInterface); } }
if (pstrPname) { if (lstrlen(pstrPname)> 0) { *ppstrPname = pstrPname; } else { HeapFree(hHeap, 0, pstrPname); } }
*pDriverNum = dwDriverNum; *pPortNum = dwPortNum;
mmr = MMSYSERR_NOERROR; } } } result = RegCloseKey(hkMidiSubkey); WinAssert(ERROR_SUCCESS == result); }
result = RegCloseKey(hkMidi); WinAssert(ERROR_SUCCESS == result); return mmr; }
MMRESULT midiOutGetIdFromInstrument(IN PTSTR pstrMidiKeyName, OUT UINT *outMidiOutId) { PTSTR pstrDeviceInterface, pstrPname; UINT DriverNum, PortNum; UINT MidiOutId; MMRESULT mmr;
mmr = midiOutGetInstrumentDriverData(pstrMidiKeyName, &pstrDeviceInterface, &DriverNum, &PortNum, &pstrPname); if (MMSYSERR_NOERROR == mmr) { if (pstrDeviceInterface) { mmr = midiOutGetIdFromDiAndIndex(pstrDeviceInterface, PortNum, &MidiOutId); } else if (pstrPname) { mmr = midiOutGetIdFromName(pstrPname, &MidiOutId); } else { PMIDIDRV pmidioutdrv = midioutdrvZ.Next; UINT DriverNum1 = DriverNum + 1;
MidiOutId = 0;
while ((pmidioutdrv != &midioutdrvZ) && (0 < DriverNum1)) { MidiOutId += pmidioutdrv->NumDevs; DriverNum1--; pmidioutdrv = pmidioutdrv->Next; }
if ((pmidioutdrv != &midioutdrvZ) && (PortNum < pmidioutdrv->NumDevs)) { MidiOutId += PortNum; } else { MidiOutId = MIDI_MAPPER; mmr = MMSYSERR_ERROR; } } if (pstrDeviceInterface) HeapFree(hHeap, 0, pstrDeviceInterface); if (pstrPname) HeapFree(hHeap, 0, pstrPname); }
if (MMSYSERR_NOERROR == mmr) { MIDIOUTCAPS moc; WinAssert(MIDI_MAPPER != MidiOutId); mmr = midiOutGetDevCaps(MidiOutId, &moc, sizeof(moc)); }
if (MMSYSERR_NOERROR == mmr) *outMidiOutId = MidiOutId; return mmr; }
MMRESULT midiOutReadCurrentInstrument(OUT PTSTR *ppstrCurrentInstrument, OUT DWORD *pSetupCount) { HKEY hkcu; HKEY hkMidiMapper; LONG result; MMRESULT mmr;
mmr = MMSYSERR_ERROR; if (!NT_SUCCESS(RtlOpenCurrentUser(GENERIC_READ, &hkcu))) return MMSYSERR_READERROR;
result = RegOpenKeyEx(hkcu, REGSTR_PATH_MULTIMEDIA_MIDIMAP, 0, KEY_QUERY_VALUE, &hkMidiMapper); if (ERROR_SUCCESS == result) { result = RegQuerySzValue(hkMidiMapper, REGSTR_VAL_MULTIMEDIA_MIDIMAP_CURRENTINSTRUMENT, ppstrCurrentInstrument); if (ERROR_SUCCESS == result) { DWORD SetupCount;
result = RegQueryDwordValue(hkMidiMapper, REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT, &SetupCount); SetupCount = (ERROR_SUCCESS == result) ? SetupCount : 0;
*pSetupCount = SetupCount; mmr = MMSYSERR_NOERROR; } else { mmr = MMSYSERR_ERROR; } result = RegCloseKey(hkMidiMapper); WinAssert(ERROR_SUCCESS == result); }
NtClose(hkcu);
return mmr; }
MMRESULT midiOutReadPreferredDeviceData(OUT PTSTR *ppstrDeviceInterface, OUT UINT *pRelativeIndex, OUT PTSTR *ppstrPname, OUT ULONG *pSetupCount) { HKEY hkcu; HKEY hkMidiMapper; LONG result; MMRESULT mmr;
if (!NT_SUCCESS(RtlOpenCurrentUser(GENERIC_READ, &hkcu))) return MMSYSERR_READERROR;
result = RegOpenKeyEx(hkcu, REGSTR_PATH_MULTIMEDIA_MIDIMAP, 0, KEY_QUERY_VALUE, &hkMidiMapper); if (ERROR_SUCCESS == result) { PTSTR pstrDeviceInterface = NULL; PTSTR pstrPname = NULL; DWORD dwIndex; DWORD dwSetupCount; // See if we have a Pname. It is okay not to.
result = RegQuerySzValue(hkMidiMapper, REGSTR_VAL_MULTIMEDIA_MIDIMAP_SZPNAME, &pstrPname); if (ERROR_FILE_NOT_FOUND == result) result = ERROR_SUCCESS;
// See if we have a device interface + relative index. It is okay not to.
if (ERROR_SUCCESS == result) result = RegQueryDwordValue(hkMidiMapper, REGSTR_VAL_MULTIMEDIA_MIDIMAP_RELATIVEINDEX, &dwIndex); if (ERROR_SUCCESS == result) result = RegQuerySzValue(hkMidiMapper, REGSTR_VAL_MULTIMEDIA_MIDIMAP_DEVICEINTERFACE, &pstrDeviceInterface); if (ERROR_FILE_NOT_FOUND == result) result = ERROR_SUCCESS;
// The device interface value might be zero length. Act as thought it
// doesn't exist in this case.
if ((ERROR_SUCCESS == result) && (pstrDeviceInterface) && (0 == lstrlen(pstrDeviceInterface))) { HeapFree(hHeap, 0, pstrDeviceInterface); pstrDeviceInterface = NULL; dwIndex = 0; }
if (ERROR_SUCCESS != RegQueryDwordValue(hkMidiMapper, REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT, &dwSetupCount)) { dwSetupCount = 0; }
if (ERROR_SUCCESS == result) { if (pstrPname || pstrDeviceInterface) { *ppstrDeviceInterface = pstrDeviceInterface; *ppstrPname = pstrPname; *pRelativeIndex = dwIndex; *pSetupCount = dwSetupCount; mmr = MMSYSERR_NOERROR; } else { mmr = MMSYSERR_VALNOTFOUND; } } else { mmr = MMSYSERR_READERROR; }
if (MMSYSERR_NOERROR != mmr) { if (pstrDeviceInterface) HeapFree(hHeap, 0, pstrDeviceInterface); if (pstrPname) HeapFree(hHeap, 0, pstrPname); } RegCloseKey(hkMidiMapper); } else { if (ERROR_FILE_NOT_FOUND == result) mmr = MMSYSERR_KEYNOTFOUND; else mmr = MMSYSERR_READERROR; }
NtClose(hkcu);
return mmr; }
MMRESULT midiOutReadPersistentPreferredId(OUT UINT *pMidiPrefId, OUT ULONG *pSetupCount) { PTSTR pstrDeviceInterface; PTSTR pstrPname; UINT RelativeIndex; UINT MidiOutId; ULONG SetupCount; MMRESULT mmr;
mmr = midiOutReadPreferredDeviceData(&pstrDeviceInterface, &RelativeIndex, &pstrPname, &SetupCount); if (MMSYSERR_NOERROR == mmr) { WinAssert(pstrDeviceInterface || pstrPname); if (pstrDeviceInterface) { mmr = midiOutGetIdFromDiAndIndex(pstrDeviceInterface, RelativeIndex, &MidiOutId); } else { WinAssert(pstrPname); mmr = midiOutGetIdFromName(pstrPname, &MidiOutId); } if (pstrDeviceInterface) HeapFree(hHeap, 0, pstrDeviceInterface); if (pstrPname) HeapFree(hHeap, 0, pstrPname); } else if (MMSYSERR_VALNOTFOUND == mmr || MMSYSERR_KEYNOTFOUND == mmr) { PTSTR pstrMidiKeyName; mmr = midiOutReadCurrentInstrument(&pstrMidiKeyName, &SetupCount); if (MMSYSERR_NOERROR == mmr) { mmr = midiOutGetIdFromInstrument(pstrMidiKeyName, &MidiOutId); // Since this is older format for storing preference, let's
// rewrite it in newer format.
if (MMSYSERR_NOERROR == mmr) { midiOutWritePersistentPref(MidiOutId, SetupCount); } HeapFree(hHeap, 0, pstrMidiKeyName); } }
if (MMSYSERR_NOERROR == mmr) { *pMidiPrefId = MidiOutId; *pSetupCount = SetupCount; }
return mmr; }
MMRESULT midiOutPickBestId(PUINT pMidiPrefId, UINT WaveOutPrefId) { MIDIOUTCAPS moc; UINT cMidiOutId; UINT MidiOutId; UINT UserSelectedMidiOutId; UINT WavetableMidiOutId; UINT SoftwareMidiOutId; UINT OtherMidiOutId; UINT FmMidiOutId; UINT ExternalMidiOutId; DWORD MidiOutIdCount; DWORD UserSelectedMidiOutIdCount; DWORD WavetableMidiOutIdCount; DWORD SoftwareMidiOutIdCount; DWORD OtherMidiOutIdCount; DWORD FmMidiOutIdCount; DWORD ExternalMidiOutIdCount; MMRESULT mmrLastError; MMRESULT mmr; BOOL f;
UserSelectedMidiOutId = MIDI_MAPPER; WavetableMidiOutId = MIDI_MAPPER; SoftwareMidiOutId = MIDI_MAPPER; OtherMidiOutId = MIDI_MAPPER; FmMidiOutId = MIDI_MAPPER; ExternalMidiOutId = MIDI_MAPPER; MidiOutId = MIDI_MAPPER;
UserSelectedMidiOutIdCount = 0; WavetableMidiOutIdCount = 0; SoftwareMidiOutIdCount = 0; OtherMidiOutIdCount = 0; FmMidiOutIdCount = 0; ExternalMidiOutIdCount = 0; MidiOutIdCount = 0;
mmr = midiOutReadPersistentPreferredId(&UserSelectedMidiOutId, &UserSelectedMidiOutIdCount);
mmrLastError = MMSYSERR_NODRIVER;
cMidiOutId = midiOutGetNumDevs(); for (MidiOutId = 0; MidiOutId < cMidiOutId; MidiOutId++) { mmr = midiOutGetDevCaps(MidiOutId, &moc, sizeof(moc)); if (MMSYSERR_NOERROR == mmr) { MidiOutIdCount = midiOutGetSetupPreferredAudioCount(MidiOutId);
if (MOD_SWSYNTH == moc.wTechnology && MM_MSFT_WDMAUDIO_MIDIOUT == moc.wPid && MM_MICROSOFT == moc.wMid) { // We need to special case this synth, and get the count from
// the preferred audio device.
SoftwareMidiOutId = MidiOutId; if ((-1) != WaveOutPrefId) { SoftwareMidiOutIdCount = waveOutGetSetupPreferredAudioCount(WaveOutPrefId); } else { SoftwareMidiOutIdCount = 0; } } else if (MOD_FMSYNTH == moc.wTechnology) { FmMidiOutId = MidiOutId; FmMidiOutIdCount = MidiOutIdCount; } else if (MOD_MIDIPORT == moc.wTechnology) { ExternalMidiOutId = MidiOutId; ExternalMidiOutIdCount = MidiOutIdCount; } else if (MOD_WAVETABLE == moc.wTechnology) { WavetableMidiOutId = MidiOutId; WavetableMidiOutIdCount = MidiOutIdCount; } else { OtherMidiOutId = MidiOutId; OtherMidiOutIdCount = MidiOutIdCount; } } else { mmrLastError = mmr; } }
MidiOutId = ExternalMidiOutId; MidiOutIdCount = ExternalMidiOutIdCount; if ((FmMidiOutIdCount >= MidiOutIdCount) && (MIDI_MAPPER != FmMidiOutId)) { MidiOutId = FmMidiOutId; MidiOutIdCount = FmMidiOutIdCount; } if ((OtherMidiOutIdCount >= MidiOutIdCount) && (MIDI_MAPPER != OtherMidiOutId)) { MidiOutId = OtherMidiOutId; MidiOutIdCount = OtherMidiOutIdCount; } if ((SoftwareMidiOutIdCount >= MidiOutIdCount) && (MIDI_MAPPER != SoftwareMidiOutId)) { MidiOutId = SoftwareMidiOutId; MidiOutIdCount = SoftwareMidiOutIdCount; } if ((WavetableMidiOutIdCount >= MidiOutIdCount) && (MIDI_MAPPER != WavetableMidiOutId)) { MidiOutId = WavetableMidiOutId; MidiOutIdCount = WavetableMidiOutIdCount; } if ((UserSelectedMidiOutIdCount >= MidiOutIdCount) && (MIDI_MAPPER != UserSelectedMidiOutId)) { MidiOutId = UserSelectedMidiOutId; MidiOutIdCount = UserSelectedMidiOutIdCount; } if ((-1) != MidiOutId) { mmr = MMSYSERR_NOERROR; } else { mmr = mmrLastError; }
if (MMSYSERR_NOERROR == mmr) *pMidiPrefId = MidiOutId; return mmr; }
void midiOutGetCurrentPreferredId(PUINT pPrefId, PDWORD pdwFlags) { *pPrefId = WAVE_MAPPER; if (pdwFlags) *pdwFlags = 0;; if (gpstrMoDefaultStringId) mregGetIdFromStringId(&midioutdrvZ, gpstrMoDefaultStringId, pPrefId); return; }
MMRESULT midiOutSetCurrentPreferredId(UINT PrefId) { MMRESULT mmr; WinAssert(PrefId < wTotalMidiOutDevs || PrefId == MIDI_MAPPER);
mmr = MMSYSERR_NOERROR;
if (gpstrMoDefaultStringId) HeapFree(hHeap, 0, gpstrMoDefaultStringId); gpstrMoDefaultStringId = NULL; if (wTotalMidiOutDevs) { PMIDIDRV pmididrv; UINT port; mmr = midiReferenceDriverById(&midioutdrvZ, PrefId, &pmididrv, &port); if (!mmr) { mmr = mregCreateStringIdFromDriverPort(pmididrv, port, &gpstrMoDefaultStringId, NULL); if (!mmr) { if (!gfDisablePreferredDeviceReordering) { // Rearrange some of the driver list so that the preferred midiOut
// device has a good chance of having device ID 0
if (0 != PrefId) { // Move the midi driver to the head of this list. This usually
// makes the preferred device have ID 0.
EnterNumDevs("midiOutSetCurrentPreferredId"); pmididrv->Prev->Next = pmididrv->Next; pmididrv->Next->Prev = pmididrv->Prev; pmididrv->Next = midioutdrvZ.Next; pmididrv->Prev = &midioutdrvZ; midioutdrvZ.Next->Prev = pmididrv; midioutdrvZ.Next = pmididrv; LeaveNumDevs("midiOutSetCurrentPreferredId"); mregDecUsagePtr(pmididrv); } } } } }
if (!mmr) { // Reconfigure the mapper only if it was already loaded. Don't cause it to
// load simply so that we can reconfigure it!
if (MidiMapperInitialized) midiOutMessage((HMIDIOUT)(UINT_PTR)MIDI_MAPPER, DRVM_MAPPER_RECONFIGURE, 0, 0); }
return mmr; }
MMRESULT midiOutSetPersistentPreferredId(UINT PrefId, DWORD dwFlags) { MMRESULT mmr; mmr = midiOutWritePersistentPref(PrefId, GetCurrentSetupPreferredAudioCount()); if (!mmr) NotifyServerPreferredDeviceChange(); return mmr; }
//------------------------------------------------------------------------------
//
//
// RefreshPreferredDevices
//
//
//------------------------------------------------------------------------------
void RefreshPreferredDevices(void) { UINT WaveOutPreferredId; DWORD WaveOutPreferredFlags; UINT WaveInPreferredId; DWORD WaveInPreferredFlags; UINT WaveOutConsoleVoiceComId; DWORD WaveOutConsoleVoiceComFlags; UINT WaveInConsoleVoiceComId; DWORD WaveInConsoleVoiceComFlags; UINT MidiOutPreferredId;
UINT OldWaveOutPreferredId; DWORD OldWaveOutPreferredFlags; UINT OldWaveInPreferredId; DWORD OldWaveInPreferredFlags; UINT OldWaveOutConsoleVoiceComId; DWORD OldWaveOutConsoleVoiceComFlags; UINT OldWaveInConsoleVoiceComId; DWORD OldWaveInConsoleVoiceComFlags; UINT OldMidiOutPreferredId;
// Squirt("RefreshPreferredDevices");
BOOL fImpersonate = FALSE; waveOutGetCurrentPreferredId(&OldWaveOutPreferredId, &OldWaveOutPreferredFlags); if (!waveOutPickBestId(&WaveOutPreferredId, &WaveOutPreferredFlags)) { if ((WaveOutPreferredId != OldWaveOutPreferredId) || (WaveOutPreferredFlags != OldWaveOutPreferredFlags) || !gfWaveOutPreferredMessageSent) { // Squirt("RefreshPreferredDevices: different waveOut preference %d -> %d", OldWaveOutPreferredId, WaveOutPreferredId);
waveOutSendPreferredMessage(TRUE); waveOutSetCurrentPreferredId(WaveOutPreferredId, WaveOutPreferredFlags); waveOutSendPreferredMessage(FALSE); }
}
waveOutGetCurrentConsoleVoiceComId(&OldWaveOutConsoleVoiceComId, &OldWaveOutConsoleVoiceComFlags); if (!wavePickBestConsoleVoiceComId(TRUE, &WaveOutConsoleVoiceComId, &WaveOutConsoleVoiceComFlags)) { if ((WaveOutConsoleVoiceComId != OldWaveOutConsoleVoiceComId) || (WaveOutConsoleVoiceComFlags != OldWaveOutConsoleVoiceComFlags)) { // Squirt("RefreshPreferredDevices: different waveOut preference %d -> %d", OldWaveOutConsoleVoiceComId, WaveOutConsoleVoiceComId);
waveOutSetCurrentConsoleVoiceComId(WaveOutConsoleVoiceComId, WaveOutConsoleVoiceComFlags); }
}
waveInGetCurrentPreferredId(&OldWaveInPreferredId, &OldWaveInPreferredFlags); if (!waveInPickBestId(&WaveInPreferredId, &WaveInPreferredFlags)) { if ((WaveInPreferredId != OldWaveInPreferredId) || (WaveInPreferredFlags != OldWaveInPreferredFlags) || !gfWaveInPreferredMessageSent) { // Squirt("RefreshPreferredDevices: different waveIn preference %d -> %d", OldWaveInPreferredId, WaveInPreferredId);
waveInSendPreferredMessage(TRUE);
waveInSetCurrentPreferredId(WaveInPreferredId, WaveInPreferredFlags);
waveInSendPreferredMessage(FALSE);
} }
waveInGetCurrentConsoleVoiceComId(&OldWaveInConsoleVoiceComId, &OldWaveInConsoleVoiceComFlags); if (!wavePickBestConsoleVoiceComId(FALSE, &WaveInConsoleVoiceComId, &WaveInConsoleVoiceComFlags)) { if ((WaveInConsoleVoiceComId != OldWaveInConsoleVoiceComId) || (WaveInConsoleVoiceComFlags != OldWaveInConsoleVoiceComFlags)) { // Squirt("RefreshPreferredDevices: different waveIn preference %d -> %d", OldWaveInConsoleVoiceComId, WaveInConsoleVoiceComId);
waveInSetCurrentConsoleVoiceComId(WaveInConsoleVoiceComId, WaveInConsoleVoiceComFlags); } }
midiOutGetCurrentPreferredId(&OldMidiOutPreferredId, NULL); if (!midiOutPickBestId(&MidiOutPreferredId, WaveOutPreferredId)) { if (MidiOutPreferredId != OldMidiOutPreferredId || !gfMidiOutPreferredMessageSent) { // Squirt("RefreshPreferredDevices: different midiOut preference %d -> %d", OldMidiOutPreferredId, MidiOutPreferredId);
midiOutSendPreferredMessage(TRUE);
midiOutSetCurrentPreferredId(MidiOutPreferredId);
midiOutSendPreferredMessage(FALSE);
} }
// Squirt("RefreshPreferredDevices: return");
return; }
void InvalidatePreferredDevices(void) { if (gpstrWoDefaultStringId) HeapFree(hHeap, 0, gpstrWoDefaultStringId); if (gpstrWiDefaultStringId) HeapFree(hHeap, 0, gpstrWiDefaultStringId); gpstrWoDefaultStringId = NULL; gpstrWiDefaultStringId = NULL; if (gpstrWoConsoleVoiceComStringId) HeapFree(hHeap, 0, gpstrWoConsoleVoiceComStringId); if (gpstrWiConsoleVoiceComStringId) HeapFree(hHeap, 0, gpstrWiConsoleVoiceComStringId); gpstrWoConsoleVoiceComStringId = NULL; gpstrWiConsoleVoiceComStringId = NULL; if (gpstrMoDefaultStringId) HeapFree(hHeap, 0, gpstrMoDefaultStringId); gpstrMoDefaultStringId = NULL; }
|