diff options
Diffstat (limited to '')
-rw-r--r-- | private/ntos/ndis/madge/detect/mdgutils.c | 1599 |
1 files changed, 1599 insertions, 0 deletions
diff --git a/private/ntos/ndis/madge/detect/mdgutils.c b/private/ntos/ndis/madge/detect/mdgutils.c new file mode 100644 index 000000000..9ee0cdec4 --- /dev/null +++ b/private/ntos/ndis/madge/detect/mdgutils.c @@ -0,0 +1,1599 @@ +/**************************************************************************** +* +* 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 ************************************************/ |