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 usefull 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 TdiSendDatagram(&FCB
->SendIrp
.InFlightRequest
,
383 FCB
->AddressFile
.Object
,
384 SendReq
->BufferArray
[0].buf
,
385 SendReq
->BufferArray
[0].len
,
387 PacketSocketSendComplete
,
391 ExFreePool( TargetAddress
);
393 SocketStateUnlock(FCB
);
395 return STATUS_PENDING
;
399 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
400 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
404 if (FCB
->PollState
& AFD_EVENT_CLOSE
)
406 AFD_DbgPrint(MIN_TRACE
,("Connection reset by remote peer\n"));
408 /* This is an unexpected remote disconnect */
409 return UnlockAndMaybeComplete(FCB
, FCB
->PollStatus
[FD_CLOSE_BIT
], Irp
, 0);
412 if (FCB
->PollState
& AFD_EVENT_ABORT
)
414 AFD_DbgPrint(MIN_TRACE
,("Connection aborted\n"));
416 /* This is an abortive socket closure on our side */
417 return UnlockAndMaybeComplete(FCB
, FCB
->PollStatus
[FD_CLOSE_BIT
], Irp
, 0);
422 AFD_DbgPrint(MIN_TRACE
,("No more sends\n"));
424 /* This is a graceful send closure */
425 return UnlockAndMaybeComplete(FCB
, STATUS_FILE_CLOSED
, Irp
, 0);
428 if( !(SendReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
429 return UnlockAndMaybeComplete
430 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
432 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
433 SendReq
->BufferCount
,
435 FALSE
, FALSE
, LockMode
);
437 if( !SendReq
->BufferArray
) {
438 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
442 AFD_DbgPrint(MID_TRACE
,("Socket state %u\n", FCB
->State
));
444 if( FCB
->State
!= SOCKET_STATE_CONNECTED
) {
445 if (!(SendReq
->AfdFlags
& AFD_OVERLAPPED
) &&
446 ((SendReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
))) {
447 AFD_DbgPrint(MID_TRACE
,("Nonblocking\n"));
448 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
449 return UnlockAndMaybeComplete( FCB
, STATUS_CANT_WAIT
, Irp
, 0 );
451 AFD_DbgPrint(MID_TRACE
,("Queuing request\n"));
452 return LeaveIrpUntilLater( FCB
, Irp
, FUNCTION_SEND
);
456 AFD_DbgPrint(MID_TRACE
,("FCB->Send.BytesUsed = %u\n",
457 FCB
->Send
.BytesUsed
));
459 SpaceAvail
= FCB
->Send
.Size
- FCB
->Send
.BytesUsed
;
461 AFD_DbgPrint(MID_TRACE
,("We can accept %u bytes\n",
464 /* Count the total transfer size */
466 for (i
= 0; i
< SendReq
->BufferCount
; i
++)
468 SendLength
+= SendReq
->BufferArray
[i
].len
;
471 /* Make sure we've got the space */
472 if (SendLength
> SpaceAvail
)
474 /* Blocking sockets have to wait here */
475 if (SendLength
<= FCB
->Send
.Size
&& !((SendReq
->AfdFlags
& AFD_IMMEDIATE
) || (FCB
->NonBlocking
)))
477 FCB
->PollState
&= ~AFD_EVENT_SEND
;
478 return LeaveIrpUntilLater(FCB
, Irp
, FUNCTION_SEND
);
481 /* Check if we can send anything */
484 FCB
->PollState
&= ~AFD_EVENT_SEND
;
486 /* Non-overlapped sockets will fail if we can send nothing */
487 if (!(SendReq
->AfdFlags
& AFD_OVERLAPPED
))
489 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
490 return UnlockAndMaybeComplete( FCB
, STATUS_CANT_WAIT
, Irp
, 0 );
494 /* Overlapped sockets just pend */
495 return LeaveIrpUntilLater(FCB
, Irp
, FUNCTION_SEND
);
500 for ( i
= 0; SpaceAvail
> 0 && i
< SendReq
->BufferCount
; i
++ )
502 BytesCopied
= MIN(SendReq
->BufferArray
[i
].len
, SpaceAvail
);
504 AFD_DbgPrint(MID_TRACE
,("Copying Buffer %u, %p:%u to %p\n",
506 SendReq
->BufferArray
[i
].buf
,
508 FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
));
510 RtlCopyMemory(FCB
->Send
.Window
+ FCB
->Send
.BytesUsed
,
511 SendReq
->BufferArray
[i
].buf
,
514 TotalBytesCopied
+= BytesCopied
;
515 SpaceAvail
-= BytesCopied
;
516 FCB
->Send
.BytesUsed
+= BytesCopied
;
519 Irp
->IoStatus
.Information
= TotalBytesCopied
;
521 if( TotalBytesCopied
== 0 ) {
522 AFD_DbgPrint(MID_TRACE
,("Empty send\n"));
523 UnlockBuffers( SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
524 return UnlockAndMaybeComplete
525 ( FCB
, STATUS_SUCCESS
, Irp
, TotalBytesCopied
);
530 FCB
->PollState
|= AFD_EVENT_SEND
;
531 FCB
->PollStatus
[FD_WRITE_BIT
] = STATUS_SUCCESS
;
532 PollReeval( FCB
->DeviceExt
, FCB
->FileObject
);
536 FCB
->PollState
&= ~AFD_EVENT_SEND
;
539 /* We use the IRP tail for some temporary storage here */
540 Irp
->Tail
.Overlay
.DriverContext
[3] = (PVOID
)Irp
->IoStatus
.Information
;
542 Status
= QueueUserModeIrp(FCB
, Irp
, FUNCTION_SEND
);
543 if (Status
== STATUS_PENDING
&& !FCB
->SendIrp
.InFlightRequest
)
545 TdiSend(&FCB
->SendIrp
.InFlightRequest
,
546 FCB
->Connection
.Object
,
554 SocketStateUnlock(FCB
);
556 return STATUS_PENDING
;
560 AfdPacketSocketWriteData(PDEVICE_OBJECT DeviceObject
, PIRP Irp
,
561 PIO_STACK_LOCATION IrpSp
) {
562 NTSTATUS Status
= STATUS_SUCCESS
;
563 PTDI_CONNECTION_INFORMATION TargetAddress
;
564 PFILE_OBJECT FileObject
= IrpSp
->FileObject
;
565 PAFD_FCB FCB
= FileObject
->FsContext
;
566 PAFD_SEND_INFO_UDP SendReq
;
567 KPROCESSOR_MODE LockMode
;
569 UNREFERENCED_PARAMETER(DeviceObject
);
571 AFD_DbgPrint(MID_TRACE
,("Called on %p\n", FCB
));
573 if( !SocketAcquireStateLock( FCB
) ) return LostSocket( Irp
);
575 FCB
->EventSelectDisabled
&= ~AFD_EVENT_SEND
;
577 /* Check that the socket is bound */
578 if( FCB
->State
!= SOCKET_STATE_BOUND
&&
579 FCB
->State
!= SOCKET_STATE_CREATED
)
581 AFD_DbgPrint(MIN_TRACE
,("Invalid socket state\n"));
582 return UnlockAndMaybeComplete(FCB
, STATUS_INVALID_PARAMETER
, Irp
, 0);
587 AFD_DbgPrint(MIN_TRACE
,("No more sends\n"));
588 return UnlockAndMaybeComplete(FCB
, STATUS_FILE_CLOSED
, Irp
, 0);
591 if( !(SendReq
= LockRequest( Irp
, IrpSp
, FALSE
, &LockMode
)) )
592 return UnlockAndMaybeComplete(FCB
, STATUS_NO_MEMORY
, Irp
, 0);
594 if (FCB
->State
== SOCKET_STATE_CREATED
)
596 if( FCB
->LocalAddress
) ExFreePool( FCB
->LocalAddress
);
598 TaBuildNullTransportAddress( ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
)->
599 Address
[0].AddressType
);
601 if( FCB
->LocalAddress
) {
602 Status
= WarmSocketForBind( FCB
, AFD_SHARE_WILDCARD
);
604 if( NT_SUCCESS(Status
) )
605 FCB
->State
= SOCKET_STATE_BOUND
;
607 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );
609 return UnlockAndMaybeComplete
610 ( FCB
, STATUS_NO_MEMORY
, Irp
, 0 );
613 SendReq
->BufferArray
= LockBuffers( SendReq
->BufferArray
,
614 SendReq
->BufferCount
,
616 FALSE
, FALSE
, LockMode
);
618 if( !SendReq
->BufferArray
)
619 return UnlockAndMaybeComplete( FCB
, STATUS_ACCESS_VIOLATION
,
623 (MID_TRACE
,("RemoteAddress #%d Type %u\n",
624 ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
)->
626 ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
)->
627 Address
[0].AddressType
));
629 Status
= TdiBuildConnectionInfo( &TargetAddress
,
630 ((PTRANSPORT_ADDRESS
)SendReq
->TdiConnection
.RemoteAddress
) );
632 /* Check the size of the Address given ... */
634 if( NT_SUCCESS(Status
) ) {
635 FCB
->PollState
&= ~AFD_EVENT_SEND
;
637 Status
= QueueUserModeIrp(FCB
, Irp
, FUNCTION_SEND
);
638 if (Status
== STATUS_PENDING
)
640 TdiSendDatagram(&FCB
->SendIrp
.InFlightRequest
,
641 FCB
->AddressFile
.Object
,
642 SendReq
->BufferArray
[0].buf
,
643 SendReq
->BufferArray
[0].len
,
645 PacketSocketSendComplete
,
649 ExFreePool(TargetAddress
);
651 SocketStateUnlock(FCB
);
653 return STATUS_PENDING
;
657 UnlockBuffers(SendReq
->BufferArray
, SendReq
->BufferCount
, FALSE
);
658 return UnlockAndMaybeComplete( FCB
, Status
, Irp
, 0 );