Windows-Server-2003/net/netbt/sys/init.c

1270 lines
42 KiB
C
Raw Normal View History

2024-08-04 01:28:15 +02:00
/**********************************************************************/
/** 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);
NbtConfig.lNumPendingNameQueries = 0;
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.NumWorkItemQueued = 0;
NbtConfig.bSystemWorkThreadQueued = FALSE;
NbtConfig.lNumTimersRunning = 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);
//
// 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 (&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.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; i<MAXIMUM_PROCESSORS; i++)
{
NbtConfig.CurrentLockNumber[i] = 0;
}
InitializeListHead(&NbtConfig.StaleRemoteNames);
#endif
//
// create trackers List
//
// #if DBG
for (i=0; i<NBT_TRACKER_NUM_TRACKER_TYPES; i++)
{
TrackTrackers[i] = 0;
TrackerHighWaterMark[i] = 0;
}
// #endif // DBG
//
// Now allocate any initial memory/Resources
//
#ifdef VXD
status = NbtInitQ (&NbtConfig.SessionBufferFreeList,
NbtConfig.iBufferSize[eNBT_SESSION_HDR],
NBT_INITIAL_NUM);
if (!NT_SUCCESS (status))
{
return status ;
}
status = NbtInitQ( &NbtConfig.SendContextFreeList,
sizeof( TDI_SEND_CONTEXT ),
NBT_INITIAL_NUM);
if (!NT_SUCCESS (status))
{
return status ;
}
status = NbtInitQ( &NbtConfig.RcvContextFreeList,
sizeof (RCV_CONTEXT),
NBT_INITIAL_NUM);
if (!NT_SUCCESS (status))
{
return status ;
}
#endif
// create the hash tables for storing names in.
status = CreateHashTable(&NbtConfig.pLocalHashTbl, NbtConfig.uNumBucketsLocal, NBT_LOCAL);
if (!NT_SUCCESS (status))
{
ASSERTMSG("NBT:Unable to create hash tables for Netbios Names\n", (status == STATUS_SUCCESS));
return status ;
}
// we always have a remote hash table, but if we are a Proxy, it is
// a larger table. In the Non-proxy case the remote table just caches
// names resolved with the NS. In the Proxy case it also holds names
// resolved for all other clients on the local broadcast area.
// The node size registry parameter controls the number of remote buckets.
status = CreateHashTable (&NbtConfig.pRemoteHashTbl, NbtConfig.uNumBucketsRemote, NBT_REMOTE);
NbtConfig.NumNameCached = 0;
if (!NT_SUCCESS (status))
{
return status;
}
status = NbtInitTrackerQ (NBT_INITIAL_NUM);
if (!NT_SUCCESS (status))
{
return status;
}
// create the timer control blocks, setting the number of concurrent timers
// allowed at one time
status = InitTimerQ ();
return status;
}
//----------------------------------------------------------------------------
NTSTATUS
InitTimersNotOs(
void
)
/*++
Routine Description:
This is the initialization routine for the Non-OS Specific side of the
NBT device driver that starts the timers needed.
Arguments:
Return Value:
NTSTATUS - The function value is the final status from the initialization
operation.
--*/
{
NTSTATUS status = STATUS_SUCCESS;
CTEPagedCode();
//
// If the timers have already been initialized, return success
//
if (TimerQ.TimersInitialized)
{
return STATUS_SUCCESS;
}
NbtConfig.pRefreshTimer = NULL;
NbtConfig.pRemoteHashTimer = NULL;
NbtConfig.pSessionKeepAliveTimer = NULL;
NbtConfig.RefreshDivisor = REFRESH_DIVISOR;
if (!NT_SUCCESS(status))
{
return status ;
}
// start a Timer to refresh names with the name service
//
if (!(NodeType & BNODE))
{
// the initial refresh rate until we can contact the name server
NbtConfig.MinimumTtl = NbtConfig.InitialRefreshTimeout;
NbtConfig.sTimeoutCount = 3;
status = StartTimer(RefreshTimeout,
NbtConfig.InitialRefreshTimeout/REFRESH_DIVISOR,
NULL, // context value
NULL, // context2 value
NULL,
NULL,
NULL, // This timer is a global timer
&NbtConfig.pRefreshTimer,
0,
FALSE);
if ( !NT_SUCCESS(status))
{
return status;
}
}
//
// Set the TimersInitialized flag
//
TimerQ.TimersInitialized = TRUE;
// calculate the count necessary to timeout out names in RemoteHashTimeout
// milliseconds
//
NbtConfig.RemoteTimeoutCount = (USHORT)((NbtConfig.RemoteHashTtl/REMOTE_HASH_TIMEOUT));
if (NbtConfig.RemoteTimeoutCount == 0)
{
NbtConfig.RemoteTimeoutCount = 1;
}
NbtConfig.InboundDgramNameCacheTimeOutCount =
(USHORT)((NbtConfig.InboundDgramNameCacheTtl/REMOTE_HASH_TIMEOUT));
if (0 == NbtConfig.InboundDgramNameCacheTimeOutCount) {
NbtConfig.InboundDgramNameCacheTimeOutCount = 1;
}
// start a Timer to timeout remote cached names from the Remote hash table.
// The timer is a one minute timer, and the hash entries count down to zero
// then time out.
//
status = StartTimer(RemoteHashTimeout, // timer expiry routine
REMOTE_HASH_TIMEOUT,
NULL, // context value
NULL, // context2 value
NULL,
NULL,
NULL, // This timer is a global timer
&NbtConfig.pRemoteHashTimer,
0,
FALSE);
if ( !NT_SUCCESS( status ) )
{
StopInitTimers();
return status ;
}
// start a Timer for Session Keep Alives which sends a session keep alive
// on a connection if the timer value is not set to -1
//
if (NbtConfig.KeepAliveTimeout != -1)
{
status = StartTimer(SessionKeepAliveTimeout, // timer expiry routine
NbtConfig.KeepAliveTimeout,
NULL, // context value
NULL, // context2 value
NULL,
NULL,
NULL, // This timer is a global timer
&NbtConfig.pSessionKeepAliveTimer,
0,
FALSE);
if ( !NT_SUCCESS( status ) )
{
StopInitTimers();
return status ;
}
}
return(STATUS_SUCCESS);
}
//----------------------------------------------------------------------------
NTSTATUS
StopInitTimers(
VOID
)
/*++
Routine Description:
This is stops the timers started in InitTimerNotOS
Arguments:
Return Value:
NTSTATUS - The function value is the final status from the initialization
operation.
--*/
{
CTEPagedCode();
//
// If the timers have already been stopped, return success
//
if (!TimerQ.TimersInitialized)
{
return STATUS_SUCCESS;
}
//
// Set the TimersInitialized flag to FALSE
//
TimerQ.TimersInitialized = FALSE;
if (NbtConfig.pRefreshTimer)
{
StopTimer(NbtConfig.pRefreshTimer,NULL,NULL);
}
if (NbtConfig.pSessionKeepAliveTimer)
{
StopTimer(NbtConfig.pSessionKeepAliveTimer,NULL,NULL);
}
if (NbtConfig.pRemoteHashTimer)
{
StopTimer(NbtConfig.pRemoteHashTimer,NULL,NULL);
}
return(STATUS_SUCCESS);
}
WORD
NbtGetProductType(void)
{
RTL_OSVERSIONINFOEXW OsVer = { 0 };
NTSTATUS status = STATUS_SUCCESS;
PAGED_CODE();
OsVer.dwOSVersionInfoSize = sizeof(OsVer);
status = RtlGetVersion((PRTL_OSVERSIONINFOW)&OsVer);
if (!NT_SUCCESS(status)) {
return FALSE;
}
return OsVer.wProductType;
}
BOOL
IsDomainController(void)
/*++
Routine Description:
Return TRUE if this machine is a DC.
Arguments:
Return Value:
--*/
{
return (NbtGetProductType() == VER_NT_DOMAIN_CONTROLLER);
}
//----------------------------------------------------------------------------
VOID
ReadParameters(
IN tNBTCONFIG *pConfig,
IN HANDLE ParmHandle
)
/*++
Routine Description:
This routine is called to read various parameters from the parameters
section of the NBT section of the registry.
Arguments:
pConfig - A pointer to the configuration data structure.
ParmHandle - a handle to the parameters Key under Nbt
Return Value:
Status
--*/
{
ULONG NodeSize;
ULONG Refresh;
BOOL UseNewSmb;
CTEPagedCode();
ReadParameters2(pConfig, ParmHandle);
pConfig->NameServerPort = (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);
if (IsDomainController()) {
pConfig->InboundDgramNameCacheTtl = CTEReadSingleIntParameter(ParmHandle,
WS_INBOUND_DGRAM_NAME_CACHE_TIMEOUT,
DEFAULT_DC_INBOUND_DGRAM_NAME_CACHE_TIMEOUT,
MIN_INBOUND_DGRAM_NAME_CACHE_TIMEOUT);
} else {
pConfig->InboundDgramNameCacheTtl = CTEReadSingleIntParameter(ParmHandle,
WS_INBOUND_DGRAM_NAME_CACHE_TIMEOUT,
DEFAULT_INBOUND_DGRAM_NAME_CACHE_TIMEOUT,
MIN_INBOUND_DGRAM_NAME_CACHE_TIMEOUT);
}
{
CTESystemTime TimeValue;
CTEQuerySystemTime(TimeValue);
pConfig->RandomNumberSeed = RandomizeFromTime( TimeValue, 0x20000) ;
}
pConfig->MaxNumNameCached = CTEReadSingleIntParameter(ParmHandle,
WS_MAX_NUM_NAME_CACHE,
pConfig->InboundDgramNameCacheTtl / 3,
pConfig->InboundDgramNameCacheTtl / 20);
// 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);
UseNewSmb = (BOOLEAN) CTEReadSingleIntParameter(ParmHandle,
L"UseNewSmb",
0, // Disabled by default
0);
if (!UseNewSmb) {
pConfig->SMBDeviceEnabled = (BOOLEAN) CTEReadSingleIntParameter(ParmHandle,
WS_SMB_DEVICE_ENABLED,
1, // Enabled by default
0);
} else {
pConfig->SMBDeviceEnabled = FALSE;
}
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(NbtGetProductType()) {
case VER_NT_WORKSTATION:
NbtConfig.lMaxNumPendingNameQueries = 32;
break;
default:
NbtConfig.lMaxNumPendingNameQueries = 256;
break;
}
if (NodeType & PROXY) {
NbtConfig.lMaxNumPendingNameQueries *= 2;
}
NbtConfig.lMaxNumPendingNameQueries = CTEReadSingleIntParameter(
ParmHandle,
WS_PENDING_NAME_QUERIES_COUNT,
NbtConfig.lMaxNumPendingNameQueries,
MIN_NBT_NUM_PENDING_NAME_QUERIES
);
//
// "2" reflects the 2 timers: RefreshTimeout and RemoteHashTimeout
//
NbtConfig.lMaxNumTimersRunning = NbtConfig.lMaxNumPendingNameQueries + 2;
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;
#ifndef VXD
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;
#ifndef VXD
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;
#ifndef VXD
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