1620 lines
38 KiB
C
1620 lines
38 KiB
C
/*
|
|
**-----------------------------------------------------------------------------
|
|
** File: Migrate.c
|
|
** Purpose: Various functions for Migrating old driver registry settings
|
|
** to new driver registry settings
|
|
** Mod Log: Created by Shawn Brown (11/14/95)
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Includes
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
#include <windows.h>
|
|
#include <mmsystem.h>
|
|
#include <regstr.h>
|
|
#include "mmddk.h"
|
|
#include "migrate.h"
|
|
#include "winmmi.h"
|
|
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Defines
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
#define MM_PATH 260
|
|
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Typedefs
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
typedef DWORD (WINAPI * MIDIRUNONCEINIT)(
|
|
HWND hWnd,
|
|
HINSTANCE hInst,
|
|
LPSTR pszCmd,
|
|
int nShow);
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Local Strings
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
static const TCHAR aszDriver32Key[] = TEXT ("Software\\Microsoft\\Windows NT\\CurrentVersion\\Drivers32");
|
|
static const TCHAR aszDriverDescKey[] = TEXT ("Software\\Microsoft\\Windows NT\\CurrentVersion\\Driver.Desc");
|
|
|
|
static const TCHAR aszMediaResKey[] = TEXT ("System\\CurrentControlSet\\Control\\MediaResources");
|
|
static const TCHAR aszMidiKey[] = TEXT ("System\\CurrentControlSet\\Control\\MediaResources\\Midi");
|
|
static const TCHAR aszMidiUserKey[] = TEXT ("Software\\Microsoft\\Windows\\CurrentVersion\\MultiMedia\\MIDIMap");
|
|
static const TCHAR aszAux[] = TEXT ("Aux");
|
|
static const TCHAR aszMidi[] = TEXT ("Midi");
|
|
static const TCHAR aszWave[] = TEXT ("Wave");
|
|
|
|
static const TCHAR asz2Format[] = TEXT ("%s\\%s");
|
|
static const TCHAR asz3Format[] = TEXT ("%s\\%s\\%s");
|
|
static const TCHAR aszDrvFormat[] = TEXT ("%s<%04ld>");
|
|
static const TCHAR aszDefFormat[] = TEXT ("%s [%02ld, %02ld]");
|
|
|
|
static const TCHAR aszActiveCount[] = TEXT ("ActiveCount");
|
|
static const TCHAR aszActive[] = TEXT ("Active");
|
|
static const TCHAR aszCurrInstrument[] = TEXT ("CurrentInstrument");
|
|
static const TCHAR aszDesc[] = TEXT ("Description");
|
|
static const TCHAR aszDeviceID[] = TEXT ("DeviceID");
|
|
static const TCHAR aszDevNode[] = TEXT ("DevNode");
|
|
static const TCHAR aszDriver[] = TEXT ("Driver");
|
|
static const TCHAR aszFriend[] = TEXT ("FriendlyName");
|
|
static const TCHAR aszPort[] = TEXT ("Port");
|
|
static const TCHAR aszPhysID[] = TEXT ("PhysDevID");
|
|
static const TCHAR aszMapConfig[] = TEXT ("MapperConfig");
|
|
static const TCHAR aszSoftwareKey[] = TEXT ("SOFTWAREKEY");
|
|
static const TCHAR aszMigrated[] = TEXT ("Migrated");
|
|
static const TCHAR aszInstruments[] = TEXT ("Instruments");
|
|
static const TCHAR aszExternal[] = TEXT ("External");
|
|
|
|
static const TCHAR aszNULL[] = TEXT ("");
|
|
static const TCHAR aszTrue[] = TEXT ("1");
|
|
static const TCHAR aszFalse[] = TEXT ("0");
|
|
|
|
static const TCHAR aszWaveOutDef[] = TEXT ("Unknown Wave Device");
|
|
static const TCHAR aszWaveInDef[] = TEXT ("Unknown Wave Device");
|
|
static const TCHAR aszMidiOutDef[] = TEXT ("Unknown Midi Device");
|
|
static const TCHAR aszMidiInDef[] = TEXT ("Unknown Midi Device");
|
|
static const TCHAR aszAuxDef[] = TEXT ("Unknown Aux Device");
|
|
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Local Prototypes
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
BOOL mregMidiUserNeedsMigrate (void);
|
|
|
|
BOOL mregMigrateMidiUser (void);
|
|
|
|
BOOL mregGetModuleName (
|
|
HMODULE hModule,
|
|
LPTSTR pszName,
|
|
UINT cchSize);
|
|
|
|
BOOL mregActivateDriverEntry (
|
|
LPCTSTR pszClass,
|
|
LPCTSTR pszDriver,
|
|
DWORD entryID,
|
|
BOOL fSet);
|
|
|
|
BOOL mregGetDriverEntryID (
|
|
LPCTSTR pszClass,
|
|
LPCTSTR pszDriver,
|
|
DWORD physID,
|
|
DWORD portID,
|
|
DWORD * pEntryID);
|
|
|
|
BOOL mregMigrateDriver (
|
|
DWORD dwClass,
|
|
DWORD dwLogID);
|
|
|
|
BOOL mregCheckDriverEntry (
|
|
LPCTSTR pszClass,
|
|
LPCTSTR pszDriver,
|
|
LPCTSTR pszDesc,
|
|
UINT physID,
|
|
UINT portID,
|
|
BOOL fExternal);
|
|
|
|
BOOL mregCreateDriverEntry (
|
|
LPCTSTR pszClass,
|
|
LPCTSTR pszDriver,
|
|
LPCTSTR pszDesc,
|
|
UINT entryID,
|
|
UINT physID,
|
|
UINT portID,
|
|
BOOL fExternal);
|
|
|
|
|
|
BOOL mregDeactivateAllEntries (
|
|
LPCTSTR pszClass);
|
|
|
|
|
|
int lstrcmpni (
|
|
LPCTSTR pszSrc1,
|
|
LPCTSTR pszSrc2,
|
|
DWORD cchSize);
|
|
|
|
BOOL FindChar (
|
|
LPTSTR pszSearch,
|
|
DWORD cchLen,
|
|
TCHAR cchFind,
|
|
DWORD * pszOffset);
|
|
|
|
BOOL ConvertToNumber (
|
|
LPTSTR pszConvert,
|
|
DWORD cchLen,
|
|
INT * pVal);
|
|
|
|
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Function definitions
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Name: MigrateMidiUser
|
|
** Purpose: Migrates all MIDI registry Settings for current User
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
|
|
BOOL MigrateMidiUser (void)
|
|
{
|
|
MigrateAllDrivers ();
|
|
|
|
if (mregMidiUserNeedsMigrate ())
|
|
{
|
|
return mregMigrateMidiUser ();
|
|
}
|
|
return TRUE;
|
|
} // End MigrateMidiUser
|
|
|
|
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Name: mregMigrateAllDrivers
|
|
** Purpose: Migrates all Multimedia drivers registry settings
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
void MigrateAllDrivers (void)
|
|
{
|
|
HANDLE hMutex;
|
|
|
|
// Prevent synchronization problems
|
|
hMutex = CreateMutex (NULL, FALSE, TEXT ("mregMigrateAllDrivers"));
|
|
if (hMutex)
|
|
{
|
|
WaitForSingleObject (hMutex, INFINITE);
|
|
}
|
|
|
|
// Migrate Midi Drivers
|
|
mregMigrateMidiDrivers ();
|
|
#if 0
|
|
// Note: We don't appear to need to set up these driver entries
|
|
// for correct functioning under NT
|
|
// Migrate Wave Drivers
|
|
mregMigrateWaveDrivers ();
|
|
|
|
// Migrate Aux Drivers
|
|
mregMigrateAuxDrivers ();
|
|
#endif
|
|
|
|
if (hMutex)
|
|
CloseHandle (hMutex);
|
|
} // End mregMigrateAllDrivers
|
|
|
|
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Name: mregMigrateWaveDrivers
|
|
** Purpose: Migrates all Wave Drivers Registry Settings
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
BOOL mregMigrateWaveDrivers (void)
|
|
{
|
|
BOOL fResult = TRUE;
|
|
UINT ii;
|
|
UINT cTotal;
|
|
|
|
// Deactivate all current entries
|
|
mregDeactivateAllEntries (aszWave);
|
|
|
|
// Migrate or Activate all current WaveOut Drivers
|
|
cTotal = waveOutGetNumDevs();
|
|
for (ii = 0; ii < cTotal; ii++)
|
|
{
|
|
if (! mregMigrateDriver (TYPE_WAVEOUT, ii))
|
|
fResult = FALSE;
|
|
}
|
|
|
|
// Migrate or Activate all current WaveIn Drivers
|
|
cTotal = waveInGetNumDevs();
|
|
for (ii = 0; ii < cTotal; ii++)
|
|
{
|
|
if (! mregMigrateDriver (TYPE_WAVEIN, ii))
|
|
fResult = FALSE;
|
|
}
|
|
|
|
return fResult;
|
|
} // End mregMigrateWaveDrivers
|
|
|
|
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Name: mregMigrateMidiDrivers
|
|
** Purpose: Migrates all Midi Drivers Registry Settings
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
BOOL mregMigrateMidiDrivers (void)
|
|
{
|
|
BOOL fResult = TRUE;
|
|
UINT ii;
|
|
UINT cTotal;
|
|
|
|
// Deactivate all current entries
|
|
mregDeactivateAllEntries (aszMidi);
|
|
|
|
// Migrate or Activate all current MidiOut Drivers
|
|
cTotal = midiOutGetNumDevs();
|
|
for (ii = 0; ii < cTotal; ii++)
|
|
{
|
|
if (! mregMigrateDriver (TYPE_MIDIOUT, ii))
|
|
fResult = FALSE;
|
|
}
|
|
|
|
|
|
#if 0
|
|
// Note: We don't need to do this as the MIDI IN entries
|
|
// Intefere with the MIDI OUT entries used by the MIDI Mapper
|
|
// Migrate or Activate all current MidiIn Drivers
|
|
cTotal = midiInGetNumDevs();
|
|
for (ii = 0; ii < cTotal; ii++)
|
|
{
|
|
if (! mregMigrateDriver (TYPE_MIDIIN, ii))
|
|
fResult = FALSE;
|
|
}
|
|
#endif
|
|
|
|
return fResult;
|
|
} // End mregMigrateMidiDrivers
|
|
|
|
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Name: mregMigrateAuxDrivers
|
|
** Purpose: Migrates all Aux Drivers Registry Settings
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
BOOL mregMigrateAuxDrivers (void)
|
|
{
|
|
BOOL fResult = TRUE;
|
|
UINT ii;
|
|
UINT cTotal;
|
|
|
|
// Deactivate all current entries
|
|
mregDeactivateAllEntries (aszAux);
|
|
|
|
// Migrate Aux Drivers
|
|
cTotal = auxGetNumDevs();
|
|
for (ii = 0; ii < cTotal; ii++)
|
|
{
|
|
if (! mregMigrateDriver (TYPE_AUX, ii))
|
|
fResult = FALSE;
|
|
}
|
|
|
|
return fResult;
|
|
} // End mregMigrateAuxDrivers
|
|
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Name: mregMidiUserNeedsMigrate
|
|
** Purpose: Checks if we need to migrate the midi stuff
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
BOOL mregMidiUserNeedsMigrate (void)
|
|
{
|
|
HKEY hKeyInstrument = NULL;
|
|
HKEY hKeyDriver = NULL;
|
|
DWORD dwType;
|
|
DWORD cbSize;
|
|
LPTSTR pszBuffer = NULL;
|
|
LPTSTR pszDriver = NULL;
|
|
BOOL fNeedsMigrate = TRUE;
|
|
|
|
// Create Strings
|
|
cbSize = MM_PATH * sizeof(TCHAR);
|
|
pszBuffer = (LPTSTR)LocalAlloc (LPTR, cbSize);
|
|
if (!pszBuffer)
|
|
return FALSE;
|
|
|
|
pszDriver = (LPTSTR)LocalAlloc (LPTR, cbSize);
|
|
if (!pszDriver)
|
|
goto lblCLEANUP;
|
|
|
|
// Get Midi User's Key
|
|
if (ERROR_SUCCESS != RegOpenKey (HKEY_CURRENT_USER, aszMidiUserKey,
|
|
&hKeyInstrument))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Get Midi User's Current Instrument
|
|
dwType = REG_SZ;
|
|
pszBuffer[0] = 0;
|
|
if (ERROR_SUCCESS != RegQueryValueEx (hKeyInstrument, aszCurrInstrument, NULL,
|
|
&dwType, (LPBYTE)(LPVOID)pszBuffer,
|
|
&cbSize))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Make sure there is something there
|
|
if (TEXT('\0') == pszBuffer[0])
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
//
|
|
// Make sure Current Instrument is valid
|
|
//
|
|
|
|
wsprintf (pszDriver, asz2Format, aszMidiKey, pszBuffer);
|
|
if (ERROR_SUCCESS != RegOpenKey (HKEY_LOCAL_MACHINE, pszDriver, &hKeyDriver))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
dwType = REG_SZ;
|
|
pszBuffer[0] = 0;
|
|
if (ERROR_SUCCESS != RegQueryValueEx (hKeyDriver, aszActive, NULL,
|
|
&dwType, (LPBYTE)(LPVOID)pszBuffer,
|
|
&cbSize))
|
|
{
|
|
// Null out bogus instrument
|
|
cbSize = (lstrlen (aszNULL) + 1) * sizeof(TCHAR);
|
|
RegSetValueEx (hKeyInstrument, aszCurrInstrument, 0,
|
|
REG_SZ, (LPBYTE)aszNULL, cbSize);
|
|
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
if (0 != lstrcmpi (aszTrue, pszBuffer))
|
|
{
|
|
// Null out bogus instrument
|
|
cbSize = (lstrlen (aszNULL) + 1) * sizeof(TCHAR);
|
|
RegSetValueEx (hKeyInstrument, aszCurrInstrument, 0,
|
|
REG_SZ, (LPBYTE)aszNULL, cbSize);
|
|
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// User is already migrated correctly
|
|
fNeedsMigrate = FALSE;
|
|
|
|
lblCLEANUP:
|
|
// Cleanup
|
|
if (hKeyDriver) RegCloseKey (hKeyDriver);
|
|
if (hKeyInstrument) RegCloseKey (hKeyInstrument);
|
|
|
|
if (pszDriver) LocalFree ((HLOCAL)pszDriver);
|
|
if (pszBuffer) LocalFree ((HLOCAL)pszBuffer);
|
|
|
|
// Needs Migrate
|
|
return fNeedsMigrate;
|
|
} // End mregMidiUserNeedsMigrate
|
|
|
|
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Name: mregMigrateMidiUser
|
|
** Purpose: Migrates the Midi User
|
|
** Notes: The code for doing this is actually contained in mmsys.cpl
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
BOOL mregMigrateMidiUser (void)
|
|
{
|
|
HINSTANCE hInstance;
|
|
HINSTANCE hLib;
|
|
DWORD dwResult;
|
|
MIDIRUNONCEINIT fnRun;
|
|
BOOL fResult = FALSE;
|
|
|
|
hInstance = GetModuleHandle (NULL);
|
|
|
|
hLib = LoadLibrary (TEXT ("mmsys.cpl"));
|
|
if (hLib)
|
|
{
|
|
// Note: Do not change this string to UNICODE
|
|
fnRun = (MIDIRUNONCEINIT)GetProcAddress (hLib, "mmseRunOnce");
|
|
|
|
if (fnRun)
|
|
{
|
|
dwResult = (BOOL) (*fnRun)(NULL, hInstance, NULL, SW_SHOWDEFAULT);
|
|
if (!dwResult)
|
|
fResult = TRUE;
|
|
}
|
|
|
|
FreeLibrary(hLib);
|
|
}
|
|
|
|
return fResult;
|
|
} // End mregMigrateMidiUser
|
|
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Name: mregGetModuleName
|
|
** Purpose: Gets driver name from module handle
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
BOOL mregGetModuleName (
|
|
HMODULE hModule,
|
|
LPTSTR pszName,
|
|
UINT cchSize)
|
|
{
|
|
LPTSTR pszPath = NULL;
|
|
BOOL fResult = FALSE;
|
|
UINT cchLen;
|
|
UINT cch;
|
|
LPTSTR pch;
|
|
LPTSTR pszSource = NULL;
|
|
DWORD cbSize;
|
|
|
|
|
|
// Validate parameters
|
|
if ((!hModule) && (!pszName))
|
|
return FALSE;
|
|
|
|
// Create String
|
|
cbSize = MM_PATH * sizeof(TCHAR);
|
|
pszPath = (LPTSTR)LocalAlloc (LPTR, cbSize);
|
|
if (!pszPath)
|
|
return FALSE;
|
|
|
|
// Get Driver Name (Full Path)
|
|
if (0 == GetModuleFileName (hModule, (LPTSTR)pszPath, MM_PATH))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
cchLen = lstrlen (pszPath);
|
|
if (0 == cchLen)
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Find last slash or ':', if any in path
|
|
for (cch = 0, pch = pszPath; (cch < cchLen) && (*pch != TEXT ('\0')); cch++, pch++)
|
|
{
|
|
if ((*pch == TEXT ('/')) ||
|
|
(*pch == TEXT ('\\')) ||
|
|
(*pch == TEXT (':')))
|
|
pszSource = pch;
|
|
}
|
|
|
|
// If there was a last slash, step past it
|
|
// to beginning of name
|
|
if (pszSource)
|
|
{
|
|
pszSource++;
|
|
}
|
|
else
|
|
pszSource = pszPath;
|
|
|
|
|
|
// Copy module name into buffer
|
|
cchLen = lstrlen (pszSource);
|
|
if (cchLen >= cchSize)
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
lstrcpy (pszName, pszSource);
|
|
pszName[cchLen] = 0;
|
|
|
|
|
|
fResult = TRUE;
|
|
|
|
lblCLEANUP:
|
|
if (pszPath) LocalFree ((HLOCAL)pszPath);
|
|
|
|
return fResult;
|
|
} // End GetModuleName
|
|
|
|
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Name: mregMigrateDriver
|
|
** Purpose: Sets up proper registry settings for this MM driver
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
BOOL mregMigrateDriver (DWORD dwClass, DWORD dwLogID)
|
|
{
|
|
UINT physID;
|
|
UINT portID;
|
|
LPCTSTR pszClass;
|
|
HMODULE hModule;
|
|
LPTSTR pszDesc = NULL;
|
|
LPTSTR pszDriver = NULL;
|
|
BOOL fResult;
|
|
DWORD cbSize;
|
|
MMRESULT mmr;
|
|
MIDIOUTCAPS caps; // Note: Use this as a buffer for all Device CAPS
|
|
BOOL fExternal = FALSE;
|
|
|
|
|
|
// Create Strings
|
|
cbSize = MM_PATH * sizeof(TCHAR);
|
|
pszDesc = (LPTSTR)LocalAlloc (LPTR, cbSize);
|
|
if (!pszDesc)
|
|
return FALSE;
|
|
|
|
pszDriver = (LPTSTR)LocalAlloc (LPTR, cbSize);
|
|
if (!pszDriver)
|
|
goto lblCLEANUP;
|
|
|
|
// Get Class Info for each class
|
|
switch (dwClass)
|
|
{
|
|
case TYPE_WAVEOUT:
|
|
pszClass = (LPTSTR)(LPVOID)aszWave;
|
|
|
|
mmr = waveOutMessage ((HWAVEOUT)dwLogID, DRV_QUERYMAPID, (DWORD)(LPVOID)&physID, (DWORD)(LPVOID)&portID);
|
|
if (MMSYSERR_NOERROR != mmr)
|
|
goto lblCLEANUP;
|
|
|
|
mmr = waveOutMessage ((HWAVEOUT)dwLogID, DRV_QUERYMODULE, (DWORD)(LPVOID)&hModule, 0L);
|
|
if ((MMSYSERR_NOERROR != mmr) || (!hModule))
|
|
goto lblCLEANUP;
|
|
|
|
mmr = waveOutGetDevCaps((UINT)dwLogID, (WAVEOUTCAPS *)(LPVOID)&caps, sizeof(WAVEOUTCAPS));
|
|
if (MMSYSERR_NOERROR != mmr)
|
|
wsprintf (pszDesc, aszDefFormat, aszWaveOutDef, physID, portID);
|
|
else
|
|
lstrcpy (pszDesc, ((LPWAVEOUTCAPS)(LPVOID)&caps)->szPname);
|
|
break;
|
|
|
|
case TYPE_WAVEIN:
|
|
pszClass = aszWave;
|
|
|
|
mmr = waveInMessage ((HWAVEIN)dwLogID, DRV_QUERYMAPID, (DWORD)(LPVOID)&physID, (DWORD)(LPVOID)&portID);
|
|
if (MMSYSERR_NOERROR != mmr)
|
|
goto lblCLEANUP;
|
|
|
|
mmr = waveInMessage ((HWAVEIN)dwLogID, DRV_QUERYMODULE, (DWORD)(LPVOID)&hModule, 0L);
|
|
if ((MMSYSERR_NOERROR != mmr) || (!hModule))
|
|
goto lblCLEANUP;
|
|
|
|
mmr = waveInGetDevCaps(dwLogID, (LPWAVEINCAPS)(LPVOID)&caps, sizeof(WAVEINCAPS));
|
|
if (MMSYSERR_NOERROR != mmr)
|
|
wsprintf (pszDesc, aszDefFormat, aszWaveInDef, physID, portID);
|
|
else
|
|
lstrcpy (pszDesc, ((LPWAVEINCAPS)(LPVOID)&caps)->szPname);
|
|
break;
|
|
|
|
case TYPE_MIDIOUT:
|
|
pszClass = aszMidi;
|
|
|
|
mmr = midiOutMessage ((HMIDIOUT)dwLogID, DRV_QUERYMAPID, (DWORD)(LPVOID)&physID, (DWORD)(LPVOID)&portID);
|
|
if (MMSYSERR_NOERROR != mmr)
|
|
goto lblCLEANUP;
|
|
|
|
mmr = midiOutMessage ((HMIDIOUT)dwLogID, DRV_QUERYMODULE, (DWORD)(LPVOID)&hModule, 0L);
|
|
if ((MMSYSERR_NOERROR != mmr) || (!hModule))
|
|
goto lblCLEANUP;
|
|
|
|
mmr = midiOutGetDevCaps ((UINT)dwLogID, (LPMIDIOUTCAPS)(LPVOID)&caps, sizeof(MIDIOUTCAPS));
|
|
if (MMSYSERR_NOERROR != mmr)
|
|
wsprintf (pszDesc, aszDefFormat, aszMidiOutDef, physID, portID);
|
|
else
|
|
lstrcpy (pszDesc, ((LPMIDIOUTCAPS)(LPVOID)&caps)->szPname);
|
|
|
|
// Is it an external MIDIOUT Device ?!?
|
|
if (MOD_FMSYNTH != ((LPMIDIOUTCAPS)(LPVOID)&caps)->wTechnology)
|
|
fExternal = TRUE;
|
|
break;
|
|
|
|
case TYPE_MIDIIN:
|
|
pszClass = aszMidi;
|
|
|
|
mmr = midiInMessage ((HMIDIIN)dwLogID, DRV_QUERYMAPID, (DWORD)(LPVOID)&physID, (DWORD)(LPVOID)&portID);
|
|
if (MMSYSERR_NOERROR != mmr)
|
|
goto lblCLEANUP;
|
|
|
|
mmr = midiInMessage ((HMIDIIN)dwLogID, DRV_QUERYMODULE, (DWORD)(LPVOID)&hModule, 0L);
|
|
if ((MMSYSERR_NOERROR != mmr) || (!hModule))
|
|
goto lblCLEANUP;
|
|
|
|
mmr = midiInGetDevCaps ((UINT)dwLogID, (LPMIDIINCAPS)(LPVOID)&caps, sizeof(MIDIINCAPS));
|
|
if (MMSYSERR_NOERROR != mmr)
|
|
wsprintf (pszDesc, aszDefFormat, aszMidiInDef, physID, portID);
|
|
else
|
|
lstrcpy (pszDesc, ((LPMIDIINCAPS)(LPVOID)&caps)->szPname);
|
|
break;
|
|
|
|
case TYPE_AUX:
|
|
pszClass = aszAux;
|
|
|
|
mmr = auxOutMessage ((UINT)dwLogID, DRV_QUERYMAPID, (DWORD)(LPVOID)&physID, (DWORD)(LPVOID)&portID);
|
|
if (MMSYSERR_NOERROR != mmr)
|
|
goto lblCLEANUP;
|
|
|
|
mmr = auxOutMessage ((UINT)dwLogID, DRV_QUERYMODULE, (DWORD)(LPVOID)&hModule, 0L);
|
|
if ((MMSYSERR_NOERROR != mmr) || (!hModule))
|
|
goto lblCLEANUP;
|
|
|
|
mmr = auxGetDevCaps ((UINT)dwLogID, (LPAUXCAPS)(LPVOID)&caps, sizeof(AUXCAPS));
|
|
if (MMSYSERR_NOERROR != mmr)
|
|
wsprintf (pszDesc, aszDefFormat, aszAuxDef, physID, portID);
|
|
else
|
|
lstrcpy (pszDesc, ((LPAUXCAPS)(LPVOID)&caps)->szPname);
|
|
break;
|
|
|
|
default:
|
|
goto lblCLEANUP;
|
|
break;
|
|
}
|
|
|
|
// Get Driver Name from module
|
|
if (! mregGetModuleName (hModule, pszDriver, MM_PATH))
|
|
{
|
|
LocalFree ((HLOCAL)pszDesc);
|
|
LocalFree ((HLOCAL)pszDriver);
|
|
return FALSE;
|
|
}
|
|
|
|
if (! mregCheckDriverEntry (pszClass, pszDriver, pszDesc,
|
|
physID, portID, fExternal))
|
|
goto lblCLEANUP;
|
|
|
|
fResult = TRUE;
|
|
|
|
lblCLEANUP:
|
|
if (pszDesc) LocalFree ((HLOCAL)pszDesc);
|
|
if (pszDriver) LocalFree ((HLOCAL)pszDriver);
|
|
|
|
return fResult;
|
|
} // End mregMigrateDriver
|
|
|
|
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Name: mregCheckDriverEntry
|
|
** Purpose: Checks if valid Driver entry exists in registry currently
|
|
** If not it creates a default one
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
BOOL mregCheckDriverEntry (
|
|
LPCTSTR pszClass,
|
|
LPCTSTR pszDriver,
|
|
LPCTSTR pszDesc,
|
|
UINT physID,
|
|
UINT portID,
|
|
BOOL fExternal)
|
|
{
|
|
DWORD entryID = 0;
|
|
|
|
// Check Driver Entry for existence
|
|
if (! mregGetDriverEntryID (pszClass, pszDriver, physID, portID, &entryID))
|
|
{
|
|
// Create New Driver Entry
|
|
return mregCreateDriverEntry (pszClass, pszDriver, pszDesc,
|
|
entryID, physID, portID, fExternal);
|
|
}
|
|
else
|
|
{
|
|
// Activate this driver entry
|
|
return mregActivateDriverEntry (pszClass, pszDriver, entryID, TRUE);
|
|
}
|
|
} // End mregCheckDriverEntry
|
|
|
|
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Name: mregGetDriverEntryID
|
|
** Purpose: Gets Entry ID for valid driver registry entry that matches
|
|
** this driver. Otherwise, it returns the first available number
|
|
** for creating a new entry
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
BOOL mregGetDriverEntryID (
|
|
LPCTSTR pszClass,
|
|
LPCTSTR pszDriver,
|
|
DWORD physID,
|
|
DWORD portID,
|
|
DWORD * pEntryID)
|
|
{
|
|
BOOL fResult = FALSE;
|
|
LPTSTR psz= NULL;
|
|
LPTSTR pszResource = NULL;
|
|
LPTSTR pszSubKey = NULL;
|
|
HKEY hClassKey = NULL;
|
|
HKEY hSubKey = NULL;
|
|
DWORD cbSize;
|
|
DWORD dwCreate;
|
|
TCHAR szValue[2];
|
|
DWORD cID;
|
|
DWORD dwVal;
|
|
DWORD cchLen;
|
|
DWORD cchBegin;
|
|
DWORD cchEnd;
|
|
DWORD dwIndex;
|
|
DWORD cchSize;
|
|
DWORD dwType;
|
|
LONG lResult;
|
|
|
|
// Validate Parameters
|
|
if ((!pszClass) || (!pszDriver))
|
|
return FALSE;
|
|
|
|
// Create Strings
|
|
cbSize = MM_PATH * sizeof(TCHAR);
|
|
pszResource = (LPTSTR)LocalAlloc (LPTR, cbSize);
|
|
if (!pszResource)
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
pszSubKey = (LPTSTR)LocalAlloc (LPTR, cbSize);
|
|
if (!pszSubKey)
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Get Resource String
|
|
wsprintf (pszResource, asz2Format, aszMediaResKey, pszClass);
|
|
|
|
// Open Resource String
|
|
lResult = RegOpenKey (HKEY_LOCAL_MACHINE, pszResource, &hClassKey);
|
|
if (ERROR_SUCCESS != lResult)
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Enumerate all keys looking for driver
|
|
cID = 0;
|
|
cchSize = MM_PATH;
|
|
dwIndex = 0;
|
|
while (ERROR_SUCCESS == RegEnumKey (hClassKey, dwIndex,
|
|
pszSubKey, cchSize))
|
|
|
|
{
|
|
dwIndex++;
|
|
cchSize = MM_PATH; // Reset Buffer Size (RegEnum Destroyed it)
|
|
|
|
// Do the driver names match
|
|
if (! lstrcmpni (pszDriver, pszSubKey, lstrlen(pszDriver)))
|
|
{
|
|
// Increment Driver Entry to next available entry number
|
|
// In case we jump out prematurely
|
|
cID++;
|
|
|
|
// Now make sure it looks valid
|
|
lResult = RegOpenKey (hClassKey, pszSubKey, &hSubKey);
|
|
if (ERROR_SUCCESS == lResult)
|
|
{
|
|
// Make sure it migrated OK
|
|
cbSize = sizeof (szValue);
|
|
dwType = REG_SZ;
|
|
lResult = RegQueryValueEx(hSubKey, aszMigrated, NULL, &dwType,
|
|
(LPBYTE)szValue, &cbSize);
|
|
if (ERROR_SUCCESS != lResult)
|
|
{
|
|
RegCloseKey (hSubKey);
|
|
continue;
|
|
}
|
|
|
|
if (szValue[0] != TEXT('1'))
|
|
{
|
|
RegCloseKey (hSubKey);
|
|
continue;
|
|
}
|
|
|
|
// compare physical ID's
|
|
cbSize = sizeof(DWORD);
|
|
dwType = REG_DWORD;
|
|
lResult = RegQueryValueEx(hSubKey, aszPhysID, NULL, &dwType,
|
|
(LPBYTE)&dwVal, &cbSize);
|
|
if (ERROR_SUCCESS != lResult)
|
|
{
|
|
RegCloseKey (hSubKey);
|
|
continue;
|
|
}
|
|
|
|
if (physID != dwVal)
|
|
{
|
|
RegCloseKey (hSubKey);
|
|
continue;
|
|
}
|
|
|
|
// compare port ID's
|
|
cbSize = sizeof(DWORD);
|
|
dwType = REG_DWORD;
|
|
lResult = RegQueryValueEx(hSubKey, aszPort, NULL, &dwType,
|
|
(LPBYTE)&dwVal, &cbSize);
|
|
if (ERROR_SUCCESS != lResult)
|
|
{
|
|
// No Port entry, defaults to 0
|
|
dwVal = 0;
|
|
}
|
|
RegCloseKey (hSubKey);
|
|
|
|
if (portID != dwVal)
|
|
continue;
|
|
|
|
// Success we found the correct driver registry key
|
|
fResult = TRUE;
|
|
cID--;
|
|
|
|
// Parse Driver Entry ID from String
|
|
cchLen = lstrlen (pszSubKey);
|
|
if (! FindChar (pszSubKey, cchLen, TEXT ('<'), &cchBegin))
|
|
break;
|
|
cchBegin++;
|
|
|
|
if (cchLen < cchBegin)
|
|
break;
|
|
if (! FindChar (&pszSubKey[cchBegin], cchLen - cchBegin, TEXT ('>'), &cchEnd))
|
|
break;
|
|
|
|
cchLen = cchEnd;
|
|
|
|
ConvertToNumber(&pszSubKey[cchBegin], cchLen, &cID);
|
|
break;
|
|
}
|
|
|
|
// The driver names are the same, but the ID's don't match
|
|
// Keep looking...
|
|
}
|
|
} // End While (RegEnum)
|
|
|
|
RegCloseKey (hClassKey);
|
|
|
|
if (pEntryID)
|
|
*pEntryID = cID;
|
|
|
|
lblCLEANUP:
|
|
|
|
if (pszResource) LocalFree ((HLOCAL)pszResource);
|
|
if (pszSubKey) LocalFree ((HLOCAL)pszSubKey);
|
|
|
|
return fResult;
|
|
} // End mregGetDriverEntryID
|
|
|
|
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Name: mregCreateDriverEntry
|
|
** Purpose: creates a default driver entry
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
BOOL mregCreateDriverEntry (
|
|
LPCTSTR pszClass,
|
|
LPCTSTR pszDriver,
|
|
LPCTSTR pszDesc,
|
|
UINT entryID,
|
|
UINT physID,
|
|
UINT portID,
|
|
BOOL fExternal)
|
|
{
|
|
BOOL fResult = FALSE;
|
|
LPTSTR pszResource = NULL;
|
|
LPTSTR pszDrvKey = NULL;
|
|
LPCTSTR pszTruthVal;
|
|
HKEY hMediaKey = NULL;
|
|
HKEY hDriverKey = NULL;
|
|
HKEY hInstrumentKey = NULL;
|
|
DWORD cbSize;
|
|
DWORD dwVal;
|
|
|
|
// Validate parameters
|
|
if ((!pszClass) || (!pszDriver) || (!pszDesc))
|
|
return FALSE;
|
|
|
|
// Create Strings
|
|
cbSize = MM_PATH * sizeof(TCHAR);
|
|
pszResource = (LPTSTR)LocalAlloc(LPTR, cbSize);
|
|
if (!pszResource)
|
|
return FALSE;
|
|
|
|
cbSize = MM_PATH * sizeof(TCHAR);
|
|
pszDrvKey = (LPTSTR)LocalAlloc(LPTR, cbSize);
|
|
if (!pszDrvKey)
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Get Media Resource Class Key
|
|
wsprintf (pszResource, asz2Format, aszMediaResKey, pszClass);
|
|
|
|
// Open Key, create it if it doesn't already exist
|
|
if (ERROR_SUCCESS != RegCreateKey (HKEY_LOCAL_MACHINE, pszResource,
|
|
&hMediaKey))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Create new driver key
|
|
wsprintf (pszDrvKey, aszDrvFormat, pszDriver, entryID);
|
|
if (ERROR_SUCCESS != RegCreateKey (hMediaKey, pszDrvKey,
|
|
&hDriverKey))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
RegCloseKey (hMediaKey);
|
|
hMediaKey = NULL;
|
|
|
|
// Set Active = "1".
|
|
cbSize = sizeof (aszTrue);
|
|
if (ERROR_SUCCESS != RegSetValueEx (hDriverKey, aszActive, 0,
|
|
REG_SZ, (LPBYTE)aszTrue, cbSize))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Set Description
|
|
cbSize = (lstrlen (pszDesc) + 1) * sizeof(TCHAR);
|
|
if (ERROR_SUCCESS != RegSetValueEx (hDriverKey, aszDesc, 0,
|
|
REG_SZ, (LPBYTE)pszDesc, cbSize))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Set DeviceID (Plug and Play)
|
|
cbSize = (lstrlen (aszNULL) + 1) * sizeof(TCHAR);
|
|
if (ERROR_SUCCESS != RegSetValueEx (hDriverKey, aszDeviceID, 0,
|
|
REG_SZ, (LPBYTE)aszNULL, cbSize))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Set DevNode (Plug and Play)
|
|
cbSize = 0;
|
|
if (ERROR_SUCCESS != RegSetValueEx (hDriverKey, aszDevNode, 0,
|
|
REG_BINARY, (LPBYTE)NULL, cbSize))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Set Driver
|
|
cbSize = (lstrlen (pszDriver) + 1) * sizeof(TCHAR);
|
|
if (ERROR_SUCCESS != RegSetValueEx (hDriverKey, aszDriver, 0,
|
|
REG_SZ, (LPBYTE)pszDriver, cbSize))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Set Friendly Name
|
|
cbSize = (lstrlen (pszDesc) + 1) * sizeof(TCHAR);
|
|
if (ERROR_SUCCESS != RegSetValueEx (hDriverKey, aszFriend, 0,
|
|
REG_SZ, (LPBYTE)pszDesc, cbSize))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Set External Device, if MIDI
|
|
if (! lstrcmpi(pszClass, aszMidi))
|
|
{
|
|
// Set External State
|
|
cbSize = (lstrlen (aszTrue) + 1) * sizeof(TCHAR);
|
|
pszTruthVal = fExternal ? aszTrue : aszFalse;
|
|
if (ERROR_SUCCESS != RegSetValueEx (hDriverKey, aszExternal, 0,
|
|
REG_SZ, (LPBYTE)pszTruthVal,
|
|
cbSize))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
}
|
|
|
|
// Set Physical Device ID
|
|
cbSize = sizeof(DWORD);
|
|
if (ERROR_SUCCESS != RegSetValueEx (hDriverKey, aszPhysID, 0,
|
|
REG_DWORD, (LPBYTE)&physID, cbSize))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Set Port
|
|
cbSize = sizeof(DWORD);
|
|
if (ERROR_SUCCESS != RegSetValueEx (hDriverKey, aszPort, 0,
|
|
REG_DWORD, (LPBYTE)&portID, cbSize))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Set Mapper Config
|
|
cbSize = sizeof(DWORD);
|
|
dwVal = 0;
|
|
if (ERROR_SUCCESS != RegSetValueEx (hDriverKey, aszMapConfig, 0,
|
|
REG_DWORD, (LPBYTE)&dwVal, cbSize))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Set SOFTWARE value (Plug and Play)
|
|
cbSize = 0;
|
|
if (ERROR_SUCCESS != RegSetValueEx (hDriverKey, aszSoftwareKey, 0,
|
|
REG_SZ, (LPBYTE)aszNULL, cbSize))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Create Instruments Key
|
|
if (ERROR_SUCCESS != RegCreateKey (hDriverKey, aszInstruments,
|
|
&hInstrumentKey))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
RegCloseKey (hInstrumentKey);
|
|
hInstrumentKey = NULL;
|
|
|
|
// Set MIGRATED value
|
|
// NOTE: this is always the very last thing to do to indicate successful creation
|
|
cbSize = (lstrlen (aszTrue) + 1) * sizeof(TCHAR);
|
|
if (ERROR_SUCCESS != RegSetValueEx (hDriverKey, aszMigrated, 0, REG_SZ, (LPBYTE)aszTrue, cbSize))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Success
|
|
fResult = TRUE;
|
|
|
|
lblCLEANUP:
|
|
if (hInstrumentKey) RegCloseKey (hInstrumentKey);
|
|
if (hDriverKey) RegCloseKey (hDriverKey);
|
|
if (hMediaKey) RegCloseKey (hMediaKey);
|
|
if (pszDrvKey) LocalFree ((HLOCAL)pszDrvKey);
|
|
if (pszResource) LocalFree ((HLOCAL)pszResource);
|
|
|
|
return fResult;
|
|
} // End mregCreateDriverEntry
|
|
|
|
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Name: mregActivateDriverEntry
|
|
** Purpose: activates a driver entry
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
BOOL mregActivateDriverEntry (
|
|
LPCTSTR pszClass,
|
|
LPCTSTR pszDriver,
|
|
DWORD entryID,
|
|
BOOL fSet)
|
|
{
|
|
BOOL fResult = FALSE;
|
|
LPTSTR pszResource = NULL;
|
|
LPTSTR pszDrvKey = NULL;
|
|
HKEY hMediaKey = NULL;
|
|
HKEY hDriverKey = NULL;
|
|
LPCTSTR pszTruth;
|
|
DWORD cbSize;
|
|
|
|
// Validate parameters
|
|
if ((!pszClass) || (!pszDriver))
|
|
return FALSE;
|
|
|
|
// Create Strings
|
|
cbSize = MM_PATH * sizeof(TCHAR);
|
|
pszResource = (LPTSTR)LocalAlloc(LPTR, cbSize);
|
|
if (!pszResource)
|
|
return FALSE;
|
|
|
|
pszDrvKey = (LPTSTR)LocalAlloc(LPTR, cbSize);
|
|
if (!pszDrvKey)
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Get Media Resource Class Key
|
|
wsprintf (pszResource, asz2Format, aszMediaResKey, pszClass);
|
|
|
|
// Open Key, create it if it doesn't already exist
|
|
if (ERROR_SUCCESS != RegCreateKey (HKEY_LOCAL_MACHINE, pszResource,
|
|
&hMediaKey))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Create new driver key
|
|
wsprintf (pszDrvKey, aszDrvFormat, pszDriver, entryID);
|
|
if (ERROR_SUCCESS != RegCreateKey (hMediaKey, pszDrvKey,
|
|
&hDriverKey))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
RegCloseKey (hMediaKey);
|
|
hMediaKey = NULL;
|
|
|
|
// Turn it on or off
|
|
pszTruth = (fSet ? aszTrue : aszFalse);
|
|
|
|
// Set Active = fSet
|
|
cbSize = sizeof (aszTrue);
|
|
if (ERROR_SUCCESS != RegSetValueEx (hDriverKey, aszActive, 0,
|
|
REG_SZ, (LPBYTE)pszTruth, cbSize))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
RegCloseKey (hDriverKey);
|
|
hDriverKey = NULL;
|
|
|
|
fResult = TRUE;
|
|
|
|
lblCLEANUP:
|
|
if (hDriverKey) RegCloseKey (hDriverKey);
|
|
if (hMediaKey) RegCloseKey (hMediaKey);
|
|
if (pszDrvKey) LocalFree ((HLOCAL)pszDrvKey);
|
|
if (pszResource) LocalFree ((HLOCAL)pszResource);
|
|
|
|
return fResult;
|
|
} // End mregActivateDriverEntry
|
|
|
|
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Name: mregDeactivateAllEntries
|
|
** Purpose: deactivates all entries for a particular class
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
BOOL mregDeactivateAllEntries (
|
|
LPCTSTR pszClass)
|
|
{
|
|
BOOL fResult = FALSE;
|
|
DWORD cbSize;
|
|
LPTSTR pszResource = NULL;
|
|
LPTSTR pszSubKey = NULL;
|
|
HKEY hClassKey;
|
|
HKEY hSubKey;
|
|
DWORD dwCreate;
|
|
DWORD dwIndex;
|
|
DWORD cchSize;
|
|
|
|
// Validate Parameters
|
|
if (!pszClass)
|
|
return FALSE;
|
|
|
|
// Create Strings
|
|
cbSize = MM_PATH * sizeof(TCHAR);
|
|
pszResource = (LPTSTR)LocalAlloc (LPTR, cbSize);
|
|
if (!pszResource)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pszSubKey = (LPTSTR)LocalAlloc (LPTR, cbSize);
|
|
if (!pszSubKey)
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Get Resource String
|
|
wsprintf (pszResource, asz2Format, aszMediaResKey, pszClass);
|
|
|
|
// Open Resource String
|
|
if (ERROR_SUCCESS != RegOpenKey (HKEY_LOCAL_MACHINE, pszResource,
|
|
&hClassKey))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Enumerate all keys looking for entries
|
|
dwIndex = 0;
|
|
cchSize = MM_PATH;
|
|
while (ERROR_SUCCESS == RegEnumKey (hClassKey, dwIndex,
|
|
pszSubKey, cchSize))
|
|
{
|
|
dwIndex++;
|
|
cchSize = MM_PATH; // Reset Buffer Size (RegEnum destroyed it)
|
|
|
|
// Open entry key
|
|
if (ERROR_SUCCESS == RegOpenKey (hClassKey, pszSubKey, &hSubKey))
|
|
{
|
|
// Set Active = "0".
|
|
cbSize = sizeof (aszFalse);
|
|
RegSetValueEx (hSubKey, aszActive, 0,
|
|
REG_SZ, (LPBYTE)aszFalse, cbSize);
|
|
RegCloseKey (hSubKey);
|
|
}
|
|
} // End While (RegEnum)
|
|
|
|
RegCloseKey (hClassKey);
|
|
|
|
fResult = TRUE;
|
|
|
|
lblCLEANUP:
|
|
|
|
if (pszResource) LocalFree ((HLOCAL)pszResource);
|
|
if (pszSubKey) LocalFree ((HLOCAL)pszSubKey);
|
|
|
|
return fResult;
|
|
} // End mregDeactivateAllEntries
|
|
|
|
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Name: FindChar
|
|
** Purpose: finds first occurence of a character in a string
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
BOOL FindChar (
|
|
LPTSTR pszSearch,
|
|
DWORD cchLen,
|
|
TCHAR cchFind,
|
|
DWORD * pdwOffset)
|
|
{
|
|
DWORD cch;
|
|
|
|
// Validate Parameters
|
|
if ((!pszSearch) || (cchLen == 0))
|
|
return FALSE;
|
|
|
|
cch = 0;
|
|
while ((cch < cchLen) && (pszSearch[cch] != TEXT ('\0')))
|
|
{
|
|
if (pszSearch[cch] == cchFind)
|
|
{
|
|
if (pdwOffset)
|
|
*pdwOffset = cch;
|
|
return TRUE;
|
|
}
|
|
cch++;
|
|
}
|
|
|
|
return FALSE;
|
|
} // End FindChar
|
|
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Name: ConvertToNumber
|
|
** Purpose: Similar to Atoi
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
BOOL ConvertToNumber (
|
|
LPTSTR pszConvert,
|
|
DWORD cchLen,
|
|
INT * pVal)
|
|
{
|
|
DWORD cchIndex;
|
|
TCHAR chVal;
|
|
DWORD fNeg = 0;
|
|
INT iVal = 0;
|
|
|
|
// Validate Parameters
|
|
if ((!pVal) || (!pszConvert) || (cchLen == 0))
|
|
return FALSE;
|
|
|
|
// Skip White Space, if any
|
|
cchIndex = 0;
|
|
while ((cchIndex < cchLen) &&
|
|
((TEXT (' ') == pszConvert[cchIndex]) ||
|
|
(TEXT ('\t') == pszConvert[cchIndex]) ||
|
|
(TEXT ('\r') == pszConvert[cchIndex]) ||
|
|
(TEXT ('\n') == pszConvert[cchIndex])))
|
|
{
|
|
cchIndex++;
|
|
}
|
|
if (cchIndex >= cchLen)
|
|
return FALSE;
|
|
|
|
// Get any sign
|
|
if (pszConvert[cchIndex] == TEXT ('-'))
|
|
{
|
|
fNeg = 1;
|
|
cchIndex++;
|
|
}
|
|
else if (pszConvert[cchIndex] == TEXT ('+'))
|
|
{
|
|
fNeg = 0;
|
|
cchIndex++;
|
|
}
|
|
|
|
// Get number
|
|
while (cchIndex < cchLen)
|
|
{
|
|
chVal = pszConvert[cchIndex];
|
|
if ((TEXT ('0') <= chVal) && (chVal <= TEXT ('9')))
|
|
iVal = iVal * 10 + (int)(chVal - TEXT ('0'));
|
|
cchIndex++;
|
|
}
|
|
|
|
// Negate
|
|
if (fNeg)
|
|
iVal = -iVal;
|
|
|
|
if (pVal)
|
|
*pVal = iVal;
|
|
|
|
return TRUE;
|
|
} // End ConvertToNumber
|
|
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Name: lstrcmpni
|
|
** Purpose: compares two strings up to length cchSize
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
int lstrcmpni (
|
|
LPCTSTR pszSrc1,
|
|
LPCTSTR pszSrc2,
|
|
DWORD cchSize)
|
|
{
|
|
int iResult;
|
|
LPTSTR psz1;
|
|
LPTSTR psz2;
|
|
DWORD cbSize;
|
|
|
|
if ((!pszSrc1) || (!pszSrc2))
|
|
return -1;
|
|
|
|
if (cchSize >= (MM_PATH-1))
|
|
return -1;
|
|
|
|
cbSize = MM_PATH * sizeof(TCHAR);
|
|
psz1 = (LPTSTR)LocalAlloc (LPTR, cbSize);
|
|
if (!psz1)
|
|
return -1;
|
|
|
|
psz2 = (LPTSTR)LocalAlloc (LPTR, cbSize);
|
|
if (!psz2)
|
|
{
|
|
LocalFree ((HLOCAL)psz1);
|
|
return -1;
|
|
}
|
|
|
|
// I use cchSize+1 instead of cchSize to work
|
|
// around an error in lstrcpyn
|
|
lstrcpyn (psz1, pszSrc1, cchSize+1);
|
|
psz1[cchSize] = 0;
|
|
|
|
lstrcpyn (psz2, pszSrc2, cchSize+1);
|
|
psz2[cchSize] = 0;
|
|
|
|
// Do actual compare
|
|
iResult = lstrcmpi (psz1, psz2);
|
|
|
|
LocalFree ((HLOCAL)psz1);
|
|
LocalFree ((HLOCAL)psz2);
|
|
|
|
return iResult;
|
|
} // End lstrcmpni
|
|
|
|
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Name: mregGetQueryDrvEntry
|
|
** Purpose: finds registry entry for this driver
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
BOOL mregGetQueryDrvEntry (
|
|
HMODULE hModule,
|
|
DWORD dwClass,
|
|
DWORD physID,
|
|
DWORD portID,
|
|
LPTSTR pszEntry,
|
|
UINT cchSize)
|
|
{
|
|
DWORD cbSize;
|
|
LPTSTR pszPath = NULL;
|
|
LPTSTR pszDriver = NULL;
|
|
BOOL fResult = FALSE;
|
|
UINT cchLen;
|
|
DWORD entryID;
|
|
LPCTSTR pszClass;
|
|
|
|
// Validate parameters
|
|
if ((!hModule) ||
|
|
(!pszEntry) ||
|
|
(!cchSize))
|
|
return FALSE;
|
|
|
|
// Create Strings
|
|
cbSize = MM_PATH * sizeof(TCHAR);
|
|
pszPath = (LPTSTR)LocalAlloc (LPTR, cbSize);
|
|
if (NULL == pszPath)
|
|
return FALSE;
|
|
|
|
pszDriver = (LPTSTR)LocalAlloc (LPTR, cbSize);
|
|
if (NULL == pszDriver)
|
|
{
|
|
LocalFree ((HLOCAL)pszPath);
|
|
return FALSE;
|
|
}
|
|
|
|
// Get Class string
|
|
switch (dwClass)
|
|
{
|
|
case TYPE_WAVEOUT:
|
|
case TYPE_WAVEIN:
|
|
pszClass = aszWave;
|
|
break;
|
|
|
|
case TYPE_MIDIOUT:
|
|
case TYPE_MIDIIN:
|
|
pszClass = aszMidi;
|
|
break;
|
|
|
|
case TYPE_AUX:
|
|
pszClass = aszAux;
|
|
break;
|
|
|
|
default:
|
|
// Unknown type
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Get Driver Name only
|
|
if (! mregGetModuleName (hModule, pszDriver, MM_PATH))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Get Entry ID
|
|
if (! mregGetDriverEntryID (pszClass, pszDriver, physID, portID, &entryID))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
wsprintf (pszPath, aszDrvFormat, pszDriver, entryID);
|
|
cchLen = lstrlen (pszPath);
|
|
if (cchLen >= cchSize)
|
|
goto lblCLEANUP;
|
|
|
|
// Copy result
|
|
lstrcpy (pszEntry, pszPath);
|
|
pszEntry[cchLen] = 0;
|
|
|
|
fResult = TRUE;
|
|
|
|
lblCLEANUP:
|
|
if (pszPath) LocalFree ((HLOCAL)pszPath);
|
|
if (pszDriver) LocalFree ((HLOCAL)pszDriver);
|
|
|
|
return fResult;
|
|
} // End GetQueryDrvEntry
|
|
|
|
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** Name: mregGetQueryName
|
|
** Purpose: gets driver description from the registry
|
|
**-----------------------------------------------------------------------------
|
|
*/
|
|
BOOL mregGetQueryName (
|
|
HMODULE hModule,
|
|
DWORD dwClass,
|
|
DWORD physID,
|
|
DWORD portID,
|
|
LPTSTR pszName,
|
|
UINT cchSize)
|
|
{
|
|
BOOL fResult = FALSE;
|
|
LPTSTR pszAlias= NULL;
|
|
LPTSTR pszBuff = NULL;
|
|
LPTSTR pszDriver = NULL;
|
|
HKEY hKey;
|
|
DWORD dwType;
|
|
DWORD cbSize;
|
|
LONG lResult;
|
|
LPCTSTR pszClass;
|
|
DWORD entryID;
|
|
|
|
// Create Strings
|
|
cbSize = MM_PATH * sizeof(TCHAR);
|
|
pszAlias = (LPTSTR)LocalAlloc (LPTR, cbSize);
|
|
if (NULL == pszAlias)
|
|
return FALSE;
|
|
|
|
pszDriver = (LPTSTR)LocalAlloc (LPTR, cbSize);
|
|
if (NULL == pszDriver)
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
pszBuff = (LPTSTR)LocalAlloc (LPTR, cbSize);
|
|
if (NULL == pszBuff)
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Get Driver
|
|
if (! mregGetModuleName (hModule, pszDriver, MM_PATH))
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Get Class
|
|
switch (dwClass)
|
|
{
|
|
case TYPE_WAVEOUT:
|
|
case TYPE_WAVEIN:
|
|
pszClass = aszWave;
|
|
break;
|
|
|
|
case TYPE_MIDIOUT:
|
|
case TYPE_MIDIIN:
|
|
pszClass = aszMidi;
|
|
break;
|
|
|
|
case TYPE_AUX:
|
|
pszClass = aszAux;
|
|
break;
|
|
|
|
default:
|
|
// Unknown type
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Get Driver Entry ID
|
|
if (! mregGetDriverEntryID (pszClass, pszDriver, physID, portID, &entryID))
|
|
goto lblCLEANUP;
|
|
|
|
// Create Driver Registry Key entry
|
|
wsprintf (pszAlias, aszDrvFormat, pszDriver, entryID);
|
|
wsprintf (pszBuff, asz3Format, aszMediaResKey, pszClass, pszAlias);
|
|
|
|
lResult = RegOpenKey (HKEY_LOCAL_MACHINE, pszBuff, &hKey);
|
|
if (ERROR_SUCCESS != lResult)
|
|
{
|
|
goto lblCLEANUP;
|
|
}
|
|
|
|
// Get Description from registry
|
|
cbSize = cchSize * sizeof(TCHAR);
|
|
dwType = REG_SZ;
|
|
lResult = RegQueryValueEx (hKey, aszDesc, NULL, &dwType, (LPSTR)pszName, &cbSize);
|
|
if (ERROR_SUCCESS != lResult)
|
|
{
|
|
RegCloseKey (hKey);
|
|
goto lblCLEANUP;
|
|
}
|
|
RegCloseKey (hKey);
|
|
|
|
// Success
|
|
fResult = TRUE;
|
|
|
|
lblCLEANUP:
|
|
if (pszDriver) LocalFree ((HLOCAL)pszDriver);
|
|
if (pszBuff) LocalFree ((HLOCAL)pszBuff);
|
|
if (pszAlias) LocalFree ((HLOCAL)pszAlias);
|
|
|
|
return fResult;
|
|
} // End mregGetQueryName
|
|
|
|
/*
|
|
**-----------------------------------------------------------------------------
|
|
** End of File
|
|
**-----------------------------------------------------------------------------
|
|
*/
|