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 FCB
->SendIrp
.InFlightRequest
= NULL
;
45 return STATUS_SUCCESS
;
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 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
80 SocketStateUnlock( FCB
);
82 return STATUS_SUCCESS
;
85 RtlMoveMemory( FCB
->Send
.Window
,
86 FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
87 FCB
->Send
.BytesUsed
- Irp
->IoStatus
.Information
);
88 FCB
->Send
.BytesUsed
-= Irp
->IoStatus
.Information
;
90 if( !FCB
->Send
.BytesUsed
&&
91 !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) &&
92 NT_SUCCESS(Status
) ) {
94 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
96 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
97 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
98 SendReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
99 Map
= (PAFD_MAPBUF
)(SendReq
->BufferArray
+ SendReq
->BufferCount
);
101 AFD_DbgPrint(MID_TRACE
,("SendReq @ %x\n", SendReq
));
103 SpaceAvail
= FCB
->Send
.Size
- FCB
->Send
.BytesUsed
;
105 for( i
= 0; i
< SendReq
->BufferCount
; i
++ ) {
106 Map
[i
].BufferAddress
=
107 MmMapLockedPages( Map
[i
].Mdl
, KernelMode
);
109 CopySize
= MIN( SpaceAvail
,
110 SendReq
->BufferArray
[i
].len
);
112 RtlCopyMemory( FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
113 Map
[i
].BufferAddress
,
116 MmUnmapLockedPages( Map
[i
].BufferAddress
, Map
[i
].Mdl
);
118 FCB
->Send
.BytesUsed
+= CopySize
;
119 TotalBytesCopied
+= CopySize
;
120 SpaceAvail
-= CopySize
;
124 /* Some data is still waiting */
125 if( FCB
->Send
.BytesUsed
) {
126 FCB
->PollState
&= ~AFD_EVENT_SEND
;
128 SocketCalloutEnter( FCB
);
130 Status
= TdiSend( &FCB
->SendIrp
.InFlightRequest
,
131 FCB
->Connection
.Object
,
139 SocketCalloutLeave( FCB
);
141 FCB
->PollState
|= AFD_EVENT_SEND
;
142 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
145 if( TotalBytesCopied
> 0 ) {
146 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
148 if( Status
== STATUS_PENDING
)
149 Status
= STATUS_SUCCESS
;
151 AFD_DbgPrint(MID_TRACE
,("Dismissing request: %x\n", Status
));
153 return UnlockAndMaybeComplete( FCB
, Status
, NextIrp
, TotalBytesCopied
,
155 } else if( NextIrp
) {
156 AFD_DbgPrint(MID_TRACE
,("Could not do any more with Irp %x\n",
158 InsertHeadList( &FCB
->PendingIrpList
[FUNCTION_SEND
],
159 &NextIrp
->Tail
.Overlay
.ListEntry
);
162 SocketStateUnlock( FCB
);
164 return STATUS_SUCCESS
;
167 static NTSTATUS NTAPI PacketSocketSendComplete
168 ( PDEVICE_OBJECT DeviceObject
,
171 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
173 AFD_DbgPrint(MID_TRACE
,("Called, status %x, %d bytes used\n",
174 Irp
->IoStatus
.Status
,
175 Irp
->IoStatus
.Information
));
178 FCB
->SendIrp
.InFlightRequest
= NULL
;
179 return STATUS_SUCCESS
;
182 /* It's ok if the FCB already died */
183 if( !SocketAcquireStateLock( FCB
) ) return STATUS_SUCCESS
;
185 FCB
->PollState
|= AFD_EVENT_SEND
;
186 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
188 FCB
->SendIrp
.InFlightRequest
= NULL
;
189 /* Request is not in flight any longer */
191 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
192 SocketStateUnlock( FCB
);
193 DestroySocket( FCB
);
194 return STATUS_SUCCESS
;
197 SocketStateUnlock( FCB
);
199 return STATUS_SUCCESS
;
203 AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
204 PIO_STACK_LOCATION IrpSp
, BOOLEAN Short
) {
205 NTSTATUS Status
= STATUS_SUCCESS
;
206 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
207 PAFD_FCB FCB
= FileObject
->FsContext
;
208 PAFD_SEND_INFO SendReq
;
209 UINT TotalBytesCopied
= 0, i
, CopySize
= 0,
210 SpaceAvail
= 0, TotalBytesEncountered
= 0;
212 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
214 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
, FALSE
);
216 FCB
->EventsFired
&= ~AFD_EVENT_SEND
;
218 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
220 PAFD_SEND_INFO_UDP SendReq
;
221 PTDI_CONNECTION_INFORMATION TargetAddress
;
223 /* Check that the socket is bound */
224 if( FCB
->State
!= SOCKET_STATE_BOUND
)
225 return UnlockAndMaybeComplete( FCB
, STATUS_UNSUCCESSFUL
, Irp
,
228 if( !(SendReq
= LockRequest( Irp
, IrpSp
)) )
229 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
, 0,
232 /* Must lock buffers before handing off user data */
233 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
234 SendReq
->BufferCount
,
238 TdiBuildConnectionInfo( &TargetAddress
, FCB
->RemoteAddress
);
240 SocketCalloutEnter( FCB
);
242 Status
= TdiSendDatagram
243 ( &FCB
->SendIrp
.InFlightRequest
,
244 FCB
->AddressFile
.Object
,
245 SendReq
->BufferArray
[0].buf
,
246 SendReq
->BufferArray
[0].len
,
249 PacketSocketSendComplete
,
252 SocketCalloutLeave( FCB
);
254 ExFreePool( TargetAddress
);
256 if( Status
== STATUS_PENDING
) Status
= STATUS_SUCCESS
;
258 AFD_DbgPrint(MID_TRACE
,("Dismissing request: %x\n", Status
));
260 return UnlockAndMaybeComplete( FCB
, Status
, Irp
,
261 SendReq
->BufferArray
[0].len
,
265 if( !(SendReq
= LockRequest( Irp
, IrpSp
)) )
266 return UnlockAndMaybeComplete
267 ( FCB
, STATUS_NO_MEMORY
, Irp
, TotalBytesCopied
, NULL
, FALSE
);
269 AFD_DbgPrint(MID_TRACE
,("Socket state %d\n", FCB
->State
));
271 if( FCB
->State
!= SOCKET_STATE_CONNECTED
) {
272 if( SendReq
->AfdFlags
& AFD_IMMEDIATE
) {
273 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
274 return UnlockAndMaybeComplete
275 ( FCB
, STATUS_CANT_WAIT
, Irp
, 0, NULL
, TRUE
);
277 AFD_DbgPrint(MID_TRACE
,("Queuing request\n"));
278 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_SEND
);
282 AFD_DbgPrint(MID_TRACE
,("We already have %d bytes waiting.\n",
283 FCB
->Send
.BytesUsed
));
285 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
286 SendReq
->BufferCount
,
290 AFD_DbgPrint(MID_TRACE
,("FCB->Send.BytesUsed = %d\n",
291 FCB
->Send
.BytesUsed
));
293 if( !FCB
->Send
.BytesUsed
) {
294 SpaceAvail
= FCB
->Send
.Size
- FCB
->Send
.BytesUsed
;
296 AFD_DbgPrint(MID_TRACE
,("We can accept %d bytes\n",
299 for( i
= 0; FCB
->Send
.BytesUsed
< FCB
->Send
.Size
&&
300 i
< SendReq
->BufferCount
; i
++ ) {
301 CopySize
= MIN( SpaceAvail
,
302 SendReq
->BufferArray
[i
].len
);
304 TotalBytesEncountered
+= SendReq
->BufferArray
[i
].len
;
306 AFD_DbgPrint(MID_TRACE
,("Copying Buffer %d, %x:%d to %x\n",
308 SendReq
->BufferArray
[i
].buf
,
310 FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
));
312 RtlCopyMemory( FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
313 SendReq
->BufferArray
[i
].buf
,
316 FCB
->Send
.BytesUsed
+= CopySize
;
317 TotalBytesCopied
+= CopySize
;
318 SpaceAvail
-= CopySize
;
321 if( TotalBytesEncountered
== 0 ) {
322 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
324 AFD_DbgPrint(MID_TRACE
,("Empty send\n"));
325 return UnlockAndMaybeComplete
326 ( FCB
, Status
, Irp
, TotalBytesCopied
, NULL
, TRUE
);
329 AFD_DbgPrint(MID_TRACE
,("Completed %d bytes\n", TotalBytesCopied
));
331 if( TotalBytesCopied
> 0 ) {
332 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
334 FCB
->SendIrp
.InFlightRequest
= (PVOID
)1; /* Placeholder */
336 SocketCalloutEnter( FCB
);
338 Status
= TdiSend( &FCB
->SendIrp
.InFlightRequest
,
339 FCB
->Connection
.Object
,
347 SocketCalloutLeave( FCB
);
349 if( Status
== STATUS_PENDING
)
350 Status
= STATUS_SUCCESS
;
352 AFD_DbgPrint(MID_TRACE
,("Dismissing request: %x (%d)\n",
353 Status
, TotalBytesCopied
));
355 return UnlockAndMaybeComplete
356 ( FCB
, Status
, Irp
, TotalBytesCopied
, NULL
, TRUE
);
360 if( SendReq
->AfdFlags
& AFD_IMMEDIATE
) {
361 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
362 return UnlockAndMaybeComplete
363 ( FCB
, STATUS_CANT_WAIT
, Irp
, 0, NULL
, TRUE
);
365 AFD_DbgPrint(MID_TRACE
,("Queuing request\n"));
366 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_SEND
);
371 AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
372 PIO_STACK_LOCATION IrpSp
) {
373 NTSTATUS Status
= STATUS_SUCCESS
;
374 PTDI_CONNECTION_INFORMATION TargetAddress
;
375 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
376 PAFD_FCB FCB
= FileObject
->FsContext
;
377 PAFD_SEND_INFO_UDP SendReq
;
379 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
381 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
, FALSE
);
383 FCB
->EventsFired
&= ~AFD_EVENT_SEND
;
384 FCB
->PollState
&= ~AFD_EVENT_SEND
;
386 /* Check that the socket is bound */
387 if( FCB
->State
!= SOCKET_STATE_BOUND
)
388 return UnlockAndMaybeComplete
389 ( FCB
, STATUS_UNSUCCESSFUL
, Irp
, 0, NULL
, FALSE
);
390 if( !(SendReq
= LockRequest( Irp
, IrpSp
)) )
391 return UnlockAndMaybeComplete
392 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0, NULL
, FALSE
);
395 (MID_TRACE
,("RemoteAddress #%d Type %d\n",
396 ((PTRANSPORT_ADDRESS
)SendReq
->RemoteAddress
)->
398 ((PTRANSPORT_ADDRESS
)SendReq
->RemoteAddress
)->
399 Address
[0].AddressType
));
401 TdiBuildConnectionInfo( &TargetAddress
,
402 ((PTRANSPORT_ADDRESS
)SendReq
->RemoteAddress
) );
404 /* Check the size of the Address given ... */
406 if( TargetAddress
) {
407 SocketCalloutEnter( FCB
);
409 Status
= TdiSendDatagram
410 ( &FCB
->SendIrp
.InFlightRequest
,
411 FCB
->AddressFile
.Object
,
412 SendReq
->BufferArray
[0].buf
,
413 SendReq
->BufferArray
[0].len
,
416 PacketSocketSendComplete
,
419 SocketCalloutLeave( FCB
);
421 ExFreePool( TargetAddress
);
422 } else Status
= STATUS_NO_MEMORY
;
424 if( Status
== STATUS_PENDING
) Status
= STATUS_SUCCESS
;
426 AFD_DbgPrint(MID_TRACE
,("Dismissing request: %x\n", Status
));
428 return UnlockAndMaybeComplete
429 ( FCB
, Status
, Irp
, SendReq
->BufferArray
[0].len
, NULL
, TRUE
);