From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/nbt/vxd/aaaaaaaa.c | 2 + private/ntos/nbt/vxd/chic.c | 1787 ++++++++++++++++ private/ntos/nbt/vxd/chicasm.asm | 122 ++ private/ntos/nbt/vxd/cinit.c | 930 +++++++++ private/ntos/nbt/vxd/client.asm | 427 ++++ private/ntos/nbt/vxd/ctimer.c | 237 +++ private/ntos/nbt/vxd/cvxdfile.asm | 186 ++ private/ntos/nbt/vxd/cxport.inc | 4 + private/ntos/nbt/vxd/depend.mk | 1279 ++++++++++++ private/ntos/nbt/vxd/dns.c | 984 +++++++++ private/ntos/nbt/vxd/fileio.c | 476 +++++ private/ntos/nbt/vxd/limit.txt | 51 + private/ntos/nbt/vxd/makefile | 28 + private/ntos/nbt/vxd/nbtinfo.c | 227 +++ private/ntos/nbt/vxd/ncb.c | 529 +++++ private/ntos/nbt/vxd/newdns.c | 1019 ++++++++++ private/ntos/nbt/vxd/pageable.inc | 36 + private/ntos/nbt/vxd/rules.mk | 4 + private/ntos/nbt/vxd/tdiaddr.c | 184 ++ private/ntos/nbt/vxd/tdicnct.c | 328 +++ private/ntos/nbt/vxd/tdihndlr.c | 1719 ++++++++++++++++ private/ntos/nbt/vxd/tdiout.c | 601 ++++++ private/ntos/nbt/vxd/util.c | 192 ++ private/ntos/nbt/vxd/vfirst.asm | 79 + private/ntos/nbt/vxd/vnbt.rcv | 15 + private/ntos/nbt/vxd/vnbtd.asm | 993 +++++++++ private/ntos/nbt/vxd/vnbtd.def | 21 + private/ntos/nbt/vxd/vnbtd.inc | 18 + private/ntos/nbt/vxd/vnbtd.mk | 318 +++ private/ntos/nbt/vxd/vxddebug.c | 659 ++++++ private/ntos/nbt/vxd/vxdfile.asm | 314 +++ private/ntos/nbt/vxd/vxdisol.c | 4042 +++++++++++++++++++++++++++++++++++++ private/ntos/nbt/vxd/vxdstub.asm | 250 +++ private/ntos/nbt/vxd/wfw.c | 694 +++++++ private/ntos/nbt/vxd/wfwasm.asm | 285 +++ 35 files changed, 19040 insertions(+) create mode 100644 private/ntos/nbt/vxd/aaaaaaaa.c create mode 100644 private/ntos/nbt/vxd/chic.c create mode 100644 private/ntos/nbt/vxd/chicasm.asm create mode 100644 private/ntos/nbt/vxd/cinit.c create mode 100644 private/ntos/nbt/vxd/client.asm create mode 100644 private/ntos/nbt/vxd/ctimer.c create mode 100644 private/ntos/nbt/vxd/cvxdfile.asm create mode 100644 private/ntos/nbt/vxd/cxport.inc create mode 100644 private/ntos/nbt/vxd/depend.mk create mode 100644 private/ntos/nbt/vxd/dns.c create mode 100644 private/ntos/nbt/vxd/fileio.c create mode 100644 private/ntos/nbt/vxd/limit.txt create mode 100644 private/ntos/nbt/vxd/makefile create mode 100644 private/ntos/nbt/vxd/nbtinfo.c create mode 100644 private/ntos/nbt/vxd/ncb.c create mode 100644 private/ntos/nbt/vxd/newdns.c create mode 100644 private/ntos/nbt/vxd/pageable.inc create mode 100644 private/ntos/nbt/vxd/rules.mk create mode 100644 private/ntos/nbt/vxd/tdiaddr.c create mode 100644 private/ntos/nbt/vxd/tdicnct.c create mode 100644 private/ntos/nbt/vxd/tdihndlr.c create mode 100644 private/ntos/nbt/vxd/tdiout.c create mode 100644 private/ntos/nbt/vxd/util.c create mode 100644 private/ntos/nbt/vxd/vfirst.asm create mode 100644 private/ntos/nbt/vxd/vnbt.rcv create mode 100644 private/ntos/nbt/vxd/vnbtd.asm create mode 100644 private/ntos/nbt/vxd/vnbtd.def create mode 100644 private/ntos/nbt/vxd/vnbtd.inc create mode 100644 private/ntos/nbt/vxd/vnbtd.mk create mode 100644 private/ntos/nbt/vxd/vxddebug.c create mode 100644 private/ntos/nbt/vxd/vxdfile.asm create mode 100644 private/ntos/nbt/vxd/vxdisol.c create mode 100644 private/ntos/nbt/vxd/vxdstub.asm create mode 100644 private/ntos/nbt/vxd/wfw.c create mode 100644 private/ntos/nbt/vxd/wfwasm.asm (limited to 'private/ntos/nbt/vxd') 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 +#include +#include +#include +#include +#include + +#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= 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; kif_index == pIAE[j].iae_index ) + { + CTEMemCopy( MacAddr, ifeAdapterInfo[k]->if_physaddr, 6 ); + break; + } + } + } + + if (pIAE) + { + CTEFreeMem( pIAE ) ; + } + } + } + + for ( k=0; kParameterData.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;ilNumBuckets;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;ilNumBuckets;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 +#include +#include +#include +#include +#include + +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 + +;;; +;;; 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 + 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 + 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 + +;;; +;;; 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, + 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 + 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 + +;;; +;;; 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, + or eax, eax + jz uub_Failure + +uub_Success: + + mov eax, 1 ; !0 == success + +;;; +;;; Common exit path. Cleanup stack & return. +;;; + +uub_Exit: + + RestoreReg + 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 + +;;; +;;; 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, + cmp eax, ecx + jne vub_Failure + +vub_Success: + + mov eax, 1 ; TRUE == success. + +;;; +;;; Common exit path. Cleanup stack & return. +;;; + +vub_Exit: + + RestoreReg + 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 +#include + +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= '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 +#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 +#include +#include + +/******************************************************************* + + 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 +#include + +#ifdef CHICAGO + +#include + +#include + +// +// 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 +#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 \\" + 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 +#include // 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 + +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 // 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 +#include + +#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 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, +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, + 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, + 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, + + 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, ; 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 + pop edx ; restore InBuffer addr +vnbt_DontUnLock_OutBuf: + + or edx, edx + jz vnbt_DontUnLock + + movzx ebx, [ebp.Client_SI] + cCall __VxdUnlockBuffer + +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 +#include + + +#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(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, + 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 +#include + +// +// 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 - + 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 +#include +#include +#include +#include +#include + +// +// 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= 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; kif_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 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 + + + -- cgit v1.2.3