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 if ( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
74 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
77 SocketStateUnlock( FCB
);
79 return STATUS_SUCCESS
;
82 RtlMoveMemory( FCB
->Send
.Window
,
83 FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
84 FCB
->Send
.BytesUsed
- Irp
->IoStatus
.Information
);
85 FCB
->Send
.BytesUsed
-= Irp
->IoStatus
.Information
;
87 if( !FCB
->Send
.BytesUsed
&&
88 !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
90 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
92 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
93 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
94 SendReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
95 Map
= (PAFD_MAPBUF
)(SendReq
->BufferArray
+ SendReq
->BufferCount
);
97 AFD_DbgPrint(MID_TRACE
,("SendReq @ %x\n", SendReq
));
99 SpaceAvail
= FCB
->Send
.Size
- FCB
->Send
.BytesUsed
;
101 for( i
= 0; i
< SendReq
->BufferCount
; i
++ ) {
102 Map
[i
].BufferAddress
=
103 MmMapLockedPages( Map
[i
].Mdl
, KernelMode
);
105 CopySize
= MIN( SpaceAvail
,
106 SendReq
->BufferArray
[i
].len
);
108 RtlCopyMemory( FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
109 Map
[i
].BufferAddress
,
112 MmUnmapLockedPages( Map
[i
].BufferAddress
, Map
[i
].Mdl
);
114 FCB
->Send
.BytesUsed
+= CopySize
;
115 TotalBytesCopied
+= CopySize
;
116 SpaceAvail
-= CopySize
;
120 /* Some data is still waiting */
121 if( FCB
->Send
.BytesUsed
) {
122 FCB
->PollState
&= ~AFD_EVENT_SEND
;
124 SocketCalloutEnter( FCB
);
126 Status
= TdiSend( &FCB
->SendIrp
.InFlightRequest
,
127 FCB
->Connection
.Object
,
135 SocketCalloutLeave( FCB
);
137 FCB
->PollState
|= AFD_EVENT_SEND
;
138 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
141 if( TotalBytesCopied
> 0 ) {
142 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
144 if( Status
== STATUS_PENDING
)
145 Status
= STATUS_SUCCESS
;
147 AFD_DbgPrint(MID_TRACE
,("Dismissing request: %x\n", Status
));
149 return UnlockAndMaybeComplete( FCB
, Status
, NextIrp
, TotalBytesCopied
,
151 } else if( NextIrp
) {
152 AFD_DbgPrint(MID_TRACE
,("Could not do any more with Irp %x\n",
154 InsertHeadList( &FCB
->PendingIrpList
[FUNCTION_SEND
],
155 &NextIrp
->Tail
.Overlay
.ListEntry
);
158 SocketStateUnlock( FCB
);
160 return STATUS_SUCCESS
;
163 static NTSTATUS NTAPI PacketSocketSendComplete
164 ( PDEVICE_OBJECT DeviceObject
,
167 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
169 AFD_DbgPrint(MID_TRACE
,("Called, status %x, %d bytes used\n",
170 Irp
->IoStatus
.Status
,
171 Irp
->IoStatus
.Information
));
173 /* It's ok if the FCB already died */
174 if( !SocketAcquireStateLock( FCB
) ) return STATUS_SUCCESS
;
176 FCB
->PollState
|= AFD_EVENT_SEND
;
177 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
179 FCB
->SendIrp
.InFlightRequest
= NULL
;
180 /* Request is not in flight any longer */
182 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
183 SocketStateUnlock( FCB
);
184 DestroySocket( FCB
);
185 return STATUS_SUCCESS
;
188 SocketStateUnlock( FCB
);
190 return STATUS_SUCCESS
;
194 AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
195 PIO_STACK_LOCATION IrpSp
, BOOLEAN Short
) {
196 NTSTATUS Status
= STATUS_SUCCESS
;
197 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
198 PAFD_FCB FCB
= FileObject
->FsContext
;
199 PAFD_SEND_INFO SendReq
;
200 UINT TotalBytesCopied
= 0, i
, CopySize
= 0,
201 SpaceAvail
= 0, TotalBytesEncountered
= 0;
203 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
205 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
207 FCB
->EventsFired
&= ~AFD_EVENT_SEND
;
209 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
211 PAFD_SEND_INFO_UDP SendReq
;
212 PTDI_CONNECTION_INFORMATION TargetAddress
;
214 /* Check that the socket is bound */
215 if( FCB
->State
!= SOCKET_STATE_BOUND
)
216 return UnlockAndMaybeComplete( FCB
, STATUS_UNSUCCESSFUL
, Irp
,
219 if( !(SendReq
= LockRequest( Irp
, IrpSp
)) )
220 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
, 0,
223 /* Must lock buffers before handing off user data */
224 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
225 SendReq
->BufferCount
,
229 if( !SendReq
->BufferArray
) {
230 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
234 TdiBuildConnectionInfo( &TargetAddress
, FCB
->RemoteAddress
);
236 if( TargetAddress
) {
237 SocketCalloutEnter( FCB
);
239 Status
= TdiSendDatagram
240 ( &FCB
->SendIrp
.InFlightRequest
,
241 FCB
->AddressFile
.Object
,
242 SendReq
->BufferArray
[0].buf
,
243 SendReq
->BufferArray
[0].len
,
246 PacketSocketSendComplete
,
249 SocketCalloutLeave( FCB
);
251 ExFreePool( TargetAddress
);
252 } else Status
= STATUS_NO_MEMORY
;
254 if( Status
== STATUS_PENDING
) Status
= STATUS_SUCCESS
;
256 AFD_DbgPrint(MID_TRACE
,("Dismissing request: %x\n", Status
));
258 return UnlockAndMaybeComplete( FCB
, Status
, Irp
,
259 SendReq
->BufferArray
[0].len
,
263 if( !(SendReq
= LockRequest( Irp
, IrpSp
)) )
264 return UnlockAndMaybeComplete
265 ( FCB
, STATUS_NO_MEMORY
, Irp
, TotalBytesCopied
, NULL
);
267 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
268 SendReq
->BufferCount
,
272 if( !SendReq
->BufferArray
) {
273 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
277 AFD_DbgPrint(MID_TRACE
,("Socket state %d\n", FCB
->State
));
279 if( FCB
->State
!= SOCKET_STATE_CONNECTED
) {
280 if( SendReq
->AfdFlags
& AFD_IMMEDIATE
) {
281 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
282 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
283 return UnlockAndMaybeComplete
284 ( FCB
, STATUS_CANT_WAIT
, Irp
, 0, NULL
);
286 AFD_DbgPrint(MID_TRACE
,("Queuing request\n"));
287 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_SEND
);
291 AFD_DbgPrint(MID_TRACE
,("FCB->Send.BytesUsed = %d\n",
292 FCB
->Send
.BytesUsed
));
294 if( !FCB
->Send
.BytesUsed
) {
295 SpaceAvail
= FCB
->Send
.Size
- FCB
->Send
.BytesUsed
;
297 AFD_DbgPrint(MID_TRACE
,("We can accept %d bytes\n",
300 for( i
= 0; FCB
->Send
.BytesUsed
< FCB
->Send
.Size
&&
301 i
< SendReq
->BufferCount
; i
++ ) {
302 CopySize
= MIN( SpaceAvail
,
303 SendReq
->BufferArray
[i
].len
);
305 TotalBytesEncountered
+= SendReq
->BufferArray
[i
].len
;
307 AFD_DbgPrint(MID_TRACE
,("Copying Buffer %d, %x:%d to %x\n",
309 SendReq
->BufferArray
[i
].buf
,
311 FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
));
313 RtlCopyMemory( FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
314 SendReq
->BufferArray
[i
].buf
,
317 FCB
->Send
.BytesUsed
+= CopySize
;
318 TotalBytesCopied
+= CopySize
;
319 SpaceAvail
-= CopySize
;
322 if( TotalBytesEncountered
== 0 ) {
323 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
325 AFD_DbgPrint(MID_TRACE
,("Empty send\n"));
326 return UnlockAndMaybeComplete
327 ( FCB
, Status
, Irp
, TotalBytesCopied
, NULL
);
330 AFD_DbgPrint(MID_TRACE
,("Completed %d bytes\n", TotalBytesCopied
));
332 if( TotalBytesCopied
> 0 ) {
333 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
335 FCB
->SendIrp
.InFlightRequest
= (PVOID
)1; /* Placeholder */
337 SocketCalloutEnter( FCB
);
339 Status
= TdiSend( &FCB
->SendIrp
.InFlightRequest
,
340 FCB
->Connection
.Object
,
348 SocketCalloutLeave( FCB
);
350 if( Status
== STATUS_PENDING
)
351 Status
= STATUS_SUCCESS
;
353 AFD_DbgPrint(MID_TRACE
,("Dismissing request: %x (%d)\n",
354 Status
, TotalBytesCopied
));
356 return UnlockAndMaybeComplete
357 ( FCB
, Status
, Irp
, TotalBytesCopied
, NULL
);
361 if( SendReq
->AfdFlags
& AFD_IMMEDIATE
) {
362 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
363 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
364 return UnlockAndMaybeComplete
365 ( FCB
, STATUS_CANT_WAIT
, Irp
, 0, NULL
);
367 AFD_DbgPrint(MID_TRACE
,("Queuing request\n"));
368 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_SEND
);
373 AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
374 PIO_STACK_LOCATION IrpSp
) {
375 NTSTATUS Status
= STATUS_SUCCESS
;
376 PTDI_CONNECTION_INFORMATION TargetAddress
;
377 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
378 PAFD_FCB FCB
= FileObject
->FsContext
;
379 PAFD_SEND_INFO_UDP SendReq
;
381 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
383 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
385 FCB
->EventsFired
&= ~AFD_EVENT_SEND
;
386 FCB
->PollState
&= ~AFD_EVENT_SEND
;
388 /* Check that the socket is bound */
389 if( FCB
->State
!= SOCKET_STATE_BOUND
)
390 return UnlockAndMaybeComplete
391 ( FCB
, STATUS_UNSUCCESSFUL
, Irp
, 0, NULL
);
392 if( !(SendReq
= LockRequest( Irp
, IrpSp
)) )
393 return UnlockAndMaybeComplete
394 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0, NULL
);
397 (MID_TRACE
,("RemoteAddress #%d Type %d\n",
398 ((PTRANSPORT_ADDRESS
)SendReq
->RemoteAddress
)->
400 ((PTRANSPORT_ADDRESS
)SendReq
->RemoteAddress
)->
401 Address
[0].AddressType
));
403 TdiBuildConnectionInfo( &TargetAddress
,
404 ((PTRANSPORT_ADDRESS
)SendReq
->RemoteAddress
) );
406 /* Check the size of the Address given ... */
408 if( TargetAddress
) {
409 SocketCalloutEnter( FCB
);
411 Status
= TdiSendDatagram
412 ( &FCB
->SendIrp
.InFlightRequest
,
413 FCB
->AddressFile
.Object
,
414 SendReq
->BufferArray
[0].buf
,
415 SendReq
->BufferArray
[0].len
,
418 PacketSocketSendComplete
,
421 SocketCalloutLeave( FCB
);
423 ExFreePool( TargetAddress
);
424 } else Status
= STATUS_NO_MEMORY
;
426 if( Status
== STATUS_PENDING
) Status
= STATUS_SUCCESS
;
428 AFD_DbgPrint(MID_TRACE
,("Dismissing request: %x\n", Status
));
430 return UnlockAndMaybeComplete
431 ( FCB
, Status
, Irp
, SendReq
->BufferArray
[0].len
, NULL
);