Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

645 lines
11 KiB

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
utils.c
Abstract:
Author:
Garth Conboy (Pacer Software)
Nikhil Kamkolkar (NikhilK)
Revision History:
GC - (06/15/92): Updated DownCaseChar to be a routine rather than a macro;
it now correctly handles the entire Macintosh
International Character Set.
GC - (09/15/92): Added OrderCaseInsensitive() for sorting the zone list
for Arap.
--*/
#define IncludeUtilsErrors 1
#include "atalk.h"
LOCAL
SHORT
DownCaseChar(
char c);
BOOLEAN
ExtendedAppleTalkNodesEqual(
PEXTENDED_NODENUMBER p1,
PEXTENDED_NODENUMBER p2
)
{
return((BOOLEAN)(((p1->NetworkNumber == p2->NetworkNumber) ||
(p1->NetworkNumber == 0) ||
(p2->NetworkNumber == 0))
&&
(p1->NodeNumber == p2->NodeNumber)));
} // ExtendedAppleTalkNodesEqual
BOOLEAN
AppleTalkAddressesEqual(
PAPPLETALK_ADDRESS p1,
PAPPLETALK_ADDRESS p2
)
{
return((BOOLEAN)(((p1->NetworkNumber == p2->NetworkNumber) ||
(p1->NetworkNumber == 0) ||
(p2->NetworkNumber == 0))
&&
(p1->NodeNumber == p2->NodeNumber)
&&
(p1->SocketNumber == p2->SocketNumber)));
} // AppleTalkAddressesEqual
BOOLEAN
CompareCaseSensitive(
register const char *s1,
register const char *s2
)
{
while (*s1 != 0) {
if (*s1++ == *s2++)
continue;
return(FALSE);
}
if (*s1 == *s2)
return(TRUE);
else
return(FALSE);
} // CompareCaseSensitive
BOOLEAN
CompareCaseInsensitive(
register const char *s1,
register const char *s2
)
{
register short c1, c2;
while (*s1 != 0) {
c1 = DownCaseChar(*s1++);
c2 = DownCaseChar(*s2++);
if (c1 == c2)
continue;
return(FALSE);
}
c1 = DownCaseChar(*s1);
c2 = DownCaseChar(*s2);
if (c1 == c2)
return(TRUE);
else
return(FALSE);
} // CompareCaseInsensitive
int
OrderCaseInsensitive(
register const char *s1,
register const char *s2
)
{
register int c1, c2;
while (*s1 != 0) {
c1 = DownCaseChar(*s1++);
c2 = DownCaseChar(*s2++);
if (c1 == c2)
continue;
return(c1 - c2);
}
c1 = DownCaseChar(*s1);
c2 = DownCaseChar(*s2);
return(c1 - c2);
} // OrderCaseInsensitive
BOOLEAN
FixedCompareCaseSensitive(
const char *s1,
int l1,
const char *s2,
int l2
)
{
if (l1 != l2)
return(FALSE);
// Optimize the common lenghts...
#if IdontHave an AlignedAddressing
switch(l1) {
case sizeof(short):
return((BOOLEAN)(*(short *)s1 == *(short *)s2));
case sizeof(long):
return((BOOLEAN)(*(long *)s1 == *(long *)s2));
case sizeof(short) + sizeof(long):
return((BOOLEAN)(*(short *)s1 == *(short *)s2 and
*(long *)(s1 + 2) == *(long *)(s2 + 2)));
case sizeof(long) + sizeof(char):
return((BOOLEAN)(*(long *)s1 == *(long *)s2 and
*(s1 + sizeof(long)) == *(s2 + sizeof(long))));
default:
break;
}
#endif
while(l1--)
if (*s1++ != *s2++)
return(FALSE);
return(TRUE);
} // FixedCompareCaseSensitive
BOOLEAN
FixedCompareCaseInsensitive(
const char *s1,
int l1,
const char *s2,
int l2
)
{
register short c1, c2;
if (l1 != l2)
return(FALSE);
while(l1--) {
c1 = DownCaseChar(*s1++);
c2 = DownCaseChar(*s2++);
if (c1 != c2)
return(FALSE);
}
return(TRUE);
} // FixedCompareCaseInsensitive
PCHAR
StringCopyReasonableAscii(
register char *dest,
register const char *source
)
{
char *returnValue = dest;
while (*source)
*dest++ = (char)(*source++ & 0x7F);
*dest = 0;
return(returnValue);
}
int
FindDefaultPort(
VOID)
{
int index;
// Find the default port in the portDescriptors.
for (index = 0; index < NumberOfPortsAllocated; index += 1)
if ((GET_PORTDESCRIPTOR(index)->Flags & PD_ACTIVE) &&
(GET_PORTDESCRIPTOR(index)->DefaultPort))
break;
if (index >= NumberOfPortsAllocated) {
return((int)-1);
}
return(index);
} // FindDefaultPort
int
ElementsOnList(
PVOID listHead
)
{
int count;
//
// Count the number of elements on a linked list... the "next" field must
// be the first member of the node structure.
//
for (count = 0; listHead != NULL; listHead = *(void **)listHead)
count += 1;
return(count);
} // ElementsOnList
BOOLEAN
IsWithinNetworkRange(
USHORT networkNumber,
PAPPLETALK_NETWORKRANGE range
)
{
if (networkNumber == range->FirstNetworkNumber)
return(TRUE);
if (networkNumber >= range->FirstNetworkNumber &&
networkNumber <= range->LastNetworkNumber)
return(TRUE);
return(FALSE);
} // IsWithinNetworkRange
BOOLEAN
Is802dot2headerGood(
PUCHAR packet,
PUCHAR protocol
)
{
if (packet[Ieee802dot2dsapOffset] != SnapSap ||
packet[Ieee802dot2ssapOffset] != SnapSap ||
packet[Ieee802dot2controlOffset] != UnnumberedInformation) {
return(FALSE);
}
if (!FixedCompareCaseSensitive(
packet + Ieee802dot2protocolOffset,
Ieee802dot2protocolTypeLength,
protocol,
Ieee802dot2protocolTypeLength)) {
return(FALSE);
}
return(TRUE);
} // Is802dot2headerGood
BOOLEAN
CheckNetworkRange(
APPLETALK_NETWORKRANGE networkRange
)
{
// Validate an AppleTalk network range.
if (networkRange.firstNetworkNumber < FirstValidNetworkNumber ||
networkRange.firstNetworkNumber > LastValidNetworkNumber ||
networkRange.lastNetworkNumber < FirstValidNetworkNumber ||
networkRange.lastNetworkNumber > LastValidNetworkNumber) {
ErrorLog("CheckNetworkRange", ISevError, __LINE__, UnknownPort,
IErrUtilsBadNetworkNumber, IMsgUtilsBadNetworkNumber,
Insert0());
return(FALSE);
}
if (networkRange.firstNetworkNumber > networkRange.lastNetworkNumber) {
ErrorLog("CheckNetworkRange", ISevError, __LINE__, UnknownPort,
IErrUtilsNegativeRange, IMsgUtilsNegativeRange,
Insert0());
return(FALSE);
}
if (networkRange.lastNetworkNumber >= FirstStartupNetworkNumber) {
ErrorLog("CheckNetworkRange", ISevError, __LINE__, UnknownPort,
IErrUtilsStartupRange, IMsgUtilsStartupRange,
Insert0());
return(FALSE);
}
return(TRUE);
} // CheckNetworkRange
BOOLEAN
RangesOverlap(
PAPPLETALK_NETWORKRANGE range1,
PAPPLETALK_NETWORKRANGE range2
)
{
APPLETALK_NETWORKRANGE temp1, temp2;
//
// If either of the ranges have "0" as the last network number, turn them
// into a range with width one using the first network number.
//
if (range1->LastNetworkNumber == UnknownNetworkNumber) {
temp1.firstNetworkNumber = temp1.lastNetworkNumber =
range1->FirstNetworkNumber;
range1 = &temp1;
}
if (range2->LastNetworkNumber == UnknownNetworkNumber) {
temp2.firstNetworkNumber = temp2.lastNetworkNumber =
range2->FirstNetworkNumber;
range2 = &temp2;
}
// Okay, check for range overlap.
if (range1->LastNetworkNumber < range2->FirstNetworkNumber)
return(FALSE);
if (range1->FirstNetworkNumber > range2->LastNetworkNumber)
return(FALSE);
return(TRUE);
} // RangesOverlap
PZONE_LIST
CopyZoneList(
PZONE_LIST zoneList
)
{
PZONE_LIST newZoneList = NULL, headOfNewZoneList = NULL;
BOOLEAN mallocFailed;
// Copy each node on the input zone list, to build a complete copy.
for ( ; zoneList != NULL; zoneList = zoneList->Next) {
mallocFailed = FALSE;
// Allocate a new node.
if (newZoneList == NULL)
if ((newZoneList = (PZONE_LIST)Calloc(sizeof(ZONE_LIST), 1)) == NULL)
mallocFailed = TRUE;
else
headOfNewZoneList = newZoneList;
else
if ((newZoneList->Next =
(PZONE_LIST)Calloc(sizeof(ZONE_LIST), 1)) == NULL)
mallocFailed = TRUE;
else
newZoneList = newZoneList->Next;
if (not mallocFailed)
if ((newZoneList->Zone =
(char *)Malloc(strlen(zoneList->Zone) + 1)) == NULL)
mallocFailed = TRUE;
// Malloc error?
if (mallocFailed) {
LOG_ERROR(
EVENT_ATALK_MEMORY_RESOURCES,
(__UTILS__ | __LINE__),
0,
NULL,
0,
0,
NULL);
FreeZoneList(headOfNewZoneList);
return(NULL);
}
// Copy zone name.
strcpy(newZoneList->Zone, zoneList->Zone);
}
return(headOfNewZoneList);
} // CopyZoneList
VOID
FreeZoneList(
PZONE_LIST zoneList
)
{
PZONE_LIST nextZone;
for ( ; zoneList != NULL; zoneList = nextZone) {
nextZone = zoneList->Next;
Free(zoneList->Zone);
Free(zoneList);
}
return;
} // FreeZoneList
BOOLEAN
ZoneOnList(
PCHAR zone,
PZONE_LIST zoneList
)
{
for ( ; zoneList != NULL; zoneList = zoneList->Next)
if (CompareCaseInsensitive(zone, zoneList->Zone))
return(TRUE);
return(FALSE);
} // ZoneOnList
PZONE_LIST
AddZoneToList(
PZONE_LIST zoneList,
PCHAR zone
)
{
PZONE_LIST newZoneList;
// Get memory for a new ZoneList node.
if ((newZoneList = (PZONE_LIST)Malloc(sizeof(ZONE_LIST ))) == NULL ||
(newZoneList->Zone = Malloc(strlen(zone) + 1)) == NULL) {
if (newZoneList != NULL)
Free(newZoneList);
FreeZoneList(zoneList);
return(NULL);
}
// Build and thread new node.
strcpy(newZoneList->Zone, zone);
newZoneList->Next = zoneList;
return(newZoneList);
} // AddZoneToList
LONG
UniqueNumber(
VOID
)
{
static long nextUniqueNumber = 0x10000; // Just for fun
long nextNumber;
// Return a unqiue positive number...
EnterCriticalSection(GLOBAL_STACK);
nextUniqueNumber += 1;
if (nextUniqueNumber < 0)
nextUniqueNumber = 1;
nextNumber = nextUniqueNumber;
LeaveCriticalSection(GLOBAL_STACK);
return(nextNumber);
} // UniqueNumber
LONG
RandomNumber(
VOID
)
{
//
// Return a positive pseudo-random number; simple linear congruential
// algorithm. ANSI C "rand()" function.
//
static long seed;
static BOOLEAN firstCall = TRUE;
if (firstCall) {
seed = (long)UniqueNumber();
firstCall = FALSE;
}
seed = seed * 0x41C64E6D + 0x3039;
return(seed & 0x7FFFFFFF);
} // RandomNumber
SHORT
DownCaseChar(
char c
)
{
// First, do all the "normal" ascii.
#if IamNot a Primos
if (not (c & 0x80)) // For testing allow funny Prime Ascii.
#endif
if (isupper(c))
return((short)(unsigned char)_tolower(c));
else
return((short)(unsigned char)c);
//
// Okay, now check for any of the funny International Macintosh character
// set characters (from page D-3 of Inside AppleTalk; Second Edition).
// One would hope that a clever compiler will generate a jump table for the
// following switch statement.
//
switch ((unsigned char)c) {
case 0xCB:
return(0x88);
case 0x80:
return(0x8A);
case 0xCC:
return(0x8B);
case 0x81:
return(0x8C);
case 0x82:
return(0x8D);
case 0x83:
return(0x8E);
case 0x84:
return(0x96);
case 0x85:
return(0x9A);
case 0xCD:
return(0x9B);
case 0x86:
return(0x9F);
case 0xAE:
return(0xBE);
case 0xAF:
return(0xBF);
case 0xCE:
return(0xCF);
}
// Otherwise, leave well enough alone.
return((unsigned char)c);
} // DownCaseChar