667 lines
19 KiB
C
667 lines
19 KiB
C
/**********************************************************************
|
|
|
|
Copyright (c) 1992-1999 Microsoft Corporation
|
|
|
|
mididev.c
|
|
|
|
DESCRIPTION:
|
|
Code to match device ID's with associated registry entries
|
|
|
|
HISTORY:
|
|
02/24/95 [jimge] created.
|
|
|
|
*********************************************************************/
|
|
#include <windows.h>
|
|
#include <windowsx.h>
|
|
#include <winerror.h>
|
|
#include <regstr.h>
|
|
#include <mmsystem.h>
|
|
#include <mmddkp.h>
|
|
|
|
#include "idf.h"
|
|
#include "midimap.h"
|
|
#include "debug.h"
|
|
|
|
typedef struct tagMDEV_NODE *PMDEV_NODE;
|
|
typedef struct tagMDEV_NODE
|
|
{
|
|
PMDEV_NODE pNext;
|
|
TCHAR szAlias[CB_MAXALIAS];
|
|
DWORD dwDevNode;
|
|
TCHAR szDriver[CB_MAXDRIVER];
|
|
UINT uDeviceID;
|
|
UINT uPort;
|
|
BOOL fNewDriver;
|
|
} MDEV_NODE;
|
|
|
|
static TCHAR BCODE gszMediaRsrcKey[] =
|
|
REGSTR_PATH_MEDIARESOURCES TEXT ("\\MIDI");
|
|
|
|
static TCHAR BCODE gszDriverKey[] =
|
|
REGSTR_PATH_MEDIARESOURCES TEXT ("\\MIDI\\%s");
|
|
|
|
static TCHAR BCODE gszDriverValue[] = TEXT ("Driver");
|
|
static TCHAR BCODE gszDevNodeValue[] = TEXT ("DevNode");
|
|
static TCHAR BCODE gszPortValue[] = TEXT ("Port");
|
|
static TCHAR BCODE gszActiveValue[] = TEXT ("Active");
|
|
static TCHAR BCODE gszMapperConfig[] = TEXT ("MapperConfig");
|
|
|
|
static PMDEV_NODE gpMDevList = NULL;
|
|
static DWORD gdwNewDrivers = (DWORD)-1L;
|
|
|
|
PRIVATE BOOL FNLOCAL mdev_BuildRegList(
|
|
void);
|
|
|
|
PRIVATE BOOL FNLOCAL mdev_SyncDeviceIDs(
|
|
void);
|
|
|
|
PRIVATE BOOL FNLOCAL mdev_MarkActiveDrivers(
|
|
void);
|
|
|
|
#ifdef DEBUG
|
|
PRIVATE VOID FNLOCAL mdev_ListActiveDrivers(
|
|
void);
|
|
#endif
|
|
|
|
BOOL FNGLOBAL mdev_Init(
|
|
void)
|
|
{
|
|
if (gpMDevList)
|
|
mdev_Free();
|
|
|
|
if ((!mdev_BuildRegList()) ||
|
|
(!mdev_SyncDeviceIDs()) ||
|
|
(!mdev_MarkActiveDrivers()))
|
|
{
|
|
mdev_Free();
|
|
return FALSE;
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
mdev_ListActiveDrivers();
|
|
#endif
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// mdev_BuildRegList
|
|
//
|
|
// Builds the base device list out of the registry
|
|
//
|
|
// Assumes the list has been cleared
|
|
//
|
|
// For each alias (key) under MediaResources\MIDI
|
|
// Make sure the Active value exists and is '1'
|
|
// Allocate a list node
|
|
// Try to read the alias's devnode
|
|
// If the alias's devnode is 0 or missing,
|
|
// Read the alias's driver name
|
|
// Read the alias's port number
|
|
// Add the alias to the global list
|
|
//
|
|
// The uDeviceID member will not be initialized by this routine;
|
|
// mdev_SyncDeviceIDs must be called to figure out the current
|
|
// device ID mapping.
|
|
//
|
|
PRIVATE BOOL FNLOCAL mdev_BuildRegList(
|
|
void)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
HKEY hKeyMediaRsrc = NULL;
|
|
HKEY hKeyThisAlias = NULL;
|
|
DWORD dwEnumAlias = 0;
|
|
LPTSTR pstrAlias = NULL;
|
|
PMDEV_NODE pmd = NULL;
|
|
TCHAR szActive[2];
|
|
DWORD dwPort;
|
|
DWORD cbValue;
|
|
DWORD dwType;
|
|
DWORD dwMapperConfig;
|
|
|
|
cbValue = CB_MAXALIAS * sizeof(TCHAR);
|
|
pstrAlias = (LPTSTR)LocalAlloc(LPTR, CB_MAXALIAS * sizeof(TCHAR));
|
|
if (NULL == pstrAlias)
|
|
{
|
|
DPF(1, TEXT ("mdev_Init: Out of memory"));
|
|
goto mBRL_Cleanup;
|
|
}
|
|
|
|
if (ERROR_SUCCESS != RegOpenKey(HKEY_LOCAL_MACHINE,
|
|
gszMediaRsrcKey,
|
|
&hKeyMediaRsrc))
|
|
{
|
|
DPF(1, TEXT ("mdev_Init: Could not open ...\\MediaResoruces\\MIDI"));
|
|
goto mBRL_Cleanup;
|
|
}
|
|
|
|
|
|
while (ERROR_SUCCESS == RegEnumKey(hKeyMediaRsrc,
|
|
dwEnumAlias++,
|
|
pstrAlias,
|
|
CB_MAXALIAS))
|
|
{
|
|
if (ERROR_SUCCESS != (RegOpenKey(hKeyMediaRsrc,
|
|
pstrAlias,
|
|
&hKeyThisAlias)))
|
|
{
|
|
DPF(1, TEXT ("mdev_Init: Could not open enum'ed key %s"), (LPTSTR)pstrAlias);
|
|
continue;
|
|
}
|
|
|
|
// MUST have Active == "1" to be running
|
|
//
|
|
cbValue = sizeof(szActive);
|
|
if (ERROR_SUCCESS != (RegQueryValueEx(hKeyThisAlias,
|
|
gszActiveValue,
|
|
NULL,
|
|
&dwType,
|
|
(LPSTR)szActive,
|
|
&cbValue)) ||
|
|
*szActive != '1')
|
|
{
|
|
DPF(2, TEXT ("mdev_Init: Device %s exists but is not loaded."),
|
|
(LPTSTR)pstrAlias);
|
|
RegCloseKey(hKeyThisAlias);
|
|
continue;
|
|
}
|
|
|
|
// Determine if we have ever configured with this driver before
|
|
//
|
|
cbValue = sizeof(dwMapperConfig);
|
|
if (ERROR_SUCCESS != (RegQueryValueEx(hKeyThisAlias,
|
|
gszMapperConfig,
|
|
NULL,
|
|
&dwType,
|
|
(LPSTR)&dwMapperConfig,
|
|
&cbValue)))
|
|
dwMapperConfig = 0;
|
|
|
|
#ifdef DEBUG
|
|
if (!dwMapperConfig)
|
|
DPF(1, TEXT ("Alias '%s' is a new driver."),
|
|
(LPTSTR)pstrAlias);
|
|
#endif
|
|
|
|
// We have a running driver, go ahead and alloc a node
|
|
// for it
|
|
//
|
|
pmd = (PMDEV_NODE)LocalAlloc(LPTR, sizeof(*pmd));
|
|
if (NULL == pmd)
|
|
{
|
|
DPF(1, TEXT ("mdev_Init: Out of memory allocating node for %s"),
|
|
(LPTSTR)pstrAlias);
|
|
RegCloseKey(hKeyThisAlias);
|
|
continue;
|
|
}
|
|
|
|
lstrcpyn(pmd->szAlias, pstrAlias, sizeof(pmd->szAlias) - 1);
|
|
pmd->szAlias[sizeof(pmd->szAlias) - 1] = '\0';
|
|
|
|
pmd->fNewDriver = (dwMapperConfig ? FALSE : TRUE);
|
|
|
|
// Try to get the DevNode value
|
|
//
|
|
cbValue = sizeof(pmd->dwDevNode);
|
|
if (ERROR_SUCCESS != RegQueryValueEx(hKeyThisAlias,
|
|
gszDevNodeValue,
|
|
NULL,
|
|
&dwType,
|
|
(LPSTR)(LPDWORD)&pmd->dwDevNode,
|
|
&cbValue))
|
|
{
|
|
// Ok to not have a devnode value, 3.1 drivers don't
|
|
//
|
|
|
|
DPF(2, TEXT ("mdev_Init: Device %s has no devnode; must be 3.1"),
|
|
(LPTSTR)pstrAlias);
|
|
pmd->dwDevNode = 0;
|
|
}
|
|
|
|
// Leave something reasonable in driver even if we don't
|
|
// expect to use it
|
|
//
|
|
*pmd->szDriver = '\0';
|
|
|
|
// If we didn't get a devnode or it was 0, and we can't find the
|
|
// driver name to match against, we can't use this entry. (If it
|
|
// has no ring 3 driver, it can't be running anyway).
|
|
//
|
|
if (!pmd->dwDevNode)
|
|
{
|
|
cbValue = sizeof(pmd->szDriver);
|
|
if (ERROR_SUCCESS != RegQueryValueEx(
|
|
hKeyThisAlias,
|
|
gszDriverValue,
|
|
NULL,
|
|
&dwType,
|
|
(LPSTR)pmd->szDriver,
|
|
&cbValue))
|
|
{
|
|
DPF(1, TEXT ("mdev_Init: Device %s has no ring 3 driver entry"),
|
|
(LPTSTR)pstrAlias);
|
|
LocalFree((HLOCAL)pmd);
|
|
RegCloseKey(hKeyThisAlias);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// Success! Now try to figure out the port number
|
|
//
|
|
cbValue = sizeof(dwPort);
|
|
|
|
// Guard against INF's which only specify a byte's worth of
|
|
// port value
|
|
//
|
|
dwPort = 0;
|
|
if (ERROR_SUCCESS != RegQueryValueEx(hKeyThisAlias,
|
|
gszPortValue,
|
|
NULL,
|
|
&dwType,
|
|
(LPSTR)(LPDWORD)&dwPort,
|
|
&cbValue))
|
|
{
|
|
DPF(2, TEXT ("mdev_Init: Device %s has no port entry; using 0."),
|
|
(LPTSTR)pstrAlias);
|
|
dwPort = 0;
|
|
}
|
|
|
|
pmd->uPort = (UINT)dwPort;
|
|
|
|
// We have a valid node, put it into the list
|
|
//
|
|
pmd->pNext = gpMDevList;
|
|
gpMDevList = pmd;
|
|
|
|
RegCloseKey(hKeyThisAlias);
|
|
}
|
|
|
|
fRet = TRUE;
|
|
|
|
mBRL_Cleanup:
|
|
|
|
|
|
if (hKeyMediaRsrc) RegCloseKey(hKeyMediaRsrc);
|
|
if (pstrAlias) LocalFree((HLOCAL)pstrAlias);
|
|
|
|
return fRet;
|
|
}
|
|
|
|
//
|
|
// mdev_SyncDeviceIDs
|
|
//
|
|
// Traverse the device list and bring the uDeviceID members up to date.
|
|
// Also remove any devices which MMSYSTEM claims are not really running.
|
|
//
|
|
// NOTE: The uDeviceID member is actually the device ID of the base driver.
|
|
// If you want to open the device, you have to add uDeviceID and uPort for
|
|
// the node you want to open.
|
|
//
|
|
// Set all uDeviceID's to NO_DEVICEID
|
|
//
|
|
// For each base device ID in MMSYSTEM (i.e. port 0 on each loaded driver)
|
|
// Get the matching alias from MMSYSTEM
|
|
// Locate the node with that alias in the device list
|
|
// Set that node's uDeviceID
|
|
//
|
|
// For each node in the device list with non-zero port
|
|
// If this node has a DevNode
|
|
// Find a matching node by DevNode with port == 0 and get its device ID
|
|
// else
|
|
// Find a matching node by driver name with port == 0 and get its device ID
|
|
//
|
|
// NOTE: We match by driver name on DevNode == 0 (3.1 devices) because it
|
|
// isn't possible to have multiple instances of a 3.1 driver loaded.
|
|
//
|
|
// For each node in the device list,
|
|
// If the node's uDeviceID is still not set,
|
|
// Remove and free the node
|
|
//
|
|
PRIVATE BOOL FNLOCAL mdev_SyncDeviceIDs(
|
|
void)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
LPTSTR pstrAlias = NULL;
|
|
|
|
PMDEV_NODE pmdCurr;
|
|
PMDEV_NODE pmdPrev;
|
|
PMDEV_NODE pmdEnum;
|
|
UINT cDev;
|
|
UINT idxDev;
|
|
DWORD cPort;
|
|
MMRESULT mmr;
|
|
DWORD cbSize;
|
|
|
|
cbSize = CB_MAXALIAS * sizeof(TCHAR);
|
|
pstrAlias = (LPTSTR)LocalAlloc(LPTR, cbSize);
|
|
if (NULL == pstrAlias)
|
|
{
|
|
goto mSDI_Cleanup;
|
|
}
|
|
|
|
// The device list has been built and the uPort member is valid.
|
|
// Now update the uDeviceID field to be proper. First, walk the list
|
|
// and set them all to NO_DEVICEID.
|
|
|
|
for (pmdCurr = gpMDevList; pmdCurr; pmdCurr = pmdCurr->pNext)
|
|
pmdCurr->uDeviceID = NO_DEVICEID;
|
|
|
|
// Now walk MMSYSTEM's list of loaded drivers and fill in all the port 0
|
|
// nodes with their proper device ID
|
|
//
|
|
|
|
cDev = midiOutGetNumDevs();
|
|
|
|
for (idxDev = 0; idxDev < cDev; )
|
|
{
|
|
mmr = (MMRESULT)midiOutMessage((HMIDIOUT)(UINT_PTR)idxDev,
|
|
#ifdef WINNT
|
|
DRV_QUERYNUMPORTS,
|
|
#else
|
|
MODM_GETNUMDEVS,
|
|
#endif // End WINNT
|
|
(DWORD_PTR)(LPDWORD)&cPort,
|
|
0);
|
|
if (mmr)
|
|
{
|
|
DPF(1, TEXT ("mdev_Sync: Device ID %u returned %u for MODM_GETNUMDEVS"),
|
|
(UINT)idxDev,
|
|
(UINT)mmr);
|
|
|
|
++idxDev;
|
|
continue;
|
|
}
|
|
|
|
mmr = (MMRESULT)midiOutMessage((HMIDIOUT)(UINT_PTR)idxDev,
|
|
DRV_QUERYDRVENTRY,
|
|
#ifdef WINNT
|
|
(DWORD_PTR)(LPTSTR)pstrAlias,
|
|
#else
|
|
(DWORD_PTR)(LPTSTR)pstrPath,
|
|
#endif // End Winnt
|
|
|
|
CB_MAXALIAS);
|
|
|
|
if (!mmr)
|
|
{
|
|
for (pmdCurr = gpMDevList; pmdCurr; pmdCurr = pmdCurr->pNext)
|
|
{
|
|
if ((0 == pmdCurr->uPort) &&
|
|
(! lstrcmpi(pstrAlias, pmdCurr->szAlias)))
|
|
{
|
|
pmdCurr->uDeviceID = idxDev;
|
|
break;
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
if (!pmdCurr)
|
|
{
|
|
DPF(1, TEXT ("mdev_Sync: Device ID %u not found in device list."),
|
|
(UINT)idxDev);
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
DPF(1, TEXT ("mdev_Sync: Device ID %u returned %u for DRV_QUERYDRVENTRY"),
|
|
(UINT)idxDev,
|
|
(UINT)mmr);
|
|
}
|
|
|
|
idxDev += (UINT)cPort;
|
|
}
|
|
|
|
// Now walk the list again. This time we catch all the non-zero ports
|
|
// and set their uDeviceID properly.
|
|
//
|
|
for (pmdCurr = gpMDevList; pmdCurr; pmdCurr = pmdCurr->pNext)
|
|
{
|
|
if (!pmdCurr->uPort)
|
|
continue;
|
|
|
|
if (pmdCurr->dwDevNode)
|
|
{
|
|
for (pmdEnum = gpMDevList; pmdEnum; pmdEnum = pmdEnum->pNext)
|
|
if (0 == pmdEnum->uPort &&
|
|
pmdEnum->dwDevNode == pmdCurr->dwDevNode)
|
|
{
|
|
pmdCurr->uDeviceID = pmdEnum->uDeviceID;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (pmdEnum = gpMDevList; pmdEnum; pmdEnum = pmdEnum->pNext)
|
|
if (0 == pmdEnum->uPort &&
|
|
!lstrcmpi(pmdEnum->szDriver, pmdCurr->szDriver))
|
|
{
|
|
pmdCurr->uDeviceID = pmdEnum->uDeviceID;
|
|
break;
|
|
}
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
if (!pmdEnum)
|
|
{
|
|
DPF(1, TEXT ("mdev_Sync: No parent driver found for %s"),
|
|
(LPTSTR)pmdCurr->szAlias);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// Now we walk the list one more time and discard anyone without a device
|
|
// ID assigned.
|
|
//
|
|
|
|
pmdPrev = NULL;
|
|
pmdCurr = gpMDevList;
|
|
|
|
while (pmdCurr)
|
|
{
|
|
if (NO_DEVICEID == pmdCurr->uDeviceID)
|
|
{
|
|
DPF(1, TEXT ("mdev_Sync: Removing %s; never found a device ID"),
|
|
(LPTSTR)pmdCurr->szAlias);
|
|
|
|
if (pmdPrev)
|
|
pmdPrev->pNext = pmdCurr->pNext;
|
|
else
|
|
gpMDevList = pmdCurr->pNext;
|
|
|
|
LocalFree((HLOCAL)pmdCurr);
|
|
|
|
pmdCurr = (pmdPrev ? pmdPrev->pNext : gpMDevList);
|
|
}
|
|
else
|
|
{
|
|
pmdPrev = pmdCurr;
|
|
pmdCurr = pmdCurr->pNext;
|
|
}
|
|
}
|
|
|
|
fRet = TRUE;
|
|
|
|
mSDI_Cleanup:
|
|
if (pstrAlias) LocalFree((HLOCAL)pstrAlias);
|
|
|
|
return fRet;
|
|
}
|
|
|
|
//
|
|
// mdev_MarkActiveDrivers
|
|
//
|
|
// Mark drivers which are loaded and have not been seen before by
|
|
// mapper configuration as seen. Also flag that we want to run
|
|
// RunOnce if there are any of these
|
|
//
|
|
PRIVATE BOOL FNLOCAL mdev_MarkActiveDrivers(
|
|
void)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
HKEY hKeyMediaRsrc = NULL;
|
|
HKEY hKeyThisAlias = NULL;
|
|
|
|
DWORD dwMapperConfig;
|
|
PMDEV_NODE pmd;
|
|
|
|
if (ERROR_SUCCESS != RegOpenKey(HKEY_LOCAL_MACHINE,
|
|
gszMediaRsrcKey,
|
|
&hKeyMediaRsrc))
|
|
{
|
|
DPF(1, TEXT ("mdev_MarkActiveDrivers: Could not open ")
|
|
TEXT ("...\\MediaResources\\MIDI"));
|
|
goto mMAD_Cleanup;
|
|
}
|
|
|
|
gdwNewDrivers = 0;
|
|
for (pmd = gpMDevList; pmd; pmd = pmd->pNext)
|
|
if (pmd->fNewDriver)
|
|
{
|
|
++gdwNewDrivers;
|
|
|
|
// Mark this driver as seen
|
|
//
|
|
if (ERROR_SUCCESS != (RegOpenKey(hKeyMediaRsrc,
|
|
pmd->szAlias,
|
|
&hKeyThisAlias)))
|
|
{
|
|
DPF(1, TEXT ("mdev_MarkActiveDrivers: Could not open alias '%s'"),
|
|
(LPTSTR)pmd->szAlias);
|
|
goto mMAD_Cleanup;
|
|
}
|
|
|
|
dwMapperConfig = 1;
|
|
RegSetValueEx(hKeyThisAlias,
|
|
gszMapperConfig,
|
|
0,
|
|
REG_DWORD,
|
|
(LPSTR)&dwMapperConfig,
|
|
sizeof(dwMapperConfig));
|
|
|
|
RegCloseKey(hKeyThisAlias);
|
|
}
|
|
|
|
fRet = TRUE;
|
|
|
|
mMAD_Cleanup:
|
|
|
|
if (hKeyMediaRsrc) RegCloseKey(hKeyMediaRsrc);
|
|
|
|
return fRet;
|
|
}
|
|
|
|
//
|
|
// mdev_ListActiveDrivers
|
|
//
|
|
// List the currently loaded drivers to debug output
|
|
//
|
|
#ifdef DEBUG
|
|
PRIVATE VOID FNLOCAL mdev_ListActiveDrivers(
|
|
void)
|
|
{
|
|
PMDEV_NODE pmd;
|
|
static TCHAR BCODE szNo[] = TEXT ("No");
|
|
static TCHAR BCODE szYes[] = TEXT ("Yes");
|
|
|
|
DPF(2, TEXT ("=== mdev_ListActiveDrivers start ==="));
|
|
for (pmd = gpMDevList; pmd; pmd = pmd->pNext)
|
|
{
|
|
DPF(2, TEXT ("Alias %-31.31s Driver %-31.31s"),
|
|
(LPTSTR)pmd->szAlias,
|
|
(LPTSTR)pmd->szDriver);
|
|
DPF(2, TEXT (" dwDevNode %08lX uDeviceID %u uPort %u fNewDriver %s"),
|
|
pmd->dwDevNode,
|
|
pmd->uDeviceID,
|
|
pmd->uPort,
|
|
(LPTSTR)(pmd->fNewDriver ? szYes : szNo));
|
|
}
|
|
DPF(2, TEXT ("=== mdev_ListActiveDrivers end ==="));
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// mdev_Free
|
|
//
|
|
// Discard the current device list
|
|
//
|
|
void FNGLOBAL mdev_Free(
|
|
void)
|
|
{
|
|
PMDEV_NODE pmdNext;
|
|
PMDEV_NODE pmdCurr;
|
|
|
|
pmdCurr = gpMDevList;
|
|
|
|
while (pmdCurr)
|
|
{
|
|
pmdNext = pmdCurr->pNext;
|
|
|
|
LocalFree((HLOCAL)pmdCurr);
|
|
pmdCurr = pmdNext;
|
|
}
|
|
|
|
gpMDevList = NULL;
|
|
|
|
gdwNewDrivers = (DWORD)-1L;
|
|
}
|
|
|
|
//
|
|
// mdev_GetDeviceID
|
|
//
|
|
// Get the current device ID for the given alias.
|
|
//
|
|
UINT FNGLOBAL mdev_GetDeviceID(
|
|
LPTSTR lpstrAlias)
|
|
{
|
|
PMDEV_NODE pmd;
|
|
|
|
for (pmd = gpMDevList; pmd; pmd = pmd->pNext)
|
|
if (!lstrcmpi(pmd->szAlias, lpstrAlias))
|
|
return pmd->uDeviceID + pmd->uPort;
|
|
|
|
DPF(1, TEXT ("mdev_GetDeviceID: Failed for %s"), lpstrAlias);
|
|
return NO_DEVICEID;
|
|
}
|
|
|
|
//
|
|
// mdev_GetAlias
|
|
//
|
|
// Get the registry alias for the requested device ID
|
|
//
|
|
BOOL FNGLOBAL mdev_GetAlias(
|
|
UINT uDeviceID,
|
|
LPTSTR lpstrBuffer,
|
|
UINT cbBuffer)
|
|
{
|
|
PMDEV_NODE pmd;
|
|
|
|
for (pmd = gpMDevList; pmd; pmd = pmd->pNext)
|
|
if (uDeviceID == (pmd->uDeviceID + pmd->uPort))
|
|
{
|
|
lstrcpyn(lpstrBuffer, pmd->szAlias, cbBuffer);
|
|
return TRUE;
|
|
}
|
|
|
|
DPF(1, TEXT ("mdev_GetAlias: Failed for device ID %u"), uDeviceID);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// mdev_NewDrivers
|
|
//
|
|
// Returns TRUE if there were new drivers in the registry that we've never
|
|
// encountered before
|
|
//
|
|
BOOL FNGLOBAL mdev_NewDrivers(
|
|
void)
|
|
{
|
|
if (gdwNewDrivers == (DWORD)-1L)
|
|
{
|
|
DPF(0, TEXT ("mdevNewDrivers() called before mdev_Init()!"));
|
|
return FALSE;
|
|
}
|
|
|
|
return (BOOL)(gdwNewDrivers != 0);
|
|
}
|