/*++ Copyright (c) 1992 Microsoft Corporation Module Name: atkutils.h Abstract: This module contains miscellaneous support routines. Author: Jameel Hyder (jameelh@microsoft.com) Nikhil Kamkolkar (nikhilk@microsoft.com) Revision History: 19 Jun 1992 Initial Version Notes: Tab stop: 4 --*/ #ifndef _ATKUTILS_ #define _ATKUTILS_ // SpinLock Macros #if DBG #define INITIALIZE_SPIN_LOCK(_pLock) \ { \ KeInitializeSpinLock(&(_pLock)->SpinLock); \ (_pLock)->FileLineLock = 0; \ } #else // DBG #define INITIALIZE_SPIN_LOCK(_pLock) \ { \ KeInitializeSpinLock(&(_pLock)->SpinLock); \ } #endif #if DBG #define ACQUIRE_SPIN_LOCK(_pLock, _pOldIrql) \ { \ KeAcquireSpinLock(&(_pLock)->SpinLock, \ _pOldIrql); \ (_pLock)->FileLineLock = (FILENUM | __LINE__); \ } #define ACQUIRE_SPIN_LOCK_DPC(_pLock) \ { \ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); \ KeAcquireSpinLockAtDpcLevel(&(_pLock)->SpinLock); \ (_pLock)->FileLineLock = (FILENUM | __LINE__ | 0x80000000); \ } #define RELEASE_SPIN_LOCK(_pLock, _OldIrql) \ { \ ASSERT ((_pLock)->FileLineLock != 0); \ ASSERT (((_pLock)->FileLineLock & 0x80000000) == 0); \ (_pLock)->FileLineLock = 0; \ (_pLock)->FileLineUnlock = (FILENUM | __LINE__); \ KeReleaseSpinLock(&(_pLock)->SpinLock, \ _OldIrql); \ } #define RELEASE_SPIN_LOCK_DPC(_pLock) \ { \ ASSERT ((_pLock)->FileLineLock != 0); \ ASSERT ((_pLock)->FileLineLock & 0x80000000); \ (_pLock)->FileLineLock = 0; \ (_pLock)->FileLineUnlock = (FILENUM | __LINE__ | 0x80000000); \ KeReleaseSpinLockFromDpcLevel(&(_pLock)->SpinLock); \ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); \ } #else // DBG #define ACQUIRE_SPIN_LOCK(_pLock, _pOldIrql) \ { \ KeAcquireSpinLock(&(_pLock)->SpinLock, \ _pOldIrql); \ } #define ACQUIRE_SPIN_LOCK_DPC(_pLock) \ { \ KeAcquireSpinLockAtDpcLevel(&(_pLock)->SpinLock); \ } #define RELEASE_SPIN_LOCK(_pLock, _OldIrql) \ { \ KeReleaseSpinLock(&(_pLock)->SpinLock, \ (_OldIrql)); \ } #define RELEASE_SPIN_LOCK_DPC(_pLock) \ { \ KeReleaseSpinLockFromDpcLevel(&(_pLock)->SpinLock); \ } \ #endif // DBG // Macros for ExInterlocked calls #define INTERLOCKED_INCREMENT_LONG(p, l) InterlockedIncrement(p) #define INTERLOCKED_DECREMENT_LONG(p, l) InterlockedDecrement(p) #define INTERLOCKED_INCREMENT_LONG_DPC(p, l) InterlockedIncrement(p) #define INTERLOCKED_DECREMENT_LONG_DPC(p, l) InterlockedDecrement(p) #define INTERLOCKED_ADD_STATISTICS(p, v, l) ExInterlockedAddLargeStatistic(p, v) #define INTERLOCKED_ADD_ULONG(p, v, l) ExInterlockedAddUlong(p, v, l) #define INTERLOCKED_ADD_LARGE_INTGR(p, v, l) ExInterlockedAddLargeInteger(p, v, l) #define INTERLOCKED_ADD_ULONG_DPC(p, v, l) ExInterlockedAddUlong(p, v, l) #define INTERLOCKED_ADD_LARGE_INTGR_DPC(p, v, l) ExInterlockedAddLargeInteger(p, v, l) #define ATALK_NODES_EQUAL(N1, N2) \ ((((N1)->atn_Network == (N2)->atn_Network) || \ ((N1)->atn_Network == 0) || \ ((N2)->atn_Network == 0)) && \ ((N1)->atn_Node == (N2)->atn_Node)) #define ATALK_ADDRS_EQUAL(A1, A2) \ ((((A1)->ata_Network == (A2)->ata_Network) || \ ((A1)->ata_Network == 0) || \ ((A2)->ata_Network == 0)) && \ ((A1)->ata_Node == (A2)->ata_Node) && \ ((A1)->ata_Socket == (A2)->ata_Socket)) #define INVALID_ADDRESS(pAddr) \ (((pAddr)->ata_Network > LAST_VALID_NETWORK) || \ (((pAddr)->ata_Node > MAX_USABLE_ATALKNODE) && \ ((pAddr)->ata_Node != ATALK_BROADCAST_NODE)) || \ ((pAddr)->ata_Socket < FIRST_VALID_SOCKET) || \ ((pAddr)->ata_Socket > LAST_VALID_SOCKET)) #define ATALKADDR_TO_TDI(pTdiAddr, pAtalkAddr) \ { \ (pTdiAddr)->TAAddressCount = 1; \ (pTdiAddr)->Address[0].AddressLength = sizeof(TDI_ADDRESS_APPLETALK); \ (pTdiAddr)->Address[0].AddressType = TDI_ADDRESS_TYPE_APPLETALK; \ (pTdiAddr)->Address[0].Address[0].Network = (pAtalkAddr)->ata_Network; \ (pTdiAddr)->Address[0].Address[0].Node = (pAtalkAddr)->ata_Node; \ (pTdiAddr)->Address[0].Address[0].Socket = (pAtalkAddr)->ata_Socket; \ } #define TDI_TO_ATALKADDR(pAtalkAddr, pTdiAddr) \ { \ ASSERTMSG("TdiAddrCount is not 1\n", \ ((pTdiAddr)->TAAddressCount == 1)); \ \ ASSERTMSG("TdiAddrLen invalid\n", \ ((pTdiAddr)->Address[0].AddressLength >= \ sizeof(TDI_ADDRESS_APPLETALK))); \ \ ASSERTMSG("TdiAddrType invalid\n", \ ((pTdiAddr)->Address[0].AddressType == \ TDI_ADDRESS_TYPE_APPLETALK)); \ \ (pAtalkAddr)->ata_Network = (pTdiAddr)->Address[0].Address[0].Network;\ (pAtalkAddr)->ata_Node = (pTdiAddr)->Address[0].Address[0].Node; \ (pAtalkAddr)->ata_Socket = (pTdiAddr)->Address[0].Address[0].Socket;\ } #define IN_NETWORK_RANGE(NetworkNumber, pRte) \ (((pRte)->rte_NwRange.anr_FirstNetwork == NetworkNumber) || \ ((NetworkNumber >= (pRte)->rte_NwRange.anr_FirstNetwork) && \ (NetworkNumber <= (pRte)->rte_NwRange.anr_LastNetwork))) #define WITHIN_NETWORK_RANGE(NetworkNumber, pRange) \ (((pRange)->anr_FirstNetwork == NetworkNumber) || \ ((NetworkNumber >= (pRange)->anr_FirstNetwork) && \ (NetworkNumber <= (pRange)->anr_LastNetwork))) #define COPY_NETWORK_ADDR(_Dst, _Src) \ { \ *((ULONG UNALIGNED *)(_Dst)) = *((ULONG UNALIGNED *)(_Src)); \ *((USHORT UNALIGNED *)((UCHAR *)(_Dst)+4)) = \ *((USHORT UNALIGNED *)((UCHAR *)(_Src)+4)); \ } // Hash functions // Make sure we're positive [thus the shift by 7 rather than 8]. // Only hash node and socket; due to the "zero matches all" for // non-extended network numbers. #define HASH_ATALK_ADDR(address) \ ((USHORT)(((address)->ata_Node << 7) + \ ((address)->ata_Socket & 0x7F))) #define HASH_ATALK_NODE(address) \ ((USHORT)((((address)->atn_Network & 0x3C) >> 2) + \ (address)->atn_Node & 0x04)) #define HASH_ID_SRCADDR(id, pSrcAddr) \ ((id) + (((pSrcAddr)->ata_Node >> 2) + ((pSrcAddr)->ata_Network & 0xFF))) /* * The following macros deal with on-the-wire integer and long values * * On the wire format is big-endian i.e. a long value of 0x01020304 is * represented as 01 02 03 04. Similarly an int value of 0x0102 is * represented as 01 02. * * The host format is not assumed since it will vary from processor to * processor. */ // Get a byte from on-the-wire format to a short in the host format #define GETBYTE2SHORT(DstPtr, SrcPtr) \ *(PUSHORT)(DstPtr) = (USHORT) (*(PBYTE)(SrcPtr)) // Get a byte from on-the-wire format to a dword in the host format #define GETBYTE2DWORD(DstPtr, SrcPtr) \ *(PDWORD)(DstPtr) = (DWORD) (*(PBYTE)(SrcPtr)) // Get a short from on-the-wire format to a dword in the host format #define GETSHORT2DWORD(DstPtr, SrcPtr) \ *(PDWORD)(DstPtr) = ((*((PBYTE)(SrcPtr)+0) << 8) + \ (*((PBYTE)(SrcPtr)+1))) // Get a short from on-the-wire format to a short in the host format #define GETSHORT2SHORT(DstPtr, SrcPtr) \ *(PUSHORT)(DstPtr) = ((*((PBYTE)(SrcPtr)+0) << 8) + \ (*((PBYTE)(SrcPtr)+1))) // Get a dword from on-the-wire format to a dword in the host format #define GETDWORD2DWORD(DstPtr, SrcPtr) \ *(PDWORD)(DstPtr) = ((*((PBYTE)(SrcPtr)+0) << 24) + \ (*((PBYTE)(SrcPtr)+1) << 16) + \ (*((PBYTE)(SrcPtr)+2) << 8) + \ (*((PBYTE)(SrcPtr)+3))) // Put a dword from the host format to a short to on-the-wire format #define PUTBYTE2BYTE(DstPtr, Src) \ *((PBYTE)(DstPtr)) = (BYTE)(Src) // Put a dword from the host format to a short to on-the-wire format #define PUTSHORT2BYTE(DstPtr, Src) \ *((PBYTE)(DstPtr)) = ((USHORT)(Src) % 256) // Put a dword from the host format to a short to on-the-wire format #define PUTSHORT2SHORT(DstPtr, Src) \ *((PBYTE)(DstPtr)+0) = (BYTE) ((USHORT)(Src) >> 8), \ *((PBYTE)(DstPtr)+1) = (BYTE)(Src) // Put a dword from the host format to a byte to on-the-wire format #define PUTDWORD2BYTE(DstPtr, Src) \ *(PBYTE)(DstPtr) = (BYTE)(Src) // Put a dword from the host format to a short to on-the-wire format #define PUTDWORD2SHORT(DstPtr, Src) \ *((PBYTE)(DstPtr)+0) = (BYTE) ((DWORD)(Src) >> 8), \ *((PBYTE)(DstPtr)+1) = (BYTE) (Src) // Put a dword from the host format to a dword to on-the-wire format #define PUTDWORD2DWORD(DstPtr, Src) \ *((PBYTE)(DstPtr)+0) = (BYTE) ((DWORD)(Src) >> 24), \ *((PBYTE)(DstPtr)+1) = (BYTE) ((DWORD)(Src) >> 16), \ *((PBYTE)(DstPtr)+2) = (BYTE) ((DWORD)(Src) >> 8), \ *((PBYTE)(DstPtr)+3) = (BYTE) (Src) // MIN/MAX macros #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define MAX(a, b) (((a) > (b)) ? (a) : (b)) extern BYTE AtalkUpCaseTable[]; extern VOID AtalkUpCase( IN PBYTE pSrc, IN BYTE SrcLen, OUT PBYTE pDst ); extern BOOLEAN AtalkCompareCaseInsensitive( IN PBYTE s1, IN PBYTE s2 ); extern int AtalkOrderCaseInsensitive( IN PBYTE s1, IN PBYTE s2 ); #define AtalkFixedCompareCaseInsensitive(s1, l1, s2, l2) \ (((l1) == (l2)) && AtalkCompareFixedCaseInsensitive(s1, s2, l1)) extern BOOLEAN AtalkCompareFixedCaseInsensitive( IN PBYTE s1, IN PBYTE s2, IN int len ); #define AtalkFixedCompareCaseSensitive(s1, l1, s2, l2) \ ((l1 == l2) && !memcmp(s1, s2, l1)) extern PBYTE AtalkSearchBuf( IN PBYTE pBuf, IN BYTE BufLen, IN BYTE SearchChar ); int GetTokenLen( IN PBYTE pTokStr, IN int WildStringLen, IN BYTE NBP_WILD_CHARACTER ); BOOLEAN SubStringMatch( IN PBYTE pTarget, IN PBYTE pTokStr, IN int StringLen, IN int TokStrLen ); extern BOOLEAN AtalkCheckNetworkRange( IN PATALK_NETWORKRANGE NetworkRange ); #define AtalkRangesOverlap(pRange1, pRange2) \ (((pRange1)->anr_LastNetwork >= (pRange2)->anr_FirstNetwork) && \ ((pRange1)->anr_FirstNetwork <= (pRange2)->anr_LastNetwork)) extern BOOLEAN AtalkIsPrime( long Step ); extern LONG AtalkRandomNumber( VOID ); extern VOID AtalkDbgIncCount( IN DWORD *Value ); extern VOID AtalkDbgDecCount( IN DWORD *Value ); // Used for calculating round trip times using Van Jacobson algorithm typedef struct { ULONG rt_New; SHORT rt_Min; SHORT rt_Max; SHORT rt_Ave; SHORT rt_Dev; SHORT rt_Base; } RT, *PRT; #define AtalkInitializeRT(pRT, Initial, Min, Max) \ { \ (pRT)->rt_Min = Min; \ (pRT)->rt_Max = Max; \ (pRT)->rt_Base = Initial; \ (pRT)->rt_Ave = Min; \ (pRT)->rt_Dev = 0; \ } #define AtalkCalculateNewRT(pRT) \ { \ SHORT baseT, error; \ \ /* VAN JACOBSEN Algorithm. From Internetworking with Tcp/ip (Comer). */\ \ if ((pRT)->rt_New == 0) \ (pRT)->rt_New = 1; /* Do not let this go to zero */ \ \ error = (SHORT)((pRT)->rt_New) - ((pRT)->rt_Ave >> 3); \ (pRT)->rt_Ave += error; \ /* Make sure not too small */ \ if ((pRT)->rt_Ave <= 0) \ { \ (pRT)->rt_Ave = (pRT)->rt_Min; \ } \ \ if (error < 0) \ error = -error; \ \ error -= ((pRT)->rt_Dev >> 2); \ (pRT)->rt_Dev += error; \ if ((pRT)->rt_Dev <= 0) \ (pRT)->rt_Dev = 1; \ \ baseT = ((((pRT)->rt_Ave >> 2) + (pRT)->rt_Dev) >> 1); \ \ /* If less then min - set it */ \ if (baseT < (pRT)->rt_Min) \ baseT = (pRT)->rt_Min; \ \ /* If greater than max - set it */ \ if (baseT > (pRT)->rt_Max) \ baseT = (pRT)->rt_Max; \ \ /* Set the new value */ \ (pRT)->rt_Base = baseT; \ } extern BOOLEAN AtalkWaitTE( IN PKEVENT pEvent, IN ULONG TimeInMs ); extern VOID AtalkSleep( IN ULONG TimeInMs ); NTSTATUS AtalkGetProtocolSocketType( PATALK_DEV_CTX Context, PUNICODE_STRING RemainingFileName, PBYTE ProtocolType, PBYTE SocketType ); INT AtalkIrpGetEaCreateType( IN PIRP Irp); LOCAL LONG atalkStringHash( IN PBYTE String, IN BYTE StrLen ); #endif // _ATKUTILS_