summaryrefslogtreecommitdiffstats
path: root/private/ntos/nbt/vxd
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nbt/vxd
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to '')
-rw-r--r--private/ntos/nbt/vxd.000/makefile37
-rw-r--r--private/ntos/nbt/vxd.000/makeres.bat5
-rw-r--r--private/ntos/nbt/vxd.000/vnbt.mk122
-rw-r--r--private/ntos/nbt/vxd/aaaaaaaa.c2
-rw-r--r--private/ntos/nbt/vxd/chic.c1787
-rw-r--r--private/ntos/nbt/vxd/chicasm.asm122
-rw-r--r--private/ntos/nbt/vxd/cinit.c930
-rw-r--r--private/ntos/nbt/vxd/client.asm427
-rw-r--r--private/ntos/nbt/vxd/ctimer.c237
-rw-r--r--private/ntos/nbt/vxd/cvxdfile.asm186
-rw-r--r--private/ntos/nbt/vxd/cxport.inc4
-rw-r--r--private/ntos/nbt/vxd/depend.mk1279
-rw-r--r--private/ntos/nbt/vxd/dns.c984
-rw-r--r--private/ntos/nbt/vxd/fileio.c476
-rw-r--r--private/ntos/nbt/vxd/limit.txt51
-rw-r--r--private/ntos/nbt/vxd/makefile28
-rw-r--r--private/ntos/nbt/vxd/nbtinfo.c227
-rw-r--r--private/ntos/nbt/vxd/ncb.c529
-rw-r--r--private/ntos/nbt/vxd/newdns.c1019
-rw-r--r--private/ntos/nbt/vxd/pageable.inc36
-rw-r--r--private/ntos/nbt/vxd/rules.mk4
-rw-r--r--private/ntos/nbt/vxd/tdiaddr.c184
-rw-r--r--private/ntos/nbt/vxd/tdicnct.c328
-rw-r--r--private/ntos/nbt/vxd/tdihndlr.c1719
-rw-r--r--private/ntos/nbt/vxd/tdiout.c601
-rw-r--r--private/ntos/nbt/vxd/util.c192
-rw-r--r--private/ntos/nbt/vxd/vfirst.asm79
-rw-r--r--private/ntos/nbt/vxd/vnbt.rcv15
-rw-r--r--private/ntos/nbt/vxd/vnbtd.asm993
-rw-r--r--private/ntos/nbt/vxd/vnbtd.def21
-rw-r--r--private/ntos/nbt/vxd/vnbtd.inc18
-rw-r--r--private/ntos/nbt/vxd/vnbtd.mk318
-rw-r--r--private/ntos/nbt/vxd/vxddebug.c659
-rw-r--r--private/ntos/nbt/vxd/vxdfile.asm314
-rw-r--r--private/ntos/nbt/vxd/vxdisol.c4042
-rw-r--r--private/ntos/nbt/vxd/vxdstub.asm250
-rw-r--r--private/ntos/nbt/vxd/wfw.c694
-rw-r--r--private/ntos/nbt/vxd/wfwasm.asm285
38 files changed, 19204 insertions, 0 deletions
diff --git a/private/ntos/nbt/vxd.000/makefile b/private/ntos/nbt/vxd.000/makefile
new file mode 100644
index 000000000..47ff1b557
--- /dev/null
+++ b/private/ntos/nbt/vxd.000/makefile
@@ -0,0 +1,37 @@
+#############################################################################
+#
+# Microsoft Confidential
+# Copyright (C) Microsoft Corporation 1995
+# All Rights Reserved.
+#
+# Makefile for VNBT directory
+#
+#############################################################################
+ROOT = $(BLDROOT)
+DEVICEDIR = NBT
+IS_32 = TRUE
+IS_PRIVATE = TRUE
+IS_SDK = TRUE
+IS_DDK = TRUE
+DIRLIST =
+COMMONMKFILE = VNBT.mk
+LIBS=vxdwraps.lib
+
+!include $(ROOT)\DEV\MASTER.MK
+
+disk:
+ copy debug\vnbt.vxd a:vnbt.VXD
+ copy debug\vnbt.sym a:
+
+#############################################################################
+#
+# Beginning of saved settings used by makemake. Do not edit between here
+# and the end of the file, except by deleting the entire section. Do not
+# delete the blank line that precedes this comment block.
+#
+# MAKE SURE TO DELETE EVERYTHING FROM HERE TO THE END OF THE MAKEFILE BEFORE
+# YOU CHECK IT IN. If you need to add more gunk, add it BEFORE this comment
+# block.
+#
+#
+#############################################################################
diff --git a/private/ntos/nbt/vxd.000/makeres.bat b/private/ntos/nbt/vxd.000/makeres.bat
new file mode 100644
index 000000000..8808af56c
--- /dev/null
+++ b/private/ntos/nbt/vxd.000/makeres.bat
@@ -0,0 +1,5 @@
+md debug
+md retail
+set INCLUDE=%BLDROOT%\dev\ddk\inc;%BLDROOT%\net\user\common\h
+%BLDROOT%\dev\sdk\bin\RC.exe -r -DDEBUG -fodebug\VNBT.res -i %BLDROOT%\dev\sdk\inc16 ..\vxd\vnbt.rcv
+%BLDROOT%\dev\sdk\bin\RC.exe -r -foretail\VNBT.res -i %BLDROOT%\dev\sdk\inc16 ..\vxd\vnbt.rcv
diff --git a/private/ntos/nbt/vxd.000/vnbt.mk b/private/ntos/nbt/vxd.000/vnbt.mk
new file mode 100644
index 000000000..ae531fed2
--- /dev/null
+++ b/private/ntos/nbt/vxd.000/vnbt.mk
@@ -0,0 +1,122 @@
+#############################################################################
+#
+# Microsoft Confidential
+# Copyright (C) Microsoft Corporation 1995
+# All Rights Reserved.
+#
+# Makefile for VNBT device
+#
+#############################################################################
+
+
+ROOT = $(BLDROOT)
+DHCP = $(BASEDIR)\private\net\sockets\tcpcmd\dhcp\client\vxd
+NTOS = $(BASEDIR)\private\NTOS
+
+!ifndef NBT
+NBT = ..\..
+!endif # NBT
+
+DEVICE = VNBT
+SRCDIR = $(NBT)\VXD
+ALTSRCDIR = $(NBT)\NBT
+NBTINC = $(NBT)\INC
+VXDINC = ..\INC
+
+DYNAMIC=TRUE
+IS_32 = TRUE
+IS_PRIVATE = TRUE
+IS_SDK = TRUE
+IS_DDK = TRUE
+MASM6 = TRUE
+WANT_MASM611C = TRUE
+WANT_C1032 = TRUE
+BUILD_COFF = TRUE
+DEPENDNAME = ..\depend.mk
+TARGETS = dev
+PROPBINS = $(386DIR)\VNBT.VXD $(SYMDIR)\VNBT.sym
+DEVDIR=$(ROOT)\DEV\DDK\INC
+COMMON=$(BLDROOT)\net\user\common
+PCHNAM=nbtprocs
+
+DEBUGFLAGS = -DDEBUG -DSAFE=4
+
+OBJS = aaaaaaaa.obj \
+ chic.obj \
+ chicasm.obj \
+ cinit.obj \
+ client.obj \
+ ctimer.obj \
+ cvxdfile.obj \
+ cxport.obj \
+ dns.obj \
+ fileio.obj \
+ hashtbl.obj \
+ hndlrs.obj \
+ inbound.obj \
+ init.obj \
+ name.obj \
+ namesrv.obj \
+ newdns.obj \
+ nbtinfo.obj \
+ nbtutils.obj \
+ ncb.obj \
+ parse.obj \
+ proxy.obj \
+ tdiaddr.obj \
+ tdicnct.obj \
+ tdihndlr.obj \
+ tdiout.obj \
+ timer.obj \
+ udpsend.obj \
+ util.obj \
+ vnbtd.obj \
+ vxddebug.obj \
+ vxdisol.obj
+
+AFLAGS = -c -DIS_32 -nologo -W2 -Cp -Cx -DMASM6 -DCHICAGO
+CFLAGS = -c -DVXD -Zp1 -GB -Oxs -nologo -D_X86_=1 -Di386=1 -DDEVL=1 -DPROXY_NODE -DCHICAGO
+CLEANLIST = $(SRCDIR)\cxport.asm $(PCHNAM).pch
+LOCALINCS = $(SRCDIR)\cxport.asm $(VXDINC)\nbtioctl.h \
+ $(VXDINC)\sockets\netinet\in.h $(VXDINC)\sys\snet\ip_proto.h \
+ $(BLDROOT)\dev\ddk\inc\vnbt.inc
+
+!include $(ROOT)\DEV\MASTER.MK
+
+CFLAGS = $(CFLAGS) -Yu$(PCHNAM).h -Fp$(PCHNAM).pch
+
+!IF "$(VERDIR)" == "retail"
+AFLAGS = $(AFLAGS) -DSAFE=0
+CFLAGS = $(CFLAGS) -DSAFE=0
+!ENDIF
+
+!IF "$(VERDIR)" == "debug"
+AFLAGS = $(AFLAGS) $(DEBUGFLAGS)
+CFLAGS = $(CFLAGS) $(DEBUGFLAGS)
+!ENDIF
+
+INCLUDE = $(SRCDIR)\..\CMN\H;$(SRCDIR)\.;$(COMMONHDIR);$(INCLUDE);
+
+.\aaaaaaaa.obj: $(SRCDIR)\aaaaaaaa.c
+ set CL=$(CFLAGS) -Yc$(PCHNAM).h
+ $(CL) -Fo$*.obj $(SRCDIR)\$*.c
+
+#
+# This is so we can get a full COFF build. TCP doesn't use
+# COFF .obj files yet. [ERH] 10-18-95
+#
+
+$(SRCDIR)\cxport.asm: $(TCP)\vtdi\cxport.asm $(TCP)\h\cxport.h
+ copy $(TCP)\vtdi\cxport.asm $(SRCDIR)\cxport.asm
+ touch $(SRCDIR)\cxport.asm
+
+$(VXDINC)\nbtioctl.h: $(BASEDIR)\private\inc\nbtioctl.h
+ copy $(BASEDIR)\private\inc\nbtioctl.h $(VXDINC)\nbtioctl.h
+
+$(VXDINC)\sockets\netinet\in.h: $(BASEDIR)\private\inc\sockets\netinet\in.h
+ copy $(BASEDIR)\private\inc\sockets\netinet\in.h $(VXDINC)\sockets\netinet\in.h
+
+$(VXDINC)\sys\snet\ip_proto.h: $(BASEDIR)\private\inc\sys\snet\ip_proto.h
+ copy $(BASEDIR)\private\inc\sys\snet\ip_proto.h $(VXDINC)\sys\snet\ip_proto.h
+
+INCLUDE = $(NBTINC);$(SRCDIR)\.;$(ALTSRCDIR)\.;$(COMMON)\H;$(TCP)\H;$(TCP)\INC;$(DHCP);$(NBT)\inc;$(VXDINC);$(INCLUDE)
diff --git a/private/ntos/nbt/vxd/aaaaaaaa.c b/private/ntos/nbt/vxd/aaaaaaaa.c
new file mode 100644
index 000000000..ff3201866
--- /dev/null
+++ b/private/ntos/nbt/vxd/aaaaaaaa.c
@@ -0,0 +1,2 @@
+
+#include "nbtprocs.h"
diff --git a/private/ntos/nbt/vxd/chic.c b/private/ntos/nbt/vxd/chic.c
new file mode 100644
index 000000000..af3fe87e6
--- /dev/null
+++ b/private/ntos/nbt/vxd/chic.c
@@ -0,0 +1,1787 @@
+/**********************************************************************/
+/** Microsoft Windows **/
+/** Copyright(c) Microsoft Corp., 1994 **/
+/**********************************************************************/
+
+/*
+
+ chic.c
+
+ Contains VxD code that is specific to Chicago
+
+
+ FILE HISTORY:
+ Johnl 14-Mar-1994 Created
+
+*/
+
+#include <nbtprocs.h>
+#include <tdiinfo.h>
+#include <llinfo.h>
+#include <ipinfo.h>
+#include <dhcpinfo.h>
+#include <nbtinfo.h>
+
+#ifdef CHICAGO
+
+//******************* Pageable Routine Declarations ****************
+//
+// any digit 0 to 9 and '.' are legal characters in an ipaddr
+//
+#define IS_IPADDR_CHAR( ch ) ( (ch >= '0' && ch <= '9') || (ch == '.') )
+
+#define MAX_ADAPTER_DESCRIPTION_LENGTH 128
+
+const char szXportName[] = "MSTCP";
+
+//
+// asking ndis to open,read,close for every single parameter slows down
+// bootup: don't open if it's already open
+//
+NDIS_HANDLE GlobalNdisHandle = NULL;
+
+//
+// This flag is set to TRUE when the first adapter is initialized. It
+// indicates that NBT globals (such as node type, scode ID etc) have
+// had the opportunity to be set by DHCP.
+//
+BOOL fGlobalsInitialized = FALSE;
+
+//
+// As each adapter gets added, the Lana offset is added
+//
+UCHAR iLanaOffset = 0;
+
+VOID GetMacAddr( ULONG IpAddress, UCHAR MacAddr[] );
+BOOL StopAllNameQueries( tDEVICECONTEXT *pDeviceContext );
+BOOL CancelAllDelayedEvents( tDEVICECONTEXT *pDeviceContext );
+extern tTIMERQ TimerQ;
+
+BOOL GetNdisParam( LPSTR pszKey,
+ ULONG * pVal,
+ NDIS_PARAMETER_TYPE ParameterType );
+
+
+//******************* Pageable Routine Declarations ****************
+#ifdef ALLOC_PRAGMA
+#pragma CTEMakePageable(PAGE, IPNotification)
+#pragma CTEMakePageable(PAGE, DestroyDeviceObject)
+#pragma CTEMakePageable(PAGE, SaveNameDnsServerAddrs)
+#pragma CTEMakePageable(PAGE, GetDnsServerAddress)
+#pragma CTEMakePageable(PAGE, GetNameServerAddress)
+#pragma CTEMakePageable(PAGE, GetMacAddr)
+#pragma CTEMakePageable(PAGE, VxdReadIniString)
+#pragma CTEMakePageable(PAGE, GetProfileInt)
+#pragma CTEMakePageable(PAGE, VxdOpenNdis)
+#pragma CTEMakePageable(PAGE, GetNdisParam)
+#pragma CTEMakePageable(PAGE, VxdCloseNdis)
+#pragma CTEMakePageable(PAGE, StopAllNameQueries)
+#pragma CTEMakePageable(PAGE, VxdUnload)
+#pragma CTEMakePageable(PAGE, ReleaseNbtConfigMem)
+#endif
+
+
+/*******************************************************************
+
+ NAME: IPNotification
+
+ SYNOPSIS: Called by the IP driver when a new Lana needs to be created
+ or destroyed for an IP address.
+
+ ENTRY: pDevNode - Plug'n'Play context
+ IpAddress - New ip address
+ IpMask - New ip mask
+ fNew - Are we creating or destroying this Lana?
+
+ NOTES: This routine is only used by Chicago
+
+ HISTORY:
+ Johnl 17-Mar-1994 Created
+
+********************************************************************/
+
+TDI_STATUS IPNotification( ULONG IpAddress,
+ ULONG IpMask,
+ PVOID pDevNode,
+ USHORT IPContext,
+ BOOL fNew )
+{
+ NTSTATUS status = STATUS_SUCCESS;
+ ULONG IpNS[COUNT_NS_ADDR];
+ ULONG IpDns[COUNT_NS_ADDR];
+ int iLana;
+ UCHAR RequestedLana;
+ int i;
+ int iEmpty;
+ UCHAR PreviousNodeType;
+ UCHAR MacAddr[6];
+
+ CTEPagedCode();
+
+ KdPrint(("IPNotification entered\r\n"));
+
+ if ( !IpAddress )
+ {
+ return TDI_SUCCESS ;
+ }
+
+ if ( fNew )
+ {
+ //
+ // parameters nodetype, scope and bcastaddr are systemwide, not per
+ // adapter: so read only once.
+ //
+ if ( !fGlobalsInitialized )
+ {
+ PreviousNodeType = NodeType;
+
+ //
+ // This will re-read the DHCPable parameters now that we have
+ // a potential DHCP source
+ //
+ VxdOpenNdis();
+ ReadParameters2( pNbtGlobConfig, NULL );
+ VxdCloseNdis();
+
+ if (PreviousNodeType & PROXY)
+ {
+ NodeType |= PROXY;
+ }
+
+
+ fGlobalsInitialized = TRUE;
+ }
+
+ //
+ // Get the name servers for this device context (ip address)
+ //
+ GetNameServerAddress( IpAddress, IpNS);
+
+ //
+ // Get the DNS servers for this device context (ip address)
+ //
+ GetDnsServerAddress( IpAddress, IpDns);
+
+ //
+ // Find a free spot in our Lana table
+ //
+
+ for ( iEmpty = 0; iEmpty < NBT_MAX_LANAS; iEmpty++)
+ {
+ if (LanaTable[iEmpty].pDeviceContext == NULL)
+ goto Found;
+ }
+
+ //
+ // Lana table is full so bail
+ //
+ CDbgPrint(DBGFLAG_ERROR,("IPNotification: LanaTable full\r\n"));
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+Found:
+
+ GetMacAddr( IpAddress, MacAddr );
+
+ status = CreateDeviceObject( pNbtGlobConfig,
+ htonl( IpAddress ),
+ htonl( IpMask ),
+ IpNS[0],
+ IpNS[1],
+ IpDns[0],
+ IpDns[1],
+ MacAddr,
+ 0 );
+ if (status != STATUS_SUCCESS)
+ {
+ CDbgPrint(DBGFLAG_ERROR,("IPNotification: CreateDeviceObject Failed\r\n"));
+ return status;
+ }
+
+ //
+ // We first try and ask for a specific Lana from vnetbios based on
+ // our Lanabase and how many other Lanas we've already added. If
+ // this fails, then we will ask for Any Lana. If the LANABASE
+ // parameter is not specified, then request Any Lana.
+ //
+
+ if ( LanaBase != VXD_ANY_LANA )
+ RequestedLana = LanaBase + iLanaOffset++ ;
+ else
+ RequestedLana = VXD_ANY_LANA;
+
+RetryRegister:
+ if ( (iLana = RegisterLana2( pDevNode, RequestedLana )) == 0xff )
+ {
+ if ( RequestedLana == VXD_ANY_LANA )
+ {
+ //
+ // We couldn't get *any* lanas so bail
+ //
+ CDbgPrint(DBGFLAG_ERROR,("IPNotification: RegisterLana2 Failed\r\n"));
+ DestroyDeviceObject( pNbtGlobConfig, htonl(IpAddress));
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ else
+ {
+ //
+ // Somebody may already have this Lana so beg for another one
+ //
+ RequestedLana = VXD_ANY_LANA;
+ goto RetryRegister;
+ }
+ }
+
+ KdPrint(("IPNotification: using Lana %d\r\n", iLana ));
+ LanaTable[iEmpty].pDeviceContext =
+ (tDEVICECONTEXT*)pNbtGlobConfig->DeviceContexts.Blink ;
+ LanaTable[iEmpty].pDeviceContext->iLana = iLana;
+
+ //
+ // remove our child (redir, that is!) and reenumerate our devnode
+ // so redir knows we are there!
+ //
+ ReconfigureDevnode( pDevNode );
+ }
+ else
+ {
+ status = DestroyDeviceObject( pNbtGlobConfig,
+ htonl(IpAddress) );
+
+ }
+
+ return status;
+}
+
+/*******************************************************************
+
+ NAME: DestroyDeviceObject
+
+ SYNOPSIS: Destroys the specified device
+
+ ENTRY: pConfig - Global config structure
+ IpAddr - Destroy the adapter with this address
+
+ NOTES: This routine is only used by Chicago
+
+ HISTORY:
+ Johnl 17-Mar-1994 Created
+
+********************************************************************/
+
+NTSTATUS DestroyDeviceObject(
+ tNBTCONFIG *pConfig,
+ ULONG IpAddr
+ )
+{
+ LIST_ENTRY * pEntry;
+ LIST_ENTRY * pHead;
+ tDEVICECONTEXT * pDeviceContext;
+ tDEVICECONTEXT * pTmpDeviceContext;
+ tDEVICECONTEXT * pNextDeviceContext;
+ tCLIENTELE * pClientEle;
+ tADDRESSELE * pAddress;
+ tNAMEADDR * pNameAddr;
+ tCONNECTELE * pConnEle;
+ tLOWERCONNECTION * pLowerConn;
+ PRCV_CONTEXT prcvCont;
+ tRCVELE * pRcvEle ;
+ tTIMERQENTRY * pTimer;
+ COMPLETIONCLIENT pClientCompletion;
+ PVOID Context;
+ tDGRAM_SEND_TRACKING * pTracker;
+ CTELockHandle OldIrq;
+ int i;
+
+
+ CTEPagedCode();
+
+ //
+ // Find which device is going away
+ // Also, find out a device object that is still active: we need that info
+ // to update some of the address ele's.
+ //
+ pDeviceContext = NULL;
+ pNextDeviceContext = NULL;
+
+ for ( pEntry = pConfig->DeviceContexts.Flink;
+ pEntry != &pConfig->DeviceContexts;
+ pEntry = pEntry->Flink )
+ {
+ pTmpDeviceContext = CONTAINING_RECORD( pEntry, tDEVICECONTEXT, Linkage);
+ if ( pTmpDeviceContext->IpAddress == IpAddr )
+ pDeviceContext = pTmpDeviceContext;
+ else
+ pNextDeviceContext = pTmpDeviceContext;
+ }
+
+ if (pDeviceContext == NULL)
+ return STATUS_INVALID_PARAMETER;
+
+ //
+ // don't accept anymore ncbs on this device
+ //
+ pDeviceContext->fDeviceUp = FALSE;
+
+ //
+ // Close all the connections
+ //
+ NbtNewDhcpAddress( pDeviceContext, 0, 0);
+
+ if ( --NbtConfig.AdapterCount == 1)
+ NbtConfig.MultiHomed = FALSE;
+
+ ASSERT(IsListEmpty(&pDeviceContext->LowerConnFreeHead));
+
+ //
+ // if we are destroying the last device then
+ //
+ if ( NbtConfig.AdapterCount == 0)
+ {
+ //
+ // Kill off all of the Receive any from any NCBs
+ //
+ while ( !IsListEmpty( &pDeviceContext->RcvAnyFromAnyHead ))
+ {
+ pEntry = RemoveHeadList( &pDeviceContext->RcvAnyFromAnyHead ) ;
+ prcvCont = CONTAINING_RECORD( pEntry, RCV_CONTEXT, ListEntry ) ;
+ ASSERT( prcvCont->Signature == RCVCONT_SIGN ) ;
+ CTEIoComplete( prcvCont->pNCB, STATUS_NETWORK_NAME_DELETED, 0 ) ;
+ }
+
+ //
+ // Kill off all of the Receive any datagrams from any
+ //
+ while ( !IsListEmpty(&pDeviceContext->RcvDGAnyFromAnyHead))
+ {
+ pEntry = RemoveHeadList( &pDeviceContext->RcvDGAnyFromAnyHead ) ;
+ pRcvEle = CONTAINING_RECORD( pEntry, tRCVELE, Linkage ) ;
+ CTEIoComplete( pRcvEle->pIrp, STATUS_NETWORK_NAME_DELETED, 0 ) ;
+ CTEMemFree( pRcvEle ) ;
+ }
+ }
+
+ //
+ // if any name queries are in progress, stop them now
+ //
+ StopAllNameQueries( pDeviceContext );
+
+ CancelAllDelayedEvents( pDeviceContext );
+
+ //
+ // walk through all names and see if any is being registered on this
+ // device context: if so, stop and complete it!
+ //
+ for (i=0;i < NbtConfig.pLocalHashTbl->lNumBuckets ;i++ )
+ {
+ pHead = &NbtConfig.pLocalHashTbl->Bucket[i];
+ pEntry = pHead->Flink;
+ while (pEntry != pHead)
+ {
+ pNameAddr = CONTAINING_RECORD(pEntry,tNAMEADDR,Linkage);
+ pEntry = pEntry->Flink;
+
+ if (pNameAddr->NameTypeState & STATE_RESOLVING)
+ {
+ pTimer = pNameAddr->pTimer;
+
+ //
+ // if the name registration was started for this name on this device
+ // context, stop the timer. (Completion routine will take care of
+ // doing registration on other device contexts if applicable)
+ //
+ if (pTimer)
+ {
+ pTracker = pTimer->Context;
+ ASSERT(pTracker->pDeviceContext->Verify == NBT_VERIFY_DEVCONTEXT);
+ if (pTracker->pDeviceContext == pDeviceContext)
+ {
+ ASSERT(pTracker->pNameAddr == pNameAddr)
+
+ pNameAddr->pTimer = NULL;
+
+ CTESpinLock(&NbtConfig.JointLock,OldIrq);
+ StopTimer(pTimer,&pClientCompletion,&Context);
+ CTESpinFree(&NbtConfig.JointLock,OldIrq);
+
+ if (pClientCompletion)
+ {
+ (*pClientCompletion)(Context,STATUS_NETWORK_NAME_DELETED);
+ }
+
+ DbgPrint("DestroyDeviceObject: stopped name reg timer") ;
+ }
+ }
+
+ }
+ }
+ }
+
+
+ //
+ // walk through all the client ele's this device context has and clean
+ // up all the mess this clientele created!
+ //
+ for ( i = 0 ; i <= pDeviceContext->cMaxNames ; i++ )
+ {
+ pClientEle = pDeviceContext->pNameTable[i];
+
+ if ( !pClientEle )
+ continue;
+
+ VxdCleanupAddress( pDeviceContext,
+ NULL,
+ pClientEle,
+ (UCHAR)i,
+ TRUE );
+ }
+
+ //
+ // close all the TDI handles
+ //
+ CloseAddressesWithTransport(pDeviceContext);
+
+ //
+ // if a call was started, but aborted then we could have some memory here!
+ //
+ while (!IsListEmpty(&pDeviceContext->UpConnectionInUse))
+ {
+ pEntry = RemoveHeadList(&pDeviceContext->UpConnectionInUse);
+ pConnEle = CONTAINING_RECORD(pEntry,tCONNECTELE,Linkage);
+ CTEMemFree( pConnEle );
+ }
+
+ while (!IsListEmpty(&pDeviceContext->LowerConnection))
+ {
+ pEntry = RemoveHeadList(&pDeviceContext->LowerConnection);
+ pLowerConn = CONTAINING_RECORD(pEntry,tLOWERCONNECTION,Linkage);
+ CTEMemFree( pLowerConn );
+ }
+
+ //
+ // Remove the device from our Lana table and Vnetbios
+ //
+ for ( i = 0; i < NBT_MAX_LANAS; i++)
+ {
+ if (LanaTable[i].pDeviceContext == pDeviceContext)
+ {
+ DeregisterLana(LanaTable[i].pDeviceContext->iLana);
+ LanaTable[i].pDeviceContext = NULL;
+ KdPrint(("DestroyDeviceObject: deregistered Lana %d\r\n",pDeviceContext->iLana));
+ break;
+ }
+ }
+
+ RemoveEntryList( &pDeviceContext->Linkage);
+
+ //
+ // Walk through the AddressHead list. If any addresses exist and they
+ // point to old device context, put the next device context. Also, update
+ // adapter mask to reflect that this device context is now gone.
+ //
+ KdPrint(("DestroyDeviceObject: setting AddrEle,NameAddr fields\r\n"));
+ pHead = pEntry = &NbtConfig.AddressHead;
+ while ((pEntry = pEntry->Flink) != pHead)
+ {
+ pAddress = CONTAINING_RECORD(pEntry,tADDRESSELE,Linkage);
+ ASSERT (pAddress->Verify == NBT_VERIFY_ADDRESS);
+ if (pAddress->pDeviceContext == pDeviceContext)
+ {
+ pAddress->pDeviceContext = pNextDeviceContext;
+ }
+
+ pAddress->pNameAddr->AdapterMask &= ~pDeviceContext->AdapterNumber;
+ }
+
+ if (pDeviceContext->pNameTable)
+ CTEMemFree( pDeviceContext->pNameTable );
+
+ if (pDeviceContext->pSessionTable)
+ CTEMemFree( pDeviceContext->pSessionTable );
+
+ CTEMemFree( pDeviceContext );
+
+ return STATUS_SUCCESS;
+}
+
+
+/*******************************************************************
+
+ NAME: SaveNameDnsServerAddrs
+
+ SYNOPSIS: Get the name server and dns server addrs from the registry
+ and save it in Nbtconfig. We do this so that when a new
+ adapter comes in or lease gets renewed (particularly the
+ latter), we don't have to go read the registry becuase it
+ may not be safe to do so.
+ This routine will have to be modified if setup ever changes
+ to allow configuration of name/dns servers per lana.
+
+ ENTRY: Nothing
+
+
+ HISTORY:
+ Koti 20-Nov-1994 Created
+
+********************************************************************/
+
+VOID SaveNameDnsServerAddrs( VOID )
+{
+ UCHAR i ;
+ PUCHAR pchSrv = "NameServer$" ;
+ PUCHAR pchDnsSrv = "NameServer" ;
+ PUCHAR pchSrvNum;
+ LPTSTR pchString ;
+ PUCHAR pchCurrent, pchNext;
+ BOOL fOneMore=TRUE;
+ ULONG IpNameServers[COUNT_NS_ADDR];
+
+ CTEPagedCode();
+
+ //
+ // Get Name Server ipaddrs
+ //
+
+ pchSrvNum = pchSrv + 10 ; // to overwrite '$' with 1,2,3 etc.
+
+ for ( i = 0; i < COUNT_NS_ADDR; i++)
+ {
+ IpNameServers[i] = LOOP_BACK;;
+ *pchSrvNum = '1' + i;
+
+ // call GetNdisParam directly so that we don't query dhcp here
+ // if ( !CTEReadIniString( NULL, pchSrv, &pchString ) )
+ //
+ if ( GetNdisParam( pchSrv, (ULONG *)&pchString, NdisParameterString ) )
+ {
+ if ( ConvertDottedDecimalToUlong( pchString, &IpNameServers[i] ))
+ {
+ DbgPrint("SaveNameDnsServerAddrs: bad name srv addr\r\n") ;
+ IpNameServers[i] = LOOP_BACK;
+ }
+ CTEFreeMem( pchString ) ;
+ }
+ }
+
+ //
+ // store the name server ipaddrs (potentially 0 if not defined in registry)
+ //
+ NbtConfig.lRegistryNameServerAddress = IpNameServers[0];
+ NbtConfig.lRegistryBackupServer = IpNameServers[1];
+
+
+ //
+ // Now get Dns Server ipaddrs
+ //
+
+ //
+ // initialize all of them to worst case
+ //
+ for ( i = 0; i < COUNT_NS_ADDR; i++)
+ {
+ IpNameServers[i] = LOOP_BACK;
+ }
+
+
+ // call GetNdisParam directly so that we don't query dhcp here
+ // if ( !CTEReadIniString( NULL, pchDnsSrv, &pchString ) )
+ //
+ if ( GetNdisParam( pchDnsSrv, (ULONG *)&pchString, NdisParameterString ) )
+ {
+ //
+ // we are generating (upto) COUNT_NS_ADDR pointers each pointing to
+ // one ipaddr. The string in system.ini looks like:
+ // NameServer = 11.101.4.26,200.200.200.200,1.2.3.4,1.91.245.10
+ //
+ pchNext = pchCurrent = pchString;
+
+ if ( IS_IPADDR_CHAR(*pchCurrent) ) // make sure at least one ipaddr defnd
+ {
+ i = 0;
+ while( (i < COUNT_NS_ADDR) && fOneMore )
+ {
+ while( IS_IPADDR_CHAR(*pchNext) )
+ pchNext++;
+
+ if ( *pchNext == ',' ) // ',' is the separator between 2 addrs
+ {
+ *pchNext = '\0';
+ pchNext++;
+ }
+ else
+ {
+ fOneMore = FALSE; // reached end of line
+ }
+
+ //
+ // as long as at least the first one ipaddr gets converted properly,
+ // ignore errors in others
+ //
+ if ( ConvertDottedDecimalToUlong( pchCurrent, &IpNameServers[i] ))
+ {
+ DbgPrint("SaveNameDnsServerAddrs: bad dns srv addr\r\n") ;
+ IpNameServers[i] = LOOP_BACK;
+ }
+
+ i++;
+
+ pchCurrent = pchNext; // go, convert the next one
+ }
+ }
+
+ if( pchString != NULL )
+ {
+ CTEFreeMem( pchString ) ;
+ }
+ }
+
+ //
+ // store the dns server ipaddrs (potentially 0 if not defined in registry)
+ //
+ NbtConfig.lRegistryDnsServerAddress = IpNameServers[0];
+ NbtConfig.lRegistryDnsBackupServer = IpNameServers[1];
+
+}
+
+
+/*******************************************************************
+
+ NAME: GetDnsServerAddress
+
+ SYNOPSIS: Gets the DNS server ipaddrs from the registry.
+ Or, if DHCP is installed and the DNS server addresses aren't
+ found, we get them from DHCP
+
+ ENTRY: IpAddr - If we can get from DHCP, get form this address
+ pIpDnsServer - Receives addresses if found (otherwise 0)
+
+ NOTES: This routine is only used by Snowball
+
+ HISTORY:
+ Koti 18-Oct-1994 Created
+
+********************************************************************/
+
+void GetDnsServerAddress( ULONG IpAddr, PULONG pIpDnsServer)
+{
+
+ UCHAR i ;
+ UINT OptId;
+ TDI_STATUS tdistatus ;
+ ULONG Buff[COUNT_NS_ADDR] ;
+ ULONG Size;
+
+ CTEPagedCode();
+
+
+ for ( i = 0; i < COUNT_NS_ADDR; i++)
+ {
+ pIpDnsServer[i] = LOOP_BACK ;
+ }
+
+ pIpDnsServer[0] = NbtConfig.lRegistryDnsServerAddress;
+ pIpDnsServer[1] = NbtConfig.lRegistryDnsBackupServer;
+
+ //
+ // if it was defined in the registry, we are done
+ //
+ if ( pIpDnsServer[0] != LOOP_BACK || pIpDnsServer[1] != LOOP_BACK )
+ {
+ return;
+ }
+
+ //
+ // it was not defined in the registry: try getting them from DHCP
+ //
+ Size = sizeof( Buff ) ;
+
+ OptId = 6; // DNS Option
+
+ tdistatus = DhcpQueryOption( IpAddr,
+ OptId,
+ &Buff,
+ &Size ) ;
+
+ switch ( tdistatus )
+ {
+ case TDI_SUCCESS:
+ case TDI_BUFFER_OVERFLOW: // May be more then one our buffer will hold
+ for ( i = 0; i < COUNT_NS_ADDR; i++ )
+ {
+ if ( Size >= (sizeof(ULONG)*(i+1)))
+ pIpDnsServer[i] = htonl(Buff[i]) ;
+ }
+ break ;
+
+ case TDI_INVALID_PARAMETER: // Option not found
+ break;
+
+ default:
+ ASSERT( FALSE ) ;
+ break ;
+ }
+
+ KdPrint(("GetDnsServerAddress: Primary: %x, backup: %x\r\n",
+ pIpDnsServer[0], pIpDnsServer[1] )) ;
+
+}
+
+
+/*******************************************************************
+
+ NAME: GetNameServerAddress
+
+ SYNOPSIS: Gets the Win server for the specified Lana.
+
+ Or, if DHCP is installed and the Name server addresses aren't
+ found, we get them from DHCP
+
+ ENTRY: IpAddr - If we can get from DHCP, get form this address
+ pIpNameServer - Receives addresses if found (otherwise 0)
+
+ NOTES: This routine is only used by Snowball
+
+ HISTORY:
+ Johnl 21-Oct-1993 Created
+
+********************************************************************/
+
+void GetNameServerAddress( ULONG IpAddr,
+ PULONG pIpNameServer)
+{
+ UCHAR i ;
+ UINT OptId;
+ TDI_STATUS tdistatus ;
+ ULONG Buff[COUNT_NS_ADDR] ;
+ ULONG Size;
+
+ CTEPagedCode();
+
+
+ for ( i = 0; i < COUNT_NS_ADDR; i++)
+ {
+ pIpNameServer[i] = LOOP_BACK ;
+ }
+
+ pIpNameServer[0] = NbtConfig.lRegistryNameServerAddress;
+ pIpNameServer[1] = NbtConfig.lRegistryBackupServer;
+
+ //
+ // if it was defined in the registry, we are done
+ //
+ if ( pIpNameServer[0] != LOOP_BACK || pIpNameServer[1] != LOOP_BACK )
+ {
+ return;
+ }
+
+
+ //
+ // not defined in the registry: try to get it from dhcp
+ //
+
+ OptId = 44; // NBNS Option
+
+ Size = sizeof( Buff ) ;
+
+ tdistatus = DhcpQueryOption( IpAddr,
+ OptId,
+ &Buff,
+ &Size ) ;
+
+ switch ( tdistatus )
+ {
+ case TDI_SUCCESS:
+ case TDI_BUFFER_OVERFLOW: // May be more then one our buffer will hold
+ for ( i = 0; i < COUNT_NS_ADDR; i++ )
+ {
+ if ( Size >= (sizeof(ULONG)*(i+1)))
+ pIpNameServer[i] = htonl(Buff[i]) ;
+ }
+ break ;
+
+ case TDI_INVALID_PARAMETER: // Option not found
+ break ;
+
+ default:
+ ASSERT( FALSE ) ;
+ break ;
+ }
+
+ KdPrint(("GetNameServerAddress: Primary: %x, backup: %x\r\n",
+ pIpNameServer[0], pIpNameServer[1] )) ;
+
+}
+
+
+/*******************************************************************
+
+ NAME: GetMacAddr
+
+ SYNOPSIS: Gets the mac address for the give ipaddr
+
+ ENTRY: IpAddress - the address for which to find mac addr
+ MacAddr - the array where to store mac addr
+
+ HISTORY:
+ Koti 19-Oct-1994 Created
+
+********************************************************************/
+
+VOID GetMacAddr( ULONG IpAddress, UCHAR MacAddr[] )
+{
+
+ TDI_STATUS tdistatus ;
+ int i, j, k ;
+ uchar Context[CONTEXT_SIZE] ;
+ TDIObjectID ID ;
+ TDIEntityID EList[MAX_TDI_ENTITIES] ;
+ ULONG Size ;
+ UINT NumReturned ;
+ NDIS_BUFFER ndisbuff ;
+ IFEntry *ifeAdapterInfo[MAX_TDI_ENTITIES];
+ UINT AdptNum;
+
+ CTEPagedCode();
+
+
+ //
+ // initialize to 0, in case things don't work out
+ //
+ memset( MacAddr, 0, 6 ) ;
+
+ //
+ // The first thing to do is get the list of available entities, and make
+ // sure that there are some interface entities present.
+ //
+ ID.toi_entity.tei_entity = GENERIC_ENTITY;
+ ID.toi_entity.tei_instance = 0;
+ ID.toi_class = INFO_CLASS_GENERIC;
+ ID.toi_type = INFO_TYPE_PROVIDER;
+ ID.toi_id = ENTITY_LIST_ID;
+
+ Size = sizeof(EList);
+ InitNDISBuff( &ndisbuff, &EList, Size, NULL ) ;
+ memset(Context, 0, CONTEXT_SIZE);
+
+ tdistatus = TdiVxdQueryInformationEx( 0,
+ &ID,
+ &ndisbuff,
+ &Size,
+ Context);
+
+ if (tdistatus != TDI_SUCCESS)
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "GetMacAddr: Querying entity list failed\r\n")) ;
+ return;
+ }
+
+ NumReturned = (uint)Size/sizeof(TDIEntityID);
+
+ AdptNum = 0;
+ //
+ // first find out info about the adapters
+ //
+ for (i = 0; i < NumReturned; i++)
+ {
+ //
+ // if this entity/instance describes an adapter
+ //
+ if ( EList[i].tei_entity == IF_ENTITY )
+ {
+ DWORD isMib;
+
+
+ ID.toi_entity.tei_entity = EList[i].tei_entity ;
+ ID.toi_entity.tei_instance = EList[i].tei_instance;
+ ID.toi_class = INFO_CLASS_GENERIC ;
+ ID.toi_type = INFO_TYPE_PROVIDER;
+ ID.toi_id = ENTITY_TYPE_ID ;
+
+ Size = sizeof( isMib );
+ InitNDISBuff( &ndisbuff, &isMib, Size, NULL ) ;
+ memset(Context, 0, CONTEXT_SIZE);
+ tdistatus = TdiVxdQueryInformationEx( 0,
+ &ID,
+ &ndisbuff,
+ &Size,
+ Context);
+ if ( tdistatus != TDI_SUCCESS )
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "GetMacAddr: Getting isMib failed\r\n")) ;
+ return ;
+ }
+
+ //
+ // Does this entity support MIB
+ //
+ if (isMib != IF_MIB)
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "GetMacAddr: skipping non-MIB entity\r\n")) ;
+ continue;
+ }
+
+ //
+ // MIB requests supported - query the adapter info
+ //
+
+ Size = sizeof(IFEntry) + MAX_ADAPTER_DESCRIPTION_LENGTH + 1;
+
+ ifeAdapterInfo[AdptNum] = (IFEntry *)CTEAllocInitMem(Size);
+
+ if ( ifeAdapterInfo[AdptNum] == NULL )
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "GetMacAddr: Couldn't allocate AdapterInfo buffer\r\n")) ;
+ for ( k=0; k<AdptNum; k++ )
+ {
+ CTEFreeMem( ifeAdapterInfo[k] ) ;
+ }
+ return;
+ }
+
+ ID.toi_class = INFO_CLASS_PROTOCOL;;
+ ID.toi_id = IF_MIB_STATS_ID;
+
+ Size = sizeof(IFEntry) + MAX_ADAPTER_DESCRIPTION_LENGTH + 1;
+ InitNDISBuff( &ndisbuff, ifeAdapterInfo[AdptNum], Size, NULL ) ;
+ memset(Context, 0, CONTEXT_SIZE);
+ tdistatus = TdiVxdQueryInformationEx( 0,
+ &ID,
+ &ndisbuff,
+ &Size,
+ Context);
+ if ( tdistatus != TDI_SUCCESS )
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "GetMacAddr: Getting IF type failed\r\n")) ;
+ for ( k=0; k<AdptNum; k++ )
+ {
+ CTEFreeMem( ifeAdapterInfo[k] ) ;
+ }
+ return ;
+ }
+
+ AdptNum++;
+ }
+ }
+
+ //
+ // now that we know about the adapters, get the ipaddrs
+ //
+ for (i = 0; i < NumReturned; i++)
+ {
+ if ( EList[i].tei_entity == CL_NL_ENTITY )
+ {
+ IPSNMPInfo IPStats ;
+ IPAddrEntry * pIAE ;
+ ULONG NLType ;
+ ULONG IpNameServer[COUNT_NS_ADDR];
+ ULONG IpDnsServer[COUNT_NS_ADDR];
+
+ //
+ // Does this entity support IP?
+ //
+
+ ID.toi_entity.tei_entity = EList[i].tei_entity ;
+ ID.toi_entity.tei_instance = EList[i].tei_instance;
+ ID.toi_class = INFO_CLASS_GENERIC ;
+ ID.toi_type = INFO_TYPE_PROVIDER;
+ ID.toi_id = ENTITY_TYPE_ID ;
+
+ Size = sizeof( NLType );
+ InitNDISBuff( &ndisbuff, &NLType, Size, NULL ) ;
+ memset(Context, 0, CONTEXT_SIZE);
+ tdistatus = TdiVxdQueryInformationEx( 0,
+ &ID,
+ &ndisbuff,
+ &Size,
+ Context);
+ if ( tdistatus != TDI_SUCCESS )
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "GetMacAddr: Getting NL type failed\r\n")) ;
+ for ( k=0; k<AdptNum; k++ )
+ {
+ CTEFreeMem( ifeAdapterInfo[k] ) ;
+ }
+ return ;
+ }
+
+ if ( NLType != CL_NL_IP )
+ continue ;
+
+ //
+ // We've got an IP driver so get it's address table
+ //
+
+ ID.toi_class = INFO_CLASS_PROTOCOL ;
+ ID.toi_id = IP_MIB_STATS_ID;
+ Size = sizeof(IPStats);
+ InitNDISBuff( &ndisbuff, &IPStats, Size, NULL ) ;
+ memset(Context, 0, CONTEXT_SIZE);
+ tdistatus = TdiVxdQueryInformationEx( 0,
+ &ID,
+ &ndisbuff,
+ &Size,
+ Context);
+ if ( tdistatus != TDI_SUCCESS )
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "GetMacAddr: Getting IPStats failed\r\n")) ;
+ continue ;
+ }
+
+ if ( IPStats.ipsi_numaddr < 1 )
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "GetMacAddr: No IP Addresses installed\r\n")) ;
+ continue ;
+ }
+
+ Size = sizeof(IPAddrEntry) * IPStats.ipsi_numaddr ;
+ if ( !(pIAE = (IPAddrEntry*) CTEAllocInitMem( Size )) )
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "GetMacAddr: Couldn't allocate IP table buffer\r\n")) ;
+ continue ;
+ }
+
+ ID.toi_id = IP_MIB_ADDRTABLE_ENTRY_ID ;
+ InitNDISBuff( &ndisbuff, pIAE, Size, NULL ) ;
+ memset( Context, 0, CONTEXT_SIZE ) ;
+ tdistatus = TdiVxdQueryInformationEx( 0,
+ &ID,
+ &ndisbuff,
+ &Size,
+ Context);
+ if ( tdistatus != TDI_SUCCESS )
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "GetMacAddr: Getting IP address table failed\r\n")) ;
+ CTEFreeMem( pIAE ) ;
+ continue ;
+ }
+
+ // ASSERT( Size/sizeof(IPAddrEntry) >= IPStats.ipsi_numaddr ) ;
+
+ //
+ // We have the IP address table for this IP driver. Look for
+ // our IP address
+ //
+
+ for ( j = 0 ; j < IPStats.ipsi_numaddr ; j++ )
+ {
+ //
+ // find our ipaddress
+ //
+ if ( pIAE[j].iae_addr != IpAddress )
+ {
+ continue ;
+ }
+
+ //
+ // now find out the mac address for this ipaddr
+ //
+ for ( k=0; k<AdptNum; k++ )
+ {
+ if ( ifeAdapterInfo[k]->if_index == pIAE[j].iae_index )
+ {
+ CTEMemCopy( MacAddr, ifeAdapterInfo[k]->if_physaddr, 6 );
+ break;
+ }
+ }
+ }
+
+ if (pIAE)
+ {
+ CTEFreeMem( pIAE ) ;
+ }
+ }
+ }
+
+ for ( k=0; k<AdptNum; k++ )
+ {
+ CTEFreeMem( ifeAdapterInfo[k] ) ;
+ }
+
+}
+
+
+/*******************************************************************
+
+ NAME: VxdReadIniString
+
+ SYNOPSIS: Vxd stub for CTEReadIniString
+
+ ENTRY: pchKey - Key value to look for in the NBT section
+ ppchString - Pointer to buffer found string is returned in
+
+ EXIT: ppchString will point to an allocated buffer
+
+ RETURNS: STATUS_SUCCESS if found
+
+ NOTES: The client must free ppchString when done with it
+
+ HISTORY:
+ Johnl 30-Aug-1993 Created
+
+********************************************************************/
+
+NTSTATUS VxdReadIniString( LPSTR pchKey, LPSTR * ppchString )
+{
+ CTEPagedCode();
+
+ if ( GetNdisParam( pchKey, (ULONG *)ppchString, NdisParameterString ) )
+ {
+ return STATUS_SUCCESS ;
+ }
+ else
+ {
+ //
+ // Does DHCP have it?
+ //
+
+ if ( *ppchString = (char *) GetDhcpOption( pchKey, 0 ) )
+ {
+ return STATUS_SUCCESS ;
+ }
+ }
+
+ return STATUS_UNSUCCESSFUL ;
+}
+
+/*******************************************************************
+
+ NAME: GetProfileInt
+
+ SYNOPSIS: Gets the specified value from the registry or DHCP
+
+ ENTRY: pchKey - Key value to look for in the NBT section
+ Default - Default value if not in registry or DHCP
+ Min - Minimum value can be
+
+ RETURNS: Registry Value or Dhcp value or default value
+
+ NOTES:
+
+ HISTORY:
+ Johnl 23-Mar-1994 Created
+
+********************************************************************/
+
+ULONG GetProfileInt( PVOID p, LPSTR pchKey, ULONG Default, ULONG Min )
+{
+ ULONG Val = Default;
+
+ CTEPagedCode();
+
+ //
+ // Is the value in the registry?
+ //
+ if ( !GetNdisParam( pchKey, &Val, NdisParameterInteger ) )
+ {
+ //
+ // No, Check DHCP
+ //
+ Val = GetDhcpOption( pchKey, Default );
+ }
+
+ if ( Val < Min )
+ {
+ Val = Min;
+ }
+
+ return Val;
+}
+
+ULONG GetProfileHex( PVOID p, LPSTR pchKey, ULONG Default, ULONG Min )
+{
+ return GetProfileInt( p, pchKey, Default, Min);
+}
+
+/*******************************************************************
+
+ NAME: VxdOpenNdis
+
+ SYNOPSIS: Prepare Ndis to read entries from the registry. Ndis
+ basically opens the registry and gives a handle back
+ which we store in GlobalNdisHandle.
+
+ ENTRY: Nothing (GlobalNdisHandle is global)
+ RETURNS: TRUE if things worked well
+ FALSE if some error occured
+
+ HISTORY:
+ Koti Nov. 20, 94
+
+********************************************************************/
+
+BOOL VxdOpenNdis( VOID )
+{
+
+ NDIS_STATUS Status;
+ NDIS_STRING Name;
+
+ CTEPagedCode();
+
+
+ ASSERT( !GlobalNdisHandle );
+
+ // Open the config information.
+ Name.Length = strlen(szXportName) + 1;
+ Name.MaximumLength = Name.Length;
+ Name.Buffer = (PUCHAR)szXportName;
+
+ NdisOpenProtocolConfiguration(&Status, &GlobalNdisHandle, &Name);
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ // Unable to open the configuration. Fail now.
+ GlobalNdisHandle = NULL;
+ ASSERT(0);
+ return FALSE;
+ }
+
+ return TRUE;
+
+}
+/*******************************************************************
+
+ NAME: GetNdisParam
+
+ SYNOPSIS: Gets the value from the MSTCP protocol sectio of the registry
+
+ ENTRY: pchKey - Key value to look for in the NBT section
+ pVal - Retrieved parameter
+ ParameterType - Type of parameter (string, int)
+
+ RETURNS: TRUE if the value was found, FALSE otherwise
+
+ NOTES: If the parameter is a string parameter, then this routine
+ will allocate memory which the client is responsible for
+ freeing.
+
+ HISTORY:
+ Johnl 23-Mar-1994 Created
+
+********************************************************************/
+
+BOOL GetNdisParam( LPSTR pszKey,
+ ULONG * pVal,
+ NDIS_PARAMETER_TYPE ParameterType )
+{
+ NDIS_STATUS Status;
+ NDIS_STRING Name;
+ uint i;
+ PNDIS_CONFIGURATION_PARAMETER Param;
+ BOOL fRet = FALSE;
+
+ CTEPagedCode();
+
+
+ ASSERT( GlobalNdisHandle );
+
+ Name.Length = strlen(pszKey) + 1;
+ Name.MaximumLength = Name.Length;
+ Name.Buffer = pszKey;
+ NdisReadConfiguration(&Status, &Param, GlobalNdisHandle, &Name,
+ ParameterType);
+
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ if ( ParameterType == NdisParameterString)
+ {
+ LPSTR lpstr = CTEAllocInitMem( Param->ParameterData.StringData.Length + 1 ) ;
+
+ if ( lpstr )
+ {
+ strcpy( lpstr, Param->ParameterData.StringData.Buffer );
+ *pVal = (ULONG) lpstr;
+ fRet = TRUE;
+ }
+ }
+ else
+ {
+ *pVal = Param->ParameterData.IntegerData;
+ fRet = TRUE;
+ }
+ }
+
+ return fRet ;
+}
+
+/*******************************************************************
+
+ NAME: VxdCloseNdis
+
+ SYNOPSIS: Close the handle that we opened in VxdOpenNdis
+
+ ENTRY: Nothing (GlobalNdisHandle is global)
+
+ HISTORY:
+ Koti Nov. 20, 94
+
+********************************************************************/
+
+VOID VxdCloseNdis( VOID )
+{
+
+ CTEPagedCode();
+
+ ASSERT(GlobalNdisHandle);
+
+ if (GlobalNdisHandle != NULL)
+ {
+ NdisCloseConfiguration(GlobalNdisHandle);
+ GlobalNdisHandle = NULL;
+ }
+}
+
+
+/*******************************************************************
+
+ NAME: StopAllNameQueries
+
+ SYNOPSIS: This routine is called when the device context is going
+ away. It finds out all the name queries that are in
+ progress (started by someone on this device context) and
+ stops them.
+
+ ENTRY: pDeviceContext - the device context that is going away.
+
+ RETURNS: TRUE if at least one name query was found and stopped
+ FALSE if there wasn't any query in progress
+
+ HISTORY:
+ Koti Nov. 19, 94
+
+********************************************************************/
+
+BOOL
+StopAllNameQueries( tDEVICECONTEXT *pDeviceContext )
+{
+
+ tDGRAM_SEND_TRACKING *pTracker;
+ NBT_WORK_ITEM_CONTEXT *Context;
+ PVOID pClientCompletion;
+ PVOID pClientContext;
+ tNAMEADDR *pNameAddr;
+ tTIMERQENTRY *pTimer;
+ PLIST_ENTRY pHead;
+ PLIST_ENTRY pEntry;
+ CTELockHandle OldIrq;
+
+ CTEPagedCode();
+
+ //
+ // first check to see if any names are on the pending list: all name
+ // queries over the network will be here (WINS, broadcast, DNS)
+ //
+ CTESpinLock(&NbtConfig.JointLock,OldIrq);
+
+ pHead = &NbtConfig.PendingNameQueries;
+ pEntry = pHead->Flink;
+ while (pEntry != pHead)
+ {
+ pNameAddr = CONTAINING_RECORD(pEntry,tNAMEADDR,Linkage);
+
+ pEntry = pEntry->Flink;
+
+ pTimer = pNameAddr->pTimer;
+ if (pTimer)
+ {
+ pTracker = (tDGRAM_SEND_TRACKING *)pTimer->Context;
+
+ ASSERT (pTracker->pDeviceContext->Verify == NBT_VERIFY_DEVCONTEXT);
+
+ if (pTracker->pDeviceContext == pDeviceContext)
+ {
+ StopTimer(pTimer,(COMPLETIONCLIENT *)&pClientCompletion,&Context);
+ if (pClientCompletion)
+ {
+ //
+ // Remove from the pending list
+ //
+ RemoveEntryList(&pNameAddr->Linkage);
+ InitializeListHead(&pNameAddr->Linkage);
+
+ pNameAddr->pTimer = NULL;
+ NbtDereferenceName(pNameAddr);
+
+ //
+ // complete client's ncb. If requests were queued on
+ // the same name by other clients, this will start new
+ // name queries for those clients
+ //
+ CTESpinFree(&NbtConfig.JointLock,OldIrq);
+ CompleteClientReq(pClientCompletion,
+ (tDGRAM_SEND_TRACKING *)Context,
+ STATUS_NETWORK_NAME_DELETED);
+ CTESpinLock(&NbtConfig.JointLock,OldIrq);
+ DbgPrint("StopAllNameQueries: stopped net name query") ;
+ }
+ }
+ }
+ }
+
+ CTESpinFree(&NbtConfig.JointLock,OldIrq);
+
+ //
+ // now check if any names are on the lmhosts queue: all name queries
+ // waiting for lmhosts (and/or hosts) parsing will be here
+ //
+
+ Context = NULL;
+ if (LmHostQueries.ResolvingNow && LmHostQueries.Context)
+ {
+ Context = (NBT_WORK_ITEM_CONTEXT *)LmHostQueries.Context;
+ pTracker = Context->pTracker;
+
+ ASSERT (pTracker->pDeviceContext->Verify == NBT_VERIFY_DEVCONTEXT);
+ if (pTracker->pDeviceContext == pDeviceContext)
+ {
+ LmHostQueries.Context = NULL;
+
+ pClientCompletion = Context->ClientCompletion;
+ pClientContext = Context->pClientContext;
+
+ // name did not resolve, so delete from table
+ RemoveName(pTracker->pNameAddr);
+
+ DereferenceTracker(pTracker);
+
+ CompleteClientReq(pClientCompletion,
+ pClientContext,
+ STATUS_NETWORK_NAME_DELETED);
+ DbgPrint("StopAllNameQueries: stopped lmhosts query in progress") ;
+ }
+ }
+
+ //
+ // now walk through the queued items and cancel all the relevant ones
+ //
+ pHead = &LmHostQueries.ToResolve;
+ pEntry = pHead->Flink;
+
+ while (pEntry != pHead)
+ {
+ Context = CONTAINING_RECORD(pEntry,NBT_WORK_ITEM_CONTEXT,Item.List);
+ pEntry = pEntry->Flink;
+
+ pTracker = Context->pTracker;
+
+ ASSERT (pTracker->pDeviceContext->Verify == NBT_VERIFY_DEVCONTEXT);
+ if (pTracker->pDeviceContext == pDeviceContext)
+ {
+ RemoveEntryList(&Context->Item.List);
+
+ pClientCompletion = Context->ClientCompletion;
+ pClientContext = Context->pClientContext;
+
+ // name did not resolve, so delete from table
+ RemoveName(pTracker->pNameAddr);
+
+ DereferenceTracker(pTracker);
+
+ CompleteClientReq(pClientCompletion,
+ pClientContext,
+ STATUS_NETWORK_NAME_DELETED);
+ DbgPrint("StopAllNameQueries: cancelled lmhosts queries in queue") ;
+ }
+ }
+
+}
+
+
+/*******************************************************************
+
+ NAME: VxdUnload
+
+ SYNOPSIS: This is where we are asked to unload. We destroy all
+ the device objects and then unload ourselves if the
+ message came from vtcp.
+
+ ENTRY: pchModuleName - name of the module that is going away.
+ We take action only if vtcp is going away
+ (in which case, pchModuleName is "MSTCP")
+
+ RETURNS: STATUS_SUCCESS if things went ok
+
+ HISTORY:
+ Koti Oct 5, 94
+
+********************************************************************/
+
+NTSTATUS
+VxdUnload( LPSTR pchModuleName )
+{
+
+ LIST_ENTRY * pEntry;
+ tDEVICECONTEXT * pDeviceContext;
+ NTSTATUS status;
+
+ CTEPagedCode();
+
+ KdPrint(("VxdUnload entered\r\n"));
+
+ if ( (pchModuleName == NULL) ||
+ (strcmp(pchModuleName,szXportName) != 0) )
+ {
+ CDbgPrint(DBGFLAG_ERROR,("VxdUnload: Unload msg not from MSTCP\r\n"));
+ return STATUS_SUCCESS;
+ }
+
+ //
+ // all devices will be destroyed by the time VxdUnload is called: this is
+ // just being paranoid
+ //
+ for ( pEntry = pNbtGlobConfig->DeviceContexts.Flink;
+ pEntry != &pNbtGlobConfig->DeviceContexts;
+ )
+ {
+ pDeviceContext = CONTAINING_RECORD( pEntry, tDEVICECONTEXT, Linkage);
+ pEntry = pEntry->Flink;
+
+ status = DestroyDeviceObject(pNbtGlobConfig, pDeviceContext->IpAddress);
+
+ if (status != STATUS_SUCCESS)
+ {
+ ASSERT(0);
+ }
+ }
+
+ //
+ // events such as name refresh etc. have been scheduled to be executed
+ // later: cancel all those
+ //
+ CancelAllDelayedEvents( NULL );
+
+ //
+ // Tell IP not to use the handler anymore
+ //
+ IPRegisterAddrChangeHandler( IPNotification, FALSE);
+
+
+ ReleaseNbtConfigMem();
+
+
+ //
+ // we don't provide any service, so don't pass our name
+ //
+ CTEUnload( (char *)NULL );
+}
+
+
+
+/*******************************************************************
+
+ NAME: ReleaseNbtConfigMem
+
+ SYNOPSIS: This is where we release all the memory that was allocated
+ at init/run time via ifs mgr.
+ We also stop the various timers.
+
+ HISTORY:
+ Koti Oct 14, 94
+
+********************************************************************/
+
+VOID ReleaseNbtConfigMem( VOID )
+{
+
+ PLIST_ENTRY pHead, pEntry;
+ tTIMERQENTRY *pTimerEntry;
+ tDGRAM_SEND_TRACKING *pTrack;
+ tADDRESSELE *pAddress;
+ tCLIENTELE *pClientEle;
+ tCONNECTELE *pConnEle;
+ tLOWERCONNECTION *pLowerConn;
+ tNAMEADDR *pNameAddr;
+ CTELockHandle OldIrq;
+ int i;
+
+
+ KdPrint(("ReleaseNbtConfigMem entered\r\n"));
+
+ CTEPagedCode();
+
+
+ //
+ // stop the timer that used to look for timed-out ncb's
+ //
+ StopTimeoutTimer();
+
+ //
+ // if any other timers are active, stop them
+ //
+ if (!IsListEmpty(&TimerQ.ActiveHead))
+ {
+ pHead = &TimerQ.ActiveHead;
+ pEntry = pHead->Flink;
+ while( pEntry != pHead )
+ {
+ pTimerEntry = CONTAINING_RECORD(pEntry,tTIMERQENTRY,Linkage);
+ pEntry = pEntry->Flink;
+ CTESpinLock(&NbtConfig.JointLock,OldIrq);
+ StopTimer(pTimerEntry,NULL,NULL);
+ CTESpinFree(&NbtConfig.JointLock,OldIrq);
+ }
+ }
+
+ //
+ // free all the timers on the free list
+ //
+ while (!IsListEmpty(&TimerQ.FreeHead))
+ {
+ pEntry = RemoveHeadList(&TimerQ.FreeHead);
+ pTimerEntry = CONTAINING_RECORD(pEntry,tTIMERQENTRY,Linkage);
+ CTEMemFree(pTimerEntry);
+ }
+
+
+ // free the various buffers
+
+ if ( pFileBuff )
+ CTEMemFree( pFileBuff );
+
+ if ( NbtConfig.pHosts )
+ CTEMemFree( NbtConfig.pHosts );
+
+ if (NbtConfig.pScope)
+ CTEMemFree( NbtConfig.pScope );
+
+ if (NbtConfig.pLmHosts)
+ CTEMemFree(NbtConfig.pLmHosts);
+
+ if (NbtConfig.pDomainName)
+ CTEMemFree(NbtConfig.pDomainName);
+
+ if (NbtConfig.pDNSDomains)
+ CTEMemFree(NbtConfig.pDNSDomains);
+
+
+ //
+ // NbtDereferenceAddress might have freed the addresses. But if
+ // ReleaseNameOnNet returned pending we wouldn't have freed the addressele
+ // yet, waiting for NameReleaseDone to be called. Well, we are about to
+ // be unloaded so free such instances now!
+ //
+ while (!IsListEmpty(&NbtConfig.AddressHead))
+ {
+ pEntry = RemoveHeadList(&NbtConfig.AddressHead);
+ pAddress = CONTAINING_RECORD(pEntry,tADDRESSELE,Linkage);
+ while (!IsListEmpty(&pAddress->ClientHead))
+ {
+ pEntry = RemoveHeadList(&pAddress->ClientHead);
+ pClientEle = CONTAINING_RECORD(pEntry,tCLIENTELE,Linkage);
+ while (!IsListEmpty(&pClientEle->ConnectActive))
+ {
+ pEntry = RemoveHeadList(&pClientEle->ConnectActive);
+ pConnEle = CONTAINING_RECORD(pEntry,tCONNECTELE,Linkage);
+ pLowerConn = pConnEle->pLowerConnId;
+ if (pLowerConn)
+ CTEMemFree(pLowerConn);
+ CTEMemFree(pConnEle);
+ }
+ CTEMemFree(pClientEle);
+ }
+ CTEMemFree( pAddress );
+ }
+
+
+ // free the DomainList
+ while (!IsListEmpty(&DomainNames.DomainList))
+ {
+ pEntry = RemoveHeadList(&DomainNames.DomainList);
+ pNameAddr = CONTAINING_RECORD(pEntry,tNAMEADDR,Linkage);
+ if (pNameAddr->pIpList)
+ CTEMemFree(pNameAddr->pIpList);
+ CTEMemFree(pNameAddr);
+ }
+
+
+ // free pLocalHashTbl
+ if (NbtConfig.pLocalHashTbl)
+ {
+ //
+ // we should have freed all the entries by now. It's possible though
+ // that we sent a name release which returned pending, so we are
+ // still hanging on to the nameaddr. If there is any such instance,
+ // free it now (when else? we are about to be unloaded now!)
+ //
+ for(i=0;i<NbtConfig.pLocalHashTbl->lNumBuckets;i++)
+ {
+ while (!IsListEmpty(&(NbtConfig.pLocalHashTbl->Bucket[i])))
+ {
+ pEntry = RemoveHeadList(&(NbtConfig.pLocalHashTbl->Bucket[i]));
+ pNameAddr = CONTAINING_RECORD(pEntry,tNAMEADDR,Linkage);
+ CTEMemFree(pNameAddr);
+ }
+ }
+ CTEMemFree( NbtConfig.pLocalHashTbl );
+ }
+
+
+ // free pRemoteHashTbl
+ if (NbtConfig.pRemoteHashTbl)
+ {
+ for(i=0;i<NbtConfig.pRemoteHashTbl->lNumBuckets;i++)
+ {
+ while (!IsListEmpty(&(NbtConfig.pRemoteHashTbl->Bucket[i])))
+ {
+ pEntry = RemoveHeadList(&(NbtConfig.pRemoteHashTbl->Bucket[i]));
+ pNameAddr = CONTAINING_RECORD(pEntry,tNAMEADDR,Linkage);
+ CTEMemFree(pNameAddr);
+ }
+ }
+ CTEMemFree( NbtConfig.pRemoteHashTbl );
+ }
+
+
+ // free up the DgramTrackerFreeQ
+ while (!IsListEmpty(&NbtConfig.DgramTrackerFreeQ))
+ {
+ pEntry = RemoveHeadList(&NbtConfig.DgramTrackerFreeQ);
+ pTrack = CONTAINING_RECORD(pEntry,tDGRAM_SEND_TRACKING,Linkage);
+ CTEMemFree( pTrack );
+ }
+
+ //
+ // shouldn't see any pending name queries at this point, but just in case!
+ //
+ while (!IsListEmpty(&NbtConfig.PendingNameQueries))
+ {
+ pEntry = RemoveHeadList(&NbtConfig.PendingNameQueries);
+ pNameAddr = CONTAINING_RECORD(pEntry,tNAMEADDR,Linkage);
+ CTEMemFree( pNameAddr );
+ }
+
+
+ // free the SessionBufferFreeList list (allocated, not used)
+ while( !IsListEmpty(&NbtConfig.SessionBufferFreeList) )
+ {
+ pEntry = RemoveHeadList(&NbtConfig.SessionBufferFreeList);
+ CTEMemFree( pEntry );
+ }
+
+
+ // free SendContextFreeList (allocated, not used)
+ while( !IsListEmpty(&NbtConfig.SendContextFreeList) )
+ {
+ pEntry = RemoveHeadList(&NbtConfig.SendContextFreeList);
+ CTEMemFree( pEntry );
+ }
+
+
+ // free RcvContextFreeList (allocated, not used)
+ while( !IsListEmpty(&NbtConfig.RcvContextFreeList) )
+ {
+ pEntry = RemoveHeadList(&NbtConfig.RcvContextFreeList);
+ CTEMemFree( pEntry );
+ }
+
+#ifdef DBG
+ if( !IsListEmpty(&DbgMemList) )
+ {
+ KdPrint(("ReleaseNbtConfigMem: memory leak!\r\n"));
+ if (DbgLeakCheck)
+ {
+ ASSERT(0);
+ }
+ }
+#endif
+
+}
+
+#endif // CHICAGO
diff --git a/private/ntos/nbt/vxd/chicasm.asm b/private/ntos/nbt/vxd/chicasm.asm
new file mode 100644
index 000000000..2536b30f7
--- /dev/null
+++ b/private/ntos/nbt/vxd/chicasm.asm
@@ -0,0 +1,122 @@
+;*****************************************************************;
+;** Copyright(c) Microsoft Corp., 1988-1993 **;
+;*****************************************************************;
+;:ts=8
+ TITLE CHICASM.ASM - Chicago (PNP) Specific vnbt routines
+.XLIST
+;*** VNBT -- NetBios over TCP/IP VxD
+;
+;
+ .386p
+ include vmm.inc
+ include dosmgr.inc
+ include netvxd.inc
+ include vdhcp.inc
+ include debug.inc
+ include vtdi.inc
+ include vip.inc
+
+ include vnbt.inc
+ include vnetbios.inc
+.LIST
+
+IFDEF CHICAGO
+
+EXTRN _GetDhcpOption:NEAR
+EXTRN NCB_Handler:NEAR
+
+
+VxD_CODE_SEG
+
+;****************************************************************************
+;** _RegisterLana2
+;
+; Registers the requested lana with the VNetbios driver.
+;
+; Entry: [ESP+4] - PNP Device context
+; [ESP+8] - Lana number to register
+;
+; Exit: EAX will return the lana registered or 0xff if the lana couldn't
+; be registered.
+;
+; Uses:
+;
+BeginProc _RegisterLana2
+
+ VxDcall VNETBIOS_Get_Version
+ jnc Do_Register
+ mov eax, 0ffh ; yukk! vnetbios is not loaded!
+ jmp Register_Fail
+
+Do_Register:
+ mov ecx, [esp+4] ; PNP device context
+ mov eax, [esp+8] ; Get the request lana to register
+
+ push ebx
+ push edx
+
+ mov ebx, 1 ; Take over RM lana
+ mov edx, NCB_Handler
+ VxDcall VNETBIOS_Register2 ; Carry set on failure
+ jnc RegLana10
+ mov eax, 0ffh ; Failed
+
+RegLana10:
+ pop edx
+ pop ebx
+Register_Fail:
+ ret
+
+EndProc _RegisterLana2
+
+
+;****************************************************************************
+;** _DeregisterLana
+;
+; Deregisters the requested lana with the VNetbios driver.
+;
+; Entry: [ESP+4] - Lana number to deregister
+;
+; Uses:
+;
+BeginProc _DeregisterLana
+
+ mov eax, [esp+4] ; Lana to deregister
+
+ VxDcall VNETBIOS_Deregister
+
+ ret
+EndProc _DeregisterLana
+
+;****************************************************************************
+;** _IPRegisterAddrChangeHandler
+;
+; Registers a handler with IP to handle binding and unbinding
+;
+; Entry: [ESP+4] - Pointer to handler
+; [ESP+8] - TRUE to set the handler, FALSE to remove the handler
+;
+; Exit: EAX will contain TRUE if successful, FALSE other wise
+;
+; Uses:
+;
+BeginProc _IPRegisterAddrChangeHandler
+
+ mov eax, [esp+8] ; bool
+ push eax
+ mov eax, [esp+8] ; Handler (yes, it should be esp+8)
+ push eax
+
+ VxDcall VIP_Register_Addr_Change; Carry set on failure
+
+ add esp, 8
+ ret
+
+EndProc _IPRegisterAddrChangeHandler
+
+VxD_CODE_ENDS
+
+ENDIF ;CHICAGO
+
+END
+
diff --git a/private/ntos/nbt/vxd/cinit.c b/private/ntos/nbt/vxd/cinit.c
new file mode 100644
index 000000000..c8e9c4efd
--- /dev/null
+++ b/private/ntos/nbt/vxd/cinit.c
@@ -0,0 +1,930 @@
+/**********************************************************************/
+/** Microsoft Windows **/
+/** Copyright(c) Microsoft Corp., 1993 **/
+/**********************************************************************/
+
+/*
+
+ Init.c
+
+ Contains VxD initialization code
+
+
+ FILE HISTORY:
+ Johnl 24-Mar-1993 Created
+
+*/
+
+#include <nbtprocs.h>
+#include <tdiinfo.h>
+#include <ipinfo.h>
+#include <dhcpinfo.h>
+#include <nbtinfo.h>
+#include <hosts.h>
+
+int Init( void ) ;
+int RegisterLana( int Lana ) ;
+
+ NTSTATUS
+NbtReadRegistry(
+ OUT tNBTCONFIG *pConfig
+ ) ;
+
+extern char DNSSectionName[]; // Section where we find DNS domain name
+
+VOID GetDNSInfo( VOID );
+
+ULONG GetDhcpOption( PUCHAR ValueName, ULONG DefaultValue );
+
+VOID ParseDomainNames(
+ PUCHAR *ppDomainName,
+ PUCHAR *ppDNSDomains
+ );
+
+//******************* Pageable Routine Declarations ****************
+#ifdef ALLOC_PRAGMA
+#pragma CTEMakePageable(INIT, Init)
+#pragma CTEMakePageable(PAGE, NbtReadRegistry)
+#pragma CTEMakePageable(PAGE, GetDNSInfo)
+#pragma CTEMakePageable(PAGE, CreateDeviceObject)
+#pragma CTEMakePageable(PAGE, GetDhcpOption)
+#endif
+//******************* Pageable Routine Declarations ****************
+
+//
+// Initialized in VNBT_Device_Init with the protocol(s) this driver sits
+// on. Note that we currently only support one. This should *not* be in
+// the initialization data segments.
+//
+TDIDispatchTable * TdiDispatch ;
+UCHAR LanaBase ;
+BOOL fInInit = TRUE ;
+
+//
+// Used in conjunction with the CHECK_INT_TABLE macro
+//
+#ifdef DEBUG
+ BYTE abVecTbl[256] ;
+ DWORD DebugFlags = DBGFLAG_ALL | DBGFLAG_KDPRINTS ;
+ char DBOut[4096] ;
+ int iCurPos = 0 ;
+
+void NbtDebugOut( char * str )
+{
+ if ( DebugFlags & (DBGFLAG_AUX_OUTPUT | DBGFLAG_ERROR) )
+ CTEPrint( str ) ;
+
+ iCurPos += strlen( str ) + 1 ;
+
+ if ( iCurPos >= sizeof(DBOut) )
+ iCurPos = 0;
+}
+
+#endif // DEBUG
+
+#pragma BEGIN_INIT
+
+//
+// While reading initialization parameters, we may need to go to
+// the DHCP driver. This communicates to the init routine which device
+// we are currently interested in.
+// 0xfffffff means get the requested option for any IP address.
+//
+// MUST BE IN NETWORK ORDER!!!
+//
+ULONG CurrentIP = 0xffffffff ;
+
+/*******************************************************************
+
+ NAME: Init
+
+ SYNOPSIS: Performs all driver initialization
+
+ RETURNS: TRUE if initialization successful, FALSE otherwise
+
+ NOTES:
+
+ HISTORY:
+ Johnl 24-Mar-1993 Created
+
+********************************************************************/
+
+int Init( void )
+{
+ NTSTATUS status ;
+ int i ;
+ ULONG ulTmp ;
+ int Retval;
+
+
+ Retval = FALSE;
+
+ if ( CTEInitialize() )
+ {
+ DbgPrint("Init: CTEInitialize succeeded\n\r") ;
+ }
+ else
+ goto fail_init;
+
+ INIT_NULL_PTR_CHECK() ;
+
+#ifdef DEBUG
+ InitializeListHead(&DbgMemList);
+ DbgLeakCheck = 0;
+#endif
+
+#ifdef CHICAGO
+ //
+ // Tell TDI who to call if someone underneath unloads
+ //
+ CTESetUnloadNotifyProc( (CTENotifyRtn)VxdUnload );
+
+ //
+ // prepare to read a bunch of parms from the registry
+ //
+ VxdOpenNdis();
+#endif
+
+ CTERefillMem() ;
+ CTEZeroMemory( pNbtGlobConfig, sizeof(*pNbtGlobConfig));
+
+ status = NbtReadRegistry( pNbtGlobConfig ) ;
+ if ( !NT_SUCCESS( status ) )
+ {
+ DbgPrint("Init: NbtReadRegistry failed\n\r") ;
+ goto fail_init;
+ }
+
+ InitializeListHead(&pNbtGlobConfig->DelayedEvents);
+
+ InitializeListHead(&pNbtGlobConfig->BlockingNcbs);
+
+ status = InitNotOs() ;
+ if ( !NT_SUCCESS( status ) )
+ {
+ DbgPrint("Init: InitNotOs failed\n\r") ;
+ goto fail_init;
+ }
+
+ status = InitTimersNotOs() ;
+ if ( !NT_SUCCESS( status ) )
+ {
+ DbgPrint("Init: InitTimersNotOs failed\n\r") ;
+ StopInitTimers() ;
+ goto fail_init;
+ }
+
+#ifdef CHICAGO
+
+ //
+ // if name server and/or dns server are defined in registry, read them now
+ //
+ SaveNameDnsServerAddrs();
+
+ //
+ // Register an IP notification routine when new adapters are added or
+ // DHCP brings up an address
+ //
+
+ if ( !IPRegisterAddrChangeHandler( IPNotification, TRUE))
+ {
+ DbgPrint("Init: Failed to register with IP driver\r\n") ;
+ StopInitTimers() ;
+ goto fail_init;
+ }
+#else
+ //
+ // Find all the active Lanas
+ //
+
+ if ( !GetActiveLanasFromIP() )
+ {
+ DbgPrint("Init: Failed to get addresses from IP driver\r\n") ;
+ StopInitTimers() ;
+ goto fail_init;
+ }
+
+#endif
+
+ //
+ // find out where hosts file is, what's the domain name etc.
+ //
+ GetDNSInfo();
+
+ //
+ // Get the NCB timeout timer going
+ //
+ if ( !CheckForTimedoutNCBs( NULL, NULL) )
+ {
+ DbgPrint("Init: CheckForTimedoutNCBs failed\n\r") ;
+ StopInitTimers() ;
+ goto fail_init;
+ }
+
+ fInInit = FALSE ;
+ CTERefillMem() ;
+ Retval = TRUE ;
+
+
+fail_init:
+
+#ifdef CHICAGO
+ VxdCloseNdis();
+#endif
+
+ return( Retval );
+}
+
+//----------------------------------------------------------------------------
+ NTSTATUS
+NbtReadRegistry(
+ OUT tNBTCONFIG *pConfig
+ )
+/*++
+
+Routine Description:
+
+ This routine is called to get information from the registry,
+ starting at RegistryPath to get the parameters.
+
+Arguments:
+
+ pNbtConfig - ptr to global configuration strucuture for NBT
+
+Return Value:
+
+ NTSTATUS - STATUS_SUCCESS if everything OK, STATUS_INSUFFICIENT_RESOURCES
+ otherwise.
+
+--*/
+{
+ NTSTATUS Status = STATUS_SUCCESS ;
+ int i;
+
+ CTEPagedCode();
+
+ //
+ // Initialize the Configuration data structure
+ //
+ CTEZeroMemory(pConfig,sizeof(tNBTCONFIG));
+
+ ReadParameters( pConfig, NULL );
+
+ //
+ // Allocate necessary memory for lmhosts support if a lmhosts file
+ // was specified (was read from .ini file in ReadParameters)
+ //
+ if ( pConfig->pLmHosts )
+ {
+ if ( !VxdInitLmHostsSupport( pConfig->pLmHosts,
+ 260 /*strlen(pConfig->pLmHosts)+1*/ ))
+ {
+ return STATUS_INSUFFICIENT_RESOURCES ;
+ }
+
+ pConfig->EnableLmHosts = TRUE ;
+ }
+ else
+ {
+ pConfig->EnableLmHosts = FALSE ;
+ }
+
+ // keep the size around for allocating memory, so that when we run over
+ // OSI, only this value should change (in theory at least)
+ pConfig->SizeTransportAddress = sizeof(TDI_ADDRESS_IP);
+
+ // fill in the node type value that is put into all name service Pdus
+ // that go out identifying this node type
+ switch (NodeType)
+ {
+ case BNODE:
+ pConfig->PduNodeType = 0;
+ break;
+ case PNODE:
+ pConfig->PduNodeType = 1 << 13;
+ break;
+ case MNODE:
+ pConfig->PduNodeType = 1 << 14;
+ break;
+ case MSNODE:
+ pConfig->PduNodeType = 3 << 13;
+ break;
+
+ }
+
+ LanaBase = (UCHAR) CTEReadSingleIntParameter( NULL,
+ VXD_LANABASE_NAME,
+ VXD_DEF_LANABASE,
+ 0 ) ;
+ CTEZeroMemory( LanaTable, NBT_MAX_LANAS * sizeof( LANA_ENTRY )) ;
+
+ return Status;
+}
+
+/*******************************************************************
+
+ NAME: GetDNSInfo
+
+ SYNOPSIS: Gets path to windows dir, then appends hosts to it
+
+ RETURNS: Nothing
+
+ NOTES: If something goes wrong, path is set to NULL
+
+ HISTORY:
+ Koti 13-July-1994 Created
+
+********************************************************************/
+
+VOID GetDNSInfo( VOID )
+{
+
+ PUCHAR pszWinPath;
+ PUCHAR pszHosts="hosts";
+ PUCHAR pszHostsPath=NULL;
+#ifdef CHICAGO
+ PUCHAR pszParmName="Domain";
+ PUCHAR pszParm2Name = "SearchList";
+#else
+ PUCHAR pszParmName="DomainName";
+ PUCHAR pszParm2Name = "DNSDomains";
+#endif
+ PUCHAR pszDomName;
+ PUCHAR pchTmp;
+ int len;
+
+
+ CTEPagedCode();
+
+ NbtConfig.pHosts = NULL;
+
+ //
+ // Remember, pszWinPath has '\' at the end: (i.e. Get_Config_Directory
+ // returns pointer to "c:\windows\" )
+ //
+ pszWinPath = VxdWindowsPath();
+
+ //
+ // doc implies Get_Config_Directory can't fail! But we are paranoid...
+ //
+
+ if (pszWinPath == NULL)
+ {
+ pszHostsPath = NULL;
+ return;
+ }
+
+ len = strlen(pszWinPath) + strlen(pszHosts) + 1;
+
+ //
+ // allocate memory to hold "c:\windows\hosts" or whatever
+ //
+ pszHostsPath = CTEAllocInitMem( len );
+ if (pszHostsPath == NULL)
+ return;
+
+ strcpy(pszHostsPath, pszWinPath);
+ strcat(pszHostsPath, pszHosts);
+
+ NbtConfig.pHosts = pszHostsPath;
+
+ NbtConfig.pDomainName = NULL;
+//
+// chicago gets the string from the registry, snowball from system.ini
+//
+ NbtConfig.pDNSDomains = NULL;
+
+#ifdef CHICAGO
+ if ( !CTEReadIniString( NULL, pszParmName, &pchTmp ) )
+ {
+ NbtConfig.pDomainName = pchTmp;
+ }
+
+ if ( !CTEReadIniString( NULL, pszParm2Name, &pchTmp ) )
+ {
+ if (pchTmp[0] != '\0')
+ {
+ NbtConfig.pDNSDomains = pchTmp;
+ }
+ else
+ {
+ CTEMemFree(pchTmp);
+ }
+ }
+#else
+ pchTmp = GetProfileString( pszParmName, NULL, DNSSectionName );
+ if ( pchTmp != NULL )
+ {
+ if ( pszDomName = CTEAllocInitMem( strlen( pchTmp ) + 1 ) )
+ {
+ strcpy( pszDomName, pchTmp ) ;
+
+ NbtConfig.pDomainName = pszDomName;
+ }
+ }
+
+ pchTmp = GetProfileString( pszParm2Name, NULL, DNSSectionName );
+ if ( pchTmp != NULL && pchTmp[0] != '\0')
+ {
+ if ( pszDomName = CTEAllocInitMem( strlen( pchTmp ) + 1) )
+ {
+ strcpy( pszDomName, pchTmp ) ;
+
+ NbtConfig.pDNSDomains = pszDomName;
+ }
+ }
+#endif
+
+ ParseDomainNames( &NbtConfig.pDomainName, &NbtConfig.pDNSDomains);
+
+ return;
+}
+
+/*******************************************************************
+
+ NAME: ParseDomainNames
+
+ SYNOPSIS: Extracts heirarchical domain names from the primary DNS
+ domain name, and prepends any found to the domains list.
+
+ ENTRY: ppDomainName - pointer to pointer to primary DNS domain name
+ ppDNSDomains - pointer to pointer to other DNS domain names
+
+ EXIT: *ppDNSDomains updated with pointer to new DNS domains list
+ if any other heirarchical levels found in *ppDomainName.
+
+ RETURNS: nothing
+
+ NOTES:
+
+ HISTORY:
+ EarleH 10-Jan-1996 Created
+
+********************************************************************/
+
+VOID ParseDomainNames(
+ PUCHAR *ppDomainName,
+ PUCHAR *ppDNSDomains
+ )
+{
+ PUCHAR pStr;
+ UINT iCount;
+ PUCHAR pDomainName = *ppDomainName, pDNSDomains = *ppDNSDomains, pNewDNSDomains;
+
+ if ( pDomainName != NULL )
+ {
+ for ( iCount = 0, pStr = pDomainName ; pStr[0] != '\0' ; pStr++ )
+ {
+ if ( pStr[0] == '.' )
+ {
+ iCount += strlen ( pStr );
+ }
+ }
+ if ( pDNSDomains != NULL )
+ {
+ iCount += strlen ( pDNSDomains );
+ if ( iCount )
+ {
+ iCount++; // for the separator
+ }
+ }
+ if (iCount++) // ++ for the terminator
+ {
+ pNewDNSDomains = CTEAllocInitMem( iCount );
+ if ( pNewDNSDomains != NULL )
+ {
+ pNewDNSDomains[0] = '\0';
+ for ( pStr = pDomainName ; pStr[0] != '\0' ; pStr++ )
+ {
+ if ( pStr[0] == '.' )
+ {
+ pStr++;
+ if ( pNewDNSDomains[0] != '\0' )
+ {
+ strcat ( pNewDNSDomains, "," );
+ }
+ strcat ( pNewDNSDomains, pStr );
+ }
+ }
+ if ( pDNSDomains != NULL )
+ {
+ strcat ( pNewDNSDomains, "," );
+ strcat ( pNewDNSDomains, pDNSDomains );
+ CTEMemFree( pDNSDomains );
+ }
+ if ( pNewDNSDomains[0] != '\0' )
+ {
+ *ppDNSDomains = pNewDNSDomains;
+ }
+ else
+ {
+ *ppDNSDomains = NULL;
+ }
+ }
+ }
+ }
+}
+
+#pragma END_INIT
+
+#ifndef CHICAGO
+#pragma BEGIN_INIT
+#endif
+/*******************************************************************
+
+ NAME: CreateDeviceObject
+
+ SYNOPSIS: Initializes the device list of the global configuration
+ structure
+
+ ENTRY: pConfig - Pointer to global config structure
+ IpAddr - IP Address for this adapter
+ IpMask - IP Mask for this adapter
+ IpNameServer - IP Address of the name server for this adapter
+ IpBackupServer - IP Address of the backup name server for
+ this adapter
+ IpDnsServer - IP Address of the dns server for this adapter
+ IpDnsBackupServer - IP Address of the backup dns server
+ MacAddr - hardware address of the adapter for this IP addr
+ IpIndex - Index of the IP Address in the IP Driver's address
+ table (used for setting address by DHCP)
+
+ EXIT: The device list in pConfig will be fully initialized
+
+ RETURNS: STATUS_SUCCESS if successful, error otherwise
+
+ NOTES:
+
+ HISTORY:
+ Johnl 14-Apr-1993 Created
+
+********************************************************************/
+
+NTSTATUS CreateDeviceObject(
+ IN tNBTCONFIG *pConfig,
+ IN ULONG IpAddr,
+ IN ULONG IpMask,
+ IN ULONG IpNameServer,
+ IN ULONG IpBackupServer,
+ IN ULONG IpDnsServer,
+ IN ULONG IpDnsBackupServer,
+ IN UCHAR MacAddr[],
+ IN UCHAR IpIndex
+ )
+{
+ NTSTATUS status;
+ tDEVICECONTEXT * pDeviceContext, *pDevtmp;
+ ULONG ulTmp ;
+ NCB * pNCB ;
+ DHCPNotify dn ;
+ PLIST_ENTRY pEntry;
+ ULONG Adapter;
+ ULONG PreviousNodeType;
+
+ CTEPagedCode();
+
+ pDeviceContext = CTEAllocInitMem(sizeof( tDEVICECONTEXT )) ;
+ if ( !pDeviceContext )
+ return STATUS_INSUFFICIENT_RESOURCES ;
+
+ //
+ // zero out the data structure
+ //
+ CTEZeroMemory( pDeviceContext, sizeof(tDEVICECONTEXT) );
+
+ // put a verifier value into the structure so that we can check that
+ // we are operating on the right data when the OS passes a device context
+ // to NBT
+ pDeviceContext->Verify = NBT_VERIFY_DEVCONTEXT;
+
+ //
+ // we aren't up yet: don't want ncb's coming in before we are ready!
+ //
+ pDeviceContext->fDeviceUp = FALSE;
+
+ // setup the spin lock);
+ CTEInitLock(&pDeviceContext->SpinLock);
+ pDeviceContext->LockNumber = DEVICE_LOCK;
+ pDeviceContext->lNameServerAddress = IpNameServer ;
+ pDeviceContext->lBackupServer = IpBackupServer ;
+ pDeviceContext->lDnsServerAddress = IpDnsServer ;
+ pDeviceContext->lDnsBackupServer = IpDnsBackupServer ;
+
+ // copy the mac addresss
+ CTEMemCopy(&pDeviceContext->MacAddress.Address[0], MacAddr, 6);
+
+ //
+ // if the node type is set to Bnode by default then switch to Hnode if
+ // there are any WINS servers configured.
+ //
+ PreviousNodeType = NodeType;
+
+ if ((NodeType & DEFAULT_NODE_TYPE) &&
+ (IpNameServer || IpBackupServer))
+ {
+ NodeType = MSNODE;
+ if (PreviousNodeType & PROXY)
+ NodeType |= PROXY;
+ }
+
+ //
+ // start the refresh timer (if we had already started it, this function
+ // just returns success)
+ //
+ status = StartRefreshTimer();
+
+ if ( !NT_SUCCESS( status ) )
+ {
+ CTEFreeMem( pDeviceContext ) ;
+ return( status ) ;
+ }
+
+
+ // initialize the pDeviceContext data structure. There is one of
+ // these data structured tied to each "device" that NBT exports
+ // to higher layers (i.e. one for each network adapter that it
+ // binds to.
+ // The initialization sets the forward link equal to the back link equal
+ // to the list head
+ InitializeListHead(&pDeviceContext->UpConnectionInUse);
+ InitializeListHead(&pDeviceContext->LowerConnection);
+ InitializeListHead(&pDeviceContext->LowerConnFreeHead);
+ InitializeListHead(&pDeviceContext->RcvAnyFromAnyHead);
+ InitializeListHead(&pDeviceContext->RcvDGAnyFromAnyHead);
+ InitializeListHead(&pDeviceContext->PartialRcvHead) ;
+
+ InitializeListHead(&pDeviceContext->DelayedEvents);
+
+ //
+ // Pick an adapter number that hasn't been used yet
+ //
+ Adapter = 1;
+ for ( pEntry = pConfig->DeviceContexts.Flink;
+ pEntry != &pConfig->DeviceContexts;
+ pEntry = pEntry->Flink )
+ {
+ pDevtmp = CONTAINING_RECORD( pEntry, tDEVICECONTEXT, Linkage );
+
+ if ( !(pDevtmp->AdapterNumber & Adapter) )
+ break;
+
+ Adapter <<= 1;
+ }
+
+ pDeviceContext->AdapterNumber = Adapter ;
+ pDeviceContext->IPIndex = IpIndex ;
+ NbtConfig.AdapterCount++ ;
+ if ( NbtConfig.AdapterCount > 1 )
+ {
+ NbtConfig.MultiHomed = TRUE ;
+ }
+
+ //
+ // Allocate our name table and session table watching for both a
+ // minimum and a maximum size.
+ //
+
+ pDeviceContext->cMaxNames = (UCHAR) min( pConfig->lRegistryMaxNames, MAX_NCB_NUMS ) ;
+
+ pDeviceContext->cMaxSessions = (UCHAR) min( pConfig->lRegistryMaxSessions, MAX_NCB_NUMS ) ;
+
+ //
+ // Add one to the table size for the zeroth element (used for permanent
+ // name in the name table). The user accessible table goes from 1 to n
+ //
+
+ if ( !(pDeviceContext->pNameTable = (tCLIENTELE**)
+ CTEAllocInitMem((USHORT)((pDeviceContext->cMaxNames+1) * sizeof(tADDRESSELE*)))) ||
+ !(pDeviceContext->pSessionTable = (tCONNECTELE**)
+ CTEAllocInitMem((pDeviceContext->cMaxSessions+1) * sizeof(tCONNECTELE*))))
+ {
+ return STATUS_INSUFFICIENT_RESOURCES ;
+ }
+
+ CTEZeroMemory( &pDeviceContext->pNameTable[0],
+ (pDeviceContext->cMaxNames+1)*sizeof(tCLIENTELE*)) ;
+ CTEZeroMemory( &pDeviceContext->pSessionTable[0],
+ (pDeviceContext->cMaxSessions+1)*sizeof(tCONNECTELE*) ) ;
+ pDeviceContext->iNcbNum = 1 ;
+ pDeviceContext->iLSNum = 1 ;
+
+ // add this new device context on to the List in the configuration
+ // data structure
+ InsertTailList(&pConfig->DeviceContexts,&pDeviceContext->Linkage);
+
+ //
+ // IpAddr can be 0 only in wfw case (when dhcp hasn't yet obtained one)
+ // (in case of chicago, we will never come this far if ipaddr is 0)
+ //
+ if (!IpAddr)
+ {
+ pDeviceContext->IpAddress = 0;
+ goto Skip_tdiaddr_init;
+ }
+
+ //
+ // open the required address objects with the underlying transport provider
+ //
+ status = NbtCreateAddressObjects(
+ IpAddr,
+ IpMask,
+ pDeviceContext);
+ if (!NT_SUCCESS(status))
+ {
+ KdPrint(("Failed to create the Address Object, status=%lC\n",status));
+ return(status);
+ }
+
+ // this call must converse with the transport underneath to create
+ // connections and associate them with the session address object
+ status = NbtInitConnQ(
+ &pDeviceContext->LowerConnFreeHead,
+ sizeof(tLOWERCONNECTION),
+ NBT_NUM_INITIAL_CONNECTIONS,
+ pDeviceContext);
+
+ if (!NT_SUCCESS(status))
+ {
+ CDbgPrint( DBGFLAG_ERROR,
+ ("CreateDeviceObject: NbtInitConnQ Failed!")) ;
+
+ return(status);
+ }
+
+ //
+ // Add the permanent name for this adapter
+ //
+ status = NbtAddPermanentName( pDeviceContext ) ;
+ if ( !NT_SUCCESS( status ))
+ {
+ return status ;
+ }
+
+Skip_tdiaddr_init:
+
+ //
+ // ok, we are ready to function! (we are setting this to TRUE even if
+ // there is no ipaddr yet (in case of wfw only) so that rdr,srv etc. can
+ // add names without error
+ //
+ pDeviceContext->fDeviceUp = TRUE;
+
+#ifndef CHICAGO
+ //
+ // Set up a DHCP notification for this device in case the IP address
+ // changes
+ //
+ dn.dn_pfnNotifyRoutine = AddrChngNotification ;
+ dn.dn_pContext = pDeviceContext ;
+
+ status = DhcpSetInfo( DHCP_SET_NOTIFY_HANDLER,
+ pDeviceContext->IPIndex,
+ &dn,
+ sizeof( dn )) ;
+ if ( status )
+ {
+ ASSERT(0);
+ CDbgPrint( DBGFLAG_ERROR,
+ ("CreateDeviceObject: Warning - Setting Dhcp notification handler failed")) ;
+ }
+#endif //!CHICAGO
+
+ return(STATUS_SUCCESS);
+}
+
+/*******************************************************************
+
+ NAME: GetDhcpOption
+
+ SYNOPSIS: Checks to see if the passed .ini parameter is a potential
+ DHCP option. If it is, it calls DHCP to get the option.
+
+ This routine is called when retrieving parameters from
+ the .ini file if the parameter is not found.
+
+ ENTRY: ValueName - String of .ini parameter name
+ DefaultValue - Value to return if not a DHCP option or
+ DHCP didn't have the option
+
+ RETURNS: DHCP option value or DefaultValue if an error occurred.
+ If the requested parameter is a string option (such as
+ scopeid), then a pointer to an allocated string is
+ returned.
+
+ NOTES: Name Server address is handled in GetNameServerAddress
+
+ HISTORY:
+ Johnl 17-Dec-1993 Created
+
+********************************************************************/
+
+#define OPTION_NETBIOS_SCOPE_OPTION 47
+#define OPTION_NETBIOS_NODE_TYPE 46
+#define OPTION_BROADCAST_ADDRESS 28
+
+struct
+{
+ PUCHAR pchParamName ;
+ ULONG DhcpOptionID ;
+} OptionMapping[] =
+ { { WS_NODE_TYPE, OPTION_NETBIOS_NODE_TYPE },
+ { NBT_SCOPEID, OPTION_NETBIOS_SCOPE_OPTION },
+ { WS_ALLONES_BCAST, OPTION_BROADCAST_ADDRESS }
+ } ;
+#define NUM_OPTIONS (sizeof(OptionMapping)/sizeof(OptionMapping[0]))
+
+
+ULONG GetDhcpOption( PUCHAR ValueName, ULONG DefaultValue )
+{
+ int i ;
+ ULONG Val ;
+ TDI_STATUS tdistatus ;
+ ULONG Size ;
+ INT OptionId ;
+ PUCHAR pStrVal ;
+
+ CTEPagedCode();
+
+ //
+ // Is this parameter a DHCP option?
+ //
+ for ( i = 0 ; i < NUM_OPTIONS ; i++ )
+ {
+ if ( !strcmp( OptionMapping[i].pchParamName, ValueName ))
+ goto FoundOption ;
+ }
+
+ return DefaultValue ;
+
+FoundOption:
+
+ switch ( OptionId = OptionMapping[i].DhcpOptionID )
+ {
+ case OPTION_NETBIOS_SCOPE_OPTION: // String options go here
+
+ //
+ // Get the size of the string resource, then get the option
+ //
+
+ Size = MAX_SCOPE_LENGTH+1 ;
+ pStrVal = CTEAllocInitMem( Size );
+ if (pStrVal == NULL)
+ {
+ DbgPrint("GetDhcpOption: failed to allocate memory") ;
+ return 0 ;
+ }
+
+ tdistatus = DhcpQueryOption( CurrentIP,
+ OptionId,
+ pStrVal,
+ &Size ) ;
+
+ if ( tdistatus == TDI_SUCCESS )
+ {
+ DbgPrint("GetDhcpOption: Successfully retrieved option ID ") ;
+ DbgPrintNum( OptionId ) ; DbgPrint("\r\n") ;
+ return (ULONG) pStrVal ;
+ }
+ else
+ {
+ DbgPrint("GetDhcpOption: returned error = 0x ") ;
+ DbgPrintNum( tdistatus ) ; DbgPrint("\r\n") ;
+ CTEMemFree( pStrVal ) ;
+ return 0 ;
+ }
+
+ default: // ULONG options go here
+ Size = sizeof( Val ) ;
+ tdistatus = DhcpQueryOption( CurrentIP,
+ OptionId,
+ &Val,
+ &Size ) ;
+ break ;
+ }
+
+ switch ( tdistatus )
+ {
+ case TDI_SUCCESS:
+ case TDI_BUFFER_OVERFLOW: // May be more then one, only take the 1st
+ DbgPrint("GetDhcpOption: Successfully retrieved option ID ") ;
+ DbgPrintNum( OptionId ) ; DbgPrint("\r\n") ;
+ return Val ;
+
+ case TDI_INVALID_PARAMETER: // Option not found
+ DbgPrint("GetDhcpOption: Failed to retrieve option ID ") ;
+ DbgPrintNum( OptionId ) ; DbgPrint("\r\n") ;
+ return DefaultValue ;
+
+ default:
+ ASSERT( FALSE ) ;
+ break ;
+ }
+
+ return DefaultValue ;
+}
+
+#ifndef CHICAGO
+#pragma END_INIT
+#endif
+
+
diff --git a/private/ntos/nbt/vxd/client.asm b/private/ntos/nbt/vxd/client.asm
new file mode 100644
index 000000000..0c44bbf79
--- /dev/null
+++ b/private/ntos/nbt/vxd/client.asm
@@ -0,0 +1,427 @@
+ page ,132
+ title client16.asm - 16-bit client support routines
+
+
+;**********************************************************************
+;** Microsoft Windows **
+;** Copyright(c) Microsoft Corp., 1993-1994 **
+;**********************************************************************
+;
+;
+; client16.asm
+;
+; VXDLIB routines for dealing with 16-bit clients.
+;
+; The following functions are exported by this module:
+;
+; VxdMapSegmentOffsetToFlat
+;
+;
+; FILE HISTORY:
+; Koti 14-Jun-1994 Stole from KeithMo
+;
+;
+
+.386p
+include vmm.inc
+include shell.inc
+include vwin32.inc
+include netvxd.inc
+include debug.inc
+
+
+;;;
+;;; Flag to _LinPage[Un]Lock.
+;;;
+
+ifdef CHICAGO
+VxdLinPageFlag equ PAGEMAPGLOBAL
+else ; !CHICAGO
+VxdLinPageFlag equ 0
+endif ; CHICAGO
+
+
+;***
+;*** Locked code segment.
+;***
+
+VXD_LOCKED_CODE_SEG
+
+;;;
+;;; Public functions.
+;;;
+
+;*******************************************************************
+;
+; NAME: VxdMapSegmentOffsetToFlat
+;
+; SYNOPSIS: Maps a segment/offset pair to the corresponding flat
+; pointer.
+;
+; ENTRY: VirtualHandle - VM handle.
+;
+; UserSegment - Segment value.
+;
+; UserOffset - Offset value
+;
+; RETURNS: LPVOID - The flat pointer, -1 if unsuccessful.
+;
+; NOTES: This routine was more-or-less stolen from the Map_Flat
+; source in dos386\vmm\vmmutil.asm.
+;
+; HISTORY:
+; KeithMo 27-Jan-1994 Created.
+;
+;********************************************************************
+BeginProc _VxdMapSegmentOffsetToFlat, PUBLIC, CCALL, ESP
+
+ArgVar VirtualHandle, DWORD
+ArgVar UserSegment, DWORD
+ArgVar UserOffset, DWORD
+
+ EnterProc
+ SaveReg <ebx, ecx, edx, esi>
+
+;;;
+;;; Capture the parameters.
+;;;
+
+ mov ebx, VirtualHandle ; (EBX) = VM handle
+ movzx eax, word ptr UserSegment ; (EAX) = segment
+ movzx esi, word ptr UserOffset ; (ESI) = offset
+
+;;;
+;;; Short-circuit for NULL pointer. This is OK.
+;;;
+
+ or eax, eax
+ jz vmsotf_Exit
+
+;;;
+;;; Determine if the current virtual machine is running in V86
+;;; mode or protected mode.
+;;;
+
+ test [ebx.CB_VM_Status], VMStat_PM_Exec
+ jz vmsotf_V86Mode
+
+;;;
+;;; The target virtual machine is in protected mode. Map the
+;;; selector to a flat pointer, then add the offset.
+;;;
+
+ VMMCall _SelectorMapFlat <ebx, eax, 0>
+ cmp eax, 0FFFFFFFFh
+ je vmsotf_Exit
+
+ add eax, esi
+
+;;;
+;;; If the pointer is within the first 1Meg+64K, add in the
+;;; high-linear offset.
+;;;
+
+ cmp eax, 00110000h
+ jae short vmsotf_Exit
+
+vmsotf_AddHighLinear:
+
+ add eax, [ebx.CB_High_Linear]
+
+;;;
+;;; Cleanup stack & return.
+;;;
+
+vmsotf_Exit:
+
+ RestoreReg <esi, edx, ecx, ebx>
+ LeaveProc
+ Return
+
+;;;
+;;; The target virtual machine is in V86 mode. Map the segment/offset
+;;; pair to a linear address.
+;;;
+
+vmsotf_V86Mode:
+
+ shl eax, 4
+ add eax, esi
+ jmp vmsotf_AddHighLinear
+
+EndProc _VxdMapSegmentOffsetToFlat
+
+
+;*******************************************************************
+;
+; NAME: VxdLockBuffer
+;
+; SYNOPSIS: Locks a user-mode buffer so it may be safely accessed
+; from ring 0.
+;
+; ENTRY: Buffer - Starting virtual address of user-mode buffer.
+;
+; BufferLength - Length (in BYTEs) of user-mode buffer.
+;
+; RETURN: LPVOID - Global locked address if successful,
+; NULL if not.
+;
+; HISTORY:
+; KeithMo 10-Nov-1993 Created.
+;
+;********************************************************************
+BeginProc _VxdLockBuffer, PUBLIC, CCALL, ESP
+
+ArgVar Buffer, DWORD
+ArgVar BufferLength, DWORD
+
+ EnterProc
+ SaveReg <ebx, edi, esi>
+
+;;;
+;;; Grab parameters from stack.
+;;;
+
+ mov eax, Buffer ; User-mode buffer address.
+ mov ebx, BufferLength ; Buffer length.
+
+;;;
+;;; Short-circuit for NULL buffer or zero length.
+;;;
+
+ or eax, eax
+ jz lub_Exit
+ or ebx, ebx
+ jz lub_Exit
+
+;;;
+;;; Calculate the starting page number & number of pages to lock.
+;;;
+
+ movzx ecx, ax
+ and ch, 0Fh ; ecx = offset within first page.
+ mov esi, ecx ; save it for later
+ add ebx, ecx
+ add ebx, 0FFFh
+ shr ebx, 12 ; ebx = number of pages to lock.
+ shr eax, 12 ; eax = starting page number.
+
+;;;
+;;; Ask VMM to lock the buffer.
+;;;
+
+ VMMCall _LinPageLock, <eax, ebx, VxdLinPageFlag>
+ or eax, eax
+ jz lub_Failure
+
+ifdef CHICAGO
+ add eax, esi ; add offset into first page.
+else ; !CHICAGO
+ mov eax, Buffer ; retrieve original address.
+endif ; CHICAGO
+
+;;;
+;;; Common exit path. Cleanup stack & return.
+;;;
+
+lub_Exit:
+
+ RestoreReg <esi, edi, ebx>
+ LeaveProc
+ Return
+
+;;;
+;;; LinPageLock failure.
+;;;
+
+lub_Failure:
+
+ Trace_Out "VxdLockBuffer: _LinPageLock failed"
+ xor eax, eax
+ jmp lub_Exit
+
+EndProc _VxdLockBuffer
+
+
+;*******************************************************************
+;
+; NAME: VxdUnlockBuffer
+;
+; SYNOPSIS: Unlocks a user-mode buffer locked with LockUserBuffer.
+;
+; ENTRY: Buffer - Starting virtual address of user-mode buffer.
+;
+; BufferLength - Length (in BYTEs) of user-mode buffer.
+;
+; RETURN: DWORD - !0 if successful, 0 if not.
+;
+; HISTORY:
+; KeithMo 10-Nov-1993 Created.
+;
+;********************************************************************
+BeginProc _VxdUnlockBuffer, PUBLIC, CCALL, ESP
+
+ArgVar Buffer, DWORD
+ArgVar BufferLength, DWORD
+
+ EnterProc
+ SaveReg <ebx, edi, esi>
+
+;;;
+;;; Grab parameters from stack.
+;;;
+
+ mov eax, Buffer ; User-mode buffer address.
+ mov ebx, BufferLength ; Buffer length.
+
+;;;
+;;; Short-circuit for NULL buffer or zero length.
+;;;
+
+ or eax, eax
+ jz uub_Success
+ or ebx, ebx
+ jz uub_Success
+
+;;;
+;;; Calculate the starting page number & number of pages to unlock.
+;;;
+
+ movzx ecx, ax
+ and ch, 0Fh ; ecx = offset within first page.
+ add ebx, ecx
+ add ebx, 0FFFh
+ shr ebx, 12 ; ebx = number of pages to lock.
+ shr eax, 12 ; eax = starting page number.
+
+;;;
+;;; Ask VMM to unlock the buffer.
+;;;
+
+ VMMCall _LinPageUnLock, <eax, ebx, VxdLinPageFlag>
+ or eax, eax
+ jz uub_Failure
+
+uub_Success:
+
+ mov eax, 1 ; !0 == success
+
+;;;
+;;; Common exit path. Cleanup stack & return.
+;;;
+
+uub_Exit:
+
+ RestoreReg <esi, edi, ebx>
+ LeaveProc
+ Return
+
+;;;
+;;; LinPageUnLock failure.
+;;;
+
+uub_Failure:
+
+ Trace_Out "VxdUnlockBuffer: _LinPageUnlock failed"
+ xor eax, eax
+ jmp uub_Exit
+
+EndProc _VxdUnlockBuffer
+
+
+;
+; BUGBUG: VxdValidateBuffer is currently not used. Unifdef it if needed
+;
+
+
+;*******************************************************************
+;
+; NAME: VxdValidateBuffer
+;
+; SYNOPSIS: Validates that all pages within the given buffer are
+; valid.
+;
+; ENTRY: Buffer - Starting virtual address of user-mode buffer.
+;
+; BufferLength - Length (in BYTEs) of user-mode buffer.
+;
+; RETURN: BOOL - TRUE if all pages in buffer are valid, FALSE
+; otherwise.
+;
+; HISTORY:
+; KeithMo 20-May-1994 Created.
+;
+;********************************************************************
+BeginProc _VxdValidateBuffer, PUBLIC, CCALL, ESP
+
+ArgVar Buffer, DWORD
+ArgVar BufferLength, DWORD
+
+ EnterProc
+ SaveReg <ebx, edi, esi>
+
+;;;
+;;; Grab parameters from stack.
+;;;
+
+ mov eax, Buffer ; User-mode buffer address.
+ mov ebx, BufferLength ; Buffer length.
+
+;;;
+;;; Short-circuit for NULL buffer or zero length.
+;;;
+
+ or eax, eax
+ jz vub_Success
+ or ebx, ebx
+ jz vub_Success
+
+;;;
+;;; Calculate the starting page number & number of pages to validate.
+;;;
+
+ movzx ecx, ax
+ and ch, 0Fh ; ecx = offset within first page.
+ add ebx, ecx
+ add ebx, 0FFFh
+ shr ebx, 12 ; ebx = number of pages to check.
+ shr eax, 12 ; eax = starting page number.
+ mov ecx, ebx ; save page count
+
+;;;
+;;; Ask VMM to validate the buffer.
+;;;
+
+ VMMCall _PageCheckLinRange, <eax, ebx, 0>
+ cmp eax, ecx
+ jne vub_Failure
+
+vub_Success:
+
+ mov eax, 1 ; TRUE == success.
+
+;;;
+;;; Common exit path. Cleanup stack & return.
+;;;
+
+vub_Exit:
+
+ RestoreReg <esi, edi, ebx>
+ LeaveProc
+ Return
+
+;;;
+;;; _PageCheckLinRange failure.
+;;;
+
+vub_Failure:
+
+ xor eax, eax
+ jmp vub_Exit
+
+EndProc _VxdValidateBuffer
+
+VXD_LOCKED_CODE_ENDS
+
+
+END
diff --git a/private/ntos/nbt/vxd/ctimer.c b/private/ntos/nbt/vxd/ctimer.c
new file mode 100644
index 000000000..29cca3179
--- /dev/null
+++ b/private/ntos/nbt/vxd/ctimer.c
@@ -0,0 +1,237 @@
+/**********************************************************************/
+/** Microsoft Windows **/
+/** Copyright(c) Microsoft Corp., 1993 **/
+/**********************************************************************/
+
+/*
+
+ Timer.c
+
+ This module checks for active sessions on all adapters for send/receive
+ NCBs that have timed out.
+
+ A single timer is used for all adapters.
+
+ If a send times out, then the session will be aborted.
+
+ FILE HISTORY:
+ Johnl 23-Sep-1993 Created
+
+*/
+
+#include <nbtprocs.h>
+#include <ctemacro.h>
+
+CTETimer TimeoutTimer ;
+
+/*******************************************************************
+
+ NAME: CheckForTimedoutNCBs
+
+ SYNOPSIS: Traverses list of all send/receive NCBs checking for
+ any that have reached their timeout point every half
+ second.
+
+ ENTRY: pEvent - Not used
+ pCont - Not used
+
+ RETURNS: TRUE if the timer successfully started, FALSE otherwise
+
+ NOTES: This is a self perpetuating function, each time it is called,
+ it schedules the timer again for a 1/2 second later to
+ call itself.
+
+ To get it going, it should be called once during
+ initialization
+
+ HISTORY:
+ Johnl 23-Sep-1993 Created
+
+********************************************************************/
+
+BOOL CheckForTimedoutNCBs( CTEEvent *pCTEEvent, PVOID pCont )
+{
+ tNAMEADDR * pNameAddr ;
+ tCLIENTELE * pClientEle ;
+ tCONNECTELE * pConnectEle ;
+ LIST_ENTRY * pEntry ;
+ LIST_ENTRY * pEntryClient ;
+ LIST_ENTRY * pEntryConn ;
+ LIST_ENTRY * pEntryRcv ;
+
+ //
+ // Look for Receive NCBs first
+ //
+ for ( pEntry = NbtConfig.AddressHead.Flink ;
+ pEntry != &NbtConfig.AddressHead ;
+ pEntry = pEntry->Flink )
+ {
+ PLIST_ENTRY pEntryClient ;
+ tADDRESSELE * pAddrEle = CONTAINING_RECORD( pEntry,
+ tADDRESSELE,
+ Linkage ) ;
+ ASSERT( pAddrEle->Verify == NBT_VERIFY_ADDRESS ) ;
+
+ for ( pEntryClient = pAddrEle->ClientHead.Flink ;
+ pEntryClient != &pAddrEle->ClientHead ;
+ pEntryClient = pEntryClient->Flink )
+ {
+ tCLIENTELE * pClientEle = CONTAINING_RECORD( pEntryClient,
+ tCLIENTELE,
+ Linkage ) ;
+ PLIST_ENTRY pEntryConn ;
+ ASSERT( pClientEle->Verify == NBT_VERIFY_CLIENT ||
+ pClientEle->Verify == NBT_VERIFY_CLIENT_DOWN ) ;
+
+ for ( pEntryConn = pClientEle->ConnectActive.Flink ;
+ pEntryConn != &pClientEle->ConnectActive ;
+ pEntryConn = pEntryConn->Flink )
+ {
+ PRCV_CONTEXT prcvCont ;
+ pConnectEle = CONTAINING_RECORD( pEntryConn,
+ tCONNECTELE,
+ Linkage ) ;
+ ASSERT( pConnectEle->Verify == NBT_VERIFY_CONNECTION ||
+ pConnectEle->Verify == NBT_VERIFY_CONNECTION_DOWN ) ;
+
+ if ( pConnectEle->RTO == NCB_INFINITE_TIME_OUT ||
+ pConnectEle->state != NBT_SESSION_UP ||
+ IsListEmpty( &pConnectEle->RcvHead ) )
+ {
+ continue ;
+ }
+
+ //
+ // Note that we only check the first receive buffer because
+ // the timeout is for the next receive indication (and not
+ // how long this NCB has been waiting).
+ //
+ pEntryRcv = pConnectEle->RcvHead.Flink ;
+ prcvCont = CONTAINING_RECORD( pEntryRcv, RCV_CONTEXT, ListEntry ) ;
+ ASSERT( prcvCont->Signature == RCVCONT_SIGN ) ;
+
+ if ( prcvCont->RTO == NCB_TIMED_OUT )
+ {
+ RemoveEntryList( &prcvCont->ListEntry ) ;
+ CTEIoComplete( prcvCont->pNCB, STATUS_TIMEOUT, 0 ) ;
+ }
+ else
+ {
+ prcvCont->RTO-- ;
+ }
+ } // ConnectActive
+ } // Client
+ } // Address
+
+ //
+ // Now look for Send NCB time outs. Only connections that specified
+ // a timeout will be put on this list.
+ //
+ for ( pEntry = NbtConfig.SendTimeoutHead.Flink ;
+ pEntry != &NbtConfig.SendTimeoutHead ;
+ )
+ {
+ PSEND_CONTEXT pSendCont ;
+
+ pSendCont = CONTAINING_RECORD( pEntry, SEND_CONTEXT, ListEntry ) ;
+ pEntry = pEntry->Flink ; // get the next one
+
+ pSendCont->STO-- ;
+ if ( pSendCont->STO == NCB_TIMED_OUT )
+ {
+ //
+ // Assumes pSendCont is stored in ncb_reserve field of NCB
+ // This will remove it from the timeout list also.
+ //
+ CTEIoComplete( CONTAINING_RECORD( pSendCont, NCB, ncb_reserve ),
+ STATUS_TIMEOUT,
+ 0 ) ;
+ // the above CTEIoComplete will trigger events from the transport
+ // which could modify the SendTimeout list before we reach this
+ // point. Best just to wait until things clear up.
+ break;
+ }
+ }
+
+ //
+ // Restart the timer for a half second from now
+ //
+ CTEInitTimer( &TimeoutTimer ) ;
+ return !!CTEStartTimer( &TimeoutTimer, 500, CheckForTimedoutNCBs, NULL ) ;
+}
+
+
+/*******************************************************************
+
+ NAME: StartRefreshTimer
+
+ SYNOPSIS: Start the refresh timer
+ This function was necessary because of this scenario:
+ No node type was defined in registry, so we defaulted to
+ BNODE and didn't start refresh timer.
+ Now, while we are still coming up, dhcp tells us we are
+ MSNODE. Shouldn't we start the refresh timer?
+ That's why this function.
+
+ HISTORY:
+ Koti 9-Jun-1994 Created
+
+********************************************************************/
+
+NTSTATUS StartRefreshTimer( VOID )
+{
+
+ NTSTATUS status = STATUS_SUCCESS;
+ tTIMERQENTRY *pTimerEntry;
+
+ //
+ // make sure it's not bnode, and that timer really needs to be started
+ //
+ if (!(NodeType & BNODE) && (!NbtConfig.pRefreshTimer))
+ {
+
+ // the initial refresh rate until we can contact the name server
+ NbtConfig.MinimumTtl = NBT_INITIAL_REFRESH_TTL;
+ NbtConfig.sTimeoutCount = 0;
+
+ status = StartTimer(
+ NbtConfig.InitialRefreshTimeout,
+ NULL, // context value
+ NULL, // context2 value
+ RefreshTimeout,
+ NULL,
+ NULL,
+ 0,
+ &pTimerEntry);
+
+ if ( !NT_SUCCESS( status ) )
+ return status ;
+
+ NbtConfig.pRefreshTimer = pTimerEntry;
+ }
+
+ return(STATUS_SUCCESS);
+}
+
+
+#ifdef CHICAGO
+
+/*******************************************************************
+
+ NAME: StopTimeoutTimer
+
+ SYNOPSIS: Stops the timer that was set in CheckForTimedoutNCBs.
+ This is needed only for Chicago which can dynamically
+ unload vnbt.
+
+ HISTORY:
+ Koti 23-May-1994 Created
+
+********************************************************************/
+
+VOID StopTimeoutTimer( VOID )
+{
+ CTEStopTimer( &TimeoutTimer );
+}
+
+#endif
diff --git a/private/ntos/nbt/vxd/cvxdfile.asm b/private/ntos/nbt/vxd/cvxdfile.asm
new file mode 100644
index 000000000..451f18501
--- /dev/null
+++ b/private/ntos/nbt/vxd/cvxdfile.asm
@@ -0,0 +1,186 @@
+;/**********************************************************************/
+;/** Microsoft Windows/NT **/
+;/** Copyright(c) Microsoft Corp., 1994 **/
+;/**********************************************************************/
+
+;/*
+; cvxdFile.asm
+;
+; Contains simple VXD File I/O routines (that use VxdInt 21h macro)
+; for dhcp.bin support
+;
+; FILE HISTORY:
+; madana 07-May-1994 Created
+; koti 10-Oct-1994 Copied over/modified for vnbt
+;
+;*/
+
+ .386p
+ include vmm.inc
+ include v86mmgr.inc
+ include dosmgr.inc
+ include opttest.inc
+ include netvxd.inc
+ include debug.inc
+ include pageable.inc
+
+EXTRN _fInInit:DWORD
+EXTRN _GetInDosFlag:NEAR
+
+
+;****************************************************************************
+;** PushState Macro
+;
+; Saves the client state.
+;
+PushState MACRO
+
+ push edi
+ push esi
+ push ebx
+
+ mov ecx, 0
+ VMMCall Begin_Critical_Section
+
+ENDM
+
+;****************************************************************************
+;** PopState Macro
+;
+; Restores client state.
+;
+PopState MACRO
+
+ VMMCall End_Critical_Section
+
+ pop ebx
+ pop esi
+ pop edi
+
+ENDM
+
+NBT_PAGEABLE_CODE_SEG
+
+;****************************************************************************
+;** _VxdFileOpen
+;
+; Opens a file
+;
+; Entry: [ESP+4] - Pointer to full path of file, path must be flat
+; pointer.
+;
+; Exit: EAX will contain a handle to the openned file
+;
+BeginProc _VxdFileOpen
+
+ PushState ; This pushes lots of crap
+
+ mov edx, [esp+16] ; move flat pointer file name
+ mov eax, 3d02h ; Open file, read/write, share
+
+ VxDInt 21h
+
+ jc VFO_6 ; Carry set if error
+ jmp VFO_10 ; successful file open, eax has file handle
+
+VFO_6:
+; Debug_Out "VxdFileOpen failed, error #EAX"
+ mov eax, 0 ; Failed to open the file
+
+VFO_10:
+ PopState
+ ret
+
+EndProc _VxdFileOpen
+
+
+;****************************************************************************
+;** _VxdFileRead
+;
+; Reads x bytes from a previously openned file
+;
+; Entry: [ESP+4] - Handle from _VxdFileOpen
+; [ESP+8] - Count of bytes to read
+; [ESP+12]- flat pointer to destination buffer
+;
+; Exit: EAX will contain the number of bytes read, 0 if EOF or
+; an error occurred.
+;
+BeginProc _VxdFileRead
+
+ PushState ; Pushes lots of crap
+
+ mov ebx, [esp+16] ; File Handle
+ mov ecx, [esp+20] ; Bytes to read
+ mov edx, [esp+24] ; flat buffer pointer
+ mov eax, 3f00h
+
+ VxDInt 21h
+
+ jc VFR_6 ; Carry set if error
+ jmp VFR_7 ; successful file open, eax has bytes read
+
+VFR_6:
+; Debug_Out "VxdFileRead failed"
+ mov eax, 0 ; Failed to read the file
+VFR_7:
+ PopState
+ ret
+
+EndProc _VxdFileRead
+
+;****************************************************************************
+;** _VxdFileClose
+;
+; Closes a file openned with VxdOpenFile
+;
+; Entry: [ESP+4] - Handle from _VxdFileOpen
+;
+BeginProc _VxdFileClose
+
+ PushState ; Pushes lots of crap
+
+ mov ebx, [esp+16] ; File Handle
+ mov eax, 3e00h
+
+ VxDInt 21h
+
+ jc VFCL_6 ; Carry set if error
+ jmp VFCL_7 ; successful set.
+
+VFCL_6:
+ Debug_Out "VxdFileClose - Read failed"
+ mov eax, 0 ; Failed to close the file
+VFCL_7:
+ PopState
+ ret
+
+EndProc _VxdFileClose
+
+;****************************************************************************
+;** _VxdWindowsPath
+;
+; Gets a pointer to (null-terminated) path to the windows directory
+;
+; This is an Init time only routine
+;
+; Entry: nothing
+;
+; Exit: pointer to path to windows directory
+;
+BeginProc _VxdWindowsPath
+ PushState ; Pushes lots of crap
+
+ VmmCall Get_Config_Directory
+
+ mov eax, edx ; path is returned in edx
+
+ PopState ; now pop all that crap
+
+ ret
+
+EndProc _VxdWindowsPath
+
+NBT_PAGEABLE_CODE_ENDS
+
+END
diff --git a/private/ntos/nbt/vxd/cxport.inc b/private/ntos/nbt/vxd/cxport.inc
new file mode 100644
index 000000000..edbc6d2a2
--- /dev/null
+++ b/private/ntos/nbt/vxd/cxport.inc
@@ -0,0 +1,4 @@
+;; Dummy include file so we can build COFF version of
+;; "cxport.obj."
+;;
+;; Eventually, this may become obsolete.
diff --git a/private/ntos/nbt/vxd/depend.mk b/private/ntos/nbt/vxd/depend.mk
new file mode 100644
index 000000000..5dba4a995
--- /dev/null
+++ b/private/ntos/nbt/vxd/depend.mk
@@ -0,0 +1,1279 @@
+#********************************************************************
+#** Copyright(c) Microsoft Corp., 1993 **
+#********************************************************************
+$(SNOVNBTOBJD)/chicasm.obj $(SNODVNBTOBJD)/chicasm.obj $(VNBTSRC)/chicasm.lst: \
+ $(VNBTSRC)/chicasm.asm ../blt/netvxd.inc ../blt/vdhcp.inc \
+ $(VNBTSRC)/vnbtd.inc $(IMPORT)/win32/ddk/inc/debug.inc \
+ $(IMPORT)/wininc/dosmgr.inc \
+ $(IMPORT)/wininc/vnetbios.inc $(NDIS3INC)/vmm.inc \
+ $(CHICAGO)/tcp/inc/vip.inc $(CHICAGO)/tcp/inc/vtdi.inc
+
+$(SNOVNBTOBJD)/client.obj $(SNODVNBTOBJD)/client.obj $(VNBTSRC)/client.lst: \
+ $(VNBTSRC)/client.asm ../blt/netvxd.inc \
+ $(IMPORT)/win32/ddk/inc/debug.inc \
+ $(IMPORT)/win32/ddk/inc/shell.inc \
+ $(IMPORT)/win32/ddk/inc/shellfsc.inc \
+ $(NDIS3INC)/vmm.inc $(NDIS3INC)/vwin32.inc
+
+$(SNOVNBTOBJD)/cvxdfile.obj $(SNODVNBTOBJD)/cvxdfile.obj $(VNBTSRC)/cvxdfile.lst: \
+ $(VNBTSRC)/cvxdfile.asm ../blt/netvxd.inc \
+ $(IMPORT)/win32/ddk/inc/debug.inc \
+ $(IMPORT)/win32/ddk/inc/opttest.inc \
+ $(IMPORT)/wininc/dosmgr.inc \
+ $(IMPORT)/wininc/v86mmgr.inc $(NDIS3INC)/vmm.inc
+
+$(SNOVNBTOBJD)/vfirst.obj $(SNODVNBTOBJD)/vfirst.obj $(VNBTSRC)/vfirst.lst: \
+ $(VNBTSRC)/vfirst.asm
+
+$(SNOVNBTOBJD)/vnbtd.obj $(SNODVNBTOBJD)/vnbtd.obj $(VNBTSRC)/vnbtd.lst: \
+ $(VNBTSRC)/vnbtd.asm ../blt/netvxd.inc ../blt/vdhcp.inc $(VNBTSRC)/vnbtd.inc \
+ $(IMPORT)/win32/ddk/inc/debug.inc \
+ $(IMPORT)/wininc/dosmgr.inc \
+ $(IMPORT)/wininc/vnetbios.inc $(NDIS3INC)/vmm.inc \
+ $(CHICAGO)/tcp/inc/vtdi.inc
+
+$(SNOVNBTOBJD)/vxdfile.obj $(SNODVNBTOBJD)/vxdfile.obj $(VNBTSRC)/vxdfile.lst: \
+ $(VNBTSRC)/vxdfile.asm ../blt/netvxd.inc \
+ $(IMPORT)/win32/ddk/inc/debug.inc \
+ $(IMPORT)/win32/ddk/inc/opttest.inc \
+ $(IMPORT)/wininc/dosmgr.inc \
+ $(IMPORT)/wininc/v86mmgr.inc $(NDIS3INC)/vmm.inc
+
+$(SNOVNBTOBJD)/vxdstub.obj $(SNODVNBTOBJD)/vxdstub.obj $(VNBTSRC)/vxdstub.lst: \
+ $(VNBTSRC)/vxdstub.asm $(IMPORT)/wininc/INT2FAPI.INC
+
+$(SNOVNBTOBJD)/wfwasm.obj $(SNODVNBTOBJD)/wfwasm.obj $(VNBTSRC)/wfwasm.lst: \
+ $(VNBTSRC)/wfwasm.asm ../blt/netvxd.inc ../blt/vdhcp.inc $(VNBTSRC)/vnbtd.inc \
+ $(IMPORT)/win32/ddk/inc/debug.inc \
+ $(IMPORT)/wininc/dosmgr.inc \
+ $(IMPORT)/wininc/vnetbios.inc $(NDIS3INC)/vmm.inc \
+ $(CHICAGO)/tcp/inc/vtdi.inc
+
+$(CHIVNBTOBJD)/chicasm.obj $(CHIDVNBTOBJD)/chicasm.obj $(VNBTSRC)/chicasm.lst: \
+ $(VNBTSRC)/chicasm.asm ../blt/vdhcp.inc $(VNBTSRC)/vnbtd.inc \
+ $(CHICAGO)/dev/ddk/inc/debug.inc $(CHICAGO)/dev/ddk/inc/dosmgr.inc \
+ $(CHICAGO)/dev/ddk/inc/netvxd.inc $(CHICAGO)/dev/ddk/inc/vmm.inc \
+ $(CHICAGO)/dev/ddk/inc/vnetbios.inc $(CHICAGO)/tcp/inc/vip.inc \
+ $(CHICAGO)/tcp/inc/vtdi.inc
+
+$(CHIVNBTOBJD)/client.obj $(CHIDVNBTOBJD)/client.obj $(VNBTSRC)/client.lst: \
+ $(VNBTSRC)/client.asm $(CHICAGO)/dev/ddk/inc/debug.inc \
+ $(CHICAGO)/dev/ddk/inc/netvxd.inc $(CHICAGO)/dev/ddk/inc/shell.inc \
+ $(CHICAGO)/dev/ddk/inc/vmm.inc $(CHICAGO)/dev/ddk/inc/vwin32.inc
+
+$(CHIVNBTOBJD)/cvxdfile.obj $(CHIDVNBTOBJD)/cvxdfile.obj $(VNBTSRC)/cvxdfile.lst: \
+ $(VNBTSRC)/cvxdfile.asm $(CHICAGO)/dev/ddk/inc/debug.inc \
+ $(CHICAGO)/dev/ddk/inc/dosmgr.inc $(CHICAGO)/dev/ddk/inc/netvxd.inc \
+ $(CHICAGO)/dev/ddk/inc/opttest.inc $(CHICAGO)/dev/ddk/inc/v86mmgr.inc \
+ $(CHICAGO)/dev/ddk/inc/vmm.inc
+
+$(CHIVNBTOBJD)/vfirst.obj $(CHIDVNBTOBJD)/vfirst.obj $(VNBTSRC)/vfirst.lst: \
+ $(VNBTSRC)/vfirst.asm
+
+$(CHIVNBTOBJD)/vnbtd.obj $(CHIDVNBTOBJD)/vnbtd.obj $(VNBTSRC)/vnbtd.lst: \
+ $(VNBTSRC)/vnbtd.asm ../blt/vdhcp.inc $(VNBTSRC)/vnbtd.inc \
+ $(CHICAGO)/dev/ddk/inc/debug.inc $(CHICAGO)/dev/ddk/inc/dosmgr.inc \
+ $(CHICAGO)/dev/ddk/inc/netvxd.inc $(CHICAGO)/dev/ddk/inc/vmm.inc \
+ $(CHICAGO)/dev/ddk/inc/vnetbios.inc $(CHICAGO)/tcp/inc/vtdi.inc
+
+$(CHIVNBTOBJD)/vxdfile.obj $(CHIDVNBTOBJD)/vxdfile.obj $(VNBTSRC)/vxdfile.lst: \
+ $(VNBTSRC)/vxdfile.asm $(CHICAGO)/dev/ddk/inc/debug.inc \
+ $(CHICAGO)/dev/ddk/inc/dosmgr.inc $(CHICAGO)/dev/ddk/inc/netvxd.inc \
+ $(CHICAGO)/dev/ddk/inc/opttest.inc $(CHICAGO)/dev/ddk/inc/v86mmgr.inc \
+ $(CHICAGO)/dev/ddk/inc/vmm.inc
+
+$(CHIVNBTOBJD)/vxdstub.obj $(CHIDVNBTOBJD)/vxdstub.obj $(VNBTSRC)/vxdstub.lst: \
+ $(VNBTSRC)/vxdstub.asm $(CHICAGO)/dev/ddk/inc/INT2FAPI.INC
+
+$(CHIVNBTOBJD)/wfwasm.obj $(CHIDVNBTOBJD)/wfwasm.obj $(VNBTSRC)/wfwasm.lst: \
+ $(VNBTSRC)/wfwasm.asm ../blt/vdhcp.inc $(VNBTSRC)/vnbtd.inc \
+ $(CHICAGO)/dev/ddk/inc/debug.inc $(CHICAGO)/dev/ddk/inc/dosmgr.inc \
+ $(CHICAGO)/dev/ddk/inc/netvxd.inc $(CHICAGO)/dev/ddk/inc/vmm.inc \
+ $(CHICAGO)/dev/ddk/inc/vnetbios.inc $(CHICAGO)/tcp/inc/vtdi.inc
+
+$(SNOVNBTOBJD)/chic.obj $(SNODVNBTOBJD)/chic.obj $(VNBTSRC)/chic.lst: \
+ $(VNBTSRC)/chic.c ../$(INC)/alpha.h ../$(INC)/alpharef.h ../$(INC)/arc.h \
+ ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h ../blt/dhcpinfo.h $(INC)/ctemacro.h \
+ $(INC)/debug.h $(INC)/nbtinfo.h $(INC)/nbtnt.h $(INC)/nbtprocs.h \
+ $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h $(INC)/vxddebug.h \
+ $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h $(CHICAGO)/tcp/h/tdivxd.h \
+ $(BASEDIR)/private/inc/ipinfo.h $(BASEDIR)/private/inc/nbtioctl.h \
+ $(BASEDIR)/private/inc/nettypes.h $(BASEDIR)/private/inc/packoff.h \
+ $(BASEDIR)/private/inc/packon.h $(BASEDIR)/private/inc/sockets/netinet/in.h \
+ $(BASEDIR)/private/inc/status.h $(BASEDIR)/private/inc/sys/snet/ip_proto.h \
+ $(BASEDIR)/private/inc/tdi.h $(BASEDIR)/private/inc/tdiinfo.h \
+ $(BASEDIR)/private/inc/tdikrnl.h $(BASEDIR)/private/inc/tdistat.h \
+ $(BASEDIR)/public/sdk/inc/alphaops.h $(BASEDIR)/public/sdk/inc/crt/ctype.h \
+ $(BASEDIR)/public/sdk/inc/crt/excpt.h $(BASEDIR)/public/sdk/inc/crt/limits.h \
+ $(BASEDIR)/public/sdk/inc/crt/stdarg.h $(BASEDIR)/public/sdk/inc/crt/stddef.h \
+ $(BASEDIR)/public/sdk/inc/crt/string.h $(BASEDIR)/public/sdk/inc/devioctl.h \
+ $(BASEDIR)/public/sdk/inc/lintfunc.hxx $(BASEDIR)/public/sdk/inc/mipsinst.h \
+ $(BASEDIR)/public/sdk/inc/nb30.h $(BASEDIR)/public/sdk/inc/netevent.h \
+ $(BASEDIR)/public/sdk/inc/nt.h $(BASEDIR)/public/sdk/inc/ntalpha.h \
+ $(BASEDIR)/public/sdk/inc/ntconfig.h $(BASEDIR)/public/sdk/inc/ntddtdi.h \
+ $(BASEDIR)/public/sdk/inc/ntdef.h $(BASEDIR)/public/sdk/inc/ntelfapi.h \
+ $(BASEDIR)/public/sdk/inc/ntexapi.h $(BASEDIR)/public/sdk/inc/nti386.h \
+ $(BASEDIR)/public/sdk/inc/ntimage.h $(BASEDIR)/public/sdk/inc/ntioapi.h \
+ $(BASEDIR)/public/sdk/inc/ntiolog.h $(BASEDIR)/public/sdk/inc/ntkeapi.h \
+ $(BASEDIR)/public/sdk/inc/ntldr.h $(BASEDIR)/public/sdk/inc/ntlpcapi.h \
+ $(BASEDIR)/public/sdk/inc/ntmips.h $(BASEDIR)/public/sdk/inc/ntmmapi.h \
+ $(BASEDIR)/public/sdk/inc/ntnls.h $(BASEDIR)/public/sdk/inc/ntobapi.h \
+ $(BASEDIR)/public/sdk/inc/ntppc.h $(BASEDIR)/public/sdk/inc/ntpsapi.h \
+ $(BASEDIR)/public/sdk/inc/ntregapi.h $(BASEDIR)/public/sdk/inc/ntrtl.h \
+ $(BASEDIR)/public/sdk/inc/ntseapi.h $(BASEDIR)/public/sdk/inc/ntstatus.h \
+ $(BASEDIR)/public/sdk/inc/ntxcapi.h $(BASEDIR)/public/sdk/inc/poppack.h \
+ $(BASEDIR)/public/sdk/inc/ppcinst.h $(BASEDIR)/public/sdk/inc/pshpack1.h \
+ $(BASEDIR)/public/sdk/inc/pshpack4.h $(BASEDIR)/public/sdk/inc/windef.h \
+ $(BASEDIR)/public/sdk/inc/winerror.h $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(SNOVNBTOBJD)/fileio.obj $(SNODVNBTOBJD)/fileio.obj $(VNBTSRC)/fileio.lst: \
+ $(VNBTSRC)/fileio.c ../$(INC)/alpha.h ../$(INC)/alpharef.h \
+ ../$(INC)/arc.h ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h $(INC)/ctemacro.h $(INC)/debug.h $(INC)/hosts.h \
+ $(INC)/nbtnt.h $(INC)/nbtprocs.h $(INC)/ntprocs.h $(INC)/timer.h \
+ $(INC)/types.h $(INC)/vxddebug.h $(INC)/vxdprocs.h \
+ $(CHICAGO)/tcp/h/oscfg.h $(CHICAGO)/tcp/h/tdivxd.h \
+ $(BASEDIR)/private/inc/nbtioctl.h $(BASEDIR)/private/inc/nettypes.h \
+ $(BASEDIR)/private/inc/packoff.h $(BASEDIR)/private/inc/packon.h \
+ $(BASEDIR)/private/inc/sockets/netinet/in.h $(BASEDIR)/private/inc/status.h \
+ $(BASEDIR)/private/inc/sys/snet/ip_proto.h $(BASEDIR)/private/inc/tdi.h \
+ $(BASEDIR)/private/inc/tdikrnl.h $(BASEDIR)/private/inc/tdistat.h \
+ $(BASEDIR)/public/sdk/inc/alphaops.h $(BASEDIR)/public/sdk/inc/crt/ctype.h \
+ $(BASEDIR)/public/sdk/inc/crt/excpt.h $(BASEDIR)/public/sdk/inc/crt/limits.h \
+ $(BASEDIR)/public/sdk/inc/crt/stdarg.h $(BASEDIR)/public/sdk/inc/crt/stddef.h \
+ $(BASEDIR)/public/sdk/inc/crt/string.h $(BASEDIR)/public/sdk/inc/devioctl.h \
+ $(BASEDIR)/public/sdk/inc/lintfunc.hxx $(BASEDIR)/public/sdk/inc/mipsinst.h \
+ $(BASEDIR)/public/sdk/inc/nb30.h $(BASEDIR)/public/sdk/inc/netevent.h \
+ $(BASEDIR)/public/sdk/inc/nt.h $(BASEDIR)/public/sdk/inc/ntalpha.h \
+ $(BASEDIR)/public/sdk/inc/ntconfig.h $(BASEDIR)/public/sdk/inc/ntddtdi.h \
+ $(BASEDIR)/public/sdk/inc/ntdef.h $(BASEDIR)/public/sdk/inc/ntelfapi.h \
+ $(BASEDIR)/public/sdk/inc/ntexapi.h $(BASEDIR)/public/sdk/inc/nti386.h \
+ $(BASEDIR)/public/sdk/inc/ntimage.h $(BASEDIR)/public/sdk/inc/ntioapi.h \
+ $(BASEDIR)/public/sdk/inc/ntiolog.h $(BASEDIR)/public/sdk/inc/ntkeapi.h \
+ $(BASEDIR)/public/sdk/inc/ntldr.h $(BASEDIR)/public/sdk/inc/ntlpcapi.h \
+ $(BASEDIR)/public/sdk/inc/ntmips.h $(BASEDIR)/public/sdk/inc/ntmmapi.h \
+ $(BASEDIR)/public/sdk/inc/ntnls.h $(BASEDIR)/public/sdk/inc/ntobapi.h \
+ $(BASEDIR)/public/sdk/inc/ntppc.h $(BASEDIR)/public/sdk/inc/ntpsapi.h \
+ $(BASEDIR)/public/sdk/inc/ntregapi.h $(BASEDIR)/public/sdk/inc/ntrtl.h \
+ $(BASEDIR)/public/sdk/inc/ntseapi.h $(BASEDIR)/public/sdk/inc/ntstatus.h \
+ $(BASEDIR)/public/sdk/inc/ntxcapi.h $(BASEDIR)/public/sdk/inc/poppack.h \
+ $(BASEDIR)/public/sdk/inc/ppcinst.h $(BASEDIR)/public/sdk/inc/pshpack1.h \
+ $(BASEDIR)/public/sdk/inc/pshpack4.h $(BASEDIR)/public/sdk/inc/windef.h \
+ $(BASEDIR)/public/sdk/inc/winerror.h $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(SNOVNBTOBJD)/init.obj $(SNODVNBTOBJD)/init.obj $(VNBTSRC)/init.lst: \
+ $(VNBTSRC)/init.c ../$(INC)/alpha.h ../$(INC)/alpharef.h ../$(INC)/arc.h \
+ ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h ../blt/dhcpinfo.h $(INC)/ctemacro.h \
+ $(INC)/debug.h $(INC)/hosts.h $(INC)/nbtinfo.h $(INC)/nbtnt.h \
+ $(INC)/nbtprocs.h $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h \
+ $(INC)/vxddebug.h $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h \
+ $(CHICAGO)/tcp/h/tdivxd.h $(BASEDIR)/private/inc/ipinfo.h \
+ $(BASEDIR)/private/inc/nbtioctl.h $(BASEDIR)/private/inc/nettypes.h \
+ $(BASEDIR)/private/inc/packoff.h $(BASEDIR)/private/inc/packon.h \
+ $(BASEDIR)/private/inc/sockets/netinet/in.h $(BASEDIR)/private/inc/status.h \
+ $(BASEDIR)/private/inc/sys/snet/ip_proto.h $(BASEDIR)/private/inc/tdi.h \
+ $(BASEDIR)/private/inc/tdiinfo.h $(BASEDIR)/private/inc/tdikrnl.h \
+ $(BASEDIR)/private/inc/tdistat.h $(BASEDIR)/public/sdk/inc/alphaops.h \
+ $(BASEDIR)/public/sdk/inc/crt/ctype.h $(BASEDIR)/public/sdk/inc/crt/excpt.h \
+ $(BASEDIR)/public/sdk/inc/crt/limits.h $(BASEDIR)/public/sdk/inc/crt/stdarg.h \
+ $(BASEDIR)/public/sdk/inc/crt/stddef.h $(BASEDIR)/public/sdk/inc/crt/string.h \
+ $(BASEDIR)/public/sdk/inc/devioctl.h $(BASEDIR)/public/sdk/inc/lintfunc.hxx \
+ $(BASEDIR)/public/sdk/inc/mipsinst.h $(BASEDIR)/public/sdk/inc/nb30.h \
+ $(BASEDIR)/public/sdk/inc/netevent.h $(BASEDIR)/public/sdk/inc/nt.h \
+ $(BASEDIR)/public/sdk/inc/ntalpha.h $(BASEDIR)/public/sdk/inc/ntconfig.h \
+ $(BASEDIR)/public/sdk/inc/ntddtdi.h $(BASEDIR)/public/sdk/inc/ntdef.h \
+ $(BASEDIR)/public/sdk/inc/ntelfapi.h $(BASEDIR)/public/sdk/inc/ntexapi.h \
+ $(BASEDIR)/public/sdk/inc/nti386.h $(BASEDIR)/public/sdk/inc/ntimage.h \
+ $(BASEDIR)/public/sdk/inc/ntioapi.h $(BASEDIR)/public/sdk/inc/ntiolog.h \
+ $(BASEDIR)/public/sdk/inc/ntkeapi.h $(BASEDIR)/public/sdk/inc/ntldr.h \
+ $(BASEDIR)/public/sdk/inc/ntlpcapi.h $(BASEDIR)/public/sdk/inc/ntmips.h \
+ $(BASEDIR)/public/sdk/inc/ntmmapi.h $(BASEDIR)/public/sdk/inc/ntnls.h \
+ $(BASEDIR)/public/sdk/inc/ntobapi.h $(BASEDIR)/public/sdk/inc/ntppc.h \
+ $(BASEDIR)/public/sdk/inc/ntpsapi.h $(BASEDIR)/public/sdk/inc/ntregapi.h \
+ $(BASEDIR)/public/sdk/inc/ntrtl.h $(BASEDIR)/public/sdk/inc/ntseapi.h \
+ $(BASEDIR)/public/sdk/inc/ntstatus.h $(BASEDIR)/public/sdk/inc/ntxcapi.h \
+ $(BASEDIR)/public/sdk/inc/poppack.h $(BASEDIR)/public/sdk/inc/ppcinst.h \
+ $(BASEDIR)/public/sdk/inc/pshpack1.h $(BASEDIR)/public/sdk/inc/pshpack4.h \
+ $(BASEDIR)/public/sdk/inc/windef.h $(BASEDIR)/public/sdk/inc/winerror.h \
+ $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(SNOVNBTOBJD)/nbtinfo.obj $(SNODVNBTOBJD)/nbtinfo.obj $(VNBTSRC)/nbtinfo.lst: \
+ $(VNBTSRC)/nbtinfo.c ../$(INC)/alpha.h ../$(INC)/alpharef.h \
+ ../$(INC)/arc.h ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h ../blt/dhcpinfo.h $(INC)/ctemacro.h \
+ $(INC)/debug.h $(INC)/nbtinfo.h $(INC)/nbtnt.h $(INC)/nbtprocs.h \
+ $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h $(INC)/vxddebug.h \
+ $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h $(CHICAGO)/tcp/h/tdivxd.h \
+ $(BASEDIR)/private/inc/nbtioctl.h $(BASEDIR)/private/inc/nettypes.h \
+ $(BASEDIR)/private/inc/packoff.h $(BASEDIR)/private/inc/packon.h \
+ $(BASEDIR)/private/inc/sockets/netinet/in.h $(BASEDIR)/private/inc/status.h \
+ $(BASEDIR)/private/inc/sys/snet/ip_proto.h $(BASEDIR)/private/inc/tdi.h \
+ $(BASEDIR)/private/inc/tdikrnl.h $(BASEDIR)/private/inc/tdistat.h \
+ $(BASEDIR)/public/sdk/inc/alphaops.h $(BASEDIR)/public/sdk/inc/crt/ctype.h \
+ $(BASEDIR)/public/sdk/inc/crt/excpt.h $(BASEDIR)/public/sdk/inc/crt/limits.h \
+ $(BASEDIR)/public/sdk/inc/crt/stdarg.h $(BASEDIR)/public/sdk/inc/crt/stddef.h \
+ $(BASEDIR)/public/sdk/inc/crt/string.h $(BASEDIR)/public/sdk/inc/devioctl.h \
+ $(BASEDIR)/public/sdk/inc/lintfunc.hxx $(BASEDIR)/public/sdk/inc/mipsinst.h \
+ $(BASEDIR)/public/sdk/inc/nb30.h $(BASEDIR)/public/sdk/inc/netevent.h \
+ $(BASEDIR)/public/sdk/inc/nt.h $(BASEDIR)/public/sdk/inc/ntalpha.h \
+ $(BASEDIR)/public/sdk/inc/ntconfig.h $(BASEDIR)/public/sdk/inc/ntddtdi.h \
+ $(BASEDIR)/public/sdk/inc/ntdef.h $(BASEDIR)/public/sdk/inc/ntelfapi.h \
+ $(BASEDIR)/public/sdk/inc/ntexapi.h $(BASEDIR)/public/sdk/inc/nti386.h \
+ $(BASEDIR)/public/sdk/inc/ntimage.h $(BASEDIR)/public/sdk/inc/ntioapi.h \
+ $(BASEDIR)/public/sdk/inc/ntiolog.h $(BASEDIR)/public/sdk/inc/ntkeapi.h \
+ $(BASEDIR)/public/sdk/inc/ntldr.h $(BASEDIR)/public/sdk/inc/ntlpcapi.h \
+ $(BASEDIR)/public/sdk/inc/ntmips.h $(BASEDIR)/public/sdk/inc/ntmmapi.h \
+ $(BASEDIR)/public/sdk/inc/ntnls.h $(BASEDIR)/public/sdk/inc/ntobapi.h \
+ $(BASEDIR)/public/sdk/inc/ntppc.h $(BASEDIR)/public/sdk/inc/ntpsapi.h \
+ $(BASEDIR)/public/sdk/inc/ntregapi.h $(BASEDIR)/public/sdk/inc/ntrtl.h \
+ $(BASEDIR)/public/sdk/inc/ntseapi.h $(BASEDIR)/public/sdk/inc/ntstatus.h \
+ $(BASEDIR)/public/sdk/inc/ntxcapi.h $(BASEDIR)/public/sdk/inc/poppack.h \
+ $(BASEDIR)/public/sdk/inc/ppcinst.h $(BASEDIR)/public/sdk/inc/pshpack1.h \
+ $(BASEDIR)/public/sdk/inc/pshpack4.h $(BASEDIR)/public/sdk/inc/windef.h \
+ $(BASEDIR)/public/sdk/inc/winerror.h $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(SNOVNBTOBJD)/ncb.obj $(SNODVNBTOBJD)/ncb.obj $(VNBTSRC)/ncb.lst: $(VNBTSRC)/ncb.c \
+ ../$(INC)/alpha.h ../$(INC)/alpharef.h ../$(INC)/arc.h \
+ ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h $(INC)/ctemacro.h $(INC)/debug.h $(INC)/nbtnt.h \
+ $(INC)/nbtprocs.h $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h \
+ $(INC)/vxddebug.h $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h \
+ $(CHICAGO)/tcp/h/tdivxd.h $(BASEDIR)/private/inc/nbtioctl.h \
+ $(BASEDIR)/private/inc/nettypes.h $(BASEDIR)/private/inc/packoff.h \
+ $(BASEDIR)/private/inc/packon.h $(BASEDIR)/private/inc/sockets/netinet/in.h \
+ $(BASEDIR)/private/inc/status.h $(BASEDIR)/private/inc/sys/snet/ip_proto.h \
+ $(BASEDIR)/private/inc/tdi.h $(BASEDIR)/private/inc/tdikrnl.h \
+ $(BASEDIR)/private/inc/tdistat.h $(BASEDIR)/public/sdk/inc/alphaops.h \
+ $(BASEDIR)/public/sdk/inc/crt/ctype.h $(BASEDIR)/public/sdk/inc/crt/excpt.h \
+ $(BASEDIR)/public/sdk/inc/crt/limits.h $(BASEDIR)/public/sdk/inc/crt/stdarg.h \
+ $(BASEDIR)/public/sdk/inc/crt/stddef.h $(BASEDIR)/public/sdk/inc/crt/string.h \
+ $(BASEDIR)/public/sdk/inc/devioctl.h $(BASEDIR)/public/sdk/inc/lintfunc.hxx \
+ $(BASEDIR)/public/sdk/inc/mipsinst.h $(BASEDIR)/public/sdk/inc/nb30.h \
+ $(BASEDIR)/public/sdk/inc/netevent.h $(BASEDIR)/public/sdk/inc/nt.h \
+ $(BASEDIR)/public/sdk/inc/ntalpha.h $(BASEDIR)/public/sdk/inc/ntconfig.h \
+ $(BASEDIR)/public/sdk/inc/ntddtdi.h $(BASEDIR)/public/sdk/inc/ntdef.h \
+ $(BASEDIR)/public/sdk/inc/ntelfapi.h $(BASEDIR)/public/sdk/inc/ntexapi.h \
+ $(BASEDIR)/public/sdk/inc/nti386.h $(BASEDIR)/public/sdk/inc/ntimage.h \
+ $(BASEDIR)/public/sdk/inc/ntioapi.h $(BASEDIR)/public/sdk/inc/ntiolog.h \
+ $(BASEDIR)/public/sdk/inc/ntkeapi.h $(BASEDIR)/public/sdk/inc/ntldr.h \
+ $(BASEDIR)/public/sdk/inc/ntlpcapi.h $(BASEDIR)/public/sdk/inc/ntmips.h \
+ $(BASEDIR)/public/sdk/inc/ntmmapi.h $(BASEDIR)/public/sdk/inc/ntnls.h \
+ $(BASEDIR)/public/sdk/inc/ntobapi.h $(BASEDIR)/public/sdk/inc/ntppc.h \
+ $(BASEDIR)/public/sdk/inc/ntpsapi.h $(BASEDIR)/public/sdk/inc/ntregapi.h \
+ $(BASEDIR)/public/sdk/inc/ntrtl.h $(BASEDIR)/public/sdk/inc/ntseapi.h \
+ $(BASEDIR)/public/sdk/inc/ntstatus.h $(BASEDIR)/public/sdk/inc/ntxcapi.h \
+ $(BASEDIR)/public/sdk/inc/poppack.h $(BASEDIR)/public/sdk/inc/ppcinst.h \
+ $(BASEDIR)/public/sdk/inc/pshpack1.h $(BASEDIR)/public/sdk/inc/pshpack4.h \
+ $(BASEDIR)/public/sdk/inc/windef.h $(BASEDIR)/public/sdk/inc/winerror.h \
+ $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(SNOVNBTOBJD)/tdiaddr.obj $(SNODVNBTOBJD)/tdiaddr.obj $(VNBTSRC)/tdiaddr.lst: \
+ $(VNBTSRC)/tdiaddr.c ../$(INC)/alpha.h ../$(INC)/alpharef.h \
+ ../$(INC)/arc.h ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h $(INC)/ctemacro.h $(INC)/debug.h $(INC)/nbtnt.h \
+ $(INC)/nbtprocs.h $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h \
+ $(INC)/vxddebug.h $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h \
+ $(CHICAGO)/tcp/h/tdivxd.h $(BASEDIR)/private/inc/nbtioctl.h \
+ $(BASEDIR)/private/inc/nettypes.h $(BASEDIR)/private/inc/packoff.h \
+ $(BASEDIR)/private/inc/packon.h $(BASEDIR)/private/inc/sockets/netinet/in.h \
+ $(BASEDIR)/private/inc/status.h $(BASEDIR)/private/inc/sys/snet/ip_proto.h \
+ $(BASEDIR)/private/inc/tdi.h $(BASEDIR)/private/inc/tdikrnl.h \
+ $(BASEDIR)/private/inc/tdistat.h $(BASEDIR)/public/sdk/inc/alphaops.h \
+ $(BASEDIR)/public/sdk/inc/crt/ctype.h $(BASEDIR)/public/sdk/inc/crt/excpt.h \
+ $(BASEDIR)/public/sdk/inc/crt/limits.h $(BASEDIR)/public/sdk/inc/crt/stdarg.h \
+ $(BASEDIR)/public/sdk/inc/crt/stddef.h $(BASEDIR)/public/sdk/inc/crt/string.h \
+ $(BASEDIR)/public/sdk/inc/devioctl.h $(BASEDIR)/public/sdk/inc/lintfunc.hxx \
+ $(BASEDIR)/public/sdk/inc/mipsinst.h $(BASEDIR)/public/sdk/inc/nb30.h \
+ $(BASEDIR)/public/sdk/inc/netevent.h $(BASEDIR)/public/sdk/inc/nt.h \
+ $(BASEDIR)/public/sdk/inc/ntalpha.h $(BASEDIR)/public/sdk/inc/ntconfig.h \
+ $(BASEDIR)/public/sdk/inc/ntddtdi.h $(BASEDIR)/public/sdk/inc/ntdef.h \
+ $(BASEDIR)/public/sdk/inc/ntelfapi.h $(BASEDIR)/public/sdk/inc/ntexapi.h \
+ $(BASEDIR)/public/sdk/inc/nti386.h $(BASEDIR)/public/sdk/inc/ntimage.h \
+ $(BASEDIR)/public/sdk/inc/ntioapi.h $(BASEDIR)/public/sdk/inc/ntiolog.h \
+ $(BASEDIR)/public/sdk/inc/ntkeapi.h $(BASEDIR)/public/sdk/inc/ntldr.h \
+ $(BASEDIR)/public/sdk/inc/ntlpcapi.h $(BASEDIR)/public/sdk/inc/ntmips.h \
+ $(BASEDIR)/public/sdk/inc/ntmmapi.h $(BASEDIR)/public/sdk/inc/ntnls.h \
+ $(BASEDIR)/public/sdk/inc/ntobapi.h $(BASEDIR)/public/sdk/inc/ntppc.h \
+ $(BASEDIR)/public/sdk/inc/ntpsapi.h $(BASEDIR)/public/sdk/inc/ntregapi.h \
+ $(BASEDIR)/public/sdk/inc/ntrtl.h $(BASEDIR)/public/sdk/inc/ntseapi.h \
+ $(BASEDIR)/public/sdk/inc/ntstatus.h $(BASEDIR)/public/sdk/inc/ntxcapi.h \
+ $(BASEDIR)/public/sdk/inc/poppack.h $(BASEDIR)/public/sdk/inc/ppcinst.h \
+ $(BASEDIR)/public/sdk/inc/pshpack1.h $(BASEDIR)/public/sdk/inc/pshpack4.h \
+ $(BASEDIR)/public/sdk/inc/windef.h $(BASEDIR)/public/sdk/inc/winerror.h \
+ $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(SNOVNBTOBJD)/tdicnct.obj $(SNODVNBTOBJD)/tdicnct.obj $(VNBTSRC)/tdicnct.lst: \
+ $(VNBTSRC)/tdicnct.c ../$(INC)/alpha.h ../$(INC)/alpharef.h \
+ ../$(INC)/arc.h ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h $(INC)/ctemacro.h $(INC)/debug.h $(INC)/nbtnt.h \
+ $(INC)/nbtprocs.h $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h \
+ $(INC)/vxddebug.h $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h \
+ $(CHICAGO)/tcp/h/tdivxd.h $(BASEDIR)/private/inc/nbtioctl.h \
+ $(BASEDIR)/private/inc/nettypes.h $(BASEDIR)/private/inc/packoff.h \
+ $(BASEDIR)/private/inc/packon.h $(BASEDIR)/private/inc/sockets/netinet/in.h \
+ $(BASEDIR)/private/inc/status.h $(BASEDIR)/private/inc/sys/snet/ip_proto.h \
+ $(BASEDIR)/private/inc/tdi.h $(BASEDIR)/private/inc/tdikrnl.h \
+ $(BASEDIR)/private/inc/tdistat.h $(BASEDIR)/public/sdk/inc/alphaops.h \
+ $(BASEDIR)/public/sdk/inc/crt/ctype.h $(BASEDIR)/public/sdk/inc/crt/excpt.h \
+ $(BASEDIR)/public/sdk/inc/crt/limits.h $(BASEDIR)/public/sdk/inc/crt/stdarg.h \
+ $(BASEDIR)/public/sdk/inc/crt/stddef.h $(BASEDIR)/public/sdk/inc/crt/string.h \
+ $(BASEDIR)/public/sdk/inc/devioctl.h $(BASEDIR)/public/sdk/inc/lintfunc.hxx \
+ $(BASEDIR)/public/sdk/inc/mipsinst.h $(BASEDIR)/public/sdk/inc/nb30.h \
+ $(BASEDIR)/public/sdk/inc/netevent.h $(BASEDIR)/public/sdk/inc/nt.h \
+ $(BASEDIR)/public/sdk/inc/ntalpha.h $(BASEDIR)/public/sdk/inc/ntconfig.h \
+ $(BASEDIR)/public/sdk/inc/ntddtdi.h $(BASEDIR)/public/sdk/inc/ntdef.h \
+ $(BASEDIR)/public/sdk/inc/ntelfapi.h $(BASEDIR)/public/sdk/inc/ntexapi.h \
+ $(BASEDIR)/public/sdk/inc/nti386.h $(BASEDIR)/public/sdk/inc/ntimage.h \
+ $(BASEDIR)/public/sdk/inc/ntioapi.h $(BASEDIR)/public/sdk/inc/ntiolog.h \
+ $(BASEDIR)/public/sdk/inc/ntkeapi.h $(BASEDIR)/public/sdk/inc/ntldr.h \
+ $(BASEDIR)/public/sdk/inc/ntlpcapi.h $(BASEDIR)/public/sdk/inc/ntmips.h \
+ $(BASEDIR)/public/sdk/inc/ntmmapi.h $(BASEDIR)/public/sdk/inc/ntnls.h \
+ $(BASEDIR)/public/sdk/inc/ntobapi.h $(BASEDIR)/public/sdk/inc/ntppc.h \
+ $(BASEDIR)/public/sdk/inc/ntpsapi.h $(BASEDIR)/public/sdk/inc/ntregapi.h \
+ $(BASEDIR)/public/sdk/inc/ntrtl.h $(BASEDIR)/public/sdk/inc/ntseapi.h \
+ $(BASEDIR)/public/sdk/inc/ntstatus.h $(BASEDIR)/public/sdk/inc/ntxcapi.h \
+ $(BASEDIR)/public/sdk/inc/poppack.h $(BASEDIR)/public/sdk/inc/ppcinst.h \
+ $(BASEDIR)/public/sdk/inc/pshpack1.h $(BASEDIR)/public/sdk/inc/pshpack4.h \
+ $(BASEDIR)/public/sdk/inc/windef.h $(BASEDIR)/public/sdk/inc/winerror.h \
+ $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(SNOVNBTOBJD)/tdihndlr.obj $(SNODVNBTOBJD)/tdihndlr.obj $(VNBTSRC)/tdihndlr.lst: \
+ $(VNBTSRC)/tdihndlr.c ../$(INC)/alpha.h ../$(INC)/alpharef.h \
+ ../$(INC)/arc.h ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h $(INC)/ctemacro.h $(INC)/debug.h $(INC)/nbtnt.h \
+ $(INC)/nbtprocs.h $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h \
+ $(INC)/vxddebug.h $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h \
+ $(CHICAGO)/tcp/h/tdivxd.h $(BASEDIR)/private/inc/nbtioctl.h \
+ $(BASEDIR)/private/inc/nettypes.h $(BASEDIR)/private/inc/packoff.h \
+ $(BASEDIR)/private/inc/packon.h $(BASEDIR)/private/inc/sockets/netinet/in.h \
+ $(BASEDIR)/private/inc/status.h $(BASEDIR)/private/inc/sys/snet/ip_proto.h \
+ $(BASEDIR)/private/inc/tdi.h $(BASEDIR)/private/inc/tdikrnl.h \
+ $(BASEDIR)/private/inc/tdistat.h $(BASEDIR)/public/sdk/inc/alphaops.h \
+ $(BASEDIR)/public/sdk/inc/crt/ctype.h $(BASEDIR)/public/sdk/inc/crt/excpt.h \
+ $(BASEDIR)/public/sdk/inc/crt/limits.h $(BASEDIR)/public/sdk/inc/crt/stdarg.h \
+ $(BASEDIR)/public/sdk/inc/crt/stddef.h $(BASEDIR)/public/sdk/inc/crt/string.h \
+ $(BASEDIR)/public/sdk/inc/devioctl.h $(BASEDIR)/public/sdk/inc/lintfunc.hxx \
+ $(BASEDIR)/public/sdk/inc/mipsinst.h $(BASEDIR)/public/sdk/inc/nb30.h \
+ $(BASEDIR)/public/sdk/inc/netevent.h $(BASEDIR)/public/sdk/inc/nt.h \
+ $(BASEDIR)/public/sdk/inc/ntalpha.h $(BASEDIR)/public/sdk/inc/ntconfig.h \
+ $(BASEDIR)/public/sdk/inc/ntddtdi.h $(BASEDIR)/public/sdk/inc/ntdef.h \
+ $(BASEDIR)/public/sdk/inc/ntelfapi.h $(BASEDIR)/public/sdk/inc/ntexapi.h \
+ $(BASEDIR)/public/sdk/inc/nti386.h $(BASEDIR)/public/sdk/inc/ntimage.h \
+ $(BASEDIR)/public/sdk/inc/ntioapi.h $(BASEDIR)/public/sdk/inc/ntiolog.h \
+ $(BASEDIR)/public/sdk/inc/ntkeapi.h $(BASEDIR)/public/sdk/inc/ntldr.h \
+ $(BASEDIR)/public/sdk/inc/ntlpcapi.h $(BASEDIR)/public/sdk/inc/ntmips.h \
+ $(BASEDIR)/public/sdk/inc/ntmmapi.h $(BASEDIR)/public/sdk/inc/ntnls.h \
+ $(BASEDIR)/public/sdk/inc/ntobapi.h $(BASEDIR)/public/sdk/inc/ntppc.h \
+ $(BASEDIR)/public/sdk/inc/ntpsapi.h $(BASEDIR)/public/sdk/inc/ntregapi.h \
+ $(BASEDIR)/public/sdk/inc/ntrtl.h $(BASEDIR)/public/sdk/inc/ntseapi.h \
+ $(BASEDIR)/public/sdk/inc/ntstatus.h $(BASEDIR)/public/sdk/inc/ntxcapi.h \
+ $(BASEDIR)/public/sdk/inc/poppack.h $(BASEDIR)/public/sdk/inc/ppcinst.h \
+ $(BASEDIR)/public/sdk/inc/pshpack1.h $(BASEDIR)/public/sdk/inc/pshpack4.h \
+ $(BASEDIR)/public/sdk/inc/windef.h $(BASEDIR)/public/sdk/inc/winerror.h \
+ $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(SNOVNBTOBJD)/tdiout.obj $(SNODVNBTOBJD)/tdiout.obj $(VNBTSRC)/tdiout.lst: \
+ $(VNBTSRC)/tdiout.c ../$(INC)/alpha.h ../$(INC)/alpharef.h \
+ ../$(INC)/arc.h ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h $(INC)/ctemacro.h $(INC)/debug.h $(INC)/nbtnt.h \
+ $(INC)/nbtprocs.h $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h \
+ $(INC)/vxddebug.h $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h \
+ $(CHICAGO)/tcp/h/tdivxd.h $(BASEDIR)/private/inc/nbtioctl.h \
+ $(BASEDIR)/private/inc/nettypes.h $(BASEDIR)/private/inc/packoff.h \
+ $(BASEDIR)/private/inc/packon.h $(BASEDIR)/private/inc/sockets/netinet/in.h \
+ $(BASEDIR)/private/inc/status.h $(BASEDIR)/private/inc/sys/snet/ip_proto.h \
+ $(BASEDIR)/private/inc/tdi.h $(BASEDIR)/private/inc/tdikrnl.h \
+ $(BASEDIR)/private/inc/tdistat.h $(BASEDIR)/public/sdk/inc/alphaops.h \
+ $(BASEDIR)/public/sdk/inc/crt/ctype.h $(BASEDIR)/public/sdk/inc/crt/excpt.h \
+ $(BASEDIR)/public/sdk/inc/crt/limits.h $(BASEDIR)/public/sdk/inc/crt/stdarg.h \
+ $(BASEDIR)/public/sdk/inc/crt/stddef.h $(BASEDIR)/public/sdk/inc/crt/string.h \
+ $(BASEDIR)/public/sdk/inc/devioctl.h $(BASEDIR)/public/sdk/inc/lintfunc.hxx \
+ $(BASEDIR)/public/sdk/inc/mipsinst.h $(BASEDIR)/public/sdk/inc/nb30.h \
+ $(BASEDIR)/public/sdk/inc/netevent.h $(BASEDIR)/public/sdk/inc/nt.h \
+ $(BASEDIR)/public/sdk/inc/ntalpha.h $(BASEDIR)/public/sdk/inc/ntconfig.h \
+ $(BASEDIR)/public/sdk/inc/ntddtdi.h $(BASEDIR)/public/sdk/inc/ntdef.h \
+ $(BASEDIR)/public/sdk/inc/ntelfapi.h $(BASEDIR)/public/sdk/inc/ntexapi.h \
+ $(BASEDIR)/public/sdk/inc/nti386.h $(BASEDIR)/public/sdk/inc/ntimage.h \
+ $(BASEDIR)/public/sdk/inc/ntioapi.h $(BASEDIR)/public/sdk/inc/ntiolog.h \
+ $(BASEDIR)/public/sdk/inc/ntkeapi.h $(BASEDIR)/public/sdk/inc/ntldr.h \
+ $(BASEDIR)/public/sdk/inc/ntlpcapi.h $(BASEDIR)/public/sdk/inc/ntmips.h \
+ $(BASEDIR)/public/sdk/inc/ntmmapi.h $(BASEDIR)/public/sdk/inc/ntnls.h \
+ $(BASEDIR)/public/sdk/inc/ntobapi.h $(BASEDIR)/public/sdk/inc/ntppc.h \
+ $(BASEDIR)/public/sdk/inc/ntpsapi.h $(BASEDIR)/public/sdk/inc/ntregapi.h \
+ $(BASEDIR)/public/sdk/inc/ntrtl.h $(BASEDIR)/public/sdk/inc/ntseapi.h \
+ $(BASEDIR)/public/sdk/inc/ntstatus.h $(BASEDIR)/public/sdk/inc/ntxcapi.h \
+ $(BASEDIR)/public/sdk/inc/poppack.h $(BASEDIR)/public/sdk/inc/ppcinst.h \
+ $(BASEDIR)/public/sdk/inc/pshpack1.h $(BASEDIR)/public/sdk/inc/pshpack4.h \
+ $(BASEDIR)/public/sdk/inc/windef.h $(BASEDIR)/public/sdk/inc/winerror.h \
+ $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(SNOVNBTOBJD)/timer.obj $(SNODVNBTOBJD)/timer.obj $(VNBTSRC)/timer.lst: \
+ $(VNBTSRC)/timer.c ../$(INC)/alpha.h ../$(INC)/alpharef.h ../$(INC)/arc.h \
+ ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h $(INC)/ctemacro.h $(INC)/debug.h $(INC)/nbtnt.h \
+ $(INC)/nbtprocs.h $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h \
+ $(INC)/vxddebug.h $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h \
+ $(CHICAGO)/tcp/h/tdivxd.h $(BASEDIR)/private/inc/nbtioctl.h \
+ $(BASEDIR)/private/inc/nettypes.h $(BASEDIR)/private/inc/packoff.h \
+ $(BASEDIR)/private/inc/packon.h $(BASEDIR)/private/inc/sockets/netinet/in.h \
+ $(BASEDIR)/private/inc/status.h $(BASEDIR)/private/inc/sys/snet/ip_proto.h \
+ $(BASEDIR)/private/inc/tdi.h $(BASEDIR)/private/inc/tdikrnl.h \
+ $(BASEDIR)/private/inc/tdistat.h $(BASEDIR)/public/sdk/inc/alphaops.h \
+ $(BASEDIR)/public/sdk/inc/crt/ctype.h $(BASEDIR)/public/sdk/inc/crt/excpt.h \
+ $(BASEDIR)/public/sdk/inc/crt/limits.h $(BASEDIR)/public/sdk/inc/crt/stdarg.h \
+ $(BASEDIR)/public/sdk/inc/crt/stddef.h $(BASEDIR)/public/sdk/inc/crt/string.h \
+ $(BASEDIR)/public/sdk/inc/devioctl.h $(BASEDIR)/public/sdk/inc/lintfunc.hxx \
+ $(BASEDIR)/public/sdk/inc/mipsinst.h $(BASEDIR)/public/sdk/inc/nb30.h \
+ $(BASEDIR)/public/sdk/inc/netevent.h $(BASEDIR)/public/sdk/inc/nt.h \
+ $(BASEDIR)/public/sdk/inc/ntalpha.h $(BASEDIR)/public/sdk/inc/ntconfig.h \
+ $(BASEDIR)/public/sdk/inc/ntddtdi.h $(BASEDIR)/public/sdk/inc/ntdef.h \
+ $(BASEDIR)/public/sdk/inc/ntelfapi.h $(BASEDIR)/public/sdk/inc/ntexapi.h \
+ $(BASEDIR)/public/sdk/inc/nti386.h $(BASEDIR)/public/sdk/inc/ntimage.h \
+ $(BASEDIR)/public/sdk/inc/ntioapi.h $(BASEDIR)/public/sdk/inc/ntiolog.h \
+ $(BASEDIR)/public/sdk/inc/ntkeapi.h $(BASEDIR)/public/sdk/inc/ntldr.h \
+ $(BASEDIR)/public/sdk/inc/ntlpcapi.h $(BASEDIR)/public/sdk/inc/ntmips.h \
+ $(BASEDIR)/public/sdk/inc/ntmmapi.h $(BASEDIR)/public/sdk/inc/ntnls.h \
+ $(BASEDIR)/public/sdk/inc/ntobapi.h $(BASEDIR)/public/sdk/inc/ntppc.h \
+ $(BASEDIR)/public/sdk/inc/ntpsapi.h $(BASEDIR)/public/sdk/inc/ntregapi.h \
+ $(BASEDIR)/public/sdk/inc/ntrtl.h $(BASEDIR)/public/sdk/inc/ntseapi.h \
+ $(BASEDIR)/public/sdk/inc/ntstatus.h $(BASEDIR)/public/sdk/inc/ntxcapi.h \
+ $(BASEDIR)/public/sdk/inc/poppack.h $(BASEDIR)/public/sdk/inc/ppcinst.h \
+ $(BASEDIR)/public/sdk/inc/pshpack1.h $(BASEDIR)/public/sdk/inc/pshpack4.h \
+ $(BASEDIR)/public/sdk/inc/windef.h $(BASEDIR)/public/sdk/inc/winerror.h \
+ $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(SNOVNBTOBJD)/util.obj $(SNODVNBTOBJD)/util.obj $(VNBTSRC)/util.lst: \
+ $(VNBTSRC)/util.c ../$(INC)/alpha.h ../$(INC)/alpharef.h ../$(INC)/arc.h \
+ ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h $(INC)/ctemacro.h $(INC)/debug.h $(INC)/nbtnt.h \
+ $(INC)/nbtprocs.h $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h \
+ $(INC)/vxddebug.h $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h \
+ $(CHICAGO)/tcp/h/tdivxd.h $(BASEDIR)/private/inc/nbtioctl.h \
+ $(BASEDIR)/private/inc/nettypes.h $(BASEDIR)/private/inc/packoff.h \
+ $(BASEDIR)/private/inc/packon.h $(BASEDIR)/private/inc/sockets/netinet/in.h \
+ $(BASEDIR)/private/inc/status.h $(BASEDIR)/private/inc/sys/snet/ip_proto.h \
+ $(BASEDIR)/private/inc/tdi.h $(BASEDIR)/private/inc/tdikrnl.h \
+ $(BASEDIR)/private/inc/tdistat.h $(BASEDIR)/public/sdk/inc/alphaops.h \
+ $(BASEDIR)/public/sdk/inc/crt/ctype.h $(BASEDIR)/public/sdk/inc/crt/excpt.h \
+ $(BASEDIR)/public/sdk/inc/crt/limits.h $(BASEDIR)/public/sdk/inc/crt/stdarg.h \
+ $(BASEDIR)/public/sdk/inc/crt/stddef.h $(BASEDIR)/public/sdk/inc/crt/string.h \
+ $(BASEDIR)/public/sdk/inc/devioctl.h $(BASEDIR)/public/sdk/inc/lintfunc.hxx \
+ $(BASEDIR)/public/sdk/inc/mipsinst.h $(BASEDIR)/public/sdk/inc/nb30.h \
+ $(BASEDIR)/public/sdk/inc/netevent.h $(BASEDIR)/public/sdk/inc/nt.h \
+ $(BASEDIR)/public/sdk/inc/ntalpha.h $(BASEDIR)/public/sdk/inc/ntconfig.h \
+ $(BASEDIR)/public/sdk/inc/ntddtdi.h $(BASEDIR)/public/sdk/inc/ntdef.h \
+ $(BASEDIR)/public/sdk/inc/ntelfapi.h $(BASEDIR)/public/sdk/inc/ntexapi.h \
+ $(BASEDIR)/public/sdk/inc/nti386.h $(BASEDIR)/public/sdk/inc/ntimage.h \
+ $(BASEDIR)/public/sdk/inc/ntioapi.h $(BASEDIR)/public/sdk/inc/ntiolog.h \
+ $(BASEDIR)/public/sdk/inc/ntkeapi.h $(BASEDIR)/public/sdk/inc/ntldr.h \
+ $(BASEDIR)/public/sdk/inc/ntlpcapi.h $(BASEDIR)/public/sdk/inc/ntmips.h \
+ $(BASEDIR)/public/sdk/inc/ntmmapi.h $(BASEDIR)/public/sdk/inc/ntnls.h \
+ $(BASEDIR)/public/sdk/inc/ntobapi.h $(BASEDIR)/public/sdk/inc/ntppc.h \
+ $(BASEDIR)/public/sdk/inc/ntpsapi.h $(BASEDIR)/public/sdk/inc/ntregapi.h \
+ $(BASEDIR)/public/sdk/inc/ntrtl.h $(BASEDIR)/public/sdk/inc/ntseapi.h \
+ $(BASEDIR)/public/sdk/inc/ntstatus.h $(BASEDIR)/public/sdk/inc/ntxcapi.h \
+ $(BASEDIR)/public/sdk/inc/poppack.h $(BASEDIR)/public/sdk/inc/ppcinst.h \
+ $(BASEDIR)/public/sdk/inc/pshpack1.h $(BASEDIR)/public/sdk/inc/pshpack4.h \
+ $(BASEDIR)/public/sdk/inc/windef.h $(BASEDIR)/public/sdk/inc/winerror.h \
+ $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(SNOVNBTOBJD)/vxddebug.obj $(SNODVNBTOBJD)/vxddebug.obj $(VNBTSRC)/vxddebug.lst: \
+ $(VNBTSRC)/vxddebug.c ../$(INC)/alpha.h ../$(INC)/alpharef.h \
+ ../$(INC)/arc.h ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h $(INC)/ctemacro.h $(INC)/debug.h $(INC)/nbtnt.h \
+ $(INC)/nbtprocs.h $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h \
+ $(INC)/vxddebug.h $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h \
+ $(CHICAGO)/tcp/h/tdivxd.h $(BASEDIR)/private/inc/nbtioctl.h \
+ $(BASEDIR)/private/inc/nettypes.h $(BASEDIR)/private/inc/packoff.h \
+ $(BASEDIR)/private/inc/packon.h $(BASEDIR)/private/inc/sockets/netinet/in.h \
+ $(BASEDIR)/private/inc/status.h $(BASEDIR)/private/inc/sys/snet/ip_proto.h \
+ $(BASEDIR)/private/inc/tdi.h $(BASEDIR)/private/inc/tdikrnl.h \
+ $(BASEDIR)/private/inc/tdistat.h $(BASEDIR)/public/sdk/inc/alphaops.h \
+ $(BASEDIR)/public/sdk/inc/crt/ctype.h $(BASEDIR)/public/sdk/inc/crt/excpt.h \
+ $(BASEDIR)/public/sdk/inc/crt/limits.h $(BASEDIR)/public/sdk/inc/crt/stdarg.h \
+ $(BASEDIR)/public/sdk/inc/crt/stddef.h $(BASEDIR)/public/sdk/inc/crt/string.h \
+ $(BASEDIR)/public/sdk/inc/devioctl.h $(BASEDIR)/public/sdk/inc/lintfunc.hxx \
+ $(BASEDIR)/public/sdk/inc/mipsinst.h $(BASEDIR)/public/sdk/inc/nb30.h \
+ $(BASEDIR)/public/sdk/inc/netevent.h $(BASEDIR)/public/sdk/inc/nt.h \
+ $(BASEDIR)/public/sdk/inc/ntalpha.h $(BASEDIR)/public/sdk/inc/ntconfig.h \
+ $(BASEDIR)/public/sdk/inc/ntddtdi.h $(BASEDIR)/public/sdk/inc/ntdef.h \
+ $(BASEDIR)/public/sdk/inc/ntelfapi.h $(BASEDIR)/public/sdk/inc/ntexapi.h \
+ $(BASEDIR)/public/sdk/inc/nti386.h $(BASEDIR)/public/sdk/inc/ntimage.h \
+ $(BASEDIR)/public/sdk/inc/ntioapi.h $(BASEDIR)/public/sdk/inc/ntiolog.h \
+ $(BASEDIR)/public/sdk/inc/ntkeapi.h $(BASEDIR)/public/sdk/inc/ntldr.h \
+ $(BASEDIR)/public/sdk/inc/ntlpcapi.h $(BASEDIR)/public/sdk/inc/ntmips.h \
+ $(BASEDIR)/public/sdk/inc/ntmmapi.h $(BASEDIR)/public/sdk/inc/ntnls.h \
+ $(BASEDIR)/public/sdk/inc/ntobapi.h $(BASEDIR)/public/sdk/inc/ntppc.h \
+ $(BASEDIR)/public/sdk/inc/ntpsapi.h $(BASEDIR)/public/sdk/inc/ntregapi.h \
+ $(BASEDIR)/public/sdk/inc/ntrtl.h $(BASEDIR)/public/sdk/inc/ntseapi.h \
+ $(BASEDIR)/public/sdk/inc/ntstatus.h $(BASEDIR)/public/sdk/inc/ntxcapi.h \
+ $(BASEDIR)/public/sdk/inc/poppack.h $(BASEDIR)/public/sdk/inc/ppcinst.h \
+ $(BASEDIR)/public/sdk/inc/pshpack1.h $(BASEDIR)/public/sdk/inc/pshpack4.h \
+ $(BASEDIR)/public/sdk/inc/windef.h $(BASEDIR)/public/sdk/inc/winerror.h \
+ $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(SNOVNBTOBJD)/vxdisol.obj $(SNODVNBTOBJD)/vxdisol.obj $(VNBTSRC)/vxdisol.lst: \
+ $(VNBTSRC)/vxdisol.c ../$(INC)/alpha.h ../$(INC)/alpharef.h \
+ ../$(INC)/arc.h ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h $(INC)/ctemacro.h $(INC)/debug.h $(INC)/nbtnt.h \
+ $(INC)/nbtprocs.h $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h \
+ $(INC)/vxddebug.h $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h \
+ $(CHICAGO)/tcp/h/tdivxd.h $(BASEDIR)/private/inc/nbtioctl.h \
+ $(BASEDIR)/private/inc/nettypes.h $(BASEDIR)/private/inc/packoff.h \
+ $(BASEDIR)/private/inc/packon.h $(BASEDIR)/private/inc/sockets/netinet/in.h \
+ $(BASEDIR)/private/inc/status.h $(BASEDIR)/private/inc/sys/snet/ip_proto.h \
+ $(BASEDIR)/private/inc/tdi.h $(BASEDIR)/private/inc/tdikrnl.h \
+ $(BASEDIR)/private/inc/tdistat.h $(BASEDIR)/public/sdk/inc/alphaops.h \
+ $(BASEDIR)/public/sdk/inc/crt/ctype.h $(BASEDIR)/public/sdk/inc/crt/excpt.h \
+ $(BASEDIR)/public/sdk/inc/crt/limits.h $(BASEDIR)/public/sdk/inc/crt/stdarg.h \
+ $(BASEDIR)/public/sdk/inc/crt/stddef.h $(BASEDIR)/public/sdk/inc/crt/string.h \
+ $(BASEDIR)/public/sdk/inc/devioctl.h $(BASEDIR)/public/sdk/inc/lintfunc.hxx \
+ $(BASEDIR)/public/sdk/inc/mipsinst.h $(BASEDIR)/public/sdk/inc/nb30.h \
+ $(BASEDIR)/public/sdk/inc/netevent.h $(BASEDIR)/public/sdk/inc/nt.h \
+ $(BASEDIR)/public/sdk/inc/ntalpha.h $(BASEDIR)/public/sdk/inc/ntconfig.h \
+ $(BASEDIR)/public/sdk/inc/ntddtdi.h $(BASEDIR)/public/sdk/inc/ntdef.h \
+ $(BASEDIR)/public/sdk/inc/ntelfapi.h $(BASEDIR)/public/sdk/inc/ntexapi.h \
+ $(BASEDIR)/public/sdk/inc/nti386.h $(BASEDIR)/public/sdk/inc/ntimage.h \
+ $(BASEDIR)/public/sdk/inc/ntioapi.h $(BASEDIR)/public/sdk/inc/ntiolog.h \
+ $(BASEDIR)/public/sdk/inc/ntkeapi.h $(BASEDIR)/public/sdk/inc/ntldr.h \
+ $(BASEDIR)/public/sdk/inc/ntlpcapi.h $(BASEDIR)/public/sdk/inc/ntmips.h \
+ $(BASEDIR)/public/sdk/inc/ntmmapi.h $(BASEDIR)/public/sdk/inc/ntnls.h \
+ $(BASEDIR)/public/sdk/inc/ntobapi.h $(BASEDIR)/public/sdk/inc/ntppc.h \
+ $(BASEDIR)/public/sdk/inc/ntpsapi.h $(BASEDIR)/public/sdk/inc/ntregapi.h \
+ $(BASEDIR)/public/sdk/inc/ntrtl.h $(BASEDIR)/public/sdk/inc/ntseapi.h \
+ $(BASEDIR)/public/sdk/inc/ntstatus.h $(BASEDIR)/public/sdk/inc/ntxcapi.h \
+ $(BASEDIR)/public/sdk/inc/poppack.h $(BASEDIR)/public/sdk/inc/ppcinst.h \
+ $(BASEDIR)/public/sdk/inc/pshpack1.h $(BASEDIR)/public/sdk/inc/pshpack4.h \
+ $(BASEDIR)/public/sdk/inc/windef.h $(BASEDIR)/public/sdk/inc/winerror.h \
+ $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(SNOVNBTOBJD)/wfw.obj $(SNODVNBTOBJD)/wfw.obj $(VNBTSRC)/wfw.lst: $(VNBTSRC)/wfw.c \
+ ../$(INC)/alpha.h ../$(INC)/alpharef.h ../$(INC)/arc.h \
+ ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h ../blt/dhcpinfo.h $(INC)/ctemacro.h \
+ $(INC)/debug.h $(INC)/nbtinfo.h $(INC)/nbtnt.h $(INC)/nbtprocs.h \
+ $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h $(INC)/vxddebug.h \
+ $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h $(CHICAGO)/tcp/h/tdivxd.h \
+ $(BASEDIR)/private/inc/ipinfo.h $(BASEDIR)/private/inc/llinfo.h \
+ $(BASEDIR)/private/inc/nbtioctl.h $(BASEDIR)/private/inc/nettypes.h \
+ $(BASEDIR)/private/inc/packoff.h $(BASEDIR)/private/inc/packon.h \
+ $(BASEDIR)/private/inc/sockets/netinet/in.h $(BASEDIR)/private/inc/status.h \
+ $(BASEDIR)/private/inc/sys/snet/ip_proto.h $(BASEDIR)/private/inc/tdi.h \
+ $(BASEDIR)/private/inc/tdiinfo.h $(BASEDIR)/private/inc/tdikrnl.h \
+ $(BASEDIR)/private/inc/tdistat.h $(BASEDIR)/public/sdk/inc/alphaops.h \
+ $(BASEDIR)/public/sdk/inc/crt/ctype.h $(BASEDIR)/public/sdk/inc/crt/excpt.h \
+ $(BASEDIR)/public/sdk/inc/crt/limits.h $(BASEDIR)/public/sdk/inc/crt/stdarg.h \
+ $(BASEDIR)/public/sdk/inc/crt/stddef.h $(BASEDIR)/public/sdk/inc/crt/string.h \
+ $(BASEDIR)/public/sdk/inc/devioctl.h $(BASEDIR)/public/sdk/inc/lintfunc.hxx \
+ $(BASEDIR)/public/sdk/inc/mipsinst.h $(BASEDIR)/public/sdk/inc/nb30.h \
+ $(BASEDIR)/public/sdk/inc/netevent.h $(BASEDIR)/public/sdk/inc/nt.h \
+ $(BASEDIR)/public/sdk/inc/ntalpha.h $(BASEDIR)/public/sdk/inc/ntconfig.h \
+ $(BASEDIR)/public/sdk/inc/ntddtdi.h $(BASEDIR)/public/sdk/inc/ntdef.h \
+ $(BASEDIR)/public/sdk/inc/ntelfapi.h $(BASEDIR)/public/sdk/inc/ntexapi.h \
+ $(BASEDIR)/public/sdk/inc/nti386.h $(BASEDIR)/public/sdk/inc/ntimage.h \
+ $(BASEDIR)/public/sdk/inc/ntioapi.h $(BASEDIR)/public/sdk/inc/ntiolog.h \
+ $(BASEDIR)/public/sdk/inc/ntkeapi.h $(BASEDIR)/public/sdk/inc/ntldr.h \
+ $(BASEDIR)/public/sdk/inc/ntlpcapi.h $(BASEDIR)/public/sdk/inc/ntmips.h \
+ $(BASEDIR)/public/sdk/inc/ntmmapi.h $(BASEDIR)/public/sdk/inc/ntnls.h \
+ $(BASEDIR)/public/sdk/inc/ntobapi.h $(BASEDIR)/public/sdk/inc/ntppc.h \
+ $(BASEDIR)/public/sdk/inc/ntpsapi.h $(BASEDIR)/public/sdk/inc/ntregapi.h \
+ $(BASEDIR)/public/sdk/inc/ntrtl.h $(BASEDIR)/public/sdk/inc/ntseapi.h \
+ $(BASEDIR)/public/sdk/inc/ntstatus.h $(BASEDIR)/public/sdk/inc/ntxcapi.h \
+ $(BASEDIR)/public/sdk/inc/poppack.h $(BASEDIR)/public/sdk/inc/ppcinst.h \
+ $(BASEDIR)/public/sdk/inc/pshpack1.h $(BASEDIR)/public/sdk/inc/pshpack4.h \
+ $(BASEDIR)/public/sdk/inc/windef.h $(BASEDIR)/public/sdk/inc/winerror.h \
+ $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(CHIVNBTOBJD)/chic.obj $(CHIDVNBTOBJD)/chic.obj $(VNBTSRC)/chic.lst: \
+ $(VNBTSRC)/chic.c ../$(INC)/alpha.h ../$(INC)/alpharef.h ../$(INC)/arc.h \
+ ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h ../blt/dhcpinfo.h $(INC)/ctemacro.h \
+ $(INC)/debug.h $(INC)/nbtinfo.h $(INC)/nbtnt.h $(INC)/nbtprocs.h \
+ $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h $(INC)/vxddebug.h \
+ $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h $(CHICAGO)/tcp/h/tdivxd.h \
+ $(BASEDIR)/private/inc/ipinfo.h $(BASEDIR)/private/inc/nbtioctl.h \
+ $(BASEDIR)/private/inc/nettypes.h $(BASEDIR)/private/inc/packoff.h \
+ $(BASEDIR)/private/inc/packon.h $(BASEDIR)/private/inc/sockets/netinet/in.h \
+ $(BASEDIR)/private/inc/status.h $(BASEDIR)/private/inc/sys/snet/ip_proto.h \
+ $(BASEDIR)/private/inc/tdi.h $(BASEDIR)/private/inc/tdiinfo.h \
+ $(BASEDIR)/private/inc/tdikrnl.h $(BASEDIR)/private/inc/tdistat.h \
+ $(BASEDIR)/public/sdk/inc/alphaops.h $(BASEDIR)/public/sdk/inc/crt/ctype.h \
+ $(BASEDIR)/public/sdk/inc/crt/excpt.h $(BASEDIR)/public/sdk/inc/crt/limits.h \
+ $(BASEDIR)/public/sdk/inc/crt/stdarg.h $(BASEDIR)/public/sdk/inc/crt/stddef.h \
+ $(BASEDIR)/public/sdk/inc/crt/string.h $(BASEDIR)/public/sdk/inc/devioctl.h \
+ $(BASEDIR)/public/sdk/inc/lintfunc.hxx $(BASEDIR)/public/sdk/inc/mipsinst.h \
+ $(BASEDIR)/public/sdk/inc/nb30.h $(BASEDIR)/public/sdk/inc/netevent.h \
+ $(BASEDIR)/public/sdk/inc/nt.h $(BASEDIR)/public/sdk/inc/ntalpha.h \
+ $(BASEDIR)/public/sdk/inc/ntconfig.h $(BASEDIR)/public/sdk/inc/ntddtdi.h \
+ $(BASEDIR)/public/sdk/inc/ntdef.h $(BASEDIR)/public/sdk/inc/ntelfapi.h \
+ $(BASEDIR)/public/sdk/inc/ntexapi.h $(BASEDIR)/public/sdk/inc/nti386.h \
+ $(BASEDIR)/public/sdk/inc/ntimage.h $(BASEDIR)/public/sdk/inc/ntioapi.h \
+ $(BASEDIR)/public/sdk/inc/ntiolog.h $(BASEDIR)/public/sdk/inc/ntkeapi.h \
+ $(BASEDIR)/public/sdk/inc/ntldr.h $(BASEDIR)/public/sdk/inc/ntlpcapi.h \
+ $(BASEDIR)/public/sdk/inc/ntmips.h $(BASEDIR)/public/sdk/inc/ntmmapi.h \
+ $(BASEDIR)/public/sdk/inc/ntnls.h $(BASEDIR)/public/sdk/inc/ntobapi.h \
+ $(BASEDIR)/public/sdk/inc/ntppc.h $(BASEDIR)/public/sdk/inc/ntpsapi.h \
+ $(BASEDIR)/public/sdk/inc/ntregapi.h $(BASEDIR)/public/sdk/inc/ntrtl.h \
+ $(BASEDIR)/public/sdk/inc/ntseapi.h $(BASEDIR)/public/sdk/inc/ntstatus.h \
+ $(BASEDIR)/public/sdk/inc/ntxcapi.h $(BASEDIR)/public/sdk/inc/poppack.h \
+ $(BASEDIR)/public/sdk/inc/ppcinst.h $(BASEDIR)/public/sdk/inc/pshpack1.h \
+ $(BASEDIR)/public/sdk/inc/pshpack4.h $(BASEDIR)/public/sdk/inc/windef.h \
+ $(BASEDIR)/public/sdk/inc/winerror.h $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(CHIVNBTOBJD)/fileio.obj $(CHIDVNBTOBJD)/fileio.obj $(VNBTSRC)/fileio.lst: \
+ $(VNBTSRC)/fileio.c ../$(INC)/alpha.h ../$(INC)/alpharef.h \
+ ../$(INC)/arc.h ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h $(INC)/ctemacro.h $(INC)/debug.h $(INC)/hosts.h \
+ $(INC)/nbtnt.h $(INC)/nbtprocs.h $(INC)/ntprocs.h $(INC)/timer.h \
+ $(INC)/types.h $(INC)/vxddebug.h $(INC)/vxdprocs.h \
+ $(CHICAGO)/tcp/h/oscfg.h $(CHICAGO)/tcp/h/tdivxd.h \
+ $(BASEDIR)/private/inc/nbtioctl.h $(BASEDIR)/private/inc/nettypes.h \
+ $(BASEDIR)/private/inc/packoff.h $(BASEDIR)/private/inc/packon.h \
+ $(BASEDIR)/private/inc/sockets/netinet/in.h $(BASEDIR)/private/inc/status.h \
+ $(BASEDIR)/private/inc/sys/snet/ip_proto.h $(BASEDIR)/private/inc/tdi.h \
+ $(BASEDIR)/private/inc/tdikrnl.h $(BASEDIR)/private/inc/tdistat.h \
+ $(BASEDIR)/public/sdk/inc/alphaops.h $(BASEDIR)/public/sdk/inc/crt/ctype.h \
+ $(BASEDIR)/public/sdk/inc/crt/excpt.h $(BASEDIR)/public/sdk/inc/crt/limits.h \
+ $(BASEDIR)/public/sdk/inc/crt/stdarg.h $(BASEDIR)/public/sdk/inc/crt/stddef.h \
+ $(BASEDIR)/public/sdk/inc/crt/string.h $(BASEDIR)/public/sdk/inc/devioctl.h \
+ $(BASEDIR)/public/sdk/inc/lintfunc.hxx $(BASEDIR)/public/sdk/inc/mipsinst.h \
+ $(BASEDIR)/public/sdk/inc/nb30.h $(BASEDIR)/public/sdk/inc/netevent.h \
+ $(BASEDIR)/public/sdk/inc/nt.h $(BASEDIR)/public/sdk/inc/ntalpha.h \
+ $(BASEDIR)/public/sdk/inc/ntconfig.h $(BASEDIR)/public/sdk/inc/ntddtdi.h \
+ $(BASEDIR)/public/sdk/inc/ntdef.h $(BASEDIR)/public/sdk/inc/ntelfapi.h \
+ $(BASEDIR)/public/sdk/inc/ntexapi.h $(BASEDIR)/public/sdk/inc/nti386.h \
+ $(BASEDIR)/public/sdk/inc/ntimage.h $(BASEDIR)/public/sdk/inc/ntioapi.h \
+ $(BASEDIR)/public/sdk/inc/ntiolog.h $(BASEDIR)/public/sdk/inc/ntkeapi.h \
+ $(BASEDIR)/public/sdk/inc/ntldr.h $(BASEDIR)/public/sdk/inc/ntlpcapi.h \
+ $(BASEDIR)/public/sdk/inc/ntmips.h $(BASEDIR)/public/sdk/inc/ntmmapi.h \
+ $(BASEDIR)/public/sdk/inc/ntnls.h $(BASEDIR)/public/sdk/inc/ntobapi.h \
+ $(BASEDIR)/public/sdk/inc/ntppc.h $(BASEDIR)/public/sdk/inc/ntpsapi.h \
+ $(BASEDIR)/public/sdk/inc/ntregapi.h $(BASEDIR)/public/sdk/inc/ntrtl.h \
+ $(BASEDIR)/public/sdk/inc/ntseapi.h $(BASEDIR)/public/sdk/inc/ntstatus.h \
+ $(BASEDIR)/public/sdk/inc/ntxcapi.h $(BASEDIR)/public/sdk/inc/poppack.h \
+ $(BASEDIR)/public/sdk/inc/ppcinst.h $(BASEDIR)/public/sdk/inc/pshpack1.h \
+ $(BASEDIR)/public/sdk/inc/pshpack4.h $(BASEDIR)/public/sdk/inc/windef.h \
+ $(BASEDIR)/public/sdk/inc/winerror.h $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(CHIVNBTOBJD)/init.obj $(CHIDVNBTOBJD)/init.obj $(VNBTSRC)/init.lst: \
+ $(VNBTSRC)/init.c ../$(INC)/alpha.h ../$(INC)/alpharef.h ../$(INC)/arc.h \
+ ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h ../blt/dhcpinfo.h $(INC)/ctemacro.h \
+ $(INC)/debug.h $(INC)/hosts.h $(INC)/nbtinfo.h $(INC)/nbtnt.h \
+ $(INC)/nbtprocs.h $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h \
+ $(INC)/vxddebug.h $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h \
+ $(CHICAGO)/tcp/h/tdivxd.h $(BASEDIR)/private/inc/ipinfo.h \
+ $(BASEDIR)/private/inc/nbtioctl.h $(BASEDIR)/private/inc/nettypes.h \
+ $(BASEDIR)/private/inc/packoff.h $(BASEDIR)/private/inc/packon.h \
+ $(BASEDIR)/private/inc/sockets/netinet/in.h $(BASEDIR)/private/inc/status.h \
+ $(BASEDIR)/private/inc/sys/snet/ip_proto.h $(BASEDIR)/private/inc/tdi.h \
+ $(BASEDIR)/private/inc/tdiinfo.h $(BASEDIR)/private/inc/tdikrnl.h \
+ $(BASEDIR)/private/inc/tdistat.h $(BASEDIR)/public/sdk/inc/alphaops.h \
+ $(BASEDIR)/public/sdk/inc/crt/ctype.h $(BASEDIR)/public/sdk/inc/crt/excpt.h \
+ $(BASEDIR)/public/sdk/inc/crt/limits.h $(BASEDIR)/public/sdk/inc/crt/stdarg.h \
+ $(BASEDIR)/public/sdk/inc/crt/stddef.h $(BASEDIR)/public/sdk/inc/crt/string.h \
+ $(BASEDIR)/public/sdk/inc/devioctl.h $(BASEDIR)/public/sdk/inc/lintfunc.hxx \
+ $(BASEDIR)/public/sdk/inc/mipsinst.h $(BASEDIR)/public/sdk/inc/nb30.h \
+ $(BASEDIR)/public/sdk/inc/netevent.h $(BASEDIR)/public/sdk/inc/nt.h \
+ $(BASEDIR)/public/sdk/inc/ntalpha.h $(BASEDIR)/public/sdk/inc/ntconfig.h \
+ $(BASEDIR)/public/sdk/inc/ntddtdi.h $(BASEDIR)/public/sdk/inc/ntdef.h \
+ $(BASEDIR)/public/sdk/inc/ntelfapi.h $(BASEDIR)/public/sdk/inc/ntexapi.h \
+ $(BASEDIR)/public/sdk/inc/nti386.h $(BASEDIR)/public/sdk/inc/ntimage.h \
+ $(BASEDIR)/public/sdk/inc/ntioapi.h $(BASEDIR)/public/sdk/inc/ntiolog.h \
+ $(BASEDIR)/public/sdk/inc/ntkeapi.h $(BASEDIR)/public/sdk/inc/ntldr.h \
+ $(BASEDIR)/public/sdk/inc/ntlpcapi.h $(BASEDIR)/public/sdk/inc/ntmips.h \
+ $(BASEDIR)/public/sdk/inc/ntmmapi.h $(BASEDIR)/public/sdk/inc/ntnls.h \
+ $(BASEDIR)/public/sdk/inc/ntobapi.h $(BASEDIR)/public/sdk/inc/ntppc.h \
+ $(BASEDIR)/public/sdk/inc/ntpsapi.h $(BASEDIR)/public/sdk/inc/ntregapi.h \
+ $(BASEDIR)/public/sdk/inc/ntrtl.h $(BASEDIR)/public/sdk/inc/ntseapi.h \
+ $(BASEDIR)/public/sdk/inc/ntstatus.h $(BASEDIR)/public/sdk/inc/ntxcapi.h \
+ $(BASEDIR)/public/sdk/inc/poppack.h $(BASEDIR)/public/sdk/inc/ppcinst.h \
+ $(BASEDIR)/public/sdk/inc/pshpack1.h $(BASEDIR)/public/sdk/inc/pshpack4.h \
+ $(BASEDIR)/public/sdk/inc/windef.h $(BASEDIR)/public/sdk/inc/winerror.h \
+ $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(CHIVNBTOBJD)/nbtinfo.obj $(CHIDVNBTOBJD)/nbtinfo.obj $(VNBTSRC)/nbtinfo.lst: \
+ $(VNBTSRC)/nbtinfo.c ../$(INC)/alpha.h ../$(INC)/alpharef.h \
+ ../$(INC)/arc.h ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h ../blt/dhcpinfo.h $(INC)/ctemacro.h \
+ $(INC)/debug.h $(INC)/nbtinfo.h $(INC)/nbtnt.h $(INC)/nbtprocs.h \
+ $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h $(INC)/vxddebug.h \
+ $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h $(CHICAGO)/tcp/h/tdivxd.h \
+ $(BASEDIR)/private/inc/nbtioctl.h $(BASEDIR)/private/inc/nettypes.h \
+ $(BASEDIR)/private/inc/packoff.h $(BASEDIR)/private/inc/packon.h \
+ $(BASEDIR)/private/inc/sockets/netinet/in.h $(BASEDIR)/private/inc/status.h \
+ $(BASEDIR)/private/inc/sys/snet/ip_proto.h $(BASEDIR)/private/inc/tdi.h \
+ $(BASEDIR)/private/inc/tdikrnl.h $(BASEDIR)/private/inc/tdistat.h \
+ $(BASEDIR)/public/sdk/inc/alphaops.h $(BASEDIR)/public/sdk/inc/crt/ctype.h \
+ $(BASEDIR)/public/sdk/inc/crt/excpt.h $(BASEDIR)/public/sdk/inc/crt/limits.h \
+ $(BASEDIR)/public/sdk/inc/crt/stdarg.h $(BASEDIR)/public/sdk/inc/crt/stddef.h \
+ $(BASEDIR)/public/sdk/inc/crt/string.h $(BASEDIR)/public/sdk/inc/devioctl.h \
+ $(BASEDIR)/public/sdk/inc/lintfunc.hxx $(BASEDIR)/public/sdk/inc/mipsinst.h \
+ $(BASEDIR)/public/sdk/inc/nb30.h $(BASEDIR)/public/sdk/inc/netevent.h \
+ $(BASEDIR)/public/sdk/inc/nt.h $(BASEDIR)/public/sdk/inc/ntalpha.h \
+ $(BASEDIR)/public/sdk/inc/ntconfig.h $(BASEDIR)/public/sdk/inc/ntddtdi.h \
+ $(BASEDIR)/public/sdk/inc/ntdef.h $(BASEDIR)/public/sdk/inc/ntelfapi.h \
+ $(BASEDIR)/public/sdk/inc/ntexapi.h $(BASEDIR)/public/sdk/inc/nti386.h \
+ $(BASEDIR)/public/sdk/inc/ntimage.h $(BASEDIR)/public/sdk/inc/ntioapi.h \
+ $(BASEDIR)/public/sdk/inc/ntiolog.h $(BASEDIR)/public/sdk/inc/ntkeapi.h \
+ $(BASEDIR)/public/sdk/inc/ntldr.h $(BASEDIR)/public/sdk/inc/ntlpcapi.h \
+ $(BASEDIR)/public/sdk/inc/ntmips.h $(BASEDIR)/public/sdk/inc/ntmmapi.h \
+ $(BASEDIR)/public/sdk/inc/ntnls.h $(BASEDIR)/public/sdk/inc/ntobapi.h \
+ $(BASEDIR)/public/sdk/inc/ntppc.h $(BASEDIR)/public/sdk/inc/ntpsapi.h \
+ $(BASEDIR)/public/sdk/inc/ntregapi.h $(BASEDIR)/public/sdk/inc/ntrtl.h \
+ $(BASEDIR)/public/sdk/inc/ntseapi.h $(BASEDIR)/public/sdk/inc/ntstatus.h \
+ $(BASEDIR)/public/sdk/inc/ntxcapi.h $(BASEDIR)/public/sdk/inc/poppack.h \
+ $(BASEDIR)/public/sdk/inc/ppcinst.h $(BASEDIR)/public/sdk/inc/pshpack1.h \
+ $(BASEDIR)/public/sdk/inc/pshpack4.h $(BASEDIR)/public/sdk/inc/windef.h \
+ $(BASEDIR)/public/sdk/inc/winerror.h $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(CHIVNBTOBJD)/ncb.obj $(CHIDVNBTOBJD)/ncb.obj $(VNBTSRC)/ncb.lst: $(VNBTSRC)/ncb.c \
+ ../$(INC)/alpha.h ../$(INC)/alpharef.h ../$(INC)/arc.h \
+ ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h $(INC)/ctemacro.h $(INC)/debug.h $(INC)/nbtnt.h \
+ $(INC)/nbtprocs.h $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h \
+ $(INC)/vxddebug.h $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h \
+ $(CHICAGO)/tcp/h/tdivxd.h $(BASEDIR)/private/inc/nbtioctl.h \
+ $(BASEDIR)/private/inc/nettypes.h $(BASEDIR)/private/inc/packoff.h \
+ $(BASEDIR)/private/inc/packon.h $(BASEDIR)/private/inc/sockets/netinet/in.h \
+ $(BASEDIR)/private/inc/status.h $(BASEDIR)/private/inc/sys/snet/ip_proto.h \
+ $(BASEDIR)/private/inc/tdi.h $(BASEDIR)/private/inc/tdikrnl.h \
+ $(BASEDIR)/private/inc/tdistat.h $(BASEDIR)/public/sdk/inc/alphaops.h \
+ $(BASEDIR)/public/sdk/inc/crt/ctype.h $(BASEDIR)/public/sdk/inc/crt/excpt.h \
+ $(BASEDIR)/public/sdk/inc/crt/limits.h $(BASEDIR)/public/sdk/inc/crt/stdarg.h \
+ $(BASEDIR)/public/sdk/inc/crt/stddef.h $(BASEDIR)/public/sdk/inc/crt/string.h \
+ $(BASEDIR)/public/sdk/inc/devioctl.h $(BASEDIR)/public/sdk/inc/lintfunc.hxx \
+ $(BASEDIR)/public/sdk/inc/mipsinst.h $(BASEDIR)/public/sdk/inc/nb30.h \
+ $(BASEDIR)/public/sdk/inc/netevent.h $(BASEDIR)/public/sdk/inc/nt.h \
+ $(BASEDIR)/public/sdk/inc/ntalpha.h $(BASEDIR)/public/sdk/inc/ntconfig.h \
+ $(BASEDIR)/public/sdk/inc/ntddtdi.h $(BASEDIR)/public/sdk/inc/ntdef.h \
+ $(BASEDIR)/public/sdk/inc/ntelfapi.h $(BASEDIR)/public/sdk/inc/ntexapi.h \
+ $(BASEDIR)/public/sdk/inc/nti386.h $(BASEDIR)/public/sdk/inc/ntimage.h \
+ $(BASEDIR)/public/sdk/inc/ntioapi.h $(BASEDIR)/public/sdk/inc/ntiolog.h \
+ $(BASEDIR)/public/sdk/inc/ntkeapi.h $(BASEDIR)/public/sdk/inc/ntldr.h \
+ $(BASEDIR)/public/sdk/inc/ntlpcapi.h $(BASEDIR)/public/sdk/inc/ntmips.h \
+ $(BASEDIR)/public/sdk/inc/ntmmapi.h $(BASEDIR)/public/sdk/inc/ntnls.h \
+ $(BASEDIR)/public/sdk/inc/ntobapi.h $(BASEDIR)/public/sdk/inc/ntppc.h \
+ $(BASEDIR)/public/sdk/inc/ntpsapi.h $(BASEDIR)/public/sdk/inc/ntregapi.h \
+ $(BASEDIR)/public/sdk/inc/ntrtl.h $(BASEDIR)/public/sdk/inc/ntseapi.h \
+ $(BASEDIR)/public/sdk/inc/ntstatus.h $(BASEDIR)/public/sdk/inc/ntxcapi.h \
+ $(BASEDIR)/public/sdk/inc/poppack.h $(BASEDIR)/public/sdk/inc/ppcinst.h \
+ $(BASEDIR)/public/sdk/inc/pshpack1.h $(BASEDIR)/public/sdk/inc/pshpack4.h \
+ $(BASEDIR)/public/sdk/inc/windef.h $(BASEDIR)/public/sdk/inc/winerror.h \
+ $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(CHIVNBTOBJD)/tdiaddr.obj $(CHIDVNBTOBJD)/tdiaddr.obj $(VNBTSRC)/tdiaddr.lst: \
+ $(VNBTSRC)/tdiaddr.c ../$(INC)/alpha.h ../$(INC)/alpharef.h \
+ ../$(INC)/arc.h ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h $(INC)/ctemacro.h $(INC)/debug.h $(INC)/nbtnt.h \
+ $(INC)/nbtprocs.h $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h \
+ $(INC)/vxddebug.h $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h \
+ $(CHICAGO)/tcp/h/tdivxd.h $(BASEDIR)/private/inc/nbtioctl.h \
+ $(BASEDIR)/private/inc/nettypes.h $(BASEDIR)/private/inc/packoff.h \
+ $(BASEDIR)/private/inc/packon.h $(BASEDIR)/private/inc/sockets/netinet/in.h \
+ $(BASEDIR)/private/inc/status.h $(BASEDIR)/private/inc/sys/snet/ip_proto.h \
+ $(BASEDIR)/private/inc/tdi.h $(BASEDIR)/private/inc/tdikrnl.h \
+ $(BASEDIR)/private/inc/tdistat.h $(BASEDIR)/public/sdk/inc/alphaops.h \
+ $(BASEDIR)/public/sdk/inc/crt/ctype.h $(BASEDIR)/public/sdk/inc/crt/excpt.h \
+ $(BASEDIR)/public/sdk/inc/crt/limits.h $(BASEDIR)/public/sdk/inc/crt/stdarg.h \
+ $(BASEDIR)/public/sdk/inc/crt/stddef.h $(BASEDIR)/public/sdk/inc/crt/string.h \
+ $(BASEDIR)/public/sdk/inc/devioctl.h $(BASEDIR)/public/sdk/inc/lintfunc.hxx \
+ $(BASEDIR)/public/sdk/inc/mipsinst.h $(BASEDIR)/public/sdk/inc/nb30.h \
+ $(BASEDIR)/public/sdk/inc/netevent.h $(BASEDIR)/public/sdk/inc/nt.h \
+ $(BASEDIR)/public/sdk/inc/ntalpha.h $(BASEDIR)/public/sdk/inc/ntconfig.h \
+ $(BASEDIR)/public/sdk/inc/ntddtdi.h $(BASEDIR)/public/sdk/inc/ntdef.h \
+ $(BASEDIR)/public/sdk/inc/ntelfapi.h $(BASEDIR)/public/sdk/inc/ntexapi.h \
+ $(BASEDIR)/public/sdk/inc/nti386.h $(BASEDIR)/public/sdk/inc/ntimage.h \
+ $(BASEDIR)/public/sdk/inc/ntioapi.h $(BASEDIR)/public/sdk/inc/ntiolog.h \
+ $(BASEDIR)/public/sdk/inc/ntkeapi.h $(BASEDIR)/public/sdk/inc/ntldr.h \
+ $(BASEDIR)/public/sdk/inc/ntlpcapi.h $(BASEDIR)/public/sdk/inc/ntmips.h \
+ $(BASEDIR)/public/sdk/inc/ntmmapi.h $(BASEDIR)/public/sdk/inc/ntnls.h \
+ $(BASEDIR)/public/sdk/inc/ntobapi.h $(BASEDIR)/public/sdk/inc/ntppc.h \
+ $(BASEDIR)/public/sdk/inc/ntpsapi.h $(BASEDIR)/public/sdk/inc/ntregapi.h \
+ $(BASEDIR)/public/sdk/inc/ntrtl.h $(BASEDIR)/public/sdk/inc/ntseapi.h \
+ $(BASEDIR)/public/sdk/inc/ntstatus.h $(BASEDIR)/public/sdk/inc/ntxcapi.h \
+ $(BASEDIR)/public/sdk/inc/poppack.h $(BASEDIR)/public/sdk/inc/ppcinst.h \
+ $(BASEDIR)/public/sdk/inc/pshpack1.h $(BASEDIR)/public/sdk/inc/pshpack4.h \
+ $(BASEDIR)/public/sdk/inc/windef.h $(BASEDIR)/public/sdk/inc/winerror.h \
+ $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(CHIVNBTOBJD)/tdicnct.obj $(CHIDVNBTOBJD)/tdicnct.obj $(VNBTSRC)/tdicnct.lst: \
+ $(VNBTSRC)/tdicnct.c ../$(INC)/alpha.h ../$(INC)/alpharef.h \
+ ../$(INC)/arc.h ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h $(INC)/ctemacro.h $(INC)/debug.h $(INC)/nbtnt.h \
+ $(INC)/nbtprocs.h $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h \
+ $(INC)/vxddebug.h $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h \
+ $(CHICAGO)/tcp/h/tdivxd.h $(BASEDIR)/private/inc/nbtioctl.h \
+ $(BASEDIR)/private/inc/nettypes.h $(BASEDIR)/private/inc/packoff.h \
+ $(BASEDIR)/private/inc/packon.h $(BASEDIR)/private/inc/sockets/netinet/in.h \
+ $(BASEDIR)/private/inc/status.h $(BASEDIR)/private/inc/sys/snet/ip_proto.h \
+ $(BASEDIR)/private/inc/tdi.h $(BASEDIR)/private/inc/tdikrnl.h \
+ $(BASEDIR)/private/inc/tdistat.h $(BASEDIR)/public/sdk/inc/alphaops.h \
+ $(BASEDIR)/public/sdk/inc/crt/ctype.h $(BASEDIR)/public/sdk/inc/crt/excpt.h \
+ $(BASEDIR)/public/sdk/inc/crt/limits.h $(BASEDIR)/public/sdk/inc/crt/stdarg.h \
+ $(BASEDIR)/public/sdk/inc/crt/stddef.h $(BASEDIR)/public/sdk/inc/crt/string.h \
+ $(BASEDIR)/public/sdk/inc/devioctl.h $(BASEDIR)/public/sdk/inc/lintfunc.hxx \
+ $(BASEDIR)/public/sdk/inc/mipsinst.h $(BASEDIR)/public/sdk/inc/nb30.h \
+ $(BASEDIR)/public/sdk/inc/netevent.h $(BASEDIR)/public/sdk/inc/nt.h \
+ $(BASEDIR)/public/sdk/inc/ntalpha.h $(BASEDIR)/public/sdk/inc/ntconfig.h \
+ $(BASEDIR)/public/sdk/inc/ntddtdi.h $(BASEDIR)/public/sdk/inc/ntdef.h \
+ $(BASEDIR)/public/sdk/inc/ntelfapi.h $(BASEDIR)/public/sdk/inc/ntexapi.h \
+ $(BASEDIR)/public/sdk/inc/nti386.h $(BASEDIR)/public/sdk/inc/ntimage.h \
+ $(BASEDIR)/public/sdk/inc/ntioapi.h $(BASEDIR)/public/sdk/inc/ntiolog.h \
+ $(BASEDIR)/public/sdk/inc/ntkeapi.h $(BASEDIR)/public/sdk/inc/ntldr.h \
+ $(BASEDIR)/public/sdk/inc/ntlpcapi.h $(BASEDIR)/public/sdk/inc/ntmips.h \
+ $(BASEDIR)/public/sdk/inc/ntmmapi.h $(BASEDIR)/public/sdk/inc/ntnls.h \
+ $(BASEDIR)/public/sdk/inc/ntobapi.h $(BASEDIR)/public/sdk/inc/ntppc.h \
+ $(BASEDIR)/public/sdk/inc/ntpsapi.h $(BASEDIR)/public/sdk/inc/ntregapi.h \
+ $(BASEDIR)/public/sdk/inc/ntrtl.h $(BASEDIR)/public/sdk/inc/ntseapi.h \
+ $(BASEDIR)/public/sdk/inc/ntstatus.h $(BASEDIR)/public/sdk/inc/ntxcapi.h \
+ $(BASEDIR)/public/sdk/inc/poppack.h $(BASEDIR)/public/sdk/inc/ppcinst.h \
+ $(BASEDIR)/public/sdk/inc/pshpack1.h $(BASEDIR)/public/sdk/inc/pshpack4.h \
+ $(BASEDIR)/public/sdk/inc/windef.h $(BASEDIR)/public/sdk/inc/winerror.h \
+ $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(CHIVNBTOBJD)/tdihndlr.obj $(CHIDVNBTOBJD)/tdihndlr.obj $(VNBTSRC)/tdihndlr.lst: \
+ $(VNBTSRC)/tdihndlr.c ../$(INC)/alpha.h ../$(INC)/alpharef.h \
+ ../$(INC)/arc.h ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h $(INC)/ctemacro.h $(INC)/debug.h $(INC)/nbtnt.h \
+ $(INC)/nbtprocs.h $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h \
+ $(INC)/vxddebug.h $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h \
+ $(CHICAGO)/tcp/h/tdivxd.h $(BASEDIR)/private/inc/nbtioctl.h \
+ $(BASEDIR)/private/inc/nettypes.h $(BASEDIR)/private/inc/packoff.h \
+ $(BASEDIR)/private/inc/packon.h $(BASEDIR)/private/inc/sockets/netinet/in.h \
+ $(BASEDIR)/private/inc/status.h $(BASEDIR)/private/inc/sys/snet/ip_proto.h \
+ $(BASEDIR)/private/inc/tdi.h $(BASEDIR)/private/inc/tdikrnl.h \
+ $(BASEDIR)/private/inc/tdistat.h $(BASEDIR)/public/sdk/inc/alphaops.h \
+ $(BASEDIR)/public/sdk/inc/crt/ctype.h $(BASEDIR)/public/sdk/inc/crt/excpt.h \
+ $(BASEDIR)/public/sdk/inc/crt/limits.h $(BASEDIR)/public/sdk/inc/crt/stdarg.h \
+ $(BASEDIR)/public/sdk/inc/crt/stddef.h $(BASEDIR)/public/sdk/inc/crt/string.h \
+ $(BASEDIR)/public/sdk/inc/devioctl.h $(BASEDIR)/public/sdk/inc/lintfunc.hxx \
+ $(BASEDIR)/public/sdk/inc/mipsinst.h $(BASEDIR)/public/sdk/inc/nb30.h \
+ $(BASEDIR)/public/sdk/inc/netevent.h $(BASEDIR)/public/sdk/inc/nt.h \
+ $(BASEDIR)/public/sdk/inc/ntalpha.h $(BASEDIR)/public/sdk/inc/ntconfig.h \
+ $(BASEDIR)/public/sdk/inc/ntddtdi.h $(BASEDIR)/public/sdk/inc/ntdef.h \
+ $(BASEDIR)/public/sdk/inc/ntelfapi.h $(BASEDIR)/public/sdk/inc/ntexapi.h \
+ $(BASEDIR)/public/sdk/inc/nti386.h $(BASEDIR)/public/sdk/inc/ntimage.h \
+ $(BASEDIR)/public/sdk/inc/ntioapi.h $(BASEDIR)/public/sdk/inc/ntiolog.h \
+ $(BASEDIR)/public/sdk/inc/ntkeapi.h $(BASEDIR)/public/sdk/inc/ntldr.h \
+ $(BASEDIR)/public/sdk/inc/ntlpcapi.h $(BASEDIR)/public/sdk/inc/ntmips.h \
+ $(BASEDIR)/public/sdk/inc/ntmmapi.h $(BASEDIR)/public/sdk/inc/ntnls.h \
+ $(BASEDIR)/public/sdk/inc/ntobapi.h $(BASEDIR)/public/sdk/inc/ntppc.h \
+ $(BASEDIR)/public/sdk/inc/ntpsapi.h $(BASEDIR)/public/sdk/inc/ntregapi.h \
+ $(BASEDIR)/public/sdk/inc/ntrtl.h $(BASEDIR)/public/sdk/inc/ntseapi.h \
+ $(BASEDIR)/public/sdk/inc/ntstatus.h $(BASEDIR)/public/sdk/inc/ntxcapi.h \
+ $(BASEDIR)/public/sdk/inc/poppack.h $(BASEDIR)/public/sdk/inc/ppcinst.h \
+ $(BASEDIR)/public/sdk/inc/pshpack1.h $(BASEDIR)/public/sdk/inc/pshpack4.h \
+ $(BASEDIR)/public/sdk/inc/windef.h $(BASEDIR)/public/sdk/inc/winerror.h \
+ $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(CHIVNBTOBJD)/tdiout.obj $(CHIDVNBTOBJD)/tdiout.obj $(VNBTSRC)/tdiout.lst: \
+ $(VNBTSRC)/tdiout.c ../$(INC)/alpha.h ../$(INC)/alpharef.h \
+ ../$(INC)/arc.h ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h $(INC)/ctemacro.h $(INC)/debug.h $(INC)/nbtnt.h \
+ $(INC)/nbtprocs.h $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h \
+ $(INC)/vxddebug.h $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h \
+ $(CHICAGO)/tcp/h/tdivxd.h $(BASEDIR)/private/inc/nbtioctl.h \
+ $(BASEDIR)/private/inc/nettypes.h $(BASEDIR)/private/inc/packoff.h \
+ $(BASEDIR)/private/inc/packon.h $(BASEDIR)/private/inc/sockets/netinet/in.h \
+ $(BASEDIR)/private/inc/status.h $(BASEDIR)/private/inc/sys/snet/ip_proto.h \
+ $(BASEDIR)/private/inc/tdi.h $(BASEDIR)/private/inc/tdikrnl.h \
+ $(BASEDIR)/private/inc/tdistat.h $(BASEDIR)/public/sdk/inc/alphaops.h \
+ $(BASEDIR)/public/sdk/inc/crt/ctype.h $(BASEDIR)/public/sdk/inc/crt/excpt.h \
+ $(BASEDIR)/public/sdk/inc/crt/limits.h $(BASEDIR)/public/sdk/inc/crt/stdarg.h \
+ $(BASEDIR)/public/sdk/inc/crt/stddef.h $(BASEDIR)/public/sdk/inc/crt/string.h \
+ $(BASEDIR)/public/sdk/inc/devioctl.h $(BASEDIR)/public/sdk/inc/lintfunc.hxx \
+ $(BASEDIR)/public/sdk/inc/mipsinst.h $(BASEDIR)/public/sdk/inc/nb30.h \
+ $(BASEDIR)/public/sdk/inc/netevent.h $(BASEDIR)/public/sdk/inc/nt.h \
+ $(BASEDIR)/public/sdk/inc/ntalpha.h $(BASEDIR)/public/sdk/inc/ntconfig.h \
+ $(BASEDIR)/public/sdk/inc/ntddtdi.h $(BASEDIR)/public/sdk/inc/ntdef.h \
+ $(BASEDIR)/public/sdk/inc/ntelfapi.h $(BASEDIR)/public/sdk/inc/ntexapi.h \
+ $(BASEDIR)/public/sdk/inc/nti386.h $(BASEDIR)/public/sdk/inc/ntimage.h \
+ $(BASEDIR)/public/sdk/inc/ntioapi.h $(BASEDIR)/public/sdk/inc/ntiolog.h \
+ $(BASEDIR)/public/sdk/inc/ntkeapi.h $(BASEDIR)/public/sdk/inc/ntldr.h \
+ $(BASEDIR)/public/sdk/inc/ntlpcapi.h $(BASEDIR)/public/sdk/inc/ntmips.h \
+ $(BASEDIR)/public/sdk/inc/ntmmapi.h $(BASEDIR)/public/sdk/inc/ntnls.h \
+ $(BASEDIR)/public/sdk/inc/ntobapi.h $(BASEDIR)/public/sdk/inc/ntppc.h \
+ $(BASEDIR)/public/sdk/inc/ntpsapi.h $(BASEDIR)/public/sdk/inc/ntregapi.h \
+ $(BASEDIR)/public/sdk/inc/ntrtl.h $(BASEDIR)/public/sdk/inc/ntseapi.h \
+ $(BASEDIR)/public/sdk/inc/ntstatus.h $(BASEDIR)/public/sdk/inc/ntxcapi.h \
+ $(BASEDIR)/public/sdk/inc/poppack.h $(BASEDIR)/public/sdk/inc/ppcinst.h \
+ $(BASEDIR)/public/sdk/inc/pshpack1.h $(BASEDIR)/public/sdk/inc/pshpack4.h \
+ $(BASEDIR)/public/sdk/inc/windef.h $(BASEDIR)/public/sdk/inc/winerror.h \
+ $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(CHIVNBTOBJD)/timer.obj $(CHIDVNBTOBJD)/timer.obj $(VNBTSRC)/timer.lst: \
+ $(VNBTSRC)/timer.c ../$(INC)/alpha.h ../$(INC)/alpharef.h ../$(INC)/arc.h \
+ ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h $(INC)/ctemacro.h $(INC)/debug.h $(INC)/nbtnt.h \
+ $(INC)/nbtprocs.h $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h \
+ $(INC)/vxddebug.h $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h \
+ $(CHICAGO)/tcp/h/tdivxd.h $(BASEDIR)/private/inc/nbtioctl.h \
+ $(BASEDIR)/private/inc/nettypes.h $(BASEDIR)/private/inc/packoff.h \
+ $(BASEDIR)/private/inc/packon.h $(BASEDIR)/private/inc/sockets/netinet/in.h \
+ $(BASEDIR)/private/inc/status.h $(BASEDIR)/private/inc/sys/snet/ip_proto.h \
+ $(BASEDIR)/private/inc/tdi.h $(BASEDIR)/private/inc/tdikrnl.h \
+ $(BASEDIR)/private/inc/tdistat.h $(BASEDIR)/public/sdk/inc/alphaops.h \
+ $(BASEDIR)/public/sdk/inc/crt/ctype.h $(BASEDIR)/public/sdk/inc/crt/excpt.h \
+ $(BASEDIR)/public/sdk/inc/crt/limits.h $(BASEDIR)/public/sdk/inc/crt/stdarg.h \
+ $(BASEDIR)/public/sdk/inc/crt/stddef.h $(BASEDIR)/public/sdk/inc/crt/string.h \
+ $(BASEDIR)/public/sdk/inc/devioctl.h $(BASEDIR)/public/sdk/inc/lintfunc.hxx \
+ $(BASEDIR)/public/sdk/inc/mipsinst.h $(BASEDIR)/public/sdk/inc/nb30.h \
+ $(BASEDIR)/public/sdk/inc/netevent.h $(BASEDIR)/public/sdk/inc/nt.h \
+ $(BASEDIR)/public/sdk/inc/ntalpha.h $(BASEDIR)/public/sdk/inc/ntconfig.h \
+ $(BASEDIR)/public/sdk/inc/ntddtdi.h $(BASEDIR)/public/sdk/inc/ntdef.h \
+ $(BASEDIR)/public/sdk/inc/ntelfapi.h $(BASEDIR)/public/sdk/inc/ntexapi.h \
+ $(BASEDIR)/public/sdk/inc/nti386.h $(BASEDIR)/public/sdk/inc/ntimage.h \
+ $(BASEDIR)/public/sdk/inc/ntioapi.h $(BASEDIR)/public/sdk/inc/ntiolog.h \
+ $(BASEDIR)/public/sdk/inc/ntkeapi.h $(BASEDIR)/public/sdk/inc/ntldr.h \
+ $(BASEDIR)/public/sdk/inc/ntlpcapi.h $(BASEDIR)/public/sdk/inc/ntmips.h \
+ $(BASEDIR)/public/sdk/inc/ntmmapi.h $(BASEDIR)/public/sdk/inc/ntnls.h \
+ $(BASEDIR)/public/sdk/inc/ntobapi.h $(BASEDIR)/public/sdk/inc/ntppc.h \
+ $(BASEDIR)/public/sdk/inc/ntpsapi.h $(BASEDIR)/public/sdk/inc/ntregapi.h \
+ $(BASEDIR)/public/sdk/inc/ntrtl.h $(BASEDIR)/public/sdk/inc/ntseapi.h \
+ $(BASEDIR)/public/sdk/inc/ntstatus.h $(BASEDIR)/public/sdk/inc/ntxcapi.h \
+ $(BASEDIR)/public/sdk/inc/poppack.h $(BASEDIR)/public/sdk/inc/ppcinst.h \
+ $(BASEDIR)/public/sdk/inc/pshpack1.h $(BASEDIR)/public/sdk/inc/pshpack4.h \
+ $(BASEDIR)/public/sdk/inc/windef.h $(BASEDIR)/public/sdk/inc/winerror.h \
+ $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(CHIVNBTOBJD)/util.obj $(CHIDVNBTOBJD)/util.obj $(VNBTSRC)/util.lst: \
+ $(VNBTSRC)/util.c ../$(INC)/alpha.h ../$(INC)/alpharef.h ../$(INC)/arc.h \
+ ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h $(INC)/ctemacro.h $(INC)/debug.h $(INC)/nbtnt.h \
+ $(INC)/nbtprocs.h $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h \
+ $(INC)/vxddebug.h $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h \
+ $(CHICAGO)/tcp/h/tdivxd.h $(BASEDIR)/private/inc/nbtioctl.h \
+ $(BASEDIR)/private/inc/nettypes.h $(BASEDIR)/private/inc/packoff.h \
+ $(BASEDIR)/private/inc/packon.h $(BASEDIR)/private/inc/sockets/netinet/in.h \
+ $(BASEDIR)/private/inc/status.h $(BASEDIR)/private/inc/sys/snet/ip_proto.h \
+ $(BASEDIR)/private/inc/tdi.h $(BASEDIR)/private/inc/tdikrnl.h \
+ $(BASEDIR)/private/inc/tdistat.h $(BASEDIR)/public/sdk/inc/alphaops.h \
+ $(BASEDIR)/public/sdk/inc/crt/ctype.h $(BASEDIR)/public/sdk/inc/crt/excpt.h \
+ $(BASEDIR)/public/sdk/inc/crt/limits.h $(BASEDIR)/public/sdk/inc/crt/stdarg.h \
+ $(BASEDIR)/public/sdk/inc/crt/stddef.h $(BASEDIR)/public/sdk/inc/crt/string.h \
+ $(BASEDIR)/public/sdk/inc/devioctl.h $(BASEDIR)/public/sdk/inc/lintfunc.hxx \
+ $(BASEDIR)/public/sdk/inc/mipsinst.h $(BASEDIR)/public/sdk/inc/nb30.h \
+ $(BASEDIR)/public/sdk/inc/netevent.h $(BASEDIR)/public/sdk/inc/nt.h \
+ $(BASEDIR)/public/sdk/inc/ntalpha.h $(BASEDIR)/public/sdk/inc/ntconfig.h \
+ $(BASEDIR)/public/sdk/inc/ntddtdi.h $(BASEDIR)/public/sdk/inc/ntdef.h \
+ $(BASEDIR)/public/sdk/inc/ntelfapi.h $(BASEDIR)/public/sdk/inc/ntexapi.h \
+ $(BASEDIR)/public/sdk/inc/nti386.h $(BASEDIR)/public/sdk/inc/ntimage.h \
+ $(BASEDIR)/public/sdk/inc/ntioapi.h $(BASEDIR)/public/sdk/inc/ntiolog.h \
+ $(BASEDIR)/public/sdk/inc/ntkeapi.h $(BASEDIR)/public/sdk/inc/ntldr.h \
+ $(BASEDIR)/public/sdk/inc/ntlpcapi.h $(BASEDIR)/public/sdk/inc/ntmips.h \
+ $(BASEDIR)/public/sdk/inc/ntmmapi.h $(BASEDIR)/public/sdk/inc/ntnls.h \
+ $(BASEDIR)/public/sdk/inc/ntobapi.h $(BASEDIR)/public/sdk/inc/ntppc.h \
+ $(BASEDIR)/public/sdk/inc/ntpsapi.h $(BASEDIR)/public/sdk/inc/ntregapi.h \
+ $(BASEDIR)/public/sdk/inc/ntrtl.h $(BASEDIR)/public/sdk/inc/ntseapi.h \
+ $(BASEDIR)/public/sdk/inc/ntstatus.h $(BASEDIR)/public/sdk/inc/ntxcapi.h \
+ $(BASEDIR)/public/sdk/inc/poppack.h $(BASEDIR)/public/sdk/inc/ppcinst.h \
+ $(BASEDIR)/public/sdk/inc/pshpack1.h $(BASEDIR)/public/sdk/inc/pshpack4.h \
+ $(BASEDIR)/public/sdk/inc/windef.h $(BASEDIR)/public/sdk/inc/winerror.h \
+ $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(CHIVNBTOBJD)/vxddebug.obj $(CHIDVNBTOBJD)/vxddebug.obj $(VNBTSRC)/vxddebug.lst: \
+ $(VNBTSRC)/vxddebug.c ../$(INC)/alpha.h ../$(INC)/alpharef.h \
+ ../$(INC)/arc.h ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h $(INC)/ctemacro.h $(INC)/debug.h $(INC)/nbtnt.h \
+ $(INC)/nbtprocs.h $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h \
+ $(INC)/vxddebug.h $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h \
+ $(CHICAGO)/tcp/h/tdivxd.h $(BASEDIR)/private/inc/nbtioctl.h \
+ $(BASEDIR)/private/inc/nettypes.h $(BASEDIR)/private/inc/packoff.h \
+ $(BASEDIR)/private/inc/packon.h $(BASEDIR)/private/inc/sockets/netinet/in.h \
+ $(BASEDIR)/private/inc/status.h $(BASEDIR)/private/inc/sys/snet/ip_proto.h \
+ $(BASEDIR)/private/inc/tdi.h $(BASEDIR)/private/inc/tdikrnl.h \
+ $(BASEDIR)/private/inc/tdistat.h $(BASEDIR)/public/sdk/inc/alphaops.h \
+ $(BASEDIR)/public/sdk/inc/crt/ctype.h $(BASEDIR)/public/sdk/inc/crt/excpt.h \
+ $(BASEDIR)/public/sdk/inc/crt/limits.h $(BASEDIR)/public/sdk/inc/crt/stdarg.h \
+ $(BASEDIR)/public/sdk/inc/crt/stddef.h $(BASEDIR)/public/sdk/inc/crt/string.h \
+ $(BASEDIR)/public/sdk/inc/devioctl.h $(BASEDIR)/public/sdk/inc/lintfunc.hxx \
+ $(BASEDIR)/public/sdk/inc/mipsinst.h $(BASEDIR)/public/sdk/inc/nb30.h \
+ $(BASEDIR)/public/sdk/inc/netevent.h $(BASEDIR)/public/sdk/inc/nt.h \
+ $(BASEDIR)/public/sdk/inc/ntalpha.h $(BASEDIR)/public/sdk/inc/ntconfig.h \
+ $(BASEDIR)/public/sdk/inc/ntddtdi.h $(BASEDIR)/public/sdk/inc/ntdef.h \
+ $(BASEDIR)/public/sdk/inc/ntelfapi.h $(BASEDIR)/public/sdk/inc/ntexapi.h \
+ $(BASEDIR)/public/sdk/inc/nti386.h $(BASEDIR)/public/sdk/inc/ntimage.h \
+ $(BASEDIR)/public/sdk/inc/ntioapi.h $(BASEDIR)/public/sdk/inc/ntiolog.h \
+ $(BASEDIR)/public/sdk/inc/ntkeapi.h $(BASEDIR)/public/sdk/inc/ntldr.h \
+ $(BASEDIR)/public/sdk/inc/ntlpcapi.h $(BASEDIR)/public/sdk/inc/ntmips.h \
+ $(BASEDIR)/public/sdk/inc/ntmmapi.h $(BASEDIR)/public/sdk/inc/ntnls.h \
+ $(BASEDIR)/public/sdk/inc/ntobapi.h $(BASEDIR)/public/sdk/inc/ntppc.h \
+ $(BASEDIR)/public/sdk/inc/ntpsapi.h $(BASEDIR)/public/sdk/inc/ntregapi.h \
+ $(BASEDIR)/public/sdk/inc/ntrtl.h $(BASEDIR)/public/sdk/inc/ntseapi.h \
+ $(BASEDIR)/public/sdk/inc/ntstatus.h $(BASEDIR)/public/sdk/inc/ntxcapi.h \
+ $(BASEDIR)/public/sdk/inc/poppack.h $(BASEDIR)/public/sdk/inc/ppcinst.h \
+ $(BASEDIR)/public/sdk/inc/pshpack1.h $(BASEDIR)/public/sdk/inc/pshpack4.h \
+ $(BASEDIR)/public/sdk/inc/windef.h $(BASEDIR)/public/sdk/inc/winerror.h \
+ $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(CHIVNBTOBJD)/vxdisol.obj $(CHIDVNBTOBJD)/vxdisol.obj $(VNBTSRC)/vxdisol.lst: \
+ $(VNBTSRC)/vxdisol.c ../$(INC)/alpha.h ../$(INC)/alpharef.h \
+ ../$(INC)/arc.h ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h $(INC)/ctemacro.h $(INC)/debug.h $(INC)/nbtnt.h \
+ $(INC)/nbtprocs.h $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h \
+ $(INC)/vxddebug.h $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h \
+ $(CHICAGO)/tcp/h/tdivxd.h $(BASEDIR)/private/inc/nbtioctl.h \
+ $(BASEDIR)/private/inc/nettypes.h $(BASEDIR)/private/inc/packoff.h \
+ $(BASEDIR)/private/inc/packon.h $(BASEDIR)/private/inc/sockets/netinet/in.h \
+ $(BASEDIR)/private/inc/status.h $(BASEDIR)/private/inc/sys/snet/ip_proto.h \
+ $(BASEDIR)/private/inc/tdi.h $(BASEDIR)/private/inc/tdikrnl.h \
+ $(BASEDIR)/private/inc/tdistat.h $(BASEDIR)/public/sdk/inc/alphaops.h \
+ $(BASEDIR)/public/sdk/inc/crt/ctype.h $(BASEDIR)/public/sdk/inc/crt/excpt.h \
+ $(BASEDIR)/public/sdk/inc/crt/limits.h $(BASEDIR)/public/sdk/inc/crt/stdarg.h \
+ $(BASEDIR)/public/sdk/inc/crt/stddef.h $(BASEDIR)/public/sdk/inc/crt/string.h \
+ $(BASEDIR)/public/sdk/inc/devioctl.h $(BASEDIR)/public/sdk/inc/lintfunc.hxx \
+ $(BASEDIR)/public/sdk/inc/mipsinst.h $(BASEDIR)/public/sdk/inc/nb30.h \
+ $(BASEDIR)/public/sdk/inc/netevent.h $(BASEDIR)/public/sdk/inc/nt.h \
+ $(BASEDIR)/public/sdk/inc/ntalpha.h $(BASEDIR)/public/sdk/inc/ntconfig.h \
+ $(BASEDIR)/public/sdk/inc/ntddtdi.h $(BASEDIR)/public/sdk/inc/ntdef.h \
+ $(BASEDIR)/public/sdk/inc/ntelfapi.h $(BASEDIR)/public/sdk/inc/ntexapi.h \
+ $(BASEDIR)/public/sdk/inc/nti386.h $(BASEDIR)/public/sdk/inc/ntimage.h \
+ $(BASEDIR)/public/sdk/inc/ntioapi.h $(BASEDIR)/public/sdk/inc/ntiolog.h \
+ $(BASEDIR)/public/sdk/inc/ntkeapi.h $(BASEDIR)/public/sdk/inc/ntldr.h \
+ $(BASEDIR)/public/sdk/inc/ntlpcapi.h $(BASEDIR)/public/sdk/inc/ntmips.h \
+ $(BASEDIR)/public/sdk/inc/ntmmapi.h $(BASEDIR)/public/sdk/inc/ntnls.h \
+ $(BASEDIR)/public/sdk/inc/ntobapi.h $(BASEDIR)/public/sdk/inc/ntppc.h \
+ $(BASEDIR)/public/sdk/inc/ntpsapi.h $(BASEDIR)/public/sdk/inc/ntregapi.h \
+ $(BASEDIR)/public/sdk/inc/ntrtl.h $(BASEDIR)/public/sdk/inc/ntseapi.h \
+ $(BASEDIR)/public/sdk/inc/ntstatus.h $(BASEDIR)/public/sdk/inc/ntxcapi.h \
+ $(BASEDIR)/public/sdk/inc/poppack.h $(BASEDIR)/public/sdk/inc/ppcinst.h \
+ $(BASEDIR)/public/sdk/inc/pshpack1.h $(BASEDIR)/public/sdk/inc/pshpack4.h \
+ $(BASEDIR)/public/sdk/inc/windef.h $(BASEDIR)/public/sdk/inc/winerror.h \
+ $(BASEDIR)/public/sdk/inc/winnt.h
+
+$(CHIVNBTOBJD)/wfw.obj $(CHIDVNBTOBJD)/wfw.obj $(VNBTSRC)/wfw.lst: $(VNBTSRC)/wfw.c \
+ ../$(INC)/alpha.h ../$(INC)/alpharef.h ../$(INC)/arc.h \
+ ../$(INC)/bugcodes.h ../$(INC)/cache.h ../$(INC)/cm.h \
+ ../$(INC)/cxport.h ../$(INC)/dbgk.h ../$(INC)/ex.h \
+ ../$(INC)/exboosts.h ../$(INC)/exlevels.h ../$(INC)/hal.h \
+ ../$(INC)/i386.h ../$(INC)/init.h ../$(INC)/io.h ../$(INC)/kd.h \
+ ../$(INC)/ke.h ../$(INC)/lfs.h ../$(INC)/lpc.h ../$(INC)/mips.h \
+ ../$(INC)/mm.h ../$(INC)/ntddk.h ../$(INC)/ntiologc.h \
+ ../$(INC)/ntmp.h ../$(INC)/ntos.h ../$(INC)/ntosdef.h ../$(INC)/ob.h \
+ ../$(INC)/ppc.h ../$(INC)/ps.h ../$(INC)/se.h ../$(INC)/updriver.h \
+ ../$(INC)/v86emul.h ../blt/dhcpinfo.h $(INC)/ctemacro.h \
+ $(INC)/debug.h $(INC)/nbtinfo.h $(INC)/nbtnt.h $(INC)/nbtprocs.h \
+ $(INC)/ntprocs.h $(INC)/timer.h $(INC)/types.h $(INC)/vxddebug.h \
+ $(INC)/vxdprocs.h $(CHICAGO)/tcp/h/oscfg.h $(CHICAGO)/tcp/h/tdivxd.h \
+ $(BASEDIR)/private/inc/ipinfo.h $(BASEDIR)/private/inc/llinfo.h \
+ $(BASEDIR)/private/inc/nbtioctl.h $(BASEDIR)/private/inc/nettypes.h \
+ $(BASEDIR)/private/inc/packoff.h $(BASEDIR)/private/inc/packon.h \
+ $(BASEDIR)/private/inc/sockets/netinet/in.h $(BASEDIR)/private/inc/status.h \
+ $(BASEDIR)/private/inc/sys/snet/ip_proto.h $(BASEDIR)/private/inc/tdi.h \
+ $(BASEDIR)/private/inc/tdiinfo.h $(BASEDIR)/private/inc/tdikrnl.h \
+ $(BASEDIR)/private/inc/tdistat.h $(BASEDIR)/public/sdk/inc/alphaops.h \
+ $(BASEDIR)/public/sdk/inc/crt/ctype.h $(BASEDIR)/public/sdk/inc/crt/excpt.h \
+ $(BASEDIR)/public/sdk/inc/crt/limits.h $(BASEDIR)/public/sdk/inc/crt/stdarg.h \
+ $(BASEDIR)/public/sdk/inc/crt/stddef.h $(BASEDIR)/public/sdk/inc/crt/string.h \
+ $(BASEDIR)/public/sdk/inc/devioctl.h $(BASEDIR)/public/sdk/inc/lintfunc.hxx \
+ $(BASEDIR)/public/sdk/inc/mipsinst.h $(BASEDIR)/public/sdk/inc/nb30.h \
+ $(BASEDIR)/public/sdk/inc/netevent.h $(BASEDIR)/public/sdk/inc/nt.h \
+ $(BASEDIR)/public/sdk/inc/ntalpha.h $(BASEDIR)/public/sdk/inc/ntconfig.h \
+ $(BASEDIR)/public/sdk/inc/ntddtdi.h $(BASEDIR)/public/sdk/inc/ntdef.h \
+ $(BASEDIR)/public/sdk/inc/ntelfapi.h $(BASEDIR)/public/sdk/inc/ntexapi.h \
+ $(BASEDIR)/public/sdk/inc/nti386.h $(BASEDIR)/public/sdk/inc/ntimage.h \
+ $(BASEDIR)/public/sdk/inc/ntioapi.h $(BASEDIR)/public/sdk/inc/ntiolog.h \
+ $(BASEDIR)/public/sdk/inc/ntkeapi.h $(BASEDIR)/public/sdk/inc/ntldr.h \
+ $(BASEDIR)/public/sdk/inc/ntlpcapi.h $(BASEDIR)/public/sdk/inc/ntmips.h \
+ $(BASEDIR)/public/sdk/inc/ntmmapi.h $(BASEDIR)/public/sdk/inc/ntnls.h \
+ $(BASEDIR)/public/sdk/inc/ntobapi.h $(BASEDIR)/public/sdk/inc/ntppc.h \
+ $(BASEDIR)/public/sdk/inc/ntpsapi.h $(BASEDIR)/public/sdk/inc/ntregapi.h \
+ $(BASEDIR)/public/sdk/inc/ntrtl.h $(BASEDIR)/public/sdk/inc/ntseapi.h \
+ $(BASEDIR)/public/sdk/inc/ntstatus.h $(BASEDIR)/public/sdk/inc/ntxcapi.h \
+ $(BASEDIR)/public/sdk/inc/poppack.h $(BASEDIR)/public/sdk/inc/ppcinst.h \
+ $(BASEDIR)/public/sdk/inc/pshpack1.h $(BASEDIR)/public/sdk/inc/pshpack4.h \
+ $(BASEDIR)/public/sdk/inc/windef.h $(BASEDIR)/public/sdk/inc/winerror.h \
+ $(BASEDIR)/public/sdk/inc/winnt.h
+
diff --git a/private/ntos/nbt/vxd/dns.c b/private/ntos/nbt/vxd/dns.c
new file mode 100644
index 000000000..f32bfccf4
--- /dev/null
+++ b/private/ntos/nbt/vxd/dns.c
@@ -0,0 +1,984 @@
+/*++
+
+Copyright (c) 1989-1996 Microsoft Corporation
+
+Module Name:
+
+ DNS.c
+
+Abstract:
+
+ VxD-specific DNS routines.
+
+ These routines try to resolve NetBIOS names using DNS.
+
+Author:
+
+ Earle R. Horton (ERH) 13-Feb-1996
+
+Revision History:
+
+--*/
+
+#include "nbtprocs.h"
+
+//
+// function prototypes for completion routines that are local to this file
+//
+//----------------------------------------------------------------------------
+ VOID
+DnsCompletion(
+ PVOID pContext,
+ PVOID pContext2,
+ tTIMERQENTRY *pTimerQEntry
+ )
+/*++
+
+Routine Description:
+
+ This routine is called by the timer code when the timer expires. It must
+ decide if another name query should be sent to the DNS server, and if not,
+ then it calls the client's completion routine (in completion2).
+
+Arguments:
+
+
+Return Value:
+
+ The function value is the status of the operation.
+
+
+Notes:
+--*/
+
+{
+
+ NTSTATUS status;
+ tDGRAM_SEND_TRACKING *pTracker;
+ tDEVICECONTEXT *pDeviceContext;
+ CTELockHandle OldIrq;
+ COMPLETIONCLIENT pClientCompletion;
+ PCHAR pchDomainName;
+ USHORT Flags;
+ BOOL fOneMoreTry;
+ tDGRAM_SEND_TRACKING *pClientTracker;
+
+
+ KdPrint(("DnsCompletion entered\r\n"));
+
+ pTracker = (tDGRAM_SEND_TRACKING *)pContext;
+ pDeviceContext = pTracker->pDeviceContext;
+
+
+ // if the client completion routine is not set anymore, then the
+ // timer has been cancelled and this routine should just clean up its
+ // buffers associated with the tracker (and return)
+ //
+ if (!pTimerQEntry)
+ {
+ // return the tracker block to its queue
+ LOCATION(0x52);
+ DereferenceTrackerNoLock((tDGRAM_SEND_TRACKING *)pContext);
+ return;
+ }
+
+
+ //
+ // to prevent a client from stopping the timer and deleting the
+ // pNameAddr, grab the lock and check if the timer has been stopped
+ //
+ CTESpinLock(&NbtConfig.JointLock,OldIrq);
+ if (pTimerQEntry->Flags & TIMER_RETIMED)
+ {
+ pTimerQEntry->Flags &= ~TIMER_RETIMED;
+ pTimerQEntry->Flags |= TIMER_RESTART;
+ //
+ // if we are not bound to this card than use a very short timeout
+ //
+ if (!pTracker->pDeviceContext->pNameServerFileObject)
+ {
+ pTimerQEntry->DeltaTime = 10;
+ }
+
+ CTESpinFree(&NbtConfig.JointLock,OldIrq);
+ return;
+ }
+
+ if (!pTimerQEntry->ClientCompletion)
+ {
+ CTESpinFree(&NbtConfig.JointLock,OldIrq);
+ return;
+ }
+
+ pClientTracker = (tDGRAM_SEND_TRACKING *)pTimerQEntry->ClientContext;
+
+ //
+ // if the tracker has been cancelled, don't do any more queries
+ //
+ if (pClientTracker->Flags & TRACKER_CANCELLED)
+ {
+ pClientCompletion = pTimerQEntry->ClientCompletion;
+
+ // remove the link from the name table to this timer block
+ CHECK_PTR(((tNAMEADDR *)pTimerQEntry->pCacheEntry));
+
+ ((tNAMEADDR *)pTimerQEntry->pCacheEntry)->pTimer = NULL;
+
+ // to synch. with the StopTimer routine, Null the client
+ // completion routine so it gets called just once.
+ //
+ CHECK_PTR(pTimerQEntry);
+ pTimerQEntry->ClientCompletion = NULL;
+
+ //
+ // remove the name from the hash table, since it did not
+ // resolve via DNS either
+ //
+ CHECK_PTR(pTracker->pNameAddr);
+ pTracker->pNameAddr->NameTypeState &= ~NAME_STATE_MASK;
+ pTracker->pNameAddr->NameTypeState |= STATE_RELEASED;
+ pTracker->pNameAddr->pTimer = NULL;
+
+ //
+ // This call will remove the name from the PendingNameQueries List
+ //
+ NbtDereferenceName(pTracker->pNameAddr);
+
+ CTESpinFree(&NbtConfig.JointLock,OldIrq);
+
+ // there can be a list of trackers Q'd up on this name
+ // query, so we must complete all of them!
+ //
+ CompleteClientReq(pClientCompletion,
+ pClientTracker,
+ STATUS_CANCELLED);
+
+ // return the tracker block to its queue
+ LOCATION(0x51);
+ DereferenceTracker(pTracker);
+
+ KdPrint(("DNS resolution cancelled by client\r\n"));
+
+ return;
+
+ }
+
+ // If done with all the (3) retries with primary, try secondary DNS srvr
+ // If secondary not defined, or done with secondary as well, stop.
+ //
+
+ fOneMoreTry = TRUE;
+
+ if (!(--pTimerQEntry->Retries))
+ {
+ //
+ // if backup server is not defined, or if it is defined but we just
+ // finished trying backup server, go back and try primary server for
+ // "other domains"
+ // e.g. DNSDomains was defined as "msft.dom2.com,msft.dom3.com,msft.dom"
+ // We were pointing at msft.dom2.com. Now, we are done with that (and
+ // didn't get a response), so try msft.dom3.com
+ //
+ if ( ( !pDeviceContext->lDnsBackupServer ) ||
+ ( pDeviceContext->lDnsBackupServer == LOOP_BACK ) ||
+ ( pTracker->Flags & NBT_DNS_SERVER_BACKUP) )
+ {
+ //
+ // if we just got done trying primary domain name, try all the
+ // "other domains" specified
+ //
+ if (pTracker->pchDomainName == NbtConfig.pDomainName)
+ {
+ pTracker->pchDomainName = NbtConfig.pDNSDomains;
+ if ( pTracker->pchDomainName )
+ {
+ pTracker->Flags &= ~NBT_DNS_SERVER_BACKUP;
+ pTracker->Flags |= NBT_DNS_SERVER;
+ pTimerQEntry->Retries = NbtConfig.uNumRetries;
+ }
+ else
+ {
+ fOneMoreTry = FALSE;
+ }
+ }
+
+ //
+ // if we had already started on "other domains", advance to the
+ // next domain within "other domains"
+ //
+ else
+ {
+ pchDomainName = pTracker->pchDomainName;
+ while( *pchDomainName != ',' && // dom names separated by comma
+ *pchDomainName != ' ' && // or space
+ *pchDomainName != '\0' )
+ pchDomainName++;
+
+ if ( *pchDomainName == '\0' )
+ fOneMoreTry = FALSE;
+ else
+ {
+ pchDomainName++;
+ pTracker->pchDomainName = pchDomainName;
+ pTracker->Flags &= ~NBT_DNS_SERVER_BACKUP;
+ pTracker->Flags |= NBT_DNS_SERVER;
+ pTimerQEntry->Retries = NbtConfig.uNumRetries;
+ }
+ }
+ }
+
+ // ok, prepare to try the backup server
+ else
+ {
+ pTimerQEntry->Retries = NbtConfig.uNumRetries;
+
+ pTracker->Flags &= ~NBT_DNS_SERVER;
+ pTracker->Flags |= NBT_DNS_SERVER_BACKUP;
+ }
+ }
+
+ // we aren't done yet: send one more query and restart the timer
+ if (fOneMoreTry)
+ {
+ pTracker->RefCount++;
+
+ CTESpinFree(&NbtConfig.JointLock,OldIrq);
+
+ status = UdpSendNSBcast(pTracker->pNameAddr,
+ NbtConfig.pScope,
+ pTracker,
+ NULL,NULL,NULL,
+ 0,0,
+ eDNS_NAME_QUERY,
+ TRUE);
+
+ DereferenceTracker(pTracker);
+
+ pTimerQEntry->Flags |= TIMER_RESTART;
+
+ KdPrint(("One more DNS query sent out\r\n"));
+ }
+
+ // yup, all done: didn't find the name! give client above the bad news
+ else
+ {
+ tDGRAM_SEND_TRACKING *pClientTracker;
+
+
+ pClientTracker = (tDGRAM_SEND_TRACKING *)pTimerQEntry->ClientContext;
+
+ pClientCompletion = pTimerQEntry->ClientCompletion;
+
+ // remove the link from the name table to this timer block
+ CHECK_PTR(((tNAMEADDR *)pTimerQEntry->pCacheEntry));
+
+ ((tNAMEADDR *)pTimerQEntry->pCacheEntry)->pTimer = NULL;
+
+ // to synch. with the StopTimer routine, Null the client
+ // completion routine so it gets called just once.
+ //
+ CHECK_PTR(pTimerQEntry);
+ pTimerQEntry->ClientCompletion = NULL;
+
+ //
+ // remove the name from the hash table, since it did not
+ // resolve via DNS either
+ //
+ CHECK_PTR(pTracker->pNameAddr);
+ pTracker->pNameAddr->NameTypeState &= ~NAME_STATE_MASK;
+ pTracker->pNameAddr->NameTypeState |= STATE_RELEASED;
+ pTracker->pNameAddr->pTimer = NULL;
+
+ //
+ // This call will remove the name from the PendingNameQueries List
+ //
+ NbtDereferenceName(pTracker->pNameAddr);
+
+ CTESpinFree(&NbtConfig.JointLock,OldIrq);
+
+ // there can be a list of trackers Q'd up on this name
+ // query, so we must complete all of them!
+ //
+ CompleteClientReq(pClientCompletion,
+ pClientTracker,
+ STATUS_TIMEOUT);
+
+ // return the tracker block to its queue
+ LOCATION(0x51);
+ DereferenceTracker(pTracker);
+
+ KdPrint(("DNS resolution failed: told client\r\n"));
+ }
+
+}
+
+//----------------------------------------------------------------------------
+ NTSTATUS
+DoDnsResolve (
+ IN NBT_WORK_ITEM_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ This function is used to allow NBT to query DNS. This is very much like
+ the name query sent out to WINS server or broadcast. Response from the
+ DNS server, if any, is handled by the QueryFromNet() routine.
+
+Arguments:
+
+ *Context (NBT_WORK_ITEM_CONTEXT)
+
+Return Value:
+
+ STATUS_PENDING (unless something goes wrong)
+
+Notes:
+--*/
+
+{
+
+ tDGRAM_SEND_TRACKING *pTracker;
+ tDEVICECONTEXT *pDeviceContext;
+ ULONG Timeout;
+ USHORT Retries;
+ NTSTATUS status;
+ PVOID pClientCompletion;
+ PVOID pCompletionRoutine;
+ PVOID pClientContext;
+
+
+
+ KdPrint(("DoDnsResolve entered\r\n"));
+
+ pTracker = Context->pTracker;
+
+ pDeviceContext = pTracker->pDeviceContext;
+
+ //
+ // If the primary DNS server is not defined, just return error.
+ if ( (!pDeviceContext->lDnsServerAddress) ||
+ ( pDeviceContext->lDnsServerAddress == LOOP_BACK) )
+ {
+ return( NRC_CMDTMO );
+ }
+
+ pTracker->Flags &= ~(NBT_BROADCAST|NBT_NAME_SERVER|NBT_NAME_SERVER_BACKUP);
+ pTracker->Flags |= NBT_DNS_SERVER;
+
+ pClientContext = Context->pClientContext;
+ pClientCompletion = Context->ClientCompletion;
+ pCompletionRoutine = DnsCompletion;
+
+ //
+ // free that memory now
+ //
+ CTEMemFree(Context);
+
+ //
+ // Put on the pending name queries list again so that when the query
+ // response comes in from DNS we can find the pNameAddr record.
+ //
+ ExInterlockedInsertTailList(&NbtConfig.PendingNameQueries,
+ &pTracker->pNameAddr->Linkage,
+ &NbtConfig.JointLock.SpinLock);
+
+ Timeout = (ULONG)pNbtGlobConfig->uRetryTimeout;
+ Retries = pNbtGlobConfig->uNumRetries;
+
+ pTracker->RefCount++;
+
+ //
+ // first time, we want to try the primary domain name
+ //
+ pTracker->pchDomainName = NbtConfig.pDomainName;
+
+ status = UdpSendNSBcast(pTracker->pNameAddr,
+ NbtConfig.pScope,
+ pTracker,
+ pCompletionRoutine,
+ pClientContext,
+ pClientCompletion,
+ Retries,
+ Timeout,
+ eDNS_NAME_QUERY,
+ TRUE);
+
+ DereferenceTracker(pTracker);
+
+ KdPrint(("Leaving DoDnsResolve\r\n"));
+
+ return( status );
+
+
+}
+
+//----------------------------------------------------------------------------
+ PCHAR
+DnsStoreName
+(
+ OUT PCHAR pDest,
+ IN PCHAR pName,
+ IN PCHAR pDomainName,
+ IN enum eNSTYPE eNsType
+ )
+/*++
+
+Routine Description:
+
+ This routine copies the netbios name (and appends the scope on the
+ end) in the DNS namequery packet
+
+Arguments:
+
+
+Return Value:
+
+ the address of the next byte in the destination after the the name
+ has been copied
+
+--*/
+{
+ LONG i;
+ LONG count;
+ PCHAR pStarting;
+ PCHAR pSrc;
+ LONG DomNameSize;
+ LONG OneMoreSubfield;
+
+ LONG lMaxCount;
+ CHAR cTerminator;
+
+ if (eNsType == eDIRECT_DNS_NAME_QUERY)
+ {
+ lMaxCount = 255;
+ cTerminator = 0;
+ }
+ else
+ {
+ lMaxCount = NETBIOS_NAME_SIZE-1;
+ cTerminator = 0x20;
+ }
+
+
+ pStarting = pDest++;
+ count = 0;
+ //
+ // copy until we reach the space padding
+ //
+ while ( ( count < lMaxCount ) && (*pName != cTerminator) )
+ {
+ *pDest++ = *pName++;
+ count++;
+ }
+
+ *pStarting = (CHAR)count;
+
+ //
+ // check if domain name exists. koti.microsoft.com will be represented
+ // as 4KOTI9microsoft3com0 (where nos. => no. of bytes of subfield)
+ //
+ pSrc = pDomainName;
+ if (pSrc && pSrc[0] != '\0')
+ {
+ OneMoreSubfield = 1;
+
+ while( OneMoreSubfield )
+ {
+ count = 0;
+ pStarting = pDest++;
+ //
+ // remember, the domain name we receive can also be a set of "other
+ // domains" to try in the form "msft.dom2.com,msft.dom3.com"
+ //
+ while ( *pSrc != '.' && *pSrc != '\0' && *pSrc != ',')
+ {
+ *pDest++ = *pSrc++;
+ count++;
+ }
+ *pStarting = (CHAR)count;
+
+ if (*pSrc == '\0' || *pSrc == ',')
+ OneMoreSubfield = 0;
+ else
+ pSrc++;
+ }
+ }
+
+ *pDest++ = 0;
+
+
+ // return the address of the next byte of the destination
+ return(pDest);
+}
+
+
+
+
+//----------------------------------------------------------------------------
+ VOID
+DnsExtractName(
+ IN PCHAR pNameHdr,
+ IN LONG NumBytes,
+ OUT PCHAR pName,
+ OUT PULONG pNameSize
+ )
+/*++
+
+Routine Description:
+
+ This routine extracts the name from the packet and then appends the scope
+ onto the end of the name to make a full name.
+
+Arguments:
+ NumBytes - the total number of bytes in the message - may include
+ more than just the name itself
+
+Return Value:
+
+
+--*/
+{
+
+
+ LONG i;
+ int iIndex;
+ LONG lValue;
+ ULONG UNALIGNED *pHdr;
+ PCHAR pSavName;
+ ULONG Len;
+
+
+ KdPrint(("DnsExtractName entered\r\n"));
+
+ //
+ // how long is the name we received
+ //
+ Len = (ULONG)((UCHAR)*pNameHdr);
+
+ ++pNameHdr; // to increment past the length byte
+
+ pSavName = pName;
+
+ // copy the name (no domain) as given by DNS server (i.e., just copy
+ // foobar when DNS returned foobar.microsoft.com in the response
+ // (this is likely to be less than the usualy 16 byte len)
+ //
+ for (i=0; i < Len ;i++ )
+ {
+ *pName = *pNameHdr;
+ pNameHdr++;
+ if (i < NETBIOS_NAME_SIZE)
+ {
+ pName++;
+ }
+ }
+
+ //
+ // now, make it look like NBNS responded, by adding the 0x20 pad
+ //
+ for (i=Len; i<NETBIOS_NAME_SIZE; i++)
+ {
+ *pName++ = 0x20;
+ }
+
+ //
+ // convert all chars to uppercase since all our names are in uppercase!
+ //
+ for (i=0; i<NETBIOS_NAME_SIZE; i++)
+ {
+ if (*pSavName >= 'a' && *pSavName <= 'z')
+ *pSavName = *pSavName - ('a'-'A');
+
+ pSavName++;
+ }
+
+ //
+ // at this point we are pointing to the '.' after foobar. Find the
+ // length of the entire name
+ //
+ while ( (*pNameHdr != '\0') && (Len < NumBytes) )
+ {
+ pNameHdr++;
+ Len++;
+ }
+
+ Len++; // to account for the trailing 0
+
+ *pNameSize = Len;
+
+ KdPrint(("Leaving DnsExtractName\r\n"));
+
+ return;
+}
+
+
+//----------------------------------------------------------------------------
+ ULONG
+domnamelen(
+ IN PCHAR pDomainName
+ )
+/*++
+
+Routine Description:
+
+ This routine determines the length of the domainname. This is basically
+ strlen, except that the DNSDomain field is stored as a bunch of
+ domain names separated by commas, so we treat '\0' as well as ',' as
+ string terminators for this function.
+
+Arguments:
+
+
+Return Value:
+
+ length of the domain name
+
+--*/
+{
+
+ ULONG ulDomnameLen=0;
+
+ if (pDomainName)
+ {
+ while(*pDomainName != '\0' && *pDomainName != ',')
+ {
+ pDomainName++;
+ ulDomnameLen++;
+ }
+ }
+
+ return( ulDomnameLen );
+}
+
+//----------------------------------------------------------------------------
+ VOID
+ProcessDnsResponse(
+ IN tDEVICECONTEXT *pDeviceContext,
+ IN PVOID pSrcAddress,
+ IN tNAMEHDR UNALIGNED *pNameHdr,
+ IN LONG lNumBytes,
+ IN USHORT OpCodeFlags
+ )
+/*++
+
+Routine Description:
+
+ This function sets the state of the name being resolved appropriately
+ depending on whether DNS sends a positive or a negative response to our
+ query; calls the client completion routine and stops any more DNS queries
+ from going.
+
+Arguments:
+
+
+Return Value:
+
+ NTSTATUS - STATUS_SUCCESS or STATUS_UNSUCCESSFUL
+
+--*/
+{
+
+
+ NTSTATUS status;
+ tDNS_QUERYRESP UNALIGNED *pQuery;
+ tNAMEADDR *pResp;
+ tTIMERQENTRY *pTimer;
+ COMPLETIONCLIENT pClientCompletion;
+ PVOID Context;
+ PTRANSPORT_ADDRESS pSourceAddress;
+ ULONG SrcAddress;
+ CTELockHandle OldIrq1;
+ LONG lNameSize;
+ LONG lTraversedSoFar=0;
+ CHAR pName[NETBIOS_NAME_SIZE];
+ CHAR pJunkBuf[NETBIOS_NAME_SIZE];
+ PUCHAR pScope;
+ PUCHAR pchQry;
+
+
+
+ KdPrint(("ProcessDnsResponse entered\r\n"));
+
+
+ // make sure this is a response
+
+ if ( !(OpCodeFlags & OP_RESPONSE) )
+ {
+ CDbgPrint(DBGFLAG_ERROR,("ProcessDnsResponse: Bad OpCodeFlags\r\n"));
+
+ return;
+ }
+
+ pSourceAddress = (PTRANSPORT_ADDRESS)pSrcAddress;
+ SrcAddress = ntohl(((PTDI_ADDRESS_IP)&pSourceAddress->Address[0].Address[0])->in_addr);
+
+ // get the name out of the network pdu and pass to routine to check
+ // local table
+ DnsExtractName( (PCHAR)&pNameHdr->NameRR.NameLength,
+ lNumBytes,
+ pName,
+ &lNameSize
+ );
+
+ CTESpinLock(&NbtConfig.JointLock,OldIrq1);
+
+ //
+ // we chopped off 16th byte while sending a query, so compare only first
+ // 15 characters for a match
+ //
+ status = FindOnPendingList(pName,pNameHdr,FALSE,NETBIOS_NAME_SIZE-1,&pResp);
+
+ if (!NT_SUCCESS(status))
+ {
+ //
+ // The name is not there in the remote name table. Nothing
+ // more to do. Just return.
+ //
+ CTESpinFree(&NbtConfig.JointLock,OldIrq1);
+
+ CDbgPrint(DBGFLAG_ERROR,("ProcessDnsResponse: name not found\r\n"));
+
+ return;
+ }
+
+ //
+ // If the response we received doesn't resolve the name, we silently return,
+ // but make sure reties is set to 1 so that when timer fires again, we don't
+ // send another name query to the same server but instead timeout the
+ // attempt on this server
+ //
+ if ((pTimer = pResp->pTimer))
+ {
+ pTimer->Retries = 1;
+ }
+
+
+ //
+ // check the pdu size for errors
+ //
+ if (lNumBytes < DNS_MINIMUM_QUERYRESPONSE)
+ {
+ CDbgPrint(DBGFLAG_ERROR,("ProcessDnsResponse: Bad lNumBytes\r\n"));
+
+ CTESpinFree(&NbtConfig.JointLock,OldIrq1);
+
+ return;
+ }
+
+//
+// BUGBUG: should we require authoritative responses from DNS servers?
+//
+
+ //
+ // if it's a negative response, quit now!
+ //
+ if (IS_NEG_RESPONSE(OpCodeFlags))
+ {
+ CTESpinFree(&NbtConfig.JointLock,OldIrq1);
+ return;
+ }
+
+ //
+ // if there is no answer section, return!
+ //
+ if ( !pNameHdr->AnCount )
+ {
+ CDbgPrint(DBGFLAG_ERROR,("ProcessDnsResponse: No answer section\r\n"));
+ CTESpinFree(&NbtConfig.JointLock,OldIrq1);
+ return;
+ }
+
+ //
+ // lNameSize is the length of the entire name, excluding the length byte
+ // for the first label (including length bytes of subsequent labels) and
+ // including the trailing 0 (tNAMEHDR struc takes care for 1st byte)
+ //
+ pchQry = (PUCHAR)&pNameHdr->NameRR.NetBiosName[lNameSize];
+
+ lTraversedSoFar += lNameSize;
+
+ //
+ // if the Question section is returned with the response then we have
+ // a little more work to do! In this case, pQuery is pointing at the
+ // beginning of the QTYPE field (end of the QNAME)
+ //
+ if ( pNameHdr->QdCount )
+ {
+ pchQry += sizeof(tQUESTIONMODS);
+ lTraversedSoFar += sizeof(tQUESTIONMODS);
+
+ // most common case: 1st byte will be 0xC0, which means next byte points
+ // to the actual name. We don't care about the name, so we skip over
+ // both the bytes
+ //
+ if ( (*pchQry) == PTR_TO_NAME )
+ {
+ pchQry += sizeof(tDNS_LABEL);
+ lTraversedSoFar += sizeof(tDNS_LABEL);
+ }
+
+ //
+ // if some implementation doesn't optimize and copies the whole name
+ // again, skip over the length of the name
+ //
+ else
+ {
+ pchQry += (lNameSize+1); // +1 because of the 1st length byte!
+ lTraversedSoFar += (lNameSize+1);
+ }
+ }
+
+ pQuery = (tDNS_QUERYRESP *)pchQry;
+
+ //
+ // if this rr is telling us about canonical name, skip over it and go to
+ // where the ipaddr is
+ //
+ if (ntohs(pQuery->RrType) == DNS_CNAME)
+ {
+ //
+ // since this is CNAME, there is no ipaddr. Instead, the data is the
+ // canonical name whose length we are adding, and subtract ipaddr's len
+ //
+ pchQry += (sizeof(tDNS_QUERYRESP) - sizeof(ULONG));
+ pchQry += ntohs(pQuery->Length);
+ lTraversedSoFar += ntohs(pQuery->Length) + sizeof(tDNS_QUERYRESP) - sizeof(ULONG);
+
+ ASSERT(lNumBytes > lTraversedSoFar);
+
+ // most common case: 1st byte will be 0xC0, which means next byte points
+ // to the actual name. We don't care about the name, so we skip over
+ // both the bytes
+ //
+ if ( (*pchQry) == PTR_TO_NAME )
+ {
+ pchQry += sizeof(tDNS_LABEL);
+ lTraversedSoFar += sizeof(tDNS_LABEL);
+ }
+
+ //
+ // if some implementation doesn't optimize and copies the whole name
+ // again, skip over the length of the name
+ //
+ else
+ {
+ // we have already taken the name out. we are calling this routine
+ // just to see how big the canonical name is (i.e.lNameSize), to skip
+ // past it
+ //
+ DnsExtractName( pchQry,
+ lNumBytes-lTraversedSoFar,
+ pJunkBuf,
+ &lNameSize
+ );
+
+ //
+ // lNameSize is the length of the entire name, excluding the length byte
+ // for the first label (including length bytes of subsequent labels) and
+ // including the trailing 0 (tNAMEHDR struc takes care for 1st byte)
+ //
+ pchQry += lNameSize+1; // +1 for the length byte of first label
+
+ }
+
+ pQuery = (tDNS_QUERYRESP *)pchQry;
+ }
+
+
+ // if we came this far, it's a positive response. stop the timer and do
+ // the needful..
+
+ // remove any timer block and call the completion routine
+ if (pTimer)
+ {
+ USHORT Flags;
+ tDGRAM_SEND_TRACKING *pTracker;
+
+ pTracker = (tDGRAM_SEND_TRACKING *)pTimer->Context;
+
+ //
+ // this routine puts the timer block back on the timer Q, and
+ // handles race conditions to cancel the timer when the timer
+ // is expiring.
+ status = StopTimer(pTimer,&pClientCompletion,&Context);
+
+ //
+ // Synchronize with DnsCompletion
+ //
+ if (pClientCompletion)
+ {
+ CHECK_PTR(pResp);
+ pResp->pTimer = NULL;
+
+ //
+ // Remove from the PendingNameQueries List
+ //
+ RemoveEntryList(&pResp->Linkage);
+ InitializeListHead(&pResp->Linkage);
+
+ KdPrint(("ProcessDnsResponse: positive DNS response received\r\n"));
+
+ if (pResp->NameTypeState & STATE_RESOLVING)
+ {
+ pResp->NameTypeState &= ~NAME_STATE_MASK;
+ pResp->NameTypeState |= STATE_RESOLVED;
+
+ pResp->IpAddress = ntohl(pQuery->IpAddress);
+
+ pResp->AdapterMask = (CTEULONGLONG)-1;
+ status = AddRecordToHashTable(pResp,NbtConfig.pScope);
+
+ if (!NT_SUCCESS(status))
+ {
+ //
+ // the name must already be in the hash table,
+ // so dereference it to remove it
+ //
+ NbtDereferenceName(pResp);
+ }
+
+ IncrementNameStats(NAME_QUERY_SUCCESS, TRUE);
+ }
+
+ status = STATUS_SUCCESS;
+
+ //
+ // Set the backup name server to be the main name server
+ // since we got a response from it.
+ //
+ if ( SrcAddress == pDeviceContext->lDnsBackupServer )
+ {
+ pDeviceContext->lDnsBackupServer =
+ pDeviceContext->lDnsServerAddress;
+
+ pDeviceContext->lDnsServerAddress = SrcAddress;
+ }
+
+ CTESpinFree(&NbtConfig.JointLock,OldIrq1);
+
+ // the completion routine has not run yet, so run it
+ (void) CTEQueueForNonDispProcessing(
+ (tDGRAM_SEND_TRACKING *)Context,
+ (PVOID)status,
+ pClientCompletion,
+ DelayedSessEstablish,
+ pDeviceContext);
+ }
+
+ else
+ {
+ CTESpinFree(&NbtConfig.JointLock,OldIrq1);
+ }
+
+ return;
+
+ }
+
+ CTESpinFree(&NbtConfig.JointLock,OldIrq1);
+
+ KdPrint(("Leaving ProcessDnsResponse\r\n"));
+
+ return;
+
+}
diff --git a/private/ntos/nbt/vxd/fileio.c b/private/ntos/nbt/vxd/fileio.c
new file mode 100644
index 000000000..b319ce290
--- /dev/null
+++ b/private/ntos/nbt/vxd/fileio.c
@@ -0,0 +1,476 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ fileio.c
+
+Abstract:
+
+ This source implements a stdio-like facility.
+
+Author:
+
+ Eric Chin (ericc) April 28, 1992
+ John Ludeman (johnl) Oct 8, 1993 - Rewrote for Vxd
+
+Revision History:
+
+--*/
+
+#include <nbtprocs.h>
+#include "hosts.h"
+
+//
+// The maximum line length for a file in the lmhosts file is 256 bytes for
+// the Vxd
+//
+#define MAX_LMHOSTS_LINE 256
+
+//
+// The number of bytes we buffer on each read
+//
+#define LMHOSTS_READ_BUFF_SIZE 256
+
+UCHAR GetNextChar( PLM_FILE pFile ) ;
+
+VOID RestoreOldData( PLM_FILE pFile );
+
+BackupCurrentData( PLM_FILE pFile );
+
+//******************* Pageable Routine Declarations ****************
+#ifdef ALLOC_PRAGMA
+#pragma CTEMakePageable(PAGE, LmCloseFile)
+#pragma CTEMakePageable(PAGE, LmFgets)
+#pragma CTEMakePageable(PAGE, GetNextChar)
+#pragma CTEMakePageable(PAGE, LmOpenFile)
+#pragma CTEMakePageable(PAGE, BackupCurrentData)
+#pragma CTEMakePageable(PAGE, RestoreOldData)
+#endif
+
+#ifdef CHICAGO
+//
+// In case of chicago, use only linear addresses (Allocate_Global_V86_Data_Area
+// call is available only at init time, not if vnbt is load dynamically!)
+//
+#define pMappedFileBuff pFileBuff
+#define pMappedFilePath pFilePath
+
+#else
+//
+// In case of snowball, this is the address of the V86 mapped memory for
+// the file read buffer and lmhosts file path
+//
+PVOID pMappedFileBuff = NULL ;
+PVOID pMappedFilePath = NULL ;
+#endif
+
+//
+// Linear address for file buffer and path (accessible from Vxd)
+//
+PUCHAR pFileBuff = NULL ;
+PUCHAR pFilePath = NULL ;
+
+
+/*******************************************************************
+
+ NAME: VxdInitLmHostsSupport
+
+ SYNOPSIS: This function just allocates memory to read the contents
+ of file into.
+ (trying to minimize on changes to snowball side of code
+ whic has already shipped: that's why this function!)
+
+ ENTRY: pchLmHostPath - path to lmhosts file (not used here)
+ ulPathSize - size, in chars, of the path
+
+ RETURNS: TRUE if it works, FALSE if it doesn't.
+ COMMENTS: This is Chicago version of the function. Snowball's
+ version is in vxdfile.asm
+
+ HISTORY:
+ Koti Oct 10, 94
+
+********************************************************************/
+
+#ifdef CHICAGO
+BOOL
+VxdInitLmHostsSupport( PUCHAR pchLmHostPath, USHORT ulPathSize )
+{
+
+ USHORT Size;
+
+ Size = ulPathSize + LMHOSTS_READ_BUFF_SIZE;
+
+ pFileBuff = CTEAllocInitMem( Size );
+ if (pFileBuff == NULL)
+ {
+ DbgPrint("VxdInitLmHostsSupport: failed to allocate memory") ;
+ return( FALSE );
+ }
+
+ pFilePath = pFileBuff + LMHOSTS_READ_BUFF_SIZE;
+
+ return( TRUE );
+
+}
+
+#endif
+//----------------------------------------------------------------------------
+
+NTSTATUS
+LmCloseFile (
+ IN PLM_FILE pfile
+ )
+
+/*++
+
+Routine Description:
+
+ This function closes a file opened via LmOpenFile(), and frees its
+ LM_FILE object.
+
+Arguments:
+
+ pfile - pointer to the LM_FILE object
+
+Return Value:
+
+ An NTSTATUS value.
+
+--*/
+
+
+{
+ CTEPagedCode();
+
+ CDbgPrint(DBGFLAG_LMHOST, "LmCloseFile entered\r\n") ;
+ CTEFreeMem( pfile->f_linebuffer );
+
+ VxdFileClose( pfile->f_handle ) ;
+
+ CTEFreeMem(pfile);
+
+ CDbgPrint(DBGFLAG_LMHOST, "LmCloseFile leaving\r\n") ;
+ return STATUS_SUCCESS ;
+
+} // LmCloseFile
+
+
+
+//----------------------------------------------------------------------------
+
+PUCHAR
+LmFgets (
+ IN PLM_FILE pfile,
+ OUT int *nbytes
+ )
+
+/*++
+
+Routine Description:
+
+ This function is vaguely similar to fgets(3).
+
+ Starting at the current seek position, it reads through a newline
+ character, or the end of the file. If a newline is encountered, it
+ is replaced with a NULL character.
+
+Arguments:
+
+ pfile - file to read from
+ nbytes - the number of characters read, excluding the NULL character
+
+Return Value:
+
+ A pointer to the beginning of the line, or NULL if we are at or past
+ the end of the file.
+
+--*/
+{
+ ULONG cbLine = 0 ;
+ UCHAR ch ;
+ BOOL fDone = FALSE ;
+ BOOL fEOL = FALSE ;
+
+
+ CTEPagedCode();
+
+ while ( TRUE )
+ {
+ switch ( ch = GetNextChar( pfile ))
+ {
+ case '\n': // End of line
+ if ( !cbLine ) // If it's just a '\n' by itself, ignore it
+ continue ;
+ //
+ // Fall through
+ //
+
+ case '\0': // End of file
+ pfile->f_linebuffer[cbLine] = '\0' ;
+ fDone = TRUE ;
+ fEOL = TRUE ;
+ break ;
+
+ case '\r': // Ignore
+ continue ;
+
+ default:
+ pfile->f_linebuffer[cbLine] = ch ;
+ if ( cbLine == (MAX_LMHOSTS_LINE-1) )
+ {
+ pfile->f_linebuffer[cbLine--] = '\0' ;
+ fDone = TRUE ;
+ }
+ break ;
+ }
+
+ if ( fDone )
+ break ;
+
+ cbLine++ ;
+ }
+
+ //
+ // Scan till the end of this line
+ //
+ if ( !fEOL )
+ {
+ while ( (ch = GetNextChar(pfile)) && ch != '\n' )
+ ;
+ }
+
+ if ( cbLine )
+ {
+ (pfile->f_lineno)++ ;
+ *nbytes = cbLine ;
+
+ CDbgPrint( DBGFLAG_LMHOST, "LmFgets returning \"") ;
+ CDbgPrint( DBGFLAG_LMHOST, pfile->f_linebuffer ) ;
+ CDbgPrint( DBGFLAG_LMHOST, "\", nbytes = 0x") ;
+ CDbgPrintNum( DBGFLAG_LMHOST, *nbytes ) ;
+ CDbgPrint( DBGFLAG_LMHOST, "\r\n") ;
+
+ return pfile->f_linebuffer ;
+ }
+
+ return NULL ;
+}
+
+/*******************************************************************
+
+ NAME: GetNextChar
+
+ SYNOPSIS: Gets the next character from the file or the line buffer
+
+ ENTRY: pFile - File we are operating on
+
+ RETURNS: Next character or '\0' if at the end of file (or there is an
+ embedded '\0' in the file).
+
+ NOTES:
+
+********************************************************************/
+
+UCHAR GetNextChar( PLM_FILE pFile )
+{
+ ULONG BytesRead ;
+
+ CTEPagedCode();
+
+ if ( pFile->f_CurPos < pFile->f_EndOfData )
+ return pFile->f_buffer[pFile->f_CurPos++] ;
+
+ if ( pFile->f_EOF )
+ return '\0' ;
+
+ //
+ // We've reached the end of the buffer, get more data
+ //
+ BytesRead = VxdFileRead( pFile->f_handle,
+ LMHOSTS_READ_BUFF_SIZE,
+ pMappedFileBuff ) ;
+ pFile->f_CurPos = 0 ;
+ if ( BytesRead < LMHOSTS_READ_BUFF_SIZE )
+ pFile->f_EOF = TRUE ;
+
+ //
+ // If haven't hit the end of the file, return the next character
+ //
+ if ( (pFile->f_EndOfData = BytesRead) )
+ return pFile->f_buffer[pFile->f_CurPos++] ;
+
+ return '\0' ;
+}
+
+
+
+//----------------------------------------------------------------------------
+
+PLM_FILE
+LmOpenFile (
+ IN PUCHAR path
+ )
+
+/*++
+
+Routine Description:
+
+ This function opens a file for use by LmFgets().
+
+Arguments:
+
+ path - a fully specified, complete path to the file.
+
+Return Value:
+
+ A pointer to an LM_FILE object, or NULL if unsuccessful.
+
+Notes:
+
+ The first time through, we map the lmhosts memory to vm memory and
+ allocate a read buffer and map that to VM memory. Note that this means
+ the path must not change and this routine is not reentrant!!
+
+ The reason for this is because the mapping is an expensive operation
+ (and there isn't a way to unmap when using Map_Lin_To_VM_Addr).
+
+--*/
+
+
+{
+ HANDLE handle;
+ PLM_FILE pfile;
+ PCHAR pLineBuff = CTEAllocMem( MAX_LMHOSTS_LINE ) ;
+ static int fInRoutine = 0 ;
+
+ CTEPagedCode();
+
+
+ if (fInRoutine++)
+ {
+ CDbgPrint( DBGFLAG_LMHOST, "exiting LmOpenFile: not reentrant!\r\n") ;
+ goto ErrorExit; // We're not reentrant
+ }
+
+ CDbgPrint( DBGFLAG_LMHOST, "LmOpenFile entered\r\n") ;
+
+ strcpy( pFilePath, path ) ;
+
+ if ( !pLineBuff || !pFileBuff )
+ goto ErrorExit ;
+
+ handle = (HANDLE) VxdFileOpen( pMappedFilePath ) ;
+
+ if ( handle == NULL )
+ {
+ goto ErrorExit ;
+ }
+
+ pfile = (PLM_FILE) CTEAllocMem( sizeof(LM_FILE) );
+
+ if (!pfile)
+ {
+ VxdFileClose( handle ) ;
+ goto ErrorExit ;
+ }
+
+ pfile->f_handle = handle;
+ pfile->f_lineno = 0;
+ pfile->f_buffer = pFileBuff ;
+ pfile->f_linebuffer = pLineBuff ;
+ pfile->f_EndOfData = 0 ;
+ pfile->f_CurPos = 0 ;
+ pfile->f_EOF = FALSE ;
+
+ CDbgPrint( DBGFLAG_LMHOST, "LmOpenFile returning\r\n") ;
+
+ fInRoutine-- ;
+
+ return pfile ;
+
+ErrorExit:
+
+ fInRoutine--;
+
+ if ( pLineBuff )
+ CTEFreeMem( pLineBuff ) ;
+
+ return NULL ;
+
+} // LmOpenFile
+
+
+//----------------------------------------------------------------------------
+
+BOOL
+BackupCurrentData( PLM_FILE pFile )
+
+/*++
+
+Routine Description:
+
+ This function backs up all the data from lmhosts file into another buffer
+ (which is allocated).
+ This function is called before opening the next file that we encountered
+ via #INCLUDE. Since the same buffer is used to store the VxdReadFile data,
+ we need to save this data.
+
+Arguments:
+
+ pFile - LMfile pointer
+
+Return Value:
+
+ TRUE if everything went ok
+ FALSE if memory couldn't be allocated
+
+--*/
+{
+
+ CTEPagedCode();
+
+ pFile->f_BackUp = CTEAllocMem( MAX_LMHOSTS_LINE ) ;
+ if (pFile->f_BackUp == NULL )
+ {
+ return( FALSE );
+ }
+
+ CTEMemCopy( pFile->f_BackUp, pFile->f_buffer, LMHOSTS_READ_BUFF_SIZE );
+
+ return( TRUE );
+}
+
+
+//----------------------------------------------------------------------------
+
+VOID RestoreOldData( PLM_FILE pFile )
+/*++
+
+Routine Description:
+
+ This function restores all the data we backed up in BackupCurrentData
+
+Arguments:
+
+ pFile - LMfile pointer
+
+Return Value:
+
+ TRUE if everything went ok
+ FALSE if memory couldn't be allocated
+
+--*/
+{
+
+ CTEPagedCode();
+
+ CTEMemCopy( pFile->f_buffer, pFile->f_BackUp, LMHOSTS_READ_BUFF_SIZE );
+
+ CTEFreeMem( pFile->f_BackUp ) ;
+
+}
+
+
diff --git a/private/ntos/nbt/vxd/limit.txt b/private/ntos/nbt/vxd/limit.txt
new file mode 100644
index 000000000..726b7c7d7
--- /dev/null
+++ b/private/ntos/nbt/vxd/limit.txt
@@ -0,0 +1,51 @@
+
+============================================================================
+ NBT Limitations
+============================================================================
+
+This document lists the currently known limitations of the NBT Vxd.
+
+* The following Netbios commands are not supported:
+
+ NCBENUM
+ NCBLANSTALERT
+ NCBACTION
+
+ NCBSEND_RCVANY (Transceive) - Not necessary to support
+
+* Permanent adapter name may not have all of its listens & calls on cleaned
+ up on reset
+
+* NCBCANCEL only supports cancelling the following NCBs:
+ NCBRECV
+ NCBDGRECV
+ NCBDGRECVBC
+ NCBRECVANY
+ NCBLISTEN
+ NCBSEND
+ NCBSENDNA
+ NCBCHAINSEND
+ NCBCHAINSENDNA
+ NCBCALL
+
+* Call NCB opens a connection which will immediately be closed by NbtConnect.
+ Need to pass a flag (or NULL connect element) indicating we haven't set up
+ an inbound connection because we don't need to in this case.
+
+* On remote disconnects, if a send was just submitted, we may have to timeout
+ the TdiDisconnect because the FYN ACK may never get submitted (queued behind
+ send which can't complete because session is down).
+
+* Would be good to keep queue of preallocated buffers for Delayed calls
+
+* Name table numbers may not match in ASTAT command (Not OS code assigns
+ numbers based on the hashtable, the Vxd needs to use its name table
+
+* Extended lowercase characters in lmhosts file may not be upper cased
+ correctly (and thus not be usable). Need better upper case code.
+
+* If a program tries to exec or open a UNC that requires the LMHosts file,
+ nbt may not be able to satisfy the request because the InDos flag will
+ be set, thus nbt will not be able to read the lmhosts file. Normally
+ it will reschedule the read for some later time, but that will not work
+ in this instance. It retries 10 times then times out the request.
diff --git a/private/ntos/nbt/vxd/makefile b/private/ntos/nbt/vxd/makefile
new file mode 100644
index 000000000..a5c9e15c5
--- /dev/null
+++ b/private/ntos/nbt/vxd/makefile
@@ -0,0 +1,28 @@
+#
+#:ts=4
+# Makefile for the NBT component
+#
+ROOTDIR=..
+!include rules.mk
+
+all: svnbt svnbtd
+
+nodebug: svnbt cvnbt
+
+debug: svnbtd cvnbtd
+
+#
+# Don't build Windows 95 version from this tree any more.
+# Use QFE tree for Windows 95 bug fixes.
+# Use makefiles in VXD.000 directory for post-Windows 95
+# versions.
+#
+#all: svnbt svnbtd cvnbt cvnbtd
+#
+#nodebug: svnbt cvnbt
+#
+#debug: svnbtd cvnbtd
+#
+
+!include vnbtd.mk
+!include depend.mk
diff --git a/private/ntos/nbt/vxd/nbtinfo.c b/private/ntos/nbt/vxd/nbtinfo.c
new file mode 100644
index 000000000..ad267685f
--- /dev/null
+++ b/private/ntos/nbt/vxd/nbtinfo.c
@@ -0,0 +1,227 @@
+/**********************************************************************/
+/** Microsoft Windows/NT **/
+/** Copyright(c) Microsoft Corp., 1993 **/
+/**********************************************************************/
+
+/*
+ Nbtinfo.c
+
+ This file contains the NBT Info APIs
+
+
+
+ FILE HISTORY:
+ Johnl 13-Dec-1993 Created
+
+*/
+
+
+#include <nbtprocs.h>
+#include <dhcpinfo.h>
+#include <nbtinfo.h>
+
+/*******************************************************************
+
+ NAME: AddrChngNotification
+
+ SYNOPSIS: Notification handler called by Dhcp when an IpAddress
+ lease has expired or changed.
+
+ ENTRY: Context - Pointer to device context
+ OldIpAddress - in network order
+ NewIpAddress - in network order
+ NewMask - in network order
+
+ NOTES:
+
+ HISTORY:
+ Johnl 21-Dec-1993 Created
+
+********************************************************************/
+
+VOID AddrChngNotification( PVOID Context,
+ ULONG OldIpAddress,
+ ULONG NewIpAddress,
+ ULONG NewMask )
+{
+ tDEVICECONTEXT * pDeviceContext = (tDEVICECONTEXT*) Context ;
+ TDI_STATUS tdistatus ;
+ NTSTATUS status ;
+ ULONG IpBuff[4] ;
+ UINT Size ;
+ ULONG TmpNodeType;
+
+ DbgPrint("DhcpNotification: Nbt being notified of IP Address change by DHCP\r\n") ;
+
+ //
+ // NBT assumes the address goes to zero then comes up on the new
+ // address, so if the address is going to a new address (not to
+ // zero first) then fake it.
+ //
+
+ if ( NewIpAddress && pDeviceContext->IpAddress )
+ {
+ if ( status = NbtNewDhcpAddress( pDeviceContext, 0, 0 ) )
+ {
+ CDbgPrint( DBGFLAG_ERROR, ("DhcpNotification: NbtSetNewDhcpAddress failed")) ;
+ }
+ }
+
+ if ( NewIpAddress == 0 )
+ {
+ if ( status = NbtNewDhcpAddress( pDeviceContext, 0, 0 ) )
+ {
+ CDbgPrint( DBGFLAG_ERROR, ("DhcpNotification: NbtSetNewDhcpAddress failed")) ;
+ }
+ pDeviceContext->IpAddress = 0 ;
+ return ;
+ }
+
+ //
+ // Get all of the values that may change when the IP address changes.
+ // Currently this is only NBNS (scope & broadcast address are global
+ // NBT config parameters).
+ //
+
+ Size = sizeof( IpBuff ) ;
+ tdistatus = DhcpQueryOption( NewIpAddress,
+ 44, // NBNS
+ IpBuff,
+ &Size ) ;
+
+ if ( tdistatus != TDI_SUCCESS &&
+ tdistatus != TDI_BUFFER_OVERFLOW )
+ {
+ CDbgPrint( DBGFLAG_ERROR, ("DhcpNotification: Query on NBNS failed")) ;
+ }
+ else
+ {
+ if ( Size >= 4 )
+ pDeviceContext->lNameServerAddress = ntohl(IpBuff[0]) ;
+
+ if ( Size >= 8 )
+ pDeviceContext->lBackupServer = ntohl(IpBuff[1]) ;
+ }
+
+ //
+ // if the node type is set to Bnode by default then switch to Hnode if
+ // there are any WINS servers configured.
+ //
+ TmpNodeType = NodeType;
+
+ if ((NodeType & DEFAULT_NODE_TYPE) &&
+ (pDeviceContext->lNameServerAddress || pDeviceContext->lBackupServer))
+ {
+ NodeType = MSNODE;
+ if (TmpNodeType & PROXY)
+ NodeType |= PROXY;
+ }
+
+ //
+ // Now set the new IP address
+ //
+
+ status = NbtNewDhcpAddress( pDeviceContext,
+ NewIpAddress,
+ NewMask ) ;
+
+ if ( NT_SUCCESS(status) )
+ {
+ if (pDeviceContext->IpAddress)
+ {
+ //
+ // Add the "permanent" name to the local name table.
+ //
+ status = NbtAddPermanentName(pDeviceContext);
+
+ if (!(NodeType & BNODE))
+ {
+ // the Ip address just changed and Dhcp may be informing
+ // us of a new Wins Server addresses, so refresh all the
+ // names to the new wins server
+ //
+ ReRegisterLocalNames();
+ }
+ else
+ {
+ //
+ // no need to refresh on a Bnode
+ //
+ LockedStopTimer(&NbtConfig.pRefreshTimer);
+ }
+ }
+ }
+
+ else
+ {
+ CDbgPrint( DBGFLAG_ERROR, ("DhcpNotification: NbtSetNewDhcpAddress failed")) ;
+ }
+
+
+
+}
+
+
+/*******************************************************************
+
+ NAME: CloseAddressesWithTransport
+
+ SYNOPSIS: Closes address objects on the passed in device
+
+ ENTRY: pDeviceContext - Device context to close
+
+ NOTES: Used after an IP address loses its DHCP lease by OS
+ independent code.
+
+ HISTORY:
+ Johnl 13-Dec-1993 Created
+
+********************************************************************/
+
+NTSTATUS
+CloseAddressesWithTransport(
+ IN tDEVICECONTEXT *pDeviceContext )
+{
+ TDI_REQUEST Request ;
+ NTSTATUS status;
+
+
+ if (pDeviceContext->pDgramFileObject)
+ {
+ Request.Handle.AddressHandle = pDeviceContext->pDgramFileObject ;
+ if ( TdiVxdCloseAddress( &Request ))
+ CDbgPrint( DBGFLAG_ERROR, ("NbtSetInfo: Warning - CloseAddress Failed\r\n")) ;
+ pDeviceContext->pDgramFileObject = NULL;
+ }
+
+ if (pDeviceContext->pNameServerFileObject)
+ {
+ Request.Handle.AddressHandle = pDeviceContext->pNameServerFileObject ;
+ if ( TdiVxdCloseAddress( &Request ))
+ CDbgPrint( DBGFLAG_ERROR, ("NbtSetInfo: Warning - CloseAddress Failed\r\n")) ;
+ pDeviceContext->pNameServerFileObject = NULL;
+ }
+
+ if (pDeviceContext->pSessionFileObject)
+ {
+ Request.Handle.AddressHandle = pDeviceContext->pSessionFileObject ;
+ if ( TdiVxdCloseAddress( &Request ))
+ CDbgPrint( DBGFLAG_ERROR, ("NbtSetInfo: Warning - CloseAddress Failed\r\n")) ;
+ pDeviceContext->pSessionFileObject = NULL;
+ }
+
+ if (pDeviceContext->hBroadcastAddress)
+ {
+ Request.Handle.ConnectionContext = pDeviceContext->hBroadcastAddress ;
+ status = NbtCloseAddress( &Request, NULL, pDeviceContext, NULL );
+ if ( !NT_SUCCESS(status) )
+ {
+ CDbgPrint( DBGFLAG_ERROR, ("NbtSetInfo: Warning - Close Broadcast Address Failed\r\n")) ;
+ ASSERT(0);
+ }
+ }
+
+ return STATUS_SUCCESS ;
+}
+
+
diff --git a/private/ntos/nbt/vxd/ncb.c b/private/ntos/nbt/vxd/ncb.c
new file mode 100644
index 000000000..534a822e6
--- /dev/null
+++ b/private/ntos/nbt/vxd/ncb.c
@@ -0,0 +1,529 @@
+/**********************************************************************/
+/** Microsoft Windows/NT **/
+/** Copyright(c) Microsoft Corp., 1993 **/
+/**********************************************************************/
+
+/*
+ NCB.c
+
+ This file contains the NCB Handler that the VNetBios driver calls
+
+ FILE HISTORY:
+ Johnl 25-Mar-1993 Created
+
+*/
+
+#include <nbtprocs.h>
+#include <debug.h>
+
+#ifdef CHICAGO
+
+#include <shell.h>
+
+#include <netvxd.h>
+
+//
+// Do this so the VXDINLINE in the header file doesn't conflict
+// with the actual function declaration in this file.
+//
+#define VNBT_NCB_X VNBT_NCB_X_CALL
+#define VNBT_LANA_MASK VNBT_LANA_MASK_CALL
+#include <vnbt.h>
+#undef VNBT_LANA_MASK
+#undef VNBT_NCB_X
+
+#endif ;; CHICAGO
+
+LANA_ENTRY LanaTable[NBT_MAX_LANAS] ;
+
+/*******************************************************************
+
+ NAME: VNBT_NCB_X
+
+ SYNOPSIS: All NCBs submitted by the VNetBios driver come through
+ here
+
+ ENTRY: pNCB - Pointer to submitted NCB
+ Ipaddr - this parm is used only by nbtstat -A, which directly
+ calls into VNBT_NCB_X
+ ipaddress to which to send AdapterStatus to
+
+ RETURNS: NCB Return code
+
+ NOTES:
+
+ HISTORY:
+ Johnl 25-Mar-1993 Created
+
+********************************************************************/
+
+ULONG
+_stdcall
+VNBT_NCB_X( PNCB pNCB,
+ PUCHAR pzDnsName,
+ PULONG pIpAddress,
+ PVOID pExtended,
+ ULONG fFlag )
+{
+ BOOL fAsync ;
+ tDEVICECONTEXT * pDeviceContext = NULL ;
+ NTSTATUS status = STATUS_SUCCESS ;
+ uchar errNCB = NRC_GOODRET ;
+ PBLOCKING_NCB_CONTEXT pBlkNcbContext;
+ ULONG Ipaddr = pIpAddress ? pIpAddress[0] : 0;
+
+ if ( !pNCB )
+ return NRC_INVADDRESS ;
+
+ pDeviceContext = GetDeviceContext( pNCB ) ;
+ if ( pDeviceContext == NULL )
+ return NRC_BRIDGE ;
+
+ if (!pDeviceContext->fDeviceUp)
+ return NRC_BRIDGE ;
+
+ fAsync = !!(pNCB->ncb_command & ASYNCH) ;
+
+ if (
+ ( pzDnsName != NULL )
+ && ( pIpAddress != NULL )
+ )
+ {
+ if ( fAsync )
+ {
+ return DoDnsResolveDirect( pNCB, pzDnsName, pIpAddress );
+ }
+ else
+ {
+ return (pNCB->ncb_retcode = pNCB->ncb_cmd_cplt = NRC_ILLCMD);
+ }
+ }
+ else if (
+ ( pIpAddress != NULL )
+ && ( Ipaddr != 0 )
+ && ( ( pNCB->ncb_command & ~ASYNCH ) != NCBASTAT )
+ )
+ {
+ IpToAscii( Ipaddr, &pNCB->ncb_callname[0] );
+ }
+
+ if ( !fAsync )
+ {
+ pBlkNcbContext = CTEAllocMem( sizeof(BLOCKING_NCB_CONTEXT) );
+ if (!pBlkNcbContext)
+ {
+ DbgPrint("VNBT_NCB_X: couldn't alloc pBlkNcbContext 1") ;
+ return NRC_NORESOURCES;
+ }
+
+ pBlkNcbContext->Verify = NBT_VERIFY_BLOCKING_NCB;
+ InitializeListHead(&pBlkNcbContext->Linkage);
+ pBlkNcbContext->pNCB = pNCB;
+
+ pBlkNcbContext->pWaitNCBBlock = CTEAllocMem( sizeof(CTEBlockStruc) );
+ if (!pBlkNcbContext->pWaitNCBBlock)
+ {
+ CTEFreeMem(pBlkNcbContext);
+ DbgPrint("VNBT_NCB_X: couldn't alloc pBlkNcbContext 2") ;
+ return NRC_NORESOURCES;
+ }
+
+ pBlkNcbContext->fNCBCompleted = FALSE ;
+
+ //
+ // The completion routine uses this flag to know if the thread is
+ // blocked and needs to be signaled.
+ //
+ pBlkNcbContext->fBlocked = FALSE;
+
+ InsertTailList(&NbtConfig.BlockingNcbs,&pBlkNcbContext->Linkage);
+ }
+
+ DbgPrint("VNBT_NCB_X: NCB Commmand Rcvd: 0x") ;
+ DbgPrintNum( pNCB->ncb_command ) ; DbgPrint(", (") ;
+ DbgPrintNum( (ULONG) pNCB ) ; DbgPrint(")\r\n") ;
+
+ pNCB->ncb_retcode = NRC_PENDING ;
+ pNCB->ncb_cmd_cplt = NRC_PENDING ;
+
+ switch ( pNCB->ncb_command & ~ASYNCH )
+ {
+ case NCBDGSEND:
+ case NCBDGSENDBC:
+ status = VxdDgramSend( pDeviceContext, pNCB ) ;
+ errNCB = MapTDIStatus2NCBErr( status ) ;
+ break ;
+
+ case NCBDGRECV:
+ case NCBDGRECVBC:
+ errNCB = VxdDgramReceive( pDeviceContext, pNCB ) ;
+ break ;
+
+ case NCBRECVANY:
+ errNCB = VxdReceiveAny( pDeviceContext, pNCB ) ;
+ break ;
+
+ case NCBCALL:
+ errNCB = VxdCall( pDeviceContext, pNCB ) ;
+ break ;
+
+ case NCBHANGUP:
+ errNCB = VxdHangup( pDeviceContext, pNCB ) ;
+ break ;
+
+ case NCBLISTEN:
+ errNCB = VxdListen( pDeviceContext, pNCB ) ;
+ break ;
+
+ case NCBRECV:
+ errNCB = VxdReceive( pDeviceContext, pNCB, TRUE ) ;
+ break ;
+
+ case NCBSEND:
+ case NCBSENDNA:
+ case NCBCHAINSEND:
+ case NCBCHAINSENDNA:
+ errNCB = VxdSend( pDeviceContext, pNCB ) ;
+ break ;
+
+#if 0
+ case NCBTRANSV:
+ errNCB = VxdTransceive( pDeviceContext, pNCB ) ;
+ break ;
+#endif
+
+ case NCBADDGRNAME:
+ case NCBADDNAME:
+ errNCB = VxdOpenName( pDeviceContext, pNCB ) ;
+ break ;
+
+ case NCBDELNAME:
+ errNCB = VxdCloseName( pDeviceContext, pNCB ) ;
+ break ;
+
+ case NCBASTAT:
+ errNCB = VxdAdapterStatus( pDeviceContext, pNCB, Ipaddr ) ;
+ break ;
+
+ case NCBSSTAT:
+ errNCB = VxdSessionStatus( pDeviceContext, pNCB ) ;
+ break ;
+
+ case NCBFINDNAME:
+ errNCB = VxdFindName( pDeviceContext, pNCB ) ;
+ break ;
+
+ case NCBRESET:
+ errNCB = VxdReset( pDeviceContext, pNCB ) ;
+ break ;
+
+ case NCBCANCEL:
+ if ( DoDnsCancelDirect( pNCB ) )
+ {
+ errNCB = NRC_GOODRET;
+ }
+ else
+ {
+ errNCB = VxdCancel( pDeviceContext, pNCB ) ;
+ }
+ break ;
+
+ //
+ // The following are no-ops that return success for compatibility
+ //
+ case NCBUNLINK:
+ case NCBTRACE:
+ CTEIoComplete( pNCB, STATUS_SUCCESS, 0 ) ;
+ break ;
+
+ default:
+ DbgPrint("VNBT_NCB_X - Unsupported command: ") ;
+ DbgPrintNum( pNCB->ncb_command & ~ASYNCH ) ;
+ DbgPrint("\n\r") ;
+ errNCB = NRC_ILLCMD ; // Bogus error for now
+ break ;
+ }
+
+Exit:
+ //
+ // If we aren't pending then set the codes
+ //
+ if ( errNCB != NRC_PENDING &&
+ errNCB != NRC_GOODRET )
+ {
+#ifdef DEBUG
+ DbgPrint("VNBT_NCB_X - Returning ") ;
+ DbgPrintNum( errNCB ) ;
+ DbgPrint(" to NCB submitter\n\r") ;
+#endif
+ pNCB->ncb_retcode = errNCB ;
+ pNCB->ncb_cmd_cplt = errNCB ;
+
+ //
+ // Errored NCBs don't have the completion routine called, so we
+ // in essence, complete it here. Note this will only set the
+ // state for the last Wait NCB (all others get NRC_IFBUSY).
+ //
+ if ( !fAsync )
+ {
+ ASSERT(pBlkNcbContext->Verify == NBT_VERIFY_BLOCKING_NCB);
+ pBlkNcbContext->fNCBCompleted = TRUE ;
+ }
+ }
+ else
+ {
+ //
+ // Some components (AKA server) don't like returning pending
+ //
+ errNCB = NRC_GOODRET ;
+
+ }
+
+ //
+ // Block until NCB completion if this wasn't an async NCB
+ //
+ if ( !fAsync )
+ {
+ ASSERT(pBlkNcbContext->Verify == NBT_VERIFY_BLOCKING_NCB);
+ if ( !pBlkNcbContext->fNCBCompleted )
+ {
+ pBlkNcbContext->fBlocked = TRUE;
+ CTEInitBlockStruc( pBlkNcbContext->pWaitNCBBlock ) ;
+ CTEBlock( pBlkNcbContext->pWaitNCBBlock ) ;
+ }
+ else
+ {
+ RemoveEntryList(&pBlkNcbContext->Linkage);
+ CTEFreeMem(pBlkNcbContext->pWaitNCBBlock);
+ CTEFreeMem(pBlkNcbContext);
+ }
+ }
+
+ return errNCB ;
+}
+
+/*******************************************************************
+
+ NAME: GetDeviceContext
+
+ SYNOPSIS: Retrieves the device context associated with the lana
+ specified in the NCB
+
+ ENTRY: pNCB - NCB to get the device context for
+
+ RETURNS: Device context or NULL if not found
+
+ NOTES: It is assumed that LanaTable is filled sequentially
+ with no holes.
+
+ HISTORY:
+ Johnl 30-Aug-1993 Created
+
+********************************************************************/
+
+tDEVICECONTEXT * GetDeviceContext( NCB * pNCB )
+{
+ int i ;
+
+ if ( !pNCB )
+ return NULL ;
+
+ for ( i = 0; i < NBT_MAX_LANAS; i++)
+ {
+ if ( LanaTable[i].pDeviceContext->iLana == pNCB->ncb_lana_num)
+ return LanaTable[i].pDeviceContext;
+ }
+
+ return NULL;
+}
+
+/*******************************************************************
+
+ NAME: NbtWouldLoopback
+
+ SYNOPSIS: Returns a BOOL that specifies whether the input
+ IP address would loop back to the local machine
+
+ ENTRY: IpAddr
+
+ RETURNS: TRUE if Nbt is bound to this address
+
+ NOTES: It is assumed that LanaTable is filled sequentially
+ with no holes.
+
+ HISTORY:
+ EarleH 28-Mar-1996 Created
+
+********************************************************************/
+
+BOOL
+NbtWouldLoopback(
+ ULONG IpAddr
+)
+{
+ int i ;
+
+ for ( i = 0; i < NBT_MAX_LANAS; i++)
+ {
+ if (
+ ( LanaTable[i].pDeviceContext )
+ && ( LanaTable[i].pDeviceContext->IpAddress == IpAddr )
+ )
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*******************************************************************
+
+ NAME: VNBT_LANA_MASK
+
+ SYNOPSIS: Returns a bit mask of LANA numbers being handled
+ by vnbt, with a DNS server configured
+
+ ENTRY: none
+
+ RETURNS: Bit mask of LANA numbers being handled by vnbt
+
+ NOTES:
+
+ HISTORY:
+ EarleH 26-Feb-1996 Created
+
+********************************************************************/
+
+ULONG
+_stdcall
+VNBT_LANA_MASK(
+ )
+{
+ int i;
+ ULONG mask = 0;
+
+ for ( i = 0 ; i < NBT_MAX_LANAS; i++)
+ {
+ if (
+ ( LanaTable[i].pDeviceContext )
+ && ( LanaTable[i].pDeviceContext->fDeviceUp )
+ && ( LanaTable[i].pDeviceContext->lDnsServerAddress )
+ && ( LanaTable[i].pDeviceContext->lDnsServerAddress != LOOP_BACK )
+ )
+ {
+ mask |= 1 << LanaTable[i].pDeviceContext->iLana;
+ }
+ }
+
+ return mask;
+}
+
+/*******************************************************************
+
+ NAME: MapTDIStatus2NCBErr
+
+ SYNOPSIS: Maps a TDI_STATUS error value to an Netbios NCR error value
+
+ ENTRY: tdistatus - TDI Status to map
+
+ RETURNS: The mapped error
+
+ NOTES:
+
+ HISTORY:
+ Johnl 15-Apr-1993 Created
+
+********************************************************************/
+
+uchar MapTDIStatus2NCBErr( TDI_STATUS tdistatus )
+{
+ uchar errNCB ;
+ if ( tdistatus == TDI_SUCCESS )
+ return NRC_GOODRET ;
+ else if ( tdistatus == TDI_PENDING )
+ return NRC_PENDING ;
+
+
+ switch ( tdistatus )
+ {
+ case TDI_NO_RESOURCES:
+ errNCB = NRC_NORES ;
+ break ;
+
+ case STATUS_CANCELLED:
+ errNCB = NRC_CMDCAN ;
+ break ;
+
+ case TDI_INVALID_CONNECTION:
+ case STATUS_CONNECTION_DISCONNECTED:
+ errNCB = NRC_SCLOSED ;
+ break ;
+
+ case TDI_CONNECTION_ABORTED:
+ errNCB = NRC_SABORT ;
+ break ;
+
+ case STATUS_TOO_MANY_COMMANDS:
+ errNCB = NRC_TOOMANY ;
+ break ;
+
+ case STATUS_OBJECT_NAME_COLLISION:
+ case STATUS_SHARING_VIOLATION:
+ errNCB = NRC_DUPNAME ;
+ break ;
+
+ case STATUS_DUPLICATE_NAME:
+ errNCB = NRC_INUSE ;
+ break ;
+
+ //
+ // Call NCB submitted with a name that can't be found
+ //
+ case STATUS_BAD_NETWORK_PATH:
+ errNCB = NRC_NOCALL ;
+ break ;
+
+ case STATUS_REMOTE_NOT_LISTENING:
+ errNCB = NRC_REMTFUL ;
+ break ;
+
+ case TDI_TIMED_OUT:
+ errNCB = NRC_CMDTMO ;
+ break ;
+
+ //
+ // Where the transport has more data available but the NCB's buffer is
+ // full
+ //
+ case TDI_BUFFER_OVERFLOW:
+ errNCB = NRC_INCOMP ;
+ break ;
+
+ case STATUS_INVALID_BUFFER_SIZE:
+ errNCB = NRC_BUFLEN ;
+ break ;
+
+ case STATUS_NETWORK_NAME_DELETED:
+ errNCB = NRC_NAMERR ;
+ break ;
+
+ case STATUS_NRC_ACTSES:
+ errNCB = NRC_ACTSES ;
+ break ;
+
+ default:
+ DbgPrint("MapTDIStatus2NCBErr - Unmapped STATUS/TDI error - " ) ;
+ DbgPrintNum( tdistatus ) ;
+ DbgPrint("\n\r") ;
+
+ case STATUS_UNSUCCESSFUL:
+ case TDI_INVALID_STATE:
+ case STATUS_INVALID_PARAMETER: // Generally detected bad struct. signature
+ case STATUS_UNEXPECTED_NETWORK_ERROR:
+ errNCB = NRC_SYSTEM ;
+ break ;
+ }
+
+ return errNCB ;
+}
+
+
diff --git a/private/ntos/nbt/vxd/newdns.c b/private/ntos/nbt/vxd/newdns.c
new file mode 100644
index 000000000..9bcf78d4b
--- /dev/null
+++ b/private/ntos/nbt/vxd/newdns.c
@@ -0,0 +1,1019 @@
+/*++
+
+Copyright (c) 1989-1996 Microsoft Corporation
+
+Module Name:
+
+ DNS.c
+
+Abstract:
+
+ VxD-specific DNS routines.
+
+ This stuff will all be obsolete when we get proper services for
+ Windows. Then we will just call Winsock for DNS name resolution.
+
+Author:
+
+ Earle R. Horton (ERH) 13-Feb-1996
+
+Revision History:
+
+--*/
+
+#include "nbtprocs.h"
+
+//----------------------------------------------------------------------------
+ ULONG
+DoDnsResolveDirect(
+ PNCB pncb,
+ PUCHAR pzDnsName,
+ PULONG pIpAddress
+)
+{
+ PDNS_DIRECT_WORK_ITEM_CONTEXT pContext;
+ PUCHAR pch;
+ tDEVICECONTEXT *pDeviceContext;
+ ULONG status;
+ CTELockHandle OldIrq;
+
+ pDeviceContext = GetDeviceContext( pncb ) ;
+
+ if ( pDeviceContext == NULL )
+ {
+ return NRC_BRIDGE ;
+ }
+
+ //
+ // If the primary DNS server is not defined, just return error.
+ // Return command timed out here.
+ //
+ if ( (!pDeviceContext->lDnsServerAddress) ||
+ ( pDeviceContext->lDnsServerAddress == LOOP_BACK) )
+ {
+ return( NRC_NOCALL );
+ }
+
+ pContext = CTEAllocMem( sizeof(DNS_DIRECT_WORK_ITEM_CONTEXT) );
+
+ if ( pContext == NULL )
+ {
+ return NRC_NORESOURCES;
+ }
+
+ CTEZeroMemory( pContext, sizeof(DNS_DIRECT_WORK_ITEM_CONTEXT) );
+
+ pContext->pDeviceContext = pDeviceContext;
+ pContext->pNCB = pncb;
+ pContext->pzDnsName = pzDnsName;
+ pContext->pIpAddress = pIpAddress;
+
+ pContext->TransactId = htons(GetTransactId() + DIRECT_DNS_NAME_QUERY_BASE );
+ pContext->pchDomainName = NbtConfig.pDomainName;
+ pContext->Flags = DNS_DIRECT_DNS_SERVER;
+
+ for ( pch = &pzDnsName[0] ; *pch++ != '\0' ; )
+ {
+ if ( pch[0] == '.' )
+ {
+ pContext->Flags |= DNS_DIRECT_NAME_HAS_DOTS;
+ pContext->pchDomainName = NULL;
+ }
+ }
+
+ //
+ // Put on the pending name queries list again so that when the query
+ // response comes in from DNS we can find the context.
+ //
+ CTESpinLock(&NbtConfig.JointLock,OldIrq);
+
+ InsertTailList(&NbtConfig.DNSDirectNameQueries,
+ &pContext->Linkage
+ );
+
+ CTESpinFree(&NbtConfig.JointLock,OldIrq);
+
+ status = UdpSendDNSBcastDirect( pContext,
+ (ULONG)pNbtGlobConfig->uRetryTimeout,
+ (ULONG)pNbtGlobConfig->uNumRetries
+ );
+
+ pncb->ncb_retcode = pncb->ncb_cmd_cplt = status ;
+
+ if ( status != NRC_PENDING )
+ {
+ pncb->ncb_retcode = pncb->ncb_cmd_cplt = status ;
+
+ DnsUnlinkAndCompleteDirect( pContext );
+ }
+ else
+ {
+ status = NRC_GOODRET;
+ }
+
+ return status;
+}
+
+//----------------------------------------------------------------------------
+ NTSTATUS
+UdpSendDNSBcastDirect(
+ IN PDNS_DIRECT_WORK_ITEM_CONTEXT pContext,
+ IN ULONG Timeout,
+ IN ULONG Retries
+)
+/*++
+
+Routine Description:
+
+ This routine sends a name query directed to the name server.
+
+Arguments:
+
+
+Return Value:
+
+ NTSTATUS - success or not
+
+History:
+
+ Adapted from UdpSendNSBcast() in "udpsend.c."
+
+ Earle R. Horton (earleh) March 18, 1996
+
+--*/
+{
+ NTSTATUS status;
+ tNAMEHDR *pNameHdr;
+ ULONG uLength;
+ ULONG uSentSize;
+ CTELockHandle OldIrq;
+ ULONG IpAddress;
+ tTIMERQENTRY *pTimerQEntry;
+ TDI_REQUEST TdiRequest;
+ PDNS_DIRECT_SEND_CONTEXT pSendContext;
+
+ pSendContext = CreateSendContextDirect(
+ pContext->pzDnsName,
+ pContext->pchDomainName,
+ (PVOID)&pNameHdr,
+ &uLength,
+ pContext);
+
+ if (pSendContext == NULL)
+ {
+ IF_DBG(NBT_DEBUG_NAMESRV)
+ KdPrint(("Nbt:Failed to Create Pdu to send to DNS.\n"));
+ return( NRC_NORES );
+ }
+
+ CTESpinLock(&NbtConfig.JointLock,OldIrq);
+
+ TdiRequest.Handle.AddressHandle = (PVOID)pContext->pDeviceContext->pNameServerFileObject;
+
+ // the completion routine is setup to free the pDgramTracker memory block
+ TdiRequest.RequestNotifyObject = SendDNSBcastDoneDirect;
+ TdiRequest.RequestContext = (PVOID)pSendContext;
+
+ // start the timer now...We didn't start it before because it could
+ // have expired during the dgram setup, perhaps before the Context was
+ // fully setup.
+ //
+ if (Timeout)
+ {
+ status = StartTimer(
+ Timeout,
+ pContext,
+ NULL,
+ DnsCompletionDirect,
+ NULL,
+ NULL,
+ (USHORT)Retries,
+ &pTimerQEntry
+ );
+
+ if (!NT_SUCCESS(status))
+ {
+ // we need to differentiate the timer failing versus lack
+ // of resources
+ CTESpinFree(&NbtConfig.JointLock,OldIrq);
+ CTEMemFree(pSendContext);
+
+ return( NRC_NORES );
+ }
+ //
+ // Cross link the nameaddr and the timer so we can stop the timer
+ // when the name query response occurs
+ //
+ pTimerQEntry->pCacheEntry = pContext;
+ pContext->pTimer = pTimerQEntry;
+ }
+
+ //
+ // in the event that DHCP has just removed the IP address, just cancel
+ // the request
+ //
+ if (pContext->pDeviceContext->IpAddress == 0)
+ {
+ StopTimer ( pContext->pTimer, NULL, NULL );
+ pContext->Flags |= DNS_DIRECT_CANCELLED;
+ }
+
+ CTESpinFree(&NbtConfig.JointLock,OldIrq);
+
+ (VOID) TdiSendDatagram(
+ &TdiRequest,
+ &pSendContext->SendInfo,
+ uLength,
+ &uSentSize,
+ &pSendContext->SendBuffer,
+ NBT_NAME_SERVICE
+ );
+
+ return( NRC_PENDING );
+}
+
+//----------------------------------------------------------------------------
+ VOID
+SendDNSBcastDoneDirect(
+ IN PVOID pSendContext,
+ IN NTSTATUS status,
+ IN ULONG lInfo
+)
+{
+ CTEMemFree(pSendContext);
+}
+
+//----------------------------------------------------------------------------
+ BOOL
+DoDnsCancelDirect(
+ PNCB pncb
+)
+{
+ PLIST_ENTRY pHead;
+ PLIST_ENTRY pEntry;
+ PDNS_DIRECT_WORK_ITEM_CONTEXT
+ pContext;
+ CTELockHandle OldIrq;
+ BOOL RetVal = FALSE;
+
+ pHead = pEntry = &NbtConfig.DNSDirectNameQueries;
+
+ CTESpinLock(&NbtConfig.JointLock,OldIrq);
+
+ while ((pEntry = pEntry->Flink) != pHead)
+ {
+ pContext = CONTAINING_RECORD(pEntry,DNS_DIRECT_WORK_ITEM_CONTEXT,Linkage);
+ if ( pContext->pNCB == pncb )
+ {
+ StopTimer ( pContext->pTimer, NULL, NULL );
+ pContext->Flags |= DNS_DIRECT_CANCELLED;
+ RetVal = TRUE;
+ break;
+ }
+ }
+
+ CTESpinFree(&NbtConfig.JointLock,OldIrq);
+
+ return RetVal;
+}
+
+//----------------------------------------------------------------------------
+/*++
+
+Routine Description:
+
+ This routine is called by the timer code when the timer expires. It must
+ decide if another name query should be sent to the DNS server, and if not,
+ then it completes the request.
+
+Arguments:
+
+
+Notes:
+--*/
+ VOID
+DnsCompletionDirect(
+ PVOID pvContext,
+ PVOID pvContext2,
+ tTIMERQENTRY *pTimerQEntry
+)
+{
+ PDNS_DIRECT_WORK_ITEM_CONTEXT pContext;
+ tDEVICECONTEXT *pDeviceContext;
+
+ NTSTATUS status;
+ CTELockHandle OldIrq;
+ PCHAR pchDomainName;
+ USHORT Flags;
+ BOOL fOneMoreTry;
+
+ KdPrint(("DnsCompletion entered\r\n"));
+
+ pContext = (PDNS_DIRECT_WORK_ITEM_CONTEXT)pvContext;
+
+
+ // if the client completion routine is not set anymore, then the
+ // timer has been cancelled or completed and this routine should
+ // just clean up its buffers associated with the tracker (and return)
+ //
+ if (!pTimerQEntry)
+ {
+ // complete the request
+ LOCATION(0x52);
+ DnsUnlinkAndCompleteDirect( pContext );
+ return;
+ }
+
+
+ //
+ // to prevent a client from stopping the timer and deleting the
+ // pContext, grab the lock and check if the timer has been stopped
+ //
+ CTESpinLock(&NbtConfig.JointLock,OldIrq);
+
+ pDeviceContext = pContext->pDeviceContext;
+
+ if (pTimerQEntry->Flags & TIMER_RETIMED)
+ {
+ //
+ // Got a wait ACK from the server.
+ //
+ pTimerQEntry->Flags &= ~TIMER_RETIMED;
+ pTimerQEntry->Flags |= TIMER_RESTART;
+ //
+ // if we are not bound to this card than use a very short timeout
+ //
+ if (
+ (!pDeviceContext->pNameServerFileObject)
+ || (pContext->Flags & DNS_DIRECT_CANCELLED)
+ )
+ {
+ pTimerQEntry->DeltaTime = 10;
+ }
+
+ CTESpinFree(&NbtConfig.JointLock,OldIrq);
+ return;
+ }
+
+ // If done with all the (3) retries with primary, try secondary DNS srvr
+ // If secondary not defined, or done with secondary as well, stop.
+ //
+
+ fOneMoreTry = TRUE;
+
+ if (!(--pTimerQEntry->Retries))
+ {
+ //
+ // if backup server is not defined, or if it is defined but we just
+ // finished trying backup server, go back and try primary server for
+ // "other domains"
+ // e.g. DNSDomains was defined as "msft.dom2.com,msft.dom3.com,msft.dom"
+ // We were pointing at msft.dom2.com. Now, we are done with that (and
+ // didn't get a response), so try msft.dom3.com
+ //
+ if ( ( !pDeviceContext->lDnsBackupServer ) ||
+ ( pDeviceContext->lDnsBackupServer == LOOP_BACK ) ||
+ ( pContext->Flags & DNS_DIRECT_DNS_BACKUP) )
+ {
+ //
+ // if we just got done trying primary domain name, try all the
+ // "other domains" specified
+ //
+ if (pContext->pchDomainName == NbtConfig.pDomainName)
+ {
+ pContext->pchDomainName = NbtConfig.pDNSDomains;
+ if ( pContext->pchDomainName )
+ {
+ pContext->Flags &= ~DNS_DIRECT_DNS_BACKUP;
+ pContext->Flags |= DNS_DIRECT_DNS_SERVER;
+ pTimerQEntry->Retries = NbtConfig.uNumRetries;
+ }
+ else
+ {
+ fOneMoreTry = FALSE;
+ }
+ }
+
+ //
+ // if we had already started on "other domains", advance to the
+ // next domain within "other domains"
+ //
+ else if ( pContext->pchDomainName )
+ {
+ pchDomainName = pContext->pchDomainName;
+ while( *pchDomainName != ',' && // dom names separated by comma
+ *pchDomainName != ' ' && // or space
+ *pchDomainName != '\0' )
+ {
+ pchDomainName++;
+ }
+
+ if ( *pchDomainName == '\0' )
+ fOneMoreTry = FALSE;
+ else
+ {
+ pchDomainName++;
+ pContext->pchDomainName = pchDomainName;
+ pContext->Flags &= ~DNS_DIRECT_DNS_BACKUP;
+ pContext->Flags |= DNS_DIRECT_DNS_SERVER;
+ pTimerQEntry->Retries = NbtConfig.uNumRetries;
+ }
+ }
+ else
+ {
+ fOneMoreTry = FALSE;
+ }
+ }
+
+ // ok, prepare to try the backup server
+ else
+ {
+ pTimerQEntry->Retries = NbtConfig.uNumRetries;
+
+ pContext->Flags &= ~DNS_DIRECT_DNS_SERVER;
+ pContext->Flags |= DNS_DIRECT_DNS_BACKUP;
+ }
+ }
+
+ // we aren't done yet: send one more query and restart the timer
+ if (fOneMoreTry)
+ {
+ CTESpinFree(&NbtConfig.JointLock,OldIrq);
+
+ status = UdpSendDNSBcastDirect( pContext, 0, 0 );
+
+ pTimerQEntry->Flags |= TIMER_RESTART;
+
+ KdPrint(("One more DNS query sent out\r\n"));
+ }
+
+ // yup, all done: didn't find the name!
+ else
+ {
+ pTimerQEntry->Flags |= TIMER_RESTART;
+ StopTimer(pTimerQEntry,NULL,NULL);
+ CTESpinFree(&NbtConfig.JointLock,OldIrq);
+ }
+}
+
+//----------------------------------------------------------------------------
+/*++
+
+Routine Description:
+
+ This routine "actually" completes the request, either by completing the
+ asociated NCB with some kind of failure, or passing it off to the
+ main NCB processing code.
+
+Arguments:
+
+
+Notes:
+--*/
+ VOID
+DnsActualCompletionDirect(
+ IN NBT_WORK_ITEM_CONTEXT * pnbtContext
+)
+{
+ PDNS_DIRECT_WORK_ITEM_CONTEXT pContext = pnbtContext->pClientContext;
+ uchar errNCB = NRC_GOODRET ;
+ NCB * pNCB = pContext->pNCB;
+
+ if ( pNCB->ncb_cmd_cplt == NRC_PENDING )
+ {
+ //
+ // Failed to resolve the name, or request was cancelled.
+ //
+ if ( pContext->pIpAddress[0] == 0 )
+ {
+ errNCB = NRC_CMDTMO;
+ }
+ else if ( pContext->Flags & DNS_DIRECT_CANCELLED )
+ {
+ errNCB = NRC_CMDCAN;
+ }
+ else
+ {
+ errNCB = VNBT_NCB_X ( pContext->pNCB, NULL, pContext->pIpAddress, NULL, 0 );
+ }
+ if ( errNCB != NRC_GOODRET )
+ {
+ pNCB->ncb_retcode = pNCB->ncb_cmd_cplt = errNCB ;
+ //
+ // call the post-routine only if the post-routine has been specified!
+ //
+ if ( pNCB->ncb_post )
+ {
+ typedef void (CALLBACK * VXDNCBPost )( void ) ;
+ VXDNCBPost ncbpost = (VXDNCBPost) pNCB->ncb_post ;
+
+ //
+ // Clients are expecting EBX to point to the NCB (instead of
+ // pushing it on the stack...). The post routine may trash
+ // ebp also, so save it.
+ //
+ _asm pushad ;
+ _asm mov ebx, pNCB ;
+ ncbpost() ;
+ _asm popad ;
+ }
+ }
+ }
+
+ CTEMemFree(pContext);
+ CTEMemFree(pnbtContext);
+}
+
+//----------------------------------------------------------------------------
+ VOID
+DnsUnlinkAndCompleteDirect(
+ IN PDNS_DIRECT_WORK_ITEM_CONTEXT pContext
+)
+/*++
+
+Routine Description:
+
+ This routine unlinks and completes the request.
+
+Arguments:
+
+
+Notes:
+--*/
+{
+ RemoveEntryList(&pContext->Linkage);
+
+ VxdScheduleDelayedCall ( NULL,
+ pContext,
+ NULL,
+ DnsActualCompletionDirect,
+ pContext->pDeviceContext
+ );
+}
+
+//----------------------------------------------------------------------------
+ VOID
+ProcessDnsResponseDirect(
+ IN tDEVICECONTEXT *pDeviceContext,
+ IN PVOID pSrcAddress,
+ IN tNAMEHDR UNALIGNED *pNameHdr,
+ IN LONG lNumBytes,
+ IN USHORT OpCodeFlags
+ )
+/*++
+
+Routine Description:
+
+ This function sets the state of the name being resolved appropriately
+ depending on whether DNS sends a positive or a negative response to our
+ query; calls the client completion routine and stops any more DNS queries
+ from going.
+
+Arguments:
+
+
+Return Value:
+
+ NTSTATUS - STATUS_SUCCESS or STATUS_UNSUCCESSFUL
+
+--*/
+{
+ NTSTATUS status;
+ tDNS_QUERYRESP UNALIGNED *pQuery;
+ PLIST_ENTRY pHead;
+ PLIST_ENTRY pEntry;
+ PDNS_DIRECT_WORK_ITEM_CONTEXT
+ pContext;
+ COMPLETIONCLIENT pClientCompletion;
+ PVOID Context;
+ PTRANSPORT_ADDRESS pSourceAddress;
+ ULONG SrcAddress;
+ ULONG IpAddress;
+ tTIMERQENTRY *pTimer = NULL;
+ CTELockHandle OldIrq1;
+ LONG lNameSize;
+ LONG lTraversedSoFar=0;
+ CHAR pJunkBuf[NETBIOS_NAME_SIZE];
+ PUCHAR pchQry;
+
+ // make sure this is a response
+
+ if ( !(OpCodeFlags & OP_RESPONSE) )
+ {
+ CDbgPrint(DBGFLAG_ERROR,("ProcessDnsResponseDirect: Bad OpCodeFlags\r\n"));
+
+ return;
+ }
+
+ pSourceAddress = (PTRANSPORT_ADDRESS)pSrcAddress;
+ SrcAddress = ntohl(((PTDI_ADDRESS_IP)&pSourceAddress->Address[0].Address[0])->in_addr);
+
+ CTESpinLock(&NbtConfig.JointLock,OldIrq1);
+
+ if ( ( pContext = FindContextDirect( pNameHdr->TransactId ) ) != NULL )
+
+ {
+ pContext->Flags |= DNS_DIRECT_ANSWERED;
+ if ( pTimer = pContext->pTimer )
+ {
+ //
+ // If the response we received doesn't resolve the name, we silently return,
+ // but make sure reties is set to 1 so that when timer fires again, we don't
+ // send another name query to the same server but instead timeout the
+ // attempt on this server
+ //
+ pTimer->Retries = 1;
+ }
+ //
+ // check the pdu size for errors
+ //
+ if (lNumBytes < DNS_MINIMUM_QUERYRESPONSE)
+ {
+ CDbgPrint(DBGFLAG_ERROR,("ProcessDnsResponseDirect: Bad lNumBytes\r\n"));
+ goto done;
+ }
+
+//
+// BUGBUG: should we require authoritative responses from DNS servers?
+//
+
+ //
+ // if it's a negative response, quit now!
+ //
+ if (IS_NEG_RESPONSE(OpCodeFlags))
+ {
+ goto done;
+ }
+
+ //
+ // if there is no answer section, return!
+ //
+ if ( !pNameHdr->AnCount )
+ {
+ CDbgPrint(DBGFLAG_ERROR,("ProcessDnsResponseDirect: No answer section\r\n"));
+ goto done;
+ }
+
+ //
+ // lNameSize is the length of the entire name, excluding the length byte
+ // for the first label (including length bytes of subsequent labels) and
+ // including the trailing 0 (tNAMEHDR struc takes care for 1st byte)
+ //
+ DnsExtractName( (PCHAR)&pNameHdr->NameRR.NameLength,
+ lNumBytes,
+ pJunkBuf,
+ &lNameSize
+ );
+ pchQry = (PUCHAR)&pNameHdr->NameRR.NetBiosName[lNameSize];
+
+ lTraversedSoFar += lNameSize;
+
+ //
+ // if the Question section is returned with the response then we have
+ // a little more work to do! In this case, pQuery is pointing at the
+ // beginning of the QTYPE field (end of the QNAME)
+ //
+ if ( pNameHdr->QdCount )
+ {
+ pchQry += sizeof(tQUESTIONMODS);
+ lTraversedSoFar += sizeof(tQUESTIONMODS);
+
+ // most common case: 1st byte will be 0xC0, which means next byte points
+ // to the actual name. We don't care about the name, so we skip over
+ // both the bytes
+ //
+ if ( (*pchQry) == PTR_TO_NAME )
+ {
+ pchQry += sizeof(tDNS_LABEL);
+ lTraversedSoFar += sizeof(tDNS_LABEL);
+ }
+
+ //
+ // if some implementation doesn't optimize and copies the whole name
+ // again, skip over the length of the name
+ //
+ else
+ {
+ pchQry += (lNameSize+1); // +1 because of the 1st length byte!
+ lTraversedSoFar += (lNameSize+1);
+ }
+ }
+
+ pQuery = (tDNS_QUERYRESP *)pchQry;
+
+ //
+ // if this rr is telling us about canonical name, skip over it and go to
+ // where the ipaddr is
+ //
+ if (ntohs(pQuery->RrType) == DNS_CNAME)
+ {
+ //
+ // since this is CNAME, there is no ipaddr. Instead, the data is the
+ // canonical name whose length we are adding, and subtract ipaddr's len
+ //
+ pchQry += (sizeof(tDNS_QUERYRESP) - sizeof(ULONG));
+ pchQry += ntohs(pQuery->Length);
+ lTraversedSoFar += ntohs(pQuery->Length) + sizeof(tDNS_QUERYRESP) - sizeof(ULONG);
+
+ ASSERT(lNumBytes > lTraversedSoFar);
+
+ // most common case: 1st byte will be 0xC0, which means next byte points
+ // to the actual name. We don't care about the name, so we skip over
+ // both the bytes
+ //
+ if ( (*pchQry) == PTR_TO_NAME )
+ {
+ pchQry += sizeof(tDNS_LABEL);
+ lTraversedSoFar += sizeof(tDNS_LABEL);
+ }
+
+ //
+ // if some implementation doesn't optimize and copies the whole name
+ // again, skip over the length of the name
+ //
+ else
+ {
+ // we have already taken the name out. we are calling this routine
+ // just to see how big the canonical name is (i.e.lNameSize), to skip
+ // past it
+ //
+ DnsExtractName( pchQry,
+ lNumBytes-lTraversedSoFar,
+ pJunkBuf,
+ &lNameSize
+ );
+
+ //
+ // lNameSize is the length of the entire name, excluding the length byte
+ // for the first label (including length bytes of subsequent labels) and
+ // including the trailing 0 (tNAMEHDR struc takes care for 1st byte)
+ //
+ pchQry += lNameSize+1; // +1 for the length byte of first label
+
+ }
+
+ pQuery = (tDNS_QUERYRESP *)pchQry;
+ }
+
+ // if we came this far, it's a positive response. do the needful.
+
+ IpAddress = ntohl(pQuery->IpAddress);
+
+ if ( !NbtWouldLoopback( IpAddress ) )
+ {
+ pContext->pIpAddress[0] = IpAddress;
+ }
+ else
+ {
+ pContext->Flags |= DNS_DIRECT_CANCELLED;
+ }
+
+ //
+ // Set the backup name server to be the main name server
+ // if we got a response from it.
+ //
+ if ( SrcAddress == pContext->pDeviceContext->lDnsBackupServer )
+ {
+ pContext->pDeviceContext->lDnsBackupServer =
+ pContext->pDeviceContext->lDnsServerAddress;
+
+ pContext->pDeviceContext->lDnsServerAddress = SrcAddress;
+ }
+
+ StopTimer(pTimer,NULL,NULL);
+ }
+
+done:
+
+ CTESpinFree(&NbtConfig.JointLock,OldIrq1);
+ return;
+}
+
+//----------------------------------------------------------------------------
+ PDNS_DIRECT_SEND_CONTEXT
+CreateSendContextDirect(
+ IN PCHAR pName,
+ IN PCHAR pchDomainName,
+ OUT PVOID *pHdrs,
+ OUT PULONG pLength,
+ IN PDNS_DIRECT_WORK_ITEM_CONTEXT pContext
+ )
+/*++
+
+Routine Description:
+
+ This routine builds a name query pdu
+
+Arguments:
+
+
+Return Value:
+
+ PDNS_DIRECT_SEND_CONTEXT - a pointer to a data structure used for the datagram
+ send that must be freed by the datagram send completion routine
+
+--*/
+{
+ tNAMEHDR *pNameHdr;
+ ULONG uLength;
+ ULONG uDomainNameSize;
+ tGENERALRR *pGeneral;
+ CTELockHandle OldIrq;
+ PDNS_DIRECT_SEND_CONTEXT
+ pSendContext;
+
+ uDomainNameSize = domnamelen(pchDomainName) + 1; // +1 for len byte
+ if (uDomainNameSize > 1)
+ {
+ uDomainNameSize++; // for the null byte
+ }
+
+ // size is size of the namehdr structure -1 for the NetbiosName[1]
+ // + the 32 bytes for the half ascii name +
+ // scope + size of the General RR structure
+ uLength = sizeof(DNS_DIRECT_SEND_CONTEXT) - 1
+ + uDomainNameSize
+ + sizeof(ULONG)
+ + strlen(pName)
+ + 1;
+
+ // Note that this memory must be deallocated when the send completes in
+ // SendDNSBcastDoneDirect()
+ pSendContext = NbtAllocMem((USHORT)uLength ,NBT_TAG('X'));
+
+ if (pSendContext)
+ {
+ CTEZeroMemory((PVOID)pSendContext,uLength);
+
+ pNameHdr = &pSendContext->NameHdr;
+
+ pNameHdr->TransactId = pContext->TransactId;
+ pNameHdr->QdCount = 1;
+ pNameHdr->AnCount = 0;
+ pNameHdr->NsCount = 0;
+
+ *pHdrs = (PVOID)pNameHdr;
+ *pLength = uLength = uLength - ( sizeof(DNS_DIRECT_SEND_CONTEXT) - sizeof(tNAMEHDR) );
+
+ // copy the netbios name ... adding the scope too
+ if ( pContext->Flags & DNS_DIRECT_NAME_HAS_DOTS )
+ {
+ char * p;
+ for ( p = pName ; *p != '.' ; p++ );
+ p[0] = '\0';
+ pGeneral = (tGENERALRR *)DnsStoreName(
+ (PCHAR)&pNameHdr->NameRR.NameLength,
+ pName,
+ &p[1],
+ eDIRECT_DNS_NAME_QUERY);
+ p[0] = '.';
+ }
+ else
+ {
+ pGeneral = (tGENERALRR *)DnsStoreName(
+ (PCHAR)&pNameHdr->NameRR.NameLength,
+ pName,
+ pContext->pchDomainName,
+ eDIRECT_DNS_NAME_QUERY);
+ }
+
+
+ pGeneral->Question.QuestionTypeClass = htonl(QUEST_DNSINTERNET);
+
+ pNameHdr->OpCodeFlags = (FL_RECURDESIRE);
+
+ pNameHdr->ArCount = 0;
+
+ pSendContext->SendBuffer.pDgramHdr = pNameHdr;
+ pSendContext->SendBuffer.HdrLength = uLength;
+ pSendContext->SendBuffer.pBuffer = NULL;
+ pSendContext->SendBuffer.Length = 0;
+ pSendContext->SendInfo.RemoteAddressLength = sizeof(pSendContext->NameServerAddress);
+ pSendContext->SendInfo.RemoteAddress = (PTRANSPORT_ADDRESS)&pSendContext->NameServerAddress;
+ pSendContext->NameServerAddress.TAAddressCount = 1;
+ pSendContext->NameServerAddress.Address[0].AddressLength = sizeof(TDI_ADDRESS_IP);
+ pSendContext->NameServerAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
+ pSendContext->NameServerAddress.Address[0].Address[0].sin_port = htons(NbtConfig.DnsServerPort);
+ if ( pContext->Flags & DNS_DIRECT_DNS_SERVER )
+ {
+ pSendContext->NameServerAddress.Address[0].Address[0].in_addr = htonl(pContext->pDeviceContext->lDnsServerAddress);
+ }
+ else
+ {
+ pSendContext->NameServerAddress.Address[0].Address[0].in_addr = htonl(pContext->pDeviceContext->lDnsBackupServer);
+ }
+ }
+
+ return(pSendContext);
+}
+
+//----------------------------------------------------------------------------
+ PDNS_DIRECT_WORK_ITEM_CONTEXT
+FindContextDirect(
+ USHORT TransactionId
+)
+/*++
+
+Routine Description:
+
+ This routine find the DNS_DIRECT_WORK_ITEM_CONTEXT having the given
+ TransactId
+
+Arguments:
+
+
+Return Value:
+
+ PDNS_DIRECT_SEND_CONTEXT - a pointer to the pContext having the given
+ TransactId, or NULL
+
+Notes:
+
+ Called with NbtConfig.JointLock held
+
+--*/
+{
+ PLIST_ENTRY pHead;
+ PLIST_ENTRY pEntry;
+ PDNS_DIRECT_WORK_ITEM_CONTEXT
+ pContext;
+
+ pHead = pEntry = &NbtConfig.DNSDirectNameQueries;
+
+ while ((pEntry = pEntry->Flink) != pHead)
+ {
+ pContext = CONTAINING_RECORD(pEntry,DNS_DIRECT_WORK_ITEM_CONTEXT,Linkage);
+ if ( pContext->TransactId == TransactionId )
+ {
+ return pContext;
+ }
+ }
+ return NULL;
+}
+
+//----------------------------------------------------------------------------
+ VOID
+IpToAscii(
+ IN DWORD IpAddress,
+ IN OUT PCHAR pcAscii
+)
+/*++
+
+Routine Description:
+
+ This routine converts an IP address to a NetBIOS name.
+
+Arguments:
+
+ DWORD IP address
+ PCHAR String pointer allocated for 16 bytes
+
+Return Value:
+
+ Note
+
+Notes:
+
+ This is a gigantic hack designed to get "net use \\<dnsname>"
+ working under Windows 95 OPK2 without destabilizing the existing
+ code base over much.
+
+--*/
+{
+ PCHAR pcIpAddressBytes = ( (PCHAR) &IpAddress ) + 3;
+ PCHAR pcIp = pcAscii;
+
+ int i,j,k,l,m;
+
+ memset ( pcAscii, 0x20, NETBIOS_NAME_SIZE );
+
+ for ( i = 4 ; i-- > 0 ; )
+ {
+
+ j = *pcIpAddressBytes-- & 0x000000FF;
+ k = j/100;
+ l = (j%100)/10;
+ m = j%10;
+
+ if ( k )
+ {
+ *pcIp++ = k + '0';
+ *pcIp++ = l + '0';
+ }
+
+ else if ( l )
+ {
+ *pcIp++ = l + '0';
+ }
+
+ *pcIp++ = m + '0';
+
+ if ( i )
+ {
+ *pcIp++ = '.';
+ }
+
+ }
+
+}
+
diff --git a/private/ntos/nbt/vxd/pageable.inc b/private/ntos/nbt/vxd/pageable.inc
new file mode 100644
index 000000000..8b13b5276
--- /dev/null
+++ b/private/ntos/nbt/vxd/pageable.inc
@@ -0,0 +1,36 @@
+;
+; Macro to define pageable code under Chicago and later
+; operating systems.
+;
+
+NBT_PAGEABLE_CODE_SEG MACRO
+
+ifdef CHICAGO
+
+VxD_PAGEABLE_CODE_SEG
+
+else
+
+VxD_CODE_SEG
+
+endif
+
+ endm
+
+
+
+
+
+NBT_PAGEABLE_CODE_ENDS MACRO
+
+ifdef CHICAGO
+
+VxD_PAGEABLE_CODE_ENDS
+
+else
+
+VxD_CODE_ENDS
+
+endif
+
+ endm
diff --git a/private/ntos/nbt/vxd/rules.mk b/private/ntos/nbt/vxd/rules.mk
new file mode 100644
index 000000000..831428e2f
--- /dev/null
+++ b/private/ntos/nbt/vxd/rules.mk
@@ -0,0 +1,4 @@
+#
+#:ts=4
+#
+!include ..\rules16.mk
diff --git a/private/ntos/nbt/vxd/tdiaddr.c b/private/ntos/nbt/vxd/tdiaddr.c
new file mode 100644
index 000000000..7b2727dfa
--- /dev/null
+++ b/private/ntos/nbt/vxd/tdiaddr.c
@@ -0,0 +1,184 @@
+//
+//
+// tdiaddr.c
+//
+// This file contains code relating to manipulation of address objects
+// that is specific to the VXD environment. It creates address endpoints
+// with the transport provider.
+
+#include <nbtprocs.h>
+#include <tdistat.h> // TDI error codes
+
+//----------------------------------------------------------------------------
+ NTSTATUS
+NbtTdiOpenAddress (
+ OUT PHANDLE pFileHandle,
+ OUT PDEVICE_OBJECT *ppDeviceObject,
+ OUT PFILE_OBJECT *ppFileObject,
+ IN tDEVICECONTEXT *pDeviceContext,
+ IN USHORT PortNumber,
+ IN ULONG IpAddress,
+ IN ULONG Flags
+ )
+/*++
+
+Routine Description:
+
+ Note: This synchronous call may take a number of seconds. It runs in
+ the context of the caller. The code Opens an Address object with the
+ transport provider and then sets up event handlers for Receive,
+ Disconnect, Datagrams and Errors.
+
+ The address data structures are found in tdi.h , but they are rather
+ confusing since the definitions have been spread across several data types.
+ This section shows the complete data type for Ip address:
+
+ typedef struct
+ {
+ int TA_AddressCount;
+ struct _TA_ADDRESS
+ {
+ USHORT AddressType;
+ USHORT AddressLength;
+ struct _TDI_ADDRESS_IP
+ {
+ USHORT sin_port;
+ USHORT in_addr;
+ UCHAR sin_zero[8];
+ } TDI_ADDRESS_IP
+
+ } TA_ADDRESS[AddressCount];
+
+ } TRANSPORT_ADDRESS
+
+ An EA buffer is allocated (for the IRP), with an EA name of "TransportAddress"
+ and value is a structure of type TRANSPORT_ADDRESS.
+
+Arguments:
+
+ bTCP - a boolean to say if we are openning a TCP port or a UDP port
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+{
+ NTSTATUS status = STATUS_SUCCESS ;
+ TA_IP_ADDRESS taip ; // This is really a TRANSPORT_ADDRESS
+ TDI_REQUEST tdirequest ;
+
+ DbgPrint("TdiOpenAddress called\n\r");
+
+
+ taip.TAAddressCount = 1 ;
+ taip.Address[0].AddressLength = sizeof( TDI_ADDRESS_IP ) ;
+ taip.Address[0].AddressType = TDI_ADDRESS_TYPE_IP ;
+ taip.Address[0].Address[0].sin_port = htons(PortNumber); // put in network order
+ taip.Address[0].Address[0].in_addr = htonl(IpAddress);
+ CTEZeroMemory( taip.Address[0].Address[0].sin_zero,
+ sizeof( taip.Address[0].Address[0].sin_zero ) ) ;
+
+ #define TCP_PORT 6
+ #define UDP_PORT 17
+ status = TdiVxdOpenAddress( &tdirequest,
+ (PTRANSPORT_ADDRESS) &taip,
+ Flags & SESSION_FLAG ? TCP_PORT : UDP_PORT,
+ NULL ) ;
+
+ if ( status == TDI_SUCCESS )
+ {
+ HANDLE hAddress = tdirequest.Handle.AddressHandle ;
+
+ //
+ // As a VXD, the p*FileObject in the DeviceContext structure will
+ // contain the TDI Address. For compatibility with NT (may want
+ // to change this with an environment specific address).
+ //
+ *ppFileObject = (PFILE_OBJECT) hAddress ;
+
+ if (Flags & TCP_FLAG)
+ {
+ // TCP port needs several event handlers for connection
+ // management
+ status = TdiVxdSetEventHandler(
+ hAddress,
+ TDI_EVENT_RECEIVE,
+ (PVOID)TdiReceiveHandler,
+ (PVOID)pDeviceContext);
+
+ ASSERTMSG( "Failed to set Receive event handler",
+ status == TDI_SUCCESS );
+
+ status = TdiVxdSetEventHandler(
+ hAddress,
+ TDI_EVENT_DISCONNECT,
+ (PVOID)TdiDisconnectHandler,
+ (PVOID)pDeviceContext);
+ ASSERTMSG( "Failed to set Disconnect event handler",
+ status == TDI_SUCCESS);
+
+ // only set an connect handler if the session flag is set.
+ // In this case the address being opened is the Netbios session
+ // port 139
+ if (Flags & SESSION_FLAG)
+ {
+ status = TdiVxdSetEventHandler(
+ hAddress,
+ TDI_EVENT_CONNECT,
+ (PVOID)TdiConnectHandler,
+ (PVOID)pDeviceContext);
+
+ ASSERTMSG((PUCHAR)"Failed to set Receive event handler",
+ status == TDI_SUCCESS );
+ }
+ }
+ else
+ {
+ // Datagram ports only need this event handler
+ if (PortNumber == NBT_DATAGRAM_UDP_PORT)
+ {
+ // Datagram Udp Handler
+ status = TdiVxdSetEventHandler(
+ hAddress,
+ TDI_EVENT_RECEIVE_DATAGRAM,
+ (PVOID)TdiRcvDatagramHandler,
+ (PVOID)pDeviceContext);
+ ASSERTMSG("Failed to set Receive Datagram event handler",
+ status == TDI_SUCCESS );
+ }
+ else
+ {
+ // Name Service Udp handler
+ status = TdiVxdSetEventHandler(
+ hAddress,
+ TDI_EVENT_RECEIVE_DATAGRAM,
+ (PVOID)TdiRcvNameSrvHandler,
+ (PVOID)pDeviceContext);
+ ASSERTMSG( "Failed to set Receive Datagram event handler",
+ status == TDI_SUCCESS );
+ }
+ }
+
+ status = TdiVxdSetEventHandler(
+ hAddress,
+ TDI_EVENT_ERROR,
+ (PVOID)TdiErrorHandler,
+ (PVOID)pDeviceContext);
+ ASSERTMSG("Failed to set Error event handler",
+ status == TDI_SUCCESS );
+
+
+ }
+
+#ifdef DEBUG
+ if ( status != STATUS_SUCCESS )
+ {
+ DbgPrint("NbtTdiOpenAddress: status == ") ;
+ DbgPrintNum( status ) ; DbgPrint("\n\r") ;
+ }
+#endif
+ return(status);
+}
+
+
diff --git a/private/ntos/nbt/vxd/tdicnct.c b/private/ntos/nbt/vxd/tdicnct.c
new file mode 100644
index 000000000..fea0ba781
--- /dev/null
+++ b/private/ntos/nbt/vxd/tdicnct.c
@@ -0,0 +1,328 @@
+//
+//
+// NBTCONNCT.C
+//
+// This file contains code relating to opening connections with the transport
+// provider. The Code is NT specific.
+
+#include <nbtprocs.h>
+
+void DummyCompletion( PVOID pContext ) ;
+
+//----------------------------------------------------------------------------
+ NTSTATUS
+NbtTdiOpenConnection (
+ IN tLOWERCONNECTION *pLowerConn,
+ IN tDEVICECONTEXT *pDeviceContext
+ )
+/*++
+
+Routine Description:
+
+ This routine opens a connection with the transport provider.
+
+Arguments:
+
+ pLowerConn - Pointer to where the handle to the Transport for this virtual
+ connection should be stored.
+
+ pNbtConfig - the name of the adapter to connect to is in this structure
+
+Return Value:
+
+ Status of the operation.
+
+ pLowerConn->pFileObject will contain the Connection ID of a successful open
+
+--*/
+{
+ NTSTATUS status;
+ TDI_REQUEST Request ;
+ DbgPrint("NbtTdiOpenConnection Entered\n\r") ;
+
+ CTEZeroMemory(pLowerConn,sizeof(tLOWERCONNECTION));
+ pLowerConn->State = NBT_IDLE;
+ pLowerConn->pDeviceContext = pDeviceContext;
+ pLowerConn->RefCount = 1;
+ pLowerConn->LockNumber = LOWERCON_LOCK;
+ pLowerConn->Verify = NBT_VERIFY_LOWERCONN;
+ pLowerConn->fOnPartialRcvList = FALSE;
+ InitializeListHead(&pLowerConn->PartialRcvList);
+
+ //
+ // Use the lower connection as the context
+ //
+ status = TdiVxdOpenConnection( &Request, pLowerConn ) ;
+#ifdef DEBUG
+ if ( status != TDI_SUCCESS )
+ {
+ DbgPrint("NbtTdiOpenConnection: OpenConnection failed, error ") ;
+ DbgPrintNum( status ) ;
+ DbgPrint("\n\r") ;
+ }
+#endif
+
+
+ //
+ // Store the handle in the Lower Connection for future reference
+ //
+ pLowerConn->pFileObject = Request.Handle.ConnectionContext ;
+ DbgPrint("TdiVxdOpenConnection - pLower Conn: 0x") ;
+ DbgPrintNum((ULONG) pLowerConn ) ;
+ DbgPrint( " Connection ID: 0x") ;
+ DbgPrintNum( (ULONG) Request.Handle.ConnectionContext ) ; DbgPrint("\r\n") ;
+
+ return status;
+} /* NbtTdiOpenConnection */
+
+//----------------------------------------------------------------------------
+ NTSTATUS
+NbtTdiAssociateConnection(
+ IN PFILE_OBJECT pFileObject,
+ IN HANDLE Handle
+ )
+/*++
+
+Routine Description:
+
+ This routine associates an open connection with the address object.
+
+Arguments:
+
+
+ pFileObject - the connection file object (actually a connection ID)
+ Handle - the address object to associate the connection with
+
+Return Value:
+
+ Status of the operation.
+
+--*/
+{
+ NTSTATUS status;
+ TDI_REQUEST Request ;
+ DbgPrint("NbtTdiAssociateConnection Entered\n\r") ;
+
+ Request.Handle.ConnectionContext = (CONNECTION_CONTEXT) pFileObject ;
+ status = TdiVxdAssociateAddress( &Request, Handle ) ;
+
+#ifdef DEBUG
+ if ( status != TDI_SUCCESS )
+ {
+ DbgPrint("NbtTdiAssociateConnection: AssociateAddress failed, error ") ;
+ DbgPrintNum( status ) ;
+ DbgPrint("\n\r") ;
+ }
+#endif
+ return status;
+}
+
+//----------------------------------------------------------------------------
+ NTSTATUS
+TdiOpenandAssocConnection(
+ IN tCONNECTELE *pConnEle,
+ IN tDEVICECONTEXT *pDeviceContext,
+ IN ULONG PortNumber
+ )
+/*++
+
+Routine Description:
+
+ This routine opens and associates an open connection
+
+Arguments:
+
+
+Return Value:
+
+ Status of the operation.
+
+--*/
+{
+ NTSTATUS status;
+ CTELockHandle OldIrq;
+ PDEVICE_OBJECT pDeviceObject;
+ tLOWERCONNECTION *pLowerConn;
+
+ DbgPrint("TdiOpenandAssocConnection Entered\n\r") ;
+
+ // allocate memory for the lower connection block.
+ pConnEle->pLowerConnId = (PVOID)CTEAllocMem(sizeof(tLOWERCONNECTION));
+ if (!pConnEle->pLowerConnId)
+ {
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ //
+ // fill in the lower connection element to point to the upper one and
+ // vice versa
+ //
+ pLowerConn = pConnEle->pLowerConnId;
+
+ //
+ // pLowerConn->pFileObject will contain the connection ID after
+ // this call
+ //
+ status = NbtTdiOpenConnection(pLowerConn,pDeviceContext);
+ if (!NT_SUCCESS(status))
+ {
+ CTEMemFree((PVOID)pConnEle->pLowerConnId);
+ return(status);
+ }
+
+ pLowerConn->pUpperConnection = pConnEle;
+ pLowerConn->State = NBT_CONNECTING;
+
+
+ if (NT_SUCCESS(status))
+ {
+
+
+ // Open an address object (aka port)
+ //
+ status = NbtTdiOpenAddress(
+ NULL, //&pLowerConn->AddrFileHandle,
+ &pDeviceObject, // dummy argument, not used here
+ &pLowerConn->pAddrFileObject, // Address Handle
+ pDeviceContext,
+ (USHORT)PortNumber, // port
+ pDeviceContext->IpAddress,
+ TCP_FLAG | SESSION_FLAG );
+
+ if (NT_SUCCESS(status))
+ {
+ // now associate the two
+ status = NbtTdiAssociateConnection(
+ pLowerConn->pFileObject,
+ pLowerConn->pAddrFileObject);
+ if (NT_SUCCESS(status))
+ {
+ //
+ // put the lower connection on the Q of active lower connections for
+ // this device
+ //
+ CTESpinLock(pDeviceContext,OldIrq);
+ InsertTailList(&pDeviceContext->LowerConnection,&pLowerConn->Linkage);
+ CTESpinFree(pDeviceContext,OldIrq);
+
+ return(status);
+ }
+
+ REQUIRE( NT_SUCCESS( NbtTdiCloseAddress( pLowerConn )) ) ;
+ }
+
+ REQUIRE( NT_SUCCESS( NbtTdiCloseConnection( pLowerConn )) ) ;
+ }
+
+ // Error Path... delete memory
+ //
+ pConnEle->pLowerConnId = NULL;
+ CTEMemFree((PVOID)pLowerConn);
+
+ return(status);
+}
+
+//----------------------------------------------------------------------------
+
+NTSTATUS
+NbtTdiCloseConnection(
+ IN tLOWERCONNECTION * pLowerConn
+ )
+/*++
+
+Routine Description:
+
+ This routine closes a TDI connection
+
+Arguments:
+
+
+Return Value:
+
+ Status of the operation.
+
+--*/
+{
+ NTSTATUS status ;
+ TDI_REQUEST Request ;
+ DbgPrint("NbtTdiCloseConnection Entered\n\r") ;
+
+ ASSERT( pLowerConn != NULL ) ;
+
+ Request.Handle.ConnectionContext = pLowerConn->pFileObject ;
+ Request.RequestNotifyObject = DummyCompletion ;
+ Request.RequestContext = NULL ;
+
+ status = TdiVxdCloseConnection( &Request ) ;
+
+#ifdef DEBUG
+ if ( !NT_SUCCESS( status ))
+ {
+ DbgPrint("NbtCloseConnection: Warning - returning 0x") ;
+ DbgPrintNum( status ) ; DbgPrint("\r\n") ;
+ }
+#endif
+ DbgPrint("TdiVxdCloseConnection - pLowerConn: 0x") ;
+ DbgPrintNum((ULONG) pLowerConn ) ;
+ DbgPrint(" Connection ID: 0x") ;
+ DbgPrintNum( (ULONG) Request.Handle.ConnectionContext ) ; DbgPrint("\r\n") ;
+ return status ;
+}
+
+//----------------------------------------------------------------------------
+NTSTATUS
+NbtTdiCloseAddress(
+ IN tLOWERCONNECTION * pLowerConn
+ )
+/*++
+
+Routine Description:
+
+ This routine closes a TDI address
+
+Arguments:
+
+
+Return Value:
+
+ Status of the operation.
+
+--*/
+{
+ DbgPrint("NbtTdiCloseAddress Entered\n\r") ;
+ ASSERT( pLowerConn != NULL ) ;
+
+ return CloseAddress( pLowerConn->pAddrFileObject ) ;
+}
+
+//----------------------------------------------------------------------------
+NTSTATUS CloseAddress( HANDLE hAddress )
+{
+ NTSTATUS status ;
+ TDI_REQUEST Request ;
+ DbgPrint("CloseAddress Entered\n\r") ;
+
+ Request.Handle.AddressHandle = hAddress ;
+ Request.RequestNotifyObject = DummyCompletion ;
+ Request.RequestContext = NULL ;
+
+ status = TdiVxdCloseAddress( &Request ) ;
+
+#ifdef DEBUG
+ if ( !NT_SUCCESS( status ))
+ {
+ DbgPrint("CloseAddress: Warning - returning 0x") ;
+ DbgPrintNum( status ) ; DbgPrint("\r\n") ;
+ }
+#endif
+ return status ;
+}
+
+
+//
+// Dummy completion routine for Close connection and Close Address
+//
+void DummyCompletion( PVOID pContext )
+{
+ return ;
+}
diff --git a/private/ntos/nbt/vxd/tdihndlr.c b/private/ntos/nbt/vxd/tdihndlr.c
new file mode 100644
index 000000000..f5a9d5425
--- /dev/null
+++ b/private/ntos/nbt/vxd/tdihndlr.c
@@ -0,0 +1,1719 @@
+/*++
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ Tdihndlr.c
+
+Abstract:
+
+
+ This file contains the TDI handlers that are setup for Connects,
+ Receives, Disconnects, and Errors on an address object (in tdiaddr.c).
+
+ This file represents the TDI interface on the Bottom of NBT. Therefore
+ the code basically decodes the incoming information and passes it to
+ a non-Os specific routine to do what it can. Upon return from that
+ routine additional Os specific work may need to be done.
+
+
+Author:
+
+ Jim Stewart (Jimst) 10-2-92
+ John Ludeman (JohnL) 04-10-93 - Rewrote for VXD
+
+Revision History:
+
+--*/
+
+#include "nbtprocs.h"
+#include "ctemacro.h"
+
+//
+// The event receive buffer takes a pointer to a flags variable that will
+// always be the same, so just use the same variable
+//
+static USHORT usFlags = TDI_RECEIVE_NORMAL ;
+
+VOID
+AcceptCompletionRoutine(
+ IN PVOID pContext,
+ IN uint tdistatus,
+ IN uint extra
+ );
+VOID
+NewSessionCompletionRoutine (
+ IN PVOID pContext,
+ IN uint tdistatus,
+ IN uint extra
+ );
+NTSTATUS
+Reindicate(
+ IN PVOID ReceiveEventContext,
+ IN PVOID ConnectionContext,
+ IN USHORT ReceiveFlags,
+ IN ULONG BytesIndicated,
+ IN ULONG BytesAvailable,
+ OUT PULONG BytesTaken,
+ IN PVOID pTsdu
+ );
+
+//
+// This ntohl swaps just three bytes, since the 4th byte could be a session
+// keep alive message type.
+//
+__inline long
+myntohl(long x)
+{
+ return((((x) >> 24) & 0x000000FFL) |
+ (((x) >> 8) & 0x0000FF00L) |
+ (((x) << 8) & 0x00FF0000L));
+}
+
+//----------------------------------------------------------------------------
+ TDI_STATUS
+TdiReceiveHandler (
+ IN PVOID ReceiveEventContext,
+ IN PVOID ConnectionContext,
+ IN USHORT ReceiveFlags,
+ IN ULONG BytesIndicated,
+ IN ULONG BytesAvailable,
+ OUT PULONG BytesTaken,
+ IN PVOID pTsdu,
+ OUT EventRcvBuffer * pevrcvbuf
+ )
+/*++
+
+Routine Description:
+
+ This routine is the receive event indication handler.
+
+ It is called when an session packet arrives from the network. It calls
+ a non OS specific routine to decide what to do. That routine passes back
+ either a RcvElement (buffer) or a client rcv handler to call.
+
+Arguments:
+
+ IN PVOID ReceiveEventContext - Context provided for this event when event set
+ IN PVOID ConnectionContext - Connection Context, (pLowerConnection)
+ IN USHORT ReceiveFlags - Flags describing the message
+ IN ULONG BytesIndicated - Number of bytes available at indication time
+ IN ULONG BytesAvailable - Number of bytes available to receive
+ OUT PULONG BytesTaken - Number of bytes consumed by redirector.
+ IN PVOID pTsdu - Data from remote machine.
+ OUT EvenRcvBuffer *ppBuffer - Receive buffer to fill if set
+
+
+Return Value:
+
+ TDI_STATUS - Status of receive operation
+
+--*/
+
+{
+ tLOWERCONNECTION *pLowerConn;
+ tCONNECTELE *pConnectEle;
+ PRCV_CONTEXT prcvCont = NULL ;
+ NTSTATUS status;
+ ULONG PduSize;
+ ULONG RemainingPdu;
+
+ DbgPrint("TRH Entered (ConnectionContext = 0x") ;
+ DbgPrintNum( (ULONG) ConnectionContext) ; DbgPrint(")\r\n") ;
+
+ pLowerConn = (tLOWERCONNECTION *)ConnectionContext;
+
+ pLowerConn->BytesRcvd += BytesAvailable;
+
+ //
+ // check if this is another part of a session pdu
+ //
+ if (pLowerConn->State == NBT_SESSION_UP)
+ {
+ DbgPrint("\tTRH: Session status is UP, Bytes: available, indicated: 0x") ;
+ DbgPrintNum( BytesAvailable ) ; DbgPrint(" 0x") ;
+ DbgPrintNum( BytesIndicated ) ;
+ DbgPrint("\r\n") ;
+
+ pConnectEle = pLowerConn->pUpperConnection;
+ pConnectEle->BytesInXport = BytesAvailable ;
+ *BytesTaken = 0 ;
+
+ DbgPrint("\tTRH: BytesInXport: 0x") ;
+ DbgPrintNum( pConnectEle->BytesInXport ) ;
+ DbgPrint("\r\n") ;
+
+
+ //
+ // ** RECEIVING A PDU STATE **
+ //
+
+ switch (pLowerConn->StateRcv)
+ {
+ case NORMAL:
+ //
+ // check indication and if less than the session header,
+ // copy to the session header buffer and go to Indic_buffer state
+ // and wait for the next indication. This is a rare case (and a pain
+ // in the butt).
+ //
+ if (BytesIndicated < sizeof(tSESSIONHDR))
+ {
+ ASSERT( pLowerConn->BytesInHdr == 0 ) ;
+ DbgPrint("\tTRH - NORMAL case: Not enough for session header, requesting 0x") ;
+ DbgPrintNum( sizeof( pLowerConn->Hdr ) ) ;
+ DbgPrint(" bytes\r\n") ;
+
+
+ if ( !GetRcvContext( &prcvCont))
+ return STATUS_INSUFFICIENT_RESOURCES ;
+
+ InitRcvContext( prcvCont, pLowerConn, NULL ) ;
+ prcvCont->usFlags = TDI_RECEIVE_NORMAL;
+ pevrcvbuf->erb_buffer = &prcvCont->ndisBuff ;
+ pevrcvbuf->erb_rtn = (CTEReqCmpltRtn) NewSessionCompletionRoutine ;
+ pevrcvbuf->erb_size = sizeof( pLowerConn->Hdr ) ;
+ pevrcvbuf->erb_context = prcvCont ;
+ pevrcvbuf->erb_flags = &usFlags ;
+ InitNDISBuff( pevrcvbuf->erb_buffer,
+ &pLowerConn->Hdr,
+ sizeof(pLowerConn->Hdr),
+ NULL ) ;
+
+ pLowerConn->StateRcv = INDICATE_BUFFER;
+
+ //
+ // Okay to use pIrpRcv here as it will only be completed if
+ // the state is FILL_IRP
+ //
+ pConnectEle->pIrpRcv = (PCTE_IRP) prcvCont ;
+
+ return TDI_MORE_PROCESSING ;
+ }
+
+ PduSize = myntohl(((tSESSIONHDR *)pTsdu)->UlongLength)
+ + sizeof(tSESSIONHDR);
+ DbgPrint("\tTRH: New message; Opcode, PduSize + hdr : 0x") ;
+ DbgPrintNum( ((tSESSIONHDR *)pTsdu)->Type ) ; DbgPrint(" 0x") ;
+ DbgPrintNum( PduSize ) ; DbgPrint("\r\n") ;
+
+ //
+ // Indicate to the client
+ //
+ ASSERT( PduSize >= sizeof(tSESSIONHDR)) ;
+ status = RcvHandlrNotOs(
+ ReceiveEventContext,
+ ConnectionContext,
+ ReceiveFlags,
+ BytesIndicated,
+ BytesAvailable,
+ BytesTaken,
+ pTsdu,
+ &prcvCont
+ );
+
+ ASSERT( *BytesTaken <= pConnectEle->BytesInXport ) ;
+ ASSERT( *BytesTaken <= BytesIndicated);
+ pConnectEle->BytesInXport -= *BytesTaken;
+ BytesIndicated -= *BytesTaken;
+ BytesAvailable -= *BytesTaken;
+ ((BYTE*)pTsdu) += *BytesTaken ;
+
+ DbgPrint("\tTRH: RcvHandlrNotOs returned, BytesTaken: 0x") ;
+ DbgPrintNum( *BytesTaken ) ;
+ DbgPrint("\r\n") ;
+
+ DbgPrint("\tTRH: RcvHandlrNotOs status, prcvCont: 0x") ;
+ DbgPrintNum( status ) ; DbgPrint(" 0x") ;
+ DbgPrintNum( (ULONG)prcvCont ) ; DbgPrint("\r\n") ;
+
+ if ( prcvCont )
+ {
+ ULONG BytesToCopy ;
+ ASSERT( status == STATUS_MORE_PROCESSING_REQUIRED );
+ ASSERT( prcvCont->Signature == RCVCONT_SIGN ) ;
+
+ //
+ // Record which session satisfied the request
+ //
+ prcvCont->pLowerConnId = pLowerConn ;
+ REQUIRE( !VxdFindLSN( pConnectEle->pClientEle->pDeviceContext,
+ pConnectEle,
+ &prcvCont->pNCB->ncb_lsn )) ;
+ //
+ // New message so strip session header
+ //
+ PduSize -= *BytesTaken ;
+ DbgPrint("\tTRH: Remaining PduSize = 0x") ;
+ DbgPrintNum( PduSize ) ; DbgPrint("\r\n") ;
+
+ DbgPrint("\tTRH: TotalPcktLen = 0x") ;
+ DbgPrintNum( pConnectEle->TotalPcktLen ) ; DbgPrint("\r\n") ;
+
+ BytesToCopy = min( pConnectEle->TotalPcktLen,
+ prcvCont->ndisBuff.Length ) ;
+
+ DbgPrint("\tTRH: BytesToCopy = 0x") ;
+ DbgPrintNum( BytesToCopy ) ; DbgPrint("\r\n") ;
+
+ //
+ // pIrpRcv is set to NULL while the request is in the
+ // transport. This prevents two completions if an error
+ // occurs
+ //
+ pLowerConn->StateRcv = FILL_IRP ;
+ pConnectEle->pIrpRcv = NULL ;
+ pConnectEle->OffsetFromStart = 0 ;
+
+ //
+ // If the data is available, then just grab it now
+ // (also, if flag is set to TDI_RECEIVE_NO_RESPONSE_EXP, we
+ // need to give hint to the xport, so let xport do the copying)
+ //
+ if ( ( BytesIndicated >= BytesToCopy ) &&
+ ( prcvCont->usFlags == TDI_RECEIVE_NORMAL ) )
+ {
+ CTEMemCopy( prcvCont->ndisBuff.VirtualAddress,
+ pTsdu,
+ BytesToCopy ) ;
+ *BytesTaken += BytesToCopy ;
+ CompletionRcv( prcvCont, STATUS_SUCCESS, BytesToCopy ) ;
+ return STATUS_SUCCESS ;
+ }
+
+ pevrcvbuf->erb_buffer = &prcvCont->ndisBuff ;
+ pevrcvbuf->erb_rtn = CompletionRcv ;
+ pevrcvbuf->erb_size = BytesToCopy ;
+ pevrcvbuf->erb_context = prcvCont ;
+ if (prcvCont->usFlags == TDI_RECEIVE_NO_RESPONSE_EXP)
+ pevrcvbuf->erb_flags = &prcvCont->usFlags ;
+ else
+ pevrcvbuf->erb_flags = &usFlags ;
+
+ DbgPrint("\tTRH: Rcv Dest Buff: 0x") ;
+ DbgPrintNum((ULONG)pevrcvbuf->erb_buffer->VirtualAddress) ; DbgPrint("\r\n") ;
+ return TDI_MORE_PROCESSING ;
+ }
+ else
+ {
+ // the client received some, all or none of the data
+ // For Keep Alives the PduSize is zero so this check
+ // will work correctly and go to the else
+ // Also, if we were attempting to complete a zero-len message
+ // but failed because there was no receive pending then we
+ // must go in PARTIAL_RCV state
+ //
+ if ( (*BytesTaken < PduSize) ||
+ ((status == STATUS_DATA_NOT_ACCEPTED) &&
+ (pConnectEle->TotalPcktLen == 0) &&
+ (pConnectEle->state == NBT_SESSION_UP)) )
+ {
+ //
+ // took some of the data, so keep track of the
+ // rest of the data left here by going to the PARTIALRCV
+ // state.
+ //
+ pLowerConn->StateRcv = PARTIAL_RCV;
+ InsertTailList( &pLowerConn->pDeviceContext->PartialRcvHead,
+ &pLowerConn->PartialRcvList ) ;
+ pLowerConn->fOnPartialRcvList = TRUE;
+
+ DbgPrint("TdiReceiveHandler:Switch to Partial Rcv Indicated\r\n") ;
+
+ return STATUS_SUCCESS ;
+ }
+ else
+ {
+ //
+ // Must have taken all of the pdu data, so check for
+ // more data available - if so then reindicate ourselves.
+ // Note that TDI will pickup the bytes taken before any posted
+ // receives are performed.
+ //
+ status = STATUS_SUCCESS ;
+
+ //
+ // The next bytes in the transport will be the
+ // beginning of a Session Header so leave the state
+ // as NORMAL
+ //
+
+ if (BytesAvailable > *BytesTaken)
+ {
+ ULONG ClientBytesTaken = 0 ;
+
+ //
+ // we already added the bytes available the first time
+ // TdiReceiveHandler got called. They will get added
+ // again, so subtract now!
+ //
+ pLowerConn->BytesRcvd -= BytesAvailable;
+
+ status = TdiReceiveHandler( ReceiveEventContext,
+ ConnectionContext,
+ ReceiveFlags,
+ BytesIndicated,
+ BytesAvailable,
+ &ClientBytesTaken,
+ pTsdu,
+ pevrcvbuf ) ;
+
+ *BytesTaken += ClientBytesTaken ;
+ //
+ // status will be more processing if pervrcvbuf
+ // was setup, else it will be success if
+ // bytes were taken. Note that BytesInXport
+ // is adjusted automatically in the call to
+ // TdiReceiveHandler
+ //
+ }
+ }
+ }
+ return status ;
+
+ case FILL_IRP:
+ {
+ NCB * pNCB = pConnectEle->pIrpRcv ;
+ ULONG BuffAvailable = pNCB->ncb_length - pConnectEle->OffsetFromStart ;
+ ULONG BytesToCopy ;
+
+ // we are still waiting for the rest of the session pdu so
+ // do not call the RcvHandlrNotOs, since we already have the buffer
+ // to put this data in.
+ prcvCont = *((PRCV_CONTEXT*)&pNCB->ncb_reserve) ;
+ ASSERT( prcvCont->Signature = RCVCONT_SIGN ) ;
+
+ //
+ // too much data may have arrived... i.e. part of the next session pdu..
+ // so check and set the receive length accordingly
+ //
+ RemainingPdu = pConnectEle->TotalPcktLen - pConnectEle->BytesRcvd;
+ BytesToCopy = min( RemainingPdu, BuffAvailable ) ;
+ pConnectEle->pIrpRcv = NULL ; // Buffer in the transport
+
+ DbgPrint("\tTRH - FILL_IRP case: Requesting 0x") ;
+ DbgPrintNum( pevrcvbuf->erb_size ) ; DbgPrint("\r\n") ;
+
+ //
+ // Append the new data onto the existing data
+ //
+ ((BYTE*)prcvCont->ndisBuff.VirtualAddress) =
+ pNCB->ncb_buffer + pConnectEle->OffsetFromStart ;
+ prcvCont->ndisBuff.Length =
+ pNCB->ncb_length - pConnectEle->OffsetFromStart ;
+
+ //
+ // If the data is available, then just grab it now
+ //
+ if ( BytesIndicated >= BytesToCopy )
+ {
+ CTEMemCopy( prcvCont->ndisBuff.VirtualAddress,
+ pTsdu,
+ BytesToCopy ) ;
+ *BytesTaken += BytesToCopy ;
+ CompletionRcv( prcvCont, STATUS_SUCCESS, BytesToCopy ) ;
+ return STATUS_SUCCESS ;
+ }
+
+ //
+ // Have to post a buffer since the data isn't available
+ // We also have a new offset for the *next* indication
+ //
+ pevrcvbuf->erb_buffer = &prcvCont->ndisBuff ;
+ pevrcvbuf->erb_rtn = CompletionRcv ;
+ pevrcvbuf->erb_size = BytesToCopy ;
+
+ pevrcvbuf->erb_context = prcvCont ;
+ pevrcvbuf->erb_flags = &usFlags ;
+ ASSERT( pConnectEle->OffsetFromStart <= pNCB->ncb_length ) ;
+
+ DbgPrint("\tTRH: offset, address: 0x") ;
+ DbgPrintNum( pConnectEle->OffsetFromStart ) ; DbgPrint(", 0x") ;
+ DbgPrintNum( (ULONG)prcvCont->ndisBuff.VirtualAddress ) ; DbgPrint("\r\n") ;
+
+ //
+ // State remains in FILL_IRP (only goes to PARTIAL_RCV when no
+ // NCBs are actively receiving and only part of a PDU has been
+ // picked up).
+ //
+ // BytesInXport adjusted in CompletinRcv
+ //
+
+ return TDI_MORE_PROCESSING ;
+ }
+ break ;
+
+ case INDICATE_BUFFER:
+ {
+ DbgPrint("\tTRH: Hit INDICATE_BUFFER state, bytes in hdr: 0x") ;
+ DbgPrintNum( pLowerConn->BytesInHdr ) ;
+ DbgPrint("\r\n") ;
+
+ //
+ // Our context is still setup so adjust things such that
+ // the location to start copying the new data into is right
+ // after the existing data in the session header buffer
+ //
+ prcvCont = (PRCV_CONTEXT) pConnectEle->pIrpRcv ;
+ ASSERT( prcvCont->Signature == RCVCONT_SIGN ) ;
+ ((BYTE*)prcvCont->ndisBuff.VirtualAddress) =
+ ((BYTE*)&pLowerConn->Hdr) + pLowerConn->BytesInHdr ;
+ prcvCont->ndisBuff.Length =
+ sizeof( pLowerConn->Hdr ) - pLowerConn->BytesInHdr ;
+ pevrcvbuf->erb_size = min( BytesAvailable,
+ sizeof(pLowerConn->Hdr) - pLowerConn->BytesInHdr) ;
+ pevrcvbuf->erb_buffer = &prcvCont->ndisBuff ;
+ pevrcvbuf->erb_rtn = NewSessionCompletionRoutine ;
+ pevrcvbuf->erb_context = prcvCont ;
+ pevrcvbuf->erb_flags = &usFlags ;
+ return TDI_MORE_PROCESSING ;
+ }
+
+ case PARTIAL_RCV:
+ //
+ // If we get indicated in this state, then the client doesn't have
+ // any receive buffers posted and we are in the middle of a
+ // PDU, so just track the new byte count and continue waiting
+ // for the client
+ //
+ DbgPrint("\tTRH: Indicated in Partial_Rcv state\r\n") ;
+ return STATUS_SUCCESS ;
+
+ default:
+ ASSERT( FALSE ) ;
+ break;
+ }
+ }
+ else if ( pLowerConn->State == NBT_SESSION_INBOUND )
+ {
+ status = Inbound(
+ ReceiveEventContext,
+ ConnectionContext,
+ ReceiveFlags,
+ BytesIndicated,
+ BytesAvailable,
+ BytesTaken,
+ pTsdu,
+ &prcvCont
+ );
+ }
+ else if ( pLowerConn->State == NBT_SESSION_OUTBOUND )
+ {
+ status = Outbound(
+ ReceiveEventContext,
+ ConnectionContext,
+ ReceiveFlags,
+ BytesIndicated,
+ BytesAvailable,
+ BytesTaken,
+ pTsdu,
+ &prcvCont
+ );
+ }
+
+ //
+ // maybe disconnect is going on: reject the data
+ //
+ else
+ {
+ *BytesTaken = BytesAvailable;
+ status = STATUS_SUCCESS;
+ }
+
+ //
+ // Client should *never* pass back a completion buffer (only used by
+ // event handler which isn't supported in a VXD
+ //
+ ASSERT( prcvCont == NULL ) ;
+
+ return status;
+}
+
+//----------------------------------------------------------------------------
+
+TDI_STATUS
+ReceiveAnyHandler ( // Handles NCBRCVANY commands, is
+ IN PVOID ReceiveEventContext, // called after all other receive
+ IN PVOID ConnectionContext, // handlers
+ IN USHORT ReceiveFlags,
+ IN ULONG BytesIndicated,
+ IN ULONG BytesAvailable,
+ OUT PULONG BytesTaken,
+ IN PVOID Data,
+ PVOID * ppBuffer // Pointer to RCV_CONTEXT
+ )
+/*++
+
+Routine Description:
+
+ This routine handles any data not processed by TdiReceiveHandler and
+ RcvHandlrNotOs. It processes ReceiveAny NCBs.
+
+ Note that TdiReceiveHandler calls RcvHandlrNotOs which may call
+ this routine (i.e., this is only called from RcvHandlrNotOs).
+
+Arguments:
+
+--*/
+{
+ TDI_STATUS tdistatus ;
+ tCLIENTELE * pClientEle;
+ PLIST_ENTRY pEntry ;
+ PRCV_CONTEXT prcvCont ;
+
+ DbgPrint("ReceiveAnyHandler Entered \r\n") ;
+ *ppBuffer = NULL ;
+
+ pClientEle = (tCLIENTELE*) ReceiveEventContext ;
+
+ ASSERT( pClientEle->Verify == NBT_VERIFY_CLIENT ) ;
+
+ //
+ // Are there any ReceiveAny NCBs queued for this connection or for
+ // any connection?
+ //
+ if ( !IsListEmpty( &pClientEle->RcvAnyHead ))
+ {
+ pEntry = RemoveHeadList( &pClientEle->RcvAnyHead ) ;
+ DbgPrint("ReceiveAnyHandler - Found Receive Any buffer\r\n") ;
+ }
+ else if ( !IsListEmpty( &pClientEle->pDeviceContext->RcvAnyFromAnyHead ))
+ {
+ pEntry = RemoveHeadList( &pClientEle->pDeviceContext->RcvAnyFromAnyHead ) ;
+ DbgPrint("ReceiveAnyHandler - Found Receive Any from Any buffer\r\n") ;
+ }
+ else
+ return STATUS_SUCCESS ;
+ //
+ // Found one
+ //
+ prcvCont = *ppBuffer = CONTAINING_RECORD( pEntry, RCV_CONTEXT, ListEntry ) ;
+ ASSERT( prcvCont->Signature == RCVCONT_SIGN ) ;
+ return TDI_MORE_PROCESSING ;
+}
+
+//----------------------------------------------------------------------------
+ VOID
+CompletionRcv(
+ IN PVOID pContext,
+ IN uint tdistatus,
+ IN uint BytesRcvd )
+/*++
+
+Routine Description:
+
+ This routine completes TdiVxdReceive. The NCB is completed or further
+ receives are performed.
+
+Arguments:
+
+ pContext - Pointer to a RCV_CONTEXT structure
+ tdistatus - Completion status
+ BytesRcvd - Bytes copied to the destination buffer
+
+--*/
+{
+ tLOWERCONNECTION *pLowerConn;
+ tCONNECTELE *pConnectEle;
+ PRCV_CONTEXT prcvcont = (PRCV_CONTEXT) pContext ;
+
+ DbgPrint("CompletionRcv Entered (BytesRcvd: 0x") ;
+ DbgPrintNum( BytesRcvd ) ; DbgPrint(")\r\n") ;
+
+ ASSERT( prcvcont->Signature == RCVCONT_SIGN ) ;
+ ASSERT( tdistatus ||
+ (!tdistatus && ((prcvcont->pLowerConnId != NULL) &&
+ (prcvcont->pLowerConnId->pUpperConnection != NULL))) ) ;
+
+ //
+ // If an error occurred, bail
+ //
+ if ( tdistatus && tdistatus != TDI_BUFFER_OVERFLOW )
+ {
+ DbgPrint("CompletionRcv: error occurred, status: 0x") ;
+ DbgPrintNum( tdistatus ) ; DbgPrint("\n\r") ;
+
+ //
+ // Make sure the receive IRP doesn't get completed twice if the
+ // connection is still up
+ //
+ if ( prcvcont->pLowerConnId &&
+ prcvcont->pLowerConnId->pUpperConnection )
+ {
+ prcvcont->pLowerConnId->pUpperConnection->pIrpRcv = NULL ;
+ }
+
+ CTEIoComplete( prcvcont->pNCB, tdistatus, 0 ) ;
+ return ;
+ }
+
+ pLowerConn = prcvcont->pLowerConnId ;
+ pConnectEle = pLowerConn->pUpperConnection;
+
+ ASSERT( pConnectEle->Verify == NBT_VERIFY_CONNECTION ) ;
+ pConnectEle->BytesRcvd += BytesRcvd;
+ pConnectEle->OffsetFromStart += BytesRcvd ;
+
+ //
+ // Since we request NCB buffer sizes, we can get more bytes then what
+ // was shown as available. If that happens then we've already consumed
+ // all transport bytes so reset to 0.
+ //
+ if ( pConnectEle->BytesInXport <= BytesRcvd )
+ pConnectEle->BytesInXport = 0 ;
+ else
+ pConnectEle->BytesInXport -= BytesRcvd ;
+
+ //
+ // this case handles when all bytes in a session pdu have arrived...
+ //
+ if (pConnectEle->BytesRcvd == pConnectEle->TotalPcktLen)
+ {
+ //
+ // we have received all of the data for this message
+ // so complete back to the client
+ //
+ DbgPrint("CompletionRcv: PDU Receive done, about to complete client with 0x") ;
+ DbgPrintNum( pConnectEle->OffsetFromStart ) ; DbgPrint(" of total PDU length: 0x") ;
+ DbgPrintNum( pConnectEle->TotalPcktLen ) ; DbgPrint("\r\n") ;
+
+ pConnectEle->pIrpRcv = NULL ;
+
+ //
+ // change the state before completing the ncb because our client can
+ // turn around and post a hangup rightaway (in fact, net send does that!)
+ //
+ pLowerConn->StateRcv = NORMAL;
+ CTEIoComplete( prcvcont->pNCB, STATUS_SUCCESS, pConnectEle->OffsetFromStart ) ;
+
+ //
+ // Freed by CTEIoComplete, make sure we don't use it again
+ //
+ prcvcont = NULL ;
+
+ pConnectEle->OffsetFromStart = 0;
+ pConnectEle->BytesRcvd = 0; // reset for the next session pdu
+ pLowerConn->BytesInHdr = 0 ;
+
+ //
+ // Check if there is still more data in the transport and reindicate
+ // if there is.
+ //
+ if (pConnectEle->BytesInXport)
+ {
+ ULONG BytesTaken = 0 ;
+ DbgPrint("Nbt:ComplRcv - Bytes left in Xport after completing a receive, BytesInXport= 0x") ;
+ DbgPrintNum(pConnectEle->BytesInXport) ;
+ DbgPrint("\r\n") ;
+
+ //
+ // The next thing to do is copy the session header into
+ // pLowerConn->Hdr which this will do.
+ //
+ tdistatus = Reindicate( NULL,
+ pLowerConn,
+ 0, // Rcv flags
+ 0, // Bytes Indicated
+ pConnectEle->BytesInXport, // Bytes Avail
+ &BytesTaken,
+ NULL ) ; // tsdu
+ }
+
+ }
+ else
+ if (pConnectEle->BytesRcvd > pConnectEle->TotalPcktLen)
+ {
+ DbgPrint("CompletionRcv: Too Many Bytes Rcvd!! Rcvd 0x") ;
+ DbgPrintNum( pConnectEle->BytesRcvd ) ;
+ DbgPrint(" Total message length:0x") ;
+ DbgPrintNum( pConnectEle->TotalPcktLen ) ;
+ //DbgPrint(" NCB Buffer size: 0x") ;
+ //DbgPrintNum( prcvcont->pNCB->ncb_length ) ;
+ DbgPrint("\r\n") ;
+ ASSERT(FALSE);
+
+ pConnectEle->pIrpRcv = NULL ;
+ pLowerConn->StateRcv = NORMAL;
+ pConnectEle->BytesRcvd = 0; // reset for the next session pdu
+ pLowerConn->BytesInHdr = 0 ;
+ CTEIoComplete( prcvcont->pNCB, TDI_INVALID_STATE, 0 ) ;
+ }
+ else
+ {
+ ASSERT( prcvcont->pNCB ) ;
+
+ //
+ // Haven't received all of the data for this PDU yet, check to
+ // see how much room the NCB has left in it.
+ //
+ if ( pConnectEle->OffsetFromStart >= prcvcont->pNCB->ncb_length )
+ {
+ // If OffsetFromStart is greater then the buffer size then we
+ // have went beyond the end of the buffer.
+ ASSERT( pConnectEle->OffsetFromStart == prcvcont->pNCB->ncb_length ) ;
+
+ DbgPrint("CompletionRcv: Completed NCB but more data available, Total BytesRecieved: 0x") ;
+ DbgPrintNum( pConnectEle->BytesRcvd ) ;
+ DbgPrint("\r\n Ncb buffer size completed: 0x") ;
+ DbgPrintNum( prcvcont->pNCB->ncb_length ) ;
+ DbgPrint("\r\n") ;
+
+ pConnectEle->pIrpRcv = NULL ;
+ pConnectEle->OffsetFromStart = 0;
+ pLowerConn->StateRcv = PARTIAL_RCV ;
+ InsertTailList( &pLowerConn->pDeviceContext->PartialRcvHead,
+ &pLowerConn->PartialRcvList ) ;
+ pLowerConn->fOnPartialRcvList = TRUE;
+
+ //
+ // Done with this NCB, set the status appropriately and hope
+ // the client will submit another NCB to pick up the rest of
+ // the PDU. prcvcont freed by the completion.
+ //
+ CTEIoComplete( prcvcont->pNCB,
+ TDI_BUFFER_OVERFLOW, //translates to: NRC_INCOMP
+ prcvcont->pNCB->ncb_length ) ;
+
+ }
+ else
+ {
+ //
+ // Room still left in the NCB so wait for the transport to
+ // indicate when more data is available (OffsetFromStart has
+ // already been adjusted)
+ //
+ pConnectEle->pIrpRcv = prcvcont->pNCB ;
+ pLowerConn->StateRcv = FILL_IRP ;
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+ VOID
+NewSessionCompletionRoutine (
+ IN PVOID pContext,
+ IN uint tdistatus,
+ IN uint BytesReceived
+ )
+/*++
+
+Routine Description:
+
+ This routine handles the completion of the receive to get the remaining
+ data left in the transport when a session PDU starts in the middle of
+ an indication from the transport. This routine is run as the completion
+ of a recv Irp passed to the transport by NBT, to get the remainder of the
+ data in the transport.
+
+ The routine then calls the normal receive handler, which can either
+ consume the data or pass back an Irp. If an Irp is passed back then
+ the data is copied into that irp in this routine.
+
+ Called when a partial message header is received - puts the data back
+ on the
+
+Arguments:
+
+
+Return Value:
+
+ pConnectionContext - connection context returned to the transport(connection to use)
+
+ NTSTATUS - Status of receive operation
+
+--*/
+
+{
+ PRCV_CONTEXT prcvCont = pContext ;
+ NTSTATUS status;
+ ULONG BytesTaken = 0;
+ ULONG BytesAvailable ;
+ tCONNECTELE *pConnEle;
+ tLOWERCONNECTION *pLowerConn;
+
+ DbgPrint("NewSessionCompletionRoutine Entered\r\n") ;
+ ASSERT( prcvCont->Signature == RCVCONT_SIGN ) ;
+
+ pLowerConn = prcvCont->pLowerConnId ;
+ pConnEle = pLowerConn->pUpperConnection ;
+
+ //
+ // If an error occurred just drop the PDU on the floor (though an
+ // error really shouldn't happen)
+ //
+ if ( tdistatus != TDI_SUCCESS )
+ {
+ FreeRcvContext( prcvCont ) ;
+ pLowerConn->StateRcv = NORMAL ;
+ return ;
+ }
+
+ //
+ // Adjust BytesInXport if there were too few bytes for the
+ // session header
+ //
+ if ( BytesReceived > pConnEle->BytesInXport )
+ pConnEle->BytesInXport = BytesReceived ;
+
+ //
+ // there may be data still in the indication buffer,
+ // so add that amount to what we just received. The transport
+ // has already copied the data into the pLowerConn->Hdr so we
+ // just need to update the state.
+ //
+ ASSERT( BytesReceived <= sizeof( pLowerConn->Hdr ) ) ;
+ pLowerConn->BytesInHdr += BytesReceived ;
+
+ //
+ // If we have a full header, process it
+ //
+ if ( pLowerConn->BytesInHdr == sizeof(pLowerConn->Hdr) )
+ {
+ ULONG BytesTaken = 0 ;
+ pLowerConn->StateRcv = NORMAL ; // New session header
+ pLowerConn->BytesInHdr = 0 ;
+ FreeRcvContext( prcvCont ) ;
+
+ //
+ // We indicate just the session header bytes, this will force
+ // the client to post a receive if they are interested in the
+ // rest of the data
+ //
+ status = Reindicate(NULL,
+ pLowerConn,
+ 0, // rcv flags
+ sizeof( pLowerConn->Hdr ),
+ pConnEle->BytesInXport,
+ &BytesTaken,
+ &pLowerConn->Hdr ) ;
+ ASSERT( BytesTaken <= sizeof( pLowerConn->Hdr ) ) ;
+ }
+ else
+ {
+ //
+ // We *still* don't have the full session header so
+ // wait for reindication
+ //
+ return ;
+ }
+}
+//----------------------------------------------------------------------------
+ NTSTATUS
+Reindicate(
+ IN PVOID ReceiveEventContext,
+ IN PVOID ConnectionContext,
+ IN USHORT ReceiveFlags,
+ IN ULONG BytesIndicated,
+ IN ULONG BytesAvailable,
+ OUT PULONG BytesTaken,
+ IN PVOID pTsdu
+ )
+/*++
+
+Routine Description:
+
+ This routine copies data from the Indicate buffer to a 128 byte buffer and
+ then fills this with data from the current indication.
+
+Arguments:
+
+
+Return Value:
+
+
+ NTSTATUS - Status of receive operation
+
+--*/
+
+{
+ NTSTATUS status = STATUS_SUCCESS ;
+ tLOWERCONNECTION *pLowerConn;
+ tCONNECTELE *pConnEle;
+ EventRcvBuffer evrcvbuf ;
+
+ DbgPrint("Reindicated Entered\r\n") ;
+ DbgPrint("\tReindicate: Bytes: available, indicated: 0x") ;
+ DbgPrintNum( BytesAvailable ) ; DbgPrint(" 0x") ;
+ DbgPrintNum( BytesIndicated ) ;
+ DbgPrint("\r\n") ;
+ pLowerConn = (tLOWERCONNECTION *)ConnectionContext;
+ pConnEle = pLowerConn->pUpperConnection;
+
+ //
+ // we already added the bytes available the first time TdiReceiveHandler
+ // got called. They will get added again, so subtract now!
+ //
+ pLowerConn->BytesRcvd -= BytesAvailable;
+
+ status = TdiReceiveHandler(NULL,
+ pLowerConn,
+ 0, // rcv flags
+ BytesIndicated,
+ BytesAvailable,
+ BytesTaken,
+ pTsdu,
+ &evrcvbuf );
+
+ //
+ // If a receive context was returned, then post the receive, if bytes
+ // were taken, the state was updated in the receive handler
+ //
+ if ( status == TDI_MORE_PROCESSING )
+ {
+ TDI_REQUEST Request ;
+ PRCV_CONTEXT prcvCont = evrcvbuf.erb_context ;
+ ULONG cbRcvLength = evrcvbuf.erb_size ;
+
+ ASSERT( (evrcvbuf.erb_rtn == CompletionRcv) ||
+ (evrcvbuf.erb_rtn == NewSessionCompletionRoutine))
+ Request.RequestNotifyObject = evrcvbuf.erb_rtn ;
+ Request.RequestContext = prcvCont ;
+ Request.Handle.ConnectionContext = pLowerConn->pFileObject ;
+
+ status = TdiVxdReceive( &Request,
+ &usFlags,
+ &cbRcvLength,
+ &prcvCont->ndisBuff ) ;
+ if ( status != TDI_PENDING )
+ {
+ DbgPrint("Reindicate: Error returned from TdiVxdReceive - 0x") ;
+ DbgPrintNum( status ) ;
+ DbgPrint("\r\n") ;
+ CTEIoComplete( prcvCont->pNCB, status, 0 ) ;
+ }
+ else
+ {
+ status = TDI_SUCCESS ;
+ }
+ }
+
+ return status ;
+}
+
+//----------------------------------------------------------------------------
+
+ TDI_STATUS
+TdiConnectHandler (
+ IN PVOID pConnectEventContext,
+ IN int RemoteAddressLength,
+ IN PVOID pRemoteAddress,
+ IN int UserDataLength,
+ IN PVOID pUserData,
+ IN int OptionsLength,
+ IN PVOID pOptions,
+ IN PVOID * AcceptingID,
+ ConnectEventInfo * pEventInfo //OUT CONNECTION_CONTEXT *pConnectionContext
+ )
+/*++
+
+Routine Description:
+
+ This routine is connect event handler. It is invoked when a request for
+ a connection has been received by the provider. NBT accepts the connection
+ on one of its connections in its LowerConnFree list
+
+ Initially a TCP connection is setup with this port. Then a Session Request
+ packet is sent across the connection to indicate the name of the destination
+ process. This packet is received in the RcvHandler.
+
+Arguments:
+
+ pConnectEventContext - the context passed to the transport when this event was setup
+ RemoteAddressLength - the length of the source address (4 bytes for IP)
+ pRemoteAddress - a ptr to the source address
+ UserDataLength - the number of bytes of user data - includes the session Request hdr
+ pUserData - ptr the the user data passed in
+ OptionsLength - number of options to pass in
+ pOptions - ptr to the options
+
+Return Value:
+
+ pConnectionContext - connection context returned to the transport(connection to use)
+
+ NTSTATUS - Status of receive operation
+
+--*/
+
+{
+ NTSTATUS status;
+ tDEVICECONTEXT * pDeviceContext;
+ tLOWERCONNECTION * pLowerConn ;
+ PTDI_CONNECTION_INFO pConnInfo ;
+
+ DbgPrint("TdiConnectHandler: Entered\r\n") ;
+
+ // convert the context value into the device context record ptr
+ pDeviceContext = (tDEVICECONTEXT *)pConnectEventContext;
+
+ ASSERTMSG("Bad Device context passed to the Connection Event Handler",
+ pDeviceContext->Verify == NBT_VERIFY_DEVCONTEXT);
+
+ // call the non-OS specific routine to find a free connection.
+
+ status = ConnectHndlrNotOs(
+ pConnectEventContext,
+ RemoteAddressLength,
+ pRemoteAddress,
+ UserDataLength,
+ pUserData,
+ &pLowerConn );
+
+ if (!NT_SUCCESS(status))
+ {
+ DbgPrint("TdiConnectHandler: NO FREE CONNECTIONS in connect handler\r\n");
+ return STATUS_DATA_NOT_ACCEPTED ;
+ }
+
+ //
+ // Fill in the completion information
+ //
+ pEventInfo->cei_rtn = AcceptCompletionRoutine ;
+ pEventInfo->cei_context = pLowerConn ;
+ pEventInfo->cei_acceptinfo = NULL ;
+ pEventInfo->cei_conninfo = NULL ;
+ *AcceptingID = pLowerConn ; // Connection Context
+
+ return TDI_MORE_PROCESSING ;
+}
+
+//----------------------------------------------------------------------------
+ VOID
+AcceptCompletionRoutine(
+ IN PVOID pContext,
+ IN uint tdistatus,
+ IN uint extra
+ )
+/*++
+
+Routine Description:
+
+ This routine handles the completion of an Accept to the transport.
+
+Arguments:
+
+
+Return Value:
+
+ NTSTATUS - success or not
+
+--*/
+{
+ tLOWERCONNECTION *pLowerConn;
+
+ DbgPrint("AcceptCompletionRoutine: Entered\r\n") ;
+ pLowerConn = (tLOWERCONNECTION *)pContext;
+
+ if (!NT_SUCCESS(tdistatus) &&
+ (pLowerConn->State == NBT_SESSION_INBOUND))
+ {
+ tDEVICECONTEXT *pDeviceContext;
+ DbgPrint("AcceptCompletionRoutine - Error returned: 0x") ;
+ DbgPrintNum( tdistatus ) ;
+ DbgPrint("\r\n") ;
+
+ // the connection setup failed, so put the lower connection block
+ // back on the free list
+ pLowerConn->State = NBT_IDLE;
+ pDeviceContext = pLowerConn->pDeviceContext;
+
+ //
+ // First remove it from pDeviceContext->LowerConnection
+ //
+ RemoveEntryList( &pLowerConn->Linkage ) ;
+ CTEInterlockedDecrementLong(&pLowerConn->RefCount);
+ InsertHeadList(&pDeviceContext->LowerConnFreeHead,
+ &pLowerConn->Linkage);
+
+ }
+}
+
+//----------------------------------------------------------------------------
+ TDI_STATUS
+TdiDisconnectHandler (
+ PVOID EventContext,
+ PVOID ConnectionContext,
+ ULONG DisconnectDataLength,
+ PVOID pDisconnectData,
+ ULONG DisconnectInformationLength,
+ PVOID pDisconnectInformation,
+ ULONG DisconnectIndicators
+ )
+/*++
+
+Routine Description:
+
+ This routine is called when a session is disconnected from a remote
+ machine.
+
+Arguments:
+
+ IN PVOID EventContext,
+ IN PCONNECTION_CONTEXT ConnectionContext,
+ IN ULONG DisconnectDataLength,
+ IN PVOID DisconnectData,
+ IN ULONG DisconnectInformationLength,
+ IN PVOID DisconnectInformation,
+ IN ULONG DisconnectIndicators
+
+Return Value:
+
+ NTSTATUS - Status of event indicator
+
+--*/
+
+{
+
+ TDI_STATUS status ;
+ tDEVICECONTEXT *pDeviceContext;
+
+ DbgPrint("TdiDisconnectHandler: Entered\r\n") ;
+
+ pDeviceContext = (tDEVICECONTEXT *)EventContext;
+ ASSERTMSG("Bad Device context passed to the Disconnect Event Handler",
+ pDeviceContext->Verify == NBT_VERIFY_DEVCONTEXT);
+
+ status = DisconnectHndlrNotOs(
+ EventContext,
+ ConnectionContext,
+ DisconnectDataLength,
+ pDisconnectData,
+ DisconnectInformationLength,
+ pDisconnectInformation,
+ DisconnectIndicators);
+
+ if (!NT_SUCCESS(status))
+ {
+ DbgPrint("NO FREE CONNECTIONS in connect handler\n\r");
+ status = TDI_CONN_REFUSED ; // return(STATUS_DATA_NOT_ACCEPTED);
+ }
+
+ DbgPrint("TdiDisconnectHandler: returning\r\n") ;
+ return status ;
+}
+
+//----------------------------------------------------------------------------
+
+TDI_STATUS
+VxdDisconnectHandler ( // Cleans up Netbios stuff for remote
+ IN PVOID DisconnectEventContext, // disconnects
+ IN PVOID ConnectionContext,
+ IN PVOID DisconnectData,
+ IN ULONG DisconnectInformationLength,
+ IN PVOID pDisconnectInformation,
+ IN ULONG DisconnectIndicators
+ )
+/*++
+
+Routine Description:
+
+ Cleans up open Netbios stuff.
+
+ Note this routine gets called from the NCB hangup completion also.
+
+Arguments:
+
+--*/
+{
+ TDI_STATUS tdistatus ;
+ tCLIENTELE * pClientEle = (tCLIENTELE*) DisconnectEventContext ;
+ tCONNECTELE * pConnEle = (tCONNECTELE*) ConnectionContext ;
+ tDEVICECONTEXT * pDeviceContext = pClientEle->pDeviceContext ;
+ tLOWERCONNECTION * pLowerConn;
+ TDI_REQUEST Request ;
+ NCBERR errNCB ;
+ UCHAR lsn ;
+ BOOL fNotified ;
+
+ DbgPrint("VxdDisconnectHandler Entered \r\n") ;
+ ASSERT( pClientEle->Verify == NBT_VERIFY_CLIENT ) ;
+ ASSERT( (pConnEle->Verify == NBT_VERIFY_CONNECTION) ||
+ (pConnEle->Verify == NBT_VERIFY_CONNECTION_DOWN)) ;
+
+ //
+ // Session is dead, kill off everything
+ //
+
+ if ( errNCB = VxdFindLSN( pDeviceContext,
+ pConnEle,
+ &lsn ))
+ {
+ //
+ // This shouldn't happen but watch for it in case we get in a
+ // weird situation
+ //
+ DbgPrint("VxdDisconnectHandler - Warning: VxdFindLsn failed\r\n") ;
+ }
+
+ REQUIRE( !VxdCompleteSessionNcbs( pDeviceContext,
+ pConnEle )) ;
+
+ pLowerConn = pConnEle->pLowerConnId ;
+ if ( pLowerConn &&
+ (pLowerConn->fOnPartialRcvList == TRUE) &&
+ pLowerConn->StateRcv == PARTIAL_RCV )
+ {
+ RemoveEntryList( &pLowerConn->PartialRcvList ) ;
+ pLowerConn->fOnPartialRcvList = FALSE;
+ InitializeListHead(&pLowerConn->PartialRcvList);
+ }
+
+ //
+ // The close may free the connection so check if the client has been
+ // notified now.
+ //
+ fNotified = !!(pConnEle->Flags & NB_CLIENT_NOTIFIED) ;
+ Request.Handle.ConnectionContext = pConnEle ;
+ tdistatus = NbtCloseConnection( &Request,
+ NULL,
+ pDeviceContext,
+ NULL ) ;
+ if ( tdistatus )
+ {
+ DbgPrint("VxdDisconnectHandler: NbtCloseConnection returned 0x") ;
+ DbgPrintNum( tdistatus ) ; DbgPrint("\r\n") ;
+ }
+
+ tdistatus = NbtDisassociateAddress( &Request ) ;
+ if ( tdistatus )
+ {
+ DbgPrint("VxdDisconnectHandler: NbtDisassociateAddress returned 0x") ;
+ DbgPrintNum( tdistatus ) ; DbgPrint("\r\n") ;
+ }
+
+ if ( !errNCB && fNotified )
+ {
+ REQUIRE( NBUnregister( pDeviceContext,
+ lsn,
+ NB_SESSION )) ;
+ }
+
+ //
+ // If this name has been deleted, check to see if this is the last session,
+ // if so, delete the name
+ //
+ if ( pClientEle->fDeregistered && !ActiveSessions(pClientEle) )
+ {
+ UCHAR NameNum ;
+ if ( VxdFindNameNum( pDeviceContext, pClientEle->pAddress, &NameNum ))
+ {
+ ASSERT( FALSE ) ;
+ return STATUS_UNSUCCESSFUL ;
+ }
+
+ (void) VxdCleanupAddress( pDeviceContext,
+ NULL,
+ pClientEle,
+ NameNum,
+ TRUE ) ;
+ }
+
+ return STATUS_SUCCESS ;
+}
+
+//----------------------------------------------------------------------------
+
+//
+// This structure is the context that is passed to the datagram completion
+// routine when we want TDI to fill in the NCB's buffer
+//
+typedef struct _RCV_DG_COMP_CONTEXT
+{
+ EventRcvBuffer evrcvbuf ;
+ NCB * pncb ;
+ tCLIENTLIST * pClientList ;
+ NDIS_BUFFER ndisRcvBuf ;
+} RCV_DG_COMP_CONTEXT, *PRCV_DG_COMP_CONTEXT ;
+
+ TDI_STATUS
+TdiRcvDatagramHandler(
+ IN PVOID pDgramEventContext,
+ IN int SourceAddressLength,
+ IN PVOID pSourceAddress,
+ IN int OptionsLength,
+ IN PVOID pOptions,
+ IN UINT Flags,
+ IN ULONG BytesIndicated,
+ IN ULONG BytesAvailable,
+ OUT ULONG *pBytesTaken,
+ IN PVOID pData,
+ OUT EventRcvBuffer * * ppBuffer
+ )
+/*++
+
+Routine Description:
+
+ This routine is the receive datagram event indication handler.
+
+ It is called when an Datagram arrives from the network, it will look for a
+ the address with an appropriate read datagram outstanding or a Datagrm
+ Event handler setup.
+
+Arguments:
+
+ pDgramEventContext - Context provided for this event - pab
+ SourceAddressLength, - length of the src address
+ pSourceAddress, - src address
+ OptionsLength, - options length for the receive
+ pOptions, - options
+ BytesIndicated, - number of bytes this indication
+ BytesAvailable, - number of bytes in complete Tsdu
+ pTsdu - pointer to the datagram
+
+
+Return Value:
+
+ *pBytesTaken - number of bytes used
+ *IoRequestPacket - Receive IRP if MORE_PROCESSING_REQUIRED.
+ NTSTATUS - Status of receive operation
+
+--*/
+
+{
+ TDI_STATUS tdistatus ;
+ tDEVICECONTEXT * pDeviceContext = (tDEVICECONTEXT *)pDgramEventContext;
+ tCLIENTLIST * pClientList = NULL ;
+ NCB * pncb = NULL ;
+
+ //
+ // Tell TDI we don't want anything unless we change our minds down below
+ //
+ *ppBuffer = NULL ;
+
+ ASSERTMSG("NBT:Invalid Device Context passed to DgramRcv Handler!!\n",
+ pDeviceContext->Verify == NBT_VERIFY_DEVCONTEXT );
+
+ // call a non-OS specific routine to decide what to do with the datagrams
+ tdistatus = DgramHndlrNotOs(
+ pDgramEventContext,
+ SourceAddressLength,
+ pSourceAddress,
+ OptionsLength,
+ pOptions,
+ 0, // Receive data flags
+ BytesIndicated,
+ BytesAvailable,
+ pBytesTaken,
+ pData,
+ &pncb,
+ &pClientList ) ;
+ if ( !NT_SUCCESS( tdistatus ) )
+ {
+ // fail the request back to the transport provider since we
+ // could not find a receive buffer or receive handler.
+ return(tdistatus);
+
+ }
+ else
+ {
+ PRCV_DG_COMP_CONTEXT prcvdgContext = NULL ;
+
+ prcvdgContext = CTEAllocMem( sizeof( RCV_DG_COMP_CONTEXT ) ) ;
+ if ( !prcvdgContext )
+ return STATUS_DATA_NOT_ACCEPTED ;
+
+ //
+ // ncb_callname filled in by the NotOs event handler
+ //
+
+ prcvdgContext->evrcvbuf.erb_rtn = CompletionRcvDgram ;
+ prcvdgContext->evrcvbuf.erb_size = BytesAvailable - *pBytesTaken ;
+ prcvdgContext->evrcvbuf.erb_context = prcvdgContext ;
+ prcvdgContext->evrcvbuf.erb_buffer = &prcvdgContext->ndisRcvBuf ;
+ prcvdgContext->pncb = pncb ;
+ prcvdgContext->evrcvbuf.erb_flags = NULL ;
+ prcvdgContext->pClientList = pClientList ;
+ InitNDISBuff( prcvdgContext->evrcvbuf.erb_buffer,
+ pncb->ncb_buffer,
+ pncb->ncb_length,
+ NULL ) ;
+ *ppBuffer = &prcvdgContext->evrcvbuf ;
+ return TDI_MORE_PROCESSING ;
+ }
+
+ //
+ // Transport will complete the processing of the request, we don't
+ // want the datagram.
+ //
+
+ return STATUS_DATA_NOT_ACCEPTED;
+}
+
+//----------------------------------------------------------------------------
+ TDI_STATUS
+TdiRcvNameSrvHandler(
+ IN PVOID pDgramEventContext,
+ IN int SourceAddressLength,
+ IN PVOID pSourceAddress,
+ IN int OptionsLength,
+ IN PVOID pOptions,
+ IN UINT Flags,
+ IN ULONG BytesIndicated,
+ IN ULONG BytesAvailable,
+ OUT ULONG *pBytesTaken,
+ IN PVOID pTsdu,
+ OUT EventRcvBuffer * * ppBuffer
+ )
+/*++
+
+Routine Description:
+
+ This routine is the Name Service datagram event indication handler.
+ It gets all datagrams destined for UDP port 137
+
+
+Arguments:
+
+ pDgramEventContext - Context provided for this event - pab
+ SourceAddressLength, - length of the src address
+ pSourceAddress, - src address
+ OptionsLength, - options length for the receive
+ pOptions, - options
+ BytesIndicated, - number of bytes this indication
+ BytesAvailable, - number of bytes in complete Tsdu
+ pTsdu - pointer to the datagram
+
+
+Return Value:
+
+ *pBytesTaken - number of bytes used
+ *IoRequestPacket - Receive IRP if MORE_PROCESSING_REQUIRED.
+ NTSTATUS - Status of receive operation
+
+--*/
+
+{
+ NTSTATUS status;
+ TDI_STATUS tdistatus ;
+ tDEVICECONTEXT *pDeviceContext = (tDEVICECONTEXT *)pDgramEventContext;
+ tNAMEHDR *pNameSrv = (tNAMEHDR *)pTsdu;
+
+ //
+ // No receive buffer
+ //
+ *ppBuffer = NULL ;
+
+ ASSERTMSG("NBT:The Device Context does not have the correct Verification value!!\n",
+ pDeviceContext->Verify == NBT_VERIFY_DEVCONTEXT );
+
+
+ // call a non-OS specific routine to decide what to do with the datagrams
+ status = NameSrvHndlrNotOs(
+ pDeviceContext,
+ pSourceAddress,
+ pNameSrv,
+ BytesIndicated);
+
+ return status ;
+
+ // to keep the compiler from generating warnings...
+ UNREFERENCED_PARAMETER( SourceAddressLength );
+ UNREFERENCED_PARAMETER( BytesIndicated );
+ UNREFERENCED_PARAMETER( BytesAvailable );
+ UNREFERENCED_PARAMETER( pBytesTaken );
+ UNREFERENCED_PARAMETER( pTsdu );
+ UNREFERENCED_PARAMETER( OptionsLength );
+ UNREFERENCED_PARAMETER( pOptions );
+
+}
+
+//----------------------------------------------------------------------------
+ VOID
+CompletionRcvDgram(
+ IN PVOID Context,
+ IN UINT tdistatus,
+ IN UINT RcvdSize
+ )
+/*++
+
+Routine Description:
+
+ This routine completes the receive datagram NCB. If multiple clients
+ were listenning then the largest NCB is used as a template and the
+ rest are completed from it.
+
+
+Arguments:
+
+ Context - Pointer to a RCV_DG_COMP_CONTEXT structure set above
+ tdistatus - Completion status
+ Rcvdsize - Number of bytes copied
+
+--*/
+{
+ PRCV_DG_COMP_CONTEXT prcvdgContext = Context ;
+ NCB * pncb = prcvdgContext->pncb ;
+ tCLIENTLIST * pClientList = prcvdgContext->pClientList;
+ PLIST_ENTRY pHead;
+ PLIST_ENTRY pEntry;
+ NTSTATUS status;
+
+ //
+ // Check to see if our buffer was big enough to get all the data
+ //
+ if ( !tdistatus &&
+ prcvdgContext->evrcvbuf.erb_size > pncb->ncb_length )
+ {
+ tdistatus = STATUS_BUFFER_OVERFLOW ;
+ }
+
+ //
+ // there may be several clients that want to see this datagram so check
+ // the client list to see...
+ //
+ if ( pClientList )
+ {
+ pHead = &pClientList->pAddress->ClientHead;
+ pEntry = pHead->Flink;
+
+#ifdef PROXY_NODE
+ if (!pClientList->fProxy)
+ {
+#endif
+ // *** Client Has posted a receive Buffer, rather than using
+ // *** receive handler - VXD case!
+ // ***
+ while (pEntry != pHead)
+ {
+ tCLIENTELE * pClientEle;
+ NCB * pncbDest ;
+
+ pClientEle = CONTAINING_RECORD(pEntry,tCLIENTELE,Linkage);
+
+ CTEInterlockedIncrementLong(&pClientEle->RefCount);
+
+ if (pClientEle == pClientList->pClientEle)
+ {
+ // this is the client whose buffer we are using - it is
+ // passed up to the client after all other clients
+ // have been processed.
+ //
+ }
+ else
+ if (!IsListEmpty(&pClientEle->RcvDgramHead))
+ {
+ PLIST_ENTRY pRcvEntry;
+ tRCVELE * pRcvEle;
+ TDI_STATUS tdistatusTmp ;
+ UINT BytesToCopy = 0 ;
+
+ pRcvEntry = RemoveHeadList(&pClientEle->RcvDgramHead);
+ pRcvEle = CONTAINING_RECORD(pRcvEntry,tRCVELE,Linkage);
+ pncbDest = (NCB*) pRcvEle->pIrp ;
+ ASSERT( pncbDest ) ;
+
+ //
+ // Only copy the data and call name if we successfully
+ // completed the datagram
+ //
+ if ( !tdistatus || tdistatus == STATUS_BUFFER_OVERFLOW )
+ {
+ BytesToCopy = min( pncbDest->ncb_length, RcvdSize ) ;
+
+ CTEMemCopy( pncbDest->ncb_buffer,
+ pncb->ncb_buffer,
+ BytesToCopy ) ;
+ CTEMemCopy( pncbDest->ncb_callname,
+ pncb->ncb_callname,
+ NETBIOS_NAME_SIZE ) ;
+
+ if ( pncbDest->ncb_length < RcvdSize ||
+ (pncbDest->ncb_length == RcvdSize &&
+ tdistatus == STATUS_BUFFER_OVERFLOW) )
+ {
+ tdistatusTmp = STATUS_BUFFER_OVERFLOW ;
+ }
+ else
+ tdistatusTmp = STATUS_SUCCESS ;
+ }
+ else
+ {
+ tdistatusTmp = tdistatus ;
+ }
+
+ CTEIoComplete( pncbDest, tdistatusTmp, BytesToCopy ) ;
+
+ // free the receive block
+ CTEMemFree((PVOID)pRcvEle);
+
+ }
+
+ pEntry = pEntry->Flink;
+
+ CTEInterlockedDecrementLong(&pClientEle->RefCount);
+
+
+ } // of while(pEntry != pHead)
+
+ //
+ // The address was referenced in DgramRcvNotOs to be sure
+ // it did not disappear until this dgram rcv was done, which
+ // is now.
+ //
+ NbtDereferenceAddress( pClientList->pAddress ) ;
+
+#ifdef PROXY_NODE
+ }
+ else
+ {
+ //
+ // Call the ProxyDoDgramDist
+ //
+ status = ProxyDoDgramDist(
+ (tDGRAMHDR *)pncb->ncb_buffer,
+ RcvdSize,
+ (tNAMEADDR *)pClientList->pAddress, //NameAddr
+ pClientList->pRemoteAddress //device context
+ );
+
+ }
+#endif
+
+
+ //
+ // Free the buffers allocated
+ //
+ if (!pClientList->fProxy)
+ {
+ CTEMemFree(pClientList->pRemoteAddress);
+ }
+ CTEMemFree(Context);
+ }
+
+ //
+ // Finally complete our template NCB (or only NCB if single receive)
+ //
+ CTEIoComplete( pncb, tdistatus, RcvdSize ) ;
+ CTEMemFree( prcvdgContext ) ;
+
+}
+//----------------------------------------------------------------------------
+ TDI_STATUS
+TdiErrorHandler (
+ IN PVOID Context,
+ IN ULONG Status
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called on any error indications passed back from the
+ transport. It implements LAN_STATUS_ALERT.
+
+Arguments:
+
+ Context - Supplies the pfcb for the address.
+
+ Status - Supplies the error.
+
+Return Value:
+
+ NTSTATUS - Status of event indication
+
+--*/
+
+{
+ DbgPrint("Nbt: Error Event HAndler hit unexpectedly\r\n");
+ return TDI_INVALID_REQUEST ;
+}
diff --git a/private/ntos/nbt/vxd/tdiout.c b/private/ntos/nbt/vxd/tdiout.c
new file mode 100644
index 000000000..147bcb785
--- /dev/null
+++ b/private/ntos/nbt/vxd/tdiout.c
@@ -0,0 +1,601 @@
+/*++
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ Tdiout.c
+
+Abstract:
+
+
+ This file represents the TDI interface on the bottom edge of NBT.
+ The procedures herein conform to the TDI I/F spec. and then convert
+ the information to NT specific Irps etc. This implementation can be
+ changed out to run on another OS.
+
+Author:
+
+ Jim Stewart (Jimst) 10-2-92
+
+Revision History:
+
+--*/
+
+#include <nbtprocs.h> // procedure headings
+
+// function prototypes for completion routines used in this file
+VOID
+SendComplete(
+ PVOID pContext,
+ TDI_STATUS tdistatus,
+ UINT cbSentSize
+ );
+VOID
+TcpConnectComplete(
+ PVOID pContext,
+ TDI_STATUS tdistatus,
+ PVOID pv
+ );
+
+VOID DisconnectWaitComplete( PVOID pContext,
+ TDI_STATUS status,
+ ULONG Extra ) ;
+
+void VxdDelayedCallHandler( struct CTEEvent *pEvent, void * pContext ) ;
+
+//----------------------------------------------------------------------------
+ NTSTATUS
+TdiSendDatagram(
+ IN PTDI_REQUEST pRequest,
+ IN PTDI_CONNECTION_INFORMATION pSendDgramInfo,
+ IN ULONG SendLength,
+ OUT PULONG pSentSize,
+ IN tBUFFER * pSendBuffer,
+ IN ULONG SendFlags
+ )
+/*++
+
+Routine Description:
+
+ This routine sends a datagram to the transport
+
+Arguments:
+
+ pSendBuffer - this is really an Mdl in NT land. It must be tacked on
+ the end of the Mdl created for the Nbt datagram header.
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+{
+ TDI_STATUS tdistatus = TDI_SUCCESS ;
+ PTDI_SEND_CONTEXT psendCont = NULL ;
+
+ if ( !GetSendContext( &psendCont ) )
+ {
+ tdistatus = STATUS_INSUFFICIENT_RESOURCES ;
+ goto ErrorExit ;
+ }
+
+ //
+ // Save away the old completion routine and context and replace them
+ // with new ones. The new completion routines will call the old ones
+ // if they are non-NULL and then free the structure.
+ //
+ psendCont->OldRequestNotifyObject = pRequest->RequestNotifyObject ;
+ psendCont->OldContext = pRequest->RequestContext ;
+ psendCont->NewContext = NULL ;
+ pRequest->RequestContext = psendCont ;
+
+ //
+ // Set the send completion callback
+ //
+ pRequest->RequestNotifyObject = SendComplete;
+
+ InitNDISBuff( &psendCont->ndisHdr,
+ pSendBuffer->pDgramHdr,
+ pSendBuffer->HdrLength,
+ &psendCont->ndisData1 ) ;
+
+ InitNDISBuff( &psendCont->ndisData1,
+ pSendBuffer->pBuffer,
+ pSendBuffer->Length,
+ NULL ) ;
+
+ tdistatus = TdiVxdSendDatagram( pRequest,
+ pSendDgramInfo,
+ SendLength,
+ pSentSize,
+ &psendCont->ndisHdr ) ;
+
+ if ( !NT_SUCCESS( tdistatus ) )
+ goto ErrorExit ;
+
+ return tdistatus ;
+
+ErrorExit:
+
+ DbgPrint("TdiSendDatagram ErrorExit: tdistatus= ") ;
+ DbgPrintNum( tdistatus ) ;
+ DbgPrint("\n\r") ;
+
+ //
+ // Call *our* completion routine which frees memory etc.
+ //
+ if ( psendCont && pRequest->RequestNotifyObject )
+ {
+ ((NBT_COMPLETION)pRequest->RequestNotifyObject)(
+ psendCont,
+ tdistatus,
+ 0 ) ;
+
+ return( STATUS_PENDING );
+ }
+
+ return tdistatus ;
+}
+
+//----------------------------------------------------------------------------
+ VOID
+SendComplete(
+ PVOID pContext,
+ TDI_STATUS tdistatus,
+ UINT cbSentSize
+ )
+/*++
+
+Routine Description:
+
+ This routine handles the completion of a datagram/session send to the
+ transport. It must call the client completion routine and free the TDI_SEND_CONTEXT
+ structure pointed at by pContext.
+
+ Note that this routine may also be called if an error is returned from
+ the send call. This is done to localize cleanup.
+
+Arguments:
+
+ pContext - Pointer to a TDI_SEND_CONTEXT
+ tdistatus - Completion status of the TDI request
+ cbSentSize- Bytes taken by TDI
+
+--*/
+{
+ PTDI_SEND_CONTEXT psendCont = pContext ;
+ if ( tdistatus != TDI_SUCCESS )
+ {
+ DbgPrint("SendComplete: TDI Error reported: 0x") ;
+ DbgPrintNum( tdistatus ) ;
+ DbgPrint("\r\n") ;
+ }
+
+ if ( psendCont )
+ {
+ if ( psendCont->OldRequestNotifyObject )
+ {
+ //
+ // This calls the name server datagram completion routine which
+ // in turn will call CTEIoComplete (VxdIoComplete) which will call
+ // the NCB post routine (and fill out the NCB)
+ //
+ psendCont->OldRequestNotifyObject( psendCont->OldContext,
+ tdistatus,
+ cbSentSize ) ;
+ }
+
+ FreeSendContext( psendCont ) ;
+ }
+}
+
+//----------------------------------------------------------------------------
+ NTSTATUS
+TdiConnect(
+ IN PTDI_REQUEST pRequest,
+ IN ULONG lTimeout,
+ IN PTDI_CONNECTION_INFORMATION pSendInfo,
+ OUT PVOID pIrp //IN PTDI_CONNECTION_INFORMATION pReturnInfo
+ )
+/*++
+
+Routine Description:
+
+ This routine sends a connect request to the tranport provider, to setup
+ a connection to the other side...
+
+Arguments:
+
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+{
+ TDI_STATUS status ;
+ DbgPrint("TdiConnect Entered\n\r") ;
+ status = TdiVxdConnect( pRequest,
+ (PVOID)lTimeout,
+ pSendInfo,
+ NULL ) ; // pReturnInfo) ;
+
+ if ( !NT_SUCCESS( status ) )
+ {
+ DbgPrint("TdiVxdConnect: Returned error " ) ;
+ DbgPrintNum( status ) ;
+ DbgPrint("\n\r") ;
+
+ //
+ // call the completion routine with this status
+ //
+ //
+ (*((NBT_COMPLETION)pRequest->RequestNotifyObject))
+ ((PVOID)pRequest->RequestContext,
+ status,
+ 0L);
+ return STATUS_PENDING;
+ }
+ else
+ {
+ DbgPrint("TdiVxdConnect - Connection ID: 0x") ;
+ DbgPrintNum( (ULONG) pRequest->Handle.ConnectionContext ) ; DbgPrint("\r\n") ;
+ }
+
+ return status ;
+}
+
+
+//----------------------------------------------------------------------------
+ NTSTATUS
+TdiDisconnect(
+ IN PTDI_REQUEST pRequest,
+ IN PVOID lTimeout,
+ IN ULONG Flags,
+ IN PTDI_CONNECTION_INFORMATION pSendInfo,
+ IN PCTE_IRP pClientIrp,
+ IN BOOLEAN Wait
+ )
+/*++
+
+Routine Description:
+
+ This routine sends a connect request to the tranport provider, to setup
+ a connection to the other side...
+
+Arguments:
+
+ Wait is only used for NT (used in case when deleting address object
+ with open connections, which Vxd doesn't allow due to Netbios spec).
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+{
+ TDI_STATUS status ;
+ DbgPrint("TdiDisconnect Entered\n\r") ;
+ DbgPrint("TdiDisconnect - Disconnecting Connection ID: 0x") ;
+ DbgPrintNum( (ULONG) pRequest->Handle.ConnectionContext ) ; DbgPrint("\r\n") ;
+
+ ASSERT( Flags <= 0xffff ) ;
+ status = TdiVxdDisconnect( pRequest,
+ lTimeout,
+ (ushort) Flags,
+ pSendInfo,
+ NULL ) ;
+
+ if ( !NT_SUCCESS( status ) )
+ {
+ DbgPrint("TdiVxdConnect: Returned error " ) ;
+ DbgPrintNum( status ) ;
+ DbgPrint("\n\r") ;
+ }
+
+ return status ;
+}
+
+//----------------------------------------------------------------------------
+ NTSTATUS
+TdiSend(
+ IN PTDI_REQUEST pRequest,
+ IN USHORT sFlags,
+ IN ULONG SendLength,
+ OUT PULONG pSentSize,
+ IN tBUFFER *pBuff,
+ IN ULONG SendFlags
+ )
+/*++
+
+Routine Description:
+
+ This routine sends a packet to the transport on a TCP connection
+
+ If this is a chain send (SendFlags & CHAIN_SEND_FLAG) then pBuff will
+ point to a tBUFFERCHAINSEND (which contains a tBUFFER as its first element).
+
+Arguments:
+
+
+Return Value:
+
+ The function value is the status of the operation.
+
+--*/
+{
+ TDI_STATUS tdistatus = TDI_SUCCESS ;
+ PTDI_SEND_CONTEXT psendCont = NULL ;
+ tBUFFERCHAINSEND * pSendBuff = (tBUFFERCHAINSEND*) pBuff ;
+ PNDIS_BUFFER pndis2 = NULL ;
+ PNDIS_BUFFER pndis1 = NULL ;
+ DbgPrint("TdiSend Entered - sending 0x") ; DbgPrintNum( SendLength ) ;
+ DbgPrint(" bytes\r\n") ;
+
+ if ( !GetSendContext( &psendCont ))
+ {
+ tdistatus = STATUS_INSUFFICIENT_RESOURCES ;
+ if ( pRequest->RequestNotifyObject )
+ {
+ ((NBT_COMPLETION)pRequest->RequestNotifyObject)(
+ pRequest->RequestContext,
+ tdistatus,
+ 0 ) ;
+ }
+ return tdistatus ;
+ }
+
+ //
+ // Save away the old completion routine and context and replace them
+ // with new ones. The new completion routines will call the old ones
+ // if they are non-NULL and then free the structure.
+ //
+ psendCont->OldRequestNotifyObject = pRequest->RequestNotifyObject ;
+ psendCont->OldContext = pRequest->RequestContext ;
+ psendCont->NewContext = NULL ;
+ pRequest->RequestContext = psendCont ;
+
+ //
+ // Set the send completion callback
+ //
+ pRequest->RequestNotifyObject = SendComplete ;
+
+ //
+ // Build the ndis buffer chain (Header and data)
+ //
+
+ if ( (SendFlags & CHAIN_SEND_FLAG) && pSendBuff->Length2 )
+ {
+ InitNDISBuff( &psendCont->ndisData2,
+ pSendBuff->pBuffer2,
+ pSendBuff->Length2,
+ NULL ) ;
+ pndis2 = &psendCont->ndisData2 ;
+ }
+
+ if ( pSendBuff->tBuff.Length && (SendLength > pSendBuff->tBuff.HdrLength) )
+ {
+ InitNDISBuff( &psendCont->ndisData1,
+ pSendBuff->tBuff.pBuffer,
+ pSendBuff->tBuff.Length,
+ pndis2 ) ;
+ pndis1 = &psendCont->ndisData1 ;
+ }
+
+ InitNDISBuff( &psendCont->ndisHdr,
+ pSendBuff->tBuff.pDgramHdr,
+ pSendBuff->tBuff.HdrLength,
+ pndis1 ) ;
+
+ tdistatus = TdiVxdSend( pRequest,
+ sFlags,
+ SendLength,
+ &psendCont->ndisHdr ) ;
+
+ if ( !NT_SUCCESS( tdistatus ) )
+ goto ErrorExit ;
+ else
+ *pSentSize = SendLength ;
+
+ return tdistatus ;
+
+ErrorExit:
+ //
+ // Call *our* completion routine which frees memory etc.
+ //
+ if ( psendCont && pRequest->RequestNotifyObject )
+ {
+ ((NBT_COMPLETION)pRequest->RequestNotifyObject)(
+ psendCont,
+ tdistatus,
+ 0 ) ;
+ }
+
+ DbgPrint("TdiSend: returning ") ;
+ DbgPrintNum( tdistatus ) ;
+ DbgPrint("\n\r") ;
+ return tdistatus ;
+}
+
+/*******************************************************************
+
+ NAME: VxdScheduleDelayedCall
+
+ SYNOPSIS: Schedules a callback at some later time
+
+ ENTRY: pClientContext - Context to pass callback
+ CallBackRoutine - Routine to call
+
+ RETURNS: STATUS_PENDING if successfully scheduled
+
+ NOTES: This is aliased to CTEQueueForNonDispProcessing.
+
+ The memory for the DCC is freed by the application
+
+ HISTORY:
+ Johnl 2-Sep-1993 Created
+
+********************************************************************/
+
+NTSTATUS VxdScheduleDelayedCall( tDGRAM_SEND_TRACKING * pTracker,
+ PVOID pClientContext,
+ PVOID ClientCompletion,
+ PVOID CallBackRoutine,
+ tDEVICECONTEXT *pDeviceContext )
+{
+ CTELockHandle OldIrq;
+ PDELAYED_CALL_CONTEXT pDCC = CTEAllocMem( sizeof( DELAYED_CALL_CONTEXT )) ;
+
+ if ( !pDCC )
+ return STATUS_INSUFFICIENT_RESOURCES ;
+
+ ASSERT( CallBackRoutine != NULL ) ;
+
+ pDCC->dc_WIC.pTracker = pTracker ;
+ pDCC->dc_WIC.pClientContext = pClientContext ;
+ pDCC->dc_WIC.ClientCompletion = ClientCompletion ;
+ pDCC->dc_Callback = CallBackRoutine ;
+ pDCC->pDeviceContext = pDeviceContext;
+
+ //
+ // put this event on the deviceContext queue if we know the devicecontext
+ // otherwise, on the nbtconfig queue. This allows us to cancel the event
+ // later if we wish to (e.g. adapter goes away in pnp, or lease expires)
+ // if the adapter is marked as going down, don't schedule an event but
+ // execute it synchronously.
+ //
+ if (pDeviceContext)
+ {
+ ASSERT( pDeviceContext->Verify == NBT_VERIFY_DEVCONTEXT );
+
+ if (!pDeviceContext->fDeviceUp)
+ {
+ pDCC->dc_Callback( pDCC ) ;
+
+ DbgPrint("VxdScheduleDelayedCall: device going down,executing now\r\n") ;
+ return( STATUS_SUCCESS );
+ }
+ else
+ {
+ CTESpinLock(pDeviceContext,OldIrq);
+ InsertTailList(&pDeviceContext->DelayedEvents,&pDCC->Linkage);
+ CTESpinFree(pDeviceContext,OldIrq);
+ }
+ }
+ else
+ {
+ CTESpinLock(&NbtConfig,OldIrq);
+ InsertTailList(&NbtConfig.DelayedEvents,&pDCC->Linkage);
+ CTESpinFree(&NbtConfig,OldIrq);
+ }
+
+ CTEInitEvent( &pDCC->dc_event, VxdDelayedCallHandler ) ;
+
+ CTEScheduleEvent( &pDCC->dc_event, pDCC) ;
+
+ return STATUS_PENDING ;
+}
+
+
+void VxdDelayedCallHandler( struct CTEEvent *pEvent, void * pContext )
+{
+ PDELAYED_CALL_CONTEXT pDCC = pContext ;
+ CTELockHandle OldIrq;
+ tDEVICECONTEXT *pDeviceContext;
+
+
+ ASSERT( pDCC != NULL && pDCC->dc_Callback != NULL ) ;
+
+ pDeviceContext = pDCC->pDeviceContext;
+
+ if (pDeviceContext)
+ {
+ ASSERT( pDeviceContext->Verify == NBT_VERIFY_DEVCONTEXT );
+ CTESpinLock(pDeviceContext,OldIrq);
+ RemoveEntryList(&pDCC->Linkage);
+ CTESpinFree(pDeviceContext,OldIrq);
+ }
+ else
+ {
+ CTESpinLock(&NbtConfig.JointLock,OldIrq);
+ RemoveEntryList(&pDCC->Linkage);
+ CTESpinFree(&NbtConfig.JointLock,OldIrq);
+ }
+
+ pDCC->dc_Callback( pDCC ) ;
+}
+
+
+/*******************************************************************
+
+ NAME: CancelAllDelayedEvents
+
+ SYNOPSIS: Since the device (or the entire vxd!) is going away,
+ cancel all the events that were queued to be scheduled
+ later. If a particular device context is going away (but
+ not the entire system) then execute all those events
+ synchronously.
+
+ ENTRY: pDeviceContext - the device context that's going away
+ NULL if the vxd is getting unloaded
+
+ RETURNS: TRUE if at least one event present and was cancelled
+ FALSE if there were no events queued.
+
+ HISTORY:
+ Koti Jan. 9, 95
+
+********************************************************************/
+
+BOOL
+CancelAllDelayedEvents( tDEVICECONTEXT *pDeviceContext )
+{
+
+ LIST_ENTRY *pHead;
+ LIST_ENTRY *pEntry;
+ PDELAYED_CALL_CONTEXT pDCC;
+ CTELockHandle OldIrq;
+ BOOL fAtLeastOne=FALSE;
+
+
+ CTESpinLock(&NbtConfig.JointLock,OldIrq);
+
+ if (pDeviceContext)
+ pHead = &pDeviceContext->DelayedEvents;
+ else
+ pHead = &NbtConfig.DelayedEvents;
+
+ pEntry = pHead->Flink;
+
+ while (pEntry != pHead)
+ {
+ pDCC = CONTAINING_RECORD(pEntry,DELAYED_CALL_CONTEXT,Linkage);
+ pEntry = pEntry->Flink;
+
+ RemoveEntryList(&pDCC->Linkage);
+
+ CTESpinFree(&NbtConfig.JointLock,OldIrq);
+
+ CTECancelEvent( &pDCC->dc_event );
+
+ //
+ // if only one device context is going away, execute the event now
+ //
+ if (pDeviceContext)
+ {
+ pDCC->dc_Callback( pDCC ) ;
+ }
+ CTESpinLock(&NbtConfig.JointLock,OldIrq);
+
+ fAtLeastOne = TRUE;
+ }
+
+ CTESpinFree(&NbtConfig.JointLock,OldIrq);
+
+ ASSERT( IsListEmpty( pHead ) );
+
+ return( fAtLeastOne );
+}
+
+
diff --git a/private/ntos/nbt/vxd/util.c b/private/ntos/nbt/vxd/util.c
new file mode 100644
index 000000000..b7060052e
--- /dev/null
+++ b/private/ntos/nbt/vxd/util.c
@@ -0,0 +1,192 @@
+//
+//
+// UTIL.C
+//
+// This file contains various utility procedures that are VxD specific. These
+// are called by other VxD specific routines.
+
+#include "nbtprocs.h"
+
+NTSTATUS
+ConvertToIntegerArray(
+ char *pszString,
+ UNALIGNED UCHAR *pArray,
+ int *piNumParts) ;
+
+NTSTATUS
+NbtCreateAddressObjects(
+ IN ULONG IPAddr,
+ IN ULONG IPMask,
+ OUT tDEVICECONTEXT *pDeviceContext);
+
+char * strrchr( const char * pch, int c );
+
+//******************* Pageable Routine Declarations ****************
+#ifdef ALLOC_PRAGMA
+#pragma CTEMakePageable(PAGE, NbtCreateAddressObjects)
+#pragma CTEMakePageable(INIT, strrchr)
+#endif
+//******************* Pageable Routine Declarations ****************
+
+#pragma BEGIN_INIT
+
+/*******************************************************************
+
+ NAME: strrchr
+
+ SYNOPSIS: Vxd-land doesn't have a strrchr runtime function so
+ roll our own.
+
+ ENTRY: pch - Pointer to string to search
+ c - Character to search for
+
+ RETURNS: Found position or NULL
+
+ HISTORY:
+ Johnl 31-Aug-1993 Created
+
+********************************************************************/
+
+char * strrchr( const char * pch, int c )
+{
+ char * pchFound = NULL ;
+
+ while ( *pch != '\0' )
+ {
+ if ( *pch == c )
+ pchFound = (char *)pch ;
+
+ //
+ // If double byte do this twice
+ //
+ pch++ ;
+ }
+
+ return pchFound ;
+}
+
+#pragma END_INIT
+
+
+//----------------------------------------------------------------------------
+ NTSTATUS
+NbtCreateAddressObjects(
+ IN ULONG IPAddr,
+ IN ULONG IPMask,
+ OUT tDEVICECONTEXT *pDeviceContext)
+
+/*++
+
+Routine Description:
+
+ This routine gets the ip address and subnet mask out of the registry
+ to calcuate the broadcast address. It then creates the address objects
+ with the transport.
+
+Arguments:
+
+ pucRegistryPath - path to NBT config info in registry
+ pucBindName - name of the service to bind to.
+ pDeviceContext - ptr to the device context... place to store IP addr
+ and Broadcast address permanently
+
+Return Value:
+
+ none
+
+--*/
+
+{
+ NTSTATUS status ;
+ pDeviceContext->IpAddress = IPAddr ;
+ pDeviceContext->SubnetMask = IPMask ;
+
+ CTEPagedCode();
+
+ if ( NbtConfig.UseRegistryBcastAddr )
+ {
+ pDeviceContext->BroadcastAddress = NbtConfig.RegistryBcastAddr ;
+ }
+ else
+ {
+ pDeviceContext->BroadcastAddress = (IPMask & IPAddr) | (~IPMask & -1);
+ }
+
+ // now create the address objects.
+
+ // open the Ip Address for inbound Datagrams.
+ status = NbtTdiOpenAddress(
+ NULL, // &pDeviceContext->hDgram,
+ NULL, // &pDeviceContext->pDgramDeviceObject,
+ &pDeviceContext->pDgramFileObject,
+ pDeviceContext,
+ (USHORT)NBT_DATAGRAM_UDP_PORT,
+ IPAddr, //IP_ANY_ADDRESS,
+ 0); // not a TCP port
+
+ if (NT_SUCCESS(status))
+ {
+ // open the Nameservice UDP port ..
+ status = NbtTdiOpenAddress(
+ NULL, //&pDeviceContext->hNameServer,
+ NULL, //&pDeviceContext->pNameServerDeviceObject,
+ &pDeviceContext->pNameServerFileObject,
+ pDeviceContext,
+ (USHORT)NBT_NAMESERVICE_UDP_PORT,
+ IPAddr,
+ 0); // not a TCP port
+
+ if (NT_SUCCESS(status))
+ {
+ KdPrint(("Nbt: Open Session port %X\n",pDeviceContext));
+ // Open the TCP port for Session Services
+ status = NbtTdiOpenAddress(
+ NULL, //&pDeviceContext->hSession,
+ NULL, //&pDeviceContext->pSessionDeviceObject,
+ &pDeviceContext->pSessionFileObject,
+ pDeviceContext,
+ (USHORT)NBT_SESSION_TCP_PORT,
+ IPAddr,
+ TCP_FLAG | SESSION_FLAG); // TCP port
+
+ if (NT_SUCCESS(status))
+ {
+ //
+ // Open the broadcast address ("*\0\0...") for this device.
+ //
+ TDI_REQUEST tdiRequest ;
+ TDI_ADDRESS_NETBIOS tdiaddr ;
+
+ tdiaddr.NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_QUICK_GROUP ;
+ CTEZeroMemory( tdiaddr.NetbiosName, NETBIOS_NAME_SIZE ) ;
+ tdiaddr.NetbiosName[0] = '*' ;
+
+ status = NbtOpenAddress( &tdiRequest,
+ &tdiaddr,
+ pDeviceContext->BroadcastAddress,
+ NULL, // Security descriptor
+ pDeviceContext,
+ NULL ) ;
+ if (NT_SUCCESS(status))
+ {
+ pDeviceContext->hBroadcastAddress = tdiRequest.Handle.AddressHandle ;
+ return(status);
+ }
+
+ DbgPrint("Unable to Open broadcast name\r\n");
+ ASSERT(0);
+ CloseAddress( (HANDLE) pDeviceContext->pSessionFileObject ) ;
+ }
+
+ KdPrint(("Unable to Open Session address with TDI, status = %X\n",status));
+ CloseAddress( (HANDLE) pDeviceContext->pNameServerFileObject ) ;
+
+ }
+ KdPrint(("Unable to Open NameServer port with TDI, status = %X\n",status));
+ CloseAddress( (HANDLE) pDeviceContext->pDgramFileObject ) ;
+ }
+
+ return(status);
+}
+
+
diff --git a/private/ntos/nbt/vxd/vfirst.asm b/private/ntos/nbt/vxd/vfirst.asm
new file mode 100644
index 000000000..c2c777f44
--- /dev/null
+++ b/private/ntos/nbt/vxd/vfirst.asm
@@ -0,0 +1,79 @@
+;*****************************************************************;
+;** Copyright(c) Microsoft Corp., 1990-1992 **;
+;*****************************************************************;
+ page ,132 ; :ts=8
+ TITLE wventry - WinVirtualRdr entrypoint
+
+;*** vfirst - First module in VxDRdr
+;
+
+.386p
+
+;* We don't use the .MODEL statement because it wants to declare
+; _DATA and DGROUP for us; which is a no-no because windows is going to.
+
+
+;* 32 Bit locked code
+_LTEXT SEGMENT DWORD USE32 PUBLIC 'LCODE'
+_LTEXT ENDS
+
+;* Contains 32 Bit locked data
+_LDATA SEGMENT DWORD PUBLIC 'LCODE'
+_LDATA ENDS
+
+_DATA SEGMENT DWORD PUBLIC 'LCODE'
+_DATA ENDS
+
+CONST SEGMENT DWORD PUBLIC 'LCODE'
+CONST ENDS
+
+_BSSbeg SEGMENT DWORD PUBLIC 'LCODE'
+ public _BSSBegin
+_BSSBegin equ this byte
+_BSSbeg ENDS
+
+_BSS SEGMENT DWORD PUBLIC 'LCODE'
+_BSS ENDS
+
+c_common SEGMENT DWORD PUBLIC 'LCODE'
+c_common ENDS
+
+_BSSend SEGMENT DWORD PUBLIC 'LCODE'
+ public _BSSDataEnd
+_BSSDataEnd dd ? ; This gaurantees that we can zero out
+ ; BSS in dwords with out stomping anything
+_BSSend ENDS
+
+;* 32 Bit initialization code
+_ITEXT SEGMENT DWORD USE32 PUBLIC 'ICODE'
+_ITEXT ENDS
+
+;* Contains 32 Bit initialization data
+_IDATA SEGMENT DWORD PUBLIC 'ICODE'
+_IDATA ENDS
+
+;* 32 Bit code
+_TEXT SEGMENT DWORD USE32 PUBLIC 'LCODE'
+_TEXT ENDS
+
+;* Contains 32 Bit data
+;;_DATA SEGMENT DWORD PUBLIC 'PCODE'
+;;_DATA ENDS
+
+;* Real Mode initialization code/data for devices
+_RCODE SEGMENT WORD USE16 PUBLIC 'RCODE'
+_RCODE ENDS
+
+_LGROUP GROUP _LTEXT, _TEXT, _LDATA, _DATA, _BSSbeg, _BSS, c_common, _BSSend
+;;DGROUP GROUP _DATA, CONST, _BSSbeg, _BSS, c_common, _BSSend
+;;DGROUP GROUP _DATA, CONST, _BSSbeg, _BSS, _BSSend
+
+_IGROUP GROUP _ITEXT, _IDATA
+
+;;_PGROUP GROUP _TEXT, _DATA
+;;_PGROUP GROUP _TEXT
+
+;;include segments.inc
+;;include vmm.inc
+
+ end
diff --git a/private/ntos/nbt/vxd/vnbt.rcv b/private/ntos/nbt/vxd/vnbt.rcv
new file mode 100644
index 000000000..aed0293f9
--- /dev/null
+++ b/private/ntos/nbt/vxd/vnbt.rcv
@@ -0,0 +1,15 @@
+/********************************************************************/
+/* VNBT.RCV */
+/* Version control data */
+/********************************************************************/
+#include <version.h>
+#include <netvxd.h>
+
+#define VER_FILETYPE VFT_VXD
+#define VER_FILESUBTYPE VNBT_Device_ID
+#define VER_FILEDESCRIPTION_STR "VNBT VxD Driver"
+#define VER_INTERNALNAME_STR "VNBT"
+#define VER_LEGALCOPYRIGHT_YEARS "1993-1995"
+#define VER_ORIGINALFILENAME_STR "VNBT.386"
+
+#include <common.ver>
diff --git a/private/ntos/nbt/vxd/vnbtd.asm b/private/ntos/nbt/vxd/vnbtd.asm
new file mode 100644
index 000000000..502f362f1
--- /dev/null
+++ b/private/ntos/nbt/vxd/vnbtd.asm
@@ -0,0 +1,993 @@
+;*****************************************************************;
+;** Copyright(c) Microsoft Corp., 1988-1993 **;
+;*****************************************************************;
+;:ts=8
+ TITLE VNBT - Netbios on TCP/IP vxd
+.XLIST
+;*** VNBT -- NetBios on TCP/IP VxD
+;
+; This module contains the device header for the NBT VxD driver.
+;
+ .386p
+ include vmm.inc
+ifdef CHICAGO
+ include ndis.inc
+endif ;; CHICAGO
+ include dosmgr.inc
+ include netvxd.inc
+IFDEF CHICAGO
+ include configmg.inc
+ENDIF
+ include vwin32.inc
+ include vdhcp.inc
+ include debug.inc
+ include vtdi.inc
+
+ Create_VNBT_Service_Table EQU True
+ifdef CHICAGO
+ include vnbt.inc
+else ;; CHICAGO
+ include vnbtd.inc
+endif ;; CHICAGO
+ include vnetbios.inc
+
+ include pageable.inc
+.LIST
+
+Declare_Virtual_Device VNBT,3,0,VNBT_Control,VNBT_Device_ID, \
+ VNBT_Init_Order,VNBT_Api_Handler,VNBT_Api_Handler
+
+
+VxD_DATA_SEG
+VxD_DATA_ENDS
+
+EXTRN __VxdMapSegmentOffsetToFlat:near ; from client.asm
+ifndef CHICAGO
+EXTRN _BSSBegin:DWORD
+EXTRN _BSSDataEnd:DWORD
+endif ;; CHICAGO
+EXTRN _TdiDispatch:DWORD
+
+EXTRN _PostInit_Proc:NEAR
+EXTRN _VxdApiWorker:NEAR
+
+ifndef CHICAGO
+EXTRN _VNBT_NCB_X@20:NEAR
+endif ;; CHICAGO
+
+EXTRN _GetDhcpOption:NEAR
+
+
+VxD_ICODE_SEG
+
+EXTRN _Init:NEAR
+
+MSTCP db 'MSTCP',0 ; Protocol this driver sits on (this will have
+ ; to be changed to get it from an .ini file)
+IFDEF CHICAGO
+bInitialized db 0 ; 0 means not initialized, 1 means we've entered
+ ; the initialization, and 2 means we've left init
+bSuccessInit db 0 ; 0 means initialization failed and all subsequent
+ ; initializations should fail
+ENDIF
+
+NBTSectionName db 'NBT',0 ; Section where parameters are stored
+
+;****************************************************************************
+;** VNBT_Device_Init - VNBT device initialization service.
+;
+; The VNBT device initialization routine. Before calling anything
+; we need to zero out the BSS data area.
+;
+;
+; Entry: (EBX) - System VM Handle
+; (EBP) - System Client Regs structure.
+;
+; Exit: 'CY' clear if we init. successfully.
+; 'CY' set if we've failed.
+;
+BeginProc VNBT_Device_Init
+
+IFDEF CHICAGO
+ ;
+ ; Chicago calls us at both dynamic and static init, so only process
+ ; once
+ ;
+ cmp bInitialized, 2 ; 2 means we've already completed initialization
+ jne Init_Continue
+ clc ; Assume success (is checked below)
+ jmp Init_Exit
+
+Init_Continue:
+ mov bInitialized, 1
+ENDIF
+
+ifndef CHICAGO
+ mov edi, OFFSET32 _BSSBegin
+ mov ecx, OFFSET32 _BSSDataEnd
+ sub ecx, edi
+ shr ecx, 2
+ sub eax, eax
+ cld
+ rep stosd
+endif ;; CHICAGO
+
+ VxDcall VTDI_Get_Version
+ jc Init_Exit ; Get out if VTDI is not installed
+
+ ;
+ ; Get the TDI Vxd dispatch table for "MSTCP" to initialize the TDI
+ ; dispatch table (which will be needed by some of our
+ ; initialization stuff)
+ ;
+ mov eax, OFFSET32 MSTCP
+ push eax
+ VxDcall VTDI_Get_Info
+ add esp, 4
+ cmp eax, 0 ; eax contains NULL or the pointer to the table
+ jne NoError
+
+ Debug_Out "VNBT_Device_Init - VTDI_Get_Info failed!"
+ stc ; Set the carry
+ jmp Init_Exit
+
+NoError:
+ mov _TdiDispatch, eax
+
+ ;
+ ; Initialize the rest of the driver
+ ;
+ call _Init
+ cmp eax, 1 ; Set 'CY' appropriately.
+
+Init_Exit:
+
+IFDEF CHICAGO
+ jc Exit2 ; Failed init, leave bSuccessInit 0
+
+ ;
+ ; If first time through and success, indicate successful initialization
+ ;
+ cmp bInitialized, 1
+ je SetInitFlag
+
+ ;
+ ; We've already been initialized once, was it successful?
+ ;
+ cmp bSuccessInit, 1
+ clc ; test clears the carry so assume success
+ je Exit2
+
+ stc ; Set the carry since we failed init. last time
+ jmp Exit2
+
+SetInitFlag:
+ clc
+ mov bSuccessInit, 1
+
+Exit2:
+ mov bInitialized, 2
+ENDIF
+ ret
+
+
+
+
+EndProc VNBT_Device_Init
+
+
+VxD_ICODE_ENDS
+
+NBT_PAGEABLE_CODE_SEG
+
+ifdef CHICAGO
+_NdisOpenProtocolConfiguration@12 PROC NEAR PUBLIC
+ VxDJmp NdisOpenProtocolConfiguration
+_NdisOpenProtocolConfiguration@12 ENDP
+
+_NdisCloseConfiguration@4 PROC NEAR PUBLIC
+ VxDJmp NdisCloseConfiguration
+_NdisCloseConfiguration@4 ENDP
+
+_NdisReadConfiguration@20 PROC NEAR PUBLIC
+ VxDJmp NdisReadConfiguration
+_NdisReadConfiguration@20 ENDP
+endif ;; CHICAGO
+
+NBT_PAGEABLE_CODE_ENDS
+
+VxD_CODE_SEG
+;****************************************************************************
+;* NCB_Handler
+;
+; Called by VNetBios when NCBs need to be submitted to this driver
+;
+; ENTRY:
+; EBX = NCB being submitted
+;
+; EXIT:
+; AL - return code
+;
+BeginProc NCB_Handler
+
+ ;
+ ; In the master portion of the mif tests, after hitting ctrl-c during
+ ; the attempt to synchronize, a wait add group name NCB is
+ ; submitted with interrupts disabled. The CTE timer event handler
+ ; checks this and schedules an event for when they are re-enabled,
+ ; however since it's a wait NCB, we deadlock in VNBT_NCB_X's block.
+ ;
+ ; Make sure interrupts are enabled.
+ ; BUGBUG - Why were we called with ints disabled?
+ ;
+ ;VMMcall Enable_VM_Ints
+
+ xor eax, eax ; second parm of VNBT_NCB_X is unused when
+
+ifndef CHICAGO
+
+ push eax
+ push eax
+ push eax ; called from here, but is used (e.g.nbtstat)
+ push eax
+ push ebx
+ call _VNBT_NCB_X@20 ; when VNBT_NCB_X is called directly
+
+else ;; CHICAGO
+if 0
+;
+; As of 08-Feb-1996 there is a bug in "vmm.h" where this doesn't
+; work properly, with the result being a misaligned stack pointer.
+;
+ VxDCall VNBT_NCB_X, <ebx, eax, eax, eax, eax>
+else ;; 0
+ push eax
+ push eax
+ push eax
+ push eax
+ push ebx
+ VxDCall VNBT_NCB_X
+endif ;; 0
+endif ;; CHICAGO
+
+ ret
+EndProc NCB_Handler
+
+;****************************************************************************
+;** _DhcpQueryOption - Queries a DHCP option
+;
+; Stub callout to the Dhcp driver
+;
+; Entry: [ESP+4] - IP Address of interest
+; [ESP+8] - DHCP Option number
+; [ESP+12]- Pointer to buffer
+; [ESP+16]- Pointer to buffer size
+;
+;
+
+BeginProc _DhcpQueryOption
+
+ VxdCall VDHCP_Get_Version
+ jnc DQI_Installed
+
+ mov eax, 26 ; DHCP not installed, return invalid param
+ ret
+
+DQI_Installed:
+ push ebp
+ mov ebp,esp
+
+ mov eax, [ebp+20] ; Buff size
+ push eax
+ mov eax, [ebp+16] ; Buff
+ push eax
+ mov eax, [ebp+12] ; Option
+ push eax
+ mov eax, [ebp+8] ; IP Address
+ push eax
+
+ VxdCall VDHCP_Query_Option
+
+ add esp, 16
+
+ pop ebp
+ ret
+
+EndProc _DhcpQueryOption
+
+;****************************************************************************
+;** VNBT_Get_Version - VNBT get version service
+;
+; Called by using devices to make sure the VNBT driver
+; is present. Also returns the version of the VNBT driver.
+;
+; Entry: Nothing
+;
+; Exit: On success, 'CY' is clear, and
+; AH - Major version # of driver.
+; AL - Minor version #
+;
+; On failure, 'CY' is set.
+;
+; Uses: AX
+;
+BeginProc VNBT_Get_Version, SERVICE
+
+ mov ax, VNBT_VERSION
+ clc
+ ret
+
+EndProc VNBT_Get_Version
+
+VxD_CODE_ENDS
+NBT_PAGEABLE_CODE_SEG
+
+;****************************************************************************
+;** VNBT_Device_PostProc - do postprocessing
+;
+; Called by the sytem when all the other stuff (in our case, rdr) is
+; loaded. At this we read the lmhosts file, so that any #INCLUDE with
+; UNC names in it will work.
+; This routine can also be used for other stuff, but for now only lmhosts
+; stuff.
+;
+BeginProc VNBT_Device_PostProc
+
+ call _PostInit_Proc
+ clc
+ ret
+
+EndProc VNBT_Device_PostProc
+
+NBT_PAGEABLE_CODE_ENDS
+VxD_CODE_SEG
+
+;****************************************************************************
+;** VNBT_Control - VNBT device control procedure
+;
+; This procedure dispatches VxD messages to the appropriate handler.
+;
+; Entry: EBX - VM handle
+; (EBP) - Client reg structure
+;
+; Exit: 'NC' is success, 'CY' on failure
+;
+; Uses: All
+;
+BeginProc VNBT_Control
+
+ Control_Dispatch Device_Init, VNBT_Device_Init
+ Control_Dispatch Sys_Dynamic_Device_Init, VNBT_Device_Init
+ Control_Dispatch Sys_Vm_Init, VNBT_Device_PostProc
+IFDEF CHICAGO
+ Control_Dispatch W32_DEVICEIOCONTROL, VNBT_DeviceIoControl
+ENDIF
+
+ clc
+ ret
+
+EndProc VNBT_Control
+
+IFDEF CHICAGO
+;*******************************************************************
+;** VNBT_DeviceIoControl
+;
+; Dispatch routine for VxD services invoked via the Win32
+; DeviceIoControl API.
+;
+; Entry: (ESI) - Points to DIOCParams structure (see VWIN32.H).
+;
+; Exit: (EAX) - Win32 status code, -1 for asynchronous
+; completion.
+; HISTORY:
+; Koti 10-Nov-1994 Created (Modified from wsock version)
+;
+;********************************************************************
+BeginProc VNBT_DeviceIoControl
+
+;;;
+;;; Setup stack frame.
+;;;
+
+ push ebx
+ push esi
+ push edi
+
+ mov eax, [esi.dwIoControlCode]
+ cmp ecx, DIOC_GETVERSION
+ je vdic_doNothing
+ cmp ecx, DIOC_CLOSEHANDLE
+ jne vdic_doSomething
+
+;;;
+;;; For devioctl calls resulting from CreateFile and CloseFile, we don't do
+;;; anything other than return success.
+;;;
+
+vdic_doNothing:
+ xor eax, eax
+ jmp vdic_CommonExit
+
+;;;
+;;; This is an ioctl requiring some work: call our api worker (VxdApiWorker)
+;;;
+
+vdic_doSomething:
+
+;;; Lock the in-buffer.
+
+ mov eax, [esi.lpvInBuffer]
+ or eax, eax
+ jz vdic_outbuf
+
+ cCall __VxdLockBuffer, <eax, [esi.cbInBuffer]>
+ or eax, eax
+ jz vdic_LockFailure
+ mov [esi.lpvInBuffer], eax
+
+vdic_outbuf:
+
+;;; Lock the out-buffer.
+
+ mov eax, [esi.lpvOutBuffer]
+ or eax, eax
+ jz vdic_callApi
+
+ cCall __VxdLockBuffer, <eax, [esi.cbOutBuffer]>
+ or eax, eax
+ jz vdic_LockFailure
+ mov [esi.lpvOutBuffer], eax
+
+vdic_callApi:
+
+ mov eax, 0 ; VxdApiWorker won't trash input buffer
+ push eax
+ mov eax, [esi.cbInBuffer]
+ push eax
+ mov eax, [esi.lpvInBuffer]
+ push eax
+ mov eax, [esi.cbOutBuffer]
+ push eax
+ mov eax, [esi.lpvOutBuffer]
+ push eax
+ mov eax, [esi.dwIoControlCode]
+ push eax
+
+ call _VxdApiWorker
+ add esp, 24
+
+
+;;; Unlock the in-buffer.
+
+ push eax ; save the return code from VxdApiWorker
+ cCall __VxdUnlockBuffer, <[esi.lpvInBuffer], [esi.cbInBuffer]>
+ pop eax
+
+;;; Unlock the out-buffer.
+
+ push eax ; save the return code from VxdApiWorker
+ cCall __VxdUnlockBuffer, <[esi.lpvOutBuffer], [esi.cbOutBuffer]>
+ pop eax
+
+vdic_CommonExit:
+
+ pop edi
+ pop esi
+ pop ebx
+
+ ret
+
+;;;
+;;; Failed to lock parameter structure.
+;;;
+
+vdic_LockFailure:
+
+ Debug_Out "VNBT_DeviceIoControl: cannot lock parameters"
+
+ mov eax, 1784 ; ERROR_INVALID_USER_BUFFER
+ jmp vdic_CommonExit
+
+EndProc VNBT_DeviceIoControl
+
+;*******************************************************************
+;** _ReconfigureDevnode
+;
+; This routine schedules an AppyTime call for the ConfigMgr to
+; call us back when it's ready. It calls our routine VNBT_ConfigCalls
+;
+; Entry: ESP+4 our devnode on the stack
+;
+; Exit: (EAX) - 0 if everything goes well
+; 1 if something goes wrong
+;
+; HISTORY:
+; Koti 15-Dec-1994 Created
+;
+;********************************************************************
+
+BeginProc _ReconfigureDevnode
+
+ push ebp
+ mov ebp, esp
+
+ xor eax, eax
+ push eax ; the flags
+ mov eax, [ebp+8] ; our devnode
+ push eax ; this is our RefData
+ lea eax, VNBT_ConfigCalls ; call back routine
+ push eax
+ VxdCall _CONFIGMG_Call_At_Appy_Time
+ add esp, 12
+ cmp eax, CR_SUCCESS
+ je ReconfigureDevnode_PASS
+ mov eax, 1
+ jmp ReconfigureDevnode_Exit
+
+ReconfigureDevnode_PASS:
+ xor eax, eax
+
+ReconfigureDevnode_Exit:
+IFDEF DBG
+ or eax, eax
+ jz ReconfigureDevnode_GoodJob
+ int 3
+ReconfigureDevnode_GoodJob:
+ENDIF
+ pop ebp
+ ret
+EndProc _ReconfigureDevnode
+
+VxD_CODE_ENDS
+
+NBT_PAGEABLE_CODE_SEG
+
+;*******************************************************************
+;** VNBT_ConfigCalls
+;
+; This routine makes all the calls to the Config Mgr so that our
+; devnode is reconfigured. We first get vredir's devnode, kill it
+; and then reenumerate all the children again. This way vredir
+; gets the msg from ConfigMgr to do whatever it does with a new devnode.
+;
+; If dhcp lease expires and then comes back in, vredir had no way
+; of knowing that lana is usable again: hence this convoluted way.
+;
+; IMPORTANT: if chicago ever changes to add more children to tcp's
+; devnode, this function needs to be modified to enumerate
+; rest of the children and kill them!
+;
+; Entry: (EDX) - our devnode
+;
+; Exit: (EAX) - 0 if everything goes well
+; 1 if something goes wrong
+;
+; HISTORY:
+; Koti 15-Dec-1994 Created
+;
+;********************************************************************
+
+VnbtScratch dd 0
+
+BeginProc VNBT_ConfigCalls
+
+ push ebp
+ mov ebp, esp
+ push esi
+ push edi
+ push ecx
+
+ ;;; First get the first child
+ xor eax, eax
+ push eax ; the flags
+ mov eax, [ebp+8]
+ push eax ; our devnode
+ lea eax, VnbtScratch ; this is where we will receive child node
+ push eax
+ VxdCall _CONFIGMG_Get_Child
+ add esp, 12
+ mov esi, dword ptr [VnbtScratch] ;save the first child in esi
+ mov edi, 0 ; for now, make esi,edi different
+ cmp eax, CR_SUCCESS
+ je ConfigCalls_Label2
+ mov ecx, 1
+ jmp ConfigCalls_Exit
+
+ ;;; Get a sibling of this child
+ConfigCalls_Label2:
+ cmp edi, esi ; did we just kill the first child
+ je ConfigCalls_Label6 ; yes: we are done with all the killings
+ xor eax, eax
+ push eax ; the flags
+ push esi ; the first child
+ lea eax, VnbtScratch ; this is where we will receive sibling
+ push eax
+ VxdCall _CONFIGMG_Get_Sibling
+ add esp, 12
+ mov edi, dword ptr [VnbtScratch] ;edi contains sibling
+ cmp eax, CR_SUCCESS ; found a sibling?
+ je ConfigCalls_Label4 ; yes, go kill it
+ cmp eax, CR_NO_SUCH_DEVNODE ; done with all siblings?
+ je ConfigCalls_Label3 ; yes, go kill the first child
+ mov ecx, 2 ; hmmm: something went wrong
+ jmp ConfigCalls_Exit
+
+ ;;; Done with all the siblings: now kill the first child
+ConfigCalls_Label3:
+ mov edi, esi ; esi=first child, edi=child to kill
+
+ConfigCalls_Label4:
+ ;;; Now, ask ConfigMgr if it's ok to kill our child
+ xor eax, eax
+ push eax ; the flags
+ push edi ; sibling's devnode
+ VxdCall _CONFIGMG_Query_Remove_SubTree
+ add esp, 8
+ cmp eax, CR_SUCCESS ; ok to kill?
+ je ConfigCalls_Label5 ; nope!
+ mov ecx, 4
+ jmp ConfigCalls_Exit
+
+ConfigCalls_Label5:
+ ;;; Now that ConfigMgr approved, kill the child
+ xor eax, eax
+ push eax ; the flags
+ push edi ; sibling's devnode
+ VxdCall _CONFIGMG_Remove_SubTree
+ add esp, 8
+ cmp eax, CR_SUCCESS ; did it die?
+ je ConfigCalls_Label2 ; yes, it did: go kill other siblings
+ mov ecx, 5 ; nope!
+ jmp ConfigCalls_Exit
+
+ConfigCalls_Label6:
+ ;;; Ok, reenumerate our devnode so our children come back to life
+ xor eax, eax
+ push eax ; the flags
+ mov eax, [ebp+8]
+ push eax ; our devnode
+ VxdCall _CONFIGMG_Reenumerate_DevNode
+ add esp, 8
+ cmp eax, CR_SUCCESS ; did it die?
+ je ConfigCalls_Label7 ; nope!
+ mov ecx, 6
+ jmp ConfigCalls_Exit
+
+ConfigCalls_Label7:
+ xor eax, eax
+
+ConfigCalls_Exit:
+IFDEF DBG
+ or eax, eax
+ jz ConfigCalls_GoodJob
+ int 3
+ConfigCalls_GoodJob:
+ENDIF
+ pop ecx
+ pop edi
+ pop esi
+ pop ebp
+ ret
+EndProc VNBT_ConfigCalls
+
+ENDIF
+
+NBT_PAGEABLE_CODE_ENDS
+
+VxD_CODE_SEG
+
+;****************************************************************************
+;** _GetInDosFlag - Retrieves the InDos flag
+;
+;
+; Note: This routine cannot be called at init time (vdosmgr complains
+; the variable not initialized yet)
+;
+; Returns the flag in ax
+;
+
+BeginProc _GetInDosFlag
+
+ push ebx
+
+ VxdCall DOSMGR_Get_IndosPtr
+
+ ;
+ ; Add CB_High_Linear if we are in V86 mode
+ ;
+
+ VMMcall Get_Cur_VM_Handle
+
+ test [ebx.CB_VM_Status], VMStat_PM_Exec
+ jnz GIF_Exit
+
+ add eax, [ebx.CB_High_Linear]
+
+GIF_Exit:
+ movzx eax, word ptr [eax]
+
+ pop ebx
+ ret
+EndProc _GetInDosFlag
+
+;****************************************************************************
+;
+; ULONG
+; RtlCompareMemory (
+; IN PVOID Source1,
+; IN PVOID Source2,
+; IN ULONG Length
+; )
+;
+; Routine Description:
+;
+; This function compares two blocks of memory and returns the number
+; of bytes that compared equal.
+;
+; Arguments:
+;
+; Source1 (ebp+8) - Supplies a pointer to the first block of memory to
+; compare.
+;
+; Source2 (ebp+12) - Supplies a pointer to the second block of memory to
+; compare.
+;
+; Length (ebp+16) - Supplies the Length, in bytes, of the memory to be
+; compared.
+;
+; Return Value:
+;
+; The number of bytes that compared equal is returned as the function
+; value. If all bytes compared equal, then the length of the orginal
+; block of memory is returned.
+;
+;--
+
+RcmSource1 equ [ebp+8]
+RcmSource2 equ [ebp+12]
+RcmLength equ [ebp+16]
+
+public _VxdRtlCompareMemory
+BeginProc _VxdRtlCompareMemory
+
+ push ebp
+ mov ebp,esp
+ push esi
+ push edi
+ cld
+
+ mov esi,RcmSource1 ; (esi) -> first block to compare
+ mov edi,RcmSource2 ; (edi) -> second block to compare
+ mov ecx,RcmLength ; (ecx) = length in bytes
+ and ecx,3 ; (ecx) = length mod 4
+ jz rcm10 ; 0 odd bytes, go do dwords
+
+;
+; Compare "odd" bytes.
+;
+
+ repe cmpsb ; compare odd bytes
+ jnz rcm40 ; mismatch, go report how far we got
+
+;
+; Compare dwords.
+;
+
+rcm10: mov ecx,RcmLength ; (ecx) = length in bytes
+ shr ecx,2 ; (ecx) = length in dwords
+ jz rcm20 ; no dwords, go exit
+
+ repe cmpsd ; compare dwords
+ jnz rcm30 ; mismatch, go find byte
+
+;
+; When we come to rcm20, we matched all the way to the end. Esi
+; points to the byte after the last byte in the block, so Esi - RcmSource1
+; equals the number of bytes that matched
+;
+
+rcm20: sub esi,RcmSource1
+ mov eax,esi
+ pop edi
+ pop esi
+ pop ebp
+ ret
+
+;
+; When we come to rcm30, esi (and edi) points to the dword after the
+; one which caused the mismatch. Back up 1 dword and find the byte.
+; Since we know the dword didn't match, we can assume one byte won't.
+;
+
+rcm30: sub esi,4 ; back up
+ sub edi,4 ; back up
+ mov ecx,5 ; ensure that ecx doesn't count out
+ repe cmpsb ; find mismatch byte
+
+;
+; When we come to rcm40, esi points to the byte after the one that
+; did not match, which is TWO after the last byte that did match.
+;
+
+rcm40: dec esi
+ sub esi,RcmSource1
+ mov eax,esi
+ pop edi
+ pop esi
+ pop ebp
+ ret
+
+EndProc _VxdRtlCompareMemory
+
+;****************************************************************************
+;** VNBT_Api_Handler - handles all request from other vxd's, v86-mode apps
+;
+; This procedure does all the address translations, memory locking etc.
+; and calls the C routine VxdApiWorker() to do the actual work
+;
+; Entry: EBX - VM handle
+; (EBP) - Client reg structure
+;
+; Exit: 'NC' is success, 'CY' on failure
+;
+; Uses: All
+;
+; HISTORY:
+; Koti 16-Jun-1994 Created (Modified from dhcp's version)
+;
+;********************************************************************
+BeginProc VNBT_Api_Handler
+
+
+ push ebp
+ push ebx
+ push esi
+ push edi
+ push edx
+ push ecx
+
+;;; get function op code
+
+ movzx edi, [ebp.Client_CX]
+
+;;;
+;;; Convert the parameter buffer pointers from segmented to flat.
+;;;
+
+;;; first, the output buffer
+
+ movzx eax, [ebp.Client_BX]
+ push eax
+ movzx eax, [ebp.Client_ES]
+ push eax
+ push ebx
+ call __VxdMapSegmentOffsetToFlat
+ add esp, 12
+
+ cmp eax, 0FFFFFFFFh
+ je vnbt_Fault
+
+;;;
+;;; Lock the output buffer.
+;;;
+
+ or eax, eax
+ jz vnbt_DontLock_OutBuf
+
+ movzx ecx, [ebp.Client_DI]
+ cCall __VxdLockBuffer, <eax, ecx>
+
+ or eax, eax
+ jz vnbt_Fault
+
+vnbt_DontLock_OutBuf:
+
+ mov esi, eax
+
+;;; now, convert and lock the input buffer
+
+ movzx eax, [ebp.Client_AX]
+ push eax
+ movzx eax, [ebp.Client_DX]
+ push eax
+ push ebx
+ call __VxdMapSegmentOffsetToFlat
+ add esp, 12
+
+ cmp eax, 0FFFFFFFFh
+ je vnbt_Fault
+
+ or eax, eax
+ jz vnbt_DontLock
+
+ movzx ebx, [ebp.Client_SI]
+ cCall __VxdLockBuffer, <eax, ebx> ; this preserves esi
+
+ or eax, eax
+ jz vnbt_Fault
+
+vnbt_DontLock:
+
+ mov edx, eax
+
+;;; call worker routine
+;;; edi - opcode
+;;; esi - OutBuffer pointer
+;;; ecx - OutBuffer length
+;;; edx - InBuffer pointer
+;;; ebx - InBuffer length
+
+;
+; RLF 05/30/94 - __VxdLockBuffer destroys contents of cx - reload
+;
+
+ push esi ; save OutBuffer addr
+ push edx ; save InBuffer addr
+
+ mov eax, 1 ; VxdApiWorker will trash input buffer
+ push eax
+ movzx ecx, [ebp.Client_DI]
+ movzx ebx, [ebp.Client_SI]
+ push ebx
+ push edx
+ push ecx
+ push esi
+ push edi
+
+ call _VxdApiWorker
+ add esp, 24
+
+ pop edx ; restore InBuffer addr
+ pop esi ; restore OutBuffer addr
+
+ mov [ebp.Client_AX], ax
+
+;;;
+;;; Unlock the parameter buffer.
+;;;
+
+ or esi, esi
+ jz vnbt_DontUnLock_OutBuf
+
+ push edx ; save InBuffer addr
+ movzx ecx, [ebp.Client_DI]
+ cCall __VxdUnlockBuffer <esi, ecx>
+ pop edx ; restore InBuffer addr
+vnbt_DontUnLock_OutBuf:
+
+ or edx, edx
+ jz vnbt_DontUnLock
+
+ movzx ebx, [ebp.Client_SI]
+ cCall __VxdUnlockBuffer <edx, ebx>
+
+vnbt_DontUnLock:
+
+vnbt_CommonExit:
+
+;;; Restore stack fame
+ pop ecx
+ pop edx
+ pop edi
+ pop esi
+ pop ebx
+ pop ebp
+ ret
+
+;;;
+;;; Either failed to map a segmented pointer to flat or failed
+;;; to lock the parameter buffer.
+;;;
+
+vnbt_Fault:
+
+ cmp eax, 0FFFFFFFFh
+ mov [ebp.Client_AX], ax
+ jmp vnbt_CommonExit
+
+
+EndProc VNBT_Api_Handler
+
+VxD_CODE_ENDS
+END
+
diff --git a/private/ntos/nbt/vxd/vnbtd.def b/private/ntos/nbt/vxd/vnbtd.def
new file mode 100644
index 000000000..2133cc04d
--- /dev/null
+++ b/private/ntos/nbt/vxd/vnbtd.def
@@ -0,0 +1,21 @@
+VXD VNBT DYNAMIC
+
+DESCRIPTION 'TCP/IP on NetBIOS (NBT) driver'
+
+EXETYPE DEV386
+
+SEGMENTS
+ _LTEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE
+ _TEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE
+ _LDATA CLASS 'LCODE' PRELOAD NONDISCARDABLE
+ _DATA CLASS 'LCODE' PRELOAD NONDISCARDABLE
+ CONST CLASS 'LCODE' PRELOAD NONDISCARDABLE
+ _BSSbeg CLASS 'LCODE' PRELOAD NONDISCARDABLE
+ _BSS CLASS 'LCODE' PRELOAD NONDISCARDABLE
+ c_common CLASS 'LCODE' PRELOAD NONDISCARDABLE
+ _BSSend CLASS 'LCODE' PRELOAD NONDISCARDABLE
+ _ITEXT CLASS 'ICODE' DISCARDABLE
+ _IDATA CLASS 'ICODE' DISCARDABLE
+
+EXPORTS
+ VNBT_DDB @1
diff --git a/private/ntos/nbt/vxd/vnbtd.inc b/private/ntos/nbt/vxd/vnbtd.inc
new file mode 100644
index 000000000..a8aa28830
--- /dev/null
+++ b/private/ntos/nbt/vxd/vnbtd.inc
@@ -0,0 +1,18 @@
+;******************************************************************************
+;
+; (C) Copyright MICROSOFT Corp., 1992
+;
+; Title: VNBT.INC - Virtual NBT Device Service Declarations
+;
+; Version: 1.01
+;
+
+
+VNBT_VERSION equ 0101h
+
+Begin_Service_Table VNBT
+
+VNBT_Service VNBT_Get_Version, LOCAL
+
+End_Service_Table VNBT
+
diff --git a/private/ntos/nbt/vxd/vnbtd.mk b/private/ntos/nbt/vxd/vnbtd.mk
new file mode 100644
index 000000000..6aeb2810a
--- /dev/null
+++ b/private/ntos/nbt/vxd/vnbtd.mk
@@ -0,0 +1,318 @@
+#
+#:ts=4
+#
+
+ROOTDIR=..
+!include rules.mk
+
+#
+# TCP should point to the root of Henry's TCP vxd tree
+#
+#
+
+!ifndef CHICAGO
+#CHICAGO=$(DEFDRIVE)$(DEFDIR)\chicago
+CHICAGO=k:\
+!endif
+
+VNBTSRC=$(ROOTDIR)\vxd
+COMVNBTOBJD=$(COMDEBOBJ)
+COMVNBTOBJ=$(COMNODEBOBJ)
+
+NBTLIBS=$(ROOTDIR)\nbt\nodebug\nbt.lib
+NBTDLIBS=$(ROOTDIR)\nbt\debug\nbt.lib
+
+NDISLIBR=$(TCP)\ndis31\retail\libndis.lib
+NDISLIBD=$(TCP)\ndis31\debug\libndis.lib
+
+#
+# Hack to get around include path limits when trying to get to the DHCP
+# header files.
+#
+IMPORT_HEADERS=$(BLT)\dhcpinfo.h $(BLT)\vdhcp.inc
+
+$(BLT)\dhcpinfo.h: $(DHCP)\dhcpinfo.h
+ copy $(DHCP)\dhcpinfo.h $(BLT)
+
+$(BLT)\vdhcp.inc: $(TCP)\inc\vdhcp.inc
+ copy $(TCP)\inc\vdhcp.inc $(BLT)
+
+
+
+CHIVNBTOBJD =$(CNODEBOBJ)
+CHIDVNBTOBJD=$(CDEBOBJ)
+SNOVNBTOBJD =$(SNODEBOBJ)
+SNODVNBTOBJD=$(SDEBOBJ)
+
+RC=$(CHICAGO)\dev\sdk\bin\rc
+ADRC2VXD=adrc2vxd
+
+VNBTOBJS=\
+ $(SNODEBOBJ)\cxport.obj \
+ $(SNODEBOBJ)\vfirst.obj \
+ $(SNODEBOBJ)\vnbtd.obj \
+ $(SNODEBOBJ)\client.obj \
+ $(SNODEBOBJ)\fileio.obj \
+ $(SNODEBOBJ)\cinit.obj \
+ $(SNODEBOBJ)\ncb.obj \
+ $(SNODEBOBJ)\vxdisol.obj \
+ $(SNODEBOBJ)\tdicnct.obj \
+ $(SNODEBOBJ)\tdiout.obj \
+ $(SNODEBOBJ)\util.obj \
+ $(SNODEBOBJ)\tdiaddr.obj \
+ $(SNODEBOBJ)\tdihndlr.obj \
+ $(SNODEBOBJ)\ctimer.obj \
+ $(SNODEBOBJ)\nbtinfo.obj \
+ $(SNODEBOBJ)\vxddebug.obj \
+ $(SNODEBOBJ)\chic.obj \
+ $(SNODEBOBJ)\chicasm.obj \
+ $(SNODEBOBJ)\wfw.obj \
+ $(SNODEBOBJ)\wfwasm.obj
+
+VXDFILEOBJ=$(SNODEBOBJ)\vxdfile.obj
+CVXDFILEOBJ=$(SNODEBOBJ)\cvxdfile.obj
+
+SNOVNBTOBJS=$(VNBTOBJS) $(VXDFILEOBJ)
+SNODVNBTOBJS=$(SNOVNBTOBJS:nodebug=debug)
+
+
+SNOVNBTOBJS_C=$(VNBTOBJS) $(CVXDFILEOBJ)
+CHIVNBTOBJS=$(SNOVNBTOBJS_C:snowball=chicago)
+CHIDVNBTOBJS=$(CHIVNBTOBJS:nodebug=debug)
+
+VTSF1=$(VNBTSRC:\=/)
+VTSF=$(VTSF1:.=\.)
+CHICAGOF=$(CHICAGO:\=/)
+TCPF=$(TCP:\=/)
+
+VNBTBINCS= $(BLT)\netvxd.inc $(BLT)\cxport.inc $(TCP)\inc\vtdi.inc
+
+VNBTAFLAGS = -DIS_32 -nologo -W2 -Zd -Cp -Cx -DMASM6 -DVMMSYS
+
+SNOVNBTAFLAGS= $(VNBTAFLAGS) -DWIN31COMPAT
+SNOVNBTAINC=$(VNBTSRC);$(NBT)\vxd;$(INC);$(BLT);$(WIN32INC);$(COMMON)\inc;$(NDIS3INC);$(IMPORT)\wininc;$(TCP)\inc;$(TCP)\blt
+
+CHIVNBTAFLAGS= $(VNBTAFLAGS) -DCHICAGO
+CHIVNBTAINC=$(VNBTSRC);$(NBT)\vxd;$(CHICAGO)\dev\ddk\inc;$(CHICAGO)\dev\inc;$(INC);$(BLT);$(WIN32INC);$(COMMON)\inc;$(NDIS3INC);$(IMPORT)\wininc;$(TCP)\inc;$(TCP)\blt
+
+VNBTCFLAGS = -c -DVXD -Zp1l -Owx -nologo -D_X86_=1 -Di386=1 -DDEVL=1 -DPROXY_NODE
+
+#
+# Note that if netvxd.inc in tcp\blt differs from tcp\blt\snowcomm in
+# something vnbt uses, we'll need different assember targets with different
+# include path statements
+#
+VNBTAINC=$(VNBTSRC);$(INC);$(BLT);$(NDIS3INC);$(WIN32INC);$(COMMON)\inc;$(IMPORT)\wininc;$(TCP)\inc;$(TCP)\blt
+#SVNBTAINC=$(VNBTAINC);$(TCP)\blt\snowcomm
+#CVNBTAINC=$(VNBTAINC);$(TCP)\blt
+
+SNOVNBTCFLAGS= $(VNBTCFLAGS)
+SNOVNBTCINC=.;..\inc;$(TCP)\h;..\..\inc;$(BASEDIR)\private\inc;$(BASEDIR)\public\sdk\inc;$(BASEDIR)\public\sdk\inc\crt;$(NDIS3INC);$(WIN32INC);$(IMPORT)\c8386\inc32;$(IMPORT)\common\h;$(IMPORT)\wininc;$(BLT)
+
+CHIVNBTCFLAGS= $(VNBTCFLAGS) -DCHICAGO
+CHIVNBTCINC=.;..\inc;$(TCP)\h;..\..\inc;$(BASEDIR)\private\inc;$(BASEDIR)\public\sdk\inc;$(BASEDIR)\public\sdk\inc\crt;$(CHICAGO)\dev\ddk\inc;$(CHICAGO)\dev\inc;$(NDIS3INC);$(WIN32INC);$(IMPORT)\c8386\inc32;$(IMPORT)\common\h;$(IMPORT)\wininc;$(BLT)
+
+#
+# \Common rules
+#
+# Note that there currently isn't any platform specific .obj that needs to
+# be built. If a file does become platform specific, then copy the following
+# four rules and replace COM*OBJ with C*OBJ and/or S*OBJ
+
+{$(VNBTSRC)}.asm{$(CHIVNBTOBJD)}.obj:
+ set INCLUDE=$(CHIVNBTAINC)
+ set ML=$(CHIVNBTAFLAGS)
+ $(ASM) -c -Fo$(CHIVNBTOBJD)\$(@B).obj $(VNBTSRC)\$(@B).asm
+
+{$(VNBTSRC)}.asm{$(CHIDVNBTOBJD)}.obj:
+ set INCLUDE=$(CHIVNBTAINC)
+ set ML=$(CHIVNBTAFLAGS) -DDEBUG
+ $(ASM) -c -Fo$(CHIDVNBTOBJD)\$(@B).obj $(VNBTSRC)\$(@B).asm
+
+{$(VNBTSRC)}.asm{$(SNOVNBTOBJD)}.obj:
+ set INCLUDE=$(SNOVNBTAINC)
+ set ML=$(SNOVNBTAFLAGS)
+ $(ASM) -c -Fo$(SNOVNBTOBJD)\$(@B).obj $(VNBTSRC)\$(@B).asm
+
+{$(VNBTSRC)}.asm{$(SNODVNBTOBJD)}.obj:
+ set INCLUDE=$(SNOVNBTAINC)
+ set ML=$(SNOVNBTAFLAGS) -DDEBUG
+ $(ASM) -c -Fo$(SNODVNBTOBJD)\$(@B).obj $(VNBTSRC)\$(@B).asm
+
+{$(VNBTSRC)}.c{$(CHIVNBTOBJD)}.obj:
+ set INCLUDE=$(CHIVNBTCINC)
+ set CL=$(CHIVNBTCFLAGS)
+ $(CL386) -Fo$(CHIVNBTOBJD)\$(@B).obj $(VNBTSRC)\$(@B).c
+
+{$(VNBTSRC)}.c{$(CHIDVNBTOBJD)}.obj:
+ set INCLUDE=$(CHIVNBTCINC)
+ set CL=$(CHIVNBTCFLAGS) -DDEBUG -DDBG=1 -Oy- -Zd
+ $(CL386) -Fo$(CHIDVNBTOBJD)\$(@B).obj $(VNBTSRC)\$(@B).c
+
+{$(VNBTSRC)}.c{$(SNOVNBTOBJD)}.obj:
+ set INCLUDE=$(SNOVNBTCINC)
+ set CL=$(SNOVNBTCFLAGS)
+ $(CL386) -Fo$(SNOVNBTOBJD)\$(@B).obj $(VNBTSRC)\$(@B).c
+
+{$(VNBTSRC)}.c{$(SNODVNBTOBJD)}.obj:
+ set INCLUDE=$(SNOVNBTCINC)
+ set CL=$(SNOVNBTCFLAGS) -DDEBUG -DDBG=1 -Oy- -Zd
+ $(CL386) -Fo$(SNODVNBTOBJD)\$(@B).obj $(VNBTSRC)\$(@B).c
+
+{$(VNBTSRC)}.h{$(BLT)}.inc:
+ $(SED) -f $(SHTOINC) <$< >$(BLT)\$(@B).inc
+
+$(CNODEBOBJ)\cxport.obj: $(TCP)\bin\chicago\nodebug\cxport.obj
+ copy $(TCP)\bin\chicago\nodebug\cxport.obj $(CNODEBOBJ)
+
+$(CDEBOBJ)\cxport.obj: $(TCP)\bin\chicago\debug\cxport.obj
+ copy $(TCP)\bin\chicago\debug\cxport.obj $(CDEBOBJ)
+
+$(SNODEBOBJ)\cxport.obj: $(TCP)\bin\snowball\nodebug\cxport.obj
+ copy $(TCP)\bin\snowball\nodebug\cxport.obj $(SNODEBOBJ)
+
+$(SDEBOBJ)\cxport.obj: $(TCP)\bin\snowball\debug\cxport.obj
+ copy $(TCP)\bin\snowball\debug\cxport.obj $(SDEBOBJ)
+
+svnbt: $(SNODEBBIN)\VNBT.386 $(TCP)\bin\snowball\nodebug\cxport.obj
+
+svnbtd: $(SDEBBIN)\VNBT.386 $(TCP)\bin\snowball\debug\cxport.obj
+
+cvnbt: $(CNODEBBIN)\VNBT.386 $(TCP)\bin\chicago\nodebug\cxport.obj
+
+cvnbtd: $(CDEBBIN)\VNBT.386 $(TCP)\bin\chicago\debug\cxport.obj
+
+clean:
+ -del $(SNODEBBIN)\*.obj
+ -del $(SNODEBBIN)\*.sym
+ -del $(SNODEBBIN)\*.386
+ -del $(SNODEBBIN)\*.map
+ -del $(SDEBBIN)\*.obj
+ -del $(SDEBBIN)\*.sym
+ -del $(SDEBBIN)\*.386
+ -del $(SDEBBIN)\*.map
+
+ -del $(CNODEBBIN)\*.obj
+ -del $(CNODEBBIN)\*.sym
+ -del $(CNODEBBIN)\*.386
+ -del $(CNODEBBIN)\*.map
+ -del $(CDEBBIN)\*.obj
+ -del $(CDEBBIN)\*.sym
+ -del $(CDEBBIN)\*.386
+ -del $(CDEBBIN)\*.map
+
+cleanlink:
+ -del $(SNODEBBIN)\*.obj
+ -del $(SNODEBBIN)\*.sym
+ -del $(SNODEBBIN)\*.386
+ -del $(SNODEBBIN)\*.map
+ -del $(SDEBBIN)\*.obj
+ -del $(SDEBBIN)\*.sym
+ -del $(SDEBBIN)\*.386
+ -del $(SDEBBIN)\*.map
+
+ -del $(CNODEBBIN)\*.obj
+ -del $(CNODEBBIN)\*.sym
+ -del $(CNODEBBIN)\*.386
+ -del $(CNODEBBIN)\*.map
+ -del $(CDEBBIN)\*.obj
+ -del $(CDEBBIN)\*.sym
+ -del $(CDEBBIN)\*.386
+ -del $(CDEBBIN)\*.map
+
+#----------------------------------------------------------------------
+
+$(SNODEBBIN)\VNBT.386: $(SNOVNBTOBJS) $(NBTLIBS) $(IMPORT_HEADERS)
+ $(LINK386) @<<
+$(SNOVNBTOBJS: =+
+) /NOD /NOI /MAP /NOLOGO
+$(SNODEBBIN)\VNBT.386
+$(SNODEBBIN)\VNBT.map
+$(NBTLIBS)
+$(VNBTSRC)\VNBTD.def
+<<
+ $(MAPSYM386) $(SNODEBBIN)\VNBT
+ -del $(SNODEBBIN)\VNBT.sym
+ $(MV) VNBT.sym $(SNODEBBIN)
+
+#----------------------------------------------------------------------
+
+$(SDEBBIN)\VNBT.386: $(SNODVNBTOBJS) $(NBTDLIBS) $(IMPORT_HEADERS)
+ $(LINK386) @<<
+$(SNODVNBTOBJS: =+
+) /NOD /NOI /MAP /NOLOGO
+$(SDEBBIN)\VNBT.386
+$(SDEBBIN)\VNBT.map
+$(NBTDLIBS)
+$(VNBTSRC)\VNBTD.def
+<<
+ $(MAPSYM386) $(SDEBBIN)\VNBT
+ -del $(SDEBBIN)\VNBT.sym
+ $(MV) VNBT.sym $(SDEBBIN)
+
+#----------------------------------------------------------------------
+
+$(CNODEBBIN)\VNBT.386: $(CHIVNBTOBJS) $(NBTLIBS) $(IMPORT_HEADERS)
+ $(LINK386) @<<
+$(CHIVNBTOBJS: =+
+) /NOD /NOI /MAP /NOLOGO
+$(CNODEBBIN)\VNBT.386
+$(CNODEBBIN)\VNBT.map
+$(NBTLIBS) $(NDISLIBR)
+$(VNBTSRC)\VNBTD.def
+<<
+ $(RC) -i $(CHICAGO)\dev\ddk\inc -i $(CHICAGO)\dev\inc -r VNBT.RCV
+ $(ADRC2VXD) $(CNODEBBIN)\VNBT.386 VNBT.RES
+ $(MAPSYM386) $(CNODEBBIN)\VNBT
+ -del $(CNODEBBIN)\VNBT.sym
+ $(MV) VNBT.sym $(CNODEBBIN)
+
+#----------------------------------------------------------------------
+
+$(CDEBBIN)\VNBT.386: $(CHIDVNBTOBJS) $(NBTDLIBS) $(IMPORT_HEADERS)
+ $(LINK386) @<<
+$(CHIDVNBTOBJS: =+
+) /NOD /NOI /MAP /NOLOGO
+$(CDEBBIN)\VNBT.386
+$(CDEBBIN)\VNBT.map
+$(NBTDLIBS) $(NDISLIBD)
+$(VNBTSRC)\VNBTD.def
+<<
+ $(RC) -i $(CHICAGO)\dev\ddk\inc -i $(CHICAGO)\dev\inc -r VNBT.RCV
+ $(ADRC2VXD) $(CDEBBIN)\VNBT.386 VNBT.RES
+ $(MAPSYM386) $(CDEBBIN)\VNBT
+ -del $(CDEBBIN)\VNBT.sym
+ $(MV) VNBT.sym $(CDEBBIN)
+
+
+$(BLT)\netvxd.inc: $(COMMON)\h\netvxd.h
+$(BLT)\cxport.inc: $(TCP)\h\cxport.h
+
+depend: VNBTdep
+
+VNBTdep: $(VNBTBINCS)
+ -copy $(VNBTSRC)\depend.mk $(VNBTSRC)\depend.old
+ echo #******************************************************************** > $(VNBTSRC)\depend.mk
+ echo #** Copyright(c) Microsoft Corp., 1993 ** >> $(VNBTSRC)\depend.mk
+ echo #******************************************************************** >> $(VNBTSRC)\depend.mk
+ set INCLUDE=$(SNOVNBTAINC)
+ -$(INCLUDES) -i -e -S$$(SNOVNBTOBJD) -S$$(SNODVNBTOBJD) -sobj $(VNBTSRC)\*.asm >> $(VNBTSRC)\depend.mk
+ set INCLUDE=$(CHIVNBTAINC)
+ -$(INCLUDES) -i -e -S$$(CHIVNBTOBJD) -S$$(CHIDVNBTOBJD) -sobj $(VNBTSRC)\*.asm >> $(VNBTSRC)\depend.mk
+ set INCLUDE=$(SNOVNBTCINC)
+ -$(INCLUDES) -i -e -S$$(SNOVNBTOBJD) -S$$(SNODVNBTOBJD) -sobj $(VNBTSRC)\*.c >> $(VNBTSRC)\depend.mk
+ set INCLUDE=$(CHIVNBTCINC)
+ -$(INCLUDES) -i -e -S$$(CHIVNBTOBJD) -S$$(CHIDVNBTOBJD) -sobj $(VNBTSRC)\*.c >> $(VNBTSRC)\depend.mk
+ $(SED) -e s`$(IMPF)`$$(IMPORT)`g <$(VNBTSRC)\depend.mk > $(VNBTSRC)\depend.tmp
+ $(SED) -e s`$(CMNF)`$$(COMMON)`g <$(VNBTSRC)\depend.tmp > $(VNBTSRC)\depend.mk
+ $(SED) -e s`$(VTSF)`$$(VNBTSRC)`g <$(VNBTSRC)\depend.mk > $(VNBTSRC)\depend.tmp
+ $(SED) -e s`$(BASEDIRF)`$$(BASEDIR)`g <$(VNBTSRC)\depend.tmp > $(VNBTSRC)\depend.mk
+ $(SED) -e s`$(INCF)`$$(INC)`g <$(VNBTSRC)\depend.mk > $(VNBTSRC)\depend.tmp
+ $(SED) -e s`$(HF)`$$(H)`g <$(VNBTSRC)\depend.tmp > $(VNBTSRC)\depend.mk
+ $(SED) -e s`$(NDIS3F)`$$(NDIS3INC)`g <$(VNBTSRC)\depend.mk > $(VNBTSRC)\depend.tmp
+ $(SED) -e s`$(CHICAGOF)`$$(CHICAGO)`g <$(VNBTSRC)\depend.tmp > $(VNBTSRC)\depend.mk
+ $(SED) -e s`$(TCPF)`$$(TCP)`g <$(VNBTSRC)\depend.mk > $(VNBTSRC)\depend.tmp
+ copy $(VNBTSRC)\depend.tmp $(VNBTSRC)\depend.mk
+ -del $(VNBTSRC)\depend.tmp
+
+!include depend.mk
diff --git a/private/ntos/nbt/vxd/vxddebug.c b/private/ntos/nbt/vxd/vxddebug.c
new file mode 100644
index 000000000..663ccf780
--- /dev/null
+++ b/private/ntos/nbt/vxd/vxddebug.c
@@ -0,0 +1,659 @@
+/**********************************************************************/
+/** Microsoft Windows NT **/
+/** Copyright(c) Microsoft Corp., 1993 **/
+/**********************************************************************/
+
+/*
+ debug.c
+
+ This module contains debug support routines.
+
+
+ FILE HISTORY:
+ KeithMo 20-Sep-1993 Created.
+
+*/
+
+#include <nbtprocs.h>
+#include <vxddebug.h>
+
+
+#ifdef DEBUG
+
+
+//
+// Private constants.
+//
+
+#define MAX_PRINTF_OUTPUT 1024 // characters
+#define MAX_SUBSTRING_LEN 256
+#define OUTPUT_LABEL "VNBT"
+
+#define IS_DIGIT(ch) (((ch) >= '0') && ((ch) <= '9'))
+
+
+//
+// Private types.
+//
+
+
+//
+// Private globals.
+//
+
+
+//
+// Private prototypes.
+//
+
+int VxdVsprintf( char * pszStr,
+ char * pszFmt,
+ char * ArgPtr );
+
+void VxdCopyToDBOut( void );
+
+//
+// Public functions.
+//
+
+/*******************************************************************
+
+ NAME: VxdAssert
+
+ SYNOPSIS: Called if an assertion fails. Displays the failed
+ assertion, file name, and line number. Gives the
+ user the opportunity to ignore the assertion or
+ break into the debugger.
+
+ ENTRY: pAssertion - The text of the failed expression.
+
+ pFileName - The containing source file.
+
+ nLineNumber - The guilty line number.
+
+ HISTORY:
+ KeithMo 20-Sep-1993 Created.
+
+********************************************************************/
+void VxdAssert( void * pAssertion,
+ void * pFileName,
+ unsigned long nLineNumber )
+{
+ VxdPrintf( "\n"
+ "*** Assertion failed: %s\n"
+ "*** Source file %s, line %lu\n\n",
+ pAssertion,
+ pFileName,
+ nLineNumber );
+
+ DEBUG_BREAK;
+
+} // VxdAssert
+
+/*******************************************************************
+
+ NAME: VxdPrintf
+
+ SYNOPSIS: Customized debug output routine.
+
+ ENTRY: Usual printf-style parameters.
+
+ HISTORY:
+ KeithMo 20-Sep-1993 Created.
+
+********************************************************************/
+char szOutput[MAX_PRINTF_OUTPUT];
+
+void VxdPrintf( char * pszFormat,
+ ... )
+{
+ va_list ArgList;
+ int cch;
+
+ cch = VxdSprintf( szOutput,
+ "%s: ",
+ OUTPUT_LABEL );
+
+ va_start( ArgList, pszFormat );
+ VxdVsprintf( szOutput + cch, pszFormat, ArgList );
+ va_end( ArgList );
+
+ VxdSprintf( szOutput, "%s\r\n", szOutput ) ;
+
+ VxdCopyToDBOut() ;
+
+ NbtDebugOut( DBOut+iCurPos ) ;
+
+} // VxdPrintf
+
+
+//
+// Private functions.
+//
+
+/*******************************************************************
+ NAME: VxdCopyToDBOut
+
+ SYNOPSIS: Copies everything from szOutput into DBOut
+ First checks to see if DBOut has enough room to hold what we
+ have temporarily put in szOutput. If not, resets the iCurPos
+ to point to beginning of DBOut.
+
+ RETURNS: Nothing
+
+ *******************************************************************/
+
+void VxdCopyToDBOut( void )
+{
+
+ int bytesTowrite;
+ int spaceAvailable;
+ int i;
+
+ spaceAvailable = sizeof(DBOut) - iCurPos;
+
+ bytesTowrite = strlen( szOutput ) + 1;
+
+ // if not enough room, start at the beginning
+ if ( spaceAvailable <= bytesTowrite )
+ {
+ for ( i=iCurPos; i<sizeof(DBOut); i++ )
+ DBOut[i] = '+'; // so that strings don't mix
+
+ iCurPos = 0;
+
+ if ( bytesTowrite > sizeof(szOutput) )
+ {
+ bytesTowrite = sizeof(szOutput);
+ szOutput[bytesTowrite-1] = '\0';
+ }
+ }
+
+ CTEMemCopy( DBOut+iCurPos, szOutput, bytesTowrite ) ;
+
+}
+
+/*******************************************************************
+
+ NAME: VxdVsprintf
+
+ SYNOPSIS: Half-baked vsprintf() clone for VxD environment.
+
+ ENTRY: pszStr - Will receive the formatted string.
+
+ pszFmt - The format, with field specifiers.
+
+ ArgPtr - Points to the actual printf() arguments.
+
+ RETURNS: int - Number of characters stored in *pszStr.
+
+ HISTORY:
+ KeithMo 20-Sep-1993 Created.
+
+********************************************************************/
+int VxdVsprintf( char * pszStr,
+ char * pszFmt,
+ char * ArgPtr )
+
+{
+ char ch;
+ char * pszStrStart;
+ int fZeroPad;
+ int cchWidth;
+ int ccMaxToCopy;
+
+ //
+ // Remember start of output, so we can calc length.
+ //
+
+ pszStrStart = pszStr;
+
+ while( ( ch = *pszFmt++ ) != '\0' )
+ {
+ //
+ // Scan for format specifiers.
+ //
+
+ if( ch != '%' )
+ {
+ *pszStr++ = ch;
+ continue;
+ }
+
+ //
+ // Got one.
+ //
+
+ ch = *pszFmt++;
+
+ //
+ // Initialize attributes for this item.
+ //
+
+ fZeroPad = 0;
+ cchWidth = 0;
+ ccMaxToCopy = MAX_SUBSTRING_LEN;
+
+ //
+ // Interpret the field specifiers.
+ //
+
+ if( ch == '-' )
+ {
+ //
+ // Left justification not supported.
+ //
+
+ ch = *pszFmt++;
+ }
+
+ if( ch == '0' )
+ {
+ //
+ // Zero padding.
+ //
+
+ fZeroPad = 1;
+ ch = *pszFmt++;
+ }
+
+ if( ch == '*' )
+ {
+ //
+ // Retrieve width from next argument.
+ //
+
+ cchWidth = va_arg( ArgPtr, int );
+ ch = *pszFmt++;
+ }
+ else
+ {
+ //
+ // Calculate width.
+ //
+
+ while( IS_DIGIT(ch) )
+ {
+ cchWidth = ( cchWidth * 10 ) + ( ch - '0' );
+ ch = *pszFmt++;
+ }
+ }
+
+ if( ch == '.' )
+ {
+ ch = *pszFmt++;
+
+ if( ch == '*' )
+ {
+ ccMaxToCopy = va_arg( ArgPtr, int );
+ ch = *pszFmt++;
+ }
+ else
+ {
+ ccMaxToCopy = 0;
+ while( IS_DIGIT(ch) )
+ {
+ ccMaxToCopy = ( ccMaxToCopy * 10 ) + ( ch - '0' );
+ ch = *pszFmt++;
+ }
+ }
+ }
+
+ //
+ // All numbers are longs.
+ //
+
+ if( ch == 'l' )
+ {
+ ch = *pszFmt++;
+ }
+
+ //
+ // Decipher the format specifier.
+ //
+
+ if( ( ch == 'd' ) || ( ch == 'u' ) || ( ch == 'x' ) || ( ch == 'X' ) )
+ {
+ unsigned long ul;
+ unsigned long radix;
+ char xbase;
+ char * pszTmp;
+ char * pszEnd;
+ int cchNum;
+ int fNegative;
+
+ //
+ // Numeric. Retrieve the value.
+ //
+
+ ul = va_arg( ArgPtr, unsigned long );
+
+ //
+ // If this is a negative number, remember and negate.
+ //
+
+ if( ( ch == 'd' ) && ( (long)ul < 0 ) )
+ {
+ fNegative = 1;
+ ul = (unsigned long)(-(long)ul);
+ }
+ else
+ {
+ fNegative = 0;
+ }
+
+ //
+ // Remember start of digits.
+ //
+
+ pszTmp = pszStr;
+ cchNum = 0;
+
+ //
+ // Special goodies for hex conversion.
+ //
+
+ radix = ( ( ch == 'x' ) || ( ch == 'X' ) ) ? 16 : 10;
+ xbase = ( ch == 'x' ) ? 'a' : 'A';
+
+ //
+ // Loop until we're out of digits.
+ //
+
+ do
+ {
+ unsigned int digit;
+
+ digit = (unsigned int)( ul % radix );
+ ul /= radix;
+
+ if( digit > 9 )
+ {
+ *pszTmp++ = (char)( digit - 10 + xbase );
+ }
+ else
+ {
+ *pszTmp++ = (char)( digit + '0' );
+ }
+
+ cchNum++;
+
+ } while( ul > 0 );
+
+ //
+ // Add the negative sign if necessary.
+ //
+
+ if( fNegative )
+ {
+ *pszTmp++ = '-';
+ cchNum++;
+ }
+
+ //
+ // Add any necessary padding.
+ //
+
+ while( cchNum < cchWidth )
+ {
+ *pszTmp++ = fZeroPad ? '0' : ' ';
+ cchNum++;
+ }
+
+ //
+ // Now reverse the digits.
+ //
+
+ pszEnd = pszTmp--;
+
+ do
+ {
+ char tmp;
+
+ tmp = *pszTmp;
+ *pszTmp = *pszStr;
+ *pszStr = tmp;
+
+ pszTmp--;
+ pszStr++;
+
+ } while( pszTmp > pszStr );
+
+ pszStr = pszEnd;
+ }
+ else
+ if( ch == 's' )
+ {
+ char * pszTmp;
+ int count;
+
+ //
+ // Copy the string.
+ //
+
+ pszTmp = va_arg( ArgPtr, char * );
+
+ count = 0;
+ while( *pszTmp )
+ {
+ *pszStr++ = *pszTmp++;
+ count++;
+ //
+ // if we get passed a weird pointer, don't go on writing! That
+ // overwrites other things (like tdidispatch table!) and very
+ // bad things happen....
+ //
+ if (count >= ccMaxToCopy)
+ break;
+ }
+ }
+ else
+ if( ch == 'c' )
+ {
+ //
+ // A single character.
+ //
+
+ *pszStr++ = (char)va_arg( ArgPtr, int );
+ }
+ else
+ {
+ //
+ // Unknown. Ideally we should copy the entire
+ // format specifier, including any width & precision
+ // values, but who really cares?
+ //
+
+ *pszStr++ = ch;
+ }
+ }
+
+ //
+ // Terminate it properly.
+ //
+
+ *pszStr = '\0';
+
+ //
+ // Return the length of the generated string.
+ //
+
+ return pszStr - pszStrStart;
+
+} // VxdVsprintf
+
+/*******************************************************************
+
+ NAME: VxdSprintf
+
+ SYNOPSIS: Half-baked sprintf() clone for VxD environment.
+
+ ENTRY: pszStr - Will receive the formatted string.
+
+ pszFmt - The format, with field specifiers.
+
+ ... - Usual printf()-like parameters.
+
+ RETURNS: int - Number of characters stored in *pszStr.
+
+ HISTORY:
+ KeithMo 20-Sep-1993 Created.
+
+********************************************************************/
+int VxdSprintf( char * pszStr,
+ char * pszFmt,
+ ... )
+{
+ int cch;
+ va_list ArgPtr;
+
+ va_start( ArgPtr, pszFmt );
+ cch = VxdVsprintf( pszStr, pszFmt, ArgPtr );
+ va_end( ArgPtr );
+
+ return( cch );
+
+} // VxdSprintf
+
+
+/*******************************************************************
+
+ NAME: DbgAllocMem
+
+ SYNOPSIS: Keep track of all allocated memory so we can catch
+ memory leak when we unload
+ This is only on debug builds. On non-debug builds
+ this function doesn't exist: calls directly go to
+ CTEAllocMem.
+
+ ENTRY: ReqSize - how much memory is needed
+
+ RETURNS: PVOID - pointer to the memory block that client will
+ use directly.
+
+ HISTORY:
+ Koti 11-Nov-1994 Created.
+
+********************************************************************/
+
+//
+// IMPORTANT: we are undef'ing CTEAllocMem because we need to make a
+// call to the actual CTE function CTEAllocMem. That's why
+// this function and this undef are at the end of the file.
+//
+#undef CTEAllocMem
+PVOID DbgAllocMem( DWORD ReqSize )
+{
+
+ DWORD ActualSize;
+ PVOID pBuffer;
+ DbgMemBlkHdr *pMemHdr;
+ PVOID pRetAddr;
+
+
+ ActualSize = ReqSize + sizeof(DbgMemBlkHdr);
+ pBuffer = CTEAllocMem( ActualSize );
+ if ( !pBuffer )
+ {
+ return( NULL );
+ }
+
+ pMemHdr = (DbgMemBlkHdr *)pBuffer;
+
+ pMemHdr->Verify = DBG_MEMALLOC_VERIFY;
+ pMemHdr->ReqSize = ReqSize;
+ pRetAddr = &pMemHdr->Owner[0];
+
+//
+// now memory is allocated from NCBHandler, too where stack trace isn't more
+// than 2 deep! unifdef when memory leaks becomes an issue...
+//
+#if 0
+ _asm
+ {
+ push ebx
+ push ecx
+ push edx
+ mov ebx, pRetAddr
+ mov eax, ebp
+ mov ecx, 4
+ again:
+ mov edx, dword ptr [eax+4] ; return address
+ mov dword ptr [ebx], edx
+ mov eax, dword ptr [eax] ; previous frame pointer
+ add ebx, 4
+ dec ecx
+ cmp ecx, 0
+ je done
+ jmp again
+ done:
+ pop edx
+ pop ecx
+ pop ebx
+ }
+#endif
+
+ //
+ // BUGBUG: if ever ported to NT (or if chicago needs MP support),
+ // put spinlocks. (we will need a spinlock field in DbgMemBlkHdr struct).
+ //
+ InsertTailList(&DbgMemList, &pMemHdr->Linkage);
+
+ return( (PCHAR)pBuffer + sizeof(DbgMemBlkHdr) );
+}
+
+/*******************************************************************
+
+ NAME: DbgFreeMem
+
+ SYNOPSIS: This routine removes the memory block from our list and
+ frees the memory by calling the CTE function CTEFreeMem
+
+ ENTRY: pBufferToFree - memory to free (caller's buffer)
+
+ RETURNS: nothing
+
+ HISTORY:
+ Koti 11-Nov-1994 Created.
+
+********************************************************************/
+
+//
+// IMPORTANT: we are undef'ing CTEFreeMem because we need to make a
+// call to the actual CTE function CTEFreeMem. That's why
+// this function and this undef are at the end of the file.
+//
+#undef CTEMemFree
+#undef CTEFreeMem
+
+VOID DbgFreeMem( PVOID pBufferToFree )
+{
+
+ DbgMemBlkHdr *pMemHdr;
+
+
+ if ( !pBufferToFree )
+ {
+ return;
+ }
+
+ pMemHdr = (DbgMemBlkHdr *)((PCHAR)pBufferToFree - sizeof(DbgMemBlkHdr));
+
+ ASSERT( pMemHdr->Verify == DBG_MEMALLOC_VERIFY );
+
+ //
+ // change our signature: if we are freeing some memory twice, we'll know!
+ //
+ pMemHdr->Verify -= 1;
+
+ //
+ // BUGBUG: if ever ported to NT (or if chicago needs MP support),
+ // put spinlocks. (we will need a spinlock field in DbgMemBlkHdr struct).
+ //
+ RemoveEntryList(&pMemHdr->Linkage);
+
+ CTEFreeMem( (PVOID)pMemHdr );
+}
+
+#endif // DEBUG
+
diff --git a/private/ntos/nbt/vxd/vxdfile.asm b/private/ntos/nbt/vxd/vxdfile.asm
new file mode 100644
index 000000000..05c7e855d
--- /dev/null
+++ b/private/ntos/nbt/vxd/vxdfile.asm
@@ -0,0 +1,314 @@
+;/**********************************************************************/
+;/** Microsoft Windows/NT **/
+;/** Copyright(c) Microsoft Corp., 1993 **/
+;/**********************************************************************/
+
+;/*
+; vxdFile.asm
+;
+; Contains simple VXD File I/O routines for lmhosts support
+;
+; FILE HISTORY:
+; Johnl 06-Oct-1993 Created
+;
+;*/
+
+ .386p
+ include vmm.inc
+ include v86mmgr.inc
+ include dosmgr.inc
+ include opttest.inc
+ include netvxd.inc
+ include debug.inc
+
+;
+; Must match manifest in vxd\fileio.c
+;
+LMHOSTS_READ_BUFF_SIZE equ 256
+
+EXTRN _pMappedFilePath:DWORD
+EXTRN _pMappedFileBuff:DWORD
+EXTRN _pFileBuff:DWORD
+EXTRN _pFilePath:DWORD
+EXTRN _fInInit:DWORD
+
+EXTRN _GetInDosFlag:NEAR
+
+;****************************************************************************
+;** CheckInDos Macro
+;
+; Breaks if the Indos flag is set
+;
+; Uses EAX
+;
+CheckInDos MACRO
+IFDEF DEBUG
+ push eax
+ cmp _fInInit, 0 ; Can't call while initializing
+ jnz @f
+ call _GetInDosFlag
+ cmp ax, 0
+ je @f
+ Debug_Out "In dos flag set and about to make dos call!"
+@@:
+ pop eax
+ENDIF
+ENDM
+
+;****************************************************************************
+;** PushState Macro
+;
+; Saves the client state and begins nested exec block. ebx will contain
+; the current VM's client handle
+;
+; Uses ECX!!
+; EBX will be set to the client area
+;
+PushState MACRO
+
+ CheckInDos
+
+ push ebx
+ VMMcall Get_Cur_VM_Handle ; Puts current handle into EBX
+ mov ebx, [ebx.CB_Client_Pointer]
+
+ mov ecx, 0
+ VMMCall Begin_Critical_Section
+
+ Push_Client_State ; This pushes lots of crap
+ VMMcall Begin_Nest_V86_Exec
+ENDM
+
+;****************************************************************************
+;** PopState Macro
+;
+; Restores client state and ends the nested exec block
+;
+;
+PopState MACRO
+
+ VMMcall End_Nest_Exec
+ Pop_Client_State
+
+ VMMCall End_Critical_Section
+
+ pop ebx
+
+ENDM
+
+
+VxD_ICODE_SEG
+
+;****************************************************************************
+;** _VxdInitLmHostsSupport
+;
+; Allocates and maps memory for lmhosts support
+;
+; This is an Init time only routine
+;
+; Entry: [ESP+4] - Pointer to full path of file,
+; [ESP+8] - strlen of path
+;
+; Exit: TRUE if successful, FALSE otherwise
+;
+BeginProc _VxdInitLmHostsSupport
+ push esi
+ push edi
+
+ mov ecx, [esp+16]
+ add ecx, LMHOSTS_READ_BUFF_SIZE
+
+ push ecx ; save ecx for the map call
+ VMMCall _Allocate_Global_V86_Data_Area, <ecx, GVDAZeroInit>
+ pop ecx
+ or eax,eax ; zero if error
+ jz ILMH_50
+
+ push eax
+ mov _pFileBuff, eax ; Save the linear address so we can access
+ add eax, LMHOSTS_READ_BUFF_SIZE ; from the vxd
+ mov _pFilePath, eax
+ pop eax
+
+ shl eax, 12 ; Convert linear to V86 address
+ shr ax, 12
+
+ mov _pMappedFileBuff, eax
+ add eax, LMHOSTS_READ_BUFF_SIZE
+ mov _pMappedFilePath, eax
+
+ jmp ILMH_70
+
+ILMH_40:
+ ; Free allocated V86 global memory (how?)
+
+
+ILMH_50:
+ ; error occurred, eax already contains zero
+
+
+ILMH_70:
+ pop edi
+ pop esi
+ ret
+
+EndProc _VxdInitLmHostsSupport
+
+
+;****************************************************************************
+;** _VxdWindowsPath
+;
+; Gets a pointer to (null-terminated) path to the windows directory
+;
+; This is an Init time only routine
+;
+; Entry: nothing
+;
+; Exit: pointer to path to windows directory
+;
+BeginProc _VxdWindowsPath
+ PushState ; Pushes lots of crap
+
+ VmmCall Get_Config_Directory
+
+ mov eax, edx ; path is returned in edx
+
+ PopState ; now pop all that crap
+
+ ret
+
+EndProc _VxdWindowsPath
+
+VxD_ICODE_ENDS
+
+VxD_CODE_SEG
+
+;****************************************************************************
+;** _VxdFileOpen
+;
+; Opens a file
+;
+; Entry: [ESP+4] - Pointer to full path of file, path must be mapped
+; to v86 memory before calling this
+;
+; Exit: EAX will contain a handle to the openned file
+;
+BeginProc _VxdFileOpen
+
+ push edi
+ push esi
+
+ mov dx, word ptr [esp+12] ; Just the offset
+ mov di, word ptr [esp+14] ; Just the segment
+
+ PushState ; This pushes lots of crap
+
+ mov [ebx.Client_ax], 3d00h ; Open file, read only, share
+ mov [ebx.Client_dx], dx
+ mov [ebx.Client_ds], di
+
+ mov eax, 21h
+ VmmCall Exec_Int
+ test [ebx.Client_Flags], CF_Mask ; Carry set if error
+ jz VFO_6 ; Carry set if error
+
+ mov eax, 0 ; Failed to open the file
+ jmp VFO_10
+
+VFO_6:
+ movzx eax, [ebx.Client_ax] ; Handle of file
+
+VFO_10:
+ PopState
+
+ pop esi
+ pop edi
+ ret
+EndProc _VxdFileOpen
+
+
+;****************************************************************************
+;** _VxdFileRead
+;
+; Reads x bytes from a previously openned file
+;
+; Entry: [ESP+4] - Handle from _VxdFileOpen
+; [ESP+8] - Count of bytes to read
+; [ESP+12]- Mapped memory of destination buffer
+;
+; Exit: EAX will contain the number of bytes read, 0 if EOF or
+; an error occurred.
+;
+BeginProc _VxdFileRead
+
+ push edi
+ push esi
+
+ mov ax, [esp+12] ; File Handle
+ mov si, [esp+16] ; Bytes to read
+ mov dx, [esp+20] ; Just the offset
+ mov di, [esp+22] ; Just the segment
+
+ PushState ; Pushes lots of crap (uses cx)
+
+ mov [ebx.Client_ax], 3f00h ; File Read
+ mov [ebx.Client_bx], ax ; File Handle
+ mov [ebx.Client_cx], si ; Bytes to read
+ mov [ebx.Client_dx], dx ; Mapped destination buffer
+ mov [ebx.Client_ds], di
+
+ mov eax, 21h
+ VmmCall Exec_Int
+ test [ebx.Client_Flags], CF_Mask ; Carry set if error
+ jz VFR_6 ; Carry set if error
+
+ mov eax, 0 ; Failed to open the file
+ jmp VFR_7
+
+VFR_6:
+ movzx eax, [ebx.Client_ax] ; Bytes read
+
+VFR_7:
+
+VFR_10:
+ PopState
+
+ pop esi
+ pop edi
+ ret
+EndProc _VxdFileRead
+
+
+;****************************************************************************
+;** _VxdFileClose
+;
+; Closes a file openned with VxdOpenFile
+;
+; Entry: [ESP+4] - Handle from _VxdFileOpen
+;
+BeginProc _VxdFileClose
+
+ mov ax, [esp+4] ; File Handle
+
+ PushState ; Pushes lots of crap
+
+ mov [ebx.Client_ax], 3e00h ; File Close
+ mov [ebx.Client_bx], ax ; File Handle
+
+ mov eax, 21h
+ VmmCall Exec_Int
+ test [ebx.Client_Flags], CF_Mask ; Carry set if error
+ jz VFCL_10 ; Carry set if error
+
+ Debug_Out "VxdFileClose - Close failed"
+ mov eax, 0 ; Failed to close the file
+
+VFCL_10:
+ PopState
+
+ ret
+EndProc _VxdFileClose
+
+
+VxD_CODE_ENDS
+END
diff --git a/private/ntos/nbt/vxd/vxdisol.c b/private/ntos/nbt/vxd/vxdisol.c
new file mode 100644
index 000000000..7c5e6dfe1
--- /dev/null
+++ b/private/ntos/nbt/vxd/vxdisol.c
@@ -0,0 +1,4042 @@
+/**********************************************************************/
+/** Microsoft Windows/NT **/
+/** Copyright(c) Microsoft Corp., 1993 **/
+/**********************************************************************/
+
+/*
+ VxdIsol.c
+
+ This file roughly corresponds to ntisol.c and contains VxD specific
+ portions of the NBT driver
+
+ FILE HISTORY:
+ Johnl 15-Apr-1993 Created
+
+*/
+
+
+#include <nbtprocs.h>
+#include <nbtioctl.h>
+
+//
+// Used by VxdFindClientElement
+//
+enum CLIENT_TYPE
+{
+ CLIENT_BC,
+ CLIENT_LOCAL
+} ;
+
+//
+// Counts the number of items in the list Head
+//
+// Assumes pEntry is defined in the procedure
+//
+#define COUNT_ELEMENTS( Head, Count ) \
+ for ( pEntry = (Head).Flink ; \
+ pEntry != &(Head); \
+ pEntry = pEntry->Flink ) \
+ { \
+ (Count)++ ; \
+ }
+
+extern BOOLEAN CachePrimed;
+extern BOOL fInInit;
+
+//
+// this is used for AdapterStatus and FindName calls because we need to retain
+// the info, so can't have it as a local var (both these calls are synchronous
+// so need not worry about stomping on this memory)
+//
+TA_NETBIOS_ADDRESS tanb_global ;
+
+
+NCBERR VxdNameToClient( tDEVICECONTEXT * pDeviceContext,
+ CHAR * pName,
+ UCHAR * pNameNum,
+ tCLIENTELE * * ppClientEle ) ;
+
+//-------------------------------------------------------------------------
+//
+// Allocates and frees the SESS_SETUP_CONTEXT contents (not the context
+// itself).
+//
+TDI_STATUS AllocSessSetupContext( PSESS_SETUP_CONTEXT pSessSetupContext,
+ BOOL fListenOnStar ) ;
+void FreeSessSetupContext( PSESS_SETUP_CONTEXT pSessSetupContext ) ;
+
+NCBERR VxdInitSessionSetup( tDEVICECONTEXT * pDeviceContext,
+ TDI_REQUEST * pRequest,
+ PSESS_SETUP_CONTEXT * ppSessSetupContext,
+ NCB * pNCB ) ;
+
+BOOL VxdCopySessionStatus( tDEVICECONTEXT * pDeviceContext,
+ tCLIENTELE * pClientEle,
+ PSESSION_HEADER pSessionHeader,
+ PSESSION_BUFFER * ppSessionBuff,
+ ULONG * pRemainingSize ) ;
+
+//-------------------------------------------------------------------------
+//
+// NCB Reset context structures
+//
+//
+
+typedef struct
+{
+ //
+ // Number of active sessions we are waiting on to close
+ //
+ int cActiveSessions ;
+
+ //
+ // Number of active names we have to wait to finish deregistering
+ //
+ int cActiveNames ;
+
+ //
+ // NCB Error if reset failed (failed to resize session table for example)
+ //
+ UCHAR errncb ;
+} RESET_CONTEXT, *PRESET_CONTEXT ;
+
+NCBERR VxdResetContinue( tDEVICECONTEXT * pDeviceContext, NCB * pNCB ) ;
+
+#define DISCONNECT_TIMEOUT 15000
+
+//-------------------------------------------------------------------------
+//
+// Last valid NCB name and logical session number
+//
+#define MAX_NCB_NUMS 254
+#define ANY_NAME 255
+
+NTSTATUS
+PostInit_Proc();
+
+//******************* Pageable Routine Declarations ****************
+#ifdef ALLOC_PRAGMA
+#pragma CTEMakePageable(PAGE, PostInit_Proc)
+#endif
+//******************* Pageable Routine Declarations ****************
+
+/*******************************************************************
+
+ NAME: VxdDgramSend
+
+ SYNOPSIS: Vxd specific Send Datagram code
+
+ ENTRY: pDeviceContext - Device to send the datagram on
+ pNCB - NCB that contains the datagram data/dest
+
+ RETURNS: NT_SUCCESS if successful, error otherwise
+
+ NOTES:
+
+ HISTORY:
+ Johnl 19-Apr-1993 Created
+
+********************************************************************/
+
+NCBERR VxdDgramSend( tDEVICECONTEXT * pDeviceContext, NCB * pNCB )
+{
+ NTSTATUS status;
+ LONG lSentLength;
+ TDI_REQUEST Request;
+ tDGRAMHDR *pDgramHdr;
+ tCLIENTELE *pClientEle;
+ char *pName ;
+ NCBERR errNCB ;
+ TDI_CONNECTION_INFORMATION SendInfo ;
+ TA_NETBIOS_ADDRESS tanb ;
+
+
+ errNCB = VxdFindClientElement( pDeviceContext,
+ pNCB->ncb_num,
+ &pClientEle,
+ CLIENT_LOCAL ) ;
+ if ( errNCB )
+ {
+ DbgPrint("VxdDgramSend: VxdFindClientElement Failed\r\n") ;
+ return errNCB ;
+ }
+
+ ASSERT( pClientEle->Verify == NBT_VERIFY_CLIENT ) ;
+
+ if ( pClientEle->fDeregistered )
+ return NRC_NOWILD ;
+
+ //
+ // If broadcast, then use "*" for destination name
+ //
+ if ( (pNCB->ncb_command & ~ASYNCH) == NCBDGSENDBC )
+ {
+ //
+ // Name must stay valid after call
+ //
+ static char BcastName[NCBNAMSZ] = "* " ;
+ pName = BcastName ;
+ }
+ else
+ {
+ pName = pNCB->ncb_callname ;
+ }
+
+ //
+ // Initialize the transport address
+ //
+ // It's Ok to pass automatic variables to NbtSendDatagram,
+ // the necessary data is copied out before returning
+ //
+ InitNBTDIConnectInfo( &SendInfo, &tanb, pName ) ;
+ Request.Handle.AddressHandle = pClientEle;
+
+ status = NbtSendDatagram(
+ &Request,
+ &SendInfo,
+ pNCB->ncb_length,
+ &lSentLength,
+ pNCB->ncb_buffer, // user data
+ pDeviceContext,
+ (PIRP) pNCB );
+
+ errNCB = MapTDIStatus2NCBErr( status ) ;
+
+ if ( errNCB != NRC_GOODRET && errNCB != NRC_PENDING)
+ {
+ DbgPrint("VxdDgramSend - returning ncb status 0x" ) ;
+ DbgPrintNum( (ULONG) errNCB ) ;
+ DbgPrint("\r\n") ;
+ }
+ else
+ {
+ //
+ // Since NbtSendDatagram always buffers datagram sends, we need to
+ // complete the NCB here since NbtSendDatagram will not complete
+ // the data gram
+ //
+ CTEIoComplete(pNCB,status,pNCB->ncb_length);
+ }
+
+ return errNCB ;
+}
+
+/*******************************************************************
+
+ NAME: VxdDgramReceive
+
+ SYNOPSIS: Vxd specific Datagram Receive code
+
+ ENTRY: pDeviceContext - Device to send the datagram on
+ pNCB - NCB that contains the datagram data/dest
+
+ RETURNS: NT_SUCCESS if successful, error otherwise
+
+ NOTES: For a receive datagram, the name number is who we want to
+ receive to, and the call name will be set to who we
+ received from. The name number may be 0xff to indicate
+ receive to any name from anyone.
+
+ HISTORY:
+ Johnl 19-Apr-1993 Created
+
+********************************************************************/
+
+NCBERR VxdDgramReceive( tDEVICECONTEXT * pDeviceContext, NCB * pNCB )
+{
+ TDI_REQUEST Request;
+ ULONG ReceivedLength;
+ tCLIENTELE * pClientEle ;
+ NCBERR errNCB ;
+ TDI_CONNECTION_INFORMATION RcvInfo ;
+ TDI_CONNECTION_INFORMATION SendInfo ;
+ NTSTATUS status ;
+
+ if ( pNCB->ncb_num != ANY_NAME )
+ {
+ //
+ // For the RcvBC case, this just confirms the ncb_num is valid, the
+ // pClientEle is replaced with the broadcast client element (mif
+ // tests invalid ncb_nums with broadcasts).
+ //
+ if ( errNCB = VxdFindClientElement( pDeviceContext,
+ pNCB->ncb_num,
+ &pClientEle,
+ CLIENT_LOCAL ) )
+ {
+ return errNCB ;
+ }
+
+ if ( pClientEle->fDeregistered )
+ return NRC_NOWILD ;
+
+ if ( (pNCB->ncb_command & ~ASYNCH) == NCBDGRECVBC )
+ {
+ if ( errNCB = VxdFindClientElement( pDeviceContext,
+ pNCB->ncb_num,
+ &pClientEle,
+ CLIENT_BC ) )
+ if ( errNCB )
+ return NRC_NAMERR ;
+ }
+
+ Request.Handle.AddressHandle = pClientEle ;
+
+ status = NbtReceiveDatagram(
+ &Request,
+ NULL, //pTdiRequest->ReceiveDatagramInformation,
+ NULL, //pTdiRequest->ReturnDatagramInformation,
+ pNCB->ncb_length,
+ &ReceivedLength,
+ pNCB->ncb_buffer, // user data
+ pDeviceContext,
+ pNCB );
+ if ( status == STATUS_PENDING )
+ return NRC_PENDING ;
+ }
+ else
+ {
+ tRCVELE * pRcvEle = (tRCVELE *)CTEAllocMem(sizeof(tRCVELE));
+ if (!pRcvEle)
+ return NRC_NORES ;
+
+ pRcvEle->pIrp = pNCB ;
+ pRcvEle->ReceiveInfo = NULL ;
+ pRcvEle->ReturnedInfo = NULL;
+ pRcvEle->RcvLength = pNCB->ncb_length ;
+ pRcvEle->pRcvBuffer = pNCB->ncb_buffer ;
+
+ InsertTailList( &pDeviceContext->RcvDGAnyFromAnyHead,
+ &pRcvEle->Linkage );
+
+ return NRC_PENDING ;
+ }
+
+ //
+ // Status should always be pending or error
+ //
+ ASSERT( status != TDI_SUCCESS ) ;
+ return MapTDIStatus2NCBErr( status ) ;
+}
+
+/*******************************************************************
+
+ NAME: VxdCall
+
+ SYNOPSIS: Attempts to setup a session with the corresponding listen
+
+ ENTRY: pDeviceContext - Adapter to call on
+ pNCB - NCB that contains the call command
+
+ RETURNS:
+
+ NOTES: Before we can do the listen we must first open the
+ connection and associate the address.
+
+ The reserve field of the NCB is used as a SESS_SETUP_CONTEXT
+ structure
+
+ HISTORY:
+ Johnl 14-May-1993 Created
+
+********************************************************************/
+
+NCBERR VxdCall( tDEVICECONTEXT * pDeviceContext, NCB * pNCB )
+{
+ NTSTATUS status;
+ NCBERR errNCB ;
+ TDI_REQUEST Request;
+ PSESS_SETUP_CONTEXT pSessSetupContext = NULL ;
+
+ if ( ( pNCB->ncb_name[0] == '*' )
+ || ( pNCB->ncb_callname[0] == '*' ) )
+ {
+ return NRC_NOWILD ;
+ }
+
+ if ( errNCB = VxdInitSessionSetup( pDeviceContext,
+ &Request,
+ &pSessSetupContext,
+ pNCB ))
+ {
+ return errNCB ;
+ }
+
+ status = NbtConnect( &Request,
+ 0, // Use system timeout
+ pSessSetupContext->pRequestConnect,
+ pSessSetupContext->pReturnConnect,
+ pNCB
+ );
+
+ if ( !NT_SUCCESS(status) )
+ {
+ VxdTearDownSession( pDeviceContext,
+ (tCONNECTELE*)Request.Handle.ConnectionContext,
+ pSessSetupContext,
+ NULL ) ;
+ }
+
+ return MapTDIStatus2NCBErr( status ) ;
+}
+
+/*******************************************************************
+
+ NAME: VxdSend
+
+ SYNOPSIS: Sends a netbios request
+
+ ENTRY: pDeviceContext - Adapter to call on
+ pNCB - NCB that contains the send command
+
+ EXIT:
+
+ RETURNS:
+
+ NOTES: pNCB->ncb_lsn - Session number to Send on
+
+ pNCB->ncb_reserved will contain a pointer to a tSESSIONHDR
+ for this NCB (freed in VxdIoComplete).
+
+ No-ack sends are treated like normal sends.
+
+ HISTORY:
+ Johnl 8-Jun-1993 Created
+
+********************************************************************/
+
+NCBERR VxdSend( tDEVICECONTEXT *pDeviceContext, NCB * pNCB )
+{
+ NTSTATUS status ;
+ NCBERR errNCB ;
+ tCONNECTELE * pConnEle;
+ CTELockHandle OldIrq;
+ tLOWERCONNECTION * pLowerConn;
+ tSESSIONHDR * pHdr=NULL;
+ tBUFFERCHAINSEND SendBuff ;
+ TDI_REQUEST Request ;
+ ULONG SentSize ;
+ ULONG SendFlags = 0 ;
+ PSEND_CONTEXT pSendCont = (PSEND_CONTEXT) pNCB->ncb_reserve ;
+
+ ASSERT( sizeof(SEND_CONTEXT) <=
+ sizeof(pNCB->ncb_reserve)+sizeof(pNCB->ncb_event)) ;
+
+ if ( errNCB = VxdFindConnectElement( pDeviceContext,
+ pNCB,
+ &pConnEle ))
+ {
+ return errNCB ;
+ }
+
+ ASSERT( pConnEle->Verify == NBT_VERIFY_CONNECTION ) ;
+
+ pLowerConn = (tLOWERCONNECTION *)pConnEle->pLowerConnId ;
+
+ // check the state of the connection
+ if (pConnEle->state == NBT_SESSION_UP)
+ {
+ if ( GetSessionHdr( &pHdr ))
+ {
+ //
+ // If this is part of a chain send, set up the 2nd buffer
+ //
+ if ( ((pNCB->ncb_command & ~ASYNCH) == NCBCHAINSEND) ||
+ ((pNCB->ncb_command & ~ASYNCH) == NCBCHAINSENDNA) )
+ {
+ SendBuff.Length2 = *((WORD*)pNCB->ncb_callname) ;
+ SendBuff.pBuffer2 = *((PUCHAR*)(pNCB->ncb_callname+2)) ;
+ SendFlags |= CHAIN_SEND_FLAG ;
+ DbgPrint("VxdSend - Doing chain send\r\n") ;
+ }
+ else
+ {
+ SendBuff.Length2 = 0 ;
+ }
+
+ pHdr->Type = NBT_SESSION_MESSAGE ;
+ pHdr->Flags = NBT_SESSION_FLAGS ;
+ pHdr->UlongLength = htonl(pNCB->ncb_length + SendBuff.Length2) ;
+
+ pSendCont->pHdr = pHdr ;
+
+ //
+ // Only sends that can time out are put on the timeout list
+ //
+ if ( (pSendCont->STO = pConnEle->STO) != NCB_INFINITE_TIME_OUT )
+ {
+ InsertTailList( &NbtConfig.SendTimeoutHead, &pSendCont->ListEntry ) ;
+ }
+
+ SendBuff.tBuff.pDgramHdr = pHdr ;
+ SendBuff.tBuff.HdrLength = sizeof( *pHdr ) ;
+ SendBuff.tBuff.pBuffer = pNCB->ncb_buffer ;
+ SendBuff.tBuff.Length = pNCB->ncb_length ;
+
+#ifdef DEBUG
+ if ( !pNCB->ncb_length ) // Make sure 0 length buffers do
+ SendBuff.tBuff.pBuffer = NULL ; // the right thing
+#endif
+
+ Request.RequestNotifyObject = VxdIoComplete ;
+ Request.RequestContext = pNCB ;
+ Request.Handle.ConnectionContext = pConnEle->pLowerConnId->pFileObject ;
+
+ status = TdiSend( &Request,
+ 0,
+ (USHORT) SendBuff.tBuff.HdrLength +
+ SendBuff.tBuff.Length + SendBuff.Length2,
+ &SentSize,
+ (tBUFFER*) &SendBuff,
+ SendFlags ) ;
+ ASSERT( !NT_SUCCESS( status ) ||
+ (SentSize == (SendBuff.tBuff.HdrLength +
+ SendBuff.tBuff.Length + SendBuff.Length2)) ) ;
+
+ pLowerConn->BytesSent += SentSize;
+
+ return NRC_PENDING ;
+
+ //
+ // if TdiSend fails, it will call the completion routine (directly
+ // or eventually, Vxdiocomplete) which will remove this from the list
+ // so, don't remove it here also or we overwrite redir's code segment!!
+ //
+ // //
+ // // Remove from the timeout list if an error occurred
+ // //
+ // if ( !NT_SUCCESS( status ) &&
+ // pConnEle->STO != NCB_INFINITE_TIME_OUT )
+ // {
+ // RemoveEntryList( &pSendCont->ListEntry ) ;
+ // }
+ }
+ else
+ {
+ status = STATUS_INSUFFICIENT_RESOURCES ;
+ goto ErrorExit ;
+ }
+ }
+ else
+ {
+ status = TDI_INVALID_CONNECTION ;
+ }
+
+ if ( !NT_SUCCESS( status ) )
+ goto ErrorExit ;
+
+
+ return MapTDIStatus2NCBErr( status ) ;
+
+ErrorExit:
+ if ( pHdr )
+ FreeSessionHdr( pHdr ) ;
+
+ DbgPrint("VxdSend returning NCB error: 0x") ;
+ DbgPrintNum( MapTDIStatus2NCBErr( status ) ) ; DbgPrint("\r\n") ;
+
+ return MapTDIStatus2NCBErr( status ) ;
+}
+
+/*******************************************************************
+
+ NAME: VxdReceiveAny
+
+ SYNOPSIS: Handles a request to accept data from any open session
+
+ ENTRY: pDeviceContext - Adapter to call on
+ pNCB - NCB that contains the receive command
+
+ EXIT:
+
+ RETURNS:
+
+ NOTES: pNCB->ncb_lsn - Session set to who to receive from if
+ an indication is found
+
+ The most common case (for WFW rdr) is to Receive on
+ a particular name number w/o any waiting connections
+
+ HISTORY:
+ Johnl 8-Jun-1993 Created
+
+********************************************************************/
+
+NCBERR VxdReceiveAny( tDEVICECONTEXT *pDeviceContext, NCB * pNCB )
+{
+ NTSTATUS status;
+ NCBERR errNCB ;
+ tLOWERCONNECTION * pLowerConn;
+ tCLIENTELE * pClientEle = NULL ;
+ PLIST_ENTRY pEntry, pHead ;
+
+#ifdef DEBUG
+ DbgPrint("VxdReceiveAny posted: Ncb length, Rcv Buff Address: 0x") ;
+ DbgPrintNum( pNCB->ncb_length ) ; DbgPrint(", 0x") ;
+ DbgPrintNum( (ULONG) pNCB->ncb_buffer ) ; DbgPrint("\r\n") ;
+#endif
+
+ //
+ // If they've given us a name number to receive on, find it
+ //
+ if ( pNCB->ncb_num != ANY_NAME )
+ {
+ if ( errNCB = VxdFindClientElement( pDeviceContext,
+ pNCB->ncb_num,
+ &pClientEle,
+ CLIENT_LOCAL ) )
+ {
+ DbgPrint("VxdReceiveAny - Couldn't find name number\r\n") ;
+ return errNCB ;
+ }
+
+ if ( !pClientEle->fDeregistered )
+ {
+ if ( IsListEmpty( &pDeviceContext->PartialRcvHead ) )
+ {
+ goto QueueRcv ;
+ }
+ }
+ else
+ {
+ return NRC_NOWILD ;
+ }
+ }
+ else
+ {
+ if ( IsListEmpty( &pDeviceContext->PartialRcvHead ) )
+ {
+ goto QueueRcv ;
+ }
+ }
+
+ //
+ // Scan for all active sessions looking for one that has indicated
+ // data that will satisfy this ReceiveAny
+ //
+ pHead = &pDeviceContext->PartialRcvHead ;
+ pEntry = pHead->Flink ;
+ ASSERT( pEntry );
+ while ( pEntry != pHead )
+ {
+ DbgPrint("VxdReceiveAny: scanning lower connections for partial receive\r\n") ;
+ pLowerConn = CONTAINING_RECORD( pEntry, tLOWERCONNECTION, PartialRcvList ) ;
+
+ ASSERT( pLowerConn->State < NBT_DISCONNECTING );
+ //
+ // If Receive any from any, then the first one we find
+ // will work, otherwise compare the names
+ //
+
+ if ( pNCB->ncb_num == ANY_NAME )
+ break ;
+
+ else
+ {
+ if ( CTEMemCmp( pClientEle->pAddress->pNameAddr->Name,
+ pLowerConn->pUpperConnection->pClientEle->
+ pAddress->pNameAddr->Name,
+ NETBIOS_NAME_SIZE ) == NETBIOS_NAME_SIZE )
+ {
+ break ;
+ }
+ }
+
+ pEntry = pEntry->Flink ;
+ }
+
+ if ( pEntry != pHead )
+ {
+ DbgPrint("VxdReceiveAny: Found partial receive, calling VxdReceive\r\n") ;
+
+ ASSERT (pLowerConn->fOnPartialRcvList == TRUE);
+ RemoveEntryList( &pLowerConn->PartialRcvList ) ;
+ pLowerConn->fOnPartialRcvList = FALSE;
+ InitializeListHead(&pLowerConn->PartialRcvList);
+
+ //
+ // Now find the session number this receive is taking place on
+ //
+ if ( errNCB = VxdFindLSN( pDeviceContext,
+ pLowerConn->pUpperConnection,
+ &pNCB->ncb_lsn ))
+ {
+ return errNCB ;
+ }
+
+ return VxdReceive( pDeviceContext, pNCB, FALSE ) ;
+ }
+ else
+ {
+ //
+ // Nothing active so queue it
+ //
+ PRCV_CONTEXT prcvCont ;
+
+QueueRcv:
+ if ( !GetRcvContext( &prcvCont ))
+ return NRC_NORESOURCES ;
+
+ InitRcvContext( prcvCont, NULL, pNCB ) ;
+ InitNDISBuff( &prcvCont->ndisBuff,
+ pNCB->ncb_buffer,
+ pNCB->ncb_length,
+ NULL ) ;
+ prcvCont->usFlags = TDI_RECEIVE_NORMAL;
+ *((PRCV_CONTEXT*)&pNCB->ncb_reserve) = prcvCont ;
+
+ if ( pNCB->ncb_num != ANY_NAME )
+ {
+ ASSERT( pClientEle != NULL ) ;
+ InsertTailList( &pClientEle->RcvAnyHead,
+ &prcvCont->ListEntry ) ;
+
+ return NRC_PENDING ;
+ }
+ else
+ {
+ InsertTailList( &pDeviceContext->RcvAnyFromAnyHead,
+ &prcvCont->ListEntry ) ;
+ }
+ }
+
+ return NRC_PENDING ;
+}
+
+/*******************************************************************
+
+ NAME: VxdReceive
+
+ SYNOPSIS: Worker for VxdReceive and VxdReceiveAny
+
+ ENTRY: pDeviceContext - Adapter to call on
+ pNCB - NCB that contains the receive command
+ fReceive - TRUE if we got here via a Receive ncb
+ - FALSE if we got here via a ReceiveAny ncb
+ EXIT:
+
+ RETURNS:
+
+ NOTES: pNCB->ncb_reserved will contain a pointer to a RCV_CONTEXT
+ for this NCB.
+
+ VxdReceiveAny calls this on an element where state==NBT_SESSION_UP
+ and StateRcv == PARTIAL_RCV, thus the receive context should
+ never be added to pConnele->RcvHead.
+
+ HISTORY:
+ Johnl 8-Jun-1993 Created
+
+********************************************************************/
+
+NCBERR VxdReceive( tDEVICECONTEXT * pDeviceContext, NCB * pNCB, BOOL fReceive )
+{
+ NTSTATUS status;
+ NCBERR errNCB ;
+ tCONNECTELE * pConnEle;
+ CTELockHandle OldIrq;
+ tLOWERCONNECTION * pLowerConn;
+ PRCV_CONTEXT prcvCont ;
+
+ if ( errNCB = VxdFindConnectElement( pDeviceContext,
+ pNCB,
+ &pConnEle ))
+ {
+ return errNCB ;
+ }
+
+ ASSERT( pConnEle->Verify == NBT_VERIFY_CONNECTION ) ;
+
+ pLowerConn = pConnEle->pLowerConnId;
+
+ DbgPrint("VxdReceive posted: Ncb length, Rcv buff Address: 0x") ;
+ DbgPrintNum( pNCB->ncb_length ) ; DbgPrint(", 0x") ;
+ DbgPrintNum( (ULONG) pNCB->ncb_buffer ) ; DbgPrint("\r\n") ;
+
+ //
+ // Setup the receive context tracker
+ //
+ if ( GetRcvContext( &prcvCont ))
+ {
+ InitRcvContext( prcvCont, pLowerConn, pNCB ) ;
+ InitNDISBuff( &prcvCont->ndisBuff,
+ pNCB->ncb_buffer,
+ pNCB->ncb_length,
+ NULL ) ;
+ prcvCont->RTO = pConnEle->RTO ;
+ prcvCont->usFlags = TDI_RECEIVE_NORMAL;
+
+ *((PRCV_CONTEXT*)&pNCB->ncb_reserve) = prcvCont ;
+
+ //
+ // If data is not available, queue the request, otherwise get the
+ // data
+ //
+ if ( pLowerConn->StateRcv != PARTIAL_RCV )
+ {
+ //
+ // Make sure a RcvAny didn't get to here
+ //
+ ASSERT( (pNCB->ncb_command & ~ASYNCH)== NCBRECV ) ;
+
+ if ( !pConnEle->Orig && fReceive )
+ {
+ prcvCont->usFlags = TDI_RECEIVE_NO_RESPONSE_EXP ;
+ }
+
+ InsertTailList(&pConnEle->RcvHead,
+ &prcvCont->ListEntry);
+
+ return NRC_PENDING ;
+ }
+ else
+ {
+ TDI_REQUEST Request ;
+ UINT cbReceiveLength ;
+ static USHORT usFlags = TDI_RECEIVE_NORMAL ;
+
+ DbgPrint("VxdReceive:A Rcv Buffer posted when data in the transport, InXport= 0x") ;
+ DbgPrintNum( pConnEle->BytesInXport ) ;
+ DbgPrint("\r\n") ;
+
+ pConnEle->OffsetFromStart = 0 ;
+
+ Request.RequestNotifyObject = CompletionRcv ;
+ Request.RequestContext = prcvCont ;
+ Request.Handle.ConnectionContext = pLowerConn->pFileObject ;
+
+ pConnEle->pIrpRcv = NULL ; // Buffer in the transport
+ pLowerConn->StateRcv = FILL_IRP ;
+ RemoveEntryList( &pLowerConn->PartialRcvList ) ;
+ pLowerConn->fOnPartialRcvList = FALSE;
+ InitializeListHead(&pLowerConn->PartialRcvList);
+
+ cbReceiveLength = min( pNCB->ncb_length,
+ pConnEle->TotalPcktLen-pConnEle->BytesRcvd ) ;
+
+ //
+ // Don't pass zero length buffers to the transport
+ //
+ if ( !cbReceiveLength )
+ {
+ CompletionRcv( prcvCont, STATUS_SUCCESS, 0 ) ;
+ return NRC_GOODRET ;
+ }
+
+ //
+ // if it's an incoming session and this is a receive (as opp. to
+ // receive-any) then give transport a hint that there is no response
+ // coming back (trying to solve the raw-write-to-smb-server-perf problem)
+ //
+ if ( !pConnEle->Orig && fReceive )
+ {
+ usFlags = TDI_RECEIVE_NO_RESPONSE_EXP ;
+ }
+
+ status = TdiVxdReceive( &Request,
+ &usFlags,
+ &cbReceiveLength,
+ &prcvCont->ndisBuff ) ;
+
+ if ( status == STATUS_PENDING )
+ return NRC_PENDING ;
+
+ //
+ // Should always get pending unless a real error occurs
+ //
+ if ( !NT_SUCCESS(status) )
+ {
+ DbgPrint("VxdReceive - TdiReceive failed, error 0x") ;
+ DbgPrintNum( status ) ;
+ DbgPrint("\r\n") ;
+ CTEIoComplete( pNCB, status, 0 ) ;
+ }
+ }
+ }
+ else
+ return NRC_NORESOURCES ;
+
+ return MapTDIStatus2NCBErr( status ) ;
+}
+
+/*******************************************************************
+
+ NAME: VxdHangup
+
+ SYNOPSIS: Sets up a session Hangup
+
+ ENTRY: pDeviceContext -
+ pNCB - NCB that contains Hangup command
+
+ RETURNS:
+
+ NOTES: The code is similar to VxdDisconnectHandler. If this
+ changes, the VxdDisconnectHandler will probably have to
+ change
+
+ HISTORY:
+ Johnl 12-Jul-1993 Created
+
+********************************************************************/
+
+NCBERR VxdHangup( tDEVICECONTEXT * pDeviceContext, NCB * pNCB )
+{
+ TDI_STATUS tdistatus ;
+ tCONNECTELE * pConnEle ;
+ NCBERR errNCB ;
+ TDI_REQUEST Request ;
+ ULONG TimeOut = DISCONNECT_TIMEOUT ;
+ tCLIENTELE * pClientEle ;
+ tLOWERCONNECTION * pLowerConn;
+
+ if ( errNCB = VxdFindConnectElement( pDeviceContext,
+ pNCB,
+ &pConnEle ))
+ {
+ //
+ // If the session was already closed but the client hasn't been
+ // notified, notify them now
+ //
+ if ( errNCB == NRC_SCLOSED )
+ {
+ CTEIoComplete( pNCB, STATUS_SUCCESS, 0 ) ;
+ errNCB = NRC_GOODRET ;
+ }
+
+ return errNCB ;
+ }
+
+ ASSERT( (pConnEle->Verify == NBT_VERIFY_CONNECTION) ||
+ (pConnEle->Verify == NBT_VERIFY_CONNECTION_DOWN)) ;
+
+ if ( tdistatus = VxdCompleteSessionNcbs( pDeviceContext, pConnEle ) )
+ {
+ DbgPrint("VxdHangup: Error return from VxdCompleteSessionNcbs\r\n") ;
+ }
+
+ if ( pClientEle = pConnEle->pClientEle )
+ {
+ ASSERT( pClientEle->Verify == NBT_VERIFY_CLIENT ||
+ pClientEle->Verify == NBT_VERIFY_CLIENT_DOWN ) ;
+ }
+
+ pLowerConn = pConnEle->pLowerConnId ;
+ if ( pLowerConn &&
+ (pLowerConn->fOnPartialRcvList == TRUE) &&
+ pLowerConn->StateRcv == PARTIAL_RCV )
+ {
+ RemoveEntryList( &pLowerConn->PartialRcvList ) ;
+ pLowerConn->fOnPartialRcvList = FALSE;
+ InitializeListHead(&pLowerConn->PartialRcvList);
+ }
+
+ Request.Handle.ConnectionContext = pConnEle ;
+ tdistatus = NbtDisconnect( &Request,
+ &TimeOut,
+ TDI_DISCONNECT_RELEASE,
+ NULL,
+ NULL,
+ NULL ) ;
+ if ( tdistatus && tdistatus != TDI_PENDING )
+ {
+ DbgPrint("VxdHangup: Warning: NbtDisconnect returned error\r\n") ;
+ }
+
+ tdistatus = NbtCloseConnection( &Request,
+ NULL,
+ pDeviceContext,
+ NULL ) ;
+ if ( tdistatus && tdistatus != TDI_PENDING )
+ {
+ DbgPrint("VxdHangup: Warning: NbtCloseConnection returned error\r\n") ;
+ }
+
+ tdistatus = NbtDisassociateAddress( &Request ) ;
+ if ( tdistatus )
+ {
+ DbgPrint("VxdHangup: NbtDisassociateAddress returned 0x") ;
+ DbgPrintNum( tdistatus ) ; DbgPrint("\r\n") ;
+ }
+
+ REQUIRE( NBUnregister( pDeviceContext, pNCB->ncb_lsn, NB_SESSION )) ;
+
+ //
+ // If this name has been deleted but there were active sessions, check
+ // to see if this is the last session, if so, delete the name
+ //
+
+ if ( pClientEle &&
+ pClientEle->fDeregistered &&
+ !ActiveSessions(pClientEle) )
+ {
+ UCHAR NameNum ;
+ if ( !VxdFindNameNum( pDeviceContext, pClientEle->pAddress, &NameNum ))
+ {
+ (void) VxdCleanupAddress( pDeviceContext,
+ NULL,
+ pClientEle,
+ NameNum,
+ TRUE ) ;
+ }
+ }
+
+ CTEIoComplete( pNCB, STATUS_SUCCESS, 0 ) ;
+
+ return NRC_GOODRET ;
+}
+
+/*******************************************************************
+
+ NAME: VxdListen
+
+ SYNOPSIS: Sets up a session listen
+
+ ENTRY: pDeviceContext -
+ pNCB - NCB that contains listen command
+
+ RETURNS:
+
+ NOTES: Before we can do the listen we must first open the
+ connection and associate the address.
+
+ The reserve field of the NCB is used as a SESS_SETUP_CONTEXT
+ structure
+
+ HISTORY:
+ Johnl 14-May-1993 Created
+
+********************************************************************/
+
+NCBERR VxdListen( tDEVICECONTEXT * pDeviceContext, NCB * pNCB )
+{
+ NTSTATUS status;
+ NCBERR errNCB ;
+ TDI_REQUEST Request;
+ PSESS_SETUP_CONTEXT pSessSetupContext = NULL ;
+
+ if ( errNCB = VxdInitSessionSetup( pDeviceContext,
+ &Request,
+ &pSessSetupContext,
+ pNCB ))
+ {
+ return errNCB ;
+ }
+
+ status = NbtListen( &Request,
+ TDI_QUERY_ACCEPT,
+ *pNCB->ncb_callname != '*' ?
+ pSessSetupContext->pRequestConnect : NULL,
+ pSessSetupContext->pReturnConnect,
+ pNCB
+ );
+
+ if ( !NT_SUCCESS( status ) )
+ {
+ VxdTearDownSession( pDeviceContext,
+ Request.Handle.ConnectionContext,
+ pSessSetupContext,
+ NULL ) ;
+ }
+
+ return MapTDIStatus2NCBErr( status ) ;
+}
+
+/*******************************************************************
+
+ NAME: VxdOpenName
+
+ SYNOPSIS: Creates an Address object in response to AddName or
+ AddGroupName.
+
+ ENTRY: pDeviceContext - Device name is being added to
+ pNCB - NCB AddName submission
+
+ RETURNS: STATUS_SUCCESS if successful, error code otherwise
+
+ NOTES:
+
+ HISTORY:
+ Johnl 20-Apr-1993 Created
+
+********************************************************************/
+
+NCBERR VxdOpenName( tDEVICECONTEXT * pDeviceContext, NCB * pNCB )
+{
+ NTSTATUS status ;
+ TDI_REQUEST tdiRequest ;
+ TDI_ADDRESS_NETBIOS tdiaddr ;
+
+ if ( pNCB->ncb_name[0] == '*' ||
+ pNCB->ncb_name[0] == '\0' )
+ {
+ return NRC_NOWILD ;
+ }
+
+ //
+ // Fill in the TDI structures appropriately
+ //
+ switch ( pNCB->ncb_command & ~ASYNCH )
+ {
+ case NCBADDGRNAME:
+ tdiaddr.NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_GROUP ;
+ break ;
+
+ case NCBADDNAME:
+ tdiaddr.NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_UNIQUE ;
+ break ;
+
+ default:
+ ASSERTMSG("VxdOpenName: Unexpected command type!\n", FALSE ) ;
+ return NRC_SYSTEM ;
+ }
+
+ CTEMemCopy( tdiaddr.NetbiosName,
+ pNCB->ncb_name,
+ sizeof(pNCB->ncb_name) ) ;
+
+ status = NbtOpenAddress( &tdiRequest,
+ &tdiaddr,
+ pDeviceContext->IpAddress,
+ NULL, // Security descriptor
+ pDeviceContext,
+ pNCB ) ;
+ if ( NT_SUCCESS( status ))
+ {
+ //
+ // Set our event handler to catch "Receive Any" and "Receve
+ // Any From Any" NCBs
+ //
+ REQUIRE( !NbtSetEventHandler( (tCLIENTELE*)tdiRequest.Handle.AddressHandle,
+ TDI_EVENT_RECEIVE,
+ ReceiveAnyHandler,
+ (tCLIENTELE*)tdiRequest.Handle.AddressHandle )) ;
+ //
+ // Set an event handler to cleanup up Netbios specific stuff on
+ // disconnect
+ //
+ REQUIRE( !NbtSetEventHandler( (tCLIENTELE*)tdiRequest.Handle.AddressHandle,
+ TDI_EVENT_DISCONNECT,
+ VxdDisconnectHandler,
+ (tCLIENTELE*)tdiRequest.Handle.AddressHandle)) ;
+ }
+
+ //
+ // If we open a non-unique name twice (such as a group name) then
+ // NbtOpenAddress doesn't complete the IRP it just returns success.
+ //
+ if ( status == TDI_SUCCESS )
+ {
+ CTEIoComplete( pNCB, status, (ULONG) tdiRequest.Handle.AddressHandle ) ;
+ }
+
+ return MapTDIStatus2NCBErr( status ) ;
+}
+
+
+/*******************************************************************
+
+ NAME: VxdCloseName
+
+ SYNOPSIS: Called in response to a Netbios Delete Name request
+
+ ENTRY: pDeviceContext - Device name should be deleted from
+ pNCB - Netbios Delete name submission
+
+ RETURNS: STATUS_SUCCESS if successful, error code otherwise
+
+ NOTES:
+
+ HISTORY:
+ Johnl 23-Apr-1993 Created
+
+********************************************************************/
+
+NCBERR VxdCloseName( tDEVICECONTEXT * pDeviceContext, NCB * pNCB )
+{
+ tCLIENTELE * pClientEle ;
+ TDI_STATUS tdistatus ;
+ UCHAR NameNum ;
+ NCBERR errNCB ;
+
+
+ if ( pNCB->ncb_name[0] == '*' ||
+ pNCB->ncb_name[0] == '\0' )
+ {
+ return NRC_NOWILD ;
+ }
+
+ if ( errNCB = VxdNameToClient( pDeviceContext,
+ pNCB->ncb_name,
+ &NameNum,
+ &pClientEle ))
+ {
+ return errNCB ;
+ }
+
+ //
+ // If any sessions are open on this name, delay deletion till last name is
+ // closed
+ //
+ if ( ActiveSessions( pClientEle ) )
+ {
+ VxdCleanupAddress( pDeviceContext, pNCB, pClientEle, NameNum, FALSE ) ;
+ CTEIoComplete( pNCB, STATUS_NRC_ACTSES, 0 ) ;
+ return NRC_GOODRET ;
+ }
+
+ //
+ // No open sessions so blow away the name
+ //
+ return VxdCleanupAddress( pDeviceContext, pNCB, pClientEle, NameNum, TRUE ) ;
+}
+
+/*******************************************************************
+
+ NAME: ActiveSessions
+
+ SYNOPSIS: Returns TRUE if pClientEle has any active sessions
+
+ ENTRY: pClientEle - Client element to check
+
+********************************************************************/
+
+BOOL ActiveSessions( tCLIENTELE * pClientEle )
+{
+ PLIST_ENTRY pHead, pEntry ;
+
+ pHead = &pClientEle->ConnectActive ;
+ pEntry = pClientEle->ConnectActive.Flink ;
+ while ( pHead != pEntry )
+ {
+ tCONNECTELE * pConnEle = CONTAINING_RECORD( pEntry, tCONNECTELE, Linkage ) ;
+
+ if ( pConnEle->state > NBT_ASSOCIATED )
+ {
+ return TRUE ;
+ }
+
+ pEntry = pEntry->Flink ;
+ }
+
+ return FALSE ;
+}
+
+/*******************************************************************
+
+ NAME: VxdCleanupAddress
+
+ SYNOPSIS: Prepares a name for deletion and optionally deletes it
+
+ ENTRY: pDeviceContext - Adapter we are dealing with
+ pNCB - Delete name NCB
+ pClientEle - Client of address element to delete
+ NameNum - Name number in table we are deleting
+ fDeleteAddress - TRUE if address should be deleted
+
+ EXIT: The address element will be marked as deregistered and all
+ non-session NCBs will be completed. The address element
+ may optionally be deleted also.
+
+ NOTES: This routine will complete pNCB as appropriate.
+
+ HISTORY:
+ Johnl 22-Sep-1993 Created
+
+********************************************************************/
+
+NCBERR VxdCleanupAddress( tDEVICECONTEXT * pDeviceContext,
+ NCB * pNCB,
+ tCLIENTELE * pClientEle,
+ UCHAR NameNum,
+ BOOL fDeleteAddress )
+{
+ TDI_REQUEST Request ;
+ NCBERR errNCB ;
+ tCLIENTELE * pClientEleBcast ;
+ TDI_STATUS tdistatus ;
+ USHORT NameType ;
+ PLIST_ENTRY pHead, pEntry ;
+ PLIST_ENTRY pNextEntry;
+ tLISTENREQUESTS * pListen ;
+ PRCV_CONTEXT prcvCont ;
+ tRCVELE * prcvEle ;
+
+ pClientEle->fDeregistered = TRUE ;
+
+ //
+ // Delete all outstanding listens on this name
+ //
+ while ( !IsListEmpty( &pClientEle->ListenHead ))
+ {
+ pEntry = RemoveHeadList( &pClientEle->ListenHead ) ;
+ pListen = CONTAINING_RECORD( pEntry, tLISTENREQUESTS, Linkage ) ;
+ CTEIoComplete( pListen->pIrp, STATUS_NETWORK_NAME_DELETED, 0 ) ;
+ CTEMemFree( pListen ) ;
+ }
+
+ //
+ // Delete all outstanding datagram receives on this name
+ //
+ while ( !IsListEmpty( &pClientEle->RcvDgramHead ))
+ {
+ pEntry = RemoveHeadList( &pClientEle->RcvDgramHead ) ;
+ prcvEle = CONTAINING_RECORD( pEntry, tRCVELE, Linkage ) ;
+ CTEIoComplete( prcvEle->pIrp, STATUS_NETWORK_NAME_DELETED, 0 ) ;
+ CTEMemFree( prcvEle ) ;
+ }
+
+ //
+ // Delete all outstanding datagram broadcast receives on this name number
+ //
+ errNCB = VxdFindClientElement( pDeviceContext,
+ 0,
+ &pClientEleBcast,
+ CLIENT_BC ) ;
+
+ if ( !errNCB )
+ {
+ //
+ // Scan the NCBs looking for a receive on this name number
+ //
+ pHead = &pClientEleBcast->RcvDgramHead ;
+ pEntry = pClientEleBcast->RcvDgramHead.Flink ;
+
+ while ( pEntry != pHead )
+ {
+ prcvEle = CONTAINING_RECORD( pEntry, tRCVELE, Linkage ) ;
+ pNextEntry = pEntry->Flink ;
+ if ( ((NCB*)prcvEle->pIrp)->ncb_num == NameNum )
+ {
+ RemoveEntryList( pEntry ) ;
+ CTEIoComplete( prcvEle->pIrp, STATUS_NETWORK_NAME_DELETED, 0 ) ;
+ CTEMemFree( prcvEle ) ;
+ }
+ pEntry = pNextEntry ;
+ }
+ }
+
+
+ //
+ // Delete all outstanding Receive Anys on this name
+ //
+ while ( !IsListEmpty( &pClientEle->RcvAnyHead ))
+ {
+ pEntry = RemoveHeadList( &pClientEle->RcvAnyHead ) ;
+ prcvCont = CONTAINING_RECORD( pEntry, RCV_CONTEXT, ListEntry ) ;
+ ASSERT( prcvCont->Signature == RCVCONT_SIGN ) ;
+ CTEIoComplete( prcvCont->pNCB, STATUS_NETWORK_NAME_DELETED, 0 ) ;
+ }
+
+ tdistatus = TDI_SUCCESS;
+ if ( fDeleteAddress )
+ {
+ Request.Handle.ConnectionContext = pClientEle ;
+ tdistatus = NbtCloseAddress( &Request,
+ NULL, //&RequestStatus,
+ pDeviceContext,
+ pNCB ) ;
+
+ if ( (tdistatus != TDI_PENDING) && pNCB )
+ CTEIoComplete( pNCB, tdistatus, 0 ) ;
+
+ REQUIRE( NBUnregister( pDeviceContext, NameNum, NB_NAME )) ;
+
+ DbgPrint("VxdCloseName: NBUnregistered:NameNum = 0x") ;
+ DbgPrintNum( NameNum ) ;
+ DbgPrint(" ClientEle = 0x") ;
+ DbgPrintNum( pClientEle ) ;
+ DbgPrint("\r\n") ;
+
+ if ( !NT_SUCCESS( tdistatus ))
+ {
+ DbgPrint("VxdCloseName: NbtCloseAddress failed with status 0x") ;
+ DbgPrintNum( tdistatus ) ; DbgPrint("\r\n") ;
+ }
+ }
+
+ return MapTDIStatus2NCBErr( tdistatus ) ;
+}
+
+/*******************************************************************
+
+ NAME: VxdAccept
+
+ SYNOPSIS: Accepts an indicated listen
+
+ ENTRY: pConnectElem - Upper part of connection we're about to
+ setup
+ pNCB - Original Listen request
+
+ RETURNS: TDI_SUCCESS if successful error code otherwise
+
+ NOTES:
+
+ HISTORY:
+ Johnl 27-May-1993 Created
+
+********************************************************************/
+
+TDI_STATUS VxdAccept( tCONNECTELE * pConnectElem, NCB * pNCB )
+{
+ TDI_REQUEST Request ;
+ PSESS_SETUP_CONTEXT pSessSetupCont = (PSESS_SETUP_CONTEXT) pNCB->ncb_reserve ;
+ TDI_STATUS status ;
+
+ Request.Handle.ConnectionContext = pConnectElem ;
+
+ status = NbtAccept( &Request,
+ pSessSetupCont->pRequestConnect,
+ pSessSetupCont->pReturnConnect,
+ NULL ) ;
+ if ( !NT_SUCCESS(status) )
+ {
+ DbgPrint( "VxdAccept: NbtAccept returned " ) ;
+ DbgPrintNum( status ) ;
+ DbgPrint("\r\n") ;
+ }
+
+ //
+ // It's OK if the accept is pending because it's just the
+ // session setup acknowledgement
+ //
+ if ( status == TDI_PENDING )
+ status = TDI_SUCCESS ;
+
+ return status ;
+}
+
+/*******************************************************************
+
+ NAME: VxdAdapterStatus
+
+ SYNOPSIS: Gets the requested adapter status
+
+ ENTRY: pDeviceContext - Adapter status to get
+ pNCB - Pointer to requesting NCB
+
+ EXIT:
+
+ NOTES:
+
+ HISTORY:
+ Johnl 10-Aug-1993 Created
+
+********************************************************************/
+
+NCBERR VxdAdapterStatus( tDEVICECONTEXT * pDeviceContext,
+ NCB * pNCB,
+ ULONG Ipaddr
+ )
+{
+ TDI_STATUS status ;
+ PADAPTER_STATUS pAdapterStatus ;
+ ULONG ActualSize;
+ ULONG Size = pNCB->ncb_length ;
+
+ //
+ // Ipaddr will always be 0 except in one case: if we came here
+ // via nbtstat -A
+ //
+ if ( !Ipaddr && *pNCB->ncb_callname == '*' )
+ {
+ //
+ // Get the local adapter status
+ //
+ DbgPrint("VxdAdapterStatus: AStat for local (*)\r\n") ;
+ status = NbtQueryAdapterStatus( pDeviceContext,
+ &pAdapterStatus,
+ &Size ) ;
+ if ( !status || status == TDI_BUFFER_OVERFLOW )
+ {
+ ActualSize = min( pNCB->ncb_length, Size ) ;
+ CTEMemCopy( pNCB->ncb_buffer,
+ pAdapterStatus,
+ ActualSize) ;
+ pNCB->ncb_length = ActualSize;
+
+ CTEFreeMem( pAdapterStatus ) ;
+ CTEIoComplete( pNCB, status, 0 ) ;
+
+ //
+ // Return a successful status (buffer overflow denoted
+ // in NCB)
+ //
+ status = NRC_GOODRET ;
+ }
+ }
+ else
+ {
+
+ ULONG IpAddrsList[2];
+
+ IpAddrsList[0] = Ipaddr;
+ IpAddrsList[1] = 0;
+
+ status = NbtSendNodeStatus( pDeviceContext,
+ pNCB->ncb_callname,
+ pNCB,
+ IpAddrsList,
+ 0,
+ NodeStatusDone);
+ }
+
+ return MapTDIStatus2NCBErr( status ) ;
+}
+
+/*******************************************************************
+
+ NAME: VxdFindName
+
+ SYNOPSIS: Gets the requested adapter status
+
+ ENTRY: pDeviceContext - Adapter status to get
+ pNCB - Pointer to requesting NCB
+
+ EXIT:
+
+ NOTES:
+
+ HISTORY:
+ Johnl 04-Oct-1993 Created
+
+********************************************************************/
+
+NCBERR VxdFindName( tDEVICECONTEXT * pDeviceContext, NCB * pNCB )
+{
+ TDI_STATUS status ;
+ TDI_CONNECTION_INFORMATION RequestInfo ;
+
+ DbgPrint("VxdFindName: Entered\r\n") ;
+ InitNBTDIConnectInfo( &RequestInfo, &tanb_global, pNCB->ncb_callname ) ;
+ status = NbtQueryFindName( &RequestInfo,
+ pDeviceContext,
+ pNCB,
+ FALSE ) ;
+
+ if ( status == STATUS_SUCCESS )
+ {
+ CTEIoComplete( pNCB, STATUS_SUCCESS, 0xffffffff ) ;
+ return STATUS_SUCCESS ;
+ }
+
+ return MapTDIStatus2NCBErr( status ) ;
+}
+/*******************************************************************
+
+ NAME: VxdSessionStatus
+
+ SYNOPSIS: Gets the requested Session status
+
+ ENTRY: pDeviceContext - Session status to get
+ pNCB - Pointer to requesting NCB
+
+ EXIT:
+
+ NOTES: VxdCopySessionStatus will automatically complete the NCB
+ if the buffer overflows. Otherwise we will.
+
+ HISTORY:
+ Johnl 23-Aug-1993 Created
+
+********************************************************************/
+
+NCBERR VxdSessionStatus( tDEVICECONTEXT * pDeviceContext, NCB * pNCB )
+{
+ TDI_STATUS status = STATUS_SUCCESS ;
+ PSESSION_HEADER pSessionHeader = (PSESSION_HEADER) pNCB->ncb_buffer ;
+ PSESSION_BUFFER pSessionBuff ;
+ ULONG RemainingSize = pNCB->ncb_length ;
+ tNAMEADDR * pNameAddr = NULL ;
+ tCLIENTELE * pClientEle = NULL ;
+ tCLIENTELE * pClientEleBcast = NULL ;
+ USHORT NameType ;
+ PLIST_ENTRY pEntry ;
+ UCHAR i ;
+ NCBERR errNCB ;
+
+ if ( RemainingSize < sizeof(SESSION_HEADER) )
+ {
+ CTEIoComplete( pNCB, STATUS_INVALID_BUFFER_SIZE, 0 ) ;
+ return NRC_GOODRET ;
+ }
+
+ pSessionHeader->sess_name = 0 ;
+ pSessionHeader->num_sess = 0 ;
+ pSessionHeader->rcv_dg_outstanding = 0 ;
+ pSessionHeader->rcv_any_outstanding = 0 ;
+
+ //
+ // For broadcast datagram statistics
+ //
+ errNCB = VxdFindClientElement( pDeviceContext,
+ 0,
+ &pClientEleBcast,
+ CLIENT_BC ) ;
+ if ( errNCB )
+ return errNCB ;
+
+ //
+ // Get all sessions?
+ //
+ if ( pNCB->ncb_name[0] == '*' )
+ {
+ for ( i = 1 ; i <= pDeviceContext->cMaxSessions ; i++ )
+ {
+ if ( pDeviceContext->pSessionTable[i] != NULL )
+ {
+ pClientEle = pDeviceContext->pSessionTable[i]->pClientEle ;
+
+ //
+ // Both normal receives and broadcast receives are
+ // kept on the same list
+ //
+ COUNT_ELEMENTS( pClientEle->RcvDgramHead,
+ pSessionHeader->rcv_dg_outstanding ) ;
+
+ COUNT_ELEMENTS( pClientEle->RcvAnyHead,
+ pSessionHeader->rcv_any_outstanding ) ;
+ }
+ }
+
+ //
+ // Only one broadcast client element per adapter
+ //
+ COUNT_ELEMENTS( pClientEleBcast->RcvDgramHead,
+ pSessionHeader->rcv_dg_outstanding ) ;
+
+ COUNT_ELEMENTS( pDeviceContext->RcvDGAnyFromAnyHead,
+ pSessionHeader->rcv_dg_outstanding ) ;
+
+ pSessionHeader->sess_name = 0xff ;
+
+ RemainingSize -= sizeof( SESSION_HEADER ) ;
+ pSessionBuff = (PSESSION_BUFFER) (pSessionHeader + 1) ;
+
+ //
+ // From this device context, traverse all of the Address elements
+ // and all of its Client elements and all of its Connect Elements
+ //
+ for ( pEntry = NbtConfig.AddressHead.Flink ;
+ pEntry != &NbtConfig.AddressHead && !status ;
+ pEntry = pEntry->Flink )
+ {
+ PLIST_ENTRY pEntryClient ;
+ tADDRESSELE * pAddrEle = CONTAINING_RECORD( pEntry,
+ tADDRESSELE,
+ Linkage ) ;
+ ASSERT( pAddrEle->Verify == NBT_VERIFY_ADDRESS ) ;
+
+ //
+ // Only get addresses for this adapter
+ //
+ if ( pAddrEle->pDeviceContext != pDeviceContext )
+ continue ;
+
+ for ( pEntryClient = pAddrEle->ClientHead.Flink ;
+ pEntryClient != &pAddrEle->ClientHead ;
+ pEntryClient = pEntryClient->Flink )
+ {
+ tCLIENTELE * pClientEle = CONTAINING_RECORD( pEntryClient,
+ tCLIENTELE,
+ Linkage ) ;
+ PLIST_ENTRY pEntryConn ;
+ ASSERT( pClientEle->Verify == NBT_VERIFY_CLIENT ||
+ pClientEle->Verify == NBT_VERIFY_CLIENT_DOWN ) ;
+
+ if (!VxdCopySessionStatus( pDeviceContext,
+ pClientEle,
+ pSessionHeader,
+ &pSessionBuff,
+ &RemainingSize ))
+ {
+ status = STATUS_BUFFER_OVERFLOW ;
+ break ;
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( errNCB = VxdNameToClient( pDeviceContext,
+ pNCB->ncb_name,
+ &pSessionHeader->sess_name,
+ &pClientEle ))
+ {
+ return errNCB ;
+ }
+
+ COUNT_ELEMENTS( pClientEle->RcvDgramHead,
+ pSessionHeader->rcv_dg_outstanding ) ;
+
+ COUNT_ELEMENTS( pClientEleBcast->RcvDgramHead,
+ pSessionHeader->rcv_dg_outstanding ) ;
+
+ COUNT_ELEMENTS( pDeviceContext->RcvDGAnyFromAnyHead,
+ pSessionHeader->rcv_dg_outstanding ) ;
+
+ COUNT_ELEMENTS( pClientEle->RcvAnyHead,
+ pSessionHeader->rcv_any_outstanding ) ;
+
+ RemainingSize -= sizeof( SESSION_HEADER ) ;
+ pSessionBuff = (PSESSION_BUFFER) (pSessionHeader + 1) ;
+ if ( !VxdCopySessionStatus( pDeviceContext,
+ pClientEle,
+ pSessionHeader,
+ &pSessionBuff,
+ &RemainingSize ))
+ {
+ status = STATUS_BUFFER_OVERFLOW ;
+ }
+ }
+
+ CTEIoComplete( pNCB,
+ status,
+ sizeof(SESSION_HEADER) +
+ pSessionHeader->num_sess * sizeof(SESSION_BUFFER) ) ;
+
+ return NRC_GOODRET ;
+}
+
+/*******************************************************************
+
+ NAME: VxdCopySessionStatus
+
+ SYNOPSIS: Copies all of the sessions associated with pClientEle
+
+ ENTRY: pDeviceContext - Adapter to use
+ pClientEle - Client to retrieve all sessions for
+ pSessionHeader - Session status header
+ pSessionBuff - Pointer to beginning of session buffers
+ pRemainingSize - Remaining size of buffer
+
+ RETURNS: TRUE if all session information was transferred,
+ FALSE if we ran out of buffer space
+
+ NOTES:
+
+ HISTORY:
+ Johnl 23-Aug-1993 Created
+
+********************************************************************/
+
+BOOL VxdCopySessionStatus( tDEVICECONTEXT * pDeviceContext,
+ tCLIENTELE * pClientEle,
+ PSESSION_HEADER pSessionHeader,
+ PSESSION_BUFFER * ppSessionBuff,
+ ULONG * pRemainingSize )
+{
+ PLIST_ENTRY pEntryConn ;
+ tCONNECTELE * pConnectEle ;
+
+ for ( pEntryConn = pClientEle->ConnectActive.Flink ;
+ pEntryConn != &pClientEle->ConnectActive ;
+ pEntryConn = pEntryConn->Flink )
+ {
+ PLIST_ENTRY pEntry ;
+ BOOL fFillRemote = FALSE ;
+ pConnectEle = CONTAINING_RECORD( pEntryConn,
+ tCONNECTELE,
+ Linkage ) ;
+ ASSERT( pConnectEle->Verify == NBT_VERIFY_CONNECTION ||
+ pConnectEle->Verify == NBT_VERIFY_CONNECTION_DOWN ) ;
+
+ if ( *pRemainingSize < sizeof(SESSION_BUFFER) )
+ {
+ return FALSE ;
+ }
+
+ *pRemainingSize -= sizeof(SESSION_BUFFER) ;
+ pSessionHeader->num_sess++ ;
+ (*ppSessionBuff)->rcvs_outstanding = 0 ;
+ (*ppSessionBuff)->sends_outstanding = 0 ; // Always 0
+ REQUIRE( !VxdFindLSN( pDeviceContext, pConnectEle, &(*ppSessionBuff)->lsn )) ;
+
+ COUNT_ELEMENTS( pConnectEle->RcvHead,
+ (*ppSessionBuff)->rcvs_outstanding ) ;
+
+ //
+ // Set the session state
+ //
+ switch ( pConnectEle->state )
+ {
+ case NBT_CONNECTING: // establishing Transport connection
+ if ( pConnectEle->Orig )
+ (*ppSessionBuff)->state = CALL_PENDING ;
+ else
+ (*ppSessionBuff)->state = LISTEN_OUTSTANDING ;
+ break ;
+
+ case NBT_SESSION_INBOUND: // waiting for a session request after tcp connectio
+ case NBT_SESSION_WAITACCEPT: // waiting for accept after a listen has been satis
+ (*ppSessionBuff)->state = LISTEN_OUTSTANDING ;
+ break ;
+
+ case NBT_SESSION_OUTBOUND: // waiting for a session response after tcp connecti
+ fFillRemote = TRUE ;
+ (*ppSessionBuff)->state = CALL_PENDING ;
+
+ case NBT_SESSION_UP: // got positive response
+ fFillRemote = TRUE ;
+ (*ppSessionBuff)->state = SESSION_ESTABLISHED ;
+ break ;
+
+ case NBT_DISCONNECTING: // sent a disconnect down to Tcp, but it hasn't comp
+ (*ppSessionBuff)->state = HANGUP_PENDING;
+ break ;
+
+ case NBT_DISCONNECTED: // a session has been disconnected but not closed wit
+ (*ppSessionBuff)->state = HANGUP_COMPLETE;
+ break ;
+
+ case NBT_IDLE: // Shouldn't be on ConnectActive list
+ case NBT_ASSOCIATED:
+ default:
+ ASSERT( FALSE ) ;
+ (*ppSessionBuff)->state = SESSION_ABORTED ;
+ break ;
+ }
+
+ //
+ // Copy local and/or remote name
+ //
+ CTEMemCopy( (*ppSessionBuff)->local_name,
+ pClientEle->pAddress->pNameAddr->Name,
+ NCBNAMSZ ) ;
+
+ if ( fFillRemote )
+ {
+ CTEMemCopy( (*ppSessionBuff)->remote_name,
+ pConnectEle->RemoteName,
+ NCBNAMSZ ) ;
+ }
+
+ (*ppSessionBuff)++ ;
+ }
+
+ return TRUE ;
+}
+
+/*******************************************************************
+
+ NAME: VxdReset
+
+ SYNOPSIS: Clears out the name tables and completes all outstanding NCBs
+
+ ENTRY: pDeviceContext - Adapter status to get
+ pNCB - Pointer to requesting NCB
+
+ EXIT:
+
+ NOTES: If a session is active then we have to wait till we disconnect
+ the connection before deleting the name. We keep count of the
+ active sessions and call the VxdResetContinue function after
+ all session disconnects have been completed.
+
+ It is assumed this is made as a "wait" call.
+
+ HISTORY:
+ Johnl 16-Aug-1993 Created
+
+********************************************************************/
+
+NCBERR VxdReset( tDEVICECONTEXT * pDeviceContext, NCB * pNCB )
+{
+ UCHAR i ;
+ TDI_STATUS tdistatus ;
+ PLIST_ENTRY pHead, pEntry ;
+ PRESET_CONTEXT pRstCont = (PRESET_CONTEXT) pNCB->ncb_reserve ;
+
+ pRstCont->cActiveSessions = 0 ;
+ pRstCont->cActiveNames = 0 ;
+ pRstCont->errncb = NRC_GOODRET ;
+
+ //
+ // Kill off all of the Receive any from any NCBs
+ //
+ while ( !IsListEmpty(&pDeviceContext->RcvAnyFromAnyHead))
+ {
+ PRCV_CONTEXT prcvCont ;
+ pEntry = RemoveHeadList( &pDeviceContext->RcvAnyFromAnyHead ) ;
+ prcvCont = CONTAINING_RECORD( pEntry, RCV_CONTEXT, ListEntry ) ;
+ ASSERT( prcvCont->Signature == RCVCONT_SIGN ) ;
+
+ CTEIoComplete( prcvCont->pNCB,
+ STATUS_CONNECTION_DISCONNECTED,
+ 0 ) ;
+ }
+
+ //
+ // Kill off all of the Receive any datagrams from any
+ //
+ while ( !IsListEmpty(&pDeviceContext->RcvDGAnyFromAnyHead))
+ {
+ tRCVELE * pRcvEle ;
+ pEntry = RemoveHeadList( &pDeviceContext->RcvDGAnyFromAnyHead ) ;
+ pRcvEle = CONTAINING_RECORD( pEntry, tRCVELE, Linkage ) ;
+ CTEIoComplete( pRcvEle->pIrp,
+ STATUS_NETWORK_NAME_DELETED, // NRC_NAMERR
+ 0 ) ;
+ CTEMemFree( pRcvEle ) ;
+ }
+
+ //
+ // Disconnect all sessions
+ //
+ for ( i = 1 ; i <= pDeviceContext->cMaxSessions ; i++ )
+ {
+ //
+ // This will also prevent any listens from being accepted on the
+ // connection
+ //
+ if ( pDeviceContext->pSessionTable[i] != NULL )
+ {
+ TDI_REQUEST Request ;
+ ULONG TimeOut = DISCONNECT_TIMEOUT ;
+ tCONNECTELE * pConnEle= pDeviceContext->pSessionTable[i] ;
+
+ Request.Handle.ConnectionContext = pConnEle ;
+ pRstCont->cActiveSessions++ ;
+ tdistatus = NbtDisconnect( &Request,
+ &TimeOut,
+ TDI_DISCONNECT_RELEASE,
+ NULL,
+ NULL,
+ pNCB ) ;
+
+ if ( tdistatus != TDI_PENDING )
+ {
+ pRstCont->cActiveSessions-- ;
+ tdistatus = NbtCloseConnection( &Request,
+ NULL,
+ pDeviceContext,
+ NULL ) ;
+ REQUIRE( NBUnregister( pDeviceContext, i, NB_SESSION )) ;
+ }
+ }
+ }
+
+ //
+ // If no active sessions, then go ahead and delete all the names
+ //
+ if ( !pRstCont->cActiveSessions )
+ {
+ pRstCont->cActiveSessions = -1 ;
+ return VxdResetContinue( pDeviceContext, pNCB ) ;
+ }
+
+ return NRC_GOODRET ;
+}
+
+/*******************************************************************
+
+ NAME: VxdResetContinue
+
+ SYNOPSIS: Finishes the reset after all sessions have been successfully
+ shutdown
+
+ ENTRY: pDeviceContext - Adapter status to get
+ pNCB - Pointer to requesting NCB
+
+ EXIT:
+
+ NOTES:
+
+ HISTORY:
+ Johnl 16-Aug-1993 Created
+
+********************************************************************/
+
+NCBERR VxdResetContinue( tDEVICECONTEXT * pDeviceContext, NCB * pNCB )
+{
+ UCHAR i ;
+ TDI_STATUS tdistatus ;
+ PLIST_ENTRY pHead, pEntry ;
+ PRESET_CONTEXT pRstCont = (PRESET_CONTEXT) pNCB->ncb_reserve ;
+ PNCB pNCBPerm ;
+
+ DbgPrint("VxdResetContinue entered\r\n") ;
+
+ //
+ // Now that all of the sessions have been disconnected, close each
+ // connection
+ //
+ for ( i = 1 ; i <= pDeviceContext->cMaxSessions ; i++ )
+ {
+ if ( pDeviceContext->pSessionTable[i] != NULL )
+ {
+ TDI_REQUEST Request ;
+ tCONNECTELE * pConnEle = pDeviceContext->pSessionTable[i] ;
+ Request.Handle.ConnectionContext = pConnEle ;
+
+ tdistatus = NbtCloseConnection( &Request,
+ NULL,
+ pDeviceContext,
+ NULL ) ;
+ REQUIRE( NBUnregister( pDeviceContext, i, NB_SESSION )) ;
+ }
+ }
+
+ //
+ // Delete all the names (including the permanent name)
+ //
+ for ( i = 0 ; i <= pDeviceContext->cMaxNames ; i++ )
+ {
+ if ( pDeviceContext->pNameTable[i] != NULL )
+ {
+ TDI_REQUEST Request ;
+
+ Request.Handle.ConnectionContext = pDeviceContext->pNameTable[i] ;
+ pRstCont->cActiveNames++ ;
+
+ tdistatus = NbtCloseAddress( &Request,
+ NULL, //&RequestStatus,
+ pDeviceContext,
+ pNCB ) ;
+ if ( tdistatus != TDI_PENDING )
+ pRstCont->cActiveNames-- ;
+
+ //
+ // Go ahead and remove the name from the table since nobody
+ // will be able to re-register with it since this is a "wait" cmd
+ //
+ REQUIRE( NBUnregister( pDeviceContext, i, NB_NAME )) ;
+
+ }
+ }
+
+ //
+ // Resize the session table If an error occurs, keep the old
+ // session table.
+ //
+ if ( pNCB->ncb_lsn != pDeviceContext->cMaxSessions )
+ {
+ UCHAR MaxSess = (UCHAR) pNCB->ncb_lsn ? pNCB->ncb_lsn : 6 ;
+ PVOID pSess = CTEAllocMem((USHORT)((MaxSess+1)*sizeof(tCONNECTELE*))) ;
+
+ if ( !pSess )
+ {
+ pRstCont->errncb = NRC_NORESOURCES ;
+ }
+ else
+ {
+ CTEFreeMem( pDeviceContext->pSessionTable ) ;
+ pDeviceContext->cMaxSessions = MaxSess ;
+ pDeviceContext->pSessionTable = pSess ;
+ CTEZeroMemory( &pDeviceContext->pSessionTable[0],
+ (pDeviceContext->cMaxSessions+1)*sizeof(tCONNECTELE*) ) ;
+ }
+ }
+
+ //
+ // Set current session/name numbers back to 1
+ //
+ pDeviceContext->iNcbNum = 1 ;
+ pDeviceContext->iLSNum = 1 ;
+
+ //
+ // re-add the permanent name for this adapter, non-fatal if it fails
+ //
+
+
+ if ( !NT_SUCCESS( NbtAddPermanentName( pDeviceContext )))
+ {
+ CDbgPrint( DBGFLAG_ERROR,
+ ("VxdResetContinue: Warning - Failed to add permanent name")) ;
+ }
+
+ if ( !pRstCont->cActiveNames )
+ CTEIoComplete( pNCB, NRC_GOODRET, 0 ) ;
+
+ return NRC_GOODRET ;
+}
+
+/*******************************************************************
+
+ NAME: VxdCancel
+
+ SYNOPSIS: Attempts to cancel the NCB pointed at by ncb_buffer
+
+ ENTRY: pDeviceContext - Adapter status to get
+ pNCB - Pointer to requesting NCB
+
+ EXIT:
+
+ NOTES:
+
+ HISTORY:
+ Johnl 18-Aug-1993 Created
+
+********************************************************************/
+
+NCBERR VxdCancel( tDEVICECONTEXT * pDeviceContext, NCB * pNCB )
+{
+ NCB * pNCBCancelled = (NCB*) pNCB->ncb_buffer ;
+ tCONNECTELE * pConnEle ;
+ tCLIENTELE * pClientEle ;
+ NCBERR errNCB = NRC_GOODRET ;
+ TDI_STATUS tdistatus ;
+ PLIST_ENTRY pHead, pEntry ;
+ USHORT NameType ;
+ tNAMEADDR * pNameAddr ;
+ tLISTENREQUESTS * pListen ;
+ PRCV_CONTEXT prcvCont ; // Used for session receives
+ tRCVELE * prcvEle ; // Used for Datagram receives
+
+ if ( pNCB->ncb_lana_num != pNCBCancelled->ncb_lana_num )
+ {
+ DbgPrint("VxdCancel: Attempt to cancel NCB w/ different lana\r\n") ;
+ return NRC_BRIDGE ;
+ }
+
+ if ( pNCB->ncb_retcode != NRC_PENDING )
+ return NRC_CANOCCR ;
+
+ switch ( pNCBCancelled->ncb_command & ~ASYNCH )
+ {
+ case NCBSEND:
+ case NCBSENDNA:
+ case NCBCHAINSEND:
+ case NCBCHAINSENDNA:
+ case NCBRECV:
+ //
+ // Cancelling a session NCB automatically closes the session
+ //
+ if ( VxdFindConnectElement( pDeviceContext,
+ pNCBCancelled,
+ &pConnEle ))
+ {
+ DbgPrint("VxdCancel: Attempted to cancel send NCB on non-existent session\r\n") ;
+ break ;
+ }
+
+ if ( (pNCBCancelled->ncb_command & ~ASYNCH) == NCBRECV )
+ {
+ errNCB = NRC_CANOCCR ;
+ for ( pEntry = pConnEle->RcvHead.Flink ;
+ pEntry != &pConnEle->RcvHead ;
+ pEntry = pEntry->Flink )
+ {
+ prcvCont = CONTAINING_RECORD( pEntry, RCV_CONTEXT, ListEntry ) ;
+ ASSERT( prcvCont->Signature == RCVCONT_SIGN ) ;
+
+ if ( prcvCont->pNCB == pNCBCancelled )
+ {
+ RemoveEntryList( pEntry ) ;
+ CTEIoComplete( prcvCont->pNCB, STATUS_CANCELLED, 0 ) ;
+ errNCB = NRC_GOODRET ;
+ break ;
+ }
+ }
+ }
+ else
+ {
+ //
+ // Sends are immediately submitted to the transport, tell
+ // caller it's too late to cancel. The transport will complete
+ // the NCB when we close the connection below.
+ //
+ errNCB = NRC_CANOCCR ;
+ }
+
+ REQUIRE( !VxdCompleteSessionNcbs( pDeviceContext, pConnEle )) ;
+ VxdTearDownSession( pDeviceContext,
+ pConnEle,
+ NULL,
+ NULL ) ;
+ //
+ // Only remove from table if we've told the client
+ //
+ if ( pConnEle->Flags & NB_CLIENT_NOTIFIED )
+ {
+ REQUIRE( NBUnregister( pDeviceContext,
+ pNCBCancelled->ncb_lsn,
+ NB_SESSION )) ;
+ }
+ break ;
+
+ case NCBCANCEL:
+ errNCB = NRC_CANCEL ; // Can't cancel a cancel
+ break ;
+
+ case NCBLISTEN:
+ //
+ // Lookup the Client Element associated with this name, then scan
+ // the listen NCBs for one that matches the one being cancelled
+ //
+ if ( errNCB = VxdNameToClient( pDeviceContext,
+ pNCBCancelled->ncb_name,
+ NULL,
+ &pClientEle ))
+ {
+ DbgPrint("VxdCancel: Tried to cancel listen on non-existent name\r\n") ;
+ errNCB = NRC_CANOCCR ;
+ break ;
+ }
+
+ errNCB = NRC_CANOCCR ;
+ for ( pEntry = pClientEle->ListenHead.Flink ;
+ pEntry != &pClientEle->ListenHead ;
+ pEntry = pEntry->Flink )
+ {
+ pListen = CONTAINING_RECORD( pEntry, tLISTENREQUESTS, Linkage ) ;
+ if ( pListen->pIrp == pNCBCancelled )
+ {
+ DbgPrint("VxdCancel: Cancelling NCB 0x") ;
+ DbgPrintNum( (ULONG) pNCBCancelled ) ; DbgPrint("\r\n") ;
+ RemoveEntryList( &pListen->Linkage ) ;
+ CTEIoComplete( pNCBCancelled, STATUS_CANCELLED, 0 ) ;
+ CTEMemFree( pListen ) ;
+ errNCB = NRC_GOODRET ;
+ break ;
+ }
+ }
+ break ;
+
+ case NCBCALL:
+ //
+ // Search the ConnectActive list for our NCB and cleanup that
+ // connection
+ //
+ if ( errNCB = VxdNameToClient( pDeviceContext,
+ pNCBCancelled->ncb_name,
+ NULL,
+ &pClientEle ))
+ {
+ DbgPrint("VxdCancel: Tried to cancel call on non-existent name\r\n") ;
+ errNCB = NRC_CANOCCR ;
+ break ;
+ }
+
+ errNCB = NRC_CANOCCR ;
+ for ( pEntry = pClientEle->ConnectActive.Flink ;
+ pEntry != &pClientEle->ConnectActive ;
+ pEntry = pEntry->Flink )
+ {
+ pConnEle = CONTAINING_RECORD( pEntry, tCONNECTELE, Linkage ) ;
+ if ( pConnEle->pIrp == pNCBCancelled )
+ {
+ tDGRAM_SEND_TRACKING * pTracker = (tDGRAM_SEND_TRACKING*)
+ pConnEle->pIrpRcv ;
+
+ //
+ // if it's too late, just say we can't cancel it
+ //
+ if (pConnEle->state >= NBT_SESSION_OUTBOUND)
+ {
+ errNCB = NRC_CANOCCR ;
+ break;
+ }
+
+ //
+ // yes, we can cancel it. we just mark the tracker to say
+ // this call is cancelled: both the original ncb and this
+ // cancel ncb will get completed at some stage.
+ //
+ DbgPrint("VxdCancel: Cancelling NCB 0x") ;
+ DbgPrintNum( (ULONG) pNCBCancelled ) ; DbgPrint("\r\n") ;
+
+ pTracker->Flags |= TRACKER_CANCELLED;
+ pConnEle->pIrpDisc = pNCB;
+
+ return NRC_GOODRET ;
+ }
+ }
+ break ;
+
+ case NCBDGRECV:
+ if ( pNCBCancelled->ncb_num == ANY_NAME )
+ {
+ pHead = &pDeviceContext->RcvDGAnyFromAnyHead ;
+ }
+ else
+ {
+ if ( errNCB = VxdFindClientElement( pDeviceContext,
+ pNCBCancelled->ncb_num,
+ &pClientEle,
+ CLIENT_LOCAL ) )
+ {
+ ASSERT( FALSE ) ;
+ break ;
+ }
+ pHead = &pClientEle->RcvDgramHead ;
+ }
+
+ errNCB = NRC_CANOCCR ;
+ for ( pEntry = pHead->Flink ;
+ pEntry != pHead ;
+ pEntry = pEntry->Flink )
+ {
+ prcvEle = CONTAINING_RECORD( pEntry, tRCVELE, Linkage ) ;
+
+ if ( prcvEle->pIrp == pNCBCancelled )
+ {
+ RemoveEntryList( pEntry ) ;
+ CTEIoComplete( pNCBCancelled, STATUS_CANCELLED, 0 ) ;
+ CTEMemFree( prcvEle ) ;
+ errNCB = NRC_GOODRET ;
+ break ;
+ }
+ }
+ break ;
+
+ case NCBDGRECVBC:
+ //
+ // For receive broadcast datagrams, we have to look through the list
+ // of clients on the Broadcast Address.
+ //
+ errNCB = VxdFindClientElement( pDeviceContext,
+ 0,
+ &pClientEle,
+ CLIENT_BC ) ;
+ if ( !errNCB )
+ {
+ errNCB = NRC_CANOCCR ;
+ for ( pEntry = pClientEle->RcvDgramHead.Flink ;
+ pEntry != &pClientEle->RcvDgramHead ;
+ pEntry = pEntry->Flink )
+ {
+ prcvEle = CONTAINING_RECORD( pEntry, tRCVELE, Linkage ) ;
+ if ( prcvEle->pIrp == pNCBCancelled )
+ {
+ RemoveEntryList( pEntry ) ;
+ CTEMemFree( prcvEle ) ;
+ CTEIoComplete( pNCBCancelled, STATUS_CANCELLED, 0 ) ;
+ errNCB = NRC_GOODRET ;
+ break ;
+ }
+ }
+ }
+ break ;
+
+ case NCBRECVANY:
+ if ( pNCBCancelled->ncb_num == ANY_NAME )
+ pHead = &pDeviceContext->RcvAnyFromAnyHead ;
+ else
+ {
+ if ( errNCB = VxdFindClientElement( pDeviceContext,
+ pNCBCancelled->ncb_num,
+ &pClientEle,
+ CLIENT_LOCAL ) )
+ {
+ ASSERT( FALSE ) ;
+ break ;
+ }
+ pHead = &pClientEle->RcvAnyHead ;
+ }
+
+ errNCB = NRC_CANOCCR ;
+ pEntry = pHead->Flink ;
+ while ( pEntry != pHead )
+ {
+ prcvCont = CONTAINING_RECORD( pEntry, RCV_CONTEXT, ListEntry ) ;
+ ASSERT( prcvCont->Signature == RCVCONT_SIGN ) ;
+
+ if ( prcvCont->pNCB == pNCBCancelled )
+ {
+ RemoveEntryList( pEntry ) ;
+ CTEIoComplete( prcvCont->pNCB, STATUS_CANCELLED, 0 ) ;
+ errNCB = NRC_GOODRET ;
+ break ;
+ }
+ pEntry = pEntry->Flink ;
+ }
+ break ;
+
+ default:
+ errNCB = NRC_CANCEL ;
+ }
+
+
+ CTEIoComplete( pNCB, errNCB, 0 ) ;
+
+ //
+ // No, no! Don't touch that ncb after completing it!
+ //
+ //pNCB->ncb_retcode = errNCB ;
+ //pNCB->ncb_cmd_cplt = errNCB ;
+
+ return errNCB ;
+}
+
+/*******************************************************************
+
+ NAME: VxdIoComplete
+
+ SYNOPSIS: Let's the NCB know that all processing is done by setting
+ the command completion fields and calling the post routine
+ if available.
+
+ ENTRY: pirp - Pointer to the NCB to notify that we are done
+ (or NULL if this didn't come from the Netbios I/F
+ status - Status of the completion
+ ulExtra - Extra parameter
+
+ NOTES: This is the procedure that CTEIoComplete maps to and is
+ roughly equivilent to "completing" an IRP.
+
+ HISTORY:
+ Johnl 27-Apr-1993 Created
+
+********************************************************************/
+
+VOID VxdIoComplete( PCTE_IRP pirp,
+ NTSTATUS status,
+ ULONG ulExtra )
+{
+ NCB * pNCB = pirp ;
+ NCBERR errNCB = NRC_GOODRET ;
+ PSESS_SETUP_CONTEXT pSessSetupCont ;
+ BOOL fAsync ;
+ tDEVICECONTEXT * pDeviceContext ;
+ PRESET_CONTEXT pRstCont ;
+ PSEND_CONTEXT pSendCont ;
+ tCONNECTELE * pConnEle ;
+
+ DbgPrint("VxdIoComplete: Completing NCB; Cmd, Addr, TDI status: 0x") ;
+ if ( pNCB )
+ {
+ DbgPrintNum( pNCB->ncb_command ) ;
+ DbgPrint(" 0x") ; DbgPrintNum( (ULONG) pNCB ) ;
+ DbgPrint(" 0x") ; DbgPrintNum( status ) ;
+ DbgPrint("\r\n") ;
+ }
+ else
+ DbgPrint("NULL\r\n") ;
+
+ //
+ // If no NCB to complete then we're done
+ //
+ if ( !pNCB )
+ return ;
+
+ fAsync = !!(pNCB->ncb_command & ASYNCH) ;
+
+ pDeviceContext = GetDeviceContext( pNCB ) ;
+
+ ASSERT(pDeviceContext);
+
+ //
+ // Note that we drop through the below case statement even if an error
+ // occurred because some commands need to free stuff before completing
+ // the NCB.
+ //
+ if ( status != STATUS_SUCCESS &&
+ ( pNCB->ncb_command & ~ASYNCH) != NCBCANCEL )
+ {
+ errNCB = MapTDIStatus2NCBErr( status ) ;
+ }
+
+ //
+ // Fill in any items in the NCB struct if necessary
+ //
+ switch( pNCB->ncb_command & ~ASYNCH )
+ {
+ case NCBRECVANY: // lsn was set when the receive was posted
+ case NCBRECV:
+ FreeRcvContext( *((PRCV_CONTEXT*)&pNCB->ncb_reserve) ) ;
+ if ( errNCB && errNCB != NRC_INCOMP )
+ {
+ break ;
+ }
+
+ ASSERT( ulExtra <= 0xffff ) ;
+ ASSERT( pNCB->ncb_length >= ulExtra ) ;
+ pNCB->ncb_length = (WORD) ulExtra ;
+
+ DbgPrint("\tSetting length to 0x") ;
+ DbgPrintNum( ulExtra ) ;
+ DbgPrint("\r\n") ;
+ break ;
+
+ case NCBSSTAT:
+ case NCBDGRECV:
+ case NCBDGRECVBC:
+ if ( errNCB && errNCB != NRC_INCOMP )
+ break ;
+
+ ASSERT( ulExtra <= 0xffff ) ;
+ ASSERT( pNCB->ncb_length >= ulExtra ) ;
+ pNCB->ncb_length = (WORD) ulExtra ;
+
+ DbgPrint("\tSetting length to 0x") ;
+ DbgPrintNum( ulExtra ) ;
+ DbgPrint("\r\n") ;
+ break ;
+
+ case NCBASTAT:
+ case NCBFINDNAME:
+ if ( errNCB && errNCB != NRC_INCOMP )
+ break ;
+
+ if ( ulExtra != 0xffffffff ) // Means buffer length already set
+ pNCB->ncb_length = (WORD) ulExtra ;
+
+ DbgPrint("\tAStat/Findname length is 0x") ;
+ DbgPrintNum( (ULONG) pNCB->ncb_length ) ;
+ DbgPrint("\r\n") ;
+ break ;
+
+ case NCBSEND:
+ case NCBSENDNA:
+ case NCBCHAINSEND:
+ case NCBCHAINSENDNA:
+ pSendCont = (PSEND_CONTEXT) pNCB->ncb_reserve ;
+ if ( errNCB )
+ {
+ //
+ // Sends are immediately given to the transport, so if a
+ // timeout occurs, we'll first be completed by the timeout
+ // code, then we'll be completed by the transport closing
+ // the connection.
+ //
+
+ if ( errNCB != NRC_CMDTMO &&
+ pSendCont->STO == NCB_TIMED_OUT )
+ {
+ //
+ // The transport has completed this NCB in response to the
+ // Close connection because of a send timeout. Map the
+ // error to timeout and complete back to the client. The
+ // session is dead so don't disconnect it again. The send
+ // has already been removed from the timeout list.
+ //
+ errNCB = NRC_CMDTMO ;
+ }
+ else
+ {
+ BOOL fTimedOutNCB = pSendCont->STO == NCB_TIMED_OUT ;
+
+ //
+ // Remove from timeout list
+ //
+ if ( pSendCont->STO != NCB_INFINITE_TIME_OUT )
+ RemoveEntryList( &pSendCont->ListEntry ) ;
+
+ //
+ // Kill the session
+ //
+ if ( VxdFindConnectElement( pDeviceContext,
+ pNCB,
+ &pConnEle ))
+
+ {
+ //
+ // There maybe multiple sends on this session, only the
+ // first should disconnect
+ //
+ CTEFreeMem( pSendCont->pHdr ) ;
+ DbgPrint("VxdIoComplete: Error occurred on non-existent session\r\n") ;
+ break ;
+ }
+
+ REQUIRE( !VxdCompleteSessionNcbs( pDeviceContext, pConnEle )) ;
+
+ //
+ // Only remove from table if we've told the client
+ //
+ if ( pConnEle->Flags & NB_CLIENT_NOTIFIED )
+ {
+ REQUIRE( NBUnregister( pDeviceContext,
+ pNCB->ncb_lsn,
+ NB_SESSION )) ;
+ }
+
+ VxdTearDownSession( pDeviceContext,
+ pConnEle,
+ NULL,
+ NULL ) ;
+
+ if ( fTimedOutNCB ) // pSendCont may already have been freed
+ {
+ //
+ // The Close Connection above will cause the transport to
+ // complete this send with a session closed error, wait
+ // for that before completing back to the client.
+ //
+ return ;
+ }
+ }
+ }
+ else
+ {
+ if ( pSendCont->STO != NCB_INFINITE_TIME_OUT )
+ RemoveEntryList( &pSendCont->ListEntry ) ;
+ }
+ FreeSessionHdr( pSendCont->pHdr ) ;
+ break ;
+
+ case NCBDGSEND:
+ case NCBDGSENDBC:
+ //
+ // Nothing to do
+ //
+ break ;
+
+ //
+ // Need to set the ncb_num field for the following commands. Note
+ // that the ulExtra parameter will contain a pointer to the address
+ // element that was just added for this name.
+ //
+ case NCBADDNAME:
+ case NCBADDGRNAME:
+ if ( errNCB )
+ break ;
+
+ if ( !NBRegister( pDeviceContext,
+ &pNCB->ncb_num,
+ (tCLIENTELE *) ulExtra,
+ NB_NAME ))
+ {
+ TDI_REQUEST Request ;
+ TDI_STATUS tdistatus ;
+
+ errNCB = NRC_NAMTFUL ;
+ Request.Handle.ConnectionContext = (tCLIENTELE *) ulExtra ;
+ tdistatus = NbtCloseAddress( &Request,
+ NULL, //&RequestStatus,
+ pDeviceContext,
+ NULL ) ;
+ ASSERT( NT_SUCCESS( tdistatus )) ;
+ }
+ else
+ {
+ DbgPrint("\tRegistered Name number ") ;
+ DbgPrintNum( pNCB->ncb_num ) ;
+ DbgPrint(" for Address Element ") ;
+ DbgPrintNum( ulExtra ) ;
+ DbgPrint("\r\n") ;
+ }
+ break ;
+
+#if 0
+ //
+ // Private NBT NCB type for processing the permanent name
+ //
+ case NCBADD_PERMANENT_NAME:
+ CTEFreeMem( pNCB ) ;
+
+ if ( errNCB )
+ {
+ DbgPrint("VxdIoComplete: Failed to add permanent name!\r\n") ;
+ }
+ else
+ {
+ ASSERT( pDeviceContext->pNameTable[0] == NULL ) ;
+ pDeviceContext->pNameTable[0] = (tCLIENTELE *) ulExtra ;
+ }
+ //
+ // Don't do any further processing of this NCB. Not only did
+ // we just free it, nobody is looking for it.
+ //
+ return ;
+#endif
+
+ case NCBCALL:
+ case NCBLISTEN:
+ pSessSetupCont = (PSESS_SETUP_CONTEXT) pNCB->ncb_reserve ;
+
+ if ( errNCB )
+ {
+ VxdTearDownSession( pDeviceContext,
+ pSessSetupCont->pConnEle,
+ pSessSetupCont,
+ NULL ) ;
+ break ;
+ }
+
+ //
+ // Put the connection in our LSN table and copy out the connecting
+ // name if necessary
+ //
+ if ( !NBRegister( pDeviceContext,
+ &pNCB->ncb_lsn,
+ (tCONNECTELE *) ulExtra,
+ NB_SESSION ))
+ {
+ VxdTearDownSession( pDeviceContext,
+ (tCONNECTELE *) ulExtra,
+ NULL,
+ NULL ) ;
+ errNCB = NRC_LOCTFUL ;
+ }
+ else
+ {
+ tCONNECTELE * pConnEle = (tCONNECTELE*) ulExtra ;
+
+ //
+ // Were we listenning for '*'? If so, copy out the connecting
+ // name.
+ //
+ if ( pSessSetupCont->fIsWorldListen )
+ {
+ DbgPrint( "VxdIoComplete: World listen accepted \"" ) ;
+ DbgPrint( pConnEle->RemoteName ) ;
+ DbgPrint("\" for connection endpoint\r\n") ;
+
+ CTEMemCopy( pNCB->ncb_callname,
+ pConnEle->RemoteName,
+ NCBNAMSZ ) ;
+ }
+
+ ((tCONNECTELE *)ulExtra)->RTO = pNCB->ncb_rto ;
+ ((tCONNECTELE *)ulExtra)->STO = pNCB->ncb_sto ;
+ ((tCONNECTELE *)ulExtra)->Flags = 0 ;
+
+ //
+ // Don't delete the connection element until the client has been
+ // notified that the connection is down
+ //
+ ((tCONNECTELE *)ulExtra)->RefCount++ ;
+
+ DbgPrint("\tRegistered Session number ") ;
+ DbgPrintNum( pNCB->ncb_lsn ) ;
+ DbgPrint(" for Connection Element ") ;
+ DbgPrintNum( (ULONG) pConnEle ) ;
+ DbgPrint("\r\n") ;
+ }
+
+ FreeSessSetupContext( pSessSetupCont ) ;
+
+ //
+ // If we're in WAITACCEPT, then this is a Listen that needs to
+ // be accepted
+ //
+ if ( ((tCONNECTELE *)ulExtra)->state == NBT_SESSION_WAITACCEPT )
+ {
+ //
+ // Accept the connection
+ //
+ VxdAccept( (tCONNECTELE *) ulExtra, NULL ) ;
+ }
+ break ;
+
+ case NCBRESET:
+ pRstCont = (PRESET_CONTEXT) pNCB->ncb_reserve ;
+ if ( pRstCont->cActiveSessions != -1 ||
+ pRstCont->cActiveNames )
+ {
+ DbgPrint("VxdIoComplete: Disconnect/Name de-reg completed from Reset, remaining disconnects, names: ") ;
+ DbgPrintNum( pRstCont->cActiveSessions ) ;
+ DbgPrintNum( pRstCont->cActiveNames ) ; DbgPrint("\r\n") ;
+
+ //
+ // Only complete the Reset NCB after all session have been
+ // disconnected and the names have been released on the network
+ //
+ if ( pRstCont->cActiveSessions != -1 )
+ {
+ if ( --pRstCont->cActiveSessions == 0 )
+ {
+ //
+ // Starts the name deletion process
+ //
+ pRstCont->cActiveSessions = -1 ;
+ VxdResetContinue( pDeviceContext, pNCB ) ;
+ }
+
+ return ;
+ }
+
+ if ( --pRstCont->cActiveNames != 0 )
+ {
+ return ;
+ }
+ }
+
+ if ( !errNCB )
+ errNCB = pRstCont->errncb ;
+
+ // Fall through
+
+ case NCBUNLINK:
+ pNCB->ncb_retcode = errNCB ;
+ pNCB->ncb_cmd_cplt = errNCB ;
+ goto SkipPost ;
+
+ case NCBCANCEL:
+ pNCB->ncb_retcode = errNCB ;
+ pNCB->ncb_cmd_cplt = errNCB ;
+ break;
+
+ case NCBHANGUP:
+ case NCBDELNAME:
+ case NCBTRACE:
+ break ;
+
+ default:
+ DbgPrint("VxdIoComplete: Unexpected NCB command: 0x") ;
+ DbgPrintNum( pNCB->ncb_command ) ; DbgPrint("\r\n") ;
+ break ;
+ }
+
+ if ( pNCB->ncb_retcode == NRC_PENDING )
+ {
+ pNCB->ncb_retcode = errNCB ;
+ pNCB->ncb_cmd_cplt = errNCB ;
+ }
+ else
+ {
+ if ( (pNCB->ncb_command & ~ASYNCH) != NCBCANCEL )
+ {
+ CTEPrint("VxdIoComplete: ncb_retcode already set!\r\n") ;
+ CTEPrint("\tCommand: 0x") ; DbgPrintNum(pNCB->ncb_command) ;
+ CTEPrint(" NCB Address: 0x") ; DbgPrintNum( (ULONG) pNCB ) ;
+ }
+ goto SkipPost ;
+ }
+
+ //
+ // call the post-routine only if this was a no-wait call and if
+ // the post-routine has been specified!
+ //
+ if ( fAsync && pNCB->ncb_post )
+ {
+ typedef void (CALLBACK * VXDNCBPost )( void ) ;
+ VXDNCBPost ncbpost = (VXDNCBPost) pNCB->ncb_post ;
+
+ //
+ // Clients are expecting EBX to point to the NCB (instead of
+ // pushing it on the stack...). The post routine may trash
+ // ebp also, so save it.
+ //
+ _asm push ebp ;
+ _asm mov ebx, pNCB ;
+ ncbpost() ;
+ _asm pop ebp ;
+ }
+
+SkipPost:
+ //
+ // Now that we've completed the NCB, unblock if it was a Wait NCB
+ //
+ if ( !fAsync )
+ {
+ PBLOCKING_NCB_CONTEXT pBlkNcbContext;
+ PLIST_ENTRY pHead, pEntry ;
+
+ //
+ // find the blocking ncb context from the list corresponding to this ncb
+ //
+ pHead = &NbtConfig.BlockingNcbs;
+ pEntry = pHead->Flink;
+ while( pEntry != pHead )
+ {
+ pBlkNcbContext = CONTAINING_RECORD( pEntry, BLOCKING_NCB_CONTEXT, Linkage ) ;
+ if (pBlkNcbContext->pNCB == pNCB)
+ break;
+ else
+ pBlkNcbContext = NULL;
+ pEntry = pEntry->Flink;
+ }
+
+ if (pBlkNcbContext)
+ {
+ ASSERT(pBlkNcbContext->Verify == NBT_VERIFY_BLOCKING_NCB);
+
+ //
+ // if the ncb is blocked for completion, remove the context from
+ // the list first (important!) and then signal the thread that we
+ // are done. Then free the memory.
+ //
+ if ( pBlkNcbContext->fBlocked )
+ {
+ RemoveEntryList(&pBlkNcbContext->Linkage);
+ CTESignal( pBlkNcbContext->pWaitNCBBlock, 0 ) ;
+ CTEFreeMem(pBlkNcbContext->pWaitNCBBlock);
+ CTEFreeMem(pBlkNcbContext);
+ }
+ else
+ {
+ pBlkNcbContext->fNCBCompleted = TRUE;
+ }
+ }
+ else
+ {
+ DbgPrint("VxdIoComplete: didn't find blocking ncb context\r\n") ;
+ DbgPrint("for NCB Address: 0x") ; DbgPrintNum( (ULONG) pNCB ) ;
+ }
+ }
+}
+
+/*******************************************************************
+
+ NAME: VxdInitSessionSetup
+
+ SYNOPSIS: Common initialization required for Call and Listen
+
+ ENTRY: pDeviceContext - Adapter to setup on
+ pRequest - Request to fill in if successful
+ ppSessSetupContext - Context to be filled
+ pNCB - NCB doing the call/listen
+
+ EXIT:
+
+ RETURNS: NRC_GOODRET if successful, error code otherwise
+
+ NOTES:
+
+ HISTORY:
+ Johnl 26-May-1993 Created
+
+********************************************************************/
+
+NCBERR VxdInitSessionSetup( tDEVICECONTEXT * pDeviceContext,
+ TDI_REQUEST * pRequest,
+ PSESS_SETUP_CONTEXT * ppSessSetupContext,
+ NCB * pNCB )
+{
+ NTSTATUS status;
+ NCBERR errNCB ;
+ TDI_REQUEST_STATUS RequestStatus ;
+ tCLIENTELE * pClientEle ;
+ tCONNECTELE * pConnEle ;
+ tNAMEADDR * pNameAddr ;
+ USHORT NameType ;
+ BOOL fIsListen = ((pNCB->ncb_command & ~ASYNCH)
+ == NCBLISTEN) ;
+
+ *ppSessSetupContext = NULL ;
+
+ //
+ // Lookup the Client Element associated with this name and verify
+ // it's valid
+ //
+ if ( errNCB = VxdNameToClient( pDeviceContext,
+ pNCB->ncb_name,
+ NULL,
+ &pClientEle ))
+ {
+ return errNCB ;
+ }
+
+ if ( pClientEle->fDeregistered )
+ return NRC_NOWILD ;
+
+ //
+ // Request.Handle.ConnectionContext will contain Connection
+ // element after we open the connection
+ //
+ if ( status = NbtOpenConnection( pRequest,
+ NULL, //ConnectionContext, // Passed to connect and disconnect handlers
+ pDeviceContext ) )
+ {
+ return MapTDIStatus2NCBErr( status ) ;
+ }
+
+ //
+ // Initialize the connection context (used by Vxd disconnect handler)
+ //
+ pConnEle = (tCONNECTELE *) pRequest->Handle.ConnectionContext ;
+ pConnEle->ConnectContext = pConnEle ;
+
+ if ( status = NbtAssociateAddress( pRequest,
+ pClientEle,
+ NULL ))
+ {
+ goto ErrorExit1 ;
+ }
+
+ ASSERT( sizeof( SESS_SETUP_CONTEXT ) <= (sizeof( pNCB->ncb_reserve ) +
+ sizeof( pNCB->ncb_event )) ) ;
+ *ppSessSetupContext = (PSESS_SETUP_CONTEXT) pNCB->ncb_reserve ;
+ if ( status = AllocSessSetupContext( *ppSessSetupContext,
+ *pNCB->ncb_callname == '*' ) )
+ goto ErrorExit0 ;
+
+ //
+ // Listen for '*' uses a NULL Request remote address
+ //
+ if ( *pNCB->ncb_callname != '*' )
+ {
+ InitNBTDIConnectInfo( (*ppSessSetupContext)->pRequestConnect,
+ (*ppSessSetupContext)->pRequestConnect->RemoteAddress,
+ pNCB->ncb_callname ) ;
+ }
+
+ InitNBTDIConnectInfo( (*ppSessSetupContext)->pReturnConnect,
+ (*ppSessSetupContext)->pReturnConnect->RemoteAddress,
+ pNCB->ncb_name ) ;
+ (*ppSessSetupContext)->fIsWorldListen = (pNCB->ncb_callname[0] == '*') ;
+ (*ppSessSetupContext)->pConnEle = pConnEle ;
+
+ return NRC_GOODRET ;
+
+ErrorExit0:
+ if ( !(NbtDisassociateAddress( pRequest ) == TDI_SUCCESS))
+ CTEPrint("VxdInitSessionSetup: AllocSesssetupContext failed and DisassociateAddress failed\r\n") ;
+
+ErrorExit1:
+ REQUIRE( NbtCloseConnection( pRequest,
+ &RequestStatus,
+ pDeviceContext,
+ NULL ) == TDI_SUCCESS ) ;
+
+ return MapTDIStatus2NCBErr( status ) ;
+}
+
+/*******************************************************************
+
+ NAME: VxdFindClientElement
+
+ SYNOPSIS: Finds the appropriate client element
+
+ ENTRY: pDeviceContext - Device to search on
+ ncbnum - NCB Name Number
+ ppClientEle - Receives result of search
+ Type - If CLIENT_BC (broadcast), then the Broadcast client
+ element for the pDeviceContext adapter is returned
+
+ RETURNS: STATUS_SUCCESS if the name is found, error code otherwise
+
+ NOTES: The device context points to a list of Address elements (one
+ address element for each Netbios name in the system). Each
+ address element has a Client Element list hanging off of it.
+ We return the first client element off of the Address Element
+ as there shouldn't be more then one client (is this true?).
+
+ HISTORY:
+ Johnl 23-Apr-1993 Created
+
+********************************************************************/
+
+NCBERR VxdFindClientElement( tDEVICECONTEXT * pDeviceContext,
+ UCHAR ncbnum,
+ tCLIENTELE * * ppClientEle,
+ enum CLIENT_TYPE Type )
+{
+ ASSERT( pDeviceContext != NULL ) ;
+ if ( !pDeviceContext )
+ return NRC_SYSTEM ;
+
+ if ( Type != CLIENT_BC )
+ {
+ if ( ncbnum > pDeviceContext->cMaxNames || !pDeviceContext->pNameTable[ncbnum] )
+ return NRC_ILLNN ;
+
+ *ppClientEle = (tCLIENTELE *) pDeviceContext->pNameTable[ncbnum] ;
+ return NRC_GOODRET ;
+ }
+ else
+ {
+ NTSTATUS status;
+ tCLIENTELE * pClientEleBcast ;
+ UCHAR pName[NETBIOS_NAME_SIZE];
+ tNAMEADDR * pNameAddr;
+ PLIST_ENTRY pHead;
+ PLIST_ENTRY pEntry;
+
+ //
+ // find the * name in the local hash table
+ //
+ CTEZeroMemory(pName,NETBIOS_NAME_SIZE);
+
+ pName[0] = '*';
+ status = FindInHashTable(NbtConfig.pLocalHashTbl,
+ pName,
+ NbtConfig.pScope,
+ &pNameAddr);
+
+ if (NT_SUCCESS(status))
+ {
+ pHead = &pNameAddr->pAddressEle->ClientHead;
+ pEntry = pHead->Flink;
+
+ while ( pEntry != pHead )
+ {
+ pClientEleBcast = CONTAINING_RECORD( pEntry, tCLIENTELE, Linkage ) ;
+ if ( pClientEleBcast->pDeviceContext == pDeviceContext )
+ {
+ *ppClientEle = pClientEleBcast ;
+ break ;
+ }
+ pEntry = pEntry->Flink ;
+ }
+ }
+ else
+ {
+ return(NRC_ILLNN);
+ }
+
+ if ( pEntry == pHead )
+ return NRC_ILLNN ;
+ }
+
+ return NRC_GOODRET ;
+}
+
+/*******************************************************************
+
+ NAME: VxdFindConnectElement
+
+ SYNOPSIS: Finds the appropriate connect element from the
+ session number
+
+ ENTRY: pDeviceContext - Device to search on
+ lsn - NCB LS Number
+ ppConnectEle - Receives result of search
+
+ RETURNS: NRC_GOODRET if successful, error otherwise
+
+ NOTES: LSN 0 will be disallowed because pSessionTable[0] is always
+ NULL
+
+ HISTORY:
+ Johnl 23-Apr-1993 Created
+
+********************************************************************/
+
+NCBERR VxdFindConnectElement( tDEVICECONTEXT * pDeviceContext,
+ NCB * pNCB,
+ tCONNECTELE * * ppConnectEle )
+{
+ UCHAR lsn ;
+ ASSERT( pNCB != NULL ) ;
+ ASSERT( pDeviceContext != NULL ) ;
+
+ if ( !pDeviceContext || !pNCB )
+ return NRC_SYSTEM ;
+
+ lsn = pNCB->ncb_lsn ;
+ if ( lsn > pDeviceContext->cMaxSessions || !pDeviceContext->pSessionTable[lsn] )
+ return NRC_SNUMOUT ;
+
+ *ppConnectEle = pDeviceContext->pSessionTable[lsn] ;
+
+ //
+ // Check to see if the connection is down but the NB client hasn't been
+ // notified, if so notify them and remove the session from the table
+ //
+ if ( ( (*ppConnectEle)->state == NBT_ASSOCIATED ||
+ (*ppConnectEle)->state == NBT_IDLE ) &&
+ (*ppConnectEle)->RefCount == 1 )
+ {
+ DbgPrint("VxdFindConnectElement: Deleting connection element\r\n") ;
+ NbtDereferenceConnection( *ppConnectEle ) ;
+ REQUIRE( NBUnregister( pDeviceContext, lsn, NB_SESSION )) ;
+ return NRC_SCLOSED ;
+ }
+
+ return NRC_GOODRET ;
+}
+
+/*******************************************************************
+
+ NAME: VxdFindLSN
+
+ SYNOPSIS: Finds a session number from its tCONNECTELE *.
+
+ ENTRY: pDeviceContext - Device to search on
+ pConnectEle - Connect element to find
+ plsn - Index pConnectEle was found at
+
+ NOTES:
+
+ HISTORY:
+ Johnl 07-Jul-1993 Created
+
+********************************************************************/
+
+NCBERR VxdFindLSN( tDEVICECONTEXT * pDeviceContext,
+ tCONNECTELE * pConnectEle,
+ UCHAR * plsn )
+{
+ ASSERT( (pDeviceContext != NULL) && (pConnectEle != NULL) && (plsn != NULL)) ;
+ ASSERT( pConnectEle->Verify == NBT_VERIFY_CONNECTION ||
+ pConnectEle->Verify == NBT_VERIFY_CONNECTION_DOWN ) ;
+
+ for ( *plsn = 0 ; *plsn <= pDeviceContext->cMaxSessions ; (*plsn)++ )
+ {
+ if ( pDeviceContext->pSessionTable[*plsn] == pConnectEle )
+ return NRC_GOODRET ;
+ }
+
+ ASSERT( FALSE ) ;
+ return NRC_SNUMOUT ;
+}
+
+/*******************************************************************
+
+ NAME: VxdFindNameNum
+
+ SYNOPSIS: Finds a name number from its tADDRESSELE *.
+
+ ENTRY: pDeviceContext - Device to search on
+ pAddressEle - Address element to find
+ pNum - Index pAddressEle was found at
+
+ NOTES:
+
+ HISTORY:
+ Johnl 07-Jul-1993 Created
+
+********************************************************************/
+
+NCBERR VxdFindNameNum( tDEVICECONTEXT * pDeviceContext,
+ tADDRESSELE * pAddressEle,
+ UCHAR * pNum )
+{
+ tCLIENTELE *pClientEle;
+
+ ASSERT( (pDeviceContext != NULL) && (pAddressEle != NULL) && (pNum != NULL)) ;
+ ASSERT( pAddressEle->Verify == NBT_VERIFY_ADDRESS ) ;
+
+ for ( *pNum = 0 ; *pNum <= pDeviceContext->cMaxNames ; (*pNum)++ )
+ {
+ pClientEle = pDeviceContext->pNameTable[*pNum];
+
+ if ( (pClientEle) && (pClientEle->pAddress == pAddressEle ) )
+ return NRC_GOODRET ;
+ }
+
+ return NRC_ILLNN ;
+}
+
+/*******************************************************************
+
+ NAME: VxdNameToClient
+
+ SYNOPSIS: Converts a ncb_callname to the corresponding client element
+ in the name table
+
+ ENTRY: pDeviceContext - Device to search on
+ pchName - Name to find
+ pNameNum - Index into table name number is at (Optional)
+ ppClientEle - Client element in the name table
+
+ NOTES:
+
+ HISTORY:
+ Johnl 15-Oct-1993 Created
+
+********************************************************************/
+
+NCBERR VxdNameToClient( tDEVICECONTEXT * pDeviceContext,
+ CHAR * pName,
+ UCHAR * pNameNum,
+ tCLIENTELE * * ppClientEle )
+{
+ USHORT NameType ;
+ tNAMEADDR * pNameAddr ;
+ UCHAR NameNum ;
+ NTSTATUS status;
+
+ //
+ // Lookup the Client Element associated with this name
+ //
+ if ( pName[0] == '*' )
+ {
+ return NRC_NOWILD ; // Also means name not found
+ }
+
+ status = FindInHashTable(
+ NbtConfig.pLocalHashTbl,
+ pName,
+ NbtConfig.pScope,
+ &pNameAddr);
+
+ if (!NT_SUCCESS(status))
+ {
+ return NRC_NOWILD ; // Also means name not found
+ }
+
+ //
+ // if the name is not registered on the adapter (provided by the client)
+ // tell the client so!
+ //
+ if ( pNameAddr->AdapterMask &&
+ !(pNameAddr->AdapterMask & pDeviceContext->AdapterNumber) )
+ {
+ DbgPrint("VxdNameToClient: wrong DeviceContext element\r\n") ;
+ return NRC_NOWILD ;
+ }
+
+ if ( VxdFindNameNum( pDeviceContext, pNameAddr->pAddressEle, &NameNum ))
+ {
+ ASSERT( FALSE ) ;
+ return NRC_NOWILD ;
+ }
+
+ REQUIRE( !VxdFindClientElement( pDeviceContext,
+ NameNum,
+ ppClientEle,
+ CLIENT_LOCAL )) ;
+ ASSERT( (*ppClientEle)->Verify == NBT_VERIFY_CLIENT ) ;
+
+ if ( pNameNum != NULL )
+ *pNameNum = NameNum ;
+
+ return NRC_GOODRET ;
+}
+
+/*******************************************************************
+
+ NAME: NBRegister
+
+ SYNOPSIS: Finds the next available slot in apElem and assigns
+ pElem to that slot according to Netbios rules
+
+
+ ENTRY: pDeviceContext - Adapter we are adding name to
+ pNCBNum - Receives the found free slot
+ pElem - Element we are registering
+ NbTable - Indicates the Name table or session table
+
+ EXIT: *pNCBNum will point to the found slot and
+ apElem[*pNCBNum] will point to pElem
+
+ RETURNS: TRUE if we found a free slot, FALSE if the table was
+ full.
+
+ NOTES: The Netbios spec states that returned NCB nums and Logical
+ Session numbers increase to 254 until they wrap to 1 (0
+ is reserved for the adapter name).
+
+ HISTORY:
+ Johnl 28-Apr-1993 Created
+
+********************************************************************/
+
+BOOL NBRegister( tDEVICECONTEXT * pDeviceContext,
+ UCHAR * pNCBNum,
+ PVOID pElem,
+ NB_TABLE_TYPE NbTable )
+{
+ UCHAR i ;
+ BOOL fFound = FALSE ;
+ BOOL fPassTwo = FALSE ;
+ UCHAR MaxNCBNum ;
+ UCHAR * piCurrent ;
+ PVOID * apElem ;
+
+ ASSERT( pElem != NULL ) ;
+
+ if ( NbTable == NB_NAME )
+ {
+ MaxNCBNum = pDeviceContext->cMaxNames ;
+ apElem = pDeviceContext->pNameTable ;
+ piCurrent = &pDeviceContext->iNcbNum ;
+ }
+ else
+ {
+ MaxNCBNum = pDeviceContext->cMaxSessions ;
+ apElem = pDeviceContext->pSessionTable ;
+ piCurrent = &pDeviceContext->iLSNum ;
+ }
+
+ //
+ // Find the next free name number and store it in pNCBNum
+ //
+ for ( i = *piCurrent ; ; i++ )
+ {
+ if ( i > MaxNCBNum )
+ i = 1 ;
+
+ if ( !apElem[i] )
+ {
+ fFound = TRUE ;
+ break ;
+ }
+
+ //
+ // Second time we hit *piCurrent means there are no free slots
+ //
+ if ( i == *piCurrent)
+ {
+ if ( fPassTwo )
+ break ;
+ else
+ fPassTwo = TRUE ;
+ }
+ }
+
+ if ( fFound )
+ {
+ apElem[i] = pElem ;
+ *pNCBNum = *piCurrent = i ;
+
+ (*piCurrent)++ ;
+ if ( *piCurrent > MaxNCBNum )
+ *piCurrent = 1 ;
+ }
+
+ return fFound ;
+}
+
+/*******************************************************************
+
+ NAME: NBUnregister
+
+ SYNOPSIS: Invalidates the passed netbios number
+
+ ENTRY: NCBNum - Name number to unregister
+
+ EXIT: The name number entry will be set to NULL
+
+
+ RETURNS: TRUE if we freed the slot, FALSE if the name wasn't
+ registered in the first place or it's out of range
+
+ NOTES:
+
+ HISTORY:
+ Johnl 05-May-1993 Created
+
+********************************************************************/
+
+BOOL NBUnregister( tDEVICECONTEXT * pDeviceContext,
+ UCHAR NCBNum,
+ NB_TABLE_TYPE NbTable )
+{
+ UCHAR MaxNCBNum ;
+ PVOID * apElem ;
+
+ if ( NbTable == NB_NAME )
+ {
+ MaxNCBNum = pDeviceContext->cMaxNames ;
+ apElem = pDeviceContext->pNameTable ;
+ }
+ else
+ {
+ MaxNCBNum = pDeviceContext->cMaxSessions ;
+ apElem = pDeviceContext->pSessionTable ;
+ }
+
+ if ( NCBNum > MaxNCBNum || apElem[NCBNum] == NULL )
+ {
+ return FALSE ;
+ }
+
+ apElem[NCBNum] = NULL ;
+
+ return TRUE ;
+}
+
+/*******************************************************************
+
+ NAME: VxdCompleteSessionNcbs
+
+ SYNOPSIS: Finds all NCBs attached to a session and completes them
+
+ ENTRY: pDeviceContext - Device we are on
+ pConnEle - Session connection element to complete NCBs on
+
+ NOTES:
+
+ HISTORY:
+ Johnl 16-Aug-1993 Broke out as common code
+
+********************************************************************/
+
+TDI_STATUS VxdCompleteSessionNcbs( tDEVICECONTEXT * pDeviceContext,
+ tCONNECTELE * pConnEle )
+{
+ PLIST_ENTRY pHead, pEntry ;
+ PRCV_CONTEXT prcvCont ;
+ BOOL fCompleteToClient = TRUE ;
+ UCHAR lsn ;
+ NCBERR errNCB ;
+ BOOL fAnyFound = FALSE ;
+
+ ASSERT( pConnEle != NULL ) ;
+ ASSERT( pConnEle->Verify == NBT_VERIFY_CONNECTION ||
+ pConnEle->Verify == NBT_VERIFY_CONNECTION_DOWN ) ;
+
+ if ( errNCB = VxdFindLSN( pDeviceContext,
+ pConnEle,
+ &lsn ))
+ {
+ //
+ // This shouldn't happen but watch for it in case we get in a
+ // weird situation
+ //
+ DbgPrint("VxdCompleteSessionNCBs - Warning: VxdFindLsn failed\r\n") ;
+ return STATUS_UNSUCCESSFUL ;
+ }
+
+ //
+ // Complete the first RcvAny
+ //
+ if ( pConnEle->pClientEle &&
+ !IsListEmpty( &pConnEle->pClientEle->RcvAnyHead ))
+ {
+ pEntry = RemoveHeadList( &pConnEle->pClientEle->RcvAnyHead ) ;
+ prcvCont = CONTAINING_RECORD( pEntry, RCV_CONTEXT, ListEntry ) ;
+ ASSERT( prcvCont->Signature == RCVCONT_SIGN ) ;
+
+ //
+ // Set the session number so the client knows which session is going
+ // away.
+ //
+ prcvCont->pNCB->ncb_lsn = lsn ;
+ CTEIoComplete( prcvCont->pNCB,
+ STATUS_CONNECTION_DISCONNECTED,
+ 0 ) ;
+ fAnyFound = TRUE ;
+ }
+
+ //
+ // Now kill all of the outstanding receives. Sends are completed as
+ // they are submitted so nothing to kill.
+ //
+ while ( !IsListEmpty( &pConnEle->RcvHead ))
+ {
+ pEntry = RemoveHeadList( &pConnEle->RcvHead ) ;
+ prcvCont = CONTAINING_RECORD( pEntry, RCV_CONTEXT, ListEntry ) ;
+ ASSERT( prcvCont->Signature == RCVCONT_SIGN ) ;
+
+ CTEIoComplete( prcvCont->pNCB,
+ STATUS_CONNECTION_DISCONNECTED,
+ 0 ) ;
+ fAnyFound = TRUE ;
+ }
+
+ //
+ // Once the client has been notified, deref the connection
+ // element so the memory will be deleted when the connection is
+ // closed. If the client wasn't notified, then the connection remains
+ // in our table until the next NCB on this session.
+ //
+ if ( fAnyFound &&
+ !(pConnEle->Flags & NB_CLIENT_NOTIFIED) )
+ {
+ DbgPrint("CompleteSessionNcbs - Marking connection as notified\r\n") ;
+ pConnEle->Flags |= NB_CLIENT_NOTIFIED ;
+ NbtDereferenceConnection( pConnEle ) ;
+ }
+
+
+ return TDI_SUCCESS ;
+}
+
+/*******************************************************************
+
+ NAME: VxdTearDownSession
+
+ SYNOPSIS: Closes a session and deletes its session context
+
+ ENTRY: pConnEle - Pointer to connection session element to close
+ pCont - Session context to delete (or NULL to ignore)
+ pSessSetupContext - Session context to delete if non-NULL
+ pNCB - NCB to complete after disconnect finishes
+
+ NOTES:
+
+ HISTORY:
+ Johnl 16-Aug-1993 Commonized
+
+********************************************************************/
+
+void VxdTearDownSession( tDEVICECONTEXT * pDeviceContext,
+ tCONNECTELE * pConnEle,
+ PSESS_SETUP_CONTEXT pSessSetupContext,
+ NCB * pNCB )
+{
+ TDI_STATUS tdistatus ;
+ TDI_REQUEST Request ;
+
+ if ( pConnEle != NULL )
+ {
+ ASSERT((pConnEle->Verify == NBT_VERIFY_CONNECTION) ||
+ (pConnEle->Verify == NBT_VERIFY_CONNECTION_DOWN)) ;
+
+ Request.Handle.ConnectionContext = pConnEle ;
+
+ tdistatus = NbtDisconnect( &Request, 0, TDI_DISCONNECT_ABORT, NULL, NULL, NULL ) ;
+ if ( tdistatus && tdistatus != TDI_PENDING )
+ {
+ DbgPrint("VxdTearDownSession - NbtDisconnect returned error " ) ;
+ DbgPrintNum( tdistatus ) ;
+ DbgPrint("\r\n") ;
+ }
+
+ tdistatus = NbtCloseConnection( &Request,
+ NULL,
+ pDeviceContext,
+ NULL ) ;
+ if ( tdistatus && tdistatus != TDI_PENDING )
+ {
+ DbgPrint("VxdTearDownSession - NbtCloseConnection returned error " ) ;
+ DbgPrintNum( tdistatus ) ;
+ DbgPrint("\r\n") ;
+ }
+ }
+
+ if ( pSessSetupContext )
+ FreeSessSetupContext( pSessSetupContext ) ;
+}
+/*******************************************************************
+
+ NAME: AllocSessSetupContext
+
+ SYNOPSIS: Allocates and initializes a listen context structure
+
+ ENTRY: pSessSetupContext - Pointer to structure
+ fListenOnStar - TRUE if the request remote address should
+ be left as NULL
+
+ NOTES:
+
+ HISTORY:
+ Johnl 19-May-1993 Created
+
+********************************************************************/
+
+TDI_STATUS AllocSessSetupContext( PSESS_SETUP_CONTEXT pSessSetupContext,
+ BOOL fListenOnStar )
+{
+ CTEZeroMemory( pSessSetupContext, sizeof( SESS_SETUP_CONTEXT ) ) ;
+
+ if ( !(pSessSetupContext->pRequestConnect =
+ CTEAllocMem( sizeof( TDI_CONNECTION_INFORMATION ))) ||
+ !(pSessSetupContext->pReturnConnect =
+ CTEAllocMem( sizeof( TDI_CONNECTION_INFORMATION))) )
+ {
+ goto ErrorExit1 ;
+ }
+
+ pSessSetupContext->pRequestConnect->RemoteAddress = NULL ;
+ pSessSetupContext->pReturnConnect->RemoteAddress = NULL ;
+
+ if ( !(pSessSetupContext->pReturnConnect->RemoteAddress =
+ CTEAllocMem( sizeof( TA_NETBIOS_ADDRESS ))) ||
+ (!fListenOnStar &&
+ !(pSessSetupContext->pRequestConnect->RemoteAddress =
+ CTEAllocMem( sizeof( TA_NETBIOS_ADDRESS )))) )
+ {
+ goto ErrorExit0 ;
+ }
+
+ return TDI_SUCCESS ;
+
+ErrorExit0:
+ if ( pSessSetupContext->pRequestConnect->RemoteAddress)
+ CTEFreeMem( pSessSetupContext->pRequestConnect->RemoteAddress ) ;
+
+ if ( pSessSetupContext->pReturnConnect->RemoteAddress)
+ CTEFreeMem( pSessSetupContext->pReturnConnect->RemoteAddress ) ;
+
+ErrorExit1:
+ if ( pSessSetupContext->pRequestConnect)
+ CTEFreeMem( pSessSetupContext->pRequestConnect ) ;
+
+ if ( pSessSetupContext->pReturnConnect)
+ CTEFreeMem( pSessSetupContext->pReturnConnect ) ;
+
+ return TDI_NO_RESOURCES ;
+}
+
+/*******************************************************************
+
+ NAME: FreeSessSetupContext
+
+ SYNOPSIS: Frees a successfully initialized listen context
+
+ ENTRY: pSessSetupContext - Context to be freed
+
+ HISTORY:
+ Johnl 19-May-1993 Created
+
+********************************************************************/
+
+void FreeSessSetupContext( PSESS_SETUP_CONTEXT pSessSetupContext )
+{
+ if ( pSessSetupContext->pRequestConnect->RemoteAddress )
+ CTEFreeMem( pSessSetupContext->pRequestConnect->RemoteAddress ) ;
+
+ CTEFreeMem( pSessSetupContext->pReturnConnect->RemoteAddress ) ;
+ CTEFreeMem( pSessSetupContext->pRequestConnect ) ;
+ CTEFreeMem( pSessSetupContext->pReturnConnect ) ;
+}
+
+
+/*******************************************************************
+
+ NAME: DelayedSessEstablish
+
+ SYNOPSIS: This routine is called by VxdScheduleDelayedEvent.
+ After name query is successful, we typically make a tcp
+ connection. We delay that step until later so that stack
+ usage is reduced. (yes, there is only 4k of stack on chicago!)
+
+ ENTRY: pContext - context that contains the actual parms
+
+ RETURNS: Nothing
+
+ HISTORY:
+ Koti Dec. 19, 94
+
+********************************************************************/
+VOID DelayedSessEstablish( PVOID pContext )
+{
+ tDGRAM_SEND_TRACKING *pTracker;
+ NTSTATUS status;
+ COMPLETIONCLIENT pClientCompletion;
+
+ //
+ // get our parameters out
+ //
+ pTracker = ((NBT_WORK_ITEM_CONTEXT *)pContext)->pTracker;
+ status = (NTSTATUS)((NBT_WORK_ITEM_CONTEXT *)pContext)->pClientContext;
+ pClientCompletion = ((NBT_WORK_ITEM_CONTEXT *)pContext)->ClientCompletion;
+
+ CTEMemFree(pContext);
+
+ CompleteClientReq(pClientCompletion,
+ pTracker,
+ status);
+}
+
+
+
+/*******************************************************************
+
+ NAME: VxdApiWorker
+
+ SYNOPSIS: When clients such as another vxd or a V86 app (such as
+ nbtstat.exe) make requests for information or some service,
+ this is the routine that gets called.
+
+ ENTRY: OpCode - what info or service is being requested
+ ClientBuffer - buffer in which to pass info
+ ClientBufLen - how big is the buffer
+
+ RETURNS: ErrorCode from the operation (0 if success)
+
+ HISTORY:
+ Koti 16-Jun-1994 Created
+
+********************************************************************/
+
+NTSTATUS
+VxdApiWorker(
+ DWORD Ioctl,
+ PVOID ClientOutBuffer,
+ DWORD ClientOutBufLen,
+ PVOID ClientInBuffer,
+ DWORD ClientInBufLen,
+ DWORD fOkToTrashInputBuffer
+ )
+{
+
+ NTSTATUS status;
+ USHORT OpCode;
+ int i;
+ USHORT NumLanas;
+ PCHAR pchBuffer;
+ DWORD dwSize;
+ DWORD dwBytesToCopy;
+ PULONG pIpAddr;
+ PLIST_ENTRY pEntry,pHead;
+ tDEVICECONTEXT *pDeviceContext;
+ NCB ncb;
+ UCHAR retcode;
+ tIPANDNAMEINFO *pIpAndNameInfo;
+ tIPCONFIG_INFO *pIpCfg;
+
+
+ status = STATUS_SUCCESS;
+
+ dwSize = ClientOutBufLen;
+
+ // always use the first adapter on the list
+ pDeviceContext = CONTAINING_RECORD(NbtConfig.DeviceContexts.Flink,tDEVICECONTEXT,Linkage);
+
+ OpCode = (USHORT)Ioctl;
+
+ switch (OpCode)
+ {
+ // nbtstat -<any option>
+ case IOCTL_NETBT_GET_IP_ADDRS :
+
+ if (ClientOutBufLen < sizeof(ULONG)*(NbtConfig.AdapterCount + 1))
+ {
+ return( STATUS_BUFFER_OVERFLOW );
+ }
+
+ if (!ClientOutBuffer)
+ {
+ return( STATUS_INVALID_PARAMETER );
+ }
+ pIpAddr = (PULONG )ClientOutBuffer;
+
+ pEntry = pHead = &NbtConfig.DeviceContexts;
+ while ((pEntry = pEntry->Flink) != pHead)
+ {
+ pDeviceContext = CONTAINING_RECORD(pEntry,tDEVICECONTEXT,Linkage);
+ if (pDeviceContext->IpAddress)
+ {
+ *pIpAddr = pDeviceContext->IpAddress;
+ pIpAddr++;
+ }
+ }
+ //
+ // put a 0 address on the end
+ //
+ *pIpAddr = 0;
+
+ status = STATUS_SUCCESS;
+
+ break;
+
+ // nbtstat -n (or -N)
+ case IOCTL_NETBT_GET_LOCAL_NAMES :
+
+ // nbtstat -c
+ case IOCTL_NETBT_GET_REMOTE_NAMES :
+
+ if (!ClientOutBuffer || ClientOutBufLen == 0)
+ return (STATUS_INSUFFICIENT_RESOURCES);
+
+ if (OpCode == IOCTL_NETBT_GET_REMOTE_NAMES )
+ {
+ // make this null, so NbtQueryAda..() knows this is for remote
+ pDeviceContext = NULL;
+ }
+
+ // return an array of netbios names that are registered
+ status = NbtQueryAdapterStatus(pDeviceContext,
+ &pchBuffer,
+ &dwSize);
+ break;
+
+ // nbtstat -r
+ case IOCTL_NETBT_GET_BCAST_NAMES :
+
+ // return an array of netbios names that are registered
+ status = NbtQueryBcastVsWins(pDeviceContext,&pchBuffer,&dwSize);
+
+ break;
+
+ // nbtstat -R
+ case IOCTL_NETBT_PURGE_CACHE :
+
+ status = NbtResyncRemoteCache();
+ break;
+
+ // nbtstat -s, nbtstat -S
+ case IOCTL_NETBT_GET_CONNECTIONS :
+
+ // return an array of netbios names that are registered
+ status = NbtQueryConnectionList(NULL,
+ &pchBuffer,
+ &dwSize);
+ break;
+
+ // nbtstat -a, nbtstat -A
+ case IOCTL_NETBT_ADAPTER_STATUS:
+
+ if (!ClientOutBuffer)
+ {
+ return( STATUS_INVALID_PARAMETER );
+ }
+
+ CTEZeroMemory( &ncb, sizeof(NCB) );
+
+ ncb.ncb_command = NCBASTAT;
+ ncb.ncb_buffer = ClientOutBuffer;
+ ncb.ncb_length = ClientOutBufLen;
+ ncb.ncb_lana_num = pDeviceContext->iLana;
+
+ if (!ClientInBuffer)
+ {
+ return( STATUS_INVALID_PARAMETER );
+ }
+ pIpAndNameInfo = (tIPANDNAMEINFO *)ClientInBuffer;
+
+ //
+ // see if Ipaddress is specified: if yes, use it
+ //
+ if ( pIpAndNameInfo->IpAddress )
+ {
+ ncb.ncb_callname[0] = '*';
+ retcode = VNBT_NCB_X( &ncb, 0, &pIpAndNameInfo->IpAddress, 0, 0 );
+ }
+ //
+ // no ipaddress: use the name that's given to us
+ //
+ else
+ {
+ CTEMemCopy(
+ &ncb.ncb_callname[0],
+ &(pIpAndNameInfo->NetbiosAddress.Address[0].Address[0].NetbiosName[0]),
+ NCBNAMSZ );
+ retcode = VNBT_NCB_X( &ncb, 0, 0, 0, 0 );
+ }
+
+ status = STATUS_UNSUCCESSFUL;
+ if (!retcode)
+ {
+ if (ncb.ncb_retcode == NRC_GOODRET)
+ status = STATUS_SUCCESS;
+ else if (ncb.ncb_retcode == NRC_INCOMP)
+ status = TDI_BUFFER_OVERFLOW;
+ }
+
+ break;
+
+ // ipconfig queries us for nodetype and scope
+ case IOCTL_NETBT_IPCONFIG_INFO:
+
+ dwBytesToCopy = sizeof(tIPCONFIG_INFO) +
+ NbtConfig.ScopeLength;
+
+ if ( !ClientOutBuffer || ClientOutBufLen < dwBytesToCopy )
+ {
+ status = STATUS_BUFFER_OVERFLOW;
+ break;
+ }
+
+ pIpCfg = (tIPCONFIG_INFO *)ClientOutBuffer;
+
+ NumLanas = 0;
+ for ( i = 0; i < NBT_MAX_LANAS; i++)
+ {
+ if (LanaTable[i].pDeviceContext != NULL)
+ {
+ pDeviceContext = LanaTable[i].pDeviceContext;
+ pIpCfg->LanaInfo[NumLanas].LanaNumber = pDeviceContext->iLana;
+ pIpCfg->LanaInfo[NumLanas].IpAddress = pDeviceContext->IpAddress;
+ pIpCfg->LanaInfo[NumLanas].NameServerAddress = pDeviceContext->lNameServerAddress;
+ pIpCfg->LanaInfo[NumLanas].BackupServer = pDeviceContext->lBackupServer;
+ pIpCfg->LanaInfo[NumLanas].lDnsServerAddress = pDeviceContext->lDnsServerAddress;
+ pIpCfg->LanaInfo[NumLanas].lDnsBackupServer = pDeviceContext->lDnsBackupServer;
+ NumLanas++;
+ }
+ }
+
+ pIpCfg->NumLanas = NumLanas;
+
+ pIpCfg->NodeType = NodeType;
+
+ pIpCfg->ScopeLength = NbtConfig.ScopeLength;
+
+ CTEMemCopy( &pIpCfg->szScope[0],
+ NbtConfig.pScope,
+ NbtConfig.ScopeLength );
+
+ status = STATUS_SUCCESS;
+
+ break;
+
+ default:
+
+ status = STATUS_NOT_SUPPORTED;
+ break;
+ }
+
+ //
+ // Copy the output into user's buffer
+ //
+ if ( (OpCode == IOCTL_NETBT_GET_LOCAL_NAMES) ||
+ (OpCode == IOCTL_NETBT_GET_REMOTE_NAMES) ||
+ (OpCode == IOCTL_NETBT_GET_CONNECTIONS) ||
+ (OpCode == IOCTL_NETBT_GET_BCAST_NAMES) )
+ {
+ if ( NT_SUCCESS(status) || (status == STATUS_BUFFER_OVERFLOW))
+ {
+ if ( status == STATUS_BUFFER_OVERFLOW )
+ {
+ dwBytesToCopy = ClientOutBufLen;
+ }
+ else
+ {
+ dwBytesToCopy = dwSize;
+ status = STATUS_SUCCESS;
+ }
+ CTEMemCopy( ClientOutBuffer, pchBuffer, dwBytesToCopy ) ;
+
+ CTEMemFree((PVOID)pchBuffer);
+ }
+ }
+
+ //
+ // we may be called either through the vxd entry point which 16 bit apps
+ // will do (for now, only nbtstat.exe), or through the file system api's
+ // which 32 bit apps will do via CreateFile and ioctl.
+ // If we came here through file system (i.e.VNBT_DeviceIoControl called us)
+ // then don't trash the input buffer since the status gets passed back as
+ // it is. For 16 bit apps (i.e.VNBT_Api_Handler called us), the only way
+ // we can pass status back (without major changes all over) is through the
+ // input buffer.
+ //
+ if ( ClientInBuffer && fOkToTrashInputBuffer )
+ {
+ *(NTSTATUS *)ClientInBuffer = status;
+ }
+
+ return( status );
+}
+
+/*******************************************************************
+
+ NAME: PostInit_Proc
+
+ SYNOPSIS: After the whole system is initialized, we get the
+ Sys_Vm_Init message and that's when this routine gets called.
+ This can be used for any post-processing, but for now we
+ only use it to load lmhosts (this way, we can load all the
+ #INCLUDE files which have UNC's in them, since now we know
+ the net is up).
+
+ RETURNS: ErrorCode from the operation (0 if success)
+
+ HISTORY:
+ Koti 12-Jul-1994 Created
+
+********************************************************************/
+
+NTSTATUS
+PostInit_Proc()
+{
+
+ LONG lRetcode;
+
+ CachePrimed = FALSE;
+
+ CTEPagedCode();
+
+
+ lRetcode = PrimeCache( NbtConfig.pLmHosts,
+ NULL,
+ TRUE,
+ NULL) ;
+ if (lRetcode != -1)
+ {
+ CachePrimed = TRUE ;
+ }
+
+}
+
+
+/*******************************************************************
+
+ NAME: CTEAllocInitMem
+
+ SYNOPSIS: Allocates memory during driver initialization
+
+ NOTES: If first allocation fails, we refill the heap spare and
+ try again. We can only do this during driver initialization
+ because the act of refilling may yield the current
+ thread.
+
+ HISTORY:
+ Johnl 27-Aug-1993 Created
+********************************************************************/
+
+PVOID CTEAllocInitMem( ULONG cbBuff )
+{
+ PVOID pv = CTEAllocMem( cbBuff ) ;
+
+ if ( pv )
+ {
+ return pv ;
+ }
+ else if ( fInInit )
+ {
+ DbgPrint("CTEAllocInitMem: Failed allocation, trying again\r\n") ;
+ CTERefillMem() ;
+ pv = CTEAllocMem( cbBuff ) ;
+ }
+
+ return pv ;
+}
diff --git a/private/ntos/nbt/vxd/vxdstub.asm b/private/ntos/nbt/vxd/vxdstub.asm
new file mode 100644
index 000000000..0404c3dda
--- /dev/null
+++ b/private/ntos/nbt/vxd/vxdstub.asm
@@ -0,0 +1,250 @@
+ name vxdstub
+;************************************************************************
+;
+; (C) Copyright MICROSOFT Corp., 1990-1991
+;
+; Title: VXDSTUB.ASM
+;
+; Date: 1-Jun-1991
+;
+; Author: Neil Sandlin
+;
+;************************************************************************
+ INCLUDE INT2FAPI.INC
+;----------------------------- M A C R O S ------------------------------
+Writel MACRO addr
+ push ax
+ push bx
+ push cx
+ push dx
+
+ mov dx,offset &addr ;Print
+ mov cx,&addr&l
+ mov bx,1 ;stdout
+ mov ah,40h ;write
+ int 21h
+
+ pop dx
+ pop cx
+ pop bx
+ pop ax
+ ENDM
+
+;----------------------------- E Q U A T E S -----------------------------
+
+cr equ 0dh
+lf equ 0ah
+
+
+_TEXT segment word public 'CODE'
+ assume cs:_TEXT,ds:_DATA
+
+;*----------------------- TSR Data Area ---------------------*
+InstData Win386_Startup_Info_Struc <>
+oldint dd 0
+
+;*----------------------- TSR Code --------------------------*
+
+
+handle2f proc
+ cmp ax,1605h
+ jnz @f
+ push di
+ lea di,InstData
+ mov word ptr cs:[di].SIS_Next_Ptr,bx
+ mov word ptr cs:[di][2].SIS_Next_Ptr,es
+ pop di
+ push cs
+ pop es
+ lea bx,InstData
+@@:
+ jmp DWORD PTR [oldint]
+handle2f endp
+
+ ALIGN 16
+init_fence:
+
+_TEXT ends
+
+;*---------------------- Initialization Data ------------------------*
+
+_DATA segment word public 'DATA'
+
+TSR_rsv dw ?
+
+intmsg db cr,lf,'Hooking interrupt '
+intmsgx dd ?
+ db cr,lf
+intmsgl equ $-intmsg
+
+hndmsg db cr,lf,'ISR entry point: '
+hndmsga dd ?
+ db ':'
+hndmsgb dd ?
+ db ', length='
+hndmsgc dd ?
+ db 'h bytes'
+ db cr,lf
+hndmsgl equ $-hndmsg
+
+tsrmsg db 'TSR; reserving '
+tsrmsgx dd ?
+ db ' paragraphs'
+ db cr,lf
+tsrmsgl equ $-tsrmsg
+
+_DATA ends
+
+
+_TEXT segment word public 'CODE'
+;*-------------------------- Initialization Code ----------------------*
+
+vxdstub proc far
+ mov ax, _DATA
+ mov ds, ax
+
+; get a pointer to the name of the load file in the environment seg.
+
+ mov ah,62h
+ int 21h ;bx -> psp
+ mov es,bx
+ mov bx,2ch ;environment segment
+ mov es,es:[bx]
+ xor di,di
+ mov cx,-1 ;big number
+ xor al,al ;search for a null
+ cld
+@@:
+ repne scasb ;get past one null and stop
+ cmp byte ptr es:[di],0 ;another null
+ jnz @b ;no.
+ add di,3 ;skip the word before the name.
+
+; prepare part of the instance data list. Stuff in pointer to the file name
+; and refernce data
+
+ lea si,InstData
+ mov word ptr CS:[si].SIS_Version,3
+ mov word ptr CS:[si].SIS_Virt_Dev_File_Ptr,di
+ mov word ptr CS:[si][2].SIS_Virt_Dev_File_Ptr,es
+
+ mov word ptr cs:[si].SIS_Instance_Data_Ptr,0
+ mov word ptr cs:[si][2].SIS_Instance_Data_Ptr,0
+
+; Write message and hook interrupt 2f
+ mov ax, 2fh
+ mov bx, offset intmsgx
+ call hexasc
+
+ Writel intmsg
+
+ mov ah, 35h
+ mov al, 2fh
+ int 21h ; get old vector
+ mov WORD PTR cs:oldint,bx ; save old vector here
+ mov WORD PTR cs:oldint+2,es
+
+ push ds
+ mov dx, offset handle2f
+ push cs ; get current code segment
+ pop ds
+ mov ah, 25h
+ mov al, 2fh ; vector to hook
+ int 21h ; hook that vector
+ pop ds
+
+
+; Print out some information about the handler
+
+ push cs ; code segment
+ pop ax
+ mov bx, offset hndmsga
+ call hexasc
+
+ mov ax, offset handle2f ; offset of ISR
+ mov bx, offset hndmsgb
+ call hexasc
+
+ mov ax, offset init_fence ; length in bytes of handler
+ mov bx, offset hndmsgc
+ call hexasc
+
+ Writel hndmsg
+
+; Compute size of TSR area
+
+ mov dx, offset init_fence ; start of initialization code
+ add dx, 15 ; round it off to paragraph
+ shr dx, 1 ; divide by 16
+ shr dx, 1
+ shr dx, 1
+ shr dx, 1
+ add dx, 32 ; add in PSP
+ mov TSR_rsv, dx ; save it
+
+ mov ax, dx
+ mov bx, offset tsrmsgx
+ call hexasc
+
+ Writel tsrmsg
+
+; Terminate and stay resident
+
+ mov ax, 3100h ; TSR
+ mov dx, TSR_rsv ; # of paragraphs to reserve
+ int 21h ; TSR
+vxdstub endp
+
+
+
+;************************************************************************
+;
+; HEXASC
+;
+; This subroutine formats hex values into ASCII
+; (utility routine from Advanced MS-DOS Programming)
+;
+;
+;************************************************************************
+
+hexasc proc near ; converts word to hex ASCII
+ ; call with AX = value,
+ ; DS:BX = address for string
+ ; returns AX, BX destroyed
+
+ push cx ; save registers
+ push dx
+
+ mov dx,4 ; initialize character counter
+hexasc1:
+ mov cx,4 ; isolate next four bits
+ rol ax,cl
+ mov cx,ax
+ and cx,0fh
+ add cx,'0' ; convert to ASCII
+ cmp cx,'9' ; is it 0-9?
+ jbe hexasc2 ; yes, jump
+ add cx,'A'-'9'-1 ; add fudge factor for A-F
+
+hexasc2: ; store this character
+ mov [bx],cl
+ inc bx ; bump string pointer
+
+ dec dx ; count characters converted
+ jnz hexasc1 ; loop, not four yet
+
+ pop dx ; restore registers
+ pop cx
+ ret ; back to caller
+
+hexasc endp
+
+
+
+_TEXT ends
+
+
+
+ end vxdstub
+
+ \ No newline at end of file
diff --git a/private/ntos/nbt/vxd/wfw.c b/private/ntos/nbt/vxd/wfw.c
new file mode 100644
index 000000000..c7f9bb7ce
--- /dev/null
+++ b/private/ntos/nbt/vxd/wfw.c
@@ -0,0 +1,694 @@
+/**********************************************************************/
+/** Microsoft Windows **/
+/** Copyright(c) Microsoft Corp., 1994 **/
+/**********************************************************************/
+
+/*
+
+ wfw.c
+
+ Contains VxD code that is specific to WFW
+
+
+ FILE HISTORY:
+ Johnl 14-Mar-1994 Created
+
+*/
+
+#include <nbtprocs.h>
+#include <tdiinfo.h>
+#include <llinfo.h>
+#include <ipinfo.h>
+#include <dhcpinfo.h>
+#include <nbtinfo.h>
+
+//
+// any digit 0 to 9 and '.' are legal characters in an ipaddr
+//
+#define IS_IPADDR_CHAR( ch ) ( (ch >= '0' && ch <= '9') || (ch == '.') )
+
+#define MAX_ADAPTER_DESCRIPTION_LENGTH 128
+
+#ifndef CHICAGO
+#pragma BEGIN_INIT
+
+extern char NBTSectionName[]; // Section in system.ini parameters are stored
+extern char DNSSectionName[]; // Section where we find DNS server ipaddrs
+
+void GetDnsServerAddress( ULONG IpAddr, PULONG pIpNameServer);
+
+extern ULONG CurrentIP ;
+
+/*******************************************************************
+
+ NAME: GetActiveLanasFromIP
+
+ SYNOPSIS: Queries TDI for all IP drivers that have a non-zero IP
+ address. For non-zero IP address, a DEVICE_CONTEXT is
+ created.
+
+ RETURNS: TRUE if successful, FALSE otherwise
+
+ NOTES: Even if we fail to setup a particular adapter, the Lana
+ count is maintained.
+
+ This routine is only used by Snowball
+
+********************************************************************/
+
+BOOL GetActiveLanasFromIP( VOID )
+{
+ NTSTATUS status ;
+ TDI_STATUS tdistatus ;
+ int i, j, k ;
+ uchar Context[CONTEXT_SIZE] ;
+ TDIObjectID ID ;
+ TDIEntityID EList[MAX_TDI_ENTITIES] ;
+ ULONG Size ;
+ UINT NumReturned ;
+ NDIS_BUFFER ndisbuff ;
+ BOOL fAnyValidIPs = FALSE ;
+ UINT iLanaOffset = 0 ;
+ IFEntry *ifeAdapterInfo[MAX_TDI_ENTITIES];
+ UINT AdptNum;
+ UCHAR MacAddr[6];
+ UCHAR PreviousNodeType;
+
+ //
+ // The first thing to do is get the list of available entities, and make
+ // sure that there are some interface entities present.
+ //
+ ID.toi_entity.tei_entity = GENERIC_ENTITY;
+ ID.toi_entity.tei_instance = 0;
+ ID.toi_class = INFO_CLASS_GENERIC;
+ ID.toi_type = INFO_TYPE_PROVIDER;
+ ID.toi_id = ENTITY_LIST_ID;
+
+ Size = sizeof(EList);
+ InitNDISBuff( &ndisbuff, &EList, Size, NULL ) ;
+ memset(Context, 0, CONTEXT_SIZE);
+
+ tdistatus = TdiVxdQueryInformationEx( 0,
+ &ID,
+ &ndisbuff,
+ &Size,
+ Context);
+
+ if (tdistatus != TDI_SUCCESS)
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "GetActiveLanasFromIP: Querying entity list failed\r\n")) ;
+ return FALSE ;
+ }
+
+ NumReturned = (uint)Size/sizeof(TDIEntityID);
+
+ AdptNum = 0;
+ //
+ // first find out info about the adapters
+ //
+ for (i = 0; i < NumReturned; i++)
+ {
+ //
+ // if this entity/instance describes an adapter
+ //
+ if ( EList[i].tei_entity == IF_ENTITY )
+ {
+ DWORD isMib;
+
+
+ ID.toi_entity.tei_entity = EList[i].tei_entity ;
+ ID.toi_entity.tei_instance = EList[i].tei_instance;
+ ID.toi_class = INFO_CLASS_GENERIC ;
+ ID.toi_type = INFO_TYPE_PROVIDER;
+ ID.toi_id = ENTITY_TYPE_ID ;
+
+ Size = sizeof( isMib );
+ InitNDISBuff( &ndisbuff, &isMib, Size, NULL ) ;
+ memset(Context, 0, CONTEXT_SIZE);
+ tdistatus = TdiVxdQueryInformationEx( 0,
+ &ID,
+ &ndisbuff,
+ &Size,
+ Context);
+ if ( tdistatus != TDI_SUCCESS )
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "GetActiveLanasFromIP: Getting isMib failed\r\n")) ;
+ return FALSE ;
+ }
+
+ //
+ // Does this entity support MIB
+ //
+ if (isMib != IF_MIB)
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "GetActiveLanasFromIP: skipping non-MIB entity\r\n")) ;
+ continue;
+ }
+
+ //
+ // MIB requests supported - query the adapter info
+ //
+
+ Size = sizeof(IFEntry) + MAX_ADAPTER_DESCRIPTION_LENGTH + 1;
+
+ ifeAdapterInfo[AdptNum] = (IFEntry *)CTEAllocInitMem((USHORT)Size);
+
+ if ( ifeAdapterInfo[AdptNum] == NULL )
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "GetActiveLanasFromIP: Couldn't allocate AdapterInfo buffer\r\n")) ;
+ return FALSE;
+ }
+
+ ID.toi_class = INFO_CLASS_PROTOCOL;;
+ ID.toi_id = IF_MIB_STATS_ID;
+
+ Size = sizeof(IFEntry) + MAX_ADAPTER_DESCRIPTION_LENGTH + 1;
+ InitNDISBuff( &ndisbuff, ifeAdapterInfo[AdptNum], Size, NULL ) ;
+ memset(Context, 0, CONTEXT_SIZE);
+ tdistatus = TdiVxdQueryInformationEx( 0,
+ &ID,
+ &ndisbuff,
+ &Size,
+ Context);
+ if ( tdistatus != TDI_SUCCESS )
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "GetActiveLanasFromIP: Getting IF type failed\r\n")) ;
+ for ( k=0; k<AdptNum; k++ )
+ {
+ CTEFreeMem( ifeAdapterInfo[k] ) ;
+ }
+ return FALSE ;
+ }
+
+ AdptNum++;
+ }
+ }
+
+ //
+ // now that we know about the adapters, get the ipaddrs
+ //
+ for (i = 0; i < NumReturned; i++)
+ {
+ if ( EList[i].tei_entity == CL_NL_ENTITY )
+ {
+ IPSNMPInfo IPStats ;
+ IPAddrEntry * pIAE ;
+ ULONG NLType ;
+ ULONG IpNameServer[COUNT_NS_ADDR];
+ ULONG IpDnsServer[COUNT_NS_ADDR];
+ UCHAR IpIndex;
+
+ //
+ // Does this entity support IP?
+ //
+
+ ID.toi_entity.tei_entity = EList[i].tei_entity ;
+ ID.toi_entity.tei_instance = EList[i].tei_instance;
+ ID.toi_class = INFO_CLASS_GENERIC ;
+ ID.toi_type = INFO_TYPE_PROVIDER;
+ ID.toi_id = ENTITY_TYPE_ID ;
+
+ Size = sizeof( NLType );
+ InitNDISBuff( &ndisbuff, &NLType, Size, NULL ) ;
+ memset(Context, 0, CONTEXT_SIZE);
+ tdistatus = TdiVxdQueryInformationEx( 0,
+ &ID,
+ &ndisbuff,
+ &Size,
+ Context);
+ if ( tdistatus != TDI_SUCCESS )
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "GetActiveLanasFromIP: Getting NL type failed\r\n")) ;
+ for ( k=0; k<AdptNum; k++ )
+ {
+ CTEFreeMem( ifeAdapterInfo[k] ) ;
+ }
+ return FALSE ;
+ }
+
+ if ( NLType != CL_NL_IP )
+ continue ;
+
+ //
+ // We've got an IP driver so get it's address table
+ //
+
+ ID.toi_class = INFO_CLASS_PROTOCOL ;
+ ID.toi_id = IP_MIB_STATS_ID;
+ Size = sizeof(IPStats);
+ InitNDISBuff( &ndisbuff, &IPStats, Size, NULL ) ;
+ memset(Context, 0, CONTEXT_SIZE);
+ tdistatus = TdiVxdQueryInformationEx( 0,
+ &ID,
+ &ndisbuff,
+ &Size,
+ Context);
+ if ( tdistatus != TDI_SUCCESS )
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "GetActiveLanasFromIP: Getting IPStats failed\r\n")) ;
+ continue ;
+ }
+
+ if ( IPStats.ipsi_numaddr < 1 )
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "GetActiveLanasFromIP: No IP Addresses installed\r\n")) ;
+ continue ;
+ }
+
+ Size = sizeof(IPAddrEntry) * IPStats.ipsi_numaddr ;
+ if ( !(pIAE = (IPAddrEntry*) CTEAllocInitMem( Size )) )
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "GetActiveLanasFromIP: Couldn't allocate IP table buffer\r\n")) ;
+ continue ;
+ }
+
+ ID.toi_id = IP_MIB_ADDRTABLE_ENTRY_ID ;
+ InitNDISBuff( &ndisbuff, pIAE, Size, NULL ) ;
+ memset( Context, 0, CONTEXT_SIZE ) ;
+ tdistatus = TdiVxdQueryInformationEx( 0,
+ &ID,
+ &ndisbuff,
+ &Size,
+ Context);
+ if ( tdistatus != TDI_SUCCESS )
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "GetActiveLanasFromIP: Getting IP address table failed\r\n")) ;
+ CTEFreeMem( pIAE ) ;
+ continue ;
+ }
+
+ ASSERT( Size/sizeof(IPAddrEntry) >= IPStats.ipsi_numaddr ) ;
+
+ //
+ // We have the IP address table for this IP driver. Look for
+ // non-zero IP addresses
+ //
+
+ for ( j = 0 ; j < IPStats.ipsi_numaddr ; j++ )
+ {
+ //
+ // Skip the loopback address
+ //
+ if ((pIAE[j].iae_addr & 0x000000ff) == 0x0000007f )
+ {
+ continue ;
+ }
+
+ CurrentIP = pIAE[j].iae_addr ;
+ if (!CurrentIP)
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "Init: ipaddr is 0, but accepting\n\r")) ;
+ }
+
+ //
+ // now find out the mac address for this ipaddr
+ //
+ memset( MacAddr, 0, 6 ) ;
+ IpIndex = -1;
+ for ( k=0; k<AdptNum; k++ )
+ {
+ if ( ifeAdapterInfo[k]->if_index == pIAE[j].iae_index )
+ {
+ CTEMemCopy( MacAddr, ifeAdapterInfo[k]->if_physaddr, 6 );
+ IpIndex = ifeAdapterInfo[k]->if_index;
+ break;
+ }
+ }
+ ASSERT(IpIndex != -1);
+
+ PreviousNodeType = NodeType;
+
+ //
+ // This will re-read the DHCPable parameters now that we have
+ // a potential DHCP source
+ //
+ ReadParameters2( pNbtGlobConfig, NULL );
+
+ if (PreviousNodeType & PROXY)
+ {
+ NodeType |= PROXY;
+ }
+
+ //
+ // Get all the NBNS servers' and DNS servers' ipaddresses
+ //
+ GetNameServerAddress( CurrentIP, IpNameServer);
+
+ GetDnsServerAddress( CurrentIP, IpDnsServer);
+
+ //
+ // IP stores the address in network order, so we will un-network order
+ // them because that's what NBT expects (would be nice to avoid conversion)
+ //
+ status = CreateDeviceObject( pNbtGlobConfig,
+ htonl( pIAE[j].iae_addr ),
+ htonl( pIAE[j].iae_mask ),
+ IpNameServer[0],
+ IpNameServer[1],
+ IpDnsServer[0],
+ IpDnsServer[1],
+ MacAddr,
+ IpIndex
+ ) ;
+
+ if ( !NT_SUCCESS( status ) )
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "Init: CreateDeviceObject failed\n\r")) ;
+ iLanaOffset++ ;
+ continue ;
+ }
+
+ if ( !RegisterLana( LanaBase + iLanaOffset ) )
+ {
+ CDbgPrint( DBGFLAG_ERROR, ( "Init: RegisterLana failed\n\r")) ;
+ iLanaOffset++ ;
+ continue ;
+ }
+
+ LanaTable[iLanaOffset].pDeviceContext =
+ (tDEVICECONTEXT*)pNbtGlobConfig->DeviceContexts.Blink ;
+ LanaTable[iLanaOffset].pDeviceContext->iLana = LanaBase +
+ iLanaOffset;
+ iLanaOffset++;
+ fAnyValidIPs = TRUE ;
+
+ } // addr traversal
+
+ CTEFreeMem( pIAE ) ;
+
+ } // if IP
+ } // entity traversal
+
+ for ( k=0; k<AdptNum; k++ )
+ {
+ CTEFreeMem( ifeAdapterInfo[k] ) ;
+ }
+
+ return fAnyValidIPs ;
+}
+
+/*******************************************************************
+
+ NAME: VxdReadIniString
+
+ SYNOPSIS: Vxd stub for CTEReadIniString
+
+ ENTRY: pchKey - Key value to look for in the NBT section
+ ppchString - Pointer to buffer found string is returned in
+
+ EXIT: ppchString will point to an allocated buffer
+
+ RETURNS: STATUS_SUCCESS if found
+
+ NOTES: The client must free ppchString when done with it
+
+ HISTORY:
+ Johnl 30-Aug-1993 Created
+ Koti 30-May-194 Added 3rd parm to GetProfileString
+
+********************************************************************/
+
+CHAR * GetProfileString( LPTSTR pchKey, LPTSTR * pchDefault, PCHAR SectName ) ;
+
+NTSTATUS VxdReadIniString( LPSTR pchKey, LPSTR * ppchString )
+{
+ char * pchTmp ;
+
+ if ( pchTmp = GetProfileString( pchKey, NULL, NBTSectionName ) )
+ {
+ if ( *ppchString = CTEAllocInitMem( strlen( pchTmp ) + 1) )
+ {
+ strcpy( *ppchString, pchTmp ) ;
+ return STATUS_SUCCESS ;
+ }
+ else
+ return STATUS_INSUFFICIENT_RESOURCES ;
+ }
+ else
+ {
+ //
+ // Does DHCP have it?
+ //
+
+ if ( pchTmp = (char *) GetDhcpOption( pchKey, 0 ) )
+ {
+ *ppchString = pchTmp ;
+ return STATUS_SUCCESS ;
+ }
+ }
+
+ return STATUS_UNSUCCESSFUL ;
+}
+
+
+/*******************************************************************
+
+ NAME: GetDnsServerAddress
+
+ SYNOPSIS: Gets the DNS server ipaddrs from the DNS section of system.ini
+
+ Or, if DHCP is installed and the DNS server addresses aren't
+ found, we get them from DHCP
+
+ ENTRY: IpAddr - If we can get from DHCP, get form this address
+ pIpDnsServer - Receives addresses if found (otherwise 0)
+
+ NOTES: This routine is only used by Snowball
+
+ HISTORY:
+ Koti 30-May-1994 Created
+
+********************************************************************/
+
+void GetDnsServerAddress( ULONG IpAddr, PULONG pIpDnsServer)
+{
+ UCHAR i ;
+ PUCHAR pchDnsSrv = "DNSServers" ;
+ UINT OptId;
+ PUCHAR pchTmp;
+ PUCHAR pchCurrent, pchNext;
+ LPTSTR pchString=NULL ;
+ TDI_STATUS tdistatus ;
+ BOOL fPrimaryFound = FALSE;
+ BOOL fOneMore=TRUE;
+ ULONG Buff[COUNT_NS_ADDR] ;
+
+
+
+ //
+ // initialize all of them to worst case
+ //
+ for ( i = 0; i < COUNT_NS_ADDR; i++)
+ {
+ pIpDnsServer[i] = LOOP_BACK ;
+ }
+
+ pchTmp = GetProfileString( pchDnsSrv, NULL, DNSSectionName );
+ if ( pchTmp == NULL )
+ {
+ goto Not_In_Sysini;
+ }
+
+ if ( !(pchString = CTEAllocInitMem( strlen( pchTmp ) + 1)) )
+ {
+ DbgPrint("GetDnsServerAddress: CTEAllocInitMem failed!\r\n") ;
+ goto Not_In_Sysini;
+ }
+
+ strcpy( pchString, pchTmp ) ;
+
+ //
+ // we are generating (upto) COUNT_NS_ADDR pointers each pointing to
+ // one ipaddr. The string in system.ini looks like:
+ // DNSServers = 11.101.4.26,200.200.200.200,1.2.3.4,1.91.245.10
+ //
+ pchNext = pchCurrent = pchString;
+
+ if ( IS_IPADDR_CHAR(*pchCurrent) ) // make sure at least one ipaddr defnd
+ {
+ i = 0;
+ while( (i < COUNT_NS_ADDR) && fOneMore )
+ {
+ while( IS_IPADDR_CHAR(*pchNext) )
+ pchNext++;
+
+ if ( *pchNext == ',' ) // ',' is the separator between 2 addrs
+ {
+ *pchNext = '\0';
+ pchNext++;
+ }
+ else
+ {
+ fOneMore = FALSE; // reached end of line
+ }
+
+ //
+ // as long as at least the first one ipaddr gets converted properly,
+ // ignore errors in others
+ //
+ if ( ConvertDottedDecimalToUlong( pchCurrent, &pIpDnsServer[i] ))
+ {
+ if ( i == 0 )
+ goto Not_In_Sysini;
+ else
+ pIpDnsServer[i] = LOOP_BACK ;
+ }
+
+ fPrimaryFound = TRUE; // => at least one ipaddr is good
+
+ i++;
+
+ pchCurrent = pchNext; // go, convert the next one
+ }
+ }
+
+
+Not_In_Sysini:
+
+ if( pchString != NULL )
+ {
+ CTEFreeMem( pchString ) ;
+ }
+
+ //
+ // if we didn't find in the .ini file, try getting them from DHCP
+ //
+ if ( !fPrimaryFound )
+ {
+ ULONG Size = sizeof( Buff ) ;
+
+ OptId = 6; // DNS Option
+
+ tdistatus = DhcpQueryOption( IpAddr,
+ OptId,
+ &Buff,
+ &Size ) ;
+
+ switch ( tdistatus )
+ {
+ case TDI_SUCCESS:
+ case TDI_BUFFER_OVERFLOW: // May be more then one our buffer will hold
+ for ( i = 0; i < COUNT_NS_ADDR; i++ )
+ {
+ if ( Size >= (sizeof(ULONG)*(i+1)))
+ pIpDnsServer[i] = htonl(Buff[i]) ;
+ }
+ break ;
+
+ case TDI_INVALID_PARAMETER: // Option not found
+ break ;
+
+ default:
+ ASSERT( FALSE ) ;
+ break ;
+ }
+ }
+
+ KdPrint(("GetDnsServerAddress: Primary: %x, backup: %x\r\n",
+ pIpDnsServer[0], pIpDnsServer[1] )) ;
+
+}
+
+/*******************************************************************
+
+ NAME: GetNameServerAddress
+
+ SYNOPSIS: Gets the Win server for the specified Lana.
+
+ Or, if DHCP is installed and the Name server addresses aren't
+ found, we get them from DHCP
+
+ ENTRY: IpAddr - If we can get from DHCP, get form this address
+ pIpNameServer - Receives addresses if found (otherwise 0)
+
+ NOTES: This routine is only used by Snowball
+
+ HISTORY:
+ Johnl 21-Oct-1993 Created
+
+********************************************************************/
+
+void GetNameServerAddress( ULONG IpAddr,
+ PULONG pIpNameServer)
+{
+ UCHAR i ;
+ PUCHAR pchSrv = "NameServer$" ;
+ PUCHAR pchSrvNum;
+ UINT OptId;
+ LPTSTR pchString ;
+ TDI_STATUS TdiStatus ;
+ BOOL fPrimaryFound = FALSE;
+ ULONG Buff[COUNT_NS_ADDR] ;
+
+
+ OptId = 44; // NBNS Option
+ pchSrvNum = pchSrv + 10 ; // to overwrite '$' with 1,2,3 etc.
+
+
+ for ( i = 0; i < COUNT_NS_ADDR; i++)
+ {
+
+ pIpNameServer[i] = LOOP_BACK ;
+ *pchSrvNum = '1' + i;
+
+ if ( !CTEReadIniString( NULL, pchSrv, &pchString ) )
+ {
+ if ( ConvertDottedDecimalToUlong( pchString, &pIpNameServer[i] ))
+ {
+ //
+ // Bad IP address format
+ //
+ DbgPrint("GetNameServerAddress: ConvertDottedDecimalToUlong failed!\r\n") ;
+ pIpNameServer[i] = LOOP_BACK ;
+ }
+ else if ( i == 0 )
+ fPrimaryFound = TRUE ;
+
+ CTEFreeMem( pchString ) ;
+ }
+ }
+
+ //
+ // Not in the .ini file, try getting them from DHCP
+ //
+
+ if ( !fPrimaryFound )
+ {
+ ULONG Size = sizeof( Buff ) ;
+ TDI_STATUS tdistatus ;
+
+ tdistatus = DhcpQueryOption( IpAddr,
+ OptId,
+ &Buff,
+ &Size ) ;
+
+ switch ( tdistatus )
+ {
+ case TDI_SUCCESS:
+ case TDI_BUFFER_OVERFLOW: // May be more then one our buffer will hold
+ for ( i = 0; i < COUNT_NS_ADDR; i++ )
+ {
+ if ( Size >= (sizeof(ULONG)*(i+1)))
+ pIpNameServer[i] = htonl(Buff[i]) ;
+ }
+ break ;
+
+ case TDI_INVALID_PARAMETER: // Option not found
+ break ;
+
+ default:
+ ASSERT( FALSE ) ;
+ break ;
+ }
+ }
+
+ KdPrint(("GetNameServerAddress: Primary: %x, backup: %x\r\n",
+ pIpNameServer[0], pIpNameServer[1] )) ;
+
+}
+
+
+#pragma END_INIT
+#endif //!CHICAGO
+
+
diff --git a/private/ntos/nbt/vxd/wfwasm.asm b/private/ntos/nbt/vxd/wfwasm.asm
new file mode 100644
index 000000000..79b9cb818
--- /dev/null
+++ b/private/ntos/nbt/vxd/wfwasm.asm
@@ -0,0 +1,285 @@
+;*****************************************************************;
+;** Copyright(c) Microsoft Corp., 1988-1993 **;
+;*****************************************************************;
+;:ts=8
+ TITLE WFWASM.ASM - WFW Specific vnbt routines
+.XLIST
+;*** VNBT -- NetBios over TCP/IP VxD
+;
+;
+ .386p
+ include vmm.inc
+ include dosmgr.inc
+ include netvxd.inc
+ include vdhcp.inc
+ include debug.inc
+ include vtdi.inc
+
+ include vnbtd.inc
+ include vnetbios.inc
+.LIST
+
+IFNDEF CHICAGO
+
+EXTRN _GetDhcpOption:NEAR
+EXTRN NCB_Handler:NEAR
+
+VxD_ICODE_SEG
+
+public _NBTSectionName
+_NBTSectionName db 'NBT',0 ; Section in system.ini parameters are stored
+public _DNSSectionName
+_DNSSectionName db 'DNS',0 ; DNS Section in system.ini
+
+;****************************************************************************
+;** _GetProfileInt
+;
+; Reads a parameter from our system.ini file (INIT TIME ONLY!)
+;
+; Entry: See ReadParamParams
+;
+; Exit: Eax contains specified value or defaulted value
+;
+
+ReadParamParams struc
+ dd ? ; Return Address
+ dd ? ; Saved edi
+ dd ? ; Saved esi
+ dd ? ; ParametersHandle (unused)
+ValueName dd ? ; Pointer to value name string
+DefaultValue dd ? ; Value to use if not in .ini file
+MinimumValue dd ? ; Specified value must be >= MinimumValue
+
+ReadParamParams ends
+
+BeginProc _GetProfileInt
+ push edi
+ push esi
+
+ ;
+ ; Get the value from the system.ini file (if can't be found then eax
+ ; will contain the default value)
+ ;
+ mov eax, [esp].DefaultValue
+ mov esi, OFFSET32 _NBTSectionName
+ mov edi, [esp].ValueName
+ VMMCall Get_Profile_Decimal_Int
+
+ jnc GPI_Found
+
+ push eax ; Default value
+ push edi ; Value name
+ call _GetDhcpOption ; Returns DHCP value or default
+ add esp, 8
+
+GPI_Found:
+ ;
+ ; Does the value meet our standards?
+ ;
+ cmp eax, [esp].MinimumValue ; Unsigned comparison
+ ja RP10
+ mov eax, [esp].MinimumValue
+
+RP10:
+ pop esi
+ pop edi
+ ret
+EndProc _GetProfileInt
+
+;****************************************************************************
+;** _GetProfileHex
+;
+; Reads a hex parameter from our system.ini file (INIT TIME ONLY!)
+;
+; Entry: See ReadParamParams
+;
+; Exit: Eax contains specified value or defaulted value
+;
+
+ReadParamParams struc
+ dd ? ; Return Address
+ dd ? ; Saved edi
+ dd ? ; Saved esi
+ dd ? ; ParametersHandle (unused)
+ValueName dd ? ; Pointer to value name string
+DefaultValue dd ? ; Value to use if not in .ini file
+MinimumValue dd ? ; Specified value must be >= MinimumValue
+
+ReadParamParams ends
+
+BeginProc _GetProfileHex
+ push edi
+ push esi
+
+ ;
+ ; Get the value from the system.ini file (if can't be found then eax
+ ; will contain the default value)
+ ;
+ mov eax, [esp].DefaultValue
+ mov esi, OFFSET32 _NBTSectionName
+ mov edi, [esp].ValueName
+ VMMCall Get_Profile_Hex_Int
+
+ jnc GPH_Found
+
+ push eax ; Default value
+ push edi ; Value name
+ call _GetDhcpOption ; Returns DHCP value or default
+ add esp, 8
+
+GPH_Found:
+ ;
+ ; Does the value meet our standards?
+ ;
+ cmp eax, [esp].MinimumValue ; Unsigned comparison
+ ja RHP10
+ mov eax, [esp].MinimumValue
+
+RHP10:
+ pop esi
+ pop edi
+ ret
+EndProc _GetProfileHex
+
+
+;****************************************************************************
+;** _GetProfileString
+;
+; Reads a string from our system.ini file (INIT TIME ONLY!)
+;
+; Entry: See GetProfileStrParams structure
+;
+; Exit: Eax contains the found value or NULL if not found
+;
+; History:
+; 30-May-94 Koti
+; this function modified to accept name of the section
+; to look at as a parameter. Getting DNS server ipaddrs
+; from the DNS section in system.ini demanded this change
+;
+
+GetProfileStrParams struc
+ dd ? ; Return Address
+ dd ? ; saved edx
+ dd ? ; Saved edi
+ dd ? ; Saved esi
+gps_ValueName dd ? ; Pointer to value name string
+gps_DefaultValue dd ? ; Value to use if not in .ini file
+gps_SectionName dd ? ; Name of the section to look at (almost always NBT)
+GetProfileStrParams ends
+
+BeginProc _GetProfileString
+ push edx
+ push edi
+ push esi
+
+ ;
+ ; Get the value from the system.ini file (if can't be found then eax
+ ; will contain the default value)
+ ;
+ mov edx, [esp].gps_DefaultValue
+ mov esi, [esp].gps_SectionName
+ mov edi, [esp].gps_ValueName
+ VMMCall Get_Profile_String
+
+ jc GetProf10
+ mov eax, edx ; Success
+ jmp short GetProf20
+
+GetProf10:
+ mov eax, 0 ; Couldn't find the string
+
+GetProf20:
+
+ pop esi
+ pop edi
+ pop edx
+ ret
+EndProc _GetProfileString
+
+;****************************************************************************
+;** _RegisterLana
+;
+; Registers the requested lana with the VNetbios driver.
+;
+; Entry: [ESP+4] - Lana number to register
+;
+; Exit: EAX will be TRUE if successful, FALSE if not
+;
+; Uses:
+;
+BeginProc _RegisterLana
+
+ mov eax, [esp+4] ; Get the request lana to register
+
+ push ebx
+ push edx
+
+ mov ebx, 1 ; Take over RM lana
+ mov edx, NCB_Handler
+ VxDcall VNETBIOS_Register ; Carry set on failure
+ jnc RegLana10
+ mov eax, 0 ; Failed
+ jmp short RegLana20
+
+RegLana10:
+ mov eax, 1 ; Success
+
+RegLana20:
+ pop edx
+ pop ebx
+ ret
+
+EndProc _RegisterLana
+
+;****************************************************************************
+;** _DhcpSetInfo - Sets DHCP information
+;
+; Stub callout to the Dhcp driver
+;
+; Entry: [ESP+4] - Info type
+; [ESP+8] - IP Address of interest
+; [ESP+12]- Pointer to buffer
+; [ESP+16]- Pointer to buffer size
+;
+; INIT TIME ONLY!
+;
+
+BeginProc _DhcpSetInfo
+
+ VxdCall VDHCP_Get_Version
+ jnc DSI_Installed
+
+ mov eax, 26 ; DHCP not installed, return invalid param
+ ret
+
+DSI_Installed:
+ push ebp
+ mov ebp,esp
+
+ mov eax, [ebp+20] ; Buff size
+ push eax
+ mov eax, [ebp+16] ; Buff
+ push eax
+ mov eax, [ebp+12] ; IP Address
+ push eax
+ mov eax, [ebp+8] ; Info type
+ push eax
+
+ VxdCall VDHCP_Set_Info
+
+ add esp, 16
+
+ pop ebp
+ ret
+
+EndProc _DhcpSetInfo
+
+VxD_ICODE_ENDS
+
+ENDIF ;!CHICAGO
+
+END
+
+
+