📄 write.c
字号:
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/net/afd/afd/write.c
* PURPOSE: Ancillary functions driver
* PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
* UPDATE HISTORY:
* 20040708 Created
*/
#include "afd.h"
#include "tdi_proto.h"
#include "tdiconn.h"
#include "debug.h"
static NTSTATUS NTAPI SendComplete
( PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context ) {
NTSTATUS Status = Irp->IoStatus.Status;
PAFD_FCB FCB = (PAFD_FCB)Context;
PLIST_ENTRY NextIrpEntry;
PIRP NextIrp = NULL;
PIO_STACK_LOCATION NextIrpSp;
PAFD_SEND_INFO SendReq = NULL;
PAFD_MAPBUF Map;
UINT TotalBytesCopied = 0, SpaceAvail, i, CopySize = 0;
/*
* The Irp parameter passed in is the IRP of the stream between AFD and
* TDI driver. It's not very usefull to us. We need the IRPs of the stream
* between usermode and AFD. Those are chained from
* FCB->PendingIrpList[FUNCTION_SEND] and you'll see them in the code
* below as "NextIrp" ('cause they are the next usermode IRP to be
* processed).
*/
AFD_DbgPrint(MID_TRACE,("Called, status %x, %d bytes used\n",
Irp->IoStatus.Status,
Irp->IoStatus.Information));
ASSERT_IRQL(APC_LEVEL);
if( !SocketAcquireStateLock( FCB ) ) return Status;
FCB->SendIrp.InFlightRequest = NULL;
/* Request is not in flight any longer */
if( FCB->State == SOCKET_STATE_CLOSED ) {
SocketStateUnlock( FCB );
DestroySocket( FCB );
return STATUS_SUCCESS;
}
if( !NT_SUCCESS(Status) ) {
/* Complete all following send IRPs with error */
while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) {
NextIrpEntry =
RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
NextIrp =
CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
SendReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
UnlockBuffers( SendReq->BufferArray,
SendReq->BufferCount,
FALSE );
NextIrp->IoStatus.Status = Status;
NextIrp->IoStatus.Information = 0;
IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT );
}
SocketStateUnlock( FCB );
return STATUS_SUCCESS;
}
RtlMoveMemory( FCB->Send.Window,
FCB->Send.Window + FCB->Send.BytesUsed,
FCB->Send.BytesUsed - Irp->IoStatus.Information );
FCB->Send.BytesUsed -= Irp->IoStatus.Information;
if( !FCB->Send.BytesUsed &&
!IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) &&
NT_SUCCESS(Status) ) {
NextIrpEntry =
RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]);
NextIrp =
CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry);
NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp );
SendReq = NextIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
Map = (PAFD_MAPBUF)(SendReq->BufferArray + SendReq->BufferCount);
AFD_DbgPrint(MID_TRACE,("SendReq @ %x\n", SendReq));
SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed;
for( i = 0; i < SendReq->BufferCount; i++ ) {
Map[i].BufferAddress =
MmMapLockedPages( Map[i].Mdl, KernelMode );
CopySize = MIN( SpaceAvail,
SendReq->BufferArray[i].len );
RtlCopyMemory( FCB->Send.Window + FCB->Send.BytesUsed,
Map[i].BufferAddress,
CopySize );
MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl );
FCB->Send.BytesUsed += CopySize;
TotalBytesCopied += CopySize;
SpaceAvail -= CopySize;
}
}
/* Some data is still waiting */
if( FCB->Send.BytesUsed ) {
FCB->PollState &= ~AFD_EVENT_SEND;
SocketCalloutEnter( FCB );
Status = TdiSend( &FCB->SendIrp.InFlightRequest,
FCB->Connection.Object,
0,
FCB->Send.Window,
FCB->Send.BytesUsed,
&FCB->SendIrp.Iosb,
SendComplete,
FCB );
SocketCalloutLeave( FCB );
} else {
FCB->PollState |= AFD_EVENT_SEND;
PollReeval( FCB->DeviceExt, FCB->FileObject );
}
if( TotalBytesCopied > 0 ) {
UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
if( Status == STATUS_PENDING )
Status = STATUS_SUCCESS;
AFD_DbgPrint(MID_TRACE,("Dismissing request: %x\n", Status));
return UnlockAndMaybeComplete( FCB, Status, NextIrp, TotalBytesCopied,
NULL, TRUE );
} else if( NextIrp ) {
AFD_DbgPrint(MID_TRACE,("Could not do any more with Irp %x\n",
NextIrp));
InsertHeadList( &FCB->PendingIrpList[FUNCTION_SEND],
&NextIrp->Tail.Overlay.ListEntry );
}
SocketStateUnlock( FCB );
return STATUS_SUCCESS;
}
static NTSTATUS NTAPI PacketSocketSendComplete
( PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context ) {
PAFD_FCB FCB = (PAFD_FCB)Context;
AFD_DbgPrint(MID_TRACE,("Called, status %x, %d bytes used\n",
Irp->IoStatus.Status,
Irp->IoStatus.Information));
/* It's ok if the FCB already died */
if( !SocketAcquireStateLock( FCB ) ) return STATUS_SUCCESS;
FCB->PollState |= AFD_EVENT_SEND;
PollReeval( FCB->DeviceExt, FCB->FileObject );
FCB->SendIrp.InFlightRequest = NULL;
/* Request is not in flight any longer */
if( FCB->State == SOCKET_STATE_CLOSED ) {
SocketStateUnlock( FCB );
DestroySocket( FCB );
return STATUS_SUCCESS;
}
SocketStateUnlock( FCB );
return STATUS_SUCCESS;
}
NTSTATUS STDCALL
AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp, BOOLEAN Short) {
NTSTATUS Status = STATUS_SUCCESS;
PFILE_OBJECT FileObject = IrpSp->FileObject;
PAFD_FCB FCB = FileObject->FsContext;
PAFD_SEND_INFO SendReq;
UINT TotalBytesCopied = 0, i, CopySize = 0,
SpaceAvail = 0, TotalBytesEncountered = 0;
AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, FALSE );
FCB->EventsFired &= ~AFD_EVENT_SEND;
if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS )
{
PAFD_SEND_INFO_UDP SendReq;
PTDI_CONNECTION_INFORMATION TargetAddress;
/* Check that the socket is bound */
if( FCB->State != SOCKET_STATE_BOUND )
return UnlockAndMaybeComplete( FCB, STATUS_UNSUCCESSFUL, Irp,
0, NULL, FALSE );
if( !(SendReq = LockRequest( Irp, IrpSp )) )
return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0,
NULL, FALSE );
/* Must lock buffers before handing off user data */
SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
SendReq->BufferCount,
NULL, NULL,
FALSE, FALSE );
TdiBuildConnectionInfo( &TargetAddress, FCB->RemoteAddress );
SocketCalloutEnter( FCB );
Status = TdiSendDatagram
( &FCB->SendIrp.InFlightRequest,
FCB->AddressFile.Object,
SendReq->BufferArray[0].buf,
SendReq->BufferArray[0].len,
TargetAddress,
&FCB->SendIrp.Iosb,
PacketSocketSendComplete,
FCB );
SocketCalloutLeave( FCB );
ExFreePool( TargetAddress );
if( Status == STATUS_PENDING ) Status = STATUS_SUCCESS;
AFD_DbgPrint(MID_TRACE,("Dismissing request: %x\n", Status));
return UnlockAndMaybeComplete( FCB, Status, Irp,
SendReq->BufferArray[0].len,
NULL, TRUE );
}
if( !(SendReq = LockRequest( Irp, IrpSp )) )
return UnlockAndMaybeComplete
( FCB, STATUS_NO_MEMORY, Irp, TotalBytesCopied, NULL, FALSE );
AFD_DbgPrint(MID_TRACE,("Socket state %d\n", FCB->State));
if( FCB->State != SOCKET_STATE_CONNECTED ) {
if( SendReq->AfdFlags & AFD_IMMEDIATE ) {
AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
return UnlockAndMaybeComplete
( FCB, STATUS_CANT_WAIT, Irp, 0, NULL, TRUE );
} else {
AFD_DbgPrint(MID_TRACE,("Queuing request\n"));
return LeaveIrpUntilLater( FCB, Irp, FUNCTION_SEND );
}
}
AFD_DbgPrint(MID_TRACE,("We already have %d bytes waiting.\n",
FCB->Send.BytesUsed));
SendReq->BufferArray = LockBuffers( SendReq->BufferArray,
SendReq->BufferCount,
NULL, NULL,
FALSE, FALSE );
AFD_DbgPrint(MID_TRACE,("FCB->Send.BytesUsed = %d\n",
FCB->Send.BytesUsed));
if( !FCB->Send.BytesUsed ) {
SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed;
AFD_DbgPrint(MID_TRACE,("We can accept %d bytes\n",
SpaceAvail));
for( i = 0; FCB->Send.BytesUsed < FCB->Send.Size &&
i < SendReq->BufferCount; i++ ) {
CopySize = MIN( SpaceAvail,
SendReq->BufferArray[i].len );
TotalBytesEncountered += SendReq->BufferArray[i].len;
AFD_DbgPrint(MID_TRACE,("Copying Buffer %d, %x:%d to %x\n",
i,
SendReq->BufferArray[i].buf,
CopySize,
FCB->Send.Window + FCB->Send.BytesUsed));
RtlCopyMemory( FCB->Send.Window + FCB->Send.BytesUsed,
SendReq->BufferArray[i].buf,
CopySize );
FCB->Send.BytesUsed += CopySize;
TotalBytesCopied += CopySize;
SpaceAvail -= CopySize;
}
if( TotalBytesEncountered == 0 ) {
UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
AFD_DbgPrint(MID_TRACE,("Empty send\n"));
return UnlockAndMaybeComplete
( FCB, Status, Irp, TotalBytesCopied, NULL, TRUE );
}
AFD_DbgPrint(MID_TRACE,("Completed %d bytes\n", TotalBytesCopied));
if( TotalBytesCopied > 0 ) {
UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE );
FCB->SendIrp.InFlightRequest = (PVOID)1; /* Placeholder */
SocketCalloutEnter( FCB );
Status = TdiSend( &FCB->SendIrp.InFlightRequest,
FCB->Connection.Object,
0,
FCB->Send.Window,
FCB->Send.BytesUsed,
&FCB->SendIrp.Iosb,
SendComplete,
FCB );
SocketCalloutLeave( FCB );
if( Status == STATUS_PENDING )
Status = STATUS_SUCCESS;
AFD_DbgPrint(MID_TRACE,("Dismissing request: %x (%d)\n",
Status, TotalBytesCopied));
return UnlockAndMaybeComplete
( FCB, Status, Irp, TotalBytesCopied, NULL, TRUE );
}
}
if( SendReq->AfdFlags & AFD_IMMEDIATE ) {
AFD_DbgPrint(MID_TRACE,("Nonblocking\n"));
return UnlockAndMaybeComplete
( FCB, STATUS_CANT_WAIT, Irp, 0, NULL, TRUE );
} else {
AFD_DbgPrint(MID_TRACE,("Queuing request\n"));
return LeaveIrpUntilLater( FCB, Irp, FUNCTION_SEND );
}
}
NTSTATUS STDCALL
AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
PIO_STACK_LOCATION IrpSp) {
NTSTATUS Status = STATUS_SUCCESS;
PTDI_CONNECTION_INFORMATION TargetAddress;
PFILE_OBJECT FileObject = IrpSp->FileObject;
PAFD_FCB FCB = FileObject->FsContext;
PAFD_SEND_INFO_UDP SendReq;
AFD_DbgPrint(MID_TRACE,("Called on %x\n", FCB));
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, FALSE );
FCB->EventsFired &= ~AFD_EVENT_SEND;
FCB->PollState &= ~AFD_EVENT_SEND;
/* Check that the socket is bound */
if( FCB->State != SOCKET_STATE_BOUND )
return UnlockAndMaybeComplete
( FCB, STATUS_UNSUCCESSFUL, Irp, 0, NULL, FALSE );
if( !(SendReq = LockRequest( Irp, IrpSp )) )
return UnlockAndMaybeComplete
( FCB, STATUS_NO_MEMORY, Irp, 0, NULL, FALSE );
AFD_DbgPrint
(MID_TRACE,("RemoteAddress #%d Type %d\n",
((PTRANSPORT_ADDRESS)SendReq->RemoteAddress)->
TAAddressCount,
((PTRANSPORT_ADDRESS)SendReq->RemoteAddress)->
Address[0].AddressType));
TdiBuildConnectionInfo( &TargetAddress,
((PTRANSPORT_ADDRESS)SendReq->RemoteAddress) );
/* Check the size of the Address given ... */
if( TargetAddress ) {
SocketCalloutEnter( FCB );
Status = TdiSendDatagram
( &FCB->SendIrp.InFlightRequest,
FCB->AddressFile.Object,
SendReq->BufferArray[0].buf,
SendReq->BufferArray[0].len,
TargetAddress,
&FCB->SendIrp.Iosb,
PacketSocketSendComplete,
FCB );
SocketCalloutLeave( FCB );
ExFreePool( TargetAddress );
} else Status = STATUS_NO_MEMORY;
if( Status == STATUS_PENDING ) Status = STATUS_SUCCESS;
AFD_DbgPrint(MID_TRACE,("Dismissing request: %x\n", Status));
return UnlockAndMaybeComplete
( FCB, Status, Irp, SendReq->BufferArray[0].len, NULL, TRUE );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -