2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/net/afd/afd/write.c
5 * PURPOSE: Ancillary functions driver
6 * PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
11 #include "tdi_proto.h"
15 static NTSTATUS NTAPI SendComplete
16 ( PDEVICE_OBJECT DeviceObject
,
19 NTSTATUS Status
= Irp
->IoStatus
.Status
;
20 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
21 PLIST_ENTRY NextIrpEntry
;
23 PIO_STACK_LOCATION NextIrpSp
;
24 PAFD_SEND_INFO SendReq
= NULL
;
26 UINT TotalBytesCopied
= 0, SpaceAvail
, i
, CopySize
= 0;
29 * The Irp parameter passed in is the IRP of the stream between AFD and
30 * TDI driver. It's not very usefull to us. We need the IRPs of the stream
31 * between usermode and AFD. Those are chained from
32 * FCB->PendingIrpList[FUNCTION_SEND] and you'll see them in the code
33 * below as "NextIrp" ('cause they are the next usermode IRP to be
37 AFD_DbgPrint(MID_TRACE
,("Called, status %x, %d bytes used\n",
39 Irp
->IoStatus
.Information
));
41 ASSERT_IRQL(APC_LEVEL
);
43 if( !SocketAcquireStateLock( FCB
) ) return Status
;
45 FCB
->SendIrp
.InFlightRequest
= NULL
;
46 /* Request is not in flight any longer */
48 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
49 SocketStateUnlock( FCB
);
51 return STATUS_SUCCESS
;
54 if( !NT_SUCCESS(Status
) ) {
55 /* Complete all following send IRPs with error */
57 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
59 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
61 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
62 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
63 SendReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
65 UnlockBuffers( SendReq
->BufferArray
,
69 NextIrp
->IoStatus
.Status
= Status
;
70 NextIrp
->IoStatus
.Information
= 0;
72 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
75 SocketStateUnlock( FCB
);
77 return STATUS_SUCCESS
;
80 RtlMoveMemory( FCB
->Send
.Window
,
81 FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
82 FCB
->Send
.BytesUsed
- Irp
->IoStatus
.Information
);
83 FCB
->Send
.BytesUsed
-= Irp
->IoStatus
.Information
;
85 if( !FCB
->Send
.BytesUsed
&&
86 !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) &&
87 NT_SUCCESS(Status
) ) {
89 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
91 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
92 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
93 SendReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
94 Map
= (PAFD_MAPBUF
)(SendReq
->BufferArray
+ SendReq
->BufferCount
);
96 AFD_DbgPrint(MID_TRACE
,("SendReq @ %x\n", SendReq
));
98 SpaceAvail
= FCB
->Send
.Size
- FCB
->Send
.BytesUsed
;
100 for( i
= 0; i
< SendReq
->BufferCount
; i
++ ) {
101 Map
[i
].BufferAddress
=
102 MmMapLockedPages( Map
[i
].Mdl
, KernelMode
);
104 CopySize
= MIN( SpaceAvail
,
105 SendReq
->BufferArray
[i
].len
);
107 RtlCopyMemory( FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
108 Map
[i
].BufferAddress
,
111 MmUnmapLockedPages( Map
[i
].BufferAddress
, Map
[i
].Mdl
);
113 FCB
->Send
.BytesUsed
+= CopySize
;
114 TotalBytesCopied
+= CopySize
;
115 SpaceAvail
-= CopySize
;
119 /* Some data is still waiting */
120 if( FCB
->Send
.BytesUsed
) {
121 FCB
->PollState
&= ~AFD_EVENT_SEND
;
123 SocketCalloutEnter( FCB
);
125 Status
= TdiSend( &FCB
->SendIrp
.InFlightRequest
,
126 FCB
->Connection
.Object
,
134 SocketCalloutLeave( FCB
);
136 FCB
->PollState
|= AFD_EVENT_SEND
;
137 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
140 if( TotalBytesCopied
> 0 ) {
141 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
143 if( Status
== STATUS_PENDING
)
144 Status
= STATUS_SUCCESS
;
146 AFD_DbgPrint(MID_TRACE
,("Dismissing request: %x\n", Status
));
148 return UnlockAndMaybeComplete( FCB
, Status
, NextIrp
, TotalBytesCopied
,
150 } else if( NextIrp
) {
151 AFD_DbgPrint(MID_TRACE
,("Could not do any more with Irp %x\n",
153 InsertHeadList( &FCB
->PendingIrpList
[FUNCTION_SEND
],
154 &NextIrp
->Tail
.Overlay
.ListEntry
);
157 SocketStateUnlock( FCB
);
159 return STATUS_SUCCESS
;
162 static NTSTATUS NTAPI PacketSocketSendComplete
163 ( PDEVICE_OBJECT DeviceObject
,
166 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
168 AFD_DbgPrint(MID_TRACE
,("Called, status %x, %d bytes used\n",
169 Irp
->IoStatus
.Status
,
170 Irp
->IoStatus
.Information
));
172 /* It's ok if the FCB already died */
173 if( !SocketAcquireStateLock( FCB
) ) return STATUS_SUCCESS
;
175 FCB
->PollState
|= AFD_EVENT_SEND
;
176 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
178 FCB
->SendIrp
.InFlightRequest
= NULL
;
179 /* Request is not in flight any longer */
181 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
182 SocketStateUnlock( FCB
);
183 DestroySocket( FCB
);
184 return STATUS_SUCCESS
;
187 SocketStateUnlock( FCB
);
189 return STATUS_SUCCESS
;
193 AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
194 PIO_STACK_LOCATION IrpSp
, BOOLEAN Short
) {
195 NTSTATUS Status
= STATUS_SUCCESS
;
196 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
197 PAFD_FCB FCB
= FileObject
->FsContext
;
198 PAFD_SEND_INFO SendReq
;
199 UINT TotalBytesCopied
= 0, i
, CopySize
= 0,
200 SpaceAvail
= 0, TotalBytesEncountered
= 0;
202 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
204 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
, FALSE
);
206 FCB
->EventsFired
&= ~AFD_EVENT_SEND
;
208 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
210 PAFD_SEND_INFO_UDP SendReq
;
211 PTDI_CONNECTION_INFORMATION TargetAddress
;
213 /* Check that the socket is bound */
214 if( FCB
->State
!= SOCKET_STATE_BOUND
)
215 return UnlockAndMaybeComplete( FCB
, STATUS_UNSUCCESSFUL
, Irp
,
218 if( !(SendReq
= LockRequest( Irp
, IrpSp
)) )
219 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
, 0,
222 /* Must lock buffers before handing off user data */
223 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
224 SendReq
->BufferCount
,
228 TdiBuildConnectionInfo( &TargetAddress
, FCB
->RemoteAddress
);
230 SocketCalloutEnter( FCB
);
232 Status
= TdiSendDatagram
233 ( &FCB
->SendIrp
.InFlightRequest
,
234 FCB
->AddressFile
.Object
,
235 SendReq
->BufferArray
[0].buf
,
236 SendReq
->BufferArray
[0].len
,
239 PacketSocketSendComplete
,
242 SocketCalloutLeave( FCB
);
244 ExFreePool( TargetAddress
);
246 if( Status
== STATUS_PENDING
) Status
= STATUS_SUCCESS
;
248 AFD_DbgPrint(MID_TRACE
,("Dismissing request: %x\n", Status
));
250 return UnlockAndMaybeComplete( FCB
, Status
, Irp
,
251 SendReq
->BufferArray
[0].len
,
255 if( !(SendReq
= LockRequest( Irp
, IrpSp
)) )
256 return UnlockAndMaybeComplete
257 ( FCB
, STATUS_NO_MEMORY
, Irp
, TotalBytesCopied
, NULL
, FALSE
);
259 AFD_DbgPrint(MID_TRACE
,("Socket state %d\n", FCB
->State
));
261 if( FCB
->State
!= SOCKET_STATE_CONNECTED
) {
262 if( SendReq
->AfdFlags
& AFD_IMMEDIATE
) {
263 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
264 return UnlockAndMaybeComplete
265 ( FCB
, STATUS_CANT_WAIT
, Irp
, 0, NULL
, TRUE
);
267 AFD_DbgPrint(MID_TRACE
,("Queuing request\n"));
268 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_SEND
);
272 AFD_DbgPrint(MID_TRACE
,("We already have %d bytes waiting.\n",
273 FCB
->Send
.BytesUsed
));
275 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
276 SendReq
->BufferCount
,
280 AFD_DbgPrint(MID_TRACE
,("FCB->Send.BytesUsed = %d\n",
281 FCB
->Send
.BytesUsed
));
283 if( !FCB
->Send
.BytesUsed
) {
284 SpaceAvail
= FCB
->Send
.Size
- FCB
->Send
.BytesUsed
;
286 AFD_DbgPrint(MID_TRACE
,("We can accept %d bytes\n",
289 for( i
= 0; FCB
->Send
.BytesUsed
< FCB
->Send
.Size
&&
290 i
< SendReq
->BufferCount
; i
++ ) {
291 CopySize
= MIN( SpaceAvail
,
292 SendReq
->BufferArray
[i
].len
);
294 TotalBytesEncountered
+= SendReq
->BufferArray
[i
].len
;
296 AFD_DbgPrint(MID_TRACE
,("Copying Buffer %d, %x:%d to %x\n",
298 SendReq
->BufferArray
[i
].buf
,
300 FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
));
302 RtlCopyMemory( FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
303 SendReq
->BufferArray
[i
].buf
,
306 FCB
->Send
.BytesUsed
+= CopySize
;
307 TotalBytesCopied
+= CopySize
;
308 SpaceAvail
-= CopySize
;
311 if( TotalBytesEncountered
== 0 ) {
312 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
314 AFD_DbgPrint(MID_TRACE
,("Empty send\n"));
315 return UnlockAndMaybeComplete
316 ( FCB
, Status
, Irp
, TotalBytesCopied
, NULL
, TRUE
);
319 AFD_DbgPrint(MID_TRACE
,("Completed %d bytes\n", TotalBytesCopied
));
321 if( TotalBytesCopied
> 0 ) {
322 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
324 FCB
->SendIrp
.InFlightRequest
= (PVOID
)1; /* Placeholder */
326 SocketCalloutEnter( FCB
);
328 Status
= TdiSend( &FCB
->SendIrp
.InFlightRequest
,
329 FCB
->Connection
.Object
,
337 SocketCalloutLeave( FCB
);
339 if( Status
== STATUS_PENDING
)
340 Status
= STATUS_SUCCESS
;
342 AFD_DbgPrint(MID_TRACE
,("Dismissing request: %x (%d)\n",
343 Status
, TotalBytesCopied
));
345 return UnlockAndMaybeComplete
346 ( FCB
, Status
, Irp
, TotalBytesCopied
, NULL
, TRUE
);
350 if( SendReq
->AfdFlags
& AFD_IMMEDIATE
) {
351 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
352 return UnlockAndMaybeComplete
353 ( FCB
, STATUS_CANT_WAIT
, Irp
, 0, NULL
, TRUE
);
355 AFD_DbgPrint(MID_TRACE
,("Queuing request\n"));
356 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_SEND
);
361 AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
362 PIO_STACK_LOCATION IrpSp
) {
363 NTSTATUS Status
= STATUS_SUCCESS
;
364 PTDI_CONNECTION_INFORMATION TargetAddress
;
365 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
366 PAFD_FCB FCB
= FileObject
->FsContext
;
367 PAFD_SEND_INFO_UDP SendReq
;
369 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
371 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
, FALSE
);
373 FCB
->EventsFired
&= ~AFD_EVENT_SEND
;
374 FCB
->PollState
&= ~AFD_EVENT_SEND
;
376 /* Check that the socket is bound */
377 if( FCB
->State
!= SOCKET_STATE_BOUND
)
378 return UnlockAndMaybeComplete
379 ( FCB
, STATUS_UNSUCCESSFUL
, Irp
, 0, NULL
, FALSE
);
380 if( !(SendReq
= LockRequest( Irp
, IrpSp
)) )
381 return UnlockAndMaybeComplete
382 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0, NULL
, FALSE
);
385 (MID_TRACE
,("RemoteAddress #%d Type %d\n",
386 ((PTRANSPORT_ADDRESS
)SendReq
->RemoteAddress
)->
388 ((PTRANSPORT_ADDRESS
)SendReq
->RemoteAddress
)->
389 Address
[0].AddressType
));
391 TdiBuildConnectionInfo( &TargetAddress
,
392 ((PTRANSPORT_ADDRESS
)SendReq
->RemoteAddress
) );
394 /* Check the size of the Address given ... */
396 if( TargetAddress
) {
397 SocketCalloutEnter( FCB
);
399 Status
= TdiSendDatagram
400 ( &FCB
->SendIrp
.InFlightRequest
,
401 FCB
->AddressFile
.Object
,
402 SendReq
->BufferArray
[0].buf
,
403 SendReq
->BufferArray
[0].len
,
406 PacketSocketSendComplete
,
409 SocketCalloutLeave( FCB
);
411 ExFreePool( TargetAddress
);
412 } else Status
= STATUS_NO_MEMORY
;
414 if( Status
== STATUS_PENDING
) Status
= STATUS_SUCCESS
;
416 AFD_DbgPrint(MID_TRACE
,("Dismissing request: %x\n", Status
));
418 return UnlockAndMaybeComplete
419 ( FCB
, Status
, Irp
, SendReq
->BufferArray
[0].len
, NULL
, TRUE
);