/**********************************************************************/ /** Microsoft Windows/NT **/ /** Copyright(c) Microsoft Corp., 1992 **/ /**********************************************************************/ /* Init.c OS Independent initialization routines FILE HISTORY: Johnl 26-Mar-1993 Created */ #include "nbtnt.h" #include "precomp.h" #include "hosts.h" VOID ReadScope( IN tNBTCONFIG *pConfig, IN HANDLE ParmHandle ); VOID ReadLmHostFile( IN tNBTCONFIG *pConfig, IN HANDLE ParmHandle ); extern tTIMERQ TimerQ; //******************* Pageable Routine Declarations **************** #ifdef ALLOC_PRAGMA #pragma CTEMakePageable(INIT, InitNotOs) #pragma CTEMakePageable(PAGE, InitTimersNotOs) #pragma CTEMakePageable(PAGE, StopInitTimers) #pragma CTEMakePageable(PAGE, ReadParameters) #pragma CTEMakePageable(PAGE, ReadParameters2) #pragma CTEMakePageable(PAGE, ReadScope) #pragma CTEMakePageable(PAGE, ReadLmHostFile) #endif //******************* Pageable Routine Declarations **************** #ifdef VXD #pragma BEGIN_INIT #endif //---------------------------------------------------------------------------- NTSTATUS InitNotOs( void ) /*++ Routine Description: This is the initialization routine for the Non-OS Specific side of the NBT device driver. pNbtGlobConfig must be initialized before this is called! Arguments: Return Value: NTSTATUS - The function value is the final status from the initialization operation. --*/ { NTSTATUS status = STATUS_SUCCESS; ULONG i; CTEPagedCode(); // // for multihomed hosts, this tracks the number of adapters as each one // is created. // NbtMemoryAllocated = 0; NbtConfig.AdapterCount = 0; NbtConfig.MultiHomed = FALSE; NbtConfig.SingleResponse = FALSE; NbtConfig.ServerMask = 0; NbtConfig.ClientMask = 0; NbtConfig.iCurrentNumBuff[eNBT_DGRAM_TRACKER] = 0; pNbtGlobConfig->iBufferSize[eNBT_DGRAM_TRACKER] = sizeof(tDGRAM_SEND_TRACKING); CTEZeroMemory (&NameStatsInfo,sizeof(tNAMESTATS_INFO)); // Initialize the name statistics CTEZeroMemory (&LmHostQueries,sizeof(tLMHSVC_REQUESTS)); // Synchronize reads from the LmHosts file InitializeListHead (&LmHostQueries.ToResolve); // // Initialize the linked lists associated with the global configuration // data structures // InitializeListHead (&NbtConfig.DeviceContexts); InitializeListHead (&NbtConfig.DevicesAwaitingDeletion); InitializeListHead (&NbtConfig.AddressHead); InitializeListHead (&NbtConfig.PendingNameQueries); InitializeListHead (&NbtConfig.WorkerQList); InitializeListHead (&NbtConfig.NodeStatusHead); InitializeListHead (&NbtConfig.DgramTrackerFreeQ); InitializeListHead (&UsedTrackers); InitializeListHead (&UsedIrps); InitializeListHead (&DomainNames.DomainList); // initialize the spin lock CTEInitLock (&NbtConfig.LockInfo.SpinLock); CTEInitLock (&NbtConfig.JointLock.LockInfo.SpinLock); CTEInitLock (&NbtConfig.WorkerQLock.LockInfo.SpinLock); #ifndef VXD pWinsInfo = NULL; NbtConfig.NumWorkerThreadsQueued = 0; NbtConfig.NumTimersRunning = 0; NbtConfig.CacheTimeStamp = 0; NbtConfig.InterfaceIndex = 0; NbtConfig.GlobalRefreshState = 0; NbtConfig.pWakeupRefreshTimer = NULL; NbtConfig.TransactionId = WINS_MAXIMUM_TRANSACTION_ID + 1; NbtConfig.RemoteCacheLen = REMOTE_CACHE_INCREMENT; NbtConfig.iBufferSize[eNBT_FREE_SESSION_MDLS] = sizeof(tSESSIONHDR); NbtConfig.iBufferSize[eNBT_DGRAM_MDLS] = DGRAM_HDR_SIZE + (NbtConfig.ScopeLength << 1); // // Set the Unitialized flag in the TimerQ, so that it can be initialized // when needed // TimerQ.TimersInitialized = FALSE; // Initialize the LastForcedReleaseTime! CTEQuerySystemTime (NbtConfig.LastForcedReleaseTime); CTEQuerySystemTime (NbtConfig.LastOutOfRsrcLogTime); CTEQuerySystemTime (NbtConfig.LastRefreshTime); ExSystemTimeToLocalTime (&NbtConfig.LastRefreshTime, &NbtConfig.LastRefreshTime); // // this resource is used to synchronize access to the Dns structure // CTEZeroMemory (&DnsQueries,sizeof(tLMHSVC_REQUESTS)); InitializeListHead (&DnsQueries.ToResolve); // // this resource is used to synchronize access to the CheckAddr structure // CTEZeroMemory(&CheckAddr,sizeof(tLMHSVC_REQUESTS)); InitializeListHead (&CheckAddr.ToResolve); // // Setup the default disconnect timeout - 10 seconds - convert // to negative 100 Ns. // DefaultDisconnectTimeout.QuadPart = Int32x32To64(DEFAULT_DISC_TIMEOUT, MILLISEC_TO_100NS); DefaultDisconnectTimeout.QuadPart = -(DefaultDisconnectTimeout.QuadPart); InitializeListHead (&NbtConfig.IrpFreeList); InitializeListHead (&FreeWinsList); // set up a list for connections when we run out of resources and need to // disconnect these connections. An Irp is also needed for this list, and // it is allocated in Driver.C after we have created the connections to the // transport and therefore know our Irp Stack Size. // InitializeListHead (&NbtConfig.OutOfRsrc.ConnectionHead); KeInitializeEvent (&NbtConfig.WorkerQLastEvent, NotificationEvent, TRUE); KeInitializeEvent (&NbtConfig.TimerQLastEvent, NotificationEvent, TRUE); KeInitializeEvent (&NbtConfig.WakeupTimerStartedEvent, NotificationEvent, TRUE); // use this resources to synchronize access to the security info between // assigning security and checking it - when adding names to the // name local name table through NbtregisterName. This also insures // that the name is in the local hash table (from a previous Registration) // before the next registration is allowed to proceed and check for // the name in the table. // ExInitializeResourceLite(&NbtConfig.Resource); #else DefaultDisconnectTimeout = DEFAULT_DISC_TIMEOUT * 1000; // convert to milliseconds InitializeListHead(&NbtConfig.SendTimeoutHead) ; InitializeListHead(&NbtConfig.SessionBufferFreeList) ; InitializeListHead(&NbtConfig.SendContextFreeList) ; InitializeListHead(&NbtConfig.RcvContextFreeList) ; // // For session headers, since they are only four bytes and we can't // change the size of the structure, we'll covertly add enough for // a full LIST_ENTRY and treat it like a standalone LIST_ENTRY structure // when adding and removing from the list. // NbtConfig.iBufferSize[eNBT_SESSION_HDR] = sizeof(tSESSIONHDR) + sizeof(LIST_ENTRY) - sizeof(tSESSIONHDR); NbtConfig.iBufferSize[eNBT_SEND_CONTEXT] = sizeof(TDI_SEND_CONTEXT); NbtConfig.iBufferSize[eNBT_RCV_CONTEXT] = sizeof(RCV_CONTEXT); NbtConfig.iCurrentNumBuff[eNBT_SESSION_HDR] = NBT_INITIAL_NUM; NbtConfig.iCurrentNumBuff[eNBT_SEND_CONTEXT] = NBT_INITIAL_NUM; NbtConfig.iCurrentNumBuff[eNBT_RCV_CONTEXT] = NBT_INITIAL_NUM; InitializeListHead (&NbtConfig.DNSDirectNameQueries); #endif #if DBG NbtConfig.LockInfo.LockNumber = NBTCONFIG_LOCK; NbtConfig.JointLock.LockInfo.LockNumber = JOINT_LOCK; NbtConfig.WorkerQLock.LockInfo.LockNumber = WORKERQ_LOCK; for (i=0; iNameServerPort = (USHORT)CTEReadSingleIntParameter(ParmHandle, WS_NS_PORT_NUM, NBT_NAMESERVER_UDP_PORT, 0); pConfig->MaxPreloadEntries = CTEReadSingleIntParameter(ParmHandle, WS_MAX_PRELOADS, DEF_PRELOAD, DEF_PRELOAD ) ; if (pConfig->MaxPreloadEntries > MAX_PRELOAD) { pConfig->MaxPreloadEntries = MAX_PRELOAD; } #ifdef VXD pConfig->DnsServerPort = (USHORT)CTEReadSingleIntParameter(ParmHandle, WS_DNS_PORT_NUM, NBT_DNSSERVER_UDP_PORT, 0); pConfig->lRegistryMaxNames = (USHORT)CTEReadSingleIntParameter(ParmHandle, VXD_NAMETABLE_SIZE_NAME, VXD_DEF_NAMETABLE_SIZE, VXD_MIN_NAMETABLE_SIZE ) ; pConfig->lRegistryMaxSessions = (USHORT)CTEReadSingleIntParameter(ParmHandle, VXD_SESSIONTABLE_SIZE_NAME, VXD_DEF_SESSIONTABLE_SIZE, VXD_MIN_SESSIONTABLE_SIZE ) ; pConfig->DoDNSDevolutions = (BOOLEAN)CTEReadSingleIntParameter(ParmHandle, WS_DO_DNS_DEVOLUTIONS, 0, // disabled by default 0); #endif pConfig->RemoteHashTtl = CTEReadSingleIntParameter(ParmHandle, WS_CACHE_TIMEOUT, DEFAULT_CACHE_TIMEOUT, MIN_CACHE_TIMEOUT); pConfig->InitialRefreshTimeout = CTEReadSingleIntParameter(ParmHandle, WS_INITIAL_REFRESH, NBT_INITIAL_REFRESH_TTL, NBT_INITIAL_REFRESH_TTL); pConfig->MinimumRefreshSleepTimeout = CTEReadSingleIntParameter(ParmHandle, WS_MINIMUM_REFRESH_SLEEP_TIME, DEFAULT_MINIMUM_REFRESH_SLEEP_TIME, 0); // retry timeouts and number of retries for both Broadcast name resolution // and Name Service resolution // pConfig->uNumBcasts = (USHORT)CTEReadSingleIntParameter(ParmHandle, WS_NUM_BCASTS, DEFAULT_NUMBER_BROADCASTS, 1); pConfig->uBcastTimeout = CTEReadSingleIntParameter(ParmHandle, WS_BCAST_TIMEOUT, DEFAULT_BCAST_TIMEOUT, MIN_BCAST_TIMEOUT); pConfig->uNumRetries = (USHORT)CTEReadSingleIntParameter(ParmHandle, WS_NAMESRV_RETRIES, DEFAULT_NUMBER_RETRIES, 1); pConfig->uRetryTimeout = CTEReadSingleIntParameter(ParmHandle, WS_NAMESRV_TIMEOUT, DEFAULT_RETRY_TIMEOUT, MIN_RETRY_TIMEOUT); pConfig->KeepAliveTimeout = CTEReadSingleIntParameter(ParmHandle, WS_KEEP_ALIVE, DEFAULT_KEEP_ALIVE, MIN_KEEP_ALIVE); pConfig->SelectAdapter = (BOOLEAN)CTEReadSingleIntParameter(ParmHandle, WS_RANDOM_ADAPTER, 0, 0); pConfig->SingleResponse = (BOOLEAN)CTEReadSingleIntParameter(ParmHandle, WS_SINGLE_RESPONSE, 0, 0); pConfig->NoNameReleaseOnDemand = (BOOLEAN)CTEReadSingleIntParameter(ParmHandle, WS_NO_NAME_RELEASE, 0, 0); // disabled by default if (pConfig->CachePerAdapterEnabled = (BOOLEAN) CTEReadSingleIntParameter(ParmHandle, WS_CACHE_PER_ADAPTER_ENABLED, 1, // Enabled by default 0)) { pConfig->ConnectOnRequestedInterfaceOnly = (BOOLEAN) CTEReadSingleIntParameter(ParmHandle, WS_CONNECT_ON_REQUESTED_IF_ONLY, 0, // Disabled by default 0); } else { pConfig->ConnectOnRequestedInterfaceOnly = FALSE; } pConfig->SendDgramOnRequestedInterfaceOnly = (BOOLEAN) CTEReadSingleIntParameter(ParmHandle, WS_SEND_DGRAM_ON_REQUESTED_IF_ONLY, 1, // Enabled by default 0); pConfig->SMBDeviceEnabled = (BOOLEAN) CTEReadSingleIntParameter(ParmHandle, WS_SMB_DEVICE_ENABLED, 1, // Enabled by default 0); pConfig->MultipleCacheFlags = (BOOLEAN) CTEReadSingleIntParameter(ParmHandle, WS_MULTIPLE_CACHE_FLAGS, 0, // Not enabled by default 0); pConfig->UseDnsOnly = (BOOLEAN)CTEReadSingleIntParameter(ParmHandle, WS_USE_DNS_ONLY, 0, 0); // disabled by default if (pConfig->UseDnsOnly) { pConfig->ResolveWithDns = TRUE; pConfig->TryAllNameServers = FALSE; } else { pConfig->ResolveWithDns = (BOOLEAN)CTEReadSingleIntParameter(ParmHandle, WS_ENABLE_DNS, 1, // Enabled by default 0); #ifdef MULTIPLE_WINS pConfig->TryAllNameServers = (BOOLEAN)CTEReadSingleIntParameter(ParmHandle, WS_TRY_ALL_NAME_SERVERS, 0, // disabled by default 0); #endif } pConfig->SmbDisableNetbiosNameCacheLookup = (BOOLEAN)CTEReadSingleIntParameter(ParmHandle, WS_SMB_DISABLE_NETBIOS_NAME_CACHE_LOOKUP, 1, // Enabled by default 0); pConfig->TryAllAddr = (BOOLEAN)CTEReadSingleIntParameter(ParmHandle, WS_TRY_ALL_ADDRS, 1, 1); // enabled by default pConfig->LmHostsTimeout = CTEReadSingleIntParameter(ParmHandle, WS_LMHOSTS_TIMEOUT, DEFAULT_LMHOST_TIMEOUT, MIN_LMHOST_TIMEOUT); pConfig->MaxDgramBuffering = CTEReadSingleIntParameter(ParmHandle, WS_MAX_DGRAM_BUFFER, DEFAULT_DGRAM_BUFFERING, DEFAULT_DGRAM_BUFFERING); pConfig->EnableProxyRegCheck = (BOOLEAN)CTEReadSingleIntParameter(ParmHandle, WS_ENABLE_PROXY_REG_CHECK, 0, 0); pConfig->WinsDownTimeout = (ULONG)CTEReadSingleIntParameter(ParmHandle, WS_WINS_DOWN_TIMEOUT, DEFAULT_WINS_DOWN_TIMEOUT, MIN_WINS_DOWN_TIMEOUT); pConfig->MaxBackLog = (ULONG)CTEReadSingleIntParameter(ParmHandle, WS_MAX_CONNECTION_BACKLOG, DEFAULT_CONN_BACKLOG, MIN_CONN_BACKLOG); pConfig->SpecialConnIncrement = (ULONG)CTEReadSingleIntParameter(ParmHandle, WS_CONNECTION_BACKLOG_INCREMENT, DEFAULT_CONN_BACKLOG_INCREMENT, MIN_CONN_BACKLOG_INCREMENT); pConfig->MinFreeLowerConnections = (ULONG)CTEReadSingleIntParameter(ParmHandle, WS_MIN_FREE_INCOMING_CONNECTIONS, DEFAULT_NBT_NUM_INITIAL_CONNECTIONS, MIN_NBT_NUM_INITIAL_CONNECTIONS); pConfig->BreakOnAssert = (BOOLEAN) CTEReadSingleIntParameter(ParmHandle, WS_BREAK_ON_ASSERT, 1, // Enabled by default 0); #ifndef REMOVE_IF_TCPIP_FIX___GATEWAY_AFTER_NOTIFY_BUG pConfig->DhcpProcessingDelay = (ULONG) CTEReadSingleIntParameter(ParmHandle, WS_DHCP_PROCESSING_DELAY, DEFAULT_DHCP_PROCESSING_DELAY, MIN_DHCP_PROCESSING_DELAY); #endif // REMOVE_IF_TCPIP_FIX___GATEWAY_AFTER_NOTIFY_BUG // // Cap the upper limit // if (pConfig->MaxBackLog > MAX_CONNECTION_BACKLOG) { pConfig->MaxBackLog = MAX_CONNECTION_BACKLOG; } if (pConfig->SpecialConnIncrement > MAX_CONNECTION_BACKLOG_INCREMENT) { pConfig->SpecialConnIncrement = MAX_CONNECTION_BACKLOG_INCREMENT; } // // Since UB chose the wrong opcode (9) we have to allow configuration // of that opcode incase our nodes refresh to their NBNS // Refresh = (ULONG)CTEReadSingleIntParameter(ParmHandle, WS_REFRESH_OPCODE, REFRESH_OPCODE, REFRESH_OPCODE); if (Refresh == UB_REFRESH_OPCODE) { pConfig->OpRefresh = OP_REFRESH_UB; } else { pConfig->OpRefresh = OP_REFRESH; } #ifndef VXD pConfig->EnableLmHosts = (BOOLEAN)CTEReadSingleIntParameter(ParmHandle, WS_ENABLE_LMHOSTS, 0, 0); #endif #ifdef PROXY_NODE { ULONG Proxy; Proxy = CTEReadSingleIntParameter(ParmHandle, WS_IS_IT_A_PROXY, IS_NOT_PROXY, //default value IS_NOT_PROXY); // // If the returned value is greater than IS_NOT_PROXY, it is a proxy // (also check that they have not entered an ascii string instead of a // dword in the registry // if ((Proxy > IS_NOT_PROXY) && (Proxy < ('0'+IS_NOT_PROXY))) { NodeType |= PROXY; RegistryNodeType |= PROXY; NbtConfig.ProxyType = Proxy; } } #endif NodeSize = CTEReadSingleIntParameter(ParmHandle, WS_NODE_SIZE, NodeType & PROXY ? LARGE : DEFAULT_NODE_SIZE, NodeType & PROXY ? LARGE : SMALL); switch (NodeSize) { default: case SMALL: pConfig->uNumLocalNames = NUMBER_LOCAL_NAMES; pConfig->uNumRemoteNames = NUMBER_REMOTE_NAMES; pConfig->uNumBucketsLocal = NUMBER_BUCKETS_LOCAL_HASH_TABLE; pConfig->uNumBucketsRemote = NUMBER_BUCKETS_REMOTE_HASH_TABLE; pConfig->iMaxNumBuff[eNBT_DGRAM_TRACKER] = NBT_NUM_DGRAM_TRACKERS; pConfig->iMaxNumBuff[eNBT_TIMER_ENTRY] = TIMER_Q_SIZE; #ifndef VXD pConfig->iMaxNumBuff[eNBT_FREE_IRPS] = NBT_NUM_IRPS; pConfig->iMaxNumBuff[eNBT_DGRAM_MDLS] = NBT_NUM_DGRAM_MDLS; pConfig->iMaxNumBuff[eNBT_FREE_SESSION_MDLS] = NBT_NUM_SESSION_MDLS; #else pConfig->iMaxNumBuff[eNBT_SESSION_HDR] = NBT_NUM_SESSION_HDR ; pConfig->iMaxNumBuff[eNBT_SEND_CONTEXT] = NBT_NUM_SEND_CONTEXT ; pConfig->iMaxNumBuff[eNBT_RCV_CONTEXT] = NBT_NUM_RCV_CONTEXT ; #endif break; case MEDIUM: pConfig->uNumLocalNames = MEDIUM_NUMBER_LOCAL_NAMES; pConfig->uNumRemoteNames = MEDIUM_NUMBER_REMOTE_NAMES; pConfig->uNumBucketsLocal = MEDIUM_NUMBER_BUCKETS_LOCAL_HASH_TABLE; pConfig->uNumBucketsRemote = MEDIUM_NUMBER_BUCKETS_REMOTE_HASH_TABLE; pConfig->iMaxNumBuff[eNBT_DGRAM_TRACKER] = MEDIUM_NBT_NUM_DGRAM_TRACKERS; pConfig->iMaxNumBuff[eNBT_TIMER_ENTRY] = MEDIUM_TIMER_Q_SIZE; #ifndef VXD pConfig->iMaxNumBuff[eNBT_FREE_IRPS] = MEDIUM_NBT_NUM_IRPS; pConfig->iMaxNumBuff[eNBT_DGRAM_MDLS] = MEDIUM_NBT_NUM_DGRAM_MDLS; pConfig->iMaxNumBuff[eNBT_FREE_SESSION_MDLS] = MEDIUM_NBT_NUM_SESSION_MDLS; #else pConfig->iMaxNumBuff[eNBT_SESSION_HDR] = MEDIUM_NBT_NUM_SESSION_HDR ; pConfig->iMaxNumBuff[eNBT_SEND_CONTEXT] = MEDIUM_NBT_NUM_SEND_CONTEXT ; pConfig->iMaxNumBuff[eNBT_RCV_CONTEXT] = MEDIUM_NBT_NUM_RCV_CONTEXT ; #endif break; case LARGE: pConfig->uNumLocalNames = LARGE_NUMBER_LOCAL_NAMES; pConfig->uNumRemoteNames = LARGE_NUMBER_REMOTE_NAMES; pConfig->uNumBucketsLocal = LARGE_NUMBER_BUCKETS_LOCAL_HASH_TABLE; pConfig->uNumBucketsRemote = LARGE_NUMBER_BUCKETS_REMOTE_HASH_TABLE; pConfig->iMaxNumBuff[eNBT_DGRAM_TRACKER] = LARGE_NBT_NUM_DGRAM_TRACKERS; pConfig->iMaxNumBuff[eNBT_TIMER_ENTRY] = LARGE_TIMER_Q_SIZE; #ifndef VXD pConfig->iMaxNumBuff[eNBT_FREE_IRPS] = LARGE_NBT_NUM_IRPS; pConfig->iMaxNumBuff[eNBT_DGRAM_MDLS] = LARGE_NBT_NUM_DGRAM_MDLS; pConfig->iMaxNumBuff[eNBT_FREE_SESSION_MDLS] = LARGE_NBT_NUM_SESSION_MDLS; #else pConfig->iMaxNumBuff[eNBT_SESSION_HDR] = LARGE_NBT_NUM_SESSION_HDR ; pConfig->iMaxNumBuff[eNBT_SEND_CONTEXT] = LARGE_NBT_NUM_SEND_CONTEXT ; pConfig->iMaxNumBuff[eNBT_RCV_CONTEXT] = LARGE_NBT_NUM_RCV_CONTEXT ; #endif break; } ReadLmHostFile(pConfig,ParmHandle); } #ifdef VXD #pragma END_INIT #endif //---------------------------------------------------------------------------- VOID ReadParameters2( IN tNBTCONFIG *pConfig, IN HANDLE ParmHandle ) /*++ Routine Description: This routine is called to read DHCPable parameters from the parameters section of the NBT section of the registry. This routine is primarily for the Vxd. Arguments: pConfig - A pointer to the configuration data structure. ParmHandle - a handle to the parameters Key under Nbt Return Value: Status --*/ { ULONG Node; ULONG ReadOne; ULONG ReadTwo; CTEPagedCode(); Node = CTEReadSingleIntParameter(ParmHandle, // handle of key to look under WS_NODE_TYPE, // wide string name 0, // default value 0); switch (Node) { case 2: NodeType = PNODE; break; case 4: NodeType = MNODE; break; case 8: NodeType = MSNODE; break; case 1: NodeType = BNODE; break; default: NodeType = BNODE | DEFAULT_NODE_TYPE; break; } RegistryNodeType = NodeType; // do a trick here - read the registry twice for the same value, passing // in two different defaults, in order to determine if the registry // value has been defined or not - since it may be defined, but equal // to one default. ReadOne = CTEReadSingleHexParameter(ParmHandle, WS_ALLONES_BCAST, DEFAULT_BCAST_ADDR, 0); ReadTwo = CTEReadSingleHexParameter(ParmHandle, WS_ALLONES_BCAST, 0, 0); if (ReadOne != ReadTwo) { NbtConfig.UseRegistryBcastAddr = FALSE; } else { NbtConfig.UseRegistryBcastAddr = TRUE; NbtConfig.RegistryBcastAddr = ReadTwo; } ReadScope(pConfig,ParmHandle); } //---------------------------------------------------------------------------- VOID ReadScope( IN tNBTCONFIG *pConfig, IN HANDLE ParmHandle ) /*++ Routine Description: This routine is called to read the scope from registry and convert it to a format where the intervening dots are length bytes. Arguments: pConfig - A pointer to the configuration data structure. ParmHandle - a handle to the parameters Key under Nbt Return Value: Status --*/ { NTSTATUS status; PUCHAR pScope, pOldScope, pNewScope; PUCHAR pBuff; PUCHAR pBuffer; PUCHAR pPeriod; ULONG Len; UCHAR Chr; CTEPagedCode(); // // this routine returns the scope in a dotted format. // "Scope.MoreScope.More" The dots are // converted to byte lengths by the code below. This routine allocates // the memory for the pScope string. // status = CTEReadIniString(ParmHandle,NBT_SCOPEID,&pBuffer); if (NT_SUCCESS(status)) { // // the user can type in an * to indicate that they really want // a null scope and that should override the DHCP scope. So check // here for an * and if so, set the scope back to null. // if ((strlen(pBuffer) == 0) || (pBuffer[0] == '*')) { CTEMemFree(pBuffer); status = STATUS_UNSUCCESSFUL; } } if (NT_SUCCESS(status)) { // length of scope is num chars plus the 0 on the end, plus // the length byte on the start(+2 total) - so allocate another buffer // that is one longer than the previous one so it can include // these extra two bytes. // Len = strlen(pBuffer); // // the scope cannot be longer than 255 characters as per RFC1002 // if (Len <= MAX_SCOPE_LENGTH) { pScope = NbtAllocMem (Len+2, NBT_TAG2('02')); if (pScope) { CTEMemCopy((pScope+1),pBuffer,Len); // // Put a null on the end of the scope // pScope[Len+1] = 0; Len = 1; // now go through the string converting periods to length // bytes - we know the first byte is a length byte so skip it. // pBuff = pScope; pBuff++; Len++; pPeriod = pScope; while (Chr = *pBuff) { Len++; if (Chr == '.') { *pPeriod = (UCHAR) (pBuff-pPeriod-1); // // Each label can be at most 63 bytes long // if (*pPeriod > MAX_LABEL_LENGTH) { status = STATUS_UNSUCCESSFUL; NbtLogEvent (EVENT_SCOPE_LABEL_TOO_LONG, STATUS_SUCCESS, 0x104); break; } // check for two periods back to back and use no scope if this // happens if (*pPeriod == 0) { status = STATUS_UNSUCCESSFUL; break; } pPeriod = pBuff++; } else pBuff++; } if (NT_SUCCESS(status)) { // the last ptr is always the end of the name. *pPeriod = (UCHAR)(pBuff - pPeriod -1); pOldScope = pConfig->pScope; pConfig->pScope = pScope; pConfig->ScopeLength = (USHORT)Len; if (pOldScope) { CTEMemFree(pOldScope); } CTEMemFree(pBuffer); return; } CTEMemFree(pScope); } CTEMemFree(pBuffer); } else { status = STATUS_UNSUCCESSFUL; NbtLogEvent (EVENT_SCOPE_LABEL_TOO_LONG, STATUS_SUCCESS, 0x105); } } // // the scope is one byte => '\0' - the length of the root name (zero) // // If the old scope and new scope are the same, then don't change the // scope tag! // pOldScope = pConfig->pScope; if (!(pOldScope) || (*pOldScope != '\0')) { if (pNewScope = NbtAllocMem ((1), NBT_TAG2('03'))) { *pNewScope = '\0'; pConfig->ScopeLength = 1; pConfig->pScope = pNewScope; if (pOldScope) { CTEMemFree(pOldScope); } } } } #ifdef VXD #pragma BEGIN_INIT #endif //---------------------------------------------------------------------------- VOID ReadLmHostFile( IN tNBTCONFIG *pConfig, IN HANDLE ParmHandle ) /*++ Routine Description: This routine is called to read the lmhost file path from the registry. Arguments: pConfig - A pointer to the configuration data structure. ParmHandle - a handle to the parameters Key under Nbt Return Value: Status --*/ { NTSTATUS status; PUCHAR pBuffer, pOldLmHosts; PUCHAR pchr; CTEPagedCode(); NbtConfig.PathLength = 0; pOldLmHosts = pConfig->pLmHosts; NbtConfig.pLmHosts = NULL; // // read in the LmHosts File location // #ifdef VXD status = CTEReadIniString(ParmHandle,WS_LMHOSTS_FILE,&pBuffer); #else status = NTGetLmHostPath(&pBuffer); #endif // // Find the last backslash so we can calculate the file path length // // Also, the lm host file must include a path of at least "c:\" i.e. // the registry contains c:\lmhost, otherwise NBT won't be // able to find the file since it doesn't know what directory // to look in. // if (NT_SUCCESS(status)) { if (pchr = strrchr(pBuffer,'\\')) { NbtConfig.pLmHosts = pBuffer; NbtConfig.PathLength = (ULONG) (pchr-pBuffer+1); // include backslash in length IF_DBG(NBT_DEBUG_NAMESRV) KdPrint(("Nbt.ReadLmHostFile: LmHostsFile path is %s\n",NbtConfig.pLmHosts)); } else { CTEMemFree(pBuffer); } } // // If we get a new Dhcp address this routine will get called again // after startup so we need to free any current lmhosts file path // if (pOldLmHosts) { CTEMemFree(pOldLmHosts); } } #ifdef VXD #pragma END_INIT #endif