summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/madge/detect/mdgutils.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/ntos/ndis/madge/detect/mdgutils.c1599
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 ************************************************/