NTSTATUS NTAPI ReceiveComplete ( PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context ) { PAFD_FCB FCB = (PAFD_FCB)Context; PLIST_ENTRY NextIrpEntry; PIRP NextIrp; PAFD_RECV_INFO RecvReq; PIO_STACK_LOCATION NextIrpSp; UNREFERENCED_PARAMETER(DeviceObject); AFD_DbgPrint(MID_TRACE,("Called\n")); if( !SocketAcquireStateLock( FCB ) ) return STATUS_FILE_CLOSED; ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp); FCB->ReceiveIrp.InFlightRequest = NULL; if( FCB->State == SOCKET_STATE_CLOSED ) { /* Cleanup our IRP queue because the FCB is being destroyed */ while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) { NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]); NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); NextIrpSp = IoGetCurrentIrpStackLocation(NextIrp); RecvReq = GetLockedData(NextIrp, NextIrpSp); NextIrp->IoStatus.Status = STATUS_FILE_CLOSED; NextIrp->IoStatus.Information = 0; UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE); if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); (void)IoSetCancelRoutine(NextIrp, NULL); IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); } SocketStateUnlock( FCB ); return STATUS_FILE_CLOSED; } else if( FCB->State == SOCKET_STATE_LISTENING ) { AFD_DbgPrint(MIN_TRACE,("!!! LISTENER GOT A RECEIVE COMPLETE !!!\n")); SocketStateUnlock( FCB ); return STATUS_INVALID_PARAMETER; } HandleReceiveComplete( FCB, Irp->IoStatus.Status, Irp->IoStatus.Information ); ReceiveActivity( FCB, NULL ); SocketStateUnlock( FCB ); return STATUS_SUCCESS; }
/* you must pass either Poll OR Irp */ VOID SignalSocket( PAFD_ACTIVE_POLL Poll OPTIONAL, PIRP _Irp OPTIONAL, PAFD_POLL_INFO PollReq, NTSTATUS Status ) { UINT i; PIRP Irp = _Irp ? _Irp : Poll->Irp; AFD_DbgPrint(MID_TRACE,("Called (Status %x)\n", Status)); if (Poll) { KeCancelTimer( &Poll->Timer ); RemoveEntryList( &Poll->ListEntry ); ExFreePool( Poll ); } Irp->IoStatus.Status = Status; Irp->IoStatus.Information = FIELD_OFFSET(AFD_POLL_INFO, Handles) + sizeof(AFD_HANDLE) * PollReq->HandleCount; CopyBackStatus( PollReq->Handles, PollReq->HandleCount ); for( i = 0; i < PollReq->HandleCount; i++ ) { AFD_DbgPrint (MAX_TRACE, ("Handle(%x): Got %x,%x\n", PollReq->Handles[i].Handle, PollReq->Handles[i].Events, PollReq->Handles[i].Status)); } UnlockHandles( AFD_HANDLES(PollReq), PollReq->HandleCount ); if( Irp->MdlAddress ) UnlockRequest( Irp, IoGetCurrentIrpStackLocation( Irp ) ); AFD_DbgPrint(MID_TRACE,("Completing\n")); (void)IoSetCancelRoutine(Irp, NULL); IoCompleteRequest( Irp, IO_NETWORK_INCREMENT ); AFD_DbgPrint(MID_TRACE,("Done\n")); }
static NTSTATUS SatisfyPreAccept( PIRP Irp, PAFD_TDI_OBJECT_QELT Qelt ) { PAFD_RECEIVED_ACCEPT_DATA ListenReceive = (PAFD_RECEIVED_ACCEPT_DATA)Irp->AssociatedIrp.SystemBuffer; PTA_IP_ADDRESS IPAddr; ListenReceive->SequenceNumber = Qelt->Seq; AFD_DbgPrint(MID_TRACE,("Giving SEQ %u to userland\n", Qelt->Seq)); AFD_DbgPrint(MID_TRACE,("Socket Address (K) %p (U) %p\n", &ListenReceive->Address, Qelt->ConnInfo->RemoteAddress)); TaCopyTransportAddressInPlace( &ListenReceive->Address, Qelt->ConnInfo->RemoteAddress ); IPAddr = (PTA_IP_ADDRESS)&ListenReceive->Address; AFD_DbgPrint(MID_TRACE,("IPAddr->TAAddressCount %d\n", IPAddr->TAAddressCount)); AFD_DbgPrint(MID_TRACE,("IPAddr->Address[0].AddressType %u\n", IPAddr->Address[0].AddressType)); AFD_DbgPrint(MID_TRACE,("IPAddr->Address[0].AddressLength %u\n", IPAddr->Address[0].AddressLength)); AFD_DbgPrint(MID_TRACE,("IPAddr->Address[0].Address[0].sin_port %x\n", IPAddr->Address[0].Address[0].sin_port)); AFD_DbgPrint(MID_TRACE,("IPAddr->Address[0].Address[0].sin_addr %x\n", IPAddr->Address[0].Address[0].in_addr)); if( Irp->MdlAddress ) UnlockRequest( Irp, IoGetCurrentIrpStackLocation( Irp ) ); Irp->IoStatus.Information = ((PCHAR)&IPAddr[1]) - ((PCHAR)ListenReceive); Irp->IoStatus.Status = STATUS_SUCCESS; (void)IoSetCancelRoutine(Irp, NULL); IoCompleteRequest( Irp, IO_NETWORK_INCREMENT ); return STATUS_SUCCESS; }
static NTSTATUS NTAPI ListenComplete( PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context ) { NTSTATUS Status = STATUS_SUCCESS; PAFD_FCB FCB = (PAFD_FCB)Context; PAFD_TDI_OBJECT_QELT Qelt; PLIST_ENTRY NextIrpEntry; PIRP NextIrp; UNREFERENCED_PARAMETER(DeviceObject); if( !SocketAcquireStateLock( FCB ) ) return STATUS_FILE_CLOSED; ASSERT(FCB->ListenIrp.InFlightRequest == Irp); FCB->ListenIrp.InFlightRequest = NULL; if( FCB->State == SOCKET_STATE_CLOSED ) { /* Cleanup our IRP queue because the FCB is being destroyed */ while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_PREACCEPT] ) ) { NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_PREACCEPT]); NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); NextIrp->IoStatus.Status = STATUS_FILE_CLOSED; NextIrp->IoStatus.Information = 0; if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); (void)IoSetCancelRoutine(NextIrp, NULL); IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); } /* Free ConnectionReturnInfo and ConnectionCallInfo */ if (FCB->ListenIrp.ConnectionReturnInfo) { ExFreePool(FCB->ListenIrp.ConnectionReturnInfo); FCB->ListenIrp.ConnectionReturnInfo = NULL; } if (FCB->ListenIrp.ConnectionCallInfo) { ExFreePool(FCB->ListenIrp.ConnectionCallInfo); FCB->ListenIrp.ConnectionCallInfo = NULL; } SocketStateUnlock( FCB ); return STATUS_FILE_CLOSED; } AFD_DbgPrint(MID_TRACE,("Completing listen request.\n")); AFD_DbgPrint(MID_TRACE,("IoStatus was %x\n", Irp->IoStatus.Status)); if (Irp->IoStatus.Status != STATUS_SUCCESS) { SocketStateUnlock(FCB); return Irp->IoStatus.Status; } Qelt = ExAllocatePool( NonPagedPool, sizeof(*Qelt) ); if( !Qelt ) { Status = STATUS_NO_MEMORY; } else { UINT AddressType = FCB->LocalAddress->Address[0].AddressType; Qelt->Object = FCB->Connection; Qelt->Seq = FCB->ConnSeq++; AFD_DbgPrint(MID_TRACE,("Address Type: %u (RA %p)\n", AddressType, FCB->ListenIrp. ConnectionReturnInfo->RemoteAddress)); Status = TdiBuildNullConnectionInfo( &Qelt->ConnInfo, AddressType ); if( NT_SUCCESS(Status) ) { TaCopyTransportAddressInPlace ( Qelt->ConnInfo->RemoteAddress, FCB->ListenIrp.ConnectionReturnInfo->RemoteAddress ); InsertTailList( &FCB->PendingConnections, &Qelt->ListEntry ); } } /* Satisfy a pre-accept request if one is available */ if( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_PREACCEPT] ) && !IsListEmpty( &FCB->PendingConnections ) ) { PLIST_ENTRY PendingIrp = RemoveHeadList( &FCB->PendingIrpList[FUNCTION_PREACCEPT] ); PLIST_ENTRY PendingConn = FCB->PendingConnections.Flink; SatisfyPreAccept ( CONTAINING_RECORD( PendingIrp, IRP, Tail.Overlay.ListEntry ), CONTAINING_RECORD( PendingConn, AFD_TDI_OBJECT_QELT, ListEntry ) ); } /* Launch new accept socket */ Status = WarmSocketForConnection( FCB ); if (NT_SUCCESS(Status)) { Status = TdiBuildNullConnectionInfoInPlace(FCB->ListenIrp.ConnectionCallInfo, FCB->LocalAddress->Address[0].AddressType); ASSERT(Status == STATUS_SUCCESS); Status = TdiBuildNullConnectionInfoInPlace(FCB->ListenIrp.ConnectionReturnInfo, FCB->LocalAddress->Address[0].AddressType); ASSERT(Status == STATUS_SUCCESS); Status = TdiListen( &FCB->ListenIrp.InFlightRequest, FCB->Connection.Object, &FCB->ListenIrp.ConnectionCallInfo, &FCB->ListenIrp.ConnectionReturnInfo, ListenComplete, FCB ); if (Status == STATUS_PENDING) Status = STATUS_SUCCESS; } /* Trigger a select return if appropriate */ if( !IsListEmpty( &FCB->PendingConnections ) ) { FCB->PollState |= AFD_EVENT_ACCEPT; FCB->PollStatus[FD_ACCEPT_BIT] = STATUS_SUCCESS; PollReeval( FCB->DeviceExt, FCB->FileObject ); } else FCB->PollState &= ~AFD_EVENT_ACCEPT; SocketStateUnlock( FCB ); return Status; }
NTSTATUS NTAPI PacketSocketRecvComplete( PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context ) { NTSTATUS Status = STATUS_SUCCESS; PAFD_FCB FCB = Context; PIRP NextIrp; PIO_STACK_LOCATION NextIrpSp; PLIST_ENTRY ListEntry; PAFD_RECV_INFO RecvReq; PAFD_STORED_DATAGRAM DatagramRecv; UINT DGSize = Irp->IoStatus.Information + sizeof( AFD_STORED_DATAGRAM ); PLIST_ENTRY NextIrpEntry, DatagramRecvEntry; UNREFERENCED_PARAMETER(DeviceObject); AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB)); if( !SocketAcquireStateLock( FCB ) ) return STATUS_FILE_CLOSED; ASSERT(FCB->ReceiveIrp.InFlightRequest == Irp); FCB->ReceiveIrp.InFlightRequest = NULL; if( FCB->State == SOCKET_STATE_CLOSED ) { /* Cleanup our IRP queue because the FCB is being destroyed */ while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) { NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]); NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); RecvReq = GetLockedData(NextIrp, NextIrpSp); NextIrp->IoStatus.Status = STATUS_FILE_CLOSED; NextIrp->IoStatus.Information = 0; UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp)); if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); (void)IoSetCancelRoutine(NextIrp, NULL); IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); } /* Free all items on the datagram list */ while( !IsListEmpty( &FCB->DatagramList ) ) { DatagramRecvEntry = RemoveHeadList(&FCB->DatagramList); DatagramRecv = CONTAINING_RECORD(DatagramRecvEntry, AFD_STORED_DATAGRAM, ListEntry); ExFreePool( DatagramRecv->Address ); ExFreePool( DatagramRecv ); } SocketStateUnlock( FCB ); return STATUS_FILE_CLOSED; } if (Irp->IoStatus.Status != STATUS_SUCCESS) { SocketStateUnlock(FCB); return Irp->IoStatus.Status; } if (FCB->TdiReceiveClosed) { SocketStateUnlock(FCB); return STATUS_FILE_CLOSED; } DatagramRecv = ExAllocatePool( NonPagedPool, DGSize ); if( DatagramRecv ) { DatagramRecv->Len = Irp->IoStatus.Information; RtlCopyMemory( DatagramRecv->Buffer, FCB->Recv.Window, DatagramRecv->Len ); AFD_DbgPrint(MID_TRACE,("Received (A %p)\n", FCB->AddressFrom->RemoteAddress)); DatagramRecv->Address = TaCopyTransportAddress( FCB->AddressFrom->RemoteAddress ); if( !DatagramRecv->Address ) Status = STATUS_NO_MEMORY; } else Status = STATUS_NO_MEMORY; if( !NT_SUCCESS( Status ) ) { if( DatagramRecv ) ExFreePool( DatagramRecv ); SocketStateUnlock( FCB ); return Status; } else { FCB->Recv.Content += DatagramRecv->Len; InsertTailList( &FCB->DatagramList, &DatagramRecv->ListEntry ); } /* Satisfy as many requests as we can */ while( !IsListEmpty( &FCB->DatagramList ) && !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) { AFD_DbgPrint(MID_TRACE,("Looping trying to satisfy request\n")); ListEntry = RemoveHeadList( &FCB->DatagramList ); DatagramRecv = CONTAINING_RECORD( ListEntry, AFD_STORED_DATAGRAM, ListEntry ); ListEntry = RemoveHeadList( &FCB->PendingIrpList[FUNCTION_RECV] ); NextIrp = CONTAINING_RECORD( ListEntry, IRP, Tail.Overlay.ListEntry ); NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); RecvReq = GetLockedData(NextIrp, NextIrpSp); AFD_DbgPrint(MID_TRACE,("RecvReq: %p, DatagramRecv: %p\n", RecvReq, DatagramRecv)); AFD_DbgPrint(MID_TRACE,("Satisfying\n")); Status = SatisfyPacketRecvRequest ( FCB, NextIrp, DatagramRecv, (PUINT)&NextIrp->IoStatus.Information ); if (RecvReq->TdiFlags & TDI_RECEIVE_PEEK) { InsertHeadList(&FCB->DatagramList, &DatagramRecv->ListEntry); } AFD_DbgPrint(MID_TRACE,("Unlocking\n")); UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, NextIrpSp) ); if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); AFD_DbgPrint(MID_TRACE,("Completing\n")); (void)IoSetCancelRoutine(NextIrp, NULL); NextIrp->IoStatus.Status = Status; IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); } if( !IsListEmpty( &FCB->DatagramList ) && IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]) ) { AFD_DbgPrint(MID_TRACE,("Signalling\n")); FCB->PollState |= AFD_EVENT_RECEIVE; FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; PollReeval( FCB->DeviceExt, FCB->FileObject ); } else FCB->PollState &= ~AFD_EVENT_RECEIVE; if( NT_SUCCESS(Irp->IoStatus.Status) ) { /* Now relaunch the datagram request */ Status = TdiReceiveDatagram ( &FCB->ReceiveIrp.InFlightRequest, FCB->AddressFile.Object, 0, FCB->Recv.Window, FCB->Recv.Size, FCB->AddressFrom, &FCB->ReceiveIrp.Iosb, PacketSocketRecvComplete, FCB ); } SocketStateUnlock( FCB ); return STATUS_SUCCESS; }
static NTSTATUS ReceiveActivity( PAFD_FCB FCB, PIRP Irp ) { PLIST_ENTRY NextIrpEntry; PIRP NextIrp; PIO_STACK_LOCATION NextIrpSp; PAFD_RECV_INFO RecvReq; UINT TotalBytesCopied = 0, RetBytesCopied = 0; NTSTATUS Status = STATUS_SUCCESS, RetStatus = STATUS_PENDING; AFD_DbgPrint(MID_TRACE,("%p %p\n", FCB, Irp)); AFD_DbgPrint(MID_TRACE,("FCB %p Receive data waiting %u\n", FCB, FCB->Recv.Content)); if( CantReadMore( FCB ) ) { /* Success here means that we got an EOF. Complete a pending read * with zero bytes if we haven't yet overread, then kill the others. */ while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) { NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]); NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); RecvReq = GetLockedData(NextIrp, NextIrpSp); AFD_DbgPrint(MID_TRACE,("Completing recv %p (%u)\n", NextIrp, TotalBytesCopied)); UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE ); if (FCB->Overread && FCB->LastReceiveStatus == STATUS_SUCCESS) { /* Overread after a graceful disconnect so complete with an error */ Status = STATUS_FILE_CLOSED; } else { /* Unexpected disconnect by the remote host or initial read after a graceful disconnnect */ Status = FCB->LastReceiveStatus; } NextIrp->IoStatus.Status = Status; NextIrp->IoStatus.Information = 0; if( NextIrp == Irp ) RetStatus = Status; if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); (void)IoSetCancelRoutine(NextIrp, NULL); IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); FCB->Overread = TRUE; } } else { /* Kick the user that receive would be possible now */ /* XXX Not implemented yet */ AFD_DbgPrint(MID_TRACE,("FCB %p Receive data waiting %u\n", FCB, FCB->Recv.Content)); /*OskitDumpBuffer( FCB->Recv.Window, FCB->Recv.Content );*/ /* Try to clear some requests */ while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_RECV] ) ) { NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_RECV]); NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); RecvReq = GetLockedData(NextIrp, NextIrpSp); AFD_DbgPrint(MID_TRACE,("RecvReq @ %p\n", RecvReq)); Status = TryToSatisfyRecvRequestFromBuffer ( FCB, RecvReq, &TotalBytesCopied ); if( Status == STATUS_PENDING ) { AFD_DbgPrint(MID_TRACE,("Ran out of data for %p\n", NextIrp)); InsertHeadList(&FCB->PendingIrpList[FUNCTION_RECV], &NextIrp->Tail.Overlay.ListEntry); break; } else { AFD_DbgPrint(MID_TRACE,("Completing recv %p (%u)\n", NextIrp, TotalBytesCopied)); UnlockBuffers( RecvReq->BufferArray, RecvReq->BufferCount, FALSE ); NextIrp->IoStatus.Status = Status; NextIrp->IoStatus.Information = TotalBytesCopied; if( NextIrp == Irp ) { RetStatus = Status; RetBytesCopied = TotalBytesCopied; } if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); (void)IoSetCancelRoutine(NextIrp, NULL); IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); } } } if( FCB->Recv.Content - FCB->Recv.BytesUsed && IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]) ) { FCB->PollState |= AFD_EVENT_RECEIVE; FCB->PollStatus[FD_READ_BIT] = STATUS_SUCCESS; PollReeval( FCB->DeviceExt, FCB->FileObject ); } else { FCB->PollState &= ~AFD_EVENT_RECEIVE; } /* Signal FD_CLOSE if no buffered data remains and the socket can't receive any more */ if (CantReadMore(FCB)) { if (FCB->LastReceiveStatus == STATUS_SUCCESS) { FCB->PollState |= AFD_EVENT_DISCONNECT; } else { FCB->PollState |= AFD_EVENT_CLOSE; } FCB->PollStatus[FD_CLOSE_BIT] = FCB->LastReceiveStatus; PollReeval(FCB->DeviceExt, FCB->FileObject); } AFD_DbgPrint(MID_TRACE,("RetStatus for irp %p is %x\n", Irp, RetStatus)); /* Sometimes we're called with a NULL Irp */ if( Irp ) { Irp->IoStatus.Status = RetStatus; Irp->IoStatus.Information = RetBytesCopied; } return RetStatus; }
static NTSTATUS NTAPI StreamSocketConnectComplete(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context) { NTSTATUS Status = Irp->IoStatus.Status; PAFD_FCB FCB = (PAFD_FCB)Context; PLIST_ENTRY NextIrpEntry; PIRP NextIrp; AFD_DbgPrint(MID_TRACE,("Called: FCB %p, FO %p\n", Context, FCB->FileObject)); /* I was wrong about this before as we can have pending writes to a not * yet connected socket */ if( !SocketAcquireStateLock( FCB ) ) return STATUS_FILE_CLOSED; AFD_DbgPrint(MID_TRACE,("Irp->IoStatus.Status = %x\n", Irp->IoStatus.Status)); ASSERT(FCB->ConnectIrp.InFlightRequest == Irp); FCB->ConnectIrp.InFlightRequest = NULL; if( FCB->State == SOCKET_STATE_CLOSED ) { /* Cleanup our IRP queue because the FCB is being destroyed */ while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_CONNECT] ) ) { NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_CONNECT]); NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); NextIrp->IoStatus.Status = STATUS_FILE_CLOSED; NextIrp->IoStatus.Information = 0; if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); (void)IoSetCancelRoutine(NextIrp, NULL); IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); } SocketStateUnlock( FCB ); return STATUS_FILE_CLOSED; } if( !NT_SUCCESS(Irp->IoStatus.Status) ) { FCB->PollState |= AFD_EVENT_CONNECT_FAIL; FCB->PollStatus[FD_CONNECT_BIT] = Irp->IoStatus.Status; AFD_DbgPrint(MID_TRACE,("Going to bound state\n")); FCB->State = SOCKET_STATE_BOUND; PollReeval( FCB->DeviceExt, FCB->FileObject ); } /* Succeed pending irps on the FUNCTION_CONNECT list */ while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_CONNECT] ) ) { NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_CONNECT]); NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); AFD_DbgPrint(MID_TRACE,("Completing connect %p\n", NextIrp)); NextIrp->IoStatus.Status = Status; NextIrp->IoStatus.Information = NT_SUCCESS(Status) ? ((ULONG_PTR)FCB->Connection.Handle) : 0; if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); (void)IoSetCancelRoutine(NextIrp, NULL); IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); } if( NT_SUCCESS(Status) ) { Status = MakeSocketIntoConnection( FCB ); if( !NT_SUCCESS(Status) ) { SocketStateUnlock( FCB ); return Status; } FCB->FilledConnectData = MIN(FCB->ConnectReturnInfo->UserDataLength, FCB->ConnectDataSize); if (FCB->FilledConnectData) { RtlCopyMemory(FCB->ConnectData, FCB->ConnectReturnInfo->UserData, FCB->FilledConnectData); } FCB->FilledConnectOptions = MIN(FCB->ConnectReturnInfo->OptionsLength, FCB->ConnectOptionsSize); if (FCB->FilledConnectOptions) { RtlCopyMemory(FCB->ConnectOptions, FCB->ConnectReturnInfo->Options, FCB->FilledConnectOptions); } if( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) { NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]); NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); AFD_DbgPrint(MID_TRACE,("Launching send request %p\n", NextIrp)); Status = AfdConnectedSocketWriteData ( DeviceObject, NextIrp, IoGetCurrentIrpStackLocation( NextIrp ), FALSE ); } if( Status == STATUS_PENDING ) Status = STATUS_SUCCESS; } SocketStateUnlock( FCB ); AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status)); return Status; }
static NTSTATUS NTAPI PacketSocketSendComplete ( PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context ) { PAFD_FCB FCB = (PAFD_FCB)Context; PLIST_ENTRY NextIrpEntry; PIRP NextIrp; PAFD_SEND_INFO SendReq; UNREFERENCED_PARAMETER(DeviceObject); AFD_DbgPrint(MID_TRACE,("Called, status %x, %u bytes used\n", Irp->IoStatus.Status, Irp->IoStatus.Information)); if( !SocketAcquireStateLock( FCB ) ) return STATUS_FILE_CLOSED; ASSERT(FCB->SendIrp.InFlightRequest == Irp); FCB->SendIrp.InFlightRequest = NULL; /* Request is not in flight any longer */ if( FCB->State == SOCKET_STATE_CLOSED ) { /* Cleanup our IRP queue because the FCB is being destroyed */ while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) { NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]); NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); SendReq = GetLockedData(NextIrp, IoGetCurrentIrpStackLocation(NextIrp)); NextIrp->IoStatus.Status = STATUS_FILE_CLOSED; NextIrp->IoStatus.Information = 0; (void)IoSetCancelRoutine(NextIrp, NULL); UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); } SocketStateUnlock( FCB ); return STATUS_FILE_CLOSED; } ASSERT(!IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND])); /* TDI spec guarantees FIFO ordering on IRPs */ NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]); NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); SendReq = GetLockedData(NextIrp, IoGetCurrentIrpStackLocation(NextIrp)); NextIrp->IoStatus.Status = Irp->IoStatus.Status; NextIrp->IoStatus.Information = Irp->IoStatus.Information; (void)IoSetCancelRoutine(NextIrp, NULL); UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); UnlockRequest(NextIrp, IoGetCurrentIrpStackLocation(NextIrp)); IoCompleteRequest(NextIrp, IO_NETWORK_INCREMENT); FCB->PollState |= AFD_EVENT_SEND; FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS; PollReeval(FCB->DeviceExt, FCB->FileObject); SocketStateUnlock(FCB); return STATUS_SUCCESS; }
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, TotalBytesProcessed = 0, SpaceAvail, i; UINT SendLength, BytesCopied; BOOLEAN HaltSendQueue; UNREFERENCED_PARAMETER(DeviceObject); /* * 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, %u bytes used\n", Irp->IoStatus.Status, Irp->IoStatus.Information)); if( !SocketAcquireStateLock( FCB ) ) return STATUS_FILE_CLOSED; ASSERT(FCB->SendIrp.InFlightRequest == Irp); FCB->SendIrp.InFlightRequest = NULL; /* Request is not in flight any longer */ if( FCB->State == SOCKET_STATE_CLOSED ) { /* Cleanup our IRP queue because the FCB is being destroyed */ while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) { NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]); NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); SendReq = GetLockedData(NextIrp, NextIrpSp); NextIrp->IoStatus.Status = STATUS_FILE_CLOSED; NextIrp->IoStatus.Information = 0; UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); (void)IoSetCancelRoutine(NextIrp, NULL); IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); } RetryDisconnectCompletion(FCB); SocketStateUnlock( FCB ); return STATUS_FILE_CLOSED; } 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 = GetLockedData(NextIrp, NextIrpSp); UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); NextIrp->IoStatus.Status = Status; NextIrp->IoStatus.Information = 0; if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); (void)IoSetCancelRoutine(NextIrp, NULL); IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); } RetryDisconnectCompletion(FCB); SocketStateUnlock( FCB ); return STATUS_SUCCESS; } RtlMoveMemory( FCB->Send.Window, FCB->Send.Window + Irp->IoStatus.Information, FCB->Send.BytesUsed - Irp->IoStatus.Information ); TotalBytesProcessed = 0; SendLength = Irp->IoStatus.Information; HaltSendQueue = FALSE; while (!IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) && SendLength > 0) { NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]); NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); SendReq = GetLockedData(NextIrp, NextIrpSp); Map = (PAFD_MAPBUF)(SendReq->BufferArray + SendReq->BufferCount); TotalBytesCopied = (ULONG_PTR)NextIrp->Tail.Overlay.DriverContext[3]; ASSERT(TotalBytesCopied != 0); /* If we didn't get enough, keep waiting */ if (TotalBytesCopied > SendLength) { /* Update the bytes left to copy */ TotalBytesCopied -= SendLength; NextIrp->Tail.Overlay.DriverContext[3] = (PVOID)TotalBytesCopied; /* Update the state variables */ FCB->Send.BytesUsed -= SendLength; TotalBytesProcessed += SendLength; SendLength = 0; /* Pend the IRP */ InsertHeadList(&FCB->PendingIrpList[FUNCTION_SEND], &NextIrp->Tail.Overlay.ListEntry); HaltSendQueue = TRUE; break; } ASSERT(NextIrp->IoStatus.Information != 0); NextIrp->IoStatus.Status = Irp->IoStatus.Status; FCB->Send.BytesUsed -= TotalBytesCopied; TotalBytesProcessed += TotalBytesCopied; SendLength -= TotalBytesCopied; (void)IoSetCancelRoutine(NextIrp, NULL); UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); if (NextIrp->MdlAddress) UnlockRequest(NextIrp, NextIrpSp); IoCompleteRequest(NextIrp, IO_NETWORK_INCREMENT); } ASSERT(SendLength == 0); if ( !HaltSendQueue && !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) { NextIrpEntry = FCB->PendingIrpList[FUNCTION_SEND].Flink; NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); SendReq = GetLockedData(NextIrp, NextIrpSp); Map = (PAFD_MAPBUF)(SendReq->BufferArray + SendReq->BufferCount); AFD_DbgPrint(MID_TRACE,("SendReq @ %p\n", SendReq)); SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed; TotalBytesCopied = 0; /* Count the total transfer size */ SendLength = 0; for (i = 0; i < SendReq->BufferCount; i++) { SendLength += SendReq->BufferArray[i].len; } /* Make sure we've got the space */ if (SendLength > SpaceAvail) { /* Blocking sockets have to wait here */ if (SendLength <= FCB->Send.Size && !((SendReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking))) { FCB->PollState &= ~AFD_EVENT_SEND; NextIrp = NULL; } /* Check if we can send anything */ if (SpaceAvail == 0) { FCB->PollState &= ~AFD_EVENT_SEND; /* We should never be non-overlapped and get to this point */ ASSERT(SendReq->AfdFlags & AFD_OVERLAPPED); NextIrp = NULL; } } if (NextIrp != NULL) { for( i = 0; i < SendReq->BufferCount; i++ ) { BytesCopied = MIN(SendReq->BufferArray[i].len, SpaceAvail); Map[i].BufferAddress = MmMapLockedPages( Map[i].Mdl, KernelMode ); RtlCopyMemory( FCB->Send.Window + FCB->Send.BytesUsed, Map[i].BufferAddress, BytesCopied ); MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl ); TotalBytesCopied += BytesCopied; SpaceAvail -= BytesCopied; FCB->Send.BytesUsed += BytesCopied; } NextIrp->IoStatus.Information = TotalBytesCopied; NextIrp->Tail.Overlay.DriverContext[3] = (PVOID)NextIrp->IoStatus.Information; } } if (FCB->Send.Size - FCB->Send.BytesUsed != 0 && !FCB->SendClosed && IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND])) { FCB->PollState |= AFD_EVENT_SEND; FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS; PollReeval( FCB->DeviceExt, FCB->FileObject ); } else { FCB->PollState &= ~AFD_EVENT_SEND; } /* Some data is still waiting */ if( FCB->Send.BytesUsed ) { Status = TdiSend( &FCB->SendIrp.InFlightRequest, FCB->Connection.Object, 0, FCB->Send.Window, FCB->Send.BytesUsed, SendComplete, FCB ); } else { /* Nothing is waiting so try to complete a pending disconnect */ RetryDisconnectCompletion(FCB); } SocketStateUnlock( FCB ); return STATUS_SUCCESS; }
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, TotalBytesProcessed = 0, SpaceAvail, i; /* * 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)); if( !SocketAcquireStateLock( FCB ) ) return STATUS_FILE_CLOSED; ASSERT(FCB->SendIrp.InFlightRequest == Irp); FCB->SendIrp.InFlightRequest = NULL; /* Request is not in flight any longer */ if( FCB->State == SOCKET_STATE_CLOSED ) { /* Cleanup our IRP queue because the FCB is being destroyed */ while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) { NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]); NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); SendReq = GetLockedData(NextIrp, NextIrpSp); NextIrp->IoStatus.Status = STATUS_FILE_CLOSED; NextIrp->IoStatus.Information = 0; UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); if( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); (void)IoSetCancelRoutine(NextIrp, NULL); IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); } RetryDisconnectCompletion(FCB); SocketStateUnlock( FCB ); return STATUS_FILE_CLOSED; } 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 = GetLockedData(NextIrp, NextIrpSp); UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); NextIrp->IoStatus.Status = Status; NextIrp->IoStatus.Information = 0; if ( NextIrp->MdlAddress ) UnlockRequest( NextIrp, IoGetCurrentIrpStackLocation( NextIrp ) ); (void)IoSetCancelRoutine(NextIrp, NULL); IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); } RetryDisconnectCompletion(FCB); SocketStateUnlock( FCB ); return STATUS_SUCCESS; } RtlMoveMemory( FCB->Send.Window, FCB->Send.Window + FCB->Send.BytesUsed, FCB->Send.BytesUsed - Irp->IoStatus.Information ); TotalBytesProcessed = 0; while (!IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) && TotalBytesProcessed != Irp->IoStatus.Information) { NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]); NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); SendReq = GetLockedData(NextIrp, NextIrpSp); Map = (PAFD_MAPBUF)(SendReq->BufferArray + SendReq->BufferCount); TotalBytesCopied = 0; for( i = 0; i < SendReq->BufferCount; i++ ) TotalBytesCopied += SendReq->BufferArray[i].len; NextIrp->IoStatus.Status = Irp->IoStatus.Status; NextIrp->IoStatus.Information = TotalBytesCopied; TotalBytesProcessed += TotalBytesCopied; (void)IoSetCancelRoutine(NextIrp, NULL); UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); if (NextIrp->MdlAddress) UnlockRequest(NextIrp, NextIrpSp); IoCompleteRequest(NextIrp, IO_NETWORK_INCREMENT); } ASSERT(TotalBytesProcessed == Irp->IoStatus.Information); FCB->Send.BytesUsed -= TotalBytesProcessed; while( !IsListEmpty( &FCB->PendingIrpList[FUNCTION_SEND] ) ) { NextIrpEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]); NextIrp = CONTAINING_RECORD(NextIrpEntry, IRP, Tail.Overlay.ListEntry); NextIrpSp = IoGetCurrentIrpStackLocation( NextIrp ); SendReq = GetLockedData(NextIrp, NextIrpSp); Map = (PAFD_MAPBUF)(SendReq->BufferArray + SendReq->BufferCount); AFD_DbgPrint(MID_TRACE,("SendReq @ %x\n", SendReq)); SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed; TotalBytesCopied = 0; for( i = 0; i < SendReq->BufferCount; i++ ) { if (SpaceAvail < SendReq->BufferArray[i].len) { InsertHeadList(&FCB->PendingIrpList[FUNCTION_SEND], &NextIrp->Tail.Overlay.ListEntry); NextIrp = NULL; break; } Map[i].BufferAddress = MmMapLockedPages( Map[i].Mdl, KernelMode ); RtlCopyMemory( FCB->Send.Window + FCB->Send.BytesUsed, Map[i].BufferAddress, SendReq->BufferArray[i].len ); MmUnmapLockedPages( Map[i].BufferAddress, Map[i].Mdl ); TotalBytesCopied += SendReq->BufferArray[i].len; SpaceAvail -= SendReq->BufferArray[i].len; } if (NextIrp != NULL) { FCB->Send.BytesUsed += TotalBytesCopied; } else break; } if (FCB->Send.Size - FCB->Send.BytesUsed != 0 && !FCB->SendClosed) { FCB->PollState |= AFD_EVENT_SEND; FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS; PollReeval( FCB->DeviceExt, FCB->FileObject ); } else { FCB->PollState &= ~AFD_EVENT_SEND; } /* Some data is still waiting */ if( FCB->Send.BytesUsed ) { Status = TdiSend( &FCB->SendIrp.InFlightRequest, FCB->Connection.Object, 0, FCB->Send.Window, FCB->Send.BytesUsed, &FCB->SendIrp.Iosb, SendComplete, FCB ); } else { /* Nothing is waiting so try to complete a pending disconnect */ RetryDisconnectCompletion(FCB); } SocketStateUnlock( FCB ); return STATUS_SUCCESS; }
NTSTATUS NTAPI 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; KPROCESSOR_MODE LockMode; UNREFERENCED_PARAMETER(DeviceObject); AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB)); if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); FCB->EventSelectDisabled &= ~AFD_EVENT_SEND; /* Check that the socket is bound */ if( FCB->State != SOCKET_STATE_BOUND && FCB->State != SOCKET_STATE_CREATED) { AFD_DbgPrint(MIN_TRACE,("Invalid socket state\n")); return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0); } if (FCB->SendClosed) { AFD_DbgPrint(MIN_TRACE,("No more sends\n")); return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0); } if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) ) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0); if (FCB->State == SOCKET_STATE_CREATED) { if( FCB->LocalAddress ) ExFreePool( FCB->LocalAddress ); FCB->LocalAddress = TaBuildNullTransportAddress( ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)-> Address[0].AddressType ); if( FCB->LocalAddress ) { Status = WarmSocketForBind( FCB, AFD_SHARE_WILDCARD ); if( NT_SUCCESS(Status) ) FCB->State = SOCKET_STATE_BOUND; else return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); } else return UnlockAndMaybeComplete ( FCB, STATUS_NO_MEMORY, Irp, 0 ); } SendReq->BufferArray = LockBuffers( SendReq->BufferArray, SendReq->BufferCount, NULL, NULL, FALSE, FALSE, LockMode ); if( !SendReq->BufferArray ) return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION, Irp, 0 ); AFD_DbgPrint (MID_TRACE,("RemoteAddress #%d Type %u\n", ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)-> TAAddressCount, ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress)-> Address[0].AddressType)); Status = TdiBuildConnectionInfo( &TargetAddress, ((PTRANSPORT_ADDRESS)SendReq->TdiConnection.RemoteAddress) ); /* Check the size of the Address given ... */ if( NT_SUCCESS(Status) ) { FCB->PollState &= ~AFD_EVENT_SEND; Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); if (Status == STATUS_PENDING) { Status = TdiSendDatagram(&FCB->SendIrp.InFlightRequest, FCB->AddressFile.Object, SendReq->BufferArray[0].buf, SendReq->BufferArray[0].len, TargetAddress, PacketSocketSendComplete, FCB); if (Status != STATUS_PENDING) { NT_VERIFY(RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]) == &Irp->Tail.Overlay.ListEntry); Irp->IoStatus.Status = Status; Irp->IoStatus.Information = 0; (void)IoSetCancelRoutine(Irp, NULL); UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); UnlockRequest(Irp, IoGetCurrentIrpStackLocation(Irp)); IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); } } ExFreePool(TargetAddress); SocketStateUnlock(FCB); return STATUS_PENDING; } else { UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); } }
NTSTATUS NTAPI 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, SpaceAvail = 0, BytesCopied, SendLength; KPROCESSOR_MODE LockMode; UNREFERENCED_PARAMETER(DeviceObject); UNREFERENCED_PARAMETER(Short); AFD_DbgPrint(MID_TRACE,("Called on %p\n", FCB)); if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); FCB->EventSelectDisabled &= ~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 || !FCB->RemoteAddress ) { AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n")); return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp, 0 ); } if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) ) return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, Irp, 0 ); /* Must lock buffers before handing off user data */ SendReq->BufferArray = LockBuffers( SendReq->BufferArray, SendReq->BufferCount, NULL, NULL, FALSE, FALSE, LockMode ); if( !SendReq->BufferArray ) { return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION, Irp, 0 ); } Status = TdiBuildConnectionInfo( &TargetAddress, FCB->RemoteAddress ); if( NT_SUCCESS(Status) ) { FCB->PollState &= ~AFD_EVENT_SEND; Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); if (Status == STATUS_PENDING) { Status = TdiSendDatagram(&FCB->SendIrp.InFlightRequest, FCB->AddressFile.Object, SendReq->BufferArray[0].buf, SendReq->BufferArray[0].len, TargetAddress, PacketSocketSendComplete, FCB); if (Status != STATUS_PENDING) { NT_VERIFY(RemoveHeadList(&FCB->PendingIrpList[FUNCTION_SEND]) == &Irp->Tail.Overlay.ListEntry); Irp->IoStatus.Status = Status; Irp->IoStatus.Information = 0; (void)IoSetCancelRoutine(Irp, NULL); UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); UnlockRequest(Irp, IoGetCurrentIrpStackLocation(Irp)); IoCompleteRequest(Irp, IO_NETWORK_INCREMENT); } } ExFreePool( TargetAddress ); SocketStateUnlock(FCB); return STATUS_PENDING; } else { UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE); return UnlockAndMaybeComplete( FCB, Status, Irp, 0 ); } } if (FCB->PollState & AFD_EVENT_CLOSE) { AFD_DbgPrint(MIN_TRACE,("Connection reset by remote peer\n")); /* This is an unexpected remote disconnect */ return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0); } if (FCB->PollState & AFD_EVENT_ABORT) { AFD_DbgPrint(MIN_TRACE,("Connection aborted\n")); /* This is an abortive socket closure on our side */ return UnlockAndMaybeComplete(FCB, FCB->PollStatus[FD_CLOSE_BIT], Irp, 0); } if (FCB->SendClosed) { AFD_DbgPrint(MIN_TRACE,("No more sends\n")); /* This is a graceful send closure */ return UnlockAndMaybeComplete(FCB, STATUS_FILE_CLOSED, Irp, 0); } if( !(SendReq = LockRequest( Irp, IrpSp, FALSE, &LockMode )) ) return UnlockAndMaybeComplete ( FCB, STATUS_NO_MEMORY, Irp, 0 ); SendReq->BufferArray = LockBuffers( SendReq->BufferArray, SendReq->BufferCount, NULL, NULL, FALSE, FALSE, LockMode ); if( !SendReq->BufferArray ) { return UnlockAndMaybeComplete( FCB, STATUS_ACCESS_VIOLATION, Irp, 0 ); } AFD_DbgPrint(MID_TRACE,("Socket state %u\n", FCB->State)); if( FCB->State != SOCKET_STATE_CONNECTED ) { AFD_DbgPrint(MID_TRACE,("Socket not connected\n")); UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); return UnlockAndMaybeComplete( FCB, STATUS_INVALID_CONNECTION, Irp, 0 ); } AFD_DbgPrint(MID_TRACE,("FCB->Send.BytesUsed = %u\n", FCB->Send.BytesUsed)); SpaceAvail = FCB->Send.Size - FCB->Send.BytesUsed; AFD_DbgPrint(MID_TRACE,("We can accept %u bytes\n", SpaceAvail)); /* Count the total transfer size */ SendLength = 0; for (i = 0; i < SendReq->BufferCount; i++) { SendLength += SendReq->BufferArray[i].len; } /* Make sure we've got the space */ if (SendLength > SpaceAvail) { /* Blocking sockets have to wait here */ if (SendLength <= FCB->Send.Size && !((SendReq->AfdFlags & AFD_IMMEDIATE) || (FCB->NonBlocking))) { FCB->PollState &= ~AFD_EVENT_SEND; return LeaveIrpUntilLater(FCB, Irp, FUNCTION_SEND); } /* Check if we can send anything */ if (SpaceAvail == 0) { FCB->PollState &= ~AFD_EVENT_SEND; /* Non-overlapped sockets will fail if we can send nothing */ if (!(SendReq->AfdFlags & AFD_OVERLAPPED)) { UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); return UnlockAndMaybeComplete( FCB, STATUS_CANT_WAIT, Irp, 0 ); } else { /* Overlapped sockets just pend */ return LeaveIrpUntilLater(FCB, Irp, FUNCTION_SEND); } } } for ( i = 0; SpaceAvail > 0 && i < SendReq->BufferCount; i++ ) { BytesCopied = MIN(SendReq->BufferArray[i].len, SpaceAvail); AFD_DbgPrint(MID_TRACE,("Copying Buffer %u, %p:%u to %p\n", i, SendReq->BufferArray[i].buf, BytesCopied, FCB->Send.Window + FCB->Send.BytesUsed)); RtlCopyMemory(FCB->Send.Window + FCB->Send.BytesUsed, SendReq->BufferArray[i].buf, BytesCopied); TotalBytesCopied += BytesCopied; SpaceAvail -= BytesCopied; FCB->Send.BytesUsed += BytesCopied; } Irp->IoStatus.Information = TotalBytesCopied; if( TotalBytesCopied == 0 ) { AFD_DbgPrint(MID_TRACE,("Empty send\n")); UnlockBuffers( SendReq->BufferArray, SendReq->BufferCount, FALSE ); return UnlockAndMaybeComplete ( FCB, STATUS_SUCCESS, Irp, TotalBytesCopied ); } if (SpaceAvail) { FCB->PollState |= AFD_EVENT_SEND; FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS; PollReeval( FCB->DeviceExt, FCB->FileObject ); } else { FCB->PollState &= ~AFD_EVENT_SEND; } /* We use the IRP tail for some temporary storage here */ Irp->Tail.Overlay.DriverContext[3] = (PVOID)Irp->IoStatus.Information; Status = QueueUserModeIrp(FCB, Irp, FUNCTION_SEND); if (Status == STATUS_PENDING && !FCB->SendIrp.InFlightRequest) { TdiSend(&FCB->SendIrp.InFlightRequest, FCB->Connection.Object, 0, FCB->Send.Window, FCB->Send.BytesUsed, SendComplete, FCB); } SocketStateUnlock(FCB); return STATUS_PENDING; }