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
);
44 if( FCB
) FCB
->SendIrp
.InFlightRequest
= NULL
;
45 return STATUS_CANCELLED
;
48 if( !SocketAcquireStateLock( FCB
) ) return Status
;
50 FCB
->SendIrp
.InFlightRequest
= NULL
;
51 /* Request is not in flight any longer */
53 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
54 SocketStateUnlock( FCB
);
56 return STATUS_SUCCESS
;
59 if( !NT_SUCCESS(Status
) ) {
60 /* Complete all following send IRPs with error */
62 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
64 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
66 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
67 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
68 SendReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
70 UnlockBuffers( SendReq
->BufferArray
,
74 NextIrp
->IoStatus
.Status
= Status
;
75 NextIrp
->IoStatus
.Information
= 0;
77 if ( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
79 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
82 SocketStateUnlock( FCB
);
84 return STATUS_SUCCESS
;
87 RtlMoveMemory( FCB
->Send
.Window
,
88 FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
89 FCB
->Send
.BytesUsed
- Irp
->IoStatus
.Information
);
90 FCB
->Send
.BytesUsed
-= Irp
->IoStatus
.Information
;
92 if( !FCB
->Send
.BytesUsed
&&
93 !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
95 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
97 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
98 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
99 SendReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
100 Map
= (PAFD_MAPBUF
)(SendReq
->BufferArray
+ SendReq
->BufferCount
);
102 AFD_DbgPrint(MID_TRACE
,("SendReq @ %x\n", SendReq
));
104 SpaceAvail
= FCB
->Send
.Size
- FCB
->Send
.BytesUsed
;
106 for( i
= 0; i
< SendReq
->BufferCount
; i
++ ) {
107 Map
[i
].BufferAddress
=
108 MmMapLockedPages( Map
[i
].Mdl
, KernelMode
);
110 CopySize
= MIN( SpaceAvail
,
111 SendReq
->BufferArray
[i
].len
);
113 RtlCopyMemory( FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
114 Map
[i
].BufferAddress
,
117 MmUnmapLockedPages( Map
[i
].BufferAddress
, Map
[i
].Mdl
);
119 FCB
->Send
.BytesUsed
+= CopySize
;
120 TotalBytesCopied
+= CopySize
;
121 SpaceAvail
-= CopySize
;
125 /* Some data is still waiting */
126 if( FCB
->Send
.BytesUsed
) {
127 FCB
->PollState
&= ~AFD_EVENT_SEND
;
129 SocketCalloutEnter( FCB
);
131 Status
= TdiSend( &FCB
->SendIrp
.InFlightRequest
,
132 FCB
->Connection
.Object
,
140 SocketCalloutLeave( FCB
);
142 FCB
->PollState
|= AFD_EVENT_SEND
;
143 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
146 if( TotalBytesCopied
> 0 ) {
147 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
149 if( Status
== STATUS_PENDING
)
150 Status
= STATUS_SUCCESS
;
152 AFD_DbgPrint(MID_TRACE
,("Dismissing request: %x\n", Status
));
154 return UnlockAndMaybeComplete( FCB
, Status
, NextIrp
, TotalBytesCopied
,
156 } else if( NextIrp
) {
157 AFD_DbgPrint(MID_TRACE
,("Could not do any more with Irp %x\n",
159 InsertHeadList( &FCB
->PendingIrpList
[FUNCTION_SEND
],
160 &NextIrp
->Tail
.Overlay
.ListEntry
);
163 SocketStateUnlock( FCB
);
165 return STATUS_SUCCESS
;
168 static NTSTATUS NTAPI PacketSocketSendComplete
169 ( PDEVICE_OBJECT DeviceObject
,
172 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
174 AFD_DbgPrint(MID_TRACE
,("Called, status %x, %d bytes used\n",
175 Irp
->IoStatus
.Status
,
176 Irp
->IoStatus
.Information
));
179 if( FCB
) FCB
->SendIrp
.InFlightRequest
= NULL
;
180 return STATUS_CANCELLED
;
183 /* It's ok if the FCB already died */
184 if( !SocketAcquireStateLock( FCB
) ) return STATUS_SUCCESS
;
186 FCB
->PollState
|= AFD_EVENT_SEND
;
187 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
189 FCB
->SendIrp
.InFlightRequest
= NULL
;
190 /* Request is not in flight any longer */
192 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
193 SocketStateUnlock( FCB
);
194 DestroySocket( FCB
);
195 return STATUS_SUCCESS
;
198 SocketStateUnlock( FCB
);
200 return STATUS_SUCCESS
;
204 AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
205 PIO_STACK_LOCATION IrpSp
, BOOLEAN Short
) {
206 NTSTATUS Status
= STATUS_SUCCESS
;
207 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
208 PAFD_FCB FCB
= FileObject
->FsContext
;
209 PAFD_SEND_INFO SendReq
;
210 UINT TotalBytesCopied
= 0, i
, CopySize
= 0,
211 SpaceAvail
= 0, TotalBytesEncountered
= 0;
213 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
215 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
217 FCB
->EventsFired
&= ~AFD_EVENT_SEND
;
219 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
221 PAFD_SEND_INFO_UDP SendReq
;
222 PTDI_CONNECTION_INFORMATION TargetAddress
;
224 /* Check that the socket is bound */
225 if( FCB
->State
!= SOCKET_STATE_BOUND
)
226 return UnlockAndMaybeComplete( FCB
, STATUS_INVALID_PARAMETER
, Irp
,
229 if( !(SendReq
= LockRequest( Irp
, IrpSp
)) )
230 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
, 0,
233 /* Must lock buffers before handing off user data */
234 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
235 SendReq
->BufferCount
,
239 if( !SendReq
->BufferArray
) {
240 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
244 TdiBuildConnectionInfo( &TargetAddress
, FCB
->RemoteAddress
);
246 if( TargetAddress
) {
247 SocketCalloutEnter( FCB
);
249 Status
= TdiSendDatagram
250 ( &FCB
->SendIrp
.InFlightRequest
,
251 FCB
->AddressFile
.Object
,
252 SendReq
->BufferArray
[0].buf
,
253 SendReq
->BufferArray
[0].len
,
256 PacketSocketSendComplete
,
259 SocketCalloutLeave( FCB
);
261 ExFreePool( TargetAddress
);
262 } else Status
= STATUS_NO_MEMORY
;
264 if( Status
== STATUS_PENDING
) Status
= STATUS_SUCCESS
;
266 AFD_DbgPrint(MID_TRACE
,("Dismissing request: %x\n", Status
));
268 return UnlockAndMaybeComplete( FCB
, Status
, Irp
,
269 SendReq
->BufferArray
[0].len
,
273 if( !(SendReq
= LockRequest( Irp
, IrpSp
)) )
274 return UnlockAndMaybeComplete
275 ( FCB
, STATUS_NO_MEMORY
, Irp
, TotalBytesCopied
, NULL
);
277 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
278 SendReq
->BufferCount
,
282 if( !SendReq
->BufferArray
) {
283 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
287 AFD_DbgPrint(MID_TRACE
,("Socket state %d\n", FCB
->State
));
289 if( FCB
->State
!= SOCKET_STATE_CONNECTED
) {
290 if( SendReq
->AfdFlags
& AFD_IMMEDIATE
) {
291 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
292 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
293 return UnlockAndMaybeComplete
294 ( FCB
, STATUS_CANT_WAIT
, Irp
, 0, NULL
);
296 AFD_DbgPrint(MID_TRACE
,("Queuing request\n"));
297 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_SEND
);
301 AFD_DbgPrint(MID_TRACE
,("FCB->Send.BytesUsed = %d\n",
302 FCB
->Send
.BytesUsed
));
304 if( !FCB
->Send
.BytesUsed
) {
305 SpaceAvail
= FCB
->Send
.Size
- FCB
->Send
.BytesUsed
;
307 AFD_DbgPrint(MID_TRACE
,("We can accept %d bytes\n",
310 for( i
= 0; FCB
->Send
.BytesUsed
< FCB
->Send
.Size
&&
311 i
< SendReq
->BufferCount
; i
++ ) {
312 CopySize
= MIN( SpaceAvail
,
313 SendReq
->BufferArray
[i
].len
);
315 TotalBytesEncountered
+= SendReq
->BufferArray
[i
].len
;
317 AFD_DbgPrint(MID_TRACE
,("Copying Buffer %d, %x:%d to %x\n",
319 SendReq
->BufferArray
[i
].buf
,
321 FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
));
323 RtlCopyMemory( FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
324 SendReq
->BufferArray
[i
].buf
,
327 FCB
->Send
.BytesUsed
+= CopySize
;
328 TotalBytesCopied
+= CopySize
;
329 SpaceAvail
-= CopySize
;
332 if( TotalBytesEncountered
== 0 ) {
333 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
335 AFD_DbgPrint(MID_TRACE
,("Empty send\n"));
336 return UnlockAndMaybeComplete
337 ( FCB
, Status
, Irp
, TotalBytesCopied
, NULL
);
340 AFD_DbgPrint(MID_TRACE
,("Completed %d bytes\n", TotalBytesCopied
));
342 if( TotalBytesCopied
> 0 ) {
343 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
345 FCB
->SendIrp
.InFlightRequest
= (PVOID
)1; /* Placeholder */
347 SocketCalloutEnter( FCB
);
349 Status
= TdiSend( &FCB
->SendIrp
.InFlightRequest
,
350 FCB
->Connection
.Object
,
358 SocketCalloutLeave( FCB
);
360 if( Status
== STATUS_PENDING
)
361 Status
= STATUS_SUCCESS
;
363 AFD_DbgPrint(MID_TRACE
,("Dismissing request: %x (%d)\n",
364 Status
, TotalBytesCopied
));
366 return UnlockAndMaybeComplete
367 ( FCB
, Status
, Irp
, TotalBytesCopied
, NULL
);
371 if( SendReq
->AfdFlags
& AFD_IMMEDIATE
) {
372 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
373 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
374 return UnlockAndMaybeComplete
375 ( FCB
, STATUS_CANT_WAIT
, Irp
, 0, NULL
);
377 AFD_DbgPrint(MID_TRACE
,("Queuing request\n"));
378 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_SEND
);
383 AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
384 PIO_STACK_LOCATION IrpSp
) {
385 NTSTATUS Status
= STATUS_SUCCESS
;
386 PTDI_CONNECTION_INFORMATION TargetAddress
;
387 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
388 PAFD_FCB FCB
= FileObject
->FsContext
;
389 PAFD_SEND_INFO_UDP SendReq
;
391 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
393 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
395 FCB
->EventsFired
&= ~AFD_EVENT_SEND
;
396 FCB
->PollState
&= ~AFD_EVENT_SEND
;
398 /* Check that the socket is bound */
399 if( FCB
->State
!= SOCKET_STATE_BOUND
)
400 return UnlockAndMaybeComplete
401 ( FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0, NULL
);
402 if( !(SendReq
= LockRequest( Irp
, IrpSp
)) )
403 return UnlockAndMaybeComplete
404 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0, NULL
);
407 (MID_TRACE
,("RemoteAddress #%d Type %d\n",
408 ((PTRANSPORT_ADDRESS
)SendReq
->RemoteAddress
)->
410 ((PTRANSPORT_ADDRESS
)SendReq
->RemoteAddress
)->
411 Address
[0].AddressType
));
413 TdiBuildConnectionInfo( &TargetAddress
,
414 ((PTRANSPORT_ADDRESS
)SendReq
->RemoteAddress
) );
416 /* Check the size of the Address given ... */
418 if( TargetAddress
) {
419 SocketCalloutEnter( FCB
);
421 Status
= TdiSendDatagram
422 ( &FCB
->SendIrp
.InFlightRequest
,
423 FCB
->AddressFile
.Object
,
424 SendReq
->BufferArray
[0].buf
,
425 SendReq
->BufferArray
[0].len
,
428 PacketSocketSendComplete
,
431 SocketCalloutLeave( FCB
);
433 ExFreePool( TargetAddress
);
434 } else Status
= STATUS_NO_MEMORY
;
436 if( Status
== STATUS_PENDING
) Status
= STATUS_SUCCESS
;
438 AFD_DbgPrint(MID_TRACE
,("Dismissing request: %x\n", Status
));
440 return UnlockAndMaybeComplete
441 ( FCB
, Status
, Irp
, SendReq
->BufferArray
[0].len
, NULL
);