2020-09-30 17:12:29 +02:00

1600 lines
36 KiB
C

/****************************************************************************
*
* MDGUTILS.C
*
* Adapter Detection DLL Utility Functions
*
* Copyright (c) Madge Networks Ltd 1994
*
* COMPANY CONFIDENTIAL - RELEASED TO MICROSOFT CORP. ONLY FOR DEVELOPMENT
* OF WINDOWS95 NETCARD DETECTION - THIS SOURCE IS NOT TO BE RELEASED OUTSIDE
* OF MICROSOFT WITHOUT EXPLICIT WRITTEN PERMISSION FROM AN AUTHORISED
* OFFICER OF MADGE NETWORKS LTD.
*
* Created: PBA 19/08/1994
* Derived initially from the DTAUX.C DDK sample.
*
****************************************************************************/
#include <ntddk.h>
#include <ntddnetd.h>
#include <windef.h>
#include <winerror.h>
//
// Prototype "borrowed" from WINUSER.H
//
extern int WINAPIV wsprintfW(LPWSTR, LPCWSTR, ...);
/*---------------------------------------------------------------------------
|
| Define API decoration for direct importing of DLL references.
|
---------------------------------------------------------------------------*/
#if !defined(_ADVAPI32_)
#define WINADVAPI DECLSPEC_IMPORT
#else
#define WINADVAPI
#endif
/*---------------------------------------------------------------------------
|
| FUDGE the definition of LPSECURITY_ATTRIBUTES.
|
|--------------------------------------------------------------------------*/
typedef void * LPSECURITY_ATTRIBUTES;
/*---------------------------------------------------------------------------
|
| File System time stamps are represented with the following structure.
|
---------------------------------------------------------------------------*/
typedef struct _FILETIME
{
DWORD dwLowDateTime;
DWORD dwHighDateTime;
}
FILETIME, *PFILETIME, *LPFILETIME;
//
// These includes require the typedefs above.
//
#include <winreg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mdgncdet.h"
/*---------------------------------------------------------------------------
|
| Maximum size of the bus information that can be extracted from the
| registry.
|
---------------------------------------------------------------------------*/
#define MAX_BUS_INFO_SIZE 16384
/*---------------------------------------------------------------------------
|
| Registry key strings.
|
---------------------------------------------------------------------------*/
static PSTR BusTypeBase = "Hardware\\Description\\System\\";
static PSTR ConfigData = "Configuration Data";
static PSTR MicroChanTypeName = "MultifunctionAdapter";
static PSTR EisaTypeName = "EisaAdapter";
static PSTR PcmciaTypeName = "PCMCIA PCCARDs";
static PSTR NetworkCardsBase =
"Software\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards";
static PSTR ServiceName = "ServiceName";
static PSTR ManufacturerName = "Manufacturer";
static PSTR MadgeName = "Madge";
static PSTR DriverName = "mdgmport";
static PSTR ServicesBase = "System\\CurrentControlSet\\Services\\";
static PSTR ParametersName = "\\Parameters";
static PSTR SlotNumberName = "SlotNumber";
static PSTR IoLocationName = "IoLocation";
static PSTR BusNumberName = "BusNumber";
static PSTR ProcessorsBase =
"Hardware\\Description\\System\\CentralProcessor";
/*---------------------------------------------------------------------------
|
| Function - GetBusTypeKey
|
| Parameters - busNumber -> Number of the bus we're interested in.
| busTypeName -> The name of the bus type.
| interfaceType -> The NT interface type of the bus.
| infoHandle -> Pointer to a holder for a pointer to
| a returned bus information structure.
|
| Purpose - Extract the information about a bus from the registry.
|
| Returns - TRUE on success or FALSE on failure.
|
---------------------------------------------------------------------------*/
static BOOLEAN
GetBusTypeKey(
ULONG busNumber,
const CHAR * busTypeName,
INT interfaceType,
VOID * * infoHandle
)
{
CHAR busTypePath[MAX_PATH];
UCHAR * bufferPointer;
char subkeyName[MAX_PATH];
PCM_FULL_RESOURCE_DESCRIPTOR fullResource;
HKEY busTypeHandle;
HKEY busHandle;
FILETIME lastWrite;
ULONG index;
DWORD type;
DWORD bufferSize;
DWORD nameSize;
LONG err;
BOOL result;
//
// Do some initialisation.
//
bufferPointer = NULL;
busTypeHandle = NULL;
busHandle = NULL;
result = FALSE;
*infoHandle = NULL;
//
// Can only deal with 98 busses.
//
if (busNumber > 98)
{
return FALSE;
}
//
// Open the root of the registry section for our bus type.
//
strcpy(busTypePath, BusTypeBase) ;
strcat(busTypePath, busTypeName);
err = RegOpenKeyExA(
HKEY_LOCAL_MACHINE,
busTypePath,
0,
KEY_READ,
&busTypeHandle
);
if (err != NO_ERROR)
{
return FALSE;
}
//
// Search through the entries in our bus section of the registry looking
// for an entry whose Configuration Data sub-entry is for our
// interface type and bus number.
//
for (index = 0; !result; index++)
{
//
// If we have already allocated a buffer for some registry
// data then trash it.
//
if (bufferPointer != NULL)
{
free(bufferPointer);
bufferPointer = NULL;
}
//
// If we have already opened a registry key for an individual
// bus then close it.
//
if (busHandle != NULL)
{
RegCloseKey(busHandle);
busHandle = NULL ;
}
//
// Enumerate through keys, searching for the proper bus number
//
nameSize = sizeof(subkeyName);
err = RegEnumKeyExA(
busTypeHandle,
index,
subkeyName,
&nameSize,
0,
NULL,
0,
&lastWrite
);
if (err != NO_ERROR)
{
break;
}
//
// Open the BusType root + Bus Number.
//
err = RegOpenKeyExA(
busTypeHandle,
subkeyName,
0,
KEY_READ,
&busHandle
);
if (err != NO_ERROR)
{
continue;
}
//
// Get some memory for the bus information.
//
bufferSize = MAX_BUS_INFO_SIZE;
bufferPointer = (UCHAR *) malloc(bufferSize) ;
if (bufferPointer == NULL)
{
break;
}
//
// Get the configuration data for this bus instance.
//
err = RegQueryValueExA(
busHandle,
ConfigData,
NULL,
&type,
bufferPointer,
&bufferSize
);
if (err != NO_ERROR)
{
break;
}
//
// Check for our bus number and type.
//
fullResource = (PCM_FULL_RESOURCE_DESCRIPTOR) bufferPointer;
result = fullResource->InterfaceType == interfaceType &&
fullResource->BusNumber == busNumber;
}
//
// Close any open registry handles.
//
if (busTypeHandle != NULL)
{
RegCloseKey(busTypeHandle);
}
if (busHandle != NULL)
{
RegCloseKey(busHandle);
}
//
// If we were successful then pass a pointer to the bus information
// back to the caller.
//
if (result)
{
*infoHandle = bufferPointer ;
}
//
// If not then free any memory.
//
else if (bufferPointer != NULL)
{
free(bufferPointer);
}
return result;
}
/****************************************************************************
*
* Function - GetMcaKey
*
* Parameters - busNumber -> Number of the bus we're interested in.
* infoHandle -> Pointer to a holder for a pointer to
* a returned bus information structure.
*
* Purpose - Extract the information about a microchannel bus from
* the registry.
*
* Returns - TRUE on success or FALSE on failure.
*
****************************************************************************/
BOOLEAN
GetMcaKey(
ULONG busNumber,
VOID * * infoHandle
)
{
return GetBusTypeKey(
busNumber,
MicroChanTypeName,
MicroChannel,
infoHandle
);
}
/****************************************************************************
*
* Function - GetMcaPosId
*
* Parameters - infoHandle -> Pointer to the bus information for an
* MCA bus.
* slotNumber -> The slot number to read.
* posId -> A pointer to a holder for the pos ID read.
*
* Purpose - Read the pos id for a slot from the bus information of
* an MCA bus.
*
* Returns - TRUE on success or FALSE on failure.
*
****************************************************************************/
BOOLEAN
GetMcaPosId(
VOID * infoHandle,
ULONG slotNumber,
ULONG * posId
)
{
PCM_FULL_RESOURCE_DESCRIPTOR fullResource;
PCM_PARTIAL_RESOURCE_LIST resourceList;
ULONG i;
ULONG totalSlots;
PCM_MCA_POS_DATA posData;
fullResource = (PCM_FULL_RESOURCE_DESCRIPTOR) infoHandle;
resourceList = &fullResource->PartialResourceList;
//
// Find the device-specific information, which is where the POS data is.
//
for (i = 0; i < resourceList->Count; i++)
{
if (resourceList->PartialDescriptors[i].Type == CmResourceTypeDeviceSpecific)
{
break;
}
}
if (i == resourceList->Count)
{
//
// Couldn't find device-specific information.
//
return FALSE;
}
//
// Now examine the device specific data.
//
totalSlots = resourceList->PartialDescriptors[i].u.DeviceSpecificData.DataSize;
totalSlots = totalSlots / sizeof(CM_MCA_POS_DATA);
if (slotNumber <= totalSlots)
{
posData = (PCM_MCA_POS_DATA) (&resourceList->PartialDescriptors[i + 1]);
posData += slotNumber - 1;
*posId = posData->AdapterId;
return TRUE;
}
//
// If we make it here there wasn't any pos data for the specified slot.
//
return FALSE;
}
/****************************************************************************
*
* Function - DeleteMcaKey
*
* Parameters - infoHandle -> Pointer to a bus information structure.
*
* Purpose - Free the memory associated with a bus information
* structure prevously returned by GetMcaKey.
*
* Returns - Nothing.
*
****************************************************************************/
VOID
DeleteMcaKey(
VOID * infoHandle
)
{
free(infoHandle) ;
}
/****************************************************************************
*
* Function - GetEisaKey
*
* Parameters - busNumber -> Number of the bus we're interested in.
* infoHandle -> Pointer to a holder for a pointer to
* a returned bus information structure.
*
* Purpose - Extract the information about an EISA bus from
* the registry.
*
* Returns - TRUE on success or FALSE on failure.
*
****************************************************************************/
BOOLEAN
GetEisaKey(
ULONG busNumber,
VOID * * infoHandle
)
{
return GetBusTypeKey(
busNumber,
EisaTypeName,
Eisa,
infoHandle
);
}
/****************************************************************************
*
* Function - GetEisaCompressedId
*
* Parameters - infoHandle -> Pointer to the bus information for an
* EISA bus.
* slotNumber -> The slot number to read.
* compressedId -> A pointer to a holder for the compressed
* ID read.
*
* Purpose - Read the compressed id for a slot from the bus information
* of an EISA bus.
*
* Returns - TRUE on success or FALSE on failure.
*
****************************************************************************/
BOOLEAN
GetEisaCompressedId(
VOID * infoHandle,
ULONG slotNumber,
ULONG * compressedId
)
{
PCM_FULL_RESOURCE_DESCRIPTOR fullResource;
PCM_PARTIAL_RESOURCE_LIST resourceList;
PCM_PARTIAL_RESOURCE_DESCRIPTOR resourceDescriptor;
ULONG i;
ULONG totalDataSize;
ULONG slotDataSize;
PCM_EISA_SLOT_INFORMATION slotInformation;
fullResource = (PCM_FULL_RESOURCE_DESCRIPTOR) infoHandle;
resourceList = &fullResource->PartialResourceList;
//
// Find the device-specific information, which is where the slot data is.
//
for (i = 0; i < resourceList->Count; i++)
{
if (resourceList->PartialDescriptors[i].Type == CmResourceTypeDeviceSpecific)
{
break;
}
}
if (i == resourceList->Count)
{
//
// Couldn't find device-specific information.
//
return FALSE;
}
//
// Now examine the device specific data.
//
resourceDescriptor = &(resourceList->PartialDescriptors[i]);
totalDataSize = resourceDescriptor->u.DeviceSpecificData.DataSize;
slotInformation = (PCM_EISA_SLOT_INFORMATION)
((UCHAR *) resourceDescriptor +
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
//
// Iterate through the slot list until we reach our slot number.
//
while (((LONG) totalDataSize) > 0)
{
if (slotInformation->ReturnCode == EISA_EMPTY_SLOT)
{
slotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
}
else
{
slotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
slotInformation->NumberFunctions *
sizeof(CM_EISA_FUNCTION_INFORMATION);
}
if (slotDataSize > totalDataSize)
{
//
// Something is wrong.
//
return FALSE;
}
//
// If we haven't reached our slot yet then advance one slot.
//
if (slotNumber > 0)
{
slotNumber--;
slotInformation = (PCM_EISA_SLOT_INFORMATION)
((PUCHAR) slotInformation + slotDataSize);
totalDataSize -= slotDataSize;
continue;
}
//
// This is our slot.
//
break;
}
//
// Check that we have really found a slot.
//
if (slotNumber != 0 || totalDataSize == 0)
{
return FALSE;
}
//
// If we make it here we have found a valid slot list entry
// for our slot number.
//
*compressedId = slotInformation->CompressedId & 0x00FFFFFF;
return TRUE;
}
/****************************************************************************
*
* Function - DeleteEisaKey
*
* Parameters - infoHandle -> Pointer to a bus information structure.
*
* Purpose - Free the memory associated with a bus information
* structure prevously returned by GetEisaKey.
*
* Returns - Nothing.
*
****************************************************************************/
VOID
DeleteEisaKey(
VOID * infoHandle
)
{
free(infoHandle);
}
/****************************************************************************
*
* Function - CheckForPcmciaCard
*
* Parameters - ioLocation -> Pointer to a holder for the IO location.
* irqNumber -> Pointer to a holder for the IRQ number.
*
* Purpose - Check for PCMCIA entry for Madge card in the registry.
*
* Returns - TRUE if there is an entry, FALSE otherwise.
*
****************************************************************************/
BOOLEAN
CheckForPcmciaCard(
ULONG * ioLocation,
ULONG * irqNumber
)
{
CHAR busTypePath[MAX_PATH];
UCHAR * bufferPointer;
PCM_FULL_RESOURCE_DESCRIPTOR fullResource;
PCM_PARTIAL_RESOURCE_LIST resList;
PCM_PARTIAL_RESOURCE_DESCRIPTOR resDesc;
HKEY busTypeHandle;
DWORD type;
DWORD bufferSize;
LONG err;
BOOL result;
UINT i;
//
// Do some initialisation.
//
bufferPointer = NULL;
busTypeHandle = NULL;
result = FALSE;
*ioLocation = RESOURCE_UNKNOWN;
*irqNumber = RESOURCE_UNKNOWN;
//
// Open the root of the registry section for PCMCIA cards.
//
strcpy(busTypePath, BusTypeBase) ;
strcat(busTypePath, PcmciaTypeName);
err = RegOpenKeyExA(
HKEY_LOCAL_MACHINE,
busTypePath,
0,
KEY_READ,
&busTypeHandle
);
if (err != NO_ERROR)
{
MadgePrint1("RegOpenKeyExA failed\n");
return FALSE;
}
//
// Query the entry for 'mdgmport.' If this works then there must be
// a Madge PCMCIA card present.
//
//
// Get some memory for the bus information.
//
bufferSize = MAX_BUS_INFO_SIZE;
bufferPointer = (UCHAR *) malloc(bufferSize) ;
if (bufferPointer == NULL)
{
return FALSE;
}
//
// Get the configuration data for Madge PCMCIA card.
//
err = RegQueryValueExA(
busTypeHandle,
DriverName,
NULL,
&type,
bufferPointer,
&bufferSize
);
if (err != NO_ERROR)
{
MadgePrint1("RegQueryValueExA failed\n");
result = FALSE;
}
else
{
MadgePrint1("RegQueryValueExA succeeded\n");
result = TRUE;
}
//
// Now look at the returned resource list to find our
// IO location and IRQ number.
//
if (result)
{
fullResource = (PCM_FULL_RESOURCE_DESCRIPTOR) bufferPointer;
resList = &fullResource->PartialResourceList;
for (i = 0; i < resList->Count; i++)
{
resDesc = &resList->PartialDescriptors[i];
switch (resDesc->Type)
{
case CmResourceTypeInterrupt:
*irqNumber = (ULONG) resDesc->u.Interrupt.Vector;
break;
case CmResourceTypePort:
*ioLocation = (ULONG) resDesc->u.Port.Start.LowPart;
break;
}
}
MadgePrint2("IO Location = %x\n", *ioLocation);
MadgePrint2("IRQ Number = %d\n", *irqNumber);
}
//
// Close any open registry handles.
//
RegCloseKey(busTypeHandle);
//
// Free memory used for query. We don't pass anything back since the
// data would mean very little. A PCMCIA card is programmed with what-
// ever values the user chooses. There isn't really a concept of reading
// the cofiguration information from the card.
//
free(bufferPointer);
return result;
}
/****************************************************************************
*
* Function - UnicodeStrLen
*
* Parameters - string -> A unicode string.
*
* Purpose - Determine the length of a unicode string.
*
* Returns - The length of string.
*
****************************************************************************/
ULONG
UnicodeStrLen(WCHAR * string)
{
ULONG length;
length = 0;
while (string[length] != L'\0')
{
length++;
}
return length;
}
/****************************************************************************
*
* Function - FindParameterString
*
* Parameters - string1 -> A unicode parameter list string to be searched.
* string2 -> A unicode string to be searched for.
*
* Purpose - Search string1 for string2 and return a pointer to
* the place in string1 where string2 starts.
*
* Returns - A pointer to the start of string2 in string1 or NULL.
*
****************************************************************************/
WCHAR *
FindParameterString(
WCHAR * string1,
WCHAR * string2
)
{
ULONG length1;
ULONG length2;
WCHAR * place;
//
// Do some initialisation.
//
place = string1;
length2 = UnicodeStrLen(string2) + 1;
length1 = UnicodeStrLen(string1) + 1;
//
// While there's more than the last NULL left look for
// string2.
//
while (length1 > 1)
{
//
// Are these the same?
//
if (memcmp(place, string2, length2 * sizeof(WCHAR)) == 0)
{
return place;
}
place = place + length1;
length1 = UnicodeStrLen(place) + 1;
}
return NULL;
}
/****************************************************************************
*
* Function - ScanForNumber
*
* Parameters - place -> A unicode string to search for a number.
* value -> Pointer to holder for the number found.
* found -> Pointer to a flag that indicates if we
* found a number.
*
* Purpose - Search the unicode string that starts a place for
* a number.
*
* Returns - Nothing. *found indicates if a number was found.
*
****************************************************************************/
VOID
ScanForNumber(
WCHAR * place,
ULONG * value,
BOOLEAN * found
)
{
ULONG tmp;
*value = 0;
*found = FALSE;
//
// Skip leading blanks.
//
while (*place == L' ')
{
place++;
}
//
// Is this a hex number?
//
if ((place[0] == L'0') && (place[1] == L'x'))
{
//
// Yes, parse it as a hex number.
//
*found = TRUE;
//
// Skip leading '0x'.
//
place += 2;
//
// Convert a hex number.
//
for (;;)
{
if ((*place >= L'0') && (*place <= L'9'))
{
tmp = ((ULONG) *place) - ((ULONG) L'0');
}
else
{
switch (*place)
{
case L'a':
case L'A':
tmp = 10;
break;
case L'b':
case L'B':
tmp = 11;
break;
case L'c':
case L'C':
tmp = 12;
break;
case L'd':
case L'D':
tmp = 13;
break;
case L'e':
case L'E':
tmp = 14;
break;
case L'f':
case L'F':
tmp = 15;
break;
default:
return;
}
}
(*value) = (*value * 16) + tmp;
place++;
}
}
//
// Is it a decimal number?
//
else if ((*place >= L'0') && (*place <= L'9'))
{
//
// Parse it as a decimal number.
//
*found = TRUE;
//
// Convert a decimal number.
//
for (;;)
{
if ((*place >= L'0') && (*place <= L'9'))
{
tmp = ((ULONG) *place) - ((ULONG) L'0');
}
else
{
return;
}
(*value) *= (*value * 10) + tmp;
place++;
}
}
}
/****************************************************************************
*
* Function - DetectAllocateHeap
*
* Parameters - size -> Number of bytes of heap required.
*
* Purpose - Allocate some heap space.
*
* Returns - A pointer to some heap or NULL.
*
****************************************************************************/
VOID *
DetectAllocateHeap(LONG size)
{
VOID * ptr;
if (size > 0)
{
ptr = malloc(size);
if (ptr != NULL)
{
memset(ptr, 0, size);
}
return ptr;
}
return NULL;
}
/****************************************************************************
*
* Function - DetectFreeHeap
*
* Parameters - ptr -> A pointer to the start of some heap to free.
*
* Purpose - Free some heap space.
*
* Returns - Nothing.
*
****************************************************************************/
VOID
DetectFreeHeap(VOID *ptr)
{
free(ptr);
}
/****************************************************************************
*
* Function - AppendParameter
*
* Parameters - buffer -> Pointer to pointer buffer to append to.
* bufferSize -> Pointer to the buffer size.
* title -> Parameter title.
* value -> Parameter value.
*
* Purpose - Append a parameter's title and value to a buffer. *buffer
* and *bufferSize are incremented and decremented accordinlgy.
*
* Returns - A WINERROR.H error code.
*
****************************************************************************/
LONG
AppendParameter(
WCHAR * * buffer,
LONG * bufferSize,
WCHAR * title,
ULONG value
)
{
LONG copyLength;
//
// Copy in the title.
//
copyLength = UnicodeStrLen(title)+ 1;
if (*bufferSize < copyLength)
{
return ERROR_INSUFFICIENT_BUFFER;
}
memcpy(
(VOID *) *buffer,
(VOID *) title,
(copyLength * sizeof(WCHAR))
);
*buffer += copyLength;
*bufferSize -= copyLength;
//
// Copy in the value
//
if (*bufferSize < 8)
{
return ERROR_INSUFFICIENT_BUFFER;
}
copyLength = wsprintfW(*buffer, L"0x%x", value);
if (copyLength < 0)
{
return ERROR_INSUFFICIENT_BUFFER;
}
copyLength++; // Add in the \0.
*buffer += copyLength;
*bufferSize -= copyLength;
return NO_ERROR;
}
/****************************************************************************
*
* Function - UnicodeStringsEqual
*
* Parameters - string1
* string2 -> Unicode strings to compare.
*
* Purpose - Test two unicode strings for equality.
*
* Returns - TRUE if the strings are equal and FALSE otherwise.
*
****************************************************************************/
BOOLEAN
UnicodeStringsEqual(
WCHAR *string1,
WCHAR *string2
)
{
while (*string1 != L'\0' && *string1 == *string2)
{
string1++;
string2++;
}
return *string1 == *string2;
}
/****************************************************************************
*
* Function - MadgeCardAlreadyInstalled
*
* Parameters - useSlotNumber -> TRUE if we are to search on slot number or
* FALSE if we are to search on IO location.
* busNumber -> The bus number.
* descriptor -> The slot number or IO location.
*
* Purpose - Search the registry to see if a Madge adapter is already
* installed at the specified slot number or IO location.
*
* Returns - TRUE if an adapter is installed or FALSE if not.
*
****************************************************************************/
BOOLEAN
MadgeCardAlreadyInstalled(
BOOLEAN useSlotNumber,
ULONG busNumber,
ULONG descriptor
)
{
CHAR driverPath[MAX_PATH];
UCHAR buffer[MAX_PATH];
char subkeyName[MAX_PATH];
HKEY netCardsHandle;
HKEY cardHandle;
HKEY driverHandle;
FILETIME lastWrite;
ULONG index;
DWORD type;
DWORD bufferSize;
DWORD nameSize;
LONG err;
BOOLEAN found;
ULONG tempDescriptor;
ULONG tempBusNumber;
//
// Do some initialisation.
//
netCardsHandle = NULL;
cardHandle = NULL;
driverHandle = NULL;
found = FALSE;
//
// Open the root of the registry section net cards.
//
err = RegOpenKeyExA(
HKEY_LOCAL_MACHINE,
NetworkCardsBase,
0,
KEY_READ,
&netCardsHandle
);
if (err != NO_ERROR)
{
return FALSE;
}
//
// Search through the network card entries looking for entries
// that are for drivers with manufacturer set to "Madge".
//
for (index = 0; !found; index++)
{
//
// Close any open registry handles.
//
if (cardHandle != NULL)
{
RegCloseKey(cardHandle);
cardHandle = NULL;
}
if (driverHandle != NULL)
{
RegCloseKey(driverHandle);
driverHandle = NULL;
}
//
// Enumerate through keys.
//
nameSize = sizeof(subkeyName);
err = RegEnumKeyExA(
netCardsHandle,
index,
subkeyName,
&nameSize,
0,
NULL,
0,
&lastWrite
);
if (err != NO_ERROR)
{
break;
}
//
// Open the net card key.
//
err = RegOpenKeyExA(
netCardsHandle,
subkeyName,
0,
KEY_READ,
&cardHandle
);
if (err != NO_ERROR)
{
continue;
}
//
// Get the manufacturer name and check that it is
// "Madge".
//
bufferSize = sizeof(buffer);
err = RegQueryValueExA(
cardHandle,
ManufacturerName,
NULL,
&type,
buffer,
&bufferSize
);
if (err != NO_ERROR)
{
continue;
}
if (strcmp(buffer, MadgeName) != 0)
{
continue;
}
//
// Get the driver name.
//
bufferSize = sizeof(buffer);
err = RegQueryValueExA(
cardHandle,
ServiceName,
NULL,
&type,
buffer,
&bufferSize
);
if (err != NO_ERROR)
{
continue;
}
//
// Open a key for the driver entry under services.
//
strcpy(driverPath, ServicesBase);
strcat(driverPath, buffer);
strcat(driverPath, ParametersName);
err = RegOpenKeyExA(
HKEY_LOCAL_MACHINE,
driverPath,
0,
KEY_READ,
&driverHandle
);
if (err != NO_ERROR)
{
continue;
}
//
// Try and read the slot number or IO location.
//
bufferSize = sizeof(buffer);
if (useSlotNumber)
{
err = RegQueryValueExA(
driverHandle,
SlotNumberName,
NULL,
&type,
buffer,
&bufferSize
);
}
else
{
err = RegQueryValueExA(
driverHandle,
IoLocationName,
NULL,
&type,
buffer,
&bufferSize
);
}
if (err != NO_ERROR)
{
continue;
}
tempDescriptor = (ULONG) *((DWORD *) buffer);
//
// Try and read the bus number.
//
bufferSize = sizeof(buffer);
err = RegQueryValueExA(
driverHandle,
BusNumberName,
NULL,
&type,
buffer,
&bufferSize
);
if (err != NO_ERROR)
{
continue;
}
tempBusNumber = (ULONG) *((DWORD *) buffer);
//
// Check to see if we have a match.
//
if (descriptor == tempDescriptor &&
busNumber == tempBusNumber)
{
MadgePrint2("Found Madge adapter at %lx\n", descriptor);
found = TRUE;
break;
}
}
//
// Close any open registry handles.
//
if (netCardsHandle != NULL)
{
RegCloseKey(netCardsHandle);
}
if (cardHandle != NULL)
{
RegCloseKey(cardHandle);
}
if (driverHandle != NULL)
{
RegCloseKey(driverHandle);
}
return found;
}
/****************************************************************************
*
* Function - IsMultiprocessor
*
* Parameters - None.
*
* Purpose - Examine the registry to find out if the machine is a
* multiprocessor.
*
* Returns - 0 for a single processor or 1 for a multiprocessor.
*
****************************************************************************/
ULONG
IsMultiprocessor(void)
{
char subkeyName[MAX_PATH];
HKEY cpuHandle;
FILETIME lastWrite;
ULONG count;
DWORD nameSize;
LONG err;
//
// Open the root of the registry section net cards.
//
err = RegOpenKeyExA(
HKEY_LOCAL_MACHINE,
ProcessorsBase,
0,
KEY_READ,
&cpuHandle
);
if (err != NO_ERROR)
{
return 0;
}
//
// Enumerate the processors.
//
count = 0;
for (;;)
{
nameSize = sizeof(subkeyName);
err = RegEnumKeyExA(
cpuHandle,
count,
subkeyName,
&nameSize,
0,
NULL,
0,
&lastWrite
);
if (err != NO_ERROR)
{
break;
}
count++;
MadgePrint2("Found a CPU, number %d\n", count);
}
//
// Close any open registry handles.
//
RegCloseKey(cpuHandle);
return (count <= 1) ? 0 : 1;
}
/****************************************************************************
*
* Function - IsValueInList
*
* Parameters - value -> Value to be checked.
* list -> Pointer to a list of values.
*
* Purpose - Check to see if a value is present in a list of values. The
* list should be terminated with a value of END_OF_LIST.
*
* Returns - TRUE if the value is in the list or FALSE if it is not.
*
****************************************************************************/
BOOLEAN
IsValueInList(
ULONG value,
ULONG * list
)
{
while (*list != END_OF_LIST && *list != value)
{
list++;
}
return *list == value;
}
/******** End of MDGUTILS.C ************************************************/