NT4/private/windows/media/winmm/migrate.c
2020-09-30 17:12:29 +02:00

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
**-----------------------------------------------------------------------------
*/