244 lines
5.5 KiB
C
244 lines
5.5 KiB
C
|
|
|||
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
send.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains code which processes all send NCB's including
|
|||
|
both session and datagram based transfers.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Colin Watson (ColinW) 12-Sep-1991
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel mode
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "nb.h"
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NbSend(
|
|||
|
IN PDNCB pdncb,
|
|||
|
IN PIRP Irp,
|
|||
|
IN PIO_STACK_LOCATION IrpSp,
|
|||
|
IN ULONG Buffer2Length
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is called to send a buffer full of data.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pdncb - Pointer to the NCB.
|
|||
|
|
|||
|
Irp - Pointer to the request packet representing the I/O request.
|
|||
|
|
|||
|
IrpSp - Pointer to current IRP stack frame.
|
|||
|
|
|||
|
Buffer2Length - Length of user provided buffer for data.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The function value is the status of the operation.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PFCB pfcb = IrpSp->FileObject->FsContext2;
|
|||
|
PCB pcb;
|
|||
|
PPCB ppcb;
|
|||
|
PDEVICE_OBJECT DeviceObject;
|
|||
|
KIRQL OldIrql; // Used when SpinLock held.
|
|||
|
|
|||
|
LOCK( pfcb, OldIrql );
|
|||
|
|
|||
|
ppcb = FindCb( pfcb, pdncb, FALSE);
|
|||
|
|
|||
|
if ( ppcb == NULL ) {
|
|||
|
// FindCb has put the error in the NCB
|
|||
|
UNLOCK( pfcb, OldIrql );
|
|||
|
if ( pdncb->ncb_retcode == NRC_SCLOSED ) {
|
|||
|
// Tell dll to hangup the connection.
|
|||
|
return STATUS_HANGUP_REQUIRED;
|
|||
|
} else {
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
}
|
|||
|
pcb = *ppcb;
|
|||
|
|
|||
|
if ( (pcb->DeviceObject == NULL) || (pcb->ConnectionObject == NULL)) {
|
|||
|
UNLOCK( pfcb, OldIrql );
|
|||
|
NCB_COMPLETE( pdncb, NRC_SCLOSED );
|
|||
|
return STATUS_INVALID_DEVICE_REQUEST;
|
|||
|
}
|
|||
|
|
|||
|
TdiBuildSend (Irp,
|
|||
|
pcb->DeviceObject,
|
|||
|
pcb->ConnectionObject,
|
|||
|
NbCompletionPDNCB,
|
|||
|
pdncb,
|
|||
|
Irp->MdlAddress,
|
|||
|
(((pdncb->ncb_command & ~ASYNCH) == NCBSENDNA ) ||
|
|||
|
((pdncb->ncb_command & ~ASYNCH) == NCBCHAINSENDNA ))?
|
|||
|
TDI_SEND_NO_RESPONSE_EXPECTED : 0,
|
|||
|
Buffer2Length);
|
|||
|
|
|||
|
DeviceObject = pcb->DeviceObject;
|
|||
|
|
|||
|
InsertTailList(&pcb->SendList, &pdncb->ncb_next);
|
|||
|
pdncb->irp = Irp;
|
|||
|
pdncb->pfcb = pfcb;
|
|||
|
pdncb->tick_count = pcb->SendTimeout;
|
|||
|
|
|||
|
UNLOCK( pfcb, OldIrql );
|
|||
|
|
|||
|
IoMarkIrpPending( Irp );
|
|||
|
IoCallDriver (DeviceObject, Irp);
|
|||
|
|
|||
|
IF_NBDBG (NB_DEBUG_SEND) {
|
|||
|
NbPrint(( "NB SEND submit: %X\n", Irp->IoStatus.Status ));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Transport will complete the request. Return pending so that
|
|||
|
// netbios does not complete as well.
|
|||
|
//
|
|||
|
|
|||
|
return STATUS_PENDING;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NbSendDatagram(
|
|||
|
IN PDNCB pdncb,
|
|||
|
IN PIRP Irp,
|
|||
|
IN PIO_STACK_LOCATION IrpSp,
|
|||
|
IN ULONG Buffer2Length
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is called to SendDatagram a buffer full of data.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pdncb - Pointer to the NCB.
|
|||
|
|
|||
|
Irp - Pointer to the request packet representing the I/O request.
|
|||
|
|
|||
|
IrpSp - Pointer to current IRP stack frame.
|
|||
|
|
|||
|
Buffer2Length - Length of user provided buffer for data.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The function value is the status of the operation.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PFCB pfcb = IrpSp->FileObject->FsContext2;
|
|||
|
PPAB ppab;
|
|||
|
PAB pab;
|
|||
|
PDEVICE_OBJECT DeviceObject;
|
|||
|
KIRQL OldIrql; // Used when SpinLock held.
|
|||
|
|
|||
|
IF_NBDBG (NB_DEBUG_SEND) {
|
|||
|
NbPrint(( "NB SEND Datagram submit, pdncb %lx\n", pdncb ));
|
|||
|
}
|
|||
|
|
|||
|
LOCK( pfcb, OldIrql );
|
|||
|
ppab = FindAbUsingNum( pfcb, pdncb, pdncb->ncb_num );
|
|||
|
|
|||
|
if ( ppab == NULL ) {
|
|||
|
// FindAb has put the error in the NCB
|
|||
|
UNLOCK( pfcb, OldIrql );
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
pab = *ppab;
|
|||
|
|
|||
|
pdncb->Information.RemoteAddressLength = sizeof(TA_NETBIOS_ADDRESS);
|
|||
|
pdncb->Information.RemoteAddress = &pdncb->RemoteAddress;
|
|||
|
|
|||
|
pdncb->RemoteAddress.TAAddressCount = 1;
|
|||
|
pdncb->RemoteAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_NETBIOS;
|
|||
|
pdncb->RemoteAddress.Address[0].Address[0].NetbiosNameType =
|
|||
|
TDI_ADDRESS_TYPE_NETBIOS;
|
|||
|
|
|||
|
if ( (pdncb->ncb_command & ~ASYNCH) == NCBDGSENDBC ) {
|
|||
|
PPAB ppab255 = FindAbUsingNum( pfcb, pdncb, MAXIMUM_ADDRESS );
|
|||
|
|
|||
|
if ( ppab255 == NULL ) {
|
|||
|
// FindAb has put the error in the NCB
|
|||
|
UNLOCK( pfcb, OldIrql );
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
pdncb->RemoteAddress.Address[0].AddressLength = (*ppab255)->NameLength;
|
|||
|
|
|||
|
RtlMoveMemory(
|
|||
|
pdncb->RemoteAddress.Address[0].Address[0].NetbiosName,
|
|||
|
&(*ppab255)->Name,
|
|||
|
(*ppab255)->NameLength
|
|||
|
);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
pdncb->RemoteAddress.Address[0].AddressLength = sizeof (TDI_ADDRESS_NETBIOS);
|
|||
|
|
|||
|
RtlMoveMemory(
|
|||
|
pdncb->RemoteAddress.Address[0].Address[0].NetbiosName,
|
|||
|
pdncb->ncb_callname,
|
|||
|
NCBNAMSZ
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
pdncb->Information.UserDataLength = 0;
|
|||
|
pdncb->Information.UserData = NULL;
|
|||
|
pdncb->Information.OptionsLength = 0;
|
|||
|
pdncb->Information.Options = NULL;
|
|||
|
|
|||
|
TdiBuildSendDatagram (Irp,
|
|||
|
pab->DeviceObject,
|
|||
|
pab->AddressObject,
|
|||
|
NbCompletionPDNCB,
|
|||
|
pdncb,
|
|||
|
Irp->MdlAddress,
|
|||
|
Buffer2Length,
|
|||
|
&pdncb->Information);
|
|||
|
|
|||
|
DeviceObject = pab->DeviceObject;
|
|||
|
pdncb->irp = Irp;
|
|||
|
pdncb->pfcb = pfcb;
|
|||
|
|
|||
|
UNLOCK( pfcb, OldIrql );
|
|||
|
|
|||
|
IoMarkIrpPending( Irp );
|
|||
|
IoCallDriver (DeviceObject, Irp);
|
|||
|
|
|||
|
IF_NBDBG (NB_DEBUG_SEND) {
|
|||
|
NbPrint(( "NB SEND Datagram submit: %X\n", Irp->IoStatus.Status ));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Transport will complete the request. Return pending so that
|
|||
|
// netbios does not complete as well.
|
|||
|
//
|
|||
|
|
|||
|
return STATUS_PENDING;
|
|||
|
|
|||
|
}
|