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/tdiout.c | 601 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 601 insertions(+) create mode 100644 private/ntos/nbt/vxd/tdiout.c (limited to 'private/ntos/nbt/vxd/tdiout.c') 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 ); +} + + -- cgit v1.2.3