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)
13 static IO_COMPLETION_ROUTINE SendComplete
;
14 static NTSTATUS NTAPI SendComplete
15 ( PDEVICE_OBJECT DeviceObject
,
18 NTSTATUS Status
= Irp
->IoStatus
.Status
;
19 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
20 PLIST_ENTRY NextIrpEntry
;
22 PIO_STACK_LOCATION NextIrpSp
;
23 PAFD_SEND_INFO SendReq
= NULL
;
25 UINT TotalBytesCopied
= 0, TotalBytesProcessed
= 0, SpaceAvail
, i
;
26 UINT SendLength
, BytesCopied
;
27 BOOLEAN HaltSendQueue
;
29 UNREFERENCED_PARAMETER(DeviceObject
);
32 * The Irp parameter passed in is the IRP of the stream between AFD and
33 * TDI driver. It's not very useful to us. We need the IRPs of the stream
34 * between usermode and AFD. Those are chained from
35 * FCB->PendingIrpList[FUNCTION_SEND] and you'll see them in the code
36 * below as "NextIrp" ('cause they are the next usermode IRP to be
40 AFD_DbgPrint(MID_TRACE
,("Called, status %x, %u bytes used\n",
42 Irp
->IoStatus
.Information
));
44 if( !SocketAcquireStateLock( FCB
) )
45 return STATUS_FILE_CLOSED
;
47 ASSERT(FCB
->SendIrp
.InFlightRequest
== Irp
);
48 FCB
->SendIrp
.InFlightRequest
= NULL
;
49 /* Request is not in flight any longer */
51 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
52 /* Cleanup our IRP queue because the FCB is being destroyed */
53 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
54 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
55 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
56 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
57 SendReq
= GetLockedData(NextIrp
, NextIrpSp
);
58 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
59 NextIrp
->IoStatus
.Information
= 0;
60 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
61 if( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
62 (void)IoSetCancelRoutine(NextIrp
, NULL
);
63 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
66 RetryDisconnectCompletion(FCB
);
68 SocketStateUnlock( FCB
);
69 return STATUS_FILE_CLOSED
;
72 if( !NT_SUCCESS(Status
) ) {
73 /* Complete all following send IRPs with error */
75 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
77 RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
79 CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
80 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
81 SendReq
= GetLockedData(NextIrp
, NextIrpSp
);
83 UnlockBuffers( SendReq
->BufferArray
,
87 NextIrp
->IoStatus
.Status
= Status
;
88 NextIrp
->IoStatus
.Information
= 0;
90 if ( NextIrp
->MdlAddress
) UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
91 (void)IoSetCancelRoutine(NextIrp
, NULL
);
92 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
95 RetryDisconnectCompletion(FCB
);
97 SocketStateUnlock( FCB
);
99 return STATUS_SUCCESS
;
102 RtlMoveMemory( FCB
->Send
.Window
,
103 FCB
->Send
.Window
+ Irp
->IoStatus
.Information
,
104 FCB
->Send
.BytesUsed
- Irp
->IoStatus
.Information
);
106 TotalBytesProcessed
= 0;
107 SendLength
= Irp
->IoStatus
.Information
;
108 HaltSendQueue
= FALSE
;
109 while (!IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_SEND
]) && SendLength
> 0) {
110 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
111 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
112 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
113 SendReq
= GetLockedData(NextIrp
, NextIrpSp
);
114 Map
= (PAFD_MAPBUF
)(SendReq
->BufferArray
+ SendReq
->BufferCount
);
116 TotalBytesCopied
= (ULONG_PTR
)NextIrp
->Tail
.Overlay
.DriverContext
[3];
117 ASSERT(TotalBytesCopied
!= 0);
119 /* If we didn't get enough, keep waiting */
120 if (TotalBytesCopied
> SendLength
)
122 /* Update the bytes left to copy */
123 TotalBytesCopied
-= SendLength
;
124 NextIrp
->Tail
.Overlay
.DriverContext
[3] = (PVOID
)TotalBytesCopied
;
126 /* Update the state variables */
127 FCB
->Send
.BytesUsed
-= SendLength
;
128 TotalBytesProcessed
+= SendLength
;
132 InsertHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
],
133 &NextIrp
->Tail
.Overlay
.ListEntry
);
134 HaltSendQueue
= TRUE
;
138 ASSERT(NextIrp
->IoStatus
.Information
!= 0);
140 NextIrp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
142 FCB
->Send
.BytesUsed
-= TotalBytesCopied
;
143 TotalBytesProcessed
+= TotalBytesCopied
;
144 SendLength
-= TotalBytesCopied
;
146 (void)IoSetCancelRoutine(NextIrp
, NULL
);
148 UnlockBuffers( SendReq
->BufferArray
,
149 SendReq
->BufferCount
,
152 if (NextIrp
->MdlAddress
) UnlockRequest(NextIrp
, NextIrpSp
);
154 IoCompleteRequest(NextIrp
, IO_NETWORK_INCREMENT
);
157 ASSERT(SendLength
== 0);
159 if ( !HaltSendQueue
&& !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
160 NextIrpEntry
= FCB
->PendingIrpList
[FUNCTION_SEND
].Flink
;
161 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
162 NextIrpSp
= IoGetCurrentIrpStackLocation( NextIrp
);
163 SendReq
= GetLockedData(NextIrp
, NextIrpSp
);
164 Map
= (PAFD_MAPBUF
)(SendReq
->BufferArray
+ SendReq
->BufferCount
);
166 AFD_DbgPrint(MID_TRACE
,("SendReq @ %p\n", SendReq
));
168 SpaceAvail
= FCB
->Send
.Size
- FCB
->Send
.BytesUsed
;
169 TotalBytesCopied
= 0;
171 /* Count the total transfer size */
173 for (i
= 0; i
< SendReq
->BufferCount
; i
++)
175 SendLength
+= SendReq
->BufferArray
[i
].len
;
178 /* Make sure we've got the space */
179 if (SendLength
> SpaceAvail
)
181 /* Blocking sockets have to wait here */
182 if (SendLength
<= FCB
->Send
.Size
&& !((SendReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
)))
184 FCB
->PollState
&= ~AFD_EVENT_SEND
;
189 /* Check if we can send anything */
192 FCB
->PollState
&= ~AFD_EVENT_SEND
;
194 /* We should never be non-overlapped and get to this point */
195 ASSERT(SendReq
->AfdFlags
& AFD_OVERLAPPED
);
203 for( i
= 0; i
< SendReq
->BufferCount
; i
++ ) {
204 BytesCopied
= MIN(SendReq
->BufferArray
[i
].len
, SpaceAvail
);
206 Map
[i
].BufferAddress
=
207 MmMapLockedPages( Map
[i
].Mdl
, KernelMode
);
209 RtlCopyMemory( FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
210 Map
[i
].BufferAddress
,
213 MmUnmapLockedPages( Map
[i
].BufferAddress
, Map
[i
].Mdl
);
215 TotalBytesCopied
+= BytesCopied
;
216 SpaceAvail
-= BytesCopied
;
217 FCB
->Send
.BytesUsed
+= BytesCopied
;
220 NextIrp
->IoStatus
.Information
= TotalBytesCopied
;
221 NextIrp
->Tail
.Overlay
.DriverContext
[3] = (PVOID
)NextIrp
->IoStatus
.Information
;
225 if (FCB
->Send
.Size
- FCB
->Send
.BytesUsed
!= 0 && !FCB
->SendClosed
&&
226 IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_SEND
]))
228 FCB
->PollState
|= AFD_EVENT_SEND
;
229 FCB
->PollStatus
[FD_WRITE_BIT
] = STATUS_SUCCESS
;
230 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
234 FCB
->PollState
&= ~AFD_EVENT_SEND
;
238 /* Some data is still waiting */
239 if( FCB
->Send
.BytesUsed
)
241 Status
= TdiSend( &FCB
->SendIrp
.InFlightRequest
,
242 FCB
->Connection
.Object
,
251 /* Nothing is waiting so try to complete a pending disconnect */
252 RetryDisconnectCompletion(FCB
);
255 SocketStateUnlock( FCB
);
257 return STATUS_SUCCESS
;
260 static IO_COMPLETION_ROUTINE PacketSocketSendComplete
;
261 static NTSTATUS NTAPI PacketSocketSendComplete
262 ( PDEVICE_OBJECT DeviceObject
,
265 PAFD_FCB FCB
= (PAFD_FCB
)Context
;
266 PLIST_ENTRY NextIrpEntry
;
268 PAFD_SEND_INFO SendReq
;
270 UNREFERENCED_PARAMETER(DeviceObject
);
272 AFD_DbgPrint(MID_TRACE
,("Called, status %x, %u bytes used\n",
273 Irp
->IoStatus
.Status
,
274 Irp
->IoStatus
.Information
));
276 if( !SocketAcquireStateLock( FCB
) )
277 return STATUS_FILE_CLOSED
;
279 ASSERT(FCB
->SendIrp
.InFlightRequest
== Irp
);
280 FCB
->SendIrp
.InFlightRequest
= NULL
;
281 /* Request is not in flight any longer */
283 if( FCB
->State
== SOCKET_STATE_CLOSED
) {
284 /* Cleanup our IRP queue because the FCB is being destroyed */
285 while( !IsListEmpty( &FCB
->PendingIrpList
[FUNCTION_SEND
] ) ) {
286 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
287 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
288 SendReq
= GetLockedData(NextIrp
, IoGetCurrentIrpStackLocation(NextIrp
));
289 NextIrp
->IoStatus
.Status
= STATUS_FILE_CLOSED
;
290 NextIrp
->IoStatus
.Information
= 0;
291 (void)IoSetCancelRoutine(NextIrp
, NULL
);
292 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
293 UnlockRequest( NextIrp
, IoGetCurrentIrpStackLocation( NextIrp
) );
294 IoCompleteRequest( NextIrp
, IO_NETWORK_INCREMENT
);
296 SocketStateUnlock( FCB
);
297 return STATUS_FILE_CLOSED
;
300 ASSERT(!IsListEmpty(&FCB
->PendingIrpList
[FUNCTION_SEND
]));
302 /* TDI spec guarantees FIFO ordering on IRPs */
303 NextIrpEntry
= RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]);
304 NextIrp
= CONTAINING_RECORD(NextIrpEntry
, IRP
, Tail
.Overlay
.ListEntry
);
306 SendReq
= GetLockedData(NextIrp
, IoGetCurrentIrpStackLocation(NextIrp
));
308 NextIrp
->IoStatus
.Status
= Irp
->IoStatus
.Status
;
309 NextIrp
->IoStatus
.Information
= Irp
->IoStatus
.Information
;
311 (void)IoSetCancelRoutine(NextIrp
, NULL
);
313 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
315 UnlockRequest(NextIrp
, IoGetCurrentIrpStackLocation(NextIrp
));
317 IoCompleteRequest(NextIrp
, IO_NETWORK_INCREMENT
);
319 FCB
->PollState
|= AFD_EVENT_SEND
;
320 FCB
->PollStatus
[FD_WRITE_BIT
] = STATUS_SUCCESS
;
321 PollReeval(FCB
->DeviceExt
, FCB
->FileObject
);
323 SocketStateUnlock(FCB
);
325 return STATUS_SUCCESS
;
329 AfdConnectedSocketWriteData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
330 PIO_STACK_LOCATION IrpSp
, BOOLEAN Short
) {
331 NTSTATUS Status
= STATUS_SUCCESS
;
332 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
333 PAFD_FCB FCB
= FileObject
->FsContext
;
334 PAFD_SEND_INFO SendReq
;
335 UINT TotalBytesCopied
= 0, i
, SpaceAvail
= 0, BytesCopied
, SendLength
;
336 KPROCESSOR_MODE LockMode
;
338 UNREFERENCED_PARAMETER(DeviceObject
);
339 UNREFERENCED_PARAMETER(Short
);
341 AFD_DbgPrint(MID_TRACE
,("Called on %p\n", FCB
));
343 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
345 FCB
->EventSelectDisabled
&= ~AFD_EVENT_SEND
;
347 if( FCB
->Flags
& AFD_ENDPOINT_CONNECTIONLESS
)
349 PAFD_SEND_INFO_UDP SendReq
;
350 PTDI_CONNECTION_INFORMATION TargetAddress
;
352 /* Check that the socket is bound */
353 if( FCB
->State
!= SOCKET_STATE_BOUND
|| !FCB
->RemoteAddress
)
355 AFD_DbgPrint(MIN_TRACE
,("Invalid parameter\n"));
356 return UnlockAndMaybeComplete( FCB
, STATUS_INVALID_PARAMETER
, Irp
,
360 if( !(SendReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
361 return UnlockAndMaybeComplete( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
363 /* Must lock buffers before handing off user data */
364 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
365 SendReq
->BufferCount
,
367 FALSE
, FALSE
, LockMode
);
369 if( !SendReq
->BufferArray
) {
370 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
374 Status
= TdiBuildConnectionInfo( &TargetAddress
, FCB
->RemoteAddress
);
376 if( NT_SUCCESS(Status
) ) {
377 FCB
->PollState
&= ~AFD_EVENT_SEND
;
379 Status
= QueueUserModeIrp(FCB
, Irp
, FUNCTION_SEND
);
380 if (Status
== STATUS_PENDING
)
382 Status
= TdiSendDatagram(&FCB
->SendIrp
.InFlightRequest
,
383 FCB
->AddressFile
.Object
,
384 SendReq
->BufferArray
[0].buf
,
385 SendReq
->BufferArray
[0].len
,
387 PacketSocketSendComplete
,
389 if (Status
!= STATUS_PENDING
)
391 NT_VERIFY(RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]) == &Irp
->Tail
.Overlay
.ListEntry
);
392 Irp
->IoStatus
.Status
= Status
;
393 Irp
->IoStatus
.Information
= 0;
394 (void)IoSetCancelRoutine(Irp
, NULL
);
395 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
396 UnlockRequest(Irp
, IoGetCurrentIrpStackLocation(Irp
));
397 IoCompleteRequest(Irp
, IO_NETWORK_INCREMENT
);
401 ExFreePool( TargetAddress
);
403 SocketStateUnlock(FCB
);
405 return STATUS_PENDING
;
409 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
410 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
414 if (FCB
->PollState
& AFD_EVENT_CLOSE
)
416 AFD_DbgPrint(MIN_TRACE
,("Connection reset by remote peer\n"));
418 /* This is an unexpected remote disconnect */
419 return UnlockAndMaybeComplete(FCB
, FCB
->PollStatus
[FD_CLOSE_BIT
], Irp
, 0);
422 if (FCB
->PollState
& AFD_EVENT_ABORT
)
424 AFD_DbgPrint(MIN_TRACE
,("Connection aborted\n"));
426 /* This is an abortive socket closure on our side */
427 return UnlockAndMaybeComplete(FCB
, FCB
->PollStatus
[FD_CLOSE_BIT
], Irp
, 0);
432 AFD_DbgPrint(MIN_TRACE
,("No more sends\n"));
434 /* This is a graceful send closure */
435 return UnlockAndMaybeComplete(FCB
, STATUS_FILE_CLOSED
, Irp
, 0);
438 if( !(SendReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
439 return UnlockAndMaybeComplete
440 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
442 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
443 SendReq
->BufferCount
,
445 FALSE
, FALSE
, LockMode
);
447 if( !SendReq
->BufferArray
) {
448 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
452 AFD_DbgPrint(MID_TRACE
,("Socket state %u\n", FCB
->State
));
454 if( FCB
->State
!= SOCKET_STATE_CONNECTED
) {
455 AFD_DbgPrint(MID_TRACE
,("Socket not connected\n"));
456 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
457 return UnlockAndMaybeComplete( FCB
, STATUS_INVALID_CONNECTION
, Irp
, 0 );
460 AFD_DbgPrint(MID_TRACE
,("FCB->Send.BytesUsed = %u\n",
461 FCB
->Send
.BytesUsed
));
463 SpaceAvail
= FCB
->Send
.Size
- FCB
->Send
.BytesUsed
;
465 AFD_DbgPrint(MID_TRACE
,("We can accept %u bytes\n",
468 /* Count the total transfer size */
470 for (i
= 0; i
< SendReq
->BufferCount
; i
++)
472 SendLength
+= SendReq
->BufferArray
[i
].len
;
475 /* Make sure we've got the space */
476 if (SendLength
> SpaceAvail
)
478 /* Blocking sockets have to wait here */
479 if (SendLength
<= FCB
->Send
.Size
&& !((SendReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
)))
481 FCB
->PollState
&= ~AFD_EVENT_SEND
;
482 return LeaveIrpUntilLater(FCB
, Irp
, FUNCTION_SEND
);
485 /* Check if we can send anything */
488 FCB
->PollState
&= ~AFD_EVENT_SEND
;
490 /* Non-overlapped sockets will fail if we can send nothing */
491 if (!(SendReq
->AfdFlags
& AFD_OVERLAPPED
))
493 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
494 return UnlockAndMaybeComplete( FCB
, STATUS_CANT_WAIT
, Irp
, 0 );
498 /* Overlapped sockets just pend */
499 return LeaveIrpUntilLater(FCB
, Irp
, FUNCTION_SEND
);
504 for ( i
= 0; SpaceAvail
> 0 && i
< SendReq
->BufferCount
; i
++ )
506 BytesCopied
= MIN(SendReq
->BufferArray
[i
].len
, SpaceAvail
);
508 AFD_DbgPrint(MID_TRACE
,("Copying Buffer %u, %p:%u to %p\n",
510 SendReq
->BufferArray
[i
].buf
,
512 FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
));
514 RtlCopyMemory(FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
515 SendReq
->BufferArray
[i
].buf
,
518 TotalBytesCopied
+= BytesCopied
;
519 SpaceAvail
-= BytesCopied
;
520 FCB
->Send
.BytesUsed
+= BytesCopied
;
523 Irp
->IoStatus
.Information
= TotalBytesCopied
;
525 if( TotalBytesCopied
== 0 ) {
526 AFD_DbgPrint(MID_TRACE
,("Empty send\n"));
527 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
528 return UnlockAndMaybeComplete
529 ( FCB
, STATUS_SUCCESS
, Irp
, TotalBytesCopied
);
534 FCB
->PollState
|= AFD_EVENT_SEND
;
535 FCB
->PollStatus
[FD_WRITE_BIT
] = STATUS_SUCCESS
;
536 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
540 FCB
->PollState
&= ~AFD_EVENT_SEND
;
543 /* We use the IRP tail for some temporary storage here */
544 Irp
->Tail
.Overlay
.DriverContext
[3] = (PVOID
)Irp
->IoStatus
.Information
;
546 Status
= QueueUserModeIrp(FCB
, Irp
, FUNCTION_SEND
);
547 if (Status
== STATUS_PENDING
&& !FCB
->SendIrp
.InFlightRequest
)
549 TdiSend(&FCB
->SendIrp
.InFlightRequest
,
550 FCB
->Connection
.Object
,
558 SocketStateUnlock(FCB
);
560 return STATUS_PENDING
;
564 AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
565 PIO_STACK_LOCATION IrpSp
) {
566 NTSTATUS Status
= STATUS_SUCCESS
;
567 PTDI_CONNECTION_INFORMATION TargetAddress
;
568 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
569 PAFD_FCB FCB
= FileObject
->FsContext
;
570 PAFD_SEND_INFO_UDP SendReq
;
571 KPROCESSOR_MODE LockMode
;
573 UNREFERENCED_PARAMETER(DeviceObject
);
575 AFD_DbgPrint(MID_TRACE
,("Called on %p\n", FCB
));
577 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
579 FCB
->EventSelectDisabled
&= ~AFD_EVENT_SEND
;
581 /* Check that the socket is bound */
582 if( FCB
->State
!= SOCKET_STATE_BOUND
&&
583 FCB
->State
!= SOCKET_STATE_CREATED
)
585 AFD_DbgPrint(MIN_TRACE
,("Invalid socket state\n"));
586 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
591 AFD_DbgPrint(MIN_TRACE
,("No more sends\n"));
592 return UnlockAndMaybeComplete(FCB
, STATUS_FILE_CLOSED
, Irp
, 0);
595 if( !(SendReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
596 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
598 if (FCB
->State
== SOCKET_STATE_CREATED
)
600 if( FCB
->LocalAddress
) ExFreePool( FCB
->LocalAddress
);
602 TaBuildNullTransportAddress( ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
)->
603 Address
[0].AddressType
);
605 if( FCB
->LocalAddress
) {
606 Status
= WarmSocketForBind( FCB
, AFD_SHARE_WILDCARD
);
608 if( NT_SUCCESS(Status
) )
609 FCB
->State
= SOCKET_STATE_BOUND
;
611 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
613 return UnlockAndMaybeComplete
614 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
617 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
618 SendReq
->BufferCount
,
620 FALSE
, FALSE
, LockMode
);
622 if( !SendReq
->BufferArray
)
623 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
627 (MID_TRACE
,("RemoteAddress #%d Type %u\n",
628 ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
)->
630 ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
)->
631 Address
[0].AddressType
));
633 Status
= TdiBuildConnectionInfo( &TargetAddress
,
634 ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
) );
636 /* Check the size of the Address given ... */
638 if( NT_SUCCESS(Status
) ) {
639 FCB
->PollState
&= ~AFD_EVENT_SEND
;
641 Status
= QueueUserModeIrp(FCB
, Irp
, FUNCTION_SEND
);
642 if (Status
== STATUS_PENDING
)
644 Status
= TdiSendDatagram(&FCB
->SendIrp
.InFlightRequest
,
645 FCB
->AddressFile
.Object
,
646 SendReq
->BufferArray
[0].buf
,
647 SendReq
->BufferArray
[0].len
,
649 PacketSocketSendComplete
,
651 if (Status
!= STATUS_PENDING
)
653 NT_VERIFY(RemoveHeadList(&FCB
->PendingIrpList
[FUNCTION_SEND
]) == &Irp
->Tail
.Overlay
.ListEntry
);
654 Irp
->IoStatus
.Status
= Status
;
655 Irp
->IoStatus
.Information
= 0;
656 (void)IoSetCancelRoutine(Irp
, NULL
);
657 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
658 UnlockRequest(Irp
, IoGetCurrentIrpStackLocation(Irp
));
659 IoCompleteRequest(Irp
, IO_NETWORK_INCREMENT
);
663 ExFreePool(TargetAddress
);
665 SocketStateUnlock(FCB
);
667 return STATUS_PENDING
;
671 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
672 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );