/*++ Copyright (c) 1992 Microsoft Corporation Module Name: AtkUtils.c Abstract: This module contains miscellaneous support routines Author: Jameel Hyder (jameelh@microsoft.com) Nikhil Kamkolkar (nikhilk@microsoft.com) Revision History: 25 Feb 1993 Initial Version Notes: Tab stop: 4 --*/ #include #pragma hdrstop #define FILENUM ATKUTILS #define ONE_MS_IN_100ns -10000L // 1ms in 100ns units extern BYTE AtalkUpCaseTable[256]; VOID AtalkUpCase( IN PBYTE pSrc, IN BYTE SrcLen, OUT PBYTE pDst ) /*++ Routine Description: Arguments: Return Value: --*/ { while (SrcLen --) { *pDst++ = AtalkUpCaseTable[*pSrc++]; } } BOOLEAN AtalkCompareCaseInsensitive( IN PBYTE s1, IN PBYTE s2 ) /*++ Routine Description: Arguments: Return Value: --*/ { BYTE c1, c2; while (((c1 = *s1++) != 0) && ((c2 = *s2++) != 0)) { if (AtalkUpCaseTable[c1] != AtalkUpCaseTable[c2]) return(FALSE); } return (c2 == 0); } int AtalkOrderCaseInsensitive( IN PBYTE s1, IN PBYTE s2 ) /*++ Routine Description: Arguments: Return Value: --*/ { BYTE c1, c2; while (((c1 = *s1++) != 0) && ((c2 = *s2++) != 0)) { c1 = AtalkUpCaseTable[c1]; c2 = AtalkUpCaseTable[c2]; if (c1 != c2) return (c1 - c2); } if (c2 == 0) return 0; return (-1); } BOOLEAN AtalkCompareFixedCaseInsensitive( IN PBYTE s1, IN PBYTE s2, IN int len ) /*++ Routine Description: Arguments: Return Value: --*/ { while(len--) { if (AtalkUpCaseTable[*s1++] != AtalkUpCaseTable[*s2++]) return(FALSE); } return(TRUE); } PBYTE AtalkSearchBuf( IN PBYTE pBuf, IN BYTE BufLen, IN BYTE SearchChar ) /*++ Routine Description: Arguments: Return Value: --*/ { for (NOTHING; (BufLen != 0); BufLen--, pBuf++) { if (*pBuf == SearchChar) { break; } } return ((BufLen == 0) ? NULL : pBuf); } int GetTokenLen( IN PBYTE pTokStr, IN int WildStringLen, IN BYTE SearchChar ) /*++ Routine Description: Find the substring between start of the given string and the first wildchar after that, and return the length of the substring --*/ { int len; len = 0; while (len < WildStringLen) { if (pTokStr[len] == SearchChar) { break; } len++; } return (len); } BOOLEAN SubStringMatch( IN PBYTE pTarget, IN PBYTE pTokStr, IN int StringLen, IN int TokStrLen ) /*++ Routine Description: Search pTarget string to see if the substring pTokStr can be found in it. --*/ { int i; if (TokStrLen > StringLen) { return (FALSE); } // if the pTarget string is "FooBarString" and if the substring is // BarStr for (i=(StringLen-TokStrLen); i>=0; i--) { if ( AtalkFixedCompareCaseInsensitive( pTarget+i, TokStrLen, pTokStr, TokStrLen) ) { return( TRUE ); } } return (FALSE); } BOOLEAN AtalkCheckNetworkRange( IN PATALK_NETWORKRANGE Range ) /*++ Routine Description: Arguments: Return Value: --*/ { if ((Range->anr_FirstNetwork < FIRST_VALID_NETWORK) || (Range->anr_FirstNetwork > LAST_VALID_NETWORK) || (Range->anr_LastNetwork < FIRST_VALID_NETWORK) || (Range->anr_LastNetwork > LAST_VALID_NETWORK) || (Range->anr_LastNetwork < Range->anr_FirstNetwork) || (Range->anr_FirstNetwork >= FIRST_STARTUP_NETWORK)) { return(FALSE); } return(TRUE); } BOOLEAN AtalkIsPrime( long Step ) /*++ Routine Description: Arguments: Return Value: --*/ { // We assume "step" is odd. long i, j; // All odds, seven and below, are prime. if (Step <= 7) return (TRUE); // Do a little divisibility checking. The "/3" is a reasonably good // shot at sqrt() because the smallest odd to come through here will be // 9. j = Step/3; for (i = 3; i <= j; i++) if (Step % i == 0) return(FALSE); return(TRUE); } LONG AtalkRandomNumber( VOID ) /*++ Routine Description: Arguments: Return Value: --*/ { LARGE_INTEGER Li; static LONG seed = 0; // Return a positive pseudo-random number; simple linear congruential // algorithm. ANSI C "rand()" function. if (seed == 0) { KeQuerySystemTime(&Li); seed = Li.LowPart; } seed *= (0x41C64E6D + 0x3039); return (seed & 0x7FFFFFFF); } BOOLEAN AtalkWaitTE( IN PKEVENT pEvent, IN ULONG TimeInMs ) /*++ Routine Description: Wait for an event to get signalled or a time to elapse Arguments: Return Value: --*/ { TIME Time; NTSTATUS Status; // Make sure we can indeed wait ASSERT (KeGetCurrentIrql() == LOW_LEVEL); // Initialize the event KeInitializeEvent(pEvent, NotificationEvent, FALSE); Time.QuadPart = Int32x32To64((LONG)TimeInMs, ONE_MS_IN_100ns); Status = KeWaitForSingleObject(pEvent, Executive, KernelMode, FALSE, &Time); return (Status != STATUS_TIMEOUT); } VOID AtalkSleep( IN ULONG TimeInMs ) /*++ Routine Description: Arguments: Return Value: --*/ { KTIMER SleepTimer; LARGE_INTEGER TimerValue; ASSERT (KeGetCurrentIrql() == LOW_LEVEL); KeInitializeTimer(&SleepTimer); TimerValue.QuadPart = Int32x32To64(TimeInMs, ONE_MS_IN_100ns); KeSetTimer(&SleepTimer, TimerValue, NULL); KeWaitForSingleObject(&SleepTimer, UserRequest, KernelMode, FALSE, NULL); } NTSTATUS AtalkGetProtocolSocketType( PATALK_DEV_CTX Context, PUNICODE_STRING RemainingFileName, PBYTE ProtocolType, PBYTE SocketType ) /*++ Routine Description: Arguments: Return Value: --*/ { NTSTATUS status = STATUS_SUCCESS; ULONG protocolType; UNICODE_STRING typeString; *ProtocolType = PROTOCOL_TYPE_UNDEFINED; *SocketType = SOCKET_TYPE_UNDEFINED; switch (Context->adc_DevType) { case ATALK_DEV_DDP : if ((UINT)RemainingFileName->Length <= (sizeof(PROTOCOLTYPE_PREFIX) - sizeof(WCHAR))) { status = STATUS_NO_SUCH_DEVICE; break; } RtlInitUnicodeString(&typeString, (PWCHAR)((PCHAR)RemainingFileName->Buffer + sizeof(PROTOCOLTYPE_PREFIX) - sizeof(WCHAR))); status = RtlUnicodeStringToInteger(&typeString, DECIMAL_BASE, &protocolType); if (NT_SUCCESS(status)) { DBGPRINT(DBG_COMP_CREATE, DBG_LEVEL_INFO, ("AtalkGetProtocolType: protocol type is %lx\n", protocolType)); if ((protocolType > DDPPROTO_DDP) && (protocolType <= DDPPROTO_MAX)) { *ProtocolType = (BYTE)protocolType; } else { status = STATUS_NO_SUCH_DEVICE; } } break; case ATALK_DEV_ADSP : // Check for the socket type if (RemainingFileName->Length == 0) { *SocketType = SOCKET_TYPE_RDM; break; } if ((UINT)RemainingFileName->Length != (sizeof(SOCKETSTREAM_SUFFIX) - sizeof(WCHAR))) { status = STATUS_NO_SUCH_DEVICE; break; } RtlInitUnicodeString(&typeString, SOCKETSTREAM_SUFFIX); // Case insensitive compare if (RtlEqualUnicodeString(&typeString, RemainingFileName, TRUE)) { *SocketType = SOCKET_TYPE_STREAM; break; } else { status = STATUS_NO_SUCH_DEVICE; break; } case ATALK_DEV_ASPC: case ATALK_DEV_ASP : case ATALK_DEV_PAP : break; default: status = STATUS_NO_SUCH_DEVICE; break; } return(status); } INT AtalkIrpGetEaCreateType( IN PIRP Irp ) /*++ Routine Description: Checks the EA name and returns the appropriate open type. Arguments: Irp - the irp for the create request, the EA value is stored in the SystemBuffer Return Value: TDI_TRANSPORT_ADDRESS_FILE: Create irp was for a transport address TDI_CONNECTION_FILE: Create irp was for a connection object ATALK_FILE_TYPE_CONTROL: Create irp was for a control channel (ea = NULL) --*/ { PFILE_FULL_EA_INFORMATION openType; BOOLEAN found; INT returnType=0; // not a valid type USHORT i; openType = (PFILE_FULL_EA_INFORMATION)Irp->AssociatedIrp.SystemBuffer; if (openType != NULL) { do { found = TRUE; for (i=0; (i<(USHORT)openType->EaNameLength) && (i < sizeof(TdiTransportAddress)); i++) { if (openType->EaName[i] == TdiTransportAddress[i]) { continue; } else { found = FALSE; break; } } if (found) { returnType = TDI_TRANSPORT_ADDRESS_FILE; break; } // // Is this a connection object? // found = TRUE; for (i=0; (i<(USHORT)openType->EaNameLength) && (i < sizeof(TdiConnectionContext)); i++) { if (openType->EaName[i] == TdiConnectionContext[i]) { continue; } else { found = FALSE; break; } } if (found) { returnType = TDI_CONNECTION_FILE; break; } } while ( FALSE ); } else { returnType = TDI_CONTROL_CHANNEL_FILE; } return(returnType); } #if DBG VOID AtalkDbgIncCount( IN DWORD *Value ) { KIRQL OldIrql; ACQUIRE_SPIN_LOCK(&AtalkDebugSpinLock, &OldIrql); (*Value)++; RELEASE_SPIN_LOCK(&AtalkDebugSpinLock, OldIrql); } VOID AtalkDbgDecCount( IN DWORD *Value ) { KIRQL OldIrql; ACQUIRE_SPIN_LOCK(&AtalkDebugSpinLock, &OldIrql); ASSERT((*Value) > 0); (*Value)--; RELEASE_SPIN_LOCK(&AtalkDebugSpinLock, OldIrql); } #endif