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 NTSTATUS DDKAPI SendComplete
16 ( PDEVICE_OBJECT DeviceObject
,
19 NTSTATUS Status
= Irp
->IoStatus
.Status
;
20 PIO_STACK_LOCATION IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
21 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
22 PLIST_ENTRY NextIrpEntry
;
24 PIO_STACK_LOCATION NextIrpSp
;
25 PAFD_SEND_INFO SendReq
= NULL
;
27 UINT TotalBytesCopied
= 0, SpaceAvail
, i
, CopySize
= 0;
29 AFD_DbgPrint(MID_TRACE
,("Called, status %x, %d bytes used\n",
31 Irp
->IoStatus
.Information
));
33 ASSERT_IRQL(APC_LEVEL
);
35 if( !SocketAcquireStateLock( FCB
) ) return Status
;
37 FCB
->SendIrp
.InFlightRequest
= NULL
;
38 /* Request is not in flight any longer */
40 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
41 SocketStateUnlock( FCB
);
43 return STATUS_SUCCESS
;
46 if( !NT_SUCCESS(Status
) ) {
47 /* Complete all following send IRPs with error */
49 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
51 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
53 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
54 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
55 SendReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
57 UnlockBuffers( SendReq
->BufferArray
,
61 NextIrp
->IoStatus
.Status
= Status
;
62 NextIrp
->IoStatus
.Information
= 0;
64 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
67 SocketStateUnlock( FCB
);
69 return STATUS_SUCCESS
;
72 RtlMoveMemory( FCB
->Send
.Window
,
73 FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
74 FCB
->Send
.BytesUsed
- Irp
->IoStatus
.Information
);
75 FCB
->Send
.BytesUsed
-= Irp
->IoStatus
.Information
;
77 if( !FCB
->Send
.BytesUsed
&&
78 !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) &&
79 NT_SUCCESS(Status
) ) {
81 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_RECV
]);
83 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
84 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
85 SendReq
= NextIrpSp
->Parameters
.DeviceIoControl
.Type3InputBuffer
;
86 Map
= (PAFD_MAPBUF
)(SendReq
->BufferArray
+ SendReq
->BufferCount
);
88 AFD_DbgPrint(MID_TRACE
,("SendReq @ %x\n", SendReq
));
90 SpaceAvail
= FCB
->Send
.Size
- FCB
->Send
.BytesUsed
;
92 for( i
= 0; FCB
->Send
.BytesUsed
< FCB
->Send
.Content
&&
93 i
< SendReq
->BufferCount
; i
++ ) {
94 Map
[i
].BufferAddress
=
95 MmMapLockedPages( Map
[i
].Mdl
, KernelMode
);
97 CopySize
= MIN( SpaceAvail
,
98 SendReq
->BufferArray
[i
].len
);
100 RtlCopyMemory( FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
101 Map
[i
].BufferAddress
,
104 MmUnmapLockedPages( Map
[i
].Mdl
, KernelMode
);
106 FCB
->Send
.BytesUsed
+= CopySize
;
107 TotalBytesCopied
+= CopySize
;
108 SpaceAvail
-= CopySize
;
112 /* Some data is still waiting */
113 if( FCB
->Send
.BytesUsed
) {
114 FCB
->PollState
&= ~AFD_EVENT_SEND
;
116 SocketCalloutEnter( FCB
);
118 Status
= TdiSend( &FCB
->SendIrp
.InFlightRequest
,
127 SocketCalloutLeave( FCB
);
129 FCB
->PollState
|= AFD_EVENT_SEND
;
130 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
133 if( TotalBytesCopied
> 0 ) {
134 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
136 if( Status
== STATUS_PENDING
)
137 Status
= STATUS_SUCCESS
;
139 AFD_DbgPrint(MID_TRACE
,("Dismissing request: %x\n", Status
));
141 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, TotalBytesCopied
,
143 } else if( NextIrp
) {
144 AFD_DbgPrint(MID_TRACE
,("Could not do any more with Irp %x\n",
146 InsertHeadList( &FCB
->PendingIrpList
[FUNCTION_SEND
],
147 &Irp
->Tail
.Overlay
.ListEntry
);
150 SocketStateUnlock( FCB
);
152 return STATUS_SUCCESS
;
155 NTSTATUS DDKAPI PacketSocketSendComplete
156 ( PDEVICE_OBJECT DeviceObject
,
159 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
161 AFD_DbgPrint(MID_TRACE
,("Called, status %x, %d bytes used\n",
162 Irp
->IoStatus
.Status
,
163 Irp
->IoStatus
.Information
));
165 /* It's ok if the FCB already died */
166 if( !SocketAcquireStateLock( FCB
) ) return STATUS_SUCCESS
;
168 FCB
->PollState
|= AFD_EVENT_SEND
;
169 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
171 FCB
->SendIrp
.InFlightRequest
= NULL
;
172 /* Request is not in flight any longer */
174 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
175 SocketStateUnlock( FCB
);
176 DestroySocket( FCB
);
177 return STATUS_SUCCESS
;
180 SocketStateUnlock( FCB
);
182 return STATUS_SUCCESS
;
186 AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
187 PIO_STACK_LOCATION IrpSp
, BOOLEAN Short
) {
188 NTSTATUS Status
= STATUS_SUCCESS
;
189 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
190 PAFD_FCB FCB
= FileObject
->FsContext
;
191 PAFD_SEND_INFO SendReq
;
192 UINT TotalBytesCopied
= 0, i
, CopySize
= 0,
193 SpaceAvail
= 0, TotalBytesEncountered
= 0;
195 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
197 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
, FALSE
);
199 FCB
->EventsFired
&= ~AFD_EVENT_SEND
;
201 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
203 PAFD_SEND_INFO_UDP SendReq
;
204 PTDI_CONNECTION_INFORMATION TargetAddress
;
206 /* Check that the socket is bound */
207 if( FCB
->State
!= SOCKET_STATE_BOUND
)
208 return UnlockAndMaybeComplete( FCB
, STATUS_UNSUCCESSFUL
, Irp
,
211 if( !(SendReq
= LockRequest( Irp
, IrpSp
)) )
212 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
, 0,
215 /* Must lock buffers before handing off user data */
216 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
217 SendReq
->BufferCount
,
221 TdiBuildConnectionInfo( &TargetAddress
, FCB
->RemoteAddress
);
223 SocketCalloutEnter( FCB
);
225 Status
= TdiSendDatagram
226 ( &FCB
->SendIrp
.InFlightRequest
,
227 FCB
->AddressFile
.Object
,
228 SendReq
->BufferArray
[0].buf
,
229 SendReq
->BufferArray
[0].len
,
232 PacketSocketSendComplete
,
235 SocketCalloutLeave( FCB
);
237 ExFreePool( TargetAddress
);
239 if( Status
== STATUS_PENDING
) Status
= STATUS_SUCCESS
;
241 AFD_DbgPrint(MID_TRACE
,("Dismissing request: %x\n", Status
));
243 return UnlockAndMaybeComplete( FCB
, Status
, Irp
,
244 SendReq
->BufferArray
[0].len
,
248 if( !(SendReq
= LockRequest( Irp
, IrpSp
)) )
249 return UnlockAndMaybeComplete
250 ( FCB
, STATUS_NO_MEMORY
, Irp
, TotalBytesCopied
, NULL
, FALSE
);
252 AFD_DbgPrint(MID_TRACE
,("Socket state %d\n", FCB
->State
));
254 if( FCB
->State
!= SOCKET_STATE_CONNECTED
) {
255 if( SendReq
->AfdFlags
& AFD_IMMEDIATE
) {
256 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
257 return UnlockAndMaybeComplete
258 ( FCB
, STATUS_CANT_WAIT
, Irp
, 0, NULL
, TRUE
);
260 AFD_DbgPrint(MID_TRACE
,("Queuing request\n"));
261 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_SEND
);
265 AFD_DbgPrint(MID_TRACE
,("We already have %d bytes waiting.\n",
266 FCB
->Send
.BytesUsed
));
268 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
269 SendReq
->BufferCount
,
273 AFD_DbgPrint(MID_TRACE
,("FCB->Send.BytesUsed = %d\n",
274 FCB
->Send
.BytesUsed
));
276 if( !FCB
->Send
.BytesUsed
) {
277 SpaceAvail
= FCB
->Send
.Size
- FCB
->Send
.BytesUsed
;
279 AFD_DbgPrint(MID_TRACE
,("We can accept %d bytes\n",
282 for( i
= 0; FCB
->Send
.BytesUsed
< FCB
->Send
.Size
&&
283 i
< SendReq
->BufferCount
; i
++ ) {
284 CopySize
= MIN( SpaceAvail
,
285 SendReq
->BufferArray
[i
].len
);
287 TotalBytesEncountered
+= SendReq
->BufferArray
[i
].len
;
289 AFD_DbgPrint(MID_TRACE
,("Copying Buffer %d, %x:%d to %x\n",
291 SendReq
->BufferArray
[i
].buf
,
293 FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
));
295 RtlCopyMemory( FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
296 SendReq
->BufferArray
[i
].buf
,
299 FCB
->Send
.BytesUsed
+= CopySize
;
300 TotalBytesCopied
+= CopySize
;
301 SpaceAvail
-= CopySize
;
304 if( TotalBytesEncountered
== 0 ) {
305 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
307 AFD_DbgPrint(MID_TRACE
,("Empty send\n"));
308 return UnlockAndMaybeComplete
309 ( FCB
, Status
, Irp
, TotalBytesCopied
, NULL
, TRUE
);
312 AFD_DbgPrint(MID_TRACE
,("Completed %d bytes\n", TotalBytesCopied
));
314 if( TotalBytesCopied
> 0 ) {
315 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
317 FCB
->SendIrp
.InFlightRequest
= (PVOID
)1; /* Placeholder */
319 SocketCalloutEnter( FCB
);
321 Status
= TdiSend( &FCB
->SendIrp
.InFlightRequest
,
322 FCB
->Connection
.Object
,
330 SocketCalloutLeave( FCB
);
332 if( Status
== STATUS_PENDING
)
333 Status
= STATUS_SUCCESS
;
335 AFD_DbgPrint(MID_TRACE
,("Dismissing request: %x (%d)\n",
336 Status
, TotalBytesCopied
));
338 return UnlockAndMaybeComplete
339 ( FCB
, Status
, Irp
, TotalBytesCopied
, NULL
, TRUE
);
343 if( SendReq
->AfdFlags
& AFD_IMMEDIATE
) {
344 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
345 return UnlockAndMaybeComplete
346 ( FCB
, STATUS_CANT_WAIT
, Irp
, 0, NULL
, TRUE
);
348 AFD_DbgPrint(MID_TRACE
,("Queuing request\n"));
349 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_SEND
);
354 AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
355 PIO_STACK_LOCATION IrpSp
) {
356 NTSTATUS Status
= STATUS_SUCCESS
;
357 PTDI_CONNECTION_INFORMATION TargetAddress
;
358 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
359 PAFD_FCB FCB
= FileObject
->FsContext
;
360 PAFD_SEND_INFO_UDP SendReq
;
362 AFD_DbgPrint(MID_TRACE
,("Called on %x\n", FCB
));
364 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
, FALSE
);
366 FCB
->EventsFired
&= ~AFD_EVENT_SEND
;
367 FCB
->PollState
&= ~AFD_EVENT_SEND
;
369 /* Check that the socket is bound */
370 if( FCB
->State
!= SOCKET_STATE_BOUND
)
371 return UnlockAndMaybeComplete
372 ( FCB
, STATUS_UNSUCCESSFUL
, Irp
, 0, NULL
, FALSE
);
373 if( !(SendReq
= LockRequest( Irp
, IrpSp
)) )
374 return UnlockAndMaybeComplete
375 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0, NULL
, FALSE
);
378 (MID_TRACE
,("RemoteAddress #%d Type %d\n",
379 ((PTRANSPORT_ADDRESS
)SendReq
->RemoteAddress
)->
381 ((PTRANSPORT_ADDRESS
)SendReq
->RemoteAddress
)->
382 Address
[0].AddressType
));
384 TdiBuildConnectionInfo( &TargetAddress
,
385 ((PTRANSPORT_ADDRESS
)SendReq
->RemoteAddress
) );
387 /* Check the size of the Address given ... */
389 if( TargetAddress
) {
390 SocketCalloutEnter( FCB
);
392 Status
= TdiSendDatagram
393 ( &FCB
->SendIrp
.InFlightRequest
,
394 FCB
->AddressFile
.Object
,
395 SendReq
->BufferArray
[0].buf
,
396 SendReq
->BufferArray
[0].len
,
399 PacketSocketSendComplete
,
402 SocketCalloutLeave( FCB
);
404 ExFreePool( TargetAddress
);
405 } else Status
= STATUS_NO_MEMORY
;
407 if( Status
== STATUS_PENDING
) Status
= STATUS_SUCCESS
;
409 AFD_DbgPrint(MID_TRACE
,("Dismissing request: %x\n", Status
));
411 return UnlockAndMaybeComplete
412 ( FCB
, Status
, Irp
, SendReq
->BufferArray
[0].len
, NULL
, TRUE
);