Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

529 lines
12 KiB

/**********************************************************************/
/** Microsoft Windows/NT **/
/** Copyright(c) Microsoft Corp., 1993 **/
/**********************************************************************/
/*
NCB.c
This file contains the NCB Handler that the VNetBios driver calls
FILE HISTORY:
Johnl 25-Mar-1993 Created
*/
#include <nbtprocs.h>
#include <debug.h>
#ifdef CHICAGO
#include <shell.h>
#include <netvxd.h>
//
// Do this so the VXDINLINE in the header file doesn't conflict
// with the actual function declaration in this file.
//
#define VNBT_NCB_X VNBT_NCB_X_CALL
#define VNBT_LANA_MASK VNBT_LANA_MASK_CALL
#include <vnbt.h>
#undef VNBT_LANA_MASK
#undef VNBT_NCB_X
#endif ;; CHICAGO
LANA_ENTRY LanaTable[NBT_MAX_LANAS] ;
/*******************************************************************
NAME: VNBT_NCB_X
SYNOPSIS: All NCBs submitted by the VNetBios driver come through
here
ENTRY: pNCB - Pointer to submitted NCB
Ipaddr - this parm is used only by nbtstat -A, which directly
calls into VNBT_NCB_X
ipaddress to which to send AdapterStatus to
RETURNS: NCB Return code
NOTES:
HISTORY:
Johnl 25-Mar-1993 Created
********************************************************************/
ULONG
_stdcall
VNBT_NCB_X( PNCB pNCB,
PUCHAR pzDnsName,
PULONG pIpAddress,
PVOID pExtended,
ULONG fFlag )
{
BOOL fAsync ;
tDEVICECONTEXT * pDeviceContext = NULL ;
NTSTATUS status = STATUS_SUCCESS ;
uchar errNCB = NRC_GOODRET ;
PBLOCKING_NCB_CONTEXT pBlkNcbContext;
ULONG Ipaddr = pIpAddress ? pIpAddress[0] : 0;
if ( !pNCB )
return NRC_INVADDRESS ;
pDeviceContext = GetDeviceContext( pNCB ) ;
if ( pDeviceContext == NULL )
return NRC_BRIDGE ;
if (!pDeviceContext->fDeviceUp)
return NRC_BRIDGE ;
fAsync = !!(pNCB->ncb_command & ASYNCH) ;
if (
( pzDnsName != NULL )
&& ( pIpAddress != NULL )
)
{
if ( fAsync )
{
return DoDnsResolveDirect( pNCB, pzDnsName, pIpAddress );
}
else
{
return (pNCB->ncb_retcode = pNCB->ncb_cmd_cplt = NRC_ILLCMD);
}
}
else if (
( pIpAddress != NULL )
&& ( Ipaddr != 0 )
&& ( ( pNCB->ncb_command & ~ASYNCH ) != NCBASTAT )
)
{
IpToAscii( Ipaddr, &pNCB->ncb_callname[0] );
}
if ( !fAsync )
{
pBlkNcbContext = CTEAllocMem( sizeof(BLOCKING_NCB_CONTEXT) );
if (!pBlkNcbContext)
{
DbgPrint("VNBT_NCB_X: couldn't alloc pBlkNcbContext 1") ;
return NRC_NORESOURCES;
}
pBlkNcbContext->Verify = NBT_VERIFY_BLOCKING_NCB;
InitializeListHead(&pBlkNcbContext->Linkage);
pBlkNcbContext->pNCB = pNCB;
pBlkNcbContext->pWaitNCBBlock = CTEAllocMem( sizeof(CTEBlockStruc) );
if (!pBlkNcbContext->pWaitNCBBlock)
{
CTEFreeMem(pBlkNcbContext);
DbgPrint("VNBT_NCB_X: couldn't alloc pBlkNcbContext 2") ;
return NRC_NORESOURCES;
}
pBlkNcbContext->fNCBCompleted = FALSE ;
//
// The completion routine uses this flag to know if the thread is
// blocked and needs to be signaled.
//
pBlkNcbContext->fBlocked = FALSE;
InsertTailList(&NbtConfig.BlockingNcbs,&pBlkNcbContext->Linkage);
}
DbgPrint("VNBT_NCB_X: NCB Commmand Rcvd: 0x") ;
DbgPrintNum( pNCB->ncb_command ) ; DbgPrint(", (") ;
DbgPrintNum( (ULONG) pNCB ) ; DbgPrint(")\r\n") ;
pNCB->ncb_retcode = NRC_PENDING ;
pNCB->ncb_cmd_cplt = NRC_PENDING ;
switch ( pNCB->ncb_command & ~ASYNCH )
{
case NCBDGSEND:
case NCBDGSENDBC:
status = VxdDgramSend( pDeviceContext, pNCB ) ;
errNCB = MapTDIStatus2NCBErr( status ) ;
break ;
case NCBDGRECV:
case NCBDGRECVBC:
errNCB = VxdDgramReceive( pDeviceContext, pNCB ) ;
break ;
case NCBRECVANY:
errNCB = VxdReceiveAny( pDeviceContext, pNCB ) ;
break ;
case NCBCALL:
errNCB = VxdCall( pDeviceContext, pNCB ) ;
break ;
case NCBHANGUP:
errNCB = VxdHangup( pDeviceContext, pNCB ) ;
break ;
case NCBLISTEN:
errNCB = VxdListen( pDeviceContext, pNCB ) ;
break ;
case NCBRECV:
errNCB = VxdReceive( pDeviceContext, pNCB, TRUE ) ;
break ;
case NCBSEND:
case NCBSENDNA:
case NCBCHAINSEND:
case NCBCHAINSENDNA:
errNCB = VxdSend( pDeviceContext, pNCB ) ;
break ;
#if 0
case NCBTRANSV:
errNCB = VxdTransceive( pDeviceContext, pNCB ) ;
break ;
#endif
case NCBADDGRNAME:
case NCBADDNAME:
errNCB = VxdOpenName( pDeviceContext, pNCB ) ;
break ;
case NCBDELNAME:
errNCB = VxdCloseName( pDeviceContext, pNCB ) ;
break ;
case NCBASTAT:
errNCB = VxdAdapterStatus( pDeviceContext, pNCB, Ipaddr ) ;
break ;
case NCBSSTAT:
errNCB = VxdSessionStatus( pDeviceContext, pNCB ) ;
break ;
case NCBFINDNAME:
errNCB = VxdFindName( pDeviceContext, pNCB ) ;
break ;
case NCBRESET:
errNCB = VxdReset( pDeviceContext, pNCB ) ;
break ;
case NCBCANCEL:
if ( DoDnsCancelDirect( pNCB ) )
{
errNCB = NRC_GOODRET;
}
else
{
errNCB = VxdCancel( pDeviceContext, pNCB ) ;
}
break ;
//
// The following are no-ops that return success for compatibility
//
case NCBUNLINK:
case NCBTRACE:
CTEIoComplete( pNCB, STATUS_SUCCESS, 0 ) ;
break ;
default:
DbgPrint("VNBT_NCB_X - Unsupported command: ") ;
DbgPrintNum( pNCB->ncb_command & ~ASYNCH ) ;
DbgPrint("\n\r") ;
errNCB = NRC_ILLCMD ; // Bogus error for now
break ;
}
Exit:
//
// If we aren't pending then set the codes
//
if ( errNCB != NRC_PENDING &&
errNCB != NRC_GOODRET )
{
#ifdef DEBUG
DbgPrint("VNBT_NCB_X - Returning ") ;
DbgPrintNum( errNCB ) ;
DbgPrint(" to NCB submitter\n\r") ;
#endif
pNCB->ncb_retcode = errNCB ;
pNCB->ncb_cmd_cplt = errNCB ;
//
// Errored NCBs don't have the completion routine called, so we
// in essence, complete it here. Note this will only set the
// state for the last Wait NCB (all others get NRC_IFBUSY).
//
if ( !fAsync )
{
ASSERT(pBlkNcbContext->Verify == NBT_VERIFY_BLOCKING_NCB);
pBlkNcbContext->fNCBCompleted = TRUE ;
}
}
else
{
//
// Some components (AKA server) don't like returning pending
//
errNCB = NRC_GOODRET ;
}
//
// Block until NCB completion if this wasn't an async NCB
//
if ( !fAsync )
{
ASSERT(pBlkNcbContext->Verify == NBT_VERIFY_BLOCKING_NCB);
if ( !pBlkNcbContext->fNCBCompleted )
{
pBlkNcbContext->fBlocked = TRUE;
CTEInitBlockStruc( pBlkNcbContext->pWaitNCBBlock ) ;
CTEBlock( pBlkNcbContext->pWaitNCBBlock ) ;
}
else
{
RemoveEntryList(&pBlkNcbContext->Linkage);
CTEFreeMem(pBlkNcbContext->pWaitNCBBlock);
CTEFreeMem(pBlkNcbContext);
}
}
return errNCB ;
}
/*******************************************************************
NAME: GetDeviceContext
SYNOPSIS: Retrieves the device context associated with the lana
specified in the NCB
ENTRY: pNCB - NCB to get the device context for
RETURNS: Device context or NULL if not found
NOTES: It is assumed that LanaTable is filled sequentially
with no holes.
HISTORY:
Johnl 30-Aug-1993 Created
********************************************************************/
tDEVICECONTEXT * GetDeviceContext( NCB * pNCB )
{
int i ;
if ( !pNCB )
return NULL ;
for ( i = 0; i < NBT_MAX_LANAS; i++)
{
if ( LanaTable[i].pDeviceContext->iLana == pNCB->ncb_lana_num)
return LanaTable[i].pDeviceContext;
}
return NULL;
}
/*******************************************************************
NAME: NbtWouldLoopback
SYNOPSIS: Returns a BOOL that specifies whether the input
IP address would loop back to the local machine
ENTRY: IpAddr
RETURNS: TRUE if Nbt is bound to this address
NOTES: It is assumed that LanaTable is filled sequentially
with no holes.
HISTORY:
EarleH 28-Mar-1996 Created
********************************************************************/
BOOL
NbtWouldLoopback(
ULONG IpAddr
)
{
int i ;
for ( i = 0; i < NBT_MAX_LANAS; i++)
{
if (
( LanaTable[i].pDeviceContext )
&& ( LanaTable[i].pDeviceContext->IpAddress == IpAddr )
)
return TRUE;
}
return FALSE;
}
/*******************************************************************
NAME: VNBT_LANA_MASK
SYNOPSIS: Returns a bit mask of LANA numbers being handled
by vnbt, with a DNS server configured
ENTRY: none
RETURNS: Bit mask of LANA numbers being handled by vnbt
NOTES:
HISTORY:
EarleH 26-Feb-1996 Created
********************************************************************/
ULONG
_stdcall
VNBT_LANA_MASK(
)
{
int i;
ULONG mask = 0;
for ( i = 0 ; i < NBT_MAX_LANAS; i++)
{
if (
( LanaTable[i].pDeviceContext )
&& ( LanaTable[i].pDeviceContext->fDeviceUp )
&& ( LanaTable[i].pDeviceContext->lDnsServerAddress )
&& ( LanaTable[i].pDeviceContext->lDnsServerAddress != LOOP_BACK )
)
{
mask |= 1 << LanaTable[i].pDeviceContext->iLana;
}
}
return mask;
}
/*******************************************************************
NAME: MapTDIStatus2NCBErr
SYNOPSIS: Maps a TDI_STATUS error value to an Netbios NCR error value
ENTRY: tdistatus - TDI Status to map
RETURNS: The mapped error
NOTES:
HISTORY:
Johnl 15-Apr-1993 Created
********************************************************************/
uchar MapTDIStatus2NCBErr( TDI_STATUS tdistatus )
{
uchar errNCB ;
if ( tdistatus == TDI_SUCCESS )
return NRC_GOODRET ;
else if ( tdistatus == TDI_PENDING )
return NRC_PENDING ;
switch ( tdistatus )
{
case TDI_NO_RESOURCES:
errNCB = NRC_NORES ;
break ;
case STATUS_CANCELLED:
errNCB = NRC_CMDCAN ;
break ;
case TDI_INVALID_CONNECTION:
case STATUS_CONNECTION_DISCONNECTED:
errNCB = NRC_SCLOSED ;
break ;
case TDI_CONNECTION_ABORTED:
errNCB = NRC_SABORT ;
break ;
case STATUS_TOO_MANY_COMMANDS:
errNCB = NRC_TOOMANY ;
break ;
case STATUS_OBJECT_NAME_COLLISION:
case STATUS_SHARING_VIOLATION:
errNCB = NRC_DUPNAME ;
break ;
case STATUS_DUPLICATE_NAME:
errNCB = NRC_INUSE ;
break ;
//
// Call NCB submitted with a name that can't be found
//
case STATUS_BAD_NETWORK_PATH:
errNCB = NRC_NOCALL ;
break ;
case STATUS_REMOTE_NOT_LISTENING:
errNCB = NRC_REMTFUL ;
break ;
case TDI_TIMED_OUT:
errNCB = NRC_CMDTMO ;
break ;
//
// Where the transport has more data available but the NCB's buffer is
// full
//
case TDI_BUFFER_OVERFLOW:
errNCB = NRC_INCOMP ;
break ;
case STATUS_INVALID_BUFFER_SIZE:
errNCB = NRC_BUFLEN ;
break ;
case STATUS_NETWORK_NAME_DELETED:
errNCB = NRC_NAMERR ;
break ;
case STATUS_NRC_ACTSES:
errNCB = NRC_ACTSES ;
break ;
default:
DbgPrint("MapTDIStatus2NCBErr - Unmapped STATUS/TDI error - " ) ;
DbgPrintNum( tdistatus ) ;
DbgPrint("\n\r") ;
case STATUS_UNSUCCESSFUL:
case TDI_INVALID_STATE:
case STATUS_INVALID_PARAMETER: // Generally detected bad struct. signature
case STATUS_UNEXPECTED_NETWORK_ERROR:
errNCB = NRC_SYSTEM ;
break ;
}
return errNCB ;
}